Skip to content

Eliminate internal vertices with FillRule::NonZero #871

@torokati44

Description

@torokati44

Given the following example:

use lyon::math::{point, Point};
use lyon::path::Path;
use lyon::tessellation::*;

fn main() {
    let mut tessellator = FillTessellator::new();

    {
        let mut builder = Path::builder();
        builder.begin(point(0.0, 0.0));
        builder.line_to(point(100.0, 0.0));
        builder.line_to(point(100.0, 100.0));
        builder.line_to(point(20.0, 100.0));
        builder.line_to(point(20.0, 20.0));
        builder.line_to(point(80.0, 20.0));
        builder.line_to(point(80.0, 80.0));
        builder.line_to(point(0.0, 80.0));
        builder.close();

        fun_name(&mut tessellator, builder.build());
    }

    {
        let mut builder = Path::builder();
        builder.begin(point(0.0, 0.0));
        builder.line_to(point(100.0, 0.0));
        builder.line_to(point(100.0, 100.0));
        builder.line_to(point(20.0, 100.0));
        builder.line_to(point(20.0, 80.0));
        builder.line_to(point(0.0, 80.0));
        builder.close();

        fun_name(&mut tessellator, builder.build());
    }
}

fn fun_name(tessellator: &mut FillTessellator, path: Path) {
    let mut geometry: VertexBuffers<Point, u16> = VertexBuffers::new();

    tessellator
        .tessellate_path(
            &path,
            &FillOptions::default().with_fill_rule(FillRule::NonZero),
            &mut BuffersBuilder::new(&mut geometry, |vertex: FillVertex| vertex.position()),
        )
        .unwrap();

    println!(
        " -- {} vertices {} indices",
        geometry.vertices.len(),
        geometry.indices.len()
    );

    for tri in geometry.indices.chunks(3) {
        println!(
            "{:?} - {:?} - {:?}",
            geometry.vertices[tri[0] as usize],
            geometry.vertices[tri[1] as usize],
            geometry.vertices[tri[2] as usize],
        );
    }
}

The output is:

 -- 9 vertices 30 indices
(100.0, 0.0) - (0.0, 0.0) - (20.0, 20.0)
(20.0, 20.0) - (0.0, 0.0) - (0.0, 80.0)
(20.0, 20.0) - (0.0, 80.0) - (20.0, 80.0)
(80.0, 20.0) - (20.0, 20.0) - (20.0, 80.0)
(80.0, 20.0) - (20.0, 80.0) - (80.0, 80.0)
(80.0, 80.0) - (20.0, 80.0) - (20.0, 100.0)
(100.0, 0.0) - (20.0, 20.0) - (80.0, 20.0)
(100.0, 0.0) - (80.0, 20.0) - (80.0, 80.0)
(100.0, 0.0) - (80.0, 80.0) - (100.0, 100.0)
(80.0, 80.0) - (20.0, 100.0) - (100.0, 100.0)
 -- 6 vertices 12 indices
(100.0, 0.0) - (0.0, 0.0) - (0.0, 80.0)
(100.0, 0.0) - (0.0, 80.0) - (20.0, 80.0)
(100.0, 0.0) - (20.0, 80.0) - (20.0, 100.0)
(100.0, 0.0) - (20.0, 100.0) - (100.0, 100.0)

The tessellations look like this:

path1

path2

I would expect the first, self-intersecting one, to be comparable to the second one, where only the outline is in the path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions