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