Browse Source

Formatting.

pull/18/head
Jeff Young 5 months ago
parent
commit
a6707a42d1
  1. 8
      pcbnew/footprint_chooser_frame.cpp
  2. 481
      pcbnew/tools/pcb_grid_helper.cpp
  3. 3
      pcbnew/tools/pcb_grid_helper.h

8
pcbnew/footprint_chooser_frame.cpp

@ -227,8 +227,8 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare
// clang-format off
// Connect Events
m_toggleDescription->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
nullptr,this );
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
nullptr, this );
m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
@ -267,8 +267,8 @@ FOOTPRINT_CHOOSER_FRAME::~FOOTPRINT_CHOOSER_FRAME()
// clang-format off
// Disconnect Events
m_toggleDescription->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
nullptr, this );
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
nullptr, this );
m_grButton3DView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),

481
pcbnew/tools/pcb_grid_helper.cpp

@ -73,16 +73,11 @@ std::optional<INTERSECTABLE_GEOM> GetBoardIntersectable( const BOARD_ITEM& aItem
switch( shape.GetShape() )
{
case SHAPE_T::SEGMENT: return SEG{ shape.GetStart(), shape.GetEnd() };
case SHAPE_T::CIRCLE: return CIRCLE{ shape.GetCenter(), shape.GetRadius() };
case SHAPE_T::ARC:
return SHAPE_ARC{ shape.GetStart(), shape.GetArcMid(), shape.GetEnd(), 0 };
case SHAPE_T::SEGMENT: return SEG{ shape.GetStart(), shape.GetEnd() };
case SHAPE_T::CIRCLE: return CIRCLE{ shape.GetCenter(), shape.GetRadius() };
case SHAPE_T::ARC: return SHAPE_ARC{ shape.GetStart(), shape.GetArcMid(), shape.GetEnd(), 0 };
case SHAPE_T::RECTANGLE: return BOX2I::ByCorners( shape.GetStart(), shape.GetEnd() );
default: break;
default: break;
}
break;
@ -91,14 +86,12 @@ std::optional<INTERSECTABLE_GEOM> GetBoardIntersectable( const BOARD_ITEM& aItem
case PCB_TRACE_T:
{
const PCB_TRACK& track = static_cast<const PCB_TRACK&>( aItem );
return SEG{ track.GetStart(), track.GetEnd() };
}
case PCB_ARC_T:
{
const PCB_ARC& arc = static_cast<const PCB_ARC&>( aItem );
return SHAPE_ARC{ arc.GetStart(), arc.GetMid(), arc.GetEnd(), 0 };
}
@ -150,7 +143,8 @@ std::optional<int64_t> FindSquareDistanceToItem( const BOARD_ITEM& item, const V
} // namespace
PCB_GRID_HELPER::PCB_GRID_HELPER( TOOL_MANAGER* aToolMgr, MAGNETIC_SETTINGS* aMagneticSettings ) :
GRID_HELPER( aToolMgr, LAYER_ANCHOR ), m_magneticSettings( aMagneticSettings )
GRID_HELPER( aToolMgr, LAYER_ANCHOR ),
m_magneticSettings( aMagneticSettings )
{
KIGFX::VIEW* view = m_toolMgr->GetView();
KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
@ -185,9 +179,7 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo
bool aIsPersistent )
{
if( !ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps )
{
return;
}
// For all the elements that get drawn construction geometry,
// add something suitable to the construction helper.
@ -218,10 +210,8 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo
{
// Two rays, extending from the segment ends
const VECTOR2I segVec = shape.GetEnd() - shape.GetStart();
constructionDrawables.emplace_back(
HALF_LINE{ shape.GetStart(), shape.GetStart() - segVec } );
constructionDrawables.emplace_back(
HALF_LINE{ shape.GetEnd(), shape.GetEnd() + segVec } );
constructionDrawables.emplace_back( HALF_LINE{ shape.GetStart(), shape.GetStart() - segVec } );
constructionDrawables.emplace_back( HALF_LINE{ shape.GetEnd(), shape.GetEnd() + segVec } );
}
if( aIsPersistent )
@ -241,17 +231,15 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo
{
if( !aExtensionOnly )
{
constructionDrawables.push_back(
CIRCLE{ shape.GetCenter(), shape.GetRadius() } );
constructionDrawables.push_back( CIRCLE{ shape.GetCenter(), shape.GetRadius() } );
}
else
{
// The rest of the circle is the arc through the opposite point to the midpoint
const VECTOR2I oppositeMid =
shape.GetCenter() + ( shape.GetCenter() - shape.GetArcMid() );
constructionDrawables.push_back(
SHAPE_ARC{ shape.GetStart(), oppositeMid, shape.GetEnd(), 0 } );
const VECTOR2I oppositeMid = shape.GetCenter() + ( shape.GetCenter() - shape.GetArcMid() );
constructionDrawables.push_back( SHAPE_ARC{ shape.GetStart(), oppositeMid, shape.GetEnd(), 0 } );
}
constructionDrawables.push_back( shape.GetCenter() );
if( aIsPersistent )
@ -288,15 +276,11 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo
constructionDrawables.push_back( refImg.GetPosition() );
if( refImg.GetTransformOriginOffset() != VECTOR2I( 0, 0 ) )
{
constructionDrawables.push_back( refImg.GetPosition()
+ refImg.GetTransformOriginOffset() );
}
constructionDrawables.push_back( refImg.GetPosition() + refImg.GetTransformOriginOffset() );
for( const SEG& seg : KIGEOM::BoxToSegs( refImg.GetBoundingBox() ) )
{
constructionDrawables.push_back( seg );
}
break;
}
default:
@ -315,13 +299,11 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo
}
if( referenceOnlyPoints.size() )
{
getSnapManager().SetReferenceOnlyPoints( std::move( referenceOnlyPoints ) );
}
// Let the manager handle it
getSnapManager().GetConstructionManager().ProposeConstructionItems(
std::move( constructionItemsBatch ), aIsPersistent );
getSnapManager().GetConstructionManager().ProposeConstructionItems( std::move( constructionItemsBatch ),
aIsPersistent );
}
@ -554,6 +536,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
if( KIGFX::ANCHOR_DEBUG* ad = enableAndGetAnchorDebug(); ad )
{
ad->ClearAnchors();
for( const ANCHOR& anchor : m_anchors )
ad->AddAnchor( anchor.pos );
@ -563,6 +546,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
// The distance to the nearest snap point, if any
std::optional<int> snapDist;
if( nearest )
snapDist = nearest->Distance( aOrigin );
@ -571,41 +555,40 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
SNAP_MANAGER& snapManager = getSnapManager();
SNAP_LINE_MANAGER& snapLineManager = snapManager.GetSnapLineManager();
const auto ptIsReferenceOnly = [&]( const VECTOR2I& aPt )
{
const std::vector<VECTOR2I>& referenceOnlyPoints = snapManager.GetReferenceOnlyPoints();
return std::find( referenceOnlyPoints.begin(), referenceOnlyPoints.end(), aPt )
!= referenceOnlyPoints.end();
};
const auto proposeConstructionForItems = [&]( const std::vector<EDA_ITEM*>& aItems )
{
// Add any involved item as a temporary construction item
// (de-duplication with existing construction items is handled later)
std::vector<BOARD_ITEM*> items;
for( EDA_ITEM* item : aItems )
{
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
const auto ptIsReferenceOnly =
[&]( const VECTOR2I& aPt )
{
const std::vector<VECTOR2I>& referenceOnlyPoints = snapManager.GetReferenceOnlyPoints();
return std::find( referenceOnlyPoints.begin(), referenceOnlyPoints.end(), aPt )
!= referenceOnlyPoints.end();
};
// Null items are allowed to arrive here as they represent geometry that isn't
// specifically tied to a board item. For example snap lines from some
// other anchor.
// But they don't produce new construction items.
if( boardItem )
const auto proposeConstructionForItems =
[&]( const std::vector<EDA_ITEM*>& aItems )
{
if( m_magneticSettings->allLayers
|| ( ( aLayers & boardItem->GetLayerSet() ).any() ) )
// Add any involved item as a temporary construction item
// (de-duplication with existing construction items is handled later)
std::vector<BOARD_ITEM*> items;
for( EDA_ITEM* item : aItems )
{
items.push_back( boardItem );
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
// Null items are allowed to arrive here as they represent geometry that isn't
// specifically tied to a board item. For example snap lines from some
// other anchor.
// But they don't produce new construction items.
if( boardItem )
{
if( m_magneticSettings->allLayers || ( ( aLayers & boardItem->GetLayerSet() ).any() ) )
items.push_back( boardItem );
}
}
}
}
// Temporary construction items are not persistent and don't
// overlay the items themselves (as the items will not be moved)
AddConstructionItems( items, true, false );
};
// Temporary construction items are not persistent and don't
// overlay the items themselves (as the items will not be moved)
AddConstructionItems( items, true, false );
};
bool snapValid = false;
@ -631,9 +614,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
// (we don't snap to reference points, but we can use them to update the snap line,
// without actually snapping)
if( !ptIsReferenceOnly( *snapLineSnap ) )
{
return *snapLineSnap;
}
}
}
@ -658,15 +639,13 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
// This is to make construction items less intrusive and more
// a result of user intent.
if( !anchorIsConstructed )
{
proposeConstructionForItems( nearest->items );
}
const auto shouldAcceptAnchor = [&]( const ANCHOR& aAnchor )
{
// If no extension snaps are enabled, don't inhibit
static const bool haveExtensions =
ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps;
static const bool haveExtensions = ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps;
if( !haveExtensions )
return true;
@ -677,8 +656,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
// This is an area most likely to be controversial/need tuning,
// as some users will think it's fiddly; without 'activation', others will
// think the snaps are intrusive.
bool allRealAreInvolved =
snapManager.GetConstructionManager().InvolvesAllGivenRealItems(
bool allRealAreInvolved = snapManager.GetConstructionManager().InvolvesAllGivenRealItems(
aAnchor.items );
return allRealAreInvolved;
};
@ -700,14 +678,15 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
}
else
{
static const bool canActivateByHitTest =
ADVANCED_CFG::GetCfg().m_ExtensionSnapActivateOnHover;
static const bool canActivateByHitTest = ADVANCED_CFG::GetCfg().m_ExtensionSnapActivateOnHover;
if( canActivateByHitTest )
{
// An exact hit on an item, even if not near a snap point
// If it's tool hard to hit by hover, this can be increased
// to make it non-exact.
const int hoverAccuracy = 0;
for( BOARD_ITEM* item : visibleItems )
{
if( item->HitTest( aOrigin, hoverAccuracy ) )
@ -726,12 +705,10 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a
// but they're useful when there isn't a grid to snap to
if( !m_enableGrid )
{
OPT_VECTOR2I nearestPointOnAnElement =
GetNearestPoint( m_pointOnLineCandidates, aOrigin );
OPT_VECTOR2I nearestPointOnAnElement = GetNearestPoint( m_pointOnLineCandidates, aOrigin );
// Got any nearest point - snap if in range
if( nearestPointOnAnElement
&& nearestPointOnAnElement->Distance( aOrigin ) <= snapRange )
if( nearestPointOnAnElement && nearestPointOnAnElement->Distance( aOrigin ) <= snapRange )
{
updateSnapPoint( { *nearestPointOnAnElement, POINT_TYPE::PT_ON_ELEMENT } );
@ -954,49 +931,46 @@ void PCB_GRID_HELPER::computeAnchors( const std::vector<BOARD_ITEM*>& aItems,
const bool excludeGraphics = aSelectionFilter && !aSelectionFilter->graphics;
const bool excludeTracks = aSelectionFilter && !aSelectionFilter->tracks;
const auto itemIsSnappable = [&]( const BOARD_ITEM& aItem )
{
// If we are filtering by layers, check if the item matches
if( aMatchLayers )
{
return m_magneticSettings->allLayers
|| ( ( *aMatchLayers & aItem.GetLayerSet() ).any() );
}
return true;
};
const auto processItem = [&]( BOARD_ITEM& item )
{
// Don't even process the item if it doesn't match the layers
if( !itemIsSnappable( item ) )
{
return;
}
const auto itemIsSnappable =
[&]( const BOARD_ITEM& aItem )
{
// If we are filtering by layers, check if the item matches
if( aMatchLayers )
return m_magneticSettings->allLayers || ( ( *aMatchLayers & aItem.GetLayerSet() ).any() );
// First, add all the key points of the item itself
computeAnchors( &item, aRefPos, aFrom, aSelectionFilter );
return true;
};
// If we are computing intersections, construct the relevant intersectables
// Points on elements also use the intersectables.
if( computeIntersections || computePointsOnElements )
{
std::optional<INTERSECTABLE_GEOM> intersectableGeom;
if( !excludeGraphics
&& ( item.Type() == PCB_SHAPE_T || item.Type() == PCB_REFERENCE_IMAGE_T ) )
{
intersectableGeom = GetBoardIntersectable( item );
}
else if( !excludeTracks && ( item.Type() == PCB_TRACE_T || item.Type() == PCB_ARC_T ) )
const auto processItem =
[&]( BOARD_ITEM& item )
{
intersectableGeom = GetBoardIntersectable( item );
}
// Don't even process the item if it doesn't match the layers
if( !itemIsSnappable( item ) )
return;
if( intersectableGeom )
{
intersectables.emplace_back( &item, *intersectableGeom );
}
}
};
// First, add all the key points of the item itself
computeAnchors( &item, aRefPos, aFrom, aSelectionFilter );
// If we are computing intersections, construct the relevant intersectables
// Points on elements also use the intersectables.
if( computeIntersections || computePointsOnElements )
{
std::optional<INTERSECTABLE_GEOM> intersectableGeom;
if( !excludeGraphics
&& ( item.Type() == PCB_SHAPE_T || item.Type() == PCB_REFERENCE_IMAGE_T ) )
{
intersectableGeom = GetBoardIntersectable( item );
}
else if( !excludeTracks && ( item.Type() == PCB_TRACE_T || item.Type() == PCB_ARC_T ) )
{
intersectableGeom = GetBoardIntersectable( item );
}
if( intersectableGeom )
intersectables.emplace_back( &item, *intersectableGeom );
}
};
for( BOARD_ITEM* item : aItems )
{
@ -1080,6 +1054,7 @@ void PCB_GRID_HELPER::computeAnchors( const std::vector<BOARD_ITEM*>& aItems,
// The intersectables can also be used for fall-back snapping to "point on line"
// snaps if no other snap is found
m_pointOnLineCandidates.clear();
if( computePointsOnElements )
{
// For the moment, it's trivial to make a NEARABLE from an INTERSECTABLE,
@ -1176,144 +1151,143 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
};
// As defaults, these are probably reasonable to avoid spamming key points
const KIGEOM::OVAL_KEY_POINT_FLAGS ovalKeyPointFlags =
KIGEOM::OVAL_CENTER | KIGEOM::OVAL_CAP_TIPS | KIGEOM::OVAL_SIDE_MIDPOINTS
| KIGEOM::OVAL_CARDINAL_EXTREMES;
auto handlePadShape = [&]( PAD* aPad, PCB_LAYER_ID aLayer )
{
addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER );
/// If we are getting a drag point, we don't want to center the edge of pads
if( aFrom )
return;
switch( aPad->GetShape( aLayer ) )
{
case PAD_SHAPE::CIRCLE:
{
const CIRCLE circle( aPad->ShapePos( aLayer ), aPad->GetSizeX() / 2 );
const KIGEOM::OVAL_KEY_POINT_FLAGS ovalKeyPointFlags = KIGEOM::OVAL_CENTER
| KIGEOM::OVAL_CAP_TIPS
| KIGEOM::OVAL_SIDE_MIDPOINTS
| KIGEOM::OVAL_CARDINAL_EXTREMES;
for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) )
auto handlePadShape =
[&]( PAD* aPad, PCB_LAYER_ID aLayer )
{
addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types );
}
addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER );
break;
}
case PAD_SHAPE::OVAL:
{
const OVAL oval( aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() );
for( const TYPED_POINT2I& pt : KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ) )
{
addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types );
}
/// If we are getting a drag point, we don't want to center the edge of pads
if( aFrom )
return;
break;
}
case PAD_SHAPE::RECTANGLE:
case PAD_SHAPE::TRAPEZOID:
case PAD_SHAPE::ROUNDRECT:
case PAD_SHAPE::CHAMFERED_RECT:
{
VECTOR2I half_size( aPad->GetSize( aLayer ) / 2 );
VECTOR2I trap_delta( 0, 0 );
switch( aPad->GetShape( aLayer ) )
{
case PAD_SHAPE::CIRCLE:
{
const CIRCLE circle( aPad->ShapePos( aLayer ), aPad->GetSizeX() / 2 );
if( aPad->GetShape( aLayer ) == PAD_SHAPE::TRAPEZOID )
trap_delta = aPad->GetDelta( aLayer ) / 2;
for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) )
addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types );
SHAPE_LINE_CHAIN corners;
break;
}
case PAD_SHAPE::OVAL:
{
const OVAL oval( aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() );
corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
corners.SetClosed( true );
for( const TYPED_POINT2I& pt : KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ) )
addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types );
corners.Rotate( aPad->GetOrientation() );
corners.Move( aPad->ShapePos( aLayer ) );
break;
}
case PAD_SHAPE::RECTANGLE:
case PAD_SHAPE::TRAPEZOID:
case PAD_SHAPE::ROUNDRECT:
case PAD_SHAPE::CHAMFERED_RECT:
{
VECTOR2I half_size( aPad->GetSize( aLayer ) / 2 );
VECTOR2I trap_delta( 0, 0 );
for( std::size_t ii = 0; ii < corners.GetSegmentCount(); ++ii )
{
const SEG& seg = corners.GetSegment( ii );
addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER );
addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_MID );
if( aPad->GetShape( aLayer ) == PAD_SHAPE::TRAPEZOID )
trap_delta = aPad->GetDelta( aLayer ) / 2;
if( ii == corners.GetSegmentCount() - 1 )
addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER );
}
SHAPE_LINE_CHAIN corners;
break;
}
corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
corners.SetClosed( true );
default:
{
const auto& outline = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
corners.Rotate( aPad->GetOrientation() );
corners.Move( aPad->ShapePos( aLayer ) );
if( !outline->IsEmpty() )
{
for( const VECTOR2I& pt : outline->Outline( 0 ).CPoints() )
addAnchor( pt, OUTLINE | SNAPPABLE, aPad );
}
for( std::size_t ii = 0; ii < corners.GetSegmentCount(); ++ii )
{
const SEG& seg = corners.GetSegment( ii );
addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER );
addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_MID );
break;
}
}
if( ii == corners.GetSegmentCount() - 1 )
addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER );
}
if( aPad->HasHole() )
{
// Holes are at the pad centre (it's the shape that may be offset)
const VECTOR2I hole_pos = aPad->GetPosition();
const VECTOR2I hole_size = aPad->GetDrillSize();
break;
}
std::vector<TYPED_POINT2I> snap_pts;
default:
{
const auto& outline = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
if( hole_size.x == hole_size.y )
{
// Circle
const CIRCLE circle( hole_pos, hole_size.x / 2 );
snap_pts = KIGEOM::GetCircleKeyPoints( circle, true );
}
else
{
// Oval
if( !outline->IsEmpty() )
{
for( const VECTOR2I& pt : outline->Outline( 0 ).CPoints() )
addAnchor( pt, OUTLINE | SNAPPABLE, aPad );
}
// For now there's no way to have an off-angle hole, so this is the
// same as the pad. In future, this may not be true:
// https://gitlab.com/kicad/code/kicad/-/issues/4124
const OVAL oval( hole_size, hole_pos, aPad->GetOrientation() );
snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags );
}
break;
}
}
for( const TYPED_POINT2I& snap_pt : snap_pts )
addAnchor( snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types );
}
};
if( aPad->HasHole() )
{
// Holes are at the pad centre (it's the shape that may be offset)
const VECTOR2I hole_pos = aPad->GetPosition();
const VECTOR2I hole_size = aPad->GetDrillSize();
const auto addRectPoints = [&]( const BOX2I& aBox, EDA_ITEM& aRelatedItem )
{
const VECTOR2I topRight( aBox.GetRight(), aBox.GetTop() );
const VECTOR2I bottomLeft( aBox.GetLeft(), aBox.GetBottom() );
std::vector<TYPED_POINT2I> snap_pts;
const SEG first( aBox.GetOrigin(), topRight );
const SEG second( topRight, aBox.GetEnd() );
const SEG third( aBox.GetEnd(), bottomLeft );
const SEG fourth( bottomLeft, aBox.GetOrigin() );
if( hole_size.x == hole_size.y )
{
// Circle
const CIRCLE circle( hole_pos, hole_size.x / 2 );
snap_pts = KIGEOM::GetCircleKeyPoints( circle, true );
}
else
{
// Oval
const int snapFlags = CORNER | SNAPPABLE;
// For now there's no way to have an off-angle hole, so this is the
// same as the pad. In future, this may not be true:
// https://gitlab.com/kicad/code/kicad/-/issues/4124
const OVAL oval( hole_size, hole_pos, aPad->GetOrientation() );
snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags );
}
addAnchor( aBox.GetCenter(), snapFlags, &aRelatedItem, POINT_TYPE::PT_CENTER );
for( const TYPED_POINT2I& snap_pt : snap_pts )
addAnchor( snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types );
}
};
addAnchor( first.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( first.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( second.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( second.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( third.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( third.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( fourth.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( fourth.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
};
const auto addRectPoints =
[&]( const BOX2I& aBox, EDA_ITEM& aRelatedItem )
{
const VECTOR2I topRight( aBox.GetRight(), aBox.GetTop() );
const VECTOR2I bottomLeft( aBox.GetLeft(), aBox.GetBottom() );
const SEG first( aBox.GetOrigin(), topRight );
const SEG second( topRight, aBox.GetEnd() );
const SEG third( aBox.GetEnd(), bottomLeft );
const SEG fourth( bottomLeft, aBox.GetOrigin() );
const int snapFlags = CORNER | SNAPPABLE;
addAnchor( aBox.GetCenter(), snapFlags, &aRelatedItem, POINT_TYPE::PT_CENTER );
addAnchor( first.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( first.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( second.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( second.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( third.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( third.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
addAnchor( fourth.A, snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER );
addAnchor( fourth.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID );
};
const auto handleShape =
[&]( PCB_SHAPE* shape )
@ -1329,26 +1303,18 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
addAnchor( start, ORIGIN | SNAPPABLE, shape, POINT_TYPE::PT_CENTER );
addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape,
POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape,
POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape,
POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape,
POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT );
addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT );
break;
}
case SHAPE_T::ARC:
addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape,
POINT_TYPE::PT_END );
addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape,
POINT_TYPE::PT_END );
addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape,
POINT_TYPE::PT_MID );
addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape,
POINT_TYPE::PT_CENTER );
addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END );
addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END );
addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_MID );
addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape, POINT_TYPE::PT_CENTER );
break;
case SHAPE_T::RECTANGLE:
@ -1360,8 +1326,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
case SHAPE_T::SEGMENT:
addAnchor( start, CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END );
addAnchor( end, CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END );
addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape,
POINT_TYPE::PT_MID );
addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_MID );
break;
case SHAPE_T::POLY:
@ -1423,7 +1388,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
if( !isHighContrast
|| PadstackUniqueLayerAppliesToLayer( pad->Padstack(), aLayer,
activeHighContrastPrimaryLayer ) )
{
handlePadShape( pad, aLayer );
}
} );
}
@ -1467,7 +1434,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
if( !isHighContrast
|| PadstackUniqueLayerAppliesToLayer( pad->Padstack(), aLayer,
activeHighContrastPrimaryLayer ) )
{
handlePadShape( pad, aLayer );
}
} );
}
@ -1567,8 +1536,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
case PCB_MARKER_T:
case PCB_TARGET_T:
addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem,
POINT_TYPE::PT_CENTER );
addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, POINT_TYPE::PT_CENTER );
break;
case PCB_VIA_T:
@ -1584,8 +1552,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
}
if( checkVisibility( aItem ) )
addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem,
POINT_TYPE::PT_CENTER );
addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, POINT_TYPE::PT_CENTER );
break;
@ -1703,10 +1670,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
if( checkVisibility( aItem ) )
{
const PCB_REFERENCE_IMAGE& image =
static_cast<const PCB_REFERENCE_IMAGE&>( *aItem );
const REFERENCE_IMAGE& refImg = image.GetReferenceImage();
const BOX2I bbox = refImg.GetBoundingBox();
const PCB_REFERENCE_IMAGE& image = static_cast<const PCB_REFERENCE_IMAGE&>( *aItem );
const REFERENCE_IMAGE& refImg = image.GetReferenceImage();
const BOX2I bbox = refImg.GetBoundingBox();
addRectPoints( bbox, *aItem );
@ -1748,6 +1714,7 @@ PCB_GRID_HELPER::ANCHOR* PCB_GRID_HELPER::nearestAnchor( const VECTOR2I& aPos, i
else
{
const double dist = anchor.pos.SquaredDistance( aPos );
if( dist < minDist )
{
// New minimum distance

3
pcbnew/tools/pcb_grid_helper.h

@ -147,7 +147,8 @@ private:
void computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom,
const PCB_SELECTION_FILTER_OPTIONS* aSelectionFilter );
MAGNETIC_SETTINGS* m_magneticSettings;
private:
MAGNETIC_SETTINGS* m_magneticSettings;
std::vector<NEARABLE_GEOM> m_pointOnLineCandidates;
};

Loading…
Cancel
Save