Skip to content

Commit

Permalink
Merge pull request #6 from elara-leitstellentechnik/master
Browse files Browse the repository at this point in the history
  • Loading branch information
micycle1 authored Mar 28, 2023
2 parents aa30e1e + 84d9011 commit f943e95
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 73 deletions.
64 changes: 33 additions & 31 deletions src/main/java/clipper2/Clipper.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package clipper2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import clipper2.core.ClipType;
import clipper2.core.FillRule;
import clipper2.core.InternalClipper;
Expand All @@ -31,6 +26,11 @@
import clipper2.rectclip.RectClip;
import clipper2.rectclip.RectClipLines;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public final class Clipper {

public static final Rect64 InvalidRect64 = new Rect64(false);
Expand Down Expand Up @@ -203,7 +203,9 @@ public static Paths64 InflatePaths(Paths64 paths, double delta, JoinType joinTyp
public static Paths64 InflatePaths(Paths64 paths, double delta, JoinType joinType, EndType endType, double miterLimit) {
ClipperOffset co = new ClipperOffset(miterLimit);
co.AddPaths(paths, joinType, endType);
return co.Execute(delta);
Paths64 solution = new Paths64();
co.Execute(delta, solution);
return solution;
}

public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType, EndType endType, double miterLimit) {
Expand All @@ -220,40 +222,40 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
Paths64 tmp = ScalePaths64(paths, scale);
ClipperOffset co = new ClipperOffset(miterLimit);
co.AddPaths(tmp, joinType, endType);
tmp = co.Execute(delta * scale);
co.Execute(delta * scale, tmp); // reuse 'tmp' to receive (scaled) solution
return ScalePathsD(tmp, 1 / scale);
}

public static Paths64 RectClip(Rect64 rect, Paths64 paths) {
return RectClip(rect, paths, false);
public static Paths64 ExecuteRectClip(Rect64 rect, Paths64 paths) {
return ExecuteRectClip(rect, paths, false);
}

public static Paths64 RectClip(Rect64 rect, Paths64 paths, boolean convexOnly) {
public static Paths64 ExecuteRectClip(Rect64 rect, Paths64 paths, boolean convexOnly) {
if (rect.IsEmpty() || paths.size() == 0) {
return new Paths64();
}
RectClip rc = new RectClip(rect);
return rc.Execute(paths, convexOnly);
}

public static Paths64 RectClip(Rect64 rect, Path64 path) {
return RectClip(rect, path, false);
public static Paths64 ExecuteRectClip(Rect64 rect, Path64 path) {
return ExecuteRectClip(rect, path, false);
}

public static Paths64 RectClip(Rect64 rect, Path64 path, boolean convexOnly) {
public static Paths64 ExecuteRectClip(Rect64 rect, Path64 path, boolean convexOnly) {
if (rect.IsEmpty() || path.size() == 0) {
return new Paths64();
}
Paths64 tmp = new Paths64();
tmp.add(path);
return RectClip(rect, tmp, convexOnly);
return ExecuteRectClip(rect, tmp, convexOnly);
}

public static PathsD RectClip(RectD rect, PathsD paths) {
return RectClip(rect, paths, 2, false);
public static PathsD ExecuteRectClip(RectD rect, PathsD paths) {
return ExecuteRectClip(rect, paths, 2, false);
}

public static PathsD RectClip(RectD rect, PathsD paths, int precision, boolean convexOnly) {
public static PathsD ExecuteRectClip(RectD rect, PathsD paths, int precision, boolean convexOnly) {
InternalClipper.CheckPrecision(precision);
if (rect.IsEmpty() || paths.size() == 0) {
return new PathsD();
Expand All @@ -266,41 +268,41 @@ public static PathsD RectClip(RectD rect, PathsD paths, int precision, boolean c
return ScalePathsD(tmpPath, 1 / scale);
}

public static PathsD RectClip(RectD rect, PathD path) {
return RectClip(rect, path, 2, false);
public static PathsD ExecuteRectClip(RectD rect, PathD path) {
return ExecuteRectClip(rect, path, 2, false);
}

public static PathsD RectClip(RectD rect, PathD path, int precision, boolean convexOnly) {
public static PathsD ExecuteRectClip(RectD rect, PathD path, int precision, boolean convexOnly) {
if (rect.IsEmpty() || path.size() == 0) {
return new PathsD();
}
PathsD tmp = new PathsD();
tmp.add(path);
return RectClip(rect, tmp, precision, convexOnly);
return ExecuteRectClip(rect, tmp, precision, convexOnly);
}

public static Paths64 RectClipLines(Rect64 rect, Paths64 paths) {
public static Paths64 ExecuteRectClipLines(Rect64 rect, Paths64 paths) {
if (rect.IsEmpty() || paths.size() == 0) {
return new Paths64();
}
RectClipLines rc = new RectClipLines(rect);
return rc.Execute(paths);
}

public static Paths64 RectClipLines(Rect64 rect, Path64 path) {
public static Paths64 ExecuteRectClipLines(Rect64 rect, Path64 path) {
if (rect.IsEmpty() || path.size() == 0) {
return new Paths64();
}
Paths64 tmp = new Paths64();
tmp.add(path);
return RectClipLines(rect, tmp);
return ExecuteRectClipLines(rect, tmp);
}

public static PathsD RectClipLines(RectD rect, PathsD paths) {
return RectClipLines(rect, paths, 2);
public static PathsD ExecuteRectClipLines(RectD rect, PathsD paths) {
return ExecuteRectClipLines(rect, paths, 2);
}

public static PathsD RectClipLines(RectD rect, PathsD paths, int precision) {
public static PathsD ExecuteRectClipLines(RectD rect, PathsD paths, int precision) {
InternalClipper.CheckPrecision(precision);
if (rect.IsEmpty() || paths.size() == 0) {
return new PathsD();
Expand All @@ -313,17 +315,17 @@ public static PathsD RectClipLines(RectD rect, PathsD paths, int precision) {
return ScalePathsD(tmpPath, 1 / scale);
}

public static PathsD RectClipLines(RectD rect, PathD path) {
return RectClipLines(rect, path, 2);
public static PathsD ExecuteRectClipLines(RectD rect, PathD path) {
return ExecuteRectClipLines(rect, path, 2);
}

public static PathsD RectClipLines(RectD rect, PathD path, int precision) {
public static PathsD ExecuteRectClipLines(RectD rect, PathD path, int precision) {
if (rect.IsEmpty() || path.size() == 0) {
return new PathsD();
}
PathsD tmp = new PathsD();
tmp.add(path);
return RectClipLines(rect, tmp, precision);
return ExecuteRectClipLines(rect, tmp, precision);
}

public static Paths64 MinkowskiSum(Path64 pattern, Path64 path, boolean isClosed) {
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/clipper2/engine/ClipperBase.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package clipper2.engine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableSet;
import java.util.TreeSet;

import clipper2.Clipper;
import clipper2.Nullable;
import clipper2.core.ClipType;
Expand All @@ -21,6 +14,13 @@
import tangible.OutObject;
import tangible.RefObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableSet;
import java.util.TreeSet;

/**
* Subject and Clip paths are passed to a Clipper object via AddSubject,
* AddOpenSubject and AddClip methods. Clipping operations are then initiated by
Expand Down Expand Up @@ -1723,7 +1723,7 @@ private void AddNewIntersectNode(Active ae1, Active ae2, long topY) {
if (absDx1 < absDx2) {
ip.x = TopX(ae1, ip.y);
} else {
ip.x = TopX(ae2, topY);
ip.x = TopX(ae2, ip.y);
}
}
}
Expand Down
83 changes: 56 additions & 27 deletions src/main/java/clipper2/offset/ClipperOffset.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

import static clipper2.core.InternalClipper.DEFAULT_ARC_TOLERANCE;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import clipper2.Clipper;
import clipper2.core.ClipType;
import clipper2.core.FillRule;
Expand All @@ -17,9 +13,14 @@
import clipper2.core.PointD;
import clipper2.core.Rect64;
import clipper2.engine.Clipper64;
import clipper2.engine.PolyTree64;
import tangible.OutObject;
import tangible.RefObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Geometric offsetting refers to the process of creating parallel curves that
* are offset a specified distance from their primary curves.
Expand Down Expand Up @@ -48,6 +49,8 @@ public class ClipperOffset {
private double abs_group_delta;
private double mitLimSqr;
private double stepsPerRad;
private double stepSin;
private double stepCos;
private JoinType joinType;
private EndType endType;
private double arcTolerance;
Expand Down Expand Up @@ -162,10 +165,10 @@ public final void AddPaths(Paths64 paths, JoinType joinType, EndType endType) {
_groupList.add(new Group(paths, joinType, endType));
}

public final Paths64 Execute(double delta) {
private void ExecuteInternal(double delta) {
solution.clear();
if (_groupList.isEmpty()) {
return solution;
return;
}

if (Math.abs(delta) < 0.5) {
Expand All @@ -174,15 +177,19 @@ public final Paths64 Execute(double delta) {
solution.add(path);
}
}
return solution;
}

this.delta = delta;
this.mitLimSqr = (getMiterLimit() <= 1 ? 2.0 : 2.0 / Clipper.Sqr(getMiterLimit()));
} else {
this.delta = delta;
this.mitLimSqr = (getMiterLimit() <= 1 ? 2.0 : 2.0 / Clipper.Sqr(getMiterLimit()));

for (Group group : _groupList) {
DoGroupOffset(group);
for (Group group : _groupList) {
DoGroupOffset(group);
}
}
}

public final void Execute(double delta, Paths64 solution) {
solution.clear();
ExecuteInternal(delta);

// clean up self-intersections ...
Clipper64 c = new Clipper64();
Expand All @@ -194,7 +201,23 @@ public final Paths64 Execute(double delta) {
} else {
c.Execute(ClipType.Union, FillRule.Positive, solution);
}
return solution;
}

public void Execute(double delta, PolyTree64 polytree) {
polytree.Clear();
ExecuteInternal(delta);

// clean up self-intersections ...
Clipper64 c = new Clipper64();
c.setPreserveCollinear(getPreserveCollinear());
// the solution should retain the orientation of the input
c.setReverseSolution(getReverseSolution() != _groupList.get(0).pathsReversed);
c.AddSubject(solution);
if (_groupList.get(0).pathsReversed) {
c.Execute(ClipType.Union, FillRule.Negative, polytree);
} else {
c.Execute(ClipType.Union, FillRule.Positive, polytree);
}
}

public final double getArcTolerance() {
Expand Down Expand Up @@ -392,12 +415,13 @@ private void DoRound(Group group, Path64 path, int j, int k, double angle) {
group.outPath.add(new Point64(pt.x + offsetVec.x, pt.y + offsetVec.y));
if (angle > -Math.PI + 0.01) // avoid 180deg concave
{
int steps = Math.max(2, (int) Math.floor(stepsPerRad * Math.abs(angle)));
double stepSin = Math.sin(angle / steps);
double stepCos = Math.cos(angle / steps);
int steps = (int) Math.ceil(stepsPerRad * Math.abs(angle));
for (int i = 1; i < steps; i++) // ie 1 less than steps
{
offsetVec = new PointD(offsetVec.x * stepCos - stepSin * offsetVec.y, offsetVec.x * stepSin + offsetVec.y * stepCos);
offsetVec = new PointD(
offsetVec.x * stepCos - stepSin * offsetVec.y,
offsetVec.x * stepSin + offsetVec.y * stepCos
);
group.outPath.add(new Point64(pt.x + offsetVec.x, pt.y + offsetVec.y));
}
}
Expand Down Expand Up @@ -428,11 +452,12 @@ private void OffsetPoint(Group group, Path64 path, int j, RefObject<Integer> k)
sinA = -1.0;
}

if (AlmostZero(cosA - 1, 0.01)) // almost straight
if (cosA > 0.99) // almost straight - less than 8 degrees
{
group.outPath.add(GetPerpendic(path.get(j), normals.get(k.argValue)));
group.outPath.add(GetPerpendic(path.get(j), normals.get(j))); // (#418)
} else if (!AlmostZero(cosA + 1, 0.01) && (sinA * group_delta < 0)) // is concave
if (cosA < 0.9998) // greater than 1 degree (#424)
group.outPath.add(GetPerpendic(path.get(j), normals.get(j))); // (#418)
} else if (cosA > -0.99 && (sinA * group_delta < 0)) // is concave
{
group.outPath.add(GetPerpendic(path.get(j), normals.get(k.argValue)));
// this extra point is the only (simple) way to ensure that
Expand Down Expand Up @@ -483,8 +508,10 @@ private void OffsetOpenPath(Group group, Path64 path) {
// do the line start cap
switch (this.endType) {
case Butt :
group.outPath.add(new Point64(path.get(highI).x - normals.get(highI).x * group_delta,
path.get(highI).y - normals.get(highI).y * group_delta));
group.outPath.add(new Point64(
path.get(0).x - normals.get(0).x * group_delta,
path.get(0).y - normals.get(0).y * group_delta
));
group.outPath.add(GetPerpendic(path.get(0), normals.get(0)));
break;
case Round :
Expand Down Expand Up @@ -542,9 +569,7 @@ private void DoGroupOffset(Group group) {
return;
}
double area = Clipper.Area(group.inPaths.get(lowestIdx.argValue));
if (area == 0) {
return;
}
//if (area == 0) return; // this is probably unhelpful (#430)
group.pathsReversed = (area < 0);
if (group.pathsReversed) {
this.group_delta = -this.delta;
Expand All @@ -566,7 +591,11 @@ private void DoGroupOffset(Group group) {
// offset (delta). Obviously very large offsets will almost always
// require much less precision. See also offset_triginometry2.svg
double arcTol = arcTolerance > 0.01 ? arcTolerance : Math.log10(2 + this.abs_group_delta) * DEFAULT_ARC_TOLERANCE;
this.stepsPerRad = 0.5 / Math.acos(1 - arcTol / this.abs_group_delta);
double stepsPer360 = Math.PI / Math.acos(1 - arcTol / abs_group_delta);
stepSin = Math.sin((2 * Math.PI) / stepsPer360);
stepCos = Math.cos((2 * Math.PI) / stepsPer360);
if (group_delta < 0.0) stepSin = -stepSin;
stepsPerRad = stepsPer360 / (2 * Math.PI);
}

boolean isJoined = (group.endType == EndType.Joined) || (group.endType == EndType.Polygon);
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/clipper2/rectclip/RectClip.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package clipper2.rectclip;

import java.util.ArrayList;
import java.util.List;

import clipper2.Clipper;
import clipper2.Nullable;
import clipper2.core.InternalClipper;
Expand All @@ -14,13 +11,16 @@
import tangible.OutObject;
import tangible.RefObject;

import java.util.ArrayList;
import java.util.List;

/**
* RectClip intersects subject polygons with the specified rectangular clipping
* ExecuteRectClipLines intersects subject polygons with the specified rectangular clipping
* region. Polygons may be simple or complex (self-intersecting).
* <p>
* This function is extremely fast when compared to the Library's general
* purpose Intersect clipper. Where Intersect has roughly O(n³) performance,
* RectClip has O(n) performance.
* ExecuteRectClipLines has O(n) performance.
*
* @since 1.0.6
*/
Expand Down
Loading

0 comments on commit f943e95

Please sign in to comment.