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.

548 lines
22 KiB

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
15 years ago
18 years ago
18 years ago
18 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 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
  1. /**
  2. * @file drc_stuff.h
  3. */
  4. /*
  5. * This program source code file is part of KiCad, a free EDA CAD application.
  6. *
  7. * Copyright (C) 2007-2016 Dick Hollenbeck, dick@softplc.com
  8. * Copyright (C) 2017-2018 KiCad Developers, see change_log.txt for contributors.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #ifndef DRC_H
  28. #define DRC_H
  29. #include <vector>
  30. #include <memory>
  31. #include <geometry/seg.h>
  32. #define OK_DRC 0
  33. #define BAD_DRC 1
  34. // DRC error codes could be defined by an enum.
  35. // however a #define is used because error code value is displayed in DRC messages,
  36. // and using #define that shows each numerical value helps for debug.
  37. /// DRC error codes:
  38. #define DRCE_ 1 // not used yet
  39. #define DRCE_UNCONNECTED_ITEMS 2 ///< items are unconnected
  40. #define DRCE_TRACK_NEAR_THROUGH_HOLE 3 ///< thru hole is too close to track
  41. #define DRCE_TRACK_NEAR_PAD 4 ///< pad too close to track
  42. #define DRCE_TRACK_NEAR_VIA 5 ///< track too close to via
  43. #define DRCE_VIA_NEAR_VIA 6 ///< via too close to via
  44. #define DRCE_VIA_NEAR_TRACK 7 ///< via too close to track
  45. #define DRCE_TRACK_ENDS1 8 ///< 2 parallel track segments too close: fine start point test
  46. #define DRCE_TRACK_ENDS2 9 ///< 2 parallel track segments too close: fine start point test
  47. #define DRCE_TRACK_ENDS3 10 ///< 2 parallel track segments too close: fine end point test
  48. #define DRCE_TRACK_ENDS4 11 ///< 2 parallel track segments too close: fine end point test
  49. #define DRCE_TRACK_SEGMENTS_TOO_CLOSE 12 ///< 2 parallel track segments too close: segm ends between segref ends
  50. #define DRCE_TRACKS_CROSSING 13 ///< tracks are crossing
  51. #define DRCE_ENDS_PROBLEM1 14 ///< track ends are too close
  52. #define DRCE_ENDS_PROBLEM2 15 ///< track ends are too close
  53. #define DRCE_ENDS_PROBLEM3 16 ///< track ends are too close
  54. #define DRCE_ENDS_PROBLEM4 17 ///< track ends are too close
  55. #define DRCE_ENDS_PROBLEM5 18 ///< track ends are too close
  56. #define DRCE_PAD_NEAR_PAD1 19 ///< pad too close to pad
  57. #define DRCE_VIA_HOLE_BIGGER 20 ///< via's hole is bigger than its diameter
  58. #define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR 21 ///< micro via's layer pair incorrect (layers must be adjacent)
  59. #define DRCE_ZONES_INTERSECT 22 ///< copper area outlines intersect
  60. #define DRCE_ZONES_TOO_CLOSE 23 ///< copper area outlines are too close
  61. #define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE 24 ///< copper area has a net but no pads in nets, which is suspicious
  62. #define DRCE_HOLE_NEAR_PAD 25 ///< hole too close to pad
  63. #define DRCE_HOLE_NEAR_TRACK 26 ///< hole too close to track
  64. #define DRCE_TOO_SMALL_TRACK_WIDTH 27 ///< Too small track width
  65. #define DRCE_TOO_SMALL_VIA 28 ///< Too small via size
  66. #define DRCE_TOO_SMALL_MICROVIA 29 ///< Too small micro via size
  67. #define DRCE_TOO_SMALL_VIA_DRILL 30 ///< Too small via drill
  68. #define DRCE_TOO_SMALL_MICROVIA_DRILL 31 ///< Too small micro via drill
  69. #define DRCE_NETCLASS_TRACKWIDTH 32 ///< netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
  70. #define DRCE_NETCLASS_CLEARANCE 33 ///< netclass has Clearance < board.m_designSettings->m_TrackClearance
  71. #define DRCE_NETCLASS_VIASIZE 34 ///< netclass has ViaSize < board.m_designSettings->m_ViasMinSize
  72. #define DRCE_NETCLASS_VIADRILLSIZE 35 ///< netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
  73. #define DRCE_NETCLASS_uVIASIZE 36 ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
  74. #define DRCE_NETCLASS_uVIADRILLSIZE 37 ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
  75. #define DRCE_VIA_INSIDE_KEEPOUT 38 ///< Via in inside a keepout area
  76. #define DRCE_TRACK_INSIDE_KEEPOUT 39 ///< Track in inside a keepout area
  77. #define DRCE_PAD_INSIDE_KEEPOUT 40 ///< Pad in inside a keepout area
  78. #define DRCE_TRACK_NEAR_COPPER 41 ///< track & copper graphic collide or are too close
  79. #define DRCE_VIA_NEAR_COPPER 42 ///< via and copper graphic collide or are too close
  80. #define DRCE_PAD_NEAR_COPPER 43 ///< pad and copper graphic collide or are too close
  81. #define DRCE_TRACK_NEAR_ZONE 44 ///< track & zone collide or are too close together
  82. #define DRCE_OVERLAPPING_FOOTPRINTS 45 ///< footprint courtyards overlap
  83. #define DRCE_MISSING_COURTYARD_IN_FOOTPRINT 46 ///< footprint has no courtyard defined
  84. #define DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT 47 ///< footprint has a courtyard but malformed
  85. ///< (not convertible to a closed polygon with holes)
  86. #define DRCE_MICRO_VIA_NOT_ALLOWED 48 ///< micro vias are not allowed
  87. #define DRCE_BURIED_VIA_NOT_ALLOWED 49 ///< buried vias are not allowed
  88. #define DRCE_DISABLED_LAYER_ITEM 50 ///< item on a disabled layer
  89. #define DRCE_DRILLED_HOLES_TOO_CLOSE 51 ///< overlapping drilled holes break drill bits
  90. class EDA_DRAW_PANEL;
  91. class PCB_EDIT_FRAME;
  92. class DIALOG_DRC_CONTROL;
  93. class BOARD_ITEM;
  94. class BOARD;
  95. class D_PAD;
  96. class ZONE_CONTAINER;
  97. class TRACK;
  98. class MARKER_PCB;
  99. class DRC_ITEM;
  100. class NETCLASS;
  101. class EDA_TEXT;
  102. class DRAWSEGMENT;
  103. class wxWindow;
  104. class wxString;
  105. class wxTextCtrl;
  106. /**
  107. * Provide an abstract interface of a DRC_ITEM* list manager. The details
  108. * of the actual list architecture are hidden from the caller. Any class
  109. * that implements this interface can then be used by a DRCLISTBOX class without
  110. * it knowing the actual architecture of the list.
  111. */
  112. class DRC_ITEM_LIST
  113. {
  114. public:
  115. /**
  116. * Function DeleteAllItems
  117. * removes and deletes all the items in the list.
  118. */
  119. virtual void DeleteAllItems() = 0;
  120. /**
  121. * Function GetItem
  122. * retrieves a DRC_ITEM by pointer. The actual item remains owned by the
  123. * list container.
  124. * @param aIndex The 0 based index into the list of the desired item.
  125. * @return const DRC_ITEM* - the desired item or NULL if aIndex is out of range.
  126. */
  127. virtual const DRC_ITEM* GetItem( int aIndex ) = 0;
  128. /**
  129. * Function DeleteAllItems
  130. * removes and deletes desired item from the list.
  131. * @param aIndex The 0 based index into the list of the desired item which
  132. * is to be deleted.
  133. */
  134. virtual void DeleteItem( int aIndex ) = 0;
  135. /**
  136. * Function GetCount
  137. * returns the number of items in the list.
  138. */
  139. virtual int GetCount() = 0;
  140. virtual ~DRC_ITEM_LIST() { }
  141. };
  142. typedef std::vector<DRC_ITEM*> DRC_LIST;
  143. /**
  144. * Design Rule Checker object that performs all the DRC tests. The output of
  145. * the checking goes to the BOARD file in the form of two MARKER lists. Those
  146. * two lists are displayable in the drc dialog box. And they can optionally
  147. * be sent to a text file on disk.
  148. * This class is given access to the windows and the BOARD
  149. * that it needs via its constructor or public access functions.
  150. */
  151. class DRC
  152. {
  153. friend class DIALOG_DRC_CONTROL;
  154. private:
  155. // protected or private functions() are lowercase first character.
  156. bool m_doPad2PadTest;
  157. bool m_doUnconnectedTest;
  158. bool m_doZonesTest;
  159. bool m_doKeepoutTest;
  160. bool m_doCreateRptFile;
  161. bool m_refillZones;
  162. bool m_reportAllTrackErrors;
  163. wxString m_rptFilename;
  164. MARKER_PCB* m_currentMarker;
  165. /**
  166. * in legacy canvas, when creating a track, the drc test must only display the
  167. * error message, and do not create a DRC marker.
  168. * if m_drcInLegacyRoutingMode it true only the message will be displayed
  169. * m_drcInLegacyRoutingMode = false is the normal Drc mode
  170. */
  171. bool m_drcInLegacyRoutingMode;
  172. /* In DRC functions, many calculations are using coordinates relative
  173. * to the position of the segment under test (segm to segm DRC, segm to pad DRC
  174. * Next variables store coordinates relative to the start point of this segment
  175. */
  176. wxPoint m_padToTestPos; // Position of the pad to compare in drc test segm to pad or pad to pad
  177. wxPoint m_segmEnd; // End point of the reference segment (start point = (0,0) )
  178. /* Some functions are comparing the ref segm to pads or others segments using
  179. * coordinates relative to the ref segment considered as the X axis
  180. * so we store the ref segment length (the end point relative to these axis)
  181. * and the segment orientation (used to rotate other coordinates)
  182. */
  183. double m_segmAngle; // Ref segm orientation in 0,1 degre
  184. int m_segmLength; // length of the reference segment
  185. /* variables used in checkLine to test DRC segm to segm:
  186. * define the area relative to the ref segment that does not contains any other segment
  187. */
  188. int m_xcliplo;
  189. int m_ycliplo;
  190. int m_xcliphi;
  191. int m_ycliphi;
  192. PCB_EDIT_FRAME* m_pcbEditorFrame; ///< The pcb frame editor which owns the board
  193. BOARD* m_pcb;
  194. DIALOG_DRC_CONTROL* m_drcDialog;
  195. DRC_LIST m_unconnected; ///< list of unconnected pads, as DRC_ITEMs
  196. /**
  197. * Update needed pointers from the one pointer which is known not to change.
  198. */
  199. void updatePointers();
  200. /**
  201. * Function newMarker
  202. * Creates a marker on a track, via or pad.
  203. *
  204. * @param aTrack/aPad The reference item.
  205. * @param aConflitItem Another item on the board which is in conflict with the
  206. * reference item.
  207. * @param aErrorCode An ID for the particular type of error that is being reported.
  208. */
  209. MARKER_PCB* newMarker( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg,
  210. int aErrorCode );
  211. MARKER_PCB* newMarker( TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aErrorCode );
  212. MARKER_PCB* newMarker( D_PAD* aPad, BOARD_ITEM* aConflictItem, int aErrorCode );
  213. /**
  214. * Function newMarker
  215. * Creates a marker at a given location.
  216. *
  217. * @param aItem The reference item.
  218. * @param aPos Usually the position of the item, but could be more specific for a zone.
  219. * @param aErrorCode An ID for the particular type of error that is being reported.
  220. */
  221. MARKER_PCB* newMarker( const wxPoint& aPos, BOARD_ITEM* aItem, int aErrorCode );
  222. MARKER_PCB* newMarker( const wxPoint& aPos, BOARD_ITEM* aItem, BOARD_ITEM* bItem,
  223. int aErrorCode );
  224. /**
  225. * Create a MARKER which will report on a generic problem with the board which is
  226. * not geographically locatable.
  227. */
  228. MARKER_PCB* newMarker( int aErrorCode, const wxString& aMessage );
  229. /**
  230. * Adds a DRC marker to the PCB through the COMMIT mechanism.
  231. */
  232. void addMarkerToPcb( MARKER_PCB* aMarker );
  233. //-----<categorical group tests>-----------------------------------------
  234. /**
  235. * Go through each NETCLASS and verifies that its clearance, via size, track width, and
  236. * track clearance are larger than those in board.m_designSettings.
  237. * This is necessary because the actual DRC checks are run against the NETCLASS
  238. * limits, so in order enforce global limits, we first check the NETCLASSes against
  239. * the global limits.
  240. * @return bool - true if succes, else false but only after
  241. * reporting _all_ NETCLASS violations.
  242. */
  243. bool testNetClasses();
  244. /**
  245. * Perform the DRC on all tracks.
  246. *
  247. * This test can take a while, a progress bar can be displayed
  248. * @param aActiveWindow = the active window ued as parent for the progress bar
  249. * @param aShowProgressBar = true to show a progress bar
  250. * (Note: it is shown only if there are many tracks)
  251. */
  252. void testTracks( wxWindow * aActiveWindow, bool aShowProgressBar );
  253. void testPad2Pad();
  254. void testDrilledHoles();
  255. void testUnconnected();
  256. void testZones();
  257. void testKeepoutAreas();
  258. // aTextItem is type BOARD_ITEM* to accept either TEXTE_PCB or TEXTE_MODULE
  259. void testCopperTextItem( BOARD_ITEM* aTextItem );
  260. void testCopperDrawItem( DRAWSEGMENT* aDrawing );
  261. void testCopperTextAndGraphics();
  262. ///> Tests for items placed on disabled layers (causing false connections).
  263. void testDisabledLayers();
  264. //-----<single "item" tests>-----------------------------------------
  265. bool doNetClass( const std::shared_ptr<NETCLASS>& aNetClass, wxString& msg );
  266. /**
  267. * Test the clearance between aRefPad and other pads.
  268. *
  269. * The pad list must be sorted by x coordinate.
  270. *
  271. * @param aRefPad is the pad to test
  272. * @param aStart is the first pad of the list to test against aRefPad
  273. * @param aEnd is the end of the list and is not included
  274. * @param x_limit is used to stop the test
  275. * (i.e. when the current pad pos X in list exceeds this limit, because the list
  276. * is sorted by X coordinate)
  277. */
  278. bool doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit );
  279. /**
  280. * Test the current segment.
  281. *
  282. * @param aRefSeg The segment to test
  283. * @param aStart the first item of track list to test against (usually BOARD::m_Track)
  284. * @param doPads true if should do pads test
  285. * @return bool - true if no problems, else false and m_currentMarker is
  286. * filled in with the problem information.
  287. */
  288. bool doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool doPads = true );
  289. /**
  290. * Test the current segment or via.
  291. *
  292. * @param aRefSeg The segment to test
  293. * @return bool - true if no problems, else false and m_currentMarker is
  294. * filled in with the problem information.
  295. */
  296. bool doTrackKeepoutDrc( TRACK* aRefSeg );
  297. /**
  298. * Test a segment in ZONE_CONTAINER * aArea:
  299. * Test Edge inside other areas
  300. * Test Edge too close other areas
  301. *
  302. * @param aArea The current area.
  303. * @param aCornerIndex The first corner of the segment to test.
  304. * @return bool - false if DRC error or true if OK
  305. */
  306. bool doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex );
  307. /**
  308. * Test for footprint courtyard overlaps.
  309. *
  310. * @return bool - false if DRC error or true if OK
  311. */
  312. bool doFootprintOverlappingDrc();
  313. //-----<single tests>----------------------------------------------
  314. /**
  315. * @param aRefPad The reference pad to check
  316. * @param aPad Another pad to check against
  317. * @return bool - true if clearance between aRefPad and aPad is >= dist_min, else false
  318. */
  319. bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad );
  320. /**
  321. * Check the distance from a pad to segment. This function uses several
  322. * instance variable not passed in:
  323. * m_segmLength = length of the segment being tested
  324. * m_segmAngle = angle of the segment with the X axis;
  325. * m_segmEnd = end coordinate of the segment
  326. * m_padToTestPos = position of pad relative to the origin of segment
  327. * @param aPad Is the pad involved in the check
  328. * @param aSegmentWidth width of the segment to test
  329. * @param aMinDist Is the minimum clearance needed
  330. *
  331. * @return true distance >= dist_min,
  332. * false if distance < dist_min
  333. */
  334. bool checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist );
  335. /**
  336. * Check the distance from a point to a segment.
  337. *
  338. * The segment is expected starting at 0,0, and on the X axis
  339. * (used to test DRC between a segment and a round pad, via or round end of a track
  340. * @param aCentre The coordinate of the circle's center
  341. * @param aRadius A "keep out" radius centered over the circle
  342. * @param aLength The length of the segment (i.e. coordinate of end, because it is on
  343. * the X axis)
  344. * @return bool - true if distance >= radius, else
  345. * false when distance < aRadius
  346. */
  347. static bool checkMarginToCircle( wxPoint aCentre, int aRadius, int aLength );
  348. /**
  349. * Function checkLine
  350. * (helper function used in drc calculations to see if one track is in contact with
  351. * another track).
  352. * Test if a line intersects a bounding box (a rectangle)
  353. * The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi
  354. * return true if the line from aSegStart to aSegEnd is outside the bounding box
  355. */
  356. bool checkLine( wxPoint aSegStart, wxPoint aSegEnd );
  357. //-----</single tests>---------------------------------------------
  358. public:
  359. DRC( PCB_EDIT_FRAME* aPcbWindow );
  360. ~DRC();
  361. /**
  362. * Function Drc
  363. * tests the current segment and returns the result and displays the error
  364. * in the status panel only if one exists.
  365. * No marker created or added to the board. Must be used only during track
  366. * creation in legacy canvas
  367. * @param aRefSeg The current segment to test.
  368. * @param aList The track list to test (usually m_Pcb->m_Track)
  369. * @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK
  370. */
  371. int DrcOnCreatingTrack( TRACK* aRefSeg, TRACK* aList );
  372. /**
  373. * Function Drc
  374. * tests the outline segment starting at CornerIndex and returns the result and displays
  375. * the error in the status panel only if one exists.
  376. * Test Edge inside other areas
  377. * Test Edge too close other areas
  378. * No marker created or added to the board. Must be used only during zone
  379. * creation in legacy canvas
  380. * @param aArea The area parent which contains the corner.
  381. * @param aCornerIndex The starting point of the segment to test.
  382. * @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK
  383. */
  384. int DrcOnCreatingZone( ZONE_CONTAINER* aArea, int aCornerIndex );
  385. /**
  386. * Tests whether distance between zones complies with the DRC rules.
  387. *
  388. * @param aZone: zone to compare with other zones, or if NULL then
  389. * all zones are compared to all others.
  390. * @param aCreateMarkers: if true create DRC markers.
  391. * False: do not create markers. only fing drc errors
  392. * @return Errors count
  393. */
  394. int TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers );
  395. /**
  396. * Open a dialog and prompts the user, then if a test run button is
  397. * clicked, runs the test(s) and creates the MARKERS. The dialog is only
  398. * created if it is not already in existence.
  399. *
  400. * @param aParent is the parent window for wxWidgets. Usually the PCB editor frame
  401. * but can be another dialog
  402. * if aParent == NULL (default), the parent will be the PCB editor frame
  403. * and the dialog will be not modal (just float on parent
  404. * if aParent is specified, the dialog will be modal.
  405. * The modal mode is mandatory if the dialog is created from another dialog, not
  406. * from the PCB editor frame
  407. */
  408. void ShowDRCDialog( wxWindow* aParent = NULL );
  409. /**
  410. * Deletes this ui dialog box and zeros out its pointer to remember
  411. * the state of the dialog's existence.
  412. *
  413. * @param aReason Indication of which button was clicked to cause the destruction.
  414. * if aReason == wxID_OK, design parameters values which can be entered from the dialog
  415. * will bbe saved in design parameters list
  416. */
  417. void DestroyDRCDialog( int aReason );
  418. /**
  419. * Save all the UI or test settings and may be called before running the tests.
  420. *
  421. * @param aPad2PadTest Tells whether to test pad to pad distances.
  422. * @param aUnconnectedTest Tells whether to list unconnected pads.
  423. * @param aZonesTest Tells whether to test zones.
  424. * @param aRefillZones Refill zones before performing DRC.
  425. * @param aKeepoutTest Tells whether to test keepout areas.
  426. * @param aReportAllTrackErrors Tells whether or not to stop checking track connections after the first error.
  427. * @param aReportName A string telling the disk file report name entered.
  428. * @param aSaveReport A boolean telling whether to generate disk file report.
  429. */
  430. void SetSettings( bool aPad2PadTest, bool aUnconnectedTest,
  431. bool aZonesTest, bool aKeepoutTest, bool aRefillZones,
  432. bool aReportAllTrackErrors,
  433. const wxString& aReportName, bool aSaveReport )
  434. {
  435. m_doPad2PadTest = aPad2PadTest;
  436. m_doUnconnectedTest = aUnconnectedTest;
  437. m_doZonesTest = aZonesTest;
  438. m_doKeepoutTest = aKeepoutTest;
  439. m_rptFilename = aReportName;
  440. m_doCreateRptFile = aSaveReport;
  441. m_refillZones = aRefillZones;
  442. m_drcInLegacyRoutingMode = false;
  443. m_reportAllTrackErrors = aReportAllTrackErrors;
  444. }
  445. /**
  446. * Run all the tests specified with a previous call to
  447. * SetSettings()
  448. * @param aMessages = a wxTextControl where to display some activity messages. Can be NULL
  449. */
  450. void RunTests( wxTextCtrl* aMessages = NULL );
  451. /**
  452. * Gather a list of all the unconnected pads and shows them in the
  453. * dialog, and optionally prints a report of such.
  454. */
  455. void ListUnconnectedPads();
  456. /**
  457. * @return a pointer to the current marker (last created marker
  458. */
  459. MARKER_PCB* GetCurrentMarker( )
  460. {
  461. return m_currentMarker;
  462. }
  463. };
  464. #endif // DRC_H