54 #include "clipper1/clipper.hpp"
64 class CSG_Converter_WorldToInt
68 CSG_Converter_WorldToInt (
void) { Create(0.0, 1.0, 0.0, 1.0); }
69 CSG_Converter_WorldToInt (
const CSG_Converter_WorldToInt &Converter) { Create(Converter); }
70 CSG_Converter_WorldToInt (
double xOffset,
double xScale,
double yOffset,
double yScale) { Create(xOffset, xScale, yOffset, yScale); }
71 CSG_Converter_WorldToInt (
const CSG_Rect &Extent,
bool bAspectRatio =
false) { Create(Extent, bAspectRatio); }
73 bool Create (
const CSG_Converter_WorldToInt &Converter)
75 return( Create(Converter.m_xOffset, Converter.m_xScale, Converter.m_yOffset, Converter.m_yScale) );
78 bool Create (
double xOffset,
double xScale,
double yOffset,
double yScale)
80 if( xScale != 0.0 && yScale != 0.0 )
93 bool Create (
const CSG_Rect &Extent,
bool bAspectRatio =
false)
102 if( xRange < yRange )
106 else if( yRange < xRange )
112 return( xRange > 0 && yRange > 0 ? Create(
113 xMin, (0x3FFFFFFFFFFFFFF) / xRange,
114 yMin, (0x3FFFFFFFFFFFFFF) / yRange
118 static ClipperLib::cInt Round (
double Value) {
return( (ClipperLib::cInt)(Value < 0.0 ? Value - 0.5 : Value + 0.5) ); }
120 ClipperLib::cInt Get_X_asInt (
double Value)
const {
return( Round((Value - m_xOffset) * m_xScale) ); }
121 ClipperLib::cInt Get_Y_asInt (
double Value)
const {
return( Round((Value - m_yOffset) * m_yScale) ); }
123 double Get_X_asWorld (ClipperLib::cInt Value)
const {
return( m_xOffset + Value / m_xScale ); }
124 double Get_Y_asWorld (ClipperLib::cInt Value)
const {
return( m_yOffset + Value / m_yScale ); }
126 bool Convert (
CSG_Shapes *pPolygons , ClipperLib::Paths &P )
const;
127 bool Convert (
const ClipperLib::Paths &P,
CSG_Shapes *pPolygons)
const;
129 bool Convert (
CSG_Shape *pPolygon , ClipperLib::Paths &P)
const;
130 bool Convert (
const ClipperLib::Paths &P,
CSG_Shape *pPolygon )
const;
132 double Get_xScale (
void)
const {
return( m_xScale ); }
133 double Get_yScale (
void)
const {
return( m_yScale ); }
138 double m_xOffset, m_xScale, m_yOffset, m_yScale;
149 bool CSG_Converter_WorldToInt::Convert(
CSG_Shapes *pPolygons, ClipperLib::Paths &Polygons)
const
153 for(
int iPolygon=0, jPolygon=0; iPolygon<pPolygons->
Get_Count(); iPolygon++)
157 for(
int iPart=0; iPart<pPolygon->
Get_Part_Count(); iPart++, jPolygon++)
163 Polygons.resize(1 + jPolygon);
170 Polygons[jPolygon][iPoint].X = Get_X_asInt(p.
x);
171 Polygons[jPolygon][iPoint].Y = Get_Y_asInt(p.
y);
176 return( Polygons.size() > 0 );
180 bool CSG_Converter_WorldToInt::Convert(
const ClipperLib::Paths &Polygons,
CSG_Shapes *pPolygons)
const
186 return( Convert(Polygons, pPolygon) );
195 bool CSG_Converter_WorldToInt::Convert(
CSG_Shape *pPolygon, ClipperLib::Paths &Polygons)
const
199 for(
int iPart=0, iPolygon=0; iPart<pPolygon->
Get_Part_Count(); iPart++, iPolygon++)
207 Polygons.resize(1 + iPolygon);
213 ClipperLib::IntPoint Point(Get_X_asInt(p.
x), Get_Y_asInt(p.
y));
215 if( iPoint == 0 || Polygons[iPolygon].back() != Point )
217 Polygons[iPolygon].push_back(Point);
221 if( pPolygon->
Get_Type() ==
SHAPE_TYPE_Polygon && Polygons[iPolygon].size() > 1 && Polygons[iPolygon][0] == Polygons[iPolygon].back() )
223 Polygons[iPolygon].pop_back();
228 return( Polygons.size() > 0 );
232 bool CSG_Converter_WorldToInt::Convert(
const ClipperLib::Paths &Polygons,
CSG_Shape *pPolygon)
const
236 for(
size_t iPolygon=0; iPolygon<Polygons.size(); iPolygon++)
238 for(
size_t iPoint=0; iPoint<Polygons[iPolygon].size(); iPoint++)
241 Get_X_asWorld(Polygons[iPolygon][iPoint].X),
242 Get_Y_asWorld(Polygons[iPolygon][iPoint].Y),
261 CSG_Converter_WorldToInt Converter(r);
263 ClipperLib::Paths Polygon, Clip, Result;
265 if( Converter.Convert(pPolygon, Polygon)
266 && Converter.Convert(pClip , Clip ) )
268 ClipperLib::Clipper Clipper;
270 Clipper.AddPaths(Clip, ClipperLib::ptClip,
true);
274 Clipper.AddPaths(Polygon, ClipperLib::ptSubject,
true);
276 if( !Clipper.Execute(ClipType, Result) )
283 Clipper.AddPaths(Polygon, ClipperLib::ptSubject,
false);
285 ClipperLib::PolyTree PolyTree;
287 if( !Clipper.Execute(ClipType, PolyTree) )
292 ClipperLib::PolyTreeToPaths(PolyTree, Result);
295 return( Converter.Convert(Result, pResult ? pResult : pPolygon) );
316 if( pResult ) pResult->
Assign(pPolygon,
false);
320 if( pResult ) pResult ->
Assign(pClip ,
false);
321 else pPolygon->
Assign(pClip ,
false);
325 return(
_SG_Polygon_Clip(ClipperLib::ctIntersection , pPolygon, pClip, pResult) );
339 if( pResult ) pResult->
Assign(pPolygon,
false);
344 return(
_SG_Polygon_Clip(ClipperLib::ctDifference , pPolygon, pClip, pResult) );
357 if( pResult ) pResult->
Assign(pPolygon,
false);
358 else pResult = pPolygon;
360 {
for(
int iPart=0, jPart=pResult->
Get_Part_Count(); iPart<pClip->Get_Part_Count(); iPart++, jPart++)
385 if( pResult ) pResult->
Assign(pPolygon,
false);
389 if( pResult ) pResult ->
Assign(pClip ,
false);
390 else pPolygon->
Assign(pClip ,
false);
394 if( pResult ) pResult->
Assign(pPolygon,
false);
395 else pResult = pPolygon;
397 {
for(
int iPart=0, jPart=pResult->
Get_Part_Count(); iPart<pClip->Get_Part_Count(); iPart++, jPart++)
416 CSG_Converter_WorldToInt Converter(pPolygon->
Get_Extent());
418 ClipperLib::Paths Polygon, Result;
420 if( Converter.Convert(pPolygon, Polygon) )
422 ClipperLib::Clipper Clipper;
424 Clipper.AddPaths(Polygon, ClipperLib::ptSubject,
true);
426 Clipper.Execute(ClipperLib::ctUnion, Result);
428 return( Converter.Convert(Result, pResult ? pResult : pPolygon) );
439 CSG_Converter_WorldToInt Converter(r,
true);
441 ClipperLib::Paths Paths, Result;
443 if( Converter.Convert(pPolygon, Paths) )
445 ClipperLib::ClipperOffset Offset(2.0, dArc * Converter.Get_xScale());
449 Offset.AddPaths(Paths, ClipperLib::jtRound, ClipperLib::etClosedPolygon);
453 Offset.AddPaths(Paths, ClipperLib::jtRound, ClipperLib::etOpenRound);
456 Offset.Execute(Result, dSize * Converter.Get_xScale());
458 return( Converter.Convert(Result, pResult ? pResult : pPolygon) );
472 return(
"Clipper1 " CLIPPER_VERSION );