///|
fn scene_item(index : ModelIndex, product : Product) -> SceneItem {
let geometries = geometries_for_product(index, product)
let transform = product_transform(index, product)
let transformed = geometries.map(geometry => {
..geometry,
points: geometry.points.map(point => transform.apply(point)),
})
let bounds = transformed.fold(init=BoundingBox::empty(), (result, geometry) => {
merge_bounds(result, bounds_of_geometry(geometry))
})
{ product, geometries: transformed, transform, bounds }
}
///|
/// Build a renderer-neutral scene for WebBIM or other front ends.
pub fn build_scene(model : Model) -> BimScene {
let index = model.index()
let items = model
.products()
.filter(product => product.representation is Some(_))
.map(product => scene_item(index, product))
let bounds = items.fold(init=BoundingBox::empty(), (result, item) => {
merge_bounds(result, item.bounds)
})
{ items, roots: spatial_roots(index), bounds }
}
///|
pub fn BimScene::product_ids(self : BimScene) -> Array[Int] {
self.items.map(item => item.product.id)
}
///|
pub fn BimScene::find(self : BimScene, id : Int) -> SceneItem? {
for item in self.items {
if item.product.id == id {
return Some(item)
}
}
None
}
///|
pub fn BimScene::geometry_count(self : BimScene) -> Int {
self.items.fold(init=0, (count, item) => count + item.geometries.length())
}
///|
pub fn BimScene::to_json(self : BimScene) -> String {
let item_json = self.items.map(item => {
"{\"product\":" +
product_to_json(item.product) +
",\"transform\":[" +
item.transform.tx.to_string() +
"," +
item.transform.ty.to_string() +
"," +
item.transform.tz.to_string() +
"]" +
",\"geometry\":[" +
join_json(item.geometries.map(geometry_to_json)) +
"]}"
})
"{\"items\":[" +
join_json(item_json) +
"],\"bounds\":{\"min\":" +
point_json(self.bounds.min) +
",\"max\":" +
point_json(self.bounds.max) +
",\"empty\":" +
self.bounds.empty.to_string() +
"}}"
}