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,
179 bool dummyBool =
false;
182 aUpdated = &dummyBool;
201 if( matchPadPositions )
205 position += posShift;
206 orientation += angleShift;
224 std::vector<PAD*> oldPads;
225 oldPads.reserve( aExisting->
Pads().size() );
228 oldPads.push_back(
pad );
230 std::vector<PAD*> newPads;
231 newPads.reserve( aNew->
Pads().size() );
234 newPads.push_back(
pad );
237 std::unordered_set<PAD*> matchedNewPads;
239 for(
const auto& match : padMatches )
241 PAD* oldPad = match.first;
242 PAD* newPad = match.second;
244 matchedNewPads.insert( newPad );
256 for(
PAD* newPad : aNew->
Pads() )
258 if( matchedNewPads.find( newPad ) != matchedNewPads.end() )
265 std::vector<BOARD_ITEM*> oldDrawings;
269 oldDrawings.push_back( item );
271 std::vector<BOARD_ITEM*> newDrawings;
275 newDrawings.push_back( item );
278 std::unordered_map<BOARD_ITEM*, BOARD_ITEM*> oldToNewDrawings;
279 std::unordered_set<BOARD_ITEM*> matchedNewDrawings;
281 for(
const auto& match : drawingMatches )
286 oldToNewDrawings[ oldItem ] = newItem;
287 matchedNewDrawings.insert( newItem );
293 if( matchedNewDrawings.find( newItem ) == matchedNewDrawings.end() )
294 newItem->ResetUuid();
297 std::vector<ZONE*> oldZones;
298 oldZones.reserve( aExisting->
Zones().size() );
301 oldZones.push_back( zone );
303 std::vector<ZONE*> newZones;
304 newZones.reserve( aNew->
Zones().size() );
307 newZones.push_back( zone );
310 std::unordered_set<ZONE*> matchedNewZones;
312 for(
const auto& match : zoneMatches )
314 ZONE* oldZone = match.first;
315 ZONE* newZone = match.second;
317 matchedNewZones.insert( newZone );
321 for(
ZONE* newZone : newZones )
323 if( matchedNewZones.find( newZone ) == matchedNewZones.end() )
324 newZone->ResetUuid();
327 std::vector<PCB_POINT*> oldPoints;
328 oldPoints.reserve( aExisting->
Points().size() );
331 oldPoints.push_back( point );
333 std::vector<PCB_POINT*> newPoints;
334 newPoints.reserve( aNew->
Points().size() );
337 newPoints.push_back( point );
340 std::unordered_set<PCB_POINT*> matchedNewPoints;
342 for(
const auto& match : pointMatches )
347 matchedNewPoints.insert( newPoint );
353 if( matchedNewPoints.find( newPoint ) == matchedNewPoints.end() )
354 newPoint->ResetUuid();
357 std::vector<PCB_GROUP*> oldGroups;
358 oldGroups.reserve( aExisting->
Groups().size() );
361 oldGroups.push_back(
group );
363 std::vector<PCB_GROUP*> newGroups;
364 newGroups.reserve( aNew->
Groups().size() );
367 newGroups.push_back(
group );
370 std::unordered_set<PCB_GROUP*> matchedNewGroups;
372 for(
const auto& match : groupMatches )
377 matchedNewGroups.insert( newGroup );
383 if( matchedNewGroups.find( newGroup ) == matchedNewGroups.end() )
384 newGroup->ResetUuid();
387 std::vector<PCB_FIELD*> oldFieldsVec;
388 std::vector<PCB_FIELD*> newFieldsVec;
390 oldFieldsVec.reserve( aExisting->
GetFields().size() );
394 wxCHECK2( field,
continue );
396 if( field->IsReference() || field->IsValue() )
399 oldFieldsVec.push_back( field );
402 newFieldsVec.reserve( aNew->
GetFields().size() );
406 wxCHECK2( field,
continue );
408 if( field->IsReference() || field->IsValue() )
411 newFieldsVec.push_back( field );
415 std::unordered_map<PCB_FIELD*, PCB_FIELD*> oldToNewFields;
416 std::unordered_set<PCB_FIELD*> matchedNewFields;
418 for(
const auto& match : fieldMatches )
423 oldToNewFields[ oldField ] = newField;
424 matchedNewFields.insert( newField );
428 for(
PCB_FIELD* newField : newFieldsVec )
430 if( matchedNewFields.find( newField ) == matchedNewFields.end() )
431 newField->ResetUuid();
434 std::unordered_map<PCB_TEXT*, PCB_TEXT*> oldToNewTexts;
436 for(
const auto& match : drawingMatches )
441 if( oldText && newText )
442 oldToNewTexts[ oldText ] = newText;
445 std::set<PCB_TEXT*> handledTextItems;
459 auto textMatchIt = oldToNewTexts.find( oldTextItem );
461 if( textMatchIt != oldToNewTexts.end() )
462 newTextItem = textMatchIt->second;
466 handledTextItems.insert( newTextItem );
467 processTextItem( *oldTextItem, *newTextItem, posShift, angleShift, resetTextContent, resetTextLayers,
468 resetTextEffects, resetTextPositions, aUpdated );
470 else if( deleteExtraTexts )
476 newTextItem =
static_cast<PCB_TEXT*
>( oldTextItem->
Clone() );
477 handledTextItems.insert( newTextItem );
478 aNew->
Add( newTextItem );
494 if( !handledTextItems.contains( newTextItem ) )
504 resetTextEffects, resetTextPositions, aUpdated );
511 resetTextLayers, resetTextEffects, resetTextPositions, aUpdated );
513 std::set<PCB_FIELD*> handledFields;
518 wxCHECK2( oldField,
continue );
521 if( oldField->IsReference() || oldField->IsValue() )
526 auto fieldMatchIt = oldToNewFields.find( oldField );
528 if( fieldMatchIt != oldToNewFields.end() )
529 newField = fieldMatchIt->second;
533 handledFields.insert( newField );
534 processTextItem( *oldField, *newField, posShift, angleShift, resetTextContent, resetTextLayers,
535 resetTextEffects, resetTextPositions, aUpdated );
537 else if( deleteExtraTexts )
544 handledFields.insert( newField );
545 aNew->
Add( newField );
552 wxCHECK2( newField,
continue );
555 if( newField->IsReference() || newField->IsValue() )
558 if( !handledFields.contains( newField ) )
565 if( resetFabricationAttrs )
577 if( resetClearanceOverrides )
605 if( aNew->
Models().size() != aExisting->
Models().size() )
611 for(
size_t ii = 0; ii < aNew->
Models().size(); ++ii )
649 if( *aUpdated ==
false )
656 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.