drc_stuff.h 19.4 KB
Newer Older
1 2 3 4
/**
 * @file drc_stuff.h
 */

dickelbeck's avatar
dickelbeck committed
5
/*
6
 * This program source code file is part of KiCad, a free EDA CAD application.
dickelbeck's avatar
dickelbeck committed
7 8
 *
 * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
9
 * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
dickelbeck's avatar
dickelbeck committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

#ifndef _DRC_STUFF_H
#define _DRC_STUFF_H


33
#include <vector>
dickelbeck's avatar
dickelbeck committed
34

35 36
#define OK_DRC  0
#define BAD_DRC 1
37

dickelbeck's avatar
dickelbeck committed
38

39
/// DRC error codes:
40 41 42 43 44 45 46
#define DRCE_                                  1    // not used yet
#define DRCE_UNCONNECTED_PADS                  2    ///< pads are unconnected
#define DRCE_TRACK_NEAR_THROUGH_HOLE           3    ///< thru hole is too close to track
#define DRCE_TRACK_NEAR_PAD                    4    ///< pad too close to track
#define DRCE_TRACK_NEAR_VIA                    5    ///< track too close to via
#define DRCE_VIA_NEAR_VIA                      6    ///< via too close to via
#define DRCE_VIA_NEAR_TRACK                    7    ///< via too close to track
47 48 49 50 51
#define DRCE_TRACK_ENDS1                       8    ///< 2 parallel track segments too close: fine start point test
#define DRCE_TRACK_ENDS2                       9    ///< 2 parallel track segments too close: fine start point test
#define DRCE_TRACK_ENDS3                       10   ///< 2 parallel track segments too close: fine end point test
#define DRCE_TRACK_ENDS4                       11   ///< 2 parallel track segments too close: fine end point test
#define DRCE_TRACK_SEGMENTS_TOO_CLOSE          12   ///< 2 parallel track segments too close: segm ends between segref ends
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
#define DRCE_TRACKS_CROSSING                   13   ///< tracks are crossing
#define DRCE_ENDS_PROBLEM1                     14   ///< track ends are too close
#define DRCE_ENDS_PROBLEM2                     15   ///< track ends are too close
#define DRCE_ENDS_PROBLEM3                     16   ///< track ends are too close
#define DRCE_ENDS_PROBLEM4                     17   ///< track ends are too close
#define DRCE_ENDS_PROBLEM5                     18   ///< track ends are too close
#define DRCE_PAD_NEAR_PAD1                     19   ///< pad too close to pad
#define DRCE_VIA_HOLE_BIGGER                   20   ///< via's hole is bigger than its diameter
#define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR    21   ///< micro via's layer pair incorrect (layers must be adjacent)
#define COPPERAREA_INSIDE_COPPERAREA           22   ///< copper area outlines intersect
#define COPPERAREA_CLOSE_TO_COPPERAREA         23   ///< copper area outlines are too close
#define DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE 24   ///< copper area outline has an incorrect netcode due to a netname not found
#define DRCE_HOLE_NEAR_PAD                     25   ///< hole too close to pad
#define DRCE_HOLE_NEAR_TRACK                   26   ///< hole too close to track
#define DRCE_TOO_SMALL_TRACK_WIDTH             27   ///< Too small track width
#define DRCE_TOO_SMALL_VIA                     28   ///< Too small via size
#define DRCE_TOO_SMALL_MICROVIA                29   ///< Too small micro via size
#define DRCE_NETCLASS_TRACKWIDTH               30   ///< netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
#define DRCE_NETCLASS_CLEARANCE                31   ///< netclass has Clearance < board.m_designSettings->m_TrackClearance
71 72 73 74
#define DRCE_NETCLASS_VIASIZE                  32   ///< netclass has ViaSize < board.m_designSettings->m_ViasMinSize
#define DRCE_NETCLASS_VIADRILLSIZE             33   ///< netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
#define DRCE_NETCLASS_uVIASIZE                 34   ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
#define DRCE_NETCLASS_uVIADRILLSIZE            35   ///< netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
75 76 77
#define DRCE_VIA_INSIDE_KEEPOUT                36   ///< Via in inside a keepout area
#define DRCE_TRACK_INSIDE_KEEPOUT              37   ///< Track in inside a keepout area
#define DRCE_PAD_INSIDE_KEEPOUT                38   ///< Pad in inside a keepout area
dickelbeck's avatar
dickelbeck committed
78 79


80
class EDA_DRAW_PANEL;
81
class PCB_EDIT_FRAME;
82
class DIALOG_DRC_CONTROL;
83 84 85 86 87 88 89 90
class BOARD_ITEM;
class BOARD;
class D_PAD;
class ZONE_CONTAINER;
class TRACK;
class MARKER_PCB;
class DRC_ITEM;
class NETCLASS;
dickelbeck's avatar
dickelbeck committed
91

dickelbeck's avatar
dickelbeck committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

/**
 * Class DRC_ITEM_LIST
 * provides an abstract interface of a DRC_ITEM* list manager.  The details
 * of the actual list architecture are hidden from the caller.  Any class
 * that implements this interface can then be used by a DRCLISTBOX class without
 * it knowing the actual architecture of the list.
 */
