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
|
* Don't check the bounding box unless it's cached. Building it is about the same speed as
|
||||||
* test below and so just slows things down by doing potentially two tests.
|
* 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 )
|
if( !m_closed || PointCount() < 3 )
|
||||||
return false;
|
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 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?
|
if( m_polys.size() == 0 ) // empty set?
|
||||||
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 );
|
return containsSingle( aP, aSubpolyIndex, aIgnoreHoles, aIgnoreEdges, 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 ) )
|
if( containsSingle( aP, polygonIdx, aIgnoreHoles, aIgnoreEdges, aUseBBoxCaches ) )
|
||||||
return true;
|
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 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
|
// Check that the point is inside the outline
|
||||||
if( pointInPolygon( aP, m_polys[aSubpolyIndex][0], aIgnoreEdges ) )
|
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),
|
// If the point is inside a hole (and not on its edge),
|
||||||
// it is outside of the polygon
|
// it is outside of the polygon
|
||||||
if( pointInPolygon( aP, hole, aIgnoreEdges ) )
|
if( pointInPolygon( aP, hole, aIgnoreEdges, aUseBBoxCaches ) )
|
||||||
return false;
|
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 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
|
* Copyright (C) 2013 CERN
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
* @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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -305,6 +305,11 @@ public:
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenerateBBoxCache()
|
||||||
|
{
|
||||||
|
m_bbox.Compute( m_points );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Collide()
|
* Function Collide()
|
||||||
*
|
*
|
||||||
|
@ -552,9 +557,11 @@ public:
|
||||||
* Checks if point aP lies inside a polygon (any type) defined by the line chain.
|
* Checks if point aP lies inside a polygon (any type) defined by the line chain.
|
||||||
* For closed shapes only.
|
* For closed shapes only.
|
||||||
* @param aPt point to check
|
* @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).
|
* @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()
|
* Function PointOnEdge()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* 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 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
* @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,
|
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
|
||||||
|
* 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
|
* 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 aIgnoreHoles controls whether or not internal holes are considered
|
||||||
* @param aIgnoreEdges controls whether or not a check for the point lying exactly on
|
* @param aIgnoreEdges controls whether or not a check for the point lying exactly on
|
||||||
* the polygon edge is made
|
* 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
|
* @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, 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)
|
///> Returns true if the set is empty (no polygons at all)
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const
|
||||||
|
@ -1118,12 +1127,6 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
bool IsVertexInHole( int aGlobalIdx );
|
bool IsVertexInHole( int aGlobalIdx );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN& getContourForCorner( int aCornerId, int& aIndexWithinContour );
|
|
||||||
VECTOR2I& vertex( int aCornerId );
|
|
||||||
const VECTOR2I& cvertex( int aCornerId ) const;
|
|
||||||
|
|
||||||
|
|
||||||
void fractureSingle( POLYGON& paths );
|
void fractureSingle( POLYGON& paths );
|
||||||
void unfractureSingle ( POLYGON& path );
|
void unfractureSingle ( POLYGON& path );
|
||||||
void importTree( ClipperLib::PolyTree* tree );
|
void importTree( ClipperLib::PolyTree* tree );
|
||||||
|
@ -1146,7 +1149,7 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
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 pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
|
||||||
bool aIgnoreEdges ) const;
|
bool aIgnoreEdges, bool aUseBBoxCaches = false ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* containsSingle function
|
* 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 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
|
* @param aIgnoreEdges can be set to true to skip checking whether or not the point
|
||||||
* lies directly on the edge
|
* 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
|
* @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, bool aIgnoreHoles = false,
|
||||||
bool aIgnoreEdges = false ) const;
|
bool aIgnoreEdges = false, bool aUseBBoxCaches = false ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
|
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
|
||||||
|
@ -1176,8 +1182,6 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
FILLETED
|
FILLETED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function chamferFilletPolygon
|
* Function chamferFilletPolygon
|
||||||
* Returns the camfered or filleted version of the aIndex-th polygon in the set, depending
|
* 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
|
// Remove areas that don't meet minimum-width criteria
|
||||||
testAreas.Inflate( -outline_half_thickness, numSegs, true );
|
testAreas.Inflate( -outline_half_thickness, numSegs, true );
|
||||||
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 );
|
buildThermalSpokes( aZone, thermalSpokes );
|
||||||
|
|
||||||
for( const SHAPE_LINE_CHAIN& spoke : 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 );
|
solidAreas.AddOutline( spoke );
|
||||||
continue;
|
continue;
|
||||||
|
@ -714,7 +718,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
||||||
|
|
||||||
for( const SHAPE_LINE_CHAIN& other : thermalSpokes )
|
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 );
|
solidAreas.AddOutline( spoke );
|
||||||
break;
|
break;
|
||||||
|
@ -914,6 +918,7 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
}
|
}
|
||||||
|
|
||||||
spoke.SetClosed( true );
|
spoke.SetClosed( true );
|
||||||
|
spoke.GenerateBBoxCache();
|
||||||
aSpokesList.push_back( std::move( spoke ) );
|
aSpokesList.push_back( std::move( spoke ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue