Require explicit decl of maxError and errorLocations.

This should reduce both performance issues and clearance issues.
This commit is contained in:
Jeff Young 2020-10-13 11:55:24 +01:00
parent 58ba5a5cc1
commit 1703729269
36 changed files with 387 additions and 318 deletions

View File

@ -349,7 +349,7 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
{ {
D_PAD dummy( *aPad ); D_PAD dummy( *aPad );
dummy.SetSize( aPad->GetSize() + aClearanceValue + aClearanceValue ); dummy.SetSize( aPad->GetSize() + aClearanceValue + aClearanceValue );
dummy.TransformShapeWithClearanceToPolygon( poly, aLayer, 0 ); dummy.TransformShapeWithClearanceToPolygon( poly, aLayer, 0, ARC_HIGH_DEF, ERROR_INSIDE );
aClearanceValue = { 0, 0 }; aClearanceValue = { 0, 0 };
} }
else else
@ -683,7 +683,8 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const PCB_SHAPE* aDrawSegm
SHAPE_POLY_SET polyList; SHAPE_POLY_SET polyList;
aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId,
aClearanceValue ); aClearanceValue,
ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
@ -736,7 +737,8 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const PCB_SHAPE* aDrawSegm
{ {
SHAPE_POLY_SET polyList; SHAPE_POLY_SET polyList;
aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, aClearanceValue ); aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, aClearanceValue,
ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST );

View File

@ -392,10 +392,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThicknessBIU(); const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThicknessBIU();
TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(), TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(),
hole_outer_radius, ARC_HIGH_DEF ); hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE );
TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(), TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(),
holediameter / 2, ARC_HIGH_DEF ); holediameter / 2, ARC_HIGH_DEF, ERROR_INSIDE );
} }
else if( curr_layer_id == layer_id[0] ) // it only adds once the THT holes else if( curr_layer_id == layer_id[0] ) // it only adds once the THT holes
{ {
@ -406,17 +406,18 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// Add through hole contourns // Add through hole contourns
// ///////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////
TransformCircleToPolygon( m_through_outer_holes_poly, via->GetStart(), TransformCircleToPolygon( m_through_outer_holes_poly, via->GetStart(),
hole_outer_radius, ARC_HIGH_DEF ); hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE );
// Add same thing for vias only // Add same thing for vias only
TransformCircleToPolygon( m_through_outer_holes_vias_poly, TransformCircleToPolygon( m_through_outer_holes_vias_poly, via->GetStart(),
via->GetStart(), hole_outer_radius, ARC_HIGH_DEF ); hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE );
if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) )
{ {
TransformCircleToPolygon( m_through_outer_ring_holes_poly, TransformCircleToPolygon( m_through_outer_ring_holes_poly,
via->GetStart(), hole_outer_ring_radius, ARC_HIGH_DEF ); via->GetStart(), hole_outer_ring_radius,
ARC_HIGH_DEF, ERROR_INSIDE );
} }
} }
} }
@ -451,7 +452,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
continue; continue;
// Add the track/via contour // Add the track/via contour
track->TransformShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0 ); track->TransformShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
} }
} }
} }
@ -506,17 +508,26 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( pad->GetAttribute () != PAD_ATTRIB_NPTH ) if( pad->GetAttribute () != PAD_ATTRIB_NPTH )
{ {
if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) )
pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, inflate ); {
pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly,
inflate,
ARC_HIGH_DEF, ERROR_INSIDE );
}
pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly, inflate ); pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly, inflate,
ARC_HIGH_DEF, ERROR_INSIDE );
} }
else else
{ {
// If not plated, no copper. // If not plated, no copper.
if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) )
pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, 0 ); {
pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
}
pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly_NPTH, 0 ); pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly_NPTH, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
} }
} }
} }
@ -535,19 +546,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
// Note: NPTH pads are not drawn on copper layers when the pad // Note: NPTH pads are not drawn on copper layers when the pad
// has same shape as its hole // has same shape as its hole
AddPadsShapesWithClearanceToContainer( module, AddPadsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0,
layerContainer, true, renderPlatedPadsAsPlated, false );
curr_layer_id,
0,
true,
renderPlatedPadsAsPlated,
false );
// Micro-wave modules may have items on copper layers // Micro-wave modules may have items on copper layers
AddGraphicsShapesWithClearanceToContainer( module, AddGraphicsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0 );
layerContainer,
curr_layer_id,
0 );
} }
} }
@ -556,21 +559,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS // ADD PLATED PADS
for( MODULE* module : m_board->Modules() ) for( MODULE* module : m_board->Modules() )
{ {
AddPadsShapesWithClearanceToContainer( module, AddPadsShapesWithClearanceToContainer( module, m_platedpads_container2D_F_Cu, F_Cu, 0,
m_platedpads_container2D_F_Cu, true, false, true );
F_Cu,
0,
true,
false,
true );
AddPadsShapesWithClearanceToContainer( module, AddPadsShapesWithClearanceToContainer( module, m_platedpads_container2D_B_Cu, B_Cu, 0,
m_platedpads_container2D_B_Cu, true, false, true );
B_Cu,
0,
true,
false,
true );
} }
} }
@ -589,9 +582,9 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
// Note: NPTH pads are not drawn on copper layers when the pad // Note: NPTH pads are not drawn on copper layers when the pad
// has same shape as its hole // has same shape as its hole
module->TransformPadsShapesWithClearanceToPolygon( curr_layer_id, *layerPoly, module->TransformPadsShapesWithClearanceToPolygon( *layerPoly, curr_layer_id,
0, ARC_HIGH_DEF, true, 0, ARC_HIGH_DEF, ERROR_INSIDE,
renderPlatedPadsAsPlated, true, renderPlatedPadsAsPlated,
false ); false );
transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly );
@ -603,15 +596,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS contourns // ADD PLATED PADS contourns
for( auto module : m_board->Modules() ) for( auto module : m_board->Modules() )
{ {
module->TransformPadsShapesWithClearanceToPolygon( F_Cu, *m_F_Cu_PlatedPads_poly, module->TransformPadsShapesWithClearanceToPolygon( *m_F_Cu_PlatedPads_poly, F_Cu,
0, ARC_HIGH_DEF, true, 0, ARC_HIGH_DEF, ERROR_INSIDE,
false, true ); true, false, true );
//transformGraphicModuleEdgeToPolygonSet( module, F_Cu, *m_F_Cu_PlatedPads_poly ); //transformGraphicModuleEdgeToPolygonSet( module, F_Cu, *m_F_Cu_PlatedPads_poly );
module->TransformPadsShapesWithClearanceToPolygon( B_Cu, *m_B_Cu_PlatedPads_poly, module->TransformPadsShapesWithClearanceToPolygon( *m_B_Cu_PlatedPads_poly, B_Cu,
0, ARC_HIGH_DEF, true, 0, ARC_HIGH_DEF, ERROR_INSIDE,
false, true ); true, false, true );
//transformGraphicModuleEdgeToPolygonSet( module, B_Cu, *m_B_Cu_PlatedPads_poly ); //transformGraphicModuleEdgeToPolygonSet( module, B_Cu, *m_B_Cu_PlatedPads_poly );
} }
@ -636,17 +629,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
{ {
AddShapeWithClearanceToContainer( (PCB_SHAPE*)item, AddShapeWithClearanceToContainer( (PCB_SHAPE*)item, layerContainer, curr_layer_id,
layerContainer,
curr_layer_id,
0 ); 0 );
} }
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
AddShapeWithClearanceToContainer( (PCB_TEXT*) item, AddShapeWithClearanceToContainer( (PCB_TEXT*) item, layerContainer, curr_layer_id,
layerContainer,
curr_layer_id,
0 ); 0 );
break; break;
@ -654,9 +643,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
case PCB_DIM_CENTER_T: case PCB_DIM_CENTER_T:
case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T: case PCB_DIM_LEADER_T:
AddShapeWithClearanceToContainer( (DIMENSION*) item, AddShapeWithClearanceToContainer( (DIMENSION*) item, layerContainer, curr_layer_id,
layerContainer,
curr_layer_id,
0 ); 0 );
break; break;
@ -689,11 +676,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, ( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly,
cur_layer_id, 0 ); cur_layer_id, 0,
ARC_HIGH_DEF,
ERROR_INSIDE );
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0,
ARC_HIGH_DEF,
ERROR_INSIDE );
break; break;
default: default:
@ -972,11 +963,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, ( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly,
curr_layer_id, 0 ); curr_layer_id, 0,
ARC_HIGH_DEF,
ERROR_INSIDE );
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0,
ARC_HIGH_DEF,
ERROR_INSIDE );
break; break;
default: default:
@ -1030,11 +1025,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
} }
else else
{ {
module->TransformPadsShapesWithClearanceToPolygon( curr_layer_id, *layerPoly, 0 ); module->TransformPadsShapesWithClearanceToPolygon( *layerPoly, curr_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
} }
// On tech layers, use a poor circle approximation, only for texts (stroke font) // On tech layers, use a poor circle approximation, only for texts (stroke font)
module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id, *layerPoly, 0 ); module->TransformGraphicTextWithClearanceToPolygonSet( *layerPoly, curr_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
// Add the remaining things with dynamic seg count for circles // Add the remaining things with dynamic seg count for circles
transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly );

