11/*******************************************************************************
22* Author : Angus Johnson *
3- * Date : 29 October 2023 *
3+ * Date : 18 December 2025 *
44* Website : https://www.angusj.com *
5- * Copyright : Angus Johnson 2010-2023 *
5+ * Copyright : Angus Johnson 2010-2025 *
66* License : https://www.boost.org/LICENSE_1_0.txt *
77*******************************************************************************/
88
99using Clipper2Dll ;
10- using System . Globalization ;
11- using System . Runtime . InteropServices ;
1210using static Clipper2Dll . Clipper2DllCore ;
1311using static Clipper2Dll . SvgWriterUtils ;
1412
@@ -68,6 +66,16 @@ private static void DrawSVG(string filename, long[]? cSubjects, long[]? cClips,
6866 OpenFileWithDefaultApp ( filename ) ;
6967 }
7068
69+ private static void DrawSVG_MultiColor ( string filename , long [ ] ? cSolution )
70+ {
71+ SvgWriter svg = new SvgWriter ( ) ;
72+ if ( cSolution == null ) return ;
73+ AddSolution_MultiColor ( svg , cSolution , false ) ;
74+ svg . SaveToFile ( filename , 400 , 400 ) ;
75+ OpenFileWithDefaultApp ( filename ) ;
76+ }
77+
78+
7179 private static void DrawSVG ( string filename , double [ ] cSubjects , double [ ] cClips , double [ ] cSolution )
7280 {
7381 SvgWriter svg = new SvgWriter ( ) ;
@@ -99,74 +107,58 @@ private static void DrawSVG(string filename, double[] cSubjects, double[] cClips
99107 OpenFileWithDefaultApp ( filename ) ;
100108 }
101109
102- /// Main Entry ////////////////////////////////////////////////////////////
103- public static void Main ( )
104- {
105- //string? ver = Marshal.PtrToStringAnsi(Version());
106- //Console.WriteLine(ver + "\n");
107-
108- #if USINGZ
109- SetZCallback64 ( MyCallBack64 ) ;
110- SetZCallbackD ( MyCallBackD ) ;
111- #endif
112-
113- /////////////////////////////////////////////////////////////////////////
114- // test BooleanOp64() ///////////////////////////////////////////////////
115- /////////////////////////////////////////////////////////////////////////
116110
111+ public static void TestBooleanOp64 ( )
112+ {
117113#if USINGZ
118- long [ ] cSubject = CreateCPathsFromCoords ( new long [ ] { 0 , 0 , 1 , 100 , 0 , 2 , 100 , 100 , 3 , 0 , 100 , 4 } ) ;
119- long [ ] cClip = CreateCPathsFromCoords ( new long [ ] { 20 , 20 , 1 , 120 , 20 , 2 , 120 , 120 , 3 , 20 , 120 , 4 } ) ;
120- counter = 11 ;
114+ long [ ] cSubject = CreateCPathsFromCoords ( new long [ ] { 0 , 0 , 1 , 100 , 0 , 2 , 100 , 100 , 3 , 0 , 100 , 4 } ) ;
115+ long [ ] cClip = CreateCPathsFromCoords ( new long [ ] { 30 , 30 , 1 , 130 , 30 , 2 , 130 , 130 , 3 , 30 , 130 , 4 } ) ;
116+ counter = 11 ;
121117#else
122- long [ ] cSubject = CreateCPathsFromCoords ( new long [ ] { 0 , 0 , 100 , 0 , 100 , 100 , 0 , 100 } ) ;
123- long [ ] cClip = CreateCPathsFromCoords ( new long [ ] { 20 , 20 , 120 , 20 , 120 , 120 , 20 , 120 } ) ;
118+ long [ ] cSubject = CreateCPathsFromCoords ( new long [ ] { 0 , 0 , 100 , 0 , 100 , 100 , 0 , 100 } ) ;
119+ long [ ] cClip = CreateCPathsFromCoords ( new long [ ] { 30 , 30 , 130 , 30 , 130 , 130 , 30 , 130 } ) ;
124120#endif
125121
126- if ( BooleanOp64 ( ( int ) ClipType . Intersection , ( int ) FillRule . NonZero , cSubject ,
127- null , cClip , out IntPtr cSol , out IntPtr cSolOpen , false , false ) != 0 ) return ;
122+ if ( BooleanOp64 ( ( int ) ClipType . Intersection , ( int ) FillRule . NonZero , cSubject ,
123+ null , cClip , out IntPtr cSol , out IntPtr cSolOpen , false , false ) != 0 ) return ;
128124
129- long [ ] ? cSolution = GetArrayFromIntPtr < long > ( cSol ) ;
125+ long [ ] ? cSolution = GetArrayFromIntPtr < long > ( cSol ) ;
130126
131- //Console.WriteLine("BooleanOp64:");
132- //LogCPaths(cSolution, " ");
127+ //Console.WriteLine("BooleanOp64:");
128+ //LogCPaths(cSolution, " ");
133129
134- // clean up unmanaged memory
135- DisposeArray64 ( ref cSol ) ;
136- DisposeArray64 ( ref cSolOpen ) ;
130+ // clean up unmanaged memory
131+ DisposeArray64 ( ref cSol ) ;
132+ DisposeArray64 ( ref cSolOpen ) ;
137133
138- DrawSVG ( @"..\..\..\rectangles.svg" , cSubject , cClip , cSolution ) ;
134+ DrawSVG ( @"..\..\..\rectangles.svg" , cSubject , cClip , cSolution ) ;
135+ }
139136
140- /////////////////////////////////////////////////////////////////////////
141- // test BooleanOpD() ////////////////////////////////////////////////////
142- /////////////////////////////////////////////////////////////////////////
143137
138+ public static void TestBooleanOpD ( )
139+ {
144140#if USINGZ
145- double [ ] cSubjectD = CreateCPathsFromCoords ( new double [ ] { 0 , 0 , 1 , 100 , 0 , 2 , 100 , 100 , 3 , 0 , 100 , 4 } ) ;
146- double [ ] cClipD = CreateCPathsFromCoords ( new double [ ] { 20 , 20 , 1 , 120 , 20 , 2 , 120 , 120 , 3 , 20 , 120 , 4 } ) ;
141+ double [ ] cSubjectD = CreateCPathsFromCoords ( new double [ ] { 0 , 0 , 1 , 100 , 0 , 2 , 100 , 100 , 3 , 0 , 100 , 4 } ) ;
142+ double [ ] cClipD = CreateCPathsFromCoords ( new double [ ] { 30 , 30 , 1 , 130 , 30 , 2 , 130 , 130 , 3 , 30 , 130 , 4 } ) ;
147143 counter = 21 ;
148144#else
149145 double [ ] cSubjectD = CreateCPathsFromCoords ( new double [ ] { 0 , 0 , 100 , 0 , 100 , 100 , 0 , 100 } ) ;
150- double [ ] cClipD = CreateCPathsFromCoords ( new double [ ] { 20 , 20 , 120 , 20 , 120 , 120 , 20 , 120 } ) ;
146+ double [ ] cClipD = CreateCPathsFromCoords ( new double [ ] { 30 , 30 , 130 , 30 , 130 , 130 , 30 , 130 } ) ;
151147#endif
152148 int resultD = BooleanOpD ( ( int ) ClipType . Intersection , ( int ) FillRule . NonZero , cSubjectD ,
153149 null , cClipD , out IntPtr cSolD , out IntPtr cSolOpenD , 2 , false , false ) ;
154150 if ( resultD != 0 ) return ;
155151 double [ ] ? cSolutionD = GetArrayFromIntPtr < double > ( cSolD ) ;
156-
157- //Console.WriteLine("BooleanOpD:");
158- //LogCPaths(cSolutionD, " ");
159152
160153 // clean up unmanaged memory
161154 DisposeArrayD ( ref cSolD ) ;
162155 DisposeArrayD ( ref cSolOpenD ) ;
163156
164157 DrawSVG ( @"..\..\..\rectangles2.svg" , cSubjectD , cClipD , cSolutionD ! ) ;
158+ }
165159
166- /////////////////////////////////////////////////////////////////////////
167- // test BooleanOp_PolyTree64() //////////////////////////////////////////
168- /////////////////////////////////////////////////////////////////////////
169-
160+ public static void TestBooleanOp_Polytree64 ( )
161+ {
170162 // create arrays of x,y coords that define 5 successively
171163 // larger rectangles centered on the origin ...
172164 List < long [ ] > cRectangles = new ( 5 ) ;
@@ -176,7 +168,7 @@ public static void Main()
176168 - i * 20 , - i * 20 , 1 , i * 20 , - i * 20 , 2 , i * 20 , i * 20 , 3 , - i * 20 , i * 20 , 4 } ) ! ) ;
177169 long [ ] cSubjects = CreateCPathsFromCPathList ( cRectangles ) ;
178170 long [ ] cClips = CreateCPathsFromCoords (
179- new long [ ] { - 90 , - 120 , 11 , 90 , - 120 , 12 , 90 , 120 , 13 , - 90 , 120 , 14 } ) ;
171+ new long [ ] { - 90 , - 120 , 11 , 90 , - 120 , 12 , 90 , 120 , 13 , - 90 , 120 , 14 } ) ;
180172 counter = 31 ;
181173#else
182174 for ( int i = 1 ; i < 6 ; ++ i )
@@ -186,7 +178,7 @@ public static void Main()
186178 long [ ] cClips = CreateCPathsFromCoords ( new long [ ] { - 90 , - 120 , 90 , - 120 , 90 , 120 , - 90 , 120 } ) ;
187179#endif
188180
189- int result3 = BooleanOp_PolyTree64 ( ( int ) ClipType . Intersection ,
181+ int result3 = BooleanOp_PolyTree64 ( ( int ) ClipType . Intersection ,
190182 ( int ) FillRule . EvenOdd , cSubjects , null , cClips ,
191183 out IntPtr cSol_pt64 , out IntPtr cSolOpen_pt64 , false , false ) ;
192184 if ( result3 != 0 ) return ;
@@ -202,11 +194,11 @@ public static void Main()
202194
203195 ConvertCPolytreeToCPaths ( cPolyTree64 , out long [ ] solution5 ) ;
204196 DrawSVG ( @"..\..\..\polytree64.svg" , cSubjects , cClips , solution5 ) ;
197+ }
205198
206- /////////////////////////////////////////////////////////////////////////
207- // test BooleanOp_PolyTreeD() ///////////////////////////////////////////
208- /////////////////////////////////////////////////////////////////////////
209-
199+
200+ public static void TestBooleanOp_PolytreeD ( )
201+ {
210202 List < double [ ] > subList2 = new ( 5 ) ;
211203#if USINGZ
212204 for ( int i = 1 ; i < 6 ; ++ i )
@@ -223,7 +215,7 @@ public static void Main()
223215 double [ ] cClip4 = CreateCPathsFromCoords ( new double [ ] { - 90 , - 120 , 90 , - 120 , 90 , 120 , - 90 , 120 } ) ;
224216#endif
225217
226- int result4 = BooleanOp_PolyTreeD ( ( int ) ClipType . Intersection ,
218+ int result4 = BooleanOp_PolyTreeD ( ( int ) ClipType . Intersection ,
227219 ( int ) FillRule . EvenOdd , cSubject4 , null , cClip4 ,
228220 out IntPtr cSol_ptD , out IntPtr cSolOpen_ptD , 2 , false , false ) ;
229221 if ( result4 != 0 ) return ;
@@ -241,9 +233,81 @@ public static void Main()
241233
242234 ConvertCPolytreeToCPaths ( cPolyTreeD , out double [ ] solution6 ) ;
243235 DrawSVG ( @"..\..\..\polytreeD.svg" , cSubject4 , cClip4 , solution6 ) ;
236+ }
237+
238+ public static void TestTriangulate ( )
239+ {
240+ // 'coral3' outline ...
241+ long arrLen = 2 + ( 2 + 248 * 2 ) + ( 2 + 28 * 2 ) + ( 2 + 20 * 2 ) ;
242+ long [ ] subjects =
243+ {
244+ arrLen , 3 , // array length, 3 polygon contours (1 outer path + 2 holes)
245+ // outer path
246+ 248 , 0 , // outer path length, discarded 0 value
247+ 5685 , 2435 , 5720 , 2510 , 5700 , 2600 , 5570 , 2770 , 5380 , 2920 , 5210 , 2990 , 5110 , 2990 , 5050 , 2970 , 4970 ,
248+ 2930 , 4850 , 2895 , 4770 , 2920 , 4700 , 3040 , 4570 , 3430 , 4440 , 3910 , 4370 , 4140 , 4270 , 4330 , 4100 , 4500 ,
249+ 3870 , 4660 , 3700 , 4820 , 3660 , 4910 , 3680 , 5010 , 3730 , 5070 , 3790 , 5100 , 3960 , 5110 , 4140 , 5070 , 4300 ,
250+ 5000 , 4520 , 4840 , 4730 , 4600 , 5110 , 4010 , 5390 , 3550 , 5470 , 3485 , 5530 , 3495 , 5560 , 3530 , 5580 , 3710 ,
251+ 5540 , 3900 , 5340 , 4310 , 5080 , 4690 , 4850 , 4990 , 4740 , 5110 , 4570 , 5220 , 4160 , 5420 , 3730 , 5560 , 3400 ,
252+ 5620 , 3060 , 5610 , 2710 , 5570 , 2380 , 5500 , 2070 , 5370 , 1770 , 5150 , 1520 , 4880 , 1060 , 4290 , 670 , 3930 ,
253+ 490 , 3740 , 370 , 3520 , 270 , 3150 , 270 , 2980 , 310 , 2920 , 370 , 2880 , 450 , 2890 , 510 , 2940 , 580 , 3130 ,
254+ 640 , 3370 , 730 , 3560 , 1040 , 3930 , 1210 , 4050 , 1300 , 4060 , 1370 , 4020 , 1460 , 3880 , 1440 , 3730 , 1340 ,
255+ 3570 , 1190 , 3390 , 830 , 3030 , 690 , 2850 , 590 , 2660 , 520 , 2460 , 510 , 2370 , 560 , 2310 , 630 , 2310 , 690 ,
256+ 2360 , 780 , 2570 , 880 , 2760 , 940 , 2810 , 1000 , 2810 , 1050 , 2760 , 1070 , 2710 , 1040 , 2570 , 820 , 2240 , 600 ,
257+ 1900 , 570 , 1770 , 590 , 1710 , 640 , 1670 , 730 , 1650 , 800 , 1680 , 930 , 1840 , 1140 , 2290 , 1220 , 2480 , 1260 ,
258+ 2690 , 1360 , 3110 , 1710 , 4010 , 1780 , 4270 , 1850 , 4560 , 1950 , 4790 , 2030 , 4840 , 2120 , 4830 , 2220 , 4780 ,
259+ 2290 , 4720 , 2340 , 4540 , 2300 , 4310 , 2200 , 4050 , 1930 , 3480 , 1800 , 3210 , 1720 , 2950 , 1630 , 2720 , 1500 ,
260+ 2470 , 1220 , 1960 , 1120 , 1730 , 1070 , 1510 , 1100 , 1340 , 1150 , 1270 , 1240 , 1210 , 1340 , 1200 , 1430 , 1260 ,
261+ 1500 , 1390 , 1530 , 1580 , 1560 , 1910 , 1620 , 2280 , 1680 , 2430 , 1750 , 2560 , 1850 , 2630 , 1980 , 2640 , 2090 ,
262+ 2590 , 2160 , 2480 , 2180 , 2340 , 2170 , 2170 , 2110 , 1800 , 2050 , 1450 , 2020 , 1280 , 1950 , 1090 , 1770 , 700 ,
263+ 1700 , 530 , 1680 , 370 , 1720 , 260 , 1820 , 190 , 1930 , 200 , 2000 , 290 , 2080 , 660 , 2150 , 1050 , 2230 , 1180 ,
264+ 2350 , 1230 , 2430 , 1200 , 2480 , 1110 , 2530 , 860 , 2580 , 620 , 2630 , 560 , 2710 , 550 , 2830 , 630 , 2870 , 760 ,
265+ 2860 , 930 , 2800 , 1120 , 2620 , 1540 , 2500 , 1930 , 2360 , 2510 , 2300 , 2810 , 2270 , 3100 , 2250 , 3580 , 2290 ,
266+ 3790 , 2340 , 3850 , 2420 , 3890 , 2500 , 3880 , 2560 , 3840 , 2650 , 3670 , 2760 , 3250 , 2830 , 2950 , 2870 , 2640 ,
267+ 2940 , 2030 , 3110 , 1270 , 3100 , 1020 , 3060 , 740 , 3060 , 510 , 3100 , 430 , 3190 , 380 , 3320 , 380 , 3390 , 430 ,
268+ 3430 , 510 , 3440 , 610 , 3440 , 840 , 3460 , 930 , 3520 , 990 , 3630 , 1020 , 3750 , 980 , 3830 , 890 , 3870 , 770 , 3920 ,
269+ 460 , 3950 , 320 , 4000 , 210 , 4110 , 160 , 4270 , 170 , 4340 , 220 , 4370 , 300 , 4330 , 540 , 4230 , 810 , 4170 , 1070 ,
270+ 4130 , 1550 , 4160 , 1750 , 4210 , 1820 , 4280 , 1860 , 4360 , 1860 , 4420 , 1820 , 4510 , 1680 , 4570 , 1470 , 4610 ,
271+ 1230 , 4650 , 980 , 4710 , 780 , 4790 , 650 , 4850 , 630 , 4930 , 635 , 5040 , 700 , 5090 , 810 , 5090 , 950 , 5060 , 1110 ,
272+ 4950 , 1460 , 4810 , 1770 , 4690 , 1920 , 4510 , 2050 , 4380 , 2170 , 4360 , 2240 , 4380 , 2300 , 4430 , 2350 , 4500 ,
273+ 2370 , 4670 , 2320 , 5010 , 2110 , 5150 , 1950 , 5270 , 1730 , 5390 , 1570 , 5450 , 1550 , 5520 , 1560 , 5570 , 1610 ,
274+ 5590 , 1680 , 5550 , 1800 , 5310 , 2110 , 5050 , 2440 , 5000 , 2590 , 5010 , 2660 , 5050 , 2720 , 5120 , 2740 , 5200 ,
275+ 2710 , 5380 , 2570 , 5560 , 2420 , 5630 , 2410 ,
276+ // hole 1
277+ 28 , 0 , // inner path length, discarded 0 value
278+ 3190 , 2270 , 3150 , 2840 , 3010 , 3410 , 2860 , 3850 , 2730 , 4200 , 2670 , 4500 , 2710 , 4580 , 2810 , 4640 , 2950 ,
279+ 4650 , 3060 , 4630 , 3200 , 4520 , 3300 , 4380 , 3360 , 4200 , 3400 , 4010 , 3450 , 3600 , 3530 , 3210 , 3770 , 2730 ,
280+ 3870 , 2480 , 3930 , 2230 , 3960 , 2000 , 3960 , 1750 , 3910 , 1540 , 3850 , 1460 , 3770 , 1410 , 3640 , 1410 , 3530 ,
281+ 1490 , 3340 , 1740 , 3230 , 1990 ,
282+ // hole 2 // inner path length, discarded 0 value
283+ 20 , 0 ,
284+ 4240 , 2700 , 4050 , 2800 , 3900 , 2970 , 3810 , 3160 , 3710 , 3580 , 3550 , 4080 , 3530 , 4310 , 3560 , 4390 , 3640 ,
285+ 4430 , 3870 , 4390 , 4040 , 4290 , 4150 , 4130 , 4230 , 3940 , 4320 , 3490 , 4380 , 3260 , 4460 , 3050 , 4540 , 2880 ,
286+ 4550 , 2770 , 4510 , 2700 , 4440 , 2670 } ;
287+
288+ IntPtr sol = Triangulate64 ( subjects , true ) ;
289+ long [ ] ? cSol64 = GetArrayFromIntPtr < long > ( sol ) ;
290+
291+ DrawSVG_MultiColor ( @"..\..\..\coral3_t.svg" , cSol64 ) ;
292+ DisposeArray64 ( ref sol ) ; // disposes DLL assigned memory
293+ }
294+
295+ /// Main Entry ////////////////////////////////////////////////////////////
296+ public static void Main ( )
297+ {
298+ //string? ver = Marshal.PtrToStringAnsi(Version());
299+ //Console.WriteLine(ver + "\n");
300+
301+ #if USINGZ
302+ SetZCallback64 ( MyCallBack64 ) ;
303+ SetZCallbackD ( MyCallBackD ) ;
304+ #endif
244305
245- /////////////////////////////////////////////////////////////////////////
246- /////////////////////////////////////////////////////////////////////////
306+ TestBooleanOp64 ( ) ;
307+ TestBooleanOpD ( ) ;
308+ TestBooleanOp_Polytree64 ( ) ;
309+ TestBooleanOp_PolytreeD ( ) ;
310+ TestTriangulate ( ) ;
247311
248312 //Console.WriteLine("\nPress any key to exit ... ");
249313 //Console.ReadKey();
0 commit comments