1use crate::backend::default::geometry::{
63 GeometryCore, GeometryInstanceData, ThemedMaterials, ThemedTextures,
64};
65use crate::cityjson::core::appearance::ThemeName;
66use crate::cityjson::core::coordinate::Coordinate;
67use crate::resources::handles::{
68 GeometryTemplateHandle, MaterialHandle, SemanticHandle, TextureHandle,
69};
70use crate::resources::id::ResourceId32;
71use crate::resources::mapping::textures::TextureMapCore;
72use crate::resources::mapping::{MaterialMap, SemanticMap, SemanticOrMaterialMap, TextureMap};
73use crate::resources::storage::StringStorage;
74use crate::v2_0::Vertices;
75use crate::v2_0::boundary::Boundary;
76use crate::v2_0::boundary::{BoundaryCoordinates, BoundaryUniqueCoordinates};
77use crate::v2_0::vertex::{VertexIndex, VertexRef};
78use std::marker::PhantomData;
79use std::ops::{Deref, Index};
80
81pub mod semantic;
82pub use crate::backend::default::geometry::AffineTransform3D;
83pub use crate::cityjson::core::geometry::{GeometryType, LoD};
84
85#[derive(Clone, Debug)]
94pub struct Geometry<VR: VertexRef, SS: StringStorage> {
95 inner: GeometryCore<VR, ResourceId32, SS>,
96}
97
98#[derive(Clone, Debug, PartialEq)]
104pub struct StoredGeometryParts<VR: VertexRef, SS: StringStorage> {
105 pub type_geometry: GeometryType,
106 pub lod: Option<LoD>,
107 pub boundaries: Option<Boundary<VR>>,
108 pub semantics: Option<SemanticMap<VR>>,
109 pub materials: Option<Vec<(ThemeName<SS>, MaterialMap<VR>)>>,
110 pub textures: Option<Vec<(ThemeName<SS>, TextureMap<VR>)>>,
111 pub instance: Option<StoredGeometryInstance<VR>>,
112}
113
114#[derive(Clone, Copy, Debug, PartialEq)]
116pub struct StoredGeometryInstance<VR: VertexRef> {
117 pub template: GeometryTemplateHandle,
118 pub reference_point: VertexIndex<VR>,
119 pub transformation: AffineTransform3D,
120}
121
122#[derive(Clone, Copy, Debug)]
129pub struct GeometryInstanceView<'a, VR: VertexRef> {
130 inner: &'a GeometryInstanceData<VR, ResourceId32>,
131}
132
133impl<VR: VertexRef> GeometryInstanceView<'_, VR> {
134 #[must_use]
135 pub fn template(&self) -> GeometryTemplateHandle {
136 GeometryTemplateHandle::from_raw(*self.inner.template())
137 }
138
139 #[must_use]
140 pub fn reference_point(&self) -> VertexIndex<VR> {
141 *self.inner.reference_point()
142 }
143
144 #[must_use]
145 pub fn transformation(&self) -> AffineTransform3D {
146 *self.inner.transformation()
147 }
148}
149
150#[derive(Clone, Copy, Debug)]
157pub struct GeometryView<'a, VR: VertexRef, SS: StringStorage> {
158 geometry: &'a Geometry<VR, SS>,
159 instance: Option<GeometryInstanceView<'a, VR>>,
160}
161
162#[derive(Clone, Copy, Debug)]
163pub struct HandleOptionSlice<'a, H> {
164 raw: &'a [Option<ResourceId32>],
165 _marker: PhantomData<H>,
166}
167
168impl<'a, H> HandleOptionSlice<'a, H> {
169 fn new(raw: &'a [Option<ResourceId32>]) -> Self {
170 Self {
171 raw,
172 _marker: PhantomData,
173 }
174 }
175
176 #[inline]
177 fn as_handle_slice(&self) -> &'a [Option<H>] {
178 const {
179 assert!(
180 std::mem::size_of::<Option<H>>() == std::mem::size_of::<Option<ResourceId32>>()
181 );
182 assert!(
183 std::mem::align_of::<Option<H>>() == std::mem::align_of::<Option<ResourceId32>>()
184 );
185 }
186
187 unsafe { std::slice::from_raw_parts(self.raw.as_ptr().cast::<Option<H>>(), self.raw.len()) }
190 }
191
192 #[must_use]
193 pub fn len(&self) -> usize {
194 self.raw.len()
195 }
196
197 #[must_use]
198 pub fn is_empty(&self) -> bool {
199 self.raw.is_empty()
200 }
201
202 #[must_use]
203 pub fn get(&self, index: usize) -> Option<&'a Option<H>> {
204 self.as_handle_slice().get(index)
205 }
206
207 pub fn iter(&self) -> std::slice::Iter<'a, Option<H>> {
208 self.as_handle_slice().iter()
209 }
210}
211
212impl<H> Index<usize> for HandleOptionSlice<'_, H> {
213 type Output = Option<H>;
214
215 fn index(&self, index: usize) -> &Self::Output {
216 &self.as_handle_slice()[index]
217 }
218}
219
220impl<'a, H: 'a> IntoIterator for HandleOptionSlice<'a, H> {
221 type Item = &'a Option<H>;
222 type IntoIter = std::slice::Iter<'a, Option<H>>;
223
224 fn into_iter(self) -> Self::IntoIter {
225 self.as_handle_slice().iter()
226 }
227}
228
229impl<'a, H: 'a> IntoIterator for &'_ HandleOptionSlice<'a, H> {
230 type Item = &'a Option<H>;
231 type IntoIter = std::slice::Iter<'a, Option<H>>;
232
233 fn into_iter(self) -> Self::IntoIter {
234 self.as_handle_slice().iter()
235 }
236}
237
238#[derive(Clone, Copy, Debug)]
245pub struct SemanticMapView<'a, VR: VertexRef> {
246 inner: &'a SemanticOrMaterialMap<VR, ResourceId32>,
247}
248
249impl<'a, VR: VertexRef> SemanticMapView<'a, VR> {
250 #[allow(clippy::trivially_copy_pass_by_ref)]
251 #[must_use]
252 pub fn points(&self) -> HandleOptionSlice<'a, SemanticHandle> {
253 HandleOptionSlice::new(self.inner.points())
254 }
255
256 #[allow(clippy::trivially_copy_pass_by_ref)]
257 #[must_use]
258 pub fn linestrings(&self) -> HandleOptionSlice<'a, SemanticHandle> {
259 HandleOptionSlice::new(self.inner.linestrings())
260 }
261
262 #[allow(clippy::trivially_copy_pass_by_ref)]
263 #[must_use]
264 pub fn surfaces(&self) -> HandleOptionSlice<'a, SemanticHandle> {
265 HandleOptionSlice::new(self.inner.surfaces())
266 }
267}
268
269#[derive(Clone, Copy, Debug)]
273pub struct MaterialMapView<'a, VR: VertexRef> {
274 inner: &'a SemanticOrMaterialMap<VR, ResourceId32>,
275}
276
277impl<'a, VR: VertexRef> MaterialMapView<'a, VR> {
278 #[allow(clippy::trivially_copy_pass_by_ref)]
279 #[must_use]
280 pub fn points(&self) -> HandleOptionSlice<'a, MaterialHandle> {
281 HandleOptionSlice::new(self.inner.points())
282 }
283
284 #[allow(clippy::trivially_copy_pass_by_ref)]
285 #[must_use]
286 pub fn linestrings(&self) -> HandleOptionSlice<'a, MaterialHandle> {
287 HandleOptionSlice::new(self.inner.linestrings())
288 }
289
290 #[allow(clippy::trivially_copy_pass_by_ref)]
291 #[must_use]
292 pub fn surfaces(&self) -> HandleOptionSlice<'a, MaterialHandle> {
293 HandleOptionSlice::new(self.inner.surfaces())
294 }
295}
296
297#[derive(Clone, Copy, Debug)]
302pub struct MaterialThemesView<'a, VR: VertexRef, SS: StringStorage> {
303 items: &'a [(ThemeName<SS>, SemanticOrMaterialMap<VR, ResourceId32>)],
304}
305
306impl<'a, VR: VertexRef, SS: StringStorage> MaterialThemesView<'a, VR, SS> {
307 #[must_use]
308 pub fn len(&self) -> usize {
309 self.items.len()
310 }
311
312 #[must_use]
313 pub fn is_empty(&self) -> bool {
314 self.items.is_empty()
315 }
316
317 pub fn iter(&self) -> impl Iterator<Item = (&'a ThemeName<SS>, MaterialMapView<'a, VR>)> + 'a {
318 self.items
319 .iter()
320 .map(|(theme, map)| (theme, MaterialMapView { inner: map }))
321 }
322
323 #[must_use]
324 pub fn first(&self) -> Option<(&'a ThemeName<SS>, MaterialMapView<'a, VR>)> {
325 self.items
326 .first()
327 .map(|(theme, map)| (theme, MaterialMapView { inner: map }))
328 }
329}
330
331#[derive(Clone, Copy, Debug)]
337pub struct TextureMapView<'a, VR: VertexRef> {
338 inner: &'a TextureMapCore<VR, ResourceId32>,
339}
340
341impl<'a, VR: VertexRef> TextureMapView<'a, VR> {
342 #[allow(clippy::trivially_copy_pass_by_ref)]
343 #[must_use]
344 pub fn vertices(&self) -> &'a [Option<VertexIndex<VR>>] {
345 self.inner.vertices()
346 }
347
348 #[allow(clippy::trivially_copy_pass_by_ref)]
349 #[must_use]
350 pub fn rings(&self) -> &'a [VertexIndex<VR>] {
351 self.inner.rings()
352 }
353
354 #[allow(clippy::trivially_copy_pass_by_ref)]
355 #[must_use]
356 pub fn ring_textures(&self) -> HandleOptionSlice<'a, TextureHandle> {
357 HandleOptionSlice::new(self.inner.ring_textures())
358 }
359}
360
361#[derive(Clone, Copy, Debug)]
362pub struct TextureThemesView<'a, VR: VertexRef, SS: StringStorage> {
363 items: &'a [(ThemeName<SS>, TextureMapCore<VR, ResourceId32>)],
364}
365
366impl<'a, VR: VertexRef, SS: StringStorage> TextureThemesView<'a, VR, SS> {
367 #[must_use]
368 pub fn len(&self) -> usize {
369 self.items.len()
370 }
371
372 #[must_use]
373 pub fn is_empty(&self) -> bool {
374 self.items.is_empty()
375 }
376
377 pub fn iter(&self) -> impl Iterator<Item = (&'a ThemeName<SS>, TextureMapView<'a, VR>)> + 'a {
378 self.items
379 .iter()
380 .map(|(theme, map)| (theme, TextureMapView { inner: map }))
381 }
382
383 #[must_use]
384 pub fn first(&self) -> Option<(&'a ThemeName<SS>, TextureMapView<'a, VR>)> {
385 self.items
386 .first()
387 .map(|(theme, map)| (theme, TextureMapView { inner: map }))
388 }
389}
390
391impl<VR: VertexRef, SS: StringStorage> Geometry<VR, SS> {
392 #[must_use]
393 pub fn from_stored_parts(parts: StoredGeometryParts<VR, SS>) -> Self {
394 let semantics = parts.semantics.map(SemanticMap::into_raw);
395 let materials = parts.materials.map(|items| {
396 items
397 .into_iter()
398 .map(|(theme, map)| (theme, map.into_raw()))
399 .collect()
400 });
401 let textures = parts.textures.map(|items| {
402 items
403 .into_iter()
404 .map(|(theme, map)| (theme, map.into_raw()))
405 .collect()
406 });
407 let instance = parts.instance.map(|instance| {
408 GeometryInstanceData::new(
409 instance.template.to_raw(),
410 instance.reference_point,
411 instance.transformation,
412 )
413 });
414
415 Self::from_raw_parts(
416 parts.type_geometry,
417 parts.lod,
418 parts.boundaries,
419 semantics,
420 materials,
421 textures,
422 instance,
423 )
424 }
425
426 pub(crate) fn from_raw_parts(
427 type_geometry: GeometryType,
428 lod: Option<LoD>,
429 boundaries: Option<Boundary<VR>>,
430 semantics: Option<SemanticOrMaterialMap<VR, ResourceId32>>,
431 materials: Option<ThemedMaterials<VR, ResourceId32, SS>>,
432 textures: Option<ThemedTextures<VR, ResourceId32, SS>>,
433 instance: Option<GeometryInstanceData<VR, ResourceId32>>,
434 ) -> Self {
435 Self {
436 inner: GeometryCore::new(
437 type_geometry,
438 lod,
439 boundaries,
440 semantics,
441 materials,
442 textures,
443 instance,
444 ),
445 }
446 }
447
448 pub(crate) fn raw(&self) -> &GeometryCore<VR, ResourceId32, SS> {
449 &self.inner
450 }
451
452 pub fn type_geometry(&self) -> &GeometryType {
453 self.inner.type_geometry()
454 }
455
456 pub fn lod(&self) -> Option<&LoD> {
457 self.inner.lod()
458 }
459
460 pub fn boundaries(&self) -> Option<&Boundary<VR>> {
461 self.inner.boundaries()
462 }
463
464 #[must_use]
465 pub fn coordinates<'a, V: Coordinate>(
466 &'a self,
467 vertices: &'a Vertices<VR, V>,
468 ) -> Option<BoundaryCoordinates<'a, VR, V>> {
469 self.boundaries()
470 .map(|boundary| boundary.coordinates(vertices))
471 }
472
473 pub fn unique_vertex_indices<'a>(
474 &'a self,
475 scratch: &'a mut Vec<VertexIndex<VR>>,
476 ) -> Option<&'a [VertexIndex<VR>]> {
477 self.boundaries()
478 .map(|boundary| boundary.unique_vertex_indices(scratch))
479 }
480
481 #[must_use]
482 pub fn unique_coordinates<'a, V: Coordinate>(
483 &'a self,
484 vertices: &'a Vertices<VR, V>,
485 scratch: &'a mut Vec<VertexIndex<VR>>,
486 ) -> Option<BoundaryUniqueCoordinates<'a, VR, V>> {
487 self.boundaries()
488 .map(|boundary| boundary.unique_coordinates(vertices, scratch))
489 }
490
491 pub fn semantics(&self) -> Option<SemanticMapView<'_, VR>> {
492 self.inner
493 .semantics()
494 .map(|inner| SemanticMapView { inner })
495 }
496
497 pub fn materials(&self) -> Option<MaterialThemesView<'_, VR, SS>> {
498 self.inner
499 .materials()
500 .map(|items| MaterialThemesView { items })
501 }
502
503 pub fn textures(&self) -> Option<TextureThemesView<'_, VR, SS>> {
504 self.inner
505 .textures()
506 .map(|items| TextureThemesView { items })
507 }
508
509 pub fn instance(&self) -> Option<GeometryInstanceView<'_, VR>> {
510 self.inner
511 .instance()
512 .map(|inner| GeometryInstanceView { inner })
513 }
514}
515
516impl<'a, VR: VertexRef, SS: StringStorage> GeometryView<'a, VR, SS> {
517 pub(crate) fn from_geometry(
518 geometry: &'a Geometry<VR, SS>,
519 instance: Option<GeometryInstanceView<'a, VR>>,
520 ) -> Self {
521 Self { geometry, instance }
522 }
523
524 #[must_use]
525 pub fn geometry(&self) -> &'a Geometry<VR, SS> {
526 self.geometry
527 }
528
529 #[must_use]
530 pub fn instance(&self) -> Option<GeometryInstanceView<'a, VR>> {
531 self.instance
532 }
533}
534
535impl<VR: VertexRef, SS: StringStorage> Deref for GeometryView<'_, VR, SS> {
536 type Target = Geometry<VR, SS>;
537
538 fn deref(&self) -> &Self::Target {
539 self.geometry
540 }
541}