lyon
lyon copied to clipboard
Eliminate internal vertices with `FillRule::NonZero`
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:
I would expect the first, self-intersecting one, to be comparable to the second one, where only the outline is in the path.
Yep, that's sort of by design, or more precisely a byproduct of the way the algorithm works. Changing this would be a pretty major project which I don't have the time to embark on. I don't expect this to change unless you or someone else feels adventurous and implements a different behavior.