View File

@ -41,7 +41,7 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
{ {
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(), aPad->GetSize().x / 2, TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(), aPad->GetSize().x / 2,
ARC_HIGH_DEF, aWidth ); aWidth, ARC_HIGH_DEF, ERROR_INSIDE );
return; return;
} }
@ -54,7 +54,8 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
const VECTOR2I& a = path.CPoint( ii ); const VECTOR2I& a = path.CPoint( ii );
const VECTOR2I& b = path.CPoint( ii + 1 ); const VECTOR2I& b = path.CPoint( ii + 1 );
TransformOvalToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, aWidth, ARC_HIGH_DEF ); TransformOvalToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, aWidth, ARC_HIGH_DEF,
ERROR_INSIDE );
} }
} }
@ -70,7 +71,10 @@ void BOARD_ADAPTER::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModul
FP_SHAPE* outline = (FP_SHAPE*) item; FP_SHAPE* outline = (FP_SHAPE*) item;
if( outline->GetLayer() == aLayer ) if( outline->GetLayer() == aLayer )
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0 ); {
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
}
} }
} }
} }

View File

@ -825,9 +825,10 @@ void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads()
const int copperThickness = m_boardAdapter.GetHolePlatingThicknessBIU(); const int copperThickness = m_boardAdapter.GetHolePlatingThicknessBIU();
pad->TransformHoleWithClearanceToPolygon( tht_outer_holes_poly, pad->TransformHoleWithClearanceToPolygon( tht_outer_holes_poly,
copperThickness, ARC_LOW_DEF ); copperThickness,
pad->TransformHoleWithClearanceToPolygon( tht_inner_holes_poly, ARC_LOW_DEF, ERROR_INSIDE );
0, ARC_LOW_DEF ); pad->TransformHoleWithClearanceToPolygon( tht_inner_holes_poly, 0,
ARC_LOW_DEF, ERROR_INSIDE );
} }
} }
} }

View File

@ -533,7 +533,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
{ {
TransformOvalToPolygon( bufferOutline, aCornerList[ ii - 1 ], aCornerList[ ii ], TransformOvalToPolygon( bufferOutline, aCornerList[ ii - 1 ], aCornerList[ ii ],
aWidth, GetPlotterArcHighDef() ); aWidth, GetPlotterArcHighDef(), ERROR_INSIDE );
} }
// enter the initial polygon: // enter the initial polygon:
@ -620,7 +620,8 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
{ {
std::vector<wxPoint> cornerList; std::vector<wxPoint> cornerList;
SHAPE_POLY_SET outlineBuffer; SHAPE_POLY_SET outlineBuffer;
TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef() ); TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef(),
ERROR_INSIDE );
const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 ); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 );
cornerList.reserve( path.PointCount() ); cornerList.reserve( path.PointCount() );
@ -777,7 +778,7 @@ void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );

View File

@ -1227,7 +1227,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
outline.Inflate( -GetCurrentLineWidth()/2, 16 ); outline.Inflate( -GetCurrentLineWidth()/2, 16 );
@ -1489,10 +1489,9 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w
if( aPlotMode != FILLED || hasRoundedCorner || m_gerberDisableApertMacros ) if( aPlotMode != FILLED || hasRoundedCorner || m_gerberDisableApertMacros )
#endif #endif
{ {
TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize, TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize, aPadOrient,
aPadOrient, aCornerRadius, aCornerRadius, aChamferRatio, aChamferPositions,
aChamferRatio, GetPlotterArcHighDef(), ERROR_INSIDE );
aChamferPositions, m_IUsPerDecimil * 2 );
// Build the corner list // Build the corner list
const SHAPE_LINE_CHAIN& corners = outline.Outline(0); const SHAPE_LINE_CHAIN& corners = outline.Outline(0);
@ -1535,9 +1534,9 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w
} }
// Build the chamfered polygon (4 to 8 corners ) // Build the chamfered polygon (4 to 8 corners )
TransformRoundChamferedRectToPolygon( outline, wxPoint( 0, 0 ), aPadSize, TransformRoundChamferedRectToPolygon( outline, wxPoint( 0, 0 ), aPadSize, 0.0, 0,
0.0, 0, aChamferRatio, aChamferRatio, aChamferPositions,
aChamferPositions, 0 ); GetPlotterArcHighDef(), ERROR_INSIDE );
// Build the corner list // Build the corner list
const SHAPE_LINE_CHAIN& corners = outline.Outline(0); const SHAPE_LINE_CHAIN& corners = outline.Outline(0);

View File

@ -640,8 +640,8 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz
aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 ); aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 );
} }
TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
std::vector<wxPoint> cornerList; std::vector<wxPoint> cornerList;

View File

@ -192,8 +192,8 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
std::vector< wxPoint > cornerList; std::vector< wxPoint > cornerList;
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon

View File

@ -311,11 +311,14 @@ void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent,
if( outerDiam <= penThickness ) if( outerDiam <= penThickness )
{ // No room to draw a ring (no room for the hole): { // No room to draw a ring (no room for the hole):
// draw a circle instead (with no hole), with the right diameter // draw a circle instead (with no hole), with the right diameter
TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF ); TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF,
ERROR_INSIDE );
} }
else else
{
TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2, TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2,
ARC_HIGH_DEF, penThickness ); penThickness, ARC_HIGH_DEF, ERROR_INSIDE );
}
} }
// Draw the cross: // Draw the cross:

View File

@ -306,7 +306,8 @@ void D_CODE::ConvertShapeToPolygon()
switch( m_Shape ) switch( m_Shape )
{ {
case APT_CIRCLE: // creates only a circle with rectangular hole case APT_CIRCLE: // creates only a circle with rectangular hole
TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, ARC_HIGH_DEF ); TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, ARC_HIGH_DEF,
ERROR_INSIDE );
addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos );
break; break;
@ -428,7 +429,8 @@ static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon,
if( aHoleShape == APT_DEF_ROUND_HOLE ) if( aHoleShape == APT_DEF_ROUND_HOLE )
{ {
TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF ); TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF,
ERROR_INSIDE );
} }
else if( aHoleShape == APT_DEF_RECT_HOLE ) else if( aHoleShape == APT_DEF_RECT_HOLE )
{ {

View File

@ -36,7 +36,7 @@
#include <convert_to_biu.h> #include <convert_to_biu.h>
#include <gr_basic.h> #include <gr_basic.h>
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <geometry/geometry_utils.h>
class BOARD; class BOARD;
class BOARD_ITEM_CONTAINER; class BOARD_ITEM_CONTAINER;
@ -360,13 +360,13 @@ public:
* @param aCornerBuffer = a buffer to store the polygon * @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad * @param aClearanceValue = the clearance around the pad
* @param aError = the maximum deviation from true circle * @param aError = the maximum deviation from true circle
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
* @param ignoreLineWidth = used for edge cut items where the line width is only * @param ignoreLineWidth = used for edge cut items where the line width is only
* for visualization * for visualization
*/ */
virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, int aClearanceValue,
int aClearanceValue, int aError, ERROR_LOC aErrorLoc,
int aError = ARC_LOW_DEF,
bool ignoreLineWidth = false ) const; bool ignoreLineWidth = false ) const;
struct ptr_cmp struct ptr_cmp

View File

