-
-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Define Tessellation as an alternative to Polygon, and use it for rend…
…ering. #951 The goal is for every Polygon to consist of valid Rings, for a simpler API and better georust integration. Thanks to @michaelkirk for starting this!
- Loading branch information
1 parent
e9ed359
commit 1be8072
Showing
7 changed files
with
178 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
use crate::{Angle, Bounds, Polygon, Pt2D}; | ||
|
||
// Deliberately not serializable | ||
/// A tessellated polygon, ready for rendering. | ||
#[derive(Clone)] | ||
pub struct Tessellation { | ||
/// These points aren't in any meaningful order. It's not generally possible to reconstruct a | ||
/// `Polygon` from this. | ||
points: Vec<Pt2D>, | ||
/// Groups of three indices make up the triangles | ||
indices: Vec<u16>, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Triangle { | ||
pub pt1: Pt2D, | ||
pub pt2: Pt2D, | ||
pub pt3: Pt2D, | ||
} | ||
|
||
impl From<Polygon> for Tessellation { | ||
fn from(polygon: Polygon) -> Self { | ||
Self::new(polygon.points, polygon.indices) | ||
} | ||
} | ||
|
||
impl Tessellation { | ||
pub fn new(points: Vec<Pt2D>, indices: Vec<u16>) -> Self { | ||
Tessellation { points, indices } | ||
} | ||
|
||
/// Returns (points, indices) for rendering | ||
pub fn consume(self) -> (Vec<Pt2D>, Vec<u16>) { | ||
(self.points, self.indices) | ||
} | ||
|
||
pub fn triangles(&self) -> Vec<Triangle> { | ||
let mut triangles: Vec<Triangle> = Vec::new(); | ||
for slice in self.indices.chunks_exact(3) { | ||
triangles.push(Triangle { | ||
pt1: self.points[slice[0] as usize], | ||
pt2: self.points[slice[1] as usize], | ||
pt3: self.points[slice[2] as usize], | ||
}); | ||
} | ||
triangles | ||
} | ||
|
||
pub fn get_bounds(&self) -> Bounds { | ||
Bounds::from(&self.points) | ||
} | ||
|
||
fn center(&self) -> Pt2D { | ||
self.get_bounds().center() | ||
} | ||
|
||
fn transform<F: Fn(&Pt2D) -> Pt2D>(&mut self, f: F) { | ||
for pt in &mut self.points { | ||
*pt = f(pt); | ||
} | ||
} | ||
|
||
pub fn translate(&mut self, dx: f64, dy: f64) { | ||
self.transform(|pt| pt.offset(dx, dy)); | ||
} | ||
|
||
pub fn scale(&mut self, factor: f64) { | ||
self.transform(|pt| Pt2D::new(pt.x() * factor, pt.y() * factor)); | ||
} | ||
|
||
pub fn scale_xy(&mut self, x_factor: f64, y_factor: f64) { | ||
self.transform(|pt| Pt2D::new(pt.x() * x_factor, pt.y() * y_factor)) | ||
} | ||
|
||
pub fn rotate(&mut self, angle: Angle) { | ||
self.rotate_around(angle, self.center()) | ||
} | ||
|
||
pub fn rotate_around(&mut self, angle: Angle, pivot: Pt2D) { | ||
self.transform(|pt| { | ||
let origin_pt = Pt2D::new(pt.x() - pivot.x(), pt.y() - pivot.y()); | ||
let (sin, cos) = angle.normalized_radians().sin_cos(); | ||
Pt2D::new( | ||
pivot.x() + origin_pt.x() * cos - origin_pt.y() * sin, | ||
pivot.y() + origin_pt.y() * cos + origin_pt.x() * sin, | ||
) | ||
}) | ||
} | ||
|
||
/// Equivalent to `self.scale(scale).translate(translate_x, translate_y).rotate_around(rotate, | ||
/// pivot)`, but modifies the polygon in-place and is faster. | ||
pub fn inplace_multi_transform( | ||
&mut self, | ||
scale: f64, | ||
translate_x: f64, | ||
translate_y: f64, | ||
rotate: Angle, | ||
pivot: Pt2D, | ||
) { | ||
let (sin, cos) = rotate.normalized_radians().sin_cos(); | ||
|
||
for pt in &mut self.points { | ||
// Scale | ||
let x = scale * pt.x(); | ||
let y = scale * pt.y(); | ||
// Translate | ||
let x = x + translate_x; | ||
let y = y + translate_y; | ||
// Rotate | ||
let origin_pt = Pt2D::new(x - pivot.x(), y - pivot.y()); | ||
*pt = Pt2D::new( | ||
pivot.x() + origin_pt.x() * cos - origin_pt.y() * sin, | ||
pivot.y() + origin_pt.y() * cos + origin_pt.x() * sin, | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.