Performance enhancements.
1) cache pad polygon outlines huge improvement in connectivity performance and a decent improvement in DRC performance 2) don't pre-allocate CONTEXT stack significant improvement in DRC rule performance 2) don't keep re-encoding strings decent improvement in DRC rule performance
This commit is contained in:
parent
d1d7f5e7fa
commit
bf445c1a95
|
@ -817,10 +817,8 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsSegments( const D_PAD* aPad,
|
|||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
SHAPE_POLY_SET corners;
|
||||
aPad->TransformShapeWithClearanceToPolygon( corners, 0 );
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int j = 0; j < path.PointCount(); j++ )
|
||||
{
|
||||
|
|
|
@ -46,10 +46,8 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
|||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
SHAPE_POLY_SET corners;
|
||||
aPad->TransformShapeWithClearanceToPolygon( corners, 0 );
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
{
|
||||
|
|
|
@ -108,7 +108,7 @@ std::string UOP::Format() const
|
|||
else if( val->GetType() == VT_NUMERIC )
|
||||
snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH NUM [%.10f]", val->AsDouble() );
|
||||
else
|
||||
snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH STR [%s]", val->AsString().c_str() );
|
||||
snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH STR [%s]", val->AsChars() );
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
#include <base_units.h>
|
||||
|
||||
|
@ -175,10 +175,10 @@ public:
|
|||
m_valueDbl( 0 )
|
||||
{};
|
||||
|
||||
VALUE( std::string aStr ) :
|
||||
VALUE( const wxString& aStr ) :
|
||||
m_type( VT_STRING ),
|
||||
m_valueDbl( 0 ),
|
||||
m_valueStr( std::move( aStr ) )
|
||||
m_valueStr( aStr )
|
||||
{};
|
||||
|
||||
VALUE( const double aVal ) :
|
||||
|
@ -191,11 +191,16 @@ public:
|
|||
return m_valueDbl;
|
||||
}
|
||||
|
||||
const std::string& AsString() const
|
||||
const wxString& AsString() const
|
||||
{
|
||||
return m_valueStr;
|
||||
}
|
||||
|
||||
const char* AsChars() const
|
||||
{
|
||||
return m_valueStr.ToStdString().c_str();
|
||||
}
|
||||
|
||||
bool operator==( const VALUE& b ) const
|
||||
{
|
||||
if( m_type == VT_NUMERIC && b.m_type == VT_NUMERIC )
|
||||
|
@ -214,7 +219,7 @@ public:
|
|||
m_valueDbl = aValue;
|
||||
}
|
||||
|
||||
void Set( const std::string& aValue )
|
||||
void Set( const wxString& aValue )
|
||||
{
|
||||
m_type = VT_STRING;
|
||||
m_valueStr = aValue;
|
||||
|
@ -237,7 +242,7 @@ public:
|
|||
private:
|
||||
VAR_TYPE_T m_type;
|
||||
double m_valueDbl;
|
||||
std::string m_valueStr;
|
||||
wxString m_valueStr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -256,47 +261,42 @@ public:
|
|||
class CONTEXT
|
||||
{
|
||||
public:
|
||||
const int c_memSize = 128;
|
||||
|
||||
CONTEXT()
|
||||
~CONTEXT()
|
||||
{
|
||||
m_sp = 0;
|
||||
|
||||
for( int i = 0; i < c_memSize; i++ )
|
||||
m_heap.emplace_back( VALUE() );
|
||||
for( VALUE* value : m_ownedValues )
|
||||
delete value;
|
||||
}
|
||||
|
||||
VALUE* AllocValue()
|
||||
{
|
||||
assert( m_memPos < c_memSize );
|
||||
auto rv = &m_heap[ m_memPos++ ];
|
||||
return rv;
|
||||
VALUE* value = new VALUE();
|
||||
m_ownedValues.push_back( value );
|
||||
return value;
|
||||
}
|
||||
|
||||
void Push( VALUE* v )
|
||||
{
|
||||
m_stack[m_sp++] = v;
|
||||
m_stack.push( v );
|
||||
}
|
||||
|
||||
VALUE* Pop()
|
||||
{
|
||||
m_sp--;
|
||||
return m_stack[m_sp];
|
||||
VALUE* value = m_stack.top();
|
||||
m_stack.pop();
|
||||
return value;
|
||||
}
|
||||
|
||||
int SP() const
|
||||
{
|
||||
return m_sp;
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
ERROR_STATUS GetErrorStatus() const { return m_errorStatus; }
|
||||
void ReportError( const wxString& aErrorMsg );
|
||||
|
||||
private:
|
||||
std::vector<VALUE> m_heap;
|
||||
VALUE* m_stack[128];
|
||||
int m_sp = 0;
|
||||
int m_memPos = 0;
|
||||
std::vector<VALUE*> m_ownedValues;
|
||||
std::stack<VALUE*> m_stack;
|
||||
ERROR_STATUS m_errorStatus;
|
||||
};
|
||||
|
||||
|
@ -467,9 +467,9 @@ protected:
|
|||
return uop;
|
||||
}
|
||||
|
||||
UOP* makeUop( int op, std::string value )
|
||||
UOP* makeUop( int op, const wxString& value )
|
||||
{
|
||||
UOP* uop = new UOP( op, new VALUE( std::move( value ) ) );
|
||||
UOP* uop = new UOP( op, new VALUE( value ) );
|
||||
return uop;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,27 +168,6 @@ bool D_PAD::IsFlipped() const
|
|||
}
|
||||
|
||||
|
||||
int D_PAD::calcBoundingRadius() const
|
||||
{
|
||||
int radius = 0;
|
||||
SHAPE_POLY_SET polygons;
|
||||
TransformShapeWithClearanceToPolygon( polygons, 0 );
|
||||
|
||||
for( int cnt = 0; cnt < polygons.OutlineCount(); ++cnt )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& poly = polygons.COutline( cnt );
|
||||
|
||||
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
||||
{
|
||||
int dist = KiROUND( ( poly.CPoint( ii ) - m_Pos ).EuclideanNorm() );
|
||||
radius = std::max( radius, dist );
|
||||
}
|
||||
}
|
||||
|
||||
return radius + 1;
|
||||
}
|
||||
|
||||
|
||||
int D_PAD::GetRoundRectCornerRadius() const
|
||||
{
|
||||
return KiROUND( std::min( m_Size.x, m_Size.y ) * m_roundedCornerScale );
|
||||
|
@ -229,6 +208,15 @@ const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
|
|||
}
|
||||
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& D_PAD::GetEffectivePolygon() const
|
||||
{
|
||||
if( m_shapesDirty )
|
||||
BuildEffectiveShapes();
|
||||
|
||||
return m_effectivePolygon;
|
||||
}
|
||||
|
||||
|
||||
const SHAPE_SEGMENT* D_PAD::GetEffectiveHoleShape() const
|
||||
{
|
||||
if( m_shapesDirty )
|
||||
|
@ -367,9 +355,27 @@ void D_PAD::BuildEffectiveShapes() const
|
|||
}
|
||||
}
|
||||
|
||||
// Polygon
|
||||
//
|
||||
m_effectivePolygon = std::make_shared<SHAPE_POLY_SET>();
|
||||
TransformShapeWithClearanceToPolygon( *m_effectivePolygon, 0 );
|
||||
|
||||
// Bounding box and radius
|
||||
//
|
||||
m_effectiveBoundingRadius = calcBoundingRadius();
|
||||
m_effectiveBoundingRadius = 0;
|
||||
|
||||
for( int cnt = 0; cnt < m_effectivePolygon->OutlineCount(); ++cnt )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& poly = m_effectivePolygon->COutline( cnt );
|
||||
|
||||
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
||||
{
|
||||
int dist = KiROUND( ( poly.CPoint( ii ) - m_Pos ).EuclideanNorm() );
|
||||
m_effectiveBoundingRadius = std::max( m_effectiveBoundingRadius, dist );
|
||||
}
|
||||
}
|
||||
|
||||
m_effectiveBoundingRadius += 1;
|
||||
|
||||
// reset the bbox to uninitialized state to prepare for merging
|
||||
m_effectiveBoundingBox = EDA_RECT();
|
||||
|
@ -798,10 +804,7 @@ bool D_PAD::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
|||
if( delta.SquaredEuclideanNorm() > SEG::Square( boundingRadius ) )
|
||||
return false;
|
||||
|
||||
SHAPE_POLY_SET polySet;
|
||||
TransformShapeWithClearanceToPolygon( polySet, aAccuracy );
|
||||
|
||||
return polySet.Contains( aPosition );
|
||||
return GetEffectivePolygon()->Contains( aPosition, -1, aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
|
@ -827,12 +830,9 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
|
|||
selRect.Append( VECTOR2I( arect.GetRight(), arect.GetBottom() ) );
|
||||
selRect.Append( VECTOR2I( arect.GetLeft(), arect.GetBottom() ) );
|
||||
|
||||
SHAPE_POLY_SET padPoly;
|
||||
TransformShapeWithClearanceToPolygon( padPoly, aAccuracy );
|
||||
selRect.BooleanIntersection( *GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
selRect.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
double padArea = padPoly.Outline( 0 ).Area();
|
||||
double padArea = GetEffectivePolygon()->Outline( 0 ).Area();
|
||||
double intersection = selRect.Outline( 0 ).Area();
|
||||
|
||||
if( intersection > ( padArea * 0.99 ) )
|
||||
|
|
|
@ -397,6 +397,8 @@ public:
|
|||
*/
|
||||
const std::vector<std::shared_ptr<SHAPE>>& GetEffectiveShapes() const;
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon() const;
|
||||
|
||||
/**
|
||||
* Function GetEffectiveHoleShape
|
||||
* Returns a list of SHAPE objects representing the pad's hole.
|
||||
|
@ -611,12 +613,6 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function calcBoundingRadius
|
||||
* returns a calculated radius of a bounding circle for this pad.
|
||||
*/
|
||||
int calcBoundingRadius() const;
|
||||
|
||||
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
|
||||
|
||||
private:
|
||||
|
@ -639,6 +635,7 @@ private:
|
|||
mutable EDA_RECT m_effectiveBoundingBox;
|
||||
mutable std::vector<std::shared_ptr<SHAPE>> m_effectiveShapes;
|
||||
mutable std::shared_ptr<SHAPE_SEGMENT> m_effectiveHoleShape;
|
||||
mutable std::shared_ptr<SHAPE_POLY_SET> m_effectivePolygon;
|
||||
|
||||
/*
|
||||
* How to build the custom shape in zone, to create the clearance area:
|
||||
|
|
|
@ -684,8 +684,8 @@ void CN_VISITOR::checkZoneZoneConnection( CN_ZONE* aZoneA, CN_ZONE* aZoneB )
|
|||
|
||||
bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
|
||||
{
|
||||
const auto parentA = aCandidate->Parent();
|
||||
const auto parentB = m_item->Parent();
|
||||
const BOARD_CONNECTED_ITEM* parentA = aCandidate->Parent();
|
||||
const BOARD_CONNECTED_ITEM* parentB = m_item->Parent();
|
||||
|
||||
if( !aCandidate->Valid() || !m_item->Valid() )
|
||||
return true;
|
||||
|
|
|
@ -66,6 +66,12 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
|||
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
// Because the trap delta is applied as +1/2 at one end and -1/2 at the other,
|
||||
// the midpoint is actually unchanged. Therefore all the cardinal points are
|
||||
// the same as for a rectangle.
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case PAD_SHAPE_RECT:
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
|
@ -89,7 +95,6 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
|||
|
||||
return pt1;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
switch( n )
|
||||
|
@ -104,9 +109,8 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
|||
if( pad->GetOrientation() )
|
||||
RotatePoint( pt1, pad->ShapePos(), pad->GetOrientation() );
|
||||
|
||||
SHAPE_POLY_SET padPolySet;
|
||||
pad->TransformShapeWithClearanceToPolygon( padPolySet, 0, ARC_LOW_DEF );
|
||||
const SHAPE_LINE_CHAIN& padOutline = padPolySet.COutline( 0 );
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& padPolySet = pad->GetEffectivePolygon();
|
||||
const SHAPE_LINE_CHAIN& padOutline = padPolySet->COutline( 0 );
|
||||
SHAPE_LINE_CHAIN::INTERSECTIONS intersections;
|
||||
|
||||
padOutline.Intersect( SEG( pt0, pt1 ), intersections );
|
||||
|
|
|
@ -227,8 +227,7 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule )
|
|||
|
||||
if( ( m_keepoutFlags & DISALLOW_PADS ) > 0 )
|
||||
{
|
||||
SHAPE_POLY_SET outline;
|
||||
pad->TransformShapeWithClearanceToPolygon( outline, 0 );
|
||||
SHAPE_POLY_SET outline = *pad->GetEffectivePolygon();
|
||||
|
||||
// Build the common area between pad and the keepout area:
|
||||
outline.BooleanIntersection( *m_zone->Outline(), SHAPE_POLY_SET::PM_FAST );
|
||||
|
|
|
@ -132,7 +132,7 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
|||
//printf("item %p get enum: '%s'\n", item , (const char*) str.c_str() );
|
||||
}
|
||||
|
||||
return LIBEVAL::VALUE( (const char*) str.c_str() );
|
||||
return LIBEVAL::VALUE( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,15 +239,14 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPl
|
|||
case PAD_SHAPE_CHAMFERED_RECT:
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polygons;
|
||||
aPad->TransformShapeWithClearanceToPolygon( polygons, 0 );
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon();
|
||||
|
||||
if( polygons.OutlineCount() == 0 )
|
||||
break;
|
||||
|
||||
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(), &polygons, aPlotMode,
|
||||
if( polygons->OutlineCount() )
|
||||
{
|
||||
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(), polygons.get(), aPlotMode,
|
||||
&gbr_metadata );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -634,12 +634,10 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad )
|
|||
// JEY TODO:
|
||||
// TOM TODO: move to SHAPE_COMPOUND...
|
||||
|
||||
SHAPE_POLY_SET outline;
|
||||
aPad->TransformShapeWithClearanceToPolygon( outline, 0 );
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& outline = aPad->GetEffectivePolygon();
|
||||
SHAPE_SIMPLE* shape = new SHAPE_SIMPLE();
|
||||
|
||||
for( auto iter = outline.CIterate( 0 ); iter; iter++ )
|
||||
for( auto iter = outline->CIterate( 0 ); iter; iter++ )
|
||||
shape->Append( *iter );
|
||||
|
||||
solid->SetShape( shape );
|
||||
|
|
|
@ -296,9 +296,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a
|
|||
if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
|
||||
continue;
|
||||
|
||||
SHAPE_POLY_SET padOutline;
|
||||
pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& padOutline = pad->GetEffectivePolygon();
|
||||
OPT<SEG> minSeg;
|
||||
SEG::ecoord center2center_squared = 0;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ bool testEvalExpr( const std::string expr, LIBEVAL::VALUE expectedResult, bool e
|
|||
if( expectedResult.GetType() == LIBEVAL::VT_NUMERIC )
|
||||
printf("result: %s (got %.10f expected: %.10f)\n", ok ? "OK" : "FAIL", result.AsDouble(), expectedResult.AsDouble() );
|
||||
else
|
||||
printf("result: %s (got '%s' expected: '%s')\n", ok ? "OK" : "FAIL", result.AsString().c_str(), expectedResult.AsString().c_str() );
|
||||
printf("result: %s (got '%s' expected: '%s')\n", ok ? "OK" : "FAIL", result.AsChars(), expectedResult.AsChars() );
|
||||
|
||||
if (!ok )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue