1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
#![doc(html_logo_url = "https://nical.github.io/lyon-doc/lyon-logo.svg")] #![deny(bare_trait_objects)] //! Alternative fill tessellation implementation using //! [libtess2](https://github.com/memononen/libtess2). //! //! # Lyon libtess2 wrapper //! //! This crate provides an alternative path fill tessellator implemented //! as a wrapper of the [libtess2](https://github.com/memononen/libtess2) //! C library. //! //! The goal of this crate is to provide an alternative tessellator for //! the potential cases where lyon_tessellation::FillTessellator is lacking //! in features or robustness, and have something to compare the latter //! against. //! //! ## Comparison with [lyon_tessellation::FillTessellator](https://docs.rs/lyon_tessellation/) //! //! Advantages: //! //! - Supports the `NonZero` fill rule. //! - More robust against precision errors when paths have many self //! intersections very close to each other. //! //! Disadvantages: //! //! - About twice slower than lyon_tessellation's fill tessellator. //! - Does not support computing vertex normals. //! - Wrapper around a C library (as opposed to pure rust with no //! unsafe code). //! //! ## API //! //! In order to avoid any overhead, this crate introduces the //! FlattenedPath type which stores already-flattened paths //! in the memory layout expected by libtess2. //! Instead of working with a `GeometryBuilder` like the tessellators //! in `lyon_tessellation`, this tessellator uses a `GeometryReceiver` //! trait that corresponds to the way libtess2 exposes its output. //! //! ## Example //! //! ``` //! extern crate lyon_tess2 as tess2; //! use tess2::{FillTessellator, FillOptions}; //! use tess2::math::{Point, point}; //! use tess2::path::Path; //! use tess2::path::builder::*; //! use tess2::geometry_builder::*; //! //! fn main() { //! // 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(); //! //! { //! // Create the tessellator. //! let mut tessellator = FillTessellator::new(); //! //! // Compute the tessellation. //! let result = tessellator.tessellate( //! &path, //! &FillOptions::default(), //! &mut BuffersBuilder::new(&mut buffers, Positions) //! ); //! assert!(result.is_ok()); //! } //! println!("The generated vertices are: {:?}.", &buffers.vertices[..]); //! println!("The generated indices are: {:?}.", &buffers.indices[..]); //! //! } //! ``` pub extern crate lyon_tessellation as tessellation; pub extern crate tess2_sys; pub use tessellation::geom; pub use tessellation::math; pub use tessellation::path; pub mod flattened_path; mod tessellator; pub use crate::tessellation::FillOptions; pub use crate::tessellator::FillTessellator; pub mod geometry_builder { pub use crate::tessellation::geometry_builder::{Positions, NoOutput, VertexBuffers}; pub use crate::tessellation::VertexId; use crate::math::Point; /// An interface with similar goals to `GeometryBuilder` for algorithms that pre-build /// the vertex and index buffers. /// /// This is primarily intended for efficient interaction with the libtess2 tessellator /// from the `lyon_tess2` crate. pub trait GeometryReceiver { fn set_geometry(&mut self, vertices: &[Point], indices: &[u32]); } /// A trait specifying how to create vertex values. pub trait BasicVertexConstructor<OutputVertex> { fn new_vertex(&mut self, point: Point) -> OutputVertex; } impl BasicVertexConstructor<Point> for Positions { fn new_vertex(&mut self, position: Point) -> Point { position } } impl<F, OutputVertex> BasicVertexConstructor<OutputVertex> for F where F: Fn(Point) -> OutputVertex, { fn new_vertex(&mut self, position: Point) -> OutputVertex { self(position) } } pub struct BuffersBuilder<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor> { buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>, vertex_constructor: Ctor, } impl<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor> BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor> { pub fn new(buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>, ctor: Ctor) -> Self { BuffersBuilder { buffers, vertex_constructor: ctor, } } pub fn buffers<'a, 'b: 'a>(&'b self) -> &'a VertexBuffers<OutputVertex, OutputIndex> { self.buffers } } impl<'l, OutputVertex, OutputIndex, Ctor> GeometryReceiver for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor> where OutputIndex: From<VertexId>, Ctor: BasicVertexConstructor<OutputVertex>, { fn set_geometry(&mut self, vertices: &[Point], indices: &[u32]) { for v in vertices { let vertex = self.vertex_constructor.new_vertex(*v); self.buffers.vertices.push(vertex); } for idx in indices { self.buffers.indices.push(OutputIndex::from((*idx).into())); } } } impl GeometryReceiver for NoOutput { fn set_geometry(&mut self, _vertices: &[Point], _indices: &[u32]) {} } }