finite_element_method/fem/
convex_hull_on_plane.rs1use std::fmt::Debug;
2use std::cmp::Ordering;
3
4use extended_matrix::FloatTrait;
5
6
7pub fn quick_sort<T>(arr: &mut [T])
8 where T: PartialOrd
9{
10 let len = arr.len();
11 _quick_sort(arr, 0, (len - 1) as isize);
12}
13
14
15fn _quick_sort<T>(arr: &mut [T], low: isize, high: isize)
16 where T: PartialOrd
17{
18 if low < high
19 {
20 let p = partition(arr, low, high);
21 _quick_sort(arr, low, p - 1);
22 _quick_sort(arr, p + 1, high);
23 }
24}
25
26
27fn partition<T>(arr: &mut [T], low: isize, high: isize) -> isize
28 where T: PartialOrd
29{
30 let pivot = high as usize;
31 let mut store_index = low - 1;
32 let mut last_index = high;
33
34 loop
35 {
36 store_index += 1;
37 while arr[store_index as usize] < arr[pivot]
38 {
39 store_index += 1;
40 }
41 last_index -= 1;
42 while last_index >= 0 && arr[last_index as usize] > arr[pivot]
43 {
44 last_index -= 1;
45 }
46 if store_index >= last_index
47 {
48 break;
49 }
50 else
51 {
52 arr.swap(store_index as usize, last_index as usize);
53 }
54 }
55 arr.swap(store_index as usize, pivot as usize);
56 store_index
57}
58
59
60#[derive(Debug, Clone)]
61pub struct Point<V>
62{
63 n: u32,
64 x: V,
65 y: V,
66}
67
68
69impl<V> Point<V>
70 where V: FloatTrait<Output = V>,
71{
72 pub fn create(n: u32, x: V, y: V) -> Self
73 {
74 Point { n, x, y }
75 }
76
77
78 fn vector_from_origin_to_point(&self) -> Vector<V>
79 {
80 Vector::create(0, V::from(0.0), V::from(0.0), self.n, self.x, self.y)
81 }
82
83
84 pub fn copy_number(&self) -> u32
85 {
86 self.n
87 }
88}
89
90
91impl<V> PartialOrd for Point<V>
92 where V: FloatTrait<Output = V>
93{
94 fn partial_cmp(&self, other: &Point<V>) -> Option<Ordering>
95 {
96 let directional_vector = Vector::create_directional_vector();
97 let lhs_vector_from_origin = self.vector_from_origin_to_point();
98 let rhs_vector_from_origin = other.vector_from_origin_to_point();
99 directional_vector
100 .cosine_of_angle_between_vectors(&lhs_vector_from_origin)
101 .my_acos()
102 .my_to_degrees()
103 .partial_cmp(
104 &(directional_vector
105 .cosine_of_angle_between_vectors(&rhs_vector_from_origin)
106 .my_acos()
107 )
108 .my_to_degrees()
109 )
110 }
111}
112
113
114impl<V> PartialEq for Point<V>
115 where V: FloatTrait<Output = V>
116{
117 fn eq(&self, other: &Point<V>) -> bool
118 {
119 let directional_vector = Vector::create_directional_vector();
120 let lhs_vector_from_origin = self.vector_from_origin_to_point();
121 let rhs_vector_from_origin = other.vector_from_origin_to_point();
122 directional_vector
123 .cosine_of_angle_between_vectors(&lhs_vector_from_origin)
124 .my_acos()
125 .my_to_degrees() ==
126 directional_vector
127 .cosine_of_angle_between_vectors(&rhs_vector_from_origin)
128 .my_acos()
129 .my_to_degrees()
130
131 }
132}
133
134
135#[derive(Debug)]
136struct Vector<V>
137{
138 point_1: Point<V>,
139 point_2: Point<V>,
140}
141
142
143fn double_signed_area<V>(p_1: &Point<V>, p_2: &Point<V>, p_3: &Point<V>) -> V
144 where V: FloatTrait<Output = V>
145{
146 (p_2.x - p_1.x) * (p_3.y - p_1.y) - (p_2.y - p_1.y) * (p_3.x - p_1.x)
147}
148
149
150impl<V> Vector<V>
151 where V: FloatTrait<Output = V>
152{
153 fn create_directional_vector() -> Self
154 {
155 Vector::create(0, V::from(0.0), V::from(0.0), 0, V::from(1.0), V::from(0.0))
156 }
157
158
159 fn create(n_1: u32, x_1: V, y_1: V, n_2: u32, x_2: V, y_2: V) -> Self
160 {
161 let point_1 = Point { n: n_1, x: x_1, y: y_1 };
162 let point_2 = Point { n: n_2, x: x_2, y: y_2 };
163 Vector { point_1, point_2 }
164 }
165
166 fn vector_length(&self) -> V
167 {
168 (
169 (self.point_1.x - self.point_2.x) * (self.point_1.x - self.point_2.x) +
170 (self.point_1.y - self.point_2.y) * (self.point_1.y - self.point_2.y)
171 ).my_sqrt()
172 }
173
174
175 fn scalar_product(&self, other: &Vector<V>) -> V
176 {
177 (self.point_1.x - self.point_2.x) * (other.point_1.x - other.point_2.x) +
178 (self.point_1.y - self.point_2.y) * (other.point_1.y - other.point_2.y)
179 }
180
181
182 fn cosine_of_angle_between_vectors(&self, other: &Vector<V>) -> V
183 {
184 let lhs_length = self.vector_length();
185 let rhs_length = other.vector_length();
186 let scalar_product = self.scalar_product(other);
187 scalar_product / (lhs_length * rhs_length)
188 }
189}
190
191
192pub fn convex_hull_on_plane<V>(data: &[Point<V>]) -> Vec<Point<V>>
193 where V: FloatTrait<Output = V>,
194{
195 let mut updated_data = data.to_vec();
196 let mut shift_x = updated_data[0].x;
197 let mut min_y = updated_data[0].y;
198 let mut min_y_position = 0;
199 for i in 0..updated_data.len()
200 {
201 if updated_data[i].y < min_y
202 {
203 shift_x = updated_data[i].x;
204 min_y = updated_data[i].y;
205 min_y_position = i;
206 }
207 }
208 updated_data.swap(0, min_y_position);
209 for i in 0..updated_data.len()
210 {
211 updated_data[i].x -= shift_x;
212 updated_data[i].y -= min_y;
213 }
214 quick_sort(&mut updated_data[1..]);
215 let mut i = 0;
216 while i + 2 < updated_data.len()
217 {
218 let doubled_area = double_signed_area(
219 &updated_data[i], &updated_data[i + 1], &updated_data[i + 2]);
220 if doubled_area <= V::from(0.0)
221 {
222 updated_data.remove(i + 1);
223 }
224 else
225 {
226 i += 1;
227 }
228 }
229 for i in 0..updated_data.len()
230 {
231 updated_data[i].x += shift_x;
232 updated_data[i].y += min_y;
233 }
234 updated_data
235}