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_3d_body.h>
37#include <pcb_text.h>
38#include <zone.h>
39
40
41static void processTextItem( const PCB_TEXT& aSrc, PCB_TEXT& aDest, const VECTOR2I& aPosShift,
42 const EDA_ANGLE& aAngleShift, bool aResetText, bool aResetTextLayers,
43 bool aResetTextEffects, bool aResetTextPositions, bool* aUpdated )
44{
45 if( aResetText )
46 *aUpdated |= aSrc.GetText() != aDest.GetText();
47 else
48 aDest.SetText( aSrc.GetText() );
49
50 if( aResetTextLayers )
51 {
52 *aUpdated |= aSrc.GetLayer() != aDest.GetLayer();
53 *aUpdated |= aSrc.IsVisible() != aDest.IsVisible();
54 }
55 else
56 {
57 aDest.SetLayer( aSrc.GetLayer() );
58 aDest.SetVisible( aSrc.IsVisible() );
59 }
60
61 VECTOR2I origPos = aDest.GetFPRelativePosition();
62
63 if( aResetTextEffects )
64 {
65 *aUpdated |= aSrc.GetHorizJustify() != aDest.GetHorizJustify();
66 *aUpdated |= aSrc.GetVertJustify() != aDest.GetVertJustify();
67 *aUpdated |= aSrc.GetTextSize() != aDest.GetTextSize();
68 *aUpdated |= aSrc.GetTextThickness() != aDest.GetTextThickness();
69 *aUpdated |= aSrc.IsKnockout() != aDest.IsKnockout();
70 aDest.KeepUpright();
71 }
72 else
73 {
74 EDA_ANGLE origAngle = aDest.GetTextAngle();
75 origAngle.Normalize();
76 aDest.SetAttributes( aSrc );
77 if( origAngle >= ANGLE_180 && aDest.IsKeepUpright() )
78 {
79 // Text is already rotated by 180 because of 'keep upright'.
80 origAngle -= ANGLE_180;
81 }
82
83 aDest.SetTextAngle( origAngle ); // apply rotation as part of position shift
84 aDest.SetIsKnockout( aSrc.IsKnockout() );
85 }
86
87 if( aResetTextPositions )
88 {
89 *aUpdated |= aSrc.GetFPRelativePosition() != origPos;
90 *aUpdated |= aSrc.GetTextAngle() != aDest.GetTextAngle();
91
92 aDest.SetFPRelativePosition( origPos );
93 }
94 else
95 {
96 VECTOR2I rotatedShift = GetRotated( aSrc.GetFPRelativePosition() - aPosShift, -aAngleShift );
97
98 aDest.SetFPRelativePosition( rotatedShift );
99 aDest.SetTextAngle( aSrc.GetTextAngle() );
100 }
101
102 aDest.SetLocked( aSrc.IsLocked() );
103 aDest.SetUuid( aSrc.m_Uuid );
104}
105
106
107template<typename T>
108static std::vector<std::pair<T*, T*>> matchItemsBySimilarity( const std::vector<T*>& aExisting,
109 const std::vector<T*>& aNew )
110{
111 struct MATCH_CANDIDATE
112 {
113 T* existing;
114 T* updated;
115 double score;
116 };
117
118 std::vector<MATCH_CANDIDATE> candidates;
119
120 for( T* existing : aExisting )
121 {
122 for( T* updated : aNew )
123 {
124 if( existing->Type() != updated->Type() )
125 continue;
126
127 double similarity = existing->Similarity( *updated );
128
129 if constexpr( std::is_same_v<T, PAD> )
130 {
131 if( existing->GetNumber() == updated->GetNumber() )
132 similarity += 2.0;
133 }
134
135 if( similarity <= 0.0 )
136 continue;
137
138 candidates.push_back( { existing, updated, similarity } );
139 }
140 }
141
142 std::sort( candidates.begin(), candidates.end(),
143 []( const MATCH_CANDIDATE& a, const MATCH_CANDIDATE& b )
144 {
145 if( a.score != b.score )
146 return a.score > b.score;
147
148 if( a.existing != b.existing )
149 return a.existing < b.existing;
150
151 return a.updated < b.updated;
152 } );
153
154 std::vector<std::pair<T*, T*>> matches;
155 matches.reserve( candidates.size() );
156
157 std::unordered_set<T*> matchedExisting;
158 std::unordered_set<T*> matchedNew;
159
160 for( const MATCH_CANDIDATE& candidate : candidates )
161 {
162 if( matchedExisting.find( candidate.existing ) != matchedExisting.end() )
163 continue;
164
165 if( matchedNew.find( candidate.updated ) != matchedNew.end() )
166 continue;
167
168 matchedExisting.insert( candidate.existing );
169 matchedNew.insert( candidate.updated );
170 matches.emplace_back( candidate.existing, candidate.updated );
171 }
172
173 return matches;
174}
175
176
178 FLIP_DIRECTION aFlipDirection,
179 bool aMatchPadPositions,
180 bool aDeleteExtraTexts,
181 bool aResetTextLayers,
182 bool aResetTextEffects,
183 bool aResetTextPositions,
184 bool aResetTextContent,
185 bool aResetFabricationAttrs,
186 bool aResetClearanceOverrides,
187 bool aReset3DModels,
188 bool aResetTransform,
189 bool* aUpdated, bool* aShifted )
190{
191 EDA_GROUP* parentGroup = aExisting->GetParentGroup();
192 bool dummyBool = false;
193
194 if( !aUpdated )
195 aUpdated = &dummyBool;
196
197 if( !aShifted )
198 aShifted = &dummyBool;
199
200 if( parentGroup )
201 {
202 aCommit.Modify( parentGroup->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
203 parentGroup->RemoveItem( aExisting );
204 parentGroup->AddItem( aNew );
205 }
206
207 aNew->SetParent( this );
208
209 // This is the position and angle shift to apply to the new footprint if the footprint
210 // has a changed anchor point or rotation compared to the existing footprint.
211 VECTOR2I posShift( 0, 0 );
212 EDA_ANGLE angleShift = ANGLE_0;
213
214 VECTOR2I position = aExisting->GetPosition();
215 EDA_ANGLE orientation = aExisting->GetOrientation();
216
217 if( aMatchPadPositions )
218 {
219 if( ComputeFootprintShift( *aExisting, *aNew, posShift, angleShift ) )
220 {
221 position += posShift;
222 orientation += angleShift;
223
224 if( posShift != VECTOR2I( 0, 0 ) || angleShift != ANGLE_0 )
225 *aShifted = true;
226 }
227 }
228
229 aNew->SetPosition( position );
230
231 if( aNew->GetLayer() != aExisting->GetLayer() )
232 aNew->Flip( aNew->GetPosition(), aFlipDirection );
233
234 if( aNew->GetOrientation() != orientation )
235 aNew->SetOrientation( orientation );
236
237 if( !aResetTransform )
238 {
239 const double existingScaleX = aExisting->GetTransform().GetScaleX();
240 const double existingScaleY = aExisting->GetTransform().GetScaleY();
241
242 if( existingScaleX != aNew->GetTransform().GetScaleX()
243 || existingScaleY != aNew->GetTransform().GetScaleY() )
244 {
245 aNew->SetTransformScale( existingScaleX, existingScaleY );
246 }
247 }
248
249 aNew->SetLocked( aExisting->IsLocked() );
250
251 aNew->SetUuid( aExisting->m_Uuid );
252 aNew->Reference().SetUuid( aExisting->Reference().m_Uuid );
253 aNew->Value().SetUuid( aExisting->Value().m_Uuid );
254 aNew->SetHeight( aExisting->GetHeight() );
255
256 std::vector<PAD*> oldPads;
257 oldPads.reserve( aExisting->Pads().size() );
258
259 for( PAD* pad : aExisting->Pads() )
260 oldPads.push_back( pad );
261
262 std::vector<PAD*> newPads;
263 newPads.reserve( aNew->Pads().size() );
264
265 for( PAD* pad : aNew->Pads() )
266 newPads.push_back( pad );
267
268 std::vector<std::pair<PAD*, PAD*>> padMatches = matchItemsBySimilarity( oldPads, newPads );
269 std::unordered_set<PAD*> matchedNewPads;
270
271 for( const std::pair<PAD*, PAD*>& match : padMatches )
272 {
273 PAD* oldPad = match.first;
274 PAD* newPad = match.second;
275
276 matchedNewPads.insert( newPad );
277 newPad->SetUuid( oldPad->m_Uuid );
279 newPad->SetPinFunction( oldPad->GetPinFunction() );
280 newPad->SetPinType( oldPad->GetPinType() );
281
282 if( newPad->IsOnCopperLayer() )
283 newPad->SetNetCode( oldPad->GetNetCode() );
284 else
286 }
287
288 for( PAD* newPad : aNew->Pads() )
289 {
290 if( matchedNewPads.find( newPad ) != matchedNewPads.end() )
291 continue;
292
293 newPad->ResetUuid();
294 newPad->SetNetCode( NETINFO_LIST::UNCONNECTED );
295 }
296
297 std::vector<BOARD_ITEM*> oldDrawings;
298 oldDrawings.reserve( aExisting->GraphicalItems().size() );
299
300 for( BOARD_ITEM* item : aExisting->GraphicalItems() )
301 oldDrawings.push_back( item );
302
303 std::vector<BOARD_ITEM*> newDrawings;
304 newDrawings.reserve( aNew->GraphicalItems().size() );
305
306 for( BOARD_ITEM* item : aNew->GraphicalItems() )
307 newDrawings.push_back( item );
308
309 std::vector<std::pair<BOARD_ITEM*, BOARD_ITEM*>> drawingMatches = matchItemsBySimilarity( oldDrawings, newDrawings );
310 std::unordered_map<BOARD_ITEM*, BOARD_ITEM*> oldToNewDrawings;
311 std::unordered_set<BOARD_ITEM*> matchedNewDrawings;
312
313 for( const std::pair<BOARD_ITEM*, BOARD_ITEM*>& match : drawingMatches )
314 {
315 BOARD_ITEM* oldItem = match.first;
316 BOARD_ITEM* newItem = match.second;
317
318 oldToNewDrawings[ oldItem ] = newItem;
319 matchedNewDrawings.insert( newItem );
320 newItem->SetUuid( oldItem->m_Uuid );
321 }
322
323 for( BOARD_ITEM* newItem : newDrawings )
324 {
325 if( matchedNewDrawings.find( newItem ) == matchedNewDrawings.end() )
326 newItem->ResetUuid();
327 }
328
329 std::vector<ZONE*> oldZones;
330 oldZones.reserve( aExisting->Zones().size() );
331
332 for( ZONE* zone : aExisting->Zones() )
333 oldZones.push_back( zone );
334
335 std::vector<ZONE*> newZones;
336 newZones.reserve( aNew->Zones().size() );
337
338 for( ZONE* zone : aNew->Zones() )
339 newZones.push_back( zone );
340
341 std::vector<std::pair<ZONE*, ZONE*>> zoneMatches = matchItemsBySimilarity( oldZones, newZones );
342 std::unordered_set<ZONE*> matchedNewZones;
343
344 for( const std::pair<ZONE*, ZONE*>& match : zoneMatches )
345 {
346 ZONE* oldZone = match.first;
347 ZONE* newZone = match.second;
348
349 matchedNewZones.insert( newZone );
350 newZone->SetUuid( oldZone->m_Uuid );
351 }
352
353 for( ZONE* newZone : newZones )
354 {
355 if( matchedNewZones.find( newZone ) == matchedNewZones.end() )
356 newZone->ResetUuid();
357 }
358
359 std::vector<PCB_POINT*> oldPoints;
360 oldPoints.reserve( aExisting->Points().size() );
361
362 for( PCB_POINT* point : aExisting->Points() )
363 oldPoints.push_back( point );
364
365 std::vector<PCB_POINT*> newPoints;
366 newPoints.reserve( aNew->Points().size() );
367
368 for( PCB_POINT* point : aNew->Points() )
369 newPoints.push_back( point );
370
371 std::vector<std::pair<PCB_POINT*, PCB_POINT*>> pointMatches = matchItemsBySimilarity( oldPoints, newPoints );
372 std::unordered_set<PCB_POINT*> matchedNewPoints;
373
374 for( const std::pair<PCB_POINT*, PCB_POINT*>& match : pointMatches )
375 {
376 PCB_POINT* oldPoint = match.first;
377 PCB_POINT* newPoint = match.second;
378
379 matchedNewPoints.insert( newPoint );
380 newPoint->SetUuid( oldPoint->m_Uuid );
381 }
382
383 for( PCB_POINT* newPoint : newPoints )
384 {
385 if( matchedNewPoints.find( newPoint ) == matchedNewPoints.end() )
386 newPoint->ResetUuid();
387 }
388
389 std::vector<PCB_GROUP*> oldGroups;
390 oldGroups.reserve( aExisting->Groups().size() );
391
392 for( PCB_GROUP* group : aExisting->Groups() )
393 oldGroups.push_back( group );
394
395 std::vector<PCB_GROUP*> newGroups;
396 newGroups.reserve( aNew->Groups().size() );
397
398 for( PCB_GROUP* group : aNew->Groups() )
399 newGroups.push_back( group );
400
401 std::vector<std::pair<PCB_GROUP*, PCB_GROUP*>> groupMatches = matchItemsBySimilarity( oldGroups, newGroups );
402 std::unordered_set<PCB_GROUP*> matchedNewGroups;
403
404 for( const std::pair<PCB_GROUP*, PCB_GROUP*>& match : groupMatches )
405 {
406 PCB_GROUP* oldGroup = match.first;
407 PCB_GROUP* newGroup = match.second;
408
409 matchedNewGroups.insert( newGroup );
410 newGroup->SetUuid( oldGroup->m_Uuid );
411 }
412
413 for( PCB_GROUP* newGroup : newGroups )
414 {
415 if( matchedNewGroups.find( newGroup ) == matchedNewGroups.end() )
416 newGroup->ResetUuid();
417 }
418
419 std::vector<PCB_FIELD*> oldFields;
420 std::vector<PCB_FIELD*> newFields;
421
422 oldFields.reserve( aExisting->GetFields().size() );
423
424 for( PCB_FIELD* field : aExisting->GetFields() )
425 {
426 wxCHECK2( field, continue );
427
428 if( field->IsReference() || field->IsValue() )
429 continue;
430
431 oldFields.push_back( field );
432 }
433
434 newFields.reserve( aNew->GetFields().size() );
435
436 for( PCB_FIELD* field : aNew->GetFields() )
437 {
438 wxCHECK2( field, continue );
439
440 if( field->IsReference() || field->IsValue() )
441 continue;
442
443 newFields.push_back( field );
444 }
445
446 std::vector<std::pair<PCB_FIELD*, PCB_FIELD*>> fieldMatches = matchItemsBySimilarity( oldFields, newFields );
447 std::unordered_map<PCB_FIELD*, PCB_FIELD*> oldToNewFields;
448 std::unordered_set<PCB_FIELD*> matchedNewFields;
449
450 for( const std::pair<PCB_FIELD*, PCB_FIELD*>& match : fieldMatches )
451 {
452 PCB_FIELD* oldField = match.first;
453 PCB_FIELD* newField = match.second;
454
455 oldToNewFields[ oldField ] = newField;
456 matchedNewFields.insert( newField );
457 newField->SetUuid( oldField->m_Uuid );
458 }
459
460 for( PCB_FIELD* newField : newFields )
461 {
462 if( matchedNewFields.find( newField ) == matchedNewFields.end() )
463 newField->ResetUuid();
464 }
465
466 std::unordered_map<PCB_TEXT*, PCB_TEXT*> oldToNewTexts;
467
468 for( const std::pair<BOARD_ITEM*, BOARD_ITEM*>& match : drawingMatches )
469 {
470 PCB_TEXT* oldText = dynamic_cast<PCB_TEXT*>( match.first );
471 PCB_TEXT* newText = dynamic_cast<PCB_TEXT*>( match.second );
472
473 if( oldText && newText )
474 oldToNewTexts[ oldText ] = newText;
475 }
476
477 std::set<PCB_TEXT*> handledTextItems;
478
479 for( BOARD_ITEM* oldItem : aExisting->GraphicalItems() )
480 {
481 PCB_TEXT* oldTextItem = dynamic_cast<PCB_TEXT*>( oldItem );
482
483 if( oldTextItem )
484 {
485 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
486 if( dynamic_cast<PCB_DIMENSION_BASE*>( oldTextItem ) )
487 continue;
488
489 PCB_TEXT* newTextItem = nullptr;
490
491 auto textMatchIt = oldToNewTexts.find( oldTextItem );
492
493 if( textMatchIt != oldToNewTexts.end() )
494 newTextItem = textMatchIt->second;
495
496 if( newTextItem )
497 {
498 handledTextItems.insert( newTextItem );
499 processTextItem( *oldTextItem, *newTextItem, posShift, angleShift, aResetTextContent,
500 aResetTextLayers, aResetTextEffects, aResetTextPositions, aUpdated );
501 }
502 else if( aDeleteExtraTexts )
503 {
504 *aUpdated = true;
505 }
506 else
507 {
508 newTextItem = static_cast<PCB_TEXT*>( oldTextItem->Clone() );
509 handledTextItems.insert( newTextItem );
510 aNew->Add( newTextItem );
511 }
512 }
513 }
514
515 // Check for any newly-added text items and set the update flag as appropriate
516 for( BOARD_ITEM* newItem : aNew->GraphicalItems() )
517 {
518 PCB_TEXT* newTextItem = dynamic_cast<PCB_TEXT*>( newItem );
519
520 if( newTextItem )
521 {
522 // Dimensions have PCB_TEXT base but are not treated like texts in the updater
523 if( dynamic_cast<PCB_DIMENSION_BASE*>( newTextItem ) )
524 continue;
525
526 if( !handledTextItems.contains( newTextItem ) )
527 {
528 *aUpdated = true;
529 break;
530 }
531 }
532 }
533
534 // Copy reference. The initial text is always used, never resetted
535 processTextItem( aExisting->Reference(), aNew->Reference(), posShift, angleShift, false, aResetTextLayers,
536 aResetTextEffects, aResetTextPositions, aUpdated );
537
538 // Copy value
539 processTextItem( aExisting->Value(), aNew->Value(), posShift, angleShift,
540 // reset value text only when it is a proxy for the footprint ID
541 // (cf replacing value "MountingHole-2.5mm" with "MountingHole-4.0mm")
542 aExisting->GetValue() == aExisting->GetFPID().GetLibItemName().wx_str(),
543 aResetTextLayers, aResetTextEffects, aResetTextPositions, aUpdated );
544
545 std::set<PCB_FIELD*> handledFields;
546
547 // Copy fields in accordance with the reset* flags
548 for( PCB_FIELD* oldField : aExisting->GetFields() )
549 {
550 wxCHECK2( oldField, continue );
551
552 // Reference and value are already handled
553 if( oldField->IsReference() || oldField->IsValue() )
554 continue;
555
556 PCB_FIELD* newField = nullptr;
557
558 auto fieldMatchIt = oldToNewFields.find( oldField );
559
560 if( fieldMatchIt != oldToNewFields.end() )
561 newField = fieldMatchIt->second;
562
563 if( newField )
564 {
565 handledFields.insert( newField );
566 processTextItem( *oldField, *newField, posShift, angleShift, aResetTextContent, aResetTextLayers,
567 aResetTextEffects, aResetTextPositions, aUpdated );
568 }
569 else if( aDeleteExtraTexts )
570 {
571 *aUpdated = true;
572 }
573 else
574 {
575 newField = new PCB_FIELD( *oldField );
576 handledFields.insert( newField );
577 aNew->Add( newField );
578 }
579 }
580
581 // Check for any newly-added fields and set the update flag as appropriate
582 for( PCB_FIELD* newField : aNew->GetFields() )
583 {
584 wxCHECK2( newField, continue );
585
586 // Reference and value are already handled
587 if( newField->IsReference() || newField->IsValue() )
588 continue;
589
590 if( !handledFields.contains( newField ) )
591 {
592 *aUpdated = true;
593 break;
594 }
595 }
596
597 if( aResetFabricationAttrs )
598 {
599 // We've replaced the existing footprint with the library one, so the fabrication attrs
600 // are already reset. Just set the aUpdated flag if appropriate.
601 if( aNew->GetAttributes() != aExisting->GetAttributes() )
602 *aUpdated = true;
603 }
604 else
605 {
606 aNew->SetAttributes( aExisting->GetAttributes() );
607 }
608
609 if( aResetClearanceOverrides )
610 {
611 if( aExisting->AllowSolderMaskBridges() != aNew->AllowSolderMaskBridges() )
612 *aUpdated = true;
613
614 if( ( aExisting->GetLocalClearance() != aNew->GetLocalClearance() )
615 || ( aExisting->GetLocalSolderMaskMargin() != aNew->GetLocalSolderMaskMargin() )
616 || ( aExisting->GetLocalSolderPasteMargin() != aNew->GetLocalSolderPasteMargin() )
618 || ( aExisting->GetLocalZoneConnection() != aNew->GetLocalZoneConnection() ) )
619 {
620 *aUpdated = true;
621 }
622 }
623 else
624 {
625 aNew->SetLocalClearance( aExisting->GetLocalClearance() );
631 }
632
633 if( aReset3DModels )
634 {
635 // We've replaced the existing footprint with the library one, so the 3D models are
636 // already reset. Just set the aUpdated flag if appropriate.
637 if( aNew->Models().size() != aExisting->Models().size() )
638 {
639 *aUpdated = true;
640 }
641 else
642 {
643 for( size_t ii = 0; ii < aNew->Models().size(); ++ii )
644 {
645 if( aNew->Models()[ii] != aExisting->Models()[ii] )
646 {
647 *aUpdated = true;
648 break;
649 }
650 }
651 }
652 }
653 else
654 {
655 // Preserve model references and all embedded model data.
656 aNew->Models() = aExisting->Models();
657
658 // Preserve extruded 3D body settings.
659 for( PCB_3D_BODY* body : aExisting->Bodies() )
660 aNew->Add( static_cast<PCB_3D_BODY*>( body->Clone() ), ADD_MODE::APPEND );
661
662 for( const auto& [name, file] : aExisting->GetEmbeddedFiles()->EmbeddedFileMap() )
663 {
665 continue;
666
667 aNew->GetEmbeddedFiles()->RemoveFile( name, true );
669 }
670 }
671
672 // Updating other parameters
673 aNew->SetPath( aExisting->GetPath() );
674 aNew->SetSheetfile( aExisting->GetSheetfile() );
675 aNew->SetSheetname( aExisting->GetSheetname() );
676 aNew->SetFilters( aExisting->GetFilters() );
678
679 if( *aUpdated == false )
680 {
681 // Check pad shapes, graphics, zones, etc. for changes
683 *aUpdated = true;
684 }
685
686 aCommit.Remove( aExisting );
687 aCommit.Add( aNew );
688
689 aNew->ClearFlags();
690}
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:87
void SetLocked(bool aLocked) override
Definition board_item.h:427
void SetUuid(const KIID &aUuid)
virtual bool IsKnockout() const
Definition board_item.h:423
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:424
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:383
VECTOR2I GetFPRelativePosition() const
@ INSTANCE_TO_INSTANCE
Definition board_item.h:585
void SetFPRelativePosition(const VECTOR2I &aPos)
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, FLIP_DIRECTION aFlipDirection, 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:228
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:599
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:394
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:347
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
void RemoveFile(const wxString &aName, 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:518
void SetPosition(const VECTOR2I &aPos) override
ZONE_CONNECTION GetLocalZoneConnection() const
Definition footprint.h:491
EDA_ANGLE GetOrientation() const
Definition footprint.h:382
ZONES & Zones()
Definition footprint.h:361
PCB_POINTS & Points()
Definition footprint.h:370
void SetOrientation(const EDA_ANGLE &aNewAngle)
void SetAllowSolderMaskBridges(bool aAllow)
Definition footprint.h:519
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:395
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition footprint.h:488
wxString GetSheetname() const
Definition footprint.h:469
void SetPath(const KIID_PATH &aPath)
Definition footprint.h:456
void SetFilters(const wxString &aFilters)
Definition footprint.h:476
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.
void SetAttributes(int aAttributes)
Definition footprint.h:510
void SetSheetfile(const wxString &aSheetfile)
Definition footprint.h:473
std::optional< int > GetLocalSolderPasteMargin() const
Definition footprint.h:484
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:831
std::optional< int > GetLocalClearance() const
Definition footprint.h:478
std::deque< PAD * > & Pads()
Definition footprint.h:355
int GetAttributes() const
Definition footprint.h:509
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition footprint.h:490
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition footprint.h:393
wxString GetSheetfile() const
Definition footprint.h:472
const LIB_ID & GetFPID() const
Definition footprint.h:417
int GetHeight() const
The overall height of the footprint, or 0 if not specified.
Definition footprint.h:438
void SetHeight(int aHeight)
Definition footprint.h:439
void SetTransformScale(double aScaleX, double aScaleY)
PCB_FIELD & Reference()
Definition footprint.h:832
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Adds an item to the container.
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition footprint.h:487
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
GROUPS & Groups()
Definition footprint.h:364
wxString GetFilters() const
Definition footprint.h:475
void SetSheetname(const wxString &aSheetname)
Definition footprint.h:470
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:375
const wxString & GetValue() const
Definition footprint.h:817
const COMPONENT_CLASS * GetStaticComponentClass() const
Returns the component class for this footprint.
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition footprint.h:482
void SetLocalClearance(std::optional< int > aClearance)
Definition footprint.h:479
const KIID_PATH & GetPath() const
Definition footprint.h:455
std::optional< int > GetLocalSolderMaskMargin() const
Definition footprint.h:481
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition footprint.h:485
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition footprint.h:1280
std::deque< PCB_3D_BODY * > & Bodies()
Definition footprint.h:422
VECTOR2I GetPosition() const override
Definition footprint.h:379
DRAWINGS & GraphicalItems()
Definition footprint.h:358
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:281
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:1969
void SetPinFunction(const wxString &aName)
Set the pad function (pin name in schematic)
Definition pad.h:153
A 3D body attached to a footprint (or, later, placed on a board).
Definition pcb_3d_body.h:93
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:695
int GetTextThickness() const override
Definition pcb_text.cpp:497
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:572
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:448
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
@ 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 and validation.
FLIP_DIRECTION
Definition mirror.h:23
Class to handle a set of BOARD_ITEMs.
static std::vector< int > candidates(const SEGMENT_INDEX &aIndex, const SEG &aQuery, int aPadding)
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:708