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.

2730 lines
80 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
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
19 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
++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
++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
14 years ago
14 years ago
18 years ago
18 years ago
17 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
++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
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
14 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
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
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 years ago
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 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) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.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-2012 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 <fctsys.h>
  34. #include <common.h>
  35. #include <kicad_string.h>
  36. #include <pcbcommon.h>
  37. #include <wxBasePcbFrame.h>
  38. #include <msgpanel.h>
  39. #include <pcb_netlist.h>
  40. #include <reporter.h>
  41. #include <base_units.h>
  42. #include <pcbnew.h>
  43. #include <colors_selection.h>
  44. #include <class_board.h>
  45. #include <class_module.h>
  46. #include <class_track.h>
  47. #include <class_zone.h>
  48. #include <class_marker_pcb.h>
  49. /* This is an odd place for this, but CvPcb won't link if it is
  50. * in class_board_item.cpp like I first tried it.
  51. */
  52. wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
  53. BOARD::BOARD() :
  54. BOARD_ITEM( (BOARD_ITEM*) NULL, PCB_T ),
  55. m_NetInfo( this ),
  56. m_paper( PAGE_INFO::A4, IsGOST() ),
  57. m_NetClasses( this )
  58. {
  59. // we have not loaded a board yet, assume latest until then.
  60. m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
  61. m_Status_Pcb = 0; // Status word: bit 1 = calculate.
  62. SetColorsSettings( &g_ColorsSettings );
  63. m_nodeCount = 0; // Number of connected pads.
  64. m_unconnectedNetCount = 0; // Number of unconnected nets.
  65. m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
  66. // zone contour currently in progress
  67. BuildListOfNets(); // prepare pad and netlist containers.
  68. for( LAYER_NUM layer = FIRST_LAYER; layer < NB_LAYERS; ++layer )
  69. {
  70. m_Layer[layer].m_Name = GetStandardLayerName( layer );
  71. if( layer <= LAST_COPPER_LAYER )
  72. m_Layer[layer].m_Type = LT_SIGNAL;
  73. else
  74. m_Layer[layer].m_Type = LT_UNDEFINED;
  75. }
  76. m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) );
  77. m_viaSizeIndex = 0;
  78. m_trackWidthIndex = 0;
  79. /* Dick 5-Feb-2012: this seems unnecessary. I don't believe the comment
  80. near line 70 of class_netclass.cpp. I stepped through with debugger.
  81. Perhaps something else is at work, it is not a constructor race.
  82. // Initialize default values in default netclass.
  83. */
  84. m_NetClasses.GetDefault()->SetParams();
  85. SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() );
  86. }
  87. BOARD::~BOARD()
  88. {
  89. while( m_ZoneDescriptorList.size() )
  90. {
  91. ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
  92. Delete( area_to_remove );
  93. }
  94. m_FullRatsnest.clear();
  95. m_LocalRatsnest.clear();
  96. DeleteMARKERs();
  97. DeleteZONEOutlines();
  98. delete m_CurrentZoneContour;
  99. m_CurrentZoneContour = NULL;
  100. }
  101. const wxPoint& BOARD::GetPosition() const
  102. {
  103. wxLogWarning( wxT( "This should not be called on the BOARD object") );
  104. return ZeroOffset;
  105. }
  106. void BOARD::SetPosition( const wxPoint& aPos )
  107. {
  108. wxLogWarning( wxT( "This should not be called on the BOARD object") );
  109. }
  110. void BOARD::Move( const wxPoint& aMoveVector ) // overload
  111. {
  112. wxLogWarning( wxT( "This should not be called on the BOARD object") );
  113. }
  114. void BOARD::chainMarkedSegments( wxPoint aPosition, LAYER_MSK aLayerMask, TRACK_PTRS* aList )
  115. {
  116. TRACK* segment; // The current segment being analyzed.
  117. TRACK* via; // The via identified, eventually destroy
  118. TRACK* candidate; // The end segment to destroy (or NULL = segment)
  119. int NbSegm;
  120. if( m_Track == NULL )
  121. return;
  122. /* Set the BUSY flag of all connected segments, first search starting at
  123. * aPosition. The search ends when a pad is found (end of a track), a
  124. * segment end has more than one other segment end connected, or when no
  125. * connected item found.
  126. *
  127. * Vias are a special case because they must look for segments connected
  128. * on other layers and they change the layer mask. They can be a track
  129. * end or not. They will be analyzer later and vias on terminal points
  130. * of the track will be considered as part of this track if they do not
  131. * connect segments of an other track together and will be considered as
  132. * part of an other track when removing the via, the segments of that other
  133. * track are disconnected.
  134. */
  135. for( ; ; )
  136. {
  137. if( GetPadFast( aPosition, aLayerMask ) != NULL )
  138. return;
  139. /* Test for a via: a via changes the layer mask and can connect a lot
  140. * of segments at location aPosition. When found, the via is just
  141. * pushed in list. Vias will be examined later, when all connected
  142. * segment are found and push in list. This is because when a via
  143. * is found we do not know at this time the number of connected items
  144. * and we do not know if this via is on the track or finish the track
  145. */
  146. via = m_Track->GetVia( NULL, aPosition, aLayerMask );
  147. if( via )
  148. {
  149. aLayerMask = via->GetLayerMask();
  150. aList->push_back( via );
  151. }
  152. /* Now we search all segments connected to point aPosition
  153. * if only 1 segment: this segment is candidate
  154. * if > 1 segment:
  155. * end of track (more than 2 segment connected at this location)
  156. */
  157. segment = m_Track; candidate = NULL;
  158. NbSegm = 0;
  159. while( ( segment = ::GetTrace( segment, NULL, aPosition, aLayerMask ) ) != NULL )
  160. {
  161. if( segment->GetState( BUSY ) ) // already found and selected: skip it
  162. {
  163. segment = segment->Next();
  164. continue;
  165. }
  166. if( segment == via ) // just previously found: skip it
  167. {
  168. segment = segment->Next();
  169. continue;
  170. }
  171. NbSegm++;
  172. if( NbSegm == 1 ) /* First time we found a connected item: segment is candidate */
  173. {
  174. candidate = segment;
  175. segment = segment->Next();
  176. }
  177. else /* More than 1 segment connected -> this location is an end of the track */
  178. {
  179. return;
  180. }
  181. }
  182. if( candidate ) // A candidate is found: flag it an push it in list
  183. {
  184. /* Initialize parameters to search items connected to this
  185. * candidate:
  186. * we must analyze connections to its other end
  187. */
  188. aLayerMask = candidate->GetLayerMask();
  189. if( aPosition == candidate->GetStart() )
  190. {
  191. aPosition = candidate->GetEnd();
  192. }
  193. else
  194. {
  195. aPosition = candidate->GetStart();
  196. }
  197. segment = m_Track; /* restart list of tracks to analyze */
  198. /* flag this item an push it in list of selected items */
  199. aList->push_back( candidate );
  200. candidate->SetState( BUSY, true );
  201. }
  202. else
  203. {
  204. return;
  205. }
  206. }
  207. }
  208. void BOARD::PushHighLight()
  209. {
  210. m_highLightPrevious = m_highLight;
  211. }
  212. void BOARD::PopHighLight()
  213. {
  214. m_highLight = m_highLightPrevious;
  215. m_highLightPrevious.Clear();
  216. }
  217. bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
  218. {
  219. NETCLASS* netClass = m_NetClasses.Find( aNetClassName );
  220. bool lists_sizes_modified = false;
  221. // if not found (should not happen) use the default
  222. if( netClass == NULL )
  223. netClass = m_NetClasses.GetDefault();
  224. m_currentNetClassName = netClass->GetName();
  225. // Initialize others values:
  226. if( m_ViasDimensionsList.size() == 0 )
  227. {
  228. VIA_DIMENSION viadim;
  229. lists_sizes_modified = true;
  230. m_ViasDimensionsList.push_back( viadim );
  231. }
  232. if( m_TrackWidthList.size() == 0 )
  233. {
  234. lists_sizes_modified = true;
  235. m_TrackWidthList.push_back( 0 );
  236. }
  237. /* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values
  238. * are always the Netclass values
  239. */
  240. if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() )
  241. lists_sizes_modified = true;
  242. m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter();
  243. if( m_TrackWidthList[0] != netClass->GetTrackWidth() )
  244. lists_sizes_modified = true;
  245. m_TrackWidthList[0] = netClass->GetTrackWidth();
  246. if( m_viaSizeIndex >= m_ViasDimensionsList.size() )
  247. m_viaSizeIndex = m_ViasDimensionsList.size();
  248. if( m_trackWidthIndex >= m_TrackWidthList.size() )
  249. m_trackWidthIndex = m_TrackWidthList.size();
  250. return lists_sizes_modified;
  251. }
  252. int BOARD::GetBiggestClearanceValue()
  253. {
  254. int clearance = m_NetClasses.GetDefault()->GetClearance();
  255. //Read list of Net Classes
  256. for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
  257. {
  258. NETCLASS* netclass = nc->second;
  259. clearance = std::max( clearance, netclass->GetClearance() );
  260. }
  261. return clearance;
  262. }
  263. int BOARD::GetSmallestClearanceValue()
  264. {
  265. int clearance = m_NetClasses.GetDefault()->GetClearance();
  266. //Read list of Net Classes
  267. for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
  268. {
  269. NETCLASS* netclass = nc->second;
  270. clearance = std::min( clearance, netclass->GetClearance() );
  271. }
  272. return clearance;
  273. }
  274. int BOARD::GetCurrentMicroViaSize()
  275. {
  276. NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
  277. return netclass->GetuViaDiameter();
  278. }
  279. int BOARD::GetCurrentMicroViaDrill()
  280. {
  281. NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
  282. return netclass->GetuViaDrill();
  283. }
  284. bool BOARD::SetLayer( LAYER_NUM aIndex, const LAYER& aLayer )
  285. {
  286. if( aIndex < NB_COPPER_LAYERS )
  287. {
  288. m_Layer[ aIndex ] = aLayer;
  289. return true;
  290. }
  291. return false;
  292. }
  293. wxString BOARD::GetLayerName( LAYER_NUM aLayer ) const
  294. {
  295. if( !IsPcbLayer( aLayer ) )
  296. return wxEmptyString;
  297. // All layer names are stored in the BOARD.
  298. if( IsLayerEnabled( aLayer ) )
  299. {
  300. // Standard names were set in BOARD::BOARD() but they may be
  301. // over-ridden by BOARD::SetLayerName().
  302. // For copper layers, return the actual copper layer name,
  303. // otherwise return the Standard English layer name.
  304. if( IsCopperLayer( aLayer ) )
  305. return m_Layer[aLayer].m_Name;
  306. }
  307. return GetStandardLayerName( aLayer );
  308. }
  309. wxString BOARD::GetStandardLayerName( LAYER_NUM aLayerNumber )
  310. {
  311. const wxChar* txt;
  312. // These are only default layer names. For Pcbnew the copper names
  313. // may be over-ridden in the BOARD (*.brd) file.
  314. // Use a switch to explicitly show the mapping more clearly
  315. switch( aLayerNumber )
  316. {
  317. case LAYER_N_FRONT: txt = wxT( "F.Cu" ); break;
  318. case LAYER_N_2: txt = wxT( "Inner1.Cu" ); break;
  319. case LAYER_N_3: txt = wxT( "Inner2.Cu" ); break;
  320. case LAYER_N_4: txt = wxT( "Inner3.Cu" ); break;
  321. case LAYER_N_5: txt = wxT( "Inner4.Cu" ); break;
  322. case LAYER_N_6: txt = wxT( "Inner5.Cu" ); break;
  323. case LAYER_N_7: txt = wxT( "Inner6.Cu" ); break;
  324. case LAYER_N_8: txt = wxT( "Inner7.Cu" ); break;
  325. case LAYER_N_9: txt = wxT( "Inner8.Cu" ); break;
  326. case LAYER_N_10: txt = wxT( "Inner9.Cu" ); break;
  327. case LAYER_N_11: txt = wxT( "Inner10.Cu" ); break;
  328. case LAYER_N_12: txt = wxT( "Inner11.Cu" ); break;
  329. case LAYER_N_13: txt = wxT( "Inner12.Cu" ); break;
  330. case LAYER_N_14: txt = wxT( "Inner13.Cu" ); break;
  331. case LAYER_N_15: txt = wxT( "Inner14.Cu" ); break;
  332. case LAYER_N_BACK: txt = wxT( "B.Cu" ); break;
  333. case ADHESIVE_N_BACK: txt = wxT( "B.Adhes" ); break;
  334. case ADHESIVE_N_FRONT: txt = wxT( "F.Adhes" ); break;
  335. case SOLDERPASTE_N_BACK: txt = wxT( "B.Paste" ); break;
  336. case SOLDERPASTE_N_FRONT: txt = wxT( "F.Paste" ); break;
  337. case SILKSCREEN_N_BACK: txt = wxT( "B.SilkS" ); break;
  338. case SILKSCREEN_N_FRONT: txt = wxT( "F.SilkS" ); break;
  339. case SOLDERMASK_N_BACK: txt = wxT( "B.Mask" ); break;
  340. case SOLDERMASK_N_FRONT: txt = wxT( "F.Mask" ); break;
  341. case DRAW_N: txt = wxT( "Dwgs.User" ); break;
  342. case COMMENT_N: txt = wxT( "Cmts.User" ); break;
  343. case ECO1_N: txt = wxT( "Eco1.User" ); break;
  344. case ECO2_N: txt = wxT( "Eco2.User" ); break;
  345. case EDGE_N: txt = wxT( "Edge.Cuts" ); break;
  346. default: txt = wxT( "BAD_INDEX" ); break;
  347. }
  348. return txt; // wxString constructed once here
  349. }
  350. bool BOARD::SetLayerName( LAYER_NUM aLayer, const wxString& aLayerName )
  351. {
  352. if( !IsCopperLayer( aLayer ) )
  353. return false;
  354. if( aLayerName == wxEmptyString || aLayerName.Len() > 20 )
  355. return false;
  356. // no quote chars in the name allowed
  357. if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
  358. return false;
  359. wxString NameTemp = aLayerName;
  360. // replace any spaces with underscores before we do any comparing
  361. NameTemp.Replace( wxT( " " ), wxT( "_" ) );
  362. if( IsLayerEnabled( aLayer ) )
  363. {
  364. for( LAYER_NUM i = FIRST_COPPER_LAYER; i < NB_COPPER_LAYERS; ++i )
  365. {
  366. if( i != aLayer && IsLayerEnabled( i ) && NameTemp == m_Layer[i].m_Name )
  367. return false;
  368. }
  369. m_Layer[aLayer].m_Name = NameTemp;
  370. return true;
  371. }
  372. return false;
  373. }
  374. LAYER_T BOARD::GetLayerType( LAYER_NUM aLayer ) const
  375. {
  376. if( !IsCopperLayer( aLayer ) )
  377. return LT_SIGNAL;
  378. //@@IMB: The original test was broken due to the discontinuity
  379. // in the layer sequence.
  380. if( IsLayerEnabled( aLayer ) )
  381. return m_Layer[aLayer].m_Type;
  382. return LT_SIGNAL;
  383. }
  384. bool BOARD::SetLayerType( LAYER_NUM aLayer, LAYER_T aLayerType )
  385. {
  386. if( !IsCopperLayer( aLayer ) )
  387. return false;
  388. //@@IMB: The original test was broken due to the discontinuity
  389. // in the layer sequence.
  390. if( IsLayerEnabled( aLayer ) )
  391. {
  392. m_Layer[aLayer].m_Type = aLayerType;
  393. return true;
  394. }
  395. return false;
  396. }
  397. const char* LAYER::ShowType( LAYER_T aType )
  398. {
  399. const char* cp;
  400. switch( aType )
  401. {
  402. default:
  403. case LT_SIGNAL:
  404. cp = "signal";
  405. break;
  406. case LT_POWER:
  407. cp = "power";
  408. break;
  409. case LT_MIXED:
  410. cp = "mixed";
  411. break;
  412. case LT_JUMPER:
  413. cp = "jumper";
  414. break;
  415. }
  416. return cp;
  417. }
  418. LAYER_T LAYER::ParseType( const char* aType )
  419. {
  420. if( strcmp( aType, "signal" ) == 0 )
  421. return LT_SIGNAL;
  422. else if( strcmp( aType, "power" ) == 0 )
  423. return LT_POWER;
  424. else if( strcmp( aType, "mixed" ) == 0 )
  425. return LT_MIXED;
  426. else if( strcmp( aType, "jumper" ) == 0 )
  427. return LT_JUMPER;
  428. else
  429. return LT_UNDEFINED;
  430. }
  431. int BOARD::GetCopperLayerCount() const
  432. {
  433. return m_designSettings.GetCopperLayerCount();
  434. }
  435. void BOARD::SetCopperLayerCount( int aCount )
  436. {
  437. m_designSettings.SetCopperLayerCount( aCount );
  438. }
  439. LAYER_MSK BOARD::GetEnabledLayers() const
  440. {
  441. return m_designSettings.GetEnabledLayers();
  442. }
  443. LAYER_MSK BOARD::GetVisibleLayers() const
  444. {
  445. return m_designSettings.GetVisibleLayers();
  446. }
  447. void BOARD::SetEnabledLayers( LAYER_MSK aLayerMask )
  448. {
  449. m_designSettings.SetEnabledLayers( aLayerMask );
  450. }
  451. void BOARD::SetVisibleLayers( LAYER_MSK aLayerMask )
  452. {
  453. m_designSettings.SetVisibleLayers( aLayerMask );
  454. }
  455. void BOARD::SetVisibleElements( int aMask )
  456. {
  457. // Call SetElementVisibility for each item
  458. // to ensure specific calculations that can be needed by some items,
  459. // just changing the visibility flags could be not sufficient.
  460. for( int ii = 0; ii < PCB_VISIBLE( END_PCB_VISIBLE_LIST ); ii++ )
  461. {
  462. int item_mask = 1 << ii;
  463. SetElementVisibility( ii, aMask & item_mask );
  464. }
  465. }
  466. void BOARD::SetVisibleAlls()
  467. {
  468. SetVisibleLayers( FULL_LAYERS );
  469. // Call SetElementVisibility for each item,
  470. // to ensure specific calculations that can be needed by some items
  471. for( int ii = 0; ii < PCB_VISIBLE(END_PCB_VISIBLE_LIST); ii++ )
  472. SetElementVisibility( ii, true );
  473. }
  474. int BOARD::GetVisibleElements() const
  475. {
  476. return m_designSettings.GetVisibleElements();
  477. }
  478. bool BOARD::IsElementVisible( int aPCB_VISIBLE ) const
  479. {
  480. return m_designSettings.IsElementVisible( aPCB_VISIBLE );
  481. }
  482. void BOARD::SetElementVisibility( int aPCB_VISIBLE, bool isEnabled )
  483. {
  484. m_designSettings.SetElementVisibility( aPCB_VISIBLE, isEnabled );
  485. switch( aPCB_VISIBLE )
  486. {
  487. case RATSNEST_VISIBLE:
  488. // we must clear or set the CH_VISIBLE flags to hide/show ratsnest
  489. // because we have a tool to show/hide ratsnest relative to a pad or a module
  490. // so the hide/show option is a per item selection
  491. if( IsElementVisible( RATSNEST_VISIBLE ) )
  492. {
  493. for( unsigned ii = 0; ii < GetRatsnestsCount(); ii++ )
  494. m_FullRatsnest[ii].m_Status |= CH_VISIBLE;
  495. }
  496. else
  497. {
  498. for( unsigned ii = 0; ii < GetRatsnestsCount(); ii++ )
  499. m_FullRatsnest[ii].m_Status &= ~CH_VISIBLE;
  500. }
  501. break;
  502. default:
  503. ;
  504. }
  505. }
  506. EDA_COLOR_T BOARD::GetVisibleElementColor( int aPCB_VISIBLE )
  507. {
  508. EDA_COLOR_T color = UNSPECIFIED_COLOR;
  509. switch( aPCB_VISIBLE )
  510. {
  511. case NON_PLATED_VISIBLE:
  512. case VIA_THROUGH_VISIBLE:
  513. case VIA_MICROVIA_VISIBLE:
  514. case VIA_BBLIND_VISIBLE:
  515. case MOD_TEXT_FR_VISIBLE:
  516. case MOD_TEXT_BK_VISIBLE:
  517. case MOD_TEXT_INVISIBLE:
  518. case ANCHOR_VISIBLE:
  519. case PAD_FR_VISIBLE:
  520. case PAD_BK_VISIBLE:
  521. case RATSNEST_VISIBLE:
  522. case GRID_VISIBLE:
  523. color = GetColorsSettings()->GetItemColor( aPCB_VISIBLE );
  524. break;
  525. default:
  526. wxLogDebug( wxT( "BOARD::GetVisibleElementColor(): bad arg %d" ), aPCB_VISIBLE );
  527. }
  528. return color;
  529. }
  530. void BOARD::SetVisibleElementColor( int aPCB_VISIBLE, EDA_COLOR_T aColor )
  531. {
  532. switch( aPCB_VISIBLE )
  533. {
  534. case NON_PLATED_VISIBLE:
  535. case VIA_THROUGH_VISIBLE:
  536. case VIA_MICROVIA_VISIBLE:
  537. case VIA_BBLIND_VISIBLE:
  538. case MOD_TEXT_FR_VISIBLE:
  539. case MOD_TEXT_BK_VISIBLE:
  540. case MOD_TEXT_INVISIBLE:
  541. case ANCHOR_VISIBLE:
  542. case PAD_FR_VISIBLE:
  543. case PAD_BK_VISIBLE:
  544. case GRID_VISIBLE:
  545. case RATSNEST_VISIBLE:
  546. GetColorsSettings()->SetItemColor( aPCB_VISIBLE, aColor );
  547. break;
  548. default:
  549. wxLogDebug( wxT( "BOARD::SetVisibleElementColor(): bad arg %d" ), aPCB_VISIBLE );
  550. }
  551. }
  552. void BOARD::SetLayerColor( LAYER_NUM aLayer, EDA_COLOR_T aColor )
  553. {
  554. GetColorsSettings()->SetLayerColor( aLayer, aColor );
  555. }
  556. EDA_COLOR_T BOARD::GetLayerColor( LAYER_NUM aLayer ) const
  557. {
  558. return GetColorsSettings()->GetLayerColor( aLayer );
  559. }
  560. bool BOARD::IsModuleLayerVisible( LAYER_NUM layer )
  561. {
  562. switch( layer )
  563. {
  564. case LAYER_N_FRONT:
  565. return IsElementVisible( PCB_VISIBLE(MOD_FR_VISIBLE) );
  566. case LAYER_N_BACK:
  567. return IsElementVisible( PCB_VISIBLE(MOD_BK_VISIBLE) );
  568. default:
  569. wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible() param error: bad layer" ) );
  570. return true;
  571. }
  572. }
  573. void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
  574. {
  575. if( aBoardItem == NULL )
  576. {
  577. wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem NULL" ) );
  578. return;
  579. }
  580. switch( aBoardItem->Type() )
  581. {
  582. // this one uses a vector
  583. case PCB_MARKER_T:
  584. aBoardItem->SetParent( this );
  585. m_markers.push_back( (MARKER_PCB*) aBoardItem );
  586. break;
  587. // this one uses a vector
  588. case PCB_ZONE_AREA_T:
  589. aBoardItem->SetParent( this );
  590. m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
  591. break;
  592. case PCB_TRACE_T:
  593. case PCB_VIA_T:
  594. TRACK* insertAid;
  595. insertAid = ( (TRACK*) aBoardItem )->GetBestInsertPoint( this );
  596. m_Track.Insert( (TRACK*) aBoardItem, insertAid );
  597. break;
  598. case PCB_ZONE_T:
  599. if( aControl & ADD_APPEND )
  600. m_Zone.PushBack( (SEGZONE*) aBoardItem );
  601. else
  602. m_Zone.PushFront( (SEGZONE*) aBoardItem );
  603. aBoardItem->SetParent( this );
  604. break;
  605. case PCB_MODULE_T:
  606. if( aControl & ADD_APPEND )
  607. m_Modules.PushBack( (MODULE*) aBoardItem );
  608. else
  609. m_Modules.PushFront( (MODULE*) aBoardItem );
  610. aBoardItem->SetParent( this );
  611. // Because the list of pads has changed, reset the status
  612. // This indicate the list of pad and nets must be recalculated before use
  613. m_Status_Pcb = 0;
  614. break;
  615. case PCB_DIMENSION_T:
  616. case PCB_LINE_T:
  617. case PCB_TEXT_T:
  618. case PCB_MODULE_EDGE_T:
  619. case PCB_TARGET_T:
  620. if( aControl & ADD_APPEND )
  621. m_Drawings.PushBack( aBoardItem );
  622. else
  623. m_Drawings.PushFront( aBoardItem );
  624. aBoardItem->SetParent( this );
  625. break;
  626. // other types may use linked list
  627. default:
  628. {
  629. wxString msg;
  630. msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
  631. aBoardItem->Type() );
  632. wxFAIL_MSG( msg );
  633. }
  634. break;
  635. }
  636. }
  637. BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem )
  638. {
  639. // find these calls and fix them! Don't send me no stinking' NULL.
  640. wxASSERT( aBoardItem );
  641. switch( aBoardItem->Type() )
  642. {
  643. case PCB_MARKER_T:
  644. // find the item in the vector, then remove it
  645. for( unsigned i = 0; i<m_markers.size(); ++i )
  646. {
  647. if( m_markers[i] == (MARKER_PCB*) aBoardItem )
  648. {
  649. m_markers.erase( m_markers.begin() + i );
  650. break;
  651. }
  652. }
  653. break;
  654. case PCB_ZONE_AREA_T: // this one uses a vector
  655. // find the item in the vector, then delete then erase it.
  656. for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
  657. {
  658. if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
  659. {
  660. m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
  661. break;
  662. }
  663. }
  664. break;
  665. case PCB_MODULE_T:
  666. m_Modules.Remove( (MODULE*) aBoardItem );
  667. break;
  668. case PCB_TRACE_T:
  669. case PCB_VIA_T:
  670. m_Track.Remove( (TRACK*) aBoardItem );
  671. break;
  672. case PCB_ZONE_T:
  673. m_Zone.Remove( (SEGZONE*) aBoardItem );
  674. break;
  675. case PCB_DIMENSION_T:
  676. case PCB_LINE_T:
  677. case PCB_TEXT_T:
  678. case PCB_MODULE_EDGE_T:
  679. case PCB_TARGET_T:
  680. m_Drawings.Remove( aBoardItem );
  681. break;
  682. // other types may use linked list
  683. default:
  684. wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
  685. }
  686. return aBoardItem;
  687. }
  688. void BOARD::DeleteMARKERs()
  689. {
  690. // the vector does not know how to delete the MARKER_PCB, it holds pointers
  691. for( unsigned i = 0; i<m_markers.size(); ++i )
  692. delete m_markers[i];
  693. m_markers.clear();
  694. }
  695. void BOARD::DeleteZONEOutlines()
  696. {
  697. // the vector does not know how to delete the ZONE Outlines, it holds
  698. // pointers
  699. for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
  700. delete m_ZoneDescriptorList[i];
  701. m_ZoneDescriptorList.clear();
  702. }
  703. int BOARD::GetNumSegmTrack() const
  704. {
  705. return m_Track.GetCount();
  706. }
  707. int BOARD::GetNumSegmZone() const
  708. {
  709. return m_Zone.GetCount();
  710. }
  711. unsigned BOARD::GetNodesCount() const
  712. {
  713. return m_nodeCount;
  714. }
  715. EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
  716. {
  717. bool hasItems = false;
  718. EDA_RECT area;
  719. // Check segments, dimensions, texts, and fiducials
  720. for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
  721. {
  722. if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != EDGE_N ) )
  723. continue;
  724. if( !hasItems )
  725. area = item->GetBoundingBox();
  726. else
  727. area.Merge( item->GetBoundingBox() );
  728. hasItems = true;
  729. }
  730. if( !aBoardEdgesOnly )
  731. {
  732. // Check modules
  733. for( MODULE* module = m_Modules; module; module = module->Next() )
  734. {
  735. if( !hasItems )
  736. area = module->GetBoundingBox();
  737. else
  738. area.Merge( module->GetBoundingBox() );
  739. hasItems = true;
  740. }
  741. // Check tracks
  742. for( TRACK* track = m_Track; track; track = track->Next() )
  743. {
  744. if( !hasItems )
  745. area = track->GetBoundingBox();
  746. else
  747. area.Merge( track->GetBoundingBox() );
  748. hasItems = true;
  749. }
  750. // Check segment zones
  751. for( TRACK* track = m_Zone; track; track = track->Next() )
  752. {
  753. if( !hasItems )
  754. area = track->GetBoundingBox();
  755. else
  756. area.Merge( track->GetBoundingBox() );
  757. hasItems = true;
  758. }
  759. // Check polygonal zones
  760. for( unsigned int i = 0; i < m_ZoneDescriptorList.size(); i++ )
  761. {
  762. ZONE_CONTAINER* aZone = m_ZoneDescriptorList[i];
  763. if( !hasItems )
  764. area = aZone->GetBoundingBox();
  765. else
  766. area.Merge( aZone->GetBoundingBox() );
  767. area.Merge( aZone->GetBoundingBox() );
  768. hasItems = true;
  769. }
  770. }
  771. m_BoundingBox = area; // save for BOARD::GetBoundingBox()
  772. return area;
  773. }
  774. // virtual, see pcbstruct.h
  775. void BOARD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
  776. {
  777. wxString txt;
  778. int viasCount = 0;
  779. int trackSegmentsCount = 0;
  780. for( BOARD_ITEM* item = m_Track; item; item = item->Next() )
  781. {
  782. if( item->Type() == PCB_VIA_T )
  783. viasCount++;
  784. else
  785. trackSegmentsCount++;
  786. }
  787. txt.Printf( wxT( "%d" ), GetPadCount() );
  788. aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );
  789. txt.Printf( wxT( "%d" ), viasCount );
  790. aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, DARKGREEN ) );
  791. txt.Printf( wxT( "%d" ), trackSegmentsCount );
  792. aList.push_back( MSG_PANEL_ITEM( _( "trackSegm" ), txt, DARKGREEN ) );
  793. txt.Printf( wxT( "%d" ), GetNodesCount() );
  794. aList.push_back( MSG_PANEL_ITEM( _( "Nodes" ), txt, DARKCYAN ) );
  795. txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() );
  796. aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
  797. /* These parameters are known only if the full ratsnest is available,
  798. * so, display them only if this is the case
  799. */
  800. if( (m_Status_Pcb & NET_CODES_OK) )
  801. {
  802. txt.Printf( wxT( "%d" ), GetRatsnestsCount() );
  803. aList.push_back( MSG_PANEL_ITEM( _( "Links" ), txt, DARKGREEN ) );
  804. txt.Printf( wxT( "%d" ), GetRatsnestsCount() - GetUnconnectedNetCount() );
  805. aList.push_back( MSG_PANEL_ITEM( _( "Connect" ), txt, DARKGREEN ) );
  806. txt.Printf( wxT( "%d" ), GetUnconnectedNetCount() );
  807. aList.push_back( MSG_PANEL_ITEM( _( "Unconnected" ), txt, BLUE ) );
  808. }
  809. }
  810. // virtual, see pcbstruct.h
  811. SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData,
  812. const KICAD_T scanTypes[] )
  813. {
  814. KICAD_T stype;
  815. SEARCH_RESULT result = SEARCH_CONTINUE;
  816. const KICAD_T* p = scanTypes;
  817. bool done = false;
  818. #if 0 && defined(DEBUG)
  819. std::cout << GetClass().mb_str() << ' ';
  820. #endif
  821. while( !done )
  822. {
  823. stype = *p;
  824. switch( stype )
  825. {
  826. case PCB_T:
  827. result = inspector->Inspect( this, testData ); // inspect me
  828. // skip over any types handled in the above call.
  829. ++p;
  830. break;
  831. /* Instances of the requested KICAD_T live in a list, either one
  832. * that I manage, or that my modules manage. If it's a type managed
  833. * by class MODULE, then simply pass it on to each module's
  834. * MODULE::Visit() function by way of the
  835. * IterateForward( m_Modules, ... ) call.
  836. */
  837. case PCB_MODULE_T:
  838. case PCB_PAD_T:
  839. case PCB_MODULE_TEXT_T:
  840. case PCB_MODULE_EDGE_T:
  841. // this calls MODULE::Visit() on each module.
  842. result = IterateForward( m_Modules, inspector, testData, p );
  843. // skip over any types handled in the above call.
  844. for( ; ; )
  845. {
  846. switch( stype = *++p )
  847. {
  848. case PCB_MODULE_T:
  849. case PCB_PAD_T:
  850. case PCB_MODULE_TEXT_T:
  851. case PCB_MODULE_EDGE_T:
  852. continue;
  853. default:
  854. ;
  855. }
  856. break;
  857. }
  858. break;
  859. case PCB_LINE_T:
  860. case PCB_TEXT_T:
  861. case PCB_DIMENSION_T:
  862. case PCB_TARGET_T:
  863. result = IterateForward( m_Drawings, inspector, testData, p );
  864. // skip over any types handled in the above call.
  865. for( ; ; )
  866. {
  867. switch( stype = *++p )
  868. {
  869. case PCB_LINE_T:
  870. case PCB_TEXT_T:
  871. case PCB_DIMENSION_T:
  872. case PCB_TARGET_T:
  873. continue;
  874. default:
  875. ;
  876. }
  877. break;
  878. }
  879. ;
  880. break;
  881. #if 0 // both these are on same list, so we must scan it twice in order
  882. // to get VIA priority, using new #else code below.
  883. // But we are not using separate lists for TRACKs and SEGVIAs, because
  884. // items are ordered (sorted) in the linked
  885. // list by netcode AND by physical distance:
  886. // when created, if a track or via is connected to an existing track or
  887. // via, it is put in linked list after this existing track or via
  888. // So usually, connected tracks or vias are grouped in this list
  889. // So the algorithm (used in ratsnest computations) which computes the
  890. // track connectivity is faster (more than 100 time regarding to
  891. // a non ordered list) because when it searches for a connection, first
  892. // it tests the near (near in term of linked list) 50 items
  893. // from the current item (track or via) in test.
  894. // Usually, because of this sort, a connected item (if exists) is
  895. // found.
  896. // If not found (and only in this case) an exhaustive (and time
  897. // consuming) search is made, but this case is statistically rare.
  898. case PCB_VIA_T:
  899. case PCB_TRACE_T:
  900. result = IterateForward( m_Track, inspector, testData, p );
  901. // skip over any types handled in the above call.
  902. for( ; ; )
  903. {
  904. switch( stype = *++p )
  905. {
  906. case PCB_VIA_T:
  907. case PCB_TRACE_T:
  908. continue;
  909. default:
  910. ;
  911. }
  912. break;
  913. }
  914. break;
  915. #else
  916. case PCB_VIA_T:
  917. result = IterateForward( m_Track, inspector, testData, p );
  918. ++p;
  919. break;
  920. case PCB_TRACE_T:
  921. result = IterateForward( m_Track, inspector, testData, p );
  922. ++p;
  923. break;
  924. #endif
  925. case PCB_MARKER_T:
  926. // MARKER_PCBS are in the m_markers std::vector
  927. for( unsigned i = 0; i<m_markers.size(); ++i )
  928. {
  929. result = m_markers[i]->Visit( inspector, testData, p );
  930. if( result == SEARCH_QUIT )
  931. break;
  932. }
  933. ++p;
  934. break;
  935. case PCB_ZONE_AREA_T:
  936. // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
  937. for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
  938. {
  939. result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
  940. if( result == SEARCH_QUIT )
  941. break;
  942. }
  943. ++p;
  944. break;
  945. case PCB_ZONE_T:
  946. result = IterateForward( m_Zone, inspector, testData, p );
  947. ++p;
  948. break;
  949. default: // catch EOT or ANY OTHER type here and return.
  950. done = true;
  951. break;
  952. }
  953. if( result == SEARCH_QUIT )
  954. break;
  955. }
  956. return result;
  957. }
  958. /* now using PcbGeneralLocateAndDisplay(), but this remains a useful example
  959. * of how the INSPECTOR can be used in a lightweight way.
  960. * // see pcbstruct.h
  961. * BOARD_ITEM* BOARD::FindPadOrModule( const wxPoint& refPos, LAYER_NUM layer )
  962. * {
  963. * class PadOrModule : public INSPECTOR
  964. * {
  965. * public:
  966. * BOARD_ITEM* found;
  967. * LAYER_NUM layer;
  968. * int layer_mask;
  969. *
  970. * PadOrModule( LAYER_NUM alayer ) :
  971. * found(0), layer(alayer), layer_mask( g_TabOneLayerMask[alayer] )
  972. * {}
  973. *
  974. * SEARCH_RESULT Inspect( EDA_ITEM* testItem, const void* testData
  975. * )
  976. * {
  977. * BOARD_ITEM* item = (BOARD_ITEM*) testItem;
  978. * const wxPoint& refPos = *(const wxPoint*) testData;
  979. *
  980. * if( item->Type() == PCB_PAD_T )
  981. * {
  982. * D_PAD* pad = (D_PAD*) item;
  983. * if( pad->HitTest( refPos ) )
  984. * {
  985. * if( layer_mask & pad->GetLayerMask() )
  986. * {
  987. * found = item;
  988. * return SEARCH_QUIT;
  989. * }
  990. * else if( !found )
  991. * {
  992. * MODULE* parent = (MODULE*) pad->m_Parent;
  993. * if( IsModuleLayerVisible( parent->GetLayer() ) )
  994. * found = item;
  995. * }
  996. * }
  997. * }
  998. *
  999. * else if( item->Type() == PCB_MODULE_T )
  1000. * {
  1001. * MODULE* module = (MODULE*) item;
  1002. *
  1003. * // consider only visible modules
  1004. * if( IsModuleLayerVisible( module->GetLayer() ) )
  1005. * {
  1006. * if( module->HitTest( refPos ) )
  1007. * {
  1008. * if( layer == module->GetLayer() )
  1009. * {
  1010. * found = item;
  1011. * return SEARCH_QUIT;
  1012. * }
  1013. *
  1014. * // layer mismatch, save in case we don't find a
  1015. * // future layer match hit.
  1016. * if( !found )
  1017. * found = item;
  1018. * }
  1019. * }
  1020. * }
  1021. * return SEARCH_CONTINUE;
  1022. * }
  1023. * };
  1024. *
  1025. * PadOrModule inspector( layer );
  1026. *
  1027. * // search only for PADs first, then MODULES, and preferably a layer match
  1028. * static const KICAD_T scanTypes[] = { PCB_PAD_T, PCB_MODULE_T, EOT };
  1029. *
  1030. * // visit this BOARD with the above inspector
  1031. * Visit( &inspector, &refPos, scanTypes );
  1032. *
  1033. * return inspector.found;
  1034. * }
  1035. */
  1036. NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
  1037. {
  1038. // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
  1039. // zero is reserved for "no connection" and is not used.
  1040. // NULL is returned for non valid netcodes
  1041. NETINFO_ITEM* net = m_NetInfo.GetNetItem( aNetcode );
  1042. #if defined(DEBUG)
  1043. if( net && aNetcode != net->GetNet()) // item can be NULL if anetcode is not valid
  1044. {
  1045. wxLogError( wxT( "FindNet() anetcode %d != GetNet() %d (net: %s)\n" ),
  1046. aNetcode, net->GetNet(), TO_UTF8( net->GetNetname() ) );
  1047. }
  1048. #endif
  1049. return net;
  1050. }
  1051. NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
  1052. {
  1053. // the first valid netcode is 1.
  1054. // zero is reserved for "no connection" and is not used.
  1055. if( aNetname.IsEmpty() )
  1056. return NULL;
  1057. int ncount = m_NetInfo.GetNetCount();
  1058. // Search for a netname = aNetname
  1059. #if 0
  1060. // Use a sequential search: easy to understand, but slow
  1061. for( int ii = 1; ii < ncount; ii++ )
  1062. {
  1063. NETINFO_ITEM* item = m_NetInfo.GetNetItem( ii );
  1064. if( item && item->GetNetname() == aNetname )
  1065. {
  1066. return item;
  1067. }
  1068. }
  1069. #else
  1070. // Use a fast binary search,
  1071. // this is possible because Nets are alphabetically ordered in list
  1072. // see NETINFO_LIST::BuildListOfNets() and
  1073. // NETINFO_LIST::Build_Pads_Full_List()
  1074. int imax = ncount - 1;
  1075. int index = imax;
  1076. while( ncount > 0 )
  1077. {
  1078. int ii = ncount;
  1079. ncount >>= 1;
  1080. if( (ii & 1) && ( ii > 1 ) )
  1081. ncount++;
  1082. NETINFO_ITEM* item = m_NetInfo.GetNetItem( index );
  1083. if( item == NULL )
  1084. return NULL;
  1085. int icmp = item->GetNetname().Cmp( aNetname );
  1086. if( icmp == 0 ) // found !
  1087. {
  1088. return item;
  1089. }
  1090. if( icmp < 0 ) // must search after item
  1091. {
  1092. index += ncount;
  1093. if( index > imax )
  1094. index = imax;
  1095. continue;
  1096. }
  1097. if( icmp > 0 ) // must search before item
  1098. {
  1099. index -= ncount;
  1100. if( index < 1 )
  1101. index = 1;
  1102. continue;
  1103. }
  1104. }
  1105. #endif
  1106. return NULL;
  1107. }
  1108. MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
  1109. {
  1110. struct FindModule : public INSPECTOR
  1111. {
  1112. MODULE* found;
  1113. FindModule() : found( 0 ) {}
  1114. // implement interface INSPECTOR
  1115. SEARCH_RESULT Inspect( EDA_ITEM* item, const void* data )
  1116. {
  1117. MODULE* module = (MODULE*) item;
  1118. const wxString& ref = *(const wxString*) data;
  1119. if( ref == module->GetReference() )
  1120. {
  1121. found = module;
  1122. return SEARCH_QUIT;
  1123. }
  1124. return SEARCH_CONTINUE;
  1125. }
  1126. } inspector;
  1127. // search only for MODULES
  1128. static const KICAD_T scanTypes[] = { PCB_MODULE_T, EOT };
  1129. // visit this BOARD with the above inspector
  1130. BOARD* nonconstMe = (BOARD*) this;
  1131. nonconstMe->Visit( &inspector, &aReference, scanTypes );
  1132. return inspector.found;
  1133. }
  1134. MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeStamp )
  1135. {
  1136. for( MODULE* module = m_Modules; module != NULL; module = module->Next() )
  1137. {
  1138. if( aSearchByTimeStamp )
  1139. {
  1140. if( aRefOrTimeStamp.CmpNoCase( module->GetPath() ) == 0 )
  1141. return module;
  1142. }
  1143. else
  1144. {
  1145. if( aRefOrTimeStamp.CmpNoCase( module->GetReference() ) == 0 )
  1146. return module;
  1147. }
  1148. }
  1149. return NULL;
  1150. }
  1151. // Sort nets by decreasing pad count
  1152. static bool s_SortByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
  1153. {
  1154. return b->GetNodesCount() < a->GetNodesCount();
  1155. }
  1156. int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
  1157. {
  1158. if( m_NetInfo.GetNetCount() == 0 )
  1159. return 0;
  1160. // Build the list
  1161. std::vector <NETINFO_ITEM*> netBuffer;
  1162. netBuffer.reserve( m_NetInfo.GetNetCount() );
  1163. for( unsigned ii = 1; ii < m_NetInfo.GetNetCount(); ii++ )
  1164. {
  1165. if( m_NetInfo.GetNetItem( ii )->GetNet() > 0 )
  1166. netBuffer.push_back( m_NetInfo.GetNetItem( ii ) );
  1167. }
  1168. // sort the list
  1169. if( aSortbyPadsCount )
  1170. sort( netBuffer.begin(), netBuffer.end(), s_SortByNodes );
  1171. for( unsigned ii = 0; ii < netBuffer.size(); ii++ )
  1172. aNames.Add( netBuffer[ii]->GetNetname() );
  1173. return netBuffer.size();
  1174. }
  1175. void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, LAYER_NUM aLayer )
  1176. {
  1177. if( !aDC )
  1178. return;
  1179. for( int ii = 0; ii < GetAreaCount(); ii++ )
  1180. {
  1181. ZONE_CONTAINER* edge_zone = GetArea( ii );
  1182. if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
  1183. edge_zone->Draw( panel, aDC, aDrawMode );
  1184. }
  1185. }
  1186. void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, LAYER_NUM aLayer )
  1187. {
  1188. if( !aDC )
  1189. return;
  1190. for( int ii = 0; ii < GetAreaCount(); ii++ )
  1191. {
  1192. ZONE_CONTAINER* edge_zone = GetArea( ii );
  1193. if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
  1194. edge_zone->DrawFilledArea( panel, aDC, aDrawMode );
  1195. }
  1196. }
  1197. ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
  1198. LAYER_NUM aStartLayer,
  1199. LAYER_NUM aEndLayer,
  1200. int aNetCode )
  1201. {
  1202. if( aEndLayer < 0 )
  1203. aEndLayer = aStartLayer;
  1204. if( aEndLayer < aStartLayer )
  1205. EXCHG( aEndLayer, aStartLayer );
  1206. for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
  1207. {
  1208. ZONE_CONTAINER* area = m_ZoneDescriptorList[ia];
  1209. LAYER_NUM layer = area->GetLayer();
  1210. if( (layer < aStartLayer) || (layer > aEndLayer) )
  1211. continue;
  1212. // In locate functions we must skip tagged items with BUSY flag set.
  1213. if( area->GetState( BUSY ) )
  1214. continue;
  1215. if( aNetCode >= 0 && area->GetNet() != aNetCode )
  1216. continue;
  1217. if( area->HitTestFilledArea( aRefPos ) )
  1218. return area;
  1219. }
  1220. return NULL;
  1221. }
  1222. int BOARD::SetAreasNetCodesFromNetNames( void )
  1223. {
  1224. int error_count = 0;
  1225. for( int ii = 0; ii < GetAreaCount(); ii++ )
  1226. {
  1227. if( !GetArea( ii )->IsOnCopperLayer() )
  1228. {
  1229. GetArea( ii )->SetNet( 0 );
  1230. continue;
  1231. }
  1232. if( GetArea( ii )->GetNet() != 0 ) // i.e. if this zone is connected to a net
  1233. {
  1234. const NETINFO_ITEM* net = FindNet( GetArea( ii )->GetNetName() );
  1235. if( net )
  1236. {
  1237. GetArea( ii )->SetNet( net->GetNet() );
  1238. }
  1239. else
  1240. {
  1241. error_count++;
  1242. // keep Net Name and set m_NetCode to -1 : error flag.
  1243. GetArea( ii )->SetNet( -1 );
  1244. }
  1245. }
  1246. }
  1247. return error_count;
  1248. }
  1249. TRACK* BOARD::GetViaByPosition( const wxPoint& aPosition, LAYER_NUM aLayer)
  1250. {
  1251. TRACK* track;
  1252. for( track = m_Track; track; track = track->Next() )
  1253. {
  1254. if( track->Type() != PCB_VIA_T )
  1255. continue;
  1256. if( track->GetStart() != aPosition )
  1257. continue;
  1258. if( track->GetState( BUSY | IS_DELETED ) )
  1259. continue;
  1260. if( aLayer == UNDEFINED_LAYER )
  1261. break;
  1262. if( track->IsOnLayer( aLayer ) )
  1263. break;
  1264. }
  1265. return track;
  1266. }
  1267. D_PAD* BOARD::GetPad( const wxPoint& aPosition, LAYER_MSK aLayerMask )
  1268. {
  1269. D_PAD* pad = NULL;
  1270. for( MODULE* module = m_Modules; module && ( pad == NULL ); module = module->Next() )
  1271. {
  1272. if( aLayerMask )
  1273. pad = module->GetPad( aPosition, aLayerMask );
  1274. else
  1275. pad = module->GetPad( aPosition, ALL_LAYERS );
  1276. }
  1277. return pad;
  1278. }
  1279. D_PAD* BOARD::GetPad( TRACK* aTrace, int aEndPoint )
  1280. {
  1281. D_PAD* pad = NULL;
  1282. wxPoint aPosition;
  1283. LAYER_MSK aLayerMask = GetLayerMask( aTrace->GetLayer() );
  1284. if( aEndPoint == FLG_START )
  1285. {
  1286. aPosition = aTrace->GetStart();
  1287. }
  1288. else
  1289. {
  1290. aPosition = aTrace->GetEnd();
  1291. }
  1292. for( MODULE* module = m_Modules; module; module = module->Next() )
  1293. {
  1294. pad = module->GetPad( aPosition, aLayerMask );
  1295. if( pad != NULL )
  1296. break;
  1297. }
  1298. return pad;
  1299. }
  1300. D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LAYER_MSK aLayerMask )
  1301. {
  1302. for( unsigned i=0; i<GetPadCount(); ++i )
  1303. {
  1304. D_PAD* pad = m_NetInfo.GetPad(i);
  1305. if( pad->GetPosition() != aPosition )
  1306. continue;
  1307. /* Pad found, it must be on the correct layer */
  1308. if( pad->GetLayerMask() & aLayerMask )
  1309. return pad;
  1310. }
  1311. return NULL;
  1312. }
  1313. D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, LAYER_MSK aLayerMask )
  1314. {
  1315. // Search the aPoint coordinates in aPadList
  1316. // aPadList is sorted by X then Y values, and a fast binary search is used
  1317. int idxmax = aPadList.size()-1;
  1318. int delta = aPadList.size();
  1319. int idx = 0; // Starting index is the beginning of list
  1320. while( delta )
  1321. {
  1322. // Calculate half size of remaining interval to test.
  1323. // Ensure the computed value is not truncated (too small)
  1324. if( (delta & 1) && ( delta > 1 ) )
  1325. delta++;
  1326. delta /= 2;
  1327. D_PAD* pad = aPadList[idx];
  1328. if( pad->GetPosition() == aPosition ) // candidate found
  1329. {
  1330. // The pad must match the layer mask:
  1331. if( aLayerMask & pad->GetLayerMask())
  1332. return pad;
  1333. // More than one pad can be at aPosition
  1334. // search for a pad at aPosition that matched this mask
  1335. // search next
  1336. for( int ii = idx+1; ii <= idxmax; ii++ )
  1337. {
  1338. pad = aPadList[ii];
  1339. if( pad->GetPosition() != aPosition )
  1340. break;
  1341. if( (aLayerMask & pad->GetLayerMask()) != 0 )
  1342. return pad;
  1343. }
  1344. // search previous
  1345. for( int ii = idx-1 ;ii >=0; ii-- )
  1346. {
  1347. pad = aPadList[ii];
  1348. if( pad->GetPosition() != aPosition )
  1349. break;
  1350. if( (aLayerMask & pad->GetLayerMask()) != 0 )
  1351. return pad;
  1352. }
  1353. // Not found:
  1354. return 0;
  1355. }
  1356. if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
  1357. {
  1358. if(pad->GetPosition().y < aPosition.y) // Must search after this item
  1359. {
  1360. idx += delta;
  1361. if( idx > idxmax )
  1362. idx = idxmax;
  1363. }
  1364. else // Must search before this item
  1365. {
  1366. idx -= delta;
  1367. if( idx < 0 )
  1368. idx = 0;
  1369. }
  1370. }
  1371. else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
  1372. {
  1373. idx += delta;
  1374. if( idx > idxmax )
  1375. idx = idxmax;
  1376. }
  1377. else // Must search before this item
  1378. {
  1379. idx -= delta;
  1380. if( idx < 0 )
  1381. idx = 0;
  1382. }
  1383. }
  1384. return NULL;
  1385. }
  1386. /**
  1387. * Function SortPadsByXCoord
  1388. * is used by GetSortedPadListByXCoord to Sort a pad list by x coordinate value.
  1389. * This function is used to build ordered pads lists
  1390. */
  1391. bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
  1392. {
  1393. if( ref->GetPosition().x == comp->GetPosition().x )
  1394. return ref->GetPosition().y < comp->GetPosition().y;
  1395. return ref->GetPosition().x < comp->GetPosition().x;
  1396. }
  1397. void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
  1398. {
  1399. if( aNetCode < 0 )
  1400. {
  1401. aVector.insert( aVector.end(), m_NetInfo.m_PadsFullList.begin(),
  1402. m_NetInfo.m_PadsFullList.end() );
  1403. }
  1404. else
  1405. {
  1406. const NETINFO_ITEM* net = m_NetInfo.GetNetItem( aNetCode );
  1407. if( net )
  1408. {
  1409. aVector.insert( aVector.end(), net->m_PadInNetList.begin(),
  1410. net->m_PadInNetList.end() );
  1411. }
  1412. }
  1413. sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
  1414. }
  1415. TRACK* BOARD::GetTrace( TRACK* aTrace, const wxPoint& aPosition, LAYER_MSK aLayerMask )
  1416. {
  1417. for( TRACK* track = aTrace; track; track = track->Next() )
  1418. {
  1419. LAYER_NUM layer = track->GetLayer();
  1420. if( track->GetState( BUSY | IS_DELETED ) )
  1421. continue;
  1422. if( m_designSettings.IsLayerVisible( layer ) == false )
  1423. continue;
  1424. if( track->Type() == PCB_VIA_T ) /* VIA encountered. */
  1425. {
  1426. if( track->HitTest( aPosition ) )
  1427. return track;
  1428. }
  1429. else
  1430. {
  1431. if( (GetLayerMask( layer ) & aLayerMask) == 0 )
  1432. continue; /* Segments on different layers. */
  1433. if( track->HitTest( aPosition ) )
  1434. return track;
  1435. }
  1436. }
  1437. return NULL;
  1438. }
  1439. TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
  1440. double* aTraceLength, double* aPadToDieLength,
  1441. bool aReorder )
  1442. {
  1443. int NbSegmBusy;
  1444. TRACK_PTRS trackList;
  1445. if( aCount )
  1446. *aCount = 0;
  1447. if( aTraceLength )
  1448. *aTraceLength = 0;
  1449. if( aTrace == NULL )
  1450. return NULL;
  1451. // Ensure the flag BUSY of all tracks of the board is cleared
  1452. // because we use it to mark segments of the track
  1453. for( TRACK* track = m_Track; track; track = track->Next() )
  1454. track->SetState( BUSY, false );
  1455. /* Set flags of the initial track segment */
  1456. aTrace->SetState( BUSY, true );
  1457. LAYER_MSK layerMask = aTrace->GetLayerMask();
  1458. trackList.push_back( aTrace );
  1459. /* Examine the initial track segment : if it is really a segment, this is
  1460. * easy.
  1461. * If it is a via, one must search for connected segments.
  1462. * If <=2, this via connect 2 segments (or is connected to only one
  1463. * segment) and this via and these 2 segments are a part of a track.
  1464. * If > 2 only this via is flagged (the track has only this via)
  1465. */
  1466. if( aTrace->Type() == PCB_VIA_T )
  1467. {
  1468. TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
  1469. Segm1 = ::GetTrace( m_Track, NULL, aTrace->GetStart(), layerMask );
  1470. if( Segm1 )
  1471. {
  1472. Segm2 = ::GetTrace( Segm1->Next(), NULL, aTrace->GetStart(), layerMask );
  1473. }
  1474. if( Segm2 )
  1475. {
  1476. Segm3 = ::GetTrace( Segm2->Next(), NULL, aTrace->GetStart(), layerMask );
  1477. }
  1478. if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
  1479. {
  1480. if( aCount )
  1481. *aCount = 1;
  1482. return aTrace;
  1483. }
  1484. if( Segm1 ) // search for others segments connected to the initial segment start point
  1485. {
  1486. layerMask = Segm1->GetLayerMask();
  1487. chainMarkedSegments( aTrace->GetStart(), layerMask, &trackList );
  1488. }
  1489. if( Segm2 ) // search for others segments connected to the initial segment end point
  1490. {
  1491. layerMask = Segm2->GetLayerMask();
  1492. chainMarkedSegments( aTrace->GetStart(), layerMask, &trackList );
  1493. }
  1494. }
  1495. else // mark the chain using both ends of the initial segment
  1496. {
  1497. chainMarkedSegments( aTrace->GetStart(), layerMask, &trackList );
  1498. chainMarkedSegments( aTrace->GetEnd(), layerMask, &trackList );
  1499. }
  1500. // Now examine selected vias and flag them if they are on the track
  1501. // If a via is connected to only one or 2 segments, it is flagged (is on the track)
  1502. // If a via is connected to more than 2 segments, it is a track end, and it
  1503. // is removed from the list
  1504. // go through the list backwards.
  1505. for( int i = trackList.size() - 1; i>=0; --i )
  1506. {
  1507. TRACK* via = trackList[i];
  1508. if( via->Type() != PCB_VIA_T )
  1509. continue;
  1510. if( via == aTrace )
  1511. continue;
  1512. via->SetState( BUSY, true ); // Try to flag it. the flag will be cleared later if needed
  1513. layerMask = via->GetLayerMask();
  1514. TRACK* track = ::GetTrace( m_Track, NULL, via->GetStart(), layerMask );
  1515. // GetTrace does not consider tracks flagged BUSY.
  1516. // So if no connected track found, this via is on the current track
  1517. // only: keep it
  1518. if( track == NULL )
  1519. continue;
  1520. /* If a track is found, this via connects also others segments of an
  1521. * other track. This case happens when the vias ends the selected
  1522. * track but must we consider this via is on the selected track, or
  1523. * on an other track.
  1524. * (this is important when selecting a track for deletion: must this
  1525. * via be deleted or not?)
  1526. * We consider here this via on the track if others segment connected
  1527. * to this via remain connected when removing this via.
  1528. * We search for all others segment connected together:
  1529. * if there are on the same layer, the via is on the selected track
  1530. * if there are on different layers, the via is on an other track
  1531. */
  1532. LAYER_NUM layer = track->GetLayer();
  1533. while( ( track = ::GetTrace( track->Next(), NULL, via->GetStart(), layerMask ) ) != NULL )
  1534. {
  1535. if( layer != track->GetLayer() )
  1536. {
  1537. // The via connects segments of an other track: it is removed
  1538. // from list because it is member of an other track
  1539. via->SetState( BUSY, false );
  1540. break;
  1541. }
  1542. }
  1543. }
  1544. /* Rearrange the track list in order to have flagged segments linked
  1545. * from firstTrack so the NbSegmBusy segments are consecutive segments
  1546. * in list, the first item in the full track list is firstTrack, and
  1547. * the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
  1548. * are the flagged segments
  1549. */
  1550. NbSegmBusy = 0;
  1551. TRACK* firstTrack;
  1552. for( firstTrack = m_Track; firstTrack; firstTrack = firstTrack->Next() )
  1553. {
  1554. // Search for the first flagged BUSY segments
  1555. if( firstTrack->GetState( BUSY ) )
  1556. {
  1557. NbSegmBusy = 1;
  1558. break;
  1559. }
  1560. }
  1561. if( firstTrack == NULL )
  1562. return NULL;
  1563. double full_len = 0;
  1564. double lenPadToDie = 0;
  1565. if( aReorder )
  1566. {
  1567. DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
  1568. wxASSERT( list );
  1569. /* Rearrange the chain starting at firstTrack
  1570. * All others flagged items are moved from their position to the end
  1571. * of the flagged list
  1572. */
  1573. TRACK* next;
  1574. for( TRACK* track = firstTrack->Next(); track; track = next )
  1575. {
  1576. next = track->Next();
  1577. if( track->GetState( BUSY ) ) // move it!
  1578. {
  1579. NbSegmBusy++;
  1580. track->UnLink();
  1581. list->Insert( track, firstTrack->Next() );
  1582. if( aTraceLength )
  1583. full_len += track->GetLength();
  1584. if( aPadToDieLength ) // Add now length die.
  1585. {
  1586. // In fact only 2 pads (maximum) will be taken in account:
  1587. // that are on each end of the track, if any
  1588. if( track->GetState( BEGIN_ONPAD ) )
  1589. {
  1590. D_PAD * pad = (D_PAD *) track->start;
  1591. lenPadToDie += (double) pad->GetPadToDieLength();
  1592. }
  1593. if( track->GetState( END_ONPAD ) )
  1594. {
  1595. D_PAD * pad = (D_PAD *) track->end;
  1596. lenPadToDie += (double) pad->GetPadToDieLength();
  1597. }
  1598. }
  1599. }
  1600. }
  1601. }
  1602. else if( aTraceLength )
  1603. {
  1604. NbSegmBusy = 0;
  1605. for( TRACK* track = firstTrack; track; track = track->Next() )
  1606. {
  1607. if( track->GetState( BUSY ) )
  1608. {
  1609. NbSegmBusy++;
  1610. track->SetState( BUSY, false );
  1611. full_len += track->GetLength();
  1612. // Add now length die.
  1613. // In fact only 2 pads (maximum) will be taken in account:
  1614. // that are on each end of the track, if any
  1615. if( track->GetState( BEGIN_ONPAD ) )
  1616. {
  1617. D_PAD * pad = (D_PAD *) track->start;
  1618. lenPadToDie += (double) pad->GetPadToDieLength();
  1619. }
  1620. if( track->GetState( END_ONPAD ) )
  1621. {
  1622. D_PAD * pad = (D_PAD *) track->end;
  1623. lenPadToDie += (double) pad->GetPadToDieLength();
  1624. }
  1625. }
  1626. }
  1627. }
  1628. if( aTraceLength )
  1629. *aTraceLength = KiROUND( full_len );
  1630. if( aPadToDieLength )
  1631. *aPadToDieLength = KiROUND( lenPadToDie );
  1632. if( aCount )
  1633. *aCount = NbSegmBusy;
  1634. return firstTrack;
  1635. }
  1636. MODULE* BOARD::GetFootprint( const wxPoint& aPosition, LAYER_NUM aActiveLayer,
  1637. bool aVisibleOnly, bool aIgnoreLocked )
  1638. {
  1639. MODULE* pt_module;
  1640. MODULE* module = NULL;
  1641. MODULE* alt_module = NULL;
  1642. int min_dim = 0x7FFFFFFF;
  1643. int alt_min_dim = 0x7FFFFFFF;
  1644. bool current_layer_back = IsBackLayer( aActiveLayer );
  1645. for( pt_module = m_Modules; pt_module; pt_module = (MODULE*) pt_module->Next() )
  1646. {
  1647. // is the ref point within the module's bounds?
  1648. if( !pt_module->HitTest( aPosition ) )
  1649. continue;
  1650. // if caller wants to ignore locked modules, and this one is locked, skip it.
  1651. if( aIgnoreLocked && pt_module->IsLocked() )
  1652. continue;
  1653. LAYER_NUM layer = pt_module->GetLayer();
  1654. // Filter non visible modules if requested
  1655. if( (!aVisibleOnly) || IsModuleLayerVisible( layer ) )
  1656. {
  1657. EDA_RECT bb = pt_module->GetFootPrintRect();
  1658. int offx = bb.GetX() + bb.GetWidth() / 2;
  1659. int offy = bb.GetY() + bb.GetHeight() / 2;
  1660. // off x & offy point to the middle of the box.
  1661. int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
  1662. ( aPosition.y - offy ) * ( aPosition.y - offy );
  1663. if( current_layer_back == IsBackLayer( layer ) )
  1664. {
  1665. if( dist <= min_dim )
  1666. {
  1667. // better footprint shown on the active side
  1668. module = pt_module;
  1669. min_dim = dist;
  1670. }
  1671. }
  1672. else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
  1673. {
  1674. if( dist <= alt_min_dim )
  1675. {
  1676. // better footprint shown on the other side
  1677. alt_module = pt_module;
  1678. alt_min_dim = dist;
  1679. }
  1680. }
  1681. }
  1682. }
  1683. if( module )
  1684. {
  1685. return module;
  1686. }
  1687. if( alt_module)
  1688. {
  1689. return alt_module;
  1690. }
  1691. return NULL;
  1692. }
  1693. BOARD_CONNECTED_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, LAYER_MSK aLayerMask )
  1694. {
  1695. for( MODULE* module = m_Modules; module; module = module->Next() )
  1696. {
  1697. D_PAD* pad = module->GetPad( aPosition, aLayerMask );
  1698. if( pad )
  1699. return pad;
  1700. }
  1701. /* No pad has been located so check for a segment of the trace. */
  1702. TRACK* segment = ::GetTrace( m_Track, NULL, aPosition, aLayerMask );
  1703. if( segment == NULL )
  1704. segment = GetTrace( m_Track, aPosition, aLayerMask );
  1705. return segment;
  1706. }
  1707. TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList )
  1708. {
  1709. /* creates an intermediate point on aSegment and break it into two segments
  1710. * at aPosition.
  1711. * The new segment starts from aPosition and ends at the end point of
  1712. * aSegment. The original segment now ends at aPosition.
  1713. */
  1714. if( aSegment->GetStart() == aPosition || aSegment->GetEnd() == aPosition )
  1715. return NULL;
  1716. /* A via is a good lock point */
  1717. if( aSegment->Type() == PCB_VIA_T )
  1718. {
  1719. aPosition = aSegment->GetStart();
  1720. return aSegment;
  1721. }
  1722. // Calculation coordinate of intermediate point relative to the start point of aSegment
  1723. wxPoint delta = aSegment->GetEnd() - aSegment->GetStart();
  1724. // calculate coordinates of aPosition relative to aSegment->GetStart()
  1725. wxPoint lockPoint = aPosition - aSegment->GetStart();
  1726. // lockPoint must be on aSegment:
  1727. // Ensure lockPoint.y/lockPoint.y = delta.y/delta.x
  1728. if( delta.x == 0 )
  1729. lockPoint.x = 0; /* horizontal segment*/
  1730. else
  1731. lockPoint.y = KiROUND( ( (double)lockPoint.x * delta.y ) / delta.x );
  1732. /* Create the intermediate point (that is to say creation of a new
  1733. * segment, beginning at the intermediate point.
  1734. */
  1735. lockPoint += aSegment->GetStart();
  1736. TRACK* newTrack = (TRACK*)aSegment->Clone();
  1737. // The new segment begins at the new point,
  1738. newTrack->SetStart(lockPoint);
  1739. newTrack->start = aSegment;
  1740. newTrack->SetState( BEGIN_ONPAD, false );
  1741. DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
  1742. wxASSERT( list );
  1743. list->Insert( newTrack, aSegment->Next() );
  1744. if( aList )
  1745. {
  1746. // Prepare the undo command for the now track segment
  1747. ITEM_PICKER picker( newTrack, UR_NEW );
  1748. aList->PushItem( picker );
  1749. // Prepare the undo command for the old track segment
  1750. // before modifications
  1751. picker.SetItem( aSegment );
  1752. picker.SetStatus( UR_CHANGED );
  1753. picker.SetLink( aSegment->Clone() );
  1754. aList->PushItem( picker );
  1755. }
  1756. // Old track segment now ends at new point.
  1757. aSegment->SetEnd(lockPoint);
  1758. aSegment->end = newTrack;
  1759. aSegment->SetState( END_ONPAD, false );
  1760. D_PAD * pad = GetPad( newTrack, FLG_START );
  1761. if ( pad )
  1762. {
  1763. newTrack->start = pad;
  1764. newTrack->SetState( BEGIN_ONPAD, true );
  1765. aSegment->end = pad;
  1766. aSegment->SetState( END_ONPAD, true );
  1767. }
  1768. aPosition = lockPoint;
  1769. return newTrack;
  1770. }
  1771. void BOARD::SetViaSizeIndex( unsigned aIndex )
  1772. {
  1773. if( aIndex >= m_ViasDimensionsList.size() )
  1774. m_viaSizeIndex = m_ViasDimensionsList.size();
  1775. else
  1776. m_viaSizeIndex = aIndex;
  1777. }
  1778. void BOARD::SetTrackWidthIndex( unsigned aIndex )
  1779. {
  1780. if( aIndex >= m_TrackWidthList.size() )
  1781. m_trackWidthIndex = m_TrackWidthList.size();
  1782. else
  1783. m_trackWidthIndex = aIndex;
  1784. }
  1785. ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
  1786. LAYER_NUM aLayer, wxPoint aStartPointPosition, int aHatch )
  1787. {
  1788. ZONE_CONTAINER* new_area = InsertArea( aNetcode,
  1789. m_ZoneDescriptorList.size( ) - 1,
  1790. aLayer, aStartPointPosition.x,
  1791. aStartPointPosition.y, aHatch );
  1792. if( aNewZonesList )
  1793. {
  1794. ITEM_PICKER picker( new_area, UR_NEW );
  1795. aNewZonesList->PushItem( picker );
  1796. }
  1797. return new_area;
  1798. }
  1799. void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
  1800. {
  1801. if( area_to_remove == NULL )
  1802. return;
  1803. if( aDeletedList )
  1804. {
  1805. ITEM_PICKER picker( area_to_remove, UR_DELETED );
  1806. aDeletedList->PushItem( picker );
  1807. Remove( area_to_remove ); // remove from zone list, but does not delete it
  1808. }
  1809. else
  1810. {
  1811. Delete( area_to_remove );
  1812. }
  1813. }
  1814. ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, LAYER_NUM layer, int x, int y, int hatch )
  1815. {
  1816. ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
  1817. new_area->SetNet( netcode );
  1818. new_area->SetLayer( layer );
  1819. new_area->SetTimeStamp( GetNewTimeStamp() );
  1820. if( iarea < (int) ( m_ZoneDescriptorList.size() - 1 ) )
  1821. m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + iarea + 1, new_area );
  1822. else
  1823. m_ZoneDescriptorList.push_back( new_area );
  1824. new_area->Outline()->Start( layer, x, y, hatch );
  1825. return new_area;
  1826. }
  1827. bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE_CONTAINER* aCurrArea )
  1828. {
  1829. CPolyLine* curr_polygon = aCurrArea->Outline();
  1830. // mark all areas as unmodified except this one, if modified
  1831. for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
  1832. m_ZoneDescriptorList[ia]->SetLocalFlags( 0 );
  1833. aCurrArea->SetLocalFlags( 1 );
  1834. if( curr_polygon->IsPolygonSelfIntersecting() )
  1835. {
  1836. std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>;
  1837. curr_polygon->UnHatch();
  1838. int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines( pa );
  1839. // If clipping has created some polygons, we must add these new copper areas.
  1840. if( n_poly > 1 )
  1841. {
  1842. ZONE_CONTAINER* NewArea;
  1843. for( int ip = 1; ip < n_poly; ip++ )
  1844. {
  1845. // create new copper area and copy poly into it
  1846. CPolyLine* new_p = (*pa)[ip - 1];
  1847. NewArea = AddArea( aNewZonesList, aCurrArea->GetNet(), aCurrArea->GetLayer(),
  1848. wxPoint(0, 0), CPolyLine::NO_HATCH );
  1849. // remove the poly that was automatically created for the new area
  1850. // and replace it with a poly from NormalizeAreaOutlines
  1851. delete NewArea->Outline();
  1852. NewArea->SetOutline( new_p );
  1853. NewArea->Outline()->Hatch();
  1854. NewArea->SetLocalFlags( 1 );
  1855. }
  1856. }
  1857. delete pa;
  1858. }
  1859. curr_polygon->Hatch();
  1860. return true;
  1861. }
  1862. void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
  1863. REPORTER* aReporter )
  1864. {
  1865. unsigned i;
  1866. wxPoint bestPosition;
  1867. wxString msg;
  1868. D_PAD* pad;
  1869. MODULE* footprint;
  1870. COMPONENT_NET net;
  1871. if( !IsEmpty() )
  1872. {
  1873. // Position new components below any existing board features.
  1874. EDA_RECT bbbox = ComputeBoundingBox( true );
  1875. if( bbbox.GetWidth() || bbbox.GetHeight() )
  1876. {
  1877. bestPosition.x = bbbox.Centre().x;
  1878. bestPosition.y = bbbox.GetBottom() + Millimeter2iu( 10 );
  1879. }
  1880. }
  1881. else
  1882. {
  1883. // Position new components in the center of the page when the board is empty.
  1884. wxSize pageSize = m_paper.GetSizeIU();
  1885. bestPosition.x = pageSize.GetWidth() / 2;
  1886. bestPosition.y = pageSize.GetHeight() / 2;
  1887. }
  1888. m_Status_Pcb = 0;
  1889. for( i = 0; i < aNetlist.GetCount(); i++ )
  1890. {
  1891. COMPONENT* component = aNetlist.GetComponent( i );
  1892. if( aReporter && aReporter->ReportAll() )
  1893. {
  1894. msg.Printf( _( "Checking netlist component footprint \"%s:%s:%s\".\n" ),
  1895. GetChars( component->GetReference() ),
  1896. GetChars( component->GetTimeStamp() ),
  1897. GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
  1898. aReporter->Report( msg );
  1899. }
  1900. if( aNetlist.IsFindByTimeStamp() )
  1901. footprint = FindModule( aNetlist.GetComponent( i )->GetTimeStamp(), true );
  1902. else
  1903. footprint = FindModule( aNetlist.GetComponent( i )->GetReference() );
  1904. if( footprint == NULL ) // A new footprint.
  1905. {
  1906. if( aReporter )
  1907. {
  1908. if( component->GetModule() != NULL )
  1909. {
  1910. msg.Printf( _( "Adding new component \"%s:%s\" footprint \"%s\".\n" ),
  1911. GetChars( component->GetReference() ),
  1912. GetChars( component->GetTimeStamp() ),
  1913. GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
  1914. if( aReporter->ReportWarnings() )
  1915. aReporter->Report( msg );
  1916. }
  1917. else
  1918. {
  1919. msg.Printf( _( "Cannot add new component \"%s:%s\" due to missing "
  1920. "footprint \"%s\".\n" ),
  1921. GetChars( component->GetReference() ),
  1922. GetChars( component->GetTimeStamp() ),
  1923. GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
  1924. if( aReporter->ReportErrors() )
  1925. aReporter->Report( msg );
  1926. }
  1927. }
  1928. if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
  1929. {
  1930. // Owned by NETLIST, can only copy it.
  1931. footprint = new MODULE( *component->GetModule() );
  1932. footprint->SetParent( this );
  1933. footprint->SetPosition( bestPosition );
  1934. footprint->SetTimeStamp( GetNewTimeStamp() );
  1935. Add( footprint, ADD_APPEND );
  1936. }
  1937. }
  1938. else // An existing footprint.
  1939. {
  1940. // Test for footprint change.
  1941. if( !component->GetFPID().empty() &&
  1942. footprint->GetFPID() != component->GetFPID() )
  1943. {
  1944. if( aNetlist.GetReplaceFootprints() )
  1945. {
  1946. if( aReporter )
  1947. {
  1948. if( component->GetModule() != NULL )
  1949. {
  1950. msg.Printf( _( "Replacing component \"%s:%s\" footprint \"%s\" with "
  1951. "\"%s\".\n" ),
  1952. GetChars( footprint->GetReference() ),
  1953. GetChars( footprint->GetPath() ),
  1954. GetChars( FROM_UTF8( footprint->GetFPID().Format().c_str() ) ),
  1955. GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
  1956. if( aReporter->ReportWarnings() )
  1957. aReporter->Report( msg );
  1958. }
  1959. else
  1960. {
  1961. msg.Printf( _( "Cannot replace component \"%s:%s\" due to missing "
  1962. "footprint \"%s\".\n" ),
  1963. GetChars( footprint->GetReference() ),
  1964. GetChars( footprint->GetPath() ),
  1965. GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
  1966. if( aReporter->ReportErrors() )
  1967. aReporter->Report( msg );
  1968. }
  1969. }
  1970. if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
  1971. {
  1972. wxASSERT( footprint != NULL );
  1973. MODULE* newFootprint = new MODULE( *component->GetModule() );
  1974. if( aNetlist.IsFindByTimeStamp() )
  1975. newFootprint->SetReference( footprint->GetReference() );
  1976. else
  1977. newFootprint->SetPath( footprint->GetPath() );
  1978. footprint->CopyNetlistSettings( newFootprint );
  1979. Remove( footprint );
  1980. Add( newFootprint, ADD_APPEND );
  1981. footprint = newFootprint;
  1982. }
  1983. }
  1984. }
  1985. // Test for reference designator field change.
  1986. if( footprint->GetReference() != component->GetReference() )
  1987. {
  1988. if( aReporter && aReporter->ReportWarnings())
  1989. {
  1990. msg.Printf( _( "Changing footprint \"%s:%s\" reference to \"%s\".\n" ),
  1991. GetChars( footprint->GetReference() ),
  1992. GetChars( footprint->GetPath() ),
  1993. GetChars( component->GetReference() ) );
  1994. aReporter->Report( msg );
  1995. }
  1996. if( !aNetlist.IsDryRun() )
  1997. footprint->SetReference( component->GetReference() );
  1998. }
  1999. // Test for value field change.
  2000. if( footprint->GetValue() != component->GetValue() )
  2001. {
  2002. if( aReporter && aReporter->ReportAll() )
  2003. {
  2004. msg.Printf( _( "Changing footprint \"%s:%s\" value from \"%s\" to \"%s\".\n" ),
  2005. GetChars( footprint->GetReference() ),
  2006. GetChars( footprint->GetPath() ),
  2007. GetChars( footprint->GetValue() ),
  2008. GetChars( component->GetValue() ) );
  2009. aReporter->Report( msg );
  2010. }
  2011. if( !aNetlist.IsDryRun() )
  2012. footprint->SetValue( component->GetValue() );
  2013. }
  2014. // Test for time stamp change.
  2015. if( footprint->GetPath() != component->GetTimeStamp() )
  2016. {
  2017. if( aReporter && aReporter->ReportWarnings() )
  2018. {
  2019. msg.Printf( _( "Changing footprint path \"%s:%s\" to \"%s\".\n" ),
  2020. GetChars( footprint->GetReference() ),
  2021. GetChars( footprint->GetPath() ),
  2022. GetChars( component->GetTimeStamp() ) );
  2023. aReporter->Report( msg );
  2024. }
  2025. if( !aNetlist.IsDryRun() )
  2026. footprint->SetPath( component->GetTimeStamp() );
  2027. }
  2028. }
  2029. if( footprint == NULL )
  2030. continue;
  2031. // At this point, the component footprint is updated. Now update the nets.
  2032. for( pad = footprint->Pads(); pad; pad = pad->Next() )
  2033. {
  2034. net = component->GetNet( pad->GetPadName() );
  2035. if( !net.IsValid() ) // Footprint pad had no net.
  2036. {
  2037. if( !pad->GetNetname().IsEmpty() )
  2038. {
  2039. if( aReporter && aReporter->ReportAll() )
  2040. {
  2041. msg.Printf( _( "Clearing component \"%s:%s\" pin \"%s\" net name.\n" ),
  2042. GetChars( footprint->GetReference() ),
  2043. GetChars( footprint->GetPath() ),
  2044. GetChars( pad->GetPadName() ) );
  2045. aReporter->Report( msg );
  2046. }
  2047. if( !aNetlist.IsDryRun() )
  2048. pad->SetNetname( wxEmptyString );
  2049. }
  2050. }
  2051. else // Footprint pad has a net.
  2052. {
  2053. if( net.GetNetName() != pad->GetNetname() )
  2054. {
  2055. if( aReporter && aReporter->ReportAll() )
  2056. {
  2057. msg.Printf( _( "Changing component \"%s:%s\" pin \"%s\" net name from "
  2058. "\"%s\" to \"%s\".\n" ),
  2059. GetChars( footprint->GetReference() ),
  2060. GetChars( footprint->GetPath() ),
  2061. GetChars( pad->GetPadName() ),
  2062. GetChars( pad->GetNetname() ),
  2063. GetChars( net.GetNetName() ) );
  2064. aReporter->Report( msg );
  2065. }
  2066. if( !aNetlist.IsDryRun() )
  2067. pad->SetNetname( net.GetNetName() );
  2068. }
  2069. }
  2070. }
  2071. }
  2072. // Remove all components not in the netlist.
  2073. if( aNetlist.GetDeleteExtraFootprints() )
  2074. {
  2075. MODULE* nextModule;
  2076. const COMPONENT* component;
  2077. for( MODULE* module = m_Modules; module != NULL; module = nextModule )
  2078. {
  2079. nextModule = module->Next();
  2080. if( module->IsLocked() )
  2081. continue;
  2082. if( aNetlist.IsFindByTimeStamp() )
  2083. component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
  2084. else
  2085. component = aNetlist.GetComponentByReference( module->GetReference() );
  2086. if( component == NULL )
  2087. {
  2088. if( aReporter && aReporter->ReportWarnings() )
  2089. {
  2090. msg.Printf( _( "Removing footprint \"%s:%s\".\n" ),
  2091. GetChars( module->GetReference() ),
  2092. GetChars( module->GetPath() ) );
  2093. aReporter->Report( msg );
  2094. }
  2095. if( !aNetlist.IsDryRun() )
  2096. module->DeleteStructure();
  2097. }
  2098. }
  2099. }
  2100. // If needed, remove the single pad nets:
  2101. if( aDeleteSinglePadNets && !aNetlist.IsDryRun() )
  2102. {
  2103. BuildListOfNets();
  2104. std::vector<D_PAD*> padlist = GetPads();
  2105. // padlist is the list of pads, sorted by netname.
  2106. int count = 0;
  2107. wxString netname;
  2108. D_PAD * pad = NULL;
  2109. D_PAD * previouspad = NULL;
  2110. for( unsigned ii = 0; ii < padlist.size(); ii++ )
  2111. {
  2112. pad = padlist[ii];
  2113. if( pad->GetNetname().IsEmpty() )
  2114. continue;
  2115. if( netname != pad->GetNetname() ) // End of net
  2116. {
  2117. if( previouspad && count == 1 )
  2118. {
  2119. if( aReporter && aReporter->ReportAll() )
  2120. {
  2121. msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad <%s>\n" ),
  2122. GetChars( pad->GetNetname() ),
  2123. GetChars( pad->GetParent()->GetReference() ),
  2124. GetChars( previouspad->GetPadName() ) );
  2125. aReporter->Report( msg );
  2126. }
  2127. previouspad->SetNetname( wxEmptyString );
  2128. }
  2129. netname = pad->GetNetname();
  2130. count = 1;
  2131. }
  2132. else
  2133. count++;
  2134. previouspad = pad;
  2135. }
  2136. // Examine last pad
  2137. if( pad && count == 1 )
  2138. pad->SetNetname( wxEmptyString );
  2139. }
  2140. // Last step: Some tests:
  2141. // verify all pads found in netlist:
  2142. // They should exist in footprints, otherwise the footprint is wrong
  2143. // note also references or time stamps are updated, so we use only
  2144. // the reference to find a footprint
  2145. if( aReporter && aReporter->ReportErrors() )
  2146. {
  2147. wxString padname;
  2148. for( i = 0; i < aNetlist.GetCount(); i++ )
  2149. {
  2150. const COMPONENT* component = aNetlist.GetComponent( i );
  2151. MODULE* footprint = FindModuleByReference( component->GetReference() );
  2152. if( footprint == NULL ) // It can be missing in partial designs
  2153. continue;
  2154. // Explore all pins/pads in component
  2155. for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
  2156. {
  2157. net = component->GetNet( jj );
  2158. padname = net.GetPinName();
  2159. if( footprint->FindPadByName( padname ) )
  2160. continue; // OK, pad found
  2161. // not found: bad footprint, report error
  2162. msg.Printf( _( "** Error: Component \"%s\" pad <%s> not found in footprint \"%s\" **\n" ),
  2163. GetChars( component->GetReference() ),
  2164. GetChars( padname ),
  2165. footprint->GetFPID().Format().c_str() );
  2166. aReporter->Report( msg );
  2167. }
  2168. }
  2169. }
  2170. // Verify zone net names validity:
  2171. // After schematic changes, a zone can have a non existing net name.
  2172. // It should be reported
  2173. if( aReporter && aReporter->ReportErrors() )
  2174. {
  2175. //Loop through all copper zones
  2176. for( i = 0; i < m_ZoneDescriptorList.size(); i++ )
  2177. {
  2178. ZONE_CONTAINER* zone = m_ZoneDescriptorList[i];
  2179. if( zone->GetNet() >= 0 || !zone->IsOnCopperLayer() )
  2180. continue;
  2181. // Net name not valid, report error
  2182. wxString coord;
  2183. coord << zone->GetPosition();
  2184. msg.Printf( _( "** Error: Zone %s layer <%s>"
  2185. " has non-existent net name \"%s\" **\n" ),
  2186. GetChars( coord ),
  2187. GetChars( zone->GetLayerName() ),
  2188. GetChars( zone->GetNetName() ) );
  2189. aReporter->Report( msg );
  2190. }
  2191. }
  2192. }