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:
parent
1541cbdf04
commit
f0b3cf8077
|
@ -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 );
|
||||||
|
|
|
@ -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() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue