summaryrefslogtreecommitdiff
path: root/pcbnew/drc_stuff.h
blob: 7441c964da4cc6295776a6e119f14b476cf6b093 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
/**
 * @file drc_stuff.h
 */

/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
 * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors.
 *
 * 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

#include <vector>
#include <boost/shared_ptr.hpp>

#define OK_DRC  0
#define BAD_DRC 1


/// DRC error codes:
#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
#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
#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_SUSPICIOUS_NET_FOR_ZONE_OUTLINE   24   ///< copper area has a net but no pads in nets, which is suspicious
#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
#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
#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
#define DRCE_VIA_INSIDE_TEXT                   39   ///< Via in inside a text area
#define DRCE_TRACK_INSIDE_TEXT                 40   ///< Track in inside a text area
#define DRCE_PAD_INSIDE_TEXT                   41   ///< Pad in inside a text area


class EDA_DRAW_PANEL;
class PCB_EDIT_FRAME;
class DIALOG_DRC_CONTROL;
class BOARD_ITEM;
class BOARD;
class D_PAD;
class ZONE_CONTAINER;
class TRACK;
class MARKER_PCB;
class DRC_ITEM;
class NETCLASS;


/**
 * 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.
     */
    virtual void DeleteAllItems() = 0;

    /**
     * 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.
     */
    virtual const DRC_ITEM* GetItem( int aIndex ) = 0;

    /**
     * Function DeleteAllItems
     * removes and deletes desired item from the list.
     * @param aIndex The 0 based index into the list of the desired item which
     *         is to be deleted.
     */
    virtual void DeleteItem( int aIndex ) = 0;

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

    virtual ~DRC_ITEM_LIST() { }
};


typedef std::vector<DRC_ITEM*> DRC_LIST;


/**
 * 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.
 */
class DRC
{
    friend class DIALOG_DRC_CONTROL;

private:

    //  protected or private functions() are lowercase first character.

    bool     m_doPad2PadTest;
    bool     m_doUnconnectedTest;
    bool     m_doZonesTest;
    bool     m_doKeepoutTest;
    bool     m_doCreateRptFile;

    wxString m_rptFilename;

    MARKER_PCB* m_currentMarker;

    bool        m_abortDRC;
    bool        m_drcInProgress;

    /* 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
     */
    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) )

    /* 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)
     */
    double m_segmAngle;     // Ref segm orientation in 0,1 degre
    int m_segmLength;       // length of the reference segment

    /* variables used in checkLine to test DRC segm to segm:
     * define the area relative to the ref segment that does not contains any other segment
     */
    int                 m_xcliplo;
    int                 m_ycliplo;
    int                 m_xcliphi;
    int                 m_ycliphi;

    PCB_EDIT_FRAME*     m_mainWindow;
    BOARD*              m_pcb;
    DIALOG_DRC_CONTROL* m_drcDialog;

    DRC_LIST            m_unconnected;  ///< list of unconnected pads, as DRC_ITEMs


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


    /**
     * 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.
     *
     * @param aTrack The reference track.
     * @param aItem  Another item on the BOARD, such as a VIA, SEGZONE,
     *               or TRACK.
     * @param aErrorCode A categorizing identifier for the particular type
     *                   of error that is being reported.
     * @param fillMe A MARKER_PCB* which is to be filled in, or NULL if one is to
     *               first be allocated, then filled.
     */
    MARKER_PCB* fillMarker( const TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe );

    MARKER_PCB* fillMarker( D_PAD* aPad, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe );

    MARKER_PCB* fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe );

    /**
     * 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.
     *
     * @param aArea The zone to test
     * @param aPos position of error
     * @param aErrorCode  Type of error
     * @param fillMe A MARKER_PCB* which is to be filled in, or NULL if one is to
     *               first be allocated, then filled.
     */
    MARKER_PCB* fillMarker( const ZONE_CONTAINER* aArea,
                            const wxPoint&        aPos,
                            int                   aErrorCode,
                            MARKER_PCB*           fillMe );

    /**
     * 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 );


    //-----<categorical group tests>-----------------------------------------

    /**
     * Function testNetClasses
     * goes through each NETCLASS and verifies that its clearance, via size,
     * track width, and track clearance are larger than those in board.m_designSettings.
     * 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.
     */
    bool testNetClasses();

    /**
     * Function testTracks
     * performs the DRC on all tracks.
     * because this test can take a while, a progress bar can be displayed
     * @param aActiveWindow = the active window ued as parent for the progress bar
     * @param aShowProgressBar = true to show a progress bar
     * (Note: it is shown only if there are many tracks)
     */
    void testTracks( wxWindow * aActiveWindow, bool aShowProgressBar );

    void testPad2Pad();

    void testUnconnected();

    void testZones();

    void testKeepoutAreas();

    void testTexts();

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

    bool doNetClass( boost::shared_ptr<NETCLASS> aNetClass, wxString& msg );

    /**
     * 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
     * @param x_limit is used to stop the test (when the any pad's X coord exceeds this)
     */
    bool doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit );

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

    /**
     * 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 );


    /**
     * 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
     */
    bool doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex );

    //-----<single tests>----------------------------------------------

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


    /**
     * Function checkClearanceSegmToPad
     * check the distance from a pad to segment.  This function uses several
     * instance variable not passed in:
     *      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
     *
     * @return true distance >= dist_min,
     *         false if distance < dist_min
     */
    bool checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist );


    /**
     * 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
     * @param aLength The length of the segment (i.e. coordinate of end, becuase it is on
     *                the X axis)
     * @return bool - true if distance >= radius, else
     *                false when distance < aRadius
     */
    static bool checkMarginToCircle( wxPoint aCentre, int aRadius, int aLength );


    /**
     * Function checkLine
     * (helper function used in drc calculations to see if one track is in contact with
     *  another track).
     * 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
     */
    bool        checkLine( wxPoint aSegStart, wxPoint aSegEnd );

    //-----</single tests>---------------------------------------------

