logo
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

Constructor.

Compute the tessellation from a path iterator.

Compute the tessellation using an iterator over endpoint and control point ids, storage for the positions and, optionally, storage for custom endpoint attributes.

Compute the tessellation from a path slice.

The tessellator will internally only track vertex sources and interpolated attributes if the path has interpolated attributes.

Tessellate a Polygon.

Tessellate an axis-aligned rectangle.

Tessellate a circle.

Tessellate an ellipse.

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::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();

Tessellate directly from a sequence of PathBuilder commands, without creating an intermediate path data structure.

Similar to FillTessellator::builder with custom attributes.

Enable/disable some verbose logging during the tessellation, for debugging purposes.

Trait Implementations

Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.