1use crate::{
15 cast,
16 geometry::{Line, Point},
17 BvError, InputType, OutputType,
18};
19use std::fmt;
20
21pub struct VoronoiVisualUtils {}
23
24impl VoronoiVisualUtils {
25 pub fn discretize<I: InputType, F: OutputType>(
44 point: &Point<I>,
45 segment: &Line<I>,
46 max_dist: F,
47 affine: &SimpleAffine<F>,
48 discretization: &mut Vec<[F; 2]>,
49 ) {
50 if discretization[0][0] == discretization[1][0]
52 && discretization[0][1] == discretization[1][1]
53 {
54 return;
55 }
56 let segm_vec_x: F =
60 affine.transform_ix(segment.end.x) - affine.transform_ix(segment.start.x);
61 let segm_vec_y: F =
62 affine.transform_iy(segment.end.y) - affine.transform_iy(segment.start.y);
63 let sqr_segment_length = segm_vec_x * segm_vec_x + segm_vec_y * segm_vec_y;
64
65 let projection_start =
68 sqr_segment_length * Self::point_projection(affine, &discretization[0], segment);
69 let projection_end =
70 sqr_segment_length * Self::point_projection(affine, &discretization[1], segment);
71
72 let point_vec_x = affine.transform_ix(point.x) - affine.transform_ix(segment.start.x);
76 let point_vec_y = affine.transform_iy(point.y) - affine.transform_iy(segment.start.y);
77 let rot_x = segm_vec_x * point_vec_x + segm_vec_y * point_vec_y;
78 let rot_y = segm_vec_x * point_vec_y - segm_vec_y * point_vec_x;
79
80 let last_point = (*discretization)[1];
82 let _ = discretization.pop();
83
84 let mut point_stack = vec![projection_end];
86 let mut cur_x = projection_start;
87 let mut cur_y = Self::parabola_y::<F>(cur_x, rot_x, rot_y);
88
89 let max_dist_transformed = max_dist * max_dist * sqr_segment_length;
91 while !point_stack.is_empty() {
92 let new_x = point_stack[point_stack.len() - 1]; let new_y = Self::parabola_y::<F>(new_x, rot_x, rot_y);
94
95 let mid_x = (new_y - cur_y) / (new_x - cur_x) * rot_y + rot_x;
98 let mid_y = Self::parabola_y::<F>(mid_x, rot_x, rot_y);
99
100 let mut dist = (new_y - cur_y) * (mid_x - cur_x) - (new_x - cur_x) * (mid_y - cur_y);
103 #[allow(clippy::suspicious_operation_groupings)]
104 {
105 dist = dist * dist
106 / ((new_y - cur_y) * (new_y - cur_y) + (new_x - cur_x) * (new_x - cur_x));
107 }
108 if dist.is_nan() {
109 break;
110 }
111 if dist <= max_dist_transformed {
112 let _ = point_stack.pop();
114 let inter_x = (segm_vec_x * new_x - segm_vec_y * new_y) / sqr_segment_length
115 + affine.transform_ix(segment.start.x);
116 let inter_y = (segm_vec_x * new_y + segm_vec_y * new_x) / sqr_segment_length
117 + affine.transform_iy(segment.start.y);
118 discretization.push([inter_x, inter_y]);
119 cur_x = new_x;
120 cur_y = new_y;
121 } else {
122 point_stack.push(mid_x);
123 }
124 }
125 let discretization_len = discretization.len();
127 discretization[discretization_len - 1] = last_point;
128 }
129
130 #[inline(always)]
132 #[allow(clippy::suspicious_operation_groupings)]
133 fn parabola_y<F: OutputType>(x: F, a: F, b: F) -> F {
134 ((x - a) * (x - a) + b * b) / (b + b)
135 }
136
137 pub fn point_projection<I: InputType, F: OutputType>(
145 affine: &SimpleAffine<F>,
146 point: &[F; 2],
147 segment: &Line<I>,
148 ) -> F {
149 let segment_vec_x: F =
150 affine.transform_ix(segment.end.x) - affine.transform_ix(segment.start.x);
151 let segment_vec_y: F =
152 affine.transform_iy(segment.end.y) - affine.transform_iy(segment.start.y);
153 let point_vec_x = point[0] - affine.transform_ix(segment.start.x);
154 let point_vec_y = point[1] - affine.transform_iy(segment.start.y);
155 let sqr_segment_length = segment_vec_x * segment_vec_x + segment_vec_y * segment_vec_y;
156 let vec_dot = segment_vec_x * point_vec_x + segment_vec_y * point_vec_y;
157 vec_dot / sqr_segment_length
158 }
159}
160
161#[derive(PartialEq, Eq, Clone, fmt::Debug)]
165pub struct Aabb2<F: OutputType> {
166 min_max_: Option<([F; 2], [F; 2])>,
167}
168
169impl<F: OutputType> Default for Aabb2<F> {
170 #[inline]
171 fn default() -> Self {
172 Self { min_max_: None }
173 }
174}
175
176impl<F: OutputType> Aabb2<F> {
177 pub fn new<I: InputType>(p1: &Point<I>, p2: &Point<I>) -> Self {
179 let mut rv = Self::default();
180 rv.update_point(p1);
181 rv.update_point(p2);
182 rv
183 }
184
185 pub fn new_from_i32<I: InputType>(x1: i32, y1: i32, x2: i32, y2: i32) -> Self {
187 let mut rv = Self::default();
188 rv.update_coordinate::<I>(x1, y1);
189 rv.update_coordinate::<I>(x2, y2);
190 rv
191 }
192
193 #[inline(always)]
194 pub fn update_point<I: InputType>(&mut self, point: &Point<I>) {
195 let x = cast::<I, F>(point.x);
196 let y = cast::<I, F>(point.y);
197 self.update_vertex(x, y);
198 }
199
200 #[inline(always)]
201 pub fn update_coordinate<I: InputType>(&mut self, x: i32, y: i32) {
202 self.update_vertex(cast::<i32, F>(x), cast::<i32, F>(y));
203 }
204
205 #[inline]
206 pub fn update_vertex(&mut self, x: F, y: F) {
207 if self.min_max_.is_none() {
208 self.min_max_ = Some(([x, y], [x, y]));
209 return;
210 }
211 let (mut aabb_min, mut aabb_max) = self.min_max_.take().unwrap();
212
213 if x < aabb_min[0] {
214 aabb_min[0] = x;
215 }
216 if y < aabb_min[1] {
217 aabb_min[1] = y;
218 }
219 if x > aabb_max[0] {
220 aabb_max[0] = x;
221 }
222 if y > aabb_max[1] {
223 aabb_max[1] = y;
224 }
225 self.min_max_ = Some((aabb_min, aabb_max));
226 }
227
228 #[inline]
229 pub fn update_i64(&mut self, x: i64, y: i64) {
230 self.update_vertex(cast::<i64, F>(x), cast::<i64, F>(y))
231 }
232
233 #[inline]
234 pub fn update_f64(&mut self, x: f64, y: f64) {
235 self.update_vertex(cast::<f64, F>(x), cast::<f64, F>(y))
236 }
237
238 #[inline(always)]
239 pub fn update_line<I: InputType>(&mut self, line: &Line<I>) {
240 self.update_point(&line.start);
241 self.update_point(&line.end);
242 }
243
244 #[inline(always)]
245 pub fn get_high(&self) -> Option<[F; 2]> {
246 if let Some((_, high)) = self.min_max_ {
247 return Some(high);
248 }
249 None
250 }
251
252 #[inline(always)]
253 pub fn get_low(&self) -> Option<[F; 2]> {
254 if let Some((low, _)) = self.min_max_ {
255 return Some(low);
256 }
257 None
258 }
259
260 pub fn grow_percent<I: InputType>(&mut self, percent: i32) {
263 if self.min_max_.is_some() {
264 let size_x = self.get_high().unwrap()[0] - self.get_low().unwrap()[0];
265 let size_y = self.get_high().unwrap()[1] - self.get_low().unwrap()[1];
266 let size = if size_x > size_y { size_x } else { size_y };
267
268 let delta = size * cast::<f32, F>((percent as f32) / 100.0);
269
270 let mut p = self.get_high().unwrap();
271 p[0] = p[0] + delta;
272 p[1] = p[1] + delta;
273 self.update_vertex(p[0], p[1]);
274 let mut p = self.get_low().unwrap();
275 p[0] = p[0] - delta;
276 p[1] = p[1] - delta;
277 self.update_vertex(p[0], p[1]);
278 }
279 }
280
281 #[inline]
294 pub fn contains_point<I: InputType>(&self, point: &Point<I>) -> Option<bool> {
295 if let Some(min_max) = self.min_max_ {
296 let x = cast::<I, F>(point.x);
297 let y = cast::<I, F>(point.y);
298
299 Some(x >= min_max.0[0] && x <= min_max.1[0] && y >= min_max.0[1] && y <= min_max.1[1])
300 } else {
301 None
302 }
303 }
304
305 #[inline]
319 pub fn contains_line<I: InputType>(&self, line: &Line<I>) -> Option<bool> {
320 if self.min_max_.is_some() {
321 Some(
323 self.contains_point(&line.start).unwrap()
324 && self.contains_point(&line.end).unwrap(),
325 )
326 } else {
327 None
328 }
329 }
330}
331
332#[derive(PartialEq, Clone, fmt::Debug)]
336pub struct SimpleAffine<F: OutputType> {
337 to_center_: [F; 2],
340 pub scale: [F; 2],
342 pub to_offset: [F; 2],
345}
346
347impl<F: OutputType> Default for SimpleAffine<F> {
348 #[inline]
349 fn default() -> Self {
350 Self {
351 to_center_: [F::zero(), F::zero()],
352 scale: [F::one(), F::one()],
353 to_offset: [F::zero(), F::zero()],
354 }
355 }
356}
357
358impl<F: OutputType> SimpleAffine<F> {
359 pub fn new<I: InputType>(
360 source_aabb: &Aabb2<F>,
361 dest_aabb: &Aabb2<F>,
362 ) -> Result<Self, BvError> {
363 let min_dim = cast::<i32, F>(10);
364
365 if let Some(s_low) = source_aabb.get_low() {
366 if let Some(s_high) = source_aabb.get_high() {
367 if let Some(d_low) = dest_aabb.get_low() {
368 if let Some(d_high) = dest_aabb.get_high() {
369 let source_aabb_center = [
372 -(s_low[0] + s_high[0]) / cast::<i32, F>(2_i32),
373 -(s_low[1] + s_high[1]) / cast::<i32, F>(2_i32),
374 ];
375 let source_aabb_size = [
376 (s_high[0] - s_low[0]).max(min_dim),
377 (s_high[1] - s_low[1]).max(min_dim),
378 ];
379
380 let dest_aabb_center = [
381 (d_low[0] + d_high[0]) / cast::<i32, F>(2_i32),
382 (d_low[1] + d_high[1]) / cast::<i32, F>(2_i32),
383 ];
384 let dest_aabb_size = [
385 (d_high[0] - d_low[0]).max(min_dim),
386 (d_high[1] - d_low[1]).max(min_dim),
387 ];
388
389 let source_aabb_size = source_aabb_size[0].max(source_aabb_size[1]);
391 let dest_aabb_size = dest_aabb_size[0].min(dest_aabb_size[1]);
392 let scale = dest_aabb_size / source_aabb_size;
393
394 return Ok(Self {
395 to_center_: source_aabb_center,
396 scale: [scale, scale],
397 to_offset: dest_aabb_center,
398 });
399 }
400 }
401 }
402 }
403 Err(BvError::InternalError(format!(
404 "could not get dimension of the AABB. {}:{}",
405 file!(),
406 line!()
407 )))
408 }
409
410 #[inline(always)]
412 pub fn reverse_transform<I: InputType>(&self, x: F, y: F) -> Result<[I; 2], BvError> {
413 let x = self.reverse_transform_x(x)?;
414 let y = self.reverse_transform_y(y)?;
415 Ok([x, y])
416 }
417
418 #[inline(always)]
420 pub fn reverse_transform_x<I: InputType>(&self, x: F) -> Result<I, BvError> {
421 super::try_cast::<F, I>(
422 ((x - self.to_offset[0]) / self.scale[0] - self.to_center_[0]).round(),
423 )
424 }
425
426 #[inline(always)]
428 pub fn reverse_transform_y<I: InputType>(&self, y: F) -> Result<I, BvError> {
429 super::try_cast::<F, I>(
430 ((y - self.to_offset[1]) / self.scale[1] - self.to_center_[1]).round(),
431 )
432 }
433
434 #[inline(always)]
436 pub fn transform(&self, x: F, y: F) -> [F; 2] {
437 [self.transform_x(x), self.transform_y(y)]
438 }
439
440 #[inline(always)]
443 pub fn transform_x(&self, x: F) -> F {
444 (x + self.to_center_[0]) * self.scale[0] + self.to_offset[0]
445 }
446
447 #[inline(always)]
450 pub fn transform_y(&self, y: F) -> F {
451 (y + self.to_center_[1]) * self.scale[1] + self.to_offset[1]
452 }
453
454 #[inline(always)]
456 pub fn transform_i<I: InputType>(&self, point: [I; 2]) -> [F; 2] {
457 [self.transform_ix(point[0]), self.transform_iy(point[1])]
458 }
459
460 #[inline(always)]
462 pub fn transform_f(&self, point: [F; 2]) -> [F; 2] {
463 [self.transform_fx(point[0]), self.transform_fy(point[1])]
464 }
465
466 #[inline(always)]
468 pub fn transform_p<I: InputType>(&self, point: &Point<I>) -> [F; 2] {
469 [self.transform_ix(point.x), self.transform_iy(point.y)]
470 }
471
472 #[inline(always)]
475 pub fn transform_ix<I: InputType>(&self, x: I) -> F {
476 (cast::<I, F>(x) + self.to_center_[0]) * self.scale[0] + self.to_offset[0]
477 }
478
479 #[inline(always)]
482 pub fn transform_iy<I: InputType>(&self, y: I) -> F {
483 (cast::<I, F>(y) + self.to_center_[1]) * self.scale[1] + self.to_offset[1]
484 }
485
486 #[inline(always)]
489 pub fn transform_fx(&self, x: F) -> F {
490 (x + self.to_center_[0]) * self.scale[0] + self.to_offset[0]
491 }
492
493 #[inline(always)]
496 pub fn transform_fy(&self, y: F) -> F {
497 (y + self.to_center_[1]) * self.scale[1] + self.to_offset[1]
498 }
499
500 #[inline(always)]
502 pub fn zoom(&mut self, f: F) {
503 self.scale = [self.scale[0] * f, self.scale[1] * f];
504 }
505}
506
507pub fn to_segments_offset<I1: InputType, I2: InputType>(
510 points: &[[I1; 4]],
511 scale_x: f64,
512 scale_y: f64,
513 dx: i64,
514 dy: i64,
515) -> Vec<Line<I2>> {
516 let fx = |x: I1| cast::<f64, I2>(cast::<I1, f64>(x) * scale_x) + cast::<i64, I2>(dx);
517 let fy = |y: I1| cast::<f64, I2>(cast::<I1, f64>(y) * scale_y) + cast::<i64, I2>(dy);
518 points
519 .iter()
520 .map(|x| Line {
521 start: Point {
522 x: fx(x[0]),
523 y: fy(x[1]),
524 },
525 end: Point {
526 x: fx(x[2]),
527 y: fy(x[3]),
528 },
529 })
530 .collect()
531}