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 // If accuracy is 0 then we need to make sure the point isn't actually on the edge.
// *exactly* on the edge -- which saves us considerable processing time // If accuracy is 1 then we don't really care whether or not the point is *exactly* on the
return inside && ( aAccuracy > 0 || !PointOnEdge( aPt ) ); // 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 bool SHAPE_POLY_SET::Collide( const SEG& aSeg, int aClearance ) const
{ {
// We are going to check to see if the segment crosses an external boundary. However, if
SHAPE_POLY_SET polySet = SHAPE_POLY_SET( *this ); // 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
// Inflate the polygon if necessary. // indicate that a collision with the edge should be treated the same as inside.
if( aClearance > 0 ) if( Collide( aSeg.A, 1 ) )
{
// 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 ) )
return true; 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; 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 bool SHAPE_POLY_SET::Collide( const VECTOR2I& aP, int aClearance ) const
{ {
SHAPE_POLY_SET polySet = SHAPE_POLY_SET( *this ); return Contains( aP, -1, aClearance );
// 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 );
} }
@ -1403,20 +1383,20 @@ void SHAPE_POLY_SET::BuildBBoxCaches()
} }
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles, bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aIgnoreEdges, bool aUseBBoxCaches ) const bool aUseBBoxCaches ) const
{ {
if( m_polys.size() == 0 ) // empty set? if( m_polys.empty() )
return false; return false;
// If there is a polygon specified, check the condition against that polygon // If there is a polygon specified, check the condition against that polygon
if( aSubpolyIndex >= 0 ) 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 // In any other case, check it against all polygons in the set
for( int polygonIdx = 0; polygonIdx < OutlineCount(); polygonIdx++ ) for( int polygonIdx = 0; polygonIdx < OutlineCount(); polygonIdx++ )
{ {
if( containsSingle( aP, polygonIdx, aIgnoreHoles, aIgnoreEdges, aUseBBoxCaches ) ) if( containsSingle( aP, polygonIdx, aAccuracy, aUseBBoxCaches ) )
return true; 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 SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aIgnoreEdges, bool aUseBBoxCaches ) const bool aUseBBoxCaches ) const
{ {
// Check that the point is inside the outline // 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 const SHAPE_LINE_CHAIN& hole = CHole( aSubpolyIndex, holeIdx );
for( int holeIdx = 0; holeIdx < HoleCount( aSubpolyIndex ); holeIdx++ )
{
const SHAPE_LINE_CHAIN& hole = CHole( aSubpolyIndex, holeIdx );
// If the point is inside a hole (and not on its edge), // If the point is inside a hole it is outside of the polygon. Do not use aAccuracy
// it is outside of the polygon // here as it's meaning would be inverted.
if( pointInPolygon( aP, hole, aIgnoreEdges, aUseBBoxCaches ) ) if( hole.PointInside( aP, 1, aUseBBoxCaches ) )
return false; return false;
}
} }
return true; 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 ) void SHAPE_POLY_SET::Move( const VECTOR2I& aVector )
{ {
for( POLYGON& poly : m_polys ) 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 ) int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
{ {
// We calculate the min dist between the segment and each outline segment // We calculate the min dist between the segment and each outline segment. However, if the
// However, if the segment to test is inside the outline, and does not cross // segment to test is inside the outline, and does not cross any edge, it can be seen outside
// any edge, it can be seen outside the polygon. // the polygon. Therefore test if a segment end is inside (testing only one end is enough).
// 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 ) ) if( containsSingle( aPoint, aPolygonIndex, 1 ) )
return 0; return 0;
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex ); 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 // We calculate the min dist between the segment and each outline segment. However, if the
// However, if the segment to test is inside the outline, and does not cross // segment to test is inside the outline, and does not cross any edge, it can be seen outside
// any edge, it can be seen outside the polygon. // the polygon. Therefore test if a segment end is inside (testing only one end is enough).
// 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 ) ) if( containsSingle( aSegment.A, aPolygonIndex, 1 ) )
return 0; return 0;
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex ); 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 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: case GBR_POLYGON:
poly = m_Polygon; poly = m_Polygon;
return poly.Contains( VECTOR2I( ref_pos ), 0 ); return poly.Contains( VECTOR2I( ref_pos ), 0, aAccuracy );
case GBR_SPOT_POLY: case GBR_SPOT_POLY:
poly = GetDcodeDescr()->m_Polygon; poly = GetDcodeDescr()->m_Polygon;
poly.Move( m_Start ); poly.Move( m_Start );
return poly.Contains( VECTOR2I( ref_pos ), 0 ); return poly.Contains( VECTOR2I( ref_pos ), 0, aAccuracy );
case GBR_SPOT_RECT: case GBR_SPOT_RECT:
return GetBoundingBox().Contains( aRefPos ); return GetBoundingBox().Contains( aRefPos );
@ -828,12 +828,7 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos, int aAccuracy ) const
case GBR_SPOT_MACRO: case GBR_SPOT_MACRO:
// Aperture macro polygons are already in absolute coordinates // Aperture macro polygons are already in absolute coordinates
auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start ); auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
for( int i = 0; i < p->OutlineCount(); ++i ) return p->Contains( VECTOR2I( aRefPos ), -1, aAccuracy );
{
if( p->Contains( VECTOR2I( aRefPos ), i ) )
return true;
}
return false;
} }
// TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items) // 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, int aCircleSegmentsCount, bool aPreserveCorners = false );
void Inflate( int aFactor, bool aPreserveCorners )
{
Inflate( aFactor, 32, aPreserveCorners );
}
void Deflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false ) void Deflate( int aFactor, int aCircleSegmentsCount, bool aPreserveCorners = false )
{ {
Inflate( -aFactor, aPreserveCorners, aPreserveCorners ); 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. * @return bool - true if there is a collision, false in any other case.
*/ */
bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex, bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
int aClearance = 0 ); int aClearance = 0 );
/** /**
* Function CollideEdge * 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. * @return bool - true if there is a collision, false in any other case.
*/ */
bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex, 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 * 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 aP is the point to check
* @param aSubpolyIndex is the subpolygon to check, or -1 to check all * @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 * @param aUseBBoxCaches gives faster performance when multiple calls are made with no
* editing in between, but the caller MUST cache the bbox caches * editing in between, but the caller MUST cache the bbox caches
* before calling (via BuildBBoxCaches(), above) * before calling (via BuildBBoxCaches(), above)
* @return true if the polygon contains the point * @return true if the polygon contains the point
*/ */
bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, bool aIgnoreHoles = false, bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, int aAccuracy = 0,
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const; bool aUseBBoxCaches = false ) const;
///> Returns true if the set is empty (no polygons at all) ///> Returns true if the set is empty (no polygons at all)
bool IsEmpty() const 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 * aIndex-th polygon. If the point is contained in the polygon, the
* distance is zero. * distance is zero.
*/ */
int DistanceToPolygon( SEG aSegment, int aIndex, int aSegmentWidth = 0 ); int DistanceToPolygon( const SEG& aSegment, int aIndex, int aSegmentWidth = 0 );
/** /**
* Function DistanceToPolygon * Function DistanceToPolygon
@ -1153,9 +1145,6 @@ class SHAPE_POLY_SET : public SHAPE
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape, void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode ); 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 * containsSingle function
* Checks whether the point aP is inside the aSubpolyIndex-th polygon of the polyset. If * 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. * the aSubpolyIndex-th polygon will be tested.
* @param aSubpolyIndex is an integer specifying which polygon in the set has to be * @param aSubpolyIndex is an integer specifying which polygon in the set has to be
* checked. * checked.
* @param aIgnoreHoles can be set to true to ignore internal holes in the polygon * @param aAccuracy accuracy in internal units
* @param aIgnoreEdges can be set to true to skip checking whether or not the point
* lies directly on the edge
* @param aUseBBoxCaches gives faster performance when multiple calls are made with no * @param aUseBBoxCaches gives faster performance when multiple calls are made with no
* editing in between, but the caller MUST cache the bbox caches * editing in between, but the caller MUST cache the bbox caches
* before calling (via BuildBBoxCaches(), above) * before calling (via BuildBBoxCaches(), above)
* @return bool - true if aP is inside aSubpolyIndex-th polygon; false in any other * @return bool - true if aP is inside aSubpolyIndex-th polygon; false in any other
* case. * case.
*/ */
bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles = false, bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const; bool aUseBBoxCaches = false ) const;
/** /**
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet * 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; 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). // Display last date the component was edited (useful in Module Editor).
wxDateTime date( static_cast<time_t>( m_LastEditTime ) ); 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 else
msg = _( "Unknown" ); 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 // 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 // display the board side placement
aList.push_back( MSG_PANEL_ITEM( _( "Board Side" ), aList.emplace_back( MSG_PANEL_ITEM( _( "Board Side" ),
IsFlipped()? _( "Back (Flipped)" ) : _( "Front" ), RED ) ); IsFlipped()? _( "Back (Flipped)" ) : _( "Front" ), RED ) );
msg.Printf( wxT( "%zu" ), m_pads.size() ); 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( ".." ); msg = wxT( ".." );
@ -480,10 +480,10 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
if( m_ModuleStatus & MODULE_is_PLACED ) if( m_ModuleStatus & MODULE_is_PLACED )
msg[1] = 'P'; 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() ); 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 // Controls on right side of the dialog
switch( m_Attributs & 255 ) switch( m_Attributs & 255 )
@ -505,8 +505,8 @@ void MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >&
break; break;
} }
aList.push_back( MSG_PANEL_ITEM( _( "Attributes" ), msg, BROWN ) ); aList.emplace_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( _( "Footprint" ), FROM_UTF8( m_fpid.Format().c_str() ), BLUE ) );
if( m_3D_Drawings.empty() ) if( m_3D_Drawings.empty() )
msg = _( "No 3D shape" ); 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 // 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; wxString doc, keyword;
doc.Printf( _( "Doc: %s" ), GetChars( m_Doc ) ); doc.Printf( _( "Doc: %s" ), m_Doc );
keyword.Printf( _( "Key Words: %s" ), GetChars( m_KeyWord ) ); keyword.Printf( _( "Key Words: %s" ), m_KeyWord );
aList.push_back( MSG_PANEL_ITEM( doc, keyword, BLACK ) ); 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 bool MODULE::HitTestAccurate( const wxPoint& aPosition, int aAccuracy ) const
{ {
SHAPE_POLY_SET shape = GetBoundingPoly(); return GetBoundingPoly().Collide( aPosition, aAccuracy );
shape.Inflate( aAccuracy, 4 );
return shape.Contains( aPosition, -1, true );
} }

View File

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

View File

@ -247,18 +247,6 @@ public:
*/ */
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override; 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 * Function HitTestFilledArea
* tests if the given wxPoint is within the bounds of a filled area of this zone. * tests if the given wxPoint is within the bounds of a filled area of this zone.
@ -575,8 +563,7 @@ public:
/** /**
* Function GetSmoothedPoly * Function GetSmoothedPoly
* returns a pointer to the corner-smoothed version of * returns a pointer to the corner-smoothed version of m_Poly.
* m_Poly if it exists, otherwise it returns m_Poly.
* @return SHAPE_POLY_SET* - pointer to the polygon. * @return SHAPE_POLY_SET* - pointer to the polygon.
*/ */
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly ) const; 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. // We trace the zone such that the copper is completely inside.
if( p.width.ToPcbUnits() > 0 ) 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 ); polygon.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
} }

View File

@ -852,10 +852,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
int zone_margin = 0; int zone_margin = 0;
#endif #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 ) if( zone->GetLayer() != layer )
continue; 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; bool filledPolyWithOutline = not m_board->GetDesignSettings().m_ZoneUseNoOutlineInFill;
if( ADVANCED_CFG::GetCfg().m_forceThickOutlinesInZones ) if( ADVANCED_CFG::GetCfg().m_forceThickOutlinesInZones )
{
filledPolyWithOutline = true; filledPolyWithOutline = true;
}
std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock ); 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 ); const VECTOR2I& testPt = spoke.CPoint( 3 );
// Hit-test against zone body // 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 ); aRawPolys.AddOutline( spoke );
continue; 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 * 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) * ( 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; 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 * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
* this zone * this zone
*/ */