Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions EPIC_SFA_CURVE_AWARENESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ Make JTS preserve OGC SFA / ISO 19125-2 curve geometries — `CIRCULARSTRING`, `
| `feat:` | **R-PR DE-9IM** for disc vs Point, LineString, hole-free Polygon, and two discs. Point: interior `0F2FF1FF2`, boundary `FF20F1FF2`, exterior `FF2FF10F2`. Line: crossing `1F20F1102`, tangent `FF20F1102`, miss `FF2FF1102`, endpoint-interior `1020F1102`. Polygon: disjoint `FF2FF1212`, nested `212FF1FF2`, disc-in-square `2FF1FF212`, crossing `212101212`. Two discs: crossing `212101212`, disjoint `FF2FF1212`, nested `212FF1FF2` / `2FF1FF212`, ext tangent `FF2F01212`, int tangent `212F01FF2`, equal `2FFF1FFF2`. Finish slice: single-member MultiSurface both orders; `equalsTopo` on equal/crossing/rotated-control discs; full SFS table; `crosses` of two areas always false. Half-disc / CompoundCurve miss still null → linearise. | **R-PR partial**. Not “any combination of curved/flat”. Do not delete `test_R_PR_*` / `test_R_CONT_*`. |
| `feat:` | Distance closed-form helpers in `CurveExact` (arc-to-segment, overlapping discs `nearestPoints` 0, `decideTolerance` arc-aware). | Helpers only. **D-PT / D-AA / D-OP** still describe the public `DistanceOp` TAG — keep those spec methods red. |
| `feat:` | Disc / arc convex hull closed forms. | **H-CV partial**. **H-CC** still open. |
| `feat:` | TestBuilder `CurveExactFns` Hausdorff laser. Public `DiscreteHausdorffDistance` still sees chords. | **D-HF half-red**. Keep the spec method. |
| `feat:` | TestBuilder `CurveExactFns` Hausdorff laser. Public `DiscreteHausdorffDistance` still sees chords in general. `DiscreteHausdorffDistance` on #7 has closed-form for two pairs only: single-arc `CircularString` → single-segment `LineString` (apex √949/6 − 7/6 ≈ 3.967641), and two circular discs. A single-member `MultiSurface` of one disc is the same pair, not a third. Exact path skips densify; densify 0.05 is not the laser. Keep the spec `fail()`. | **D-HF half-red**. Keep the spec method. |
| `feat:` | Disc `CurvePolygon` area 25π. | **M-AREA-CP partial** (circular discs). Keep the spec method. |
| `arch:` | PERF-GATE: identity/chord-path rows use `assertChordPath`; slack stays **15%** (`1.15`). | Contract, not a TAG. |

These closed-form subsets of **OV** and **R-PR** did **not** wait for N-SS. Line–circle clip is used *inside* R1.6; there is still no public arc-arc / arc-line utility and no arc `SegmentString`.

**Still open** (say so, do not close as “future work” a TAG that already has a named subset):

- Public `DiscreteHausdorffDistance` (D-HF) — TestBuilder laser only
- Public `DiscreteHausdorffDistance` (D-HF) — still sees chords in general; TestBuilder laser only. `DiscreteHausdorffDistance` on #7 has closed-form for two pairs only: single-arc `CircularString` → single-segment `LineString` (apex √949/6 − 7/6 ≈ 3.967641), and two circular discs. A single-member `MultiSurface` of one disc is the same pair, not a third.
- General circular noding / CompoundCurve overlay (N-AA, N-AL, N-SS, rest of OV)
- Open-arc buffer, CompoundCurve hull, Fréchet, LEC
- OFF = concentric arc (refactor)
Expand Down Expand Up @@ -199,7 +199,7 @@ Mirror the `CompoundCurve` work onto the remaining composite types.

- **D-PT / D-AA** — analytical point-arc and arc-arc distance. Closed-form helpers exist in `CurveExact`; the public `DistanceOp` TAG is still red.
- **D-OP** — `DistanceOp` accepts curved inputs without forced densification. Still the public TAG; keep the spec method.
- **D-HF** — `DiscreteHausdorffDistance` / `DiscreteFrechetDistance` parameterise by arc length. **Partial (half-red):** TestBuilder `CurveExactFns` laser only. Public `DiscreteHausdorffDistance` still sees chords. Keep the spec method. Fréchet is still open.
- **D-HF** — **Partial (half-red):** public DHD still sees chords in general; TestBuilder `CurveExactFns` laser only. `DiscreteHausdorffDistance` on #7 has closed-form for two pairs only: single-arc `CircularString` → single-segment `LineString` (apex √949/6 − 7/6 ≈ 3.967641), and two circular discs. A single-member `MultiSurface` of one disc is the same pair, not a third. Exact path skips densify; densify 0.05 is not the laser. Keep the spec `fail()`.
- **C-LIN / C-AREA / C-IP** — centroids and interior point.

**Depends on:** Phase 1 (F-CP for `CurvePolygon` cases).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,39 +261,39 @@ public void test_D_OP_distanceOpForCurveInputs() throws Exception {
* B = LINESTRING (0 0, 10 0) // the chord / diameter baseline
* </pre>
* Oriented Hausdorff {@code h(A,B) = max_{a in A} min_{b in B} d(a,b)} is the
* max height of A above B. On the true circular arc the apex sits near
* {@code (5, 3.968)} (circle centre {@code (5, -7/6)}, r ≈ 5.134), so
* continuous {@code h(A,B) ≈ 3.968}. The control-point-only discrete reading
* attains only the mid control {@code (2, 3)} → {@code h = 3}. Chord-fraction
* densify cannot close the gap: it densifies the straight control chords,
* which lie <em>inside</em> the arc and never reach the true apex.
* <p>
* Spec: densify / sample along <em>arc length</em> (uniform sweep), so the
* discrete max-min approaches the continuous directed Hausdorff. Same gap
* applies to {@code DiscreteFrechetDistance}. Delete on green (epic D-HF).
* max height of A above B. {@code DiscreteHausdorffDistance} on #7 has
* closed-form for two pairs only: single-arc {@code CircularString} →
* single-segment {@code LineString} (apex {@code √949/6 − 7/6} ≈ 3.967641),
* and two circular discs. A single-member {@code MultiSurface} of one disc
* is the same pair, not a third. The exact path owns APEX and skips densify;
* densify 0.05 is not the laser. Stale mid-control {@code h = 3} is retired.
* That exception is not the full TAG: public DHD still sees chords in
* general. Keep this {@code fail()}.
*/
public void test_D_HF_hausdorffFrechetCurveAware() throws Exception {
Geometry arc = read("CIRCULARSTRING (0 0, 2 3, 10 0)");
Geometry baseline = read("LINESTRING (0 0, 10 0)");

// Continuous directed Hausdorff (analytic apex of the circle through the
// three control points, relative to the x-axis baseline): ≈ 3.96764.
final double expectedContinuous = 3.96764;
// Apex of the locked pair: √949/6 − 7/6. Exact path owns this; densifyFrac
// is skipped on this pair (not the laser).
final double expectedContinuous = 3.967641;
final double tol = 1e-3;

double controlOnly =
double exactPath =
DiscreteHausdorffDistance.orientedDistance(arc, baseline);
double chordDensified =
double densifyCall =
DiscreteHausdorffDistance.orientedDistance(arc, baseline, 0.05);

// Red ratchet: always fail with measured numbers. When arc-length densify
// (or a curve-native path) reaches expectedContinuous within tol, delete
// this method (do not edit it green) — epic D-HF.
fail("D-HF: oriented DiscreteHausdorffDistance on CIRCULARSTRING(0 0, 2 3, 10 0) "
+ "vs LINESTRING(0 0, 10 0) should approach continuous h≈" + expectedContinuous
+ " (±" + tol + ") by sampling along arc length; control-only got " + controlOnly
+ ", chord-densify(frac=0.05) got " + chordDensified
+ " (today both ≈ mid-control height 3 — densify walks control chords, not the arc).");
// Full-TAG ratchet: always fail. Exact path owns APEX; densify is skipped
// on this pair, not the laser. Stale h=3 retired. Keep this fail().
fail("D-HF: full TAG still open. Public DiscreteHausdorffDistance still sees chords in general. "
+ "DiscreteHausdorffDistance on #7 has closed-form for two pairs only: "
+ "single-arc CircularString → single-segment LineString "
+ "(apex √949/6 − 7/6 ≈ " + expectedContinuous + "), and two circular discs. "
+ "A single-member MultiSurface of one disc is the same pair, not a third. "
+ "Exact path owns APEX (orientedDistance got " + exactPath
+ "); densifyFrac is skipped on this pair (call returned " + densifyCall
+ ", not the laser). Stale h=3 retired. Keep this fail() (±" + tol + ").");
}

// ============================================================
Expand Down
Loading