@ -25,26 +25,26 @@
#ifndef CONVERT_BASIC_SHAPES_TO_POLYGON_H #ifndef CONVERT_BASIC_SHAPES_TO_POLYGON_H
#define CONVERT_BASIC_SHAPES_TO_POLYGON_H #define CONVERT_BASIC_SHAPES_TO_POLYGON_H
/**
* @file convert_basic_shapes_to_polygon.h
*/
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
#include <geometry/geometry_utils.h>
#include <wx/gdicmn.h> // for wxPoint #include <wx/gdicmn.h> // for wxPoint
// The chamfer positions of chamfered rect shape. // The chamfer positions of chamfered rect shape.
// the position is relative to a pad with orientation = 0 // the position is relative to a pad with orientation = 0
// we can have 1 to 4 chamfered corners (0 corner = roundrect) // we can have 1 to 4 chamfered corners (0 corner = roundrect)
// The position list is the OR of corner to chamfer // The position list is the OR of corner to chamfer
enum RECT_CHAMFER_POSITIONS : int enum RECT_CHAMFER_POSITIONS : int
{ {
RECT_NO_CHAMFER = 0, RECT_NO_CHAMFER = 0,
RECT_CHAMFER_TOP_LEFT = 1, RECT_CHAMFER_TOP_LEFT = 1,
RECT_CHAMFER_TOP_RIGHT = 2, RECT_CHAMFER_TOP_RIGHT = 2,
RECT_CHAMFER_BOTTOM_LEFT = 4, RECT_CHAMFER_BOTTOM_LEFT = 4,
RECT_CHAMFER_BOTTOM_RIGHT = 8, RECT_CHAMFER_BOTTOM_RIGHT = 8,
RECT_CHAMFER_ALL = RECT_CHAMFER_BOTTOM_RIGHT | RECT_CHAMFER_BOTTOM_LEFT RECT_CHAMFER_ALL = RECT_CHAMFER_BOTTOM_RIGHT
| RECT_CHAMFER_TOP_RIGHT | RECT_CHAMFER_TOP_LEFT | RECT_CHAMFER_BOTTOM_LEFT
| RECT_CHAMFER_TOP_RIGHT
| RECT_CHAMFER_TOP_LEFT
}; };
@ -55,11 +55,10 @@ enum RECT_CHAMFER_POSITIONS : int
* @param aCenter = the center of the circle * @param aCenter = the center of the circle
* @param aRadius = the radius of the circle * @param aRadius = the radius of the circle
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
* Note: the polygon is inside the circle, so if you want to have the polygon * @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
* outside the circle, you should give aRadius calculated with a correction factor
*/ */
void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius,
int aError ); int aError, ERROR_LOC aErrorLoc );
/** /**
@ -75,9 +74,10 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i
* @param aEnd = the second point of the segment * @param aEnd = the second point of the segment
* @param aWidth = the width of the segment * @param aWidth = the width of the segment
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
*/ */
void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd,
int aWidth, int aError ); int aWidth, int aError, ERROR_LOC aErrorLoc );
/** /**
@ -112,11 +112,13 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint&
* 8 = BOTTOM_RIGHT * 8 = BOTTOM_RIGHT
* One can have more than one chamfered corner by ORing the corner identifers * One can have more than one chamfered corner by ORing the corner identifers
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
*/ */
void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
double aRotation, int aCornerRadius, double aRotation, int aCornerRadius,
double aChamferRatio, int aChamferCorners, int aError ); double aChamferRatio, int aChamferCorners,
int aError, ERROR_LOC aErrorLoc );
/** /**
* Function TransformArcToPolygon * Function TransformArcToPolygon
@ -126,11 +128,12 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* @param aCentre = centre of the arc or circle * @param aCentre = centre of the arc or circle
* @param aStart = start point of the arc, or a point on the circle * @param aStart = start point of the arc, or a point on the circle
* @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600 * @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600
* @param aError = the IU allowed for error in approximation
* @param aWidth = width (thickness) of the line * @param aWidth = width (thickness) of the line
* @param aError = the IU allowed for error in approximation
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
*/ */
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart,
double aArcAngle, int aError, int aWidth ); double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc );
/** /**
* Function TransformRingToPolygon * Function TransformRingToPolygon
@ -139,10 +142,11 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPo
* @param aCornerBuffer = a buffer to store the polygon * @param aCornerBuffer = a buffer to store the polygon
* @param aCentre = centre of the arc or circle * @param aCentre = centre of the arc or circle
* @param aRadius = radius of the circle * @param aRadius = radius of the circle
* @param aError = the IU allowed for error in approximation
* @param aWidth = width (thickness) of the ring * @param aWidth = width (thickness) of the ring
* @param aError = the IU allowed for error in approximation
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
*/ */
void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius,
int aError, int aWidth ); int aWidth, int aError, ERROR_LOC aErrorLoc );
#endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H #endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H

View File

