Struct lyon_tessellation::FillTessellator
source · pub struct FillTessellator { /* private fields */ }
Expand description
A Context object that can tessellate fill operations for complex paths.
Overview
The most important structure is FillTessellator
.
It implements the path fill tessellation algorithm which is by far the most advanced
feature in all lyon crates.
The FillTessellator
takes a description of the input path and
FillOptions
as input. The description of the path can be an
PathEvent
iterator, or an iterator of IdEvent
with an implementation ofPositionStore
to retrieve positions form endpoint and control point ids, and optionally an AttributeStore
providing custom endpoint attributes that the tessellator can hand over to the geometry builder.
The output of the tessellator is produced by the
FillGeometryBuilder
(see the
geometry_builder
documentation for more details about
how tessellators produce their output geometry, and how to generate custom vertex layouts).
The tessellator’s wiki page is a good place to learn more about how the tessellator’s algorithm works. The source code also contains inline documentation for the adventurous who want to delve into more details.
The tessellator does not handle NaN
values in any of its inputs.
Associating custom attributes with vertices.
It is sometimes useful to be able to link vertices generated by the tessellator back with the path’s original data, for example to be able to add attributes that the tessellator does not know about (vertex color, texture coordinates, etc.).
The fill tessellator has two mechanisms to help with these advanced use cases. One is simple to use and one that, while more complicated to use, can cover advanced scenarios.
Before going delving into these mechanisms, it is important to understand that the vertices generated by the tessellator don’t always correspond to the vertices existing in the original path.
- Self-intersections, for example, introduce a new vertex where two edges meet.
- When several vertices are at the same position, they are merged into a single vertex from the point of view of the tessellator.
- The tessellator does not handle curves, and uses an approximation that introduces a number of line segments and therefore endpoints between the original endpoints of any quadratic or cubic bézier curve.
This complicates the task of adding extra data to vertices without loosing the association during tessellation.
Vertex sources
This is the complicated, but most powerful mechanism. The tessellator keeps track of where
each vertex comes from in the original path, and provides access to this information via
an iterator of VertexSource
in FillVertex::sources
.
It is most common for the vertex source iterator to yield a single VertexSource::Endpoint
source, which happens when the vertex directly corresponds to an endpoint of the original path.
More complicated cases can be expressed.
For example if a vertex is inserted at an intersection halfway in the edge AB and two thirds
of the way through edge BC, the source for this new vertex is VertexSource::Edge { from: A, to: B, t: 0.5 }
and VertexSource::Edge { from: C, to: D, t: 0.666666 }
where A, B, C and D are endpoint IDs.
To use this feature, make sure to use FillTessellator::tessellate_with_ids
instead of
FillTessellator::tessellate
.
Interpolated float attributes
Having to iterate over potentially several sources for each vertex can be cumbersome, in addition to having to deal with generating proper values for the attributes of vertices that were introduced at intersections or along curves.
In many scenarios, vertex attributes are made of floating point numbers and the most reasonable way to generate new attributes is to linearly interpolate these numbers between the endpoints of the edges they originate from.
Custom endpoint attributes are represented as &[f32]
slices accessible via
FillVertex::interpolated_attributes
. All vertices, whether they originate from a single
endpoint or some more complex source, have exactly the same number of attributes.
Without having to know about the meaning of attributes, the tessellator can either
forward the slice of attributes from a provided AttributeStore
when possible or
generate the values via linear interpolation.
To use this feature, make sure to use FillTessellator::tessellate_path
or
FillTessellator::tessellate_with_ids
instead of FillTessellator::tessellate
.
Attributes are lazily computed when calling FillVertex::interpolated_attributes
.
In other words they don’t add overhead when not used, however it is best to avoid calling
interpolated_attributes several times per vertex.
Examples
// Create a simple path.
let mut path_builder = Path::builder();
path_builder.begin(point(0.0, 0.0));
path_builder.line_to(point(1.0, 2.0));
path_builder.line_to(point(2.0, 0.0));
path_builder.line_to(point(1.0, 1.0));
path_builder.end(true);
let path = path_builder.build();
// Create the destination vertex and index buffers.
let mut buffers: VertexBuffers<Point, u16> = VertexBuffers::new();
{
let mut vertex_builder = simple_builder(&mut buffers);
// Create the tessellator.
let mut tessellator = FillTessellator::new();
// Compute the tessellation.
let result = tessellator.tessellate_path(
&path,
&FillOptions::default(),
&mut vertex_builder
);
assert!(result.is_ok());
}
println!("The generated vertices are: {:?}.", &buffers.vertices[..]);
println!("The generated indices are: {:?}.", &buffers.indices[..]);
// Create a path with three custom endpoint attributes.
let mut path_builder = Path::builder_with_attributes(3);
path_builder.begin(point(0.0, 0.0), &[0.0, 0.1, 0.5]);
path_builder.line_to(point(1.0, 2.0), &[1.0, 1.0, 0.1]);
path_builder.line_to(point(2.0, 0.0), &[1.0, 0.0, 0.8]);
path_builder.line_to(point(1.0, 1.0), &[0.1, 0.3, 0.5]);
path_builder.end(true);
let path = path_builder.build();
struct MyVertex {
x: f32, y: f32,
r: f32, g: f32, b: f32, a: f32,
}
// A custom vertex constructor, see the geometry_builder module.
struct Ctor;
impl FillVertexConstructor<MyVertex> for Ctor {
fn new_vertex(&mut self, mut vertex: FillVertex) -> MyVertex {
let position = vertex.position();
let attrs = vertex.interpolated_attributes();
MyVertex {
x: position.x,
y: position.y,
r: attrs[0],
g: attrs[1],
b: attrs[2],
a: 1.0,
}
}
}
// Create the destination vertex and index buffers.
let mut buffers: VertexBuffers<MyVertex, u16> = VertexBuffers::new();
{
// We use our custom vertex constructor here.
let mut vertex_builder = BuffersBuilder::new(&mut buffers, Ctor);
// Create the tessellator.
let mut tessellator = FillTessellator::new();
// Compute the tessellation. Here we use tessellate_with_ids
// which has a slightly more complicated interface. The provides
// the iterator as well as storage for positions and attributes at
// the same time.
let result = tessellator.tessellate_with_ids(
path.id_iter(), // Iterator over ids in the path
&path, // PositionStore
Some(&path), // AttributeStore
&FillOptions::default(),
&mut vertex_builder
);
assert!(result.is_ok());
}
Implementations§
source§impl FillTessellator
impl FillTessellator
sourcepub fn tessellate(
&mut self,
path: impl IntoIterator<Item = PathEvent>,
options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate( &mut self, path: impl IntoIterator<Item = PathEvent>, options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Compute the tessellation from a path iterator.
sourcepub fn tessellate_with_ids(
&mut self,
path: impl IntoIterator<Item = IdEvent>,
positions: &impl PositionStore,
custom_attributes: Option<&dyn AttributeStore>,
options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_with_ids( &mut self, path: impl IntoIterator<Item = IdEvent>, positions: &impl PositionStore, custom_attributes: Option<&dyn AttributeStore>, options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Compute the tessellation using an iterator over endpoint and control point ids, storage for the positions and, optionally, storage for custom endpoint attributes.
sourcepub fn tessellate_path<'l>(
&'l mut self,
path: impl Into<PathSlice<'l>>,
options: &'l FillOptions,
builder: &'l mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_path<'l>( &'l mut self, path: impl Into<PathSlice<'l>>, options: &'l FillOptions, builder: &'l mut dyn FillGeometryBuilder ) -> TessellationResult
Compute the tessellation from a path slice.
The tessellator will internally only track vertex sources and interpolated attributes if the path has interpolated attributes.
sourcepub fn tessellate_polygon(
&mut self,
polygon: Polygon<'_, Point>,
options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_polygon( &mut self, polygon: Polygon<'_, Point>, options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Tessellate a Polygon
.
sourcepub fn tessellate_rectangle(
&mut self,
rect: &Rect,
_options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_rectangle( &mut self, rect: &Rect, _options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Tessellate an axis-aligned rectangle.
sourcepub fn tessellate_circle(
&mut self,
center: Point,
radius: f32,
options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_circle( &mut self, center: Point, radius: f32, options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Tessellate a circle.
sourcepub fn tessellate_ellipse(
&mut self,
center: Point,
radii: Vector,
x_rotation: Angle,
winding: Winding,
options: &FillOptions,
output: &mut dyn FillGeometryBuilder
) -> TessellationResult
pub fn tessellate_ellipse( &mut self, center: Point, radii: Vector, x_rotation: Angle, winding: Winding, options: &FillOptions, output: &mut dyn FillGeometryBuilder ) -> TessellationResult
Tessellate an ellipse.
sourcepub fn builder<'l>(
&'l mut self,
options: &'l FillOptions,
output: &'l mut dyn FillGeometryBuilder
) -> FillBuilder<'l>
pub fn builder<'l>( &'l mut self, options: &'l FillOptions, output: &'l mut dyn FillGeometryBuilder ) -> FillBuilder<'l>
Tessellate directly from a sequence of PathBuilder
commands, without
creating an intermediate path data structure.
The returned builder implements the lyon_path::traits::PathBuilder
trait,
is compatible with the all PathBuilder
adapters.
It also has all requirements documented in PathBuilder
(All sub-paths must be
wrapped in a begin
/end
pair).
Example
use lyon_tessellation::{FillTessellator, FillOptions};
use lyon_tessellation::geometry_builder::{simple_builder, VertexBuffers};
use lyon_tessellation::path::traits::*;
use lyon_tessellation::math::{Point, point};
let mut buffers: VertexBuffers<Point, u16> = VertexBuffers::new();
let mut vertex_builder = simple_builder(&mut buffers);
let mut tessellator = FillTessellator::new();
let options = FillOptions::default();
// Create a temporary builder (borrows the tessellator).
let mut builder = tessellator.builder(&options, &mut vertex_builder);
// Build the path directly in the tessellator, skipping an intermediate data
// structure.
builder.begin(point(0.0, 0.0));
builder.line_to(point(10.0, 0.0));
builder.line_to(point(10.0, 10.0));
builder.line_to(point(0.0, 10.0));
builder.end(true);
// Finish the tessellation and get the result.
let result = builder.build();
sourcepub fn set_logging(&mut self, is_enabled: bool)
pub fn set_logging(&mut self, is_enabled: bool)
Enable/disable some verbose logging during the tessellation, for debugging purposes.