public:
    DRC( PCB_EDIT_FRAME* aPcbWindow );

    ~DRC();

    /**
     * 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 );

    /**
     * Function Drc
     * tests the outline segment starting at CornerIndex and returns the result and displays
     * the error in the status panel only if one exists.
     *      Test Edge inside other areas
     *      Test Edge too close other areas
     * @param aArea The areaparent which contains the corner.
     * @param aCornerIndex The starting point of the segment to test.
     * @return int - BAD_DRC (1) if DRC error  or OK_DRC (0) if OK
     */
    int Drc( ZONE_CONTAINER* aArea, int aCornerIndex );

    /**
     * Function DrcBlind
     * tests the current segment and returns the result.  Any error is not
     * 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();

        if( ! doTrackDrc( aRefSeg, aList ) )
            return BAD_DRC;

        return doTrackKeepoutDrc( aRefSeg ) ? OK_DRC : BAD_DRC;
    }


    /**
     * Function ShowDialog
     * opens a dialog and prompts the user, then if a test run button is
     * clicked, runs the test(s) and creates the MARKERS.  The dialog is only
     * created if it is not already in existence.
     */
    void ShowDialog();

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


    /**
     * Function SetSettings
     * saves all the UI or test settings and may be called before running the tests.
     * @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.
     * @param aKeepoutTest Tells whether to test keepout areas.
     * @param aReportName A string telling the disk file report name entered.
     * @param aSaveReport A boolean telling whether to generate disk file report.
     */
    void SetSettings( bool aPad2PadTest, bool aUnconnectedTest,
                      bool aZonesTest, bool aKeepoutTest,
                      const wxString& aReportName, bool aSaveReport )
    {
        m_doPad2PadTest     = aPad2PadTest;
        m_doUnconnectedTest = aUnconnectedTest;
        m_doZonesTest       = aZonesTest;
        m_doKeepoutTest     = aKeepoutTest;
        m_rptFilename       = aReportName;
        m_doCreateRptFile   = aSaveReport;
    }


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

    /**
     * Function ListUnconnectedPad
     * gathers a list of all the unconnected pads and shows them in the
     * dialog, and optionally prints a report of such.
     */
    void ListUnconnectedPads();

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

};


#endif  // _DRC_STUFF_H

//EOF