1
2 /*
3 This file is a part of the RepSnapper project.
4 Copyright (C) 2012 martin.dieringer@gmx.de
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "clipping.h"
22
23 //////////////////////////////////////////////////////////////////////////////////////////
24 //
25 // old API compatibility
26 // polytree to expolygons
27 // http://www.angusj.com/delphi/clipper/documentation/Docs/Overview/Compatibility%20with%20Prior%20Versions.htm
28
AddOuterPolyNodeToExPolygons(const CL::PolyNode * polynode,ExPolygons & expolygons)29 void Clipping::AddOuterPolyNodeToExPolygons(const CL::PolyNode * polynode,
30 ExPolygons& expolygons)
31 {
32 size_t cnt = expolygons.size();
33 expolygons.resize(cnt + 1);
34 expolygons[cnt].outer = polynode->Contour;
35 expolygons[cnt].holes.resize(polynode->ChildCount());
36 for (int i = 0; i < polynode->ChildCount(); ++i)
37 {
38 expolygons[cnt].holes[i] = polynode->Childs[i]->Contour;
39 //Add outer polygons contained by (nested within) holes ...
40 for (int j = 0; j < polynode->Childs[i]->ChildCount(); ++j)
41 AddOuterPolyNodeToExPolygons(polynode->Childs[i]->Childs[j], expolygons);
42 }
43 }
44
PolyTreeToExPolygons(const CL::PolyTree * polytree,ExPolygons & expolygons)45 void Clipping::PolyTreeToExPolygons(const CL::PolyTree * polytree, ExPolygons& expolygons)
46 {
47 expolygons.clear();
48 for (int i = 0; i < polytree->ChildCount(); ++i)
49 AddOuterPolyNodeToExPolygons(polytree->Childs[i], expolygons);
50 }
51
52 //
53 //////////////////////////////////////////////////////////////////////////////////////////
54
55
56
57
printCLpolygon(CL::Path & p)58 void printCLpolygon(CL::Path &p) {
59 cout << p.size() << endl;
60 for (uint k = 0; k < p.size(); k++) {
61 cout << p[k].X <<", " << p[k].Y << "," << endl;
62 }
63 cout << endl;
64 }
65
printCLpolygons(CL::Paths & p)66 void printCLpolygons(CL::Paths &p) {
67 for (uint j = 0; j < p.size(); j++) {
68 printCLpolygon(p[j]);
69 cout << endl;
70 }
71 }
printCLpolygons(vector<CL::Paths> & p)72 void printCLpolygons(vector<CL::Paths> &p) {
73 uint numpolys = 0;
74 for (uint i = 0; i < p.size(); i++) numpolys += p[i].size();
75 cout << numpolys << endl;
76 for (uint i = 0; i < p.size(); i++) {
77 printCLpolygons(p[i]);
78 }
79 }
80
81
clear()82 void Clipping::clear()
83 {
84 clpr.Clear();
85 if(debug) {
86 subjpolygons.clear();
87 clippolygons.clear();
88 }
89 }
90
ClipperPoint(const Vector2d & v)91 CL::IntPoint Clipping::ClipperPoint(const Vector2d &v)
92 {
93 return CL::IntPoint(CL_FACTOR*(v.x()+CL_OFFSET),
94 CL_FACTOR*(v.y()+CL_OFFSET));
95 }
getPoint(const CL::IntPoint & p)96 Vector2d Clipping::getPoint(const CL::IntPoint &p)
97 {
98 return Vector2d(p.X/CL_FACTOR-CL_OFFSET,
99 p.Y/CL_FACTOR-CL_OFFSET);
100 }
101
getClipperPolygon(const Poly & poly)102 CL::Path Clipping::getClipperPolygon(const Poly &poly)
103 {
104 CL::Path cpoly(poly.vertices.size());
105 for(size_t i=0; i<poly.vertices.size();i++){
106 Vector2d P1;
107 // if (reverse)
108 P1 = poly.getVertexCircular(-i); // have to reverse from/to clipper
109 // else
110 // P1 = poly.getVertexCircular(i);
111 cpoly[i]=(ClipperPoint(P1));
112 }
113 // doesn't work...:
114 // cerr<< "poly is hole? "<< hole;
115 // cerr<< " -- orient=" <<ClipperLib::Orientation(cpoly) << endl;
116 // if (ClipperLib::Orientation(cpoly) == hole)
117 // std::reverse(cpoly.begin(),cpoly.end());
118 return cpoly;
119 }
120
getClipperPolygons(const vector<Poly> & polys)121 CL::Paths Clipping::getClipperPolygons(const vector<Poly> &polys)
122 {
123 ClipperLib::Paths cpolys(polys.size());
124 for (uint i=0; i<polys.size(); i++)
125 {
126 cpolys[i] = getClipperPolygon(polys[i]);
127 }
128 return cpolys;
129 }
getClipperPolygons(const ExPoly & expoly)130 CL::Paths Clipping::getClipperPolygons(const ExPoly &expoly)
131 {
132 return getClipperPolygons(getPolys(expoly));
133 }
134
135 /* // not used
136 CL::PolyTree Clipping::getClipperTree(const vector<ExPoly> &expolys)
137 {
138 CL::PolyTree polytree;
139 // for (uint i=0; i<expolys.size(); i++) {
140 // CL::PolyNode expoly;
141 // polytree[i].Contour = getClipperPolygon(expolys[i].outer);
142 // for (uint h=0; h<expolys[i].holes.size(); h++) {
143 // CL::PolyNode hole;
144 // hole.Contour = getClipperPolygon(expolys[i].holes[h]);
145 // hole.Parent = &polytrees[i];
146 // polytrees[i].Childs.push_back(&hole);
147 // }
148 // }
149 return polytree;
150 }
151 */
152
CLType(JoinType type)153 CL::JoinType Clipping::CLType(JoinType type)
154 {
155 switch (type)
156 {
157 case jsquare: return CL::jtSquare;
158 case jmiter: return CL::jtMiter;
159 case jround: return CL::jtRound;
160 }
161 return CL::jtMiter; // default
162 }
CLType(PolyType type)163 CL::PolyType Clipping::CLType(PolyType type)
164 {
165 switch (type)
166 {
167 case subject: return CL::ptSubject;
168 case clip: return CL::ptClip;
169 }
170 return CL::ptSubject; // default
171 }
172
addPoly(const Poly & poly,PolyType type)173 void Clipping::addPoly(const Poly &poly, PolyType type)
174 {
175 clpr.AddPath(getClipperPolygon(poly), CLType(type), true);
176 lastZ = poly.getZ();
177 lastExtrF = poly.getExtrusionFactor();
178 }
179
addPolys(const vector<Poly> & polys,PolyType type)180 void Clipping::addPolys(const vector<Poly> &polys, PolyType type)
181 {
182 CL::Paths cp = getClipperPolygons(polys);
183 if(debug) {
184 if (type==clip)
185 clippolygons.push_back(cp);
186 else if (type==subject)
187 subjpolygons.push_back(cp);
188 }
189 // try {
190 clpr.AddPaths(cp, CLType(type), true);
191 // } catch (...) {
192 // vector<CL::Paths> vcp;
193 // vcp.push_back(cp);
194 // printCLpolygons(vcp);
195 // for (uint i = 0; i < cp.size(); i++) {
196 // cerr << "try polygon "<< i << endl;
197 // clpr.Clear();
198 // printCLpolygon(cp[i]);
199 // clpr.AddPath(cp[i],CLType(type), true);
200 // }
201 // throw("end");
202 // }
203 if (polys.size()>0) {
204 lastZ = polys.back().getZ();
205 lastExtrF = polys.back().getExtrusionFactor();
206 }
207 }
addPolys(const ExPoly & expoly,PolyType type)208 void Clipping::addPolys(const ExPoly &expoly, PolyType type)
209 {
210 vector<Poly> polys = getPolys(expoly);
211 addPolys(polys, type);
212 }
addPolys(const vector<ExPoly> & expolys,PolyType type)213 void Clipping::addPolys(const vector<ExPoly> &expolys, PolyType type)
214 {
215 for (uint i = 0; i < expolys.size(); i++)
216 addPolys(expolys[i], type);
217 }
addPolygons(const CL::Paths & cp,PolyType type)218 void Clipping::addPolygons(const CL::Paths &cp, PolyType type)
219 {
220 clpr.AddPaths(cp, CLType(type), true);
221 }
222
223
224
225 // // return intersection polys
226 // vector< vector<Vector2d> > Clipping::intersect(const Poly poly1, const Poly poly2)
227 // {
228 // CL::Path cpoly1 = getClipperPolygon(poly1),
229 // cpoly2 = getClipperPolygon(poly2);
230 // clpr.Clear();
231 // CL::Paths sol;
232 // clpr.AddPath(cpoly1,CL::ptSubject);
233 // clpr.AddPath(cpoly2,CL::ptClip);
234 // clpr.Execute(CL::ctIntersection, sol, CL::pftEvenOdd, CL::pftEvenOdd);
235
236 // vector< vector<Vector2d> > result;
237 // for(size_t i=0; i<sol.size();i++)
238 // {
239 // vector<Vector2d> polypoints;
240 // CL::Path cpoly = sol[i];
241 // for(size_t j=0; j<cpoly.size();j++){
242 // polypoints.push_back(Vector2d(cpoly[j].X,cpoly[j].Y));
243 // }
244 // result.push_back(polypoints);
245 // }
246 // return result;
247 // }
248
249 // have added Polyons by addPolygon(s)
intersect(CL::PolyFillType sft,CL::PolyFillType cft)250 vector<Poly> Clipping::intersect(CL::PolyFillType sft,
251 CL::PolyFillType cft)
252 {
253 CL::Paths inter;
254 clpr.Execute(CL::ctIntersection, inter, sft, cft);
255 return getPolys(inter, lastZ, lastExtrF);
256 }
ext_intersect(CL::PolyFillType sft,CL::PolyFillType cft)257 vector<ExPoly> Clipping::ext_intersect(CL::PolyFillType sft,
258 CL::PolyFillType cft)
259 {
260 CL::PolyTree inter;
261 clpr.Execute(CL::ctIntersection, inter, sft, cft);
262 return getExPolys(inter, lastZ, lastExtrF);
263 }
264
265 // have added Polyons by addPolygon(s)
unite(CL::PolyFillType sft,CL::PolyFillType cft)266 vector<Poly> Clipping::unite(CL::PolyFillType sft,
267 CL::PolyFillType cft)
268 {
269 CL::Paths united;
270 clpr.Execute(CL::ctUnion, united, sft, cft);
271 return getPolys(united, lastZ, lastExtrF);
272 }
ext_unite(CL::PolyFillType sft,CL::PolyFillType cft)273 vector<ExPoly> Clipping::ext_unite(CL::PolyFillType sft,
274 CL::PolyFillType cft)
275 {
276 CL::PolyTree inter;
277 clpr.Execute(CL::ctUnion, inter, sft, cft);
278 return getExPolys(inter, lastZ, lastExtrF);
279 }
280
281
282 // have added Polyons by addPolygon(s)
subtract(CL::PolyFillType sft,CL::PolyFillType cft)283 vector<Poly> Clipping::subtract(CL::PolyFillType sft,
284 CL::PolyFillType cft)
285 {
286 CL::Paths diff;
287 clpr.Execute(CL::ctDifference, diff, sft, cft);
288 return getPolys(diff, lastZ, lastExtrF);
289 }
ext_subtract(CL::PolyFillType sft,CL::PolyFillType cft)290 vector<ExPoly> Clipping::ext_subtract(CL::PolyFillType sft,
291 CL::PolyFillType cft)
292 {
293 CL::PolyTree diff;
294 // if (debug) {
295 // try {
296 // clpr.Execute(CL::ctDifference, diff, sft, cft);
297 // } catch (int e){
298 // cerr << lastZ<<" - " << lastExtrF<< endl;
299 // if (e == 22){
300 // cout << "Subject" << endl;
301 // printCLpolygons(subjpolygons);
302 // cout << "Clip" << endl;
303 // printCLpolygons(clippolygons);
304 // // vector<ExPoly> empty;
305 // // return empty;
306 // }
307 // }
308 // }
309 // else
310 clpr.Execute(CL::ctDifference, diff, sft, cft);//CL::pftEvenOdd, CL::pftEvenOdd);
311 return getExPolys(diff, lastZ, lastExtrF);
312 }
subtractMerged(double dist,CL::PolyFillType sft,CL::PolyFillType cft)313 vector<Poly> Clipping::subtractMerged(double dist,
314 CL::PolyFillType sft,
315 CL::PolyFillType cft)
316 {
317 CL::Paths diff;
318 clpr.Execute(CL::ctDifference, diff, sft, cft);
319 return getPolys(getMerged(diff, dist), lastZ, lastExtrF);
320 }
321
Xor(CL::PolyFillType sft,CL::PolyFillType cft)322 vector<Poly> Clipping::Xor(CL::PolyFillType sft,
323 CL::PolyFillType cft)
324 {
325 CL::Paths xored;
326 clpr.Execute(CL::ctXor, xored, sft, cft);
327 return getPolys(xored, lastZ, lastExtrF);
328 }
329
getOffset(const Poly & poly,double distance,JoinType jtype,double miterdist)330 vector<Poly> Clipping::getOffset(const Poly &poly, double distance,
331 JoinType jtype, double miterdist)
332 {
333 CL::Paths cpolys(1); cpolys[0]=getClipperPolygon(poly);
334 CL::Paths offset = CLOffset(cpolys, CL_FACTOR*distance, CLType(jtype), miterdist);
335 return getPolys(offset, poly.getZ(), poly.getExtrusionFactor());
336 }
getOffset(const vector<Poly> & polys,double distance,JoinType jtype,double miterdist)337 vector<Poly> Clipping::getOffset(const vector<Poly> &polys, double distance,
338 JoinType jtype, double miterdist)
339 {
340 CL::Paths cpolys = getClipperPolygons(polys);
341 CL::Paths offset = CLOffset(cpolys, CL_FACTOR*distance, CLType(jtype), miterdist);
342 double z=0, extrf=1.;;
343 if (polys.size()>0) {
344 z = polys.back().getZ();
345 extrf = polys.back().getExtrusionFactor();
346 }
347 return getPolys(offset,z,extrf);
348 }
getOffset(const ExPoly & expoly,double distance,JoinType jtype,double miterdist)349 vector<Poly> Clipping::getOffset(const ExPoly &expoly, double distance,
350 JoinType jtype, double miterdist)
351 {
352 vector<Poly> polys = getPolys(expoly);
353 return getOffset(polys,distance,jtype,miterdist);
354 }
355
getOffset(const vector<ExPoly> & expolys,double distance,JoinType jtype,double miterdist)356 vector<Poly> Clipping::getOffset(const vector<ExPoly> &expolys, double distance,
357 JoinType jtype, double miterdist)
358 {
359 return getOffset(getPolys(expolys),distance,jtype,miterdist);
360 }
361
362
363 // vector<ExPoly> Clipping::getOffset(const vector<ExPoly> expolys, double distance,
364 // JoinType jtype, double miterdist)
365 // {
366 // CL::ExPolygons excpolys = getClipperPolygons(expolys);
367 // double z=0, extrf=1.;;
368 // vector<Poly> polys(excpolys.size());
369 // if (expolys.size()>0) {
370 // z = expolys.back().outer.getZ();
371 // extrf = expolys.back().outer.getExtrusionFactor();
372 // }
373 // for (uint i = 0 ; i < expolys.size(); i++) {
374 // CL::Paths outer = CLOffset(excpolys[i].outer,
375 // CL_FACTOR*distance, CLType(jtype), miterdist);
376 // polys[i].outer = getPoly(outer, z, extrusionfactor);
377 // vector<Poly> polys[i].holes;
378 // for (uint h = 0 ; h < polys[i].holes.size(); h++) {
379 // CL::Paths holes = CLOffset(excpolys[i].holes[h],
380 // CL_FACTOR*distance, CLType(jtype), miterdist);
381 // vector<Poly> hpolys = CL:getPolys(holes, z, extrusionfactor);
382 // polys[i].holes.insert(polys[i].holes.end(),hpolys.begin(),hpolys.end());
383 // }
384 // }
385 // return getExPolys(offset,z,extrf);
386 // }
387
388 // first goes in then out to get capped corners
getShrinkedCapped(const vector<Poly> & polys,double distance,JoinType jtype,double miterdist)389 vector<Poly> Clipping::getShrinkedCapped(const vector<Poly> &polys, double distance,
390 JoinType jtype, double miterdist)
391 {
392 CL::Paths cpolys = getClipperPolygons(polys);
393 CL::Paths offset1 = CLOffset(cpolys, -2*CL_FACTOR*distance, CLType(jtype), 0);// CL::jtRound);
394 CL::Paths offset = CLOffset(offset1, 1*CL_FACTOR*distance, CLType(jtype), 0);
395 double z=0, extrf=1.;;
396 if (polys.size()>0) {
397 z= polys.back().getZ();
398 extrf = polys.back().getExtrusionFactor();
399 }
400 return getPolys(offset,z,extrf);
401 }
402
403
404 // offset with reverse test
CLOffset(const CL::Paths & cpolys,int cldist,CL::JoinType cljtype,double miter_limit,bool reverse)405 CL::Paths Clipping::CLOffset(const CL::Paths &cpolys, int cldist,
406 CL::JoinType cljtype, double miter_limit, bool reverse)
407 {
408 CL::Paths opolys;
409 if (reverse)
410 CL::ReversePaths(opolys);
411 CL::ClipperOffset co(miter_limit, miter_limit);
412 co.AddPaths(cpolys, cljtype, CL::etClosedPolygon);
413 co.Execute(opolys, cldist);
414 CL::SimplifyPolygons(opolys);//, CL::pftNonZero);
415 return opolys;
416 }
417
418 // overlap a bit and unite to merge adjacent polys
getMerged(const vector<Poly> & polys,double overlap)419 vector<Poly> Clipping::getMerged(const vector<Poly> &polys, double overlap)
420 {
421 CL::Paths cpolys = getClipperPolygons(polys);
422 CL::Paths merged = getMerged(cpolys, CL_FACTOR*overlap);
423 double z=0, extrf = 1.;
424 if (polys.size()>0) {
425 z= polys.back().getZ();
426 extrf = polys.back().getExtrusionFactor();
427 }
428 return getPolys(merged, z, extrf);
429 }
430 // overlap a bit and unite to merge adjacent polys
getMerged(const CL::Paths & cpolys,int overlap)431 CL::Paths Clipping::getMerged(const CL::Paths &cpolys, int overlap)
432 {
433 CL::Clipper clpr;
434 // return polys;
435 // make wider to get overlap
436 CL::Paths offset;
437 offset = CLOffset(cpolys, overlap, CL::jtMiter, 1);
438 //CL::OffsetPolygons(cpolys, offset, 10, ClipperLib::jtMiter, 1);
439 // return getPolys(offset, polys.back().getZ(),polys.back().getExtrusionFactor());
440 clpr.AddPaths(offset, CL::ptSubject, true);
441 CL::Paths cpolys3;
442 clpr.Execute(CL::ctUnion, cpolys3, CL::pftEvenOdd, CL::pftEvenOdd);
443 //cerr << cpolys3.size() << " - "<<offset.size() << endl;
444 // shrink the result
445 return CLOffset(cpolys3, -overlap, CL::jtMiter, 1);
446 }
447
getPoly(const CL::Path & cpoly,double z,double extrusionfactor)448 Poly Clipping::getPoly(const CL::Path &cpoly, double z, double extrusionfactor)
449 {
450 Poly p(z, extrusionfactor);
451 p.vertices.clear();
452 uint count = cpoly.size();
453 p.vertices.resize(count);
454 for (uint i = 0 ; i<count; i++) {
455 p.vertices[count-i-1] = getPoint(cpoly[i]); // reverse!
456 // //p.vertices[i] = getPoint(cpoly[i]);
457 }
458 p.calcHole();
459 return p;
460 }
461
getPolys(const CL::Paths & cpolys,double z,double extrusionfactor)462 vector<Poly> Clipping::getPolys(const CL::Paths &cpolys, double z, double extrusionfactor)
463 {
464 uint count = cpolys.size();
465 vector<Poly> polys(count);
466 for (uint i = 0 ; i<count; i++)
467 polys[i] = getPoly(cpolys[i], z, extrusionfactor);
468 return polys;
469 }
470
getExPolys(const CL::PolyTree & ctree,double z,double extrusionfactor)471 vector<ExPoly> Clipping::getExPolys(const CL::PolyTree &ctree, double z,
472 double extrusionfactor)
473 {
474 ExPolygons cexpolys;
475 PolyTreeToExPolygons(&ctree, cexpolys);
476 vector<ExPoly> expolys(cexpolys.size());
477 for (uint j = 0 ; j < cexpolys.size(); j++) {
478 expolys[j].outer = getPoly(cexpolys[0].outer, z, extrusionfactor);
479 for (uint i = 0 ; i < cexpolys[j].holes.size(); i++)
480 expolys[j].holes.push_back(getPoly(cexpolys[j].holes[i], z, extrusionfactor));
481 }
482 return expolys;
483 }
getPolys(const ExPoly & expoly)484 vector<Poly> Clipping::getPolys(const ExPoly &expoly)
485 {
486 Clipping clipp;
487 clipp.addPoly(expoly.outer, subject);
488 clipp.addPolys(expoly.holes, clip);
489 vector<Poly> polys = clipp.subtract();
490 return polys;
491 }
getPolys(const vector<ExPoly> & expolys)492 vector<Poly> Clipping::getPolys(const vector<ExPoly> &expolys)
493 {
494 vector<Poly> polys;
495 for (uint i = 0; i< expolys.size(); i++) {
496 vector<Poly> p = getPolys(expolys[i]);
497 polys.insert(polys.end(),p.begin(),p.end());
498 }
499 return polys;
500 }
501
getExPolys(const vector<Poly> & polys)502 vector<ExPoly> Clipping::getExPolys(const vector<Poly> &polys)
503 {
504 /*
505 CL::PolyTree tree = getClipperTree(polys);
506 return getExPolys(tree, polys.back().getZ(), polys.back().getExtrusionFactor());
507 */
508 vector<ExPoly> expolys;
509 vector<Poly> holes;
510 for (uint i = 0; i<polys.size(); i++) {
511 if (polys[i].isHole()) {
512 holes.push_back(polys[i]);
513 } else {
514 ExPoly expoly;
515 expoly.outer = polys[i];
516 expolys.push_back(expoly);
517 }
518 }
519 for (uint i = 0; i<holes.size(); i++)
520 for (uint j = 0; j<expolys.size(); j++)
521 if (holes[i].size()>0)
522 if (expolys[j].outer.vertexInside(holes[i].vertices[0])) // just test one point
523 //if (holes[i].isInside(expolys[j].outer)) // test all
524 expolys[j].holes.push_back(holes[i]);
525 return expolys;
526 }
527
getExPolys(const vector<Poly> & polys,double z,double extrusionfactor)528 vector<ExPoly> Clipping::getExPolys(const vector<Poly> &polys,
529 double z, double extrusionfactor)
530 {
531 vector<Poly> ppolys(polys.size());
532 for (uint i = 0; i<polys.size(); i++) {
533 ppolys[i]= Poly(polys[i],z);
534 ppolys[i].setExtrusionFactor(extrusionfactor);
535 }
536 return getExPolys(ppolys);
537 }
538
getClipperTree(const vector<Poly> & polys)539 CL::PolyTree Clipping::getClipperTree(const vector<Poly> &polys)
540 {
541 CL::Paths cpolys = getClipperPolygons(polys);
542 CL::Clipper clpr;
543 clpr.AddPaths(cpolys, CL::ptSubject, true);
544 CL::PolyTree ctree;
545 clpr.Execute(CL::ctUnion, ctree, CL::pftEvenOdd, CL::pftEvenOdd);
546 return ctree;
547 }
548
Area(const Poly & poly)549 double Clipping::Area(const Poly &poly){
550 CL::Path cp = getClipperPolygon(poly);
551 return (double)((long double)(CL::Area(cp))/CL_FACTOR/CL_FACTOR);
552 }
Area(const vector<Poly> & polys)553 double Clipping::Area(const vector<Poly> &polys){
554 double a=0;
555 for (uint i=0; i<polys.size(); i++)
556 a += Area(polys[i]);
557 return a;
558 }
559
Area(const ExPoly & expoly)560 double Clipping::Area(const ExPoly &expoly){
561 double a = Area(expoly.outer);
562 for (uint i = 0; i < expoly.holes.size(); i++) {
563 a -= Area(expoly.holes[i]);
564 }
565 return a;
566 }
Area(const vector<ExPoly> & expolys)567 double Clipping::Area(const vector<ExPoly> &expolys){
568 double a=0;
569 for (uint i=0; i<expolys.size(); i++)
570 a += Area(expolys[i]);
571 return a;
572 }
573
ReversePoints(vector<Poly> & polys)574 void Clipping::ReversePoints(vector<Poly> &polys) {
575 for (uint i=0; i<polys.size(); i++)
576 polys[i].reverse();
577 }
578
579
580
581
582