Commit d3932f5f authored by Marco Mattila's avatar Marco Mattila

Pcbnew: Fix add similar/cutout zone. Fix zone corner smoothing for zones with cutouts.

parent 0f09b337
...@@ -65,7 +65,7 @@ void WinEDA_PcbFrame::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -65,7 +65,7 @@ void WinEDA_PcbFrame::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container
// Use the general event handle to set others params (like toolbar) */ // Use the general event handle to set others params (like toolbar) */
wxCommandEvent evt; wxCommandEvent evt;
evt.SetId( ID_PCB_ZONES_BUTT ); evt.SetId( ID_PCB_ZONES_BUTT );
Process_Special_Functions( evt ); OnSelectTool( evt );
} }
...@@ -91,7 +91,7 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -91,7 +91,7 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container
// Use the general event handle to set others params (like toolbar) */ // Use the general event handle to set others params (like toolbar) */
wxCommandEvent evt; wxCommandEvent evt;
evt.SetId( ID_PCB_ZONES_BUTT ); evt.SetId( ID_PCB_ZONES_BUTT );
Process_Special_Functions( evt ); OnSelectTool( evt );
} }
......
...@@ -907,141 +907,159 @@ void CPolyLine::RemoveContour( int icont ) ...@@ -907,141 +907,159 @@ void CPolyLine::RemoveContour( int icont )
} }
int CPolyLine::Chamfer( unsigned int aIndex, unsigned int aDistance ) CPolyLine* CPolyLine::Chamfer( unsigned int aDistance )
{ {
int x1, y1; CPolyLine* newPoly = new CPolyLine;
long xa, ya, xb, yb, nx, ny;
if( !aDistance ) if( !aDistance )
return 0; {
newPoly->Copy( this );
return newPoly;
}
x1 = corner[aIndex].x; for( int contour = 0; contour < GetNumContours(); contour++ )
y1 = corner[aIndex].y; {
unsigned int startIndex = GetContourStart( contour );
unsigned int endIndex = GetContourEnd( contour );
for( unsigned int index = startIndex; index <= endIndex; index++ )
{
int x1, y1, nx, ny;
long long xa, ya, xb, yb;
if( aIndex == 0 ) x1 = corner[index].x;
y1 = corner[index].y;
if( index == startIndex )
{ {
xa = corner[corner.size()-1].x - x1; xa = corner[endIndex].x - x1;
ya = corner[corner.size()-1].y - y1; ya = corner[endIndex].y - y1;
} }
else else
{ {
xa = corner[aIndex-1].x - x1; xa = corner[index-1].x - x1;
ya = corner[aIndex-1].y - y1; ya = corner[index-1].y - y1;
} }
if( aIndex == corner.size()-1 ) if( index == endIndex )
{ {
xb = corner[0].x - x1; xb = corner[startIndex].x - x1;
yb = corner[0].y - y1; yb = corner[startIndex].y - y1;
} }
else else
{ {
xb = corner[aIndex+1].x - x1; xb = corner[index+1].x - x1;
yb = corner[aIndex+1].y - y1; yb = corner[index+1].y - y1;
} }
// Move the first vertex into new position unsigned int lena = (unsigned int)sqrt( (double)(xa*xa + ya*ya) );
nx = (long) ( (double) (aDistance*xa)/sqrt( (double) (xa*xa + ya*ya) ) ); unsigned int lenb = (unsigned int)sqrt( (double)(xb*xb + yb*yb) );
ny = (long) ( (double) (aDistance*ya)/sqrt( (double) (xa*xa + ya*ya) ) );
corner[aIndex].x = x1 + nx;
corner[aIndex].y = y1 + ny;
// Add one new vertex
nx = (long) ( (double) (aDistance*xb)/sqrt( (double) (xb*xb + yb*yb) ) );
ny = (long) ( (double) (aDistance*yb)/sqrt( (double) (xb*xb + yb*yb) ) );
InsertCorner( aIndex, x1 + nx, y1 + ny );
return 1; // Added one vertex
}
CPolyLine* CPolyLine::Chamfer( unsigned int aDistance )
{
CPolyLine* newPoly = new CPolyLine;
unsigned int lena, lenb;
newPoly->Copy( this );
for( unsigned int i = 0, index = 0; i < corner.size(); i++, index++ )
{
if( i == 0 )
lena = GetEdgeLength( corner.size()-1 );
else
lena = GetEdgeLength( i - 1 );
lenb = GetEdgeLength( i );
unsigned int distance = aDistance; unsigned int distance = aDistance;
// Chamfer one half of an edge at most // Chamfer one half of an edge at most
if( 0.5*lena < distance ) if( 0.5*lena < distance )
distance = (unsigned int) 0.5*lena; distance = 0.5*lena;
if( 0.5*lenb < distance ) if( 0.5*lenb < distance )
distance = (unsigned int) 0.5*lenb; distance = 0.5*lenb;
nx = (int) ( (double) (distance*xa)/sqrt( (double) (xa*xa + ya*ya) ) );
ny = (int) ( (double) (distance*ya)/sqrt( (double) (xa*xa + ya*ya) ) );
// Chamfer this corner and keep tract of added vertices if( index == startIndex )
index += newPoly->Chamfer( index, distance ); newPoly->Start( GetLayer(), x1 + nx, y1 + ny, GetHatchStyle() );
else
newPoly->AppendCorner( x1 + nx, y1 + ny );
nx = (int) ( (double) (distance*xb)/sqrt( (double) (xb*xb + yb*yb) ) );
ny = (int) ( (double) (distance*yb)/sqrt( (double) (xb*xb + yb*yb) ) );
newPoly->AppendCorner( x1 + nx, y1 + ny );
}
newPoly->Close();
} }
return newPoly; return newPoly;
} }
int CPolyLine::Fillet( unsigned int aIndex, unsigned int aRadius, CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments )
unsigned int aSegments )
{ {
int x1, y1; // Current vertex CPolyLine* newPoly = new CPolyLine;
int xa, ya; // Previous vertex
int xb, yb; // Next vertex
double nx, ny;
if( !aRadius ) if( !aRadius )
return 0; {
newPoly->Copy( this );
return newPoly;
}
x1 = corner[aIndex].x; for( int contour = 0; contour < GetNumContours(); contour++ )
y1 = corner[aIndex].y; {
unsigned int startIndex = GetContourStart( contour );
unsigned int endIndex = GetContourEnd( contour );
if( aIndex == 0 ) for( unsigned int index = startIndex; index <= endIndex; index++ )
{ {
xa = corner[corner.size()-1].x - x1;
ya = corner[corner.size()-1].y - y1; int x1, y1; // Current vertex
long long xa, ya; // Previous vertex
long long xb, yb; // Next vertex
double nx, ny;
x1 = corner[index].x;
y1 = corner[index].y;
if( index == startIndex )
{
xa = corner[endIndex].x - x1;
ya = corner[endIndex].y - y1;
} }
else else
{ {
xa = corner[aIndex-1].x - x1; xa = corner[index-1].x - x1;
ya = corner[aIndex-1].y - y1; ya = corner[index-1].y - y1;
} }
if( aIndex == corner.size()-1 ) if( index == endIndex )
{ {
xb = corner[0].x - x1; xb = corner[startIndex].x - x1;
yb = corner[0].y - y1; yb = corner[startIndex].y - y1;
} }
else else
{ {
xb = corner[aIndex+1].x - x1; xb = corner[index+1].x - x1;
yb = corner[aIndex+1].y - y1; yb = corner[index+1].y - y1;
} }
double lena = sqrt( (double) (xa*xa + ya*ya) ); double lena = sqrt( (double) (xa*xa + ya*ya) );
double lenb = sqrt( (double) (xb*xb + yb*yb) ); double lenb = sqrt( (double) (xb*xb + yb*yb) );
double cosine = ( xa*xb + ya*yb )/( lena*lenb ); double cosine = ( xa*xb + ya*yb )/( lena*lenb );
unsigned int radius = aRadius;
double denom = sqrt( 2.0/( 1+cosine )-1 );
// Limit rounding distance to one half of an edge
if( 0.5*lena*denom < radius )
radius = 0.5*lena*denom;
if( 0.5*lenb*denom < radius )
radius = 0.5*lenb*denom;
// Calculate fillet arc absolute center point (xc, yx) // Calculate fillet arc absolute center point (xc, yx)
double k = aRadius / sqrt( .5*( 1-cosine ) ); double k = radius / sqrt( .5*( 1-cosine ) );
double lenab = sqrt( ( xa/lena + xb/lenb )*( xa/lena + xb/lenb ) + double lenab = sqrt( ( xa/lena + xb/lenb )*( xa/lena + xb/lenb ) +
( ya/lena + yb/lenb )*( ya/lena + yb/lenb ) ); ( ya/lena + yb/lenb )*( ya/lena + yb/lenb ) );
double xc = x1 + k*( xa/lena + xb/lenb )/lenab; double xc = x1 + k*( xa/lena + xb/lenb )/lenab;
double yc = y1 + k*( ya/lena + yb/lenb )/lenab; double yc = y1 + k*( ya/lena + yb/lenb )/lenab;
// Calculate arc start and end vectors // Calculate arc start and end vectors
k = aRadius / sqrt( 2/( 1+cosine )-1 ); k = radius / sqrt( 2/( 1+cosine )-1 );
double xs = x1 + k*xa/lena - xc; double xs = x1 + k*xa/lena - xc;
double ys = y1 + k*ya/lena - yc; double ys = y1 + k*ya/lena - yc;
double xe = x1 + k*xb/lenb - xc; double xe = x1 + k*xb/lenb - xc;
double ye = y1 + k*yb/lenb - yc; double ye = y1 + k*yb/lenb - yc;
// Cosine of arc angle // Cosine of arc angle
double argument = ( xs*xe + ys*ye ) / ( aRadius*aRadius ); double argument = ( xs*xe + ys*ye ) / ( radius*radius );
if( argument < -1 ) // Just in case... if( argument < -1 ) // Just in case...
argument = -1; argument = -1;
...@@ -1055,63 +1073,33 @@ int CPolyLine::Fillet( unsigned int aIndex, unsigned int aRadius, ...@@ -1055,63 +1073,33 @@ int CPolyLine::Fillet( unsigned int aIndex, unsigned int aRadius,
if( tempSegments - (int)tempSegments > 0 ) if( tempSegments - (int)tempSegments > 0 )
tempSegments++; tempSegments++;
aSegments = (unsigned int) tempSegments; unsigned int segments = (unsigned int) tempSegments;
double deltaAngle = arcAngle / aSegments; double deltaAngle = arcAngle / segments;
double startAngle = atan2( -ys, xs ); double startAngle = atan2( -ys, xs );
// Flip arc for inner corners // Flip arc for inner corners
if( xa*yb - ya*xb <= 0 ) if( xa*yb - ya*xb <= 0 )
deltaAngle *= -1; deltaAngle *= -1;
// Move first vertex into new position
nx = xc + xs + 0.5; nx = xc + xs + 0.5;
ny = yc + ys + 0.5; ny = yc + ys + 0.5;
corner[aIndex].x = (int)nx; if( index == startIndex )
corner[aIndex].y = (int)ny; newPoly->Start( GetLayer(), (int)nx, (int)ny, GetHatchStyle() );
else
newPoly->AppendCorner( (int)nx, (int)ny );
// Add new vertices
unsigned int nVertices = 0; unsigned int nVertices = 0;
for( unsigned int j = 0; j < aSegments; j++ ) for( unsigned int j = 0; j < segments; j++ )
{ {
nx = xc + cos( startAngle + (j+1)*deltaAngle )*aRadius + 0.5; nx = xc + cos( startAngle + (j+1)*deltaAngle )*radius + 0.5;
ny = yc - sin( startAngle + (j+1)*deltaAngle )*aRadius + 0.5; ny = yc - sin( startAngle + (j+1)*deltaAngle )*radius + 0.5;
InsertCorner( aIndex + nVertices, (int)nx, (int)ny ); newPoly->AppendCorner( (int)nx, (int)ny );
nVertices++; nVertices++;
} }
return nVertices; // Return the number of added vertices
}
CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments )
{
CPolyLine* newPoly = new CPolyLine;
unsigned int lena, lenb;
newPoly->Copy( this );
for( unsigned int i = 0, index = 0; i < corner.size(); i++, index++ )
{
if( i == 0 )
lena = GetEdgeLength( corner.size()-1 );
else
lena = GetEdgeLength( i - 1 );
lenb = GetEdgeLength( i );
unsigned int radius = aRadius;
double denom = sqrt( 2.0/( 1+GetCosine( i ) )-1 );
// Limit rounding distance to one half of an edge
if( 0.5*lena*denom < radius )
radius = (unsigned int) ( 0.5 * (double) lena * denom );
if( 0.5*lenb*denom < radius )
radius = (unsigned int) ( 0.5 * (double) lenb * denom );
// Round this corner and keep tract of added vertices
index += newPoly->Fillet( index, radius, aSegments );
} }
newPoly->Close();
}
return newPoly; return newPoly;
} }
...@@ -1205,63 +1193,6 @@ int CPolyLine::GetEndContour( int ic ) ...@@ -1205,63 +1193,6 @@ int CPolyLine::GetEndContour( int ic )
} }
unsigned int CPolyLine::GetEdgeLength( unsigned int aIndex )
{
long xa, ya, xb, yb;
xa = corner[aIndex].x;
ya = corner[aIndex].y;
if( aIndex == corner.size()-1 )
{
xb = corner[0].x;
yb = corner[0].y;
}
else
{
xb = corner[aIndex+1].x;
yb = corner[aIndex+1].y;
}
return (unsigned int) sqrt( (double) (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
}
double CPolyLine::GetCosine( unsigned int aIndex )
{
int x1, y1;
long xa, ya, xb, yb;
x1 = corner[aIndex].x;
y1 = corner[aIndex].y;
if( aIndex == 0 )
{
xa = corner[corner.size()-1].x - x1;
ya = corner[corner.size()-1].y - y1;
}
else
{
xa = corner[aIndex-1].x - x1;
ya = corner[aIndex-1].y - y1;
}
if( aIndex == corner.size() - 1 )
{
xb = corner[0].x - x1;
yb = corner[0].y - y1;
}
else
{
xb = corner[aIndex+1].x - x1;
yb = corner[aIndex+1].y - y1;
}
double lena = sqrt( (double)xa*xa + ya*ya );
double lenb = sqrt( (double)xb*xb + yb*yb );
return ( xa*xb + ya*yb )/( lena*lenb );
}
CRect CPolyLine::GetBounds() CRect CPolyLine::GetBounds()
{ {
CRect r = GetCornerBounds(); CRect r = GetCornerBounds();
......
...@@ -132,15 +132,6 @@ public: ...@@ -132,15 +132,6 @@ public:
void Close( int style = STRAIGHT, bool bDraw = false ); void Close( int style = STRAIGHT, bool bDraw = false );
void RemoveContour( int icont ); void RemoveContour( int icont );
/**
* Function Chamfer
* chamfers a corner.
* @param aIndex is the corner index.
* @param aDistance is the chamfering distance.
* @return int - The number of segments added.
*/
int Chamfer( unsigned int aIndex, unsigned int aDistance );
/** /**
* Function Chamfer * Function Chamfer
* returns a chamfered version of a polygon. * returns a chamfered version of a polygon.
...@@ -149,17 +140,6 @@ public: ...@@ -149,17 +140,6 @@ public:
*/ */
CPolyLine* Chamfer( unsigned int aDistance ); CPolyLine* Chamfer( unsigned int aDistance );
/**
* Function Fillet
* rounds a corner.
* @param aIndex is the corner index.
* @param aDistance is the fillet radius.
* @param aSegments is the number of segments / 360 degrees.
* @return int - The number of segments added.
*/
int Fillet( unsigned int aIndex, unsigned int aRadius,
unsigned int aSegments );
/** /**
* Function Fillet * Function Fillet
* returns a filleted version of a polygon. * returns a filleted version of a polygon.
...@@ -200,22 +180,6 @@ public: ...@@ -200,22 +180,6 @@ public:
int GetY( int ic ); int GetY( int ic );
int GetEndContour( int ic ); int GetEndContour( int ic );
/**
* Function GetEdgeLength
* returns the length of the edge starting at given corner index.
* @param aIndex is the corner index.
* @return unsigned int - the length of the edge.
*/
unsigned int GetEdgeLength( unsigned int aIndex );
/**
* Function GetCosine
* returns the cosine between the two edge vectors at a corner.
* @param aIndex is the corner index.
* @return double - the cosine value.
*/
double GetCosine( unsigned int aIndex );
int GetUtility( int ic ) { return corner[ic].utility; }; int GetUtility( int ic ) { return corner[ic].utility; };
void SetUtility( int ic, int utility ) { corner[ic].utility = utility; }; void SetUtility( int ic, int utility ) { corner[ic].utility = utility; };
int GetSideStyle( int is ); int GetSideStyle( int is );
......
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