Commit f8f35a8c authored by Dr. Thomas Spindler's avatar Dr. Thomas Spindler Committed by Dick Hollenbeck

specctra_export supports interior polygons and circles on the Edge.Cuts layer.

Interior regions on Edge.Cuts are out as keepouts for specctra DSN file
and downstream routers.  Point to point matching during polygon assembly
can have individual thresholds, one for board edge and another for interior polygons.
This is more forgiving for sloppy graphical mousers, or those that work without
grid snap on.  Currently the threshold for board edge is at zero, meaning the
board edge has to be precisely defined as a polygon, just as before.  But it
is easily tunable for experimentation.
parent f50f31e5
...@@ -3704,14 +3704,14 @@ class SPECCTRA_DB : public SPECCTRA_LEXER ...@@ -3704,14 +3704,14 @@ class SPECCTRA_DB : public SPECCTRA_LEXER
//-----<FromBOARD>------------------------------------------------------- //-----<FromBOARD>-------------------------------------------------------
/** /**
* Function makeBOUNDARY * Function fillBOUNDARY
* makes the board perimeter for the DSN file. * makes the board perimeter for the DSN file by filling the BOUNDARY element
* in the specctra element tree.
* @param aBoard The BOARD to get information from in order to make the BOUNDARY. * @param aBoard The BOARD to get information from in order to make the BOUNDARY.
* @param aBoundary The empty BOUNDARY to fill in. * @param aBoundary The empty BOUNDARY to fill in.
*/ */
void fillBOUNDARY( BOARD* aBoard, BOUNDARY* aBoundary ) throw( IO_ERROR ); void fillBOUNDARY( BOARD* aBoard, BOUNDARY* aBoundary ) throw( IO_ERROR );
/** /**
* Function makeIMAGE * Function makeIMAGE
* allocates an IMAGE on the heap and creates all the PINs according * allocates an IMAGE on the heap and creates all the PINs according
...@@ -3722,7 +3722,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER ...@@ -3722,7 +3722,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER
*/ */
IMAGE* makeIMAGE( BOARD* aBoard, MODULE* aModule ); IMAGE* makeIMAGE( BOARD* aBoard, MODULE* aModule );
/** /**
* Function makePADSTACK * Function makePADSTACK
* creates a PADSTACK which matches the given pad. Only pads which do not * creates a PADSTACK which matches the given pad. Only pads which do not
...@@ -3755,7 +3754,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER ...@@ -3755,7 +3754,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER
*/ */
PADSTACK* makeVia( const SEGVIA* aVia ); PADSTACK* makeVia( const SEGVIA* aVia );
/** /**
* Function deleteNETs * Function deleteNETs
* deletes all the NETs that may be in here. * deletes all the NETs that may be in here.
...@@ -3768,14 +3766,12 @@ class SPECCTRA_DB : public SPECCTRA_LEXER ...@@ -3768,14 +3766,12 @@ class SPECCTRA_DB : public SPECCTRA_LEXER
nets.clear(); nets.clear();
} }
/** /**
* Function exportNETCLASS * Function exportNETCLASS
* exports \a aNetClass to the DSN file. * exports \a aNetClass to the DSN file.
*/ */
void exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ); void exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard );
//-----</FromBOARD>------------------------------------------------------ //-----</FromBOARD>------------------------------------------------------
//-----<FromSESSION>----------------------------------------------------- //-----<FromSESSION>-----------------------------------------------------
...@@ -3786,7 +3782,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER ...@@ -3786,7 +3782,6 @@ class SPECCTRA_DB : public SPECCTRA_LEXER
*/ */
TRACK* makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IO_ERROR ); TRACK* makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IO_ERROR );
/** /**
* Function makeVIA * Function makeVIA
* instantiates a KiCad SEGVIA on the heap and initializes it with internal * instantiates a KiCad SEGVIA on the heap and initializes it with internal
...@@ -3847,7 +3842,6 @@ public: ...@@ -3847,7 +3842,6 @@ public:
} }
SESSION* GetSESSION() { return session; } SESSION* GetSESSION() { return session; }
/** /**
* Function LoadPCB * Function LoadPCB
* is a recursive descent parser for a SPECCTRA DSN "design" file. * is a recursive descent parser for a SPECCTRA DSN "design" file.
...@@ -3859,7 +3853,6 @@ public: ...@@ -3859,7 +3853,6 @@ public:
*/ */
void LoadPCB( const wxString& filename ) throw( IO_ERROR ); void LoadPCB( const wxString& filename ) throw( IO_ERROR );
/** /**
* Function LoadSESSION * Function LoadSESSION
* is a recursive descent parser for a SPECCTRA DSN "session" file. * is a recursive descent parser for a SPECCTRA DSN "session" file.
...@@ -3872,10 +3865,8 @@ public: ...@@ -3872,10 +3865,8 @@ public:
*/ */
void LoadSESSION( const wxString& filename ) throw( IO_ERROR ); void LoadSESSION( const wxString& filename ) throw( IO_ERROR );
void ThrowIOError( const wxChar* fmt, ... ) throw( IO_ERROR ); void ThrowIOError( const wxChar* fmt, ... ) throw( IO_ERROR );
/** /**
* Function ExportPCB * Function ExportPCB
* writes the internal PCB instance out as a SPECTRA DSN format file. * writes the internal PCB instance out as a SPECTRA DSN format file.
...@@ -3887,7 +3878,6 @@ public: ...@@ -3887,7 +3878,6 @@ public:
*/ */
void ExportPCB( wxString aFilename, bool aNameChange=false ) throw( IO_ERROR ); void ExportPCB( wxString aFilename, bool aNameChange=false ) throw( IO_ERROR );
/** /**
* Function FromBOARD * Function FromBOARD
* adds the entire BOARD to the PCB but does not write it out. Note that * adds the entire BOARD to the PCB but does not write it out. Note that
......
...@@ -69,6 +69,41 @@ using namespace DSN; ...@@ -69,6 +69,41 @@ using namespace DSN;
static const double safetyMargin = 0.1; static const double safetyMargin = 0.1;
/**
* Function close_ness
* is a non-exact distance calculator used to approximate the distance between
* two points. The distance is very in-exact, but can be helpful when used
* to pick between alternative neighboring points.
* @param aLeft is the first point
* @param aRight is the second point
* @return unsigned - a measure of proximity that the caller knows about, in BIU,
* but remember it is only an approximation.
*/
static unsigned close_ness( const wxPoint& aLeft, const wxPoint& aRight )
{
// Don't need an accurate distance calculation, just something
// approximating it, for relative orering.
return unsigned( abs( aLeft.x - aRight.x ) + abs( aLeft.y - aRight.y ) );
}
/**
* Function close_enough
* is a local and tunable method of qualifying the proximity of two points.
*
* @param aLeft is the first point
* @param aRight is the second point
* @param aLimit is a measure of proximity that the caller knows about.
* @return bool - true if the two points are close enough, else false.
*/
inline bool close_enough( const wxPoint& aLeft, const wxPoint& aRight, unsigned aLimit )
{
// We don't use an accurate distance calculation, just something
// approximating it, since aLimit is non-exact anyway except when zero.
return close_ness( aLeft, aRight ) <= aLimit;
}
// see wxPcbStruct.h // see wxPcbStruct.h
void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
{ {
...@@ -76,11 +111,11 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) ...@@ -76,11 +111,11 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
wxString path; wxString path;
wxString name; wxString name;
wxString ext; wxString ext;
wxString dsn_ext = wxT( ".dsn" ); wxString dsn_ext = wxT( ".dsn" );
wxString mask = wxT( "*" ) + dsn_ext; wxString mask = wxT( "*" ) + dsn_ext;
wxFileName::SplitPath( fullFileName, &path, &name, &ext ); wxFileName::SplitPath( fullFileName, &path, &name, &ext );
name += dsn_ext; name += dsn_ext;
fullFileName = EDA_FileSelector( _( "Specctra DSN file:" ), fullFileName = EDA_FileSelector( _( "Specctra DSN file:" ),
...@@ -92,6 +127,7 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) ...@@ -92,6 +127,7 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
wxFD_SAVE, wxFD_SAVE,
false false
); );
if( fullFileName == wxEmptyString ) if( fullFileName == wxEmptyString )
return; return;
...@@ -104,7 +140,7 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) ...@@ -104,7 +140,7 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
db.SetPCB( SPECCTRA_DB::MakePCB() ); db.SetPCB( SPECCTRA_DB::MakePCB() );
SetLocaleTo_C_standard( ); // Switch the locale to standard C LOCALE_IO toggle; // Switch the locale to standard C
// DSN Images (=KiCad MODULES and pads) must be presented from the // DSN Images (=KiCad MODULES and pads) must be presented from the
// top view. So we temporarily flip any modules which are on the back // top view. So we temporarily flip any modules which are on the back
...@@ -128,12 +164,9 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) ...@@ -128,12 +164,9 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
errorText = ioe.errorText; errorText = ioe.errorText;
} }
SetLocaleTo_Default( ); // revert to the current locale
// done assuredly, even if an exception was thrown and caught. // done assuredly, even if an exception was thrown and caught.
db.RevertMODULEs( GetBoard() ); db.RevertMODULEs( GetBoard() );
// The two calls below to MODULE::Flip(), both set the // The two calls below to MODULE::Flip(), both set the
// modified flag, yet their actions cancel each other out, so it should // modified flag, yet their actions cancel each other out, so it should
// be ok to clear the modify flag. // be ok to clear the modify flag.
...@@ -154,8 +187,6 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) ...@@ -154,8 +187,6 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
namespace DSN { namespace DSN {
const KICAD_T SPECCTRA_DB::scanPADs[] = { PCB_PAD_T, EOT }; const KICAD_T SPECCTRA_DB::scanPADs[] = { PCB_PAD_T, EOT };
// "specctra reported units" are what we tell the external router that our // "specctra reported units" are what we tell the external router that our
...@@ -179,11 +210,12 @@ static inline double scale( int kicadDist ) ...@@ -179,11 +210,12 @@ static inline double scale( int kicadDist )
#else #else
// deci-mils to mils. // deci-mils to mils.
return kicadDist/10.0; return kicadDist / 10.0;
#endif #endif
} }
/// Convert integer internal units to float um
// / Convert integer internal units to float um
static inline double IU2um( int kicadDist ) static inline double IU2um( int kicadDist )
{ {
return kicadDist * (1000.0 / IU_PER_MM); return kicadDist * (1000.0 / IU_PER_MM);
...@@ -192,12 +224,13 @@ static inline double IU2um( int kicadDist ) ...@@ -192,12 +224,13 @@ static inline double IU2um( int kicadDist )
static inline double mapX( int x ) static inline double mapX( int x )
{ {
return scale(x); return scale( x );
} }
static inline double mapY( int y ) static inline double mapY( int y )
{ {
return -scale(y); // make y negative, since it is increasing going down. return -scale( y ); // make y negative, since it is increasing going down.
} }
...@@ -210,6 +243,7 @@ static inline double mapY( int y ) ...@@ -210,6 +243,7 @@ static inline double mapY( int y )
static POINT mapPt( const wxPoint& pt ) static POINT mapPt( const wxPoint& pt )
{ {
POINT ret; POINT ret;
ret.x = mapX( pt.x ); ret.x = mapX( pt.x );
ret.y = mapY( pt.y ); ret.y = mapY( pt.y );
ret.FixNegativeZero(); ret.FixNegativeZero();
...@@ -226,11 +260,16 @@ static POINT mapPt( const wxPoint& pt ) ...@@ -226,11 +260,16 @@ static POINT mapPt( const wxPoint& pt )
* @return DRAWSEGMENT* - The first DRAWSEGMENT that has a start or end point matching * @return DRAWSEGMENT* - The first DRAWSEGMENT that has a start or end point matching
* aPoint, otherwise NULL if none. * aPoint, otherwise NULL if none.
*/ */
static DRAWSEGMENT* findPoint( const wxPoint& aPoint, TYPE_COLLECTOR* items ) static DRAWSEGMENT* findPoint( const wxPoint& aPoint, TYPE_COLLECTOR* items, unsigned aLimit )
{ {
for( int i=0; i<items->GetCount(); ++i ) unsigned min_d = INT_MAX;
int ndx_min;
// find the point closest to aPoint and perhaps exactly matching aPoint.
for( int i = 0; i<items->GetCount(); ++i )
{ {
DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i]; DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i];
unsigned d;
wxASSERT( graphic->Type() == PCB_LINE_T ); wxASSERT( graphic->Type() == PCB_LINE_T );
...@@ -239,25 +278,60 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, TYPE_COLLECTOR* items ) ...@@ -239,25 +278,60 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, TYPE_COLLECTOR* items )
case S_ARC: case S_ARC:
if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() ) if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
{ {
items->Remove(i); items->Remove( i );
return graphic; return graphic;
} }
d = close_ness( aPoint, graphic->GetArcStart() );
if( d < min_d )
{
min_d = d;
ndx_min = i;
}
d = close_ness( aPoint, graphic->GetArcEnd() );
if( d < min_d )
{
min_d = d;
ndx_min = i;
}
break; break;
default: default:
if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() ) if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
{ {
items->Remove(i); items->Remove( i );
return graphic; return graphic;
} }
d = close_ness( aPoint, graphic->GetStart() );
if( d < min_d )
{
min_d = d;
ndx_min = i;
}
d = close_ness( aPoint, graphic->GetEnd() );
if( d < min_d )
{
min_d = d;
ndx_min = i;
}
}
} }
if( min_d <= aLimit )
{
DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[ndx_min];
items->Remove( ndx_min );
return graphic;
} }
#if defined(DEBUG) #if defined(DEBUG)
printf("Unable to find segment matching point (%d,%d)\n", printf( "Unable to find segment matching point (%d,%d)\n",
aPoint.x, aPoint.y ); aPoint.x, aPoint.y );
for( int i=0; i<items->GetCount(); ++i ) for( int i = 0; i< items->GetCount(); ++i )
{ {
DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i]; DRAWSEGMENT* graphic = (DRAWSEGMENT*) (*items)[i];
...@@ -330,7 +404,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -330,7 +404,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
uniqifier += 'A'; // A for all layers uniqifier += 'A'; // A for all layers
const int copperCount = aBoard->GetCopperLayerCount(); const int copperCount = aBoard->GetCopperLayerCount();
for( LAYER_NUM layer=FIRST_LAYER; layer<copperCount; ++layer ) for( int layer=0; layer<copperCount; ++layer )
{ {
LAYER_NUM kilayer = pcbLayer2kicad[layer]; LAYER_NUM kilayer = pcbLayer2kicad[layer];
...@@ -342,7 +416,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -342,7 +416,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
{ {
if( layer == 0 ) if( layer == 0 )
uniqifier += 'T'; uniqifier += 'T';
else if( layer == copperCount-1 ) else if( layer == copperCount - 1 )
uniqifier += 'B'; uniqifier += 'B';
else else
uniqifier += char('0' + layer); // layer index char uniqifier += char('0' + layer); // layer index char
...@@ -374,14 +448,16 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -374,14 +448,16 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
default: default:
case PAD_CIRCLE: case PAD_CIRCLE:
{ {
double diameter = scale(aPad->GetSize().x); double diameter = scale( aPad->GetSize().x );
for( LAYER_NUM ndx=FIRST_LAYER; ndx<reportedLayers; ++ndx ) for( int ndx=0; ndx<reportedLayers; ++ndx )
{ {
SHAPE* shape = new SHAPE( padstack ); SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape ); padstack->Append( shape );
CIRCLE* circle = new CIRCLE( shape ); CIRCLE* circle = new CIRCLE( shape );
shape->SetShape( circle ); shape->SetShape( circle );
circle->SetLayerId( layerName[ndx] ); circle->SetLayerId( layerName[ndx] );
...@@ -392,7 +468,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -392,7 +468,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
snprintf( name, sizeof(name), "Round%sPad_%.6g_um", snprintf( name, sizeof(name), "Round%sPad_%.6g_um",
uniqifier.c_str(), IU2um( aPad->GetSize().x ) ); uniqifier.c_str(), IU2um( aPad->GetSize().x ) );
name[ sizeof(name)-1 ] = 0; name[ sizeof(name) - 1 ] = 0;
padstack->SetPadstackId( name ); padstack->SetPadstackId( name );
} }
...@@ -409,12 +485,14 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -409,12 +485,14 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
lowerLeft += dsnOffset; lowerLeft += dsnOffset;
upperRight += dsnOffset; upperRight += dsnOffset;
for( LAYER_NUM ndx=FIRST_LAYER; ndx<reportedLayers; ++ndx ) for( int ndx=0; ndx<reportedLayers; ++ndx )
{ {
SHAPE* shape = new SHAPE( padstack ); SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape ); padstack->Append( shape );
RECTANGLE* rect = new RECTANGLE( shape ); RECTANGLE* rect = new RECTANGLE( shape );
shape->SetShape( rect ); shape->SetShape( rect );
rect->SetLayerId( layerName[ndx] ); rect->SetLayerId( layerName[ndx] );
...@@ -426,7 +504,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -426,7 +504,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
IU2um( aPad->GetSize().x ), IU2um( aPad->GetSize().x ),
IU2um( aPad->GetSize().y ) ); IU2um( aPad->GetSize().y ) );
name[ sizeof(name)-1 ] = 0; name[ sizeof(name) - 1 ] = 0;
padstack->SetPadstackId( name ); padstack->SetPadstackId( name );
} }
...@@ -460,12 +538,13 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -460,12 +538,13 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
start += dsnOffset; start += dsnOffset;
stop += dsnOffset; stop += dsnOffset;
for( LAYER_NUM ndx=FIRST_LAYER; ndx<reportedLayers; ++ndx ) for( int ndx=0; ndx<reportedLayers; ++ndx )
{ {
SHAPE* shape; SHAPE* shape;
PATH* path; PATH* path;
// see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408 // see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408
shape = new SHAPE( padstack ); shape = new SHAPE( padstack );
padstack->Append( shape ); padstack->Append( shape );
path = makePath( start, stop, layerName[ndx] ); path = makePath( start, stop, layerName[ndx] );
shape->SetShape( path ); shape->SetShape( path );
...@@ -476,7 +555,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -476,7 +555,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
uniqifier.c_str(), uniqifier.c_str(),
IU2um( aPad->GetSize().x ), IU2um( aPad->GetSize().x ),
IU2um( aPad->GetSize().y ) ); IU2um( aPad->GetSize().y ) );
name[ sizeof(name)-1 ] = 0; name[ sizeof(name) - 1 ] = 0;
padstack->SetPadstackId( name ); padstack->SetPadstackId( name );
} }
...@@ -501,13 +580,15 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -501,13 +580,15 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
upperRight += dsnOffset; upperRight += dsnOffset;
lowerRight += dsnOffset; lowerRight += dsnOffset;
for( LAYER_NUM ndx=FIRST_LAYER; ndx<reportedLayers; ++ndx ) for( int ndx=0; ndx<reportedLayers; ++ndx )
{ {
SHAPE* shape = new SHAPE( padstack ); SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape ); padstack->Append( shape );
// a T_polygon exists as a PATH // a T_polygon exists as a PATH
PATH* polygon = new PATH( shape, T_polygon ); PATH* polygon = new PATH( shape, T_polygon );
shape->SetShape( polygon ); shape->SetShape( polygon );
polygon->SetLayerId( layerName[ndx] ); polygon->SetLayerId( layerName[ndx] );
...@@ -518,7 +599,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) ...@@ -518,7 +599,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
polygon->AppendPoint( lowerRight ); polygon->AppendPoint( lowerRight );
} }
D(printf( "m_DeltaSize: %d,%d\n", aPad->GetDelta().x, aPad->GetDelta().y );) D( printf( "m_DeltaSize: %d,%d\n", aPad->GetDelta().x, aPad->GetDelta().y ); )
// this string _must_ be unique for a given physical shape // this string _must_ be unique for a given physical shape
snprintf( name, sizeof(name), "Trapz%sPad_%.6gx%.6g_%c%.6gx%c%.6g_um", snprintf( name, sizeof(name), "Trapz%sPad_%.6gx%.6g_%c%.6gx%c%.6g_um",
...@@ -568,12 +649,14 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -568,12 +649,14 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
POINT vertex = mapPt( pad->GetPos0() ); POINT vertex = mapPt( pad->GetPos0() );
int layerCount = aBoard->GetCopperLayerCount(); int layerCount = aBoard->GetCopperLayerCount();
for( LAYER_NUM layer=FIRST_LAYER; layer<layerCount; ++layer ) for( int layer=0; layer<layerCount; ++layer )
{ {
KEEPOUT* keepout = new KEEPOUT(image, T_keepout); KEEPOUT* keepout = new KEEPOUT( image, T_keepout );
image->keepouts.push_back( keepout ); image->keepouts.push_back( keepout );
CIRCLE* circle = new CIRCLE( keepout ); CIRCLE* circle = new CIRCLE( keepout );
keepout->SetShape( circle ); keepout->SetShape( circle );
circle->SetDiameter( diameter ); circle->SetDiameter( diameter );
...@@ -581,14 +664,13 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -581,14 +664,13 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
circle->SetLayerId( layerIds[layer].c_str() ); circle->SetLayerId( layerIds[layer].c_str() );
} }
} }
// else if() could there be a square keepout here? // else if() could there be a square keepout here?
else else
{ {
PADSTACK* padstack = makePADSTACK( aBoard, pad ); PADSTACK* padstack = makePADSTACK( aBoard, pad );
PADSTACKSET::iterator iter = padstackset.find( *padstack ); PADSTACKSET::iterator iter = padstackset.find( *padstack );
if( iter != padstackset.end() ) if( iter != padstackset.end() )
{ {
// padstack is a duplicate, delete it and use the original // padstack is a duplicate, delete it and use the original
...@@ -600,7 +682,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -600,7 +682,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
padstackset.insert( padstack ); padstackset.insert( padstack );
} }
PIN* pin = new PIN(image); PIN* pin = new PIN( image );
padName = pad->GetPadName(); padName = pad->GetPadName();
pin->pin_id = TO_UTF8( padName ); pin->pin_id = TO_UTF8( padName );
...@@ -627,9 +709,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -627,9 +709,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
pin->padstack_id = padstack->padstack_id; pin->padstack_id = padstack->padstack_id;
int angle = pad->GetOrientation() - aModule->GetOrientation(); // tenths of degrees int angle = pad->GetOrientation() - aModule->GetOrientation(); // tenths of degrees
if( angle ) if( angle )
{ {
NORMALIZE_ANGLE_POS(angle); NORMALIZE_ANGLE_POS( angle );
pin->SetRotation( angle / 10.0 ); pin->SetRotation( angle / 10.0 );
} }
...@@ -645,7 +728,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -645,7 +728,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
// get all the MODULE's EDGE_MODULEs and convert those to DSN outlines. // get all the MODULE's EDGE_MODULEs and convert those to DSN outlines.
moduleItems.Collect( aModule, scanEDGEs ); moduleItems.Collect( aModule, scanEDGEs );
for( int i=0; i<moduleItems.GetCount(); ++i ) for( int i = 0; i<moduleItems.GetCount(); ++i )
{ {
EDGE_MODULE* graphic = (EDGE_MODULE*) moduleItems[i]; EDGE_MODULE* graphic = (EDGE_MODULE*) moduleItems[i];
SHAPE* outline; SHAPE* outline;
...@@ -655,8 +738,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -655,8 +738,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
{ {
case S_SEGMENT: case S_SEGMENT:
outline = new SHAPE( image, T_outline ); outline = new SHAPE( image, T_outline );
image->Append( outline ); image->Append( outline );
path = new PATH( outline ); path = new PATH( outline );
outline->SetShape( path ); outline->SetShape( path );
path->SetAperture( scale( graphic->GetWidth() ) ); path->SetAperture( scale( graphic->GetWidth() ) );
path->SetLayerId( "signal" ); path->SetLayerId( "signal" );
...@@ -670,8 +755,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -670,8 +755,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
// for now, support by using line segments. // for now, support by using line segments.
outline = new SHAPE( image, T_outline ); outline = new SHAPE( image, T_outline );
image->Append( outline ); image->Append( outline );
path = new PATH( outline ); path = new PATH( outline );
outline->SetShape( path ); outline->SetShape( path );
path->SetAperture( scale( graphic->GetWidth() ) ); path->SetAperture( scale( graphic->GetWidth() ) );
path->SetLayerId( "signal" ); path->SetLayerId( "signal" );
...@@ -682,20 +769,22 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -682,20 +769,22 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
// lexer/beautifier, and the spec is not clear that this is // lexer/beautifier, and the spec is not clear that this is
// required. Fixed point floats are all that should be needed. // required. Fixed point floats are all that should be needed.
double radius = hypot( double( graphic->GetStart().x - graphic->GetEnd().x ), double radius = hypot( double(graphic->GetStart().x - graphic->GetEnd().x),
double( graphic->GetStart().y - graphic->GetEnd().y ) ); double(graphic->GetStart().y - graphic->GetEnd().y) );
// better if evenly divisible into 360 // better if evenly divisible into 360
const int DEGREE_INTERVAL = 18; // 18 means 20 line segments const int DEGREE_INTERVAL = 18; // 18 means 20 line segments
for( double radians = 0.0; radians < 2*M_PI; radians += DEGREE_INTERVAL * M_PI / 180.0 ) for( double radians = 0.0;
radians < 2 * M_PI;
radians += DEGREE_INTERVAL * M_PI / 180.0 )
{ {
wxPoint point( int( radius * cos( radians ) ), wxPoint point( int( radius * cos( radians ) ),
int( radius * sin( radians ) ) ); int( radius * sin( radians ) ) );
point += graphic->m_Start0; // an offset point += graphic->m_Start0; // an offset
path->AppendPoint( mapPt(point) ); path->AppendPoint( mapPt( point ) );
} }
} }
break; break;
...@@ -703,11 +792,12 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -703,11 +792,12 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
case S_RECT: case S_RECT:
case S_ARC: case S_ARC:
default: default:
D( printf("makeIMAGE(): unsupported shape %s\n", D( printf( "makeIMAGE(): unsupported shape %s\n",
TO_UTF8( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() )) );) TO_UTF8( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) ); )
continue; continue;
} }
} }
#endif #endif
return image; return image;
...@@ -715,19 +805,20 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) ...@@ -715,19 +805,20 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter, PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
LAYER_NUM aTopLayer, LAYER_NUM aBotLayer ) int aTopLayer, int aBotLayer )
{ {
char name[48]; char name[48];
PADSTACK* padstack = new PADSTACK(); PADSTACK* padstack = new PADSTACK();
double dsnDiameter = scale( aCopperDiameter ); double dsnDiameter = scale( aCopperDiameter );
for( LAYER_NUM layer=aTopLayer; layer<=aBotLayer; ++layer ) for( int layer=aTopLayer; layer<=aBotLayer; ++layer )
{ {
SHAPE* shape = new SHAPE( padstack ); SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape ); padstack->Append( shape );
CIRCLE* circle = new CIRCLE( shape ); CIRCLE* circle = new CIRCLE( shape );
shape->SetShape( circle ); shape->SetShape( circle );
circle->SetDiameter( dsnDiameter ); circle->SetDiameter( dsnDiameter );
...@@ -740,7 +831,7 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter, ...@@ -740,7 +831,7 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
IU2um( aDrillDiameter ) IU2um( aDrillDiameter )
); );
name[ sizeof(name)-1 ] = 0; name[ sizeof(name) - 1 ] = 0;
padstack->SetPadstackId( name ); padstack->SetPadstackId( name );
return padstack; return padstack;
...@@ -749,13 +840,13 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter, ...@@ -749,13 +840,13 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia ) PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
{ {
LAYER_NUM topLayer; LAYER_NUM topLayerNum;
LAYER_NUM botLayer; LAYER_NUM botLayerNum;
aVia->ReturnLayerPair( &topLayer, &botLayer ); aVia->ReturnLayerPair( &topLayerNum, &botLayerNum );
topLayer = kicadLayer2pcb[topLayer]; int topLayer = kicadLayer2pcb[topLayerNum];
botLayer = kicadLayer2pcb[botLayer]; int botLayer = kicadLayer2pcb[botLayerNum];
if( topLayer > botLayer ) if( topLayer > botLayer )
EXCHG( topLayer, botLayer ); EXCHG( topLayer, botLayer );
...@@ -767,15 +858,16 @@ PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia ) ...@@ -767,15 +858,16 @@ PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ERROR ) void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ERROR )
{ {
TYPE_COLLECTOR items; TYPE_COLLECTOR items;
unsigned prox; // a proximity BIU metric, not an accurate distance
// get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N, // Get all the DRAWSEGMENTS and module graphics into 'items',
// and those segments comprise the board's perimeter. // then keep only those on layer == EDGE_N.
static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT }; static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
items.Collect( aBoard, scan_graphics ); items.Collect( aBoard, scan_graphics );
for( int i=0; i<items.GetCount(); ) for( int i = 0; i<items.GetCount(); )
{ {
if( items[i]->GetLayer() != EDGE_N ) if( items[i]->GetLayer() != EDGE_N )
{ {
...@@ -796,16 +888,105 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -796,16 +888,105 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
wxPoint prevPt; wxPoint prevPt;
DRAWSEGMENT* graphic = (DRAWSEGMENT*) items[0]; DRAWSEGMENT* graphic;
// the first DRAWSEGMENT is in 'graphic*', ok to remove it from 'items' // Find edge point with minimum x, this should be in the outer polygon
items.Remove( 0 ); // which will define the perimeter Edge.Cuts polygon.
wxPoint xmin = wxPoint( INT_MAX, 0 );
int xmini = 0;
for( int i = 0; i < items.GetCount(); i++ )
{
graphic = (DRAWSEGMENT*) items[i];
switch( graphic->GetShape() )
{
case S_SEGMENT:
{
if( graphic->GetStart().x < xmin.x )
{
xmin = graphic->GetStart();
xmini = i;
}
if( graphic->GetEnd().x < xmin.x )
{
xmin = graphic->GetEnd();
xmini = i;
}
}
break;
case S_ARC:
// freerouter does not yet understand arcs, so approximate
// an arc with a series of short lines and put those
// line segments into the !same! PATH.
{
const int STEPS = 9; // in an arc of 90 degrees
wxPoint start = graphic->GetArcStart();
wxPoint center = graphic->GetCenter();
double angle = -graphic->GetAngle();
wxPoint pt;
for( int step = 1; step<=STEPS; ++step )
{
double rotation = ( angle * step ) / STEPS;
pt = start;
RotatePoint( &pt.x, &pt.y, center.x, center.y, rotation );
if( pt.x < xmin.x )
{
xmin = pt;
xmini = i;
}
}
}
break;
case S_CIRCLE:
// Freerouter does not understand circles.
// This might be a mounting hole or something, ignore it without error
// because some of our demo boards have used the edges pcb layer to
// hold islanded circles, rather than simply using holes.
break;
default:
{
wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
ThrowIOError( error );
}
break;
}
}
// Grab the left most point, assume its on the board's perimeter, and see if we
// can put enough graphics together by matching endpoints to formulate a cohesive
// polygon.
graphic = (DRAWSEGMENT*) items[xmini];
// The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
items.Remove( xmini );
wxPoint startPt = wxPoint( graphic->GetEnd() );
prevPt = graphic->GetEnd(); prevPt = graphic->GetEnd();
path->AppendPoint( mapPt( prevPt ) ); path->AppendPoint( mapPt( prevPt ) );
// do not append the other end point yet, this first 'graphic' might be an arc // Do not append the other end point yet of this 'graphic', this first
// 'graphic' might be an arc.
// Set maximum proximity threshold for point to point nearness metric for
// board perimeter only, not interior keepouts yet.
prox = Mils2iu( 0 );
// Output the Edge.Cuts perimeter polygon.
for(;;) for(;;)
{ {
switch( graphic->GetShape() ) switch( graphic->GetShape() )
...@@ -814,24 +995,24 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -814,24 +995,24 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
{ {
wxPoint nextPt; wxPoint nextPt;
if( prevPt != graphic->GetStart() ) if( !close_enough( prevPt, graphic->GetStart(), prox ) )
{ {
wxASSERT( prevPt == graphic->GetEnd() ); wxASSERT( close_enough( prevPt, graphic->GetEnd(), prox ) );
nextPt = graphic->GetStart(); nextPt = graphic->GetStart();
} }
else else
{ {
wxASSERT( prevPt == graphic->GetStart() ); wxASSERT( close_enough( prevPt, graphic->GetStart(), prox ) );
nextPt = graphic->GetEnd(); nextPt = graphic->GetEnd();
} }
path->AppendPoint( mapPt(nextPt) ); path->AppendPoint( mapPt( nextPt ) );
prevPt = nextPt; prevPt = nextPt;
} }
break; break;
case S_ARC: case S_ARC:
// freerouter does not yet understand arcs, so approximate // Freerouter does not yet understand arcs, so approximate
// an arc with a series of short lines and put those // an arc with a series of short lines and put those
// line segments into the !same! PATH. // line segments into the !same! PATH.
{ {
...@@ -842,9 +1023,9 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -842,9 +1023,9 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
wxPoint center = graphic->GetCenter(); wxPoint center = graphic->GetCenter();
double angle = -graphic->GetAngle(); double angle = -graphic->GetAngle();
if( prevPt != start ) if( !close_enough( prevPt, start, prox ) )
{ {
wxASSERT( prevPt == graphic->GetArcEnd() ); wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) );
angle = -angle; angle = -angle;
EXCHG( start, end ); EXCHG( start, end );
...@@ -852,9 +1033,9 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -852,9 +1033,9 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
wxPoint nextPt; wxPoint nextPt;
for( int step=1; step<=STEPS; ++step ) for( int step = 1; step<=STEPS; ++step )
{ {
double rotation = ( angle * step )/STEPS; double rotation = ( angle * step ) / STEPS;
nextPt = start; nextPt = start;
...@@ -868,26 +1049,17 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -868,26 +1049,17 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
break; break;
case S_CIRCLE: case S_CIRCLE:
#if 0 // Freerouter does not understand circles. And although we can mimic
// do not output a circle, freerouter does not understand it. // a circle for it by line segments, we'd have to ensure that the circle
// this might be a mounting hole or something, ignore it without error // was the only graphic on the board's edge. @todo that.
// because some of our demo boards have used the edges pcb layer to //
// hold islanded circles, rather than simply using holes. // Tell user his board has a problem, this is better than silently
break; // ignoring the error.
#else
// Do not output a circle, freerouter does not understand it.
// tell user his board has a problem, this is better than silently
// ignoring the error. "edges pcb" layer should not be used
// to hold islanded circles which could or should be better done
// as simple holes. (Some of our demo boards have this problem.)
// fall thru here to report the error. // fall thru here to report the error.
#endif
default: default:
{ {
wxString error; wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
error.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) ); GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
ThrowIOError( error ); ThrowIOError( error );
...@@ -895,31 +1067,166 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -895,31 +1067,166 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
break; break;
} }
if( items.GetCount() == 0 ) if( close_enough( startPt, prevPt, prox ) ) // the polygon is closed.
break; break;
graphic = findPoint( prevPt, &items ); graphic = findPoint( prevPt, &items, prox );
if( !graphic ) if( !graphic )
{ {
wxString error; wxString error = wxString::Format(
_( "Unable to find the next segment with an endpoint of (%d,%d).\n"
"Edit Edge.Cuts line segments, making them contiguous." ),
prevPt.x,
prevPt.y );
ThrowIOError( error );
}
}
// Output the interior Edge.Cuts graphics as keepouts, using nearness metric
// for sloppy graphical items.
prox = Mils2iu( 10 );
while( items.GetCount() )
{
// emit a signal layers keepout for every interior polygon left...
KEEPOUT* keepout = new KEEPOUT( NULL, T_keepout );
PATH* poly_ko = new PATH( NULL, T_polygon );
keepout->SetShape( poly_ko );
poly_ko->SetLayerId( "signal" );
pcb->structure->keepouts.push_back( keepout );
graphic = (DRAWSEGMENT*) items[0];
items.Remove( 0 );
if( graphic->GetShape() == S_CIRCLE )
{
// do a circle segmentation
const int STEPS = 36;
wxPoint start;
wxPoint center = graphic->GetCenter();
int radius = graphic->GetRadius();
double angle = 3600.0;
start = center;
start.x += radius;
wxPoint nextPt;
for( int step = 0; step<STEPS; ++step )
{
double rotation = ( angle * step ) / STEPS;
nextPt = start;
RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
poly_ko->AppendPoint( mapPt( nextPt ) );
}
}
else
{
wxPoint startPt = wxPoint( graphic->GetEnd() );
prevPt = graphic->GetEnd();
poly_ko->AppendPoint( mapPt( prevPt ) );
// do not append the other end point yet, this first 'graphic' might be an arc
for(;;)
{
switch( graphic->GetShape() )
{
case S_SEGMENT:
{
wxPoint nextPt;
if( !close_enough( prevPt, graphic->GetStart(), prox ) )
{
wxASSERT( close_enough( prevPt, graphic->GetEnd(), prox ) );
nextPt = graphic->GetStart();
}
else
{
wxASSERT( close_enough( prevPt, graphic->GetStart(), prox ) );
nextPt = graphic->GetEnd();
}
prevPt = nextPt;
poly_ko->AppendPoint( mapPt( prevPt ) );
}
break;
case S_ARC:
// freerouter does not yet understand arcs, so approximate
// an arc with a series of short lines and put those
// line segments into the !same! PATH.
{
const int STEPS = 9; // in an arc of 90 degrees
wxPoint start = graphic->GetArcStart();
wxPoint end = graphic->GetArcEnd();
wxPoint center = graphic->GetCenter();
double angle = -graphic->GetAngle();
if( !close_enough( prevPt, start, prox ) )
{
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) );
angle = -angle;
EXCHG( start, end );
}
wxPoint nextPt;
for( int step = 1; step<=STEPS; ++step )
{
double rotation = ( angle * step ) / STEPS;
nextPt = start;
RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
poly_ko->AppendPoint( mapPt( nextPt ) );
}
prevPt = nextPt;
}
break;
default:
{
wxString error = wxString::Format(
_( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
error << _("Unable to find the next segment with an endpoint of ");
error << prevPt;
error << wxChar('\n');
error << _("Edit Edges_Pcb segments, making them contiguous.");
ThrowIOError( error ); ThrowIOError( error );
} }
break;
} }
#if 0 && defined(DEBUG) if( close_enough( startPt, prevPt, prox ) )
STRING_FORMATTER sf; break;
path->Format( &sf, 0 );
printf( "%s\n", sf.GetString().c_str() ); graphic = findPoint( prevPt, &items, prox );
#endif
if( !graphic )
{
wxString error = wxString::Format(
_( "Unable to find the next segment with an endpoint of (%d,%d)\n."
"Edit Edge.Cuts interior graphics, making them contiguous polygons each." ),
prevPt
);
ThrowIOError( error );
}
}
}
}
} }
else else
{ {
// User has not defined a board perimeter yet...
EDA_RECT bbbox = aBoard->ComputeBoundingBox(); EDA_RECT bbbox = aBoard->ComputeBoundingBox();
RECTANGLE* rect = new RECTANGLE( boundary ); RECTANGLE* rect = new RECTANGLE( boundary );
...@@ -936,7 +1243,6 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER ...@@ -936,7 +1243,6 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
} }
typedef std::set<std::string> STRINGSET; typedef std::set<std::string> STRINGSET;
typedef std::pair<STRINGSET::iterator, bool> STRINGSET_PAIR; typedef std::pair<STRINGSET::iterator, bool> STRINGSET_PAIR;
...@@ -990,21 +1296,30 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -990,21 +1296,30 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
int layerCount = aBoard->GetCopperLayerCount(); int layerCount = aBoard->GetCopperLayerCount();
for( LAYER_NUM pcbNdx=FIRST_LAYER; pcbNdx<layerCount; ++pcbNdx ) for( int pcbNdx=0; pcbNdx<layerCount; ++pcbNdx )
{ {
LAYER* layer = new LAYER( pcb->structure ); LAYER* layer = new LAYER( pcb->structure );
pcb->structure->layers.push_back( layer ); pcb->structure->layers.push_back( layer );
layer->name = layerIds[pcbNdx]; layer->name = layerIds[pcbNdx];
DSN_T layerType; DSN_T layerType;
switch( aBoard->GetLayerType( pcbLayer2kicad[pcbNdx] ) ) switch( aBoard->GetLayerType( pcbLayer2kicad[pcbNdx] ) )
{ {
default: default:
case LT_SIGNAL: layerType = T_signal; break; case LT_SIGNAL:
case LT_POWER: layerType = T_power; break; layerType = T_signal; break;
case LT_MIXED: layerType = T_mixed; break;
case LT_JUMPER: layerType = T_jumper; break; case LT_POWER:
layerType = T_power; break;
case LT_MIXED:
layerType = T_mixed; break;
case LT_JUMPER:
layerType = T_jumper; break;
} }
layer->layer_type = layerType; layer->layer_type = layerType;
...@@ -1023,7 +1338,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1023,7 +1338,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
//-----<unit_descriptor> & <resolution_descriptor>-------------------- //-----<unit_descriptor> & <resolution_descriptor>--------------------
{ {
#if defined(USE_PCBNEW_NANOMETRES) #if defined(USE_PCBNEW_NANOMETRES)
// tell freerouter to use "tenths of micrometers", // tell freerouter to use "tenths of micrometers",
// which is 100 nm resolution. Possibly more resolution is possible // which is 100 nm resolution. Possibly more resolution is possible
...@@ -1052,7 +1366,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1052,7 +1366,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// Because fillBOUNDARY() can throw an exception, we link in an // Because fillBOUNDARY() can throw an exception, we link in an
// empty boundary so the BOUNDARY does not get lost in the event of // empty boundary so the BOUNDARY does not get lost in the event of
// of an exception. // of an exception.
BOUNDARY* boundary = new BOUNDARY(0); BOUNDARY* boundary = new BOUNDARY( 0 );
pcb->structure->SetBOUNDARY( boundary ); pcb->structure->SetBOUNDARY( boundary );
fillBOUNDARY( aBoard, boundary ); fillBOUNDARY( aBoard, boundary );
} }
...@@ -1072,7 +1387,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1072,7 +1387,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
sprintf( rule, "(width %.6g)", scale( defaultTrackWidth ) ); sprintf( rule, "(width %.6g)", scale( defaultTrackWidth ) );
rules.push_back( rule ); rules.push_back( rule );
sprintf( rule, "(clearance %.6g)", clearance+safetyMargin ); sprintf( rule, "(clearance %.6g)", clearance + safetyMargin );
rules.push_back( rule ); rules.push_back( rule );
// On a high density board (a board with 4 mil tracks, 4 mil spacing) // On a high density board (a board with 4 mil tracks, 4 mil spacing)
...@@ -1084,6 +1399,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1084,6 +1399,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// a different net. So if the baseline trace to trace clearance was say 4 mils, then // a different net. So if the baseline trace to trace clearance was say 4 mils, then
// the SMD to trace clearance should be at least 6 mils. // the SMD to trace clearance should be at least 6 mils.
double default_smd = clearance + safetyMargin; double default_smd = clearance + safetyMargin;
if( default_smd <= 6.0 ) if( default_smd <= 6.0 )
default_smd = 6.0; default_smd = 6.0;
...@@ -1114,13 +1430,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1114,13 +1430,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
rules.push_back( rule ); rules.push_back( rule );
*/ */
// well, the user is going to text edit these in the DSN file anyway,
// at least until we have an export dialog.
// Pad to pad spacing on a single SMT part can be closer than our // Pad to pad spacing on a single SMT part can be closer than our
// clearance, we don't want freerouter complaining about that, so // clearance, we don't want freerouter complaining about that, so
// output a significantly smaller pad to pad clearance to freerouter. // output a significantly smaller pad to pad clearance to freerouter.
clearance = scale( defaultClearance )/4; clearance = scale( defaultClearance ) / 4;
sprintf( rule, "(clearance %.6g (type smd_smd))", clearance ); sprintf( rule, "(clearance %.6g (type smd_smd))", clearance );
rules.push_back( rule ); rules.push_back( rule );
...@@ -1135,7 +1448,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1135,7 +1448,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
static const KICAD_T scanZONEs[] = { PCB_ZONE_AREA_T, EOT }; static const KICAD_T scanZONEs[] = { PCB_ZONE_AREA_T, EOT };
items.Collect( aBoard, scanZONEs ); items.Collect( aBoard, scanZONEs );
for( int i=0; i<items.GetCount(); ++i ) for( int i = 0; i<items.GetCount(); ++i )
{ {
ZONE_CONTAINER* item = (ZONE_CONTAINER*) items[i]; ZONE_CONTAINER* item = (ZONE_CONTAINER*) items[i];
...@@ -1143,9 +1456,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1143,9 +1456,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
continue; continue;
COPPER_PLANE* plane = new COPPER_PLANE( pcb->structure ); COPPER_PLANE* plane = new COPPER_PLANE( pcb->structure );
pcb->structure->planes.push_back( plane ); pcb->structure->planes.push_back( plane );
PATH* mainPolygon = new PATH( plane, T_polygon ); PATH* mainPolygon = new PATH( plane, T_polygon );
plane->SetShape( mainPolygon ); plane->SetShape( mainPolygon );
plane->name = TO_UTF8( item->GetNetName() ); plane->name = TO_UTF8( item->GetNetName() );
...@@ -1192,9 +1507,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1192,9 +1507,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
if( item->Outline()->m_CornersList[ndx-1].end_contour ) if( item->Outline()->m_CornersList[ndx-1].end_contour )
{ {
window = new WINDOW( plane ); window = new WINDOW( plane );
plane->AddWindow( window ); plane->AddWindow( window );
cutout = new PATH( window, T_polygon ); cutout = new PATH( window, T_polygon );
window->SetShape( cutout ); window->SetShape( cutout );
cutout->layer_id = layerIds[ kicadLayer2pcb[ item->GetLayer() ] ]; cutout->layer_id = layerIds[ kicadLayer2pcb[ item->GetLayer() ] ];
...@@ -1288,23 +1605,26 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1288,23 +1605,26 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
//-----<build the images, components, and netlist>----------------------- //-----<build the images, components, and netlist>-----------------------
{ {
PIN_REF empty( pcb->network ); PIN_REF empty( pcb->network );
std::string componentId; std::string componentId;
// find the highest numbered netCode within the board. // find the highest numbered netCode within the board.
int highestNetCode = aBoard->GetNetCount() - 1; int highestNetCode = aBoard->GetNetCount() - 1;
deleteNETs(); deleteNETs();
// expand the net vector to highestNetCode+1, setting empty to NULL // expand the net vector to highestNetCode+1, setting empty to NULL
nets.resize( highestNetCode+1, NULL ); nets.resize( highestNetCode + 1, NULL );
// skip netcode = 0 // skip netcode = 0
for( unsigned i=1; i<nets.size(); ++i ) for( unsigned i = 1; i<nets.size(); ++i )
nets[i] = new NET( pcb->network ); nets[i] = new NET( pcb->network );
for( unsigned ii = 0; ii < aBoard->GetNetCount(); ii++ ) for( unsigned ii = 0; ii < aBoard->GetNetCount(); ii++ )
{ {
NETINFO_ITEM* net = aBoard->FindNet(ii); NETINFO_ITEM* net = aBoard->FindNet( ii );
int netcode = net->GetNet(); int netcode = net->GetNet();
if( netcode > 0 ) if( netcode > 0 )
nets[ netcode ]->net_id = TO_UTF8( net->GetNetname() ); nets[ netcode ]->net_id = TO_UTF8( net->GetNetname() );
} }
...@@ -1313,7 +1633,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1313,7 +1633,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
padstackset.clear(); padstackset.clear();
for( int m=0; m<items.GetCount(); ++m ) for( int m = 0; m<items.GetCount(); ++m )
{ {
MODULE* module = (MODULE*) items[m]; MODULE* module = (MODULE*) items[m];
...@@ -1329,12 +1649,12 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1329,12 +1649,12 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// exported netlist will have some fabricated pin names in it. // exported netlist will have some fabricated pin names in it.
// If you don't like fabricated pin names, then make sure all pads // If you don't like fabricated pin names, then make sure all pads
// within your MODULEs are uniquely named! // within your MODULEs are uniquely named!
for( unsigned p = 0; p<image->pins.size(); ++p )
for( unsigned p=0; p<image->pins.size(); ++p )
{ {
PIN* pin = &image->pins[p]; PIN* pin = &image->pins[p];
int netcode = pin->kiNetCode; int netcode = pin->kiNetCode;
if( netcode > 0 ) if( netcode > 0 )
{ {
NET* net = nets[netcode]; NET* net = nets[netcode];
...@@ -1350,6 +1670,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1350,6 +1670,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
IMAGE* registered = pcb->library->LookupIMAGE( image ); IMAGE* registered = pcb->library->LookupIMAGE( image );
if( registered != image ) if( registered != image )
{ {
// If our new 'image' is not a unique IMAGE, delete it. // If our new 'image' is not a unique IMAGE, delete it.
...@@ -1361,6 +1682,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1361,6 +1682,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
COMPONENT* comp = pcb->placement->LookupCOMPONENT( image->GetImageId() ); COMPONENT* comp = pcb->placement->LookupCOMPONENT( image->GetImageId() );
PLACE* place = new PLACE( comp ); PLACE* place = new PLACE( comp );
comp->places.push_back( place ); comp->places.push_back( place );
place->SetRotation( module->GetOrientation()/10.0 ); place->SetRotation( module->GetOrientation()/10.0 );
...@@ -1372,8 +1694,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1372,8 +1694,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
if( module->GetFlag() ) if( module->GetFlag() )
{ {
int angle = 1800 - module->GetOrientation(); int angle = 1800 - module->GetOrientation();
NORMALIZE_ANGLE_POS(angle); NORMALIZE_ANGLE_POS( angle );
place->SetRotation( angle/10.0 ); place->SetRotation( angle / 10.0 );
place->side = T_back; place->side = T_back;
} }
...@@ -1381,8 +1703,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1381,8 +1703,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// copy the SPECCTRA_DB::padstackset to the LIBRARY. Since we are // copy the SPECCTRA_DB::padstackset to the LIBRARY. Since we are
// removing, do not increment the iterator // removing, do not increment the iterator
for( PADSTACKSET::iterator i=padstackset.begin(); i!=padstackset.end(); for( PADSTACKSET::iterator i = padstackset.begin(); i!=padstackset.end();
i=padstackset.begin() ) i = padstackset.begin() )
{ {
PADSTACKSET::auto_type ps = padstackset.release( i ); PADSTACKSET::auto_type ps = padstackset.release( i );
PADSTACK* padstack = ps.release(); PADSTACK* padstack = ps.release();
...@@ -1391,9 +1713,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1391,9 +1713,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
} }
// copy our SPECCTRA_DB::nets to the pcb->network // copy our SPECCTRA_DB::nets to the pcb->network
for( unsigned n=1; n<nets.size(); ++n ) for( unsigned n = 1; n<nets.size(); ++n )
{ {
NET* net = nets[n]; NET* net = nets[n];
if( net->pins.size() ) if( net->pins.size() )
{ {
// give ownership to pcb->network // give ownership to pcb->network
...@@ -1424,7 +1747,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1424,7 +1747,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// output the stock vias, but preserve uniqueness in the via container by // output the stock vias, but preserve uniqueness in the via container by
// using LookupVia(). // using LookupVia().
for( unsigned i=0; i < aBoard->m_ViasDimensionsList.size(); ++i ) for( unsigned i = 0; i < aBoard->m_ViasDimensionsList.size(); ++i )
{ {
int viaSize = aBoard->m_ViasDimensionsList[i].m_Diameter; int viaSize = aBoard->m_ViasDimensionsList[i].m_Diameter;
int viaDrill = aBoard->m_ViasDimensionsList[i].m_Drill; int viaDrill = aBoard->m_ViasDimensionsList[i].m_Drill;
...@@ -1434,6 +1757,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1434,6 +1757,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// maybe add 'via' to the library, but only if unique. // maybe add 'via' to the library, but only if unique.
PADSTACK* registered = pcb->library->LookupVia( via ); PADSTACK* registered = pcb->library->LookupVia( via );
if( registered != via ) if( registered != via )
delete via; delete via;
} }
...@@ -1451,6 +1775,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1451,6 +1775,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// maybe add 'via' to the library, but only if unique. // maybe add 'via' to the library, but only if unique.
PADSTACK* registered = pcb->library->LookupVia( via ); PADSTACK* registered = pcb->library->LookupVia( via );
if( registered != via ) if( registered != via )
delete via; delete via;
} }
...@@ -1502,6 +1827,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1502,6 +1827,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
} }
WIRE* wire = new WIRE( wiring ); WIRE* wire = new WIRE( wiring );
wiring->wires.push_back( wire ); wiring->wires.push_back( wire );
wire->net_id = netname; wire->net_id = netname;
...@@ -1511,6 +1837,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1511,6 +1837,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
LAYER_NUM pcbLayer = kicadLayer2pcb[kiLayer]; LAYER_NUM pcbLayer = kicadLayer2pcb[kiLayer];
path = new PATH( wire ); path = new PATH( wire );
wire->SetShape( path ); wire->SetShape( path );
path->layer_id = layerIds[pcbLayer]; path->layer_id = layerIds[pcbLayer];
...@@ -1532,12 +1859,13 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1532,12 +1859,13 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
items.Collect( aBoard, scanVIAs ); items.Collect( aBoard, scanVIAs );
for( int i=0; i<items.GetCount(); ++i ) for( int i = 0; i<items.GetCount(); ++i )
{ {
SEGVIA* via = (SEGVIA*) items[i]; SEGVIA* via = (SEGVIA*) items[i];
wxASSERT( via->Type() == PCB_VIA_T ); wxASSERT( via->Type() == PCB_VIA_T );
int netcode = via->GetNet(); int netcode = via->GetNet();
if( netcode == 0 ) if( netcode == 0 )
continue; continue;
...@@ -1552,6 +1880,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1552,6 +1880,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
} }
WIRE_VIA* dsnVia = new WIRE_VIA( pcb->wiring ); WIRE_VIA* dsnVia = new WIRE_VIA( pcb->wiring );
pcb->wiring->wire_vias.push_back( dsnVia ); pcb->wiring->wire_vias.push_back( dsnVia );
dsnVia->padstack_id = registered->padstack_id; dsnVia->padstack_id = registered->padstack_id;
...@@ -1578,7 +1907,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1578,7 +1907,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
// be done after exporting existing vias as WIRE_VIAs. // be done after exporting existing vias as WIRE_VIAs.
VIA* vias = pcb->structure->via; VIA* vias = pcb->structure->via;
for( unsigned viaNdx=0; viaNdx < pcb->library->vias.size(); ++viaNdx ) for( unsigned viaNdx = 0; viaNdx < pcb->library->vias.size(); ++viaNdx )
{ {
vias->AppendVia( pcb->library->vias[viaNdx].padstack_id.c_str() ); vias->AppendVia( pcb->library->vias[viaNdx].padstack_id.c_str() );
} }
...@@ -1600,38 +1929,38 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) ...@@ -1600,38 +1929,38 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR )
void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ) void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard )
{ {
/* From page 11 of specctra spec: /* From page 11 of specctra spec:
*
Routing and Placement Rule Hierarchies * Routing and Placement Rule Hierarchies
*
Routing and placement rules can be defined at multiple levels of design * Routing and placement rules can be defined at multiple levels of design
specification. When a routing or placement rule is defined for an object at * specification. When a routing or placement rule is defined for an object at
multiple levels, a predefined routing or placement precedence order * multiple levels, a predefined routing or placement precedence order
automatically determines which rule to apply to the object. The routing rule * automatically determines which rule to apply to the object. The routing rule
precedence order is * precedence order is
*
pcb < layer < class < class layer < group_set < group_set layer < net < * pcb < layer < class < class layer < group_set < group_set layer < net <
net layer < group < group layer < fromto < fromto layer < class_class < * net layer < group < group layer < fromto < fromto layer < class_class <
class_class layer < padstack < region < class region < net region < * class_class layer < padstack < region < class region < net region <
class_class region * class_class region
*
A pcb rule (global rule for the PCB design) has the lowest precedence in the * A pcb rule (global rule for the PCB design) has the lowest precedence in the
hierarchy. A class-to-class region rule has the highest precedence. Rules * hierarchy. A class-to-class region rule has the highest precedence. Rules
set at one level of the hierarchy override conflicting rules set at lower * set at one level of the hierarchy override conflicting rules set at lower
levels. The placement rule precedence order is * levels. The placement rule precedence order is
*
pcb < image_set < image < component < super cluster < room < * pcb < image_set < image < component < super cluster < room <
room_image_set < family_family < image_image * room_image_set < family_family < image_image
*
A pcb rule (global rule for the PCB design) has the lowest precedence in the * A pcb rule (global rule for the PCB design) has the lowest precedence in the
hierarchy. An image-to-image rule has the highest precedence. Rules set at * hierarchy. An image-to-image rule has the highest precedence. Rules set at
one level of the hierarchy override conflicting rules set at lower levels. * one level of the hierarchy override conflicting rules set at lower levels.
*/ */
char text[256]; char text[256];
CLASS* clazz = new CLASS( pcb->network ); CLASS* clazz = new CLASS( pcb->network );
pcb->network->classes.push_back( clazz ); pcb->network->classes.push_back( clazz );
// freerouter creates a class named 'default' anyway, and if we // freerouter creates a class named 'default' anyway, and if we
...@@ -1679,7 +2008,6 @@ void SPECCTRA_DB::FlipMODULEs( BOARD* aBoard ) ...@@ -1679,7 +2008,6 @@ void SPECCTRA_DB::FlipMODULEs( BOARD* aBoard )
for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
{ {
module->SetFlag( 0 ); module->SetFlag( 0 );
if( module->GetLayer() == LAYER_N_BACK ) if( module->GetLayer() == LAYER_N_BACK )
{ {
module->Flip( module->GetPosition() ); module->Flip( module->GetPosition() );
...@@ -1709,6 +2037,4 @@ void SPECCTRA_DB::RevertMODULEs( BOARD* aBoard ) ...@@ -1709,6 +2037,4 @@ void SPECCTRA_DB::RevertMODULEs( BOARD* aBoard )
modulesAreFlipped = false; modulesAreFlipped = false;
} }
} // namespace DSN } // namespace DSN
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