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.

871 lines
22 KiB

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
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
++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
// 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
18 years ago
14 years ago
19 years ago
19 years ago
14 years ago
18 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
18 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
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
14 years ago
18 years ago
18 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
  5. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file class_pad.cpp
  27. * D_PAD class implementation.
  28. */
  29. #include <fctsys.h>
  30. #include <PolyLine.h>
  31. #include <common.h>
  32. #include <confirm.h>
  33. #include <kicad_string.h>
  34. #include <trigo.h>
  35. #include <protos.h>
  36. #include <richio.h>
  37. #include <wxstruct.h>
  38. #include <macros.h>
  39. #include <pcbnew.h>
  40. #include <pcbnew_id.h> // ID_TRACK_BUTT
  41. #include <class_board.h>
  42. #include <class_module.h>
  43. #include <polygon_test_point_inside.h>
  44. #include <convert_from_iu.h>
  45. int D_PAD::m_PadSketchModePenSize = 0; // Pen size used to draw pads in sketch mode
  46. D_PAD::D_PAD( MODULE* parent ) :
  47. BOARD_CONNECTED_ITEM( parent, PCB_PAD_T )
  48. {
  49. m_NumPadName = 0;
  50. m_Size.x = m_Size.y = 500; // give it a reasonable size
  51. m_Orient = 0; // Pad rotation in 1/10 degrees
  52. m_LengthDie = 0;
  53. if( m_Parent && m_Parent->Type() == PCB_MODULE_T )
  54. {
  55. m_Pos = GetParent()->GetPosition();
  56. }
  57. m_PadShape = PAD_CIRCLE; // Shape: PAD_CIRCLE, PAD_RECT PAD_OVAL
  58. // PAD_TRAPEZOID
  59. m_Attribute = PAD_STANDARD; // Type: NORMAL, PAD_SMD, PAD_CONN
  60. m_DrillShape = PAD_CIRCLE; // Drill shape = circle
  61. m_LocalClearance = 0;
  62. m_LocalSolderMaskMargin = 0;
  63. m_LocalSolderPasteMargin = 0;
  64. m_LocalSolderPasteMarginRatio = 0.0;
  65. m_ZoneConnection = UNDEFINED_CONNECTION; // Use parent setting by default
  66. m_ThermalWidth = 0; // Use parent setting by default
  67. m_ThermalGap = 0; // Use parent setting by default
  68. // set layers mask to default for a standard pad
  69. m_layerMask = PAD_STANDARD_DEFAULT_LAYERS;
  70. SetSubRatsnest( 0 ); // used in ratsnest calculations
  71. m_boundingRadius = -1;
  72. }
  73. int D_PAD::boundingRadius() const
  74. {
  75. int x, y;
  76. int radius;
  77. switch( GetShape() )
  78. {
  79. case PAD_CIRCLE:
  80. radius = m_Size.x / 2;
  81. break;
  82. case PAD_OVAL:
  83. radius = std::max( m_Size.x, m_Size.y ) / 2;
  84. break;
  85. case PAD_RECT:
  86. radius = 1 + (int) ( sqrt( (double) m_Size.y * m_Size.y
  87. + (double) m_Size.x * m_Size.x ) / 2 );
  88. break;
  89. case PAD_TRAPEZOID:
  90. x = m_Size.x + std::abs( m_DeltaSize.y ); // Remember: m_DeltaSize.y is the m_Size.x change
  91. y = m_Size.y + std::abs( m_DeltaSize.x ); // Remember: m_DeltaSize.x is the m_Size.y change
  92. radius = 1 + (int) ( sqrt( (double) y * y + (double) x * x ) / 2 );
  93. break;
  94. default:
  95. radius = 0;
  96. }
  97. return radius;
  98. }
  99. EDA_RECT D_PAD::GetBoundingBox() const
  100. {
  101. EDA_RECT area;
  102. // radius of pad area, enclosed in minimum sized circle
  103. int radius = boundingRadius();
  104. area.SetOrigin( m_Pos );
  105. area.Inflate( radius );
  106. return area;
  107. }
  108. void D_PAD::SetOrientation( double aAngle )
  109. {
  110. NORMALIZE_ANGLE_POS( aAngle );
  111. m_Orient = aAngle;
  112. }
  113. void D_PAD::Flip( int aTranslationY )
  114. {
  115. int y = GetPosition().y - aTranslationY;
  116. y = -y; // invert about x axis.
  117. y += aTranslationY;
  118. SetY( y );
  119. NEGATE( m_Pos0.y );
  120. NEGATE( m_Offset.y );
  121. NEGATE( m_DeltaSize.y );
  122. SetOrientation( -GetOrientation() );
  123. // flip pads layers
  124. SetLayerMask( ChangeSideMaskLayer( m_layerMask ) );
  125. // m_boundingRadius = -1; the shape has not been changed
  126. }
  127. void D_PAD::AppendConfigs( PARAM_CFG_ARRAY* aResult )
  128. {
  129. aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadDrill" ),
  130. &m_Drill.x,
  131. Millimeter2iu( 0.6 ),
  132. Millimeter2iu( 0.1 ), Millimeter2iu( 10.0 ),
  133. NULL, MM_PER_IU ) );
  134. aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeH" ),
  135. &m_Size.x,
  136. Millimeter2iu( 1.4 ),
  137. Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
  138. NULL, MM_PER_IU ) );
  139. aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeV" ),
  140. &m_Size.y,
  141. Millimeter2iu( 1.4 ),
  142. Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
  143. NULL, MM_PER_IU ) );
  144. }
  145. // Returns the position of the pad.
  146. const wxPoint D_PAD::ReturnShapePos() const
  147. {
  148. if( m_Offset.x == 0 && m_Offset.y == 0 )
  149. return m_Pos;
  150. wxPoint shape_pos;
  151. int dX, dY;
  152. dX = m_Offset.x;
  153. dY = m_Offset.y;
  154. RotatePoint( &dX, &dY, m_Orient );
  155. shape_pos.x = m_Pos.x + dX;
  156. shape_pos.y = m_Pos.y + dY;
  157. return shape_pos;
  158. }
  159. const wxString D_PAD::GetPadName() const
  160. {
  161. #if 0 // m_Padname is not ASCII and not UTF8, it is LATIN1 basically, whatever
  162. // 8 bit font is supported in KiCad plotting and drawing.
  163. // Return pad name as wxString, assume it starts as a non-terminated
  164. // utf8 character sequence
  165. char temp[sizeof(m_Padname)+1]; // a place to terminate with '\0'
  166. strncpy( temp, m_Padname, sizeof(m_Padname) );
  167. temp[sizeof(m_Padname)] = 0;
  168. return FROM_UTF8( temp );
  169. #else
  170. wxString name;
  171. ReturnStringPadName( name );
  172. return name;
  173. #endif
  174. }
  175. void D_PAD::ReturnStringPadName( wxString& text ) const
  176. {
  177. #if 0 // m_Padname is not ASCII and not UTF8, it is LATIN1 basically, whatever
  178. // 8 bit font is supported in KiCad plotting and drawing.
  179. // Return pad name as wxString, assume it starts as a non-terminated
  180. // utf8 character sequence
  181. char temp[sizeof(m_Padname)+1]; // a place to terminate with '\0'
  182. strncpy( temp, m_Padname, sizeof(m_Padname) );
  183. temp[sizeof(m_Padname)] = 0;
  184. text = FROM_UTF8( temp );
  185. #else
  186. text.Empty();
  187. for( int ii = 0; ii < PADNAMEZ && m_Padname[ii]; ii++ )
  188. {
  189. // m_Padname is 8 bit KiCad font junk, do not sign extend
  190. text.Append( (unsigned char) m_Padname[ii] );
  191. }
  192. #endif
  193. }
  194. // Change pad name
  195. void D_PAD::SetPadName( const wxString& name )
  196. {
  197. int ii, len;
  198. len = name.Length();
  199. if( len > PADNAMEZ )
  200. len = PADNAMEZ;
  201. // m_Padname[] is not UTF8, it is an 8 bit character that matches the KiCad font,
  202. // so only copy the lower 8 bits of each character.
  203. for( ii = 0; ii < len; ii++ )
  204. m_Padname[ii] = (char) name.GetChar( ii );
  205. for( ii = len; ii < PADNAMEZ; ii++ )
  206. m_Padname[ii] = '\0';
  207. }
  208. /**
  209. * Function SetNetname
  210. * @param aNetname: the new netname
  211. */
  212. void D_PAD::SetNetname( const wxString& aNetname )
  213. {
  214. m_Netname = aNetname;
  215. m_ShortNetname = m_Netname.AfterLast( '/' );
  216. }
  217. void D_PAD::Copy( D_PAD* source )
  218. {
  219. if( source == NULL )
  220. return;
  221. m_Pos = source->m_Pos;
  222. m_layerMask = source->m_layerMask;
  223. m_NumPadName = source->m_NumPadName;
  224. SetNet( source->GetNet() );
  225. m_Drill = source->m_Drill;
  226. m_DrillShape = source->m_DrillShape;
  227. m_Offset = source->m_Offset;
  228. m_Size = source->m_Size;
  229. m_DeltaSize = source->m_DeltaSize;
  230. m_Pos0 = source->m_Pos0;
  231. m_boundingRadius = source->m_boundingRadius;
  232. m_PadShape = source->m_PadShape;
  233. m_Attribute = source->m_Attribute;
  234. m_Orient = source->m_Orient;
  235. m_LengthDie = source->m_LengthDie;
  236. m_LocalClearance = source->m_LocalClearance;
  237. m_LocalSolderMaskMargin = source->m_LocalSolderMaskMargin;
  238. m_LocalSolderPasteMargin = source->m_LocalSolderPasteMargin;
  239. m_LocalSolderPasteMarginRatio = source->m_LocalSolderPasteMarginRatio;
  240. m_ZoneConnection = source->m_ZoneConnection;
  241. m_ThermalWidth = source->m_ThermalWidth;
  242. m_ThermalGap = source->m_ThermalGap;
  243. SetSubRatsnest( 0 );
  244. SetSubNet( 0 );
  245. m_Netname = source->m_Netname;
  246. m_ShortNetname = source->m_ShortNetname;
  247. }
  248. /**
  249. * Function GetClearance (virtual)
  250. * returns the clearance in internal units. If \a aItem is not NULL then the
  251. * returned clearance is the greater of this object's clearance and
  252. * aItem's clearance. If \a aItem is NULL, then this object clearance is returned.
  253. * @param aItem is another BOARD_CONNECTED_ITEM or NULL
  254. * @return int - the clearance in internal units.
  255. */
  256. int D_PAD::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
  257. {
  258. // A pad can have specific clearance parameters that
  259. // overrides its NETCLASS clearance value
  260. int clearance = m_LocalClearance;
  261. if( clearance == 0 )
  262. {
  263. // If local clearance is 0, use the parent footprint clearance value
  264. if( GetParent() && GetParent()->GetLocalClearance() )
  265. clearance = GetParent()->GetLocalClearance();
  266. }
  267. if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value
  268. return BOARD_CONNECTED_ITEM::GetClearance( aItem );
  269. // We have a specific clearance.
  270. // if aItem, return the biggest clearance
  271. if( aItem )
  272. {
  273. int hisClearance = aItem->GetClearance();
  274. return std::max( hisClearance, clearance );
  275. }
  276. // Return the specific clearance.
  277. return clearance;
  278. }
  279. // Mask margins handling:
  280. /**
  281. * Function GetSolderMaskMargin
  282. * @return the margin for the solder mask layer
  283. * usually > 0 (mask shape bigger than pad
  284. * value is
  285. * 1 - the local value
  286. * 2 - if null, the parent footprint value
  287. * 1 - if null, the global value
  288. */
  289. int D_PAD::GetSolderMaskMargin()
  290. {
  291. int margin = m_LocalSolderMaskMargin;
  292. MODULE* module = GetParent();
  293. if( module )
  294. {
  295. if( margin == 0 )
  296. {
  297. if( module->GetLocalSolderMaskMargin() )
  298. margin = module->GetLocalSolderMaskMargin();
  299. }
  300. if( margin == 0 )
  301. {
  302. BOARD* brd = GetBoard();
  303. margin = brd->GetDesignSettings().m_SolderMaskMargin;
  304. }
  305. }
  306. // ensure mask have a size always >= 0
  307. if( margin < 0 )
  308. {
  309. int minsize = -std::min( m_Size.x, m_Size.y ) / 2;
  310. if( margin < minsize )
  311. minsize = minsize;
  312. }
  313. return margin;
  314. }
  315. /**
  316. * Function GetSolderPasteMargin
  317. * @return the margin for the solder mask layer
  318. * usually < 0 (mask shape smaller than pad
  319. * value is
  320. * 1 - the local value
  321. * 2 - if null, the parent footprint value
  322. * 1 - if null, the global value
  323. */
  324. wxSize D_PAD::GetSolderPasteMargin()
  325. {
  326. int margin = m_LocalSolderPasteMargin;
  327. double mratio = m_LocalSolderPasteMarginRatio;
  328. MODULE* module = GetParent();
  329. if( module )
  330. {
  331. if( margin == 0 )
  332. margin = module->GetLocalSolderPasteMargin();
  333. BOARD * brd = GetBoard();
  334. if( margin == 0 )
  335. margin = brd->GetDesignSettings().m_SolderPasteMargin;
  336. if( mratio == 0.0 )
  337. mratio = module->GetLocalSolderPasteMarginRatio();
  338. if( mratio == 0.0 )
  339. {
  340. mratio = brd->GetDesignSettings().m_SolderPasteMarginRatio;
  341. }
  342. }
  343. wxSize pad_margin;
  344. pad_margin.x = margin + KiROUND( m_Size.x * mratio );
  345. pad_margin.y = margin + KiROUND( m_Size.y * mratio );
  346. // ensure mask have a size always >= 0
  347. if( pad_margin.x < -m_Size.x / 2 )
  348. pad_margin.x = -m_Size.x / 2;
  349. if( pad_margin.y < -m_Size.y / 2 )
  350. pad_margin.y = -m_Size.y / 2;
  351. return pad_margin;
  352. }
  353. ZoneConnection D_PAD::GetZoneConnection() const
  354. {
  355. MODULE* module = (MODULE*) GetParent();
  356. if( m_ZoneConnection == UNDEFINED_CONNECTION && module )
  357. return module->GetZoneConnection();
  358. else
  359. return m_ZoneConnection;
  360. }
  361. int D_PAD::GetThermalWidth() const
  362. {
  363. MODULE* module = (MODULE*) GetParent();
  364. if( m_ThermalWidth == 0 && module )
  365. return module->GetThermalWidth();
  366. else
  367. return m_ThermalWidth;
  368. }
  369. int D_PAD::GetThermalGap() const
  370. {
  371. MODULE* module = (MODULE*) GetParent();
  372. if( m_ThermalGap == 0 && module )
  373. return module->GetThermalGap();
  374. else
  375. return m_ThermalGap;
  376. }
  377. void D_PAD::DisplayInfo( EDA_DRAW_FRAME* frame )
  378. {
  379. MODULE* module;
  380. wxString Line;
  381. BOARD* board;
  382. frame->EraseMsgBox();
  383. module = (MODULE*) m_Parent;
  384. if( module )
  385. {
  386. wxString msg = module->GetReference();
  387. frame->AppendMsgPanel( _( "Module" ), msg, DARKCYAN );
  388. ReturnStringPadName( Line );
  389. frame->AppendMsgPanel( _( "RefP" ), Line, BROWN );
  390. }
  391. frame->AppendMsgPanel( _( "Net" ), m_Netname, DARKCYAN );
  392. /* For test and debug only: display m_physical_connexion and
  393. * m_logical_connexion */
  394. #if 1 // Used only to debug connectivity calculations
  395. Line.Printf( wxT( "%d-%d-%d " ), GetSubRatsnest(), GetSubNet(), GetZoneSubNet() );
  396. frame->AppendMsgPanel( wxT( "L-P-Z" ), Line, DARKGREEN );
  397. #endif
  398. board = GetBoard();
  399. wxString layerInfo;
  400. if( (m_layerMask & ALL_CU_LAYERS) == 0 ) // pad is not on any copper layers
  401. {
  402. switch( m_layerMask & ~ALL_CU_LAYERS )
  403. {
  404. case ADHESIVE_LAYER_BACK:
  405. layerInfo = board->GetLayerName( ADHESIVE_N_BACK );
  406. break;
  407. case ADHESIVE_LAYER_FRONT:
  408. layerInfo = board->GetLayerName( ADHESIVE_N_FRONT );
  409. break;
  410. case SOLDERPASTE_LAYER_BACK:
  411. layerInfo = board->GetLayerName( SOLDERPASTE_N_BACK );
  412. break;
  413. case SOLDERPASTE_LAYER_FRONT:
  414. layerInfo = board->GetLayerName( SOLDERPASTE_N_FRONT );
  415. break;
  416. case SILKSCREEN_LAYER_BACK:
  417. layerInfo = board->GetLayerName( SILKSCREEN_N_BACK );
  418. break;
  419. case SILKSCREEN_LAYER_FRONT:
  420. layerInfo = board->GetLayerName( SILKSCREEN_N_FRONT );
  421. break;
  422. case SOLDERMASK_LAYER_BACK:
  423. layerInfo = board->GetLayerName( SOLDERMASK_N_BACK );
  424. break;
  425. case SOLDERMASK_LAYER_FRONT:
  426. layerInfo = board->GetLayerName( SOLDERMASK_N_FRONT );
  427. break;
  428. case DRAW_LAYER:
  429. layerInfo = board->GetLayerName( DRAW_N );
  430. break;
  431. case COMMENT_LAYER:
  432. layerInfo = board->GetLayerName( COMMENT_N );
  433. break;
  434. case ECO1_LAYER:
  435. layerInfo = board->GetLayerName( ECO1_N );
  436. break;
  437. case ECO2_LAYER:
  438. layerInfo = board->GetLayerName( ECO2_N );
  439. break;
  440. case EDGE_LAYER:
  441. layerInfo = board->GetLayerName( EDGE_N );
  442. break;
  443. default:
  444. layerInfo = _( "Non-copper" );
  445. break;
  446. }
  447. }
  448. else
  449. {
  450. #define INTERIOR_COPPER (ALL_CU_LAYERS & ~(LAYER_BACK | LAYER_FRONT))
  451. static const wxChar* andInternal = _( " & int" );
  452. if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == LAYER_BACK )
  453. {
  454. layerInfo = board->GetLayerName( LAYER_N_BACK );
  455. if( m_layerMask & INTERIOR_COPPER )
  456. layerInfo += andInternal;
  457. }
  458. else if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == (LAYER_BACK | LAYER_FRONT) )
  459. {
  460. layerInfo = board->GetLayerName( LAYER_N_BACK ) + wxT(", ") +
  461. board->GetLayerName( LAYER_N_FRONT );
  462. if( m_layerMask & INTERIOR_COPPER )
  463. layerInfo += andInternal;
  464. }
  465. else if( (m_layerMask & (LAYER_BACK | LAYER_FRONT)) == LAYER_FRONT )
  466. {
  467. layerInfo = board->GetLayerName( LAYER_N_FRONT );
  468. if( m_layerMask & INTERIOR_COPPER )
  469. layerInfo += andInternal;
  470. }
  471. else // necessarily true: if( m_layerMask & INTERIOR_COPPER )
  472. {
  473. layerInfo = _( "internal" );
  474. }
  475. }
  476. frame->AppendMsgPanel( _( "Layer" ), layerInfo, DARKGREEN );
  477. frame->AppendMsgPanel( ShowPadShape(), ShowPadAttr(), DARKGREEN );
  478. Line = frame->CoordinateToString( m_Size.x );
  479. frame->AppendMsgPanel( _( "H Size" ), Line, RED );
  480. Line = frame->CoordinateToString( m_Size.y );
  481. frame->AppendMsgPanel( _( "V Size" ), Line, RED );
  482. Line = frame->CoordinateToString( (unsigned) m_Drill.x );
  483. if( m_DrillShape == PAD_CIRCLE )
  484. {
  485. frame->AppendMsgPanel( _( "Drill" ), Line, RED );
  486. }
  487. else
  488. {
  489. Line = frame->CoordinateToString( (unsigned) m_Drill.x );
  490. wxString msg;
  491. msg = frame->CoordinateToString( (unsigned) m_Drill.y );
  492. Line += wxT( "/" ) + msg;
  493. frame->AppendMsgPanel( _( "Drill X / Y" ), Line, RED );
  494. }
  495. int module_orient = module ? module->GetOrientation() : 0;
  496. if( module_orient )
  497. Line.Printf( wxT( "%3.1f(+%3.1f)" ),
  498. (double) ( m_Orient - module_orient ) / 10,
  499. (double) module_orient / 10 );
  500. else
  501. Line.Printf( wxT( "%3.1f" ), (double) m_Orient / 10 );
  502. frame->AppendMsgPanel( _( "Orient" ), Line, LIGHTBLUE );
  503. Line = frame->CoordinateToString( m_Pos.x );
  504. frame->AppendMsgPanel( _( "X Pos" ), Line, LIGHTBLUE );
  505. Line = frame->CoordinateToString( m_Pos.y );
  506. frame->AppendMsgPanel( _( "Y pos" ), Line, LIGHTBLUE );
  507. if( GetDieLength() )
  508. {
  509. Line = frame->CoordinateToString( GetDieLength() );
  510. frame->AppendMsgPanel( _( "Length on die" ), Line, CYAN );
  511. }
  512. }
  513. // see class_pad.h
  514. bool D_PAD::IsOnLayer( int aLayer ) const
  515. {
  516. return (1 << aLayer) & m_layerMask;
  517. }
  518. bool D_PAD::HitTest( const wxPoint& aPosition )
  519. {
  520. int dx, dy;
  521. double dist;
  522. wxPoint shape_pos = ReturnShapePos();
  523. wxPoint delta = aPosition - shape_pos;
  524. // first test: a test point must be inside a minimum sized bounding circle.
  525. int radius = GetBoundingRadius();
  526. if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) )
  527. return false;
  528. dx = m_Size.x >> 1; // dx also is the radius for rounded pads
  529. dy = m_Size.y >> 1;
  530. switch( m_PadShape & 0x7F )
  531. {
  532. case PAD_CIRCLE:
  533. dist = hypot( delta.x, delta.y );
  534. if( KiROUND( dist ) <= dx )
  535. return true;
  536. break;
  537. case PAD_TRAPEZOID:
  538. {
  539. wxPoint poly[4];
  540. BuildPadPolygon( poly, wxSize(0,0), 0 );
  541. RotatePoint( &delta, -m_Orient );
  542. return TestPointInsidePolygon( poly, 4, delta );
  543. }
  544. default:
  545. RotatePoint( &delta, -m_Orient );
  546. if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
  547. return true;
  548. break;
  549. }
  550. return false;
  551. }
  552. int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
  553. {
  554. int diff;
  555. if( ( diff = padref->m_PadShape - padcmp->m_PadShape ) != 0 )
  556. return diff;
  557. if( ( diff = padref->m_DrillShape - padcmp->m_DrillShape ) != 0)
  558. return diff;
  559. if( ( diff = padref->m_Drill.x - padcmp->m_Drill.x ) != 0 )
  560. return diff;
  561. if( ( diff = padref->m_Drill.y - padcmp->m_Drill.y ) != 0 )
  562. return diff;
  563. if( ( diff = padref->m_Size.x - padcmp->m_Size.x ) != 0 )
  564. return diff;
  565. if( ( diff = padref->m_Size.y - padcmp->m_Size.y ) != 0 )
  566. return diff;
  567. if( ( diff = padref->m_Offset.x - padcmp->m_Offset.x ) != 0 )
  568. return diff;
  569. if( ( diff = padref->m_Offset.y - padcmp->m_Offset.y ) != 0 )
  570. return diff;
  571. if( ( diff = padref->m_DeltaSize.x - padcmp->m_DeltaSize.x ) != 0 )
  572. return diff;
  573. if( ( diff = padref->m_DeltaSize.y - padcmp->m_DeltaSize.y ) != 0 )
  574. return diff;
  575. // Dick: specctra_export needs this
  576. // Lorenzo: gencad also needs it to implement padstacks!
  577. if( ( diff = padref->m_layerMask - padcmp->m_layerMask ) != 0 )
  578. return diff;
  579. return 0;
  580. }
  581. wxString D_PAD::ShowPadShape() const
  582. {
  583. switch( m_PadShape )
  584. {
  585. case PAD_CIRCLE:
  586. return _( "Circle" );
  587. case PAD_OVAL:
  588. return _( "Oval" );
  589. case PAD_RECT:
  590. return _( "Rect" );
  591. case PAD_TRAPEZOID:
  592. return _( "Trap" );
  593. default:
  594. return wxT( "??Unknown??" );
  595. }
  596. }
  597. wxString D_PAD::ShowPadAttr() const
  598. {
  599. switch( GetAttribute() )
  600. {
  601. case PAD_STANDARD:
  602. return _( "Std" );
  603. case PAD_SMD:
  604. return _( "Smd" );
  605. case PAD_CONN:
  606. return _( "Conn" );
  607. case PAD_HOLE_NOT_PLATED:
  608. return _( "Not Plated" );
  609. default:
  610. return wxT( "??Unkown??" );
  611. }
  612. }
  613. wxString D_PAD::GetSelectMenuText() const
  614. {
  615. wxString text;
  616. wxString padlayers;
  617. BOARD * board = GetBoard();
  618. if ( (m_layerMask & ALL_CU_LAYERS) == ALL_CU_LAYERS )
  619. padlayers = _("all copper layers");
  620. else if( (m_layerMask & LAYER_BACK ) == LAYER_BACK )
  621. padlayers = board->GetLayerName(LAYER_N_BACK);
  622. else if( (m_layerMask & LAYER_FRONT) == LAYER_FRONT )
  623. padlayers = board->GetLayerName(LAYER_N_FRONT);
  624. else
  625. padlayers = _( "???" );
  626. text.Printf( _( "Pad [%s] (%s) of %s" ),
  627. GetChars(GetPadName() ), GetChars( padlayers ),
  628. GetChars(( (MODULE*) GetParent() )->GetReference() ) );
  629. return text;
  630. }
  631. EDA_ITEM* D_PAD::Clone() const
  632. {
  633. return new D_PAD( *this );
  634. }
  635. #if defined(DEBUG)
  636. void D_PAD::Show( int nestLevel, std::ostream& os ) const
  637. {
  638. char padname[5] = { m_Padname[0], m_Padname[1], m_Padname[2], m_Padname[3], 0 };
  639. char layerMask[16];
  640. sprintf( layerMask, "0x%08X", m_layerMask );
  641. // for now, make it look like XML:
  642. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  643. " shape=\"" << ShowPadShape() << '"' <<
  644. " attr=\"" << ShowPadAttr( ) << '"' <<
  645. " num=\"" << padname << '"' <<
  646. " net=\"" << m_Netname.mb_str() << '"' <<
  647. " netcode=\"" << GetNet() << '"' <<
  648. " layerMask=\"" << layerMask << '"' << m_Pos << "/>\n";
  649. // NestedSpace( nestLevel+1, os ) << m_Text.mb_str() << '\n';
  650. // NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str()
  651. // << ">\n";
  652. }
  653. #endif