1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Library for 2D geometric spaces (AKA "the plane"). This library focuses on
//! integer geometry, and is intended to be used in discrete 2D games.
//!
//! This crate supports 2D generic vectors (for representing points, sizes,
//! actual vectors, etc) with arithmetic operations on them (including dot
//! product and magnitude). It also defines "straight" basic directions in a
//! plane (i.e. up, left, down, right), using axis as indices and rectangles.
//!
//! It implements specialized maps and sets using points as keys. You could
//! think of maps as associating data with points in a plane, while sets could
//! be thought as specs of sub-planes. Both of them supports getting the first
//! or the last neighbour in a given direction.
//!
//! Finally, the crate has simple graphs whose vertices are points in the plane
//! and they can be connected (forming edges). It is useful to create planar
//! graphs (i.e. no edges cross), but the implementation won't prevent you from
//! forming non-planar graphs, although the graph still is in a 2D plane. The
//! graph also implements the "A Star" (or "A*") algorithm to make a path
//! between two points, using only a given region (creating vertices if
//! necessary).
//!
//! As an example, here is the execution of A*:
//! ```rust
//! use gardiz::{
//!     coord::Vec2,
//!     graph::Graph,
//!     direc::{Direction, DirecVector},
//! };
//! use std::collections::HashSet;
//!
//! # fn main() {
//! // `i64` is the type of the coordinate of the points.
//! let mut graph = Graph::<i64>::new();
//! // Initial and final points.
//! let start = Vec2 { x: -3, y: -3 };
//! let goal = Vec2 { x: 2, y: 4 };
//! graph.create_vertex(start);
//! graph.create_vertex(goal);
//!
//! // Penalty whenever the path takes a turn.
//! let penalty = 2;
//!
//! // Valid points to be used in the path.
//! let mut valid_points = HashSet::new();
//! for x in -3 .. 1 {
//!     for y in -3 .. 0 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//! for x in 0 .. 3 {
//!     for y in 0 .. 2 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//! for x in -1 .. 2 {
//!     for y in 2 .. 3 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//! for x in -2 .. 0 {
//!     for y in 3 .. 5 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//! for x in -3 .. 7 {
//!     for y in 5 .. 7 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//! for x in 1 .. 9 {
//!     for y in 4 .. 9 {
//!         valid_points.insert(Vec2 { x, y });
//!     }
//! }
//!
//! // Cloning the graph before making the path (which will modify it).
//! let mut expected = graph.clone();
//!
//! // Runs A*
//! let directions = graph.make_path(
//!     &start,
//!     &goal,
//!     &penalty,
//!     |point| valid_points.contains(&point)
//! );
//!
//! // Checks whether the computed directions are correct.
//! assert_eq!(
//!     directions,
//!     Some(vec![
//!         // x = -3, y = -3
//!         DirecVector { direction: Direction::Right, magnitude: 3 },
//!         // x = 0, y = -3
//!         DirecVector { direction: Direction::Down, magnitude: 5 },
//!         // x = 0, y = 2
//!         DirecVector { direction: Direction::Left, magnitude: 1 },
//!         // x = -1, y = 2
//!         DirecVector { direction: Direction::Down, magnitude: 3 },
//!         // x = -1, y = 5
//!         DirecVector { direction: Direction::Right, magnitude: 3 },
//!         // x = 2, y = 5
//!         DirecVector { direction: Direction::Up, magnitude: 1 },
//!         // x = 2, y = 4
//!     ])
//! );
//!
//! // Insert the vertices created when making the path.
//! expected.create_vertex(Vec2 { x: 0, y: -3 });
//! expected.create_vertex(Vec2 { x: 0, y: 2 });
//! expected.create_vertex(Vec2 { x: -1, y: 2 });
//! expected.create_vertex(Vec2 { x: -1, y: 5 });
//! expected.create_vertex(Vec2 { x: 2, y: 5 });
//!
//! // Connect the vertices in the path.
//! expected
//!     .connect(Vec2 { x: -3, y: -3 }.as_ref(), Vec2 { x: 0, y: -3 }.as_ref());
//! expected
//!     .connect(Vec2 { x: 0, y: 2 }.as_ref(), Vec2 { x: 0, y: -3 }.as_ref());
//! expected
//!     .connect(Vec2 { x: 0, y: 2 }.as_ref(), Vec2 { x: -1, y: 2 }.as_ref());
//! expected
//!     .connect(Vec2 { x: -1, y: 5 }.as_ref(), Vec2 { x: -1, y: 2 }.as_ref());
//! expected
//!     .connect(Vec2 { x: -1, y: 5 }.as_ref(), Vec2 { x: 2, y: 5 }.as_ref());
//! expected
//!     .connect(Vec2 { x: 2, y: 4 }.as_ref(), Vec2 { x: 2, y: 5 }.as_ref());
//!
//! // Test if the graph produced by `make_path` is the expected one we built.
//! assert_eq!(graph, expected);
//! # }
//! ```

#![warn(missing_docs, missing_debug_implementations)]

pub mod bits;
pub mod axis;
pub mod direc;
pub mod coord;
pub mod rect;
pub mod map;
pub mod set;
pub mod graph;