Improve performance, commenting and API of some polygon classes.

This commit is contained in:
Jeff Young 2019-07-13 17:35:57 +01:00
parent 560fda70a2
commit 1a7cef2950
11 changed files with 87 additions and 143 deletions

View File

@ -392,9 +392,16 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUs
}
}
// If aAccuracy is > 0 then by definition we don't care whether or not the point is
// *exactly* on the edge -- which saves us considerable processing time
return inside && ( aAccuracy > 0 || !PointOnEdge( aPt ) );
// If accuracy is 0 then we need to make sure the point isn't actually on the edge.
// If accuracy is 1 then we don't really care whether or not the point is *exactly* on the
// edge, so we skip edge processing for performance.
// If accuracy is > 1, then we use "OnEdge(accuracy-1)" as a proxy for "Inside(accuracy)".
if( aAccuracy == 0 )
return inside && !PointOnEdge( aPt );
else if( aAccuracy == 1 )
return inside;
else
return inside || PointOnEdge( aPt, aAccuracy - 1 );
}

View File

@ -1191,28 +1191,18 @@ bool SHAPE_POLY_SET::PointOnEdge( const VECTOR2I& aP ) const
bool SHAPE_POLY_SET::Collide( const SEG& aSeg, int aClearance ) const
{
SHAPE_POLY_SET polySet = SHAPE_POLY_SET( *this );
// Inflate the polygon if necessary.
if( aClearance > 0 )
{
// fixme: the number of arc segments should not be hardcoded
polySet.Inflate( aClearance, 8 );
}
// We are going to check to see if the segment crosses an external
// boundary. However, if the full segment is inside the polyset, this
// will not be true. So we first test to see if one of the points is
// inside. If true, then we collide
if( polySet.Contains( aSeg.A ) )
// We are going to check to see if the segment crosses an external boundary. However, if
// the full segment is inside the polyset, this will not be true. So we first test to see
// if one of the points is inside. If true, then we collide. Use an accuracy of "1" to
// indicate that a collision with the edge should be treated the same as inside.
if( Collide( aSeg.A, 1 ) )
return true;
for( SEGMENT_ITERATOR iterator = polySet.IterateSegmentsWithHoles(); iterator; iterator++ )
for( SEGMENT_ITERATOR it = ( (SHAPE_POLY_SET*) this )->IterateSegmentsWithHoles(); it; it++ )
{
SEG polygonEdge = *iterator;
SEG polygonEdge = *it;
if( polygonEdge.Intersect( aSeg, true ) )
if( polygonEdge.Collide( aSeg, aClearance ) )
return true;
}
@ -1222,17 +1212,7 @@ bool SHAPE_POLY_SET::Collide( const SEG& aSeg, int aClearance ) const
bool SHAPE_POLY_SET::Collide( const VECTOR2I& aP, int aClearance ) const
{
SHAPE_POLY_SET polySet = SHAPE_POLY_SET( *this );
// Inflate the polygon if necessary.
if( aClearance > 0 )
{
// fixme: the number of arc segments should not be hardcoded
polySet.Inflate( aClearance, 8 );
}
// There is a collision if and only if the point is inside of the polygon.
return polySet.Contains( aP );
return Contains( aP, -1, aClearance );
}
@ -1403,20 +1383,20 @@ void SHAPE_POLY_SET::BuildBBoxCaches()
}
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
bool aIgnoreEdges, bool aUseBBoxCaches ) const
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aUseBBoxCaches ) const
{
if( m_polys.size() == 0 ) // empty set?
if( m_polys.empty() )
return false;
// If there is a polygon specified, check the condition against that polygon
if( aSubpolyIndex >= 0 )
return containsSingle( aP, aSubpolyIndex, aIgnoreHoles, aIgnoreEdges, aUseBBoxCaches );
return containsSingle( aP, aSubpolyIndex, aAccuracy, aUseBBoxCaches );
// In any other case, check it against all polygons in the set
for( int polygonIdx = 0; polygonIdx < OutlineCount(); polygonIdx++ )
{
if( containsSingle( aP, polygonIdx, aIgnoreHoles, aIgnoreEdges, aUseBBoxCaches ) )
if( containsSingle( aP, polygonIdx, aAccuracy, aUseBBoxCaches ) )
return true;
}
@ -1442,24 +1422,21 @@ void SHAPE_POLY_SET::RemoveVertex( VERTEX_INDEX aIndex )
}
bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
bool aIgnoreEdges, bool aUseBBoxCaches ) const
bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aUseBBoxCaches ) const
{
// Check that the point is inside the outline
if( pointInPolygon( aP, m_polys[aSubpolyIndex][0], aIgnoreEdges ) )
if( m_polys[aSubpolyIndex][0].PointInside( aP, aAccuracy ) )
{
if( !aIgnoreHoles )
// Check that the point is not in any of the holes
for( int holeIdx = 0; holeIdx < HoleCount( aSubpolyIndex ); holeIdx++ )
{
// Check that the point is not in any of the holes
for( int holeIdx = 0; holeIdx < HoleCount( aSubpolyIndex ); holeIdx++ )
{
const SHAPE_LINE_CHAIN& hole = CHole( aSubpolyIndex, holeIdx );
const SHAPE_LINE_CHAIN& hole = CHole( aSubpolyIndex, holeIdx );
// If the point is inside a hole (and not on its edge),
// it is outside of the polygon
if( pointInPolygon( aP, hole, aIgnoreEdges, aUseBBoxCaches ) )
return false;
}
// If the point is inside a hole it is outside of the polygon. Do not use aAccuracy
// here as it's meaning would be inverted.
if( hole.PointInside( aP, 1, aUseBBoxCaches ) )
return false;
}
return true;
@ -1469,13 +1446,6 @@ bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool
}
bool SHAPE_POLY_SET::pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
bool aIgnoreEdges, bool aUseBBoxCaches ) const
{
return aPath.PointInside( aP, aIgnoreEdges ? 1 : 0, aUseBBoxCaches );
}
void SHAPE_POLY_SET::Move( const VECTOR2I& aVector )
{
for( POLYGON& poly : m_polys )
@ -1526,11 +1496,11 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::FilletPolygon( unsigned int aRadius,
int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
{
// We calculate the min dist between the segment and each outline segment
// However, if the segment to test is inside the outline, and does not cross
// any edge, it can be seen outside the polygon.
// Therefore test if a segment end is inside ( testing only one end is enough )
if( containsSingle( aPoint, aPolygonIndex ) )
// We calculate the min dist between the segment and each outline segment. However, if the
// segment to test is inside the outline, and does not cross any edge, it can be seen outside
// the polygon. Therefore test if a segment end is inside (testing only one end is enough).
// Use an accuracy of "1" to say that we don't care if it's exactly on the edge or not.
if( containsSingle( aPoint, aPolygonIndex, 1 ) )
return 0;
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex );
@ -1552,13 +1522,13 @@ int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
}
int SHAPE_POLY_SET::DistanceToPolygon( SEG aSegment, int aPolygonIndex, int aSegmentWidth )
int SHAPE_POLY_SET::DistanceToPolygon( const SEG& aSegment, int aPolygonIndex, int aSegmentWidth )
{
// We calculate the min dist between the segment and each outline segment
// However, if the segment to test is inside the outline, and does not cross
// any edge, it can be seen outside the polygon.
// Therefore test if a segment end is inside ( testing only one end is enough )
if( containsSingle( aSegment.A, aPolygonIndex ) )
// We calculate the min dist between the segment and each outline segment. However, if the
// segment to test is inside the outline, and does not cross any edge, it can be seen outside
// the polygon. Therefore test if a segment end is inside (testing only one end is enough).
// Use an accuracy of "1" to say that we don't care if it's exactly on the edge or not.
if( containsSingle( aSegment.A, aPolygonIndex, 1 ) )
return 0;
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex );

View File

@ -236,7 +236,7 @@ const EDA_RECT WS_DRAW_ITEM_POLYPOLYGONS::GetBoundingBox() const
bool WS_DRAW_ITEM_POLYPOLYGONS::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
return m_Polygons.Contains( aPosition );
return m_Polygons.Collide( aPosition, aAccuracy );
}