class DRC_ITEM_LIST
{
public:

    /**
     * Function DeleteAllItems
     * removes and deletes all the items in the list.
     */
108
    virtual void DeleteAllItems() = 0;
109

dickelbeck's avatar
dickelbeck committed
110 111 112 113 114 115 116
    /**
     * Function GetItem
     * retrieves a DRC_ITEM by pointer.  The actual item remains owned by the
     * list container.
     * @param aIndex The 0 based index into the list of the desired item.
     * @return const DRC_ITEM* - the desired item or NULL if aIndex is out of range.
     */
117
    virtual const DRC_ITEM* GetItem( int aIndex ) = 0;
dickelbeck's avatar
dickelbeck committed
118 119 120 121

    /**
     * Function DeleteAllItems
     * removes and deletes desired item from the list.
122
     * @param aIndex The 0 based index into the list of the desired item which
dickelbeck's avatar
dickelbeck committed
123 124
     *         is to be deleted.
     */
125
    virtual void DeleteItem( int aIndex ) = 0;
dickelbeck's avatar
dickelbeck committed
126 127 128 129 130

    /**
     * Function GetCount
     * returns the number of items in the list.
     */
131
    virtual int GetCount() = 0;
132 133

    virtual ~DRC_ITEM_LIST() { }
dickelbeck's avatar
dickelbeck committed
134 135 136
};


137
typedef std::vector<DRC_ITEM*> DRC_LIST;
dickelbeck's avatar
dickelbeck committed
138

dickelbeck's avatar
dickelbeck committed
139

dickelbeck's avatar
dickelbeck committed
140
/**
141 142 143 144 145 146 147
 * Class DRC
 * is the Design Rule Checker, and performs all the DRC tests.  The output of
 * the checking goes to the BOARD file in the form of two MARKER lists.  Those
 * two lists are displayable in the drc dialog box.  And they can optionally
 * be sent to a text file on disk.
 * This class is given access to the windows and the BOARD
 * that it needs via its constructor or public access functions.
148
 */
149
class DRC
dickelbeck's avatar
dickelbeck committed
150
{
151
    friend class DIALOG_DRC_CONTROL;
152

153
private:
154

155
    //  protected or private functions() are lowercase first character.
156 157 158 159

    bool     m_doPad2PadTest;
    bool     m_doUnconnectedTest;
    bool     m_doZonesTest;
160
    bool     m_doKeepoutTest;
161 162 163 164
    bool     m_doCreateRptFile;

    wxString m_rptFilename;

165
    MARKER_PCB* m_currentMarker;
166

167
    bool        m_abortDRC;
168
    bool        m_drcInProgress;
169

170 171 172 173
    /* In DRC functions, many calculations are using coordinates relative
     * to the position of the segment under test (segm to segm DRC, segm to pad DRC
     * Next variables store coordinates relative to the start point of this segment
     */
174 175
    wxPoint m_padToTestPos; // Position of the pad to compare in drc test segm to pad or pad to pad
    wxPoint m_segmEnd;      // End point of the reference segment (start point = (0,0) )
176 177 178 179 180 181

    /* Some functions are comparing the ref segm to pads or others segments using
     * coordinates relative to the ref segment considered as the X axis
     * so we store the ref segment length (the end point relative to these axis)
     * and the segment orientation (used to rotate other coordinates)
     */
182
    double m_segmAngle;     // Ref segm orientation in 0,1 degre
183
    int m_segmLength;       // length of the reference segment
184

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
     */
jean-pierre charras's avatar
jean-pierre charras committed
188 189 190 191
    int                 m_xcliplo;
    int                 m_ycliplo;
    int                 m_xcliphi;
    int                 m_ycliphi;
192

193
    PCB_EDIT_FRAME*     m_mainWindow;
194 195
    BOARD*              m_pcb;
    DIALOG_DRC_CONTROL* m_ui;
196

197
    DRC_LIST            m_unconnected;  ///< list of unconnected pads, as DRC_ITEMs
198 199 200


    /**
201 202 203 204
     * Function updatePointers
     * is a private helper function used to update needed pointers from the
     * one pointer which is known not to change, m_mainWindow.
     */
205
    void updatePointers();
206

207 208 209

    /**
     * Function fillMarker
210 211
     * optionally creates a marker and fills it in with information,
     * but does not add it to the BOARD.  Use this to report any kind of
212 213
     * DRC problem, or unconnected pad problem.
     *
214
     * @param aTrack The reference track.
215
     * @param aItem  Another item on the BOARD, such as a SEGVIA, SEGZONE,
216
     *               or TRACK.
217
     * @param aErrorCode A categorizing identifier for the particular type
218
     *                   of error that is being reported.
219
     * @param fillMe A MARKER_PCB* which is to be filled in, or NULL if one is to
220
     *               first be allocated, then filled.
221
     */
222
    MARKER_PCB* fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe );
