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 aMatchPadPositions,
178 bool aDeleteExtraTexts,
179 bool aResetTextLayers,
180 bool aResetTextEffects,
181 bool aResetTextPositions,
182 bool aResetTextContent,
183 bool aResetFabricationAttrs,
184 bool aResetClearanceOverrides,
185 bool aReset3DModels,
186 bool aResetTransform,
187 bool* aUpdated, bool* aShifted )
188{
189 EDA_GROUP* parentGroup = aExisting->GetParentGroup();
190 bool dummyBool = false;
191
192 if( !aUpdated )
193 aUpdated = &dummyBool;
194
195 if( !aShifted )
196 aShifted = &dummyBool;
197
198 if( parentGroup )
199 {
200 aCommit.Modify( parentGroup->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
201 parentGroup->RemoveItem( aExisting );
202 parentGroup->AddItem( aNew );
203 }
204
205 aNew->SetParent( this );
206
207 // This is the position and angle shift to apply to the new footprint if the footprint
208 // has a changed anchor point or rotation compared to the existing footprint.
209 VECTOR2I posShift( 0, 0 );
210 EDA_ANGLE angleShift = ANGLE_0;
211
212 VECTOR2I position = aExisting->GetPosition();
213 EDA_ANGLE orientation = aExisting->GetOrientation();
214
215 if( aMatchPadPositions )
216 {
217 if( ComputeFootprintShift( *aExisting, *aNew, posShift, angleShift ) )
218 {
219 position += posShift;
220 orientation += angleShift;
221
222 if( posShift != VECTOR2I( 0, 0 ) || angleShift != ANGLE_0 )
223 *aShifted = true;
224 }
225 }
226
227 aNew->SetPosition( position );
228
229 if( aNew->GetLayer() != aExisting->GetLayer() )
231
232 if( aNew->GetOrientation() != orientation )
233 aNew->SetOrientation( orientation );
234
235 if( !aResetTransform )
236 {
237 const double existingScaleX = aExisting->GetTransform().GetScaleX();
238 const double existingScaleY = aExisting->GetTransform().GetScaleY();
239
240 if( existingScaleX != aNew->GetTransform().GetScaleX()
241 || existingScaleY != aNew->GetTransform().GetScaleY() )
242 {
243 aNew->SetTransformScale( existingScaleX, existingScaleY );
244 }
245 }
246
247 aNew->SetLocked( aExisting->IsLocked() );
248
249 aNew->SetUuid( aExisting->m_Uuid );
250 aNew->Reference().SetUuid( aExisting->Reference().m_Uuid );
251 aNew->Value().SetUuid( aExisting->Value().m_Uuid );
252
253 std::vector<PAD*> oldPads;
254 oldPads.reserve( aExisting->Pads().size() );
255
256 for( PAD* pad : aExisting->Pads() )
257 oldPads.push_back( pad );
258
259 std::vector<PAD*> newPads;
260 newPads.reserve( aNew->Pads().size() );
261
262 for( PAD* pad : aNew->Pads() )
263 newPads.push_back( pad );
264
265 std::vector<std::pair<PAD*, PAD*>> padMatches = matchItemsBySimilarity( oldPads, newPads );
266 std::unordered_set<PAD*> matchedNewPads;
267
268 for( const std::pair<PAD*, PAD*>& match : padMatches )
269 {
270 PAD* oldPad = match.first;
271 PAD* newPad = match.second;
272
273 matchedNewPads.insert( newPad );
274 newPad->SetUuid( oldPad->m_Uuid );
276 newPad->SetPinFunction( oldPad->GetPinFunction() );
277 newPad->SetPinType( oldPad->GetPinType() );
278
279 if( newPad->IsOnCopperLayer() )
280 newPad->SetNetCode( oldPad->GetNetCode() );
281 else
283 }
284
285 for( PAD* newPad : aNew->Pads() )
286 {
287 if( matchedNewPads.find( newPad ) != matchedNewPads.end() )
288 continue;
289
290 newPad->ResetUuid();
291 newPad->SetNetCode( NETINFO_LIST::UNCONNECTED );
292 }
293
294 std::vector<BOARD_ITEM*> oldDrawings;
295 oldDrawings.reserve( aExisting->GraphicalItems().size() );
296
297 for( BOARD_ITEM* item : aExisting->GraphicalItems() )
298 oldDrawings.push_back( item );
299
300 std::vector<BOARD_ITEM*> newDrawings;
301 newDrawings.reserve( aNew->GraphicalItems().size() );
302
303 for( BOARD_ITEM* item : aNew->GraphicalItems() )
304 newDrawings.push_back( item );
305
306 std::vector<std::pair<BOARD_ITEM*, BOARD_ITEM*>> drawingMatches = matchItemsBySimilarity( oldDrawings, newDrawings );
307 std::unordered_map<BOARD_ITEM*, BOARD_ITEM*> oldToNewDrawings;
308 std::unordered_set<BOARD_ITEM*> matchedNewDrawings;
309
310 for( const std::pair<BOARD_ITEM*, BOARD_ITEM*>& match : drawingMatches )
311 {
312 BOARD_ITEM* oldItem = match.first;
313 BOARD_ITEM* newItem = match.second;
314
315 oldToNewDrawings[ oldItem ] = newItem;
316 matchedNewDrawings.insert( newItem );
317 newItem->SetUuid( oldItem->m_Uuid );
318 }
319
320 for( BOARD_ITEM* newItem : newDrawings )
321 {
322 if( matchedNewDrawings.find( newItem ) == matchedNewDrawings.end() )
323 newItem->ResetUuid();
324 }
325
326 std::vector<ZONE*> oldZones;
327 oldZones.reserve( aExisting->Zones().size() );
328
329 for( ZONE* zone : aExisting->Zones() )
330 oldZones.push_back( zone );
331
332 std::vector<ZONE*> newZones;
333 newZones.reserve( aNew->Zones().size() );
334
335 for( ZONE* zone : aNew->Zones() )
336 newZones.push_back( zone );
337
338 std::vector<std::pair<ZONE*, ZONE*>> zoneMatches = matchItemsBySimilarity( oldZones, newZones );
339 std::unordered_set<ZONE*> matchedNewZones;
340
341 for( const std::pair<ZONE*, ZONE*>& match : zoneMatches )
342 {
343 ZONE* oldZone = match.first;
344 ZONE* newZone = match.second;
345
346 matchedNewZones.insert( newZone );
347 newZone->SetUuid( oldZone->m_Uuid );
348 }
349
350 for( ZONE* newZone : newZones )
351 {
352 if( matchedNewZones.find( newZone ) == matchedNewZones.end() )
353 newZone->ResetUuid();
354 }
355
356 std::vector<PCB_POINT*> oldPoints;
357 oldPoints.reserve( aExisting->Points().size() );
358
359 for( PCB_POINT* point : aExisting->Points() )
360 oldPoints.push_back( point );
361
362 std::vector<PCB_POINT*> newPoints;
363 newPoints.reserve( aNew->Points().size() );
364
365 for( PCB_POINT* point : aNew->Points() )
366 newPoints.push_back( point );
367
368 std::vector<std::pair<PCB_POINT*, PCB_POINT*>> pointMatches = matchItemsBySimilarity( oldPoints, newPoints );
369 std::unordered_set<PCB_POINT*> matchedNewPoints;
370
371 for( const std::pair<PCB_POINT*, PCB_POINT*>& match : pointMatches )
372 {
373 PCB_POINT* oldPoint = match.first;
374 PCB_POINT* newPoint = match.second;
375
376 matchedNewPoints.insert( newPoint );
377 newPoint->SetUuid( oldPoint->m_Uuid );
378 }
379
380 for( PCB_POINT* newPoint : newPoints )
381 {
382 if( matchedNewPoints.find( newPoint ) == matchedNewPoints.end() )
383 newPoint->ResetUuid();
384 }
385
386 std::vector<PCB_GROUP*> oldGroups;
387 oldGroups.reserve( aExisting->Groups().size() );
388
389 for( PCB_GROUP* group : aExisting->Groups() )
390 oldGroups.push_back( group );
391
392 std::vector<PCB_GROUP*> newGroups;
393 newGroups.reserve( aNew->Groups().size() );
394
395 for( PCB_GROUP* group : aNew->Groups() )
396 newGroups.push_back( group );
397
398 std::vector<std::pair<PCB_GROUP*, PCB_GROUP*>> groupMatches = matchItemsBySimilarity( oldGroups, newGroups );
399 std::unordered_set<PCB_GROUP*> matchedNewGroups;
400
401 for( const std::pair<PCB_GROUP*, PCB_GROUP*>& match : groupMatches )
402 {
403 PCB_GROUP* oldGroup = match.first;
404 PCB_GROUP* newGroup = match.second;
405
406 matchedNewGroups.insert( newGroup );
407 newGroup->SetUuid( oldGroup->m_Uuid );
408 }
409
410 for( PCB_GROUP* newGroup : newGroups )
411 {
412 if( matchedNewGroups.find( newGroup ) == matchedNewGroups.end() )
413 newGroup->ResetUuid();
414 }
415
416 std::vector<PCB_FIELD*> oldFields;
417 std::vector<PCB_FIELD*> newFields;
418
419 oldFields.reserve( aExisting->GetFields().size() );
420
421 for( PCB_FIELD* field : aExisting->GetFields() )
422 {
423 wxCHECK2( field, continue );
424
425 if( field->IsReference() || field->IsValue() )
426 continue;
427
428 oldFields.push_back( field );
429 }
430
431 newFields.reserve( aNew->GetFields().size() );
432
433 for( PCB_FIELD* field : aNew->GetFields() )
434 {
435 wxCHECK2( field, continue );
436
437 if( field->IsReference() || field->IsValue() )
438 continue;
439
440 newFields.push_back( field );
441 }
442
443 std::vector<std::pair<PCB_FIELD*, PCB_FIELD*>> fieldMatches = matchItemsBySimilarity( oldFields, newFields );
444 std::unordered_map<PCB_FIELD*, PCB_FIELD*> oldToNewFields;
445 std::unordered_set<PCB_FIELD*> matchedNewFields;
446
447 for( const std::pair<PCB_FIELD*, PCB_FIELD*>& match : fieldMatches )
448 {
449 PCB_FIELD* oldField = match.first;
450 PCB_FIELD* newField = match.second;
451
452 oldToNewFields[ oldField ] = newField;
453 matchedNewFields.insert( newField );
454 newField->SetUuid( oldField->m_Uuid );
455 }
456
457 for( PCB_FIELD* newField : newFields )
458 {
459 if( matchedNewFields.find( newField ) == matchedNewFields.end() )
460 newField->ResetUuid();
461 }
462
463 std::unordered_map<PCB_TEXT*, PCB_TEXT*> oldToNewTexts;
464
465 for( const std::pair<BOARD_ITEM*, BOARD_ITEM*>& match : drawingMatches )
466 {
467 PCB_TEXT* oldText = dynamic_cast<PCB_TEXT*>( match.first );
468 PCB_TEXT* newText = dynamic_cast<PCB_TEXT*>( match.second );
469
470 if( oldText && newText )
471 oldToNewTexts[ oldText ] = newText;
472 }
473
474 std::set<PCB_TEXT*> handledTextItems;
475
476 for( BOARD_ITEM* oldItem : aExisting->GraphicalItems() )
477 {
478 PCB_TEXT* oldTextItem = dynamic_cast<PCB_TEXT*>( oldItem );
479
480 if( oldTextItem )
481 {
482 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
483 if( dynamic_cast<PCB_DIMENSION_BASE*>( oldTextItem ) )
484 continue;
485
486 PCB_TEXT* newTextItem = nullptr;
487
488 auto textMatchIt = oldToNewTexts.find( oldTextItem );
489
490 if( textMatchIt != oldToNewTexts.end() )
491 newTextItem = textMatchIt->second;
492
493 if( newTextItem )
494 {
495 handledTextItems.insert( newTextItem );
496 processTextItem( *oldTextItem, *newTextItem, posShift, angleShift, aResetTextContent,
497 aResetTextLayers, aResetTextEffects, aResetTextPositions, aUpdated );
498 }
499 else if( aDeleteExtraTexts )
500 {
501 *aUpdated = true;
502 }
503 else
504 {
505 newTextItem = static_cast<PCB_TEXT*>( oldTextItem->Clone() );
506 handledTextItems.insert( newTextItem );
507 aNew->Add( newTextItem );
508 }
509 }
510 }
511
512 // Check for any newly-added text items and set the update flag as appropriate
513 for( BOARD_ITEM* newItem : aNew->GraphicalItems() )
514 {
515 PCB_TEXT* newTextItem = dynamic_cast<PCB_TEXT*>( newItem );
516
517 if( newTextItem )
518 {
519 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
520 if( dynamic_cast<PCB_DIMENSION_BASE*>( newTextItem ) )
521 continue;
522
523 if( !handledTextItems.contains( newTextItem ) )
524 {
525 *aUpdated = true;
526 break;
527 }
528 }
529 }
530
531 // Copy reference. The initial text is always used, never resetted
532 processTextItem( aExisting->Reference(), aNew->Reference(), posShift, angleShift, false, aResetTextLayers,
533 aResetTextEffects, aResetTextPositions, aUpdated );
534
535 // Copy value
536 processTextItem( aExisting->Value(), aNew->Value(), posShift, angleShift,
537 // reset value text only when it is a proxy for the footprint ID
538 // (cf replacing value "MountingHole-2.5mm" with "MountingHole-4.0mm")
539 aExisting->GetValue() == aExisting->GetFPID().GetLibItemName().wx_str(),
540 aResetTextLayers, aResetTextEffects, aResetTextPositions, aUpdated );
541
542 std::set<PCB_FIELD*> handledFields;
543
544 // Copy fields in accordance with the reset* flags
545 for( PCB_FIELD* oldField : aExisting->GetFields() )
546 {
547 wxCHECK2( oldField, continue );
548
549 // Reference and value are already handled
550 if( oldField->IsReference() || oldField->IsValue() )
551 continue;
552
553 PCB_FIELD* newField = nullptr;
554
555 auto fieldMatchIt = oldToNewFields.find( oldField );
556
557 if( fieldMatchIt != oldToNewFields.end() )
558 newField = fieldMatchIt->second;
559
560 if( newField )
561 {
562 handledFields.insert( newField );
563 processTextItem( *oldField, *newField, posShift, angleShift, aResetTextContent, aResetTextLayers,
564 aResetTextEffects, aResetTextPositions, aUpdated );
565 }
566 else if( aDeleteExtraTexts )
567 {
568 *aUpdated = true;
569 }
570 else
571 {
572 newField = new PCB_FIELD( *oldField );
573 handledFields.insert( newField );
574 aNew->Add( newField );
575 }
576 }
577
578 // Check for any newly-added fields and set the update flag as appropriate
579 for( PCB_FIELD* newField : aNew->GetFields() )
580 {
581 wxCHECK2( newField, continue );
582
583 // Reference and value are already handled
584 if( newField->IsReference() || newField->IsValue() )
585 continue;
586
587 if( !handledFields.contains( newField ) )
588 {
589 *aUpdated = true;
590 break;
591 }
592 }
593
594 if( aResetFabricationAttrs )
595 {
596 // We've replaced the existing footprint with the library one, so the fabrication attrs
597 // are already reset. Just set the aUpdated flag if appropriate.
598 if( aNew->GetAttributes() != aExisting->GetAttributes() )
599 *aUpdated = true;
600 }
601 else
602 {
603 aNew->SetAttributes( aExisting->GetAttributes() );
604 }
605
606 if( aResetClearanceOverrides )
607 {
608 if( aExisting->AllowSolderMaskBridges() != aNew->AllowSolderMaskBridges() )
609 *aUpdated = true;
610
611 if( ( aExisting->GetLocalClearance() != aNew->GetLocalClearance() )
612 || ( aExisting->GetLocalSolderMaskMargin() != aNew->GetLocalSolderMaskMargin() )
613 || ( aExisting->GetLocalSolderPasteMargin() != aNew->GetLocalSolderPasteMargin() )
615 || ( aExisting->GetLocalZoneConnection() != aNew->GetLocalZoneConnection() ) )
616 {
617 *aUpdated = true;
618 }
619 }
620 else
621 {
622 aNew->SetLocalClearance( aExisting->GetLocalClearance() );
628 }
629
630 if( aReset3DModels )
631 {
632 // We've replaced the existing footprint with the library one, so the 3D models are
633 // already reset. Just set the aUpdated flag if appropriate.
634 if( aNew->Models().size() != aExisting->Models().size() )
635 {
636 *aUpdated = true;
637 }
638 else
639 {
640 for( size_t ii = 0; ii < aNew->Models().size(); ++ii )
641 {
642 if( aNew->Models()[ii] != aExisting->Models()[ii] )
643 {
644 *aUpdated = true;
645 break;
646 }
647 }
648 }
649 }
650 else
651 {
652 // Preserve model references and all embedded model data.
653 aNew->Models() = aExisting->Models();
654
655 // Preserve extruded 3D body settings.
656 if( aExisting->HasExtrudedBody() )
657 aNew->SetExtrudedBody( std::make_unique<EXTRUDED_3D_BODY>( *aExisting->GetExtrudedBody() ) );
658 else
659 aNew->ClearExtrudedBody();
660
661 for( const auto& [name, file] : aExisting->GetEmbeddedFiles()->EmbeddedFileMap() )
662 {
664 continue;
665
666 aNew->GetEmbeddedFiles()->RemoveFile( name, true );
668 }
669 }
670
671 // Updating other parameters
672 aNew->SetPath( aExisting->GetPath() );
673 aNew->SetSheetfile( aExisting->GetSheetfile() );
674 aNew->SetSheetname( aExisting->GetSheetname() );
675 aNew->SetFilters( aExisting->GetFilters() );
676 aNew->SetStaticComponentClass( aExisting->GetComponentClass() );
677
678 if( *aUpdated == false )
679 {
680 // Check pad shapes, graphics, zones, etc. for changes
682 *aUpdated = true;
683 }
684
685 aCommit.Remove( aExisting );
686 aCommit.Add( aNew );
687
688 aNew->ClearFlags();
689}
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:86
void SetLocked(bool aLocked) override
Definition board_item.h:417
void SetUuid(const KIID &aUuid)
virtual bool IsKnockout() const
Definition board_item.h:413
bool IsLocked() const override
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:414
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:374
VECTOR2I GetFPRelativePosition() const
@ INSTANCE_TO_INSTANCE
Definition board_item.h:559
void SetFPRelativePosition(const VECTOR2I &aPos)
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool aMatchPadPositions, bool aDeleteExtraTexts=true, bool aResetTextLayers=true, bool aResetTextEffects=true, bool aResetTextPositions=true, bool aResetTextContent=true, bool aResetFabricationAttrs=true, bool aResetClearanceOverrides=true, bool aReset3DModels=true, bool aResetTransform=false, bool *aUpdated=nullptr, bool *aShifted=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:43
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:597
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:160
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
bool IsKeepUpright() const
Definition eda_text.h:245
virtual bool IsVisible() const
Definition eda_text.h:226
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:389
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:342
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:231
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:559
void SetPosition(const VECTOR2I &aPos) override
ZONE_CONNECTION GetLocalZoneConnection() const
Definition footprint.h:532
void SetLocked(bool isLocked) override
Set the #MODULE_is_LOCKED bit in the m_ModuleStatus.
Definition footprint.h:703
EDA_ANGLE GetOrientation() const
Definition footprint.h:438
ZONES & Zones()
Definition footprint.h:410
PCB_POINTS & Points()
Definition footprint.h:419
void SetOrientation(const EDA_ANGLE &aNewAngle)
void SetAllowSolderMaskBridges(bool aAllow)
Definition footprint.h:560
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:451
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition footprint.h:529
wxString GetSheetname() const
Definition footprint.h:510
void SetPath(const KIID_PATH &aPath)
Definition footprint.h:497
void SetFilters(const wxString &aFilters)
Definition footprint.h:517
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:428
void SetAttributes(int aAttributes)
Definition footprint.h:551
void SetSheetfile(const wxString &aSheetfile)
Definition footprint.h:514
std::optional< int > GetLocalSolderPasteMargin() const
Definition footprint.h:525
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:939
bool HasExtrudedBody() const
Definition footprint.h:427
std::optional< int > GetLocalClearance() const
Definition footprint.h:519
void ClearExtrudedBody()
Definition footprint.h:432
std::deque< PAD * > & Pads()
Definition footprint.h:404
int GetAttributes() const
Definition footprint.h:550
const COMPONENT_CLASS * GetComponentClass() const
Returns the component class for this footprint.
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition footprint.h:531
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition footprint.h:449
void SetExtrudedBody(std::unique_ptr< EXTRUDED_3D_BODY > aBody)
wxString GetSheetfile() const
Definition footprint.h:513
const LIB_ID & GetFPID() const
Definition footprint.h:473
bool IsLocked() const override
Definition footprint.h:680
void SetTransformScale(double aScaleX, double aScaleY)
PCB_FIELD & Reference()
Definition footprint.h:940
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:528
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
GROUPS & Groups()
Definition footprint.h:413
wxString GetFilters() const
Definition footprint.h:516
void SetSheetname(const wxString &aSheetname)
Definition footprint.h:511
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:424
const wxString & GetValue() const
Definition footprint.h:925
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition footprint.h:523
void SetLocalClearance(std::optional< int > aClearance)
Definition footprint.h:520
const KIID_PATH & GetPath() const
Definition footprint.h:496
std::optional< int > GetLocalSolderMaskMargin() const
Definition footprint.h:522
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition footprint.h:526
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition footprint.h:1389
VECTOR2I GetPosition() const override
Definition footprint.h:435
DRAWINGS & GraphicalItems()
Definition footprint.h:407
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:280
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:1887
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:560
void KeepUpright()
Called when rotating the parent footprint.
Definition pcb_text.cpp:390
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_text.cpp:694
int GetTextThickness() const override
Definition pcb_text.cpp:497
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:569
VECTOR2I GetTextSize() const override
Definition pcb_text.cpp:470
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:422
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:426
@ NO_RECURSE
Definition eda_item.h:52
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