Reverted commits that remove boost::polygon dependency (need more testing).

This commit is contained in:
Maciej Suminski
2015-07-14 22:23:13 +02:00
parent 9f18e5a98f
commit d2ebf688f9
57 changed files with 5030 additions and 1209 deletions
+91 -23
View File
@@ -542,14 +542,15 @@ static const LAYER_ID plot_seq[] = {
/* Plot outlines of copper, for copper layer
*/
void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter,
#include "clipper.hpp"
void PlotLayerOutlines( BOARD *aBoard, PLOTTER* aPlotter,
LSET aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
{
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
itemplotter.SetLayerSet( aLayerMask );
SHAPE_POLY_SET outlines;
CPOLYGONS_LIST outlines;
for( LSEQ seq = aLayerMask.Seq( plot_seq, DIM( plot_seq ) ); seq; ++seq )
{
@@ -558,25 +559,51 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter,
outlines.RemoveAllContours();
aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
outlines.Simplify();
// Merge all overlapping polygons.
KI_POLYGON_SET kpolygons;
KI_POLYGON_SET ktmp;
outlines.ExportTo( ktmp );
kpolygons += ktmp;
// Plot outlines
std::vector< wxPoint > cornerList;
// Now we have one or more basic polygons: plot each polygon
for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
for( unsigned ii = 0; ii < kpolygons.size(); ii++ )
{
cornerList.clear();
const SHAPE_LINE_CHAIN& path = outlines.COutline( ii );
KI_POLYGON polygon = kpolygons[ii];
for( int jj = 0; jj < path.PointCount(); jj++ )
cornerList.push_back( wxPoint( path.CPoint( jj ).x , path.CPoint( jj ).x ) );
// polygon contains only one polygon, but it can have holes linked by
// overlapping segments.
// To plot clean outlines, we have to break this polygon into more polygons with
// no overlapping segments, using Clipper, because boost::polygon
// does not allow that
ClipperLib::Path raw_polygon;
ClipperLib::Paths normalized_polygons;
// Ensure the polygon is closed
if( cornerList[0] != cornerList[cornerList.size() - 1] )
cornerList.push_back( cornerList[0] );
for( unsigned ic = 0; ic < polygon.size(); ic++ )
{
KI_POLY_POINT corner = *(polygon.begin() + ic);
raw_polygon.push_back( ClipperLib::IntPoint( corner.x(), corner.y() ) );
}
aPlotter->PlotPoly( cornerList, NO_FILL );
ClipperLib::SimplifyPolygon( raw_polygon, normalized_polygons );
// Now we have one or more basic polygons: plot each polygon
for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ )
{
ClipperLib::Path& polygon = normalized_polygons[ii];
cornerList.clear();
for( unsigned jj = 0; jj < polygon.size(); jj++ )
cornerList.push_back( wxPoint( polygon[jj].X , polygon[jj].Y ) );
// Ensure the polygon is closed
if( cornerList[0] != cornerList[cornerList.size()-1] )
cornerList.push_back( cornerList[0] );
aPlotter->PlotPoly( cornerList, NO_FILL );
}
}
// Plot pad holes
@@ -677,8 +704,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
// This extra margin is used to merge too close shapes
// (distance < aMinThickness), and will be removed when creating
// the actual shapes
SHAPE_POLY_SET areas; // Contains shapes to plot
SHAPE_POLY_SET initialPolys; // Contains exact shapes to plot
CPOLYGONS_LIST bufferPolys; // Contains shapes to plot
CPOLYGONS_LIST initialPolys; // Contains exact shapes to plot
/* calculates the coeff to compensate radius reduction of holes clearance
* due to the segment approx ( 1 /cos( PI/circleToSegmentsCount )
@@ -695,7 +722,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
circleToSegmentsCount, correction );
// add shapes inflated by aMinThickness/2
module->TransformPadsShapesWithClearanceToPolygon( layer,
areas, inflate,
bufferPolys, inflate,
circleToSegmentsCount, correction );
}
@@ -727,7 +754,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
if( !( via_set & aLayerMask ).any() )
continue;
via->TransformShapeWithClearanceToPolygon( areas, via_margin,
via->TransformShapeWithClearanceToPolygon( bufferPolys, via_margin,
circleToSegmentsCount,
correction );
via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance,
@@ -744,7 +771,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
if( zone->GetLayer() != layer )
continue;
zone->TransformOutlinesShapeWithClearanceToPolygon( areas,
zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys,
inflate, true );
zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys,
0, true );
@@ -761,15 +788,56 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
zone.SetMinThickness( 0 ); // trace polygons only
zone.SetLayer ( layer );
areas.BooleanAdd( initialPolys );
areas.Inflate( -inflate, circleToSegmentsCount );
// Now:
// 1 - merge polygons which are intersecting, i.e. remove gaps
// having a thickness < aMinThickness
// 2 - deflate resulting polygons by aMinThickness/2
KI_POLYGON_SET areasToMerge;
bufferPolys.ExportTo( areasToMerge );
KI_POLYGON_SET initialAreas;
initialPolys.ExportTo( initialAreas );
// Merge polygons: because each shape was created with an extra margin
// = aMinThickness/2, shapes too close ( dist < aMinThickness )
// will be merged, because they are overlapping
KI_POLYGON_SET areas;
areas |= areasToMerge; // Populates with merged polygons
// Deflate: remove the extra margin, to create the actual shapes
// Here I am using polygon:resize, because this function creates better shapes
// than deflate algo.
// Use here deflate made by Clipper, because:
// Clipper is (by far) faster and better, event using arcs to deflate shapes
// boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs
// boost::polygon >=1.56 polygon resize function just does not work
// Note also we combine polygons using boost::polygon, which works better than Clipper,
// especially with zones using holes linked to main outlines by overlapping segments
CPOLYGONS_LIST tmp;
tmp.ImportFrom( areas );
// Deflate area using Clipper, better than boost::polygon
ClipperLib::Paths areasDeflate;
tmp.ExportTo( areasDeflate );
// Deflate areas: they will have the right size after deflate
ClipperLib::ClipperOffset offset_engine;
circleToSegmentsCount = 16;
offset_engine.ArcTolerance = (double)inflate / 3.14 / circleToSegmentsCount;
offset_engine.AddPaths( areasDeflate, ClipperLib::jtRound, ClipperLib::etClosedPolygon );
offset_engine.Execute( areasDeflate, -inflate );
// 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
areas.BooleanAdd( initialPolys );
areas.Fracture();
tmp.RemoveAllContours();
tmp.ImportFrom( areasDeflate );
areas.clear();
tmp.ExportTo( areas );
zone.AddFilledPolysList( areas );
// Resize slightly changes shapes (the transform is not perfect).
// So *ensure* initial shapes are kept
areas |= initialAreas;
zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas );
itemplotter.PlotFilledAreas( &zone );
}