melvin_ob/objective/
known_img_objective.rs1use crate::imaging::CameraAngle;
2use crate::util::Vec2D;
3use crate::http_handler::{ImageObjective, ZoneType};
4use chrono::{DateTime, Utc};
5use fixed::types::I32F32;
6use num::ToPrimitive;
7use std::cmp::Ordering;
8
9#[derive(Debug, Clone)]
13pub struct KnownImgObjective {
14 id: usize,
16 name: String,
18 start: DateTime<Utc>,
20 end: DateTime<Utc>,
22 zone: [i32; 4],
24 optic_required: CameraAngle,
26 coverage_required: f64,
28}
29
30impl KnownImgObjective {
31 pub fn new(
33 id: usize,
34 name: String,
35 start: DateTime<Utc>,
36 end: DateTime<Utc>,
37 zone: [i32; 4],
38 optic_required: CameraAngle,
39 coverage_required: f64,
40 ) -> KnownImgObjective {
41 KnownImgObjective { id, name, start, end, zone, optic_required, coverage_required }
42 }
43
44 pub fn id(&self) -> usize { self.id }
46 pub fn start(&self) -> DateTime<Utc> { self.start }
48 pub fn end(&self) -> DateTime<Utc> { self.end }
50 pub fn name(&self) -> &str { &self.name }
52 pub fn zone(&self) -> [i32; 4] { self.zone }
54 pub fn optic_required(&self) -> CameraAngle { self.optic_required }
56 pub fn coverage_required(&self) -> f64 { self.coverage_required }
58 pub fn width(&self) -> i32 { self.zone[2] - self.zone[0] }
60 pub fn height(&self) -> i32 { self.zone[3] - self.zone[1] }
62
63 pub fn get_single_image_point(&self) -> Vec2D<I32F32> {
65 let x_size = self.zone[2] - self.zone[0];
66 let y_size = self.zone[3] - self.zone[1];
67 let pos = Vec2D::new(self.zone[0] + x_size / 2, self.zone[1] + y_size / 2);
68 Vec2D::new(I32F32::from(pos.x()), I32F32::from(pos.y())).wrap_around_map()
69 }
70
71 pub fn get_corners(&self) -> [(Vec2D<I32F32>, Vec2D<I32F32>); 4] {
73 let first = Vec2D::new(I32F32::from(self.zone[0]), I32F32::from(self.zone[1]));
74 let second = Vec2D::new(I32F32::from(self.zone[0]), I32F32::from(self.zone[3]));
75 let third = Vec2D::new(I32F32::from(self.zone[2]), I32F32::from(self.zone[1]));
76 let fourth = Vec2D::new(I32F32::from(self.zone[2]), I32F32::from(self.zone[3]));
77 [
78 (first, first.unwrapped_to(&fourth)),
79 (second, second.unwrapped_to(&third)),
80 (third, third.unwrapped_to(&second)),
81 (fourth, fourth.unwrapped_to(&first)),
82 ]
83 }
84
85 #[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
90 pub fn min_images(&self) -> i32 {
91 let lens_square_side_length = u32::from(self.optic_required().get_square_side_length());
92 let zone_width = self.zone[2] - self.zone[0];
93 let zone_height = self.zone[3] - self.zone[1];
94
95 let total_zone_area_size = f64::from(zone_width * zone_height);
96 let lens_area_size = f64::from(lens_square_side_length.pow(2));
97 let min_area_required = total_zone_area_size * self.coverage_required;
98
99 let min_number_of_images_required = (min_area_required / lens_area_size).ceil();
100 min_number_of_images_required.to_i32().unwrap()
101 }
102}
103
104impl TryFrom<ImageObjective> for KnownImgObjective {
105 type Error = std::io::Error;
106
107 fn try_from(obj: ImageObjective) -> Result<Self, Self::Error> {
112 match obj.zone_type() {
113 ZoneType::KnownZone(zone) => Ok(Self {
114 id: obj.id(),
115 name: String::from(obj.name()),
116 start: obj.start(),
117 end: obj.end(),
118 zone: *zone,
119 optic_required: CameraAngle::from(obj.optic_required()),
120 coverage_required: obj.coverage_required(),
121 }),
122 ZoneType::SecretZone(_) => Err(std::io::Error::new(
123 std::io::ErrorKind::Other,
124 "[FATAL] Wrong objective conversion!",
125 )),
126 }
127 }
128}
129
130impl TryFrom<(ImageObjective, [i32; 4])> for KnownImgObjective {
131 type Error = std::io::Error;
132
133 fn try_from(obj_with_zone: (ImageObjective, [i32; 4])) -> Result<Self, Self::Error> {
138 let obj = obj_with_zone.0;
139 match obj.zone_type() {
140 ZoneType::SecretZone(_) => Ok(Self {
141 id: obj.id(),
142 name: String::from(obj.name()),
143 start: obj.start(),
144 end: obj.end(),
145 zone: obj_with_zone.1,
146 optic_required: CameraAngle::from(obj.optic_required()),
147 coverage_required: obj.coverage_required(),
148 }),
149 ZoneType::KnownZone(_) => Err(std::io::Error::new(
150 std::io::ErrorKind::Other,
151 "[FATAL] Wrong objective conversion!",
152 )),
153 }
154 }
155}
156
157impl Eq for KnownImgObjective {}
158
159impl PartialEq<Self> for KnownImgObjective {
160 fn eq(&self, other: &Self) -> bool { self.end == other.end }
162}
163
164impl PartialOrd<Self> for KnownImgObjective {
165 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
167}
168
169impl Ord for KnownImgObjective {
170 fn cmp(&self, other: &Self) -> Ordering { self.end.cmp(&other.end) }
172}