View File

@ -776,12 +776,12 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos, int aAccuracy ) const
{
case GBR_POLYGON:
poly = m_Polygon;
return poly.Contains( VECTOR2I( ref_pos ), 0 );
return poly.Contains( VECTOR2I( ref_pos ), 0, aAccuracy );
case GBR_SPOT_POLY:
poly = GetDcodeDescr()->m_Polygon;
poly.Move( m_Start );
return poly.Contains( VECTOR2I( ref_pos ), 0 );
return poly.Contains( VECTOR2I( ref_pos ), 0, aAccuracy );
case GBR_SPOT_RECT:
return GetBoundingBox().Contains( aRefPos );
@ -828,12 +828,7 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos, int aAccuracy ) const
case GBR_SPOT_MACRO:
// Aperture macro polygons are already in absolute coordinates
auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
for( int i = 0; i < p->OutlineCount(); ++i )
{
if( p->Contains( VECTOR2I( aRefPos ), i ) )
return true;
}
return false;
return p->Contains( VECTOR2I( aRefPos ), -1, aAccuracy );
}
// TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)

View File

@ -844,11 +844,6 @@ class SHAPE_POLY_SET : public SHAPE
*/
void Inflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false );
void Inflate( int aFactor, bool aPreserveCorners )
{
Inflate( aFactor, 32, aPreserveCorners );
}
void Deflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false )
{
Inflate( -aFactor, aPreserveCorners, aPreserveCorners );
@ -961,7 +956,7 @@ class SHAPE_POLY_SET : public SHAPE
* @return bool - true if there is a collision, false in any other case.
*/
bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
int aClearance = 0 );
int aClearance = 0 );
/**
* Function CollideEdge
@ -974,7 +969,7 @@ class SHAPE_POLY_SET : public SHAPE
* @return bool - true if there is a collision, false in any other case.
*/
bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
int aClearance = 0 );
int aClearance = 0 );
/**
* Constructs BBoxCaches for Contains(), below. These caches MUST be built before a
@ -987,16 +982,13 @@ class SHAPE_POLY_SET : public SHAPE
*
* @param aP is the point to check
* @param aSubpolyIndex is the subpolygon to check, or -1 to check all
* @param aIgnoreHoles controls whether or not internal holes are considered
* @param aIgnoreEdges controls whether or not a check for the point lying exactly on
* the polygon edge is made
* @param aUseBBoxCaches gives faster performance when multiple calls are made with no
* editing in between, but the caller MUST cache the bbox caches
* before calling (via BuildBBoxCaches(), above)
* @return true if the polygon contains the point
*/
bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, bool aIgnoreHoles = false,
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const;
bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, int aAccuracy = 0,
bool aUseBBoxCaches = false ) const;
///> Returns true if the set is empty (no polygons at all)
bool IsEmpty() const
@ -1102,7 +1094,7 @@ class SHAPE_POLY_SET : public SHAPE
* aIndex-th polygon. If the point is contained in the polygon, the
* distance is zero.
*/
int DistanceToPolygon( SEG aSegment, int aIndex, int aSegmentWidth = 0 );
int DistanceToPolygon( const SEG& aSegment, int aIndex, int aSegmentWidth = 0 );
/**
* Function DistanceToPolygon
@ -1153,9 +1145,6 @@ class SHAPE_POLY_SET : public SHAPE
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
bool aIgnoreEdges, bool aUseBBoxCaches = false ) const;
/**
* containsSingle function
* Checks whether the point aP is inside the aSubpolyIndex-th polygon of the polyset. If
@ -1164,17 +1153,15 @@ class SHAPE_POLY_SET : public SHAPE
* the aSubpolyIndex-th polygon will be tested.
* @param aSubpolyIndex is an integer specifying which polygon in the set has to be
* checked.
* @param aIgnoreHoles can be set to true to ignore internal holes in the polygon
* @param aIgnoreEdges can be set to true to skip checking whether or not the point
* lies directly on the edge
* @param aAccuracy accuracy in internal units
* @param aUseBBoxCaches gives faster performance when multiple calls are made with no
* editing in between, but the caller MUST cache the bbox caches
* before calling (via BuildBBoxCaches(), above)
* @return bool - true if aP is inside aSubpolyIndex-th polygon; false in any other
* case.
*/
bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles = false,
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const;
bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aUseBBoxCaches = false ) const;
/**
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet

View File

@ -448,7 +448,7 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
{
wxString msg;
aList.push_back( MSG_PANEL_ITEM( m_Reference->GetShownText(), m_Value->GetShownText(), DARKCYAN ) );
aList.emplace_back( MSG_PANEL_ITEM( m_Reference->GetShownText(), m_Value->GetShownText(), DARKCYAN ) );
// Display last date the component was edited (useful in Module Editor).
wxDateTime date( static_cast<time_t>( m_LastEditTime ) );
@ -459,18 +459,18 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
else
msg = _( "Unknown" );
aList.push_back( MSG_PANEL_ITEM( _( "Last Change" ), msg, BROWN ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Last Change" ), msg, BROWN ) );
// display schematic path
aList.push_back( MSG_PANEL_ITEM( _( "Netlist Path" ), m_Path, BROWN ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Netlist Path" ), m_Path, BROWN ) );
// display the board side placement
aList.push_back( MSG_PANEL_ITEM( _( "Board Side" ),
IsFlipped()? _( "Back (Flipped)" ) : _( "Front" ), RED ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Board Side" ),
IsFlipped()? _( "Back (Flipped)" ) : _( "Front" ), RED ) );
msg.Printf( wxT( "%zu" ), m_pads.size() );
aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), msg, BLUE ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Pads" ), msg, BLUE ) );
msg = wxT( ".." );
@ -480,10 +480,10 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
if( m_ModuleStatus & MODULE_is_PLACED )
msg[1] = 'P';
aList.push_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) );
msg.Printf( wxT( "%.1f" ), GetOrientationDegrees() );
aList.push_back( MSG_PANEL_ITEM( _( "Rotation" ), msg, BROWN ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Rotation" ), msg, BROWN ) );
// Controls on right side of the dialog
switch( m_Attributs & 255 )
@ -505,8 +505,8 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
break;
}
aList.push_back( MSG_PANEL_ITEM( _( "Attributes" ), msg, BROWN ) );
aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), FROM_UTF8( m_fpid.Format().c_str() ), BLUE ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Attributes" ), msg, BROWN ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "Footprint" ), FROM_UTF8( m_fpid.Format().c_str() ), BLUE ) );
if( m_3D_Drawings.empty() )
msg = _( "No 3D shape" );
@ -515,12 +515,12 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
// Search the first active 3D shape in list
aList.push_back( MSG_PANEL_ITEM( _( "3D-Shape" ), msg, RED ) );
aList.emplace_back( MSG_PANEL_ITEM( _( "3D-Shape" ), msg, RED ) );
wxString doc, keyword;
doc.Printf( _( "Doc: %s" ), GetChars( m_Doc ) );
keyword.Printf( _( "Key Words: %s" ), GetChars( m_KeyWord ) );
aList.push_back( MSG_PANEL_ITEM( doc, keyword, BLACK ) );
doc.Printf( _( "Doc: %s" ), m_Doc );
keyword.Printf( _( "Key Words: %s" ), m_KeyWord );
aList.emplace_back( MSG_PANEL_ITEM( doc, keyword, BLACK ) );
}
@ -533,10 +533,7 @@ bool MODULE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
bool MODULE::HitTestAccurate( const wxPoint& aPosition, int aAccuracy ) const
{
SHAPE_POLY_SET shape = GetBoundingPoly();
shape.Inflate( aAccuracy, 4 );
return shape.Contains( aPosition, -1, true );
return GetBoundingPoly().Collide( aPosition, aAccuracy );
}

View File

@ -1198,9 +1198,10 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly ) const
* Convert the zone filled areas polygons to polygons
* inflated (optional) by max( aClearanceValue, the zone clearance)
* and copy them in aCornerBuffer
* param aClearanceValue = the clearance around polygons
* param aAddClearance = true to add a clearance area to the polygon
* false to create the outline polygon.
* @param aMinClearanceValue the min clearance around outlines
* @param aUseNetClearance true to use a clearance which is the max value between
* aMinClearanceValue and the net clearance
* false to use aMinClearanceValue only
*/
void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
SHAPE_POLY_SET& aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance ) const
@ -1215,6 +1216,7 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
if( aUseNetClearance && IsOnCopperLayer() )
{
clearance = GetClearance();
if( aMinClearanceValue > clearance )
clearance = aMinClearanceValue;
}
@ -1223,7 +1225,7 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
// holes are linked to the main outline, so only one polygon is created.
if( clearance )
{
auto board = GetBoard();
BOARD* board = GetBoard();
int maxError = ARC_HIGH_DEF;
if( board )
@ -1232,6 +1234,7 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
int segCount = std::max( GetArcToSegmentCount( clearance, maxError, 360.0 ), 3 );
polybuffer.Inflate( clearance, segCount );
}
polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
aCornerBuffer.Append( polybuffer );
}

