geo_bevy/
lib.rs

1use bevy::prelude::{info_span, Mesh};
2use build_mesh::BuildMesh;
3use geo_traits::*;
4use line_string::LineStringMeshBuilder;
5use polygon::PolygonMeshBuilder;
6use std::iter;
7
8pub use point::SpritePosition;
9pub use polygon::PolygonMesh;
10
11mod build_mesh;
12mod line_string;
13mod point;
14mod polygon;
15
16pub fn line_to_mesh(line: impl LineTrait) -> Result<Mesh, Error> {
17    let mut mesh_builder = LineStringMeshBuilder::new();
18    mesh_builder.add_coords(iter::once(line.start()).chain(iter::once(line.end())))?;
19    mesh_builder.try_into()
20}
21
22pub fn line_string_to_mesh(line_string: impl LineStringTrait) -> Result<Mesh, Error> {
23    let mut mesh_builder = LineStringMeshBuilder::new();
24    mesh_builder.add_coords(line_string.coords())?;
25    mesh_builder.try_into()
26}
27
28pub fn multi_line_string_to_mesh(
29    multi_line_string: impl MultiLineStringTrait,
30) -> Result<Vec<Mesh>, Error> {
31    let mut line_string_meshes = Vec::with_capacity(multi_line_string.num_line_strings());
32
33    for line_string in multi_line_string.line_strings() {
34        line_string_meshes.push(line_string_to_mesh(line_string)?);
35    }
36
37    Ok(line_string_meshes)
38}
39
40pub fn polygon_to_mesh<Scalar: geo_types::CoordFloat>(
41    polygon: impl PolygonTrait<T = Scalar>,
42) -> Result<PolygonMesh, Error> {
43    let mut mesh_builder = PolygonMeshBuilder::new();
44    mesh_builder.add_polygon(&polygon)?;
45    mesh_builder.try_into()
46}
47
48pub fn multi_polygon_to_mesh<Scalar: geo_types::CoordFloat>(
49    multi_polygon: impl MultiPolygonTrait<T = Scalar>,
50) -> Result<Vec<PolygonMesh>, Error> {
51    let polygons = multi_polygon.polygons();
52    let mut polygon_meshes = Vec::with_capacity(polygons.len());
53    for polygon in polygons {
54        polygon_meshes.push(polygon_to_mesh(polygon)?);
55    }
56
57    Ok(polygon_meshes)
58}
59
60pub fn rect_to_mesh<Scalar: geo_types::CoordFloat>(
61    rect: impl RectTrait<T = Scalar>,
62) -> Result<PolygonMesh, Error> {
63    let mut mesh_builder = PolygonMeshBuilder::default();
64    mesh_builder.add_polygon_from_exterior_coords(
65        [
66            (rect.min().x(), rect.min().y()),
67            (rect.min().x(), rect.max().y()),
68            (rect.max().x(), rect.max().y()),
69            (rect.max().x(), rect.min().y()),
70            (rect.min().x(), rect.min().y()),
71        ]
72        .into_iter(),
73    )?;
74    PolygonMesh::try_from(mesh_builder)
75}
76
77pub fn triangle_to_mesh<Scalar: geo_types::CoordFloat>(
78    triangle: impl TriangleTrait<T = Scalar>,
79) -> Result<PolygonMesh, Error> {
80    let mut mesh_builder = PolygonMeshBuilder::default();
81    mesh_builder.add_polygon_from_exterior_coords(
82        [
83            (triangle.first().x(), triangle.first().y()),
84            (triangle.second().x(), triangle.second().y()),
85            (triangle.third().x(), triangle.third().y()),
86            (triangle.first().x(), triangle.first().y()),
87        ]
88        .into_iter(),
89    )?;
90    PolygonMesh::try_from(mesh_builder)
91}
92
93pub fn geometry_to_mesh<Scalar: geo_types::CoordFloat>(
94    geometry: impl GeometryTrait<T = Scalar>,
95) -> Result<GeometryMesh, Error> {
96    let mut ctx = build_mesh::BuildBevyMeshesContext::default();
97
98    info_span!("Populating Bevy mesh builder")
99        .in_scope(|| build_mesh::populate_geometry_mesh_builders(&geometry, &mut ctx))?;
100
101    info_span!("Building Bevy meshes").in_scope(|| {
102        [
103            ctx.point_mesh_builder.build(),
104            ctx.line_string_mesh_builder.build(),
105            ctx.polygon_mesh_builder.build(),
106        ]
107        .into_iter()
108        .find(|prepared_mesh| prepared_mesh.is_ok())
109        .unwrap_or(Err(Error::CouldNotBuildMesh))
110    })
111}
112
113pub enum GeometryMesh {
114    Point(Vec<SpritePosition>),
115    LineString(Mesh),
116    Polygon(polygon::PolygonMesh),
117}
118
119#[derive(Debug)]
120pub enum Error {
121    CouldNotBuildMesh,
122    CouldNotConvertToF32,
123    EmptyGeometry,
124    BevyEarcutr(bevy_earcutr::Error),
125}