Skip to main content

egml_core/model/geometry/aggregates/
multi_point.rs

1use crate::model::common::{ApplyTransform, ComputeEnvelope, IterGeometries};
2use crate::model::geometry::Envelope;
3use crate::model::geometry::aggregates::{
4    AbstractGeometricAggregate, AsAbstractGeometricAggregate, AsAbstractGeometricAggregateMut,
5};
6use crate::model::geometry::primitives::{PointArrayProperty, PointProperty};
7use crate::model::geometry::refs::AbstractGeometryKindRef;
8use crate::{
9    Error, impl_abstract_geometric_aggregate_mut_traits, impl_abstract_geometric_aggregate_traits,
10    impl_has_geometry_type,
11};
12use nalgebra::{Isometry3, Rotation3, Scale3, Transform3, Vector3};
13use rayon::iter::IntoParallelRefMutIterator;
14use rayon::iter::ParallelIterator;
15
16#[derive(Debug, Clone, PartialEq)]
17pub struct MultiPoint {
18    pub abstract_geometric_aggregate: AbstractGeometricAggregate,
19    point_members: Option<PointArrayProperty>,
20    point_member: Vec<PointProperty>,
21}
22
23impl MultiPoint {
24    pub fn new(point_members: Option<PointArrayProperty>) -> Result<Self, Error> {
25        Ok(Self {
26            abstract_geometric_aggregate: AbstractGeometricAggregate::default(),
27            point_members,
28            point_member: Vec::new(),
29        })
30    }
31
32    pub fn from_abstract_geometric_aggregate(
33        abstract_geometric_aggregate: AbstractGeometricAggregate,
34        point_members: Option<PointArrayProperty>,
35    ) -> Self {
36        Self {
37            abstract_geometric_aggregate,
38            point_members,
39            point_member: Vec::new(),
40        }
41    }
42
43    pub fn point_members(&self) -> Option<&PointArrayProperty> {
44        self.point_members.as_ref()
45    }
46
47    pub fn set_point_members(&mut self, val: PointArrayProperty) {
48        self.point_members = Some(val);
49    }
50
51    pub fn set_point_members_opt(&mut self, val: Option<PointArrayProperty>) {
52        self.point_members = val;
53    }
54
55    pub fn clear_point_members(&mut self) {
56        self.point_members = None;
57    }
58
59    pub fn point_member(&self) -> &[PointProperty] {
60        &self.point_member
61    }
62
63    pub fn set_point_member(&mut self, val: Vec<PointProperty>) {
64        self.point_member = val;
65    }
66
67    pub fn push_point_member(&mut self, member: PointProperty) {
68        self.point_member.push(member);
69    }
70
71    pub fn extend_point_members(&mut self, members: impl IntoIterator<Item = PointProperty>) {
72        self.point_member.extend(members);
73    }
74}
75
76impl ApplyTransform for MultiPoint {
77    fn apply_transform(&mut self, transform: Transform3<f64>) {
78        if let Some(members) = &mut self.point_members {
79            members
80                .objects_mut()
81                .par_iter_mut()
82                .for_each(|p| p.apply_transform(transform));
83        }
84        self.point_member.par_iter_mut().for_each(|p| {
85            if let Some(object) = p.object_mut() {
86                object.apply_transform(transform);
87            }
88        });
89    }
90
91    fn apply_isometry(&mut self, isometry: Isometry3<f64>) {
92        if let Some(members) = &mut self.point_members {
93            members
94                .objects_mut()
95                .par_iter_mut()
96                .for_each(|p| p.apply_isometry(isometry));
97        }
98        self.point_member.par_iter_mut().for_each(|p| {
99            if let Some(object) = p.object_mut() {
100                object.apply_isometry(isometry);
101            }
102        });
103    }
104
105    fn apply_translation(&mut self, vector: Vector3<f64>) {
106        if let Some(members) = &mut self.point_members {
107            members
108                .objects_mut()
109                .par_iter_mut()
110                .for_each(|p| p.apply_translation(vector));
111        }
112        self.point_member.par_iter_mut().for_each(|p| {
113            if let Some(object) = p.object_mut() {
114                object.apply_translation(vector);
115            }
116        });
117    }
118
119    fn apply_rotation(&mut self, rotation: Rotation3<f64>) {
120        if let Some(members) = &mut self.point_members {
121            members
122                .objects_mut()
123                .par_iter_mut()
124                .for_each(|p| p.apply_rotation(rotation));
125        }
126        self.point_member.par_iter_mut().for_each(|p| {
127            if let Some(object) = p.object_mut() {
128                object.apply_rotation(rotation);
129            }
130        });
131    }
132
133    fn apply_scale(&mut self, scale: Scale3<f64>) {
134        if let Some(members) = &mut self.point_members {
135            members
136                .objects_mut()
137                .par_iter_mut()
138                .for_each(|p| p.apply_scale(scale));
139        }
140        self.point_member.par_iter_mut().for_each(|p| {
141            if let Some(object) = p.object_mut() {
142                object.apply_scale(scale);
143            }
144        });
145    }
146}
147
148impl ComputeEnvelope for MultiPoint {
149    fn compute_envelope(&self) -> Option<Envelope> {
150        let points: Vec<_> = self
151            .point_members
152            .iter()
153            .flat_map(|members| members.objects().iter())
154            .chain(self.point_member.iter().flat_map(|x| x.object()))
155            .map(|p| *p.pos())
156            .collect();
157        Envelope::from_points(&points).ok()
158    }
159}
160
161impl AsAbstractGeometricAggregate for MultiPoint {
162    fn abstract_geometric_aggregate(&self) -> &AbstractGeometricAggregate {
163        &self.abstract_geometric_aggregate
164    }
165}
166
167impl AsAbstractGeometricAggregateMut for MultiPoint {
168    fn abstract_geometric_aggregate_mut(&mut self) -> &mut AbstractGeometricAggregate {
169        &mut self.abstract_geometric_aggregate
170    }
171}
172
173impl_abstract_geometric_aggregate_traits!(MultiPoint);
174impl_abstract_geometric_aggregate_mut_traits!(MultiPoint);
175impl_has_geometry_type!(MultiPoint, MultiPoint);
176
177impl IterGeometries for MultiPoint {
178    fn iter_geometries(&self) -> Box<dyn Iterator<Item = AbstractGeometryKindRef<'_>> + '_> {
179        Box::new(
180            std::iter::once(self.into())
181                .chain(
182                    self.point_members
183                        .iter()
184                        .flat_map(|members| members.objects().iter())
185                        .flat_map(|x| x.iter_geometries()),
186                )
187                .chain(
188                    self.point_member
189                        .iter()
190                        .filter_map(|x| x.object())
191                        .flat_map(|x| x.iter_geometries()),
192                ),
193        )
194    }
195}