@ -37,6 +37,13 @@
class EDA_RECT; class EDA_RECT;
/**
* When approximating an arc or circle, should the error be placed on the outside
* or inside of the curve? (Generally speaking filled shape errors go on the inside
* and knockout errors go on the outside. This preserves minimum clearances.)
*/
enum ERROR_LOC { ERROR_OUTSIDE, ERROR_INSIDE };
/** /**
* @return the number of segments to approximate a arc by segments * @return the number of segments to approximate a arc by segments
* with a given max error (this number is >= 1) * with a given max error (this number is >= 1)

View File

@ -39,14 +39,15 @@
void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, int aRadius, void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, int aRadius,
int aError ) int aError, ERROR_LOC aErrorLoc )
{ {
wxPoint corner_position; wxPoint corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
int delta = 3600 / numSegs; // rotate angle in 0.1 degree int delta = 3600 / numSegs; // rotate angle in 0.1 degree
int correction = GetCircleToPolyCorrection( aError ); int radius = aRadius;
int radius = aRadius + correction; // make segments outside the circles
double halfstep = delta / 2.0; // the starting value for rot angles if( aErrorLoc == ERROR_OUTSIDE )
radius += GetCircleToPolyCorrection( aError );
for( int angle = 0; angle < 3600; angle += delta ) for( int angle = 0; angle < 3600; angle += delta )
{ {
@ -62,13 +63,15 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter,
void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius,
int aError ) int aError, ERROR_LOC aErrorLoc )
{ {
wxPoint corner_position; wxPoint corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
int delta = 3600 / numSegs; // rotate angle in 0.1 degree int delta = 3600 / numSegs; // rotate angle in 0.1 degree
int correction = GetCircleToPolyCorrection( aError ); int radius = aRadius;
int radius = aRadius + correction; // make segments outside the circles
if( aErrorLoc == ERROR_OUTSIDE )
radius += GetCircleToPolyCorrection( aError );
aCornerBuffer.NewOutline(); aCornerBuffer.NewOutline();
@ -90,7 +93,7 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i
void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd,
int aWidth, int aError ) int aWidth, int aError, ERROR_LOC aErrorLoc )
{ {
// To build the polygonal shape outside the actual shape, we use a bigger // To build the polygonal shape outside the actual shape, we use a bigger
// radius to build rounded ends. // radius to build rounded ends.
@ -102,7 +105,8 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPo
int delta = 3600 / numSegs; // rotate angle in 0.1 degree int delta = 3600 / numSegs; // rotate angle in 0.1 degree
int correction = GetCircleToPolyCorrection( aError ); int correction = GetCircleToPolyCorrection( aError );
radius += correction; // make segments outside the circles if( aErrorLoc == ERROR_OUTSIDE )
radius += correction;
// end point is the coordinate relative to aStart // end point is the coordinate relative to aStart
wxPoint endp = aEnd - aStart; wxPoint endp = aEnd - aStart;
@ -218,7 +222,7 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint&
void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition, void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition,
const wxSize& aSize, double aRotation, const wxSize& aSize, double aRotation,
int aCornerRadius, double aChamferRatio, int aCornerRadius, double aChamferRatio,
int aChamferCorners, int aError ) int aChamferCorners, int aError, ERROR_LOC aErrorLoc )
{ {
// Build the basic shape in orientation 0.0, position 0,0 for chamfered corners // Build the basic shape in orientation 0.0, position 0,0 for chamfered corners
// or in actual position/orientation for round rect only // or in actual position/orientation for round rect only
@ -244,28 +248,13 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const
// radius to build rounded corners. // radius to build rounded corners.
int correction = GetCircleToPolyCorrection( aError ); int correction = GetCircleToPolyCorrection( aError );
int radius = aCornerRadius + correction; // make segments outside the circles int radius = aCornerRadius;
if( aErrorLoc == ERROR_OUTSIDE )
radius += correction;
outline.Inflate( radius, numSegs ); outline.Inflate( radius, numSegs );
if( correction > 1.0 )
{
// Refinement: clamp the inflated polygonal shape by the rectangular shape
// containing the rounded polygon
SHAPE_POLY_SET bbox; // the rectangular shape
bbox.NewOutline();
for( const wxPoint& corner : corners )
bbox.Append( corner );
// Just build the rectangular bbox
bbox.Inflate( aCornerRadius, 1, SHAPE_POLY_SET::CORNER_STRATEGY::ALLOW_ACUTE_CORNERS );
// Now, clamp the shape
outline.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
// Note the final polygon is a simple, convex polygon with no hole
// due to the shape of initial polygons
}
if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer
{ {
// Add the outline: // Add the outline:
@ -334,7 +323,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart,
double aArcAngle, int aError, int aWidth ) double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc )
{ {
wxPoint arc_start, arc_end; wxPoint arc_start, arc_end;
int dist = EuclideanNorm( aCentre - aStart ); int dist = EuclideanNorm( aCentre - aStart );
@ -360,34 +349,35 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPo
{ {
curr_end = arc_start; curr_end = arc_start;
RotatePoint( &curr_end, aCentre, -ii ); RotatePoint( &curr_end, aCentre, -ii );
TransformOvalToPolygon( aCornerBuffer, curr_start, curr_end, aWidth, aError ); TransformOvalToPolygon( aCornerBuffer, curr_start, curr_end, aWidth, aError, aErrorLoc );
curr_start = curr_end; curr_start = curr_end;
} }
if( curr_end != arc_end ) if( curr_end != arc_end )
TransformOvalToPolygon( aCornerBuffer, curr_end, arc_end, aWidth, aError ); TransformOvalToPolygon( aCornerBuffer, curr_end, arc_end, aWidth, aError, aErrorLoc );
} }
void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius,
int aError, int aWidth ) int aWidth, int aError, ERROR_LOC aErrorLoc )
{ {
int inner_radius = aRadius - ( aWidth / 2 ); int inner_radius = aRadius - ( aWidth / 2 );
int outer_radius = inner_radius + aWidth; int outer_radius = inner_radius + aWidth;
if( inner_radius <= 0 ) if( inner_radius <= 0 )
{ //In this case, the ring is just a circle (no hole inside) { //In this case, the ring is just a circle (no hole inside)
TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError ); TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError,
aErrorLoc );
return; return;
} }
SHAPE_POLY_SET buffer; SHAPE_POLY_SET buffer;
TransformCircleToPolygon( buffer, aCentre, outer_radius, aError ); TransformCircleToPolygon( buffer, aCentre, outer_radius, aError, aErrorLoc );
// Build the hole: // Build the hole:
buffer.NewHole(); buffer.NewHole();
TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError ); TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError, aErrorLoc );
buffer.Fracture( SHAPE_POLY_SET::PM_FAST ); buffer.Fracture( SHAPE_POLY_SET::PM_FAST );
aCornerBuffer.Append( buffer ); aCornerBuffer.Append( buffer );

View File

@ -46,40 +46,48 @@
// These variables are parameters used in addTextSegmToPoly. // These variables are parameters used in addTextSegmToPoly.
// But addTextSegmToPoly is a call-back function, // But addTextSegmToPoly is a call-back function,
// so we cannot send them as arguments. // so we cannot send them as arguments.
struct TSEGM_2_POLY_PRMS { struct TSEGM_2_POLY_PRMS
{
int m_textWidth; int m_textWidth;
int m_error; int m_error;
SHAPE_POLY_SET* m_cornerBuffer; SHAPE_POLY_SET* m_cornerBuffer;
}; };
TSEGM_2_POLY_PRMS prms; TSEGM_2_POLY_PRMS prms;
// This is a call back function, used by GRText to draw the 3D text shape: // This is a call back function, used by GRText to draw the 3D text shape:
static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData )
{ {
TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData ); TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData );
TransformOvalToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0 ), wxPoint( xf, yf ), TransformOvalToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0 ), wxPoint( xf, yf ),
prm->m_textWidth, prm->m_error ); prm->m_textWidth, prm->m_error, ERROR_INSIDE );
} }
void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines )
{ {
int maxError = GetDesignSettings().m_MaxError;
// convert tracks and vias: // convert tracks and vias:
for( auto track : m_tracks ) for( auto track : m_tracks )
{ {
if( !track->IsOnLayer( aLayer ) ) if( !track->IsOnLayer( aLayer ) )
continue; continue;
track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0 ); track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
} }
// convert pads // convert pads
for( auto module : m_modules ) for( MODULE* module : m_modules )
{ {
module->TransformPadsShapesWithClearanceToPolygon( aLayer, aOutlines, 0 ); module->TransformPadsShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
// Micro-wave modules may have items on copper layers // Micro-wave modules may have items on copper layers
module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aOutlines, 0 ); module->TransformGraphicShapesWithClearanceToPolygonSet( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
} }
// convert copper zones // convert copper zones
@ -90,7 +98,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
} }
// convert graphic items on copper layers (texts) // convert graphic items on copper layers (texts)
for( auto item : m_drawings ) for( BOARD_ITEM* item : m_drawings )
{ {
if( !item->IsOnLayer( aLayer ) ) if( !item->IsOnLayer( aLayer ) )
continue; continue;
@ -98,11 +106,18 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0 ); {
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
shape->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
}
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( aOutlines, 0 ); {
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformShapeWithClearanceToPolygonSet( aOutlines, 0, maxError, ERROR_INSIDE );
}
break; break;
default: default:
@ -112,9 +127,9 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
} }
void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, void MODULE::TransformPadsShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aInflateValue, int aMaxError, int aMaxError, ERROR_LOC aErrorLoc,
bool aSkipNPTHPadsWihNoCopper, bool aSkipNPTHPadsWihNoCopper,
bool aSkipPlatedPads, bool aSkipPlatedPads,
bool aSkipNonPlatedPads ) const bool aSkipNonPlatedPads ) const
@ -160,7 +175,7 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer,
if( aSkipNonPlatedPads && !isPlated ) if( aSkipNonPlatedPads && !isPlated )
continue; continue;
wxSize clearance( aInflateValue, aInflateValue ); wxSize clearance( aClearance, aClearance );
switch( aLayer ) switch( aLayer )
{ {
@ -191,12 +206,13 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer,
{ {
D_PAD dummy( *pad ); D_PAD dummy( *pad );
dummy.SetSize( pad->GetSize() + clearance + clearance ); dummy.SetSize( pad->GetSize() + clearance + clearance );
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, aMaxError ); dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
aMaxError, aErrorLoc );
} }
else else
{ {
pad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, clearance.x, pad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, clearance.x,
aMaxError ); aMaxError, aErrorLoc );
} }
} }
} }
@ -209,10 +225,9 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer,
* @aIncludeText = indicates footprint text items (reference, value, etc.) should be included * @aIncludeText = indicates footprint text items (reference, value, etc.) should be included
* in the outline * in the outline
*/ */
void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aInflateValue, int aError, ERROR_LOC aErrorLoc,
int aError,
bool aIncludeText, bool aIncludeText,
bool aIncludeEdges ) const bool aIncludeEdges ) const
{ {
@ -233,7 +248,10 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
FP_SHAPE* outline = static_cast<FP_SHAPE*>( item ); FP_SHAPE* outline = static_cast<FP_SHAPE*>( item );
if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer ) if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer )
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, aError ); {
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
aError, aErrorLoc );
}
} }
} }
@ -253,7 +271,7 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
bool forceBold = true; bool forceBold = true;
int penWidth = 0; // force max width for bold text int penWidth = 0; // force max width for bold text
prms.m_textWidth = textmod->GetEffectiveTextPenWidth() + ( 2 * aInflateValue ); prms.m_textWidth = textmod->GetEffectiveTextPenWidth() + ( 2 * aClearance );
prms.m_error = aError; prms.m_error = aError;
wxSize size = textmod->GetTextSize(); wxSize size = textmod->GetTextSize();
@ -339,7 +357,8 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCorn
* @aError = the maximum error to allow when approximating curves * @aError = the maximum error to allow when approximating curves
*/ */
void PCB_TEXT::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, void PCB_TEXT::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
int aClearanceValue, int aError ) const int aClearanceValue,
int aError, ERROR_LOC aErrorLoc ) const
{ {
wxSize size = GetTextSize(); wxSize size = GetTextSize();
@ -378,8 +397,8 @@ void PCB_TEXT::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerB
void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, int aClearanceValue,
int aClearanceValue, int aError, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const bool ignoreLineWidth ) const
{ {
int width = ignoreLineWidth ? 0 : m_Width; int width = ignoreLineWidth ? 0 : m_Width;
@ -397,9 +416,15 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
{ {
case S_CIRCLE: case S_CIRCLE:
if( width == 0 ) if( width == 0 )
TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError ); {
TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError,
aErrorLoc );
}
else else
TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width ); {
TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), width, aError,
aErrorLoc );
}
break; break;
case S_RECT: case S_RECT:
@ -417,20 +442,21 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
if( width > 0 ) if( width > 0 )
{ {
// Add in segments // Add in segments
TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError ); TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError, aErrorLoc );
TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError ); TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError, aErrorLoc );
TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError ); TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError, aErrorLoc );
TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError ); TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError, aErrorLoc );
} }
} }
break; break;
case S_ARC: case S_ARC:
TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, width ); TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, width,
aError, aErrorLoc );
break; break;
case S_SEGMENT: case S_SEGMENT:
TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc );
break; break;
case S_POLYGON: case S_POLYGON:
@ -470,7 +496,10 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
for( wxPoint pt2 : poly ) for( wxPoint pt2 : poly )
{ {
if( pt2 != pt1 ) if( pt2 != pt1 )
TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width, aError ); {
TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width,
aError, aErrorLoc );
}
pt1 = pt2; pt1 = pt2;
} }
@ -488,7 +517,10 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
if( width != 0 ) if( width != 0 )
{ {
for( unsigned ii = 1; ii < poly.size(); ii++ ) for( unsigned ii = 1; ii < poly.size(); ii++ )
TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError ); {
TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width,
aError, aErrorLoc );
}
} }
} }
break; break;
@ -502,8 +534,8 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, int aClearanceValue,
int aClearanceValue, int aError, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." );
@ -514,7 +546,7 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
case PCB_VIA_T: case PCB_VIA_T:
{ {
int radius = ( m_Width / 2 ) + aClearanceValue; int radius = ( m_Width / 2 ) + aClearanceValue;
TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError, aErrorLoc );
} }
break; break;
@ -525,7 +557,8 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
VECTOR2D center( arc->GetCenter() ); VECTOR2D center( arc->GetCenter() );
double angle = arc->GetAngle(); double angle = arc->GetAngle();
TransformArcToPolygon( aCornerBuffer, (wxPoint) center, GetStart(), angle, aError, width ); TransformArcToPolygon( aCornerBuffer, (wxPoint) center, GetStart(), angle, width,
aError, aErrorLoc );
} }
break; break;
@ -533,7 +566,7 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
{ {
int width = m_Width + ( 2 * aClearanceValue ); int width = m_Width + ( 2 * aClearanceValue );
TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc );
} }
break; break;
} }
@ -541,8 +574,8 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, int aClearanceValue,
int aClearanceValue, int aError, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." );
@ -564,7 +597,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
case PAD_SHAPE_OVAL: case PAD_SHAPE_OVAL:
if( dx == dy ) if( dx == dy )
{ {
TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError ); TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError,
aErrorLoc );
} }
else else
{ {
@ -574,7 +608,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
RotatePoint( &delta, angle ); RotatePoint( &delta, angle );
TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta, TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta,
( half_width + aClearanceValue ) * 2, aError ); ( half_width + aClearanceValue ) * 2, aError, aErrorLoc );
} }
break; break;
@ -619,19 +653,19 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
case PAD_SHAPE_CHAMFERED_RECT: case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
int radius = GetRoundRectCornerRadius() + aClearanceValue; int radius = GetRoundRectCornerRadius();
int clearance = aClearanceValue + GetCircleToPolyCorrection( aError );
wxSize shapesize( m_size ); wxSize shapesize( m_size );
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
radius = radius + GetCircleToPolyCorrection( aError ); radius += aClearanceValue;
shapesize.x += clearance * 2; shapesize.x += aClearanceValue * 2;
shapesize.y += clearance * 2; shapesize.y += aClearanceValue * 2;
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius, TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius,
doChamfer ? GetChamferRectRatio() : 0.0, doChamfer ? GetChamferRectRatio() : 0.0,
doChamfer ? GetChamferPositions() : 0, aError ); doChamfer ? GetChamferPositions() : 0,
aError, aErrorLoc );
aCornerBuffer.Append( outline ); aCornerBuffer.Append( outline );
} }
@ -648,7 +682,10 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
{ {
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
pad_min_seg_per_circle_count ); pad_min_seg_per_circle_count );
int clearance = aClearanceValue + GetCircleToPolyCorrection( aError ); int clearance = aClearanceValue;
if( aErrorLoc == ERROR_OUTSIDE )
clearance += GetCircleToPolyCorrection( aError );
outline.Inflate( clearance, numSegs ); outline.Inflate( clearance, numSegs );
outline.Simplify( SHAPE_POLY_SET::PM_FAST ); outline.Simplify( SHAPE_POLY_SET::PM_FAST );
@ -669,7 +706,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
int aError ) const int aError, ERROR_LOC aErrorLoc ) const
{ {
wxSize drillsize = GetDrillSize(); wxSize drillsize = GetDrillSize();
@ -679,7 +716,7 @@ bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const SHAPE_SEGMENT* seg = GetEffectiveHoleShape(); const SHAPE_SEGMENT* seg = GetEffectiveHoleShape();
TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B, TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B,
seg->GetWidth() + aInflateValue * 2, aError ); seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc );
return true; return true;
} }
@ -687,7 +724,8 @@ bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearance, PCB_LAYER_ID aLayer, int aClearance,
int aError, bool ignoreLineWidth ) const int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." );