223

224
    MARKER_PCB* fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER_PCB* fillMe );
225

226
    MARKER_PCB* fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe );
227 228 229 230 231 232 233

    /**
     * Function fillMarker
     * optionally creates a marker and fills it in with information,
     * but does not add it to the BOARD.  Use this to report any kind of
     * DRC problem, or unconnected pad problem.
     *
234
     * @param aArea The zone to test
235 236
     * @param aPos position of error
     * @param aErrorCode  Type of error
237
     * @param fillMe A MARKER_PCB* which is to be filled in, or NULL if one is to
238
     *               first be allocated, then filled.
239
     */
240 241 242 243
    MARKER_PCB* fillMarker( const ZONE_CONTAINER* aArea,
                            const wxPoint&        aPos,
                            int                   aErrorCode,
                            MARKER_PCB*           fillMe );
244

245 246 247 248 249 250 251
    /**
     * Function fillMarker
     * fills a MARKER which will report on a generic problem with the board which is
     * not geographically locatable.
     */
    MARKER_PCB* fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe );

252

253 254
    //-----<categorical group tests>-----------------------------------------

255 256 257
    /**
     * Function testNetClasses
     * goes through each NETCLASS and verifies that its clearance, via size,
258
     * track width, and track clearance are larger than those in board.m_designSettings.
259 260 261 262 263 264
     * This is necessary because the actual DRC checks are run against the NETCLASS
     * limits, so in order enforce global limits, we first check the NETCLASSes against
     * the global limits.
     * @return bool - true if succes, else false but only after
     *  reporting _all_ NETCLASS violations.
     */
265
    bool testNetClasses();
266

267 268 269
    /**
     * Function testTracks
     * performs the DRC on all tracks.
270
     * because this test can take a while, a progress bar can be displayed
271
     * @param aShowProgressBar = true to show a progrsse bar
272
     * (Note: it is shown only if there are many tracks)
273 274
     */
    void testTracks( bool aShowProgressBar );
275

276
    void testPad2Pad();
277

278
    void testUnconnected();
279

280
    void testZones();
281

282
    void testKeepoutAreas();
283 284

    //-----<single "item" tests>-----------------------------------------
285

286
    bool doNetClass( NETCLASS* aNetClass, wxString& msg );
287

288 289 290 291 292 293 294
    /**
     * Function doPadToPadsDrc
     * tests the clearance between aRefPad and other pads.
     * The pad list must be sorted by x coordinate.
     * @param aRefPad The pad to test
     * @param aStart The start of the pad list to test against
     * @param aEnd Marks the end of the list and is not included
295
     * @param x_limit is used to stop the test (when the any pad's X coord exceeds this)
296
     */
297
    bool doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit );
298

299 300
    /**
     * Function DoTrackDrc
301
     * tests the current segment.
302 303
     * @param aRefSeg The segment to test
     * @param aStart The head of a list of tracks to test against (usually BOARD::m_Track)
304
     * @param doPads true if should do pads test
305
     * @return bool - true if no poblems, else false and m_currentMarker is
306 307
     *          filled in with the problem information.
     */
