File indexing completed on 2025-04-20 03:36:29
0001 /******************************************************************************* 0002 * Author : Angus Johnson * 0003 * Date : 30 May 2023 * 0004 * Website : http://www.angusj.com * 0005 * Copyright : Angus Johnson 2010-2023 * 0006 * Purpose : This module exports the Clipper2 Library (ie DLL/so) * 0007 * License : http://www.boost.org/LICENSE_1_0.txt * 0008 *******************************************************************************/ 0009 0010 // The exported functions below refer to simple structures that 0011 // can be understood across multiple languages. Consequently 0012 // Path64, PathD, Polytree64 etc are converted from C++ classes 0013 // (std::vector<> etc) into the following data structures: 0014 // 0015 // CPath64 (int64_t*) & CPathD (double_t*): 0016 // Path64 and PathD are converted into arrays of x,y coordinates. 0017 // However in these arrays the first x,y coordinate pair is a 0018 // counter with 'x' containing the number of following coordinate 0019 // pairs. ('y' should be 0, with one exception explained below.) 0020 // __________________________________ 0021 // |counter|coord1|coord2|...|coordN| 0022 // |N ,0 |x1, y1|x2, y2|...|xN, yN| 0023 // __________________________________ 0024 // 0025 // CPaths64 (int64_t**) & CPathsD (double_t**): 0026 // These are arrays of pointers to CPath64 and CPathD where 0027 // the first pointer is to a 'counter path'. This 'counter 0028 // path' has a single x,y coord pair with 'y' (not 'x') 0029 // containing the number of paths that follow. ('x' = 0). 0030 // _______________________________ 0031 // |counter|path1|path2|...|pathN| 0032 // |addr0 |addr1|addr2|...|addrN| (*addr0[0]=0; *addr0[1]=N) 0033 // _______________________________ 0034 // 0035 // The structures of CPolytree64 and CPolytreeD are defined 0036 // below and these structures don't need to be explained here. 0037 0038 #ifndef CLIPPER2_EXPORT_H 0039 #define CLIPPER2_EXPORT_H 0040 0041 #include <cstdlib> 0042 #include <vector> 0043 0044 #include "clipper2/clipper.core.h" 0045 #include "clipper2/clipper.engine.h" 0046 #include "clipper2/clipper.offset.h" 0047 #include "clipper2/clipper.rectclip.h" 0048 0049 namespace Clipper2Lib { 0050 0051 typedef int64_t* CPath64; 0052 typedef int64_t** CPaths64; 0053 typedef double* CPathD; 0054 typedef double** CPathsD; 0055 0056 typedef struct CPolyPath64 { 0057 CPath64 polygon; 0058 uint32_t is_hole; 0059 uint32_t child_count; 0060 CPolyPath64* childs; 0061 } 0062 CPolyTree64; 0063 0064 typedef struct CPolyPathD { 0065 CPathD polygon; 0066 uint32_t is_hole; 0067 uint32_t child_count; 0068 CPolyPathD* childs; 0069 } 0070 CPolyTreeD; 0071 0072 template <typename T> 0073 struct CRect { 0074 T left; 0075 T top; 0076 T right; 0077 T bottom; 0078 }; 0079 0080 typedef CRect<int64_t> CRect64; 0081 typedef CRect<double> CRectD; 0082 0083 template <typename T> 0084 inline bool CRectIsEmpty(const CRect<T>& rect) 0085 { 0086 return (rect.right <= rect.left) || (rect.bottom <= rect.top); 0087 } 0088 0089 template <typename T> 0090 inline Rect<T> CRectToRect(const CRect<T>& rect) 0091 { 0092 Rect<T> result; 0093 result.left = rect.left; 0094 result.top = rect.top; 0095 result.right = rect.right; 0096 result.bottom = rect.bottom; 0097 return result; 0098 } 0099 0100 #define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport) 0101 0102 ////////////////////////////////////////////////////// 0103 // EXPORTED FUNCTION DEFINITIONS 0104 ////////////////////////////////////////////////////// 0105 0106 EXTERN_DLL_EXPORT const char* Version(); 0107 0108 // Some of the functions below will return data in the various CPath 0109 // and CPolyTree structures which are pointers to heap allocated 0110 // memory. Eventually this memory will need to be released with one 0111 // of the following 'DisposeExported' functions. (This may be the 0112 // only safe way to release this memory since the executable 0113 // accessing these exported functions may use a memory manager that 0114 // allocates and releases heap memory in a different way. Also, 0115 // CPath structures that have been constructed by the executable 0116 // should not be destroyed using these 'DisposeExported' functions.) 0117 EXTERN_DLL_EXPORT void DisposeExportedCPath64(CPath64 p); 0118 EXTERN_DLL_EXPORT void DisposeExportedCPaths64(CPaths64& pp); 0119 EXTERN_DLL_EXPORT void DisposeExportedCPathD(CPathD p); 0120 EXTERN_DLL_EXPORT void DisposeExportedCPathsD(CPathsD& pp); 0121 EXTERN_DLL_EXPORT void DisposeExportedCPolyTree64(CPolyTree64*& cpt); 0122 EXTERN_DLL_EXPORT void DisposeExportedCPolyTreeD(CPolyTreeD*& cpt); 0123 0124 // Boolean clipping: 0125 // cliptype: None=0, Intersection=1, Union=2, Difference=3, Xor=4 0126 // fillrule: EvenOdd=0, NonZero=1, Positive=2, Negative=3 0127 EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype, 0128 uint8_t fillrule, const CPaths64 subjects, 0129 const CPaths64 subjects_open, const CPaths64 clips, 0130 CPaths64& solution, CPaths64& solution_open, 0131 bool preserve_collinear = true, bool reverse_solution = false); 0132 EXTERN_DLL_EXPORT int BooleanOpPt64(uint8_t cliptype, 0133 uint8_t fillrule, const CPaths64 subjects, 0134 const CPaths64 subjects_open, const CPaths64 clips, 0135 CPolyTree64*& solution, CPaths64& solution_open, 0136 bool preserve_collinear = true, bool reverse_solution = false); 0137 EXTERN_DLL_EXPORT int BooleanOpD(uint8_t cliptype, 0138 uint8_t fillrule, const CPathsD subjects, 0139 const CPathsD subjects_open, const CPathsD clips, 0140 CPathsD& solution, CPathsD& solution_open, int precision = 2, 0141 bool preserve_collinear = true, bool reverse_solution = false); 0142 EXTERN_DLL_EXPORT int BooleanOpPtD(uint8_t cliptype, 0143 uint8_t fillrule, const CPathsD subjects, 0144 const CPathsD subjects_open, const CPathsD clips, 0145 CPolyTreeD*& solution, CPathsD& solution_open, int precision = 2, 0146 bool preserve_collinear = true, bool reverse_solution = false); 0147 0148 // Polygon offsetting (inflate/deflate): 0149 // jointype: Square=0, Round=1, Miter=2 0150 // endtype: Polygon=0, Joined=1, Butt=2, Square=3, Round=4 0151 EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths, 0152 double delta, uint8_t jointype, uint8_t endtype, 0153 double miter_limit = 2.0, double arc_tolerance = 0.0, 0154 bool reverse_solution = false); 0155 EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths, 0156 double delta, uint8_t jointype, uint8_t endtype, 0157 int precision = 2, double miter_limit = 2.0, 0158 double arc_tolerance = 0.0, bool reverse_solution = false); 0159 0160 // RectClip & RectClipLines: 0161 EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect, 0162 const CPaths64 paths); 0163 EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect, 0164 const CPathsD paths, int precision = 2); 0165 EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect, 0166 const CPaths64 paths); 0167 EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect, 0168 const CPathsD paths, int precision = 2); 0169 0170 ////////////////////////////////////////////////////// 0171 // INTERNAL FUNCTIONS 0172 ////////////////////////////////////////////////////// 0173 0174 inline CPath64 CreateCPath64(size_t cnt1, size_t cnt2); 0175 inline CPath64 CreateCPath64(const Path64& p); 0176 inline CPaths64 CreateCPaths64(const Paths64& pp); 0177 inline Path64 ConvertCPath64(const CPath64& p); 0178 inline Paths64 ConvertCPaths64(const CPaths64& pp); 0179 0180 inline CPathD CreateCPathD(size_t cnt1, size_t cnt2); 0181 inline CPathD CreateCPathD(const PathD& p); 0182 inline CPathsD CreateCPathsD(const PathsD& pp); 0183 inline PathD ConvertCPathD(const CPathD& p); 0184 inline PathsD ConvertCPathsD(const CPathsD& pp); 0185 0186 // the following function avoid multiple conversions 0187 inline CPathD CreateCPathD(const Path64& p, double scale); 0188 inline CPathsD CreateCPathsD(const Paths64& pp, double scale); 0189 inline Path64 ConvertCPathD(const CPathD& p, double scale); 0190 inline Paths64 ConvertCPathsD(const CPathsD& pp, double scale); 0191 0192 inline CPolyTree64* CreateCPolyTree64(const PolyTree64& pt); 0193 inline CPolyTreeD* CreateCPolyTreeD(const PolyTree64& pt, double scale); 0194 0195 EXTERN_DLL_EXPORT const char* Version() 0196 { 0197 return CLIPPER2_VERSION; 0198 } 0199 0200 EXTERN_DLL_EXPORT void DisposeExportedCPath64(CPath64 p) 0201 { 0202 if (p) delete[] p; 0203 } 0204 0205 EXTERN_DLL_EXPORT void DisposeExportedCPaths64(CPaths64& pp) 0206 { 0207 if (!pp) return; 0208 CPaths64 v = pp; 0209 CPath64 cnts = *v; 0210 const size_t cnt = static_cast<size_t>(cnts[1]); 0211 for (size_t i = 0; i <= cnt; ++i) //nb: cnt +1 0212 DisposeExportedCPath64(*v++); 0213 delete[] pp; 0214 pp = nullptr; 0215 } 0216 0217 EXTERN_DLL_EXPORT void DisposeExportedCPathD(CPathD p) 0218 { 0219 if (p) delete[] p; 0220 } 0221 0222 EXTERN_DLL_EXPORT void DisposeExportedCPathsD(CPathsD& pp) 0223 { 0224 if (!pp) return; 0225 CPathsD v = pp; 0226 CPathD cnts = *v; 0227 size_t cnt = static_cast<size_t>(cnts[1]); 0228 for (size_t i = 0; i <= cnt; ++i) //nb: cnt +1 0229 DisposeExportedCPathD(*v++); 0230 delete[] pp; 0231 pp = nullptr; 0232 } 0233 0234 EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype, 0235 uint8_t fillrule, const CPaths64 subjects, 0236 const CPaths64 subjects_open, const CPaths64 clips, 0237 CPaths64& solution, CPaths64& solution_open, 0238 bool preserve_collinear, bool reverse_solution) 0239 { 0240 if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4; 0241 if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3; 0242 0243 Paths64 sub, sub_open, clp, sol, sol_open; 0244 sub = ConvertCPaths64(subjects); 0245 sub_open = ConvertCPaths64(subjects_open); 0246 clp = ConvertCPaths64(clips); 0247 0248 Clipper64 clipper; 0249 clipper.PreserveCollinear = preserve_collinear; 0250 clipper.ReverseSolution = reverse_solution; 0251 if (sub.size() > 0) clipper.AddSubject(sub); 0252 if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open); 0253 if (clp.size() > 0) clipper.AddClip(clp); 0254 if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), sol, sol_open)) 0255 return -1; // clipping bug - should never happen :) 0256 solution = CreateCPaths64(sol); 0257 solution_open = CreateCPaths64(sol_open); 0258 return 0; //success !! 0259 } 0260 0261 EXTERN_DLL_EXPORT int BooleanOpPt64(uint8_t cliptype, 0262 uint8_t fillrule, const CPaths64 subjects, 0263 const CPaths64 subjects_open, const CPaths64 clips, 0264 CPolyTree64*& solution, CPaths64& solution_open, 0265 bool preserve_collinear, bool reverse_solution) 0266 { 0267 if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4; 0268 if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3; 0269 Paths64 sub, sub_open, clp, sol_open; 0270 sub = ConvertCPaths64(subjects); 0271 sub_open = ConvertCPaths64(subjects_open); 0272 clp = ConvertCPaths64(clips); 0273 0274 PolyTree64 pt; 0275 Clipper64 clipper; 0276 clipper.PreserveCollinear = preserve_collinear; 0277 clipper.ReverseSolution = reverse_solution; 0278 if (sub.size() > 0) clipper.AddSubject(sub); 0279 if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open); 0280 if (clp.size() > 0) clipper.AddClip(clp); 0281 if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), pt, sol_open)) 0282 return -1; // clipping bug - should never happen :) 0283 0284 solution = CreateCPolyTree64(pt); 0285 solution_open = CreateCPaths64(sol_open); 0286 return 0; //success !! 0287 } 0288 0289 EXTERN_DLL_EXPORT int BooleanOpD(uint8_t cliptype, 0290 uint8_t fillrule, const CPathsD subjects, 0291 const CPathsD subjects_open, const CPathsD clips, 0292 CPathsD& solution, CPathsD& solution_open, int precision, 0293 bool preserve_collinear, bool reverse_solution) 0294 { 0295 if (precision < -8 || precision > 8) return -5; 0296 if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4; 0297 if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3; 0298 const double scale = std::pow(10, precision); 0299 0300 Paths64 sub, sub_open, clp, sol, sol_open; 0301 sub = ConvertCPathsD(subjects, scale); 0302 sub_open = ConvertCPathsD(subjects_open, scale); 0303 clp = ConvertCPathsD(clips, scale); 0304 0305 Clipper64 clipper; 0306 clipper.PreserveCollinear = preserve_collinear; 0307 clipper.ReverseSolution = reverse_solution; 0308 if (sub.size() > 0) clipper.AddSubject(sub); 0309 if (sub_open.size() > 0) 0310 clipper.AddOpenSubject(sub_open); 0311 if (clp.size() > 0) clipper.AddClip(clp); 0312 if (!clipper.Execute(ClipType(cliptype), 0313 FillRule(fillrule), sol, sol_open)) return -1; 0314 0315 if (sol.size() > 0) solution = CreateCPathsD(sol, 1 / scale); 0316 if (sol_open.size() > 0) 0317 solution_open = CreateCPathsD(sol_open, 1 / scale); 0318 return 0; 0319 } 0320 0321 EXTERN_DLL_EXPORT int BooleanOpPtD(uint8_t cliptype, 0322 uint8_t fillrule, const CPathsD subjects, 0323 const CPathsD subjects_open, const CPathsD clips, 0324 CPolyTreeD*& solution, CPathsD& solution_open, int precision, 0325 bool preserve_collinear, bool reverse_solution) 0326 { 0327 if (precision < -8 || precision > 8) return -5; 0328 if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4; 0329 if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3; 0330 0331 const double scale = std::pow(10, precision); 0332 Paths64 sub, sub_open, clp, sol_open; 0333 sub = ConvertCPathsD(subjects, scale); 0334 sub_open = ConvertCPathsD(subjects_open, scale); 0335 clp = ConvertCPathsD(clips, scale); 0336 0337 PolyTree64 sol; 0338 Clipper64 clipper; 0339 clipper.PreserveCollinear = preserve_collinear; 0340 clipper.ReverseSolution = reverse_solution; 0341 if (sub.size() > 0) clipper.AddSubject(sub); 0342 if (sub_open.size() > 0) 0343 clipper.AddOpenSubject(sub_open); 0344 if (clp.size() > 0) clipper.AddClip(clp); 0345 if (!clipper.Execute(ClipType(cliptype), 0346 FillRule(fillrule), sol, sol_open)) return -1; 0347 0348 solution = CreateCPolyTreeD(sol, 1 / scale); 0349 if (sol_open.size() > 0) 0350 solution_open = CreateCPathsD(sol_open, 1 / scale); 0351 return 0; 0352 } 0353 0354 EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths, 0355 double delta, uint8_t jointype, uint8_t endtype, double miter_limit, 0356 double arc_tolerance, bool reverse_solution) 0357 { 0358 Paths64 pp; 0359 pp = ConvertCPaths64(paths); 0360 0361 ClipperOffset clip_offset( miter_limit, 0362 arc_tolerance, reverse_solution); 0363 clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype)); 0364 Paths64 result; 0365 clip_offset.Execute(delta, result); 0366 return CreateCPaths64(result); 0367 } 0368 0369 EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths, 0370 double delta, uint8_t jointype, uint8_t endtype, 0371 int precision, double miter_limit, 0372 double arc_tolerance, bool reverse_solution) 0373 { 0374 if (precision < -8 || precision > 8 || !paths) return nullptr; 0375 const double scale = std::pow(10, precision); 0376 ClipperOffset clip_offset(miter_limit, arc_tolerance, reverse_solution); 0377 Paths64 pp = ConvertCPathsD(paths, scale); 0378 clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype)); 0379 Paths64 result; 0380 clip_offset.Execute(delta * scale, result); 0381 return CreateCPathsD(result, 1/scale); 0382 } 0383 0384 EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect, const CPaths64 paths) 0385 { 0386 if (CRectIsEmpty(rect) || !paths) return nullptr; 0387 Rect64 r64 = CRectToRect(rect); 0388 class RectClip64 rc(r64); 0389 Paths64 pp = ConvertCPaths64(paths); 0390 Paths64 result = rc.Execute(pp); 0391 return CreateCPaths64(result); 0392 } 0393 0394 EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect, const CPathsD paths, int precision) 0395 { 0396 if (CRectIsEmpty(rect) || !paths) return nullptr; 0397 if (precision < -8 || precision > 8) return nullptr; 0398 const double scale = std::pow(10, precision); 0399 0400 RectD r = CRectToRect(rect); 0401 Rect64 rec = ScaleRect<int64_t, double>(r, scale); 0402 Paths64 pp = ConvertCPathsD(paths, scale); 0403 class RectClip64 rc(rec); 0404 Paths64 result = rc.Execute(pp); 0405 return CreateCPathsD(result, 1/scale); 0406 } 0407 0408 EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect, 0409 const CPaths64 paths) 0410 { 0411 if (CRectIsEmpty(rect) || !paths) return nullptr; 0412 Rect64 r = CRectToRect(rect); 0413 class RectClipLines64 rcl (r); 0414 Paths64 pp = ConvertCPaths64(paths); 0415 Paths64 result = rcl.Execute(pp); 0416 return CreateCPaths64(result); 0417 } 0418 0419 EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect, 0420 const CPathsD paths, int precision) 0421 { 0422 if (CRectIsEmpty(rect) || !paths) return nullptr; 0423 if (precision < -8 || precision > 8) return nullptr; 0424 const double scale = std::pow(10, precision); 0425 Rect64 r = ScaleRect<int64_t, double>(CRectToRect(rect), scale); 0426 class RectClipLines64 rcl(r); 0427 Paths64 pp = ConvertCPathsD(paths, scale); 0428 Paths64 result = rcl.Execute(pp); 0429 return CreateCPathsD(result, 1/scale); 0430 } 0431 0432 inline CPath64 CreateCPath64(size_t cnt1, size_t cnt2) 0433 { 0434 // allocates memory for CPath64, fills in the counter, and 0435 // returns the structure ready to be filled with path data 0436 CPath64 result = new int64_t[2 + cnt1 *2]; 0437 result[0] = cnt1; 0438 result[1] = cnt2; 0439 return result; 0440 } 0441 0442 inline CPath64 CreateCPath64(const Path64& p) 0443 { 0444 // allocates memory for CPath64, fills the counter 0445 // and returns the memory filled with path data 0446 size_t cnt = p.size(); 0447 if (!cnt) return nullptr; 0448 CPath64 result = CreateCPath64(cnt, 0); 0449 CPath64 v = result; 0450 v += 2; // skip counters 0451 for (const Point64& pt : p) 0452 { 0453 *v++ = pt.x; 0454 *v++ = pt.y; 0455 } 0456 return result; 0457 } 0458 0459 inline Path64 ConvertCPath64(const CPath64& p) 0460 { 0461 Path64 result; 0462 if (p && *p) 0463 { 0464 CPath64 v = p; 0465 const size_t cnt = static_cast<size_t>(p[0]); 0466 v += 2; // skip counters 0467 result.reserve(cnt); 0468 for (size_t i = 0; i < cnt; ++i) 0469 { 0470 // x,y here avoids right to left function evaluation 0471 // result.push_back(Point64(*v++, *v++)); 0472 int64_t x = *v++; 0473 int64_t y = *v++; 0474 result.push_back(Point64(x, y)); 0475 } 0476 } 0477 return result; 0478 } 0479 0480 inline CPaths64 CreateCPaths64(const Paths64& pp) 0481 { 0482 // allocates memory for multiple CPath64 and 0483 // and returns this memory filled with path data 0484 size_t cnt = pp.size(), cnt2 = cnt; 0485 0486 // don't allocate space for empty paths 0487 for (size_t i = 0; i < cnt; ++i) 0488 if (!pp[i].size()) --cnt2; 0489 if (!cnt2) return nullptr; 0490 0491 CPaths64 result = new int64_t* [cnt2 + 1]; 0492 CPaths64 v = result; 0493 *v++ = CreateCPath64(0, cnt2); // assign a counter path 0494 for (const Path64& p : pp) 0495 { 0496 *v = CreateCPath64(p); 0497 if (*v) ++v; 0498 } 0499 return result; 0500 } 0501 0502 inline Paths64 ConvertCPaths64(const CPaths64& pp) 0503 { 0504 Paths64 result; 0505 if (pp) 0506 { 0507 CPaths64 v = pp; 0508 CPath64 cnts = pp[0]; 0509 const size_t cnt = static_cast<size_t>(cnts[1]); // nb 2nd cnt 0510 ++v; // skip cnts 0511 result.reserve(cnt); 0512 for (size_t i = 0; i < cnt; ++i) 0513 result.push_back(ConvertCPath64(*v++)); 0514 } 0515 return result; 0516 } 0517 0518 inline CPathD CreateCPathD(size_t cnt1, size_t cnt2) 0519 { 0520 // allocates memory for CPathD, fills in the counter, and 0521 // returns the structure ready to be filled with path data 0522 CPathD result = new double[2 + cnt1 * 2]; 0523 result[0] = static_cast<double>(cnt1); 0524 result[1] = static_cast<double>(cnt2); 0525 return result; 0526 } 0527 0528 inline CPathD CreateCPathD(const PathD& p) 0529 { 0530 // allocates memory for CPath, fills the counter 0531 // and returns the memory fills with path data 0532 size_t cnt = p.size(); 0533 if (!cnt) return nullptr; 0534 CPathD result = CreateCPathD(cnt, 0); 0535 CPathD v = result; 0536 v += 2; // skip counters 0537 for (const PointD& pt : p) 0538 { 0539 *v++ = pt.x; 0540 *v++ = pt.y; 0541 } 0542 return result; 0543 } 0544 0545 inline PathD ConvertCPathD(const CPathD& p) 0546 { 0547 PathD result; 0548 if (p) 0549 { 0550 CPathD v = p; 0551 size_t cnt = static_cast<size_t>(v[0]); 0552 v += 2; // skip counters 0553 result.reserve(cnt); 0554 for (size_t i = 0; i < cnt; ++i) 0555 { 0556 // x,y here avoids right to left function evaluation 0557 // result.push_back(PointD(*v++, *v++)); 0558 double x = *v++; 0559 double y = *v++; 0560 result.push_back(PointD(x, y)); 0561 } 0562 } 0563 return result; 0564 } 0565 0566 inline CPathsD CreateCPathsD(const PathsD& pp) 0567 { 0568 size_t cnt = pp.size(), cnt2 = cnt; 0569 // don't allocate space for empty paths 0570 for (size_t i = 0; i < cnt; ++i) 0571 if (!pp[i].size()) --cnt2; 0572 if (!cnt2) return nullptr; 0573 CPathsD result = new double * [cnt2 + 1]; 0574 CPathsD v = result; 0575 *v++ = CreateCPathD(0, cnt2); // assign counter path 0576 for (const PathD& p : pp) 0577 { 0578 *v = CreateCPathD(p); 0579 if (*v) { ++v; } 0580 } 0581 return result; 0582 } 0583 0584 inline PathsD ConvertCPathsD(const CPathsD& pp) 0585 { 0586 PathsD result; 0587 if (pp) 0588 { 0589 CPathsD v = pp; 0590 CPathD cnts = v[0]; 0591 size_t cnt = static_cast<size_t>(cnts[1]); 0592 ++v; // skip cnts path 0593 result.reserve(cnt); 0594 for (size_t i = 0; i < cnt; ++i) 0595 result.push_back(ConvertCPathD(*v++)); 0596 } 0597 return result; 0598 } 0599 0600 inline Path64 ConvertCPathD(const CPathD& p, double scale) 0601 { 0602 Path64 result; 0603 if (p) 0604 { 0605 CPathD v = p; 0606 size_t cnt = static_cast<size_t>(*v); 0607 v += 2; // skip counters 0608 result.reserve(cnt); 0609 for (size_t i = 0; i < cnt; ++i) 0610 { 0611 // x,y here avoids right to left function evaluation 0612 // result.push_back(PointD(*v++, *v++)); 0613 double x = *v++ * scale; 0614 double y = *v++ * scale; 0615 result.push_back(Point64(x, y)); 0616 } 0617 } 0618 return result; 0619 } 0620 0621 inline Paths64 ConvertCPathsD(const CPathsD& pp, double scale) 0622 { 0623 Paths64 result; 0624 if (pp) 0625 { 0626 CPathsD v = pp; 0627 CPathD cnts = v[0]; 0628 size_t cnt = static_cast<size_t>(cnts[1]); 0629 result.reserve(cnt); 0630 ++v; // skip cnts path 0631 for (size_t i = 0; i < cnt; ++i) 0632 result.push_back(ConvertCPathD(*v++, scale)); 0633 } 0634 return result; 0635 } 0636 0637 inline CPathD CreateCPathD(const Path64& p, double scale) 0638 { 0639 // allocates memory for CPathD, fills in the counter, and 0640 // returns the structure filled with *scaled* path data 0641 size_t cnt = p.size(); 0642 if (!cnt) return nullptr; 0643 CPathD result = CreateCPathD(cnt, 0); 0644 CPathD v = result; 0645 v += 2; // skip cnts 0646 for (const Point64& pt : p) 0647 { 0648 *v++ = pt.x * scale; 0649 *v++ = pt.y * scale; 0650 } 0651 return result; 0652 } 0653 0654 inline CPathsD CreateCPathsD(const Paths64& pp, double scale) 0655 { 0656 // allocates memory for *multiple* CPathD, and 0657 // returns the structure filled with scaled path data 0658 size_t cnt = pp.size(), cnt2 = cnt; 0659 // don't allocate space for empty paths 0660 for (size_t i = 0; i < cnt; ++i) 0661 if (!pp[i].size()) --cnt2; 0662 if (!cnt2) return nullptr; 0663 CPathsD result = new double* [cnt2 + 1]; 0664 CPathsD v = result; 0665 *v++ = CreateCPathD(0, cnt2); 0666 for (const Path64& p : pp) 0667 { 0668 *v = CreateCPathD(p, scale); 0669 if (*v) ++v; 0670 } 0671 return result; 0672 } 0673 0674 inline void InitCPolyPath64(CPolyTree64* cpt, 0675 bool is_hole, const std::unique_ptr <PolyPath64>& pp) 0676 { 0677 cpt->polygon = CreateCPath64(pp->Polygon()); 0678 cpt->is_hole = is_hole; 0679 size_t child_cnt = pp->Count(); 0680 cpt->child_count = static_cast<uint32_t>(child_cnt); 0681 cpt->childs = nullptr; 0682 if (!child_cnt) return; 0683 cpt->childs = new CPolyPath64[child_cnt]; 0684 CPolyPath64* child = cpt->childs; 0685 for (const std::unique_ptr <PolyPath64>& pp_child : *pp) 0686 InitCPolyPath64(child++, !is_hole, pp_child); 0687 } 0688 0689 inline CPolyTree64* CreateCPolyTree64(const PolyTree64& pt) 0690 { 0691 CPolyTree64* result = new CPolyTree64(); 0692 result->polygon = nullptr; 0693 result->is_hole = false; 0694 size_t child_cnt = pt.Count(); 0695 result->childs = nullptr; 0696 result->child_count = static_cast<uint32_t>(child_cnt); 0697 if (!child_cnt) return result; 0698 result->childs = new CPolyPath64[child_cnt]; 0699 CPolyPath64* child = result->childs; 0700 for (const std::unique_ptr <PolyPath64>& pp : pt) 0701 InitCPolyPath64(child++, true, pp); 0702 return result; 0703 } 0704 0705 inline void DisposeCPolyPath64(CPolyPath64* cpp) 0706 { 0707 if (!cpp->child_count) return; 0708 CPolyPath64* child = cpp->childs; 0709 for (size_t i = 0; i < cpp->child_count; ++i) 0710 DisposeCPolyPath64(child); 0711 delete[] cpp->childs; 0712 } 0713 0714 EXTERN_DLL_EXPORT void DisposeExportedCPolyTree64(CPolyTree64*& cpt) 0715 { 0716 if (!cpt) return; 0717 DisposeCPolyPath64(cpt); 0718 delete cpt; 0719 cpt = nullptr; 0720 } 0721 0722 inline void InitCPolyPathD(CPolyTreeD* cpt, 0723 bool is_hole, const std::unique_ptr <PolyPath64>& pp, double scale) 0724 { 0725 cpt->polygon = CreateCPathD(pp->Polygon(), scale); 0726 cpt->is_hole = is_hole; 0727 size_t child_cnt = pp->Count(); 0728 cpt->child_count = static_cast<uint32_t>(child_cnt); 0729 cpt->childs = nullptr; 0730 if (!child_cnt) return; 0731 cpt->childs = new CPolyPathD[child_cnt]; 0732 CPolyPathD* child = cpt->childs; 0733 for (const std::unique_ptr <PolyPath64>& pp_child : *pp) 0734 InitCPolyPathD(child++, !is_hole, pp_child, scale); 0735 } 0736 0737 inline CPolyTreeD* CreateCPolyTreeD(const PolyTree64& pt, double scale) 0738 { 0739 CPolyTreeD* result = new CPolyTreeD(); 0740 result->polygon = nullptr; 0741 result->is_hole = false; 0742 size_t child_cnt = pt.Count(); 0743 result->child_count = static_cast<uint32_t>(child_cnt); 0744 result->childs = nullptr; 0745 if (!child_cnt) return result; 0746 result->childs = new CPolyPathD[child_cnt]; 0747 CPolyPathD* child = result->childs; 0748 for (const std::unique_ptr <PolyPath64>& pp : pt) 0749 InitCPolyPathD(child++, true, pp, scale); 0750 return result; 0751 } 0752 0753 inline void DisposeCPolyPathD(CPolyPathD* cpp) 0754 { 0755 if (!cpp->child_count) return; 0756 CPolyPathD* child = cpp->childs; 0757 for (size_t i = 0; i < cpp->child_count; ++i) 0758 DisposeCPolyPathD(child++); 0759 delete[] cpp->childs; 0760 } 0761 0762 EXTERN_DLL_EXPORT void DisposeExportedCPolyTreeD(CPolyTreeD*& cpt) 0763 { 0764 if (!cpt) return; 0765 DisposeCPolyPathD(cpt); 0766 delete cpt; 0767 cpt = nullptr; 0768 } 0769 0770 } // end Clipper2Lib namespace 0771 0772 #endif // CLIPPER2_EXPORT_H