View File

@ -247,18 +247,6 @@ public:
*/
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
/**
* Function HitTest
* tests if a point is inside the zone area, i.e. inside the main outline
* and outside holes.
* @param aPosition : the wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTestInsideZone( const wxPoint& aPosition ) const
{
return m_Poly->Contains( VECTOR2I( aPosition ), 0 );
}
/**
* Function HitTestFilledArea
* tests if the given wxPoint is within the bounds of a filled area of this zone.
@ -575,8 +563,7 @@ public:
/**
* Function GetSmoothedPoly
* returns a pointer to the corner-smoothed version of
* m_Poly if it exists, otherwise it returns m_Poly.
* returns a pointer to the corner-smoothed version of m_Poly.
* @return SHAPE_POLY_SET* - pointer to the polygon.
*/
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly ) const;

View File

@ -1186,7 +1186,7 @@ ZONE_CONTAINER* EAGLE_PLUGIN::loadPolygon( wxXmlNode* aPolyNode )
// We trace the zone such that the copper is completely inside.
if( p.width.ToPcbUnits() > 0 )
{
polygon.Inflate( p.width.ToPcbUnits() / 2, true );
polygon.Inflate( p.width.ToPcbUnits() / 2, 32, true );
polygon.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
}

View File

@ -852,10 +852,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
int zone_margin = 0;
#endif
for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ )
for( ZONE_CONTAINER* zone : aBoard->Zones() )
{
ZONE_CONTAINER* zone = aBoard->GetArea( ii );
if( zone->GetLayer() != layer )
continue;

View File

@ -111,9 +111,7 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE_CONTAINER*>& aZones, bool aCheck
bool filledPolyWithOutline = not m_board->GetDesignSettings().m_ZoneUseNoOutlineInFill;
if( ADVANCED_CFG::GetCfg().m_forceThickOutlinesInZones )
{
filledPolyWithOutline = true;
}
std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock );
@ -722,7 +720,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
const VECTOR2I& testPt = spoke.CPoint( 3 );
// Hit-test against zone body
if( testAreas.Contains( testPt, -1, false, true, USE_BBOX_CACHES ) )
if( testAreas.Contains( testPt, -1, 1, USE_BBOX_CACHES ) )
{
aRawPolys.AddOutline( spoke );
continue;
@ -782,7 +780,8 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
}
/* Build the filled solid areas data from real outlines (stored in m_Poly)
/*
* Build the filled solid areas data from real outlines (stored in m_Poly)
* The solid areas can be more than one on copper layers, and do not have holes
* ( holes are linked by overlapping segments to the main outline)
*/
@ -791,7 +790,8 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPol
{
SHAPE_POLY_SET smoothedPoly;
/* convert outlines + holes to outlines without holes (adding extra segments if necessary)
/*
* convert outlines + holes to outlines without holes (adding extra segments if necessary)
* m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
* this zone
*/