308
    bool doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool doPads = true );
309

310 311 312 313 314 315 316 317 318
    /**
     * Function doTrackKeepoutDrc
     * tests the current segment or via.
     * @param aRefSeg The segment to test
     * @return bool - true if no poblems, else false and m_currentMarker is
     *          filled in with the problem information.
     */
    bool doTrackKeepoutDrc( TRACK* aRefSeg );

319

dickelbeck's avatar
dickelbeck committed
320 321 322 323 324 325 326 327 328
    /**
     * Function doEdgeZoneDrc
     * tests a segment in ZONE_CONTAINER * aArea:
     *      Test Edge inside other areas
     *      Test Edge too close other areas
     * @param aArea The current area.
     * @param aCornerIndex The first corner of the segment to test.
     * @return bool - false if DRC error  or true if OK
     */
329
    bool doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex );
330

331 332 333 334 335 336
    //-----<single tests>----------------------------------------------

    /**
     * Function checkClearancePadToPad
     * @param aRefPad The reference pad to check
     * @param aPad Another pad to check against
337
     * @return bool - true if clearance between aRefPad and aPad is >= dist_min, else false
338
     */
339
    bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad );
340 341


342 343 344 345
    /**
     * Function checkClearanceSegmToPad
     * check the distance from a pad to segment.  This function uses several
     * instance variable not passed in:
346 347 348 349 350 351 352
     *      m_segmLength = length of the segment being tested
     *      m_segmAngle  = angle of the segment with the X axis;
     *      m_segmEnd    = end coordinate of the segment
     *      m_padToTestPos = position of pad relative to the origin of segment
     * @param aPad Is the pad involved in the check
     * @param aSegmentWidth width of the segment to test
     * @param aMinDist Is the minimum clearance needed
353
     *
354 355
     * @return true distance >= dist_min,
     *         false if distance < dist_min
356
     */
357
    bool checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist );
358

359 360

    /**
jean-pierre charras's avatar
jean-pierre charras committed
361 362 363 364 365 366
     * Helper function checkMarginToCircle
     * Check the distance from a point to
     * a segment. the segment is expected starting at 0,0, and on the X axis
     * (used to test DRC between a segment and a round pad, via or round end of a track
     * @param aCentre The coordinate of the circle's center
     * @param aRadius A "keep out" radius centered over the circle
367 368
     * @param aLength The length of the segment (i.e. coordinate of end, becuase it is on
     *                the X axis)
369
     * @return bool - true if distance >= radius, else
jean-pierre charras's avatar
jean-pierre charras committed
370
     *                false when distance < aRadius
371
     */
jean-pierre charras's avatar
jean-pierre charras committed
372
    static bool checkMarginToCircle( wxPoint aCentre, int aRadius, int aLength );
373

374

375 376
    /**
     * Function checkLine
377 378
     * (helper function used in drc calculations to see if one track is in contact with
     *  another track).
jean-pierre charras's avatar
jean-pierre charras committed
379 380 381
     * Test if a line intersects a bounding box (a rectangle)
     * The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi
     * return true if the line from aSegStart to aSegEnd is outside the bounding box
382
     */
jean-pierre charras's avatar
jean-pierre charras committed
383
    bool        checkLine( wxPoint aSegStart, wxPoint aSegEnd );
384

385
    //-----</single tests>---------------------------------------------
386

dickelbeck's avatar
dickelbeck committed
387
public:
388
    DRC( PCB_EDIT_FRAME* aPcbWindow );
389

dickelbeck's avatar
dickelbeck committed
390
    ~DRC();
391

392 393 394 395 396 397 398 399 400
    /**
     * Function Drc
     * tests the current segment and returns the result and displays the error
     * in the status panel only if one exists.
     * @param aRefSeg The current segment to test.
     * @param aList The track list to test (usually m_Pcb->m_Track)
     * @return int - BAD_DRC (1) if DRC error  or OK_DRC (0) if OK
     */
    int Drc( TRACK* aRefSeg, TRACK* aList );
401

