98 const std::vector<T*>& aNew )
100 struct MATCH_CANDIDATE
107 std::vector<MATCH_CANDIDATE> candidates;
109 for(
T* existing : aExisting )
111 for(
T* updated : aNew )
113 if( existing->Type() != updated->Type() )
116 double similarity = existing->Similarity( *updated );
118 if constexpr( std::is_same_v<T, PAD> )
120 if( existing->GetNumber() == updated->GetNumber() )
124 if( similarity <= 0.0 )
127 candidates.push_back( { existing, updated, similarity } );
131 std::sort( candidates.begin(), candidates.end(),
132 [](
const MATCH_CANDIDATE& a,
const MATCH_CANDIDATE& b )
134 if( a.score != b.score )
135 return a.score > b.score;
137 if( a.existing != b.existing )
138 return a.existing < b.existing;
140 return a.updated < b.updated;
143 std::vector<std::pair<T*, T*>> matches;
144 matches.reserve( candidates.size() );
146 std::unordered_set<T*> matchedExisting;
147 std::unordered_set<T*> matchedNew;
149 for(
const MATCH_CANDIDATE& candidate : candidates )
151 if( matchedExisting.find( candidate.existing ) != matchedExisting.end() )
154 if( matchedNew.find( candidate.updated ) != matchedNew.end() )
157 matchedExisting.insert( candidate.existing );
158 matchedNew.insert( candidate.updated );
159 matches.emplace_back( candidate.existing, candidate.updated );
167 bool matchPadPositions,
168 bool deleteExtraTexts,
169 bool resetTextLayers,
170 bool resetTextEffects,
171 bool resetTextPositions,
172 bool resetTextContent,
173 bool resetFabricationAttrs,
174 bool resetClearanceOverrides,
180 bool dummyBool =
false;
183 aUpdated = &dummyBool;
202 if( matchPadPositions )
206 position += posShift;
207 orientation += angleShift;
219 if( !resetTransform )
237 std::vector<PAD*> oldPads;
238 oldPads.reserve( aExisting->
Pads().size() );
241 oldPads.push_back(
pad );
243 std::vector<PAD*> newPads;
244 newPads.reserve( aNew->
Pads().size() );
247 newPads.push_back(
pad );
250 std::unordered_set<PAD*> matchedNewPads;
252 for(
const auto& match : padMatches )
254 PAD* oldPad = match.first;
255 PAD* newPad = match.second;
257 matchedNewPads.insert( newPad );
269 for(
PAD* newPad : aNew->
Pads() )
271 if( matchedNewPads.find( newPad ) != matchedNewPads.end() )
278 std::vector<BOARD_ITEM*> oldDrawings;
282 oldDrawings.push_back( item );
284 std::vector<BOARD_ITEM*> newDrawings;
288 newDrawings.push_back( item );
291 std::unordered_map<BOARD_ITEM*, BOARD_ITEM*> oldToNewDrawings;
292 std::unordered_set<BOARD_ITEM*> matchedNewDrawings;
294 for(
const auto& match : drawingMatches )
299 oldToNewDrawings[ oldItem ] = newItem;
300 matchedNewDrawings.insert( newItem );
306 if( matchedNewDrawings.find( newItem ) == matchedNewDrawings.end() )
307 newItem->ResetUuid();
310 std::vector<ZONE*> oldZones;
311 oldZones.reserve( aExisting->
Zones().size() );
314 oldZones.push_back( zone );
316 std::vector<ZONE*> newZones;
317 newZones.reserve( aNew->
Zones().size() );
320 newZones.push_back( zone );
323 std::unordered_set<ZONE*> matchedNewZones;
325 for(
const auto& match : zoneMatches )
327 ZONE* oldZone = match.first;
328 ZONE* newZone = match.second;
330 matchedNewZones.insert( newZone );
334 for(
ZONE* newZone : newZones )
336 if( matchedNewZones.find( newZone ) == matchedNewZones.end() )
337 newZone->ResetUuid();
340 std::vector<PCB_POINT*> oldPoints;
341 oldPoints.reserve( aExisting->
Points().size() );
344 oldPoints.push_back( point );
346 std::vector<PCB_POINT*> newPoints;
347 newPoints.reserve( aNew->
Points().size() );
350 newPoints.push_back( point );
353 std::unordered_set<PCB_POINT*> matchedNewPoints;
355 for(
const auto& match : pointMatches )
360 matchedNewPoints.insert( newPoint );
366 if( matchedNewPoints.find( newPoint ) == matchedNewPoints.end() )
367 newPoint->ResetUuid();
370 std::vector<PCB_GROUP*> oldGroups;
371 oldGroups.reserve( aExisting->
Groups().size() );
374 oldGroups.push_back(
group );
376 std::vector<PCB_GROUP*> newGroups;
377 newGroups.reserve( aNew->
Groups().size() );
380 newGroups.push_back(
group );
383 std::unordered_set<PCB_GROUP*> matchedNewGroups;
385 for(
const auto& match : groupMatches )
390 matchedNewGroups.insert( newGroup );
396 if( matchedNewGroups.find( newGroup ) == matchedNewGroups.end() )
397 newGroup->ResetUuid();
400 std::vector<PCB_FIELD*> oldFieldsVec;
401 std::vector<PCB_FIELD*> newFieldsVec;
403 oldFieldsVec.reserve( aExisting->
GetFields().size() );
407 wxCHECK2( field,
continue );
409 if( field->IsReference() || field->IsValue() )
412 oldFieldsVec.push_back( field );
415 newFieldsVec.reserve( aNew->
GetFields().size() );
419 wxCHECK2( field,
continue );
421 if( field->IsReference() || field->IsValue() )
424 newFieldsVec.push_back( field );
428 std::unordered_map<PCB_FIELD*, PCB_FIELD*> oldToNewFields;
429 std::unordered_set<PCB_FIELD*> matchedNewFields;
431 for(
const auto& match : fieldMatches )
436 oldToNewFields[ oldField ] = newField;
437 matchedNewFields.insert( newField );
441 for(
PCB_FIELD* newField : newFieldsVec )
443 if( matchedNewFields.find( newField ) == matchedNewFields.end() )
444 newField->ResetUuid();
447 std::unordered_map<PCB_TEXT*, PCB_TEXT*> oldToNewTexts;
449 for(
const auto& match : drawingMatches )
454 if( oldText && newText )
455 oldToNewTexts[ oldText ] = newText;
458 std::set<PCB_TEXT*> handledTextItems;
472 auto textMatchIt = oldToNewTexts.find( oldTextItem );
474 if( textMatchIt != oldToNewTexts.end() )
475 newTextItem = textMatchIt->second;
479 handledTextItems.insert( newTextItem );
480 processTextItem( *oldTextItem, *newTextItem, posShift, angleShift, resetTextContent, resetTextLayers,
481 resetTextEffects, resetTextPositions, aUpdated );
483 else if( deleteExtraTexts )
489 newTextItem =
static_cast<PCB_TEXT*
>( oldTextItem->
Clone() );
490 handledTextItems.insert( newTextItem );
491 aNew->
Add( newTextItem );
507 if( !handledTextItems.contains( newTextItem ) )
517 resetTextEffects, resetTextPositions, aUpdated );
524 resetTextLayers, resetTextEffects, resetTextPositions, aUpdated );
526 std::set<PCB_FIELD*> handledFields;
531 wxCHECK2( oldField,
continue );
534 if( oldField->IsReference() || oldField->IsValue() )
539 auto fieldMatchIt = oldToNewFields.find( oldField );
541 if( fieldMatchIt != oldToNewFields.end() )
542 newField = fieldMatchIt->second;
546 handledFields.insert( newField );
547 processTextItem( *oldField, *newField, posShift, angleShift, resetTextContent, resetTextLayers,
548 resetTextEffects, resetTextPositions, aUpdated );
550 else if( deleteExtraTexts )
557 handledFields.insert( newField );
558 aNew->
Add( newField );
565 wxCHECK2( newField,
continue );
568 if( newField->IsReference() || newField->IsValue() )
571 if( !handledFields.contains( newField ) )
578 if( resetFabricationAttrs )
590 if( resetClearanceOverrides )
618 if( aNew->
Models().size() != aExisting->
Models().size() )
624 for(
size_t ii = 0; ii < aNew->
Models().size(); ++ii )
662 if( *aUpdated ==
false )
669 aCommit.
Remove( aExisting );
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.