Skip to content

Instantly share code, notes, and snippets.

@giobel
Last active November 13, 2024 14:13
Show Gist options
  • Save giobel/08e254a4ee54c6f38425c4b6c93b450a to your computer and use it in GitHub Desktop.
Save giobel/08e254a4ee54c6f38425c4b6c93b450a to your computer and use it in GitHub Desktop.
# IFC files using XBim and Geometry Gym
/*
* Power BI Visual CLI
*
* Copyright (c) Microsoft Corporation
* All rights reserved.
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the ""Software""), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
"use strict";
import powerbi from "powerbi-visuals-api";
import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";
import "./../style/visual.less";
import * as THREE from 'three';
import * as OBC from 'openbim-components';
import { FragmentsGroup, Fragment } from 'bim-fragment';
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import { VisualFormattingSettingsModel } from "./settings";
export class Visual implements IVisual {
private target: HTMLElement;
private updateCount: number;
private textNode: Text;
private formattingSettings: VisualFormattingSettingsModel;
private formattingSettingsService: FormattingSettingsService;
private viewer: OBC.Components;
private fragMap: { [expressID: string]: {fragment: Fragment} } = {};
private guidToexpressIdMap: { [expressID: string]: number } = {};
private propertiesProcessor: OBC.IfcPropertiesProcessor;
private green : THREE.Color = new THREE.Color(0x5CC45C)
private red: THREE.Color = new THREE.Color(0xCC0000)
private highlighter: OBC.FragmentHighlighter
private tco2Values: {[ifcGuid: string]: {value: number, update: boolean}} = {}
private model: FragmentsGroup
private async LoadModel(filepath: string, viewer: OBC.Components, fragmentLoader:OBC.FragmentIfcLoader, fragmentManager: OBC.FragmentManager, scene: THREE.Scene, propertiesProcessor: OBC.IfcPropertiesProcessor){
try{
fragmentLoader.settings.wasm = {
path: "https://unpkg.com/[email protected]/",
absolute: true
}
fragmentLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
fragmentLoader.settings.webIfc.OPTIMIZE_PROFILES = true;
const file = await fetch(filepath);
console.log(file)
const data = await file.arrayBuffer();
console.log(data)
const buffer = new Uint8Array(data);
this.model = await fragmentLoader.load(buffer, 'test');
scene.add(this.model);
console.log('model', this.model)
propertiesProcessor.process(this.model)
const fragmentsGroup = fragmentManager.groups[0]
const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
for (const [key] of Object.entries(properties)) {
try{
//console.log(properties[parseInt(key)])
const {expressID, GlobalId} = properties[parseInt(key)];
if (expressID && GlobalId){
this.guidToexpressIdMap[GlobalId.value] = expressID
}
}
catch(error){
//console.log('error', error)
}
}
//console.log('guidExIdMap', this.guidToexpressIdMap)
for (const frag of fragmentsGroup.items){
//console.log(frag)
for (let index = 0; index < frag.items.length; index++) {
this.fragMap[frag.items[index]] = {fragment: frag}
}
}
//console.log('fragmap', this.fragMap)
return this.model
}
catch(error){
console.log('error', error)
}
}
constructor(options: VisualConstructorOptions) {
const host = options.host
const target = options.element
//#region create scene
const container = document.createElement( 'div' )
container.className = 'full-screen'
container.style.zIndex = '2000'
target.style.cursor = 'default'
target.appendChild( container )
this.viewer = new OBC.Components()
const sceneComponent = new OBC.SimpleScene(this.viewer)
sceneComponent.setup()
this.viewer.scene = sceneComponent
this.viewer.scene.get().background = new THREE.Color( 0xf3f3f7 );
const rendererComponent = new OBC.PostproductionRenderer(this.viewer, container)
this.viewer.renderer = rendererComponent
const postproduction = rendererComponent.postproduction
const cameraComponent = new OBC.OrthoPerspectiveCamera(this.viewer)
this.viewer.camera = cameraComponent
cameraComponent.controls.setLookAt( 10, 10, 10, 0, 0, 0 );
const raycasterComponent = new OBC.SimpleRaycaster(this.viewer)
this.viewer.raycaster = raycasterComponent
this.viewer.init()
cameraComponent.updateAspect()
postproduction.enabled = true
//const grid = new OBC.SimpleGrid(this.viewer, new THREE.Color(0x666666))
//postproduction.customEffects.excludedMeshes.push(grid.get())
const fragmentManager = new OBC.FragmentManager(this.viewer)
const ifcLoader = new OBC.FragmentIfcLoader(this.viewer)
// this.highlighter = new OBC.FragmentHighlighter(this.viewer)
// this.highlighter.setup()
// this.highlighter.add('notSelected', [new THREE.MeshStandardMaterial({color: 0x808080})])
this.propertiesProcessor = new OBC.IfcPropertiesProcessor(this.viewer)
// this.highlighter.events.select.onClear.add(() => {
// propertiesProcessor.cleanPropertiesList()
// })
//#endregion
const mainToolbar = new OBC.Toolbar(this.viewer)
mainToolbar.addChild(
this.propertiesProcessor.uiElement.get("main")
)
this.viewer.ui.addToolbar(mainToolbar)
this.LoadModel('http://localhost:5173/CSW-2200-crop.ifc', this.viewer, ifcLoader, fragmentManager, this.viewer.scene.get(), this.propertiesProcessor)
}
private async addColor(highlighter: OBC.FragmentHighlighter, percentage: number, fragMap: OBC.FragmentIdMap){
await highlighter.highlightByID(percentage.toString(), fragMap, true, true)
}
public update(options: VisualUpdateOptions) {
console.log('update')
console.log(this.highlighter)
if (this.highlighter){
console.log('dispose highlighter')
//this.highlighter.dispose();
this.highlighter.clear();
}
console.log('viewer', this.viewer)
this.highlighter = new OBC.FragmentHighlighter(this.viewer)
this.highlighter.setup()
this.highlighter.update()
console.log(this.highlighter)
try{
this.highlighter.events.select.onHighlight.add((selection) => {
const fragmentID = Object.keys(selection)[0]
const expressID = Number([...selection[fragmentID]][0])
this.propertiesProcessor.renderProperties(this.model, expressID)
})
this.highlighter.update()
this.highlighter.add('notSelected', [new THREE.MeshStandardMaterial({color: 0x808080})])
this.highlighter.events.select.onClear.add(() => {
this.propertiesProcessor.cleanPropertiesList()
})
}
catch(error){console.log(error)}
//console.log('Visual update', options);
//this.highlighter.clear()
// const propertiesProcessor = new OBC.IfcPropertiesProcessor(this.viewer)
// this.highlighter.events.select.onClear.add(() => {
// propertiesProcessor.cleanPropertiesList()
// })
let dataViews = options.dataViews;
console.log('datavview', dataViews)
let categorical = dataViews[0].categorical;
let guids = <string[]>categorical.categories[0].values;
let tco2 = <number[]>categorical.values[0].values;
let volumes = <number[]>categorical.values[1].values;
//const tco2Values: {[ifcGuid: string]: {value: number, update: boolean}} = {}
for (let index = 0; index < tco2.length; index++) {
//console.log(data)
const tco2value = tco2[index]* volumes[index]
if (!this.tco2Values[guids[index]]){
this.tco2Values[guids[index]] = {value:tco2value, update:true}
}
}
let tco2Max = 0
for (const key in this.tco2Values) {
if (this.tco2Values[key].value > tco2Max) {
tco2Max = this.tco2Values[key].value;
}
}
for (let index = 0; index < guids.length; index++) {
const expressID = this.guidToexpressIdMap[guids[index]];
if (expressID){
const foundItem = Object.entries(this.fragMap).find(([x]) => x === String(expressID));
console.log(foundItem)
const percentage = tco2[index]*volumes[index]/(tco2Max)
//console.log(percentage)
const colorT = new THREE.Color()
colorT.lerpColors(this.green, this.red, percentage)
const existingMaterial = this.highlighter.highlightMats[percentage.toString()]
if (!existingMaterial){
this.highlighter.add(percentage.toString(), [new THREE.MeshStandardMaterial({color: colorT})])
}
const {fragment} = foundItem[1]
const fragmentmap: OBC.FragmentIdMap = {}
fragmentmap[fragment.id] = new Set<string>();
fragmentmap[fragment.id].add(expressID.toString())
//console.log('guid', item[0])
//console.log('fid map', mybeam)
this.addColor(this.highlighter, percentage, fragmentmap)
//this.highlighter.highlightByID(percentage.toString(), fragmentmap, true, true)
}
}
/*
for (const guid of Object.entries(this.tco2Values)){
console.log('guid', guid[0])
if (guids.includes(guid[0])){
//update
this.tco2Values[guid[0]].update = true
//console.log('update')
}
else{
//do not update
//console.log('not update')
this.tco2Values[guid[0]].update = false
}
}
console.log('guid', guids)
console.log('guidmap', this.guidToexpressIdMap)
console.log(this.tco2Values)
//this.highlighter.clear();
for (const item of Object.entries(this.tco2Values)){
const expressID = this.guidToexpressIdMap[item[0]];
if (expressID){
const foundItem = Object.entries(this.fragMap).find(([x]) => x === String(expressID));
if (item[1].update){
console.log(foundItem)
const percentage = item[1].value/(tco2Max)
//console.log(percentage)
const colorT = new THREE.Color()
colorT.lerpColors(this.green, this.red, percentage)
const existingMaterial = this.highlighter.highlightMats[percentage.toString()]
//console.log('ex material', existingMaterial)
if (!existingMaterial){
this.highlighter.add(percentage.toString(), [new THREE.MeshStandardMaterial({color: colorT})])
}
const {fragment} = foundItem[1]
const mybeam: OBC.FragmentIdMap = {}
mybeam[fragment.id] = new Set<string>();
mybeam[fragment.id].add(expressID.toString())
//console.log('guid', item[0])
//console.log('fid map', mybeam)
this.highlighter.highlightByID(percentage.toString(), mybeam, true, true)
}
else{
//console.log('grey color')
const {fragment} = foundItem[1]
const mybeam: OBC.FragmentIdMap = {}
mybeam[fragment.id] = new Set<string>();
mybeam[fragment.id].add(expressID.toString())
//this.highlighter.highlightByID('notSelected', mybeam, true, true)
//this.highlighter.fillEnabled = false
}
}
}
*/
//this.highlighter.update()
//this.viewer.scene.get().updateMatrix()
console.log('done')
console.log(this.highlighter)
}
}
XbimPoint3D minPt = new XbimPoint3D(-45700, -27800, -10000);
XbimPoint3D maxPt = new XbimPoint3D(-32732, 0, 1000);
XbimRect3D selBox = new XbimRect3D(minPt,maxPt); //bounding box you need
foreach (var instance in instances)
{
var transfor = instance.Transformation; //Transformation matrix (location point inside)
XbimShapeGeometry geometry = context.ShapeGeometry(instance); //Instance's geometry
XbimRect3D box = geometry.BoundingBox; //bounding box you need
var wcsbox = box.Transform(transfor);
if (selBox.Intersects(wcsbox))
{
Console.WriteLine($"#{instance.IfcProductLabel} Intersects!");
}
}
//https://stackoverflow.com/questions/56596815/how-to-retrieve-geometry-from-ifc-file-using-xbim-or-is-there-anyother-alterna
using (var model = IfcStore.Open("ifc_file.ifc"))
{
Xbim3DModelContext context = new Xbim3DModelContext(model);
context.CreateContext();
List<XbimShapeGeometry> geometrys = context.ShapeGeometries().ToList();
List<XbimShapeInstance> instances = context.ShapeInstances().ToList();
//Check all the instances
foreach (var instance in instances)
{
var transfor = instance.Transformation; //Transformation matrix (location point inside)
XbimShapeGeometry geometry = context.ShapeGeometry(instance); //Instance's geometry
XbimRect3D box = geometry.BoundingBox; //bounding box you need
var wcsbox = box.Transform(transfor);
byte[] datas = ((IXbimShapeGeometryData)geometry).ShapeData;
Console.WriteLine($"item #{instance.IfcProductLabel} shape geo label {instance.ShapeGeometryLabel} " +
$" loc: min {wcsbox.Min} max {wcsbox.Max}");
XbimRect3D box = geometry.BoundingBox; //bounding box you need
byte[] data = ((IXbimShapeGeometryData)geometry).ShapeData;
//If you want to get all the faces and trinagulation use this
using (var stream = new MemoryStream(data))
{
using (var reader = new BinaryReader(stream))
{
var mesh = reader.ReadShapeTriangulation();
List<XbimFaceTriangulation> faces = mesh.Faces as List<XbimFaceTriangulation>;
List<XbimPoint3D> vertices = mesh.Vertices as List<XbimPoint3D>;
}
}
}
}
//https://github.com/xBimTeam/XbimEssentials/issues/340#issuecomment-649715537
using Xbim.Common;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
// snip
var fileName="your.ifc";
using (var model = IfcStore.Open(fileName))
{
IEnumerable<int> matchingElements = from i in model.Instances.OfType<IIfcRelDefinesByProperties>()
// Find all properties in Pset called 'Dimensions' with 'Area' > 20.5
where i.RelatingPropertyDefinition is IIfcPropertySet
let pset = i.RelatingPropertyDefinition as IIfcPropertySet
where pset.Name == "Dimensions"
let property = pset.HasProperties.OfType<IIfcPropertySingleValue>().FirstOrDefault(v => v.Name == "Area")
where property?.NominalValue is IExpressRealType
where ((IExpressRealType)property.NominalValue).Value > 20.5d
// Now get the elements
from element in i.RelatedObjects
select element.EntityLabel;
}
# IFC creation using Geometry Gym
using GeometryGym.Ifc;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows;
namespace CreatePiles
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DatabaseIfc db = new DatabaseIfc(ModelView.Ifc2x3Coordination);
IfcSite site = new IfcSite(db, "Site01");
IfcLocalPlacement locPlace = site.ObjectPlacement as IfcLocalPlacement;
IfcAxis2Placement3D wcsPlace = locPlace.RelativePlacement as IfcAxis2Placement3D;
wcsPlace.Location = new IfcCartesianPoint(db, 1000, 2000, 300);
wcsPlace.Axis = new IfcDirection(db, 0, 0, 1);
wcsPlace.RefDirection = new IfcDirection(db, 1, 0, 0);
IfcProject project = new IfcProject(site, "IfcProject", IfcUnitAssignment.Length.Metre) { };
IfcBuilding building = new IfcBuilding(site, "Station") { };
IfcBuildingStorey storey = new IfcBuildingStorey(building, "Base Level", 0);
List<IfcProperty> properties = new List<IfcProperty>();
//PROPERTIES WILL BE THE SAME FOR ALL PILES
//IfcPropertySingleValue psv = new IfcPropertySingleValue(db, "Is Constructed", new IfcBoolean(false));
//properties.Add(psv);
//IfcPropertySingleValue psv2 = new IfcPropertySingleValue(db, "Material", "Concrete");
//properties.Add(psv2);
//IfcPropertySingleValue psv1 = new IfcPropertySingleValue(db, "Pile Name", "Placeholder");
//properties.Add(psv1);
//this way the property is the same for all piles (can't edit single pile value)
//IfcPropertySingleValue constructProperty = new IfcPropertySingleValue(db, "Is Constructed", new IfcBoolean(false));
List<Pile> piles = new List<Pile>();
using (var reader = new StreamReader(this.inputCsvFile.Text))
{
string headerLine = reader.ReadLine();
string line;
while ((line = reader.ReadLine()) != null)
{
if ( line != "")
{
var values = line.Split(',');
piles.Add(new Pile(values[0], int.Parse(values[1]), double.Parse(values[2]), double.Parse(values[3]), double.Parse(values[4]), double.Parse(values[5])));
}
}
}
IfcMaterial mat = new IfcMaterial(db, "Steel");
IfcProfileDef pdef = new IfcProfileDef(db, "150UC37.2");
IfcMaterialProfile matProf = new IfcMaterialProfile("150UC", mat, pdef);
//IfcColumnStandardCase col = new IfcColumnStandardCase(db, new IfcMaterialProfileSetUsage())
List<IfcPile> ifcpiles = new List<IfcPile>();
foreach (Pile item in piles)
{
IfcExtrudedAreaSolid extrudedAreaSolid = new IfcExtrudedAreaSolid(new IfcCircleProfileDef(db, $"D{item.Diameter}", item.Diameter*0.0005), item.Length);
IfcProductDefinitionShape productDefinitionShape = new IfcProductDefinitionShape(new IfcShapeRepresentation(extrudedAreaSolid));
IfcObjectPlacement placement = new IfcLocalPlacement(
new IfcAxis2Placement3D(
new IfcCartesianPoint(db, item.Easting, item.Northings, item.CutOffLevel)
)
);
placement.PlacementRelTo = site.ObjectPlacement;
//building container
//IfcPile pile = new IfcPile(building, placement, productDefinitionShape);
//or storey container
IfcPile pile = new IfcPile(storey, placement, productDefinitionShape);
pile.Name = item.Name;
pile.Description = $"A bored {item.Diameter} dia pile";
pile.ConstructionType = IfcPileConstructionEnum.BORED;
ifcpiles.Add(pile);
IfcPropertySet pilePSet = new IfcPropertySet(pile, "SEPA");
pilePSet.AddProperty(new IfcPropertySingleValue(db, "Pile Name", item.Name));
pilePSet.AddProperty(new IfcPropertySingleValue(db, "Diameter", item.Diameter));
//pilePSet.AddProperty(constructProperty); //this way the property is the same for all piles (can't edit single pile value)
pilePSet.AddProperty(new IfcPropertySingleValue(db, "Is Constructed", new IfcBoolean(false)));
//new IfcRelDefinesByProperties(pile, pilePSet);
//IfcPropertySet pilePSet = pile.FindPropertySet("SEPA") as IfcPropertySet;
// IfcPropertySingleValue pileNameProp = pilePSet.FindProperty("Pile Name") as IfcPropertySingleValue;
// pileNameProp.NominalValue.Value = item.Name;
//IfcPropertySingleValue psv1 = new IfcPropertySingleValue(db, "Name", pile.Name);
//properties.Add(psv1);
}
//foreach (IfcPile pile in ifcpiles)
//{
// IfcPropertySet pilePSet = pile.FindPropertySet("SEPA") as IfcPropertySet;
// pilePSet.AddProperty(constructProperty);
//}
db.WriteFile(this.outputFolder.Text);
System.Diagnostics.Process.Start(this.outputFolder.Text);
}
}
internal class Pile
{
public string Name { get; set; }
public int Diameter { get; set; }
public double Easting { get; set; }
public double Northings { get; set; }
public double CutOffLevel { get; set; }
public double Length { get; set; }
public Pile(string Name, int Diameter, double Easting, double Northern, double CutOffLevel, double Length)
{
this.Name = Name;
this.Diameter = Diameter;
this.Easting = Easting;
this.Northings = Northern;
this.CutOffLevel = CutOffLevel;
this.Length = Length;
}
}
}
import os
import ifcopenshell
import trimesh
import numpy as np
def get_ifc_files(directory):
# List all files in the directory
files = os.listdir(directory)
# Filter only .ifc files
ifc_files = [file for file in files if file.lower().endswith('.ifc')]
return ifc_files
def extract_local_placement_and_point(ifc_file):
# Look for entities of type IfcLocalPlacement
local_placements = ifc_file.by_type("IfcLocalPlacement")
if not local_placements:
print("No IfcLocalPlacement found in the file.")
return None
# Iterate through each IfcLocalPlacement entity
for local_placement in local_placements:
# Get the relative placement (it should contain an IfcAxis2Placement3D or IfcCartesianPoint)
relative_placement = local_placement.RelativePlacement
if relative_placement and hasattr(relative_placement, "Location"):
# Extract the location (If it's an IfcCartesianPoint, you get the coordinates)
location = relative_placement.Location
if location and location.is_a("IfcCartesianPoint"):
# Extract the Cartesian coordinates
x = location.Coordinates[0]
y = location.Coordinates[1]
z = location.Coordinates[2] if len(location.Coordinates) > 2 else 0.0 # Default Z to 0 if missing
result = f"LocalPlacement Location: X={x}, Y={y}, Z={z}"
#print(f"LocalPlacement Location: X={x}, Y={y}, Z={z}")
return result
print("No IfcCartesianPoint found in any IfcLocalPlacement.")
return None
allFiles = get_ifc_files(folder)
for fileName in allFiles:
ifc_file = ifcopenshell.open(folder+'\\'+fileName)
products = ifc_file.by_type("IfcProduct")
for p in products:
type = ifcopenshell.util.element.get_type(p)
print (type)
psets = ifcopenshell.util.element.get_psets(p)
pset = ifcopenshell.util.element.get_pset(p, 'BaseQuantities')['NetVolume']
print (pset)
break
site = None
for s in ifc_file.by_type("IfcSite"):
site = s
break # Assuming there's only one site in the file, you can remove this if multiple sites exist
if site is None:
print("No IfcSite found in the file.")
geographic_location = site.get_info(True)['ObjectPlacement']
local_placements = extract_local_placement_and_point(ifc_file)
print (fileName + " " + local_placements)
break
import React from 'react'
import * as OBC from "openbim-components"
import * as THREE from "three"
import { Fragment } from "bim-fragment";
import { color } from 'three/examples/jsm/nodes/Nodes.js';
const TCdata =[
{
"modelId": "C731KCVe5oA",
"trimbleid": 22,
"ifcGUID": "069xHa4Sv9FgrxXmVtail0",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.303"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 23,
"ifcGUID": "069xHa4Sv9FgrxXmVtail7",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 24,
"ifcGUID": "069xHa4Sv9FgrxXmVtail6",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 26,
"ifcGUID": "069xHa4Sv9FgrxXmVtail5",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 27,
"ifcGUID": "069xHa4Sv9FgrxXmVtail4",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 28,
"ifcGUID": "069xHa4Sv9FgrxXmVtaiWx",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 29,
"ifcGUID": "069xHa4Sv9FgrxXmVtaiWw",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 14,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO2",
"mixType": "VR535/65",
"supplier": "Holcim",
"tCO2_m3": 0.4269,
"volume": "1.375"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 6,
"ifcGUID": "0yzQgqfmjFMxAsJeeoKgk8",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.925"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 2,
"ifcGUID": "23Rn8oK6XBKPC0kMTttlFx",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.447"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 15,
"ifcGUID": "3sVk1mOwbExhUkvilYAT62",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 17,
"ifcGUID": "0zIVzQ4GT9fPRoeUGfzqp9",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 18,
"ifcGUID": "0hzINTH11819vAcsaJSN$l",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 20,
"ifcGUID": "2ouI1mE9P6Hhdor6$1lFOE",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.101"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 41,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJu",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 16,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$VW",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 19,
"ifcGUID": "3SAVs4fkT0Bh2MxZMwdX$q",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 33,
"ifcGUID": "1ipwC82Hr6k8quZdAck27W",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 0,
"ifcGUID": "25lA26vsP69AU1XNSA6bZE",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.661"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 25,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vc",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 30,
"ifcGUID": "1WXgstI7f79x6VgYVpMKIS",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 34,
"ifcGUID": "2_1uf7JOL7kgdbGPYR48fO",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 42,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJw",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 7,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO6",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.658"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 43,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJy",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 35,
"ifcGUID": "2GbIojRS95lPgC6muSNFgp",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 3,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO4",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.499"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 21,
"ifcGUID": "1Y5QF84jv6zRGMNAWgjJGp",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 5,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Va",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 4,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJ_",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 31,
"ifcGUID": "1cfv5D7f982g2IBjUwZ2xm",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 1,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vg",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 36,
"ifcGUID": "0nuO8mIVb0NAE6UWMLiNBV",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 8,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOu",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.496"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 44,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQI0",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 9,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOw",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.496"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 10,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Ve",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 37,
"ifcGUID": "3qAzL9s393lPXc6mKQLZR2",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 40,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQI2",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 39,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vk",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 38,
"ifcGUID": "1aZNOaxOL7R9Gvdm6ceIqB",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 12,
"ifcGUID": "0fu1_CJJbCheMhMp09uGsj",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 32,
"ifcGUID": "1rwepkfnH3ngdBK4L$ZWGI",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 11,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO_",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.497"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 13,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOy",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.377"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 45,
"ifcGUID": "1veR3NRpjCYQOtDyFkigty",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.067"
}
]
const green = new THREE.Color(0x5CC45C)
const red = new THREE.Color(0xCC0000)
console.log(green, red)
export default () => {
const [modelCount, setModelCount] = React.useState(0)
function getRandomColor() {
return new THREE.Color(Math.random(), Math.random(), Math.random());
}
const tco2Values: {[ifcGuid: string]: number} = {}
for (const data of TCdata){
//console.log(data)
const tco2 = data.tCO2_m3* Number.parseFloat(data.volume)
tco2Values[data.ifcGUID] = tco2
}
//const tco2Min = Math.min(...Object.values(tco2Values))
const tco2Max = Math.max(...Object.values(tco2Values))
React.useEffect(() => {
const viewer = new OBC.Components()
const sceneComponent = new OBC.SimpleScene(viewer)
sceneComponent.setup()
viewer.scene = sceneComponent
const viewerContainer = document.getElementById("viewerContainer") as HTMLDivElement
const rendererComponent = new OBC.PostproductionRenderer(viewer, viewerContainer)
viewer.renderer = rendererComponent
const postproduction = rendererComponent.postproduction
const cameraComponent = new OBC.OrthoPerspectiveCamera(viewer)
viewer.camera = cameraComponent
const raycasterComponent = new OBC.SimpleRaycaster(viewer)
viewer.raycaster = raycasterComponent
viewer.init()
cameraComponent.updateAspect()
postproduction.enabled = true
const grid = new OBC.SimpleGrid(viewer, new THREE.Color(0x666666))
postproduction.customEffects.excludedMeshes.push(grid.get())
const fragmentManager = new OBC.FragmentManager(viewer)
const ifcLoader = new OBC.FragmentIfcLoader(viewer)
const highlighter = new OBC.FragmentHighlighter(viewer)
highlighter.setup()
const propertiesProcessor = new OBC.IfcPropertiesProcessor(viewer)
highlighter.events.select.onClear.add(() => {
propertiesProcessor.cleanPropertiesList()
})
const fragmentClassifier = new OBC.FragmentClassifier(viewer)
const guidToexpressIdMap: { [expressID: string]: number } = {};
async function loadIfcAsFragments(path: string, ifcLoader : OBC.FragmentIfcLoader, scene: THREE.Scene) {
const file = await fetch(path);
//console.log(file)
const data = await file.arrayBuffer();
//console.log(data)
const buffer = new Uint8Array(data);
const model = await ifcLoader.load(buffer, 'test');
scene.add(model);
console.log('model', model)
setModelCount(fragmentManager.groups.length)
propertiesProcessor.process(model)
highlighter.events.select.onHighlight.add((selection) => {
const fragmentID = Object.keys(selection)[0]
const expressID = Number([...selection[fragmentID]][0])
propertiesProcessor.renderProperties(model, expressID)
})
highlighter.update()
//fragmentClassifier.byEntity(model)
//console.log('fra group', fragmentsGroup)
//const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
//console.log(properties)
//fragmentClassifier.byModel(model.id.toString(), fragmentsGroup)
//fragmentClassifier.byPredefinedType(fragmentsGroup)
//const entities = fragmentClassifier.get().entities
//console.log('entities', entities)
//console.log('slab', entities['IFCSLAB'])
// for (const entity in entities){
// console.log('entity', entity)
// highlighter.add(entity, [new THREE.MeshStandardMaterial({color: getRandomColor()})])
// console.log('ee', entities[entity])
// highlighter.highlightByID(entity, entities[entity], true)
// }
//MAP IFC GUID TO EXPRESSID
const fragmentsGroup = fragmentManager.groups[0]
const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
for (const [key] of Object.entries(properties)) {
try{
//console.log(properties[parseInt(key)])
const {expressID, GlobalId} = properties[parseInt(key)];
if (expressID && GlobalId){
guidToexpressIdMap[GlobalId.value] = expressID
}
}
catch{}
}
console.log('pmasp', guidToexpressIdMap)
const fragment = fragmentManager.list;
//console.log('fragment', fragment)
const f = fragmentsGroup.items[0]
//console.log('f', f)
const mybeam: OBC.FragmentIdMap = {}
mybeam[f.id] = new Set<string>();
mybeam[f.id].add("3010");
mybeam[f.id].add("2946");
mybeam[f.id].add("138");
mybeam[f.id].add("1603");
console.log(mybeam)
// highlighter.add('slab-material', [new THREE.MeshStandardMaterial({color: red})])
// highlighter.highlightByID('slab-material', mybeam, true)
const fragMap: { [expressID: string]: {fragment: Fragment} } = {};
for (const frag of fragmentsGroup.items){
//console.log(frag)
for (let index = 0; index < frag.items.length; index++) {
fragMap[frag.items[index]] = {fragment: frag}
}
}
console.log('tc values', tco2Values)
console.log(tco2Max)
for (const item of Object.entries(tco2Values)){
console.log('item', item)
const expressID = guidToexpressIdMap[item[0]];
if (expressID){
const foundItem = Object.entries(fragMap).find(([x]) => x === String(expressID));
console.log(foundItem)
if (foundItem){
//item co2 value/max co2 value
const percentage = item[1]/tco2Max
console.log(percentage)
const colorT = new THREE.Color()
colorT.lerpColors(green, red, percentage)
console.log(colorT)
highlighter.add(percentage.toString(), [new THREE.MeshStandardMaterial({color: colorT})])
const {fragment} = foundItem[1]
const mybeam: OBC.FragmentIdMap = {}
mybeam[fragment.id] = new Set<string>();
mybeam[fragment.id].add(expressID.toString())
highlighter.highlightByID(percentage.toString(), mybeam, true)
console.log(fragment)
}
}
}
return model
}
//const path = 'http://localhost:5173/small.ifc'
//const path = 'http://localhost:5173/SBS-2322.ifc'
//const path = 'http://localhost:5173/DETACHED.ifc'
const path = 'http://localhost:5173/CSW-2200-crop.ifc'
//const path = 'http://localhost:5173/SEP-084-C-SEPA-MOD-13-RWE-CSW-2200_IFC.ifc'
loadIfcAsFragments(path, ifcLoader, viewer.scene.get())
const mainToolbar = new OBC.Toolbar(viewer)
mainToolbar.addChild(
ifcLoader.uiElement.get("main"),
propertiesProcessor.uiElement.get("main")
)
viewer.ui.addToolbar(mainToolbar)
}, [])
const viewerContainerStyle: React.CSSProperties = {
width: "100%",
height: "100%",
position: "relative",
gridArea: "viewer"
}
const titleStyle: React.CSSProperties = {
position: "absolute",
top: "15px",
left: "15px"
}
return (
<>
<div id="viewerContainer" style={viewerContainerStyle}>
<h3 style={titleStyle}>Models loaded: {modelCount}</h3>
</div>
</>
)
}
import React from 'react'
import * as OBC from "openbim-components"
import * as THREE from "three"
import { Fragment } from "bim-fragment";
import { color } from 'three/examples/jsm/nodes/Nodes.js';
const TCdata =[
{
"modelId": "C731KCVe5oA",
"trimbleid": 22,
"ifcGUID": "069xHa4Sv9FgrxXmVtail0",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.303"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 23,
"ifcGUID": "069xHa4Sv9FgrxXmVtail7",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 24,
"ifcGUID": "069xHa4Sv9FgrxXmVtail6",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 26,
"ifcGUID": "069xHa4Sv9FgrxXmVtail5",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 27,
"ifcGUID": "069xHa4Sv9FgrxXmVtail4",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 28,
"ifcGUID": "069xHa4Sv9FgrxXmVtaiWx",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 29,
"ifcGUID": "069xHa4Sv9FgrxXmVtaiWw",
"mixType": "VR450/50",
"supplier": "Holcim",
"tCO2_m3": 0.3594,
"volume": "1.209"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 14,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO2",
"mixType": "VR535/65",
"supplier": "Holcim",
"tCO2_m3": 0.4269,
"volume": "1.375"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 6,
"ifcGUID": "0yzQgqfmjFMxAsJeeoKgk8",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.925"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 2,
"ifcGUID": "23Rn8oK6XBKPC0kMTttlFx",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.447"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 15,
"ifcGUID": "3sVk1mOwbExhUkvilYAT62",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 17,
"ifcGUID": "0zIVzQ4GT9fPRoeUGfzqp9",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 18,
"ifcGUID": "0hzINTH11819vAcsaJSN$l",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.444"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 20,
"ifcGUID": "2ouI1mE9P6Hhdor6$1lFOE",
"mixType": "VR400/40",
"supplier": "Holcim",
"tCO2_m3": 0.1886,
"volume": "1.101"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 41,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJu",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 16,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$VW",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 19,
"ifcGUID": "3SAVs4fkT0Bh2MxZMwdX$q",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 33,
"ifcGUID": "1ipwC82Hr6k8quZdAck27W",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 0,
"ifcGUID": "25lA26vsP69AU1XNSA6bZE",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.661"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 25,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vc",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 30,
"ifcGUID": "1WXgstI7f79x6VgYVpMKIS",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 34,
"ifcGUID": "2_1uf7JOL7kgdbGPYR48fO",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 42,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJw",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 7,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO6",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.658"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 43,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJy",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 35,
"ifcGUID": "2GbIojRS95lPgC6muSNFgp",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 3,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO4",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.499"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 21,
"ifcGUID": "1Y5QF84jv6zRGMNAWgjJGp",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 5,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Va",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 4,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQJ_",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 31,
"ifcGUID": "1cfv5D7f982g2IBjUwZ2xm",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 1,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vg",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 36,
"ifcGUID": "0nuO8mIVb0NAE6UWMLiNBV",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 8,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOu",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.496"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 44,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQI0",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 9,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOw",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.496"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 10,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Ve",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 37,
"ifcGUID": "3qAzL9s393lPXc6mKQLZR2",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 40,
"ifcGUID": "32iTgiIfbBMg2gdvFyEQI2",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.016"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 39,
"ifcGUID": "0I6OWAUgTE0RT3HTt6e$Vk",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 38,
"ifcGUID": "1aZNOaxOL7R9Gvdm6ceIqB",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.005"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 12,
"ifcGUID": "0fu1_CJJbCheMhMp09uGsj",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 32,
"ifcGUID": "1rwepkfnH3ngdBK4L$ZWGI",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.000"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 11,
"ifcGUID": "0V8JK1XRr2yBilET5mpIO_",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.497"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 13,
"ifcGUID": "0V8JK1XRr2yBilET5mpIOy",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.377"
},
{
"modelId": "C731KCVe5oA",
"trimbleid": 45,
"ifcGUID": "1veR3NRpjCYQOtDyFkigty",
"mixType": "VR400/40",
"supplier": "Boral",
"tCO2_m3": 0.2906,
"volume": "0.067"
}
]
const green = new THREE.Color(0x5CC45C)
const red = new THREE.Color(0xCC0000)
console.log(green, red)
export default () => {
const [modelCount, setModelCount] = React.useState(0)
function getRandomColor() {
return new THREE.Color(Math.random(), Math.random(), Math.random());
}
const tco2Values: {[ifcGuid: string]: number} = {}
for (const data of TCdata){
//console.log(data)
const tco2 = data.tCO2_m3* Number.parseFloat(data.volume)
tco2Values[data.ifcGUID] = tco2
}
//const tco2Min = Math.min(...Object.values(tco2Values))
const tco2Max = Math.max(...Object.values(tco2Values))
React.useEffect(() => {
const viewer = new OBC.Components()
const sceneComponent = new OBC.SimpleScene(viewer)
sceneComponent.setup()
viewer.scene = sceneComponent
const viewerContainer = document.getElementById("viewerContainer") as HTMLDivElement
const rendererComponent = new OBC.PostproductionRenderer(viewer, viewerContainer)
viewer.renderer = rendererComponent
const postproduction = rendererComponent.postproduction
const cameraComponent = new OBC.OrthoPerspectiveCamera(viewer)
viewer.camera = cameraComponent
const raycasterComponent = new OBC.SimpleRaycaster(viewer)
viewer.raycaster = raycasterComponent
viewer.init()
cameraComponent.updateAspect()
postproduction.enabled = true
const grid = new OBC.SimpleGrid(viewer, new THREE.Color(0x666666))
postproduction.customEffects.excludedMeshes.push(grid.get())
const fragmentManager = new OBC.FragmentManager(viewer)
const ifcLoader = new OBC.FragmentIfcLoader(viewer)
const highlighter = new OBC.FragmentHighlighter(viewer)
highlighter.setup()
const propertiesProcessor = new OBC.IfcPropertiesProcessor(viewer)
highlighter.events.select.onClear.add(() => {
propertiesProcessor.cleanPropertiesList()
})
//const fragmentClassifier = new OBC.FragmentClassifier(viewer)
const guidToexpressIdMap: { [expressID: string]: number } = {};
async function loadIfcAsFragments(path: string, ifcLoader : OBC.FragmentIfcLoader, scene: THREE.Scene) {
const file = await fetch(path);
//console.log(file)
const data = await file.arrayBuffer();
//console.log(data)
const buffer = new Uint8Array(data);
const model = await ifcLoader.load(buffer, 'test');
scene.add(model);
console.log('model', model)
setModelCount(fragmentManager.groups.length)
propertiesProcessor.process(model)
highlighter.events.select.onHighlight.add((selection) => {
const fragmentID = Object.keys(selection)[0]
const expressID = Number([...selection[fragmentID]][0])
propertiesProcessor.renderProperties(model, expressID)
})
highlighter.update()
//fragmentClassifier.byEntity(model)
//console.log('fra group', fragmentsGroup)
//const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
//console.log(properties)
//fragmentClassifier.byModel(model.id.toString(), fragmentsGroup)
//fragmentClassifier.byPredefinedType(fragmentsGroup)
//const entities = fragmentClassifier.get().entities
//console.log('entities', entities)
//console.log('slab', entities['IFCSLAB'])
// for (const entity in entities){
// console.log('entity', entity)
// highlighter.add(entity, [new THREE.MeshStandardMaterial({color: getRandomColor()})])
// console.log('ee', entities[entity])
// highlighter.highlightByID(entity, entities[entity], true)
// }
//MAP IFC GUID TO EXPRESSID
const fragmentsGroup = fragmentManager.groups[0]
const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
for (const [key] of Object.entries(properties)) {
try{
//console.log(properties[parseInt(key)])
const {expressID, GlobalId} = properties[parseInt(key)];
if (expressID && GlobalId){
guidToexpressIdMap[GlobalId.value] = expressID
}
}
catch{}
}
console.log('pmasp', guidToexpressIdMap)
const fragment = fragmentManager.list;
//console.log('fragment', fragment)
const f = fragmentsGroup.items[0]
//console.log('f', f)
const mybeam: OBC.FragmentIdMap = {}
mybeam[f.id] = new Set<string>();
mybeam[f.id].add("3010");
mybeam[f.id].add("2946");
mybeam[f.id].add("138");
mybeam[f.id].add("1603");
console.log(mybeam)
// highlighter.add('slab-material', [new THREE.MeshStandardMaterial({color: red})])
// highlighter.highlightByID('slab-material', mybeam, true)
const fragMap: { [expressID: string]: {fragment: Fragment} } = {};
for (const frag of fragmentsGroup.items){
//console.log(frag)
for (let index = 0; index < frag.items.length; index++) {
fragMap[frag.items[index]] = {fragment: frag}
}
}
console.log('tc values', tco2Values)
console.log(tco2Max)
for (const item of Object.entries(tco2Values)){
console.log('item', item)
const expressID = guidToexpressIdMap[item[0]];
if (expressID){
const foundItem = Object.entries(fragMap).find(([x]) => x === String(expressID));
console.log(foundItem)
if (foundItem){
//item co2 value/max co2 value
const percentage = item[1]/tco2Max
console.log(percentage)
const colorT = new THREE.Color()
colorT.lerpColors(green, red, percentage)
console.log(colorT)
highlighter.add(percentage.toString(), [new THREE.MeshStandardMaterial({color: colorT})])
const {fragment} = foundItem[1]
const mybeam: OBC.FragmentIdMap = {}
mybeam[fragment.id] = new Set<string>();
mybeam[fragment.id].add(expressID.toString())
highlighter.highlightByID(percentage.toString(), mybeam, true)
console.log(fragment)
}
}
}
return model
}
//const path = 'http://localhost:5173/small.ifc'
//const path = 'http://localhost:5173/SBS-2322.ifc'
//const path = 'http://localhost:5173/DETACHED.ifc'
const path = 'http://localhost:5173/CSW-2200-crop.ifc'
//const path = 'http://localhost:5173/SEP-084-C-SEPA-MOD-13-RWE-CSW-2200_IFC.ifc'
loadIfcAsFragments(path, ifcLoader, viewer.scene.get())
const mainToolbar = new OBC.Toolbar(viewer)
mainToolbar.addChild(
ifcLoader.uiElement.get("main"),
propertiesProcessor.uiElement.get("main")
)
viewer.ui.addToolbar(mainToolbar)
}, [])
const viewerContainerStyle: React.CSSProperties = {
width: "100%",
height: "100%",
position: "relative",
gridArea: "viewer"
}
const titleStyle: React.CSSProperties = {
position: "absolute",
top: "15px",
left: "15px"
}
return (
<>
<div id="viewerContainer" style={viewerContainerStyle}>
<h3 style={titleStyle}>Models loaded: {modelCount}</h3>
</div>
</>
)
}
import React from 'react'
import * as OBC from "openbim-components"
import * as THREE from "three"
import { Fragment } from "bim-fragment";
const TCdata = [
{
"modelId": "O96YRmBUFIk",
"id": 92,
"ifcGUID": "20Kz1qluL2Wg558svTerh7",
"materialName": "Holcim",
"kgCO2eq": 5047,
"volume": "5.600"
},
{
"modelId": "O96YRmBUFIk",
"id": 95,
"ifcGUID": "20Kz1qluL2Wg558svTereQ",
"materialName": "Holcim",
"kgCO2eq": 5047,
"volume": "5.600"
},
{
"modelId": "O96YRmBUFIk",
"id": 96,
"ifcGUID": "20Kz1qluL2Wg558svTerf7",
"materialName": "Holcim",
"kgCO2eq": 5047,
"volume": "5.600"
},
{
"modelId": "O96YRmBUFIk",
"id": 97,
"ifcGUID": "20Kz1qluL2Wg558svTerf5",
"materialName": "Holcim",
"kgCO2eq": 5047,
"volume": "5.600"
},
{
"modelId": "O96YRmBUFIk",
"id": 144,
"ifcGUID": "0vxJ9HCOfDuwHcb42u4AVr",
"materialName": "Steel",
"kgCO2eq": 615.27,
"volume": "0.000"
},
{
"modelId": "O96YRmBUFIk",
"id": 199,
"ifcGUID": "1j9eE0E4H4Lhvf0aOOWmMQ",
"materialName": "Steel",
"kgCO2eq": 615.27,
"volume": "0.011"
}
]
export default () => {
const [modelCount, setModelCount] = React.useState(0)
function getRandomColor() {
return new THREE.Color(Math.random(), Math.random(), Math.random());
}
async function loadIfcAsFragments(path: string, ifcLoader : OBC.FragmentIfcLoader, scene: THREE.Scene) {
const file = await fetch(path);
//console.log(file)
const data = await file.arrayBuffer();
//console.log(data)
const buffer = new Uint8Array(data);
const model = await ifcLoader.load(buffer, 'test');
scene.add(model);
}
interface exIDtoFrag {
expressID?: string,
fragment?: Fragment,
itemIndex?: number,
}
React.useEffect(() => {
const colorMap: { [materialName: string]: THREE.Color } = {};
TCdata.forEach(item => {
if (!colorMap[item.materialName]) {
colorMap[item.materialName] = getRandomColor();
}
});
//console.log(colorMap)
//#region define Viewer
const viewer = new OBC.Components()
const sceneComponent = new OBC.SimpleScene(viewer)
sceneComponent.setup()
viewer.scene = sceneComponent
const viewerContainer = document.getElementById("viewerContainer") as HTMLDivElement
const rendererComponent = new OBC.PostproductionRenderer(viewer, viewerContainer)
viewer.renderer = rendererComponent
const postproduction = rendererComponent.postproduction
const cameraComponent = new OBC.OrthoPerspectiveCamera(viewer)
viewer.camera = cameraComponent
const raycasterComponent = new OBC.SimpleRaycaster(viewer)
viewer.raycaster = raycasterComponent
viewer.init()
cameraComponent.updateAspect()
postproduction.enabled = true
const fragmentManager = new OBC.FragmentManager(viewer)
//console.log(fragmentManager)
const ifcLoader = new OBC.FragmentIfcLoader(viewer)
const scene = viewer.scene.get();
scene.background = new THREE.Color( 0xf3f3f7 );
//#endregion
const path = 'http://localhost:3000/SBS-2322.ifc'
loadIfcAsFragments(path, ifcLoader, scene).then(()=>{
//mesh index equals expressId position in the array
const fragMap: { [expressID: string]: {fragment: Fragment,meshIndex: number} } = {};
const fragmentsGroup = fragmentManager.groups[0]
//console.log(fragmentsGroup)
//SET MESH COLOURS
//create an array with expressId, its index in the items array and the fragment
for (const frag of fragmentsGroup.items){
//console.log(frag)
for (let index = 0; index < frag.items.length; index++) {
fragMap[frag.items[index]] = {fragment: frag, meshIndex: index}
}
}
//console.log(fragMap)
const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
//console.log(properties)
for (const [key] of Object.entries(properties)) {
try{
const {expressID, GlobalId} = properties[parseInt(key)];
//console.log(expressID)
//console.log(GlobalId.value)
const itemData = TCdata.find(item => item.ifcGUID === GlobalId.value);
if (itemData){
// console.log('global id', GlobalId)
// console.log('express id', expressID)
// console.log('item data', itemData)
//console.log('expressId', expressID, itemData)
const foundItem = Object.entries(fragMap).find(([x]) => x === String(expressID));
if (foundItem){
const color = colorMap[itemData.materialName]
//console.log(color)
//console.log('found', foundItem)
const {fragment, meshIndex} = foundItem[1]
fragment.mesh.setColorAt(meshIndex, color)
//console.log('composite', fragment.composites)
if (fragment.composites){
for (let index = 1; index < fragment.composites[expressID]; index++) {
const compositeExpressId = expressID +'.'+ index
//console.log('ceid', compositeExpressId)
const foundItem = Object.entries(fragMap).find(([x]) => x === compositeExpressId);
if (foundItem){
//console.log('found composite', foundItem)
const color = colorMap[itemData.materialName]
const {fragment, meshIndex} = foundItem[1]
fragment.mesh.setColorAt(meshIndex, color)
}
}
}
}
}
}
catch{}
//console.log('exid', expressID, 'globalid', GlobalId)
}
//get 1 item
// const fragment = fragmentsGroup.items[0]
// console.log(fragment)
// let color = new THREE.Color();
// fragment.mesh.setColorAt(0, color.set(0xFFD966))
// fragment.mesh.setColorAt(1, color.set(0x6AA84F))
// fragment.mesh.setColorAt(2, color.set(0x6FA8DC))
//
})
})
//#region Tentative1
// React.useEffect(()=>{
// const components = new OBC.Components()
// const sceneComponent = new OBC.SimpleScene(components)
// sceneComponent.setup()
// components.scene = sceneComponent
// const viewerContainer = document.getElementById("viewerContainer") as HTMLDivElement
// const rendererComponent = new OBC.PostproductionRenderer(components, viewerContainer)
// components.renderer = rendererComponent
// const postproduction = rendererComponent.postproduction
// const cameraComponent = new OBC.OrthoPerspectiveCamera(components)
// components.camera = cameraComponent
// const raycasterComponent = new OBC.SimpleRaycaster(components)
// components.raycaster = raycasterComponent
// components.init()
// cameraComponent.updateAspect()
// postproduction.enabled = true
// const scene = components.scene.get();
// const cubes = [];
// const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
// const material = new THREE.MeshLambertMaterial({ color: '#6528D7' });
// const cube = new THREE.Mesh(boxGeometry, material);
// cube.position.x = getRandomNumber(10);
// cube.position.y = getRandomNumber(10);
// cube.position.z = getRandomNumber(10);
// cube.updateMatrix();
// scene.add(cube);
// cubes.push(cube);
// console.log(cube)
// const materialManager = new OBC.MaterialManager(components);
// const cubeColor = new THREE.Color(0x71d728);
// const cubeMaterial = new THREE.MeshBasicMaterial({color: cubeColor});
// materialManager.addMaterial("cubeMaterial", cubeMaterial);
// materialManager.addMeshes("cubeMaterial", cubes);
// let counter = 0
// const changeCubeMaterial = () => {
// if (counter === 0){
// materialManager.set(true, ["cubeMaterial"]);
// counter = 1
// }
// else{
// materialManager.set(false, ["cubeMaterial"]);
// counter = 0
// }
// }
// viewerContainer.addEventListener('dblclick', () => OnClick());
// const fragmentManager = new OBC.FragmentManager(components)
// console.log('fmanager', fragmentManager)
// const ifcLoader = new OBC.FragmentIfcLoader(components)
// const path = 'http://localhost:3000/Simple_project_01.ifc'
// const ifcmeshes: any = []
// async function loadIfcAsFragments(path: string) {
// const file = await fetch(path);
// console.log(file)
// const data = await file.arrayBuffer();
// console.log(data)
// const buffer = new Uint8Array(data);
// const model = await ifcLoader.load(buffer, 'test');
// scene.add(model);
// console.log('model', model)
// console.log(model.items)
// const ifcInfo = OBC.IfcPropertiesManager.getIFCInfo(model);
// console.log('ifcinfo', ifcInfo)
// const { properties } = OBC.IfcPropertiesManager.getIFCInfo(model);
// //console.log(properties)
// for (const [key] of Object.entries(properties)) {
// //console.log(properties[parseInt(key)])
// //const {expressID, GlobalId} = properties[parseInt(key)];
// //console.log('frag', fragment)
// }
// const fragment = fragmentManager.list['22620'];
// console.log('slab', fragment)
// const classifier = new OBC.FragmentClassifier(components);
// classifier.byEntity(model);
// console.log('classifier', classifier)
// const {mesh} = model.items[2];
// console.log('mesh 2', mesh)
// ifcmeshes.push(mesh)
// //const block = model.items[2].blocks
// //console.log('block', block)
// const entityData = model.data[22620];
// console.log('edata', entityData)
// for (const key of entityData[0]) {
// const fragmentID = model.keyFragments[key];
// console.log(fragmentID)
// }
// // for (const fragment of model.items) {
// // console.log(fragment)
// // const {mesh} = fragment;
// // ifcmeshes.push(mesh)
// // console.log('f mesh', mesh)
// // console.log('f items', fragment.items)
// // return
// // }
// }
// const OnClick = async () =>{
// console.log('click')
// changeCubeMaterial()
// const fragments = fragmentManager
// const fragment = fragments.list['23620'];
// console.log('fragment',fragment)
// ifcmeshes.push(fragment)
// }
// const highlighter = new OBC.FragmentHighlighter(components)
// highlighter.setup()
// const propertiesProcessor = new OBC.IfcPropertiesProcessor(components)
// highlighter.events.select.onClear.add(() => {
// propertiesProcessor.cleanPropertiesList()
// })
// highlighter.events.select.onHighlight.add(async (selection) => {
// console.log('highlight')
// console.log(selection);
// const meshes = fragmentManager.meshes;
// console.log(meshes)
// const result: any = components.raycaster.castRay(meshes);
// if (!result){
// const mesh = result.object as FragmentMesh;
// console.log('mesh', mesh)
// ifcmeshes.push(mesh)
// materialManager.addMeshes("cubeMaterial", [mesh])
// }
// console.log(result?.object)
// })
// // let lastSelection: any;
// // let singleSelection = {
// // value: true,
// // };
// // const highlightMaterial = new THREE.MeshBasicMaterial({
// // color: '#BCF124',
// // depthTest: false,
// // opacity: 0.8,
// // transparent: true
// // });
// // highlighter.add('default', [highlightMaterial])
// // //highlighter.add('default', highlightMaterial);
// // console.log('hig', highlighter)
// // async function highlightOnClick(event) {
// // console.log('click')
// // const result = await highlighter.highlight('default', singleSelection.value);
// // console.log('sel res', result)
// // if (result) {
// // lastSelection = {};
// // for (const fragment of result.fragments) {
// // const fragmentID = fragment.id;
// // console.log(fragmentID)
// // lastSelection[fragmentID] = [result.id];
// // highlighter.highlightByID('default', lastSelection);
// // }
// // }
// // }
// // viewerContainer.addEventListener('click', (event) => highlightOnClick(event));
// loadIfcAsFragments(path).then(res=>{
// console.log('ifcmehs', ifcmeshes)
// materialManager.addMeshes("cubeMaterial", ifcmeshes)
// })
// },[])
//#endregion
//#region Tentative2
// React.useEffect(() => {
// const viewer = new OBC.Components()
// const sceneComponent = new OBC.SimpleScene(viewer)
// sceneComponent.setup()
// viewer.scene = sceneComponent
// const viewerContainer = document.getElementById("viewerContainer") as HTMLDivElement
// const rendererComponent = new OBC.PostproductionRenderer(viewer, viewerContainer)
// viewer.renderer = rendererComponent
// const postproduction = rendererComponent.postproduction
// const cameraComponent = new OBC.OrthoPerspectiveCamera(viewer)
// viewer.camera = cameraComponent
// const raycasterComponent = new OBC.SimpleRaycaster(viewer)
// viewer.raycaster = raycasterComponent
// viewer.init()
// cameraComponent.updateAspect()
// postproduction.enabled = true
// const grid = new OBC.SimpleGrid(viewer, new THREE.Color(0x666666))
// postproduction.customEffects.excludedMeshes.push(grid.get())
// const fragmentManager = new OBC.FragmentManager(viewer)
// const ifcLoader = new OBC.FragmentIfcLoader(viewer)
// const highlighter = new OBC.FragmentHighlighter(viewer)
// highlighter.setup()
// const propertiesProcessor = new OBC.IfcPropertiesProcessor(viewer)
// highlighter.events.select.onClear.add(() => {
// propertiesProcessor.cleanPropertiesList()
// })
// function download(file: File) {
// const link = document.createElement("a");
// link.href = URL.createObjectURL(file);
// link.download = file.name;
// document.body.appendChild(link);
// link.click();
// link.remove();
// }
// const scene = viewer.scene.get();
// scene.background = new THREE.Color( 0xf3f3f7 );
// const meshes: any = [];
// const materialManager = new OBC.MaterialManager(viewer);
// async function loadIfcAsFragments(path: string) {
// const file = await fetch(path);
// console.log(file)
// const data = await file.arrayBuffer();
// console.log(data)
// const buffer = new Uint8Array(data);
// const model = await ifcLoader.load(buffer, 'test');
// scene.add(model);
// for (const fragment of model.items) {
// const {mesh} = fragment;
// meshes.push(mesh);
// console.log(mesh)
// }
// }
// const whiteColor = new THREE.Color("white");
// const whiteMaterial = new THREE.MeshBasicMaterial({color: whiteColor});
// console.log('meshes', meshes)
// materialManager.addMaterial("white", whiteMaterial);
// materialManager.addMeshes("white", meshes);
// const path = 'http://localhost:3000/Simple_project_01.ifc'
// const boxMaterial = new THREE.MeshStandardMaterial({ color: '#6528D7' });
// const boxGeometry = new THREE.BoxGeometry(3, 3, 3);
// const cube = new THREE.Mesh(boxGeometry, boxMaterial);
// cube.position.set(0, 1.5, 0);
// scene.add(cube);
// loadIfcAsFragments(path).then(res=>{
// console.log(res)
// console.log('scee model', scene.children[3])
// const model = scene.children[3] as FragmentsGroup
// const { properties } = OBC.IfcPropertiesManager.getIFCInfo(model);
// console.log(properties)
// })
// ifcLoader.onIfcLoaded.add(model => {
// console.log('model', model)
// const data = fragmentManager.export(fragmentManager.groups[0])
// const blob = new Blob([data]);
// console.log(blob)
// const file = new File([blob], "small.frag");
// download(file);
// const { properties } = OBC.IfcPropertiesManager.getIFCInfo(model);
// for (const [key] of Object.entries(properties)) {
// console.log(properties[parseInt(key)])
// return
// try{
// const {expressID, GlobalId} = properties[parseInt(key)];
// console.log(expressID, GlobalId)
// const {mesh} = fragmentManager.list[expressID];
// console.log('mesh' ,mesh)
// }
// catch(error){
// console.log(error)
// }
// try{
// console.log(Name.value, expressID, GlobalId.value)
// }
// catch{}
// }
// const meshes : any = [];
// console.log('look roof mesh')
// for (const fragment of model.items) {
// const {mesh} = fragment;
// console.log('loaded mesh', mesh.id, mesh)
// if (mesh.id === 22620){
// console.log('roof mesh', mesh.id)
// meshes.push(mesh)
// }
// }
// console.log(fragmentManager.groups[0].items)
// setModelCount(fragmentManager.groups.length)
// propertiesProcessor.process(model)
// const classify = async () =>{
// const classifier = new OBC.FragmentClassifier(viewer);
// classifier.byEntity(model);
// classifier.byStorey(model);
// const found = await classifier.find({entities: ["IFCSLAB"]});
// console.log('**********found', found)
// highlighter.highlightByID('default', found);
// }
// classify();
// const GetMeshById = async () =>{
// const ifcmeshes = []
// get all fragments
// const fragments = fragmentManager;
// select 1 fragment
// const meshgroup = fragments.groups[0].items[0]
// console.log('mgroup', meshgroup)
// console.log('mgroupId', meshgroup.id)
// console.log('ids', meshgroup.items)
// console.log('count of blocks', meshgroup.blocks.count)
// items inside the fragment
// const items = meshgroup.items;
// console.log('tems', items)
// const composites = meshgroup.mesh.fragment.composites["338"];
// console.log('compsite', composites)
// const _tempMatrix = new THREE.Matrix4();
// const { instanceID } = meshgroup.getInstanceAndBlockID("22620");
// console.log('instance id', instanceID)
// const instance = meshgroup.getInstance(instanceID, _tempMatrix);
// console.log('instance', instance)
// const instance = meshgroup.mesh.fragment.getInstance(instanceID, _tempMatrix)
// console.log('instance', instance)
// const selection = meshgroup.fragments["default"];
// console.log('sel', selection)
// selection.setInstance(0, {
// ids: Array.from(meshgroup.ids),
// transform: _tempMatrix,
// });
// create selection map
// const result: FragmentIdMap = {};
// const set = new Set<string>
// add expressId
// set.add("22620")
// meshgroup.setVisibility(false, set)
// const fragmGeometry = meshgroup.mesh.geometry;
// const index = fragmGeometry.index;
// result[meshgroup.id] = set;
// console.log('**********result', result)
// highlighter.highlightByID('default', result);
// const cubeColor = new THREE.Color(0x71d728);
// const cubeMaterial = new THREE.MeshBasicMaterial({color: cubeColor});
// materialManager.addMaterial("cubeMaterial", cubeMaterial);
// const mm = materialManager.get()
// console.log('mmanager', mm)
// const subFragment = meshgroup.addFragment("cubeMaterial", [cubeMaterial]);
// console.log('subF', subFragment)
// const indices = meshgroup.mesh.geometry.index.array;
// console.log('indices', indices)
// for (let i = 0; i < indices.length - 2; i += 3) {
// const index = indices[i];
// const blockID = meshgroup.mesh.geometry.attributes.blockID.array;
// console.log('block id', blockID)
// const block = blockID[index];
// const itemID = meshgroup.mesh.fragment.getItemID(1, block);
// const matrix = new THREE.Matrix4()
// const instance = meshgroup.mesh.fragment.getInstance(1, matrix)
// console.log('instane', instance)
// console.log('idtem id', itemID)
// }
// const geometry = meshgroup.mesh.geometry;
// console.log('geom', geometry)
// for (const fragID in result) {
// console.log('frag Id', fragID)
// const fragment = fragments.list[fragID];
// console.log('fragmnet', fragment)
// const idsNum = new Set<number>();
// for (const id of result[fragID]) {
// styles[fragID].add(id);
// idsNum.add(parseInt(id, 10));
// }
// for (const id of idsNum) {
// console.log('id num', idsNum)
// }
// console.log('fragment mesh', fragment.mesh)
// const subFragment = fragment.addFragment("cubeMaterial", [cubeMaterial]);
// console.log('count of blocks', fragment.blocks.count)
// const isBlockFragment = fragment.blocks.count > 1;
// console.log(isBlockFragment)
// let i = 0;
// const selection: {
// [selectionID: string]: FragmentIdMap;
// } = {};
// console.log('meshcount', fragment.mesh.count)
// const { instanceID } = fragment.getInstanceAndBlockID("22620");
// console.log('instance id', instanceID)
// console.log('block', fragment.blocks)
// const ints = fragment.getInstance(instanceID, _tempMatrix);
// console.log('ints', ints)
// console.log('subfrag', subFragment)
// ifcmeshes.push(fragment.mesh)
// subFragment.mesh.renderOrder = 2;
// subFragment.mesh.frustumCulled = false;
// }
// const model = fragments.groups[0];
// console.log('modello', model)
// const idMap: OBC.FragmentIdMap = {};
// const fragment = model.items[0]
// let color = new THREE.Color();
// fragment.mesh.setColorAt(0, color.set(0xFFD966))
// fragment.mesh.setColorAt(1, color.set(0x6AA84F))
// fragment.mesh.setColorAt(2, color.set(0x6FA8DC))
// for (const fragmentKey of model.data['22620'][0]) {
// console.log(fragmentKey)
//   const fragmentId = model.keyFragments[fragmentKey];
// console.log('fragId', fragmentId)
// const fragment = fragments.list[fragmentId];
// console.log(fragment)
// const composites = fragment.items.filter((id) => parseInt(id, 10) === layer.expressID);
// idMap[fragmentId] = new Set(composites);
// console.log(idMap)
// const meshes = Object.values(fragments.list).map((frag) =>
// frag.mesh)
// const instMesh = meshes[0] as THREE.InstancedMesh
// console.log(instMesh.count)
// let color = new THREE.Color();
// instMesh.setColorAt(0, color.set(0xffffff))
// const bufferGeom = meshes[0].geometry as THREE.BufferGeometry
// console.log('instacne color', meshes[0].instanceColor)
// if (meshes[0].instanceColor)
// {
// meshes[0].instanceColor.needsUpdate = true
// }
// console.log('firt frag mes', bufferGeom)
// }
// materialManager.addMeshes("cubeMaterial", ifcmeshes)
// materialManager.set(true, ["cubeMaterial"]);
// }
// GetMeshById()
// highlighter.events.select.onHighlight.add(async (selection) => {
// console.log('sel', selection)
// materialManager.set(true, ['whiteMaterial'])
// console.log('me', meshes)
// const fragmentID = Object.keys(selection)[0]
// console.log('fid', fragmentID)
// const expressID = Number([...selection[fragmentID]][0])
// console.log('expressId', expressID)
// propertiesProcessor.renderProperties(model, expressID)
// const { name } = OBC.IfcPropertiesUtils.getEntityName(properties, expressID);
// const prop = properties[expressID];
// console.log('name', name)
// console.log(prop)
// })
// highlighter.update()
// })
// let lastSelection : any= {};
// let singleSelection = {value: true};
// const highlightMaterial = new THREE.MeshBasicMaterial({
// color: '#BCF124',
// depthTest: false,
// opacity: 0.8,
// transparent: true
// });
// highlighter.add('default', [highlightMaterial]);
// highlighter.outlineMaterial.color.set(0xf0ff7a);
// const highlightOnClick = async () =>{
// const result = await highlighter.highlight('default', singleSelection.value);
// console.log(result)
// if (result){
// lastSelection = {}
// for (const fragment of result.fragments){
// const fragmentID = fragment.id
// console.log(fragmentID)
// lastSelection[fragmentID] = [result.id];
// console.log(lastSelection)
// }
// }
// var scene_objects = scene.children[3] as FragmentsGroup
// console.log('scene objects', scene_objects)
// const mySet = new Set<string>;
// mySet.add("22620")
// highlighter.highlightByID('default', {["ec970173-d0f3-4d0b-a827-648c6607e234"]: mySet});
// highlighter.highlightByID('default', [fid]);
// }
// viewerContainer.addEventListener('click', (event) => highlightOnClick(event));
// const mainToolbar = new OBC.Toolbar(viewer)
// mainToolbar.addChild(
// ifcLoader.uiElement.get("main"),
// propertiesProcessor.uiElement.get("main")
// )
// viewer.ui.addToolbar(mainToolbar)
// }, [])
//#endregion
const viewerContainerStyle: React.CSSProperties = {
width: "100%",
height: "100%",
position: "relative",
gridArea: "viewer"
}
const titleStyle: React.CSSProperties = {
position: "absolute",
top: "15px",
left: "15px"
}
return (
<>
<div id="viewerContainer" style={viewerContainerStyle}>
<h3 style={titleStyle}>Models loaded: {modelCount}</h3>
</div>
</>
)
}
import json
import sys
import ifcopenshell
import ifcopenshell.api
import csv
from datetime import datetime
class EntityData:
pass
class TaskData:
pass
id = []
instancesList = []
folder = r'00-WORKING-SHARED\231213 Live Activities\\'
newFile = r'2200_IFC_live.ifc'
with open(folder+'Synchro3DObjects.csv', newline='', encoding='utf-8-sig') as csvfile:
excelReader = csv.reader(csvfile)
csv_headings = next(excelReader)
for row in excelReader:
entityInstance = EntityData()
for h,r in zip(csv_headings, row):
setattr(entityInstance, h.replace(' ','_').replace(':','_').replace('3',''), r)
instancesList.append(entityInstance)
id.append(row[1])
tasksList = []
with open(r'C:\temp\123\P6_Activities.csv', newline='', encoding='utf-8-sig') as csvfile:
excelReader = csv.reader(csvfile)
csv_headings = next(excelReader)
for row in excelReader:
task = TaskData()
for h,r in zip(csv_headings, row):
setattr(task, h, r)
tasksList.append(task)
for instance in instancesList:
task_id = instance.DUF_Task_ID.split(',')
savedStart = datetime(3000,1,1)
savedFinish = datetime(2000,1,1)
date_format = '%d/%m/%Y'
if len(task_id)==1:
try:
found_task = [t for t in tasksList if t.task_code == task_id[0]][0]
if found_task:
for prop, value in found_task.__dict__.items():
setattr(instance, prop, value)
except Exception as error:
print (error)
else:
for tId in task_id:
try:
found_task = [t for t in tasksList if t.task_code == tId][0]
if found_task:
currentStart = datetime.strptime(getattr(found_task, 'ActivityStartDate'), date_format)
currentEnd = datetime.strptime(getattr(found_task, 'ActivityFinishDate'), date_format)
if currentStart < savedStart:
setattr(instance, 'ActivityStartDate', found_task.ActivityStartDate)
setattr(instance, 'TaskCodeStart', found_task.task_code)
savedStart = currentStart
setattr(instance, 'act_start_date', found_task.act_start_date)
if currentEnd > savedFinish:
setattr(instance, 'ActivityFinishDate', found_task.ActivityFinishDate)
setattr(instance, 'TaskCodeFinish', found_task.task_code)
setattr(instance, 'status_code', found_task.status_code)
savedFinish = currentEnd
setattr(instance, 'act_end_date', found_task.act_end_date)
#for prop, value in found_task.__dict__.items():
# setattr(instance, prop, value)
except Exception as error:
print (error)
print (f'could not find task {tId} for instance {instance.DUF_Element_Identifier}')
actions = []
statusActionId = '82b048b1-7f99-ee11-ab9f-0690b7055a58'
#prepare objects for Trimble Connect
for instance in instancesList:
try:
date = instance.act_start_date
format_date = ''
if date != 'NULL':
date_format = '%d/%m/%Y'
date_obj = datetime.strptime(date, date_format)
format_date = date_obj.strftime('%Y-%m-%d %H:%M')
else:
date_format = '%d/%m/%Y'
date_obj = datetime.strptime(instance.ActivityStartDate, date_format)
format_date = date_obj.strftime('%Y-%m-%d %H:%M')
# print (t.GlobalId)
# print (p6['start_date'])
actions.append({'objectId': instance.DUF_Element_Identifier,
'statusActionId': statusActionId,
"value": "Started",
"valueDate": format_date
})
end_date = instance.act_end_date
format_end_date = ''
if end_date != 'NULL':
end_date_format = '%d/%m/%Y'
end_date_obj = datetime.strptime(end_date, end_date_format)
format_end_date = end_date_obj.strftime('%Y-%m-%d %H:%M')
else:
date_format = '%d/%m/%Y'
date_obj = datetime.strptime(instance.ActivityFinishDate, date_format)
format_end_date = date_obj.strftime('%Y-%m-%d %H:%M')
actions.append({'objectId': instance.DUF_Element_Identifier,
'statusActionId': statusActionId,
"value": "Completed",
"valueDate": format_end_date
})
#print (f'OK {instance.DUF_Element_Identifier}')
except:
continue
#print (f'FAILED {instance.DUF_Element_Identifier}')
json_data = json.dumps(actions, default = lambda x: x.__dict__)
with open("actions_coolstore.json", "w") as json_file:
json_file.write(json_data)
#sys.exit("Error message")
#[print(t) for t in instancesList]
model = ifcopenshell.open(r'2200_IFC.ifc')
allEntities = model.by_type("IfcElement")
#print (allEntities)
results = []
errors = []
for t in allEntities:
pset = ifcopenshell.api.run("pset.add_pset", model, product=t, name="P6_Data")
elementId = t.Name.split(':')[-1]
#print(elementId)
try:
trimbleIndex = id.index(elementId)
currentInstance = instancesList[trimbleIndex]
#print (currentInstance)
for p in vars(currentInstance):
#print (p)
#print(vars(currentTreeData)[p])
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties={p : vars(currentInstance)[p]})
results.append(t)
except:
errors.append(t)
model.write(folder+newFile)
print ('results', results)
print ('errors', errors)
print ('completed')
"use strict";
import powerbi from "powerbi-visuals-api";
import * as THREE from 'three';
import * as OBC from 'openbim-components';
import { FragmentsGroup, Fragment } from 'bim-fragment';
import DataView = powerbi.DataView;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import IViewport = powerbi.IViewport;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import { VisualSettings } from "./settings";
// Import React dependencies and the added component
import * as React from "react";
import * as ReactDOM from "react-dom";
import ReactCircleCard from "./component";
import {UploadForm} from "./UploadForm"
import "./../style/visual.less";
interface ChartDataPoint {
value: string;
category: string;
color: THREE.Color;
guid: string;
};
export class CustomVisual implements IVisual {
static Config = {
default_color: new THREE.Color('#F5F5F5'),
opacity_of_unselected_objects: 0.3,
color1: new THREE.Color('#00FF00'),
color2: new THREE.Color('#FFFF00'),
color3: new THREE.Color('#FF0000')
};
public host: IVisualHost;
private options: VisualUpdateOptions; // so we can call update from the constructor when the model is loaded TBC
private model_loaded: boolean = false
private visualSettings: VisualSettings;
private viewport: IViewport;
public scene: THREE.Scene;
private first_load: boolean = true;
private constructor_options: VisualConstructorOptions;
private target: HTMLElement;
private container!: HTMLDivElement
private components!: OBC.Components
private fragmentManager: OBC.FragmentManager
private highlighter: OBC.FragmentHighlighter
private reactRoot: React.ComponentElement<any, any>;
private green : THREE.Color = new THREE.Color(0x5CC45C)
private red: THREE.Color = new THREE.Color(0xCC0000)
public static Instances: CustomVisual[] = [];
public static Instance: CustomVisual;
public upload_form : UploadForm;
//open-bim properties
private fragMap: { [expressID: string]: {fragment: Fragment} } = {};
private guidToexpressIdMap: { [expressID: string]: number } = {};
private materialList = []
constructor(options: VisualConstructorOptions) {
this.constructor_options = options;
CustomVisual.Instance = this;
this.host = options.host; //is this the right place to call this?
this.target = options.element;
this.first_load = true;
CustomVisual.Instances.push(this);
console.log('finish constuctor')
console.log('loading', this.first_load)
//#region create scene
this.container = document.createElement( 'div' )
this.container.className = 'full-screen'
this.container.style.zIndex = '2000'
this.target.style.cursor = 'default'
this.target.appendChild( this.container )
this.components = new OBC.Components();
this.components.scene = new OBC.SimpleScene( this.components );
this.components.renderer = new OBC.PostproductionRenderer( this.components, this.container );
this.components.camera = new OBC.SimpleCamera( this.components );
this.components.raycaster = new OBC.SimpleRaycaster( this.components );
this.fragmentManager = new OBC.FragmentManager(this.components)
console.log('init component***')
this.components.init();
( this.components.renderer as OBC.PostproductionRenderer ).postproduction.enabled = true;
const scene = this.components.scene.get();
scene.background = new THREE.Color( 0xf3f3f7 );
( this.components.camera as OBC.SimpleCamera ).controls.setLookAt( 10, 10, 10, 0, 0, 0 );
//const grid = new OBC.SimpleGrid(this.components);
// const boxMaterial = new THREE.MeshStandardMaterial({ color: '#6528D7' });
// const boxGeometry = new THREE.BoxGeometry(3, 3, 3);
// const cube = new THREE.Mesh(boxGeometry, boxMaterial);
// cube.position.set(0, 1.5, 0);
// scene.add(cube);
const directionalLight = new THREE.DirectionalLight();
directionalLight.position.set( 5, 10, 3 );
directionalLight.intensity = 0.5;
scene.add( directionalLight );
const ambientLight = new THREE.AmbientLight();
ambientLight.intensity = 0.5;
scene.add( ambientLight );
this.scene = scene
this.highlighter = new OBC.FragmentHighlighter(this.components)
this.highlighter.setup()
//#endregion
// const geometry = new THREE.BoxGeometry( 10, 10, 10);
// const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// const cube = new THREE.Mesh( geometry, material );
// scene.add( cube );
//this._initScene('http://localhost:5173/SBS-2322.ifc', scene);
this._initScene('http://localhost:5173/CSW-2200-crop.ifc', scene);
}
//#region old update
// public update(options: VisualUpdateOptions) {
// console.log('updated, first load:', this.first_load)
// try{
// this.viewport = options.viewport;
// const { width, height } = this.viewport;
// //console.log('w', width, 'h', height)
// this.options = options; // so we can call update from the constructor when the model is loaded
// let dataView: DataView = options.dataViews[0];
// this.visualSettings = VisualSettings.parse<VisualSettings>(dataView);
// //console.log(dataView)
// if(!this.model_loaded)
// {
// console.log('model not loaded')
// if(this.visualSettings.model.url!="" && this.first_load) // The first load check is extremely important, otherwise the loader will be called twice and the render will freeze
// {
// //CustomVisual.Load3DModel(this.visualSettings.model.url);
// this._initScene('http://localhost:3000/SBS-2322.ifc');
// this.first_load = false;
// }
// else if (this.first_load)
// {
// console.log('first load')
// // Create form to input URL. If there's already a URL defined and we're reloading the model, no input form is created, because it leads to a bug.
// this.reactRoot = React.createElement(UploadForm, {});
// ReactDOM.render(this.reactRoot, this.target);
// //this._initScene(this.options)
// this.first_load = false;
// return;
// } else
// {
// return;
// }
// }
// }
// catch(error){
// console.log(error)
// UploadForm.show_error_message(error);
// throw error;
// }
// console.log('model loaded:', this.model_loaded, 'scene defined:', this.scene)
// // Return if no model available
// if(!this.model_loaded || this.scene == undefined) // the load model process is asyncronous so we need another if
// {
// console.log('no model abvailable')
// return;
// }
// // Update 3D visualization
// console.log('Update 3D visualization')
// try
// {
// console.log('children', this.scene.children)
// //check if fragments have been loaded
// if (this.scene.children[3] != undefined) // beacuse of the asyncronous load process
// {
// this.visualTransform(options, this.host);
// }
// // this.renderer.setClearColor( 0xffffff, 0);
// // this.renderer.setSize(window.innerWidth, window.innerHeight);
// // this.camera.aspect = window.innerWidth/window.innerHeight;
// // this.camera.updateProjectionMatrix();
// // CustomVisual.Instance.renderer.render(this.scene,this.camera);
// }
// catch (e) {
// console.error(e);
// UploadForm.show_error_message(e);
// throw e;
// }
// }
//#endregion
public update(options: VisualUpdateOptions){
console.log('update')
//this.visualTransform(options, this.host)
//console.log('update this scene', this.scene)
var scene_objects = this.scene
console.log('update scene objects', scene_objects)
//this.visualTransform(options, this.host)
this.visualTransform(options, this.host)
}
private _initScene(filepath: string, scene: THREE.Scene){
try{
let fragmentIfcLoader = new OBC.FragmentIfcLoader(this.components);
fragmentIfcLoader.settings.wasm = {
path: "https://unpkg.com/[email protected]/",
absolute: true
}
fragmentIfcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
fragmentIfcLoader.settings.webIfc.OPTIMIZE_PROFILES = true;
this.loadIfcAsFragments(filepath,this.fragmentManager, fragmentIfcLoader, scene)
}
catch{
}
}
private async loadIfcAsFragments(filepath: string,fragmentManager: OBC.FragmentManager, fragmentIfcLoader: OBC.FragmentIfcLoader, scene: THREE.Scene) {
//const file = await fetch('../../../resources/small.ifc');
const file = await fetch(filepath);
console.log(file)
const data = await file.arrayBuffer();
console.log(data)
const buffer = new Uint8Array(data);
const model = await fragmentIfcLoader.load(buffer, 'test');
scene.add(model);
console.log('model', model)
const fragmentsGroup = fragmentManager.groups[0]
const { properties } = OBC.IfcPropertiesManager.getIFCInfo(fragmentsGroup);
for (const [key] of Object.entries(properties)) {
try{
//console.log(properties[parseInt(key)])
const {expressID, GlobalId} = properties[parseInt(key)];
if (expressID && GlobalId){
this.guidToexpressIdMap[GlobalId.value] = expressID
}
}
catch{}
}
console.log('pmasp', this.guidToexpressIdMap)
for (const frag of fragmentsGroup.items){
//console.log(frag)
for (let index = 0; index < frag.items.length; index++) {
this.fragMap[frag.items[index]] = {fragment: frag}
}
}
console.log('fragmap', this.fragMap)
return model
}
private visualTransform(options: VisualUpdateOptions, host: IVisualHost) {
this.highlighter.update()
//this.highlighter.clear();
let dataViews = options.dataViews;
//console.log('dv', dataViews)
let categorical = dataViews[0].categorical;
let guid = categorical.categories[0].values;
//let tco2 = categorical.categories[1];
let tco2 = categorical.values[0].values;
let volumes = categorical.values[1].values;
console.log('guid', guid, 'tco2', tco2)
const fragmentsGroup = this.scene.children[3] as FragmentsGroup
//console.log('fragments group', fragmentsGroup)
const tco2Values: {[ifcGuid: string]: number} = {}
for (let index = 0; index < guid.length; index++) {
const guidvalue = <string>guid[index]
//console.log(data)
const tco2value = <number>tco2[index] * Number.parseFloat(<string>volumes[index])
//const tco2value = <number>tco2[index]
tco2Values[guidvalue] = tco2value
}
//we can get min and max from the measure
//const tco2Min = Math.min(...Object.values(tco2Values))
const tco2Max = Math.max(...Object.values(tco2Values))
console.log(tco2Values)
const percentages: number[] = []
for (const item of Object.entries(tco2Values)){
//console.log('item', item)
const expressID = this.guidToexpressIdMap[item[0]];
if (expressID){
const foundItem = Object.entries(this.fragMap).find(([x]) => x === String(expressID));
//console.log(foundItem)
if (foundItem){
//item co2 value/max co2 value
const percentage = item[1]/tco2Max
//console.log(percentage)
const colorT = new THREE.Color()
colorT.lerpColors(this.green, this.red, percentage)
//console.log(colorT)
if (!percentages.includes(percentage)){
percentages.push(percentage)
this.highlighter.add(percentage.toString(), [new THREE.MeshStandardMaterial({color: colorT})])
}
const {fragment} = foundItem[1]
const mybeam: OBC.FragmentIdMap = {}
mybeam[fragment.id] = new Set<string>();
mybeam[fragment.id].add(expressID.toString())
this.highlighter.highlightByID(percentage.toString(), mybeam, true)
//console.log(fragment)
}
}
}
console.log(percentages)
}
// private _initSceneOld(filepath: string, scene: THREE.Scene){
// try{
// let fragments = new OBC.FragmentManager(this.components);
// let fragmentIfcLoader = new OBC.FragmentIfcLoader(this.components);
// fragmentIfcLoader.settings.wasm = {
// path: "https://unpkg.com/[email protected]/",
// absolute: true
// }
// // fragmentIfcLoader.settings.wasm = {
// // path: "./wasm/",
// // absolute: true
// // }
// fragmentIfcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
// fragmentIfcLoader.settings.webIfc.OPTIMIZE_PROFILES = true;
// const highlighter = new OBC.FragmentHighlighter(this.components);
// highlighter.update();
// // const mainToolbar = new OBC.Toolbar(this.components, { name: 'Main Toolbar', position: 'bottom' });
// // this.components.ui.addToolbar(mainToolbar);
// // const ifcButton : OBC.Button = fragmentIfcLoader.uiElement.get("main");
// // mainToolbar.addChild(ifcButton);
// async function loadIfcAsFragments() {
// //const file = await fetch('../../../resources/small.ifc');
// const file = await fetch(filepath);
// console.log(file)
// const data = await file.arrayBuffer();
// console.log(data)
// const buffer = new Uint8Array(data);
// const model = await fragmentIfcLoader.load(buffer, 'test');
// scene.add(model);
// console.log('model', model)
// return model
// }
// loadIfcAsFragments().then(model=>{
// const { properties } = OBC.IfcPropertiesManager.getIFCInfo(model);
// //console.log(properties)
// for (const [key] of Object.entries(properties)) {
// try{
// const {expressID, GlobalId} = properties[parseInt(key)];
// // console.log('express id', expressID)
// // console.log('global id', GlobalId.value)
// if (expressID && GlobalId){
// this.guidToexpressIdMap[GlobalId.value] = expressID
// }
// }
// catch{}
// }
// //create an array with expressId, its index in the items array and the fragment
// for (const frag of model.items){
// //console.log(frag)
// for (let index = 0; index < frag.items.length; index++) {
// //this.fragMap[frag.items[index]] = {fragment: frag, meshIndex: index}
// }
// }
// })
// for (let index = 0; index < 10; index++) {
// this.materialList.push(this.getRandomColor());
// }
// // CustomVisual.Instance.model_loaded = true;
// // CustomVisual.Instance.first_load = false
// // CustomVisual.Instance.scene = scene;
// }
// catch (error){
// console.log('error', error);
// }
// console.log('finish init')
// }
private getRandomColor() {
return new THREE.Color(Math.random(), Math.random(), Math.random());
}
private getColumnColorByValue(
value: number,
min_value: number,
max_value: number
): THREE.Color {
let factor = 1.0;
if (max_value!=min_value)
{
factor = (Math.round(value*100)/100-min_value)/(max_value-min_value);
}
let color = new THREE.Color();
if(factor<=0.5)
{
color = (new THREE.Color ()).lerpColors(CustomVisual.Config.color1, CustomVisual.Config.color2, 2*factor);
}else
{
color = (new THREE.Color ()).lerpColors(CustomVisual.Config.color2, CustomVisual.Config.color3, 2*(factor-0.5));
}
return color;
}
// private visualTransform2(options: VisualUpdateOptions, host: IVisualHost){
// let dataViews = options.dataViews;
// let categorical = dataViews[0].categorical;
// let guid;
// let category;
// if (categorical.categories.length >1)
// {
// if(categorical.categories[0].values.length == 0 || categorical.categories[1].values.length == 0)
// {
// console.log('Some category has no values.')
// return;
// }
// if((categorical.categories[0].values[0]))
// {
// guid = categorical.categories[0];
// category = categorical.categories[1];
// }else if ((categorical.categories[1].values[0]))
// {
// guid = categorical.categories[1];
// category = categorical.categories[0];
// }else
// {
// console.log('No valid GUIDs imported.')
// return;
// }
// }else
// {
// guid = categorical.categories[0];
// }
// console.log('category', category)
// console.log('guid', guid)
// const item = category.values[0]
// console.log(item)
// for (let index = 0; index < category.values.length; index++) {
// const pbcolor = this.host.colorPalette.getColor(category.values[index]);
// console.log('color', pbcolor)
// }
// let dataValue = undefined;
// let all_values;
// let min_value : number = 0;
// let max_value : number = 0;
// var values_by_category: { [category: string] : number; } = {};
// if(dataViews[0].categorical.values)
// {
// dataValue = categorical.values[0];
// console.log('data value', dataValue)
// all_values = dataValue.values.map(item => <number>item)
// console.log('all values', all_values)
// if (categorical.categories.length >1)
// {
// console.log('length', categorical.categories.length)
// for(let i = 0, len = Math.max(guid.values.length); i < len; i++)
// {
// if(values_by_category[category.values[i]]!= undefined){
// values_by_category[category.values[i]] += all_values[i];
// }
// }
// min_value = Math.max(values_by_category[category.values[0]],0); // to avoid negative values
// for (const key in values_by_category)
// {
// min_value = Math.min(values_by_category[key], min_value);
// max_value = Math.max(values_by_category[key], max_value);
// }
// }else
// {
// min_value = Math.min(...all_values);
// max_value = Math.max(...all_values);
// }
// console.log(min_value)
// console.log(max_value)
// console.log('val by cat', values_by_category)
// }
// }
// private visualTransformOld(options: VisualUpdateOptions, host: IVisualHost) {
// console.log('visual transform1')
// // console.log('data view', dataViews)
// // console.log('vt scene', this.scene)
// // var frag = fragmentsGroup.items[0] as Fragment
// // console.log('fragment', frag)
// // const cube = this.scene.children[3] as THREE.Mesh
// // cube.material = new THREE.MeshBasicMaterial({color: this.getRandomColor()})
// //frag.mesh.material[0] = new THREE.MeshBasicMaterial({color: this.getRandomColor()})
// // const color = this.getRandomColor()
// // frag.mesh.setColorAt(0, color)
// // frag.mesh.instanceColor.needsUpdate = true;
// let dataViews = options.dataViews;
// console.log('DV', dataViews)
// const fragmentsGroup = this.scene.children[3] as FragmentsGroup
// console.log('fragments group', fragmentsGroup)
// let categorical = dataViews[0].categorical;
// for (const frag of fragmentsGroup.items){
// //console.log(frag)
// for (let index = 0; index < frag.items.length; index++) {
// this.fragMap[frag.items[index]] = {fragment: frag, meshIndex: index}
// }
// }
// //console.log('fmap', this.fragMap)
// console.log('data view', dataViews)
// const ifcGuids = dataViews[0].categorical.categories[0].values
// //console.log('ifcguids', ifcGuids)
// const materials = dataViews[0].categorical.categories[1].values
// console.log('materials', materials)
// const colorMap: { [materialName: string]: THREE.Color } = {};
// for (let index = 0; index < materials.length; index++) {
// console.log('material', materials[index])
// const pbcolor = this.host.colorPalette.getColor(<string>materials[index]).value;
// console.log(new THREE.Color(pbcolor))
// if (!colorMap[materials[index].toString()]){
// const pbcolor = this.host.colorPalette.getColor(<string>materials[index]).value;
// //colorMap[materials[index].toString()] = this.materialList[index]
// colorMap[materials[index].toString()] = new THREE.Color(pbcolor)
// }
// }
// console.log(colorMap)
// // materials.forEach(materials => {
// // if (!colorMap[m.toString()]) {
// // colorMap[m.toString()] = this.getRandomColor();
// // }
// // })
// const TCdata = []
// // let dataValue = categorical.values[0];
// // console.log('values', dataValue)
// // let barChartDataPoints: ChartDataPoint[] = [];
// // for (let i = 0, len = category.values.length; i < len; i++) {
// // //console.log('color', colorPalette.getColor(dataValue.values[i].toString()).value)
// // barChartDataPoints.push({
// // category: <string>category.values[i],
// // value: <string>dataValue.values[i],
// // color: new THREE.Color(colorPalette.getColor(dataValue.values[i].toString()).value),
// // guid: <string>ifcGuids[i]
// // });
// // }
// //console.log('chart data point', barChartDataPoints)
// //console.log('cpalette', colorPalette)
// //let color = new THREE.Color(colorPalette.getColor(categorical.categories[0].values[index].toString()).value);
// let category = categorical.categories[0];
// console.log('cat', category)
// for (let index = 0; index < ifcGuids.length; index++) {
// TCdata.push({"ifcGUID": ifcGuids[index], "materialName": materials[index], "color": null})
// }
// console.log('tc data', TCdata)
// //console.log(colorMap)
// const greyColor = new THREE.Color('#F5F5F5')
// console.log(this.fragMap)
// Object.entries(this.fragMap).map(x=>{
// const {fragment, meshIndex} = x[1]
// fragment.mesh.setColorAt(meshIndex, greyColor)
// fragment.mesh.instanceColor.needsUpdate = true;
// })
// if (categorical.categories.length >1)
// {
// console.log('a')
// }
// for (const item of TCdata){
// //for (const item of chartDataPoints){
// const expressID = this.guidToexpressIdMap[item.ifcGUID];
// if (expressID){
// //console.log(expressID)
// const foundItem = Object.entries(this.fragMap).find(([x]) => x === String(expressID));
// //console.log(foundItem)
// if (foundItem){
// const color = colorMap[item.materialName]
// //const color = item.color;
// //const color = this.getColumnColorByValue()
// //console.log(color)
// const {fragment, meshIndex} = foundItem[1]
// //console.log('fragment', fragment)
// //console.log('mindex', meshIndex)
// fragment.mesh.setColorAt(meshIndex, color)
// fragment.mesh.instanceColor.needsUpdate = true;
// //console.log('color', color)
// if (fragment.composites){
// for (let index = 1; index < fragment.composites[expressID]; index++) {
// const compositeExpressId = expressID +'.'+ index
// //console.log('ceid', compositeExpressId)
// const foundItem = Object.entries(this.fragMap).find(([x]) => x === compositeExpressId);
// if (foundItem){
// //console.log('found composite', foundItem)
// //const color = colorMap[item.materialName]
// //const color = item.color;
// const {fragment, meshIndex} = foundItem[1]
// fragment.mesh.setColorAt(meshIndex, color)
// fragment.mesh.instanceColor.needsUpdate = true;
// }
// }
// }
// }
// }
// }
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment