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;
|
||||
}
|
||||
|
||||
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
|
||||
|
||||
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)
|
||||
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,
|
||||
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,
|
||||
aErrorHandler );
|
||||
chainingEpsilon, aErrorHandler );
|
||||
|
||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||
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
|
||||
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
|
||||
* @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
|
||||
*/
|
||||
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 )
|
||||
return true;
|
||||
|
@ -237,7 +239,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
wxPoint center = graphic->GetCenter();
|
||||
double angle = -graphic->GetAngle();
|
||||
double radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
|
||||
int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 );
|
||||
wxPoint pt;
|
||||
|
||||
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();
|
||||
double angle = -graphic->GetAngle();
|
||||
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;
|
||||
std::swap( pstart, pend );
|
||||
|
@ -514,7 +516,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
|
||||
// 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 ) )
|
||||
{
|
||||
|
@ -526,7 +528,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
|
||||
// Finished, or ran into trouble...
|
||||
|
||||
if( close_enough( startPt, prevPt, aTolerance ) )
|
||||
if( close_enough( startPt, prevPt, aChainingEpsilon ) )
|
||||
{
|
||||
polygonComplete = true;
|
||||
break;
|
||||
|
@ -595,7 +597,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
double angle = 3600.0;
|
||||
wxPoint start = center;
|
||||
int radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( radius, aTolerance, 360.0 );
|
||||
int steps = GetArcToSegmentCount( radius, aErrorMax, 360.0 );
|
||||
wxPoint nextPt;
|
||||
|
||||
start.x += radius;
|
||||
|
@ -673,11 +675,12 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
wxPoint pcenter = graphic->GetCenter();
|
||||
double angle = -graphic->GetAngle();
|
||||
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;
|
||||
std::swap( pstart, pend );
|
||||
|
@ -757,7 +760,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
|
||||
// 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 ) )
|
||||
{
|
||||
|
@ -769,7 +772,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
|
||||
// Finished, or ran into trouble...
|
||||
|
||||
if( close_enough( startPt, prevPt, aTolerance ) )
|
||||
if( close_enough( startPt, prevPt, aChainingEpsilon ) )
|
||||
{
|
||||
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
|
||||
* All contours should be closed, i.e. valid closed polygon vertices
|
||||
*/
|
||||
bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
||||
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||
bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aErrorMax,
|
||||
int aChainingEpsilon, OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||
{
|
||||
PCB_TYPE_COLLECTOR items;
|
||||
bool success = false;
|
||||
|
@ -863,7 +866,8 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aT
|
|||
|
||||
if( segList.size() )
|
||||
{
|
||||
success = ConvertOutlineToPolygon( segList, aOutlines, aTolerance, aErrorHandler );
|
||||
success = ConvertOutlineToPolygon( segList, aOutlines, aErrorMax, aChainingEpsilon,
|
||||
aErrorHandler );
|
||||
}
|
||||
|
||||
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
|
||||
* as a hole, and the outer edge will be formed using the bounding box.
|
||||
*/
|
||||
bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
||||
OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||
bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aErrorMax,
|
||||
int aChainingEpsilon, OUTLINE_ERROR_HANDLER* aErrorHandler )
|
||||
|
||||
{
|
||||
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] ) );
|
||||
}
|
||||
|
||||
bool success = ConvertOutlineToPolygon( segList, outlines, aTolerance, aErrorHandler );
|
||||
bool success = ConvertOutlineToPolygon( segList, outlines, aErrorMax, aChainingEpsilon,
|
||||
aErrorHandler );
|
||||
|
||||
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
|
||||
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
* from lines, arcs and circle items on edge cut layer
|
||||
* Any closed outline inside the main outline is a hole
|
||||
* 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
|
||||
* Extracts the board outlines and build a closed polygon from lines, arcs and circle items on
|
||||
* edge cut layer. Any closed outline inside the main outline is a hole. 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
|
||||
*/
|
||||
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 );
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ private:
|
|||
|
||||
void DRC_TEST_PROVIDER_MISC::testOutline()
|
||||
{
|
||||
SHAPE_POLY_SET boardOutlines;
|
||||
SHAPE_POLY_SET dummyOutline;
|
||||
bool errorHandled = false;
|
||||
|
||||
OUTLINE_ERROR_HANDLER errorHandler =
|
||||
|
@ -95,7 +95,12 @@ void DRC_TEST_PROVIDER_MISC::testOutline()
|
|||
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 )
|
||||
{
|
||||
|
|
|
@ -1801,18 +1801,29 @@ void FOOTPRINT::BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler )
|
|||
if( !list_front.size() && !list_back.size() )
|
||||
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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlags( MALFORMED_B_COURTYARD );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT::SwapData( BOARD_ITEM* aImage )
|
||||
|
|
Loading…
Reference in New Issue