View File

@ -598,12 +598,9 @@ public:
wxPoint* aErrorLocation = nullptr ); wxPoint* aErrorLocation = nullptr );
/** /**
* Build a set of polygons which are the outlines of copper items * Build a set of polygons which are the outlines of copper items (pads, tracks, vias, texts,
* (pads, tracks, vias, texts, zones) * zones). Holes in vias or pads are ignored. The polygons are not merged.
* Holes in vias or pads are ignored * Useful to export the shape of copper layers to dxf polygons or 3D viewer
* Useful to export the shape of copper layers to dxf polygons
* or 3D viewer
* the polygons are not merged.
* @param aLayer = A copper layer, like B_Cu, etc. * @param aLayer = A copper layer, like B_Cu, etc.
* @param aOutlines The SHAPE_POLY_SET to fill in with items outline. * @param aOutlines The SHAPE_POLY_SET to fill in with items outline.
*/ */

View File

@ -128,8 +128,8 @@ void BOARD_ITEM::SwapData( BOARD_ITEM* aImage )
void BOARD_ITEM::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void BOARD_ITEM::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, int aClearanceValue,
int aClearanceValue, int aError, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( false, "Called TransformShapeWithClearanceToPolygon() on unsupported BOARD_ITEM." ); wxASSERT_MSG( false, "Called TransformShapeWithClearanceToPolygon() on unsupported BOARD_ITEM." );

View File

