Commit a26e59d8 authored by Dick Hollenbeck's avatar Dick Hollenbeck

pass round boards to freerouter via specctra_export

parent d55ab920
...@@ -855,6 +855,38 @@ PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia ) ...@@ -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 ...@@ -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 ...@@ -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 ) );
nextPt = graphic->GetStart();
}
else
{ {
wxASSERT( close_enough( prevPt, graphic->GetStart(), prox ) ); wxPoint nextPt;
nextPt = graphic->GetEnd();
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();
}
path->AppendPoint( mapPt( nextPt ) );
prevPt = nextPt;
} }
break;
path->AppendPoint( mapPt( nextPt ) ); case S_ARC:
prevPt = nextPt; // Freerouter does not yet understand arcs, so approximate
} // an arc with a series of short lines and put those
break; // line segments into the !same! PATH.
{
const int STEPS = 9; // in an arc of 90 degrees
case S_ARC: wxPoint start = graphic->GetArcStart();
// Freerouter does not yet understand arcs, so approximate wxPoint end = graphic->GetArcEnd();
// an arc with a series of short lines and put those wxPoint center = graphic->GetCenter();
// line segments into the !same! PATH. double angle = -graphic->GetAngle();
{
const int STEPS = 9; // in an arc of 90 degrees
wxPoint start = graphic->GetArcStart(); if( !close_enough( prevPt, start, prox ) )
wxPoint end = graphic->GetArcEnd(); {
wxPoint center = graphic->GetCenter(); wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) );
double angle = -graphic->GetAngle();
if( !close_enough( prevPt, start, prox ) ) angle = -angle;
{ EXCHG( start, end );
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) ); }
angle = -angle; wxPoint nextPt;
EXCHG( start, end );
}
wxPoint nextPt; for( int step = 1; step<=STEPS; ++step )
{
double rotation = ( angle * step ) / STEPS;
for( int step = 1; step<=STEPS; ++step ) nextPt = start;
{
double rotation = ( angle * step ) / STEPS;
nextPt = start; RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation ); path->AppendPoint( mapPt( nextPt ) );
}
path->AppendPoint( mapPt( nextPt ) ); prevPt = nextPt;
} }
break;
default:
{
wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
prevPt = nextPt; 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 );
{
wxString error = wxString::Format( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( (STROKE_T) graphic->GetShape() ) ) );
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 ); 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 ...@@ -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
{ {
......
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