You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1792 lines
46 KiB

++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
11 years ago
18 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
14 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
14 years ago
14 years ago
18 years ago
18 years ago
17 years ago
17 years ago
17 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
Changed the way of looking up NETINFO_ITEM using net names (using boost::unordered_map). Added a hash function (wxString) for that. Introduced NETINFO_ITEM::GetNetItem( wxString ). BOARD::FindNet() uses the map. Net codes are updated upon net list update. (BOARD::ReplaceNetlist()) Added in some places (mostly class_board.cpp) pad->SetNet() calls to synchronize net codes. On creation of NETINFO_LIST, the first NETINFO_ITEM is added (the unconnected items net). Removed COMPONENT_NET::m_netNumber, as it was not used anywhere. Added an assert to D_PAD::GetNetname(), checking if net code and net name is consistent for unconnected pads. Added an assert for NETINFO_LIST::AppendNet() to assure that appended nets are unique. It seems that at this point: - Updating net lists works fine. The only difference between the file ouput is that after changes it contains empty nets as well. - Nets are not saved in the lexical order. Still, net names and net codes are properly assigned to all items in the .kicad_pcb file. It is going to be addressed in the next commit. I believe it should not create any problems, as pads are sorted by their net names anyway (NETINFO_LIST::buildPadsFullList()) Performed tests: - Created a blank PCB, saved as pic_programmer.kicad_pcb (from demos folder). Updated net lists. .kicad_pcb file (comparing to the results from master branch) differ with net order (as mentioned before), net codes and timestamps. - Removed some of components from the above .kicad_pcb file and updated net lists. Modules reappeared. .kicad_pcb file differs in the same way as described above. - Trying to change a pad net name (via properties dialog) results in assert being fired. It is done on purpose (as there is a call to GetNetname() and net name and net code do not match). This will not happen after the next commit. - Prepared a simple project (starting with schematics). Imported net list, changed schematic, reimported net list - changes are applied. - Eagle & KiCad legacy boards seem to load without any problem.
12 years ago
18 years ago
18 years ago
18 years ago
11 years ago
11 years ago
11 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
11 years ago
11 years ago
11 years ago
8 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. /**
  2. * @file class_board.cpp
  3. * @brief BOARD class functions.
  4. */
  5. /*
  6. * This program source code file is part of KiCad, a free EDA CAD application.
  7. *
  8. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  9. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  10. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
  11. *
  12. * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, you may find one here:
  26. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  27. * or you may search the http://www.gnu.org website for the version 2 license,
  28. * or you may write to the Free Software Foundation, Inc.,
  29. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  30. */
  31. #include <limits.h>
  32. #include <algorithm>
  33. #include <iterator>
  34. #include <fctsys.h>
  35. #include <common.h>
  36. #include <kicad_string.h>
  37. #include <pcb_base_frame.h>
  38. #include <msgpanel.h>
  39. #include <pcb_netlist.h>
  40. #include <reporter.h>
  41. #include <base_units.h>
  42. #include <ratsnest_data.h>
  43. #include <ratsnest_viewitem.h>
  44. #include <ws_proxy_view_item.h>
  45. #include <pcbnew.h>
  46. #include <collectors.h>
  47. #include <class_board.h>
  48. #include <class_module.h>
  49. #include <class_track.h>
  50. #include <class_zone.h>
  51. #include <class_marker_pcb.h>
  52. #include <class_drawsegment.h>
  53. #include <class_pcb_text.h>
  54. #include <class_pcb_target.h>
  55. #include <class_dimension.h>
  56. #include <connectivity/connectivity_data.h>
  57. /**
  58. * A singleton item of this class is returned for a weak reference that no longer exists.
  59. * Its sole purpose is to flag the item as having been deleted.
  60. */
  61. class DELETED_BOARD_ITEM : public BOARD_ITEM
  62. {
  63. public:
  64. DELETED_BOARD_ITEM() :
  65. BOARD_ITEM( nullptr, NOT_USED )
  66. {}
  67. wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override
  68. {
  69. return _( "(Deleted Item)" );
  70. }
  71. wxString GetClass() const override
  72. {
  73. return wxT( "DELETED_BOARD_ITEM" );
  74. }
  75. // pure virtuals:
  76. const wxPoint GetPosition() const override { return wxPoint(); }
  77. void SetPosition( const wxPoint& ) override {}
  78. void Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& aOffset ) override {}
  79. #if defined(DEBUG)
  80. void Show( int , std::ostream& ) const override {}
  81. #endif
  82. };
  83. DELETED_BOARD_ITEM g_DeletedItem;
  84. /* This is an odd place for this, but CvPcb won't link if it is
  85. * in class_board_item.cpp like I first tried it.
  86. */
  87. wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
  88. // this is a dummy colors settings (defined colors are the vdefulat values)
  89. // used to initialize the board.
  90. // these settings will be overriden later, depending on the draw frame that displays the board.
  91. // However, when a board is created by a python script, outside a frame, the colors must be set
  92. // so dummyColorsSettings provide this default initialization
  93. static COLORS_DESIGN_SETTINGS dummyColorsSettings( FRAME_PCB );
  94. BOARD::BOARD() :
  95. BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
  96. m_paper( PAGE_INFO::A4 ), m_NetInfo( this )
  97. {
  98. // we have not loaded a board yet, assume latest until then.
  99. m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
  100. m_colorsSettings = &dummyColorsSettings;
  101. m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
  102. // zone contour currently in progress
  103. BuildListOfNets(); // prepare pad and netlist containers.
  104. for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
  105. {
  106. m_Layer[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
  107. if( IsCopperLayer( layer ) )
  108. m_Layer[layer].m_type = LT_SIGNAL;
  109. else
  110. m_Layer[layer].m_type = LT_UNDEFINED;
  111. }
  112. // Initialize default netclass.
  113. NETCLASSPTR defaultClass = m_designSettings.GetDefault();
  114. defaultClass->SetDescription( _( "This is the default net class." ) );
  115. m_designSettings.SetCurrentNetClass( defaultClass->GetName() );
  116. // Set sensible initial values for custom track width & via size
  117. m_designSettings.UseCustomTrackViaSize( false );
  118. m_designSettings.SetCustomTrackWidth( m_designSettings.GetCurrentTrackWidth() );
  119. m_designSettings.SetCustomViaSize( m_designSettings.GetCurrentViaSize() );
  120. m_designSettings.SetCustomViaDrill( m_designSettings.GetCurrentViaDrill() );
  121. // Initialize ratsnest
  122. m_connectivity.reset( new CONNECTIVITY_DATA() );
  123. }
  124. BOARD::~BOARD()
  125. {
  126. while( m_ZoneDescriptorList.size() )
  127. {
  128. ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
  129. Delete( area_to_remove );
  130. }
  131. DeleteMARKERs();
  132. DeleteZONEOutlines();
  133. delete m_CurrentZoneContour;
  134. m_CurrentZoneContour = NULL;
  135. }
  136. void BOARD::BuildConnectivity()
  137. {
  138. GetConnectivity()->Build( this );
  139. }
  140. const wxPoint BOARD::GetPosition() const
  141. {
  142. return ZeroOffset;
  143. }
  144. void BOARD::SetPosition( const wxPoint& aPos )
  145. {
  146. wxLogWarning( wxT( "This should not be called on the BOARD object") );
  147. }
  148. void BOARD::Move( const wxPoint& aMoveVector ) // overload
  149. {
  150. // @todo : anything like this elsewhere? maybe put into GENERAL_COLLECTOR class.
  151. static const KICAD_T top_level_board_stuff[] = {
  152. PCB_MARKER_T,
  153. PCB_TEXT_T,
  154. PCB_LINE_T,
  155. PCB_DIMENSION_T,
  156. PCB_TARGET_T,
  157. PCB_VIA_T,
  158. PCB_TRACE_T,
  159. // PCB_PAD_T, Can't be at board level
  160. // PCB_MODULE_TEXT_T, Can't be at board level
  161. PCB_MODULE_T,
  162. PCB_ZONE_AREA_T,
  163. EOT
  164. };
  165. INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
  166. {
  167. BOARD_ITEM* brd_item = (BOARD_ITEM*) item;
  168. // aMoveVector was snapshotted, don't need "data".
  169. brd_item->Move( aMoveVector );
  170. return SEARCH_CONTINUE;
  171. };
  172. Visit( inspector, NULL, top_level_board_stuff );
  173. }
  174. TRACKS BOARD::TracksInNet( int aNetCode )
  175. {
  176. TRACKS ret;
  177. INSPECTOR_FUNC inspector = [aNetCode,&ret] ( EDA_ITEM* item, void* testData )
  178. {
  179. TRACK* t = (TRACK*) item;
  180. if( t->GetNetCode() == aNetCode )
  181. ret.push_back( t );
  182. return SEARCH_CONTINUE;
  183. };
  184. // visit this BOARD's TRACKs and VIAs with above TRACK INSPECTOR which
  185. // appends all in aNetCode to ret.
  186. Visit( inspector, NULL, GENERAL_COLLECTOR::Tracks );
  187. return ret;
  188. }
  189. bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
  190. {
  191. if( unsigned( aIndex ) < arrayDim( m_Layer ) )
  192. {
  193. m_Layer[ aIndex ] = aLayer;
  194. return true;
  195. }
  196. return false;
  197. }
  198. const PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
  199. {
  200. // Look for the BOARD specific copper layer names
  201. for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
  202. {
  203. if ( IsCopperLayer( layer ) && ( m_Layer[ layer ].m_name == aLayerName ) )
  204. {
  205. return ToLAYER_ID( layer );
  206. }
  207. }
  208. // Otherwise fall back to the system standard layer names
  209. for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
  210. {
  211. if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
  212. {
  213. return ToLAYER_ID( layer );
  214. }
  215. }
  216. return UNDEFINED_LAYER;
  217. }
  218. const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
  219. {
  220. // All layer names are stored in the BOARD.
  221. if( IsLayerEnabled( aLayer ) )
  222. {
  223. // Standard names were set in BOARD::BOARD() but they may be
  224. // over-ridden by BOARD::SetLayerName().
  225. // For copper layers, return the actual copper layer name,
  226. // otherwise return the Standard English layer name.
  227. if( IsCopperLayer( aLayer ) )
  228. return m_Layer[aLayer].m_name;
  229. }
  230. return GetStandardLayerName( aLayer );
  231. }
  232. bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
  233. {
  234. if( !IsCopperLayer( aLayer ) )
  235. return false;
  236. if( aLayerName == wxEmptyString )
  237. return false;
  238. // no quote chars in the name allowed
  239. if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
  240. return false;
  241. wxString nameTemp = aLayerName;
  242. // replace any spaces with underscores before we do any comparing
  243. nameTemp.Replace( wxT( " " ), wxT( "_" ) );
  244. if( IsLayerEnabled( aLayer ) )
  245. {
  246. #if 0
  247. for( LAYER_NUM i = FIRST_COPPER_LAYER; i < NB_COPPER_LAYERS; ++i )
  248. {
  249. if( i != aLayer && IsLayerEnabled( i ) && nameTemp == m_Layer[i].m_Name )
  250. return false;
  251. }
  252. #else
  253. for( LSEQ cu = GetEnabledLayers().CuStack(); cu; ++cu )
  254. {
  255. PCB_LAYER_ID id = *cu;
  256. // veto changing the name if it exists elsewhere.
  257. if( id != aLayer && nameTemp == m_Layer[id].m_name )
  258. // if( id != aLayer && nameTemp == wxString( m_Layer[id].m_name ) )
  259. return false;
  260. }
  261. #endif
  262. m_Layer[aLayer].m_name = nameTemp;
  263. return true;
  264. }
  265. return false;
  266. }
  267. LAYER_T BOARD::GetLayerType( PCB_LAYER_ID aLayer ) const
  268. {
  269. if( !IsCopperLayer( aLayer ) )
  270. return LT_SIGNAL;
  271. //@@IMB: The original test was broken due to the discontinuity
  272. // in the layer sequence.
  273. if( IsLayerEnabled( aLayer ) )
  274. return m_Layer[aLayer].m_type;
  275. return LT_SIGNAL;
  276. }
  277. bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
  278. {
  279. if( !IsCopperLayer( aLayer ) )
  280. return false;
  281. //@@IMB: The original test was broken due to the discontinuity
  282. // in the layer sequence.
  283. if( IsLayerEnabled( aLayer ) )
  284. {
  285. m_Layer[aLayer].m_type = aLayerType;
  286. return true;
  287. }
  288. return false;
  289. }
  290. const char* LAYER::ShowType( LAYER_T aType )
  291. {
  292. const char* cp;
  293. switch( aType )
  294. {
  295. default:
  296. case LT_SIGNAL:
  297. cp = "signal";
  298. break;
  299. case LT_POWER:
  300. cp = "power";
  301. break;
  302. case LT_MIXED:
  303. cp = "mixed";
  304. break;
  305. case LT_JUMPER:
  306. cp = "jumper";
  307. break;
  308. }
  309. return cp;
  310. }
  311. LAYER_T LAYER::ParseType( const char* aType )
  312. {
  313. if( strcmp( aType, "signal" ) == 0 )
  314. return LT_SIGNAL;
  315. else if( strcmp( aType, "power" ) == 0 )
  316. return LT_POWER;
  317. else if( strcmp( aType, "mixed" ) == 0 )
  318. return LT_MIXED;
  319. else if( strcmp( aType, "jumper" ) == 0 )
  320. return LT_JUMPER;
  321. else
  322. return LT_UNDEFINED;
  323. }
  324. int BOARD::GetCopperLayerCount() const
  325. {
  326. return m_designSettings.GetCopperLayerCount();
  327. }
  328. void BOARD::SetCopperLayerCount( int aCount )
  329. {
  330. m_designSettings.SetCopperLayerCount( aCount );
  331. }
  332. LSET BOARD::GetEnabledLayers() const
  333. {
  334. return m_designSettings.GetEnabledLayers();
  335. }
  336. LSET BOARD::GetVisibleLayers() const
  337. {
  338. return m_designSettings.GetVisibleLayers();
  339. }
  340. void BOARD::SetEnabledLayers( LSET aLayerSet )
  341. {
  342. m_designSettings.SetEnabledLayers( aLayerSet );
  343. }
  344. void BOARD::SetVisibleLayers( LSET aLayerSet )
  345. {
  346. m_designSettings.SetVisibleLayers( aLayerSet );
  347. }
  348. void BOARD::SetVisibleElements( int aMask )
  349. {
  350. // Call SetElementVisibility for each item
  351. // to ensure specific calculations that can be needed by some items,
  352. // just changing the visibility flags could be not sufficient.
  353. for( GAL_LAYER_ID ii = GAL_LAYER_ID_START; ii < GAL_LAYER_ID_BITMASK_END; ++ii )
  354. {
  355. int item_mask = 1 << GAL_LAYER_INDEX( ii );
  356. SetElementVisibility( ii, aMask & item_mask );
  357. }
  358. }
  359. void BOARD::SetVisibleAlls()
  360. {
  361. SetVisibleLayers( LSET().set() );
  362. // Call SetElementVisibility for each item,
  363. // to ensure specific calculations that can be needed by some items
  364. for( GAL_LAYER_ID ii = GAL_LAYER_ID_START; ii < GAL_LAYER_ID_BITMASK_END; ++ii )
  365. SetElementVisibility( ii, true );
  366. }
  367. int BOARD::GetVisibleElements() const
  368. {
  369. return m_designSettings.GetVisibleElements();
  370. }
  371. bool BOARD::IsElementVisible( GAL_LAYER_ID aLayer ) const
  372. {
  373. return m_designSettings.IsElementVisible( aLayer );
  374. }
  375. void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
  376. {
  377. m_designSettings.SetElementVisibility( aLayer, isEnabled );
  378. switch( aLayer )
  379. {
  380. case LAYER_RATSNEST:
  381. {
  382. // because we have a tool to show/hide ratsnest relative to a pad or a module
  383. // so the hide/show option is a per item selection
  384. for( auto track : Tracks() )
  385. track->SetLocalRatsnestVisible( isEnabled );
  386. for( auto mod : Modules() )
  387. {
  388. for( auto pad : mod->Pads() )
  389. pad->SetLocalRatsnestVisible( isEnabled );
  390. }
  391. for( int i = 0; i<GetAreaCount(); i++ )
  392. {
  393. auto zone = GetArea( i );
  394. zone->SetLocalRatsnestVisible( isEnabled );
  395. }
  396. break;
  397. }
  398. default:
  399. ;
  400. }
  401. }
  402. bool BOARD::IsModuleLayerVisible( PCB_LAYER_ID aLayer )
  403. {
  404. switch( aLayer )
  405. {
  406. case F_Cu:
  407. return IsElementVisible( LAYER_MOD_FR );
  408. case B_Cu:
  409. return IsElementVisible( LAYER_MOD_BK );
  410. default:
  411. wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible() param error: bad layer" ) );
  412. return true;
  413. }
  414. }
  415. void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
  416. {
  417. if( aBoardItem == NULL )
  418. {
  419. wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem NULL" ) );
  420. return;
  421. }
  422. switch( aBoardItem->Type() )
  423. {
  424. case PCB_NETINFO_T:
  425. m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
  426. break;
  427. // this one uses a vector
  428. case PCB_MARKER_T:
  429. m_markers.push_back( (MARKER_PCB*) aBoardItem );
  430. break;
  431. // this one uses a vector
  432. case PCB_ZONE_AREA_T:
  433. m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
  434. break;
  435. case PCB_TRACE_T:
  436. case PCB_VIA_T:
  437. if( aMode == ADD_APPEND )
  438. m_tracks.push_back( static_cast<TRACK*>( aBoardItem ) );
  439. else
  440. m_tracks.push_front( static_cast<TRACK*>( aBoardItem ) );
  441. break;
  442. case PCB_MODULE_T:
  443. if( aMode == ADD_APPEND )
  444. m_modules.push_back( (MODULE*) aBoardItem );
  445. else
  446. m_modules.push_front( (MODULE*) aBoardItem );
  447. break;
  448. case PCB_DIMENSION_T:
  449. case PCB_LINE_T:
  450. case PCB_TEXT_T:
  451. case PCB_TARGET_T:
  452. if( aMode == ADD_APPEND )
  453. m_drawings.push_back( aBoardItem );
  454. else
  455. m_drawings.push_front( aBoardItem );
  456. break;
  457. // other types may use linked list
  458. default:
  459. {
  460. wxString msg;
  461. msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
  462. aBoardItem->Type() );
  463. wxFAIL_MSG( msg );
  464. return;
  465. }
  466. break;
  467. }
  468. aBoardItem->SetParent( this );
  469. m_connectivity->Add( aBoardItem );
  470. }
  471. void BOARD::Remove( BOARD_ITEM* aBoardItem )
  472. {
  473. // find these calls and fix them! Don't send me no stinking' NULL.
  474. wxASSERT( aBoardItem );
  475. switch( aBoardItem->Type() )
  476. {
  477. case PCB_NETINFO_T:
  478. {
  479. NETINFO_ITEM* item = (NETINFO_ITEM*) aBoardItem;
  480. m_NetInfo.RemoveNet( item );
  481. break;
  482. }
  483. case PCB_MARKER_T:
  484. // find the item in the vector, then remove it
  485. for( unsigned i = 0; i<m_markers.size(); ++i )
  486. {
  487. if( m_markers[i] == (MARKER_PCB*) aBoardItem )
  488. {
  489. m_markers.erase( m_markers.begin() + i );
  490. break;
  491. }
  492. }
  493. break;
  494. case PCB_ZONE_AREA_T: // this one uses a vector
  495. // find the item in the vector, then delete then erase it.
  496. for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
  497. {
  498. if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
  499. {
  500. m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
  501. break;
  502. }
  503. }
  504. break;
  505. case PCB_MODULE_T:
  506. m_modules.erase( std::remove_if( m_modules.begin(), m_modules.end(),
  507. [aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) );
  508. break;
  509. case PCB_TRACE_T:
  510. case PCB_VIA_T:
  511. m_tracks.erase( std::remove_if( m_tracks.begin(), m_tracks.end(),
  512. [aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) );
  513. break;
  514. case PCB_DIMENSION_T:
  515. case PCB_LINE_T:
  516. case PCB_TEXT_T:
  517. case PCB_TARGET_T:
  518. m_drawings.erase(
  519. std::remove_if( m_drawings.begin(), m_drawings.end(),
  520. [aBoardItem](BOARD_ITEM* aItem)
  521. { return aItem == aBoardItem;} ) );
  522. break;
  523. // other types may use linked list
  524. default:
  525. wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
  526. }
  527. m_connectivity->Remove( aBoardItem );
  528. }
  529. wxString BOARD::GetSelectMenuText( EDA_UNITS_T aUnits ) const
  530. {
  531. return wxString::Format( _( "PCB" ) );
  532. }
  533. void BOARD::DeleteMARKERs()
  534. {
  535. // the vector does not know how to delete the MARKER_PCB, it holds pointers
  536. for( MARKER_PCB* marker : m_markers )
  537. delete marker;
  538. m_markers.clear();
  539. }
  540. void BOARD::DeleteZONEOutlines()
  541. {
  542. // the vector does not know how to delete the ZONE Outlines, it holds pointers
  543. for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
  544. delete zone;
  545. m_ZoneDescriptorList.clear();
  546. }
  547. BOARD_ITEM* BOARD::GetItem( void* aWeakReference )
  548. {
  549. for( TRACK* track : Tracks() )
  550. if( track == aWeakReference )
  551. return track;
  552. for( MODULE* module : Modules() )
  553. {
  554. if( module == aWeakReference )
  555. return module;
  556. for( D_PAD* pad : module->Pads() )
  557. if( pad == aWeakReference )
  558. return pad;
  559. if( &module->Reference() == aWeakReference )
  560. return &module->Reference();
  561. if( &module->Value() == aWeakReference )
  562. return &module->Value();
  563. for( BOARD_ITEM* drawing : module->GraphicalItems() )
  564. if( drawing == aWeakReference )
  565. return drawing;
  566. }
  567. for( ZONE_CONTAINER* zone : Zones() )
  568. if( zone == aWeakReference )
  569. return zone;
  570. for( BOARD_ITEM* drawing : Drawings() )
  571. if( drawing == aWeakReference )
  572. return drawing;
  573. // Not found; weak reference has been deleted.
  574. return &g_DeletedItem;
  575. }
  576. unsigned BOARD::GetNodesCount( int aNet )
  577. {
  578. unsigned retval = 0;
  579. for( auto mod : Modules() )
  580. {
  581. for( auto pad : mod->Pads() )
  582. {
  583. if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
  584. retval++;
  585. }
  586. }
  587. return retval;
  588. }
  589. unsigned BOARD::GetUnconnectedNetCount() const
  590. {
  591. return m_connectivity->GetUnconnectedCount();
  592. }
  593. EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
  594. {
  595. bool hasItems = false;
  596. EDA_RECT area;
  597. LSET visible = GetVisibleLayers();
  598. // Check segments, dimensions, texts, and fiducials
  599. for( auto item : m_drawings )
  600. {
  601. if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) )
  602. continue;
  603. if( !( item->GetLayerSet() & visible ).any() )
  604. continue;
  605. if( !hasItems )
  606. area = item->GetBoundingBox();
  607. else
  608. area.Merge( item->GetBoundingBox() );
  609. hasItems = true;
  610. }
  611. if( !aBoardEdgesOnly )
  612. {
  613. // Check modules
  614. for( auto module : m_modules )
  615. {
  616. if( !( module->GetLayerSet() & visible ).any() )
  617. continue;
  618. if( !hasItems )
  619. area = module->GetBoundingBox();
  620. else
  621. area.Merge( module->GetBoundingBox() );
  622. hasItems = true;
  623. }
  624. // Check tracks
  625. for( auto track : m_tracks )
  626. {
  627. if( !( track->GetLayerSet() & visible ).any() )
  628. continue;
  629. if( !hasItems )
  630. area = track->GetBoundingBox();
  631. else
  632. area.Merge( track->GetBoundingBox() );
  633. hasItems = true;
  634. }
  635. // Check zones
  636. for( auto aZone : m_ZoneDescriptorList )
  637. {
  638. if( !( aZone->GetLayerSet() & visible ).any() )
  639. continue;
  640. if( !hasItems )
  641. area = aZone->GetBoundingBox();
  642. else
  643. area.Merge( aZone->GetBoundingBox() );
  644. area.Merge( aZone->GetBoundingBox() );
  645. hasItems = true;
  646. }
  647. }
  648. return area;
  649. }
  650. void BOARD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
  651. {
  652. wxString txt;
  653. int viasCount = 0;
  654. int trackSegmentsCount = 0;
  655. for( auto item : m_tracks )
  656. {
  657. if( item->Type() == PCB_VIA_T )
  658. viasCount++;
  659. else
  660. trackSegmentsCount++;
  661. }
  662. txt.Printf( wxT( "%d" ), GetPadCount() );
  663. aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );
  664. txt.Printf( wxT( "%d" ), viasCount );
  665. aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, DARKGREEN ) );
  666. txt.Printf( wxT( "%d" ), trackSegmentsCount );
  667. aList.push_back( MSG_PANEL_ITEM( _( "Track Segments" ), txt, DARKGREEN ) );
  668. txt.Printf( wxT( "%d" ), GetNodesCount() );
  669. aList.push_back( MSG_PANEL_ITEM( _( "Nodes" ), txt, DARKCYAN ) );
  670. txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() - 1 /* Don't include "No Net" in count */ );
  671. aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
  672. txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
  673. aList.push_back( MSG_PANEL_ITEM( _( "Unrouted" ), txt, BLUE ) );
  674. }
  675. SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
  676. {
  677. KICAD_T stype;
  678. SEARCH_RESULT result = SEARCH_CONTINUE;
  679. const KICAD_T* p = scanTypes;
  680. bool done = false;
  681. #if 0 && defined(DEBUG)
  682. std::cout << GetClass().mb_str() << ' ';
  683. #endif
  684. while( !done )
  685. {
  686. stype = *p;
  687. switch( stype )
  688. {
  689. case PCB_T:
  690. result = inspector( this, testData ); // inspect me
  691. // skip over any types handled in the above call.
  692. ++p;
  693. break;
  694. /* Instances of the requested KICAD_T live in a list, either one
  695. * that I manage, or that my modules manage. If it's a type managed
  696. * by class MODULE, then simply pass it on to each module's
  697. * MODULE::Visit() function by way of the
  698. * IterateForward( m_Modules, ... ) call.
  699. */
  700. case PCB_MODULE_T:
  701. case PCB_PAD_T:
  702. case PCB_MODULE_TEXT_T:
  703. case PCB_MODULE_EDGE_T:
  704. // this calls MODULE::Visit() on each module.
  705. result = IterateForward<MODULE*>( m_modules, inspector, testData, p );
  706. // skip over any types handled in the above call.
  707. for( ; ; )
  708. {
  709. switch( stype = *++p )
  710. {
  711. case PCB_MODULE_T:
  712. case PCB_PAD_T:
  713. case PCB_MODULE_TEXT_T:
  714. case PCB_MODULE_EDGE_T:
  715. continue;
  716. default:
  717. ;
  718. }
  719. break;
  720. }
  721. break;
  722. case PCB_LINE_T:
  723. case PCB_TEXT_T:
  724. case PCB_DIMENSION_T:
  725. case PCB_TARGET_T:
  726. result = IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, p );
  727. // skip over any types handled in the above call.
  728. for( ; ; )
  729. {
  730. switch( stype = *++p )
  731. {
  732. case PCB_LINE_T:
  733. case PCB_TEXT_T:
  734. case PCB_DIMENSION_T:
  735. case PCB_TARGET_T:
  736. continue;
  737. default:
  738. ;
  739. }
  740. break;
  741. }
  742. ;
  743. break;
  744. #if 0 // both these are on same list, so we must scan it twice in order
  745. // to get VIA priority, using new #else code below.
  746. // But we are not using separate lists for TRACKs and VIA, because
  747. // items are ordered (sorted) in the linked
  748. // list by netcode AND by physical distance:
  749. // when created, if a track or via is connected to an existing track or
  750. // via, it is put in linked list after this existing track or via
  751. // So usually, connected tracks or vias are grouped in this list
  752. // So the algorithm (used in ratsnest computations) which computes the
  753. // track connectivity is faster (more than 100 time regarding to
  754. // a non ordered list) because when it searches for a connection, first
  755. // it tests the near (near in term of linked list) 50 items
  756. // from the current item (track or via) in test.
  757. // Usually, because of this sort, a connected item (if exists) is
  758. // found.
  759. // If not found (and only in this case) an exhaustive (and time
  760. // consuming) search is made, but this case is statistically rare.
  761. case PCB_VIA_T:
  762. case PCB_TRACE_T:
  763. result = IterateForward( m_Track, inspector, testData, p );
  764. // skip over any types handled in the above call.
  765. for( ; ; )
  766. {
  767. switch( stype = *++p )
  768. {
  769. case PCB_VIA_T:
  770. case PCB_TRACE_T:
  771. continue;
  772. default:
  773. ;
  774. }
  775. break;
  776. }
  777. break;
  778. #else
  779. case PCB_VIA_T:
  780. result = IterateForward<TRACK*>( m_tracks, inspector, testData, p );
  781. ++p;
  782. break;
  783. case PCB_TRACE_T:
  784. result = IterateForward<TRACK*>( m_tracks, inspector, testData, p );
  785. ++p;
  786. break;
  787. #endif
  788. case PCB_MARKER_T:
  789. // MARKER_PCBS are in the m_markers std::vector
  790. for( unsigned i = 0; i<m_markers.size(); ++i )
  791. {
  792. result = m_markers[i]->Visit( inspector, testData, p );
  793. if( result == SEARCH_QUIT )
  794. break;
  795. }
  796. ++p;
  797. break;
  798. case PCB_ZONE_AREA_T:
  799. // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
  800. for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
  801. {
  802. result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
  803. if( result == SEARCH_QUIT )
  804. break;
  805. }
  806. ++p;
  807. break;
  808. default: // catch EOT or ANY OTHER type here and return.
  809. done = true;
  810. break;
  811. }
  812. if( result == SEARCH_QUIT )
  813. break;
  814. }
  815. return result;
  816. }
  817. NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
  818. {
  819. // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
  820. // zero is reserved for "no connection" and is not actually a net.
  821. // NULL is returned for non valid netcodes
  822. wxASSERT( m_NetInfo.GetNetCount() > 0 );
  823. if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
  824. return &NETINFO_LIST::ORPHANED_ITEM;
  825. else
  826. return m_NetInfo.GetNetItem( aNetcode );
  827. }
  828. NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
  829. {
  830. return m_NetInfo.GetNetItem( aNetname );
  831. }
  832. MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
  833. {
  834. MODULE* found = nullptr;
  835. // search only for MODULES
  836. static const KICAD_T scanTypes[] = { PCB_MODULE_T, EOT };
  837. INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
  838. {
  839. MODULE* module = (MODULE*) item;
  840. if( aReference == module->GetReference() )
  841. {
  842. found = module;
  843. return SEARCH_QUIT;
  844. }
  845. return SEARCH_CONTINUE;
  846. };
  847. // visit this BOARD with the above inspector
  848. BOARD* nonconstMe = (BOARD*) this;
  849. nonconstMe->Visit( inspector, NULL, scanTypes );
  850. return found;
  851. }
  852. MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeStamp ) const
  853. {
  854. if( aSearchByTimeStamp )
  855. {
  856. for( auto module : m_modules )
  857. {
  858. if( aRefOrTimeStamp.CmpNoCase( module->GetPath() ) == 0 )
  859. return module;
  860. }
  861. }
  862. else
  863. {
  864. return FindModuleByReference( aRefOrTimeStamp );
  865. }
  866. return NULL;
  867. }
  868. // The pad count for each netcode, stored in a buffer for a fast access.
  869. // This is needed by the sort function sortNetsByNodes()
  870. static std::vector<int> padCountListByNet;
  871. // Sort nets by decreasing pad count.
  872. // For same pad count, sort by alphabetic names
  873. static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
  874. {
  875. int countA = padCountListByNet[a->GetNet()];
  876. int countB = padCountListByNet[b->GetNet()];
  877. if( countA == countB )
  878. return a->GetNetname() < b->GetNetname();
  879. else
  880. return countB < countA;
  881. }
  882. // Sort nets by alphabetic names
  883. static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
  884. {
  885. return a->GetNetname() < b->GetNetname();
  886. }
  887. int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
  888. {
  889. if( m_NetInfo.GetNetCount() == 0 )
  890. return 0;
  891. // Build the list
  892. std::vector <NETINFO_ITEM*> netBuffer;
  893. netBuffer.reserve( m_NetInfo.GetNetCount() );
  894. int max_netcode = 0;
  895. for( NETINFO_ITEM* net : m_NetInfo )
  896. {
  897. auto netcode = net->GetNet();
  898. if( netcode > 0 && net->IsCurrent() )
  899. {
  900. netBuffer.push_back( net );
  901. max_netcode = std::max( netcode, max_netcode);
  902. }
  903. }
  904. // sort the list
  905. if( aSortbyPadsCount )
  906. {
  907. // Build the pad count by net:
  908. padCountListByNet.clear();
  909. std::vector<D_PAD*> pads = GetPads();
  910. padCountListByNet.assign( max_netcode + 1, 0 );
  911. for( D_PAD* pad : pads )
  912. padCountListByNet[pad->GetNetCode()]++;
  913. sort( netBuffer.begin(), netBuffer.end(), sortNetsByNodes );
  914. }
  915. else
  916. {
  917. sort( netBuffer.begin(), netBuffer.end(), sortNetsByNames );
  918. }
  919. for( NETINFO_ITEM* net : netBuffer )
  920. aNames.Add( UnescapeString( net->GetNetname() ) );
  921. return netBuffer.size();
  922. }
  923. ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
  924. PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer, int aNetCode )
  925. {
  926. if( aEndLayer < 0 )
  927. aEndLayer = aStartLayer;
  928. if( aEndLayer < aStartLayer )
  929. std::swap( aEndLayer, aStartLayer );
  930. for( ZONE_CONTAINER* area : m_ZoneDescriptorList )
  931. {
  932. if( area->GetLayer() < aStartLayer || area->GetLayer() > aEndLayer )
  933. continue;
  934. // In locate functions we must skip tagged items with BUSY flag set.
  935. if( area->GetState( BUSY ) )
  936. continue;
  937. if( aNetCode >= 0 && area->GetNetCode() != aNetCode )
  938. continue;
  939. if( area->HitTestFilledArea( aRefPos ) )
  940. return area;
  941. }
  942. return NULL;
  943. }
  944. int BOARD::SetAreasNetCodesFromNetNames()
  945. {
  946. int error_count = 0;
  947. for( int ii = 0; ii < GetAreaCount(); ii++ )
  948. {
  949. ZONE_CONTAINER* it = GetArea( ii );
  950. if( !it->IsOnCopperLayer() )
  951. {
  952. it->SetNetCode( NETINFO_LIST::UNCONNECTED );
  953. continue;
  954. }
  955. if( it->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
  956. {
  957. const NETINFO_ITEM* net = it->GetNet();
  958. if( net )
  959. {
  960. it->SetNetCode( net->GetNet() );
  961. }
  962. else
  963. {
  964. error_count++;
  965. // keep Net Name and set m_NetCode to -1 : error flag.
  966. it->SetNetCode( -1 );
  967. }
  968. }
  969. }
  970. return error_count;
  971. }
  972. D_PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet )
  973. {
  974. if( !aLayerSet.any() )
  975. aLayerSet = LSET::AllCuMask();
  976. for( auto module : m_modules )
  977. {
  978. D_PAD* pad = NULL;
  979. if( module->HitTest( aPosition ) )
  980. pad = module->GetPad( aPosition, aLayerSet );
  981. if( pad )
  982. return pad;
  983. }
  984. return NULL;
  985. }
  986. D_PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
  987. {
  988. const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
  989. LSET lset( aTrace->GetLayer() );
  990. return GetPad( aPosition, lset );
  991. }
  992. D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
  993. {
  994. for( auto mod : Modules() )
  995. {
  996. for ( auto pad : mod->Pads() )
  997. {
  998. if( pad->GetPosition() != aPosition )
  999. continue;
  1000. // Pad found, it must be on the correct layer
  1001. if( ( pad->GetLayerSet() & aLayerSet ).any() )
  1002. return pad;
  1003. }
  1004. }
  1005. return nullptr;
  1006. }
  1007. D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet )
  1008. {
  1009. // Search aPadList for aPosition
  1010. // aPadList is sorted by X then Y values, and a fast binary search is used
  1011. int idxmax = aPadList.size()-1;
  1012. int delta = aPadList.size();
  1013. int idx = 0; // Starting index is the beginning of list
  1014. while( delta )
  1015. {
  1016. // Calculate half size of remaining interval to test.
  1017. // Ensure the computed value is not truncated (too small)
  1018. if( (delta & 1) && ( delta > 1 ) )
  1019. delta++;
  1020. delta /= 2;
  1021. D_PAD* pad = aPadList[idx];
  1022. if( pad->GetPosition() == aPosition ) // candidate found
  1023. {
  1024. // The pad must match the layer mask:
  1025. if( ( aLayerSet & pad->GetLayerSet() ).any() )
  1026. return pad;
  1027. // More than one pad can be at aPosition
  1028. // search for a pad at aPosition that matched this mask
  1029. // search next
  1030. for( int ii = idx+1; ii <= idxmax; ii++ )
  1031. {
  1032. pad = aPadList[ii];
  1033. if( pad->GetPosition() != aPosition )
  1034. break;
  1035. if( ( aLayerSet & pad->GetLayerSet() ).any() )
  1036. return pad;
  1037. }
  1038. // search previous
  1039. for( int ii = idx-1 ;ii >=0; ii-- )
  1040. {
  1041. pad = aPadList[ii];
  1042. if( pad->GetPosition() != aPosition )
  1043. break;
  1044. if( ( aLayerSet & pad->GetLayerSet() ).any() )
  1045. return pad;
  1046. }
  1047. // Not found:
  1048. return 0;
  1049. }
  1050. if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
  1051. {
  1052. if( pad->GetPosition().y < aPosition.y ) // Must search after this item
  1053. {
  1054. idx += delta;
  1055. if( idx > idxmax )
  1056. idx = idxmax;
  1057. }
  1058. else // Must search before this item
  1059. {
  1060. idx -= delta;
  1061. if( idx < 0 )
  1062. idx = 0;
  1063. }
  1064. }
  1065. else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
  1066. {
  1067. idx += delta;
  1068. if( idx > idxmax )
  1069. idx = idxmax;
  1070. }
  1071. else // Must search before this item
  1072. {
  1073. idx -= delta;
  1074. if( idx < 0 )
  1075. idx = 0;
  1076. }
  1077. }
  1078. return NULL;
  1079. }
  1080. /**
  1081. * Function SortPadsByXCoord
  1082. * is used by GetSortedPadListByXCoord to Sort a pad list by x coordinate value.
  1083. * This function is used to build ordered pads lists
  1084. */
  1085. bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
  1086. {
  1087. if( ref->GetPosition().x == comp->GetPosition().x )
  1088. return ref->GetPosition().y < comp->GetPosition().y;
  1089. return ref->GetPosition().x < comp->GetPosition().x;
  1090. }
  1091. void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
  1092. {
  1093. for ( auto mod : Modules() )
  1094. {
  1095. for ( auto pad : mod->Pads( ) )
  1096. {
  1097. if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
  1098. {
  1099. aVector.push_back( pad );
  1100. }
  1101. }
  1102. }
  1103. std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
  1104. }
  1105. void BOARD::PadDelete( D_PAD* aPad )
  1106. {
  1107. GetConnectivity()->Remove( aPad );
  1108. aPad->DeleteStructure();
  1109. }
  1110. std::tuple<int, double, double> BOARD::GetTrackLength( const TRACK& aTrack ) const
  1111. {
  1112. int count = 0;
  1113. double length = 0.0;
  1114. double package_length = 0.0;
  1115. constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_PAD_T, EOT };
  1116. auto connectivity = GetBoard()->GetConnectivity();
  1117. for( auto item : connectivity->GetConnectedItems(
  1118. static_cast<const BOARD_CONNECTED_ITEM*>( &aTrack ), types ) )
  1119. {
  1120. count++;
  1121. if( auto track = dyn_cast<TRACK*>( item ) )
  1122. {
  1123. bool inPad = false;
  1124. for( auto pad_it : connectivity->GetConnectedPads( item ) )
  1125. {
  1126. auto pad = static_cast<D_PAD*>( pad_it );
  1127. if( pad->HitTest( track->GetStart(), track->GetWidth() / 2 )
  1128. && pad->HitTest( track->GetEnd(), track->GetWidth() / 2 ) )
  1129. {
  1130. inPad = true;
  1131. break;
  1132. }
  1133. }
  1134. if( !inPad )
  1135. length += track->GetLength();
  1136. }
  1137. else if( auto pad = dyn_cast<D_PAD*>( item ) )
  1138. package_length += pad->GetPadToDieLength();
  1139. }
  1140. return std::make_tuple( count, length, package_length );
  1141. }
  1142. MODULE* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
  1143. bool aVisibleOnly, bool aIgnoreLocked )
  1144. {
  1145. MODULE* module = NULL;
  1146. MODULE* alt_module = NULL;
  1147. int min_dim = 0x7FFFFFFF;
  1148. int alt_min_dim = 0x7FFFFFFF;
  1149. bool current_layer_back = IsBackLayer( aActiveLayer );
  1150. for( auto pt_module : m_modules )
  1151. {
  1152. // is the ref point within the module's bounds?
  1153. if( !pt_module->HitTest( aPosition ) )
  1154. continue;
  1155. // if caller wants to ignore locked modules, and this one is locked, skip it.
  1156. if( aIgnoreLocked && pt_module->IsLocked() )
  1157. continue;
  1158. PCB_LAYER_ID layer = pt_module->GetLayer();
  1159. // Filter non visible modules if requested
  1160. if( !aVisibleOnly || IsModuleLayerVisible( layer ) )
  1161. {
  1162. EDA_RECT bb = pt_module->GetFootprintRect();
  1163. int offx = bb.GetX() + bb.GetWidth() / 2;
  1164. int offy = bb.GetY() + bb.GetHeight() / 2;
  1165. // off x & offy point to the middle of the box.
  1166. int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
  1167. ( aPosition.y - offy ) * ( aPosition.y - offy );
  1168. if( current_layer_back == IsBackLayer( layer ) )
  1169. {
  1170. if( dist <= min_dim )
  1171. {
  1172. // better footprint shown on the active side
  1173. module = pt_module;
  1174. min_dim = dist;
  1175. }
  1176. }
  1177. else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
  1178. {
  1179. if( dist <= alt_min_dim )
  1180. {
  1181. // better footprint shown on the other side
  1182. alt_module = pt_module;
  1183. alt_min_dim = dist;
  1184. }
  1185. }
  1186. }
  1187. }
  1188. if( module )
  1189. {
  1190. return module;
  1191. }
  1192. if( alt_module)
  1193. {
  1194. return alt_module;
  1195. }
  1196. return NULL;
  1197. }
  1198. ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
  1199. PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch )
  1200. {
  1201. ZONE_CONTAINER* new_area = InsertArea( aNetcode,
  1202. m_ZoneDescriptorList.size( ) - 1,
  1203. aLayer, aStartPointPosition.x,
  1204. aStartPointPosition.y, aHatch );
  1205. if( aNewZonesList )
  1206. {
  1207. ITEM_PICKER picker( new_area, UR_NEW );
  1208. aNewZonesList->PushItem( picker );
  1209. }
  1210. return new_area;
  1211. }
  1212. void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
  1213. {
  1214. if( area_to_remove == NULL )
  1215. return;
  1216. if( aDeletedList )
  1217. {
  1218. ITEM_PICKER picker( area_to_remove, UR_DELETED );
  1219. aDeletedList->PushItem( picker );
  1220. Remove( area_to_remove ); // remove from zone list, but does not delete it
  1221. }
  1222. else
  1223. {
  1224. Delete( area_to_remove );
  1225. }
  1226. }
  1227. ZONE_CONTAINER* BOARD::InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
  1228. int aCornerX, int aCornerY, int aHatch )
  1229. {
  1230. ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
  1231. new_area->SetNetCode( aNetcode );
  1232. new_area->SetLayer( aLayer );
  1233. new_area->SetTimeStamp( GetNewTimeStamp() );
  1234. if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
  1235. m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
  1236. else
  1237. m_ZoneDescriptorList.push_back( new_area );
  1238. new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
  1239. // Add the first corner to the new zone
  1240. new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
  1241. return new_area;
  1242. }
  1243. bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE_CONTAINER* aCurrArea )
  1244. {
  1245. // mark all areas as unmodified except this one, if modified
  1246. for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
  1247. zone->SetLocalFlags( 0 );
  1248. aCurrArea->SetLocalFlags( 1 );
  1249. if( aCurrArea->Outline()->IsSelfIntersecting() )
  1250. {
  1251. aCurrArea->UnHatch();
  1252. // Normalize copied area and store resulting number of polygons
  1253. int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
  1254. // If clipping has created some polygons, we must add these new copper areas.
  1255. if( n_poly > 1 )
  1256. {
  1257. ZONE_CONTAINER* NewArea;
  1258. // Move the newly created polygons to new areas, removing them from the current area
  1259. for( int ip = 1; ip < n_poly; ip++ )
  1260. {
  1261. // Create new copper area and copy poly into it
  1262. SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
  1263. NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
  1264. wxPoint(0, 0), aCurrArea->GetHatchStyle() );
  1265. // remove the poly that was automatically created for the new area
  1266. // and replace it with a poly from NormalizeAreaOutlines
  1267. delete NewArea->Outline();
  1268. NewArea->SetOutline( new_p );
  1269. NewArea->Hatch();
  1270. NewArea->SetLocalFlags( 1 );
  1271. }
  1272. SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
  1273. delete aCurrArea->Outline();
  1274. aCurrArea->SetOutline( new_p );
  1275. }
  1276. }
  1277. aCurrArea->Hatch();
  1278. return true;
  1279. }
  1280. BOARD_ITEM* BOARD::Duplicate( const BOARD_ITEM* aItem,
  1281. bool aAddToBoard )
  1282. {
  1283. BOARD_ITEM* new_item = NULL;
  1284. switch( aItem->Type() )
  1285. {
  1286. case PCB_MODULE_T:
  1287. case PCB_TEXT_T:
  1288. case PCB_LINE_T:
  1289. case PCB_TRACE_T:
  1290. case PCB_VIA_T:
  1291. case PCB_ZONE_AREA_T:
  1292. case PCB_TARGET_T:
  1293. case PCB_DIMENSION_T:
  1294. new_item = static_cast<BOARD_ITEM*>( aItem->Clone() );
  1295. break;
  1296. default:
  1297. // Un-handled item for duplication
  1298. new_item = NULL;
  1299. break;
  1300. }
  1301. if( new_item && aAddToBoard )
  1302. Add( new_item );
  1303. return new_item;
  1304. }
  1305. /* Extracts the board outlines and build a closed polygon
  1306. * from lines, arcs and circle items on edge cut layer
  1307. * Any closed outline inside the main outline is a hole
  1308. * All contours should be closed, i.e. are valid vertices for a closed polygon
  1309. * return true if success, false if a contour is not valid
  1310. */
  1311. extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
  1312. wxString* aErrorText, unsigned int aTolerance,
  1313. wxPoint* aErrorLocation = nullptr );
  1314. bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText, wxPoint* aErrorLocation )
  1315. {
  1316. bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText,
  1317. GetDesignSettings().m_MaxError, aErrorLocation );
  1318. // Make polygon strictly simple to avoid issues (especially in 3D viewer)
  1319. aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
  1320. return success;
  1321. }
  1322. const std::vector<D_PAD*> BOARD::GetPads()
  1323. {
  1324. std::vector<D_PAD*> allPads;
  1325. for( MODULE* mod : Modules() )
  1326. {
  1327. for( D_PAD* pad : mod->Pads() )
  1328. allPads.push_back( pad );
  1329. }
  1330. return allPads;
  1331. }
  1332. unsigned BOARD::GetPadCount()
  1333. {
  1334. unsigned retval = 0;
  1335. for( auto mod : Modules() )
  1336. retval += mod->Pads().size();
  1337. return retval;
  1338. }
  1339. /**
  1340. * Function GetPad
  1341. * @return D_PAD* - at the \a aIndex
  1342. */
  1343. D_PAD* BOARD::GetPad( unsigned aIndex ) const
  1344. {
  1345. unsigned count = 0;
  1346. for( auto mod : m_modules )
  1347. {
  1348. for( auto pad : mod->Pads() )
  1349. {
  1350. if( count == aIndex )
  1351. return pad;
  1352. count++;
  1353. }
  1354. }
  1355. return nullptr;
  1356. }
  1357. void BOARD::ClearAllNetCodes()
  1358. {
  1359. for( auto zone : Zones() )
  1360. zone->SetNetCode( 0 );
  1361. for( auto pad : GetPads() )
  1362. pad->SetNetCode( 0 );
  1363. for( auto track : Tracks() )
  1364. track->SetNetCode( 0 );
  1365. }
  1366. const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
  1367. {
  1368. std::vector<BOARD_CONNECTED_ITEM*> items;
  1369. for( auto track : Tracks() )
  1370. {
  1371. items.push_back( track );
  1372. }
  1373. for( auto mod : Modules() )
  1374. {
  1375. for( auto pad : mod->Pads() )
  1376. {
  1377. items.push_back( pad );
  1378. }
  1379. }
  1380. for( int i = 0; i<GetAreaCount(); i++ )
  1381. {
  1382. auto zone = GetArea( i );
  1383. items.push_back( zone );
  1384. }
  1385. return items;
  1386. }
  1387. void BOARD::SanitizeNetcodes()
  1388. {
  1389. for ( auto item : AllConnectedItems() )
  1390. {
  1391. if( FindNet( item->GetNetCode() ) == nullptr )
  1392. item->SetNetCode( NETINFO_LIST::ORPHANED );
  1393. }
  1394. }