Skip to content

Polyline refuses distance evaluation though its arc length is an exact sum #107

Description

@GeneralPawz

DistanceConvention::Unsupported currently covers three curve families, and one of them does not belong there: a polyline has an exact closed-form arc length, unlike an ellipse or a B-spline.

What refuses today

let curve = Curve3::Polyline(Polyline3 {
    points: vec![
        Point3::new(0.0, 0.0, 0.0),
        Point3::new(3.0, 4.0, 0.0),   // 5 m
        Point3::new(3.0, 4.0, 12.0),  // 12 m
    ],
    closed: false,
});

ev.distance_convention(&curve);          // Unsupported
ev.point_at(&curve, CurveMeasure::Distance(5.0));
// Err(Unsupported { backend: "axiolid-evaluate", operation: CurveEvaluation })

The answer at 5 m is exactly (3, 4, 0). No integral, no iteration.

Why the three families are not alike

The shipped rationale groups them together:

Ellipse, BSpline and Polyline have no closed-form arc length (the ellipse needs an elliptic integral), so distance is refused rather than approximated behind an exact-looking signature.

That is right for two of them and wrong for the third.

Family Arc length Cost
Ellipse incomplete elliptic integral of the second kind genuinely transcendental
BSpline no closed form; needs quadrature + numeric inversion genuinely iterative
Polyline finite sum of segment lengths exact, O(n)

A polyline is an ordered point list. Locating a distance is a running sum until the interval is found, then one linear interpolation. Every operation is already exact in Scalar; the only transcendental is the sqrt in each segment length, which Line already relies on and reports as ArcLength3d.

The inconsistency is visible within the current table: Curve3::Line reports ArcLength3d via d / |direction|. A polyline is a sequence of lines. Refusing the sequence while accepting each element is hard to justify from exactness.

Why it matters downstream

IFC4x3 allows IfcLinearPlacement.PlacementRelTo to be any IfcCurve, not only an alignment centreline. IfcPolyline and IfcIndexedPolyCurve are common as basis curves for simple linear referencing -- a kerb line, a fence run, a utility trace -- where nobody authored a full horizontal/vertical alignment.

For those we currently refuse by type rather than place the product, and the refusal is not a statement about the file: the geometry is exactly locatable, the capability is just declared absent.

Ellipse and BSpline we are happy to keep refusing. Neither appears as an alignment basis curve in practice, and an approximation there would be a worse answer than a refusal.

Suggested shape

Polyline reports ArcLength3d and is evaluable by distance. No new enum variant, no trait change, no change for existing callers -- a family moves out of Unsupported.

Three edges worth pinning, because each has a wrong answer that looks plausible:

  • A seam is ambiguous. At a vertex the tangent is two-valued. Picking the outgoing segment is defensible; leaving it undefined is not. frame_at at a seam has the same question, and it matters more there, because a sign at a kink would silently take one of two headings.
  • Degenerate segments. Repeated identical points give a zero-length segment and a zero tangent. Skipping them changes the parameterisation; refusing is cleaner than normalising a zero vector.
  • closed: true. The wrap segment from last point back to first is real length. Whether distance may exceed the open length, and whether it wraps, should be stated rather than discovered.

What we are NOT asking for

Not arc-length reparameterisation in general. BSpline would need quadrature plus Newton inversion, with tolerance and convergence policy attached -- that is a real design decision with exactness tradeoffs, and it should stay refused until someone has a concrete need. This issue is only the family where the exact answer is a sum.

Our side

ifc-geometry reaches this through CurveEvaluator behind a non-default feature, so nothing is needed from us beyond widening one dispatch arm once the convention changes. Verified against 0.2.1: the contract wiring, the CurveMeasure distinction and the reference-up frame_at all work end to end for the Elevated path.

Happy to take the implementation if you would rather review than write it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

needs-triageFiled but not yet accepted, sized, or scheduled

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions