STEP export: Stricter contiguity check

Stricter contiguity check points the user to gaps in the outline.

Fixes: lp:1774351
* https://bugs.launchpad.net/kicad/+bug/1774351
This commit is contained in:
Maciej Suminski 2018-06-18 17:34:43 +02:00
parent 1541cbdf04
commit f0b3cf8077
4 changed files with 29 additions and 38 deletions

View File

@ -2897,15 +2897,13 @@ BOARD_ITEM* BOARD::Duplicate( const BOARD_ITEM* aItem,
* All contours should be closed, i.e. are valid vertices for a closed polygon * All contours should be closed, i.e. are valid vertices for a closed polygon
* return true if success, false if a contour is not valid * return true if success, false if a contour is not valid
*/ */
extern bool BuildBoardPolygonOutlines( BOARD* aBoard, extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
SHAPE_POLY_SET& aOutlines, wxString* aErrorText, unsigned int aTolerance );
wxString* aErrorText );
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText )
wxString* aErrorText )
{ {
bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText ); bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText, Millimeter2iu( 0.05 ) );
// Make polygon strictly simple to avoid issues (especially in 3D viewer) // Make polygon strictly simple to avoid issues (especially in 3D viewer)
aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );

View File

@ -1436,8 +1436,8 @@ double MODULE::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
// see convert_drawsegment_list_to_polygon.cpp: // see convert_drawsegment_list_to_polygon.cpp:
extern bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, extern bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
SHAPE_POLY_SET& aPolygons, wxString* aErrorText); wxString* aErrorText, unsigned int aTolerance );
bool MODULE::BuildPolyCourtyard() bool MODULE::BuildPolyCourtyard()
{ {
@ -1466,10 +1466,14 @@ bool MODULE::BuildPolyCourtyard()
wxString error_msg; wxString error_msg;
bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, &error_msg ); bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front,
&error_msg, Millimeter2iu( 0.05 ) );
if( success ) if( success )
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, &error_msg ); {
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back,
&error_msg, Millimeter2iu( 0.05 ) );
}
if( !error_msg.IsEmpty() ) if( !error_msg.IsEmpty() )
{ {

View File

@ -175,12 +175,12 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT*
* These closed inner outlines are considered as holes in the main outline * These closed inner outlines are considered as holes in the main outline
* @param aSegList the initial list of drawsegments (only lines, circles and arcs). * @param aSegList the initial list of drawsegments (only lines, circles and arcs).
* @param aPolygons will contain the complex polygon. * @param aPolygons will contain the complex polygon.
* @param aTolerance is the max distance between points that is still accepted as connected (internal units)
* @param aErrorText is a wxString to return error message. * @param aErrorText is a wxString to return error message.
*/ */
bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
SHAPE_POLY_SET& aPolygons, wxString* aErrorText ) wxString* aErrorText, unsigned int aTolerance )
{ {
if( aSegList.size() == 0 ) if( aSegList.size() == 0 )
return true; return true;
@ -189,7 +189,6 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
// Make a working copy of aSegList, because the list is modified during calculations // Make a working copy of aSegList, because the list is modified during calculations
std::vector< DRAWSEGMENT* > segList = aSegList; std::vector< DRAWSEGMENT* > segList = aSegList;
unsigned prox; // a proximity BIU metric, not an accurate distance
DRAWSEGMENT* graphic; DRAWSEGMENT* graphic;
wxPoint prevPt; wxPoint prevPt;
@ -279,11 +278,6 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
// The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items' // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
segList.erase( segList.begin() + xmini ); segList.erase( segList.begin() + xmini );
// Set maximum proximity threshold for point to point nearness metric for
// board perimeter only, not interior keepouts yet.
prox = Millimeter2iu( 0.01 ); // should be enough to fix rounding issues
// is arc start and end point calculations
// Output the Edge.Cuts perimeter as circle or polygon. // Output the Edge.Cuts perimeter as circle or polygon.
if( graphic->GetShape() == S_CIRCLE ) if( graphic->GetShape() == S_CIRCLE )
{ {
@ -337,9 +331,9 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
double radius = graphic->GetRadius(); double radius = graphic->GetRadius();
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 ); int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
if( !close_enough( prevPt, pstart, prox ) ) if( !close_enough( prevPt, pstart, aTolerance ) )
{ {
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) ); wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
angle = -angle; angle = -angle;
std::swap( pstart, pend ); std::swap( pstart, pend );
@ -374,14 +368,14 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
// Get next closest segment. // Get next closest segment.
graphic = findPoint( prevPt, segList, prox ); graphic = findPoint( prevPt, segList, aTolerance );
// If there are no more close segments, check if the board // If there are no more close segments, check if the board
// outline polygon can be closed. // outline polygon can be closed.
if( !graphic ) if( !graphic )
{ {
if( close_enough( startPt, prevPt, prox ) ) if( close_enough( startPt, prevPt, aTolerance ) )
{ {
// Close the polygon back to start point // Close the polygon back to start point
// aPolygons.Append( startPt ); // not needed // aPolygons.Append( startPt ); // not needed
@ -407,11 +401,6 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
} }
} }
// Output the interior Edge.Cuts graphics as keepouts, using same nearness
// metric as the board edge as otherwise we have trouble completing complex
// polygons.
prox = Millimeter2iu( 0.05 );
while( segList.size() ) while( segList.size() )
{ {
// emit a signal layers keepout for every interior polygon left... // emit a signal layers keepout for every interior polygon left...
@ -488,9 +477,9 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
int radius = graphic->GetRadius(); int radius = graphic->GetRadius();
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 ); int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
if( !close_enough( prevPt, pstart, prox ) ) if( !close_enough( prevPt, pstart, aTolerance ) )
{ {
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), prox ) ); wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
angle = -angle; angle = -angle;
std::swap( pstart, pend ); std::swap( pstart, pend );
@ -526,14 +515,14 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
// Get next closest segment. // Get next closest segment.
graphic = findPoint( prevPt, segList, prox ); graphic = findPoint( prevPt, segList, aTolerance );
// If there are no more close segments, check if polygon // If there are no more close segments, check if polygon
// can be closed. // can be closed.
if( !graphic ) if( !graphic )
{ {
if( close_enough( startPt, prevPt, prox ) ) if( close_enough( startPt, prevPt, aTolerance ) )
{ {
// Close the polygon back to start point // Close the polygon back to start point
// aPolygons.Append( startPt, -1, hole ); // not needed // aPolygons.Append( startPt, -1, hole ); // not needed
@ -570,9 +559,8 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
* Any closed outline inside the main outline is a hole * Any closed outline inside the main outline is a hole
* All contours should be closed, i.e. valid closed polygon vertices * All contours should be closed, i.e. valid closed polygon vertices
*/ */
bool BuildBoardPolygonOutlines( BOARD* aBoard, bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
SHAPE_POLY_SET& aOutlines, wxString* aErrorText, unsigned int aTolerance )
wxString* aErrorText )
{ {
PCB_TYPE_COLLECTOR items; PCB_TYPE_COLLECTOR items;
@ -590,7 +578,7 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard,
segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) ); segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
} }
bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText ); bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance );
if( !success || !aOutlines.OutlineCount() ) if( !success || !aOutlines.OutlineCount() )
{ {

View File

@ -219,6 +219,8 @@ void DIALOG_EXPORT_STEP::onUpdateYPos( wxUpdateUIEvent& aEvent )
aEvent.Enable( m_rbUserDefinedOrigin->GetValue() ); aEvent.Enable( m_rbUserDefinedOrigin->GetValue() );
} }
extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
wxString* aErrorText, unsigned int aTolerance );
void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent ) void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
{ {
@ -226,8 +228,7 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
wxString msg; wxString msg;
// Check if the board outline is continuous // Check if the board outline is continuous
// TODO the check below is more forgiving than kicad2step, needs to be more strict if( !BuildBoardPolygonOutlines( m_parent->GetBoard(), outline, &msg, Millimeter2iu( 0.01 ) ) )
if( !m_parent->GetBoard()->GetBoardPolygonOutlines( outline, &msg ) )
{ {
DisplayErrorMessage( this, _( "Cannot determine the board outline." ), msg ); DisplayErrorMessage( this, _( "Cannot determine the board outline." ), msg );
return; return;