mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-15 10:43:15 +02:00
Give Clipper1 a Viking funeral
Clears out the last spot where we were only using Clipper1 (how'd I miss that?) and remove all calls to the Clipper1 structures
This commit is contained in:
parent
fd137279c8
commit
e9bc8cfe9d
@ -947,9 +947,7 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
|||||||
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
||||||
m_board->GetDesignSettings().m_MaxError,
|
m_board->GetDesignSettings().m_MaxError,
|
||||||
chainingEpsilon );
|
chainingEpsilon );
|
||||||
|
m_board_poly.Simplify();
|
||||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
|
||||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
|
|
||||||
if( !success && aErrorMsg )
|
if( !success && aErrorMsg )
|
||||||
{
|
{
|
||||||
|
@ -650,7 +650,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
|||||||
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
|
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
|
|
||||||
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyList.Simplify();
|
||||||
|
|
||||||
if( margin != 0 )
|
if( margin != 0 )
|
||||||
{
|
{
|
||||||
@ -700,7 +700,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
|||||||
// Some polygons can be a bit complex (especially when coming from a
|
// Some polygons can be a bit complex (especially when coming from a
|
||||||
// picture ot a text converted to a polygon
|
// picture ot a text converted to a polygon
|
||||||
// So call Simplify before calling ConvertPolygonToTriangles, just in case.
|
// So call Simplify before calling ConvertPolygonToTriangles, just in case.
|
||||||
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyList.Simplify();
|
||||||
|
|
||||||
if( polyList.IsEmpty() ) // Just for caution
|
if( polyList.IsEmpty() ) // Just for caution
|
||||||
break;
|
break;
|
||||||
|
@ -780,10 +780,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
// End Build Copper layers
|
// End Build Copper layers
|
||||||
|
|
||||||
// This will make a union of all added contours
|
// This will make a union of all added contours
|
||||||
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_TH_ODPolys.Simplify();
|
||||||
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_NPTH_ODPolys.Simplify();
|
||||||
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_viaTH_ODPolys.Simplify();
|
||||||
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_viaAnnuliPolys.Simplify();
|
||||||
|
|
||||||
// Build Tech layers
|
// Build Tech layers
|
||||||
// Based on:
|
// Based on:
|
||||||
@ -1022,7 +1022,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This will make a union of all added contours
|
// This will make a union of all added contours
|
||||||
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
|
layerPoly->Simplify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End Build Tech layers
|
// End Build Tech layers
|
||||||
@ -1061,14 +1061,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
// TRIM PLATED COPPER TO SOLDERMASK
|
// TRIM PLATED COPPER TO SOLDERMASK
|
||||||
if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
|
if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
|
||||||
{
|
{
|
||||||
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
|
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
|
if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
|
||||||
{
|
{
|
||||||
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
|
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtract plated copper from unplated copper
|
// Subtract plated copper from unplated copper
|
||||||
@ -1077,15 +1075,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
|
|
||||||
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
|
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
|
||||||
{
|
{
|
||||||
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
|
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys );
|
||||||
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys );
|
||||||
hasF_Cu = true;
|
hasF_Cu = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
|
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
|
||||||
{
|
{
|
||||||
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
|
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys );
|
||||||
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys );
|
||||||
hasB_Cu = true;
|
hasB_Cu = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,10 +1094,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
|
if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
|
||||||
m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
|
m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
|
||||||
|
|
||||||
m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_frontPlatedPadAndGraphicPolys->Simplify();
|
||||||
m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_backPlatedPadAndGraphicPolys->Simplify();
|
||||||
m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_frontPlatedCopperPolys->Simplify();
|
||||||
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_backPlatedCopperPolys->Simplify();
|
||||||
|
|
||||||
// ADD PLATED PADS
|
// ADD PLATED PADS
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
@ -1168,7 +1166,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
{
|
{
|
||||||
// This will make a union of all added contours
|
// This will make a union of all added contours
|
||||||
layerPoly->second->ClearArcs();
|
layerPoly->second->ClearArcs();
|
||||||
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
|
layerPoly->second->Simplify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,12 +1191,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
{
|
{
|
||||||
// found
|
// found
|
||||||
SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
|
SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
|
||||||
polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyLayer->Simplify();
|
||||||
|
|
||||||
wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
|
wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
|
||||||
|
|
||||||
polyLayer = m_layerHoleIdPolys[layer];
|
polyLayer = m_layerHoleIdPolys[layer];
|
||||||
polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyLayer->Simplify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,13 +476,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||||||
m_antiBoardPolys.Append( VECTOR2I( -INT_MAX/2, INT_MAX/2 ) );
|
m_antiBoardPolys.Append( VECTOR2I( -INT_MAX/2, INT_MAX/2 ) );
|
||||||
m_antiBoardPolys.Outline( 0 ).SetClosed( true );
|
m_antiBoardPolys.Outline( 0 ).SetClosed( true );
|
||||||
|
|
||||||
m_antiBoardPolys.BooleanSubtract( m_boardAdapter.GetBoardPoly(),
|
m_antiBoardPolys.BooleanSubtract( m_boardAdapter.GetBoardPoly() );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
m_antiBoard = createBoard( m_antiBoardPolys );
|
m_antiBoard = createBoard( m_antiBoardPolys );
|
||||||
|
|
||||||
SHAPE_POLY_SET board_poly_with_holes = m_boardAdapter.GetBoardPoly().CloneDropTriangulation();
|
SHAPE_POLY_SET board_poly_with_holes = m_boardAdapter.GetBoardPoly().CloneDropTriangulation();
|
||||||
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
|
||||||
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
|
||||||
|
|
||||||
m_boardWithHoles = createBoard( board_poly_with_holes );
|
m_boardWithHoles = createBoard( board_poly_with_holes );
|
||||||
|
|
||||||
@ -495,8 +494,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||||||
|
|
||||||
SHAPE_POLY_SET outerPolyTHT = m_boardAdapter.GetTH_ODPolys().CloneDropTriangulation();
|
SHAPE_POLY_SET outerPolyTHT = m_boardAdapter.GetTH_ODPolys().CloneDropTriangulation();
|
||||||
|
|
||||||
outerPolyTHT.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
|
outerPolyTHT.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
|
|
||||||
m_outerThroughHoles = generateHoles( m_boardAdapter.GetTH_ODs().GetList(), outerPolyTHT,
|
m_outerThroughHoles = generateHoles( m_boardAdapter.GetTH_ODs().GetList(), outerPolyTHT,
|
||||||
1.0f, 0.0f, false, &m_boardAdapter.GetTH_IDs() );
|
1.0f, 0.0f, false, &m_boardAdapter.GetTH_IDs() );
|
||||||
@ -575,29 +573,24 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||||||
|
|
||||||
if( LSET::PhysicalLayersMask().test( layer ) )
|
if( LSET::PhysicalLayersMask().test( layer ) )
|
||||||
{
|
{
|
||||||
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
|
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( layer != B_Mask && layer != F_Mask )
|
if( layer != B_Mask && layer != F_Mask )
|
||||||
{
|
{
|
||||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
|
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
|
||||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
|
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
|
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
|
||||||
{
|
{
|
||||||
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
|
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
|
||||||
{
|
{
|
||||||
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
|
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
|
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
|
||||||
{
|
{
|
||||||
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
|
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,9 +613,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||||||
if( frontPlatedPadAndGraphicPolys )
|
if( frontPlatedPadAndGraphicPolys )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
||||||
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
|
||||||
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
|
||||||
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
|
||||||
|
|
||||||
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, F_Cu );
|
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, F_Cu );
|
||||||
|
|
||||||
@ -634,9 +627,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||||||
if( backPlatedPadAndGraphicPolys )
|
if( backPlatedPadAndGraphicPolys )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
||||||
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
|
||||||
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
|
||||||
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
|
||||||
|
|
||||||
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, B_Cu );
|
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, B_Cu );
|
||||||
|
|
||||||
@ -839,9 +832,9 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subtract the holes
|
// Subtract the holes
|
||||||
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
|
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly );
|
||||||
|
|
||||||
tht_outer_holes_poly.BooleanSubtract( m_antiBoardPolys, SHAPE_POLY_SET::PM_FAST );
|
tht_outer_holes_poly.BooleanSubtract( m_antiBoardPolys );
|
||||||
|
|
||||||
CONTAINER_2D holesContainer;
|
CONTAINER_2D holesContainer;
|
||||||
|
|
||||||
|
@ -415,8 +415,8 @@ void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarn
|
|||||||
|
|
||||||
buildBoardBoundingBoxPoly( m_boardAdapter.GetBoard(), antiboardPoly );
|
buildBoardBoundingBoxPoly( m_boardAdapter.GetBoard(), antiboardPoly );
|
||||||
|
|
||||||
antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
|
antiboardPoly.BooleanSubtract( boardPolyCopy );
|
||||||
antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
antiboardPoly.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
|
for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
|
||||||
{
|
{
|
||||||
@ -427,7 +427,7 @@ void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarn
|
|||||||
|
|
||||||
m_antioutlineBoard2dObjects->BuildBVH();
|
m_antioutlineBoard2dObjects->BuildBVH();
|
||||||
|
|
||||||
boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
|
boardPolyCopy.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < outlineCount; ii++ )
|
for( int ii = 0; ii < outlineCount; ii++ )
|
||||||
{
|
{
|
||||||
|
@ -612,10 +612,9 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
|
|||||||
|
|
||||||
subBlockPoly.AddOutline( sb );
|
subBlockPoly.AddOutline( sb );
|
||||||
|
|
||||||
// We need here a strictly simple polygon with outlines and holes
|
// We need here a simple polygon with outlines and holes
|
||||||
SHAPE_POLY_SET solution;
|
SHAPE_POLY_SET solution;
|
||||||
solution.BooleanIntersection( aMainPath, subBlockPoly,
|
solution.BooleanIntersection( aMainPath, subBlockPoly );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
|
|
||||||
OUTERS_AND_HOLES outersAndHoles;
|
OUTERS_AND_HOLES outersAndHoles;
|
||||||
|
|
||||||
@ -659,68 +658,3 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
|
|||||||
topToBottom += topToBottom_inc;
|
topToBottom += topToBottom_inc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void polygon_Convert( const ClipperLib::Path& aPath, SEGMENTS& aOutSegment,
|
|
||||||
float aBiuTo3dUnitsScale )
|
|
||||||
{
|
|
||||||
aOutSegment.resize( aPath.size() );
|
|
||||||
|
|
||||||
for( unsigned i = 0; i < aPath.size(); i++ )
|
|
||||||
{
|
|
||||||
aOutSegment[i].m_Start = SFVEC2F(
|
|
||||||
(float) aPath[i].X * aBiuTo3dUnitsScale, (float) -aPath[i].Y * aBiuTo3dUnitsScale );
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int j = aOutSegment.size() - 1;
|
|
||||||
|
|
||||||
for( i = 0; i < aOutSegment.size(); j = i++ )
|
|
||||||
{
|
|
||||||
// Calculate constants for each segment
|
|
||||||
aOutSegment[i].m_inv_JY_minus_IY =
|
|
||||||
1.0f / ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y );
|
|
||||||
aOutSegment[i].m_JX_minus_IX = ( aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Polygon2d_TestModule()
|
|
||||||
{
|
|
||||||
// "This structure contains a sequence of IntPoint vertices defining a single contour"
|
|
||||||
ClipperLib::Path aPath;
|
|
||||||
|
|
||||||
SEGMENTS aSegments;
|
|
||||||
|
|
||||||
aPath.resize( 4 );
|
|
||||||
|
|
||||||
aPath[0] = ClipperLib::IntPoint( -2, -2 );
|
|
||||||
aPath[1] = ClipperLib::IntPoint( 2, -2 );
|
|
||||||
aPath[2] = ClipperLib::IntPoint( 2, 2 );
|
|
||||||
aPath[3] = ClipperLib::IntPoint( -2, 2 );
|
|
||||||
|
|
||||||
// It must be an outer polygon
|
|
||||||
wxASSERT( ClipperLib::Orientation( aPath ) );
|
|
||||||
|
|
||||||
polygon_Convert( aPath, aSegments, 1.0f );
|
|
||||||
|
|
||||||
wxASSERT( aPath.size() == aSegments.size() );
|
|
||||||
|
|
||||||
wxASSERT( aSegments[0].m_Start == SFVEC2F( -2.0f, 2.0f ) );
|
|
||||||
wxASSERT( aSegments[1].m_Start == SFVEC2F( 2.0f, 2.0f ) );
|
|
||||||
wxASSERT( aSegments[2].m_Start == SFVEC2F( 2.0f, -2.0f ) );
|
|
||||||
wxASSERT( aSegments[3].m_Start == SFVEC2F( -2.0f, -2.0f ) );
|
|
||||||
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 0.0f, 0.0f ) ) );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, -1.9f ) ) );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, 1.9f ) ) );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, 1.9f ) ) );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, -1.9f ) ) );
|
|
||||||
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, -2.0f ) ) == false );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, 2.0f ) ) == false );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, 2.0f ) ) == false );
|
|
||||||
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, -2.0f ) ) == false );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -152,6 +152,5 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
|
|||||||
float aBiuTo3dUnitsScale, float aDivFactor,
|
float aBiuTo3dUnitsScale, float aDivFactor,
|
||||||
const BOARD_ITEM& aBoardItem, int aPolyIndex );
|
const BOARD_ITEM& aBoardItem, int aPolyIndex );
|
||||||
|
|
||||||
void Polygon2d_TestModule();
|
|
||||||
|
|
||||||
#endif // _CPOLYGON2D_H_
|
#endif // _CPOLYGON2D_H_
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "../accelerators/container_2d.h"
|
#include "../accelerators/container_2d.h"
|
||||||
#include <geometry/shape_line_chain.h>
|
#include <geometry/shape_line_chain.h>
|
||||||
#include <geometry/shape_poly_set.h>
|
#include <geometry/shape_poly_set.h>
|
||||||
#include <clipper.hpp>
|
|
||||||
|
|
||||||
class TRIANGLE_2D : public OBJECT_2D
|
class TRIANGLE_2D : public OBJECT_2D
|
||||||
{
|
{
|
||||||
|
@ -524,15 +524,15 @@ void BITMAPCONV_INFO::createOutputData( BMP2CMP_MOD_LAYER aModLayer )
|
|||||||
// at the end of a group of a positive path and its negative children, fill.
|
// at the end of a group of a positive path and its negative children, fill.
|
||||||
if( paths->next == nullptr || paths->next->sign == '+' )
|
if( paths->next == nullptr || paths->next->sign == '+' )
|
||||||
{
|
{
|
||||||
polyset_areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polyset_areas.Simplify();
|
||||||
polyset_holes.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polyset_holes.Simplify();
|
||||||
polyset_areas.BooleanSubtract( polyset_holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polyset_areas.BooleanSubtract( polyset_holes );
|
||||||
|
|
||||||
// Ensure there are no self intersecting polygons
|
// Ensure there are no self intersecting polygons
|
||||||
if( polyset_areas.NormalizeAreaOutlines() )
|
if( polyset_areas.NormalizeAreaOutlines() )
|
||||||
{
|
{
|
||||||
// Convert polygon with holes to a unique polygon
|
// Convert polygon with holes to a unique polygon
|
||||||
polyset_areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polyset_areas.Fracture();
|
||||||
|
|
||||||
// Output current resulting polygon(s)
|
// Output current resulting polygon(s)
|
||||||
for( int ii = 0; ii < polyset_areas.OutlineCount(); ii++ )
|
for( int ii = 0; ii < polyset_areas.OutlineCount(); ii++ )
|
||||||
|
@ -98,7 +98,6 @@ static const wxChar AllowManualCanvasScale[] = wxT( "AllowManualCanvasScale" );
|
|||||||
static const wxChar UpdateUIEventInterval[] = wxT( "UpdateUIEventInterval" );
|
static const wxChar UpdateUIEventInterval[] = wxT( "UpdateUIEventInterval" );
|
||||||
static const wxChar V3DRT_BevelHeight_um[] = wxT( "V3DRT_BevelHeight_um" );
|
static const wxChar V3DRT_BevelHeight_um[] = wxT( "V3DRT_BevelHeight_um" );
|
||||||
static const wxChar V3DRT_BevelExtentFactor[] = wxT( "V3DRT_BevelExtentFactor" );
|
static const wxChar V3DRT_BevelExtentFactor[] = wxT( "V3DRT_BevelExtentFactor" );
|
||||||
static const wxChar UseClipper2[] = wxT( "UseClipper2" );
|
|
||||||
static const wxChar EnableDesignBlocks[] = wxT( "EnableDesignBlocks" );
|
static const wxChar EnableDesignBlocks[] = wxT( "EnableDesignBlocks" );
|
||||||
static const wxChar EnableGenerators[] = wxT( "EnableGenerators" );
|
static const wxChar EnableGenerators[] = wxT( "EnableGenerators" );
|
||||||
static const wxChar EnableGit[] = wxT( "EnableGit" );
|
static const wxChar EnableGit[] = wxT( "EnableGit" );
|
||||||
@ -263,7 +262,6 @@ ADVANCED_CFG::ADVANCED_CFG()
|
|||||||
m_3DRT_BevelHeight_um = 30;
|
m_3DRT_BevelHeight_um = 30;
|
||||||
m_3DRT_BevelExtentFactor = 1.0 / 16.0;
|
m_3DRT_BevelExtentFactor = 1.0 / 16.0;
|
||||||
|
|
||||||
m_UseClipper2 = true;
|
|
||||||
m_EnableAPILogging = false;
|
m_EnableAPILogging = false;
|
||||||
|
|
||||||
m_Use3DConnexionDriver = true;
|
m_Use3DConnexionDriver = true;
|
||||||
@ -464,9 +462,6 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
|||||||
m_3DRT_BevelExtentFactor, 0.0, 100.0,
|
m_3DRT_BevelExtentFactor, 0.0, 100.0,
|
||||||
AC_GROUPS::V3D_RayTracing ) );
|
AC_GROUPS::V3D_RayTracing ) );
|
||||||
|
|
||||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::UseClipper2,
|
|
||||||
&m_UseClipper2, m_UseClipper2 ) );
|
|
||||||
|
|
||||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Use3DConnexionDriver,
|
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Use3DConnexionDriver,
|
||||||
&m_Use3DConnexionDriver, m_Use3DConnexionDriver ) );
|
&m_Use3DConnexionDriver, m_Use3DConnexionDriver ) );
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ void CALLBACK_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal
|
|||||||
KIFONT::OUTLINE_GLYPH glyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
|
KIFONT::OUTLINE_GLYPH glyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
|
||||||
|
|
||||||
if( glyph.HasHoles() )
|
if( glyph.HasHoles() )
|
||||||
glyph.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
glyph.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < glyph.OutlineCount(); ++ii )
|
for( int ii = 0; ii < glyph.OutlineCount(); ++ii )
|
||||||
m_outlineCallback( glyph.Outline( ii ) );
|
m_outlineCallback( glyph.Outline( ii ) );
|
||||||
|
@ -1022,9 +1022,9 @@ void EDA_DRAW_FRAME::FocusOnLocation( const VECTOR2I& aPos )
|
|||||||
{
|
{
|
||||||
GetCanvas()->GetView()->SetCenter( aPos, dialogScreenRects );
|
GetCanvas()->GetView()->SetCenter( aPos, dialogScreenRects );
|
||||||
}
|
}
|
||||||
catch( const ClipperLib::clipperException& e )
|
catch( const Clipper2Lib::Clipper2Exception& e )
|
||||||
{
|
{
|
||||||
wxFAIL_MSG( wxString::Format( wxT( "Clipper exception occurred centering object: %s" ),
|
wxFAIL_MSG( wxString::Format( wxT( "Clipper2 exception occurred centering object: %s" ),
|
||||||
e.what() ) );
|
e.what() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,9 +250,9 @@ static void convertPolygon( std::list<std::unique_ptr<IMPORTED_SHAPE>>& aShapes,
|
|||||||
upscaledPaths.push_back( lc );
|
upscaledPaths.push_back( lc );
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAPE_POLY_SET result = SHAPE_POLY_SET::BuildPolysetFromOrientedPaths(
|
SHAPE_POLY_SET result;
|
||||||
upscaledPaths, false, aFillRule == GRAPHICS_IMPORTER::PF_EVEN_ODD );
|
result.BuildPolysetFromOrientedPaths( upscaledPaths, aFillRule == GRAPHICS_IMPORTER::PF_EVEN_ODD );
|
||||||
result.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
result.Fracture();
|
||||||
|
|
||||||
for( int outl = 0; outl < result.OutlineCount(); outl++ )
|
for( int outl = 0; outl < result.OutlineCount(); outl++ )
|
||||||
{
|
{
|
||||||
|
@ -574,8 +574,8 @@ void DXF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
|
|||||||
// polygon and its thick outline
|
// polygon and its thick outline
|
||||||
|
|
||||||
// create the outline which contains thick outline:
|
// create the outline which contains thick outline:
|
||||||
bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
|
bufferPolybase.BooleanAdd( bufferOutline );
|
||||||
bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
|
bufferPolybase.Fracture();
|
||||||
|
|
||||||
if( bufferPolybase.OutlineCount() < 1 ) // should not happen
|
if( bufferPolybase.OutlineCount() < 1 ) // should not happen
|
||||||
return;
|
return;
|
||||||
|
@ -622,7 +622,7 @@ void VIEW::SetCenter( const VECTOR2D& aCenter, const std::vector<BOX2D>& obscuri
|
|||||||
for( const BOX2D& obscuringScreenRect : obscuringScreenRects )
|
for( const BOX2D& obscuringScreenRect : obscuringScreenRects )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET obscuringPoly( obscuringScreenRect );
|
SHAPE_POLY_SET obscuringPoly( obscuringScreenRect );
|
||||||
unobscuredPoly.BooleanSubtract( obscuringPoly, SHAPE_POLY_SET::PM_FAST );
|
unobscuredPoly.BooleanSubtract( obscuringPoly );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -91,7 +91,7 @@ std::unordered_map<uint32_t, SHAPE_POLY_SET> ConvertImageToPolygons( wxImage im
|
|||||||
|
|
||||||
for( auto& [color, polySet] : colorPolys )
|
for( auto& [color, polySet] : colorPolys )
|
||||||
{
|
{
|
||||||
polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polySet.Simplify();
|
||||||
|
|
||||||
for( int i = 0; i < polySet.OutlineCount(); i++ )
|
for( int i = 0; i < polySet.OutlineCount(); i++ )
|
||||||
{
|
{
|
||||||
@ -114,7 +114,7 @@ void ConvertImageToLibShapes( LIB_SYMBOL* aSymbol, int unit, wxImage img, VECTOR
|
|||||||
|
|
||||||
for( auto& [color, polySet] : colorPolys )
|
for( auto& [color, polySet] : colorPolys )
|
||||||
{
|
{
|
||||||
polySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polySet.Fracture();
|
||||||
|
|
||||||
for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
|
for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
|
||||||
{
|
{
|
||||||
|
@ -664,8 +664,8 @@ static void knockoutText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2
|
|||||||
finalPoly.Append( bbox.GetRight(), bbox.GetBottom() );
|
finalPoly.Append( bbox.GetRight(), bbox.GetBottom() );
|
||||||
finalPoly.Append( bbox.GetLeft(), bbox.GetBottom() );
|
finalPoly.Append( bbox.GetLeft(), bbox.GetBottom() );
|
||||||
|
|
||||||
finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
|
finalPoly.BooleanSubtract( knockouts );
|
||||||
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
finalPoly.Fracture();
|
||||||
|
|
||||||
aGal.SetIsStroke( false );
|
aGal.SetIsStroke( false );
|
||||||
aGal.SetIsFill( true );
|
aGal.SetIsFill( true );
|
||||||
|
@ -124,19 +124,19 @@ SHAPE_POLY_SET* APERTURE_MACRO::GetApertureMacroShape( const GERBER_DRAW_ITEM* a
|
|||||||
|
|
||||||
if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
|
if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
|
||||||
{
|
{
|
||||||
m_shape.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
|
m_shape.BooleanSubtract( holeBuffer );
|
||||||
holeBuffer.RemoveAllContours();
|
holeBuffer.RemoveAllContours();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge and cleanup basic shape polygons
|
// Merge and cleanup basic shape polygons
|
||||||
m_shape.Simplify( SHAPE_POLY_SET::PM_FAST );
|
m_shape.Simplify();
|
||||||
|
|
||||||
// A hole can be is defined inside a polygon, or the polygons themselve can create
|
// A hole can be is defined inside a polygon, or the polygons themselve can create
|
||||||
// a hole when merged, so we must fracture the polygon to be able to drawn it
|
// a hole when merged, so we must fracture the polygon to be able to drawn it
|
||||||
// (i.e link holes by overlapping edges)
|
// (i.e link holes by overlapping edges)
|
||||||
m_shape.Fracture( SHAPE_POLY_SET::PM_FAST );
|
m_shape.Fracture();
|
||||||
|
|
||||||
// Move m_shape to the actual draw position:
|
// Move m_shape to the actual draw position:
|
||||||
for( int icnt = 0; icnt < m_shape.OutlineCount(); icnt++ )
|
for( int icnt = 0; icnt < m_shape.OutlineCount(); icnt++ )
|
||||||
|
@ -448,6 +448,6 @@ static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, APERTURE_DEF_HOLETYPE aH
|
|||||||
holeBuffer.Append( VECTOR2I( currpos ) ); // close hole
|
holeBuffer.Append( VECTOR2I( currpos ) ); // close hole
|
||||||
}
|
}
|
||||||
|
|
||||||
aPolygon->BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
|
aPolygon->BooleanSubtract( holeBuffer );
|
||||||
aPolygon->Fracture( SHAPE_POLY_SET::PM_FAST );
|
aPolygon->Fracture();
|
||||||
}
|
}
|
||||||
|
@ -574,7 +574,7 @@ void GBR_TO_PCB_EXPORTER::writePcbPolygon( const SHAPE_POLY_SET& aPolys, int aLa
|
|||||||
void GBR_TO_PCB_EXPORTER::writePcbZoneItem( const GERBER_DRAW_ITEM* aGbrItem, int aLayer )
|
void GBR_TO_PCB_EXPORTER::writePcbZoneItem( const GERBER_DRAW_ITEM* aGbrItem, int aLayer )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET polys = aGbrItem->m_ShapeAsPolygon.CloneDropTriangulation();
|
SHAPE_POLY_SET polys = aGbrItem->m_ShapeAsPolygon.CloneDropTriangulation();
|
||||||
polys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polys.Simplify();
|
||||||
|
|
||||||
if( polys.OutlineCount() == 0 )
|
if( polys.OutlineCount() == 0 )
|
||||||
return;
|
return;
|
||||||
|
@ -428,15 +428,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
double m_3DRT_BevelExtentFactor;
|
double m_3DRT_BevelExtentFactor;
|
||||||
|
|
||||||
/**
|
|
||||||
* Use Clipper2 instead of Clipper1.
|
|
||||||
*
|
|
||||||
* Setting name: "UseClipper2"
|
|
||||||
* Valid values: 0 or 1
|
|
||||||
* Default value: 1
|
|
||||||
*/
|
|
||||||
bool m_UseClipper2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the 3DConnexion Driver.
|
* Use the 3DConnexion Driver.
|
||||||
*
|
*
|
||||||
|
@ -299,7 +299,7 @@ public:
|
|||||||
{
|
{
|
||||||
if( m_poly.HoleCount( ii ) )
|
if( m_poly.HoleCount( ii ) )
|
||||||
{
|
{
|
||||||
m_poly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
m_poly.Fracture();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,6 @@ add_library( kimath STATIC
|
|||||||
|
|
||||||
target_link_libraries( kimath
|
target_link_libraries( kimath
|
||||||
core
|
core
|
||||||
clipper
|
|
||||||
clipper2
|
clipper2
|
||||||
othermath
|
othermath
|
||||||
rtree
|
rtree
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <advanced_config.h>
|
#include <advanced_config.h>
|
||||||
#include <clipper.hpp>
|
|
||||||
#include <geometry/shape_line_chain.h>
|
#include <geometry/shape_line_chain.h>
|
||||||
#include <geometry/shape_poly_set.h>
|
#include <geometry/shape_poly_set.h>
|
||||||
#include <geometry/vertex_set.h>
|
#include <geometry/vertex_set.h>
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#define __SHAPE_LINE_CHAIN
|
#define __SHAPE_LINE_CHAIN
|
||||||
|
|
||||||
|
|
||||||
#include <clipper.hpp>
|
|
||||||
#include <clipper2/clipper.h>
|
#include <clipper2/clipper.h>
|
||||||
#include <geometry/seg.h>
|
#include <geometry/seg.h>
|
||||||
#include <geometry/shape.h>
|
#include <geometry/shape.h>
|
||||||
@ -37,7 +36,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable
|
* Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable
|
||||||
* after an operation with ClipperLib
|
* after an operation with Clipper2Lib
|
||||||
*/
|
*/
|
||||||
struct CLIPPER_Z_VALUE
|
struct CLIPPER_Z_VALUE
|
||||||
{
|
{
|
||||||
@ -176,10 +175,6 @@ public:
|
|||||||
|
|
||||||
SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false );
|
SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false );
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
|
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer );
|
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
|
SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer );
|
const std::vector<SHAPE_ARC>& aArcBuffer );
|
||||||
@ -920,13 +915,6 @@ protected:
|
|||||||
return m_shapes[aSegment].second;
|
return m_shapes[aSegment].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Clipper path from the SHAPE_LINE_CHAIN in a given orientation
|
|
||||||
*/
|
|
||||||
ClipperLib::Path convertToClipper( bool aRequiredOrientation,
|
|
||||||
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
std::vector<SHAPE_ARC>& aArcBuffer ) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Clipper2 path from the SHAPE_LINE_CHAIN in a given orientation
|
* Create a new Clipper2 path from the SHAPE_LINE_CHAIN in a given orientation
|
||||||
*/
|
*/
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include <stdlib.h> // for abs
|
#include <stdlib.h> // for abs
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <clipper.hpp> // for ClipType, PolyTree (ptr only)
|
|
||||||
#include <clipper2/clipper.h>
|
#include <clipper2/clipper.h>
|
||||||
#include <core/mirror.h> // for FLIP_DIRECTION
|
#include <core/mirror.h> // for FLIP_DIRECTION
|
||||||
#include <geometry/corner_strategy.h>
|
#include <geometry/corner_strategy.h>
|
||||||
@ -986,55 +985,30 @@ public:
|
|||||||
return CIterateSegments( aOutline, aOutline, true );
|
return CIterateSegments( aOutline, aOutline, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Operations on polygons use a \a aFastMode param
|
|
||||||
* if aFastMode is #PM_FAST (true) the result can be a weak polygon
|
|
||||||
* if aFastMode is #PM_STRICTLY_SIMPLE (false) (default) the result is (theoretically) a
|
|
||||||
* strictly simple polygon, but calculations can be really significantly time consuming
|
|
||||||
* Most of time #PM_FAST is preferable.
|
|
||||||
* #PM_STRICTLY_SIMPLE can be used in critical cases (Gerber output for instance)
|
|
||||||
*/
|
|
||||||
enum POLYGON_MODE
|
|
||||||
{
|
|
||||||
PM_FAST = true,
|
|
||||||
PM_STRICTLY_SIMPLE = false
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Perform boolean polyset union
|
/// Perform boolean polyset union
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanAdd( const SHAPE_POLY_SET& b );
|
||||||
void BooleanAdd( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset difference
|
/// Perform boolean polyset difference
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanSubtract( const SHAPE_POLY_SET& b );
|
||||||
void BooleanSubtract( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset intersection
|
/// Perform boolean polyset intersection
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanIntersection( const SHAPE_POLY_SET& b );
|
||||||
void BooleanIntersection( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset exclusive or
|
/// Perform boolean polyset exclusive or
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanXor( const SHAPE_POLY_SET& b );
|
||||||
void BooleanXor( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset union between a and b, store the result in it self
|
/// Perform boolean polyset union between a and b, store the result in it self
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
|
||||||
void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
|
||||||
POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset difference between a and b, store the result in it self
|
/// Perform boolean polyset difference between a and b, store the result in it self
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
|
||||||
void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
|
||||||
POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset intersection between a and b, store the result in it self
|
/// Perform boolean polyset intersection between a and b, store the result in it self
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
|
||||||
void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
|
||||||
POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Perform boolean polyset exclusive or between a and b, store the result in it self
|
/// Perform boolean polyset exclusive or between a and b, store the result in it self
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
|
||||||
void BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
|
||||||
POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract all contours from this polygon set, then recreate polygons with holes.
|
* Extract all contours from this polygon set, then recreate polygons with holes.
|
||||||
@ -1085,20 +1059,17 @@ public:
|
|||||||
* Perform outline inflation/deflation, using round corners.
|
* Perform outline inflation/deflation, using round corners.
|
||||||
*
|
*
|
||||||
* Polygons can have holes and/or linked holes with main outlines. The resulting
|
* Polygons can have holes and/or linked holes with main outlines. The resulting
|
||||||
* polygons are also polygons with linked holes to main outlines. For \a aFastMode
|
* polygons are also polygons with linked holes to main outlines.
|
||||||
* meaning, see function booleanOp .
|
|
||||||
*/
|
*/
|
||||||
void InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError,
|
void InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError );
|
||||||
POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Convert a set of polygons with holes to a single outline with "slits"/"fractures"
|
/// Convert a set of polygons with holes to a single outline with "slits"/"fractures"
|
||||||
/// connecting the outer ring to the inner holes
|
/// connecting the outer ring to the inner holes
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void Fracture();
|
||||||
void Fracture( POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/// Convert a single outline slitted ("fractured") polygon into a set ouf outlines
|
/// Convert a single outline slitted ("fractured") polygon into a set ouf outlines
|
||||||
/// with holes.
|
/// with holes.
|
||||||
void Unfracture( POLYGON_MODE aFastMode );
|
void Unfracture();
|
||||||
|
|
||||||
/// Return true if the polygon set has any holes.
|
/// Return true if the polygon set has any holes.
|
||||||
bool HasHoles() const;
|
bool HasHoles() const;
|
||||||
@ -1108,8 +1079,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/// Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
|
/// Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
|
||||||
/// For \a aFastMode meaning, see function booleanOp
|
void Simplify();
|
||||||
void Simplify( POLYGON_MODE aFastMode );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplifies the lines in the polyset. This checks intermediate points to see if they are
|
* Simplifies the lines in the polyset. This checks intermediate points to see if they are
|
||||||
@ -1464,11 +1434,9 @@ public:
|
|||||||
* Build a SHAPE_POLY_SET from a bunch of outlines in provided in random order.
|
* Build a SHAPE_POLY_SET from a bunch of outlines in provided in random order.
|
||||||
*
|
*
|
||||||
* @param aPath set of closed outlines forming the polygon. Positive orientation = outline, negative = hole
|
* @param aPath set of closed outlines forming the polygon. Positive orientation = outline, negative = hole
|
||||||
* @param aReverseOrientation inverts the sign of the orientation of aPaths (so negative = outline)
|
|
||||||
* @param aEvenOdd forces the even-off fill rule (default is non zero)
|
* @param aEvenOdd forces the even-off fill rule (default is non zero)
|
||||||
* @return the constructed poly set
|
|
||||||
*/
|
*/
|
||||||
static const SHAPE_POLY_SET BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths, bool aReverseOrientation = false, bool aEvenOdd = false );
|
void BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths, bool aEvenOdd = false );
|
||||||
|
|
||||||
void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
|
void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
|
||||||
ERROR_LOC aErrorLoc ) const override
|
ERROR_LOC aErrorLoc ) const override
|
||||||
@ -1487,9 +1455,6 @@ private:
|
|||||||
|
|
||||||
void fractureSingle( POLYGON& paths );
|
void fractureSingle( POLYGON& paths );
|
||||||
void unfractureSingle ( POLYGON& path );
|
void unfractureSingle ( POLYGON& path );
|
||||||
void importTree( ClipperLib::PolyTree* tree,
|
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffe );
|
|
||||||
void importTree( Clipper2Lib::PolyTree64& tree,
|
void importTree( Clipper2Lib::PolyTree64& tree,
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffe );
|
const std::vector<SHAPE_ARC>& aArcBuffe );
|
||||||
@ -1500,7 +1465,6 @@ private:
|
|||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer );
|
const std::vector<SHAPE_ARC>& aArcBuffer );
|
||||||
|
|
||||||
void inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy );
|
|
||||||
void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
|
void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
|
||||||
|
|
||||||
void inflateLine2( const SHAPE_LINE_CHAIN& aLine, int aAmount, int aCircleSegCount,
|
void inflateLine2( const SHAPE_LINE_CHAIN& aLine, int aAmount, int aCircleSegCount,
|
||||||
@ -1510,20 +1474,9 @@ private:
|
|||||||
* This is the engine to execute all polygon boolean transforms (AND, OR, ... and polygon
|
* This is the engine to execute all polygon boolean transforms (AND, OR, ... and polygon
|
||||||
* simplification (merging overlapping polygons).
|
* simplification (merging overlapping polygons).
|
||||||
*
|
*
|
||||||
* @param aType is the transform type ( see ClipperLib::ClipType )
|
* @param aType is the transform type ( see Clipper2Lib::ClipType )
|
||||||
* @param aOtherShape is the SHAPE_LINE_CHAIN to combine with me.
|
* @param aOtherShape is the SHAPE_LINE_CHAIN to combine with me.
|
||||||
* @param aFastMode is an option to choose if the result can be a weak polygon
|
|
||||||
* or a strictly simple polygon.
|
|
||||||
* if aFastMode is PM_FAST the result can be a weak polygon
|
|
||||||
* if aFastMode is PM_STRICTLY_SIMPLE (default) the result is (theoretically) a strictly
|
|
||||||
* simple polygon, but calculations can be really significantly time consuming
|
|
||||||
*/
|
*/
|
||||||
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 );
|
|
||||||
|
|
||||||
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape );
|
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape );
|
||||||
|
|
||||||
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,
|
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,
|
||||||
|
@ -214,7 +214,7 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aBuffer, const VECTOR2I& aStart, co
|
|||||||
bbox.Append( corner.x, corner.y );
|
bbox.Append( corner.x, corner.y );
|
||||||
|
|
||||||
// Now, clamp the shape
|
// Now, clamp the shape
|
||||||
polyshape.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polyshape.BooleanIntersection( bbox );
|
||||||
// Note the final polygon is a simple, convex polygon with no hole
|
// Note the final polygon is a simple, convex polygon with no hole
|
||||||
// due to the shape of initial polygons
|
// due to the shape of initial polygons
|
||||||
|
|
||||||
@ -663,6 +663,6 @@ void TransformRingToPolygon( SHAPE_POLY_SET& aBuffer, const VECTOR2I& aCentre, i
|
|||||||
TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius,
|
TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius,
|
||||||
aError, inner_err_loc );
|
aError, inner_err_loc );
|
||||||
|
|
||||||
buffer.Fracture( SHAPE_POLY_SET::PM_FAST );
|
buffer.Fracture();
|
||||||
aBuffer.Append( buffer );
|
aBuffer.Append( buffer );
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string> // for basic_string
|
#include <string> // for basic_string
|
||||||
|
|
||||||
#include <clipper.hpp>
|
|
||||||
#include <clipper2/clipper.h>
|
#include <clipper2/clipper.h>
|
||||||
#include <core/kicad_algo.h> // for alg::run_on_pair
|
#include <core/kicad_algo.h> // for alg::run_on_pair
|
||||||
#include <geometry/circle.h>
|
#include <geometry/circle.h>
|
||||||
@ -79,50 +78,6 @@ SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed ) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
|
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer ) :
|
|
||||||
SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ),
|
|
||||||
m_closed( true ), m_width( 0 )
|
|
||||||
{
|
|
||||||
std::map<ssize_t, ssize_t> loadedArcs;
|
|
||||||
m_points.reserve( aPath.size() );
|
|
||||||
m_shapes.reserve( aPath.size() );
|
|
||||||
|
|
||||||
auto loadArc =
|
|
||||||
[&]( ssize_t aArcIndex ) -> ssize_t
|
|
||||||
{
|
|
||||||
if( aArcIndex == SHAPE_IS_PT )
|
|
||||||
{
|
|
||||||
return SHAPE_IS_PT;
|
|
||||||
}
|
|
||||||
else if( loadedArcs.count( aArcIndex ) == 0 )
|
|
||||||
{
|
|
||||||
loadedArcs.insert( { aArcIndex, m_arcs.size() } );
|
|
||||||
m_arcs.push_back( aArcBuffer.at( aArcIndex ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return loadedArcs.at( aArcIndex );
|
|
||||||
};
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < aPath.size(); ++ii )
|
|
||||||
{
|
|
||||||
Append( aPath[ii].X, aPath[ii].Y );
|
|
||||||
|
|
||||||
m_shapes[ii].first = loadArc( aZValueBuffer[aPath[ii].Z].m_FirstArcIdx );
|
|
||||||
m_shapes[ii].second = loadArc( aZValueBuffer[aPath[ii].Z].m_SecondArcIdx );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clipper shouldn't return duplicate contiguous points. if it did, these would be
|
|
||||||
// removed during Append() and we would have different number of shapes to points
|
|
||||||
wxASSERT( m_shapes.size() == m_points.size() );
|
|
||||||
|
|
||||||
// Clipper might mess up the rotation of the indices such that an arc can be split between
|
|
||||||
// the end point and wrap around to the start point. Lets fix the indices up now
|
|
||||||
fixIndicesRotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
|
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer ) :
|
const std::vector<SHAPE_ARC>& aArcBuffer ) :
|
||||||
@ -167,40 +122,6 @@ SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ClipperLib::Path SHAPE_LINE_CHAIN::convertToClipper( bool aRequiredOrientation,
|
|
||||||
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
std::vector<SHAPE_ARC>& aArcBuffer ) const
|
|
||||||
{
|
|
||||||
ClipperLib::Path c_path;
|
|
||||||
SHAPE_LINE_CHAIN input;
|
|
||||||
bool orientation = Area( false ) >= 0;
|
|
||||||
ssize_t shape_offset = aArcBuffer.size();
|
|
||||||
|
|
||||||
if( orientation != aRequiredOrientation )
|
|
||||||
input = Reverse();
|
|
||||||
else
|
|
||||||
input = *this;
|
|
||||||
|
|
||||||
int pointCount = input.PointCount();
|
|
||||||
c_path.reserve( pointCount );
|
|
||||||
|
|
||||||
for( int i = 0; i < pointCount; i++ )
|
|
||||||
{
|
|
||||||
const VECTOR2I& vertex = input.CPoint( i );
|
|
||||||
|
|
||||||
CLIPPER_Z_VALUE z_value( input.m_shapes[i], shape_offset );
|
|
||||||
size_t z_value_ptr = aZValueBuffer.size();
|
|
||||||
aZValueBuffer.push_back( z_value );
|
|
||||||
|
|
||||||
c_path.emplace_back( vertex.x, vertex.y, z_value_ptr );
|
|
||||||
}
|
|
||||||
|
|
||||||
aArcBuffer.insert( aArcBuffer.end(), input.m_arcs.begin(), input.m_arcs.end() );
|
|
||||||
|
|
||||||
return c_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Clipper2Lib::Path64 SHAPE_LINE_CHAIN::convertToClipper2( bool aRequiredOrientation,
|
Clipper2Lib::Path64 SHAPE_LINE_CHAIN::convertToClipper2( bool aRequiredOrientation,
|
||||||
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
std::vector<SHAPE_ARC>& aArcBuffer ) const
|
std::vector<SHAPE_ARC>& aArcBuffer ) const
|
||||||
|
@ -744,118 +744,6 @@ void SHAPE_POLY_SET::RebuildHolesFromContours()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
|
||||||
POLYGON_MODE aFastMode )
|
|
||||||
{
|
|
||||||
booleanOp( aType, *this, aOtherShape, aFastMode );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
|
|
||||||
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode )
|
|
||||||
{
|
|
||||||
if( ( aShape.OutlineCount() > 1 || aOtherShape.OutlineCount() > 0 )
|
|
||||||
&& ( aShape.ArcCount() > 0 || aOtherShape.ArcCount() > 0 ) )
|
|
||||||
{
|
|
||||||
wxFAIL_MSG( wxT( "Boolean ops on curved polygons are not supported. You should call "
|
|
||||||
"ClearArcs() before carrying out the boolean operation." ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
ClipperLib::Clipper c;
|
|
||||||
|
|
||||||
c.StrictlySimple( aFastMode == PM_STRICTLY_SIMPLE );
|
|
||||||
|
|
||||||
std::vector<CLIPPER_Z_VALUE> zValues;
|
|
||||||
std::vector<SHAPE_ARC> arcBuffer;
|
|
||||||
std::map<VECTOR2I, CLIPPER_Z_VALUE> newIntersectPoints;
|
|
||||||
|
|
||||||
for( const POLYGON& poly : aShape.m_polys )
|
|
||||||
{
|
|
||||||
for( size_t i = 0; i < poly.size(); i++ )
|
|
||||||
{
|
|
||||||
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
|
|
||||||
ClipperLib::ptSubject, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( const POLYGON& poly : aOtherShape.m_polys )
|
|
||||||
{
|
|
||||||
for( size_t i = 0; i < poly.size(); i++ )
|
|
||||||
{
|
|
||||||
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
|
|
||||||
ClipperLib::ptClip, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClipperLib::PolyTree solution;
|
|
||||||
|
|
||||||
ClipperLib::ZFillCallback callback =
|
|
||||||
[&]( ClipperLib::IntPoint & e1bot, ClipperLib::IntPoint & e1top,
|
|
||||||
ClipperLib::IntPoint & e2bot, ClipperLib::IntPoint & e2top,
|
|
||||||
ClipperLib::IntPoint & pt )
|
|
||||||
{
|
|
||||||
auto arcIndex =
|
|
||||||
[&]( const ssize_t& aZvalue, const ssize_t& aCompareVal = -1 ) -> ssize_t
|
|
||||||
{
|
|
||||||
ssize_t retval;
|
|
||||||
|
|
||||||
retval = zValues.at( aZvalue ).m_SecondArcIdx;
|
|
||||||
|
|
||||||
if( retval == -1 || ( aCompareVal > 0 && retval != aCompareVal ) )
|
|
||||||
retval = zValues.at( aZvalue ).m_FirstArcIdx;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto arcSegment =
|
|
||||||
[&]( const ssize_t& aBottomZ, const ssize_t aTopZ ) -> ssize_t
|
|
||||||
{
|
|
||||||
ssize_t retval = arcIndex( aBottomZ );
|
|
||||||
|
|
||||||
if( retval != -1 )
|
|
||||||
{
|
|
||||||
if( retval != arcIndex( aTopZ, retval ) )
|
|
||||||
retval = -1; // Not an arc segment as the two indices do not match
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
};
|
|
||||||
|
|
||||||
ssize_t e1ArcSegmentIndex = arcSegment( e1bot.Z, e1top.Z );
|
|
||||||
ssize_t e2ArcSegmentIndex = arcSegment( e2bot.Z, e2top.Z );
|
|
||||||
|
|
||||||
CLIPPER_Z_VALUE newZval;
|
|
||||||
|
|
||||||
if( e1ArcSegmentIndex != -1 )
|
|
||||||
{
|
|
||||||
newZval.m_FirstArcIdx = e1ArcSegmentIndex;
|
|
||||||
newZval.m_SecondArcIdx = e2ArcSegmentIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newZval.m_FirstArcIdx = e2ArcSegmentIndex;
|
|
||||||
newZval.m_SecondArcIdx = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t z_value_ptr = zValues.size();
|
|
||||||
zValues.push_back( newZval );
|
|
||||||
|
|
||||||
// Only worry about arc segments for later processing
|
|
||||||
if( newZval.m_FirstArcIdx != -1 )
|
|
||||||
newIntersectPoints.insert( { VECTOR2I( pt.X, pt.Y ), newZval } );
|
|
||||||
|
|
||||||
pt.Z = z_value_ptr;
|
|
||||||
//@todo amend X,Y values to true intersection between arcs or arc and segment
|
|
||||||
};
|
|
||||||
|
|
||||||
c.ZFillFunction( std::move( callback ) ); // register callback
|
|
||||||
|
|
||||||
c.Execute( aType, solution, ClipperLib::pftNonZero, ClipperLib::pftNonZero );
|
|
||||||
|
|
||||||
importTree( &solution, zValues, arcBuffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape )
|
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape )
|
||||||
{
|
{
|
||||||
booleanOp( aType, *this, aOtherShape );
|
booleanOp( aType, *this, aOtherShape );
|
||||||
@ -970,155 +858,60 @@ void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SE
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b )
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Union, b );
|
booleanOp( Clipper2Lib::ClipType::Union, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b )
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Difference, b );
|
booleanOp( Clipper2Lib::ClipType::Difference, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& b )
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Intersection, b );
|
booleanOp( Clipper2Lib::ClipType::Intersection, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& b )
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Xor, b );
|
booleanOp( Clipper2Lib::ClipType::Xor, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
|
||||||
POLYGON_MODE aFastMode )
|
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Union, a, b );
|
booleanOp( Clipper2Lib::ClipType::Union, a, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
|
||||||
POLYGON_MODE aFastMode )
|
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Difference, a, b );
|
booleanOp( Clipper2Lib::ClipType::Difference, a, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
|
||||||
POLYGON_MODE aFastMode )
|
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Intersection, a, b );
|
booleanOp( Clipper2Lib::ClipType::Intersection, a, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
|
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
|
||||||
POLYGON_MODE aFastMode )
|
|
||||||
{
|
{
|
||||||
booleanOp( Clipper2Lib::ClipType::Xor, a, b );
|
booleanOp( Clipper2Lib::ClipType::Xor, a, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy,
|
void SHAPE_POLY_SET::InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy,
|
||||||
int aMaxError, POLYGON_MODE aFastMode )
|
int aMaxError )
|
||||||
{
|
{
|
||||||
Unfracture( aFastMode );
|
Unfracture();
|
||||||
Inflate( aFactor, aCornerStrategy, aMaxError );
|
Inflate( aFactor, aCornerStrategy, aMaxError );
|
||||||
Fracture( aFastMode );
|
Fracture();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy )
|
|
||||||
{
|
|
||||||
using namespace ClipperLib;
|
|
||||||
// A static table to avoid repetitive calculations of the coefficient
|
|
||||||
// 1.0 - cos( M_PI / aCircleSegCount )
|
|
||||||
// aCircleSegCount is most of time <= 64 and usually 8, 12, 16, 32
|
|
||||||
#define SEG_CNT_MAX 64
|
|
||||||
static double arc_tolerance_factor[SEG_CNT_MAX + 1];
|
|
||||||
|
|
||||||
ClipperOffset c;
|
|
||||||
|
|
||||||
// N.B. see the Clipper documentation for jtSquare/jtMiter/jtRound. They are poorly named
|
|
||||||
// and are not what you'd think they are.
|
|
||||||
// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/JoinType.htm
|
|
||||||
JoinType joinType = jtRound; // The way corners are offsetted
|
|
||||||
double miterLimit = 2.0; // Smaller value when using jtMiter for joinType
|
|
||||||
JoinType miterFallback = jtSquare;
|
|
||||||
|
|
||||||
switch( aCornerStrategy )
|
|
||||||
{
|
|
||||||
case CORNER_STRATEGY::ALLOW_ACUTE_CORNERS:
|
|
||||||
joinType = jtMiter;
|
|
||||||
miterLimit = 10; // Allows large spikes
|
|
||||||
miterFallback = jtSquare;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS: // Acute angles are chamfered
|
|
||||||
joinType = jtMiter;
|
|
||||||
miterFallback = jtRound;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CORNER_STRATEGY::ROUND_ACUTE_CORNERS: // Acute angles are rounded
|
|
||||||
joinType = jtMiter;
|
|
||||||
miterFallback = jtSquare;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CORNER_STRATEGY::CHAMFER_ALL_CORNERS: // All angles are chamfered.
|
|
||||||
joinType = jtSquare;
|
|
||||||
miterFallback = jtSquare;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CORNER_STRATEGY::ROUND_ALL_CORNERS: // All angles are rounded.
|
|
||||||
joinType = jtRound;
|
|
||||||
miterFallback = jtSquare;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CLIPPER_Z_VALUE> zValues;
|
|
||||||
std::vector<SHAPE_ARC> arcBuffer;
|
|
||||||
|
|
||||||
for( const POLYGON& poly : m_polys )
|
|
||||||
{
|
|
||||||
for( size_t i = 0; i < poly.size(); i++ )
|
|
||||||
{
|
|
||||||
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
|
|
||||||
joinType, etClosedPolygon );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PolyTree solution;
|
|
||||||
|
|
||||||
// Calculate the arc tolerance (arc error) from the seg count by circle. The seg count is
|
|
||||||
// nn = M_PI / acos(1.0 - c.ArcTolerance / abs(aAmount))
|
|
||||||
// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
|
|
||||||
|
|
||||||
if( aCircleSegCount < 6 ) // avoid incorrect aCircleSegCount values
|
|
||||||
aCircleSegCount = 6;
|
|
||||||
|
|
||||||
double coeff;
|
|
||||||
|
|
||||||
if( aCircleSegCount > SEG_CNT_MAX || arc_tolerance_factor[aCircleSegCount] == 0 )
|
|
||||||
{
|
|
||||||
coeff = 1.0 - cos( M_PI / aCircleSegCount );
|
|
||||||
|
|
||||||
if( aCircleSegCount <= SEG_CNT_MAX )
|
|
||||||
arc_tolerance_factor[aCircleSegCount] = coeff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
coeff = arc_tolerance_factor[aCircleSegCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ArcTolerance = std::abs( aAmount ) * coeff;
|
|
||||||
c.MiterLimit = miterLimit;
|
|
||||||
c.MiterFallback = miterFallback;
|
|
||||||
c.Execute( solution, aAmount );
|
|
||||||
|
|
||||||
importTree( &solution, zValues, arcBuffer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1341,30 +1134,6 @@ void SHAPE_POLY_SET::OffsetLineChain( const SHAPE_LINE_CHAIN& aLine, int aAmount
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::importTree( ClipperLib::PolyTree* tree,
|
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer )
|
|
||||||
{
|
|
||||||
m_polys.clear();
|
|
||||||
|
|
||||||
for( ClipperLib::PolyNode* n = tree->GetFirst(); n; n = n->GetNext() )
|
|
||||||
{
|
|
||||||
if( !n->IsHole() )
|
|
||||||
{
|
|
||||||
POLYGON paths;
|
|
||||||
paths.reserve( n->Childs.size() + 1 );
|
|
||||||
|
|
||||||
paths.emplace_back( n->Contour, aZValueBuffer, aArcBuffer );
|
|
||||||
|
|
||||||
for( unsigned int i = 0; i < n->Childs.size(); i++ )
|
|
||||||
paths.emplace_back( n->Childs[i]->Contour, aZValueBuffer, aArcBuffer );
|
|
||||||
|
|
||||||
m_polys.push_back( paths );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::importPolyPath( const std::unique_ptr<Clipper2Lib::PolyPath64>& aPolyPath,
|
void SHAPE_POLY_SET::importPolyPath( const std::unique_ptr<Clipper2Lib::PolyPath64>& aPolyPath,
|
||||||
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
|
||||||
const std::vector<SHAPE_ARC>& aArcBuffer )
|
const std::vector<SHAPE_ARC>& aArcBuffer )
|
||||||
@ -1886,9 +1655,9 @@ void SHAPE_POLY_SET::fractureSingle( POLYGON& paths )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::Fracture( POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::Fracture()
|
||||||
{
|
{
|
||||||
Simplify( aFastMode ); // remove overlapping holes/degeneracy
|
Simplify(); // remove overlapping holes/degeneracy
|
||||||
|
|
||||||
for( POLYGON& paths : m_polys )
|
for( POLYGON& paths : m_polys )
|
||||||
fractureSingle( paths );
|
fractureSingle( paths );
|
||||||
@ -2077,16 +1846,16 @@ bool SHAPE_POLY_SET::HasHoles() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::Unfracture( POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::Unfracture()
|
||||||
{
|
{
|
||||||
for( POLYGON& path : m_polys )
|
for( POLYGON& path : m_polys )
|
||||||
unfractureSingle( path );
|
unfractureSingle( path );
|
||||||
|
|
||||||
Simplify( aFastMode ); // remove overlapping holes/degeneracy
|
Simplify(); // remove overlapping holes/degeneracy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SHAPE_POLY_SET::Simplify( POLYGON_MODE aFastMode )
|
void SHAPE_POLY_SET::Simplify()
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET empty;
|
SHAPE_POLY_SET empty;
|
||||||
|
|
||||||
@ -2110,7 +1879,7 @@ int SHAPE_POLY_SET::NormalizeAreaOutlines()
|
|||||||
{
|
{
|
||||||
// We are expecting only one main outline, but this main outline can have holes
|
// We are expecting only one main outline, but this main outline can have holes
|
||||||
// if holes: combine holes and remove them from the main outline.
|
// if holes: combine holes and remove them from the main outline.
|
||||||
// Note also we are using SHAPE_POLY_SET::PM_STRICTLY_SIMPLE in polygon
|
// Note also we are usingin polygon
|
||||||
// calculations, but it is not mandatory. It is used mainly
|
// calculations, but it is not mandatory. It is used mainly
|
||||||
// because there is usually only very few vertices in area outlines
|
// because there is usually only very few vertices in area outlines
|
||||||
SHAPE_POLY_SET::POLYGON& outline = Polygon( 0 );
|
SHAPE_POLY_SET::POLYGON& outline = Polygon( 0 );
|
||||||
@ -2124,13 +1893,13 @@ int SHAPE_POLY_SET::NormalizeAreaOutlines()
|
|||||||
outline.pop_back();
|
outline.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
Simplify();
|
||||||
|
|
||||||
// If any hole, subtract it to main outline
|
// If any hole, subtract it to main outline
|
||||||
if( holesBuffer.OutlineCount() )
|
if( holesBuffer.OutlineCount() )
|
||||||
{
|
{
|
||||||
holesBuffer.Simplify( SHAPE_POLY_SET::PM_FAST );
|
holesBuffer.Simplify();
|
||||||
BooleanSubtract( holesBuffer, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
BooleanSubtract( holesBuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
// In degenerate cases, simplify might return no outlines
|
// In degenerate cases, simplify might return no outlines
|
||||||
@ -3210,10 +2979,10 @@ static SHAPE_POLY_SET partitionPolyIntoRegularCellGrid( const SHAPE_POLY_SET& aP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ps1.BooleanIntersection( maskSetOdd, SHAPE_POLY_SET::PM_FAST );
|
ps1.BooleanIntersection( maskSetOdd );
|
||||||
ps2.BooleanIntersection( maskSetEven, SHAPE_POLY_SET::PM_FAST );
|
ps2.BooleanIntersection( maskSetEven );
|
||||||
ps1.Fracture( SHAPE_POLY_SET::PM_FAST );
|
ps1.Fracture();
|
||||||
ps2.Fracture( SHAPE_POLY_SET::PM_FAST );
|
ps2.Fracture();
|
||||||
|
|
||||||
for( int i = 0; i < ps2.OutlineCount(); i++ )
|
for( int i = 0; i < ps2.OutlineCount(); i++ )
|
||||||
ps1.AddOutline( ps2.COutline( i ) );
|
ps1.AddOutline( ps2.COutline( i ) );
|
||||||
@ -3269,10 +3038,6 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
|
|||||||
++pass;
|
++pass;
|
||||||
|
|
||||||
if( pass == 1 )
|
if( pass == 1 )
|
||||||
{
|
|
||||||
polySet.Fracture( PM_FAST );
|
|
||||||
}
|
|
||||||
else if( pass == 2 )
|
|
||||||
{
|
{
|
||||||
polySet.SimplifyOutlines( TRIANGULATESIMPLIFICATIONLEVEL );
|
polySet.SimplifyOutlines( TRIANGULATESIMPLIFICATIONLEVEL );
|
||||||
}
|
}
|
||||||
@ -3310,9 +3075,9 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
|
|||||||
flattened.ClearArcs();
|
flattened.ClearArcs();
|
||||||
|
|
||||||
if( flattened.HasHoles() || flattened.IsSelfIntersecting() )
|
if( flattened.HasHoles() || flattened.IsSelfIntersecting() )
|
||||||
flattened.Fracture( PM_FAST );
|
flattened.Fracture();
|
||||||
else if( aSimplify )
|
else if( aSimplify )
|
||||||
flattened.Simplify( PM_FAST );
|
flattened.Simplify();
|
||||||
|
|
||||||
SHAPE_POLY_SET partitions = partitionPolyIntoRegularCellGrid( flattened, 1e7 );
|
SHAPE_POLY_SET partitions = partitionPolyIntoRegularCellGrid( flattened, 1e7 );
|
||||||
|
|
||||||
@ -3336,8 +3101,7 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
|
|||||||
SHAPE_POLY_SET tmpSet( *this );
|
SHAPE_POLY_SET tmpSet( *this );
|
||||||
|
|
||||||
tmpSet.ClearArcs();
|
tmpSet.ClearArcs();
|
||||||
|
tmpSet.Fracture();
|
||||||
tmpSet.Fracture( PM_FAST );
|
|
||||||
|
|
||||||
if( !triangulate( tmpSet, -1, m_triangulatedPolys, aHintData ) )
|
if( !triangulate( tmpSet, -1, m_triangulatedPolys, aHintData ) )
|
||||||
{
|
{
|
||||||
@ -3498,55 +3262,35 @@ SHAPE_POLY_SET::TRIANGULATED_POLYGON::~TRIANGULATED_POLYGON()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const SHAPE_POLY_SET
|
void
|
||||||
SHAPE_POLY_SET::BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths,
|
SHAPE_POLY_SET::BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths,
|
||||||
bool aReverseOrientation, bool aEvenOdd )
|
bool aEvenOdd )
|
||||||
{
|
{
|
||||||
ClipperLib::Clipper clipper;
|
Clipper2Lib::Clipper64 clipper;
|
||||||
ClipperLib::PolyTree tree;
|
Clipper2Lib::PolyTree64 tree;
|
||||||
|
Clipper2Lib::Paths64 paths;
|
||||||
// fixme: do we need aReverseOrientation?
|
|
||||||
|
|
||||||
for( const SHAPE_LINE_CHAIN& path : aPaths )
|
for( const SHAPE_LINE_CHAIN& path : aPaths )
|
||||||
{
|
{
|
||||||
ClipperLib::Path lc;
|
Clipper2Lib::Path64 lc;
|
||||||
|
lc.reserve( path.PointCount() );
|
||||||
|
|
||||||
for( int i = 0; i < path.PointCount(); i++ )
|
for( int i = 0; i < path.PointCount(); i++ )
|
||||||
{
|
|
||||||
lc.emplace_back( path.CPoint( i ).x, path.CPoint( i ).y );
|
lc.emplace_back( path.CPoint( i ).x, path.CPoint( i ).y );
|
||||||
|
|
||||||
|
paths.push_back( lc );
|
||||||
}
|
}
|
||||||
|
|
||||||
clipper.AddPath( lc, ClipperLib::ptSubject, true );
|
clipper.AddSubject( paths );
|
||||||
}
|
clipper.Execute( Clipper2Lib::ClipType::Union, aEvenOdd ? Clipper2Lib::FillRule::EvenOdd
|
||||||
|
: Clipper2Lib::FillRule::NonZero, tree );
|
||||||
|
|
||||||
clipper.StrictlySimple( true );
|
|
||||||
clipper.Execute( ClipperLib::ctUnion, tree,
|
|
||||||
aEvenOdd ? ClipperLib::pftEvenOdd : ClipperLib::pftNonZero,
|
|
||||||
ClipperLib::pftNonZero );
|
|
||||||
SHAPE_POLY_SET result;
|
|
||||||
|
|
||||||
for( ClipperLib::PolyNode* n = tree.GetFirst(); n; n = n->GetNext() )
|
std::vector<CLIPPER_Z_VALUE> zValues;
|
||||||
{
|
std::vector<SHAPE_ARC> arcBuffer;
|
||||||
if( !n->IsHole() )
|
|
||||||
{
|
|
||||||
int outl = result.NewOutline();
|
|
||||||
|
|
||||||
for( unsigned int i = 0; i < n->Contour.size(); i++ )
|
importTree( tree, zValues, arcBuffer );
|
||||||
result.Outline( outl ).Append( n->Contour[i].X, n->Contour[i].Y );
|
tree.Clear(); // Free used memory (not done in dtor)
|
||||||
|
|
||||||
for( unsigned int i = 0; i < n->Childs.size(); i++ )
|
|
||||||
{
|
|
||||||
int outh = result.NewHole( outl );
|
|
||||||
for( unsigned int j = 0; j < n->Childs[i]->Contour.size(); j++ )
|
|
||||||
{
|
|
||||||
result.Hole( outl, outh )
|
|
||||||
.Append( n->Childs[i]->Contour[j].X, n->Childs[i]->Contour[j].Y );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ bool AR_AUTOPLACER::fillMatrix()
|
|||||||
|
|
||||||
// Create a single board outline:
|
// Create a single board outline:
|
||||||
SHAPE_POLY_SET brd_shape = m_boardShape.CloneDropTriangulation();
|
SHAPE_POLY_SET brd_shape = m_boardShape.CloneDropTriangulation();
|
||||||
brd_shape.Fracture( SHAPE_POLY_SET::PM_FAST );
|
brd_shape.Fracture();
|
||||||
const SHAPE_LINE_CHAIN& outline = brd_shape.Outline(0);
|
const SHAPE_LINE_CHAIN& outline = brd_shape.Outline(0);
|
||||||
const BOX2I& rect = outline.BBox();
|
const BOX2I& rect = outline.BBox();
|
||||||
|
|
||||||
@ -393,8 +393,8 @@ void AR_AUTOPLACER::genModuleOnRoutingMatrix( FOOTPRINT* Module )
|
|||||||
buildFpAreas( Module, margin );
|
buildFpAreas( Module, margin );
|
||||||
|
|
||||||
// Substract the shape to free areas
|
// Substract the shape to free areas
|
||||||
m_topFreeArea.BooleanSubtract( m_fpAreaTop, SHAPE_POLY_SET::PM_FAST );
|
m_topFreeArea.BooleanSubtract( m_fpAreaTop );
|
||||||
m_bottomFreeArea.BooleanSubtract( m_fpAreaBottom, SHAPE_POLY_SET::PM_FAST );
|
m_bottomFreeArea.BooleanSubtract( m_fpAreaBottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -802,7 +802,7 @@ void AR_AUTOPLACER::drawPlacementRoutingMatrix( )
|
|||||||
m_overlay->SetIsStroke( false );
|
m_overlay->SetIsStroke( false );
|
||||||
|
|
||||||
SHAPE_POLY_SET freeArea = m_topFreeArea.CloneDropTriangulation();
|
SHAPE_POLY_SET freeArea = m_topFreeArea.CloneDropTriangulation();
|
||||||
freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
|
freeArea.Fracture();
|
||||||
|
|
||||||
// Draw the free polygon areas, top side:
|
// Draw the free polygon areas, top side:
|
||||||
if( freeArea.OutlineCount() > 0 )
|
if( freeArea.OutlineCount() > 0 )
|
||||||
@ -814,7 +814,7 @@ void AR_AUTOPLACER::drawPlacementRoutingMatrix( )
|
|||||||
}
|
}
|
||||||
|
|
||||||
freeArea = m_bottomFreeArea;
|
freeArea = m_bottomFreeArea;
|
||||||
freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
|
freeArea.Fracture();
|
||||||
|
|
||||||
// Draw the free polygon areas, bottom side:
|
// Draw the free polygon areas, bottom side:
|
||||||
if( freeArea.OutlineCount() > 0 )
|
if( freeArea.OutlineCount() > 0 )
|
||||||
|
@ -2541,7 +2541,7 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||||
aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aOutlines.Simplify();
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,7 @@ static bool isCopperOutside( const FOOTPRINT* aFootprint, SHAPE_POLY_SET& aShape
|
|||||||
|
|
||||||
poly.ClearArcs();
|
poly.ClearArcs();
|
||||||
|
|
||||||
poly.BooleanIntersection( *pad->GetEffectivePolygon( aLayer, ERROR_INSIDE ),
|
poly.BooleanIntersection( *pad->GetEffectivePolygon( aLayer, ERROR_INSIDE ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
|
|
||||||
if( poly.OutlineCount() == 0 )
|
if( poly.OutlineCount() == 0 )
|
||||||
{
|
{
|
||||||
|
@ -283,7 +283,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
|
|||||||
otherPadHoles, 0, maxError, ERROR_INSIDE );
|
otherPadHoles, 0, maxError, ERROR_INSIDE );
|
||||||
}
|
}
|
||||||
|
|
||||||
otherPadOutline.BooleanSubtract( otherPadHoles, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
otherPadOutline.BooleanSubtract( otherPadHoles );
|
||||||
|
|
||||||
// If the pad hole under test intersects with another pad outline,
|
// If the pad hole under test intersects with another pad outline,
|
||||||
// the annular width calculated above is used.
|
// the annular width calculated above is used.
|
||||||
|
@ -384,7 +384,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||||||
ERROR_OUTSIDE );
|
ERROR_OUTSIDE );
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsPoly.Poly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
itemsPoly.Poly.Fracture();
|
||||||
|
|
||||||
done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );
|
done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
|
|||||||
// exclude it. This is particularly important for detecting copper fills as
|
// exclude it. This is particularly important for detecting copper fills as
|
||||||
// they will be exactly touching along the entire exclusion border.
|
// they will be exactly touching along the entire exclusion border.
|
||||||
SHAPE_POLY_SET areaPoly = ruleArea->Outline()->CloneDropTriangulation();
|
SHAPE_POLY_SET areaPoly = ruleArea->Outline()->CloneDropTriangulation();
|
||||||
areaPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
areaPoly.Fracture();
|
||||||
areaPoly.Deflate( epsilon, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, ARC_LOW_DEF );
|
areaPoly.Deflate( epsilon, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, ARC_LOW_DEF );
|
||||||
|
|
||||||
DRC_RTREE* zoneRTree = board->m_CopperZoneRTreeCache[ copperZone ].get();
|
DRC_RTREE* zoneRTree = board->m_CopperZoneRTreeCache[ copperZone ].get();
|
||||||
|
@ -555,7 +555,7 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER
|
|||||||
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
|
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
|
||||||
|
|
||||||
// Turn fractured fill into outlines and holes
|
// Turn fractured fill into outlines and holes
|
||||||
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
|
fill.Simplify();
|
||||||
|
|
||||||
for( int outlineIdx = 0; outlineIdx < fill.OutlineCount(); ++outlineIdx )
|
for( int outlineIdx = 0; outlineIdx < fill.OutlineCount(); ++outlineIdx )
|
||||||
{
|
{
|
||||||
|
@ -155,7 +155,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
|
|||||||
if( m_drcEngine->IsCancelled() )
|
if( m_drcEngine->IsCancelled() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
poly.Simplify( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
poly.Simplify();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
@ -122,8 +122,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* aItem )
|
|||||||
{
|
{
|
||||||
if( zone->IsOnLayer( layer ) )
|
if( zone->IsOnLayer( layer ) )
|
||||||
{
|
{
|
||||||
solderMask->GetFill( layer )->BooleanAdd( *zone->GetFilledPolysList( layer ),
|
solderMask->GetFill( layer )->BooleanAdd( *zone->GetFilledPolysList( layer ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,8 +221,8 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
|
|||||||
return true;
|
return true;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
solderMask->GetFill( F_Mask )->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
solderMask->GetFill( F_Mask )->Simplify();
|
||||||
solderMask->GetFill( B_Mask )->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
solderMask->GetFill( B_Mask )->Simplify();
|
||||||
|
|
||||||
solderMask->GetFill( F_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS,
|
solderMask->GetFill( F_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS,
|
||||||
m_maxError );
|
m_maxError );
|
||||||
|
@ -177,7 +177,7 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
|
|||||||
SHAPE_POLY_SET poly = outlineGlyph->CloneDropTriangulation();
|
SHAPE_POLY_SET poly = outlineGlyph->CloneDropTriangulation();
|
||||||
poly.Deflate( constraint.Value().Min() / 2,
|
poly.Deflate( constraint.Value().Min() / 2,
|
||||||
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, ARC_LOW_DEF );
|
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, ARC_LOW_DEF );
|
||||||
poly.Simplify( SHAPE_POLY_SET::PM_FAST );
|
poly.Simplify();
|
||||||
|
|
||||||
int resultingOutlineCount = poly.OutlineCount();
|
int resultingOutlineCount = poly.OutlineCount();
|
||||||
int resultingHoleCount = 0;
|
int resultingHoleCount = 0;
|
||||||
|
@ -502,7 +502,7 @@ bool HYPERLYNX_EXPORTER::writeNetObjects( const std::vector<BOARD_ITEM*>& aObjec
|
|||||||
const wxString layerName = m_board->GetLayerName( layer );
|
const wxString layerName = m_board->GetLayerName( layer );
|
||||||
SHAPE_POLY_SET fill = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
|
SHAPE_POLY_SET fill = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
|
||||||
|
|
||||||
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
|
fill.Simplify();
|
||||||
|
|
||||||
for( int i = 0; i < fill.OutlineCount(); i++ )
|
for( int i = 0; i < fill.OutlineCount(); i++ )
|
||||||
{
|
{
|
||||||
|
@ -394,8 +394,8 @@ void EXPORTER_PCB_VRML::ExportVrmlSolderMask()
|
|||||||
outlines = m_pcbOutlines;
|
outlines = m_pcbOutlines;
|
||||||
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer, holes );
|
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer, holes );
|
||||||
|
|
||||||
outlines.BooleanSubtract( holes, SHAPE_POLY_SET::PM_FAST );
|
outlines.BooleanSubtract( holes );
|
||||||
outlines.Fracture( SHAPE_POLY_SET::PM_FAST );
|
outlines.Fracture();
|
||||||
ExportVrmlPolygonSet( vrmllayer, outlines );
|
ExportVrmlPolygonSet( vrmllayer, outlines );
|
||||||
|
|
||||||
pcb_layer = B_Mask;
|
pcb_layer = B_Mask;
|
||||||
@ -426,8 +426,8 @@ void EXPORTER_PCB_VRML::ExportStandardLayers()
|
|||||||
|
|
||||||
outlines.RemoveAllContours();
|
outlines.RemoveAllContours();
|
||||||
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer[lcnt], outlines );
|
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer[lcnt], outlines );
|
||||||
outlines.BooleanIntersection( m_pcbOutlines, SHAPE_POLY_SET::PM_FAST );
|
outlines.BooleanIntersection( m_pcbOutlines );
|
||||||
outlines.Fracture( SHAPE_POLY_SET::PM_FAST );
|
outlines.Fracture();
|
||||||
|
|
||||||
ExportVrmlPolygonSet( vrmllayer[lcnt], outlines );
|
ExportVrmlPolygonSet( vrmllayer[lcnt], outlines );
|
||||||
}
|
}
|
||||||
|
@ -463,7 +463,7 @@ void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin )
|
|||||||
{
|
{
|
||||||
SHAPE_POLY_SET fill_shape;
|
SHAPE_POLY_SET fill_shape;
|
||||||
zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
|
zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
|
||||||
fill_shape.Unfracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fill_shape.Unfracture();
|
||||||
|
|
||||||
fill_shape.SimplifyOutlines( ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel );
|
fill_shape.SimplifyOutlines( ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel );
|
||||||
|
|
||||||
@ -640,31 +640,31 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||||||
for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
|
for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];
|
SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];
|
||||||
poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly.Simplify();
|
||||||
|
|
||||||
poly.SimplifyOutlines( pcbIUScale.mmToIU( 0.003 ) );
|
poly.SimplifyOutlines( pcbIUScale.mmToIU( 0.003 ) );
|
||||||
poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly.Simplify();
|
||||||
|
|
||||||
SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
|
SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
|
||||||
holes.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
holes.Simplify();
|
||||||
|
|
||||||
// Mask layer is negative
|
// Mask layer is negative
|
||||||
if( pcblayer == F_Mask || pcblayer == B_Mask )
|
if( pcblayer == F_Mask || pcblayer == B_Mask )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET mask = pcbOutlinesNoArcs;
|
SHAPE_POLY_SET mask = pcbOutlinesNoArcs;
|
||||||
|
|
||||||
mask.BooleanSubtract( poly, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
mask.BooleanSubtract( poly );
|
||||||
mask.BooleanSubtract( holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
mask.BooleanSubtract( holes );
|
||||||
|
|
||||||
poly = mask;
|
poly = mask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Subtract holes
|
// Subtract holes
|
||||||
poly.BooleanSubtract( holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly.BooleanSubtract( holes );
|
||||||
|
|
||||||
// Clip to board outline
|
// Clip to board outline
|
||||||
poly.BooleanIntersection( pcbOutlinesNoArcs, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly.BooleanIntersection( pcbOutlinesNoArcs );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin );
|
m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin );
|
||||||
|
@ -1561,7 +1561,7 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
|
|||||||
double aThickness, double aZposition, const VECTOR2D& aOrigin )
|
double aThickness, double aZposition, const VECTOR2D& aOrigin )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET workingPoly = aPolySet;
|
SHAPE_POLY_SET workingPoly = aPolySet;
|
||||||
workingPoly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
workingPoly.Simplify();
|
||||||
|
|
||||||
SHAPE_POLY_SET fallbackPoly = workingPoly;
|
SHAPE_POLY_SET fallbackPoly = workingPoly;
|
||||||
|
|
||||||
|
@ -2777,7 +2777,7 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
|
|||||||
{
|
{
|
||||||
SHAPE_POLY_SET padPoly;
|
SHAPE_POLY_SET padPoly;
|
||||||
aItem->TransformShapeToPolygon( padPoly, aLayer, 0, ARC_LOW_DEF, ERROR_OUTSIDE );
|
aItem->TransformShapeToPolygon( padPoly, aLayer, 0, ARC_LOW_DEF, ERROR_OUTSIDE );
|
||||||
poly.BooleanAdd( padPoly, SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanAdd( padPoly );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2837,7 +2837,7 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
coveredRegion.BooleanIntersection( footprintRegion, SHAPE_POLY_SET::PM_FAST );
|
coveredRegion.BooleanIntersection( footprintRegion );
|
||||||
|
|
||||||
double footprintRegionArea = polygonArea( footprintRegion );
|
double footprintRegionArea = polygonArea( footprintRegion );
|
||||||
double uncoveredRegionArea = footprintRegionArea - polygonArea( coveredRegion );
|
double uncoveredRegionArea = footprintRegionArea - polygonArea( coveredRegion );
|
||||||
@ -3327,7 +3327,7 @@ void FOOTPRINT::CheckNetTies( const std::function<void( const BOARD_ITEM* aItem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copperOutlines.Simplify( SHAPE_POLY_SET::PM_FAST );
|
copperOutlines.Simplify();
|
||||||
|
|
||||||
// Index each pad to the outline in the set that it is part of.
|
// Index each pad to the outline in the set that it is part of.
|
||||||
|
|
||||||
|
@ -1804,7 +1804,7 @@ SHAPE_LINE_CHAIN PCB_TUNING_PATTERN::getOutline() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
SHAPE_POLY_SET merged;
|
SHAPE_POLY_SET merged;
|
||||||
merged.BooleanAdd( chain1, chain2, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
merged.BooleanAdd( chain1, chain2 );
|
||||||
|
|
||||||
if( merged.OutlineCount() > 0 )
|
if( merged.OutlineCount() > 0 )
|
||||||
return merged.Outline( 0 );
|
return merged.Outline( 0 );
|
||||||
@ -1832,7 +1832,7 @@ SHAPE_LINE_CHAIN PCB_TUNING_PATTERN::getOutline() const
|
|||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, false );
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, false );
|
||||||
|
|
||||||
SHAPE_POLY_SET merged;
|
SHAPE_POLY_SET merged;
|
||||||
merged.BooleanAdd( poly, polyCoupled, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
merged.BooleanAdd( poly, polyCoupled );
|
||||||
|
|
||||||
if( merged.OutlineCount() > 0 )
|
if( merged.OutlineCount() > 0 )
|
||||||
return merged.Outline( 0 );
|
return merged.Outline( 0 );
|
||||||
|
@ -1956,7 +1956,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
|
|||||||
aClearance += aMaxError;
|
aClearance += aMaxError;
|
||||||
|
|
||||||
outline.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aMaxError );
|
outline.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aMaxError );
|
||||||
outline.Fracture( SHAPE_POLY_SET::PM_FAST );
|
outline.Fracture();
|
||||||
}
|
}
|
||||||
else if( aClearance < 0 )
|
else if( aClearance < 0 )
|
||||||
{
|
{
|
||||||
@ -1965,7 +1965,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
|
|||||||
|
|
||||||
// aClearance is negative so this is actually a deflate
|
// aClearance is negative so this is actually a deflate
|
||||||
outline.Inflate( aClearance, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, aMaxError );
|
outline.Inflate( aClearance, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, aMaxError );
|
||||||
outline.Fracture( SHAPE_POLY_SET::PM_FAST );
|
outline.Fracture();
|
||||||
}
|
}
|
||||||
|
|
||||||
aBuffer.Append( outline );
|
aBuffer.Append( outline );
|
||||||
@ -2008,7 +2008,7 @@ std::vector<PCB_SHAPE*> PAD::Recombine( bool aIsDryRun, int maxError )
|
|||||||
|
|
||||||
SHAPE_POLY_SET drawPoly;
|
SHAPE_POLY_SET drawPoly;
|
||||||
shape->TransformShapeToPolygon( drawPoly, aLayer, 0, maxError, ERROR_INSIDE );
|
shape->TransformShapeToPolygon( drawPoly, aLayer, 0, maxError, ERROR_INSIDE );
|
||||||
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
|
drawPoly.BooleanIntersection( padPoly );
|
||||||
|
|
||||||
if( !drawPoly.IsEmpty() )
|
if( !drawPoly.IsEmpty() )
|
||||||
return shape;
|
return shape;
|
||||||
@ -2275,7 +2275,7 @@ void PAD::doCheckPad( PCB_LAYER_ID aLayer, UNITS_PROVIDER* aUnitsProvider,
|
|||||||
hole->GetWidth(), ARC_HIGH_DEF, ERROR_OUTSIDE );
|
hole->GetWidth(), ARC_HIGH_DEF, ERROR_OUTSIDE );
|
||||||
|
|
||||||
SHAPE_POLY_SET copper = padOutline;
|
SHAPE_POLY_SET copper = padOutline;
|
||||||
copper.BooleanSubtract( holeOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
copper.BooleanSubtract( holeOutline );
|
||||||
|
|
||||||
if( copper.IsEmpty() )
|
if( copper.IsEmpty() )
|
||||||
{
|
{
|
||||||
@ -2284,7 +2284,7 @@ void PAD::doCheckPad( PCB_LAYER_ID aLayer, UNITS_PROVIDER* aUnitsProvider,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Test if the pad hole is fully inside the copper area
|
// Test if the pad hole is fully inside the copper area
|
||||||
holeOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
holeOutline.BooleanSubtract( padOutline );
|
||||||
|
|
||||||
if( !holeOutline.IsEmpty() )
|
if( !holeOutline.IsEmpty() )
|
||||||
aErrorHandler( DRCE_PADSTACK, _( "(PTH pad hole non fully inside copper)" ) );
|
aErrorHandler( DRCE_PADSTACK, _( "(PTH pad hole non fully inside copper)" ) );
|
||||||
|
@ -45,7 +45,7 @@ void PAD::AddPrimitivePoly( PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPoly, in
|
|||||||
poly_no_hole.Append( aPoly );
|
poly_no_hole.Append( aPoly );
|
||||||
|
|
||||||
if( poly_no_hole.HasHoles() )
|
if( poly_no_hole.HasHoles() )
|
||||||
poly_no_hole.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly_no_hole.Fracture();
|
||||||
|
|
||||||
// There should never be multiple shapes, but if there are, we split them into
|
// There should never be multiple shapes, but if there are, we split them into
|
||||||
// primitives so that we can edit them both.
|
// primitives so that we can edit them both.
|
||||||
@ -142,13 +142,13 @@ void PAD::addPadPrimitivesToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET* aMerge
|
|||||||
primitive->TransformShapeToPolygon( polyset, UNDEFINED_LAYER, 0, aError, aErrorLoc );
|
primitive->TransformShapeToPolygon( polyset, UNDEFINED_LAYER, 0, aError, aErrorLoc );
|
||||||
}
|
}
|
||||||
|
|
||||||
polyset.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyset.Simplify();
|
||||||
|
|
||||||
// Merge all polygons with the initial pad anchor shape
|
// Merge all polygons with the initial pad anchor shape
|
||||||
if( polyset.OutlineCount() )
|
if( polyset.OutlineCount() )
|
||||||
{
|
{
|
||||||
aMergedPolygon->BooleanAdd( polyset, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aMergedPolygon->BooleanAdd( polyset );
|
||||||
aMergedPolygon->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aMergedPolygon->Fracture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
viewportPoly.BooleanSubtract( dialogPoly, SHAPE_POLY_SET::PM_FAST );
|
viewportPoly.BooleanSubtract( dialogPoly );
|
||||||
}
|
}
|
||||||
catch( const std::exception& e )
|
catch( const std::exception& e )
|
||||||
{
|
{
|
||||||
@ -426,7 +426,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clippedPoly.BooleanIntersection( itemPoly, viewportPoly, SHAPE_POLY_SET::PM_FAST );
|
clippedPoly.BooleanIntersection( itemPoly, viewportPoly );
|
||||||
}
|
}
|
||||||
catch( const std::exception& e )
|
catch( const std::exception& e )
|
||||||
{
|
{
|
||||||
|
@ -598,7 +598,7 @@ void ALTIUM_PCB::Parse( const ALTIUM_PCB_COMPOUND_FILE& altiumP
|
|||||||
if( !zone->HasFilledPolysForLayer( layer ) )
|
if( !zone->HasFilledPolysForLayer( layer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
zone->GetFilledPolysList( layer )->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
zone->GetFilledPolysList( layer )->Fracture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2824,9 +2824,9 @@ void ALTIUM_PCB::ParseRegions6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( zone->HasFilledPolysForLayer( klayer ) )
|
if( zone->HasFilledPolysForLayer( klayer ) )
|
||||||
fill.BooleanAdd( *zone->GetFill( klayer ), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fill.BooleanAdd( *zone->GetFill( klayer ) );
|
||||||
|
|
||||||
fill.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fill.Fracture();
|
||||||
|
|
||||||
zone->SetFilledPolysList( klayer, fill );
|
zone->SetFilledPolysList( klayer, fill );
|
||||||
zone->SetIsFilled( true );
|
zone->SetIsFilled( true );
|
||||||
|
@ -2173,7 +2173,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
poly.ClearArcs();
|
poly.ClearArcs();
|
||||||
fill.BooleanAdd( poly, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fill.BooleanAdd( poly );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2186,11 +2186,10 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
|
|||||||
|
|
||||||
if( pouredZone->HasFilledPolysForLayer( getKiCadLayer( csCopper.LayerID ) ) )
|
if( pouredZone->HasFilledPolysForLayer( getKiCadLayer( csCopper.LayerID ) ) )
|
||||||
{
|
{
|
||||||
fill.BooleanAdd( *pouredZone->GetFill( getKiCadLayer( csCopper.LayerID ) ),
|
fill.BooleanAdd( *pouredZone->GetFill( getKiCadLayer( csCopper.LayerID ) ) );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fill.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fill.Fracture();
|
||||||
|
|
||||||
pouredZone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
|
pouredZone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
|
||||||
pouredZone->SetIsFilled( true );
|
pouredZone->SetIsFilled( true );
|
||||||
@ -2270,7 +2269,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
|
|||||||
zone->SetAssignedPriority( m_zonesMap.size() + 1 ); // Highest priority (always fill first)
|
zone->SetAssignedPriority( m_zonesMap.size() + 1 ); // Highest priority (always fill first)
|
||||||
|
|
||||||
SHAPE_POLY_SET fill( *zone->Outline() );
|
SHAPE_POLY_SET fill( *zone->Outline() );
|
||||||
fill.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
|
fill.Fracture();
|
||||||
|
|
||||||
zone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
|
zone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
|
||||||
}
|
}
|
||||||
@ -2822,7 +2821,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarShape( const SHAPE& aCadstarShape,
|
|||||||
aScalingFactor, aTransformCentre,
|
aScalingFactor, aTransformCentre,
|
||||||
aMirrorInvert );
|
aMirrorInvert );
|
||||||
|
|
||||||
shapePolys.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
|
shapePolys.Fracture();
|
||||||
|
|
||||||
shape->SetPolyShape( shapePolys );
|
shape->SetPolyShape( shapePolys );
|
||||||
shape->SetStroke( STROKE_PARAMS( aLineThickness, LINE_STYLE::SOLID ) );
|
shape->SetStroke( STROKE_PARAMS( aLineThickness, LINE_STYLE::SOLID ) );
|
||||||
@ -3770,9 +3769,9 @@ bool CADSTAR_PCB_ARCHIVE_LOADER::calculateZonePriorities( PCB_LAYER_ID& aLayer )
|
|||||||
SHAPE_POLY_SET lowerZoneFill( *aLowerZone->GetFilledPolysList( aLayer ) );
|
SHAPE_POLY_SET lowerZoneFill( *aLowerZone->GetFilledPolysList( aLayer ) );
|
||||||
SHAPE_POLY_SET lowerZoneOutline( *aLowerZone->Outline() );
|
SHAPE_POLY_SET lowerZoneOutline( *aLowerZone->Outline() );
|
||||||
|
|
||||||
lowerZoneOutline.BooleanSubtract( intersectShape, SHAPE_POLY_SET::PM_FAST );
|
lowerZoneOutline.BooleanSubtract( intersectShape );
|
||||||
|
|
||||||
lowerZoneFill.BooleanSubtract( lowerZoneOutline, SHAPE_POLY_SET::PM_FAST );
|
lowerZoneFill.BooleanSubtract( lowerZoneOutline );
|
||||||
|
|
||||||
double leftOverArea = lowerZoneFill.Area();
|
double leftOverArea = lowerZoneFill.Area();
|
||||||
|
|
||||||
@ -3790,7 +3789,7 @@ bool CADSTAR_PCB_ARCHIVE_LOADER::calculateZonePriorities( PCB_LAYER_ID& aLayer )
|
|||||||
outLineB.Inflate( inflateValue( aZoneA, aZoneB ), CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
outLineB.Inflate( inflateValue( aZoneA, aZoneB ), CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
ARC_HIGH_DEF );
|
ARC_HIGH_DEF );
|
||||||
|
|
||||||
outLineA.BooleanIntersection( outLineB, SHAPE_POLY_SET::PM_FAST );
|
outLineA.BooleanIntersection( outLineB );
|
||||||
|
|
||||||
return outLineA.Area();
|
return outLineA.Area();
|
||||||
};
|
};
|
||||||
|
@ -572,7 +572,7 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fillPolySet.Fracture();
|
||||||
|
|
||||||
zone->SetFilledPolysList( layer, fillPolySet );
|
zone->SetFilledPolysList( layer, fillPolySet );
|
||||||
zone->SetIsFilled( true );
|
zone->SetIsFilled( true );
|
||||||
|
@ -880,7 +880,7 @@ FOOTPRINT* PCB_IO_EASYEDAPRO_PARSER::ParseFootprint( const nlohmann::json&
|
|||||||
true );
|
true );
|
||||||
}
|
}
|
||||||
|
|
||||||
polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
polySet.Simplify();
|
||||||
|
|
||||||
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
|
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
|
||||||
|
|
||||||
@ -1158,7 +1158,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
|||||||
zoneFillPoly.AddOutline( contour );
|
zoneFillPoly.AddOutline( contour );
|
||||||
|
|
||||||
zoneFillPoly.RebuildHolesFromContours();
|
zoneFillPoly.RebuildHolesFromContours();
|
||||||
zoneFillPoly.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
zoneFillPoly.Fracture();
|
||||||
|
|
||||||
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
|
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
|
||||||
|
|
||||||
@ -1771,7 +1771,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
|||||||
|
|
||||||
// The contour can be self-intersecting
|
// The contour can be self-intersecting
|
||||||
SHAPE_POLY_SET simple( contour );
|
SHAPE_POLY_SET simple( contour );
|
||||||
simple.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
simple.Simplify();
|
||||||
|
|
||||||
if( dataId == 0 )
|
if( dataId == 0 )
|
||||||
{
|
{
|
||||||
@ -1779,7 +1779,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thisPoly.BooleanSubtract( simple, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
thisPoly.BooleanSubtract( simple );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1801,16 +1801,16 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
|||||||
|
|
||||||
if( !fillPolySet.IsEmpty() )
|
if( !fillPolySet.IsEmpty() )
|
||||||
{
|
{
|
||||||
fillPolySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fillPolySet.Simplify();
|
||||||
|
|
||||||
const int strokeWidth = pcbIUScale.MilsToIU( 8 ); // Seems to be 8 mils
|
const int strokeWidth = pcbIUScale.MilsToIU( 8 ); // Seems to be 8 mils
|
||||||
|
|
||||||
fillPolySet.Inflate( strokeWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
fillPolySet.Inflate( strokeWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
ARC_HIGH_DEF, false );
|
ARC_HIGH_DEF, false );
|
||||||
|
|
||||||
fillPolySet.BooleanAdd( thermalSpokes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fillPolySet.BooleanAdd( thermalSpokes );
|
||||||
|
|
||||||
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
fillPolySet.Fracture();
|
||||||
|
|
||||||
zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
|
zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
|
||||||
zone->SetNeedRefill( false );
|
zone->SetNeedRefill( false );
|
||||||
|
@ -2724,7 +2724,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
poly_outline.Fracture();
|
||||||
|
|
||||||
poly_outline.Move( -newpad->GetPosition() );
|
poly_outline.Move( -newpad->GetPosition() );
|
||||||
|
|
||||||
@ -3324,7 +3324,7 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
|
|||||||
|
|
||||||
SHAPE_POLY_SET poly_outline = loadShapePolySet( aLine->segment );
|
SHAPE_POLY_SET poly_outline = loadShapePolySet( aLine->segment );
|
||||||
|
|
||||||
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
poly_outline.Fracture();
|
||||||
|
|
||||||
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
|
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
|
||||||
return false;
|
return false;
|
||||||
@ -3552,7 +3552,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
|
|||||||
{
|
{
|
||||||
SHAPE_POLY_SET poly_outline = loadShapePolySet( *( geom.elements ) );
|
SHAPE_POLY_SET poly_outline = loadShapePolySet( *( geom.elements ) );
|
||||||
|
|
||||||
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
poly_outline.Fracture();
|
||||||
|
|
||||||
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
|
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
|
||||||
continue;
|
continue;
|
||||||
|
@ -606,7 +606,7 @@ void PCB_IO_IPC2581::addKnockoutText( wxXmlNode* aContentNode, PCB_TEXT* aText )
|
|||||||
SHAPE_POLY_SET finalPoly;
|
SHAPE_POLY_SET finalPoly;
|
||||||
|
|
||||||
aText->TransformTextToPolySet( finalPoly, 0, ARC_HIGH_DEF, ERROR_INSIDE );
|
aText->TransformTextToPolySet( finalPoly, 0, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||||
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
finalPoly.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
|
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
|
||||||
addContourNode( aContentNode, finalPoly, ii );
|
addContourNode( aContentNode, finalPoly, ii );
|
||||||
@ -889,7 +889,7 @@ void PCB_IO_IPC2581::addShape( wxXmlNode* aContentNode, const PAD& aPad, PCB_LAY
|
|||||||
if( expansion.x )
|
if( expansion.x )
|
||||||
{
|
{
|
||||||
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
maxError, SHAPE_POLY_SET::PM_FAST );
|
maxError );
|
||||||
}
|
}
|
||||||
|
|
||||||
addContourNode( entry_node, outline );
|
addContourNode( entry_node, outline );
|
||||||
@ -910,8 +910,7 @@ void PCB_IO_IPC2581::addShape( wxXmlNode* aContentNode, const PAD& aPad, PCB_LAY
|
|||||||
if( expansion != VECTOR2I( 0, 0 ) )
|
if( expansion != VECTOR2I( 0, 0 ) )
|
||||||
{
|
{
|
||||||
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
|
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addContourNode( entry_node, shape );
|
addContourNode( entry_node, shape );
|
||||||
|
@ -2627,8 +2627,7 @@ void PCB_IO_KICAD_LEGACY::loadZONE_CONTAINER()
|
|||||||
|
|
||||||
inflatedFill.InflateWithLinkedHoles( zc->GetMinThickness() / 2,
|
inflatedFill.InflateWithLinkedHoles( zc->GetMinThickness() / 2,
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
ARC_HIGH_DEF / 2,
|
ARC_HIGH_DEF / 2 );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
|
|
||||||
zc->SetFilledPolysList( layer, inflatedFill );
|
zc->SetFilledPolysList( layer, inflatedFill );
|
||||||
}
|
}
|
||||||
|
@ -7231,8 +7231,7 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
|
|||||||
{
|
{
|
||||||
polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
|
polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
ARC_HIGH_DEF / 2,
|
ARC_HIGH_DEF / 2 );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7271,7 +7270,7 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
|
|||||||
TransformOvalToPolygon( segPolygon, seg.A, seg.B, zone->GetMinThickness(),
|
TransformOvalToPolygon( segPolygon, seg.A, seg.B, zone->GetMinThickness(),
|
||||||
ARC_HIGH_DEF, ERROR_OUTSIDE );
|
ARC_HIGH_DEF, ERROR_OUTSIDE );
|
||||||
|
|
||||||
layerFill.BooleanAdd( segPolygon, SHAPE_POLY_SET::PM_FAST );
|
layerFill.BooleanAdd( segPolygon );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ void FEATURES_MANAGER::AddShape( const PCB_SHAPE& aShape, PCB_LAYER_ID aLayer )
|
|||||||
if( soldermask_min_thickness == 0 )
|
if( soldermask_min_thickness == 0 )
|
||||||
{
|
{
|
||||||
poly_set = aShape.GetPolyShape().CloneDropTriangulation();
|
poly_set = aShape.GetPolyShape().CloneDropTriangulation();
|
||||||
poly_set.Fracture( SHAPE_POLY_SET::PM_FAST );
|
poly_set.Fracture();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -152,11 +152,11 @@ void FEATURES_MANAGER::AddShape( const PCB_SHAPE& aShape, PCB_LAYER_ID aLayer )
|
|||||||
aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
|
aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
|
||||||
maxError, ERROR_OUTSIDE );
|
maxError, ERROR_OUTSIDE );
|
||||||
|
|
||||||
poly_set.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly_set.Simplify();
|
||||||
poly_set.Deflate( soldermask_min_thickness / 2 - 1,
|
poly_set.Deflate( soldermask_min_thickness / 2 - 1,
|
||||||
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||||
poly_set.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
|
poly_set.BooleanAdd( initialPolys );
|
||||||
poly_set.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
poly_set.Fracture();
|
||||||
}
|
}
|
||||||
|
|
||||||
int strokeWidth = aShape.GetStroke().GetWidth();
|
int strokeWidth = aShape.GetStroke().GetWidth();
|
||||||
@ -338,7 +338,7 @@ void FEATURES_MANAGER::AddPadShape( const PAD& aPad, PCB_LAYER_ID aLayer )
|
|||||||
if( mask_clearance )
|
if( mask_clearance )
|
||||||
{
|
{
|
||||||
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||||
maxError, SHAPE_POLY_SET::PM_FAST );
|
maxError );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int ii = 0; ii < outline.OutlineCount(); ++ii )
|
for( int ii = 0; ii < outline.OutlineCount(); ++ii )
|
||||||
@ -360,8 +360,7 @@ void FEATURES_MANAGER::AddPadShape( const PAD& aPad, PCB_LAYER_ID aLayer )
|
|||||||
if( expansion != VECTOR2I( 0, 0 ) )
|
if( expansion != VECTOR2I( 0, 0 ) )
|
||||||
{
|
{
|
||||||
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
|
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int ii = 0; ii < shape.OutlineCount(); ++ii )
|
for( int ii = 0; ii < shape.OutlineCount(); ++ii )
|
||||||
@ -644,7 +643,7 @@ void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_I
|
|||||||
|
|
||||||
text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
|
text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
finalpolyset.Fracture( SHAPE_POLY_SET::PM_FAST );
|
finalpolyset.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
|
for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
|
||||||
{
|
{
|
||||||
|
@ -2238,7 +2238,7 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
|
|||||||
{
|
{
|
||||||
SHAPE_POLY_SET finalPoly;
|
SHAPE_POLY_SET finalPoly;
|
||||||
aText->TransformTextToPolySet( finalPoly, 0, m_maxError, ERROR_INSIDE );
|
aText->TransformTextToPolySet( finalPoly, 0, m_maxError, ERROR_INSIDE );
|
||||||
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
finalPoly.Fracture();
|
||||||
|
|
||||||
m_gal->SetIsStroke( false );
|
m_gal->SetIsStroke( false );
|
||||||
m_gal->SetIsFill( true );
|
m_gal->SetIsFill( true );
|
||||||
|
@ -538,7 +538,7 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance,
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
font->Draw( &callback_gal, GetShownText( true ), GetTextPos(), attrs, GetFontMetrics() );
|
font->Draw( &callback_gal, GetShownText( true ), GetTextPos(), attrs, GetFontMetrics() );
|
||||||
textShape.Simplify( SHAPE_POLY_SET::PM_FAST );
|
textShape.Simplify();
|
||||||
|
|
||||||
if( IsKnockout() )
|
if( IsKnockout() )
|
||||||
{
|
{
|
||||||
@ -546,7 +546,7 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance,
|
|||||||
int margin = GetKnockoutTextMargin( attrs.m_Size, penWidth );
|
int margin = GetKnockoutTextMargin( attrs.m_Size, penWidth );
|
||||||
|
|
||||||
buildBoundingHull( &finalPoly, textShape, margin + aClearance );
|
buildBoundingHull( &finalPoly, textShape, margin + aClearance );
|
||||||
finalPoly.BooleanSubtract( textShape, SHAPE_POLY_SET::PM_FAST );
|
finalPoly.BooleanSubtract( textShape );
|
||||||
|
|
||||||
aBuffer.Append( finalPoly );
|
aBuffer.Append( finalPoly );
|
||||||
}
|
}
|
||||||
|
@ -665,7 +665,7 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearanc
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer.Simplify( SHAPE_POLY_SET::PM_FAST );
|
buffer.Simplify();
|
||||||
}
|
}
|
||||||
|
|
||||||
aBuffer.Append( buffer );
|
aBuffer.Append( buffer );
|
||||||
|
@ -860,8 +860,7 @@ static void enclosedByAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itemShape.BooleanSubtract( *aArea->Outline(),
|
itemShape.BooleanSubtract( *aArea->Outline() );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
|
|
||||||
enclosedByArea = itemShape.IsEmpty();
|
enclosedByArea = itemShape.IsEmpty();
|
||||||
}
|
}
|
||||||
|
@ -467,8 +467,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
||||||
// which can create bad shapes if margin.x is < 0
|
// which can create bad shapes if margin.x is < 0
|
||||||
outline.InflateWithLinkedHoles( mask_clearance,
|
outline.InflateWithLinkedHoles( mask_clearance,
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
dummy.DeletePrimitivesList();
|
dummy.DeletePrimitivesList();
|
||||||
dummy.AddPrimitivePoly( aLayer, outline, 0, true );
|
dummy.AddPrimitivePoly( aLayer, outline, 0, true );
|
||||||
|
|
||||||
@ -518,8 +517,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
|
dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
outline.InflateWithLinkedHoles( mask_clearance,
|
outline.InflateWithLinkedHoles( mask_clearance,
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
|
|
||||||
// Initialize the dummy pad shape:
|
// Initialize the dummy pad shape:
|
||||||
dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
|
dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
|
||||||
@ -554,8 +552,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
||||||
// which can create bad shapes if margin.x is < 0
|
// which can create bad shapes if margin.x is < 0
|
||||||
shape.InflateWithLinkedHoles( mask_clearance,
|
shape.InflateWithLinkedHoles( mask_clearance,
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
dummy.DeletePrimitivesList();
|
dummy.DeletePrimitivesList();
|
||||||
dummy.AddPrimitivePoly( aLayer, shape, 0, true );
|
dummy.AddPrimitivePoly( aLayer, shape, 0, true );
|
||||||
|
|
||||||
@ -792,7 +789,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
outlines.RemoveAllContours();
|
outlines.RemoveAllContours();
|
||||||
aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
|
aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
|
||||||
|
|
||||||
outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
|
outlines.Simplify();
|
||||||
|
|
||||||
// Plot outlines
|
// Plot outlines
|
||||||
std::vector<VECTOR2I> cornerList;
|
std::vector<VECTOR2I> cornerList;
|
||||||
@ -1046,7 +1043,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
|
|
||||||
// Merge all polygons: After deflating, not merged (not overlapping) polygons will have the
|
// Merge all polygons: After deflating, not merged (not overlapping) polygons will have the
|
||||||
// initial shape (with perhaps small changes due to deflating transform)
|
// initial shape (with perhaps small changes due to deflating transform)
|
||||||
areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
areas.Simplify();
|
||||||
areas.Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
areas.Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||||
|
|
||||||
// To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
|
// To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
|
||||||
@ -1060,8 +1057,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
|
|
||||||
// Combine the current areas to initial areas. This is mandatory because inflate/deflate
|
// Combine the current areas to initial areas. This is mandatory because inflate/deflate
|
||||||
// transform is not perfect, and we want the initial areas perfectly kept
|
// transform is not perfect, and we want the initial areas perfectly kept
|
||||||
areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
|
areas.BooleanAdd( initialPolys );
|
||||||
areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
areas.Fracture();
|
||||||
|
|
||||||
itemplotter.PlotZone( &zone, layer, areas );
|
itemplotter.PlotZone( &zone, layer, areas );
|
||||||
}
|
}
|
||||||
|
@ -733,7 +733,7 @@ void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, boo
|
|||||||
|
|
||||||
text->TransformTextToPolySet( finalPoly, 0, m_board->GetDesignSettings().m_MaxError,
|
text->TransformTextToPolySet( finalPoly, 0, m_board->GetDesignSettings().m_MaxError,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
finalPoly.Fracture();
|
||||||
|
|
||||||
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
|
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
|
||||||
m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
|
m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
|
||||||
@ -966,7 +966,7 @@ void BRDITEMS_PLOTTER::PlotShape( const PCB_SHAPE* aShape )
|
|||||||
// This must be simplified and fractured to prevent overlapping polygons
|
// This must be simplified and fractured to prevent overlapping polygons
|
||||||
// from generating invalid Gerber files
|
// from generating invalid Gerber files
|
||||||
SHAPE_POLY_SET tmpPoly = aShape->GetPolyShape().CloneDropTriangulation();
|
SHAPE_POLY_SET tmpPoly = aShape->GetPolyShape().CloneDropTriangulation();
|
||||||
tmpPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
tmpPoly.Fracture();
|
||||||
|
|
||||||
if( margin < 0 )
|
if( margin < 0 )
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,7 @@ const SHAPE_LINE_CHAIN HOLE::Hull( int aClearance, int aWalkaroundThickness, int
|
|||||||
BuildHullForPrimitiveShape( shape, aClearance, aWalkaroundThickness ) );
|
BuildHullForPrimitiveShape( shape, aClearance, aWalkaroundThickness ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
hullSet.Simplify();
|
||||||
return hullSet.Outline( 0 );
|
return hullSet.Outline( 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#define __PNS_ITEM_H
|
#define __PNS_ITEM_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <math/vector2d.h>
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, in
|
|||||||
aWalkaroundThickness ) );
|
aWalkaroundThickness ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
hullSet.Simplify();
|
||||||
return hullSet.Outline( 0 );
|
return hullSet.Outline( 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -843,7 +843,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint )
|
|||||||
TransformCircleToPolygon( polyBuffer, graphic->GetEnd() - move,
|
TransformCircleToPolygon( polyBuffer, graphic->GetEnd() - move,
|
||||||
graphic->GetWidth() / 2, ARC_HIGH_DEF, ERROR_INSIDE );
|
graphic->GetWidth() / 2, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||||
|
|
||||||
polyBuffer.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polyBuffer.Simplify();
|
||||||
SHAPE_LINE_CHAIN& poly = polyBuffer.Outline( 0 );
|
SHAPE_LINE_CHAIN& poly = polyBuffer.Outline( 0 );
|
||||||
|
|
||||||
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
||||||
|
@ -388,7 +388,7 @@ bool TEARDROP_MANAGER::computeAnchorPoints( const TEARDROP_PARAMETERS& aParams,
|
|||||||
clipping_rect.Move( ref_on_track );
|
clipping_rect.Move( ref_on_track );
|
||||||
|
|
||||||
// Clip the shape to the max allowed teadrop area
|
// Clip the shape to the max allowed teadrop area
|
||||||
c_buffer.BooleanIntersection( clipping_rect, SHAPE_POLY_SET::PM_FAST );
|
c_buffer.BooleanIntersection( clipping_rect );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* in aPts:
|
/* in aPts:
|
||||||
|
@ -1320,11 +1320,10 @@ static bool mergeZones( EDA_DRAW_FRAME* aFrame, BOARD_COMMIT& aCommit,
|
|||||||
|
|
||||||
for( unsigned int i = 1; i < aOriginZones.size(); i++ )
|
for( unsigned int i = 1; i < aOriginZones.size(); i++ )
|
||||||
{
|
{
|
||||||
aOriginZones[0]->Outline()->BooleanAdd( *aOriginZones[i]->Outline(),
|
aOriginZones[0]->Outline()->BooleanAdd( *aOriginZones[i]->Outline() );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aOriginZones[0]->Outline()->Simplify( SHAPE_POLY_SET::PM_FAST );
|
aOriginZones[0]->Outline()->Simplify();
|
||||||
|
|
||||||
// We should have one polygon, possibly with holes. If we end up with two polygons (either
|
// We should have one polygon, possibly with holes. If we end up with two polygons (either
|
||||||
// because the intersection was a single point or because the intersection was within one of
|
// because the intersection was a single point or because the intersection was within one of
|
||||||
|
@ -373,7 +373,7 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
|
|||||||
polySet.Append( makePolysFromOpenGraphics( selection.GetItems(), 0 ) );
|
polySet.Append( makePolysFromOpenGraphics( selection.GetItems(), 0 ) );
|
||||||
|
|
||||||
polySet.ClearArcs();
|
polySet.ClearArcs();
|
||||||
polySet.Simplify( SHAPE_POLY_SET::PM_FAST );
|
polySet.Simplify();
|
||||||
|
|
||||||
// Now inflate the bounding hull by cfg.m_Gap
|
// Now inflate the bounding hull by cfg.m_Gap
|
||||||
polySet.Inflate( cfg.m_Gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, bds.m_MaxError,
|
polySet.Inflate( cfg.m_Gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, bds.m_MaxError,
|
||||||
|
@ -571,8 +571,7 @@ std::optional<wxString> POLYGON_MERGE_ROUTINE::GetStatusMessage() const
|
|||||||
|
|
||||||
bool POLYGON_MERGE_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
bool POLYGON_MERGE_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
||||||
{
|
{
|
||||||
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
|
GetWorkingPolygons().BooleanAdd( aPolygon );
|
||||||
GetWorkingPolygons().BooleanAdd( aPolygon, poly_mode );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,11 +598,9 @@ std::optional<wxString> POLYGON_SUBTRACT_ROUTINE::GetStatusMessage() const
|
|||||||
|
|
||||||
bool POLYGON_SUBTRACT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
bool POLYGON_SUBTRACT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
||||||
{
|
{
|
||||||
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
|
|
||||||
|
|
||||||
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
|
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
|
||||||
SHAPE_POLY_SET working_copy = working_polygons;
|
SHAPE_POLY_SET working_copy = working_polygons;
|
||||||
working_copy.BooleanSubtract( aPolygon, poly_mode );
|
working_copy.BooleanSubtract( aPolygon );
|
||||||
|
|
||||||
// Subtraction can create holes or delete the polygon
|
// Subtraction can create holes or delete the polygon
|
||||||
// In theory we can allow holes as the EDA_SHAPE will fracture for us, but that's
|
// In theory we can allow holes as the EDA_SHAPE will fracture for us, but that's
|
||||||
@ -642,11 +639,9 @@ std::optional<wxString> POLYGON_INTERSECT_ROUTINE::GetStatusMessage() const
|
|||||||
|
|
||||||
bool POLYGON_INTERSECT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
bool POLYGON_INTERSECT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
|
||||||
{
|
{
|
||||||
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
|
|
||||||
|
|
||||||
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
|
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
|
||||||
SHAPE_POLY_SET working_copy = working_polygons;
|
SHAPE_POLY_SET working_copy = working_polygons;
|
||||||
working_copy.BooleanIntersection( aPolygon, poly_mode );
|
working_copy.BooleanIntersection( aPolygon );
|
||||||
|
|
||||||
// Is there anything left?
|
// Is there anything left?
|
||||||
if( working_copy.OutlineCount() == 0 )
|
if( working_copy.OutlineCount() == 0 )
|
||||||
|
@ -36,7 +36,6 @@ using namespace std::placeholders;
|
|||||||
#include <board.h>
|
#include <board.h>
|
||||||
#include <board_design_settings.h>
|
#include <board_design_settings.h>
|
||||||
#include <board_item.h>
|
#include <board_item.h>
|
||||||
#include <clipper.hpp>
|
|
||||||
#include <pcb_reference_image.h>
|
#include <pcb_reference_image.h>
|
||||||
#include <pcb_track.h>
|
#include <pcb_track.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
|
@ -171,7 +171,7 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
|
|||||||
toolMgr->RunAction( PCB_ACTIONS::selectionClear );
|
toolMgr->RunAction( PCB_ACTIONS::selectionClear );
|
||||||
|
|
||||||
SHAPE_POLY_SET originalOutline( *aZone.Outline() );
|
SHAPE_POLY_SET originalOutline( *aZone.Outline() );
|
||||||
originalOutline.BooleanSubtract( *aCutout.Outline(), SHAPE_POLY_SET::PM_FAST );
|
originalOutline.BooleanSubtract( *aCutout.Outline() );
|
||||||
|
|
||||||
// After substracting the hole, originalOutline can have more than one main outline.
|
// After substracting the hole, originalOutline can have more than one main outline.
|
||||||
// But a zone can have only one main outline, so create as many zones as originalOutline
|
// But a zone can have only one main outline, so create as many zones as originalOutline
|
||||||
|
@ -344,8 +344,7 @@ void TRACKS_CLEANER::deleteTracksInPads()
|
|||||||
track->TransformShapeToPolygon( poly, track->GetLayer(), 0, ARC_HIGH_DEF,
|
track->TransformShapeToPolygon( poly, track->GetLayer(), 0, ARC_HIGH_DEF,
|
||||||
ERROR_INSIDE );
|
ERROR_INSIDE );
|
||||||
|
|
||||||
poly.BooleanSubtract( *pad->GetEffectivePolygon( track->GetLayer(), ERROR_INSIDE ),
|
poly.BooleanSubtract( *pad->GetEffectivePolygon( track->GetLayer(), ERROR_INSIDE ) );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
|
|
||||||
if( poly.IsEmpty() )
|
if( poly.IsEmpty() )
|
||||||
{
|
{
|
||||||
|
@ -991,7 +991,7 @@ void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
|
|||||||
SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
|
SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
|
||||||
|
|
||||||
// Add the cutout back to the zone
|
// Add the cutout back to the zone
|
||||||
m_Poly->BooleanAdd( cutPoly, SHAPE_POLY_SET::PM_FAST );
|
m_Poly->BooleanAdd( cutPoly );
|
||||||
|
|
||||||
SetNeedRefill( true );
|
SetNeedRefill( true );
|
||||||
}
|
}
|
||||||
@ -1434,7 +1434,7 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
|
|||||||
{
|
{
|
||||||
withFillets = flattened;
|
withFillets = flattened;
|
||||||
smooth( withFillets );
|
smooth( withFillets );
|
||||||
withFillets.BooleanAdd( flattened, SHAPE_POLY_SET::PM_FAST );
|
withFillets.BooleanAdd( flattened );
|
||||||
maxExtents = &withFillets;
|
maxExtents = &withFillets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,7 +1466,7 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
|
|||||||
if( diffNetZone->HigherPriority( sameNetZone )
|
if( diffNetZone->HigherPriority( sameNetZone )
|
||||||
&& diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
|
&& diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
|
||||||
{
|
{
|
||||||
diffNetPoly.BooleanAdd( *diffNetZone->Outline(), SHAPE_POLY_SET::PM_FAST );
|
diffNetPoly.BooleanAdd( *diffNetZone->Outline() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1479,19 +1479,19 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
|
|||||||
{
|
{
|
||||||
SHAPE_POLY_SET thisPoly = Outline()->CloneDropTriangulation();
|
SHAPE_POLY_SET thisPoly = Outline()->CloneDropTriangulation();
|
||||||
|
|
||||||
thisPoly.BooleanSubtract( diffNetPoly, SHAPE_POLY_SET::PM_FAST );
|
thisPoly.BooleanSubtract( diffNetPoly );
|
||||||
isolated = thisPoly.OutlineCount() == 0;
|
isolated = thisPoly.OutlineCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isolated )
|
if( !isolated )
|
||||||
{
|
{
|
||||||
sameNetPoly.ClearArcs();
|
sameNetPoly.ClearArcs();
|
||||||
aSmoothedPoly.BooleanAdd( sameNetPoly, SHAPE_POLY_SET::PM_FAST );
|
aSmoothedPoly.BooleanAdd( sameNetPoly );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aBoardOutline )
|
if( aBoardOutline )
|
||||||
aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aSmoothedPoly.BooleanIntersection( *aBoardOutline );
|
||||||
|
|
||||||
SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
|
SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
|
||||||
|
|
||||||
@ -1508,13 +1508,13 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
|
|||||||
poly.Inflate( m_ZoneMinThickness, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
poly.Inflate( m_ZoneMinThickness, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
|
|
||||||
if( !keepExternalFillets )
|
if( !keepExternalFillets )
|
||||||
poly.BooleanIntersection( withSameNetIntersectingZones, SHAPE_POLY_SET::PM_FAST );
|
poly.BooleanIntersection( withSameNetIntersectingZones );
|
||||||
|
|
||||||
*aSmoothedPolyWithApron = aSmoothedPoly;
|
*aSmoothedPolyWithApron = aSmoothedPoly;
|
||||||
aSmoothedPolyWithApron->BooleanIntersection( poly, SHAPE_POLY_SET::PM_FAST );
|
aSmoothedPolyWithApron->BooleanIntersection( poly );
|
||||||
}
|
}
|
||||||
|
|
||||||
aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
|
aSmoothedPoly.BooleanIntersection( *maxExtents );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1576,7 +1576,7 @@ void ZONE::TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aBuffer, int aClea
|
|||||||
polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
|
||||||
}
|
}
|
||||||
|
|
||||||
polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
|
polybuffer.Fracture();
|
||||||
aBuffer.Append( polybuffer );
|
aBuffer.Append( polybuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1612,8 +1612,7 @@ void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer
|
|||||||
if( aErrorLoc == ERROR_OUTSIDE )
|
if( aErrorLoc == ERROR_OUTSIDE )
|
||||||
aClearance += aError;
|
aClearance += aError;
|
||||||
|
|
||||||
temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError,
|
temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aBuffer.Append( temp_buf );
|
aBuffer.Append( temp_buf );
|
||||||
|
@ -796,8 +796,7 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE*>& aZones, bool aCheck, wxWindow*
|
|||||||
|
|
||||||
|
|
||||||
island.AddOutline( test_poly );
|
island.AddOutline( test_poly );
|
||||||
intersection.BooleanIntersection( m_boardOutline, island,
|
intersection.BooleanIntersection( m_boardOutline, island );
|
||||||
SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
|
||||||
|
|
||||||
// Nominally, all of these areas should be either inside or outside the
|
// Nominally, all of these areas should be either inside or outside the
|
||||||
// board outline. So this test should be able to just compare areas (if
|
// board outline. So this test should be able to just compare areas (if
|
||||||
@ -1118,7 +1117,7 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aFill.BooleanSubtract( holes, SHAPE_POLY_SET::PM_FAST );
|
aFill.BooleanSubtract( holes );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1505,7 +1504,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aHoles.Simplify( SHAPE_POLY_SET::PM_FAST );
|
aHoles.Simplify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1533,7 +1532,7 @@ void ZONE_FILLER::subtractHigherPriorityZones( const ZONE* aZone, PCB_LAYER_ID a
|
|||||||
SHAPE_POLY_SET outline = aKnockout->Outline()->CloneDropTriangulation();
|
SHAPE_POLY_SET outline = aKnockout->Outline()->CloneDropTriangulation();
|
||||||
outline.ClearArcs();
|
outline.ClearArcs();
|
||||||
|
|
||||||
aRawFill.BooleanSubtract( outline, SHAPE_POLY_SET::PM_FAST );
|
aRawFill.BooleanSubtract( outline );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1617,7 +1616,7 @@ void ZONE_FILLER::connect_nearby_polys( SHAPE_POLY_SET& aPolys, double aDistance
|
|||||||
{ \
|
{ \
|
||||||
m_board->SetLayerName( b, c ); \
|
m_board->SetLayerName( b, c ); \
|
||||||
SHAPE_POLY_SET d = a; \
|
SHAPE_POLY_SET d = a; \
|
||||||
d.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); \
|
d.Fracture(); \
|
||||||
aFillPolys = d; \
|
aFillPolys = d; \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
@ -1699,7 +1698,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
|
|||||||
// because the "real" subtract-clearance-holes has to be done after the spokes are added.
|
// because the "real" subtract-clearance-holes has to be done after the spokes are added.
|
||||||
static const bool USE_BBOX_CACHES = true;
|
static const bool USE_BBOX_CACHES = true;
|
||||||
SHAPE_POLY_SET testAreas = aFillPolys.CloneDropTriangulation();
|
SHAPE_POLY_SET testAreas = aFillPolys.CloneDropTriangulation();
|
||||||
testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
|
testAreas.BooleanSubtract( clearanceHoles );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( testAreas, In4_Cu, wxT( "minus-clearance-holes" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( testAreas, In4_Cu, wxT( "minus-clearance-holes" ) );
|
||||||
|
|
||||||
// Prune features that don't meet minimum-width criteria
|
// Prune features that don't meet minimum-width criteria
|
||||||
@ -1767,7 +1766,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
|
|||||||
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanSubtract( clearanceHoles );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In8_Cu, wxT( "after-spoke-trimming" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In8_Cu, wxT( "after-spoke-trimming" ) );
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------
|
||||||
@ -1818,7 +1817,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
|
|||||||
* Connect nearby polygons with zero-width lines in order to ensure correct
|
* Connect nearby polygons with zero-width lines in order to ensure correct
|
||||||
* re-inflation.
|
* re-inflation.
|
||||||
*/
|
*/
|
||||||
aFillPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.Fracture();
|
||||||
connect_nearby_polys( aFillPolys, aZone->GetMinThickness() );
|
connect_nearby_polys( aFillPolys, aZone->GetMinThickness() );
|
||||||
|
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In10_Cu, wxT( "connected-nearby-polys" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In10_Cu, wxT( "connected-nearby-polys" ) );
|
||||||
@ -1845,9 +1844,9 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
|
|||||||
for( PAD* pad : thermalConnectionPads )
|
for( PAD* pad : thermalConnectionPads )
|
||||||
addHoleKnockout( pad, 0, clearanceHoles );
|
addHoleKnockout( pad, 0, clearanceHoles );
|
||||||
|
|
||||||
aFillPolys.BooleanIntersection( aMaxExtents, SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanIntersection( aMaxExtents );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In16_Cu, wxT( "after-trim-to-outline" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In16_Cu, wxT( "after-trim-to-outline" ) );
|
||||||
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanSubtract( clearanceHoles );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In17_Cu, wxT( "after-trim-to-clearance-holes" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In17_Cu, wxT( "after-trim-to-clearance-holes" ) );
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------
|
||||||
@ -1857,7 +1856,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
|
|||||||
subtractHigherPriorityZones( aZone, aLayer, aFillPolys );
|
subtractHigherPriorityZones( aZone, aLayer, aFillPolys );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In18_Cu, wxT( "minus-higher-priority-zones" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In18_Cu, wxT( "minus-higher-priority-zones" ) );
|
||||||
|
|
||||||
aFillPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.Fracture();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1911,7 +1910,7 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
aFillPolys = aSmoothedOutline;
|
aFillPolys = aSmoothedOutline;
|
||||||
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanSubtract( clearanceHoles );
|
||||||
|
|
||||||
for( ZONE* keepout : m_board->Zones() )
|
for( ZONE* keepout : m_board->Zones() )
|
||||||
{
|
{
|
||||||
@ -1927,13 +1926,13 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|||||||
{
|
{
|
||||||
if( keepout->Outline()->ArcCount() == 0 )
|
if( keepout->Outline()->ArcCount() == 0 )
|
||||||
{
|
{
|
||||||
aFillPolys.BooleanSubtract( *keepout->Outline(), SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanSubtract( *keepout->Outline() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET keepoutOutline( *keepout->Outline() );
|
SHAPE_POLY_SET keepoutOutline( *keepout->Outline() );
|
||||||
keepoutOutline.ClearArcs();
|
keepoutOutline.ClearArcs();
|
||||||
aFillPolys.BooleanSubtract( keepoutOutline, SHAPE_POLY_SET::PM_FAST );
|
aFillPolys.BooleanSubtract( keepoutOutline );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1958,7 +1957,7 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|||||||
if( half_min_width - epsilon > epsilon )
|
if( half_min_width - epsilon > epsilon )
|
||||||
aFillPolys.Inflate( half_min_width - epsilon, CORNER_STRATEGY::ROUND_ALL_CORNERS, m_maxError );
|
aFillPolys.Inflate( half_min_width - epsilon, CORNER_STRATEGY::ROUND_ALL_CORNERS, m_maxError );
|
||||||
|
|
||||||
aFillPolys.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aFillPolys.Fracture();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2375,12 +2374,12 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
|
|||||||
SHAPE_POLY_SET deflatedFilledPolys = aFillPolys.CloneDropTriangulation();
|
SHAPE_POLY_SET deflatedFilledPolys = aFillPolys.CloneDropTriangulation();
|
||||||
deflatedFilledPolys.Deflate( outline_margin - aZone->GetMinThickness(),
|
deflatedFilledPolys.Deflate( outline_margin - aZone->GetMinThickness(),
|
||||||
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||||
holes.BooleanIntersection( deflatedFilledPolys, SHAPE_POLY_SET::PM_FAST );
|
holes.BooleanIntersection( deflatedFilledPolys );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( holes, In11_Cu, wxT( "fill-clipped-hatch-holes" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( holes, In11_Cu, wxT( "fill-clipped-hatch-holes" ) );
|
||||||
|
|
||||||
SHAPE_POLY_SET deflatedOutline = aZone->Outline()->CloneDropTriangulation();
|
SHAPE_POLY_SET deflatedOutline = aZone->Outline()->CloneDropTriangulation();
|
||||||
deflatedOutline.Deflate( outline_margin, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
deflatedOutline.Deflate( outline_margin, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||||
holes.BooleanIntersection( deflatedOutline, SHAPE_POLY_SET::PM_FAST );
|
holes.BooleanIntersection( deflatedOutline );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( holes, In12_Cu, wxT( "outline-clipped-hatch-holes" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( holes, In12_Cu, wxT( "outline-clipped-hatch-holes" ) );
|
||||||
|
|
||||||
if( aZone->GetNetCode() != 0 )
|
if( aZone->GetNetCode() != 0 )
|
||||||
@ -2438,7 +2437,7 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
holes.BooleanSubtract( aprons, SHAPE_POLY_SET::PM_FAST );
|
holes.BooleanSubtract( aprons );
|
||||||
}
|
}
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( holes, In13_Cu, wxT( "pad-via-clipped-hatch-holes" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( holes, In13_Cu, wxT( "pad-via-clipped-hatch-holes" ) );
|
||||||
|
|
||||||
@ -2454,9 +2453,9 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
|
|||||||
++ii;
|
++ii;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create grid. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
|
// create grid. Useto
|
||||||
// generate strictly simple polygons needed by Gerber files and Fracture()
|
// generate strictly simple polygons needed by Gerber files and Fracture()
|
||||||
aFillPolys.BooleanSubtract( aFillPolys, holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
aFillPolys.BooleanSubtract( aFillPolys, holes );
|
||||||
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In14_Cu, wxT( "after-hatching" ) );
|
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In14_Cu, wxT( "after-hatching" ) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -131,21 +131,6 @@ BOOST_AUTO_TEST_CASE( ClipperConstructorCase1 )
|
|||||||
// Case of an arc followed by a segment
|
// Case of an arc followed by a segment
|
||||||
// The clipper path is not in order (on purpose), to simulate the typical return from clipper
|
// The clipper path is not in order (on purpose), to simulate the typical return from clipper
|
||||||
|
|
||||||
ClipperLib::Path pathClipper1 = {
|
|
||||||
{ { 125663951, 120099260, 24 }, { 125388111, 120170850, 25 }, { 125124975, 120280270, 26 },
|
|
||||||
{ 124879705, 120425376, 27 }, { 124657110, 120603322, 28 }, { 124461556, 120810617, 29 },
|
|
||||||
{ 124296876, 121043198, 30 }, { 124166301, 121296503, 31 }, { 124072391, 121565564, 32 },
|
|
||||||
{ 124016988, 121845106, 33 }, { 124001177, 122129646, 34 }, { 124025270, 122413605, 35 },
|
|
||||||
{ 124088794, 122691414, 36 }, { 124190502, 122957625, 37 }, { 124328401, 123207018, 38 },
|
|
||||||
{ 124499787, 123434703, 39 }, { 124598846, 123537154, 40 }, { 127171000, 123786000, 4 },
|
|
||||||
{ 127287862, 123704439, 5 }, { 127499716, 123513831, 6 }, { 127682866, 123295498, 7 },
|
|
||||||
{ 127833720, 123053722, 8 }, { 127949321, 122793242, 9 }, { 128027402, 122519168, 10 },
|
|
||||||
{ 128066430, 122236874, 11 }, { 128065642, 121951896, 12 }, { 128025053, 121669823, 13 },
|
|
||||||
{ 127945457, 121396185, 14 }, { 127828417, 121136349, 15 }, { 127676227, 120895410, 16 },
|
|
||||||
{ 127491873, 120678094, 17 }, { 127278968, 120488661, 18 }, { 127041689, 120330827, 19 },
|
|
||||||
{ 126784688, 120207687, 20 }, { 126513005, 120121655, 21 }, { 126231968, 120074419, 22 },
|
|
||||||
{ 125947087, 120066905, 23 } }
|
|
||||||
};
|
|
||||||
Clipper2Lib::Path64 pathClipper2 = {
|
Clipper2Lib::Path64 pathClipper2 = {
|
||||||
{ { 125663951, 120099260, 24 }, { 125388111, 120170850, 25 }, { 125124975, 120280270, 26 },
|
{ { 125663951, 120099260, 24 }, { 125388111, 120170850, 25 }, { 125124975, 120280270, 26 },
|
||||||
{ 124879705, 120425376, 27 }, { 124657110, 120603322, 28 }, { 124461556, 120810617, 29 },
|
{ 124879705, 120425376, 27 }, { 124657110, 120603322, 28 }, { 124461556, 120810617, 29 },
|
||||||
@ -180,22 +165,16 @@ BOOST_AUTO_TEST_CASE( ClipperConstructorCase1 )
|
|||||||
SHAPE_ARC( { 127171000, 123786000 }, { 126231718, 120077003 }, { 124598846, 123537154 }, 0 )
|
SHAPE_ARC( { 127171000, 123786000 }, { 126231718, 120077003 }, { 124598846, 123537154 }, 0 )
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN clipper1chain( pathClipper1, z_values, arcs );
|
|
||||||
SHAPE_LINE_CHAIN clipper2chain( pathClipper2, z_values, arcs );
|
SHAPE_LINE_CHAIN clipper2chain( pathClipper2, z_values, arcs );
|
||||||
|
|
||||||
BOOST_CHECK( GEOM_TEST::IsOutlineValid( clipper1chain ) );
|
|
||||||
BOOST_CHECK( GEOM_TEST::IsOutlineValid( clipper2chain ) );
|
BOOST_CHECK( GEOM_TEST::IsOutlineValid( clipper2chain ) );
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( clipper1chain.PointCount(), 37 );
|
|
||||||
BOOST_CHECK_EQUAL( clipper2chain.PointCount(), 37 );
|
BOOST_CHECK_EQUAL( clipper2chain.PointCount(), 37 );
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( clipper1chain.ArcCount(), 1 );
|
|
||||||
BOOST_CHECK_EQUAL( clipper2chain.ArcCount(), 1 );
|
BOOST_CHECK_EQUAL( clipper2chain.ArcCount(), 1 );
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( clipper1chain.ShapeCount(), 2 );
|
|
||||||
BOOST_CHECK_EQUAL( clipper2chain.ShapeCount(), 2 );
|
BOOST_CHECK_EQUAL( clipper2chain.ShapeCount(), 2 );
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( clipper1chain.IsClosed(), true );
|
|
||||||
BOOST_CHECK_EQUAL( clipper2chain.IsClosed(), true );
|
BOOST_CHECK_EQUAL( clipper2chain.IsClosed(), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE( TestSimplify )
|
|||||||
{
|
{
|
||||||
BOOST_TEST_CONTEXT( "Simplify Iteration " << i )
|
BOOST_TEST_CONTEXT( "Simplify Iteration " << i )
|
||||||
{
|
{
|
||||||
testPoly.Simplify( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
|
testPoly.Simplify();
|
||||||
|
|
||||||
std::vector<SHAPE_ARC> foundArcs;
|
std::vector<SHAPE_ARC> foundArcs;
|
||||||
testPoly.GetArcs( foundArcs );
|
testPoly.GetArcs( foundArcs );
|
||||||
@ -119,14 +119,14 @@ BOOST_AUTO_TEST_CASE( TestIntersectUnion )
|
|||||||
double opPolyArea = opPoly.Area();
|
double opPolyArea = opPoly.Area();
|
||||||
|
|
||||||
SHAPE_POLY_SET intersectionPoly = testPoly;
|
SHAPE_POLY_SET intersectionPoly = testPoly;
|
||||||
intersectionPoly.BooleanIntersection( opPoly, SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
|
intersectionPoly.BooleanIntersection( opPoly );
|
||||||
double intersectArea = intersectionPoly.Area();
|
double intersectArea = intersectionPoly.Area();
|
||||||
|
|
||||||
BOOST_CHECK( GEOM_TEST::IsPolySetValid( intersectionPoly ) );
|
BOOST_CHECK( GEOM_TEST::IsPolySetValid( intersectionPoly ) );
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET unionPoly = testPoly;
|
SHAPE_POLY_SET unionPoly = testPoly;
|
||||||
unionPoly.BooleanAdd( opPoly, SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
|
unionPoly.BooleanAdd( opPoly );
|
||||||
double unionArea = unionPoly.Area();
|
double unionArea = unionPoly.Area();
|
||||||
|
|
||||||
BOOST_CHECK( GEOM_TEST::IsPolySetValid( unionPoly ) );
|
BOOST_CHECK( GEOM_TEST::IsPolySetValid( unionPoly ) );
|
||||||
|
@ -158,8 +158,7 @@ BOOST_FIXTURE_TEST_CASE( NotchedZones, ZONE_FILL_TEST_FIXTURE )
|
|||||||
{
|
{
|
||||||
if( zone->GetLayerSet().Contains( F_Cu ) )
|
if( zone->GetLayerSet().Contains( F_Cu ) )
|
||||||
{
|
{
|
||||||
frontCopper.BooleanAdd( *zone->GetFilledPolysList( F_Cu ),
|
frontCopper.BooleanAdd( *zone->GetFilledPolysList( F_Cu ) );
|
||||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ int runDRCProto( PROJECT_CONTEXT project, std::shared_ptr<KIGFX::VIEW_OVERLAY> a
|
|||||||
{
|
{
|
||||||
drcEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
|
drcEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
|
||||||
}
|
}
|
||||||
catch( const ClipperLib::clipperException& e )
|
catch( const Clipper2Lib::Clipper2Exception& e )
|
||||||
{
|
{
|
||||||
consoleLog.Print( wxString::Format( "Clipper exception %s occurred.", e.what() ) );
|
consoleLog.Print( wxString::Format( "Clipper exception %s occurred.", e.what() ) );
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ int polygon_triangulation_main( int argc, char *argv[] )
|
|||||||
ignore_unused( poly );
|
ignore_unused( poly );
|
||||||
#if 0
|
#if 0
|
||||||
PROF_TIMER unfrac("unfrac");
|
PROF_TIMER unfrac("unfrac");
|
||||||
poly.Unfracture( SHAPE_POLY_SET::PM_FAST );
|
poly.Unfracture();
|
||||||
unfrac.Show();
|
unfrac.Show();
|
||||||
|
|
||||||
PROF_TIMER triangulate("triangulate");
|
PROF_TIMER triangulate("triangulate");
|
||||||
|
@ -307,12 +307,12 @@ int playground_main_func( int argc, char* argv[] )
|
|||||||
|
|
||||||
SHAPE_POLY_SET xorPad1ToPad2 = pad1Outline;
|
SHAPE_POLY_SET xorPad1ToPad2 = pad1Outline;
|
||||||
|
|
||||||
xorPad1ToPad2.BooleanXor( pad2Outline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
xorPad1ToPad2.BooleanXor( pad2Outline );
|
||||||
xorPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 10 ), 0 ) );
|
xorPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 10 ), 0 ) );
|
||||||
|
|
||||||
SHAPE_POLY_SET andPad1ToPad2 = pad2Outline;
|
SHAPE_POLY_SET andPad1ToPad2 = pad2Outline;
|
||||||
|
|
||||||
andPad1ToPad2.BooleanIntersection( pad1Outline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
andPad1ToPad2.BooleanIntersection( pad1Outline );
|
||||||
andPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 20 ), 0 ) );
|
andPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 20 ), 0 ) );
|
||||||
|
|
||||||
std::shared_ptr<SHAPE_SEGMENT> slot = pad2.GetEffectiveHoleShape();
|
std::shared_ptr<SHAPE_SEGMENT> slot = pad2.GetEffectiveHoleShape();
|
||||||
|
1
thirdparty/CMakeLists.txt
vendored
1
thirdparty/CMakeLists.txt
vendored
@ -34,7 +34,6 @@ set( CMAKE_POLICY_DEFAULT_CMP0077 NEW )
|
|||||||
|
|
||||||
set( ARGPARSE_INSTALL OFF )
|
set( ARGPARSE_INSTALL OFF )
|
||||||
add_subdirectory( argparse )
|
add_subdirectory( argparse )
|
||||||
add_subdirectory( clipper )
|
|
||||||
add_subdirectory( clipper2 )
|
add_subdirectory( clipper2 )
|
||||||
add_subdirectory( compoundfilereader )
|
add_subdirectory( compoundfilereader )
|
||||||
add_subdirectory( delaunator )
|
add_subdirectory( delaunator )
|
||||||
|
9
thirdparty/clipper/CMakeLists.txt
vendored
9
thirdparty/clipper/CMakeLists.txt
vendored
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
add_library( clipper OBJECT
|
|
||||||
clipper.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories( clipper
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
23
thirdparty/clipper/LICENSE.BOOSTv1_0
vendored
23
thirdparty/clipper/LICENSE.BOOSTv1_0
vendored
@ -1,23 +0,0 @@
|
|||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
4
thirdparty/clipper/README.txt
vendored
4
thirdparty/clipper/README.txt
vendored
@ -1,4 +0,0 @@
|
|||||||
This directory contains the Clipper library for interacting with polygons.
|
|
||||||
https://sourceforge.net/projects/polyclipping/
|
|
||||||
|
|
||||||
It is licensed under the Boost Software License, with the license text in this directory.
|
|
5999
thirdparty/clipper/clipper.cpp
vendored
5999
thirdparty/clipper/clipper.cpp
vendored
File diff suppressed because it is too large
Load Diff
457
thirdparty/clipper/clipper.hpp
vendored
457
thirdparty/clipper/clipper.hpp
vendored
@ -1,457 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* *
|
|
||||||
* Author : Angus Johnson *
|
|
||||||
* Version : 6.4.2 *
|
|
||||||
* Date : 27 February 2017 *
|
|
||||||
* Website : http://www.angusj.com *
|
|
||||||
* Copyright : Angus Johnson 2010-2017 *
|
|
||||||
* *
|
|
||||||
* License: *
|
|
||||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
|
||||||
* http://www.boost.org/LICENSE_1_0.txt *
|
|
||||||
* *
|
|
||||||
* Attributions: *
|
|
||||||
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
|
|
||||||
* "A generic solution to polygon clipping" *
|
|
||||||
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
|
|
||||||
* http://portal.acm.org/citation.cfm?id=129906 *
|
|
||||||
* *
|
|
||||||
* Computer graphics and geometric modeling: implementation and algorithms *
|
|
||||||
* By Max K. Agoston *
|
|
||||||
* Springer; 1 edition (January 4, 2005) *
|
|
||||||
* http://books.google.com/books?q=vatti+clipping+agoston *
|
|
||||||
* *
|
|
||||||
* See also: *
|
|
||||||
* "Polygon Offsetting by Computing Winding Numbers" *
|
|
||||||
* Paper no. DETC2005-85513 pp. 565-575 *
|
|
||||||
* ASME 2005 International Design Engineering Technical Conferences *
|
|
||||||
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
|
|
||||||
* September 24-28, 2005 , Long Beach, California, USA *
|
|
||||||
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
|
|
||||||
* *
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef clipper_hpp
|
|
||||||
#define clipper_hpp
|
|
||||||
|
|
||||||
#define CLIPPER_VERSION "6.4.2"
|
|
||||||
|
|
||||||
// use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
|
||||||
// improve performance but coordinate values are limited to the range +/- 46340
|
|
||||||
// #define use_int32
|
|
||||||
|
|
||||||
// use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
|
|
||||||
#define use_xyz
|
|
||||||
|
|
||||||
// use_lines: Enables line clipping. Adds a very minor cost to performance.
|
|
||||||
#define use_lines
|
|
||||||
|
|
||||||
// use_deprecated: Enables temporary support for the obsolete functions
|
|
||||||
// #define use_deprecated
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <set>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <ostream>
|
|
||||||
#include <functional>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace ClipperLib {
|
|
||||||
enum ClipType
|
|
||||||
{
|
|
||||||
ctIntersection, ctUnion, ctDifference, ctXor
|
|
||||||
};
|
|
||||||
enum PolyType
|
|
||||||
{
|
|
||||||
ptSubject, ptClip
|
|
||||||
};
|
|
||||||
// By far the most widely used winding rules for polygon filling are
|
|
||||||
// EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
|
|
||||||
// Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
|
|
||||||
// see http://glprogramming.com/red/chapter11.html
|
|
||||||
enum PolyFillType
|
|
||||||
{
|
|
||||||
pftEvenOdd, pftNonZero, pftPositive, pftNegative
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef use_int32
|
|
||||||
typedef int cInt;
|
|
||||||
static cInt const loRange = 0x7FFF;
|
|
||||||
static cInt const hiRange = 0x7FFF;
|
|
||||||
#else
|
|
||||||
typedef signed long long cInt;
|
|
||||||
static cInt const loRange = 0x3FFFFFFF;
|
|
||||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
|
||||||
typedef signed long long long64; // used by Int128 class
|
|
||||||
typedef unsigned long long ulong64;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct IntPoint
|
|
||||||
{
|
|
||||||
cInt X;
|
|
||||||
cInt Y;
|
|
||||||
#ifdef use_xyz
|
|
||||||
cInt Z;
|
|
||||||
IntPoint( cInt x = 0, cInt y = 0, cInt z = 0 ) : X( x ), Y( y ), Z( z ) {};
|
|
||||||
#else
|
|
||||||
IntPoint( cInt x = 0, cInt y = 0 ) : X( x ), Y( y ) {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend inline bool operator==( const IntPoint& a, const IntPoint& b )
|
|
||||||
{
|
|
||||||
return a.X == b.X && a.Y == b.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend inline bool operator!=( const IntPoint& a, const IntPoint& b )
|
|
||||||
{
|
|
||||||
return a.X != b.X || a.Y != b.Y;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef std::vector<IntPoint> Path;
|
|
||||||
typedef std::vector<Path> Paths;
|
|
||||||
|
|
||||||
inline Path& operator <<( Path& poly, const IntPoint& p )
|
|
||||||
{
|
|
||||||
poly.push_back( p ); return poly;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline Paths& operator <<( Paths& polys, const Path& p )
|
|
||||||
{
|
|
||||||
polys.push_back( p ); return polys;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::ostream& operator <<( std::ostream& s, const IntPoint& p );
|
|
||||||
std::ostream& operator <<( std::ostream& s, const Path& p );
|
|
||||||
std::ostream& operator <<( std::ostream& s, const Paths& p );
|
|
||||||
|
|
||||||
struct DoublePoint
|
|
||||||
{
|
|
||||||
double X;
|
|
||||||
double Y;
|
|
||||||
DoublePoint( double x = 0, double y = 0 ) : X( x ), Y( y ) {}
|
|
||||||
DoublePoint( IntPoint ip ) : X( (double) ip.X ), Y( (double) ip.Y ) {}
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef use_xyz
|
|
||||||
typedef std::function<void( IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top,
|
|
||||||
IntPoint& pt )> ZFillCallback;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum InitOptions
|
|
||||||
{
|
|
||||||
ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4
|
|
||||||
};
|
|
||||||
enum JoinType
|
|
||||||
{
|
|
||||||
jtSquare, jtRound, jtMiter
|
|
||||||
};
|
|
||||||
enum EndType
|
|
||||||
{
|
|
||||||
etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound
|
|
||||||
};
|
|
||||||
|
|
||||||
class PolyNode;
|
|
||||||
typedef std::vector<PolyNode*> PolyNodes;
|
|
||||||
|
|
||||||
class PolyNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PolyNode();
|
|
||||||
virtual ~PolyNode() {};
|
|
||||||
Path Contour;
|
|
||||||
PolyNodes Childs;
|
|
||||||
PolyNode* Parent;
|
|
||||||
PolyNode* GetNext() const;
|
|
||||||
bool IsHole() const;
|
|
||||||
bool IsOpen() const;
|
|
||||||
int ChildCount() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// PolyNode& operator =(PolyNode& other);
|
|
||||||
unsigned Index; // node index in Parent.Childs
|
|
||||||
bool m_IsOpen;
|
|
||||||
JoinType m_jointype;
|
|
||||||
EndType m_endtype;
|
|
||||||
PolyNode* GetNextSiblingUp() const;
|
|
||||||
void AddChild( PolyNode& child );
|
|
||||||
|
|
||||||
friend class Clipper; // to access Index
|
|
||||||
friend class ClipperOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PolyTree : public PolyNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~PolyTree() { Clear(); };
|
|
||||||
PolyNode* GetFirst() const;
|
|
||||||
void Clear();
|
|
||||||
int Total() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// PolyTree& operator =(PolyTree& other);
|
|
||||||
PolyNodes AllNodes;
|
|
||||||
friend class Clipper; // to access AllNodes
|
|
||||||
};
|
|
||||||
|
|
||||||
bool Orientation( const Path& poly );
|
|
||||||
double Area( const Path& poly );
|
|
||||||
int PointInPolygon( const IntPoint& pt, const Path& path );
|
|
||||||
|
|
||||||
void SimplifyPolygon( const Path& in_poly, Paths& out_polys,
|
|
||||||
PolyFillType fillType = pftEvenOdd );
|
|
||||||
void SimplifyPolygons( const Paths& in_polys,
|
|
||||||
Paths& out_polys,
|
|
||||||
PolyFillType fillType = pftEvenOdd );
|
|
||||||
void SimplifyPolygons( Paths& polys, PolyFillType fillType = pftEvenOdd );
|
|
||||||
|
|
||||||
void CleanPolygon( const Path& in_poly, Path& out_poly, double distance = 1.415 );
|
|
||||||
void CleanPolygon( Path& poly, double distance = 1.415 );
|
|
||||||
void CleanPolygons( const Paths& in_polys, Paths& out_polys, double distance = 1.415 );
|
|
||||||
void CleanPolygons( Paths& polys, double distance = 1.415 );
|
|
||||||
|
|
||||||
void MinkowskiSum( const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed );
|
|
||||||
void MinkowskiSum( const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed );
|
|
||||||
void MinkowskiDiff( const Path& poly1, const Path& poly2, Paths& solution );
|
|
||||||
|
|
||||||
void PolyTreeToPaths( const PolyTree& polytree, Paths& paths );
|
|
||||||
void ClosedPathsFromPolyTree( const PolyTree& polytree, Paths& paths );
|
|
||||||
void OpenPathsFromPolyTree( PolyTree& polytree, Paths& paths );
|
|
||||||
|
|
||||||
void ReversePath( Path& p );
|
|
||||||
void ReversePaths( Paths& p );
|
|
||||||
|
|
||||||
struct IntRect
|
|
||||||
{
|
|
||||||
cInt left; cInt top; cInt right; cInt bottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
// enums that are used internally ...
|
|
||||||
enum EdgeSide
|
|
||||||
{
|
|
||||||
esLeft = 1, esRight = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// forward declarations (for stuff used internally) ...
|
|
||||||
struct TEdge;
|
|
||||||
struct IntersectNode;
|
|
||||||
struct LocalMinimum;
|
|
||||||
struct OutPt;
|
|
||||||
struct OutRec;
|
|
||||||
struct Join;
|
|
||||||
|
|
||||||
typedef std::vector <OutRec*> PolyOutList;
|
|
||||||
typedef std::vector <TEdge*> EdgeList;
|
|
||||||
typedef std::vector <Join*> JoinList;
|
|
||||||
typedef std::vector <IntersectNode*> IntersectList;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// ClipperBase is the ancestor to the Clipper class. It should not be
|
|
||||||
// instantiated directly. This class simply abstracts the conversion of sets of
|
|
||||||
// polygon coordinates into edge objects that are stored in a LocalMinima list.
|
|
||||||
class ClipperBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClipperBase();
|
|
||||||
virtual ~ClipperBase();
|
|
||||||
virtual bool AddPath( const Path& pg, PolyType PolyTyp, bool Closed );
|
|
||||||
bool AddPaths( const Paths& ppg, PolyType PolyTyp, bool Closed );
|
|
||||||
virtual void Clear();
|
|
||||||
IntRect GetBounds();
|
|
||||||
|
|
||||||
bool PreserveCollinear() { return m_PreserveCollinear; };
|
|
||||||
void PreserveCollinear( bool value ) { m_PreserveCollinear = value; };
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void DisposeLocalMinimaList();
|
|
||||||
TEdge* AddBoundsToLML( TEdge* e, bool IsClosed );
|
|
||||||
virtual void Reset();
|
|
||||||
TEdge* ProcessBound( TEdge* E, bool IsClockwise );
|
|
||||||
void InsertScanbeam( const cInt Y );
|
|
||||||
bool PopScanbeam( cInt& Y );
|
|
||||||
bool LocalMinimaPending();
|
|
||||||
bool PopLocalMinima( cInt Y, const LocalMinimum*& locMin );
|
|
||||||
OutRec* CreateOutRec();
|
|
||||||
void DisposeAllOutRecs();
|
|
||||||
void DisposeOutRec( PolyOutList::size_type index );
|
|
||||||
void SwapPositionsInAEL( TEdge* edge1, TEdge* edge2 );
|
|
||||||
void DeleteFromAEL( TEdge* e );
|
|
||||||
void UpdateEdgeIntoAEL( TEdge*& e );
|
|
||||||
|
|
||||||
typedef std::vector<LocalMinimum> MinimaList;
|
|
||||||
MinimaList::iterator m_CurrentLM;
|
|
||||||
MinimaList m_MinimaList;
|
|
||||||
|
|
||||||
bool m_UseFullRange;
|
|
||||||
EdgeList m_edges;
|
|
||||||
bool m_PreserveCollinear;
|
|
||||||
bool m_HasOpenPaths;
|
|
||||||
PolyOutList m_PolyOuts;
|
|
||||||
TEdge* m_ActiveEdges;
|
|
||||||
|
|
||||||
typedef std::priority_queue<cInt> ScanbeamList;
|
|
||||||
ScanbeamList m_Scanbeam;
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class Clipper : public virtual ClipperBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Clipper( int initOptions = 0 );
|
|
||||||
bool Execute( ClipType clipType,
|
|
||||||
Paths& solution,
|
|
||||||
PolyFillType fillType = pftEvenOdd );
|
|
||||||
bool Execute( ClipType clipType,
|
|
||||||
Paths& solution,
|
|
||||||
PolyFillType subjFillType,
|
|
||||||
PolyFillType clipFillType );
|
|
||||||
bool Execute( ClipType clipType,
|
|
||||||
PolyTree& polytree,
|
|
||||||
PolyFillType fillType = pftEvenOdd );
|
|
||||||
bool Execute( ClipType clipType,
|
|
||||||
PolyTree& polytree,
|
|
||||||
PolyFillType subjFillType,
|
|
||||||
PolyFillType clipFillType );
|
|
||||||
|
|
||||||
bool ReverseSolution() { return m_ReverseOutput; };
|
|
||||||
void ReverseSolution( bool value ) { m_ReverseOutput = value; };
|
|
||||||
bool StrictlySimple() { return m_StrictSimple; };
|
|
||||||
void StrictlySimple( bool value ) { m_StrictSimple = value; };
|
|
||||||
// set the callback function for z value filling on intersections (otherwise Z is 0)
|
|
||||||
#ifdef use_xyz
|
|
||||||
void ZFillFunction( ZFillCallback zFillFunc );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool ExecuteInternal();
|
|
||||||
|
|
||||||
private:
|
|
||||||
JoinList m_Joins;
|
|
||||||
JoinList m_GhostJoins;
|
|
||||||
IntersectList m_IntersectList;
|
|
||||||
ClipType m_ClipType;
|
|
||||||
typedef std::list<cInt> MaximaList;
|
|
||||||
MaximaList m_Maxima;
|
|
||||||
TEdge* m_SortedEdges;
|
|
||||||
bool m_ExecuteLocked;
|
|
||||||
PolyFillType m_ClipFillType;
|
|
||||||
PolyFillType m_SubjFillType;
|
|
||||||
bool m_ReverseOutput;
|
|
||||||
bool m_UsingPolyTree;
|
|
||||||
bool m_StrictSimple;
|
|
||||||
#ifdef use_xyz
|
|
||||||
ZFillCallback m_ZFill; // custom callback
|
|
||||||
#endif
|
|
||||||
void SetWindingCount( TEdge& edge );
|
|
||||||
bool IsEvenOddFillType( const TEdge& edge ) const;
|
|
||||||
bool IsEvenOddAltFillType( const TEdge& edge ) const;
|
|
||||||
void InsertLocalMinimaIntoAEL( const cInt botY );
|
|
||||||
void InsertEdgeIntoAEL( TEdge* edge, TEdge* startEdge );
|
|
||||||
void AddEdgeToSEL( TEdge* edge );
|
|
||||||
bool PopEdgeFromSEL( TEdge*& edge );
|
|
||||||
void CopyAELToSEL();
|
|
||||||
void DeleteFromSEL( TEdge* e );
|
|
||||||
void SwapPositionsInSEL( TEdge* edge1, TEdge* edge2 );
|
|
||||||
bool IsContributing( const TEdge& edge ) const;
|
|
||||||
bool IsTopHorz( const cInt XPos );
|
|
||||||
void DoMaxima( TEdge* e );
|
|
||||||
void ProcessHorizontals();
|
|
||||||
void ProcessHorizontal( TEdge* horzEdge );
|
|
||||||
void AddLocalMaxPoly( TEdge* e1, TEdge* e2, const IntPoint& pt );
|
|
||||||
OutPt* AddLocalMinPoly( TEdge* e1, TEdge* e2, const IntPoint& pt );
|
|
||||||
OutRec* GetOutRec( int idx );
|
|
||||||
void AppendPolygon( TEdge* e1, TEdge* e2 );
|
|
||||||
void IntersectEdges( TEdge* e1, TEdge* e2, IntPoint& pt );
|
|
||||||
OutPt* AddOutPt( TEdge* e, const IntPoint& pt );
|
|
||||||
OutPt* GetLastOutPt( TEdge* e );
|
|
||||||
bool ProcessIntersections( const cInt topY );
|
|
||||||
void BuildIntersectList( const cInt topY );
|
|
||||||
void ProcessIntersectList();
|
|
||||||
void ProcessEdgesAtTopOfScanbeam( const cInt topY );
|
|
||||||
void BuildResult( Paths& polys );
|
|
||||||
void BuildResult2( PolyTree& polytree );
|
|
||||||
void SetHoleState( TEdge* e, OutRec* outrec );
|
|
||||||
void DisposeIntersectNodes();
|
|
||||||
bool FixupIntersectionOrder();
|
|
||||||
void FixupOutPolygon( OutRec& outrec );
|
|
||||||
void FixupOutPolyline( OutRec& outrec );
|
|
||||||
bool IsHole( TEdge* e );
|
|
||||||
bool FindOwnerFromSplitRecs( OutRec& outRec, OutRec*& currOrfl );
|
|
||||||
void FixHoleLinkage( OutRec& outrec );
|
|
||||||
void AddJoin( OutPt* op1, OutPt* op2, const IntPoint offPt );
|
|
||||||
void ClearJoins();
|
|
||||||
void ClearGhostJoins();
|
|
||||||
void AddGhostJoin( OutPt* op, const IntPoint offPt );
|
|
||||||
bool JoinPoints( Join* j, OutRec* outRec1, OutRec* outRec2 );
|
|
||||||
void JoinCommonEdges();
|
|
||||||
void DoSimplePolygons();
|
|
||||||
void FixupFirstLefts1( OutRec* OldOutRec, OutRec* NewOutRec );
|
|
||||||
void FixupFirstLefts2( OutRec* InnerOutRec, OutRec* OuterOutRec );
|
|
||||||
void FixupFirstLefts3( OutRec* OldOutRec, OutRec* NewOutRec );
|
|
||||||
|
|
||||||
#ifdef use_xyz
|
|
||||||
void SetZ( IntPoint& pt, TEdge& e1, TEdge& e2 );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class ClipperOffset
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClipperOffset( double miterLimit = 2.0, double roundPrecision = 0.25 );
|
|
||||||
~ClipperOffset();
|
|
||||||
void AddPath( const Path& path, JoinType joinType, EndType endType );
|
|
||||||
void AddPaths( const Paths& paths, JoinType joinType, EndType endType );
|
|
||||||
void Execute( Paths& solution, double delta );
|
|
||||||
void Execute( PolyTree& solution, double delta );
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
double MiterLimit;
|
|
||||||
JoinType MiterFallback;
|
|
||||||
double ArcTolerance;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Paths m_destPolys;
|
|
||||||
Path m_srcPoly;
|
|
||||||
Path m_destPoly;
|
|
||||||
std::vector<DoublePoint> m_normals;
|
|
||||||
double m_delta, m_sinA, m_sin, m_cos;
|
|
||||||
double m_miterLim, m_StepsPerRad;
|
|
||||||
IntPoint m_lowest;
|
|
||||||
PolyNode m_polyNodes;
|
|
||||||
|
|
||||||
void FixOrientations();
|
|
||||||
void DoOffset( double delta );
|
|
||||||
void OffsetPoint( int j, int& k, JoinType jointype );
|
|
||||||
void DoSquare( int j, int k );
|
|
||||||
void DoMiter( int j, int k, double r );
|
|
||||||
void DoRound( int j, int k );
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class clipperException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
clipperException( const char* description ) : m_descr( description ) {}
|
|
||||||
virtual ~clipperException() throw() {}
|
|
||||||
virtual const char* what() const throw()override { return m_descr.c_str(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_descr;
|
|
||||||
};
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
} // ClipperLib namespace
|
|
||||||
|
|
||||||
#endif // clipper_hpp
|
|
Loading…
x
Reference in New Issue
Block a user