Skip to content

Commit

Permalink
Merge pull request #9 from gibbz00/specific_geometries
Browse files Browse the repository at this point in the history
Prepare a mesh for a given geometry.
  • Loading branch information
frewsxcv authored Jul 1, 2023
2 parents 09a3bec + fa1f58a commit d163547
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 166 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ license = "MIT OR Apache-2.0"
bevy-earcutr = "0.9"
bevy = { version = "0.10", default-features = false, features = ["bevy_render"] }
geo = "0.25"
geo-types = "0.7"
143 changes: 143 additions & 0 deletions src/build_mesh.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use geo_types::*;
use std::num::TryFromIntError;

pub trait BuildMesh {
fn build(self) -> Option<crate::GeometryMesh>;
}

#[derive(Default)]
pub struct BuildBevyMeshesContext {
pub point_mesh_builder: crate::point::PointMeshBuilder,
pub line_string_mesh_builder: crate::line_string::LineStringMeshBuilder,
pub polygon_mesh_builder: crate::polygon::PolygonMeshBuilder,
}

pub trait BuildBevyMeshes {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError>;
}

impl BuildBevyMeshes for Point {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.point_mesh_builder.add_point(self)
}
}

impl BuildBevyMeshes for LineString {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.line_string_mesh_builder.add_line_string(self)
}
}

impl BuildBevyMeshes for Polygon {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.polygon_mesh_builder.add_polygon(self)
}
}

impl BuildBevyMeshes for MultiPoint {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for point in &self.0 {
point.populate_mesh_builders(ctx)?;
}
Ok(())
}
}

impl BuildBevyMeshes for MultiLineString {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for line_string in &self.0 {
line_string.populate_mesh_builders(ctx)?;
}
Ok(())
}
}

impl BuildBevyMeshes for MultiPolygon {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for polygon in &self.0 {
polygon.populate_mesh_builders(ctx)?;
}
Ok(())
}
}

impl BuildBevyMeshes for Line {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
LineString::from(self).populate_mesh_builders(ctx)
}
}

impl BuildBevyMeshes for Triangle {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
self.to_polygon().populate_mesh_builders(ctx)
}
}

impl BuildBevyMeshes for Rect {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
self.to_polygon().populate_mesh_builders(ctx)
}
}

impl BuildBevyMeshes for Geometry {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
match self {
Geometry::Point(g) => g.populate_mesh_builders(ctx)?,
Geometry::Line(g) => g.populate_mesh_builders(ctx)?,
Geometry::LineString(g) => g.populate_mesh_builders(ctx)?,
Geometry::Polygon(g) => g.populate_mesh_builders(ctx)?,
Geometry::MultiPoint(g) => g.populate_mesh_builders(ctx)?,
Geometry::MultiLineString(g) => g.populate_mesh_builders(ctx)?,
Geometry::MultiPolygon(g) => g.populate_mesh_builders(ctx)?,
Geometry::GeometryCollection(g) => g.populate_mesh_builders(ctx)?,
Geometry::Triangle(g) => g.populate_mesh_builders(ctx)?,
Geometry::Rect(g) => g.populate_mesh_builders(ctx)?,
};
Ok(())
}
}

impl BuildBevyMeshes for GeometryCollection {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for g in self {
g.populate_mesh_builders(ctx)?;
}
Ok(())
}
}
214 changes: 70 additions & 144 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,177 +1,103 @@
use bevy::prelude::*;
use bevy::prelude::{info_span, Mesh};
use build_mesh::{BuildBevyMeshes, BuildMesh};
use geo_types::geometry::*;
use line_string::LineStringMeshBuilder;
use polygon::PolygonMeshBuilder;
use std::num::TryFromIntError;

pub use polygon::PolygonMesh;

mod build_mesh;
mod line_string;
mod point;
mod polygon;

pub enum PreparedMesh {
Point(Vec<geo::Point>),
LineString {
mesh: Mesh,
},
Polygon {
polygon_mesh: Mesh,
exterior_mesh: Mesh,
interior_meshes: Vec<Mesh>,
},
}

