pass round boards to freerouter via specctra_export
This commit is contained in:
parent
d55ab920d2
commit
a26e59d8ed
|
@ -855,6 +855,38 @@ PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makeCircle
|
||||||
|
* does a line segmented circle into aPath.
|
||||||
|
*/
|
||||||
|
static void makeCircle( PATH* aPath, DRAWSEGMENT* aGraphic )
|
||||||
|
{
|
||||||
|
// do a circle segmentation
|
||||||
|
const int STEPS = 2 * 36;
|
||||||
|
|
||||||
|
wxPoint start;
|
||||||
|
wxPoint center = aGraphic->GetCenter();
|
||||||
|
int radius = aGraphic->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 );
|
||||||
|
|
||||||
|
aPath->AppendPoint( mapPt( nextPt ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -948,10 +980,18 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_CIRCLE:
|
case S_CIRCLE:
|
||||||
// Freerouter does not understand circles.
|
{
|
||||||
// This might be a mounting hole or something, ignore it without error
|
wxPoint pt = graphic->GetCenter();
|
||||||
// because some of our demo boards have used the edges pcb layer to
|
|
||||||
// hold islanded circles, rather than simply using holes.
|
// pt has minimum x point
|
||||||
|
pt.x -= graphic->GetRadius();
|
||||||
|
|
||||||
|
if( pt.x < xmin.x )
|
||||||
|
{
|
||||||
|
xmin = pt;
|
||||||
|
xmini = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -974,112 +1014,110 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
|
||||||
// The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
|
// The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
|
||||||
items.Remove( xmini );
|
items.Remove( xmini );
|
||||||
|
|
||||||
wxPoint startPt = wxPoint( graphic->GetEnd() );
|
|
||||||
|
|
||||||
prevPt = graphic->GetEnd();
|
|
||||||
path->AppendPoint( mapPt( prevPt ) );
|
|
||||||
|
|
||||||
// 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
|
// Set maximum proximity threshold for point to point nearness metric for
|
||||||
// board perimeter only, not interior keepouts yet.
|
// board perimeter only, not interior keepouts yet.
|
||||||
prox = Mils2iu( 0 );
|
prox = Mils2iu( 0 );
|
||||||
|
|
||||||
// Output the Edge.Cuts perimeter polygon.
|
// Output the Edge.Cuts perimeter as circle or polygon.
|
||||||
for(;;)
|
if( graphic->GetShape() == S_CIRCLE )
|
||||||
{
|
{
|
||||||
switch( graphic->GetShape() )
|
makeCircle( path, graphic );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxPoint startPt = wxPoint( graphic->GetEnd() );
|
||||||
|
|
||||||
|
prevPt = graphic->GetEnd();
|
||||||
|
path->AppendPoint( mapPt( prevPt ) );
|
||||||
|
|
||||||
|
// Do not append the other end point yet of this 'graphic', this first
|
||||||
|
// 'graphic' might be an arc.
|
||||||
|
|
||||||
|
for(;;)
|
||||||
{
|
{
|
||||||
case S_SEGMENT:
|
switch( graphic->GetShape() )
|
||||||
{
|
{
|
||||||
wxPoint nextPt;
|
case S_SEGMENT:
|
||||||
|
|
||||||
if( !close_enough( prevPt, graphic->GetStart(), prox ) )
|
|
||||||
{
|
{
|
||||||
wxASSERT( close_enough( prevPt, graphic->GetEnd(), prox ) );
|
wxPoint nextPt;
|
||||||
nextPt = graphic->GetStart();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxASSERT( close_enough( prevPt, graphic->GetStart(), prox ) );
|
|
||||||
nextPt = graphic->GetEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
path->AppendPoint( mapPt( nextPt ) );
|
if( !close_enough( prevPt, graphic->GetStart(), prox ) )
|
||||||
prevPt = nextPt;
|
{
|
||||||
}
|
wxASSERT( close_enough( prevPt, graphic->GetEnd(), prox ) );
|
||||||
break;
|
nextPt = graphic->GetStart();
|
||||||
|
}
|
||||||
case S_ARC:
|
else
|
||||||
// Freerouter does not yet understand arcs, so approximate
|
{
|
||||||
// an arc with a series of short lines and put those
|
wxASSERT( close_enough( prevPt, graphic->GetStart(), prox ) );
|
||||||
// line segments into the !same! PATH.
|
nextPt = graphic->GetEnd();
|
||||||
{
|
}
|
||||||
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 );
|
|
||||||
|
|
||||||
path->AppendPoint( mapPt( nextPt ) );
|
path->AppendPoint( mapPt( nextPt ) );
|
||||||
|
prevPt = nextPt;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
prevPt = nextPt;
|
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 );
|
||||||
|
|
||||||
|
path->AppendPoint( mapPt( nextPt ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
prevPt = nextPt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
|
||||||
|
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
|
||||||
|
|
||||||
|
ThrowIOError( error );
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case S_CIRCLE:
|
if( close_enough( startPt, prevPt, prox ) ) // the polygon is closed.
|
||||||
// Freerouter does not understand circles. And although we can mimic
|
break;
|
||||||
// a circle for it by line segments, we'd have to ensure that the circle
|
|
||||||
// was the only graphic on the board's edge. @todo that.
|
|
||||||
//
|
|
||||||
// Tell user his board has a problem, this is better than silently
|
|
||||||
// ignoring the error.
|
|
||||||
// fall thru here to report the error.
|
|
||||||
|
|
||||||
default:
|
graphic = findPoint( prevPt, &items, prox );
|
||||||
|
|
||||||
|
if( !graphic )
|
||||||
{
|
{
|
||||||
wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
|
wxString error = wxString::Format(
|
||||||
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
|
_( "Unable to find the next segment with an endpoint of (%d,%d).\n"
|
||||||
|
"Edit Edge.Cuts perimeter graphics, making them contiguous polygons each." ),
|
||||||
|
prevPt.x,
|
||||||
|
prevPt.y );
|
||||||
ThrowIOError( error );
|
ThrowIOError( error );
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( close_enough( startPt, prevPt, prox ) ) // the polygon is closed.
|
|
||||||
break;
|
|
||||||
|
|
||||||
graphic = findPoint( prevPt, &items, prox );
|
|
||||||
|
|
||||||
if( !graphic )
|
|
||||||
{
|
|
||||||
wxString error = wxString::Format(
|
|
||||||
_( "Unable to find the next segment with an endpoint of (%d,%d).\n"
|
|
||||||
"Edit Edge.Cuts perimeter graphics, making them contiguous polygons each." ),
|
|
||||||
prevPt.x,
|
|
||||||
prevPt.y );
|
|
||||||
ThrowIOError( error );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,29 +1139,7 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
|
||||||
|
|
||||||
if( graphic->GetShape() == S_CIRCLE )
|
if( graphic->GetShape() == S_CIRCLE )
|
||||||
{
|
{
|
||||||
// do a circle segmentation
|
makeCircle( poly_ko, graphic );
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue