1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #ifndef FOOTPRINT_H
26 #define FOOTPRINT_H
27 
28 #include <deque>
29 
30 #include <board_item_container.h>
31 #include <board_item.h>
32 #include <collectors.h>
33 #include <convert_to_biu.h>
34 #include <layer_ids.h> // ALL_LAYERS definition.
35 #include <lib_id.h>
36 #include <list>
37 
38 #include <zones.h>
39 #include <convert_shape_list_to_polygon.h>
40 #include <pcb_item_containers.h>
41 #include <fp_text.h>
42 #include <functional>
43 
44 class LINE_READER;
45 class EDA_3D_CANVAS;
46 class PAD;
47 class BOARD;
48 class MSG_PANEL_ITEM;
49 class SHAPE;
50 
51 namespace KIGFX {
52 class VIEW;
53 }
54 
55 enum INCLUDE_NPTH_T
56 {
57     DO_NOT_INCLUDE_NPTH = false,
58     INCLUDE_NPTH = true
59 };
60 
61 /**
62  * The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes()
63  * and FOOTPRINT::GetAttributes().  These are to be ORed together when calling
64  * FOOTPRINT::SetAttributes()
65  */
66 enum FOOTPRINT_ATTR_T
67 {
68     FP_THROUGH_HOLE           = 0x0001,
69     FP_SMD                    = 0x0002,
70     FP_EXCLUDE_FROM_POS_FILES = 0x0004,
71     FP_EXCLUDE_FROM_BOM       = 0x0008,
72     FP_BOARD_ONLY             = 0x0010,   // Footprint has no corresponding symbol
73     FP_JUST_ADDED             = 0x0020    // Footprint just added by netlist update
74 };
75 
76 class FP_3DMODEL
77 {
78 public:
FP_3DMODEL()79     FP_3DMODEL() :
80         // Initialize with sensible values
81         m_Scale { 1, 1, 1 },
82         m_Rotation { 0, 0, 0 },
83         m_Offset { 0, 0, 0 },
84         m_Opacity( 1.0 ),
85         m_Show( true )
86     {
87     }
88 
89     struct VECTOR3D
90     {
91         double x, y, z;
92     };
93 
94     VECTOR3D m_Scale;       ///< 3D model scaling factor (dimensionless)
95     VECTOR3D m_Rotation;    ///< 3D model rotation (degrees)
96     VECTOR3D m_Offset;      ///< 3D model offset (mm)
97     double   m_Opacity;
98     wxString m_Filename;    ///< The 3D shape filename in 3D library
99     bool     m_Show;        ///< Include model in rendering
100 };
101 
102 
103 class FOOTPRINT : public BOARD_ITEM_CONTAINER
104 {
105 public:
106     FOOTPRINT( BOARD* parent );
107 
108     FOOTPRINT( const FOOTPRINT& aFootprint );
109 
110     // Move constructor and operator needed due to std containers inside the footprint
111     FOOTPRINT( FOOTPRINT&& aFootprint );
112 
113     ~FOOTPRINT();
114 
115     FOOTPRINT& operator=( const FOOTPRINT& aOther );
116     FOOTPRINT& operator=( FOOTPRINT&& aOther );
117 
ClassOf(const EDA_ITEM * aItem)118     static inline bool ClassOf( const EDA_ITEM* aItem )
119     {
120         return aItem && aItem->Type() == PCB_FOOTPRINT_T;
121     }
122 
123     ///< @copydoc BOARD_ITEM_CONTAINER::Add()
124     void Add( BOARD_ITEM* aItem, ADD_MODE aMode = ADD_MODE::INSERT ) override;
125 
126     ///< @copydoc BOARD_ITEM_CONTAINER::Remove()
127     void Remove( BOARD_ITEM* aItem, REMOVE_MODE aMode = REMOVE_MODE::NORMAL ) override;
128 
129     /**
130      * Clear (i.e. force the ORPHANED dummy net info) the net info which
131      * depends on a given board for all pads of the footprint.
132      *
133      * This is needed when a footprint is copied between the fp editor and
134      * the board editor for instance, because net info become fully broken
135      */
136     void ClearAllNets();
137 
138     /**
139      * Old footprints do not alway have a valid UUID (some can be set to null uuid)
140      * However null UUIDs, having a special meaning in editor, create issues when
141      * editing a footprint
142      * So all null uuids a re replaced by a valid uuid
143      * @return true if at least one uuid is changed, false if no change
144      */
145     bool FixUuids();
146 
147     /**
148      * Return the bounding box containing pads when the footprint is on the front side,
149      * orientation 0, position 0,0.
150      *
151      * Mainly used in Gerber place file to draw a footprint outline when the courtyard
152      * is missing or broken.
153      *
154      * @return The rectangle containing the pads for the normalized footprint.
155      */
156     EDA_RECT GetFpPadsLocalBbox() const;
157 
158     /**
159      * Return a bounding polygon for the shapes and pads in the footprint.
160      *
161      * This operation is slower but more accurate than calculating a bounding box.
162      */
163     SHAPE_POLY_SET GetBoundingHull() const;
164 
165     // Virtual function
166     const EDA_RECT GetBoundingBox() const override;
167     const EDA_RECT GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const;
168 
Pads()169     PADS& Pads()             { return m_pads; }
Pads()170     const PADS& Pads() const { return m_pads; }
171 
GraphicalItems()172     DRAWINGS& GraphicalItems()             { return m_drawings; }
GraphicalItems()173     const DRAWINGS& GraphicalItems() const { return m_drawings; }
174 
Zones()175     FP_ZONES& Zones()             { return m_fp_zones; }
Zones()176     const FP_ZONES& Zones() const { return m_fp_zones; }
177 
Groups()178     FP_GROUPS& Groups()             { return m_fp_groups; }
Groups()179     const FP_GROUPS& Groups() const { return m_fp_groups; }
180 
181     bool HasThroughHolePads() const;
182 
Models()183     std::list<FP_3DMODEL>& Models()             { return m_3D_Drawings; }
Models()184     const std::list<FP_3DMODEL>& Models() const { return m_3D_Drawings; }
185 
186     void SetPosition( const wxPoint& aPos ) override;
GetPosition()187     wxPoint GetPosition() const override { return m_pos; }
188 
189     void SetOrientation( double aNewAngle );
SetOrientationDegrees(double aOrientation)190     void SetOrientationDegrees( double aOrientation ) { SetOrientation( aOrientation * 10.0 ); }
GetOrientation()191     double GetOrientation() const { return m_orient; }
GetOrientationDegrees()192     double GetOrientationDegrees() const { return m_orient / 10.0; }
GetOrientationRadians()193     double GetOrientationRadians() const { return m_orient * M_PI / 1800; }
194 
GetFPID()195     const LIB_ID& GetFPID() const { return m_fpid; }
SetFPID(const LIB_ID & aFPID)196     void SetFPID( const LIB_ID& aFPID ) { m_fpid = aFPID; }
197 
GetDescription()198     const wxString& GetDescription() const { return m_doc; }
SetDescription(const wxString & aDoc)199     void SetDescription( const wxString& aDoc ) { m_doc = aDoc; }
200 
GetKeywords()201     const wxString& GetKeywords() const { return m_keywords; }
SetKeywords(const wxString & aKeywords)202     void SetKeywords( const wxString& aKeywords ) { m_keywords = aKeywords; }
203 
GetPath()204     const KIID_PATH& GetPath() const { return m_path; }
SetPath(const KIID_PATH & aPath)205     void SetPath( const KIID_PATH& aPath ) { m_path = aPath; }
206 
GetLocalSolderMaskMargin()207     int GetLocalSolderMaskMargin() const { return m_localSolderMaskMargin; }
SetLocalSolderMaskMargin(int aMargin)208     void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; }
209 
GetLocalClearance()210     int GetLocalClearance() const { return m_localClearance; }
SetLocalClearance(int aClearance)211     void SetLocalClearance( int aClearance ) { m_localClearance = aClearance; }
212 
GetLocalClearance(wxString * aSource)213     int GetLocalClearance( wxString* aSource ) const
214     {
215         if( aSource )
216             *aSource = wxString::Format( _( "footprint %s" ), GetReference() );
217 
218         return m_localClearance;
219     }
220 
GetLocalSolderPasteMargin()221     int GetLocalSolderPasteMargin() const { return m_localSolderPasteMargin; }
SetLocalSolderPasteMargin(int aMargin)222     void SetLocalSolderPasteMargin( int aMargin ) { m_localSolderPasteMargin = aMargin; }
223 
GetLocalSolderPasteMarginRatio()224     double GetLocalSolderPasteMarginRatio() const { return m_localSolderPasteMarginRatio; }
SetLocalSolderPasteMarginRatio(double aRatio)225     void SetLocalSolderPasteMarginRatio( double aRatio ) { m_localSolderPasteMarginRatio = aRatio; }
226 
SetZoneConnection(ZONE_CONNECTION aType)227     void SetZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; }
GetZoneConnection()228     ZONE_CONNECTION GetZoneConnection() const { return m_zoneConnection; }
229 
SetThermalWidth(int aWidth)230     void SetThermalWidth( int aWidth ) { m_thermalWidth = aWidth; }
GetThermalWidth()231     int GetThermalWidth() const { return m_thermalWidth; }
232 
SetThermalGap(int aGap)233     void SetThermalGap( int aGap ) { m_thermalGap = aGap; }
GetThermalGap()234     int GetThermalGap() const { return m_thermalGap; }
235 
GetAttributes()236     int GetAttributes() const { return m_attributes; }
SetAttributes(int aAttributes)237     void SetAttributes( int aAttributes ) { m_attributes = aAttributes; }
238 
SetFlag(int aFlag)239     void SetFlag( int aFlag ) { m_arflag = aFlag; }
IncrementFlag()240     void IncrementFlag() { m_arflag += 1; }
GetFlag()241     int GetFlag() const { return m_arflag; }
242 
243     // A bit of a hack until net ties are supported as first class citizens
IsNetTie()244     bool IsNetTie() const
245     {
246         return GetKeywords().StartsWith( wxT( "net tie" ) );
247     }
248 
249     /**
250      * Returns the most likely attribute based on pads
251      * Either FP_THROUGH_HOLE/FP_SMD/OTHER(0)
252      * @return 0/FP_SMD/FP_THROUGH_HOLE
253      */
254     int GetLikelyAttribute() const;
255 
256     void Move( const wxPoint& aMoveVector ) override;
257 
258     void Rotate( const wxPoint& aRotCentre, double aAngle ) override;
259 
260     void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
261 
262     /**
263      * Move the reference point of the footprint.
264      *
265      * It looks like a move footprint:
266      * the footprints elements (pads, outlines, edges .. ) are moved
267      * However:
268      * - the footprint position is not modified.
269      * - the relative (local) coordinates of these items are modified
270      * (a move footprint does not change these local coordinates,
271      * but changes the footprint position)
272      */
273     void MoveAnchorPosition( const wxPoint& aMoveVector );
274 
275     /**
276      * @return true if the footprint is flipped, i.e. on the back side of the board
277      */
IsFlipped()278     bool IsFlipped() const { return GetLayer() == B_Cu; }
279 
280     /**
281      * A special IsOnLayer for footprints: return true if the footprint contains only items on the
282      * given layer, even if that layer is not one of the valid footprint layers F_Cu and B_Cu.
283      * This allows selection of "graphic" footprints that contain only silkscreen, for example.
284      */
285     bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
286 
287 // m_footprintStatus bits:
288 #define FP_is_LOCKED        0x01        ///< footprint LOCKED: no autoplace allowed
289 #define FP_is_PLACED        0x02        ///< In autoplace: footprint automatically placed
290 #define FP_to_PLACE         0x04        ///< In autoplace: footprint waiting for autoplace
291 #define FP_PADS_are_LOCKED  0x08
292 
293 
IsLocked()294     bool IsLocked() const override
295     {
296         return ( m_fpStatus & FP_is_LOCKED ) != 0;
297     }
298 
299     /**
300      * Set the #MODULE_is_LOCKED bit in the m_ModuleStatus.
301      *
302      * @param isLocked true means turn on locked status, else unlock
303      */
SetLocked(bool isLocked)304     void SetLocked( bool isLocked ) override
305     {
306         if( isLocked )
307             m_fpStatus |= FP_is_LOCKED;
308         else
309             m_fpStatus &= ~FP_is_LOCKED;
310     }
311 
IsPlaced()312     bool IsPlaced() const { return m_fpStatus & FP_is_PLACED;  }
SetIsPlaced(bool isPlaced)313     void SetIsPlaced( bool isPlaced )
314     {
315         if( isPlaced )
316             m_fpStatus |= FP_is_PLACED;
317         else
318             m_fpStatus &= ~FP_is_PLACED;
319     }
320 
NeedsPlaced()321     bool NeedsPlaced() const { return m_fpStatus & FP_to_PLACE;  }
SetNeedsPlaced(bool needsPlaced)322     void SetNeedsPlaced( bool needsPlaced )
323     {
324         if( needsPlaced )
325             m_fpStatus |= FP_to_PLACE;
326         else
327             m_fpStatus &= ~FP_to_PLACE;
328     }
329 
LegacyPadsLocked()330     bool LegacyPadsLocked() const { return m_fpStatus & FP_PADS_are_LOCKED;  }
331 
332     /*
333     void SetPadsLocked( bool aPadsLocked )
334     {
335         if( aPadsLocked )
336             m_fpStatus |= FP_PADS_are_LOCKED;
337         else
338             m_fpStatus &= ~FP_PADS_are_LOCKED;
339     }
340     */
341 
SetLastEditTime(timestamp_t aTime)342     void SetLastEditTime( timestamp_t aTime ) { m_lastEditTime = aTime; }
SetLastEditTime()343     void SetLastEditTime() { m_lastEditTime = time( nullptr ); }
GetLastEditTime()344     timestamp_t GetLastEditTime() const { return m_lastEditTime; }
345 
346     /**
347      * Test if footprint attributes for type (SMD/Through hole/Other) match the expected
348      * type based on the pads in the footprint.
349      * Footprints with plated through-hole pads should usually be marked through hole even if they also
350      * have SMD because they might not be auto-placed.  Exceptions to this might be shielded connectors
351      * Otherwise, footprints with SMD pads should be marked SMD
352      * Footprints with no connecting pads should be marked "Other"
353      *
354      * @param aErrorHandler callback to handle the error messages generated
355      */
356     void CheckFootprintAttributes( const std::function<void( const wxString& msg )>* aErrorHandler );
357 
358     /**
359      * Test if footprint attributes for type (SMD/Through hole/Other) match the expected
360      * type based on the pads in the footprint.
361      * Footprints with plated through-hole pads should usually be marked through hole even if they also
362      * have SMD because they might not be auto-placed.  Exceptions to this might be shielded connectors
363      * Otherwise, footprints with SMD pads should be marked SMD
364      * Footprints with no connecting pads should be marked "Other"
365      *
366      * @param aErrorHandler callback to handle the error messages generated
367      */
368     void CheckFootprintTHPadNoHoles( const std::function
369                                      <void( const wxString& msg, const wxPoint& position )>*
370                                      aErrorHandler );
371 
372     /**
373      * Generate pads shapes on layer \a aLayer as polygons and adds these polygons to
374      * \a aCornerBuffer.
375      *
376      * Useful to generate a polygonal representation of a footprint in 3D view and plot functions,
377      * when a full polygonal approach is needed.
378      *
379      * @param aLayer is the layer to consider, or #UNDEFINED_LAYER to consider all layers.
380      * @param aCornerBuffer i the buffer to store polygons.
381      * @param aClearance is an additional size to add to pad shapes.
382      * @param aMaxError is the maximum deviation from true for arcs.
383      * @param aSkipNPTHPadsWihNoCopper if true, do not add a NPTH pad shape, if the shape has
384      *          same size and position as the hole. Usually, these pads are not drawn on copper
385      *          layers, because there is actually no copper
386      *          Due to diff between layers and holes, these pads must be skipped to be sure
387      *          there is no copper left on the board (for instance when creating Gerber Files or
388      *          3D shapes).  Defaults to false.
389      * @param aSkipPlatedPads is used on 3D-Viewer to extract plated and non-plated pads.
390      * @param aSkipNonPlatedPads is used on 3D-Viewer to extract plated and plated pads.
391      */
392     void TransformPadsWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
393                                               PCB_LAYER_ID aLayer, int aClearance,
394                                               int aMaxError, ERROR_LOC aErrorLoc,
395                                               bool aSkipNPTHPadsWihNoCopper = false,
396                                               bool aSkipPlatedPads = false,
397                                               bool aSkipNonPlatedPads = false ) const;
398 
399     /**
400      * Generate shapes of graphic items (outlines) on layer \a aLayer as polygons and adds these
401      * polygons to \a aCornerBuffer.
402      *
403      * Useful to generate a polygonal representation of a footprint in 3D view and plot functions,
404      * when a full polygonal approach is needed.
405      *
406      * @param aLayer is the layer to consider, or #UNDEFINED_LAYER to consider all.
407      * @param aCornerBuffer is the buffer to store polygons.
408      * @param aClearance is a value to inflate shapes.
409      * @param aError is the maximum error between true arc and polygon approximation.
410      * @param aIncludeText set to true to transform text shapes.
411      * @param aIncludeShapes set to true to transform footprint shapes.
412      */
413     void TransformFPShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
414                                                   PCB_LAYER_ID aLayer, int aClearance,
415                                                   int aError, ERROR_LOC aErrorLoc,
416                                                   bool aIncludeText = true,
417                                                   bool aIncludeShapes = true ) const;
418 
419     /**
420      * This function is the same as TransformGraphicShapesWithClearanceToPolygonSet
421      * but only generate text.
422      */
TransformFPTextWithClearanceToPolygonSet(SHAPE_POLY_SET & aCornerBuffer,PCB_LAYER_ID aLayer,int aClearance,int aError,ERROR_LOC aErrorLoc)423     void TransformFPTextWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
424                                                    PCB_LAYER_ID aLayer, int aClearance,
425                                                    int aError, ERROR_LOC aErrorLoc ) const
426     {
427         TransformFPShapesWithClearanceToPolygon( aCornerBuffer, aLayer, aClearance, aError,
428                                                  aErrorLoc, true, false );
429     }
430 
431     /**
432      * Return the list of system text vars for this footprint.
433      */
434     void GetContextualTextVars( wxArrayString* aVars ) const;
435 
436     /**
437      * Resolve any references to system tokens supported by the component.
438      *
439      * @param aDepth a counter to limit recursion and circular references.
440      */
441     bool ResolveTextVar( wxString* token, int aDepth = 0 ) const;
442 
443     ///< @copydoc EDA_ITEM::GetMsgPanelInfo
444     void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
445 
446     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
447 
448     /**
449      * Test if a point is inside the bounding polygon of the footprint.
450      *
451      * The other hit test methods are just checking the bounding box, which can be quite
452      * inaccurate for rotated or oddly-shaped footprints.
453      *
454      * @param aPosition is the point to test
455      * @return true if aPosition is inside the bounding polygon
456      */
457     bool HitTestAccurate( const wxPoint& aPosition, int aAccuracy = 0 ) const;
458 
459     bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
460 
461     /**
462      * @return reference designator text.
463      */
GetReference()464     const wxString& GetReference() const
465     {
466         return m_reference->GetText();
467     }
468 
469     /**
470      * @param aReference A reference to a wxString object containing the reference designator
471      *                   text.
472      */
SetReference(const wxString & aReference)473     void SetReference( const wxString& aReference )
474     {
475         m_reference->SetText( aReference );
476     }
477 
478     /**
479      * Bump the current reference by \a aDelta.
480      */
481     void IncrementReference( int aDelta );
482 
483     /**
484      * @return the value text.
485      */
GetValue()486     const wxString& GetValue() const
487     {
488         return m_value->GetText();
489     }
490 
491     /**
492      * @param aValue A reference to a wxString object containing the value text.
493      */
SetValue(const wxString & aValue)494     void SetValue( const wxString& aValue )
495     {
496         m_value->SetText( aValue );
497     }
498 
499     /// read/write accessors:
Value()500     FP_TEXT& Value()           { return *m_value; }
Reference()501     FP_TEXT& Reference()       { return *m_reference; }
502 
503     /// The const versions to keep the compiler happy.
Value()504     FP_TEXT& Value() const     { return *m_value; }
Reference()505     FP_TEXT& Reference() const { return *m_reference; }
506 
GetProperties()507     const std::map<wxString, wxString>& GetProperties() const { return m_properties; }
SetProperties(const std::map<wxString,wxString> & aProps)508     void SetProperties( const std::map<wxString, wxString>& aProps ) { m_properties = aProps; }
GetProperty(const wxString & aKey)509     const wxString& GetProperty( const wxString& aKey) { return m_properties[ aKey ]; }
HasProperty(const wxString & aKey)510     bool HasProperty( const wxString& aKey)
511     {
512         return m_properties.find( aKey ) != m_properties.end();
513     }
SetProperty(const wxString & aKey,const wxString & aVal)514     void SetProperty( const wxString& aKey, const wxString& aVal ) { m_properties[ aKey ] = aVal; }
515 
516     /**
517      * Return a #PAD with a matching number.
518      *
519      * @note Numbers may not be unique depending on how the footprint was created.
520      *
521      * @param aPadNumber the pad number to find.
522      * @param aSearchAfterMe = not nullptr to find a pad living after aAfterMe
523      * @return the first matching numbered #PAD is returned or NULL if not found.
524      */
525     PAD* FindPadByNumber( const wxString& aPadNumber, PAD* aSearchAfterMe = nullptr ) const;
526 
527     /**
528      * Get a pad at \a aPosition on \a aLayerMask in the footprint.
529      *
530      * @param aPosition A wxPoint object containing the position to hit test.
531      * @param aLayerMask A layer or layers to mask the hit test.
532      * @return A pointer to a #PAD object if found otherwise NULL.
533      */
534     PAD* GetPad( const wxPoint& aPosition, LSET aLayerMask = LSET::AllLayersMask() );
535 
536     PAD* GetTopLeftPad();
537 
538     /**
539      * Return the number of pads.
540      *
541      * @param aIncludeNPTH includes non-plated through holes when true.  Does not include
542      *                     non-plated through holes when false.
543      * @return the number of pads according to \a aIncludeNPTH.
544      */
545     unsigned GetPadCount( INCLUDE_NPTH_T aIncludeNPTH = INCLUDE_NPTH_T(INCLUDE_NPTH) ) const;
546 
547     /**
548      * Return the number of unique non-blank pads.
549      *
550      * A complex pad can be built with many pads having the same pad name to create a complex
551      * shape or fragmented solder paste areas.
552      *
553      * @param aIncludeNPTH includes non-plated through holes when true.  Does not include
554      *                     non-plated through holes when false.
555      * @return the number of unique pads according to \a aIncludeNPTH.
556      */
557     unsigned GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH = INCLUDE_NPTH_T(INCLUDE_NPTH) ) const;
558 
559     /**
560      * Return the next available pad number in the footprint.
561      *
562      * @param aFillSequenceGaps true if the numbering should "fill in" gaps in the sequence,
563      *                          else return the highest value + 1
564      * @return the next available pad number
565      */
566     wxString GetNextPadNumber( const wxString& aLastPadName ) const;
567 
568     /**
569      * Get the type of footprint
570      * @return "SMD"/"Through hole"/"Other" based on attributes
571      */
572     wxString GetTypeName() const;
573 
574     double GetArea( int aPadding = 0 ) const;
575 
GetLink()576     KIID GetLink() const { return m_link; }
SetLink(const KIID & aLink)577     void SetLink( const KIID& aLink ) { m_link = aLink; }
578 
GetPlacementCost180()579     int GetPlacementCost180() const { return m_rot180Cost; }
SetPlacementCost180(int aCost)580     void SetPlacementCost180( int aCost )   { m_rot180Cost = aCost; }
581 
GetPlacementCost90()582     int GetPlacementCost90() const { return m_rot90Cost; }
SetPlacementCost90(int aCost)583     void SetPlacementCost90( int aCost )    { m_rot90Cost = aCost; }
584 
585     BOARD_ITEM* Duplicate() const override;
586 
587     /**
588      * Duplicate a given item within the footprint, optionally adding it to the board.
589      *
590      * @return the new item, or NULL if the item could not be duplicated.
591      */
592     BOARD_ITEM* DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootprint = false );
593 
594     /**
595      * Add \a a3DModel definition to the end of the 3D model list.
596      *
597      * @param a3DModel A pointer to a #FP_3DMODEL to add to the list.
598      */
599     void Add3DModel( FP_3DMODEL* a3DModel );
600 
601     SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override;
602 
GetClass()603     wxString GetClass() const override
604     {
605         return wxT( "FOOTPRINT" );
606     }
607 
608     wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
609 
610     BITMAPS GetMenuImage() const override;
611 
612     EDA_ITEM* Clone() const override;
613 
614     /**
615      * Invoke a function on all BOARD_ITEMs that belong to the footprint (pads, drawings, texts).
616      *
617      * @note This function should not add or remove items to the footprint.
618      *
619      * @param aFunction is the function to be invoked.
620      */
621     void RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction ) const;
622 
623     /**
624      * Return a set of all layers that this footprint has drawings on similar to ViewGetLayers().
625      *
626      * @param aLayers is an array to store layer ids.
627      * @param aCount is the number of layers stored in the array.
628      * @param aIncludePads controls whether to also include pad layers.
629      */
630     void GetAllDrawingLayers( int aLayers[], int& aCount, bool aIncludePads = true ) const;
631 
632     virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
633 
634     double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
635 
636     virtual const BOX2I ViewBBox() const override;
637 
638     /**
639      * Test for validity of a name of a footprint to be used in a footprint library
640      * ( no spaces, dir separators ... ).
641      *
642      * @param aName is the name in library to validate.
643      * @return true if the given name is valid
644      */
645     static bool IsLibNameValid( const wxString& aName );
646 
647     /**
648      * Test for validity of the name in a library of the footprint ( no spaces, dir
649      * separators ... ).
650      *
651      * @param aUserReadable set to false to get the list of invalid characters or  true to get
652      *                      a readable form (i.e ' ' = 'space' '\\t'= 'tab').
653      *
654      * @return the list of invalid chars in the library name.
655      */
656     static const wxChar* StringLibNameInvalidChars( bool aUserReadable );
657 
658     /**
659      * Take ownership of caller's heap allocated aInitialComments block.
660      *
661      * The comments are single line strings already containing the s-expression comments with
662      * optional leading whitespace and then a '#' character followed by optional single line
663      * text (text with no line endings, not even one).  This block of single line comments
664      * will be output upfront of any generated s-expression text in the PCBIO::Format() function.
665      *
666      * @note A block of single line comments constitutes a multiline block of single line
667      *       comments.  That is, the block is made of consecutive single line comments.
668      *
669      * @param aInitialComments is a heap allocated wxArrayString or NULL, which the caller
670      *                         gives up ownership of over to this FOOTPRINT.
671      */
SetInitialComments(wxArrayString * aInitialComments)672     void SetInitialComments( wxArrayString* aInitialComments )
673     {
674         delete m_initial_comments;
675         m_initial_comments = aInitialComments;
676     }
677 
678     /**
679      * Calculate the ratio of total area of the footprint pads and graphical items to the
680      * area of the footprint. Used by selection tool heuristics.
681      *
682      * @return the ratio.
683      */
684     double CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const;
685 
686     static double GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLECTOR& aCollector );
687 
688     ///< Return the initial comments block or NULL if none, without transfer of ownership.
GetInitialComments()689     const wxArrayString* GetInitialComments() const { return m_initial_comments; }
690 
691     /**
692      * Used in DRC to test the courtyard area (a complex polygon).
693      *
694      * @return the courtyard polygon.
695      */
GetPolyCourtyard(PCB_LAYER_ID aLayer)696     const SHAPE_POLY_SET& GetPolyCourtyard( PCB_LAYER_ID aLayer ) const
697     {
698         if( IsBackLayer( aLayer ) )
699             return m_poly_courtyard_back;
700         else
701             return m_poly_courtyard_front;
702     }
703 
704     /**
705      * Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
706      *
707      * @note Set the #MALFORMED_F_COURTYARD and #MALFORMED_B_COURTYARD status flags if the given
708      *       courtyard layer does not contain a (single) closed shape.
709      */
710     void BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
711 
712     virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
713 
714     virtual void SwapData( BOARD_ITEM* aImage ) override;
715 
716     struct cmp_drawings
717     {
718         bool operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const;
719     };
720 
721     struct cmp_pads
722     {
723         bool operator()( const PAD* aFirst, const PAD* aSecond ) const;
724     };
725 
726 
727 #if defined(DEBUG)
Show(int nestLevel,std::ostream & os)728     virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
729 #endif
730 
731 private:
732     DRAWINGS        m_drawings;          // BOARD_ITEMs for drawings on the board, owned by pointer.
733     PADS            m_pads;              // PAD items, owned by pointer
734     FP_ZONES        m_fp_zones;          // FP_ZONE items, owned by pointer
735     FP_GROUPS       m_fp_groups;         // PCB_GROUP items, owned by pointer
736 
737     double          m_orient;            // Orientation in tenths of a degree, 900=90.0 degrees.
738     wxPoint         m_pos;               // Position of footprint on the board in internal units.
739     FP_TEXT*        m_reference;         // Component reference designator value (U34, R18..)
740     FP_TEXT*        m_value;             // Component value (74LS00, 22K..)
741     LIB_ID          m_fpid;              // The #LIB_ID of the FOOTPRINT.
742     int             m_attributes;        // Flag bits ( see FOOTPRINT_ATTR_T )
743     int             m_fpStatus;          // For autoplace: flags (LOCKED, FIELDS_AUTOPLACED)
744 
745     // Bounding box caching strategy:
746     // While we attempt to notice the low-hanging fruit operations and update the bounding boxes
747     // accordingly, we rely mostly on a "if anything changed then the caches are stale" approach.
748     // We implement this by having PCB_BASE_FRAME's OnModify() method increment an operation
749     // counter, and storing that as a timestamp for the various caches.
750     // This means caches will get regenerated often -- but still far less often than if we had no
751     // caches at all.  The principal opitmization would be to change to dirty flag and make sure
752     // that any edit that could affect the bounding boxes (including edits to the footprint
753     // children) marked the bounding boxes dirty.  It would definitely be faster -- but also more
754     // fragile.
755     mutable EDA_RECT       m_cachedBoundingBox;
756     mutable int            m_boundingBoxCacheTimeStamp;
757     mutable EDA_RECT       m_cachedVisibleBBox;
758     mutable int            m_visibleBBoxCacheTimeStamp;
759     mutable EDA_RECT       m_cachedTextExcludedBBox;
760     mutable int            m_textExcludedBBoxCacheTimeStamp;
761     mutable SHAPE_POLY_SET m_cachedHull;
762     mutable int            m_hullCacheTimeStamp;
763 
764     ZONE_CONNECTION m_zoneConnection;
765     int             m_thermalWidth;
766     int             m_thermalGap;
767     int             m_localClearance;
768     int             m_localSolderMaskMargin;       // Solder mask margin
769     int             m_localSolderPasteMargin;      // Solder paste margin absolute value
770     double          m_localSolderPasteMarginRatio; // Solder mask margin ratio value of pad size
771 
772     wxString        m_doc;               // File name and path for documentation file.
773     wxString        m_keywords;          // Search keywords to find footprint in library.
774     KIID_PATH       m_path;              // Path to associated symbol ([sheetUUID, .., symbolUUID]).
775     timestamp_t     m_lastEditTime;
776     int             m_arflag;            // Use to trace ratsnest and auto routing.
777     KIID            m_link;              // Temporary logical link used during editing
778     int             m_rot90Cost;         // Horizontal automatic placement cost ( 0..10 ).
779     int             m_rot180Cost;        // Vertical automatic placement cost ( 0..10 ).
780 
781     std::list<FP_3DMODEL>         m_3D_Drawings;       // Linked list of 3D models.
782     std::map<wxString, wxString>  m_properties;
783     wxArrayString*                m_initial_comments;  // s-expression comments in the footprint,
784                                                        // lazily allocated only if needed for speed
785 
786     SHAPE_POLY_SET  m_poly_courtyard_front;  // Note that a footprint can have both front and back
787     SHAPE_POLY_SET  m_poly_courtyard_back;   // courtyards populated.
788 };
789 
790 #endif     // FOOTPRINT_H
791