trait BuildMesh {
fn build(self) -> Option<PreparedMesh>;
pub fn line_to_mesh(line: &Line) -> Result<Option<Mesh>, TryFromIntError> {
line_string_to_mesh(&line.into())
}

#[derive(Default)]
pub struct BuildBevyMeshesContext {
point_mesh_builder: point::PointMeshBuilder,
line_string_mesh_builder: line_string::LineStringMeshBuilder,
polygon_mesh_builder: polygon::PolygonMeshBuilder,
pub fn line_string_to_mesh(line_string: &LineString) -> Result<Option<Mesh>, TryFromIntError> {
let mut mesh_builder = LineStringMeshBuilder::default();
mesh_builder.add_line_string(line_string)?;
Ok(mesh_builder.into())
}

pub fn build_bevy_meshes<G: BuildBevyMeshes>(
geo: &G,
) -> Result<impl Iterator<Item = PreparedMesh>, TryFromIntError> {
let mut ctx = BuildBevyMeshesContext::default();
pub fn multi_line_string_to_mesh(
multi_line_string: &MultiLineString,
) -> Result<Vec<Mesh>, TryFromIntError> {
let line_strings = &multi_line_string.0;
let mut line_string_meshes = Vec::with_capacity(line_strings.len());

info_span!("Populating Bevy mesh builder").in_scope(|| geo.populate_mesh_builders(&mut ctx))?;

info_span!("Building Bevy meshes").in_scope(|| {
Ok([
ctx.point_mesh_builder.build(),
ctx.line_string_mesh_builder.build(),
ctx.polygon_mesh_builder.build(),
]
.into_iter()
.flatten())
})
}

pub trait BuildBevyMeshes {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError>;
}

impl BuildBevyMeshes for geo::Point {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.point_mesh_builder.add_point(self)
for line_string in line_strings {
if let Some(line_string_mesh) = line_string_to_mesh(line_string)? {
line_string_meshes.push(line_string_mesh);
}
}
}

impl BuildBevyMeshes for geo::LineString {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.line_string_mesh_builder.add_line_string(self)
}
Ok(line_string_meshes)
}

impl BuildBevyMeshes for geo::Polygon {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
ctx.polygon_mesh_builder.add_polygon_components(self)
}
pub fn polygon_to_mesh(polygon: &Polygon) -> Result<Option<PolygonMesh>, TryFromIntError> {
let mut mesh_builder = PolygonMeshBuilder::default();
mesh_builder.add_polygon(polygon)?;
Ok(mesh_builder.into())
}

impl BuildBevyMeshes for geo::MultiPoint {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for point in &self.0 {
point.populate_mesh_builders(ctx)?;
pub fn multi_polygon_to_mesh(
multi_polygon: &MultiPolygon,
) -> Result<Vec<PolygonMesh>, TryFromIntError> {
let polygons = &multi_polygon.0;
let mut polygon_meshes = Vec::with_capacity(polygons.len());
for polygon in polygons {
if let Some(polygon_mesh) = polygon_to_mesh(polygon)? {
polygon_meshes.push(polygon_mesh);
}
Ok(())
}
}

impl BuildBevyMeshes for geo::MultiLineString {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for line_string in &self.0 {
line_string.populate_mesh_builders(ctx)?;
}
Ok(())
}
Ok(polygon_meshes)
}

impl BuildBevyMeshes for geo::MultiPolygon {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for polygon in &self.0 {
polygon.populate_mesh_builders(ctx)?;
}
Ok(())
}
pub fn rect_to_mesh(rect: &Rect) -> Result<Option<PolygonMesh>, TryFromIntError> {
polygon_to_mesh(&rect.to_polygon())
}

impl BuildBevyMeshes for geo::Line {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
geo::LineString::new(vec![self.start, self.end]).populate_mesh_builders(ctx)
}
pub fn triangle_to_mesh(triangle: &Triangle) -> Result<Option<PolygonMesh>, TryFromIntError> {
polygon_to_mesh(&triangle.to_polygon())
}

impl BuildBevyMeshes for geo::Triangle {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
self.to_polygon().populate_mesh_builders(ctx)
}
}
pub fn geometry_to_mesh(geometry: &Geometry) -> Result<Option<GeometryMesh>, TryFromIntError> {
let mut ctx = build_mesh::BuildBevyMeshesContext::default();

impl BuildBevyMeshes for geo::Rect {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
self.to_polygon().populate_mesh_builders(ctx)
}
}
info_span!("Populating Bevy mesh builder")
.in_scope(|| geometry.populate_mesh_builders(&mut ctx))?;

impl BuildBevyMeshes for geo::Geometry {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
match self {
geo::Geometry::Point(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::Line(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::LineString(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::Polygon(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::MultiPoint(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::MultiLineString(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::MultiPolygon(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::GeometryCollection(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::Triangle(g) => g.populate_mesh_builders(ctx)?,
geo::Geometry::Rect(g) => g.populate_mesh_builders(ctx)?,
};
Ok(())
}
info_span!("Building Bevy meshes").in_scope(|| {
Ok([
ctx.point_mesh_builder.build(),
ctx.line_string_mesh_builder.build(),
ctx.polygon_mesh_builder.build(),
]
.into_iter()
.find(|prepared_mesh| prepared_mesh.is_some())
.unwrap_or_default())
})
}

impl BuildBevyMeshes for geo::GeometryCollection {
fn populate_mesh_builders(
&self,
ctx: &mut BuildBevyMeshesContext,
) -> Result<(), TryFromIntError> {
for g in self {
g.populate_mesh_builders(ctx)?;
pub fn geometry_collection_to_mesh(
geometry_collection: &GeometryCollection,
) -> Result<Vec<GeometryMesh>, TryFromIntError> {
let mut geometry_meshes = Vec::with_capacity(geometry_collection.len());
for geometry in geometry_collection {
if let Some(geometry_mesh) = geometry_to_mesh(geometry)? {
geometry_meshes.push(geometry_mesh);
}
Ok(())
}

Ok(geometry_meshes)
}

pub enum GeometryMesh {
Point(Vec<Point>),
LineString(Mesh),
Polygon(polygon::PolygonMesh),
}
Loading

0 comments on commit d163547

Please sign in to comment.