kicad2step: Add short segments to fix outline contiguity for arcs

STEP exporter keeps outline contiguous by storing the last point
coordinates and using them as the starting point for the next segment. It
might create a problem for arcs, as one of the arc end points may become
translated (changed to the last outline point), while the remaining
points (center and the other endpoint) are kept original. For large
deltas it renders an arc invalid, as it cannot pass through a modified
endpoint anymore.

To fix this, short segments are added to link the last outline point
with an arc endpoint, but only if the distance between the two is below
a certain threshold. This way the outline is kept contiguous and the arc
end point is unmodified, warranting its correctness.

Fixes: lp:1774351
* https://bugs.launchpad.net/kicad/+bug/1774351
This commit is contained in:
Maciej Suminski 2018-06-18 17:25:07 +02:00
parent 44c1f5785b
commit 1541cbdf04
1 changed files with 27 additions and 0 deletions

View File

@ -1460,6 +1460,33 @@ bool OUTLINE::addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBL
case CURVE_ARC: case CURVE_ARC:
{ {
// Arcs are particularly tricky to be used in contiguous outlines.
// If an arc is not precisely aligned with the previous segment end point
// (aLastPoint != aCurve.m_end), then it might be impossible to request an arc
// passing through aLastPoint and the other arc end. To fix this, a small segment
// is added, joining aLastPoint and aCurve.m_end, but only if the distance
// is small.
double dx = aLastPoint.x - aCurve.m_end.x;
double dy = aLastPoint.y - aCurve.m_end.y;
double distance = dx * dx + dy * dy;
if( distance > 0 && distance < MIN_LENGTH2 )
{
std::ostringstream ostr;
#ifdef __WXDEBUG__
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
ostr << " * added an auxiliary segment from "
<< aLastPoint << " to " << aCurve.m_end << "\n";
wxLogMessage( "%s", ostr.str().c_str() );
edge = BRepBuilderAPI_MakeEdge( gp_Pnt( aLastPoint.x, aLastPoint.y, 0.0 ),
gp_Pnt( aCurve.m_end.x, aCurve.m_end.y, 0.0 ) );
aWire->Add( edge );
aLastPoint = aCurve.m_end;
}
gp_Circ arc( gp_Ax2( gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 ), gp_Circ arc( gp_Ax2( gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 ),
gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius ); gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius );