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 ;
1813import clipper2 .core .Rect64 ;
1914import clipper2 .core .RectD ;
2015import clipper2 .engine .Clipper64 ;
16+ import clipper2 .engine .ClipperBase ;
2117import clipper2 .engine .ClipperD ;
2218import clipper2 .engine .PointInPolygonResult ;
2319import clipper2 .engine .PolyPath64 ;
24- import clipper2 .engine .PolyPathBase ;
2520import clipper2 .engine .PolyPathD ;
21+ import clipper2 .engine .PolyPathNode ;
2622import clipper2 .engine .PolyTree64 ;
2723import clipper2 .engine .PolyTreeD ;
2824import clipper2 .offset .ClipperOffset ;
2925import clipper2 .offset .EndType ;
3026import clipper2 .offset .JoinType ;
27+ import clipper2 .rectclip .RectClip ;
28+ import clipper2 .rectclip .RectClipLines ;
29+
30+ import java .util .ArrayList ;
31+ import java .util .Arrays ;
32+ import java .util .Collections ;
33+ import java .util .List ;
3134
3235public final class Clipper {
3336
3437 public static final Rect64 MaxInvalidRect64 = new Rect64 (Long .MAX_VALUE , Long .MAX_VALUE , Long .MIN_VALUE , Long .MIN_VALUE );
3538
3639 public static final RectD MaxInvalidRectD = new RectD (Double .MAX_VALUE , Double .MAX_VALUE , -Double .MAX_VALUE , -Double .MAX_VALUE );
40+ public static final String PRECISION_RANGE_ERROR = "Error: Precision is out of range." ;
3741
3842 public static Paths64 Intersect (Paths64 subject , Paths64 clip , FillRule fillRule ) {
3943 return BooleanOp (ClipType .Intersection , subject , clip , fillRule );
@@ -43,8 +47,8 @@ public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule) {
4347 return Intersect (subject , clip , fillRule , 2 );
4448 }
4549
46- public static PathsD Intersect (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
47- return BooleanOp (ClipType .Intersection , subject , clip , fillRule , roundingDecimalPrecision );
50+ public static PathsD Intersect (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
51+ return BooleanOp (ClipType .Intersection , subject , clip , fillRule , precision );
4852 }
4953
5054 public static Paths64 Union (Paths64 subject , FillRule fillRule ) {
@@ -63,8 +67,8 @@ public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule) {
6367 return Union (subject , clip , fillRule , 2 );
6468 }
6569
66- public static PathsD Union (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
67- return BooleanOp (ClipType .Union , subject , clip , fillRule , roundingDecimalPrecision );
70+ public static PathsD Union (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
71+ return BooleanOp (ClipType .Union , subject , clip , fillRule , precision );
6872 }
6973
7074 public static Paths64 Difference (Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -75,8 +79,8 @@ public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule)
7579 return Difference (subject , clip , fillRule , 2 );
7680 }
7781
78- public static PathsD Difference (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
79- return BooleanOp (ClipType .Difference , subject , clip , fillRule , roundingDecimalPrecision );
82+ public static PathsD Difference (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
83+ return BooleanOp (ClipType .Difference , subject , clip , fillRule , precision );
8084 }
8185
8286 public static Paths64 Xor (Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -87,8 +91,8 @@ public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule) {
8791 return Xor (subject , clip , fillRule , 2 );
8892 }
8993
90- public static PathsD Xor (PathsD subject , PathsD clip , FillRule fillRule , int roundingDecimalPrecision ) {
91- return BooleanOp (ClipType .Xor , subject , clip , fillRule , roundingDecimalPrecision );
94+ public static PathsD Xor (PathsD subject , PathsD clip , FillRule fillRule , int precision ) {
95+ return BooleanOp (ClipType .Xor , subject , clip , fillRule , precision );
9296 }
9397
9498 public static Paths64 BooleanOp (ClipType clipType , Paths64 subject , Paths64 clip , FillRule fillRule ) {
@@ -109,10 +113,9 @@ public static PathsD BooleanOp(ClipType clipType, PathsD subject, PathsD clip, F
109113 return BooleanOp (clipType , subject , clip , fillRule , 2 );
110114 }
111115
112- public static PathsD BooleanOp (ClipType clipType , PathsD subject , @ Nullable PathsD clip , FillRule fillRule ,
113- int roundingDecimalPrecision ) {
116+ public static PathsD BooleanOp (ClipType clipType , PathsD subject , @ Nullable PathsD clip , FillRule fillRule , int precision ) {
114117 PathsD solution = new PathsD ();
115- ClipperD c = new ClipperD (roundingDecimalPrecision );
118+ ClipperD c = new ClipperD (precision );
116119 c .AddSubjectsD (subject );
117120 if (clip != null ) {
118121 c .AddClipsD (clip );
@@ -184,7 +187,7 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
184187
185188 public static PathsD InflatePaths (PathsD paths , double delta , JoinType joinType , EndType endType , double miterLimit , int precision ) {
186189 if (precision < -8 || precision > 8 ) {
187- throw new IllegalArgumentException ("Error: Precision is out of range." );
190+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
188191 }
189192 double scale = Math .pow (10 , precision );
190193 Paths64 tmp = ScalePaths64 (paths , scale );
@@ -194,6 +197,157 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
194197 return ScalePathsD (tmp , 1 / scale );
195198 }
196199
200+ public static Path64 RectClip (Rect64 rect , Path64 path )
201+ {
202+ if (rect .IsEmpty () || path .isEmpty ()) return new Path64 ();
203+ RectClip rc = new RectClip (rect );
204+ return rc .ExecuteInternal (path );
205+ }
206+
207+ public static Paths64 RectClip (Rect64 rect , Paths64 paths )
208+ {
209+ if (rect .IsEmpty () || paths .isEmpty ()) return new Paths64 ();
210+
211+ Paths64 result = new Paths64 (paths .size ());
212+ RectClip rc = new RectClip (rect );
213+ for (Path64 path : paths ) {
214+ Rect64 pathRec = ClipperBase .GetBounds (path );
215+ if (!rect .Intersects (pathRec ))
216+ continue ;
217+ else if (rect .Contains (pathRec ))
218+ result .add (path );
219+ else
220+ {
221+ Path64 p = rc .ExecuteInternal (path );
222+ if (p .size () > 0 ) result .add (p );
223+ }
224+ }
225+ return result ;
226+ }
227+
228+ public static PathD RectClip (RectD rect , PathD path ){
229+ return RectClip (rect , path , 2 );
230+ }
231+
232+ public static PathD RectClip (RectD rect , PathD path , int precision )
233+ {
234+ if (precision < -8 || precision > 8 )
235+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
236+ if (rect .IsEmpty () || path .size () == 0 ) return new PathD ();
237+ double scale = Math .pow (10 , precision );
238+ Rect64 r = ScaleRect (rect , scale );
239+ Path64 tmpPath = ScalePath64 (path , scale );
240+ RectClip rc = new RectClip (r );
241+ tmpPath = rc .ExecuteInternal (tmpPath );
242+ return ScalePathD (tmpPath , 1 / scale );
243+ }
244+
245+ public static PathsD RectClip (RectD rect , PathsD paths )
246+ {
247+ return RectClip (rect , paths , 2 );
248+ }
249+
250+ public static PathsD RectClip (RectD rect , PathsD paths , int precision )
251+ {
252+ if (precision < -8 || precision > 8 )
253+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
254+ if (rect .IsEmpty () || paths .size () == 0 ) return new PathsD ();
255+ double scale = Math .pow (10 , precision );
256+ Rect64 r = ScaleRect (rect , scale );
257+ RectClip rc = new RectClip (r );
258+ PathsD result = new PathsD (paths .size ());
259+ for (PathD p : paths ) {
260+ RectD pathRec = ClipperBase .GetBounds (p );
261+ if (!rect .Intersects (pathRec ))
262+ continue ;
263+ else if (rect .Contains (pathRec ))
264+ result .add (p );
265+ else
266+ {
267+ Path64 p64 = ScalePath64 (p , scale );
268+ p64 = rc .ExecuteInternal (p64 );
269+ if (p64 .size () > 0 )
270+ result .add (ScalePathD (p64 , 1 / scale ));
271+ }
272+ }
273+ return result ;
274+ }
275+ public static Paths64 RectClipLines (Rect64 rect , Path64 path )
276+ {
277+ if (rect .IsEmpty () || path .size () == 0 ) return new Paths64 ();
278+ RectClipLines rco = new RectClipLines (rect );
279+ return rco .NewExecuteInternal (path );
280+ }
281+
282+ public static Paths64 RectClipLines (Rect64 rect , Paths64 paths )
283+ {
284+ Paths64 result = new Paths64 (paths .size ());
285+ if (rect .IsEmpty () || paths .size () == 0 ) return result ;
286+ RectClipLines rco = new RectClipLines (rect );
287+ for (Path64 path : paths ) {
288+ Rect64 pathRec = ClipperBase .GetBounds (path );
289+ if (!rect .Intersects (pathRec ))
290+ continue ;
291+ else if (rect .Contains (pathRec ))
292+ result .add (path );
293+ else
294+ {
295+ Paths64 pp = rco .NewExecuteInternal (path );
296+ if (pp .size () > 0 ) result .addAll (pp );
297+ }
298+ }
299+ return result ;
300+ }
301+
302+ public static PathsD RectClipLines (RectD rect , PathD path )
303+ {
304+ return RectClipLines (rect , path , 2 );
305+ }
306+
307+ public static PathsD RectClipLines (RectD rect , PathD path , int precision )
308+ {
309+ if (precision < -8 || precision > 8 )
310+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
311+ if (rect .IsEmpty () || path .size () == 0 ) return new PathsD ();
312+ double scale = Math .pow (10 , precision );
313+ Rect64 r = ScaleRect (rect , scale );
314+ Path64 tmpPath = ScalePath64 (path , scale );
315+ RectClipLines rco = new RectClipLines (r );
316+ Paths64 tmpPaths = rco .NewExecuteInternal (tmpPath );
317+ return ScalePathsD (tmpPaths , 1 / scale );
318+ }
319+ public static PathsD RectClipLines (RectD rect , PathsD paths )
320+ {
321+ return RectClipLines (rect , paths , 2 );
322+ }
323+
324+ public static PathsD RectClipLines (RectD rect , PathsD paths , int precision )
325+ {
326+ if (precision < -8 || precision > 8 )
327+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
328+ PathsD result = new PathsD (paths .size ());
329+ if (rect .IsEmpty () || paths .size () == 0 ) return result ;
330+ double scale = Math .pow (10 , precision );
331+ Rect64 r = ScaleRect (rect , scale );
332+ RectClipLines rco = new RectClipLines (r );
333+ for (PathD p : paths ) {
334+ RectD pathRec = ClipperBase .GetBounds (p );
335+ if (!rect .Intersects (pathRec ))
336+ continue ;
337+ else if (rect .Contains (pathRec ))
338+ result .add (p );
339+ else
340+ {
341+ Path64 p64 = ScalePath64 (p , scale );
342+ Paths64 pp64 = rco .NewExecuteInternal (p64 );
343+ if (pp64 .size () == 0 ) continue ;
344+ PathsD ppd = ScalePathsD (pp64 , 1 / scale );
345+ result .addAll (ppd );
346+ }
347+ }
348+ return result ;
349+ }
350+
197351 public static Paths64 MinkowskiSum (Path64 pattern , Path64 path , boolean isClosed ) {
198352 return Minkowski .Sum (pattern , path , isClosed );
199353 }
@@ -353,6 +507,17 @@ public static PointD ScalePointD(Point64 pt, double scale) {
353507 return result ;
354508 }
355509
510+ public static Rect64 ScaleRect (RectD rec , double scale )
511+ {
512+ Rect64 result = new Rect64 (
513+ (long ) (rec .left * scale ),
514+ (long ) (rec .top * scale ),
515+ (long ) (rec .right * scale ),
516+ (long ) (rec .bottom * scale )
517+ );
518+ return result ;
519+ }
520+
356521 public static Path64 ScalePath (Path64 path , double scale ) {
357522 if (InternalClipper .IsAlmostZero (scale - 1 )) {
358523 return path ;
@@ -528,6 +693,18 @@ public static PathsD ReversePaths(PathsD paths) {
528693 return result ;
529694 }
530695
696+ public static Rect64 GetBounds (Path64 path )
697+ {
698+ Rect64 result = MaxInvalidRect64 ;
699+ for (Point64 pt : path ) {
700+ if (pt .x < result .left ) result .left = pt .x ;
701+ if (pt .x > result .right ) result .right = pt .x ;
702+ if (pt .y < result .top ) result .top = pt .y ;
703+ if (pt .y > result .bottom ) result .bottom = pt .y ;
704+ }
705+ return result .IsEmpty () ? new Rect64 () : result ;
706+ }
707+
531708 public static Rect64 GetBounds (Paths64 paths ) {
532709 Rect64 result = MaxInvalidRect64 ;
533710 for (Path64 path : paths ) {
@@ -669,7 +846,7 @@ public static void AddPolyNodeToPathsD(PolyPathD polyPath, PathsD paths) {
669846
670847 public static PathsD PolyTreeToPathsD (PolyTreeD polyTree ) {
671848 PathsD result = new PathsD ();
672- for (PolyPathBase polyPathBase : polyTree ) {
849+ for (PolyPathNode polyPathBase : polyTree ) {
673850 PolyPathD p = (PolyPathD ) polyPathBase ;
674851 AddPolyNodeToPathsD (p , result );
675852 }
@@ -939,7 +1116,7 @@ public static PathD TrimCollinear(PathD path, int precision) {
9391116 */
9401117 public static PathD TrimCollinear (PathD path , int precision , boolean isOpen ) {
9411118 if (precision < -8 || precision > 8 ) {
942- throw new IllegalArgumentException ("Error: Precision is out of range." );
1119+ throw new IllegalArgumentException (PRECISION_RANGE_ERROR );
9431120 }
9441121 double scale = Math .pow (10 , precision );
9451122 Path64 p = ScalePath64 (path , scale );
0 commit comments