@@ -203,6 +205,11 @@ public final void Execute(double delta, Paths64 solution) {
}
}
+ public void Execute(DeltaCallback64 deltaCallback64, Paths64 solution) {
+ deltaCallback = deltaCallback64;
+ Execute(1.0, solution);
+ }
+
public void Execute(double delta, PolyTree64 polytree) {
polytree.Clear();
ExecuteInternal(delta);
@@ -260,6 +267,14 @@ public final void setReverseSolution(boolean value) {
reverseSolution = value;
}
+ public final void setDeltaCallBack64(DeltaCallback64 callback) {
+ deltaCallback = callback;
+ }
+
+ public final DeltaCallback64 getDeltaCallBack64() {
+ return deltaCallback;
+ }
+
private static PointD GetUnitNormal(Point64 pt1, Point64 pt2) {
double dx = (pt2.x - pt1.x);
double dy = (pt2.y - pt1.y);
@@ -370,14 +385,14 @@ private PointD GetPerpendicD(Point64 pt, PointD norm) {
private void DoSquare(Group group, Path64 path, int j, int k) {
PointD vec;
if (j == k) {
- vec = new PointD(normals.get(0).y, -normals.get(0).x);
+ vec = new PointD(normals.get(j).y, -normals.get(j).x);
} else {
vec = GetAvgUnitVector(new PointD(-normals.get(k).y, normals.get(k).x), new PointD(normals.get(j).y, -normals.get(j).x));
}
-
+ double absDelta = Math.abs(groupDelta);
// now offset the original vertex delta units along unit vector
PointD ptQ = new PointD(path.get(j));
- ptQ = TranslatePoint(ptQ, absGroupDelta * vec.x, absGroupDelta * vec.y);
+ ptQ = TranslatePoint(ptQ, absDelta * vec.x, absDelta * vec.y);
// get perpendicular vertices
PointD pt1 = TranslatePoint(ptQ, groupDelta * vec.y, groupDelta * -vec.x);
@@ -401,12 +416,26 @@ private void DoSquare(Group group, Path64 path, int j, int k) {
}
private void DoMiter(Group group, Path64 path, int j, int k, double cosA) {
- double q = groupDelta / (cosA + 1);
+ final double q = groupDelta / (cosA + 1);
group.outPath.add(new Point64(path.get(j).x + (normals.get(k).x + normals.get(j).x) * q,
path.get(j).y + (normals.get(k).y + normals.get(j).y) * q));
}
private void DoRound(Group group, Path64 path, int j, int k, double angle) {
+ if (deltaCallback != null) {
+ // when deltaCallback is assigned, groupDelta won't be constant,
+ // so we'll need to do the following calculations for *every* vertex.
+ double absDelta = Math.abs(groupDelta);
+ double arcTol = arcTolerance > 0.01 ? arcTolerance : Math.log10(2 + absDelta) * DEFAULT_ARC_TOLERANCE;
+ double stepsPer360 = Math.PI / Math.acos(1 - arcTol / absDelta);
+ stepSin = Math.sin((2 * Math.PI) / stepsPer360);
+ stepCos = Math.cos((2 * Math.PI) / stepsPer360);
+ if (groupDelta < 0.0) {
+ stepSin = -stepSin;
+ }
+ stepsPerRad = stepsPer360 / (2 * Math.PI);
+ }
+
Point64 pt = path.get(j);
PointD offsetVec = new PointD(normals.get(k).x * groupDelta, normals.get(k).y * groupDelta);
if (j == k) {
@@ -449,21 +478,23 @@ private void OffsetPoint(Group group, Path64 path, int j, RefObject
+ * Implementations of this interface define how to calculate the delta (the
+ * amount of offset) to apply at each point in a polygon during an offset
+ * operation. The offset can vary from point to point, allowing for variable
+ * offsetting.
+ */
+@FunctionalInterface
+public interface DeltaCallback64 {
+ /**
+ * Calculates the delta (offset) for a given point in the polygon path.
+ *
+ * This method is used during polygon offsetting operations to determine the
+ * amount by which each point of the polygon should be offset.
+ *
+ * @param path The {@link Path64} object representing the original polygon
+ * path.
+ * @param path_norms The {@link PathD} object containing the normals of the
+ * path, which may be used to influence the delta calculation.
+ * @param currPt The index of the current point in the path for which the
+ * delta is being calculated.
+ * @param prevPt The index of the previous point in the path, which can be
+ * referenced to determine the delta based on adjacent
+ * segments.
+ * @return A {@code double} value representing the calculated delta for the
+ * current point. This value will be used to offset the point in the
+ * resulting polygon.
+ */
+ double calculate(Path64 path, PathD path_norms, int currPt, int prevPt);
+}
diff --git a/src/main/java/clipper2/rectclip/RectClip.java b/src/main/java/clipper2/rectclip/RectClip64.java
similarity index 98%
rename from src/main/java/clipper2/rectclip/RectClip.java
rename to src/main/java/clipper2/rectclip/RectClip64.java
index 1b3d7b1..8bb7cd3 100644
--- a/src/main/java/clipper2/rectclip/RectClip.java
+++ b/src/main/java/clipper2/rectclip/RectClip64.java
@@ -15,16 +15,16 @@
import tangible.RefObject;
/**
- * RectClip intersects subject polygons with the specified rectangular clipping
- * region. Polygons may be simple or complex (self-intersecting).
+ * RectClip64 intersects subject polygons with the specified rectangular
+ * clipping region. Polygons may be simple or complex (self-intersecting).
*
* 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.
+ * RectClip64 has O(n) performance.
*
* @since 1.0.6
*/
-public class RectClip {
+public class RectClip64 {
protected static class OutPt2 {
@Nullable
@@ -55,7 +55,7 @@ protected enum Location {
protected int currIdx = -1;
@SuppressWarnings("unchecked")
- public RectClip(Rect64 rect) {
+ public RectClip64(Rect64 rect) {
currIdx = -1;
this.rect = rect;
mp = rect.MidPoint();
@@ -586,7 +586,7 @@ private void ExecuteInternal(Path64 path) {
}
}
} else if (loc.argValue != Location.INSIDE && (loc.argValue != firstCross || startLocs.size() > 2)) {
- if (startLocs.size() > 0) {
+ if (!startLocs.isEmpty()) {
prev.argValue = loc.argValue;
for (Location loc2 : startLocs) {
if (prev.argValue == loc2) {
@@ -603,7 +603,7 @@ private void ExecuteInternal(Path64 path) {
}
}
- public Paths64 Execute(Paths64 paths, boolean convexOnly) {
+ public Paths64 Execute(Paths64 paths) {
Paths64 result = new Paths64();
if (rect.IsEmpty()) {
return result;
@@ -621,11 +621,9 @@ public Paths64 Execute(Paths64 paths, boolean convexOnly) {
continue;
}
ExecuteInternal(path);
- if (!convexOnly) {
- CheckEdges();
- for (int i = 0; i < 4; ++i) {
- TidyEdgePair(i, edges[i * 2], edges[i * 2 + 1]);
- }
+ CheckEdges();
+ for (int i = 0; i < 4; ++i) {
+ TidyEdgePair(i, edges[i * 2], edges[i * 2 + 1]);
}
for (@Nullable
diff --git a/src/main/java/clipper2/rectclip/RectClipLines.java b/src/main/java/clipper2/rectclip/RectClipLines64.java
similarity index 91%
rename from src/main/java/clipper2/rectclip/RectClipLines.java
rename to src/main/java/clipper2/rectclip/RectClipLines64.java
index a8040bd..0f9b915 100644
--- a/src/main/java/clipper2/rectclip/RectClipLines.java
+++ b/src/main/java/clipper2/rectclip/RectClipLines64.java
@@ -9,18 +9,18 @@
import tangible.RefObject;
/**
- * RectClipLines intersects subject open paths (polylines) with the specified
+ * RectClipLines64 intersects subject open paths (polylines) with the specified
* rectangular clipping region.
*
* This function is extremely fast when compared to the Library's general
* purpose Intersect clipper. Where Intersect has roughly O(n³) performance,
- * RectClipLines has O(n) performance.
+ * RectClipLines64 has O(n) performance.
*
* @since 1.0.6
*/
-public class RectClipLines extends RectClip {
+public class RectClipLines64 extends RectClip64 {
- public RectClipLines(Rect64 rect) {
+ public RectClipLines64(Rect64 rect) {
super(rect);
}
@@ -123,9 +123,8 @@ private void ExecuteInternal(Path64 path) {
// we must be crossing the rect boundary to get here
////////////////////////////////////////////////////
- if (loc.argValue == Location.INSIDE) // path must be entering rect
- {
- Add(ip);
+ if (loc.argValue == Location.INSIDE) { // path must be entering rect
+ Add(ip, true);
} else if (prev.argValue != Location.INSIDE) {
// passing right through rect. 'ip' here will be the second
// intersect pt but we'll also need the first intersect pt (ip2)
diff --git a/src/main/java/clipper2/rectclip/package-info.java b/src/main/java/clipper2/rectclip/package-info.java
index 021dae3..ec7f2f2 100644
--- a/src/main/java/clipper2/rectclip/package-info.java
+++ b/src/main/java/clipper2/rectclip/package-info.java
@@ -1,5 +1,5 @@
/**
- * This unit contains the code that implements the RectClip functions found in
+ * This unit contains the code that implements the RectClip64 functions found in
* the Clipper Unit.
*
* @since 1.0.6