@ -349,8 +349,7 @@ public:
* when a full polygonal approach is needed * when a full polygonal approach is needed
* @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all * @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all
* @param aCornerBuffer = the buffer to store polygons * @param aCornerBuffer = the buffer to store polygons
* @param aInflateValue = an additionnal size to add to pad shapes * @param aClearance = an additionnal size to add to pad shapes
* aInflateValue = 0 to have the exact pad size
* @param aMaxError = Maximum deviation from true for arcs * @param aMaxError = Maximum deviation from true for arcs
* @param aSkipNPTHPadsWihNoCopper = if true, do not add a NPTH pad shape, if the shape has * @param aSkipNPTHPadsWihNoCopper = if true, do not add a NPTH pad shape, if the shape has
* same size and position as the hole. Usually, these pads are not drawn on copper * same size and position as the hole. Usually, these pads are not drawn on copper
@ -361,11 +360,12 @@ public:
* @param aSkipPlatedPads = used on 3D-Viewer to extract plated and nontplated pads. * @param aSkipPlatedPads = used on 3D-Viewer to extract plated and nontplated pads.
* @param aSkipNonPlatedPads = used on 3D-Viewer to extract plated and plated pads. * @param aSkipNonPlatedPads = used on 3D-Viewer to extract plated and plated pads.
*/ */
void TransformPadsShapesWithClearanceToPolygon(PCB_LAYER_ID aLayer, void TransformPadsShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer,int aClearance,
bool aSkipNPTHPadsWihNoCopper = false, int aMaxError, ERROR_LOC aErrorLoc,
bool aSkipPlatedPads = false, bool aSkipNPTHPadsWihNoCopper = false,
bool aSkipNonPlatedPads = false ) const; bool aSkipPlatedPads = false,
bool aSkipNonPlatedPads = false ) const;
/** /**
* function TransformGraphicShapesWithClearanceToPolygonSet * function TransformGraphicShapesWithClearanceToPolygonSet
@ -375,26 +375,28 @@ public:
* when a full polygonal approach is needed * when a full polygonal approach is needed
* @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all * @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all
* @param aCornerBuffer = the buffer to store polygons * @param aCornerBuffer = the buffer to store polygons
* @param aInflateValue = a value to inflate shapes * @param aClearance = a value to inflate shapes
* aInflateValue = 0 to have the exact shape size
* @param aError = Maximum error between true arc and polygon approx * @param aError = Maximum error between true arc and polygon approx
* @param aIncludeText = True to transform text shapes * @param aIncludeText = True to transform text shapes
* @param aIncludeEdges = True to transform module shapes * @param aIncludeEdges = True to transform module shapes
*/ */
void TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, void TransformGraphicShapesWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer, int aClearance,
bool aIncludeText = true, bool aIncludeEdges = true ) const; int aError, ERROR_LOC aErrorLoc,
bool aIncludeText = true,
bool aIncludeEdges = true ) const;
/** /**
* @brief TransformGraphicTextWithClearanceToPolygonSet * @brief TransformGraphicTextWithClearanceToPolygonSet
* This function is the same as TransformGraphicShapesWithClearanceToPolygonSet * This function is the same as TransformGraphicShapesWithClearanceToPolygonSet
* but only generate text * but only generate text
*/ */
void TransformGraphicTextWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, void TransformGraphicTextWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF ) const PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const
{ {
TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aCornerBuffer, aInflateValue, TransformGraphicShapesWithClearanceToPolygonSet( aCornerBuffer, aLayer, aClearance,
aError, true, false ); aError, aErrorLoc, true, false );
} }
/** /**

View File

@ -287,6 +287,9 @@ int D_PAD::GetBoundingRadius() const
void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
{ {
BOARD* board = GetBoard();
int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
m_effectiveShape = std::make_shared<SHAPE_COMPOUND>(); m_effectiveShape = std::make_shared<SHAPE_COMPOUND>();
m_effectiveHoleShape = nullptr; m_effectiveHoleShape = nullptr;
@ -385,15 +388,10 @@ void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
case PAD_SHAPE_CHAMFERED_RECT: case PAD_SHAPE_CHAMFERED_RECT:
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
auto board = GetBoard();
int maxError = ARC_HIGH_DEF;
if( board )
maxError = board->GetDesignSettings().m_MaxError;
TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient, TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient,
GetRoundRectCornerRadius(), GetChamferRectRatio(), GetRoundRectCornerRadius(), GetChamferRectRatio(),
GetChamferPositions(), maxError ); GetChamferPositions(), maxError, ERROR_INSIDE );
add( new SHAPE_SIMPLE( outline.COutline( 0 ) ) ); add( new SHAPE_SIMPLE( outline.COutline( 0 ) ) );
} }
@ -421,7 +419,7 @@ void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
// Polygon // Polygon
// //
m_effectivePolygon = std::make_shared<SHAPE_POLY_SET>(); m_effectivePolygon = std::make_shared<SHAPE_POLY_SET>();
TransformShapeWithClearanceToPolygon( *m_effectivePolygon, aLayer, 0 ); TransformShapeWithClearanceToPolygon( *m_effectivePolygon, aLayer, 0, maxError, ERROR_INSIDE );
// Bounding box and radius // Bounding box and radius
// //

View File

@ -372,10 +372,12 @@ public:
* @param aCornerBuffer = a buffer to store the polygon * @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad * @param aClearanceValue = the clearance around the pad
* @param aMaxError = maximum error from true when converting arcs * @param aMaxError = maximum error from true when converting arcs
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
* @param ignoreLineWidth = used for edge cuts where the line width is only for visualization * @param ignoreLineWidth = used for edge cuts where the line width is only for visualization
*/ */
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
int aClearanceValue, int aMaxError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer, int aClearanceValue,
int aMaxError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override; bool ignoreLineWidth = false ) const override;
/** /**
@ -384,10 +386,11 @@ public:
* @param aCornerBuffer = a buffer to fill. * @param aCornerBuffer = a buffer to fill.
* @param aInflateValue = the clearance or margin value. * @param aInflateValue = the clearance or margin value.
* @param aError = maximum deviation of an arc from the polygon approximation * @param aError = maximum deviation of an arc from the polygon approximation
* @param aErrorLoc = should the approximation error be placed outside or inside the polygon?
* @return false if the pad has no hole, true otherwise * @return false if the pad has no hole, true otherwise
*/ */
bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
int aError = ARC_HIGH_DEF ) const; int aError, ERROR_LOC aErrorLoc ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape // @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
@ -634,7 +637,7 @@ public:
private: private:
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer, void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer,
int aError ) const; int aError, ERROR_LOC aErrorLoc ) const;
private: private:
wxString m_name; // Pad name (pin number in schematic) wxString m_name; // Pad name (pin number in schematic)

View File

@ -164,8 +164,9 @@ public:
* @param ignoreLineWidth = used for edge cut items where the line width is only * @param ignoreLineWidth = used for edge cut items where the line width is only
* for visualization * for visualization
*/ */
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
int aClearanceValue, int aError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override; bool ignoreLineWidth = false ) const override;
// @copydoc BOARD_ITEM::GetEffectiveShape // @copydoc BOARD_ITEM::GetEffectiveShape

View File