dickelbeck's avatar
dickelbeck committed
402 403
    /**
     * Function Drc
404 405
     * tests the outline segment starting at CornerIndex and returns the result and displays
     * the error in the status panel only if one exists.
dickelbeck's avatar
dickelbeck committed
406 407
     *      Test Edge inside other areas
     *      Test Edge too close other areas
408 409
     * @param aArea The areaparent which contains the corner.
     * @param aCornerIndex The starting point of the segment to test.
dickelbeck's avatar
dickelbeck committed
410 411
     * @return int - BAD_DRC (1) if DRC error  or OK_DRC (0) if OK
     */
412
    int Drc( ZONE_CONTAINER* aArea, int aCornerIndex );
413

414 415
    /**
     * Function DrcBlind
416
     * tests the current segment and returns the result.  Any error is not
417 418 419 420 421 422 423 424
     * displayed in the status panel.
     * @param aRefSeg The current segment to test.
     * @param aList The track list to test (usually m_Pcb->m_Track)
     * @return int - BAD_DRC (1) if DRC error  or OK_DRC (0) if OK
     */
    int DrcBlind( TRACK* aRefSeg, TRACK* aList )
    {
        updatePointers();
425

426 427 428 429
        if( ! doTrackDrc( aRefSeg, aList ) )
            return BAD_DRC;

        return doTrackKeepoutDrc( aRefSeg ) ? OK_DRC : BAD_DRC;
dickelbeck's avatar
dickelbeck committed
430
    }
431

432

433 434
    /**
     * Function ShowDialog
435
     * opens a dialog and prompts the user, then if a test run button is
dickelbeck's avatar
dickelbeck committed
436 437
     * clicked, runs the test(s) and creates the MARKERS.  The dialog is only
     * created if it is not already in existence.
438
     */
439
    void ShowDialog();
dickelbeck's avatar
dickelbeck committed
440 441 442 443

    /**
     * Function DestroyDialog
     * deletes this ui dialog box and zeros out its pointer to remember
dickelbeck's avatar
dickelbeck committed
444 445
     * the state of the dialog's existence.
     * @param aReason Indication of which button was clicked to cause the destruction.
dickelbeck's avatar
dickelbeck committed
446
     */
447
    void DestroyDialog( int aReason );
448

dickelbeck's avatar
dickelbeck committed
449

dickelbeck's avatar
dickelbeck committed
450
    /**
451 452
     * Function SetSettings
     * saves all the UI or test settings and may be called before running the tests.
dickelbeck's avatar
dickelbeck committed
453 454 455
     * @param aPad2PadTest Tells whether to test pad to pad distances.
     * @param aUnconnectedTest Tells whether to list unconnected pads.
     * @param aZonesTest Tells whether to test zones.
456
     * @param aKeepoutTest Tells whether to test keepout areas.
457
     * @param aReportName A string telling the disk file report name entered.
458
     * @param aSaveReport A boolean telling whether to generate disk file report.
dickelbeck's avatar
dickelbeck committed
459
     */
460
    void SetSettings( bool aPad2PadTest, bool aUnconnectedTest,
461 462
                      bool aZonesTest, bool aKeepoutTest,
                      const wxString& aReportName, bool aSaveReport )
dickelbeck's avatar
dickelbeck committed
463
    {
464 465
        m_doPad2PadTest     = aPad2PadTest;
        m_doUnconnectedTest = aUnconnectedTest;
466
        m_doZonesTest       = aZonesTest;
467
        m_doKeepoutTest     = aKeepoutTest;
468 469
        m_rptFilename       = aReportName;
        m_doCreateRptFile   = aSaveReport;
dickelbeck's avatar
dickelbeck committed
470
    }
471

472

473 474 475 476
    /**
     * Function RunTests
     * will actually run all the tests specified with a previous call to
     * SetSettings()
477
     * @param aMessages = a wxTextControl where to display some activity messages. Can be NULL
478
     */
479
    void RunTests( wxTextCtrl* aMessages = NULL );
480

dickelbeck's avatar
dickelbeck committed
481 482
    /**
     * Function ListUnconnectedPad
483
     * gathers a list of all the unconnected pads and shows them in the
dickelbeck's avatar
dickelbeck committed
484 485
     * dialog, and optionally prints a report of such.
     */
486
    void ListUnconnectedPads();
487 488 489 490 491 492 493 494 495

    /**
     * @return a pointer to the current marker (last created marker
     */
    MARKER_PCB* GetCurrentMarker( )
    {
        return m_currentMarker;
    }

dickelbeck's avatar
dickelbeck committed
496 497 498 499 500 501
};


#endif  // _DRC_STUFF_H

//EOF