svg_path/arrangement_graph
Arrangement-graph primitives for Boolean path operations.
This module provides arrangement construction, endpoint clustering,
coincident-edge multiplicity, and invariant validation. build refines
intersections and endpoint-bounded overlaps into atomic segments before
inserting them as graph edges.
An atomic segment has no proper intersection or partial overlap with any other edge segment. Atomic segments may meet at their endpoint vertices. Geometrically coincident atomic segments are represented by one edge with directional multiplicities.
The public types are transparent so callers can inspect, serialize, and
draw an arrangement. build is the supported constructor: code that
assembles these representations directly is responsible for all documented
invariants.
Types
One directed geometric edge of an arrangement.
The stored segment runs from start_vertex to end_vertex. Its endpoints
remain the normalized source endpoints and are within the build tolerance
of the corresponding vertex points; construction does not move the segment
to the cluster centers. The segment’s chord is at least minimum_chord.
forward_multiplicity counts coincident source segments oriented like the
stored segment, and reverse_multiplicity counts those oriented against it.
Both are non-negative and their sum is positive in a constructed graph.
pub type ArrangementEdge {
ArrangementEdge(
id: Int,
segment: svg_path.Segment,
start_vertex: Int,
end_vertex: Int,
forward_multiplicity: Int,
reverse_multiplicity: Int,
)
}
Constructors
-
ArrangementEdge( id: Int, segment: svg_path.Segment, start_vertex: Int, end_vertex: Int, forward_multiplicity: Int, reverse_multiplicity: Int, )Arguments
- id
-
The edge’s unique identifier in a graph returned by
build. - segment
-
The atomic segment, oriented from
start_vertextoend_vertex. - start_vertex
-
Identifier of the segment’s start endpoint cluster.
- end_vertex
-
Identifier of the segment’s end endpoint cluster.
- forward_multiplicity
-
Number of coincident source segments with the stored orientation.
- reverse_multiplicity
-
Number of coincident source segments with the reverse orientation.
A possibly disconnected planar arrangement of normalized path segments.
Graphs returned by build have unique vertex and edge identifiers. Every
edge refers to two existing, distinct vertices, and every vertex is incident
to an edge. Different atomic edges have no proper intersections or partial
overlaps; they meet only through endpoint clusters. Coincident pieces are
consolidated into one edge with directional multiplicities.
Cyclic edge order is not stored. Consumers derive it from the segment
geometry and vertex point. For closed-boundary input, the sum of incident
edge multiplicities at every vertex is positive and even. validate
enforces this closed-boundary condition, so an arrangement built from open
subpaths may be inspectable but fail validation.
pub type ArrangementGraph {
ArrangementGraph(
vertices: List(ArrangementVertex),
edges: List(ArrangementEdge),
)
}
Constructors
-
ArrangementGraph( vertices: List(ArrangementVertex), edges: List(ArrangementEdge), )Arguments
- vertices
-
Endpoint clusters in the arrangement.
- edges
-
Non-intersecting atomic edges in the arrangement.
An arrangement graph and the normalized source paths from which it was constructed.
normalized_paths has the same path order and count as the input to
build; subpath order is also preserved within each path. Normalization
replaces line-degenerate segment sequences before refinement and may change
segment decomposition. These are the official source paths corresponding to
the graph and should be used for later winding classification.
pub type ArrangementGraphBuild {
ArrangementGraphBuild(
graph: ArrangementGraph,
normalized_paths: List(svg_path.Path),
)
}
Constructors
-
ArrangementGraphBuild( graph: ArrangementGraph, normalized_paths: List(svg_path.Path), )Arguments
- graph
-
The arrangement produced from
normalized_paths. - normalized_paths
-
Normalized sources, retaining the input path and subpath order.
One endpoint cluster in the embedded arrangement.
point is the center of the smallest circle enclosing endpoint_samples.
Construction accepts a sample only when that circle’s squared radius does
not exceed the graph’s squared endpoint tolerance. Consequently every
sample lies within tolerance of point, without making the result depend
on endpoint insertion order.
pub type ArrangementVertex {
ArrangementVertex(
id: Int,
point: svg_path.Point,
endpoint_samples: List(svg_path.Point),
)
}
Constructors
-
ArrangementVertex( id: Int, point: svg_path.Point, endpoint_samples: List(svg_path.Point), )Arguments
- id
-
The vertex identifier referenced by incident edges.
- point
-
The representative location of this endpoint cluster.
- endpoint_samples
-
The original segment endpoints assigned to this cluster.
pub type Error {
PathError(svg_path.Error)
InternalNormalizationError
InvalidTolerance(tolerance: Float)
InvalidMinimumChord(minimum_chord: Float)
SegmentTooShort(chord: Float, minimum: Float)
SegmentCollapsedToVertex(vertex: Int)
LoopEdge(vertex: Int)
MissingVertex(vertex: Int)
IsolatedVertex(vertex: Int)
InvalidMultiplicity(edge: Int)
OddWeightedDegree(vertex: Int, degree: Int)
EdgeEndpointMismatch(edge: Int, vertex: Int, distance: Float)
VertexWithoutEndpointSamples(vertex: Int)
VertexCenterMismatch(vertex: Int, distance_squared: Float)
VertexSampleOutsideTolerance(
vertex: Int,
distance_squared: Float,
tolerance_squared: Float,
)
}
Constructors
-
PathError(svg_path.Error)An underlying path operation failed.
-
InternalNormalizationErrorNormalization failed for a reason outside its path-operation contract.
-
InvalidTolerance(tolerance: Float)Endpoint tolerance must be greater than zero.
-
InvalidMinimumChord(minimum_chord: Float)Minimum edge chord length must be greater than zero.
-
SegmentTooShort(chord: Float, minimum: Float)A segment is shorter than the required minimum chord length.
-
SegmentCollapsedToVertex(vertex: Int)Endpoint clustering collapsed an inserted segment to one vertex.
-
LoopEdge(vertex: Int)A graph edge refers to the same vertex at both ends.
-
MissingVertex(vertex: Int)An edge refers to a vertex that is not in the graph.
-
IsolatedVertex(vertex: Int)A vertex has no incident edge.
-
InvalidMultiplicity(edge: Int)An edge’s total directional multiplicity is not positive.
-
OddWeightedDegree(vertex: Int, degree: Int)A closed-boundary graph has an odd weighted degree at a vertex.
-
EdgeEndpointMismatch(edge: Int, vertex: Int, distance: Float)A segment endpoint is farther than tolerance from its vertex point.
-
VertexWithoutEndpointSamples(vertex: Int)A vertex does not retain any source endpoints for its cluster.
-
VertexCenterMismatch(vertex: Int, distance_squared: Float)A vertex point is not the canonical center of its endpoint samples.
-
VertexSampleOutsideTolerance( vertex: Int, distance_squared: Float, tolerance_squared: Float, )A vertex’s endpoint cluster exceeds the graph tolerance.
Values
pub fn build(
paths: List(svg_path.Path),
tolerance tolerance: Float,
minimum_chord minimum_chord: Float,
) -> Result(ArrangementGraphBuild, Error)
Build an arrangement graph and return the normalized sources it represents.
Normalization retains path and subpath order. Construction then flattens the normalized paths into segments, refines them at point intersections and endpoint-bounded overlap boundaries, and inserts the resulting atomic segments. Its output geometry is independent of input processing order. Overlap detection uses endpoint projection, so semantically equal arcs need not have structurally equal SVG flags or matching original subdivision points.
pub fn validate(
graph: ArrangementGraph,
tolerance tolerance: Float,
minimum_chord minimum_chord: Float,
) -> Result(Nil, Error)
Validate local representation and closed-boundary invariants.
This checks multiplicity totals, vertex references, non-loop edges, endpoint
tolerance, minimum chord length, endpoint-cluster centers and radii, vertex
incidence, and even weighted degree. It does not test pairwise edge
intersections, atomicity, identifier uniqueness, or individual directional
multiplicity signs; use build to establish those construction invariants.