Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions geo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ robust = "1.1.0"
rstar = "0.12.0"
serde = { version = "1.0", optional = true, features = ["derive"] }
i_overlay = { version = "2.0.0, < 2.1.0", default-features = false }
geo-traits = ">=0.3.0"

[dev-dependencies]
approx = ">= 0.4.0, < 0.6.0"
Expand Down
32 changes: 19 additions & 13 deletions geo/src/algorithm/kernels/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use num_traits::Zero;
use std::cmp::Ordering;

use crate::{coord, Coord, CoordNum};
use crate::CoordNum;
use geo_traits::CoordTrait;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum Orientation {
Expand All @@ -24,11 +25,14 @@ impl Orientation {

/// Kernel trait to provide predicates to operate on
/// different scalar types.
pub trait Kernel<T: CoordNum> {
pub trait Kernel<T: CoordTrait>
where
T::T: CoordNum,
{
/// Gives the orientation of 3 2-dimensional points:
/// ccw, cw or collinear (None)
fn orient2d(p: Coord<T>, q: Coord<T>, r: Coord<T>) -> Orientation {
let res = (q.x - p.x) * (r.y - q.y) - (q.y - p.y) * (r.x - q.x);
fn orient2d(p: T, q: T, r: T) -> Orientation {
let res = (q.x() - p.x()) * (r.y() - q.y()) - (q.y() - p.y()) * (r.x() - q.x());
if res > Zero::zero() {
Orientation::CounterClockwise
} else if res < Zero::zero() {
Expand All @@ -38,21 +42,23 @@ pub trait Kernel<T: CoordNum> {
}
}

fn square_euclidean_distance(p: Coord<T>, q: Coord<T>) -> T {
(p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y)
fn square_euclidean_distance(p: T, q: T) -> T::T {
(p.x() - q.x()) * (p.x() - q.x()) + (p.y() - q.y()) * (p.y() - q.y())
}

/// Compute the sign of the dot product of `u` and `v` using
/// robust predicates. The output is `CounterClockwise` if
/// the sign is positive, `Clockwise` if negative, and
/// `Collinear` if zero.
fn dot_product_sign(u: Coord<T>, v: Coord<T>) -> Orientation {
let zero = Coord::zero();
let vdash = coord! {
x: T::zero() - v.y,
y: v.x,
};
Self::orient2d(zero, u, vdash)
fn dot_product_sign(u: T, v: T) -> Orientation {
let dot_product = u.x() * v.x() + u.y() * v.y();
if dot_product > T::T::zero() {
Orientation::CounterClockwise
} else if dot_product < T::T::zero() {
Orientation::Clockwise
} else {
Orientation::Collinear
}
}
}

Expand Down
21 changes: 11 additions & 10 deletions geo/src/algorithm/kernels/robust.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{CoordNum, Kernel, Orientation};
use crate::Coord;
use geo_traits::CoordTrait;

use num_traits::{Float, NumCast};

Expand All @@ -11,25 +11,26 @@ use num_traits::{Float, NumCast};
#[derive(Default, Debug)]
pub struct RobustKernel;

impl<T> Kernel<T> for RobustKernel
impl<P> Kernel<P> for RobustKernel
where
T: CoordNum + Float,
P: CoordTrait,
P::T: CoordNum + Float,
{
fn orient2d(p: Coord<T>, q: Coord<T>, r: Coord<T>) -> Orientation {
fn orient2d(p: P, q: P, r: P) -> Orientation {
use robust::{orient2d, Coord};

let orientation = orient2d(
Coord {
x: <f64 as NumCast>::from(p.x).unwrap(),
y: <f64 as NumCast>::from(p.y).unwrap(),
x: <f64 as NumCast>::from(p.x()).unwrap(),
y: <f64 as NumCast>::from(p.y()).unwrap(),
Comment on lines -23 to +25
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the .unwrap()s make me sweat but I didn't do it first!

},
Coord {
x: <f64 as NumCast>::from(q.x).unwrap(),
y: <f64 as NumCast>::from(q.y).unwrap(),
x: <f64 as NumCast>::from(q.x()).unwrap(),
y: <f64 as NumCast>::from(q.y()).unwrap(),
},
Coord {
x: <f64 as NumCast>::from(r.x).unwrap(),
y: <f64 as NumCast>::from(r.y).unwrap(),
x: <f64 as NumCast>::from(r.x()).unwrap(),
y: <f64 as NumCast>::from(r.y()).unwrap(),
},
);

Expand Down
8 changes: 7 additions & 1 deletion geo/src/algorithm/kernels/simple.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use super::Kernel;
use crate::CoordNum;
use geo_traits::CoordTrait;

/// Simple kernel provides the direct implementation of the
/// predicates. These are meant to be used with exact
/// arithmetic signed types (eg. i32, i64).
#[derive(Default, Debug)]
pub struct SimpleKernel;

impl<T: CoordNum> Kernel<T> for SimpleKernel {}
impl<T> Kernel<T> for SimpleKernel
where
T: CoordTrait,
T::T: CoordNum,
{
}
15 changes: 6 additions & 9 deletions geo/src/algorithm/old_sweep/line_or_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,10 @@ mod tests {
use geo_types::{Coord, LineString};
use wkt::ToWkt;

use crate::{GeoFloat, GeoNum, Kernel};
use crate::{
kernels::{RobustKernel, SimpleKernel},
GeoFloat, GeoNum, Kernel,
};

use super::LineOrPoint;

Expand Down Expand Up @@ -385,13 +388,7 @@ mod tests {
eprintln!("l1: {}", l87.to_wkt());
eprintln!("lo: {}", lo.to_wkt());

eprintln!(
"pred: {:?}",
<f64 as GeoNum>::Ker::orient2d(pt_8, pt_7, pt_17)
);
eprintln!(
"pred: {:?}",
<f64 as GeoNum>::Ker::orient2d(pt_8, pt_14, pt_16)
);
eprintln!("pred: {:?}", SimpleKernel::orient2d(pt_8, pt_7, pt_17));
eprintln!("pred: {:?}", RobustKernel::orient2d(pt_8, pt_14, pt_16));
}
}
6 changes: 3 additions & 3 deletions geo/src/algorithm/winding_order.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::kernels::*;
use crate::coords_iter::CoordsIter;
use crate::utils::EitherIter;
use crate::{CoordNum, GeoFloat, GeoNum, LineString, Point};
use crate::{Coord, CoordNum, GeoFloat, GeoNum, LineString, Point};
use geo_types::{PointsIter, Triangle};
use std::iter::Rev;

Expand Down Expand Up @@ -117,8 +117,8 @@ pub trait Winding {

impl<T, K> Winding for LineString<T>
where
T: GeoNum<Ker = K>,
K: Kernel<T>,
T: GeoNum<Ker<Coord<T>> = K>,
K: Kernel<Coord<T>>,
{
type Scalar = T;

Expand Down
7 changes: 4 additions & 3 deletions geo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ use std::cmp::Ordering;

pub use crate::algorithm::sweep::Intersections;
pub use crate::relate::PreparedGeometry;
use geo_traits::CoordTrait;
pub use geo_types::{coord, line_string, point, polygon, wkt, CoordFloat, CoordNum};

pub mod geometry;
Expand Down Expand Up @@ -345,7 +346,7 @@ impl<T> GeoFloat for T where

/// A trait for methods which work for both integers **and** floating point
pub trait GeoNum: CoordNum {
type Ker: Kernel<Self>;
type Ker<C: CoordTrait<T = Self>>: Kernel<C>;

/// Return the ordering between self and other.
///
Expand All @@ -361,7 +362,7 @@ pub trait GeoNum: CoordNum {
macro_rules! impl_geo_num_for_float {
($t: ident) => {
impl GeoNum for $t {
type Ker = RobustKernel;
type Ker<C: CoordTrait<T = Self>> = RobustKernel;
fn total_cmp(&self, other: &Self) -> Ordering {
self.total_cmp(other)
}
Expand All @@ -371,7 +372,7 @@ macro_rules! impl_geo_num_for_float {
macro_rules! impl_geo_num_for_int {
($t: ident) => {
impl GeoNum for $t {
type Ker = SimpleKernel;
type Ker<C: CoordTrait<T = Self>> = SimpleKernel;
fn total_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
Expand Down