1use std::{collections::HashMap, fmt, io::BufRead, path::Path};
4
5mod level;
6mod object;
7mod region;
8
9pub use level::SemanticLevel;
10pub use object::SemanticObject;
11pub use region::SemanticRegion;
12
13use crate::{Aabb, Dataset};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum ElementKind {
18 Images,
20 Panoramas,
22 Vertices,
24 Surfaces,
26 Segments,
28 Objects,
30 Categories,
32 Regions,
34 Portals,
36 Levels,
38}
39
40impl ElementKind {
41 pub(crate) const fn as_str(self) -> &'static str {
42 match self {
43 Self::Images => "images",
44 Self::Panoramas => "panoramas",
45 Self::Vertices => "vertices",
46 Self::Surfaces => "surfaces",
47 Self::Segments => "segments",
48 Self::Objects => "objects",
49 Self::Categories => "categories",
50 Self::Regions => "regions",
51 Self::Portals => "portals",
52 Self::Levels => "levels",
53 }
54 }
55}
56
57#[derive(Debug, Clone)]
62pub struct SemanticScene<ObjectCategory, RegionCategory> {
63 pub(crate) name: String,
64 pub(crate) label: String,
65 pub(crate) counts: HashMap<&'static str, usize>,
66 pub(crate) aabb: Option<Aabb>,
67 pub(crate) levels: Vec<SemanticLevel<ObjectCategory, RegionCategory>>,
68}
69
70impl<ObjectCategory, RegionCategory> Default for SemanticScene<ObjectCategory, RegionCategory> {
71 fn default() -> Self {
72 Self {
73 name: String::new(),
74 label: String::new(),
75 counts: HashMap::new(),
76 aabb: None,
77 levels: Vec::new(),
78 }
79 }
80}
81
82impl<ObjectCategory, RegionCategory> SemanticScene<ObjectCategory, RegionCategory> {
83 #[must_use]
89 pub fn from_parts(
90 name: impl Into<String>,
91 label: impl Into<String>,
92 counts: HashMap<&'static str, usize>,
93 aabb: Option<Aabb>,
94 levels: Vec<SemanticLevel<ObjectCategory, RegionCategory>>,
95 ) -> Self {
96 Self {
97 name: name.into(),
98 label: label.into(),
99 counts,
100 aabb,
101 levels,
102 }
103 }
104
105 #[must_use]
107 pub fn name(&self) -> &str {
108 &self.name
109 }
110
111 #[must_use]
113 pub fn label(&self) -> &str {
114 &self.label
115 }
116
117 #[must_use]
122 pub const fn aabb(&self) -> Option<&Aabb> {
123 self.aabb.as_ref()
124 }
125
126 pub(crate) fn count(&self, element: ElementKind) -> Option<usize> {
127 self.counts.get(element.as_str()).copied()
128 }
129
130 #[must_use]
132 pub fn levels(&self) -> &[SemanticLevel<ObjectCategory, RegionCategory>] {
133 &self.levels
134 }
135
136 pub fn regions(&self) -> impl Iterator<Item = &SemanticRegion<ObjectCategory, RegionCategory>> {
138 self.levels.iter().flat_map(SemanticLevel::regions)
139 }
140
141 pub fn objects(&self) -> impl Iterator<Item = &SemanticObject<ObjectCategory>> {
143 self.levels.iter().flat_map(SemanticLevel::objects)
144 }
145}
146
147impl<ObjectCategory, RegionCategory> fmt::Display
148 for SemanticScene<ObjectCategory, RegionCategory>
149{
150 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
151 if formatter.alternate() {
152 write!(
153 formatter,
154 "SemanticScene {:?}\n label: {:?}\n bounds: {}\n counts: {}",
155 self.name,
156 self.label,
157 self.display_aabb(),
158 self.display_counts()
159 )
160 } else {
161 write!(
162 formatter,
163 "SemanticScene {:?}: {}, bounds=[{}]",
164 self.name,
165 self.display_counts(),
166 self.display_aabb()
167 )
168 }
169 }
170}
171
172impl SemanticScene<(), ()> {
173 pub fn load<D: Dataset>(
180 path: impl AsRef<Path>,
181 options: D::Options,
182 ) -> Result<SemanticScene<D::ObjectCategory, D::RegionCategory>, D::Error>
183 where
184 D::Error: From<std::io::Error>,
185 {
186 D::from_path(path, options)
187 }
188
189 pub fn from_reader<D: Dataset, R: BufRead>(
195 reader: R,
196 options: D::Options,
197 ) -> Result<SemanticScene<D::ObjectCategory, D::RegionCategory>, D::Error> {
198 D::from_reader(reader, options)
199 }
200
201 pub fn from_str<D: Dataset>(
207 input: &str,
208 options: D::Options,
209 ) -> Result<SemanticScene<D::ObjectCategory, D::RegionCategory>, D::Error> {
210 D::from_str(input, options)
211 }
212}
213
214impl<ObjectCategory, RegionCategory> SemanticScene<ObjectCategory, RegionCategory> {
215 const fn display_aabb(&self) -> DisplayAabb<'_> {
216 DisplayAabb(self.aabb.as_ref())
217 }
218
219 const fn display_counts(&self) -> DisplayCounts<'_, ObjectCategory, RegionCategory> {
220 DisplayCounts(self)
221 }
222}
223
224struct DisplayAabb<'a>(Option<&'a Aabb>);
225
226impl fmt::Display for DisplayAabb<'_> {
227 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
228 match self.0 {
229 Some(aabb) => aabb.fmt(formatter),
230 None => formatter.write_str("none"),
231 }
232 }
233}
234
235struct DisplayCounts<'a, ObjectCategory, RegionCategory>(
236 &'a SemanticScene<ObjectCategory, RegionCategory>,
237);
238
239impl<ObjectCategory, RegionCategory> fmt::Display
240 for DisplayCounts<'_, ObjectCategory, RegionCategory>
241{
242 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
243 write!(
244 formatter,
245 "levels={}, regions={}, objects={}, categories={}, segments={}",
246 self.0.levels.len(),
247 self.0.regions().count(),
248 self.0.objects().count(),
249 self.0.count(ElementKind::Categories).unwrap_or(0),
250 self.0.count(ElementKind::Segments).unwrap_or(0),
251 )
252 }
253}