Commit 0f725ee2 authored by charras's avatar charras

DRC: added test pads to holes (pcbnew). Others minor changes

parent aa45e5a4
......@@ -5,6 +5,14 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.
2009-mar-16 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++pcbnew:
in DRC: added test pads to holes.
++Al:
minor changes.
2009-mar-16 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
......
......@@ -198,7 +198,9 @@ wxString MakeFileName( const wxString& dir,
{
if( !wxIsAbsolutePath( shortname ) )
{
if( !shortname.StartsWith( wxT( "./" ) ) && !shortname.StartsWith( wxT( "../" ) ) )
if( !shortname.StartsWith( wxT( "./" ) ) && !shortname.StartsWith( wxT( "../" ) ) // under unix
&& !shortname.StartsWith( wxT( ".\\" ) ) && !shortname.StartsWith( wxT( "..\\" ) )) // under Windows
{ /* no absolute path in shortname, add dir to shortname */
fullfilename = dir;
}
......
......@@ -190,7 +190,7 @@
<property name="name">orientationRadioBox</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="selection">3</property>
<property name="selection">0</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
<property name="subclass"></property>
......@@ -255,7 +255,7 @@
<property name="name">mirrorRadioBox</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="selection">2</property>
<property name="selection">0</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
<property name="subclass"></property>
......@@ -872,7 +872,7 @@
<property name="name">m_StyleRadioBox</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="selection">3</property>
<property name="selection">0</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
<property name="subclass"></property>
......
......@@ -39,7 +39,7 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP(
wxString orientationRadioBoxChoices[] = { _("0"), _("+90"), _("180"), _("-90") };
int orientationRadioBoxNChoices = sizeof( orientationRadioBoxChoices ) / sizeof( wxString );
orientationRadioBox = new wxRadioBox( this, wxID_ANY, _("Orientation (Degrees)"), wxDefaultPosition, wxDefaultSize, orientationRadioBoxNChoices, orientationRadioBoxChoices, 1, wxRA_SPECIFY_COLS );
orientationRadioBox->SetSelection( 3 );
orientationRadioBox->SetSelection( 0 );
orientationRadioBox->SetToolTip( _("Select if the component is to be rotated when drawn") );
orientationSizer->Add( orientationRadioBox, 1, wxALL, 8 );
......@@ -52,7 +52,7 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP(
wxString mirrorRadioBoxChoices[] = { _("Normal"), _("Mirror ---"), _("Mirror |") };
int mirrorRadioBoxNChoices = sizeof( mirrorRadioBoxChoices ) / sizeof( wxString );
mirrorRadioBox = new wxRadioBox( this, wxID_ANY, _("Mirror"), wxDefaultPosition, wxDefaultSize, mirrorRadioBoxNChoices, mirrorRadioBoxChoices, 1, wxRA_SPECIFY_COLS );
mirrorRadioBox->SetSelection( 2 );
mirrorRadioBox->SetSelection( 0 );
mirrorRadioBox->SetToolTip( _("Pick the graphical transformation to be used when displaying the component, if any") );
mirrorSizer->Add( mirrorRadioBox, 1, wxALL, 8 );
......@@ -134,7 +134,7 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP(
wxString m_StyleRadioBoxChoices[] = { _("Normal"), _("Italic"), _("Bold"), _("Bold Italic") };
int m_StyleRadioBoxNChoices = sizeof( m_StyleRadioBoxChoices ) / sizeof( wxString );
m_StyleRadioBox = new wxRadioBox( this, wxID_ANY, _("Style:"), wxDefaultPosition, wxDefaultSize, m_StyleRadioBoxNChoices, m_StyleRadioBoxChoices, 1, wxRA_SPECIFY_COLS );
m_StyleRadioBox->SetSelection( 3 );
m_StyleRadioBox->SetSelection( 0 );
m_StyleRadioBox->SetToolTip( _("The style of the currently selected field's text in the schemati") );
visibilitySizer->Add( m_StyleRadioBox, 1, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
......
......@@ -3,7 +3,7 @@
#ifndef KICAD_BUILD_VERSION
#define KICAD_BUILD_VERSION
#define BUILD_VERSION wxT("(20090216-final)")
#define BUILD_VERSION wxT("(20090332-unstable)")
COMMON_GLOBL wxString g_BuildVersion
#ifdef EDA_BASE
......
......@@ -73,6 +73,10 @@ wxString DRC_ITEM::GetErrorText() const
return wxString( _("Copper areas intersect or are too close"));
case DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE:
return wxString( _("Copper area has a non existent net name"));
case DRCE_HOLE_NEAR_PAD:
return wxString( _("Hole near pad"));
case DRCE_HOLE_NEAR_TRACK:
return wxString( _("Hole near track"));
default:
......
......@@ -79,6 +79,7 @@ public:
* @return const wxString * , a pointer to the full netname
*/
wxString GetNetname() const { return m_Netname; }
/**
* Function GetShortNetname
* @return const wxString * , a pointer to the short netname
......@@ -89,13 +90,13 @@ public:
* Function SetNetname
* @param const wxString : the new netname
*/
void SetNetname( const wxString & aNetname );
void SetNetname( const wxString& aNetname );
/**
* Function GetShape
* @return the shape of this pad.
*/
int GetShape( ) { return (m_PadShape & 0xFF); }
int GetShape() { return m_PadShape & 0xFF; }
/**
* Function GetPosition
......@@ -113,6 +114,7 @@ public:
m_Pos = aPos;
}
/* Reading and writing data on files */
int ReadDescr( FILE* File, int* LineNum = NULL );
......@@ -202,7 +204,7 @@ public:
static int Compare( const D_PAD* padref, const D_PAD* padcmp );
#if defined (DEBUG)
#if defined(DEBUG)
/**
* Function Show
......@@ -216,4 +218,4 @@ public:
#endif
};
typedef class D_PAD * LISTE_PAD;
typedef class D_PAD* LISTE_PAD;
......@@ -362,8 +362,8 @@ void D_PAD::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin
}
RotatePoint( &delta_cx, &delta_cy, angle );
GRFillCSegm( &panel->m_ClipBox, DC, ux0 + delta_cx, uy0 + delta_cy,
ux0 - delta_cx, uy0 - delta_cy,
GRFillCSegm( &panel->m_ClipBox, DC, cx0 + delta_cx, cy0 + delta_cy,
cx0 - delta_cx, cy0 - delta_cy,
rotdx, color );
break;
......
......@@ -74,7 +74,7 @@ void DRC::ShowDialog()
else
updatePointers();
m_ui->Show(true);
m_ui->Show( true );
}
......@@ -132,13 +132,15 @@ DRC::DRC( WinEDA_PcbFrame* aPcbWindow )
m_drawPanel = 0;
}
DRC::~DRC()
{
// maybe someday look at pointainer.h <- google for "pointainer.h"
for( unsigned i=0; i<m_unconnected.size(); ++i )
for( unsigned i = 0; i<m_unconnected.size(); ++i )
delete m_unconnected[i];
}
/*********************************************/
int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
/*********************************************/
......@@ -158,8 +160,9 @@ int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
/**************************************************************/
int DRC::Drc( ZONE_CONTAINER * aArea, int CornerIndex )
int DRC::Drc( ZONE_CONTAINER* aArea, int CornerIndex )
/*************************************************************/
/**
* Function Drc
* tests the outline segment starting at CornerIndex and returns the result and displays the error
......@@ -173,7 +176,7 @@ int DRC::Drc( ZONE_CONTAINER * aArea, int CornerIndex )
{
updatePointers();
if( ! doEdgeZoneDrc( aArea, CornerIndex ) )
if( !doEdgeZoneDrc( aArea, CornerIndex ) )
{
wxASSERT( m_currentMarker );
m_currentMarker->Display_Infos( m_mainWindow );
......@@ -184,7 +187,6 @@ int DRC::Drc( ZONE_CONTAINER * aArea, int CornerIndex )
}
void DRC::RunTests()
{
// Ensure ratsnest is up to date:
......@@ -216,7 +218,6 @@ void DRC::RunTests()
}
/***************************************************************/
void DRC::ListUnconnectedPads()
/***************************************************************/
......@@ -234,7 +235,7 @@ void DRC::updatePointers()
m_drawPanel = m_mainWindow->DrawPanel;
m_pcb = m_mainWindow->GetBoard();
if ( m_ui ) // Use diag list boxes only in DRC dialog
if( m_ui ) // Use diag list boxes only in DRC dialog
{
m_ui->m_ClearanceListBox->SetList( new DRC_LIST_MARKERS( m_pcb ) );
......@@ -245,7 +246,7 @@ void DRC::updatePointers()
void DRC::testTracks()
{
for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm=segm->Next() )
for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
{
if( !doTrackDrc( segm, segm->Next(), true ) )
{
......@@ -257,7 +258,9 @@ void DRC::testTracks()
}
/***********************/
void DRC::testPad2Pad()
/***********************/
{
std::vector<D_PAD*> sortedPads;
......@@ -266,18 +269,18 @@ void DRC::testPad2Pad()
// find the max size of the pads (used to stop the test)
int max_size = 0;
for( unsigned i=0; i<sortedPads.size(); ++i )
for( unsigned i = 0; i<sortedPads.size(); ++i )
{
D_PAD* pad = sortedPads[i];
if( pad->m_Rayon > max_size )
if( pad->m_Rayon > max_size ) // m_Rayon is the radius value of the circle containing the pad
max_size = pad->m_Rayon;
}
// Test the pads
D_PAD** listEnd = &sortedPads[ sortedPads.size() ];
for( unsigned i=0; i<sortedPads.size(); ++i )
for( unsigned i = 0; i<sortedPads.size(); ++i )
{
D_PAD* pad = sortedPads[i];
......@@ -303,7 +306,7 @@ void DRC::testUnconnected()
return;
CHEVELU* rat = m_pcb->m_Ratsnest;
for( int i=0; i<m_pcb->GetNumRatsnests(); ++i, ++rat )
for( int i = 0; i<m_pcb->GetNumRatsnests(); ++i, ++rat )
{
if( (rat->status & CH_ACTIF) == 0 )
continue;
......@@ -312,18 +315,18 @@ void DRC::testUnconnected()
D_PAD* padEnd = rat->pad_end;
DRC_ITEM* uncItem = new DRC_ITEM( DRCE_UNCONNECTED_PADS, padStart->GetPosition(),
padStart->MenuText(m_pcb), padEnd->MenuText(m_pcb),
padStart->MenuText( m_pcb ), padEnd->MenuText( m_pcb ),
padStart->GetPosition(), padEnd->GetPosition() );
m_unconnected.push_back( uncItem );
}
}
/**********************************************/
void DRC::testZones(bool adoTestFillSegments)
void DRC::testZones( bool adoTestFillSegments )
/**********************************************/
{
// Test copper areas for valide netcodes
// if a netcode is < 0 the netname was not found when reading a netlist
// if a netcode is == 0 the netname is void, and the zone is not connected.
......@@ -331,7 +334,7 @@ void DRC::testZones(bool adoTestFillSegments)
for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* Area_To_Test = m_pcb->GetArea( ii );
if( ! Area_To_Test->IsOnCopperLayer() )
if( !Area_To_Test->IsOnCopperLayer() )
continue;
if( Area_To_Test->GetNet() < 0 )
{
......@@ -417,7 +420,7 @@ MARKER* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKE
if( fillMe )
{
if ( aItem )
if( aItem )
fillMe->SetData( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
......@@ -427,7 +430,7 @@ MARKER* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKE
}
else
{
if ( aItem )
if( aItem )
fillMe = new MARKER( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
......@@ -456,7 +459,8 @@ MARKER* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER* fillM
return fillMe;
}
MARKER* DRC::fillMarker( ZONE_CONTAINER * aArea, int aErrorCode, MARKER* fillMe )
MARKER* DRC::fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
......@@ -471,7 +475,10 @@ MARKER* DRC::fillMarker( ZONE_CONTAINER * aArea, int aErrorCode, MARKER* fillMe
}
MARKER* DRC::fillMarker( const ZONE_CONTAINER * aArea, const wxPoint & aPos, int aErrorCode, MARKER* fillMe )
MARKER* DRC::fillMarker( const ZONE_CONTAINER* aArea,
const wxPoint& aPos,
int aErrorCode,
MARKER* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
......@@ -515,41 +522,38 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( aRefSeg->Type() == TYPE_VIA )
{
// test if via's hole is bigger than its diameter
// This test seems necessary since the dialog box that displays the
// desired via hole size and width does not enforce a hole size smaller
// than the via's diameter.
// This test is necessary since the via hole size and width can be modified
// and an default via hole can be bigger than some vias sizes
if( aRefSeg->GetDrillValue() > aRefSeg->m_Width )
{
#if 0 // a temporary way to fix a bad board here, change for your values
if( aRefSeg->GetDrillValue()==120 && aRefSeg->m_Width==100 )
aRefSeg->m_Width = 180;
#else
m_currentMarker = fillMarker( aRefSeg, NULL,
DRCE_VIA_HOLE_BIGGER, m_currentMarker );
return false;
#endif
}
// For microvias: test if they are blindvias and only between 2 layers
// For microvias: test if they are blind vias and only between 2 layers
// because they are used for very small drill size and are drill by laser
// and **only** one layer can be drilled
if( aRefSeg->Shape() == VIA_MICROVIA )
{
int layer1, layer2;
bool err = true;
((SEGVIA*)aRefSeg)->ReturnLayerPair(&layer1, &layer2);
if (layer1> layer2 ) EXCHG(layer1,layer2);
( (SEGVIA*) aRefSeg )->ReturnLayerPair( &layer1, &layer2 );
if( layer1> layer2 )
EXCHG( layer1, layer2 );
// test:
if (layer1 == COPPER_LAYER_N && layer2 == LAYER_N_2 ) err = false;
if (layer1 == (g_DesignSettings.m_CopperLayerCount - 2 ) && layer2 == LAYER_CMP_N ) err = false;
if ( err )
if( layer1 == COPPER_LAYER_N && layer2 == LAYER_N_2 )
err = false;
if( layer1 == (g_DesignSettings.m_CopperLayerCount - 2 ) && layer2 == LAYER_CMP_N )
err = false;
if( err )
{
m_currentMarker = fillMarker( aRefSeg, NULL,
DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR, m_currentMarker );
return false;
}
}
}
// for a non horizontal or vertical segment Compute the segment angle
......@@ -577,7 +581,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( testPads )
{
for( unsigned ii=0; ii<m_pcb->m_Pads.size(); ++ii )
for( unsigned ii = 0; ii<m_pcb->m_Pads.size(); ++ii )
{
D_PAD* pad = m_pcb->m_Pads[ii];
......@@ -615,8 +619,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
/* The pad must be in a net (i.e pt_pad->GetNet() != 0 )
* but no problem if the pad netcode is the current netcode (same net)
*/
if( pad->GetNet() && // the pad must be connected
net_code_ref == pad->GetNet() ) // the pad net is the same as current net -> Ok
if( pad->GetNet() // the pad must be connected
&& net_code_ref == pad->GetNet() ) // the pad net is the same as current net -> Ok
continue;
// DRC for the pad
......@@ -639,7 +643,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// At this point the reference segment is the X axis
// Test the reference segment with other track segments
for( track=aStart; track; track=track->Next() )
for( track = aStart; track; track = track->Next() )
{
// coord des extremites du segment teste dans le repere modifie
int x0;
......@@ -897,7 +901,12 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
int x_limite = max_size + g_DesignSettings.m_TrackClearence +
aRefPad->m_Rayon + aRefPad->GetPosition().x;
for( LISTE_PAD* pad_list=aStart; pad_list<aEnd; ++pad_list )
static D_PAD dummypad( (MODULE*) NULL ); // used to test DRC pad to holes: this dummypad is the hole to test
dummypad.m_Masque_Layer = ALL_CU_LAYERS;
for( LISTE_PAD* pad_list = aStart; pad_list<aEnd; ++pad_list )
{
D_PAD* pad = *pad_list;
if( pad == aRefPad )
......@@ -908,18 +917,66 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
if( pad->m_Pos.x > x_limite )
break;
/* No probleme if pads are on different copper layers */
/* No problem if pads are on different copper layers,
* but their hole (if any ) can create RDC error because they are on all copper layers, so we test them
*/
if( (pad->m_Masque_Layer & layerMask ) == 0 )
{
/* if holes are in the same location and have the same size and shape, this can be accepted */
if( pad->GetPosition() == aRefPad->GetPosition()
&& pad->m_Drill == aRefPad->m_Drill
&& pad->m_DrillShape == aRefPad->m_DrillShape )
{
if( aRefPad->m_DrillShape == PAD_CIRCLE )
continue;
if( pad->m_Orient == aRefPad->m_Orient ) // for oval holes: must also have the same orientation
continue;
}
/* Here, we must test clearance between holes and pads
* dummypad size and shape is adjusted to pad drill size and shape
*/
if( pad->m_Drill.x ) // pad under testing has a hole, test this hole against pad reference
{
dummypad.SetPosition( pad->GetPosition() );
dummypad.m_Size = pad->m_Drill;
dummypad.m_PadShape = pad->m_DrillShape == PAD_OVAL ? PAD_OVAL : PAD_CIRCLE;
dummypad.m_Orient = pad->m_Orient;
if( !checkClearancePadToPad( aRefPad, &dummypad, g_DesignSettings.m_TrackClearence ) )
{
// here we have a drc error on pad!
m_currentMarker = fillMarker( pad, aRefPad,
DRCE_HOLE_NEAR_PAD, m_currentMarker );
return false;
}
}
if( aRefPad->m_Drill.x ) // pad reference has a hole
{
dummypad.SetPosition( aRefPad->GetPosition() );
dummypad.m_Size = aRefPad->m_Drill;
dummypad.m_PadShape = aRefPad->m_DrillShape == PAD_OVAL ? PAD_OVAL : PAD_CIRCLE;
dummypad.m_Orient = aRefPad->m_Orient;
if( !checkClearancePadToPad( pad, &dummypad, g_DesignSettings.m_TrackClearence ) )
{
// here we have a drc erroron aRefPad!
m_currentMarker = fillMarker( aRefPad, pad,
DRCE_HOLE_NEAR_PAD, m_currentMarker );
return false;
}
}
continue;
}
/* The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
* But no problem if pads have the same netcode (same net)*/
if( pad->GetNet() && (aRefPad->GetNet() == pad->GetNet()) )
if( pad->GetNet() && ( aRefPad->GetNet() == pad->GetNet() ) )
continue;
/* No problem if pads are from the same footprint
* and have the same pad number ( equivalent pads ) */
if( (pad->GetParent() == aRefPad->GetParent()) && (pad->m_NumPadName == aRefPad->m_NumPadName) )
if( ( pad->GetParent() == aRefPad->GetParent() )
&& (pad->m_NumPadName == aRefPad->m_NumPadName) )
continue;
if( !checkClearancePadToPad( aRefPad, pad, g_DesignSettings.m_TrackClearence ) )
......@@ -941,6 +998,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, const int dist_mi
{
wxPoint rel_pos;
int dist;;
wxPoint shape_pos;
int pad_angle;
......@@ -998,8 +1056,8 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, const int dist_mi
if( aPad->m_PadShape == PAD_RECT )
{
wxSize size = aPad->m_Size;
if( (pad_angle == 0) || (pad_angle == 900) || (pad_angle == 1800) ||
(pad_angle == 2700) )
if( (pad_angle == 0) || (pad_angle == 900) || (pad_angle == 1800)
|| (pad_angle == 2700) )
{
if( (pad_angle == 900) || (pad_angle == 2700) )
{
......@@ -1057,6 +1115,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, const int dist_mi
break;
}
case PAD_TRAPEZOID:
default:
/* TODO...*/
break;
......@@ -1227,6 +1286,7 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int dis
return true;
}
/**********************************************************************/
bool DRC::checkMarginToCircle( int cx, int cy, int radius, int longueur )
/**********************************************************************/
......@@ -1250,7 +1310,6 @@ bool DRC::checkMarginToCircle( int cx, int cy, int radius, int longueur )
}
/**********************************************/
/* int Tst_Ligne(int x1,int y1,int x2,int y2) */
/**********************************************/
......@@ -1363,12 +1422,11 @@ bool DRC::checkLine( int x1, int y1, int x2, int y2 )
}
}
if( ( (x2 + x1)/2 <= m_xcliphi ) && ( (x2 + x1)/2 >= m_xcliplo ) \
&& ( (y2 + y1)/2 <= m_ycliphi ) && ( (y2 + y1)/2 >= m_ycliplo ) )
if( ( (x2 + x1) / 2 <= m_xcliphi ) && ( (x2 + x1) / 2 >= m_xcliplo ) \
&& ( (y2 + y1) / 2 <= m_ycliphi ) && ( (y2 + y1) / 2 >= m_ycliplo ) )
{
return false;
}
else
return true;
}
......@@ -58,6 +58,8 @@
#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
/**
* Class DRC_ITEM
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment