When polygonizing arcs don't use synthesized center and angle.
Start, mid and end are the "real" properties and come with less error. Also collapses two arc polygonization routines into one. Also fixes DRC checks to be cognizant of arc approximation error. Fixes https://gitlab.com/kicad/code/kicad/issues/6039
This commit is contained in:
parent
b683871d93
commit
59f3fefd17
|
@ -118,8 +118,8 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
* @param aError = the IU allowed for error in approximation
|
||||
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
|
||||
*/
|
||||
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart,
|
||||
double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc );
|
||||
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aMid,
|
||||
wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc );
|
||||
|
||||
/**
|
||||
* Function TransformRingToPolygon
|
||||
|
|
|
@ -322,39 +322,26 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const
|
|||
}
|
||||
|
||||
|
||||
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart,
|
||||
double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc )
|
||||
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aMid,
|
||||
wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc )
|
||||
{
|
||||
wxPoint arc_start, arc_end;
|
||||
int dist = EuclideanNorm( aCentre - aStart );
|
||||
int numSegs = GetArcToSegmentCount( dist, aError, 360.0 );
|
||||
int delta = 3600 / numSegs; // rotate angle in 0.1 degree
|
||||
SHAPE_ARC arc( aStart, aMid, aEnd, aWidth );
|
||||
SHAPE_LINE_CHAIN arcSpine = arc.ConvertToPolyline( aError );
|
||||
|
||||
arc_end = arc_start = aStart;
|
||||
if( aErrorLoc == ERROR_OUTSIDE )
|
||||
aWidth += 2 * aError;
|
||||
else
|
||||
aWidth -= 2 * aError;
|
||||
|
||||
if( aArcAngle != 3600 )
|
||||
RotatePoint( &arc_end, aCentre, -aArcAngle );
|
||||
|
||||
if( aArcAngle < 0 )
|
||||
for( int ii = 0; ii < arcSpine.GetSegmentCount(); ++ii )
|
||||
{
|
||||
std::swap( arc_start, arc_end );
|
||||
aArcAngle = -aArcAngle;
|
||||
SEG seg = arcSpine.GetSegment( ii );
|
||||
|
||||
// Note that the error here is only for the rounded ends; we still need to shrink or
|
||||
// expand the width above for the segments themselves.
|
||||
TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg.A, (wxPoint) seg.B, aWidth, aError,
|
||||
aErrorLoc );
|
||||
}
|
||||
|
||||
// Compute the ends of segments and creates poly
|
||||
wxPoint curr_end = arc_start;
|
||||
wxPoint curr_start = arc_start;
|
||||
|
||||
for( int ii = delta; ii < aArcAngle; ii += delta )
|
||||
{
|
||||
curr_end = arc_start;
|
||||
RotatePoint( &curr_end, aCentre, -ii );
|
||||
TransformOvalToPolygon( aCornerBuffer, curr_start, curr_end, aWidth, aError, aErrorLoc );
|
||||
curr_start = curr_end;
|
||||
}
|
||||
|
||||
if( curr_end != arc_end )
|
||||
TransformOvalToPolygon( aCornerBuffer, curr_end, arc_end, aWidth, aError, aErrorLoc );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -401,13 +401,6 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
|
|||
|
||||
width += 2 * aClearanceValue;
|
||||
|
||||
// Creating a reliable clearance shape for circles and arcs is not so easy, due to
|
||||
// the error created by segment approximation.
|
||||
// for a circle this is not so hard: create a polygon from a circle slightly bigger:
|
||||
// thickness = width + s_error_max, and radius = initial radius + s_error_max/2
|
||||
// giving a shape with a suitable internal radius and external radius
|
||||
// For an arc this is more tricky: TODO
|
||||
|
||||
switch( m_Shape )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
|
@ -447,7 +440,7 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
|
|||
break;
|
||||
|
||||
case S_ARC:
|
||||
TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, width,
|
||||
TransformArcToPolygon( aCornerBuffer, GetArcStart(), GetArcMid(), GetArcEnd(), width,
|
||||
aError, aErrorLoc );
|
||||
break;
|
||||
|
||||
|
@ -550,11 +543,9 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
{
|
||||
const ARC* arc = static_cast<const ARC*>( this );
|
||||
int width = m_Width + ( 2 * aClearanceValue );
|
||||
VECTOR2D center( arc->GetCenter() );
|
||||
double angle = arc->GetAngle();
|
||||
|
||||
TransformArcToPolygon( aCornerBuffer, (wxPoint) center, GetStart(), angle, width,
|
||||
aError, aErrorLoc );
|
||||
TransformArcToPolygon( aCornerBuffer, (wxPoint) arc->GetStart(), (wxPoint) arc->GetMid(),
|
||||
(wxPoint) arc->GetEnd(), width, aError, aErrorLoc );
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -534,6 +534,14 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
|
|||
if( !refVia->FlashLayer( aLayer ) )
|
||||
halfWidth = refVia->GetDrill() / 2 + bds.GetHolePlatingThickness();
|
||||
}
|
||||
else if ( aRefSeg->Type() == PCB_ARC_T )
|
||||
{
|
||||
// We're going to do a collision with the arc "spine" using an increased
|
||||
// clearance to proxy for both the clearance and the arc track width. We
|
||||
// therefore need to subtract the polygonization error from the track width
|
||||
// so that it is all "inside" the track.
|
||||
halfWidth -= bds.m_MaxError / 2;
|
||||
}
|
||||
|
||||
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
|
||||
aRefSeg, zone, aLayer );
|
||||
|
|
Loading…
Reference in New Issue