Added more sophisticated checking for thermal spoke connections.
And, again, some more performance optimizations to make up for it.
This commit is contained in:
parent
49610085ea
commit
3784950603
|
@ -390,7 +390,9 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy ) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return inside && !PointOnEdge( aPt, aAccuracy );
|
// 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 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1391,19 +1391,20 @@ bool SHAPE_POLY_SET::CollideEdge( const VECTOR2I& aPoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles ) const
|
bool SHAPE_POLY_SET::Contains( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
|
||||||
|
bool aIgnoreEdges ) 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 );
|
return containsSingle( aP, aSubpolyIndex, aIgnoreHoles, aIgnoreEdges );
|
||||||
|
|
||||||
// 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 ) )
|
if( containsSingle( aP, polygonIdx, aIgnoreHoles, aIgnoreEdges ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,10 +1430,11 @@ void SHAPE_POLY_SET::RemoveVertex( VERTEX_INDEX aIndex )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles ) const
|
bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles,
|
||||||
|
bool aIgnoreEdges ) const
|
||||||
{
|
{
|
||||||
// Check that the point is inside the outline
|
// Check that the point is inside the outline
|
||||||
if( pointInPolygon( aP, m_polys[aSubpolyIndex][0] ) )
|
if( pointInPolygon( aP, m_polys[aSubpolyIndex][0], aIgnoreEdges ) )
|
||||||
{
|
{
|
||||||
if( !aIgnoreHoles )
|
if( !aIgnoreHoles )
|
||||||
{
|
{
|
||||||
|
@ -1443,7 +1445,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 ) )
|
if( pointInPolygon( aP, hole, aIgnoreEdges ) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1455,9 +1457,10 @@ bool SHAPE_POLY_SET::containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHAPE_POLY_SET::pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath ) const
|
bool SHAPE_POLY_SET::pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
|
||||||
|
bool aIgnoreEdges ) const
|
||||||
{
|
{
|
||||||
return aPath.PointInside( aP );
|
return aPath.PointInside( aP, aIgnoreEdges ? 1 : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1466,10 +1469,8 @@ void SHAPE_POLY_SET::Move( const VECTOR2I& aVector )
|
||||||
for( POLYGON& poly : m_polys )
|
for( POLYGON& poly : m_polys )
|
||||||
{
|
{
|
||||||
for( SHAPE_LINE_CHAIN& path : poly )
|
for( SHAPE_LINE_CHAIN& path : poly )
|
||||||
{
|
|
||||||
path.Move( aVector );
|
path.Move( aVector );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1478,10 +1479,8 @@ void SHAPE_POLY_SET::Rotate( double aAngle, const VECTOR2I& aCenter )
|
||||||
for( POLYGON& poly : m_polys )
|
for( POLYGON& poly : m_polys )
|
||||||
{
|
{
|
||||||
for( SHAPE_LINE_CHAIN& path : poly )
|
for( SHAPE_LINE_CHAIN& path : poly )
|
||||||
{
|
|
||||||
path.Rotate( aAngle, aCenter );
|
path.Rotate( aAngle, aCenter );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1492,10 +1491,8 @@ int SHAPE_POLY_SET::TotalVertices() const
|
||||||
for( const POLYGON& poly : m_polys )
|
for( const POLYGON& poly : m_polys )
|
||||||
{
|
{
|
||||||
for( const SHAPE_LINE_CHAIN& path : poly )
|
for( const SHAPE_LINE_CHAIN& path : poly )
|
||||||
{
|
|
||||||
c += path.PointCount();
|
c += path.PointCount();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -977,9 +977,12 @@ 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 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
|
||||||
* @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 ) const;
|
bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, bool aIgnoreHoles = false,
|
||||||
|
bool aIgnoreEdges = 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
|
||||||
|
@ -1136,14 +1139,14 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
* if aFastMode is PM_STRICTLY_SIMPLE (default) the result is (theorically) a strictly
|
* if aFastMode is PM_STRICTLY_SIMPLE (default) the result is (theorically) a strictly
|
||||||
* simple polygon, but calculations can be really significantly time consuming
|
* simple polygon, but calculations can be really significantly time consuming
|
||||||
*/
|
*/
|
||||||
void booleanOp( ClipperLib::ClipType aType,
|
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
||||||
|
POLYGON_MODE aFastMode );
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
void booleanOp( ClipperLib::ClipType aType,
|
bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath,
|
||||||
const SHAPE_POLY_SET& aShape,
|
bool aIgnoreEdges ) const;
|
||||||
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath ) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* containsSingle function
|
* containsSingle function
|
||||||
|
@ -1154,10 +1157,13 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
* @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 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
|
||||||
* @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 ) const;
|
bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles = false,
|
||||||
|
bool aIgnoreEdges = false ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
|
* Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
|
||||||
|
|
|
@ -492,8 +492,7 @@ void ZONE_FILLER::knockoutThermals( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET&
|
||||||
* Removes clearance from the shape for copper items which share the zone's layer but are
|
* Removes clearance from the shape for copper items which share the zone's layer but are
|
||||||
* not connected to it.
|
* not connected to it.
|
||||||
*/
|
*/
|
||||||
void ZONE_FILLER::knockoutCopperItems( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill,
|
void ZONE_FILLER::knockoutCopperItems( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill )
|
||||||
std::deque<SHAPE_LINE_CHAIN>& aSpokes)
|
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET holes;
|
SHAPE_POLY_SET holes;
|
||||||
|
|
||||||
|
@ -705,7 +704,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
||||||
dumper->BeginGroup( "clipper-zone" );
|
dumper->BeginGroup( "clipper-zone" );
|
||||||
|
|
||||||
SHAPE_POLY_SET solidAreas = aSmoothedOutline;
|
SHAPE_POLY_SET solidAreas = aSmoothedOutline;
|
||||||
std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
|
std::deque<THERMAL_SPOKE> thermalSpokes;
|
||||||
|
|
||||||
int numSegs = std::max( GetArcToSegmentCount( outline_half_thickness, m_high_def, 360.0 ), 6 );
|
int numSegs = std::max( GetArcToSegmentCount( outline_half_thickness, m_high_def, 360.0 ), 6 );
|
||||||
|
|
||||||
|
@ -719,7 +718,7 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
||||||
|
|
||||||
buildThermalSpokes( aZone, thermalSpokes );
|
buildThermalSpokes( aZone, thermalSpokes );
|
||||||
|
|
||||||
knockoutCopperItems( aZone, solidAreas, thermalSpokes );
|
knockoutCopperItems( aZone, solidAreas );
|
||||||
|
|
||||||
if( s_DumpZonesWhenFilling )
|
if( s_DumpZonesWhenFilling )
|
||||||
dumper->Write( &solidAreas, "solid-areas-minus-clearances" );
|
dumper->Write( &solidAreas, "solid-areas-minus-clearances" );
|
||||||
|
@ -728,11 +727,14 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone,
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET amalgamatedSpokes;
|
SHAPE_POLY_SET amalgamatedSpokes;
|
||||||
|
|
||||||
for( SHAPE_LINE_CHAIN& spoke : thermalSpokes )
|
for( THERMAL_SPOKE& spoke : thermalSpokes )
|
||||||
{
|
{
|
||||||
// Add together all spokes whose endpoints lie within the zone's filled area
|
// Add together all spokes whose endpoints lie within the zone's filled area
|
||||||
if( solidAreas.Contains( spoke.Point(2) ) && solidAreas.Contains( spoke.Point(3) ) )
|
if( solidAreas.Contains( spoke.m_TestPtA, -1, false, true )
|
||||||
amalgamatedSpokes.AddOutline( spoke );
|
&& solidAreas.Contains( spoke.m_TestPtB, -1, false, true ) )
|
||||||
|
{
|
||||||
|
amalgamatedSpokes.AddOutline( spoke.m_Outline );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
amalgamatedSpokes.Simplify( SHAPE_POLY_SET::PM_FAST );
|
amalgamatedSpokes.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||||
|
@ -851,7 +853,7 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPol
|
||||||
* Function buildThermalSpokes
|
* Function buildThermalSpokes
|
||||||
*/
|
*/
|
||||||
void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
std::deque<SHAPE_LINE_CHAIN>& aSpokesList )
|
std::deque<THERMAL_SPOKE>& aSpokesList )
|
||||||
{
|
{
|
||||||
auto zoneBB = aZone->GetBoundingBox();
|
auto zoneBB = aZone->GetBoundingBox();
|
||||||
int zone_clearance = aZone->GetZoneClearance();
|
int zone_clearance = aZone->GetZoneClearance();
|
||||||
|
@ -860,17 +862,17 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
zoneBB.Inflate( biggest_clearance );
|
zoneBB.Inflate( biggest_clearance );
|
||||||
|
|
||||||
// half size of the pen used to draw/plot zones outlines
|
// half size of the pen used to draw/plot zones outlines
|
||||||
int pen_radius = aZone->GetMinThickness() / 2;
|
int pen_w = aZone->GetMinThickness() / 2;
|
||||||
|
|
||||||
// Is a point on the boundary of the polygon inside or outside? This small correction
|
// Is a point on the boundary of the polygon inside or outside? This small epsilon lets
|
||||||
// lets us avoid the question.
|
// us avoid the question.
|
||||||
int boundaryCorrection = KiROUND( IU_PER_MM * 0.04 );
|
int epsilon = KiROUND( IU_PER_MM * 0.04 );
|
||||||
|
|
||||||
// We'd normally add in an arcCorrection for circles (since a finite number of segments
|
// We'd normally add in an arcCorrection for circles (since a finite number of segments
|
||||||
// is only an approximation of the circle radius). However, boundaryCorrection is already
|
// is only an approximation of the circle radius). However, epsilon is already twice even
|
||||||
// twice even our ARC_LOW_DEF error tolerance, so there's little benefit to it (and a small
|
// our LOW resolution error tolerance, so there's little benefit to it (and a small but
|
||||||
// but existant performance penalty).
|
// existant performance penalty).
|
||||||
//int numSegs = std::max( GetArcToSegmentCount( pen_raidus, m_high_def, 360.0 ), 6 );
|
//int numSegs = std::max( GetArcToSegmentCount( pen_w, m_high_def, 360.0 ), 6 );
|
||||||
//double arcCorrection = GetCircletoPolyCorrectionFactor( numSegs );
|
//double arcCorrection = GetCircletoPolyCorrectionFactor( numSegs );
|
||||||
|
|
||||||
for( auto module : m_board->Modules() )
|
for( auto module : m_board->Modules() )
|
||||||
|
@ -883,17 +885,16 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
int thermalReliefGap = aZone->GetThermalReliefGap( pad );
|
int thermalReliefGap = aZone->GetThermalReliefGap( pad );
|
||||||
|
|
||||||
// Calculate thermal bridge half width
|
// Calculate thermal bridge half width
|
||||||
int spokeThickness = aZone->GetThermalReliefCopperBridge( pad )
|
int spoke_w = aZone->GetThermalReliefCopperBridge( pad ) - aZone->GetMinThickness();
|
||||||
- aZone->GetMinThickness();
|
|
||||||
|
|
||||||
if( spokeThickness <= 0 )
|
if( spoke_w <= 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
spokeThickness = spokeThickness / 2;
|
spoke_w = spoke_w / 2;
|
||||||
|
|
||||||
// Quick test here to possibly save us some work
|
// Quick test here to possibly save us some work
|
||||||
BOX2I itemBB = pad->GetBoundingBox();
|
BOX2I itemBB = pad->GetBoundingBox();
|
||||||
itemBB.Inflate( thermalReliefGap + pen_radius + boundaryCorrection );
|
itemBB.Inflate( thermalReliefGap + pen_w + epsilon );
|
||||||
|
|
||||||
if( !( itemBB.Intersects( zoneBB ) ) )
|
if( !( itemBB.Intersects( zoneBB ) ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -907,7 +908,7 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
pad->SetOrientation( 0.0 );
|
pad->SetOrientation( 0.0 );
|
||||||
pad->SetPosition( - pad->GetOffset() );
|
pad->SetPosition( - pad->GetOffset() );
|
||||||
BOX2I reliefBB = pad->GetBoundingBox();
|
BOX2I reliefBB = pad->GetBoundingBox();
|
||||||
reliefBB.Inflate( thermalReliefGap + pen_radius + boundaryCorrection );
|
reliefBB.Inflate( thermalReliefGap + pen_w + epsilon );
|
||||||
|
|
||||||
// For circle pads, the thermal stubs orientation is 45 deg
|
// For circle pads, the thermal stubs orientation is 45 deg
|
||||||
if( pad->GetShape() == PAD_SHAPE_CIRCLE )
|
if( pad->GetShape() == PAD_SHAPE_CIRCLE )
|
||||||
|
@ -915,47 +916,60 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
|
||||||
|
|
||||||
for( int i = 0; i < 4; i++ )
|
for( int i = 0; i < 4; i++ )
|
||||||
{
|
{
|
||||||
SHAPE_LINE_CHAIN spoke;
|
THERMAL_SPOKE spoke;
|
||||||
// polygons are rectangles with width of copper bridge value
|
// polygons are rectangles with width of copper bridge value
|
||||||
switch( i )
|
switch( i )
|
||||||
{
|
{
|
||||||
case 0: // lower stub
|
case 0: // lower stub
|
||||||
spoke.Append( +spokeThickness, 0 );
|
spoke.m_Outline.Append( +spoke_w, 0 );
|
||||||
spoke.Append( -spokeThickness, 0 );
|
spoke.m_Outline.Append( -spoke_w, 0 );
|
||||||
spoke.Append( -spokeThickness, reliefBB.GetBottom() );
|
spoke.m_Outline.Append( -spoke_w, reliefBB.GetBottom() );
|
||||||
spoke.Append( +spokeThickness, reliefBB.GetBottom() );
|
spoke.m_Outline.Append( +spoke_w, reliefBB.GetBottom() );
|
||||||
|
spoke.m_TestPtA = { epsilon - spoke_w, reliefBB.GetBottom() };
|
||||||
|
spoke.m_TestPtB = { spoke_w - epsilon, reliefBB.GetBottom() };
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // upper stub
|
case 1: // upper stub
|
||||||
spoke.Append( +spokeThickness, 0 );
|
spoke.m_Outline.Append( +spoke_w, 0 );
|
||||||
spoke.Append( -spokeThickness, 0 );
|
spoke.m_Outline.Append( -spoke_w, 0 );
|
||||||
spoke.Append( -spokeThickness, reliefBB.GetTop() );
|
spoke.m_Outline.Append( -spoke_w, reliefBB.GetTop() );
|
||||||
spoke.Append( +spokeThickness, reliefBB.GetTop() );
|
spoke.m_Outline.Append( +spoke_w, reliefBB.GetTop() );
|
||||||
|
spoke.m_TestPtA = { epsilon - spoke_w, reliefBB.GetTop() };
|
||||||
|
spoke.m_TestPtB = { spoke_w - epsilon, reliefBB.GetTop() };
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // right stub
|
case 2: // right stub
|
||||||
spoke.Append( 0, spokeThickness );
|
spoke.m_Outline.Append( 0, spoke_w );
|
||||||
spoke.Append( 0, -spokeThickness );
|
spoke.m_Outline.Append( 0, -spoke_w );
|
||||||
spoke.Append( reliefBB.GetRight(), -spokeThickness );
|
spoke.m_Outline.Append( reliefBB.GetRight(), -spoke_w );
|
||||||
spoke.Append( reliefBB.GetRight(), spokeThickness );
|
spoke.m_Outline.Append( reliefBB.GetRight(), spoke_w );
|
||||||
|
spoke.m_TestPtA = { reliefBB.GetRight(), epsilon - spoke_w };
|
||||||
|
spoke.m_TestPtB = { reliefBB.GetRight(), spoke_w - epsilon };
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // left stub
|
case 3: // left stub
|
||||||
spoke.Append( 0, spokeThickness );
|
spoke.m_Outline.Append( 0, spoke_w );
|
||||||
spoke.Append( 0, -spokeThickness );
|
spoke.m_Outline.Append( 0, -spoke_w );
|
||||||
spoke.Append( reliefBB.GetLeft(), -spokeThickness );
|
spoke.m_Outline.Append( reliefBB.GetLeft(), -spoke_w );
|
||||||
spoke.Append( reliefBB.GetLeft(), spokeThickness );
|
spoke.m_Outline.Append( reliefBB.GetLeft(), spoke_w );
|
||||||
|
spoke.m_TestPtA = { reliefBB.GetLeft(), epsilon - spoke_w };
|
||||||
|
spoke.m_TestPtB = { reliefBB.GetLeft(), spoke_w - epsilon };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int ic = 0; ic < spoke.PointCount(); ic++ )
|
for( int j = 0; j < spoke.m_Outline.PointCount(); j++ )
|
||||||
{
|
{
|
||||||
RotatePoint( spoke.Point( ic ), spokeAngle );
|
RotatePoint( spoke.m_Outline.Point( j ), spokeAngle );
|
||||||
spoke.Point( ic ) += padPos + pad->GetOffset();
|
spoke.m_Outline.Point( j ) += padPos + pad->GetOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
spoke.SetClosed( true );
|
RotatePoint( spoke.m_TestPtA, spokeAngle );
|
||||||
aSpokesList.push_back( spoke );
|
spoke.m_TestPtA += padPos + pad->GetOffset();
|
||||||
|
RotatePoint( spoke.m_TestPtB, spokeAngle );
|
||||||
|
spoke.m_TestPtB += padPos + pad->GetOffset();
|
||||||
|
|
||||||
|
spoke.m_Outline.SetClosed( true );
|
||||||
|
aSpokesList.push_back( std::move( spoke ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->SetPosition( padPos );
|
pad->SetPosition( padPos );
|
||||||
|
|
|
@ -35,6 +35,20 @@ class COMMIT;
|
||||||
class SHAPE_POLY_SET;
|
class SHAPE_POLY_SET;
|
||||||
class SHAPE_LINE_CHAIN;
|
class SHAPE_LINE_CHAIN;
|
||||||
|
|
||||||
|
struct THERMAL_SPOKE
|
||||||
|
{
|
||||||
|
SHAPE_LINE_CHAIN m_Outline;
|
||||||
|
VECTOR2I m_TestPtA;
|
||||||
|
VECTOR2I m_TestPtB;
|
||||||
|
|
||||||
|
THERMAL_SPOKE()
|
||||||
|
{
|
||||||
|
m_TestPtA = { 0, 0 };
|
||||||
|
m_TestPtB = { 0, 0 };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class ZONE_FILLER
|
class ZONE_FILLER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -52,8 +66,7 @@ private:
|
||||||
|
|
||||||
void knockoutThermals( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill );
|
void knockoutThermals( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill );
|
||||||
|
|
||||||
void knockoutCopperItems( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill,
|
void knockoutCopperItems( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFill );
|
||||||
std::deque<SHAPE_LINE_CHAIN>& aSpokes );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function computeRawFilledArea
|
* Function computeRawFilledArea
|
||||||
|
@ -73,7 +86,7 @@ private:
|
||||||
* Function buildThermalSpokes
|
* Function buildThermalSpokes
|
||||||
* Constructs a list of all thermal spokes for the given zone.
|
* Constructs a list of all thermal spokes for the given zone.
|
||||||
*/
|
*/
|
||||||
void buildThermalSpokes( const ZONE_CONTAINER* aZone, std::deque<SHAPE_LINE_CHAIN>& aSpokes );
|
void buildThermalSpokes( const ZONE_CONTAINER* aZone, std::deque<THERMAL_SPOKE>& aSpokes );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the filled solid areas polygons from zone outlines (stored in m_Poly)
|
* Build the filled solid areas polygons from zone outlines (stored in m_Poly)
|
||||||
|
|
Loading…
Reference in New Issue