1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com 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 CLASS_BOARD_H_ 26 #define CLASS_BOARD_H_ 27 28 #include <board_item_container.h> 29 #include <common.h> // Needed for stl hash extensions 30 #include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER 31 #include <layer_ids.h> 32 #include <netinfo.h> 33 #include <pcb_item_containers.h> 34 #include <pcb_plot_params.h> 35 #include <title_block.h> 36 #include <tools/pcb_selection.h> 37 #include <mutex> 38 #include <list> 39 40 class BOARD_DESIGN_SETTINGS; 41 class BOARD_CONNECTED_ITEM; 42 class BOARD_COMMIT; 43 class DRC_RTREE; 44 class PCB_BASE_FRAME; 45 class PCB_EDIT_FRAME; 46 class PICKED_ITEMS_LIST; 47 class BOARD; 48 class FOOTPRINT; 49 class ZONE; 50 class PCB_TRACK; 51 class PAD; 52 class PCB_GROUP; 53 class PCB_MARKER; 54 class MSG_PANEL_ITEM; 55 class NETLIST; 56 class REPORTER; 57 class SHAPE_POLY_SET; 58 class CONNECTIVITY_DATA; 59 class COMPONENT; 60 class PROJECT; 61 class PROGRESS_REPORTER; 62 63 // Forward declare endpoint from class_track.h 64 enum ENDPOINT_T : int; 65 66 /** 67 * The allowed types of layers, same as Specctra DSN spec. 68 */ 69 enum LAYER_T 70 { 71 LT_UNDEFINED = -1, 72 LT_SIGNAL, 73 LT_POWER, 74 LT_MIXED, 75 LT_JUMPER 76 }; 77 78 79 /** 80 * Container to hold information pertinent to a layer of a BOARD. 81 */ 82 struct LAYER 83 { LAYERLAYER84 LAYER() 85 { 86 clear(); 87 } 88 clearLAYER89 void clear() 90 { 91 m_type = LT_SIGNAL; 92 m_visible = true; 93 m_number = 0; 94 m_name.clear(); 95 m_userName.clear(); 96 } 97 98 /* 99 LAYER( const wxString& aName = wxEmptyString, 100 LAYER_T aType = LT_SIGNAL, bool aVisible = true, int aNumber = -1 ) : 101 m_name( aName ), 102 m_type( aType ), 103 m_visible( aVisible ), 104 m_number( aNumber ) 105 { 106 } 107 */ 108 109 wxString m_name; ///< The canonical name of the layer. @see #LSET::Name 110 wxString m_userName; ///< The user defined name of the layer. 111 LAYER_T m_type; ///< The type of the layer. @see #LAYER_T 112 bool m_visible; 113 int m_number; ///< The layer ID. @see PCB_LAYER_ID 114 115 /** 116 * Convert a #LAYER_T enum to a string representation of the layer type. 117 * 118 * @param aType The #LAYER_T to convert 119 * @return The string representation of the layer type. 120 */ 121 static const char* ShowType( LAYER_T aType ); 122 123 /** 124 * Convert a string to a #LAYER_T 125 * 126 * @param aType The layer name to convert. 127 * @return The binary representation of the layer type, or 128 * LAYER_T(-1) if the string is invalid. 129 */ 130 static LAYER_T ParseType( const char* aType ); 131 }; 132 133 134 // Helper class to handle high light nets 135 class HIGH_LIGHT_INFO 136 { 137 protected: 138 std::set<int> m_netCodes; // net(s) selected for highlight (-1 when no net selected ) 139 bool m_highLightOn; // highlight active 140 Clear()141 void Clear() 142 { 143 m_netCodes.clear(); 144 m_highLightOn = false; 145 } 146 HIGH_LIGHT_INFO()147 HIGH_LIGHT_INFO() 148 { 149 Clear(); 150 } 151 152 private: 153 friend class BOARD; 154 }; 155 156 /** 157 * Provide an interface to hook into board modifications and get callbacks 158 * on certain modifications that are made to the board. This allows updating 159 * auxiliary views other than the primary board editor view. 160 */ 161 class BOARD; 162 163 class BOARD_LISTENER 164 { 165 public: ~BOARD_LISTENER()166 virtual ~BOARD_LISTENER() { } OnBoardItemAdded(BOARD & aBoard,BOARD_ITEM * aBoardItem)167 virtual void OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aBoardItem ) { } OnBoardItemsAdded(BOARD & aBoard,std::vector<BOARD_ITEM * > & aBoardItem)168 virtual void OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItem ) { } OnBoardItemRemoved(BOARD & aBoard,BOARD_ITEM * aBoardItem)169 virtual void OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBoardItem ) { } OnBoardItemsRemoved(BOARD & aBoard,std::vector<BOARD_ITEM * > & aBoardItem)170 virtual void OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItem ) { } OnBoardNetSettingsChanged(BOARD & aBoard)171 virtual void OnBoardNetSettingsChanged( BOARD& aBoard ) { } OnBoardItemChanged(BOARD & aBoard,BOARD_ITEM * aBoardItem)172 virtual void OnBoardItemChanged( BOARD& aBoard, BOARD_ITEM* aBoardItem ) { } OnBoardItemsChanged(BOARD & aBoard,std::vector<BOARD_ITEM * > & aBoardItem)173 virtual void OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItem ) { } OnBoardHighlightNetChanged(BOARD & aBoard)174 virtual void OnBoardHighlightNetChanged( BOARD& aBoard ) { } 175 }; 176 177 178 /** 179 * Flags to specify how the board is being used. 180 */ 181 enum class BOARD_USE 182 { 183 NORMAL, // A normal board 184 FPHOLDER // A board that holds a single footprint 185 }; 186 187 188 /** 189 * Information pertinent to a Pcbnew printed circuit board. 190 */ 191 class BOARD : public BOARD_ITEM_CONTAINER 192 { 193 public: ClassOf(const EDA_ITEM * aItem)194 static inline bool ClassOf( const EDA_ITEM* aItem ) 195 { 196 return aItem && PCB_T == aItem->Type(); 197 } 198 199 /** 200 * Set what the board is going to be used for. 201 * 202 * @param aUse is the flag 203 */ SetBoardUse(BOARD_USE aUse)204 void SetBoardUse( BOARD_USE aUse ) { m_boardUse = aUse; } 205 206 /** 207 * Get what the board use is. 208 * 209 * @return what the board is being used for 210 */ GetBoardUse()211 BOARD_USE GetBoardUse() const { return m_boardUse; } 212 213 void IncrementTimeStamp(); 214 GetTimeStamp()215 int GetTimeStamp() const { return m_timeStamp; } 216 217 /** 218 * Find out if the board is being used to hold a single footprint for editing/viewing. 219 * 220 * @return if the board is just holding a footprint 221 */ IsFootprintHolder()222 bool IsFootprintHolder() const 223 { 224 return m_boardUse == BOARD_USE::FPHOLDER; 225 } 226 SetFileName(const wxString & aFileName)227 void SetFileName( const wxString& aFileName ) { m_fileName = aFileName; } 228 GetFileName()229 const wxString &GetFileName() const { return m_fileName; } 230 Tracks()231 TRACKS& Tracks() { return m_tracks; } Tracks()232 const TRACKS& Tracks() const { return m_tracks; } 233 Footprints()234 FOOTPRINTS& Footprints() { return m_footprints; } Footprints()235 const FOOTPRINTS& Footprints() const { return m_footprints; } 236 Drawings()237 DRAWINGS& Drawings() { return m_drawings; } Drawings()238 const DRAWINGS& Drawings() const { return m_drawings; } 239 Zones()240 ZONES& Zones() { return m_zones; } Zones()241 const ZONES& Zones() const { return m_zones; } 242 Markers()243 MARKERS& Markers() { return m_markers; } Markers()244 const MARKERS& Markers() const { return m_markers; } 245 246 /** 247 * The groups must maintain the following invariants. These are checked by 248 * GroupsSanityCheck(): 249 * - An item may appear in at most one group 250 * - Each group must contain at least one item 251 * - If a group specifies a name, it must be unique 252 * - The graph of groups containing subgroups must be cyclic. 253 */ Groups()254 GROUPS& Groups() { return m_groups; } Groups()255 const GROUPS& Groups() const { return m_groups; } 256 257 const std::vector<BOARD_CONNECTED_ITEM*> AllConnectedItems(); 258 GetProperties()259 const std::map<wxString, wxString>& GetProperties() const { return m_properties; } SetProperties(const std::map<wxString,wxString> & aProps)260 void SetProperties( const std::map<wxString, wxString>& aProps ) { m_properties = aProps; } 261 262 bool ResolveTextVar( wxString* token, int aDepth ) const; 263 264 /// Visibility settings stored in board prior to 6.0, only used for loading legacy files 265 LSET m_LegacyVisibleLayers; 266 GAL_SET m_LegacyVisibleItems; 267 268 /// True if the legacy board design settings were loaded from a file 269 bool m_LegacyDesignSettingsLoaded; 270 bool m_LegacyCopperEdgeClearanceLoaded; 271 272 /// True if netclasses were loaded from the file 273 bool m_LegacyNetclassesLoaded; 274 275 BOARD(); 276 ~BOARD(); 277 278 wxPoint GetPosition() const override; 279 void SetPosition( const wxPoint& aPos ) override; GetFocusPosition()280 const wxPoint GetFocusPosition() const override { return GetBoundingBox().GetCenter(); } 281 IsEmpty()282 bool IsEmpty() const 283 { 284 return m_drawings.empty() && m_footprints.empty() && m_tracks.empty() && m_zones.empty(); 285 } 286 287 void Move( const wxPoint& aMoveVector ) override; 288 SetFileFormatVersionAtLoad(int aVersion)289 void SetFileFormatVersionAtLoad( int aVersion ) { m_fileFormatVersionAtLoad = aVersion; } GetFileFormatVersionAtLoad()290 int GetFileFormatVersionAtLoad() const { return m_fileFormatVersionAtLoad; } 291 SetGenerator(const wxString & aGenerator)292 void SetGenerator( const wxString& aGenerator ) { m_generator = aGenerator; } GetGenerator()293 const wxString& GetGenerator() const { return m_generator; } 294 295 void Add( BOARD_ITEM* aItem, ADD_MODE aMode = ADD_MODE::INSERT ) override; 296 297 void Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode = REMOVE_MODE::NORMAL ) override; 298 299 /** 300 * Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for 301 * listeners. 302 */ 303 void FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems ); 304 305 /** 306 * Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event 307 * for listeners. 308 */ 309 void FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems ); 310 311 /** 312 * Get the first footprint on the board or nullptr. 313 * 314 * This is used primarily by the footprint editor which knows there is only one. 315 * 316 * @return first footprint or null pointer 317 */ GetFirstFootprint()318 FOOTPRINT* GetFirstFootprint() const 319 { 320 return m_footprints.empty() ? nullptr : m_footprints.front(); 321 } 322 323 /** 324 * Remove all footprints from the deque and free the memory associated with them. 325 */ 326 void DeleteAllFootprints(); 327 328 /** 329 * @return null if aID is null. Returns an object of Type() == NOT_USED if the aID is not found. 330 */ 331 BOARD_ITEM* GetItem( const KIID& aID ) const; 332 333 void FillItemMap( std::map<KIID, EDA_ITEM*>& aMap ); 334 335 /** 336 * Convert cross-references back and forth between ${refDes:field} and ${kiid:field} 337 */ 338 wxString ConvertCrossReferencesToKIIDs( const wxString& aSource ) const; 339 wxString ConvertKIIDsToCrossReferences( const wxString& aSource ) const; 340 341 /** 342 * Return a list of missing connections between components/tracks. 343 * @return an object that contains information about missing connections. 344 */ GetConnectivity()345 std::shared_ptr<CONNECTIVITY_DATA> GetConnectivity() const { return m_connectivity; } 346 347 /** 348 * Build or rebuild the board connectivity database for the board, 349 * especially the list of connected items, list of nets and rastnest data 350 * Needed after loading a board to have the connectivity database updated. 351 */ 352 void BuildConnectivity( PROGRESS_REPORTER* aReporter = nullptr ); 353 354 /** 355 * Delete all MARKERS from the board. 356 */ 357 void DeleteMARKERs(); 358 359 void DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions ); 360 GetProject()361 PROJECT* GetProject() const { return m_project; } 362 363 /** 364 * Link a board to a given project. 365 * 366 * Should be called immediately after loading board in order for everything to work. 367 * 368 * @param aProject is a loaded project to link to. 369 */ 370 void SetProject( PROJECT* aProject ); 371 372 void ClearProject(); 373 374 /** 375 * Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS. 376 */ 377 std::vector<PCB_MARKER*> ResolveDRCExclusions(); 378 379 /** 380 * Reset all high light data to the init state 381 */ 382 void ResetNetHighLight(); 383 384 /** 385 * @return the set of net codes that should be highlighted 386 */ GetHighLightNetCodes()387 const std::set<int>& GetHighLightNetCodes() const 388 { 389 return m_highLight.m_netCodes; 390 } 391 392 /** 393 * Select the netcode to be highlighted. 394 * 395 * @param aNetCode is the net to highlight. 396 * @param aMulti is true if you want to add a highlighted net without clearing the old one. 397 */ 398 void SetHighLightNet( int aNetCode, bool aMulti = false ); 399 400 /** 401 * @return true if a net is currently highlighted 402 */ IsHighLightNetON()403 bool IsHighLightNetON() const { return m_highLight.m_highLightOn; } 404 405 /** 406 * Enable or disable net highlighting. 407 * 408 * If a netcode >= 0 has been set with SetHighLightNet and aValue is true, the net will be 409 * highlighted. If aValue is false, net highlighting will be disabled regardless of 410 * the highlight netcode being set. 411 */ 412 void HighLightON( bool aValue = true ); 413 414 /** 415 * Disable net highlight. 416 */ HighLightOFF()417 void HighLightOFF() 418 { 419 HighLightON( false ); 420 } 421 422 /** 423 * @return The number of copper layers in the BOARD. 424 */ 425 int GetCopperLayerCount() const; 426 void SetCopperLayerCount( int aCount ); 427 428 /** 429 * A proxy function that calls the corresponding function in m_BoardSettings. 430 * 431 * @return the enabled layers in bit-mapped form. 432 */ 433 LSET GetEnabledLayers() const; 434 435 /** 436 * A proxy function that calls the correspondent function in m_BoardSettings. 437 * 438 * @param aLayerMask the new bit-mask of enabled layers. 439 */ 440 void SetEnabledLayers( LSET aLayerMask ); 441 442 /** 443 * A proxy function that calls the correspondent function in m_BoardSettings 444 * tests whether a given layer is enabled 445 * @param aLayer = The layer to be tested 446 * @return true if the layer is visible. 447 */ 448 bool IsLayerEnabled( PCB_LAYER_ID aLayer ) const; 449 450 /** 451 * A proxy function that calls the correspondent function in m_BoardSettings 452 * tests whether a given layer is visible 453 * 454 * @param aLayer is the layer to be tested. 455 * @return true if the layer is visible otherwise false. 456 */ 457 bool IsLayerVisible( PCB_LAYER_ID aLayer ) const; 458 459 /** 460 * A proxy function that calls the correspondent function in m_BoardSettings. 461 * 462 * @return the visible layers in bit-mapped form. 463 */ 464 LSET GetVisibleLayers() const; 465 466 /** 467 * A proxy function that calls the correspondent function in m_BoardSettings 468 * changes the bit-mask of visible layers. 469 * 470 * @param aLayerMask is the new bit-mask of visible layers. 471 */ 472 void SetVisibleLayers( LSET aLayerMask ); 473 474 // these 2 functions are not tidy at this time, since there are PCB_LAYER_IDs that 475 // are not stored in the bitmap. 476 477 /** 478 * Return a set of all the element categories that are visible. 479 * 480 * @return the set of visible GAL layers. 481 * @see enum GAL_LAYER_ID 482 */ 483 GAL_SET GetVisibleElements() const; 484 485 /** 486 * A proxy function that calls the correspondent function in m_BoardSettings. 487 * 488 * @param aMask is the new bit-mask of visible element bitmap or-ed from enum GAL_LAYER_ID 489 * @see enum GAL_LAYER_ID 490 */ 491 void SetVisibleElements( const GAL_SET& aMask ); 492 493 /** 494 * Change the bit-mask of visible element categories and layers. 495 * 496 * @see enum GAL_LAYER_ID 497 */ 498 void SetVisibleAlls(); 499 500 /** 501 * Test whether a given element category is visible. 502 * 503 * @param aLayer is from the enum by the same name. 504 * @return true if the element is visible otherwise false. 505 * @see enum GAL_LAYER_ID 506 */ 507 bool IsElementVisible( GAL_LAYER_ID aLayer ) const; 508 509 /** 510 * Change the visibility of an element category. 511 * 512 * @param aLayer is from the enum by the same name. 513 * @param aNewState is the new visibility state of the element category. 514 * @see enum GAL_LAYER_ID 515 */ 516 void SetElementVisibility( GAL_LAYER_ID aLayer, bool aNewState ); 517 518 /** 519 * Expect either of the two layers on which a footprint can reside, and returns 520 * whether that layer is visible. 521 * 522 * @param aLayer is one of the two allowed layers for footprints: F_Cu or B_Cu 523 * @return true if the layer is visible, otherwise false. 524 */ 525 bool IsFootprintLayerVisible( PCB_LAYER_ID aLayer ) const; 526 527 /** 528 * @return the BOARD_DESIGN_SETTINGS for this BOARD 529 */ 530 BOARD_DESIGN_SETTINGS& GetDesignSettings() const; 531 532 const ZONE_SETTINGS& GetZoneSettings() const override; 533 534 void SetZoneSettings( const ZONE_SETTINGS& aSettings ) override; 535 GetPageSettings()536 const PAGE_INFO& GetPageSettings() const { return m_paper; } SetPageSettings(const PAGE_INFO & aPageSettings)537 void SetPageSettings( const PAGE_INFO& aPageSettings ) { m_paper = aPageSettings; } 538 GetPlotOptions()539 const PCB_PLOT_PARAMS& GetPlotOptions() const { return m_plotOptions; } SetPlotOptions(const PCB_PLOT_PARAMS & aOptions)540 void SetPlotOptions( const PCB_PLOT_PARAMS& aOptions ) { m_plotOptions = aOptions; } 541 GetTitleBlock()542 TITLE_BLOCK& GetTitleBlock() { return m_titles; } GetTitleBlock()543 const TITLE_BLOCK& GetTitleBlock() const { return m_titles; } SetTitleBlock(const TITLE_BLOCK & aTitleBlock)544 void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) { m_titles = aTitleBlock; } 545 546 wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; 547 548 /** 549 * Extract the board outlines and build a closed polygon from lines, arcs and circle items 550 * on edge cut layer. 551 * 552 * Any closed outline inside the main outline is a hole. All contours should be closed, 553 * i.e. have valid vertices to build a closed polygon. 554 * 555 * @param aOutlines is the #SHAPE_POLY_SET to fill in with outlines/holes. 556 * @param aErrorHandler is an optional DRC_ITEM error handler. 557 * @return true if success, false if a contour is not valid 558 */ 559 bool GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, 560 OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr ); 561 562 /** 563 * Build a set of polygons which are the outlines of copper items (pads, tracks, vias, texts, 564 * zones). 565 * 566 * Holes in vias or pads are ignored. The polygons are not merged. This is useful to 567 * export the shape of copper layers to dxf polygons or 3D viewer/ 568 * 569 * @param aLayer is a copper layer, like B_Cu, etc. 570 * @param aOutlines is the SHAPE_POLY_SET to fill in with items outline. 571 */ 572 void ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) const; 573 574 /** 575 * Return the ID of a layer. 576 */ 577 const PCB_LAYER_ID GetLayerID( const wxString& aLayerName ) const; 578 579 /** 580 * Return the name of a \a aLayer. 581 * 582 * @param aLayer is the #PCB_LAYER_ID of the layer. 583 * @return a string containing the name of the layer. 584 */ 585 const wxString GetLayerName( PCB_LAYER_ID aLayer ) const; 586 587 /** 588 * Changes the name of the layer given by aLayer. 589 * @param aLayer A layer, like B_Cu, etc. 590 * @param aLayerName The new layer name 591 * @return true if aLayerName was legal and unique among other layer names at other layer 592 * indices and aLayer was within range, else false. 593 */ 594 bool SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName ); 595 596 /** 597 * Return an "English Standard" name of a PCB layer when given \a aLayerNumber. 598 * 599 * This function is static so it can be called without a BOARD instance. Use 600 * GetLayerName() if want the layer names of a specific BOARD, which could 601 * be different than the default if the user has renamed any copper layers. 602 * 603 * @param aLayerId is the layer identifier (index) to fetch. 604 * @return a string containing the layer name or "BAD INDEX" if aLayerId is not legal. 605 */ GetStandardLayerName(PCB_LAYER_ID aLayerId)606 static wxString GetStandardLayerName( PCB_LAYER_ID aLayerId ) 607 { 608 // a BOARD's standard layer name is the PCB_LAYER_ID fixed name 609 return LayerName( aLayerId ); 610 } 611 612 /** 613 * Return the type of the copper layer given by aLayer. 614 * 615 * @param aIndex A layer index in m_Layer 616 * @param aLayer A reference to a LAYER description. 617 * @return false if the index was out of range. 618 */ 619 bool SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer ); 620 621 /** 622 * Return the type of the copper layer given by aLayer. 623 * 624 * @param aLayer A layer index, like B_Cu, etc. 625 * @return the layer type, or LAYER_T(-1) if the index was out of range. 626 */ 627 LAYER_T GetLayerType( PCB_LAYER_ID aLayer ) const; 628 629 /** 630 * Change the type of the layer given by aLayer. 631 * 632 * @param aLayer A layer index, like B_Cu, etc. 633 * @param aLayerType The new layer type. 634 * @return true if aLayerType was legal and aLayer was within range, else false. 635 */ 636 bool SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType ); 637 638 /** 639 * @param aNet Only count nodes belonging to this net. 640 * @return the number of pads members of nets (i.e. with netcode > 0). 641 */ 642 unsigned GetNodesCount( int aNet = -1 ) const; 643 644 /** 645 * @return the number of unconnected nets in the current ratsnest. 646 */ 647 unsigned GetUnconnectedNetCount() const; 648 649 /** 650 * Return a reference to a list of all the pads. 651 * 652 * The returned list is not sorted and contains pointers to PADS, but those pointers do 653 * not convey ownership of the respective PADs. 654 * 655 * @return a full list of pads. 656 */ 657 const std::vector<PAD*> GetPads() const; 658 BuildListOfNets()659 void BuildListOfNets() 660 { 661 m_NetInfo.buildListOfNets(); 662 } 663 664 /** 665 * Search for a net with the given netcode. 666 * 667 * @param aNetcode A netcode to search for. 668 * @return the net if found or NULL if not found. 669 */ 670 NETINFO_ITEM* FindNet( int aNetcode ) const; 671 672 /** 673 * Search for a net with the given name. 674 * 675 * @param aNetname A Netname to search for. 676 * @return the net if found or NULL if not found. 677 */ 678 NETINFO_ITEM* FindNet( const wxString& aNetname ) const; 679 GetNetInfo()680 const NETINFO_LIST& GetNetInfo() const 681 { 682 return m_NetInfo; 683 } 684 GetNetInfo()685 NETINFO_LIST& GetNetInfo() 686 { 687 return m_NetInfo; 688 } 689 690 #ifndef SWIG 691 /** 692 * @return iterator to the first element of the NETINFO_ITEMs list. 693 */ BeginNets()694 NETINFO_LIST::iterator BeginNets() const 695 { 696 return m_NetInfo.begin(); 697 } 698 699 /** 700 * @return iterator to the last element of the NETINFO_ITEMs list. 701 */ EndNets()702 NETINFO_LIST::iterator EndNets() const 703 { 704 return m_NetInfo.end(); 705 } 706 #endif 707 708 /** 709 * @return the number of nets (NETINFO_ITEM). 710 */ GetNetCount()711 unsigned GetNetCount() const 712 { 713 return m_NetInfo.GetNetCount(); 714 } 715 716 /** 717 * Calculate the bounding box containing all board items (or board edge segments). 718 * 719 * @param aBoardEdgesOnly is true if we are interested in board edge segments only. 720 * @return the board's bounding box. 721 */ 722 EDA_RECT ComputeBoundingBox( bool aBoardEdgesOnly = false ) const; 723 GetBoundingBox()724 const EDA_RECT GetBoundingBox() const override 725 { 726 return ComputeBoundingBox( false ); 727 } 728 729 /** 730 * Return the board bounding box calculated using exclusively the board edges (graphics 731 * on Edge.Cuts layer). 732 * 733 * If there are items outside of the area limited by Edge.Cuts graphics, the items will 734 * not be taken into account. 735 * 736 * @return bounding box calculated using exclusively the board edges. 737 */ GetBoardEdgesBoundingBox()738 const EDA_RECT GetBoardEdgesBoundingBox() const 739 { 740 return ComputeBoundingBox( true ); 741 } 742 743 void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; 744 745 /** 746 * May be re-implemented for each derived class in order to handle 747 * all the types given by its member data. Implementations should call 748 * inspector->Inspect() on types in scanTypes[], and may use IterateForward() 749 * to do so on lists of such data. 750 * @param inspector An INSPECTOR instance to use in the inspection. 751 * @param testData Arbitrary data used by the inspector. 752 * @param scanTypes Which KICAD_T types are of interest and the order 753 * is significant too, terminated by EOT. 754 * @return SEARCH_QUIT if the Iterator is to stop the scan, else SCAN_CONTINUE, and 755 * determined by the inspector. 756 */ 757 SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override; 758 759 /** 760 * Search for a FOOTPRINT within this board with the given reference designator. 761 * 762 * Finds only the first one, if there is more than one such FOOTPRINT. 763 * 764 * @param aReference The reference designator of the FOOTPRINT to find. 765 * @return If found the FOOTPRINT having the given reference designator, else nullptr. 766 */ 767 FOOTPRINT* FindFootprintByReference( const wxString& aReference ) const; 768 769 /** 770 * Search for a FOOTPRINT within this board with the given path. 771 * 772 * @param aPath The path ([sheetUUID, .., symbolUUID]) to search for. 773 * @return If found, the FOOTPRINT having the given uuid, else NULL. 774 */ 775 FOOTPRINT* FindFootprintByPath( const KIID_PATH& aPath ) const; 776 777 /** 778 * Return a list of name candidates for netclass assignment. 779 * 780 * Tokens may appear more than once if they were harvested from hierarchical nets 781 * (ie: /CLK, /sheet1/CLK). 782 */ 783 std::vector<wxString> GetNetClassAssignmentCandidates() const; 784 785 /** 786 * Copy NETCLASS info to each NET, based on NET membership in a NETCLASS. 787 * 788 * Must be called after a Design Rules edit, or after reading a netlist (or editing 789 * the list of nets) Also this function removes the non existing nets in netclasses 790 * and add net nets in default netclass (this happens after reading a netlist) 791 */ 792 void SynchronizeNetsAndNetClasses(); 793 794 /** 795 * Copy the current project's text variables into the boards property cache. 796 */ 797 void SynchronizeProperties(); 798 GetClass()799 wxString GetClass() const override 800 { 801 return wxT( "BOARD" ); 802 } 803 804 #if defined(DEBUG) Show(int nestLevel,std::ostream & os)805 void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } 806 #endif 807 808 809 /*************************/ 810 /* Copper Areas handling */ 811 /*************************/ 812 813 /** 814 * Set the .m_NetCode member of all copper areas, according to the area Net Name 815 * The SetNetCodesFromNetNames is an equivalent to net name, for fast comparisons. 816 * However the Netcode is an arbitrary equivalence, it must be set after each netlist read 817 * or net change 818 * Must be called after pad netcodes are calculated 819 * @return : error count 820 * For non copper areas, netcode is set to 0 821 */ 822 int SetAreasNetCodesFromNetNames(); 823 824 /** 825 * Return the Zone at a given index. 826 * 827 * @param index The array type index into a collection of ZONE *. 828 * @return a pointer to the Area or NULL if index out of range. 829 */ GetArea(int index)830 ZONE* GetArea( int index ) const 831 { 832 if( (unsigned) index < m_zones.size() ) 833 return m_zones[index]; 834 835 return nullptr; 836 } 837 838 /** 839 * @return a std::list of pointers to all board zones (possibly including zones in footprints) 840 */ 841 std::list<ZONE*> GetZoneList( bool aIncludeZonesInFootprints = false ) const; 842 843 /** 844 * @return The number of copper pour areas or ZONEs. 845 */ GetAreaCount()846 int GetAreaCount() const 847 { 848 return static_cast<int>( m_zones.size() ); 849 } 850 851 /* Functions used in test, merge and cut outlines */ 852 853 /** 854 * Add an empty copper area to board areas list. 855 * 856 * @param aNewZonesList is a PICKED_ITEMS_LIST * where to store new areas pickers (useful 857 * in undo commands) can be NULL. 858 * @param aNetcode is the netcode of the copper area (0 = no net). 859 * @param aLayer is the layer of area. 860 * @param aStartPointPosition is position of the first point of the polygon outline of this 861 * area. 862 * @param aHatch is the hatch option. 863 * @return a reference to the new area. 864 */ 865 ZONE* AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, 866 wxPoint aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch ); 867 868 /** 869 * Process an area that has been modified, by normalizing its polygon against itself. 870 * i.e. convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s) 871 * 872 * This may change the number and order of copper areas in the net. 873 * 874 * @param aNewZonesList is a PICKED_ITEMS_LIST where to store new created areas pickers. 875 * @param aCurrArea is the zone to process. 876 * @return true if changes are made. 877 */ 878 bool NormalizeAreaPolygon( PICKED_ITEMS_LIST* aNewZonesList, ZONE* aCurrArea ); 879 880 /** 881 * Process an area that has been modified, by normalizing its polygon 882 * and merging the intersecting polygons for any other areas on the same net. 883 * 884 * This may change the number and order of copper areas in the net. 885 * 886 * @param aModifiedZonesList is a #PICKED_ITEMS_LIST where to store deleted or added areas 887 * (useful in undo commands can be NULL). 888 * @param modified_area is the area to test. 889 * @return true if some areas modified. 890 */ 891 bool OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, ZONE* modified_area ); 892 893 /** 894 * Test for intersection of 2 copper areas. 895 * 896 * @param aZone1 is the area reference. 897 * @param aZone2 is the area to compare for intersection calculations. 898 * @return false if no intersection, true if intersection. 899 */ 900 bool TestZoneIntersection( ZONE* aZone1, ZONE* aZone2 ); 901 902 /** 903 * Find a pad \a aPosition on \a aLayer. 904 * 905 * @param aPosition A wxPoint object containing the position to hit test. 906 * @param aLayerMask A layer or layers to mask the hit test. 907 * @return A pointer to a PAD object if found or NULL if not found. 908 */ 909 PAD* GetPad( const wxPoint& aPosition, LSET aLayerMask ) const; GetPad(const wxPoint & aPosition)910 PAD* GetPad( const wxPoint& aPosition ) const 911 { 912 return GetPad( aPosition, LSET().set() ); 913 } 914 915 /** 916 * Find a pad connected to \a aEndPoint of \a aTrace. 917 * 918 * @param aTrace A pointer to a PCB_TRACK object to hit test against. 919 * @param aEndPoint The end point of \a aTrace the hit test against. 920 * @return A pointer to a PAD object if found or NULL if not found. 921 */ 922 PAD* GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const; 923 924 /** 925 * Return pad found at \a aPosition on \a aLayerMask using the fast search method. 926 * <p> 927 * The fast search method only works if the pad list has already been built. 928 * </p> 929 * @param aPosition A wxPoint object containing the position to hit test. 930 * @param aLayerMask A layer or layers to mask the hit test. 931 * @return A pointer to a PAD object if found or NULL if not found. 932 */ 933 PAD* GetPadFast( const wxPoint& aPosition, LSET aLayerMask ) const; 934 935 /** 936 * Locate the pad connected at \a aPosition on \a aLayer starting at list position 937 * \a aPad 938 * <p> 939 * This function uses a fast search in this sorted pad list and it is faster than 940 * GetPadFast(). This list is a sorted pad list must be built before calling this 941 * function. 942 * </p> 943 * @note The normal pad list is sorted by increasing netcodes. 944 * @param aPadList is the list of pads candidates (a std::vector<PAD*>). 945 * @param aPosition A wxPoint object containing the position to test. 946 * @param aLayerMask A layer or layers to mask the hit test. 947 * @return a PAD object pointer to the connected pad. 948 */ 949 PAD* GetPad( std::vector<PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerMask ) const; 950 951 /** 952 * Delete a given pad from the BOARD by removing it from its footprint and from the 953 * m_NetInfo. Makes no UI calls. 954 * 955 * @param aPad is the pad to delete. 956 */ 957 void PadDelete( PAD* aPad ); 958 959 /** 960 * First empties then fills the vector with all pads and sorts them by increasing x 961 * coordinate, and for increasing y coordinate for same values of x coordinates. The vector 962 * only holds pointers to the pads and those pointers are only references to pads which are 963 * owned by the BOARD through other links. 964 * 965 * @param aVector Where to put the pad pointers. 966 * @param aNetCode = the netcode filter: 967 * = -1 to build the full pad list. 968 * = a given netcode to build the pad list relative to the given net 969 */ 970 void GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode = -1 ) const; 971 972 /** 973 * Return data on the length and number of track segments connected to a given track. 974 * This uses the connectivity data for the board to calculate connections 975 * 976 * @param aTrack Starting track (can also be a via) to check against for connection. 977 * @return a tuple containing <number, length, package length> 978 */ 979 std::tuple<int, double, double> GetTrackLength( const PCB_TRACK& aTrack ) const; 980 981 /** 982 * Collect all the TRACKs and VIAs that are members of a net given by aNetCode. 983 * Used from python. 984 * 985 * @param aNetCode gives the id of the net. 986 * @return list of track which are in the net identified by @a aNetCode. 987 */ 988 TRACKS TracksInNet( int aNetCode ); 989 990 /** 991 * Get a footprint by its bounding rectangle at \a aPosition on \a aLayer. 992 * 993 * If more than one footprint is at \a aPosition, then the closest footprint on the 994 * active layer is returned. The distance is calculated via manhattan distance from 995 * the center of the bounding rectangle to \a aPosition. 996 * 997 * @param aPosition A wxPoint object containing the position to test. 998 * @param aActiveLayer Layer to test. 999 * @param aVisibleOnly Search only the visible layers if true. 1000 * @param aIgnoreLocked Ignore locked footprints when true. 1001 */ 1002 FOOTPRINT* GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer, 1003 bool aVisibleOnly, bool aIgnoreLocked = false ) const; 1004 1005 /** 1006 * Reset all items' netcodes to 0 (no net). 1007 */ 1008 void ClearAllNetCodes(); 1009 1010 /** 1011 * Map all nets in the given board to nets with the same name (if any) in the destination 1012 * board. This allows us to share layouts which came from the same hierarchical sheet in 1013 * the schematic. 1014 */ 1015 void MapNets( const BOARD* aDestBoard ); 1016 1017 void SanitizeNetcodes(); 1018 1019 /** 1020 * Add a listener to the board to receive calls whenever something on the 1021 * board has been modified. The board does not take ownership of the 1022 * listener object. Make sure to call RemoveListener before deleting the 1023 * listener object. The order of listener invocations is not guaranteed. 1024 * If the specified listener object has been added before, it will not be 1025 * added again. 1026 */ 1027 void AddListener( BOARD_LISTENER* aListener ); 1028 1029 /** 1030 * Remove the specified listener. If it has not been added before, it 1031 * will do nothing. 1032 */ 1033 void RemoveListener( BOARD_LISTENER* aListener ); 1034 1035 /** 1036 * Notify the board and its listeners that an item on the board has 1037 * been modified in some way. 1038 */ 1039 void OnItemChanged( BOARD_ITEM* aItem ); 1040 1041 /** 1042 * Notify the board and its listeners that an item on the board has 1043 * been modified in some way. 1044 */ 1045 void OnItemsChanged( std::vector<BOARD_ITEM*>& aItems ); 1046 1047 /** 1048 * Consistency check of internal m_groups structure. 1049 * 1050 * @param repair if true, modify groups structure until it passes the sanity check. 1051 * @return empty string on success. Or error description if there's a problem. 1052 */ 1053 wxString GroupsSanityCheck( bool repair = false ); 1054 1055 /** 1056 * @param repair if true, make one modification to groups structure that brings it 1057 * closer to passing the sanity check. 1058 * @return empty string on success. Or error description if there's a problem. 1059 */ 1060 wxString GroupsSanityCheckInternal( bool repair ); 1061 1062 struct GroupLegalOpsField 1063 { 1064 bool create : 1; 1065 bool ungroup : 1; 1066 bool removeItems : 1; 1067 bool enter : 1; 1068 }; 1069 1070 /** 1071 * Check which selection tool group operations are legal given the selection. 1072 * 1073 * @return bit field of legal ops. 1074 */ 1075 GroupLegalOpsField GroupLegalOps( const PCB_SELECTION& selection ) const; 1076 1077 // --------- Item order comparators --------- 1078 1079 struct cmp_items 1080 { 1081 bool operator() ( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const; 1082 }; 1083 1084 struct cmp_drawings 1085 { 1086 bool operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const; 1087 }; 1088 1089 // ------------ Run-time caches ------------- 1090 std::mutex m_CachesMutex; 1091 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideCourtyardCache; 1092 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideFCourtyardCache; 1093 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideBCourtyardCache; 1094 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideAreaCache; 1095 std::map< wxString, LSET > m_LayerExpressionCache; 1096 1097 std::map< ZONE*, std::unique_ptr<DRC_RTREE> > m_CopperZoneRTrees; 1098 1099 private: 1100 // The default copy constructor & operator= are inadequate, 1101 // either write one or do not use it at all 1102 BOARD( const BOARD& aOther ) = delete; 1103 1104 BOARD& operator=( const BOARD& aOther ) = delete; 1105 1106 template <typename Func, typename... Args> InvokeListeners(Func && aFunc,Args &&...args)1107 void InvokeListeners( Func&& aFunc, Args&&... args ) 1108 { 1109 for( auto&& l : m_listeners ) 1110 ( l->*aFunc )( std::forward<Args>( args )... ); 1111 } 1112 1113 friend class PCB_EDIT_FRAME; 1114 1115 /// What is this board being used for 1116 BOARD_USE m_boardUse; 1117 int m_timeStamp; // actually a modification counter 1118 1119 wxString m_fileName; 1120 MARKERS m_markers; 1121 DRAWINGS m_drawings; 1122 FOOTPRINTS m_footprints; 1123 TRACKS m_tracks; 1124 GROUPS m_groups; 1125 ZONES m_zones; 1126 1127 LAYER m_layers[PCB_LAYER_ID_COUNT]; 1128 1129 HIGH_LIGHT_INFO m_highLight; // current high light data 1130 HIGH_LIGHT_INFO m_highLightPrevious; // a previously stored high light data 1131 1132 int m_fileFormatVersionAtLoad; // the version loaded from the file 1133 wxString m_generator; // the generator tag from the file 1134 1135 std::map<wxString, wxString> m_properties; 1136 std::shared_ptr<CONNECTIVITY_DATA> m_connectivity; 1137 1138 PAGE_INFO m_paper; 1139 TITLE_BLOCK m_titles; // text in lower right of screen and plots 1140 PCB_PLOT_PARAMS m_plotOptions; 1141 PROJECT* m_project; // project this board is a part of 1142 1143 /** 1144 * All of the board design settings are stored as a JSON object inside the project file. The 1145 * object itself is located here because the alternative is to require a valid project be 1146 * passed in when constructing a BOARD, since things in the BOARD constructor rely on access 1147 * to the BOARD_DESIGN_SETTINGS object. 1148 * 1149 * A reference to this object is set up in the PROJECT_FILE for the PROJECT this board is 1150 * part of, so that the JSON load/store operations work. This link is established when 1151 * boards are loaded from disk. 1152 */ 1153 std::unique_ptr<BOARD_DESIGN_SETTINGS> m_designSettings; 1154 1155 NETINFO_LIST m_NetInfo; // net info list (name, design constraints... 1156 1157 std::vector<BOARD_LISTENER*> m_listeners; 1158 }; 1159 1160 #endif // CLASS_BOARD_H_ 1161