Separate polygonization error from chaining error.
This way we can report anything that doesn't exactly chain while still applying a fudge factor for our own stuff. Fixes https://gitlab.com/kicad/code/kicad/issues/1795
This commit is contained in:
parent
359c29639f
commit
ef25c78a04
|
@ -473,8 +473,11 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
|
||||||
|
|
||||||
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
||||||
m_board->GetDesignSettings().m_MaxError );
|
m_board->GetDesignSettings().m_MaxError,
|
||||||
|
chainingEpsilon );
|
||||||
|
|
||||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||||
|
|
|
@ -1844,8 +1844,10 @@ bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE* aCurr
|
||||||
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
||||||
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||||
{
|
{
|
||||||
|
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
|
||||||
|
|
||||||
bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
|
bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
|
||||||
aErrorHandler );
|
chainingEpsilon, aErrorHandler );
|
||||||
|
|
||||||
// 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 );
|
||||||
|
|
|
@ -185,11 +185,13 @@ static PCB_SHAPE* findNext( PCB_SHAPE* aShape, const wxPoint& aPoint,
|
||||||
* 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 error distance when polygonizing a curve (internal units)
|
* @param aErrorMax is the max error distance when polygonizing a curve (internal units)
|
||||||
|
* @param aChainingEpsilon is the max error distance when polygonizing a curve (internal units)
|
||||||
* @param aErrorHandler = an optional error handler
|
* @param aErrorHandler = an optional error handler
|
||||||
*/
|
*/
|
||||||
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
||||||
int aTolerance, OUTLINE_ERROR_HANDLER* aErrorHandler )
|
int aErrorMax, int aChainingEpsilon,
|
||||||
|
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||||
{
|
{
|
||||||
if( aSegList.size() == 0 )
|
if( aSegList.size() == 0 )
|
||||||
return true;
|
return true;
|
||||||
|
@ -237,7 +239,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
wxPoint center = graphic->GetCenter();
|
wxPoint center = graphic->GetCenter();
|
||||||
double angle = -graphic->GetAngle();
|
double angle = -graphic->GetAngle();
|
||||||
double radius = graphic->GetRadius();
|
double radius = graphic->GetRadius();
|
||||||
int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
|
int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 );
|
||||||
wxPoint pt;
|
wxPoint pt;
|
||||||
|
|
||||||
for( int step = 1; step<=steps; ++step )
|
for( int step = 1; step<=steps; ++step )
|
||||||
|
@ -432,11 +434,11 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
wxPoint pcenter = graphic->GetCenter();
|
wxPoint pcenter = graphic->GetCenter();
|
||||||
double angle = -graphic->GetAngle();
|
double angle = -graphic->GetAngle();
|
||||||
double radius = graphic->GetRadius();
|
double radius = graphic->GetRadius();
|
||||||
int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
|
int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 );
|
||||||
|
|
||||||
if( !close_enough( prevPt, pstart, aTolerance ) )
|
if( !close_enough( prevPt, pstart, aChainingEpsilon ) )
|
||||||
{
|
{
|
||||||
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
|
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aChainingEpsilon ) );
|
||||||
|
|
||||||
angle = -angle;
|
angle = -angle;
|
||||||
std::swap( pstart, pend );
|
std::swap( pstart, pend );
|
||||||
|
@ -514,7 +516,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
|
|
||||||
// Get next closest segment.
|
// Get next closest segment.
|
||||||
|
|
||||||
PCB_SHAPE* nextGraphic = findNext( graphic, prevPt, aSegList, aTolerance );
|
PCB_SHAPE* nextGraphic = findNext( graphic, prevPt, aSegList, aChainingEpsilon );
|
||||||
|
|
||||||
if( nextGraphic && !( nextGraphic->GetFlags() & SKIP_STRUCT ) )
|
if( nextGraphic && !( nextGraphic->GetFlags() & SKIP_STRUCT ) )
|
||||||
{
|
{
|
||||||
|
@ -526,7 +528,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
|
|
||||||
// Finished, or ran into trouble...
|
// Finished, or ran into trouble...
|
||||||
|
|
||||||
if( close_enough( startPt, prevPt, aTolerance ) )
|
if( close_enough( startPt, prevPt, aChainingEpsilon ) )
|
||||||
{
|
{
|
||||||
polygonComplete = true;
|
polygonComplete = true;
|
||||||
break;
|
break;
|
||||||
|
@ -595,7 +597,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
double angle = 3600.0;
|
double angle = 3600.0;
|
||||||
wxPoint start = center;
|
wxPoint start = center;
|
||||||
int radius = graphic->GetRadius();
|
int radius = graphic->GetRadius();
|
||||||
int steps = GetArcToSegmentCount( radius, aTolerance, 360.0 );
|
int steps = GetArcToSegmentCount( radius, aErrorMax, 360.0 );
|
||||||
wxPoint nextPt;
|
wxPoint nextPt;
|
||||||
|
|
||||||
start.x += radius;
|
start.x += radius;
|
||||||
|
@ -673,11 +675,12 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
wxPoint pcenter = graphic->GetCenter();
|
wxPoint pcenter = graphic->GetCenter();
|
||||||
double angle = -graphic->GetAngle();
|
double angle = -graphic->GetAngle();
|
||||||
int radius = graphic->GetRadius();
|
int radius = graphic->GetRadius();
|
||||||
int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
|
int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 );
|
||||||
|
|
||||||
if( !close_enough( prevPt, pstart, aTolerance ) )
|
if( !close_enough( prevPt, pstart, aChainingEpsilon ) )
|
||||||
{
|
{
|
||||||
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
|
wxASSERT( close_enough( prevPt, graphic->GetArcEnd(),
|
||||||
|
aChainingEpsilon ) );
|
||||||
|
|
||||||
angle = -angle;
|
angle = -angle;
|
||||||
std::swap( pstart, pend );
|
std::swap( pstart, pend );
|
||||||
|
@ -757,7 +760,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
|
|
||||||
// Get next closest segment.
|
// Get next closest segment.
|
||||||
|
|
||||||
PCB_SHAPE* nextGraphic = findNext( graphic, prevPt, aSegList, aTolerance );
|
PCB_SHAPE* nextGraphic = findNext( graphic, prevPt, aSegList, aChainingEpsilon );
|
||||||
|
|
||||||
if( nextGraphic && !( nextGraphic->GetFlags() & SKIP_STRUCT ) )
|
if( nextGraphic && !( nextGraphic->GetFlags() & SKIP_STRUCT ) )
|
||||||
{
|
{
|
||||||
|
@ -769,7 +772,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
|
|
||||||
// Finished, or ran into trouble...
|
// Finished, or ran into trouble...
|
||||||
|
|
||||||
if( close_enough( startPt, prevPt, aTolerance ) )
|
if( close_enough( startPt, prevPt, aChainingEpsilon ) )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -842,8 +845,8 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
||||||
* 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, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aErrorMax,
|
||||||
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
int aChainingEpsilon, OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||||
{
|
{
|
||||||
PCB_TYPE_COLLECTOR items;
|
PCB_TYPE_COLLECTOR items;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
@ -863,7 +866,8 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aT
|
||||||
|
|
||||||
if( segList.size() )
|
if( segList.size() )
|
||||||
{
|
{
|
||||||
success = ConvertOutlineToPolygon( segList, aOutlines, aTolerance, aErrorHandler );
|
success = ConvertOutlineToPolygon( segList, aOutlines, aErrorMax, aChainingEpsilon,
|
||||||
|
aErrorHandler );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !success || !aOutlines.OutlineCount() )
|
if( !success || !aOutlines.OutlineCount() )
|
||||||
|
@ -1055,8 +1059,8 @@ int findEndSegments( SHAPE_LINE_CHAIN& aChain, SEG& aStartSeg, SEG& aEndSeg )
|
||||||
* * If copper is located outside a closed outline, then that outline will be treated
|
* * If copper is located outside a closed outline, then that outline will be treated
|
||||||
* as a hole, and the outer edge will be formed using the bounding box.
|
* as a hole, and the outer edge will be formed using the bounding box.
|
||||||
*/
|
*/
|
||||||
bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aErrorMax,
|
||||||
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
int aChainingEpsilon, OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||||
|
|
||||||
{
|
{
|
||||||
PCB_TYPE_COLLECTOR items;
|
PCB_TYPE_COLLECTOR items;
|
||||||
|
@ -1075,7 +1079,8 @@ bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, in
|
||||||
segList.push_back( static_cast<PCB_SHAPE*>( items[ii] ) );
|
segList.push_back( static_cast<PCB_SHAPE*>( items[ii] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = ConvertOutlineToPolygon( segList, outlines, aTolerance, aErrorHandler );
|
bool success = ConvertOutlineToPolygon( segList, outlines, aErrorMax, aChainingEpsilon,
|
||||||
|
aErrorHandler );
|
||||||
|
|
||||||
FOOTPRINT* footprint = aBoard->GetFirstFootprint();
|
FOOTPRINT* footprint = aBoard->GetFirstFootprint();
|
||||||
|
|
||||||
|
|
|
@ -45,20 +45,22 @@ const std::function<void( const wxString& msg, BOARD_ITEM* itemA, BOARD_ITEM* it
|
||||||
* 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 error distance when polygonizing a curve (internal units)
|
* @param aErrorMax is the max error distance when polygonizing a curve (internal units)
|
||||||
|
* @param aChainingEpsilon is the max distance from one endPt to the next startPt (internal units)
|
||||||
* @param aErrorHandler = an optional error handler
|
* @param aErrorHandler = an optional error handler
|
||||||
*/
|
*/
|
||||||
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
||||||
int aTolerance, OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
int aErrorMax, int aChainingEpsilon,
|
||||||
|
OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the board outlines and build a closed polygon
|
* Extracts the board outlines and build a closed polygon from lines, arcs and circle items on
|
||||||
* from lines, arcs and circle items on edge cut layer
|
* edge cut layer. Any closed outline inside the main outline is a hole. All contours should be
|
||||||
* Any closed outline inside the main outline is a hole
|
* 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, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
|
||||||
|
int aErrorMax, int aChainingEpsilon,
|
||||||
OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ private:
|
||||||
|
|
||||||
void DRC_TEST_PROVIDER_MISC::testOutline()
|
void DRC_TEST_PROVIDER_MISC::testOutline()
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET boardOutlines;
|
SHAPE_POLY_SET dummyOutline;
|
||||||
bool errorHandled = false;
|
bool errorHandled = false;
|
||||||
|
|
||||||
OUTLINE_ERROR_HANDLER errorHandler =
|
OUTLINE_ERROR_HANDLER errorHandler =
|
||||||
|
@ -95,7 +95,12 @@ void DRC_TEST_PROVIDER_MISC::testOutline()
|
||||||
errorHandled = true;
|
errorHandled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if( !m_board->GetBoardPolygonOutlines( boardOutlines, &errorHandler ) )
|
// Use a really tight chaining epsilon here so that we report errors that might affect
|
||||||
|
// other tools (such as STEP export).
|
||||||
|
constexpr int chainingEpsilon = Millimeter2iu( 0.02 ) / 100;
|
||||||
|
|
||||||
|
if( BuildBoardPolygonOutlines( m_board, dummyOutline, m_board->GetDesignSettings().m_MaxError,
|
||||||
|
chainingEpsilon, &errorHandler ) )
|
||||||
{
|
{
|
||||||
if( errorHandled )
|
if( errorHandled )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1801,18 +1801,29 @@ void FOOTPRINT::BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||||
if( !list_front.size() && !list_back.size() )
|
if( !list_front.size() && !list_back.size() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
constexpr int errorMax = Millimeter2iu( 0.02 ); /* error max for polygonization */
|
int errorMax = Millimeter2iu( 0.02 ); // max error for polygonization
|
||||||
|
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
|
||||||
|
|
||||||
if( ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, aErrorHandler ) )
|
if( ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, chainingEpsilon,
|
||||||
|
aErrorHandler ) )
|
||||||
|
{
|
||||||
m_poly_courtyard_front.CacheTriangulation( false );
|
m_poly_courtyard_front.CacheTriangulation( false );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
SetFlags( MALFORMED_F_COURTYARD );
|
SetFlags( MALFORMED_F_COURTYARD );
|
||||||
|
}
|
||||||
|
|
||||||
if( ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, aErrorHandler ) )
|
if( ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, chainingEpsilon,
|
||||||
|
aErrorHandler ) )
|
||||||
|
{
|
||||||
m_poly_courtyard_back.CacheTriangulation( false );
|
m_poly_courtyard_back.CacheTriangulation( false );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
SetFlags( MALFORMED_B_COURTYARD );
|
SetFlags( MALFORMED_B_COURTYARD );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT::SwapData( BOARD_ITEM* aImage )
|
void FOOTPRINT::SwapData( BOARD_ITEM* aImage )
|
||||||
|
|
Loading…
Reference in New Issue