@ -386,8 +386,9 @@ public:
* @param ignoreLineWidth = used for edge cut items where the line width is only * @param ignoreLineWidth = used for edge cut items where the line width is only
* for visualization * for visualization
*/ */
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
int aClearanceValue, int aError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override; bool ignoreLineWidth = false ) const override;
/** /**

View File

@ -338,7 +338,8 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
// Output the outline perimeter as polygon. // Output the outline perimeter as polygon.
if( graphic->GetShape() == S_CIRCLE ) if( graphic->GetShape() == S_CIRCLE )
{ {
TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), aTolerance ); TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(),
ARC_LOW_DEF, ERROR_INSIDE );
} }
else if( graphic->GetShape() == S_RECT ) else if( graphic->GetShape() == S_RECT )
{ {

View File

@ -1146,8 +1146,8 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P
{ {
SHAPE_POLY_SET polySet; SHAPE_POLY_SET polySet;
const int corner_radius = aPad->GetRoundRectCornerRadius(); const int corner_radius = aPad->GetRoundRectCornerRadius();
TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), 0.0,
0.0, corner_radius, 0.0, 0, ARC_HIGH_DEF ); corner_radius, 0.0, 0, ARC_HIGH_DEF, ERROR_INSIDE );
std::vector< wxRealPoint > cornerList; std::vector< wxRealPoint > cornerList;
// TransformRoundChamferedRectToPolygon creates only one convex polygon // TransformRoundChamferedRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN poly( polySet.Outline( 0 ) ); SHAPE_LINE_CHAIN poly( polySet.Outline( 0 ) );

View File

@ -173,12 +173,12 @@ void D_PAD::DeletePrimitivesList()
void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer, void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer,
int aError ) const int aError, ERROR_LOC aErrorLoc ) const
{ {
SHAPE_POLY_SET polyset; SHAPE_POLY_SET polyset;
for( const std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives ) for( const std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives )
primitive->TransformShapeWithClearanceToPolygon( polyset, aLayer, 0, aError ); primitive->TransformShapeWithClearanceToPolygon( polyset, aLayer, 0, aError, aErrorLoc );
polyset.Simplify( SHAPE_POLY_SET::PM_FAST ); polyset.Simplify( SHAPE_POLY_SET::PM_FAST );
@ -192,11 +192,8 @@ void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER
void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer ) const void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer ) const
{ {
auto board = GetBoard(); BOARD* board = GetBoard();
int maxError = ARC_HIGH_DEF; int maxError = board ? board->GetDesignSettings().m_MaxError: ARC_HIGH_DEF;
if( board )
maxError = board->GetDesignSettings().m_MaxError;
aMergedPolygon->RemoveAllContours(); aMergedPolygon->RemoveAllContours();
@ -213,18 +210,19 @@ void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_
default: default:
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, maxError ); TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, maxError,
ERROR_INSIDE );
break; break;
} }
addPadPrimitivesToPolygon( aMergedPolygon, aLayer, maxError ); addPadPrimitivesToPolygon( aMergedPolygon, aLayer, maxError, ERROR_INSIDE );
} }
bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos ) bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
{ {
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
addPadPrimitivesToPolygon( &poly, UNDEFINED_LAYER, ARC_LOW_DEF ); addPadPrimitivesToPolygon( &poly, UNDEFINED_LAYER, ARC_LOW_DEF, ERROR_INSIDE );
if( poly.OutlineCount() > 1 ) if( poly.OutlineCount() > 1 )
return false; return false;

View File

@ -186,7 +186,8 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
SHAPE_POLY_SET testPoly; SHAPE_POLY_SET testPoly;
item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0 ); item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0,
ARC_LOW_DEF, ERROR_INSIDE );
testPoly.BooleanIntersection( footprintCourtyard, SHAPE_POLY_SET::PM_FAST ); testPoly.BooleanIntersection( footprintCourtyard, SHAPE_POLY_SET::PM_FAST );
if( testPoly.OutlineCount() ) if( testPoly.OutlineCount() )
@ -242,7 +243,8 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
{ {
SHAPE_POLY_SET testPoly; SHAPE_POLY_SET testPoly;
item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0 ); item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0,
ARC_LOW_DEF, ERROR_INSIDE );
testPoly.BooleanIntersection( *zone->Outline(), SHAPE_POLY_SET::PM_FAST ); testPoly.BooleanIntersection( *zone->Outline(), SHAPE_POLY_SET::PM_FAST );
if( testPoly.OutlineCount() ) if( testPoly.OutlineCount() )

View File

@ -858,7 +858,8 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
} }
// Pad drawing // Pad drawing
COLOR4D color; BOARD_DESIGN_SETTINGS& bds = aPad->GetBoard()->GetDesignSettings();
COLOR4D color;
// Pad hole color is pad-type-specific: the background color for plated holes and the // Pad hole color is pad-type-specific: the background color for plated holes and the
// pad color for NPTHs. Note the extra check for "should be" NPTHs to keep mis-marked // pad color for NPTHs. Note the extra check for "should be" NPTHs to keep mis-marked
@ -947,7 +948,8 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
else else
{ {
SHAPE_POLY_SET polySet; SHAPE_POLY_SET polySet;
aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x ); aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x,
bds.m_MaxError, ERROR_INSIDE );
m_gal->DrawPolygon( polySet ); m_gal->DrawPolygon( polySet );
} }
@ -991,13 +993,14 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
{ {
SHAPE_POLY_SET polySet; SHAPE_POLY_SET polySet;
aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ),
clearance ); clearance,
bds.m_MaxError, ERROR_OUTSIDE );
m_gal->DrawPolygon( polySet ); m_gal->DrawPolygon( polySet );
} }
} }
else if( aPad->GetEffectiveHoleShape() ) else if( aPad->GetEffectiveHoleShape() )
{ {
clearance += aPad->GetBoard()->GetDesignSettings().GetHolePlatingThickness(); clearance += bds.GetHolePlatingThickness();
const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,

View File

@ -311,8 +311,9 @@ public:
* @param ignoreLineWidth = used for edge cut items where the line width is only * @param ignoreLineWidth = used for edge cut items where the line width is only
* for visualization * for visualization
*/ */
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
int aClearanceValue, int aError = ARC_HIGH_DEF, PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override; bool ignoreLineWidth = false ) const override;
virtual wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; virtual wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -116,11 +116,11 @@ public:
* Used in 3D viewer * Used in 3D viewer
* Circles and arcs are approximated by segments * Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon * @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the text * @param aClearance = the clearance around the text
* @param aError = deviation from true arc position to segment approx * @param aError = deviation from true arc position to segment approx
*/ */
void TransformShapeWithClearanceToPolygonSet( void TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, int aClearance,
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError = ARC_HIGH_DEF ) const; int aError, ERROR_LOC aErrorLoc ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape // @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;

View File

@ -756,6 +756,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness ) const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
{ {
int maxError = aBoard->GetDesignSettings().m_MaxError;
PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask; PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
SHAPE_POLY_SET buffer; SHAPE_POLY_SET buffer;
SHAPE_POLY_SET* boardOutline = nullptr; SHAPE_POLY_SET* boardOutline = nullptr;
@ -763,14 +764,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
if( aBoard->GetBoardPolygonOutlines( buffer ) ) if( aBoard->GetBoardPolygonOutlines( buffer ) )
boardOutline = &buffer; boardOutline = &buffer;
// Set the current arc to segment max approx error
int currMaxError = aBoard->GetDesignSettings().m_MaxError;
aBoard->GetDesignSettings().m_MaxError = Millimeter2iu( 0.005 );
// We remove 1nm as we expand both sides of the shapes, so allowing for // We remove 1nm as we expand both sides of the shapes, so allowing for
// a strictly greater than or equal comparison in the shape separation (boolean add) // a strictly greater than or equal comparison in the shape separation (boolean add)
// means that we will end up with separate shapes that then are shrunk // means that we will end up with separate shapes that then are shrunk
int inflate = aMinThickness/2 - 1; int inflate = aMinThickness/2 - 1;
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt ); BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
itemplotter.SetLayerSet( aLayerMask ); itemplotter.SetLayerSet( aLayerMask );
@ -814,9 +811,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
for( MODULE* module : aBoard->Modules() ) for( MODULE* module : aBoard->Modules() )
{ {
// add shapes with their exact mask layer size in initialPolys // add shapes with their exact mask layer size in initialPolys
module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 ); module->TransformPadsShapesWithClearanceToPolygon( initialPolys, layer, 0, maxError,
ERROR_OUTSIDE );
// add shapes inflated by aMinThickness/2 in areas // add shapes inflated by aMinThickness/2 in areas
module->TransformPadsShapesWithClearanceToPolygon( layer, areas, inflate ); module->TransformPadsShapesWithClearanceToPolygon( areas, layer, inflate, maxError,
ERROR_OUTSIDE );
} }
// Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true, // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
@ -846,9 +845,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
continue; continue;
// add shapes with their exact mask layer size in initialPolys // add shapes with their exact mask layer size in initialPolys
via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance ); via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance,
maxError, ERROR_OUTSIDE );
// add shapes inflated by aMinThickness/2 in areas // add shapes inflated by aMinThickness/2 in areas
via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin ); via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin, maxError,
ERROR_OUTSIDE );
} }
} }
@ -870,16 +871,12 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline ); zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline );
} }
int maxError = aBoard->GetDesignSettings().m_MaxError;
int numSegs = GetArcToSegmentCount( inflate, maxError, 360.0 ); int numSegs = GetArcToSegmentCount( inflate, maxError, 360.0 );
// Merge all polygons: After deflating, not merged (not overlapping) polygons // Merge all polygons: After deflating, not merged (not overlapping) polygons
// will have the initial shape (with perhaps small changes due to deflating transform) // will have the initial shape (with perhaps small changes due to deflating transform)
areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
areas.Deflate( inflate, numSegs ); areas.Deflate( inflate, numSegs );
// Restore initial settings:
aBoard->GetDesignSettings().m_MaxError = currMaxError;
} }
#if !NEW_ALGO #if !NEW_ALGO

View File

@ -1541,7 +1541,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
zone->SetDoNotAllowCopperPour( true ); zone->SetDoNotAllowCopperPour( true );
shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF, shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF,
false ); ERROR_INSIDE );
zone->Outline()->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); // the outline is not a single polygon! zone->Outline()->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); // the outline is not a single polygon!
zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE, zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
@ -2094,7 +2094,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader,
zone->SetDoNotAllowCopperPour( true ); zone->SetDoNotAllowCopperPour( true );
shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF, shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF,
false ); ERROR_INSIDE );
zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE, zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
ZONE_CONTAINER::GetDefaultHatchPitch(), true ); ZONE_CONTAINER::GetDefaultHatchPitch(), true );

View File

@ -487,7 +487,8 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
0, rradius, 0, rradius,
aPad->GetChamferRectRatio(), aPad->GetChamferRectRatio(),
doChamfer ? aPad->GetChamferPositions() : 0, doChamfer ? aPad->GetChamferPositions() : 0,
aBoard->GetDesignSettings().m_MaxError ); aBoard->GetDesignSettings().m_MaxError,
ERROR_INSIDE );
SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 ); SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 );
for( int ndx=0; ndx < reportedLayers; ++ndx ) for( int ndx=0; ndx < reportedLayers; ++ndx )

