Performance improvement for zone filling.
This commit is contained in:
parent
50f6844e71
commit
7ee6afeace
|
@ -349,12 +349,14 @@ int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
|
|||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy ) const
|
||||
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUseBBoxCache ) const
|
||||
{
|
||||
/*
|
||||
* Don't check the bounding box. Building it is about the same speed as the rigorous
|
||||
* test below and so just slows things down by doing potentially two tests.
|
||||
* Don't check the bounding box unless it's cached. Building it is about the same speed as
|
||||
* the rigorous test below and so just slows things down by doing potentially two tests.
|
||||
*/
|
||||
if( aUseBBoxCache && !m_bbox.Contains( aPt ) )
|
||||
return false;
|
||||
|
||||
if( !m_closed || PointCount() < 3 )
|
||||
return false;
|
||||
|
|
|
@ -1391,20 +1391,32 @@ bool SHAPE_POLY_SET::CollideEdge( const VECTOR2I& aPoint,
|
|||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::BuildBBoxCaches()
|
||||
{
|
||||
for( int polygonIdx = 0; polygonIdx < OutlineCount(); polygonIdx++ )
|
||||
{
|
||||
Outline( polygonIdx ).GenerateBBoxCache();
|
||||
|
||||
for( int holeIdx = 0; holeIdx < HoleCount( polygonIdx ); holeIdx++ )
|
||||
Hole( polygonIdx, holeIdx ).GenerateBBoxCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
|
||||
bool aIgnoreEdges ) const
|
||||
bool aIgnoreEdges, bool aUseBBoxCaches ) const
|
||||
{
|
||||
if( m_polys.size() == 0 ) // empty set?
|
||||
return false;
|
||||
|
||||
// If there is a polygon specified, check the condition against that polygon
|
||||
if( aSubpolyIndex >= 0 )
|
||||
return containsSingle( aP, aSubpolyIndex, aIgnoreHoles, aIgnoreEdges );
|
||||
return containsSingle( aP, aSubpolyIndex, aIgnoreHoles, aIgnoreEdges, 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 ) )
|
||||
if( containsSingle( aP, polygonIdx, aIgnoreHoles, aIgnoreEdges, aUseBBoxCaches ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1431,7 +1443,7 @@ void SHAPE_POLY_SET::RemoveVertex( VERTEX_INDEX aIndex )
|
|||
|
||||
|
||||
bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
|
||||
bool aIgnoreEdges ) const
|
||||
bool aIgnoreEdges, bool aUseBBoxCaches ) const
|
||||
{
|
||||
// Check that the point is inside the outline
|
||||
if( pointInPolygon( aP, m_polys[aSubpolyIndex][0], aIgnoreEdges ) )
|
||||
|
@ -1445,7 +1457,7 @@ bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool
|
|||
|
||||
// If the point is inside a hole (and not on its edge),
|
||||
// it is outside of the polygon
|
||||
if( pointInPolygon( aP, hole, aIgnoreEdges ) )
|
||||
if( pointInPolygon( aP, hole, aIgnoreEdges, aUseBBoxCaches ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1458,9 +1470,9 @@ 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 ) const
|
||||
bool aIgnoreEdges, bool aUseBBoxCaches ) const
|
||||
{
|
||||
return aPath.PointInside( aP, aIgnoreEdges ? 1 : 0 );
|
||||
return aPath.PointInside( aP, aIgnoreEdges ? 1 : 0, aUseBBoxCaches );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* Copyright (C) 2013-2017
|
||||
* Copyright (C) 2013-2019
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -305,6 +305,11 @@ public:
|
|||
return bbox;
|
||||
}
|
||||
|
||||
void GenerateBBoxCache()
|
||||
{
|
||||
m_bbox.Compute( m_points );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
|
@ -552,9 +557,11 @@ public:
|
|||
* Checks if point aP lies inside a polygon (any type) defined by the line chain.
|
||||
* For closed shapes only.
|
||||
* @param aPt point to check
|
||||
* @param aUseBBoxCache gives better peformance if the bounding boxe caches have been
|
||||
* generated.
|
||||
* @return true if the point is inside the shape (edge is not treated as being inside).
|
||||
*/
|
||||
bool PointInside( const VECTOR2I& aPt, int aAccuracy = 0 ) const;
|
||||
bool PointInside( const VECTOR2I& aPt, int aAccuracy = 0, bool aUseBBoxCache = false ) const;
|
||||
|
||||
/**
|
||||
* Function PointOnEdge()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 CERN
|
||||
* Copyright (C) 2015-2019 CERN
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
*
|
||||
|
@ -971,6 +971,12 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
|
||||
int aClearance = 0 );
|
||||
|
||||
/**
|
||||
* Constructs BBoxCaches for Contains(), below. These caches MUST be built before a
|
||||
* group of calls to Contains(). They are NOT kept up-to-date by editing actions.
|
||||
*/
|
||||
void BuildBBoxCaches();
|
||||
|
||||
/**
|
||||
* Returns true if a given subpolygon contains the point aP
|
||||
*
|
||||
|
@ -979,10 +985,13 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* @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 ) const;
|
||||
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const;
|
||||
|
||||
///> Returns true if the set is empty (no polygons at all)
|
||||
bool IsEmpty() const
|
||||
|
@ -1118,12 +1127,6 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
bool IsVertexInHole( int aGlobalIdx );
|
||||
|
||||
private:
|
||||
|
||||
SHAPE_LINE_CHAIN& getContourForCorner( int aCornerId, int& aIndexWithinContour );
|
||||
VECTOR2I& vertex( int aCornerId );
|
||||
const VECTOR2I& cvertex( int aCornerId ) const;
|
||||
|
||||
|
||||
void fractureSingle( POLYGON& paths );
|
||||
void unfractureSingle ( POLYGON& path );
|
||||
void importTree( ClipperLib::PolyTree* tree );
|
||||
|
@ -1146,7 +1149,7 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
|
||||
|
||||
bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
|
||||
bool aIgnoreEdges ) const;
|
||||
bool aIgnoreEdges, bool aUseBBoxCaches = false ) const;
|
||||
|
||||
/**
|
||||
* containsSingle function
|
||||
|
@ -1159,11 +1162,14 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* @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 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 ) const;
|
||||
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const;
|
||||
|
||||
/**
|
||||
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
|
||||
|
@ -1176,8 +1182,6 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
FILLETED
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function chamferFilletPolygon
|
||||
* Returns the camfered or filleted version of the aIndex-th polygon in the set, depending
|
||||
|
|
|
@ -701,12 +701,16 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
|||
// Remove areas that don't meet minimum-width criteria
|
||||
testAreas.Inflate( -outline_half_thickness, numSegs, true );
|
||||
testAreas.Inflate( outline_half_thickness, numSegs, true );
|
||||
testAreas.BuildBBoxCaches();
|
||||
|
||||
static const bool USE_BBOX_CACHES = true;
|
||||
buildThermalSpokes( aZone, thermalSpokes );
|
||||
|
||||
for( const SHAPE_LINE_CHAIN& spoke : thermalSpokes )
|
||||
{
|
||||
if( testAreas.Contains( spoke.CPoint( 3 ), -1, false, true ) )
|
||||
const VECTOR2I& testPt = spoke.CPoint( 3 );
|
||||
|
||||
if( testAreas.Contains( testPt, -1, false, true, USE_BBOX_CACHES ) )
|
||||
{
|
||||
solidAreas.AddOutline( spoke );
|
||||
continue;
|
||||
|
@ -714,7 +718,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
|||
|
||||
for( const SHAPE_LINE_CHAIN& other : thermalSpokes )
|
||||
{
|
||||
if( &other != &spoke && other.PointInside( spoke.CPoint( 3 ), 1 ) )
|
||||
if( &other != &spoke && other.PointInside( testPt, 1, USE_BBOX_CACHES ) )
|
||||
{
|
||||
solidAreas.AddOutline( spoke );
|
||||
break;
|
||||
|
@ -914,6 +918,7 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
|||
}
|
||||
|
||||
spoke.SetClosed( true );
|
||||
spoke.GenerateBBoxCache();
|
||||
aSpokesList.push_back( std::move( spoke ) );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue