pub struct PathShape { /* private fields */ }Expand description
A parsed, normalized, resampled closed contour.
The points are the contour itself: samples of them, evenly spaced by arc
length around the outline and not repeating the first at the end — the
closing edge from the last point back to the first is implicit, and both the
distance field and the arc-length walk here assume it.
Implementations§
Source§impl PathShape
impl PathShape
Sourcepub fn parse(d: &str, samples: usize) -> Result<Self, PathError>
pub fn parse(d: &str, samples: usize) -> Result<Self, PathError>
Parse inline SVG path data into a normalized contour of samples points.
samples is trusted to be in MIN_SAMPLES..=MAX_SAMPLES; the
[path] table checks it at the load boundary, which is where a range
belongs.
Sourcepub fn points(&self) -> &[[f32; 2]]
pub fn points(&self) -> &[[f32; 2]]
The contour’s points, normalized into [-1, 1] on its longer axis.
Sourcepub fn source_center(&self) -> [f32; 2]
pub fn source_center(&self) -> [f32; 2]
The centre of the source drawing’s bounding box, in the source’s own units — the translation the normalization applied, recorded.
Sourcepub fn source_scale(&self) -> f32
pub fn source_scale(&self) -> f32
The factor the source drawing was scaled by — the reciprocal of half its longer bounding-box axis, recorded.
Sourcepub fn star_shaped(&self) -> bool
pub fn star_shaped(&self) -> bool
Whether a ray from the figure’s centre meets this outline exactly
once, to within STAR_SHAPED_TOLERANCE.
The scaled-copy coordinate (coord_mode = 1) divides by the boundary
radius along such a ray, so on a contour where the answer is false that
coordinate has no single value: the shader takes the outermost crossing,
every point between the crossings reads as interior, and a figure with
fins or a crescent collapses to a dot inside a few huge rays. The scene
draws the distance instead and the load boundary says so.
The centre is the origin of these points, because that is the point the
shader’s own ray starts from — shape_field’s path_boundary_radius
builds its direction as p / length(p) and intersects the contour from
there. The normalization has already put the source drawing’s
bounding-box centre on that origin, so this is a test about the bounding
box’s centre and not about the centroid; the two differ on any figure
that is heavier on one side, and a test about the wrong one convicts good
figures and clears bad ones.
Sourcepub fn signed_area(&self) -> f32
pub fn signed_area(&self) -> f32
Twice the shoelace sum: positive when the contour winds counter-clockwise in a y-up frame, negative when it winds clockwise.
The stored contour is in that frame — parse negates SVG’s downward y
— so this sign is the winding an author sees on screen, and a d string
that reads clockwise in a browser reports negative here.
The sign is what a morph pair has to agree on (ADR-0107) — a clockwise contour interpolating into a counter-clockwise one turns inside out through the middle, passing through zero area on the way.
Sourcepub fn aligned_to(&self, from: &Self) -> Option<Self>
pub fn aligned_to(&self, from: &Self) -> Option<Self>
This contour re-expressed so that interpolating toward it from from
is a morph rather than a scramble (ADR-0107).
The two alignment problems ADR-0107 says have answers, solved in the order they have to be:
- Winding, by signed area. A clockwise contour interpolating into a counter-clockwise one turns inside out through the middle — every intermediate frame is a valid shape and the motion is wrong — and the contour passes through zero enclosed area on the way. When the two signs disagree, the target is walked backwards.
- Start point, by minimising total displacement over cyclic
offsets. Without it a star morphing into a star can unwind through a
spiral: each point travels to a correspondent rather than to its
neighbour, and every intermediate frame is again valid.
O(N^2)at load, which at this arity is thousands of operations, so the brute-force search is affordable and no cleverness is owed.
The third — two paths with different subpath counts — has no answer, and is refused at the parser rather than guessed at here.
Both contours must already carry the same number of points; None if
they do not, which the load boundary prevents by parsing the pair at one
arity.
Sourcepub fn piece_count(&self) -> usize
pub fn piece_count(&self) -> usize
How many arc pieces the fit kept — 0 where the figure stays a polyline.
The count rather than the chain, so a caller outside the crate can report
what a curve cost without biarc::Piece
being public API.