View File

@ -613,31 +613,36 @@ PCB_LAYER_ID PAD_TOOL::explodePad( D_PAD* aPad )
void PAD_TOOL::recombinePad( D_PAD* aPad ) void PAD_TOOL::recombinePad( D_PAD* aPad )
{ {
auto findNext = [&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE* int maxError = board()->GetDesignSettings().m_MaxError;
{
SHAPE_POLY_SET padPoly;
aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0 );
for( BOARD_ITEM* item : board()->GetFirstModule()->GraphicalItems() ) auto findNext =
{ [&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE*
PCB_SHAPE* draw = dynamic_cast<PCB_SHAPE*>( item ); {
SHAPE_POLY_SET padPoly;
aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0, maxError,
ERROR_INSIDE );
if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) ) for( BOARD_ITEM* item : board()->GetFirstModule()->GraphicalItems() )
continue; {
PCB_SHAPE* draw = dynamic_cast<PCB_SHAPE*>( item );
if( draw->GetLayer() != aLayer ) if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) )
continue; continue;
SHAPE_POLY_SET drawPoly; if( draw->GetLayer() != aLayer )
draw->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0 ); continue;
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
if( !drawPoly.IsEmpty() ) SHAPE_POLY_SET drawPoly;
return (FP_SHAPE*) item; draw->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0, maxError,
} ERROR_INSIDE );
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
return nullptr; if( !drawPoly.IsEmpty() )
}; return (FP_SHAPE*) item;
}
return nullptr;
};
BOARD_COMMIT commit( frame() ); BOARD_COMMIT commit( frame() );
PCB_LAYER_ID layer; PCB_LAYER_ID layer;
@ -666,7 +671,8 @@ void PAD_TOOL::recombinePad( D_PAD* aPad )
// to a polygon primitive // to a polygon primitive
SHAPE_POLY_SET existingOutline; SHAPE_POLY_SET existingOutline;
int maxError = board()->GetDesignSettings().m_MaxError; int maxError = board()->GetDesignSettings().m_MaxError;
aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError ); aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError,
ERROR_INSIDE );
aPad->SetAnchorPadShape( PAD_SHAPE_CIRCLE ); aPad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
wxSize minAnnulus( Millimeter2iu( 0.2 ), Millimeter2iu( 0.2 ) ); wxSize minAnnulus( Millimeter2iu( 0.2 ), Millimeter2iu( 0.2 ) );

View File

@ -342,17 +342,18 @@ void TRACKS_CLEANER::deleteTracksInPads()
if( pad->HitTest( track->GetStart() ) && pad->HitTest( track->GetEnd() ) ) if( pad->HitTest( track->GetStart() ) && pad->HitTest( track->GetEnd() ) )
{ {
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
track->TransformShapeWithClearanceToPolygon( poly, track->GetLayer(), 0 ); track->TransformShapeWithClearanceToPolygon( poly, track->GetLayer(), 0,
ARC_HIGH_DEF, ERROR_INSIDE );
poly.BooleanSubtract( *pad->GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( *pad->GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST );
if( poly.IsEmpty() ) if( poly.IsEmpty() )
{ {
std::shared_ptr<CLEANUP_ITEM> item( new CLEANUP_ITEM( CLEANUP_TRACK_IN_PAD ) ); std::shared_ptr<CLEANUP_ITEM> item( new CLEANUP_ITEM( CLEANUP_TRACK_IN_PAD ) );
item->SetItems( track ); item->SetItems( track );
m_itemsList->push_back( item ); m_itemsList->push_back( item );
toRemove.insert( track ); toRemove.insert( track );
} }
} }
} }

View File

@ -577,7 +577,8 @@ void ZONE_FILLER::addKnockout( D_PAD* aPad, PCB_LAYER_ID aLayer, int aGap, SHAPE
if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
{ {
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
aPad->TransformShapeWithClearanceToPolygon( poly, aLayer, aGap, m_maxError ); aPad->TransformShapeWithClearanceToPolygon( poly, aLayer, aGap, m_maxError,
ERROR_OUTSIDE );
// the pad shape in zone can be its convex hull or the shape itself // the pad shape in zone can be its convex hull or the shape itself
if( aPad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL ) if( aPad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
@ -595,7 +596,8 @@ void ZONE_FILLER::addKnockout( D_PAD* aPad, PCB_LAYER_ID aLayer, int aGap, SHAPE
} }
else else
{ {
aPad->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError ); aPad->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
ERROR_OUTSIDE );
} }
} }
@ -613,7 +615,7 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap,
{ {
PCB_SHAPE* shape = (PCB_SHAPE*) aItem; PCB_SHAPE* shape = (PCB_SHAPE*) aItem;
shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError, shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
aIgnoreLineWidth ); ERROR_OUTSIDE, aIgnoreLineWidth );
break; break;
} }
case PCB_TEXT_T: case PCB_TEXT_T:
@ -626,7 +628,7 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap,
{ {
FP_SHAPE* shape = (FP_SHAPE*) aItem; FP_SHAPE* shape = (FP_SHAPE*) aItem;
shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError, shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
aIgnoreLineWidth ); ERROR_OUTSIDE, aIgnoreLineWidth );
break; break;
} }
case PCB_FP_TEXT_T: case PCB_FP_TEXT_T:
@ -790,16 +792,19 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
if( !via->FlashLayer( aLayer ) ) if( !via->FlashLayer( aLayer ) )
{ {
int radius = via->GetDrillValue() / 2 + bds.GetHolePlatingThickness() + gap; int radius = via->GetDrillValue() / 2 + bds.GetHolePlatingThickness() + gap;
TransformCircleToPolygon( aHoles, via->GetPosition(), radius, m_maxError ); TransformCircleToPolygon( aHoles, via->GetPosition(), radius, m_maxError,
ERROR_OUTSIDE );
} }
else else
{ {
via->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError ); via->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError,
ERROR_OUTSIDE );
} }
} }
else else
{ {
track->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError ); track->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError,
ERROR_OUTSIDE );
} }
} }
} }
@ -872,7 +877,9 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
{ {
// 6.0 uses filled areas with clearance // 6.0 uses filled areas with clearance
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap ); aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap,
m_maxError,
ERROR_OUTSIDE );
aHoles.Append( poly ); aHoles.Append( poly );
} }
} }
@ -1448,7 +1455,8 @@ void ZONE_FILLER::addHatchFillTypeOnZone( const ZONE_CONTAINER* aZone, PCB_LAYER
int r = std::max( min_apron_radius, int r = std::max( min_apron_radius,
via->GetDrillValue() / 2 + outline_margin ); via->GetDrillValue() / 2 + outline_margin );
TransformCircleToPolygon( aprons, via->GetPosition(), r, ARC_HIGH_DEF ); TransformCircleToPolygon( aprons, via->GetPosition(), r, ARC_HIGH_DEF,
ERROR_OUTSIDE );
} }
} }
} }
@ -1474,7 +1482,7 @@ void ZONE_FILLER::addHatchFillTypeOnZone( const ZONE_CONTAINER* aZone, PCB_LAYER
clearance = std::max( 0, clearance - linethickness / 2 ); clearance = std::max( 0, clearance - linethickness / 2 );
pad->TransformShapeWithClearanceToPolygon( aprons, aLayer, clearance, pad->TransformShapeWithClearanceToPolygon( aprons, aLayer, clearance,
ARC_HIGH_DEF ); ARC_HIGH_DEF, ERROR_OUTSIDE );
} }
} }
} }

View File

@ -45,7 +45,8 @@ void process( const BOARD_CONNECTED_ITEM* item, int net )
SHAPE_POLY_SET pset; SHAPE_POLY_SET pset;
item->TransformShapeWithClearanceToPolygon( pset, UNDEFINED_LAYER, 1, ARC_HIGH_DEF ); item->TransformShapeWithClearanceToPolygon( pset, UNDEFINED_LAYER, 1, ARC_HIGH_DEF,
ERROR_OUTSIDE );
SHAPE_FILE_IO shapeIo; // default = stdout SHAPE_FILE_IO shapeIo; // default = stdout
shapeIo.Write( &pset ); shapeIo.Write( &pset );