KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_exchange_footprint.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 */
11
12#include <algorithm>
13#include <memory>
14#include <set>
15#include <type_traits>
16#include <unordered_map>
17#include <unordered_set>
18#include <vector>
19
20#include <board.h>
21#include <board_commit.h>
23#include <board_item.h>
24#include <core/mirror.h>
25#include <eda_group.h>
26#include <embedded_files.h>
27#include <footprint.h>
28#include <footprint_utils.h>
29#include <math/util.h>
30#include <netinfo.h>
31#include <pad.h>
32#include <pcb_dimension.h>
33#include <pcb_field.h>
34#include <pcb_group.h>
35#include <pcb_point.h>
36#include <pcb_text.h>
37#include <zone.h>
38
39
40static void processTextItem( const PCB_TEXT& aSrc, PCB_TEXT& aDest, const VECTOR2I& aPosShift,
41 const EDA_ANGLE& aAngleShift, bool aResetText, bool aResetTextLayers,
42 bool aResetTextEffects, bool aResetTextPositions, bool* aUpdated )
43{
44 if( aResetText )
45 *aUpdated |= aSrc.GetText() != aDest.GetText();
46 else
47 aDest.SetText( aSrc.GetText() );
48
49 if( aResetTextLayers )
50 {
51 *aUpdated |= aSrc.GetLayer() != aDest.GetLayer();
52 *aUpdated |= aSrc.IsVisible() != aDest.IsVisible();
53 }
54 else
55 {
56 aDest.SetLayer( aSrc.GetLayer() );
57 aDest.SetVisible( aSrc.IsVisible() );
58 }
59
60 VECTOR2I origPos = aDest.GetFPRelativePosition();
61
62 if( aResetTextEffects )
63 {
64 *aUpdated |= aSrc.GetHorizJustify() != aDest.GetHorizJustify();
65 *aUpdated |= aSrc.GetVertJustify() != aDest.GetVertJustify();
66 *aUpdated |= aSrc.GetTextSize() != aDest.GetTextSize();
67 *aUpdated |= aSrc.GetTextThickness() != aDest.GetTextThickness();
68 *aUpdated |= aSrc.IsKnockout() != aDest.IsKnockout();
69 aDest.KeepUpright();
70 }
71 else
72 {
73 EDA_ANGLE origAngle = aDest.GetTextAngle();
74 origAngle.Normalize();
75 aDest.SetAttributes( aSrc );
76 if( origAngle >= ANGLE_180 && aDest.IsKeepUpright() )
77 {
78 // Text is already rotated by 180 because of 'keep upright'.
79 origAngle -= ANGLE_180;
80 }
81
82 aDest.SetTextAngle( origAngle ); // apply rotation as part of position shift
83 aDest.SetIsKnockout( aSrc.IsKnockout() );
84 }
85
86 if( aResetTextPositions )
87 {
88 *aUpdated |= aSrc.GetFPRelativePosition() != origPos;
89 *aUpdated |= aSrc.GetTextAngle() != aDest.GetTextAngle();
90
91 aDest.SetFPRelativePosition( origPos );
92 }
93 else
94 {
95 VECTOR2I rotatedShift = GetRotated( aSrc.GetFPRelativePosition() - aPosShift, -aAngleShift );
96
97 aDest.SetFPRelativePosition( rotatedShift );
98 aDest.SetTextAngle( aSrc.GetTextAngle() );
99 }
100
101 aDest.SetLocked( aSrc.IsLocked() );
102 aDest.SetUuid( aSrc.m_Uuid );
103}
104
105
106template<typename T>
107static std::vector<std::pair<T*, T*>> matchItemsBySimilarity( const std::vector<T*>& aExisting,
108 const std::vector<T*>& aNew )
109{
110 struct MATCH_CANDIDATE
111 {
112 T* existing;
113 T* updated;
114 double score;
115 };
116
117 std::vector<MATCH_CANDIDATE> candidates;
118
119 for( T* existing : aExisting )
120 {
121 for( T* updated : aNew )
122 {
123 if( existing->Type() != updated->Type() )
124 continue;
125
126 double similarity = existing->Similarity( *updated );
127
128 if constexpr( std::is_same_v<T, PAD> )
129 {
130 if( existing->GetNumber() == updated->GetNumber() )
131 similarity += 2.0;
132 }
133
134 if( similarity <= 0.0 )
135 continue;
136
137 candidates.push_back( { existing, updated, similarity } );
138 }
139 }
140
141 std::sort( candidates.begin(), candidates.end(),
142 []( const MATCH_CANDIDATE& a, const MATCH_CANDIDATE& b )
143 {
144 if( a.score != b.score )
145 return a.score > b.score;
146
147 if( a.existing != b.existing )
148 return a.existing < b.existing;
149
150 return a.updated < b.updated;
151 } );
152
153 std::vector<std::pair<T*, T*>> matches;
154 matches.reserve( candidates.size() );
155
156 std::unordered_set<T*> matchedExisting;
157 std::unordered_set<T*> matchedNew;
158
159 for( const MATCH_CANDIDATE& candidate : candidates )
160 {
161 if( matchedExisting.find( candidate.existing ) != matchedExisting.end() )
162 continue;
163
164 if( matchedNew.find( candidate.updated ) != matchedNew.end() )
165 continue;
166
167 matchedExisting.insert( candidate.existing );
168 matchedNew.insert( candidate.updated );
169 matches.emplace_back( candidate.existing, candidate.updated );
170 }
171
172 return matches;
173}
174
175
177 bool matchPadPositions,
178 bool deleteExtraTexts,
179 bool resetTextLayers,
180 bool resetTextEffects,
181 bool resetTextPositions,
182 bool resetTextContent,
183 bool resetFabricationAttrs,
184 bool resetClearanceOverrides,
185 bool reset3DModels,
186 bool resetTransform,
187 bool* aUpdated )
188{
189 EDA_GROUP* parentGroup = aExisting->GetParentGroup();
190 bool dummyBool = false;
191
192 if( !aUpdated )
193 aUpdated = &dummyBool;
194
195 if( parentGroup )
196 {
197 aCommit.Modify( parentGroup->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
198 parentGroup->RemoveItem( aExisting );
199 parentGroup->AddItem( aNew );
200 }
201
202 aNew->SetParent( this );
203
204 // This is the position and angle shift to apply to the new footprint if the footprint
205 // has a change anchor point or rotation compared to the existing footprint.
206 VECTOR2I posShift( 0, 0 );
207 EDA_ANGLE angleShift = ANGLE_0;
208
209 VECTOR2I position = aExisting->GetPosition();
210 EDA_ANGLE orientation = aExisting->GetOrientation();
211
212 if( matchPadPositions )
213 {
214 if( ComputeFootprintShift( *aExisting, *aNew, posShift, angleShift ) )
215 {
216 position += posShift;
217 orientation += angleShift;
218 }
219 }
220
221 aNew->SetPosition( position );
222
223 if( aNew->GetLayer() != aExisting->GetLayer() )
225
226 if( aNew->GetOrientation() != orientation )
227 aNew->SetOrientation( orientation );
228
229 if( !resetTransform )
230 {
231 const double existingScaleX = aExisting->GetTransform().GetScaleX();
232 const double existingScaleY = aExisting->GetTransform().GetScaleY();
233
234 if( existingScaleX != aNew->GetTransform().GetScaleX()
235 || existingScaleY != aNew->GetTransform().GetScaleY() )
236 {
237 aNew->SetTransformScale( existingScaleX, existingScaleY );
238 }
239 }
240
241 aNew->SetLocked( aExisting->IsLocked() );
242
243 aNew->SetUuid( aExisting->m_Uuid );
244 aNew->Reference().SetUuid( aExisting->Reference().m_Uuid );
245 aNew->Value().SetUuid( aExisting->Value().m_Uuid );
246
247 std::vector<PAD*> oldPads;
248 oldPads.reserve( aExisting->Pads().size() );
249
250 for( PAD* pad : aExisting->Pads() )
251 oldPads.push_back( pad );
252
253 std::vector<PAD*> newPads;
254 newPads.reserve( aNew->Pads().size() );
255
256 for( PAD* pad : aNew->Pads() )
257 newPads.push_back( pad );
258
259 auto padMatches = matchItemsBySimilarity<PAD>( oldPads, newPads );
260 std::unordered_set<PAD*> matchedNewPads;
261
262 for( const auto& match : padMatches )
263 {
264 PAD* oldPad = match.first;
265 PAD* newPad = match.second;
266
267 matchedNewPads.insert( newPad );
268 newPad->SetUuid( oldPad->m_Uuid );
270 newPad->SetPinFunction( oldPad->GetPinFunction() );
271 newPad->SetPinType( oldPad->GetPinType() );
272
273 if( newPad->IsOnCopperLayer() )
274 newPad->SetNetCode( oldPad->GetNetCode() );
275 else
277 }
278
279 for( PAD* newPad : aNew->Pads() )
280 {
281 if( matchedNewPads.find( newPad ) != matchedNewPads.end() )
282 continue;
283
284 newPad->ResetUuid();
285 newPad->SetNetCode( NETINFO_LIST::UNCONNECTED );
286 }
287
288 std::vector<BOARD_ITEM*> oldDrawings;
289 oldDrawings.reserve( aExisting->GraphicalItems().size() );
290
291 for( BOARD_ITEM* item : aExisting->GraphicalItems() )
292 oldDrawings.push_back( item );
293
294 std::vector<BOARD_ITEM*> newDrawings;
295 newDrawings.reserve( aNew->GraphicalItems().size() );
296
297 for( BOARD_ITEM* item : aNew->GraphicalItems() )
298 newDrawings.push_back( item );
299
300 auto drawingMatches = matchItemsBySimilarity<BOARD_ITEM>( oldDrawings, newDrawings );
301 std::unordered_map<BOARD_ITEM*, BOARD_ITEM*> oldToNewDrawings;
302 std::unordered_set<BOARD_ITEM*> matchedNewDrawings;
303
304 for( const auto& match : drawingMatches )
305 {
306 BOARD_ITEM* oldItem = match.first;
307 BOARD_ITEM* newItem = match.second;
308
309 oldToNewDrawings[ oldItem ] = newItem;
310 matchedNewDrawings.insert( newItem );
311 newItem->SetUuid( oldItem->m_Uuid );
312 }
313
314 for( BOARD_ITEM* newItem : newDrawings )
315 {
316 if( matchedNewDrawings.find( newItem ) == matchedNewDrawings.end() )
317 newItem->ResetUuid();
318 }
319
320 std::vector<ZONE*> oldZones;
321 oldZones.reserve( aExisting->Zones().size() );
322
323 for( ZONE* zone : aExisting->Zones() )
324 oldZones.push_back( zone );
325
326 std::vector<ZONE*> newZones;
327 newZones.reserve( aNew->Zones().size() );
328
329 for( ZONE* zone : aNew->Zones() )
330 newZones.push_back( zone );
331
332 auto zoneMatches = matchItemsBySimilarity<ZONE>( oldZones, newZones );
333 std::unordered_set<ZONE*> matchedNewZones;
334
335 for( const auto& match : zoneMatches )
336 {
337 ZONE* oldZone = match.first;
338 ZONE* newZone = match.second;
339
340 matchedNewZones.insert( newZone );
341 newZone->SetUuid( oldZone->m_Uuid );
342 }
343
344 for( ZONE* newZone : newZones )
345 {
346 if( matchedNewZones.find( newZone ) == matchedNewZones.end() )
347 newZone->ResetUuid();
348 }
349
350 std::vector<PCB_POINT*> oldPoints;
351 oldPoints.reserve( aExisting->Points().size() );
352
353 for( PCB_POINT* point : aExisting->Points() )
354 oldPoints.push_back( point );
355
356 std::vector<PCB_POINT*> newPoints;
357 newPoints.reserve( aNew->Points().size() );
358
359 for( PCB_POINT* point : aNew->Points() )
360 newPoints.push_back( point );
361
362 auto pointMatches = matchItemsBySimilarity<PCB_POINT>( oldPoints, newPoints );
363 std::unordered_set<PCB_POINT*> matchedNewPoints;
364
365 for( const auto& match : pointMatches )
366 {
367 PCB_POINT* oldPoint = match.first;
368 PCB_POINT* newPoint = match.second;
369
370 matchedNewPoints.insert( newPoint );
371 newPoint->SetUuid( oldPoint->m_Uuid );
372 }
373
374 for( PCB_POINT* newPoint : newPoints )
375 {
376 if( matchedNewPoints.find( newPoint ) == matchedNewPoints.end() )
377 newPoint->ResetUuid();
378 }
379
380 std::vector<PCB_GROUP*> oldGroups;
381 oldGroups.reserve( aExisting->Groups().size() );
382
383 for( PCB_GROUP* group : aExisting->Groups() )
384 oldGroups.push_back( group );
385
386 std::vector<PCB_GROUP*> newGroups;
387 newGroups.reserve( aNew->Groups().size() );
388
389 for( PCB_GROUP* group : aNew->Groups() )
390 newGroups.push_back( group );
391
392 auto groupMatches = matchItemsBySimilarity<PCB_GROUP>( oldGroups, newGroups );
393 std::unordered_set<PCB_GROUP*> matchedNewGroups;
394
395 for( const auto& match : groupMatches )
396 {
397 PCB_GROUP* oldGroup = match.first;
398 PCB_GROUP* newGroup = match.second;
399
400 matchedNewGroups.insert( newGroup );
401 newGroup->SetUuid( oldGroup->m_Uuid );
402 }
403
404 for( PCB_GROUP* newGroup : newGroups )
405 {
406 if( matchedNewGroups.find( newGroup ) == matchedNewGroups.end() )
407 newGroup->ResetUuid();
408 }
409
410 std::vector<PCB_FIELD*> oldFieldsVec;
411 std::vector<PCB_FIELD*> newFieldsVec;
412
413 oldFieldsVec.reserve( aExisting->GetFields().size() );
414
415 for( PCB_FIELD* field : aExisting->GetFields() )
416 {
417 wxCHECK2( field, continue );
418
419 if( field->IsReference() || field->IsValue() )
420 continue;
421
422 oldFieldsVec.push_back( field );
423 }
424
425 newFieldsVec.reserve( aNew->GetFields().size() );
426
427 for( PCB_FIELD* field : aNew->GetFields() )
428 {
429 wxCHECK2( field, continue );
430
431 if( field->IsReference() || field->IsValue() )
432 continue;
433
434 newFieldsVec.push_back( field );
435 }
436
437 auto fieldMatches = matchItemsBySimilarity<PCB_FIELD>( oldFieldsVec, newFieldsVec );
438 std::unordered_map<PCB_FIELD*, PCB_FIELD*> oldToNewFields;
439 std::unordered_set<PCB_FIELD*> matchedNewFields;
440
441 for( const auto& match : fieldMatches )
442 {
443 PCB_FIELD* oldField = match.first;
444 PCB_FIELD* newField = match.second;
445
446 oldToNewFields[ oldField ] = newField;
447 matchedNewFields.insert( newField );
448 newField->SetUuid( oldField->m_Uuid );
449 }
450
451 for( PCB_FIELD* newField : newFieldsVec )
452 {
453 if( matchedNewFields.find( newField ) == matchedNewFields.end() )
454 newField->ResetUuid();
455 }
456
457 std::unordered_map<PCB_TEXT*, PCB_TEXT*> oldToNewTexts;
458
459 for( const auto& match : drawingMatches )
460 {
461 PCB_TEXT* oldText = dynamic_cast<PCB_TEXT*>( match.first );
462 PCB_TEXT* newText = dynamic_cast<PCB_TEXT*>( match.second );
463
464 if( oldText && newText )
465 oldToNewTexts[ oldText ] = newText;
466 }
467
468 std::set<PCB_TEXT*> handledTextItems;
469
470 for( BOARD_ITEM* oldItem : aExisting->GraphicalItems() )
471 {
472 PCB_TEXT* oldTextItem = dynamic_cast<PCB_TEXT*>( oldItem );
473
474 if( oldTextItem )
475 {
476 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
477 if( dynamic_cast<PCB_DIMENSION_BASE*>( oldTextItem ) )
478 continue;
479
480 PCB_TEXT* newTextItem = nullptr;
481
482 auto textMatchIt = oldToNewTexts.find( oldTextItem );
483
484 if( textMatchIt != oldToNewTexts.end() )
485 newTextItem = textMatchIt->second;
486
487 if( newTextItem )
488 {
489 handledTextItems.insert( newTextItem );
490 processTextItem( *oldTextItem, *newTextItem, posShift, angleShift, resetTextContent, resetTextLayers,
491 resetTextEffects, resetTextPositions, aUpdated );
492 }
493 else if( deleteExtraTexts )
494 {
495 *aUpdated = true;
496 }
497 else
498 {
499 newTextItem = static_cast<PCB_TEXT*>( oldTextItem->Clone() );
500 handledTextItems.insert( newTextItem );
501 aNew->Add( newTextItem );
502 }
503 }
504 }
505
506 // Check for any newly-added text items and set the update flag as appropriate
507 for( BOARD_ITEM* newItem : aNew->GraphicalItems() )
508 {
509 PCB_TEXT* newTextItem = dynamic_cast<PCB_TEXT*>( newItem );
510
511 if( newTextItem )
512 {
513 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
514 if( dynamic_cast<PCB_DIMENSION_BASE*>( newTextItem ) )
515 continue;
516
517 if( !handledTextItems.contains( newTextItem ) )
518 {
519 *aUpdated = true;
520 break;
521 }
522 }
523 }
524
525 // Copy reference. The initial text is always used, never resetted
526 processTextItem( aExisting->Reference(), aNew->Reference(), posShift, angleShift, false, resetTextLayers,
527 resetTextEffects, resetTextPositions, aUpdated );
528
529 // Copy value
530 processTextItem( aExisting->Value(), aNew->Value(), posShift, angleShift,
531 // reset value text only when it is a proxy for the footprint ID
532 // (cf replacing value "MountingHole-2.5mm" with "MountingHole-4.0mm")
533 aExisting->GetValue() == aExisting->GetFPID().GetLibItemName().wx_str(),
534 resetTextLayers, resetTextEffects, resetTextPositions, aUpdated );
535
536 std::set<PCB_FIELD*> handledFields;
537
538 // Copy fields in accordance with the reset* flags
539 for( PCB_FIELD* oldField : aExisting->GetFields() )
540 {
541 wxCHECK2( oldField, continue );
542
543 // Reference and value are already handled
544 if( oldField->IsReference() || oldField->IsValue() )
545 continue;
546
547 PCB_FIELD* newField = nullptr;
548
549 auto fieldMatchIt = oldToNewFields.find( oldField );
550
551 if( fieldMatchIt != oldToNewFields.end() )
552 newField = fieldMatchIt->second;
553
554 if( newField )
555 {
556 handledFields.insert( newField );
557 processTextItem( *oldField, *newField, posShift, angleShift, resetTextContent, resetTextLayers,
558 resetTextEffects, resetTextPositions, aUpdated );
559 }
560 else if( deleteExtraTexts )
561 {
562 *aUpdated = true;
563 }
564 else
565 {
566 newField = new PCB_FIELD( *oldField );
567 handledFields.insert( newField );
568 aNew->Add( newField );
569 }
570 }
571
572 // Check for any newly-added fields and set the update flag as appropriate
573 for( PCB_FIELD* newField : aNew->GetFields() )
574 {
575 wxCHECK2( newField, continue );
576
577 // Reference and value are already handled
578 if( newField->IsReference() || newField->IsValue() )
579 continue;
580
581 if( !handledFields.contains( newField ) )
582 {
583 *aUpdated = true;
584 break;
585 }
586 }
587
588 if( resetFabricationAttrs )
589 {
590 // We've replaced the existing footprint with the library one, so the fabrication attrs
591 // are already reset. Just set the aUpdated flag if appropriate.
592 if( aNew->GetAttributes() != aExisting->GetAttributes() )
593 *aUpdated = true;
594 }
595 else
596 {
597 aNew->SetAttributes( aExisting->GetAttributes() );
598 }
599
600 if( resetClearanceOverrides )
601 {
602 if( aExisting->AllowSolderMaskBridges() != aNew->AllowSolderMaskBridges() )
603 *aUpdated = true;
604
605 if( ( aExisting->GetLocalClearance() != aNew->GetLocalClearance() )
606 || ( aExisting->GetLocalSolderMaskMargin() != aNew->GetLocalSolderMaskMargin() )
607 || ( aExisting->GetLocalSolderPasteMargin() != aNew->GetLocalSolderPasteMargin() )
609 || ( aExisting->GetLocalZoneConnection() != aNew->GetLocalZoneConnection() ) )
610 {
611 *aUpdated = true;
612 }
613 }
614 else
615 {
616 aNew->SetLocalClearance( aExisting->GetLocalClearance() );
622 }
623
624 if( reset3DModels )
625 {
626 // We've replaced the existing footprint with the library one, so the 3D models are
627 // already reset. Just set the aUpdated flag if appropriate.
628 if( aNew->Models().size() != aExisting->Models().size() )
629 {
630 *aUpdated = true;
631 }
632 else
633 {
634 for( size_t ii = 0; ii < aNew->Models().size(); ++ii )
635 {
636 if( aNew->Models()[ii] != aExisting->Models()[ii] )
637 {
638 *aUpdated = true;
639 break;
640 }
641 }
642 }
643 }
644 else
645 {
646 // Preserve model references and all embedded model data.
647 aNew->Models() = aExisting->Models();
648
649 // Preserve extruded 3D body settings.
650 if( aExisting->HasExtrudedBody() )
651 aNew->SetExtrudedBody( std::make_unique<EXTRUDED_3D_BODY>( *aExisting->GetExtrudedBody() ) );
652 else
653 aNew->ClearExtrudedBody();
654
655 for( const auto& [name, file] : aExisting->GetEmbeddedFiles()->EmbeddedFileMap() )
656 {
658 continue;
659
660 aNew->GetEmbeddedFiles()->RemoveFile( name, true );
662 }
663 }
664
665 // Updating other parameters
666 aNew->SetPath( aExisting->GetPath() );
667 aNew->SetSheetfile( aExisting->GetSheetfile() );
668 aNew->SetSheetname( aExisting->GetSheetname() );
669 aNew->SetFilters( aExisting->GetFilters() );
670 aNew->SetStaticComponentClass( aExisting->GetComponentClass() );
671
672 if( *aUpdated == false )
673 {
674 // Check pad shapes, graphics, zones, etc. for changes
676 *aUpdated = true;
677 }
678
679 aCommit.Remove( aExisting );
680 aCommit.Add( aNew );
681
682 aNew->ClearFlags();
683}
684
const char * name
static std::vector< std::pair< T *, T * > > matchItemsBySimilarity(const std::vector< T * > &aExisting, const std::vector< T * > &aNew)
static void processTextItem(const PCB_TEXT &aSrc, PCB_TEXT &aDest, const VECTOR2I &aPosShift, const EDA_ANGLE &aAngleShift, bool aResetText, bool aResetTextLayers, bool aResetTextEffects, bool aResetTextPositions, bool *aUpdated)
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetLocalRatsnestVisible(bool aVisible)
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:85
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:295
void SetLocked(bool aLocked) override
Definition board_item.h:386
void SetUuid(const KIID &aUuid)
virtual bool IsKnockout() const
Definition board_item.h:382
bool IsLocked() const override
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:383
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:343
VECTOR2I GetFPRelativePosition() const
@ INSTANCE_TO_INSTANCE
Definition board_item.h:528
void SetFPRelativePosition(const VECTOR2I &aPos)
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool matchPadPositions, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetTextPositions=true, bool resetTextContent=true, bool resetFabricationAttrs=true, bool resetClearanceOverrides=true, bool reset3DModels=true, bool resetTransform=false, bool *aUpdated=nullptr)
Replace aExisting with aNew, preserving connectivity and metadata.
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:86
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:74
EDA_ANGLE Normalize()
Definition eda_angle.h:229
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:42
void RemoveItem(EDA_ITEM *aItem)
Remove item from group.
Definition eda_group.cpp:77
void AddItem(EDA_ITEM *aItem)
Add item to group.
Definition eda_group.cpp:58
virtual EDA_ITEM * AsEdaItem()=0
const KIID m_Uuid
Definition eda_item.h:531
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:114
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:154
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
bool IsKeepUpright() const
Definition eda_text.h:227
virtual bool IsVisible() const
Definition eda_text.h:208
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:428
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:221
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:224
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
void RemoveFile(const wxString &name, bool aErase=true)
Remove a file from the collection and frees the memory.
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
bool AllowSolderMaskBridges() const
Definition footprint.h:516
void SetPosition(const VECTOR2I &aPos) override
ZONE_CONNECTION GetLocalZoneConnection() const
Definition footprint.h:492
void SetLocked(bool isLocked) override
Set the #MODULE_is_LOCKED bit in the m_ModuleStatus.
Definition footprint.h:660
EDA_ANGLE GetOrientation() const
Definition footprint.h:409
ZONES & Zones()
Definition footprint.h:381
PCB_POINTS & Points()
Definition footprint.h:390
void SetOrientation(const EDA_ANGLE &aNewAngle)
void SetAllowSolderMaskBridges(bool aAllow)
Definition footprint.h:517
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:422
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition footprint.h:489
wxString GetSheetname() const
Definition footprint.h:470
void SetPath(const KIID_PATH &aPath)
Definition footprint.h:468
void SetFilters(const wxString &aFilters)
Definition footprint.h:477
void SetStaticComponentClass(const COMPONENT_CLASS *aClass) const
Sets the component class object pointer for this footprint.
bool FootprintNeedsUpdate(const FOOTPRINT *aLibFP, int aCompareFlags=0, REPORTER *aReporter=nullptr)
Return true if a board footprint differs from the library version.
const EXTRUDED_3D_BODY * GetExtrudedBody() const
Definition footprint.h:399
void SetAttributes(int aAttributes)
Definition footprint.h:511
void SetSheetfile(const wxString &aSheetfile)
Definition footprint.h:474
std::optional< int > GetLocalSolderPasteMargin() const
Definition footprint.h:485
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:893
bool HasExtrudedBody() const
Definition footprint.h:398
std::optional< int > GetLocalClearance() const
Definition footprint.h:479
void ClearExtrudedBody()
Definition footprint.h:403
std::deque< PAD * > & Pads()
Definition footprint.h:375
int GetAttributes() const
Definition footprint.h:510
const COMPONENT_CLASS * GetComponentClass() const
Returns the component class for this footprint.
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition footprint.h:491
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition footprint.h:420
void SetExtrudedBody(std::unique_ptr< EXTRUDED_3D_BODY > aBody)
wxString GetSheetfile() const
Definition footprint.h:473
const LIB_ID & GetFPID() const
Definition footprint.h:444
bool IsLocked() const override
Definition footprint.h:637
void SetTransformScale(double aScaleX, double aScaleY)
PCB_FIELD & Reference()
Definition footprint.h:894
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition footprint.h:488
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
GROUPS & Groups()
Definition footprint.h:384
wxString GetFilters() const
Definition footprint.h:476
void SetSheetname(const wxString &aSheetname)
Definition footprint.h:471
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
std::vector< FP_3DMODEL > & Models()
Definition footprint.h:395
const wxString & GetValue() const
Definition footprint.h:879
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition footprint.h:483
void SetLocalClearance(std::optional< int > aClearance)
Definition footprint.h:480
const KIID_PATH & GetPath() const
Definition footprint.h:467
std::optional< int > GetLocalSolderMaskMargin() const
Definition footprint.h:482
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition footprint.h:486
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition footprint.h:1321
VECTOR2I GetPosition() const override
Definition footprint.h:406
DRAWINGS & GraphicalItems()
Definition footprint.h:378
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:256
Definition pad.h:61
void SetPinType(const wxString &aType)
Set the pad electrical type.
Definition pad.h:159
const wxString & GetPinType() const
Definition pad.h:160
const wxString & GetPinFunction() const
Definition pad.h:154
bool IsOnCopperLayer() const override
Definition pad.cpp:1863
void SetPinFunction(const wxString &aName)
Set the pad function (pin name in schematic)
Definition pad.h:153
Abstract dimension API.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Definition pcb_point.h:39
EDA_ANGLE GetTextAngle() const override
Definition pcb_text.cpp:544
void KeepUpright()
Called when rotating the parent footprint.
Definition pcb_text.cpp:374
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_text.cpp:678
int GetTextThickness() const override
Definition pcb_text.cpp:481
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:553
VECTOR2I GetTextSize() const override
Definition pcb_text.cpp:454
double GetScaleX() const
double GetScaleY() const
wxString wx_str() const
Definition utf8.cpp:41
Handle a list of polygons defining a copper zone.
Definition zone.h:70
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
@ NO_RECURSE
Definition eda_item.h:50
bool ComputeFootprintShift(const FOOTPRINT &aExisting, const FOOTPRINT &aNew, VECTOR2I &aShift, EDA_ANGLE &aAngleShift)
Compute position and angle shift between two footprints.
Collection of reusable/testable functions for footprint manipulation.
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
Class to handle a set of BOARD_ITEMs.
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
Definition trigo.h:73
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683