11package clipper2 ;
22
3- import java .util .ArrayList ;
4- import java .util .Arrays ;
5- import java .util .Collections ;
6- import java .util .List ;
7-
83import clipper2 .core .ClipType ;
94import clipper2 .core .FillRule ;
105import clipper2 .core .InternalClipper ;
2116import clipper2 .engine .ClipperD ;
2217import clipper2 .engine .PointInPolygonResult ;
2318import clipper2 .engine .PolyPath64 ;
24- import clipper2 .engine .PolyPathBase ;
2519import clipper2 .engine .PolyPathD ;
20+ import clipper2 .engine .PolyPathNode ;
2621import clipper2 .engine .PolyTree64 ;
2722import clipper2 .engine .PolyTreeD ;
2823import clipper2 .offset .ClipperOffset ;
2924import clipper2 .offset .EndType ;
3025import clipper2 .offset .JoinType ;
26+ import clipper2 .rectclip .RectClip ;
27+ import clipper2 .rectclip .RectClipLines ;
28+
29+ import java .util .ArrayList ;
30+ import java .util .Arrays ;
31+ import java .util .Collections ;
32+ import java .util .List ;
3133
3234public final class Clipper {
3335
3436 public static final Rect64 MaxInvalidRect64 = new Rect64 (Long .MAX_VALUE , Long .MAX_VALUE , Long .MIN_VALUE , Long .MIN_VALUE );
3537
3638 public static final RectD MaxInvalidRectD = new RectD (Double .MAX_VALUE , Double .MAX_VALUE , -Double .MAX_VALUE , -Double .MAX_VALUE );
39+ private static final String PRECISION_RANGE_ERROR = "Error: Precision is out of range." ;
3740
3841 public static Paths64 Intersect (Paths64 subject , Paths64 clip , FillRule fillRule ) {
3942 return BooleanOp (ClipType .Intersection , subject , clip , fillRule );
@@ -43,8 +46,8 @@ public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule) {
4346 return Intersect (subject , clip , fillRule , 2 );
4447 }
4548
46- public static PathsD Intersect (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
47- return BooleanOp (ClipType .Intersection , subject , clip , fillRule , roundingDecimalPrecision );
49+ public static PathsD Intersect (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
50+ return BooleanOp (ClipType .Intersection , subject , clip , fillRule , precision );
4851 }
4952
5053 public static Paths64 Union (Paths64 subject , FillRule fillRule ) {
@@ -63,8 +66,8 @@ public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule) {
6366 return Union (subject , clip , fillRule , 2 );
6467 }
6568
66- public static PathsD Union (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
67- return BooleanOp (ClipType .Union , subject , clip , fillRule , roundingDecimalPrecision );
69+ public static PathsD Union (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
70+ return BooleanOp (ClipType .Union , subject , clip , fillRule , precision );
6871 }
6972
7073 public static Paths64 Difference (Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -75,8 +78,8 @@ public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule)
7578 return Difference (subject , clip , fillRule , 2 );
7679 }
7780
78- public static PathsD Difference (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
79- return BooleanOp (ClipType .Difference , subject , clip , fillRule , roundingDecimalPrecision );
81+ public static PathsD Difference (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
82+ return BooleanOp (ClipType .Difference , subject , clip , fillRule , precision );
8083 }
8184
8285 public static Paths64 Xor (Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -87,8 +90,8 @@ public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule) {
8790 return Xor (subject , clip , fillRule , 2 );
8891 }
8992
90- public static PathsD Xor (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
91- return BooleanOp (ClipType .Xor , subject , clip , fillRule , roundingDecimalPrecision );
93+ public static PathsD Xor (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
94+ return BooleanOp (ClipType .Xor , subject , clip , fillRule , precision );
9295 }
9396
9497 public static Paths64 BooleanOp (ClipType clipType , Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -109,10 +112,9 @@ public static PathsD BooleanOp(ClipType clipType, PathsD subject, PathsD clip, F
109112 return BooleanOp (clipType , subject , clip , fillRule , 2 );
110113 }
111114
112- public static PathsD BooleanOp (ClipType clipType , PathsD subject , @ Nullable PathsD clip , FillRule fillRule ,
113- int roundingDecimalPrecision ) {
115+ public static PathsD BooleanOp (ClipType clipType , PathsD subject , @ Nullable PathsD clip , FillRule fillRule , int precision ) {
114116 PathsD solution = new PathsD ();
115- ClipperD c = new ClipperD (roundingDecimalPrecision );
117+ ClipperD c = new ClipperD (precision );
116118 c .AddSubjectsD (subject );
117119 if (clip != null ) {
118120 c .AddClipsD (clip );
@@ -184,7 +186,7 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
184186
185187 public static PathsD InflatePaths (PathsD paths , double delta , JoinType joinType , EndType endType , double miterLimit , int precision ) {
186188 if (precision < -8 || precision > 8 ) {
187- throw new IllegalArgumentException ("Error: Precision is out of range." );
189+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
188190 }
189191 double scale = Math .pow (10 , precision );
190192 Paths64 tmp = ScalePaths64 (paths , scale );
@@ -194,6 +196,157 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
194196 return ScalePathsD (tmp , 1 / scale );
195197 }
196198
199+ public static Path64 RectClip (Rect64 rect , Path64 path )
200+ {
201+ if (rect .IsEmpty () || path .isEmpty ()) return new Path64 ();
202+ RectClip rc = new RectClip (rect );
203+ return rc .ExecuteInternal (path );
204+ }
205+
206+ public static Paths64 RectClip (Rect64 rect , Paths64 paths )
207+ {
208+ if (rect .IsEmpty () || paths .isEmpty ()) return new Paths64 ();
209+
210+ Paths64 result = new Paths64 (paths .size ());
211+ RectClip rc = new RectClip (rect );
212+ for (Path64 path : paths ) {
213+ Rect64 pathRec = GetBounds (path );
214+ if (!rect .Intersects (pathRec ))
215+ continue ;
216+ else if (rect .Contains (pathRec ))
217+ result .add (path );
218+ else
219+ {
220+ Path64 p = rc .ExecuteInternal (path );
221+ if (p .size () > 0 ) result .add (p );
222+ }
223+ }
224+ return result ;
225+ }
226+
227+ public static PathD RectClip (RectD rect , PathD path ){
228+ return RectClip (rect , path , 2 );
229+ }
230+
231+ public static PathD RectClip (RectD rect , PathD path , int precision )
232+ {
233+ if (precision < -8 || precision > 8 )
234+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
235+ if (rect .IsEmpty () || path .size () == 0 ) return new PathD ();
236+ double scale = Math .pow (10 , precision );
237+ Rect64 r = ScaleRect (rect , scale );
238+ Path64 tmpPath = ScalePath64 (path , scale );
239+ RectClip rc = new RectClip (r );
240+ tmpPath = rc .ExecuteInternal (tmpPath );
241+ return ScalePathD (tmpPath , 1 / scale );
242+ }
243+
244+ public static PathsD RectClip (RectD rect , PathsD paths )
245+ {
246+ return RectClip (rect , paths , 2 );
247+ }
248+
249+ public static PathsD RectClip (RectD rect , PathsD paths , int precision )
250+ {
251+ if (precision < -8 || precision > 8 )
252+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
253+ if (rect .IsEmpty () || paths .size () == 0 ) return new PathsD ();
254+ double scale = Math .pow (10 , precision );
255+ Rect64 r = ScaleRect (rect , scale );
256+ RectClip rc = new RectClip (r );
257+ PathsD result = new PathsD (paths .size ());
258+ for (PathD p : paths ) {
259+ RectD pathRec = GetBounds (p );
260+ if (!rect .Intersects (pathRec ))
261+ continue ;
262+ else if (rect .Contains (pathRec ))
263+ result .add (p );
264+ else
265+ {
266+ Path64 p64 = ScalePath64 (p , scale );
267+ p64 = rc .ExecuteInternal (p64 );
268+ if (p64 .size () > 0 )
269+ result .add (ScalePathD (p64 , 1 / scale ));
270+ }
271+ }
272+ return result ;
273+ }
274+ public static Paths64 RectClipLines (Rect64 rect , Path64 path )
275+ {
276+ if (rect .IsEmpty () || path .size () == 0 ) return new Paths64 ();
277+ RectClipLines rco = new RectClipLines (rect );
278+ return rco .NewExecuteInternal (path );
279+ }
280+
281+ public static Paths64 RectClipLines (Rect64 rect , Paths64 paths )
282+ {
283+ Paths64 result = new Paths64 (paths .size ());
284+ if (rect .IsEmpty () || paths .size () == 0 ) return result ;
285+ RectClipLines rco = new RectClipLines (rect );
286+ for (Path64 path : paths ) {
287+ Rect64 pathRec = GetBounds (path );
288+ if (!rect .Intersects (pathRec ))
289+ continue ;
290+ else if (rect .Contains (pathRec ))
291+ result .add (path );
292+ else
293+ {
294+ Paths64 pp = rco .NewExecuteInternal (path );
295+ if (pp .size () > 0 ) result .addAll (pp );
296+ }
297+ }
298+ return result ;
299+ }
300+
301+ public static PathsD RectClipLines (RectD rect , PathD path )
302+ {
303+ return RectClipLines (rect , path , 2 );
304+ }
305+
306+ public static PathsD RectClipLines (RectD rect , PathD path , int precision )
307+ {
308+ if (precision < -8 || precision > 8 )
309+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
310+ if (rect .IsEmpty () || path .size () == 0 ) return new PathsD ();
311+ double scale = Math .pow (10 , precision );
312+ Rect64 r = ScaleRect (rect , scale );
313+ Path64 tmpPath = ScalePath64 (path , scale );
314+ RectClipLines rco = new RectClipLines (r );
315+ Paths64 tmpPaths = rco .NewExecuteInternal (tmpPath );
316+ return ScalePathsD (tmpPaths , 1 / scale );
317+ }
318+ public static PathsD RectClipLines (RectD rect , PathsD paths )
319+ {
320+ return RectClipLines (rect , paths , 2 );
321+ }
322+
323+ public static PathsD RectClipLines (RectD rect , PathsD paths , int precision )
324+ {
325+ if (precision < -8 || precision > 8 )
326+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
327+ PathsD result = new PathsD (paths .size ());
328+ if (rect .IsEmpty () || paths .size () == 0 ) return result ;
329+ double scale = Math .pow (10 , precision );
330+ Rect64 r = ScaleRect (rect , scale );
331+ RectClipLines rco = new RectClipLines (r );
332+ for (PathD p : paths ) {
333+ RectD pathRec = GetBounds (p );
334+ if (!rect .Intersects (pathRec ))
335+ continue ;
336+ else if (rect .Contains (pathRec ))
337+ result .add (p );
338+ else
339+ {
340+ Path64 p64 = ScalePath64 (p , scale );
341+ Paths64 pp64 = rco .NewExecuteInternal (p64 );
342+ if (pp64 .size () == 0 ) continue ;
343+ PathsD ppd = ScalePathsD (pp64 , 1 / scale );
344+ result .addAll (ppd );
345+ }
346+ }
347+ return result ;
348+ }
349+
197350 public static Paths64 MinkowskiSum (Path64 pattern , Path64 path , boolean isClosed ) {
198351 return Minkowski .Sum (pattern , path , isClosed );
199352 }
@@ -353,6 +506,17 @@ public static PointD ScalePointD(Point64 pt, double scale) {
353506 return result ;
354507 }
355508
509+ public static Rect64 ScaleRect (RectD rec , double scale )
510+ {
511+ Rect64 result = new Rect64 (
512+ (long ) (rec .left * scale ),
513+ (long ) (rec .top * scale ),
514+ (long ) (rec .right * scale ),
515+ (long ) (rec .bottom * scale )
516+ );
517+ return result ;
518+ }
519+
356520 public static Path64 ScalePath (Path64 path , double scale ) {
357521 if (InternalClipper .IsAlmostZero (scale - 1 )) {
358522 return path ;
@@ -528,6 +692,30 @@ public static PathsD ReversePaths(PathsD paths) {
528692 return result ;
529693 }
530694
695+ public static Rect64 GetBounds (Path64 path )
696+ {
697+ Rect64 result = MaxInvalidRect64 ;
698+ for (Point64 pt : path ) {
699+ if (pt .x < result .left ) result .left = pt .x ;
700+ if (pt .x > result .right ) result .right = pt .x ;
701+ if (pt .y < result .top ) result .top = pt .y ;
702+ if (pt .y > result .bottom ) result .bottom = pt .y ;
703+ }
704+ return result .IsEmpty () ? new Rect64 () : result ;
705+ }
706+
707+ public static RectD GetBounds (PathD path )
708+ {
709+ RectD result = MaxInvalidRectD ;
710+ for (PointD pt : path ) {
711+ if (pt .x < result .left ) result .left = pt .x ;
712+ if (pt .x > result .right ) result .right = pt .x ;
713+ if (pt .y < result .top ) result .top = pt .y ;
714+ if (pt .y > result .bottom ) result .bottom = pt .y ;
715+ }
716+ return result .IsEmpty () ? new RectD () : result ;
717+ }
718+
531719 public static Rect64 GetBounds (Paths64 paths ) {
532720 Rect64 result = MaxInvalidRect64 ;
533721 for (Path64 path : paths ) {
@@ -669,7 +857,7 @@ public static void AddPolyNodeToPathsD(PolyPathD polyPath, PathsD paths) {
669857
670858 public static PathsD PolyTreeToPathsD (PolyTreeD polyTree ) {
671859 PathsD result = new PathsD ();
672- for (PolyPathBase polyPathBase : polyTree ) {
860+ for (PolyPathNode polyPathBase : polyTree ) {
673861 PolyPathD p = (PolyPathD ) polyPathBase ;
674862 AddPolyNodeToPathsD (p , result );
675863 }
@@ -939,7 +1127,7 @@ public static PathD TrimCollinear(PathD path, int precision) {
9391127 */
9401128 public static PathD TrimCollinear (PathD path , int precision , boolean isOpen ) {
9411129 if (precision < -8 || precision > 8 ) {
942- throw new IllegalArgumentException ("Error: Precision is out of range." );
1130+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
9431131 }
9441132 double scale = Math .pow (10 , precision );
9451133 Path64 p = ScalePath64 (path , scale );
0 commit comments