25#include <unordered_map>
55 const auto getUniquelyNumberedPads =
56 [](
const FOOTPRINT& fp ) -> std::unordered_map<wxString, VECTOR2I>
58 std::unordered_map<wxString, VECTOR2I>
result;
59 std::unordered_set<wxString> seenDuplicate;
61 for(
PAD*
pad : fp.Pads() )
63 const wxString& number =
pad->GetNumber();
67 if( seenDuplicate.find( number ) != seenDuplicate.end() )
75 seenDuplicate.insert( number );
82 result[number] =
pad->GetLibraryPosition();
88 std::unordered_map<wxString, VECTOR2I> existingPads = getUniquelyNumberedPads( aExisting );
89 std::unordered_map<wxString, VECTOR2I> newPads = getUniquelyNumberedPads( aNew );
97 for(
auto& [number, pos] : newPads )
101 std::vector<VECTOR2I> existingPoints;
102 std::vector<VECTOR2I> newPoints;
106 for(
const auto& [number, pos] : existingPads )
108 auto it = newPads.find( number );
110 if( it == newPads.end() )
113 existingPoints.push_back( pos );
114 newPoints.push_back( it->second );
119 std::optional<ITEM_REALIGNER_BASE::TRANSFORM> transform =
122 if( !transform.has_value() )
131 aAngleShift = transform->m_Rotation;
138 const FOOTPRINT& aFootprint,
const std::function<
void(
const wxString& )>& aErrorHandler )
143 if( setAttr && likelyAttr && setAttr != likelyAttr )
150 msg.Printf(
_(
"(expected 'Through hole'; actual '%s')" ), aFootprint.
GetTypeName() );
153 msg.Printf(
_(
"(expected 'SMD'; actual '%s')" ), aFootprint.
GetTypeName() );
158 aErrorHandler( msg );
166 if( aErrorHandler ==
nullptr )
174 aErrorHandler( *
pad, aResult );
182 const std::function<
void(
const PAD*,
const PAD*,
int aErrorCode,
185 std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
191 for(
PAD* other : aFootprint.
Pads() )
200 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
203 if( checkedPairs.find( { a, b } ) == checkedPairs.end() )
205 checkedPairs[ { a, b } ] = 1;
207 if(
pad->HasDrilledHole() && other->HasDrilledHole() )
211 if(
pad->GetPosition() == other->GetPosition() )
219 std::shared_ptr<SHAPE_SEGMENT> holeB = other->GetEffectiveHoleShape(
UNDEFINED_LAYER,
222 if( holeA->Collide( holeB->GetSeg(), 0 ) )
233 if(
pad->GetBoundingBox().Intersects( other->GetBoundingBox() ) )
237 for(
PCB_LAYER_ID l :
pad->Padstack().RelevantShapeLayers( other->Padstack() ) )
239 SHAPE* padShape =
pad->GetEffectiveShape( l ).get();
240 SHAPE* otherShape = other->GetEffectiveShape( l ).get();
242 if( padShape->
Collide( otherShape, 0,
nullptr, &pos ) )
264 std::vector<BOARD_ITEM*> copperItems;
268 if( item->IsOnCopperLayer() )
269 copperItems.push_back( item );
275 copperItems.push_back( descendent );
282 if( !zone->GetIsRuleArea() && zone->IsOnCopperLayer() )
283 copperItems.push_back( zone );
288 if( field->IsOnCopperLayer() )
289 copperItems.push_back( field );
299 std::map<int, std::vector<const PAD*>> outlineIdxToPadsMap;
303 if( item->IsOnLayer( layer ) )
305 item->TransformShapeToPolygon( copperOutlines, layer, 0, aFootprint.
GetMaxError(),
316 for(
int ii = 0; ii < copperOutlines.
OutlineCount(); ++ii )
318 if(
pad->GetEffectiveShape( layer )->Collide( &copperOutlines.
Outline( ii ), 0 ) )
319 outlineIdxToPadsMap[ ii ].emplace_back(
pad );
326 for(
const auto& [ outlineIdx, pads ] : outlineIdxToPadsMap )
328 if( pads.size() > 1 )
330 const PAD* firstPad = pads[0];
331 int firstGroupIdx = padNumberToGroupIdxMap[ firstPad->
GetNumber() ];
333 for(
size_t ii = 1; ii < pads.size(); ++ii )
335 const PAD* thisPad = pads[ii];
336 int thisGroupIdx = padNumberToGroupIdxMap[ thisPad->
GetNumber() ];
338 if( thisGroupIdx < 0 || thisGroupIdx != firstGroupIdx )
347 if( item->HitTest( pos, 1 ) )
355 aErrorHandler( shortingItem, firstPad, thisPad, pos );
357 aErrorHandler( firstPad, thisPad,
nullptr, pos );
367 const FOOTPRINT& aFootprint,
const std::function<
void(
const wxString& )>& aErrorHandler )
369 std::set<wxString> padNumbers;
378 msg.Printf(
_(
"(net-tie pad group contains unknown pad number %s)" ), padNumber );
379 aErrorHandler( msg );
381 else if( !padNumbers.insert(
pad->GetNumber() ).second )
383 msg.Printf(
_(
"(pad %s appears in more than one net-tie pad group)" ), padNumber );
384 aErrorHandler( msg );
394 auto checkColliding =
401 if( !item->
IsOnLayer( silk ) || !other->IsOnLayer( mask ) )
405 std::shared_ptr<SHAPE> otherShape = other->GetEffectiveShape( mask );
409 if( itemShape->Collide( otherShape.get(), 0, &
actual, &pos ) )
410 aErrorHandler( item, other, pos );
419 checkColliding( item, other );
423 checkColliding( item,
pad );
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
virtual bool IsOnCopperLayer() const
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
This is a relatively straight-forward implementation of the ITEM_REALIGNER_BASE that should handle mo...
std::optional< TRANSFORM > GetTransform(const std::vector< VECTOR2I > &aPtsA, const std::vector< VECTOR2I > &aPtsB) const override
Compute the best fit transform to align the two sets of points.
const wxString & GetNumber() const
VECTOR2I GetPosition() const override
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
Represent a set of closed polygons.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
An abstract shape on 2D plane.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Handle a list of polygons defining a copper zone.
@ HOLE_TO_HOLE_CONSTRAINT
@ DRCE_DRILLED_HOLES_TOO_CLOSE
@ DRCE_DRILLED_HOLES_COLOCATED
static constexpr EDA_ANGLE ANGLE_0
PCB_LAYER_ID
A quick note on layer IDs:
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
void CheckPad(const PAD &aPad, const UNITS_PROVIDER &aUnitsProvider, bool aForPadProperties, const PAD_CHECK_HANDLER &aErrorHandler)
Run non-board-specific checks on a pad.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
A single finding from CheckPad().
wxString result
Test unit parsing edge cases and error handling.
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
VECTOR2< int32_t > VECTOR2I