├── .gitignore
├── src
├── areas
│ ├── tests
│ │ ├── 1_intersection.svg
│ │ ├── 3_difference.svg
│ │ ├── 1_union.svg
│ │ ├── 2_intersection.svg
│ │ ├── 2_difference.svg
│ │ ├── 1_difference.svg
│ │ └── mod.rs
│ ├── debug.rs
│ └── mod.rs
├── convert_2d_3d.rs
├── angles.rs
├── rough_eq.rs
├── bbox.rs
├── lib.rs
├── band.rs
├── closed_line_path.rs
├── grid.rs
├── segment_grid.rs
├── util.rs
├── intersect.rs
├── embedding.rs
├── edit_arc_line_path.rs
├── arc_line_path.rs
├── line_path.rs
├── segments.rs
└── area_embedding.rs
├── Cargo.toml
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
7 | Cargo.lock
8 |
9 | # These are backup files generated by rustfmt
10 | **/*.rs.bk
11 |
--------------------------------------------------------------------------------
/src/areas/tests/1_intersection.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/areas/tests/3_difference.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/areas/tests/1_union.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/areas/tests/2_intersection.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/convert_2d_3d.rs:
--------------------------------------------------------------------------------
1 | use {V2, P2, V3, P3};
2 |
3 | pub trait Into2d {
4 | type Target;
5 | fn into_2d(self) -> Self::Target;
6 | }
7 |
8 | impl Into2d for V3 {
9 | type Target = V2;
10 | fn into_2d(self) -> V2 {
11 | V2::new(self.x, self.y)
12 | }
13 | }
14 |
15 | impl Into2d for P3 {
16 | type Target = P2;
17 | fn into_2d(self) -> P2 {
18 | P2::new(self.x, self.y)
19 | }
20 | }
21 |
22 | pub trait Into3d {
23 | type Target;
24 | fn into_3d(self) -> Self::Target;
25 | }
26 |
27 | impl Into3d for V2 {
28 | type Target = V3;
29 | fn into_3d(self) -> V3 {
30 | V3::new(self.x, self.y, 0.0)
31 | }
32 | }
33 |
34 | impl Into3d for P2 {
35 | type Target = P3;
36 | fn into_3d(self) -> P3 {
37 | P3::new(self.x, self.y, 0.0)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/areas/tests/2_difference.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "descartes"
3 | version = "0.1.20"
4 | description = "Imprecision-tolerant computational geometry for Rust"
5 | authors = ["Anselm Eickhoff "]
6 | repository = "https://github.com/aeickhoff/descartes"
7 | license = "MIT"
8 | [badges]
9 | maintenance = { status = "experimental" }
10 |
11 | [dependencies]
12 | nalgebra = "0.20"
13 | ordered-float = "0.5.0"
14 | itertools = "0.7.6"
15 | fnv = "1.0.6"
16 | serde = {version = "1", optional = true}
17 | serde_derive = {version = "1", optional = true}
18 | stable-vec = "0.3.1"
19 | smallvec = "0.6.5"
20 |
21 | [dependencies.compact]
22 | version = "0.2.9"
23 | optional = true
24 |
25 | [dependencies.compact_macros]
26 | version = "0.1.0"
27 | optional = true
28 |
29 | [dev-dependencies]
30 | pretty_assertions = "0.5.1"
31 |
32 | [features]
33 | default = []
34 | compact_containers = ["compact", "compact_macros"]
35 | stdweb = ["nalgebra/stdweb"]
36 | serde-serialization = ["serde", "serde_derive", "nalgebra/serde-serialize"]
--------------------------------------------------------------------------------
/src/areas/tests/1_difference.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Anselm Eickhoff
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/angles.rs:
--------------------------------------------------------------------------------
1 | use {V2, N, dot, PI};
2 |
3 | #[inline]
4 | pub fn angle_to(a: V2, b: V2) -> N {
5 | let theta: N = dot(&a, &b) / (a.norm() * b.norm());
6 | theta.min(1.0).max(-1.0).acos()
7 | }
8 |
9 | #[inline]
10 | pub fn angle_along_to(a: V2, a_direction: V2, b: V2) -> N {
11 | let simple_angle = angle_to(a, b);
12 | let linear_direction = (b - a).normalize();
13 |
14 | if a_direction.dot(&linear_direction) >= 0.0 {
15 | simple_angle
16 | } else {
17 | 2.0 * PI - simple_angle
18 | }
19 | }
20 |
21 | #[inline]
22 | pub fn signed_angle_to(a: V2, b: V2) -> N {
23 | // https://stackoverflow.com/a/2150475
24 | let det = a.x * b.y - a.y * b.x;
25 | let dot = a.x * b.x + a.y * b.y;
26 | (det).atan2(dot)
27 | }
28 |
29 | //
30 | // DESCARTES ASSUMES
31 | // A RIGHT HAND COORDINATE SYSTEM
32 | //
33 | // positive angles are counter-clockwise if z axis points out of screen
34 | //
35 |
36 | pub trait WithUniqueOrthogonal: ::std::ops::Neg