Repository navigation
Story: Implement COMPOUNDCURVE spatial type #25
Description
Implement COMPOUNDCURVE spatial type
As a developer using spatial-types,
I want COMPOUNDCURVE to be fully implemented as a concrete spatial type,
so that continuous curves composed of multiple curve components can be represented and consumed by downstream libraries such as the EWKT decoder.
Context
COMPOUNDCURVE is an instantiable subtype of CURVE.
It is required for the spatial-types 1.0.0 release because it belongs to the geometry set required to complete the targeted EWKT decoding support in spatial-decoder.
A CompoundCurve represents a continuous curve constructed from an ordered sequence of curve components.
For the spatial-types 1.0.0 scope, the supported components required by the current spatial model are:
LINESTRING;CIRCULARSTRING.
The components are connected end to end.
For every pair of consecutive components, the end point of the preceding component must be equal to the start point of the following component.
This continuity requirement is an invariant of the CompoundCurve and must be enforced by spatial-types.
All components must also satisfy the coordinate-dimension and spatial-reference consistency rules established by the library.
Functional Requirements
COMPOUNDCURVE must follow the existing spatial-types architecture and expose the public contracts appropriate for an instantiable CURVE.
The implementation must support the coordinate dimensions supported by the LongitudeOne spatial model:
XY;XYZ;XYM;XYZM.
A CompoundCurve is represented as an ordered collection of supported curve components.
The order of the components is significant and defines the traversal of the CompoundCurve.
For consecutive components:
end(component[n]) == start(component[n + 1])
must hold according to the point equality semantics established by spatial-types.
The CompoundCurve must preserve its component curves. It must not flatten a CIRCULARSTRING into a LINESTRING or approximate circular interpolation using linear segments.
An empty CompoundCurve must be representable consistently with the existing empty-geometry model.
Component Types
For the 1.0.0 implementation, a CompoundCurve must accept:
LINESTRING;CIRCULARSTRING.
The public design should rely on the appropriate curve abstraction where possible and must not unnecessarily prevent additional compatible curve implementations from being supported in future backward-compatible releases.
A component must itself represent a valid curve according to its own spatial type contract.
Continuity
The components of a non-empty CompoundCurve must form a continuous sequence.
For each pair of consecutive components:
- the preceding component must have an end point;
- the following component must have a start point;
- both points must be equal.
A discontinuity between two components makes the CompoundCurve invalid.
For example:
LINESTRING(A, B, C)
\
C
\
CIRCULARSTRING(C, D, E)
is continuous because both components meet at C.
Conversely:
LINESTRING(A, B, C)
CIRCULARSTRING(D, E, F)
is not a valid CompoundCurve when C != D.
Coordinate Dimension
All components of a CompoundCurve must use the same coordinate dimension.
The implementation must support:
XY;XYZ;XYM;XYZM.
Mixing components with different coordinate dimensions in the same CompoundCurve must be rejected according to the existing dimension-consistency rules of spatial-types.
Spatial Reference
All components of a CompoundCurve must use compatible spatial references according to the existing spatial-reference rules of spatial-types.
A CompoundCurve containing components with incompatible spatial references must be rejected.
Closure
A non-empty CompoundCurve is closed when the start point of its first component is equal to the end point of its last component.
Closure does not remove the continuity requirement between intermediate components.
The implementation must preserve the distinction between:
- an open CompoundCurve;
- a closed CompoundCurve.
Any ring semantics applicable to a closed and simple CompoundCurve must remain consistent with the normative spatial model and the existing curve contracts.
Public Contract
The implementation must provide the same architectural guarantees as the other concrete curve types exposed by spatial-types.
The public API must allow consumers to:
- construct an empty CompoundCurve;
- construct a CompoundCurve from supported curve components;
- access its components in their original order;
- access its start and end points through the applicable curve contract;
- determine whether it is closed according to the applicable curve contract;
- determine its coordinate dimension;
- determine its spatial reference according to the existing spatial type contracts;
- identify its geometry type as
COMPOUNDCURVE; - use it through the applicable spatial and curve interfaces.
The API must preserve the distinction between the component curve types.
It must not expose implementation details that would unnecessarily constrain future internal evolution after spatial-types 1.0.0.
Validation
Validation must reject a CompoundCurve when:
- consecutive components are not continuous;
- components use inconsistent coordinate dimensions;
- components use incompatible spatial references;
- a component violates an invariant required by its own spatial type;
- another existing invariant inherited from the applicable
spatial-typescontracts is violated.
Validation must not alter, linearize or otherwise normalize valid component curves merely to establish continuity.
Implementation Status
Once this Story is completed, COMPOUNDCURVE is no longer considered a not-yet-implemented geometry type.
SpatialTypeImplementationStatus::isFullyImplemented() must return true for GeometryTypeEnum::COMPOUNDCURVE.
Acceptance Criteria
- A public concrete implementation exists for
COMPOUNDCURVE. -
COMPOUNDCURVEfollows the applicableCURVEand spatial type contracts. - Empty CompoundCurves are supported consistently with the existing empty-geometry model.
- A CompoundCurve can contain
LINESTRINGcomponents. - A CompoundCurve can contain
CIRCULARSTRINGcomponents. - A CompoundCurve can contain a combination of
LINESTRINGandCIRCULARSTRINGcomponents. - Component order is preserved.
- Consecutive components are required to be continuous.
- Discontinuous components are rejected.
- The original component curve types are preserved and are not linearized.
-
XYCompoundCurves are supported. -
XYZCompoundCurves are supported. -
XYMCompoundCurves are supported. -
XYZMCompoundCurves are supported. - Components with inconsistent coordinate dimensions are rejected.
- Components with incompatible spatial references are rejected.
- Open CompoundCurves are supported.
- Closed CompoundCurves are supported.
- The geometry type is reported as
COMPOUNDCURVE. -
SpatialTypeImplementationStatus::isFullyImplemented()returnstrueforCOMPOUNDCURVE. - Unit tests cover CompoundCurves composed only of
LINESTRINGcomponents. - Unit tests cover CompoundCurves composed only of
CIRCULARSTRINGcomponents. - Unit tests cover mixed
LINESTRINGandCIRCULARSTRINGcomponents. - Unit tests cover continuity and discontinuity between components.
- Unit tests cover open and closed CompoundCurves.
- Unit tests cover
XY,XYZ,XYMandXYZM. - Dimension and spatial-reference inconsistencies are covered by tests.
- The public implementation can be consumed without relying on internal APIs.
- The complete test suite passes.
- All project quality checks pass.
Dependencies
This Story depends on the implementation of CIRCULARSTRING.
CIRCULARSTRING must therefore be completed before COMPOUNDCURVE can be considered fully implemented for the spatial-types 1.0.0 release.
Out of Scope
This Story does not implement:
CIRCULARSTRINGitself;CURVEPOLYGON;- additional curve types;
- EWKT parsing or decoding;
- WKT, WKB, EWKB or other serialization formats;
- curve linearization or rendering.
Those concerns belong to their respective Stories or libraries.
Activity
spatial-types1.0.0 #23spatial-types1.0.0 #26CIRCULARSTRINGspatial type #24Alexandre-T commentedon Oct 4, 2026
Pre-checks completed: Story #25 is Ready, type Story, 5 points, priority P2; parent #23 reviewed; dependency #24 is Closed / Done. No files were modified.
API decision required before implementation
CurveInterfaceis currently a marker interface with no methods. The Story requires endpoints and closure semantics, and the approval of #24 requiresCompoundCurveto depend onCurveInterface, while explicitly requiring another API Gate for any new contract decision.Two concrete options:
getStartPoint(): ?PointInterface,getEndPoint(): ?PointInterface, andisClosed(): booltoCurveInterface, with implementations forLineString,CircularString, andCompoundCurve. This requires both an API Gate and a Breaking Gate: third-party implementations of these interfaces will need to implement the new methods.CurveInterfaceas a marker interface: expose these methods only on a newCompoundCurveInterface, then use internal adaptations for the two allowed component types. This is backward-compatible, but provides no common endpoint contract.Standard consulted
The standard actually consulted was ISO/IEC CD 13249-3:201x(E), clauses 4.2.7, 7.4.1 rules 7–10, and 7.4.6–7.4.7.
It confirms the use of
LineStringandCircularStringcomponents, continuity requirements, and null endpoints forEMPTYgeometries. It does not prescribe the PHP API contract.Reason for stopping
Implementation was stopped in accordance with longitudeone-spatial-governance/SKILL.md:
This is also consistent with the human approval recorded for #24, as described above.
No PR was created. The reviewer should be run after this gate is resolved and the PR has been created.
Alexandre-T commentedon Oct 4, 2026
API Gate and Breaking Gate approved.
Proceed with the recommended solution.
Add the following common curve contract to
CurveInterface:Implement this contract consistently for
LineString,CircularString, and the newCompoundCurve.For
EMPTYcurves, the start and end points must benull, consistently with the normative behavior identified during the review.I explicitly approve the backward-incompatible change to the existing public interfaces. We are still before the
1.0.0stable API boundary, and establishing a meaningful common curve abstraction now is preferable to keepingCurveInterfaceas a marker interface.CompoundCurvemust depend onCurveInterfacefor its curve components rather than on a union of the currently supported concrete curve interfaces.This approval is limited to this common endpoint and closure contract. Any additional public API or breaking-contract decision that cannot be derived from the approved Story, existing architecture, or normative requirements must go through a new API/Breaking Gate.
[-]Implement `COMPOUNDCURVE` spatial type[/-][+]Story: Implement `COMPOUNDCURVE` spatial type[/+]