web-ifc-viewer
Version:
187 lines • 8.27 kB
JavaScript
import { Mesh, Vector3 } from 'three';
import { IFCBUILDINGSTOREY, IFCBUILDING } from 'web-ifc';
import { CameraProjections, NavigationModes } from '../../../base-types';
import { UnitType } from '../../ifc/units';
import { disposeMeshRecursively } from '../../../utils/ThreeUtils';
export class PlanManager {
constructor(ifc, context, clipper) {
this.ifc = ifc;
this.context = context;
this.clipper = clipper;
this.planLists = {};
this.active = false;
this.defaultSectionOffset = 1.5;
this.defaultCameraOffset = 30;
this.storeys = [];
this.floorPlanViewCached = false;
this.previousCamera = new Vector3();
this.previousTarget = new Vector3();
this.previousProjection = CameraProjections.Perspective;
this.sectionFill = new Mesh();
}
dispose() {
disposeMeshRecursively(this.sectionFill);
this.sectionFill = null;
this.storeys = null;
this.planLists = null;
}
getAll(modelID) {
const currentPlans = this.planLists[modelID];
if (!currentPlans)
throw new Error("The requested model doesn't have floor plans generated");
return Object.keys(currentPlans);
}
async create(config) {
const { modelID, name } = config;
const ortho = config.ortho || true;
if (this.planLists[modelID] === undefined)
this.planLists[modelID] = {};
const currentPlanlist = this.planLists[modelID];
const expressID = config.expressID;
if (currentPlanlist[expressID])
return;
currentPlanlist[expressID] = { modelID, name, ortho, expressID };
await this.createClippingPlane(config, currentPlanlist[expressID]);
}
async goTo(modelID, name, animate = false) {
var _a;
if (((_a = this.currentPlan) === null || _a === void 0 ? void 0 : _a.modelID) === modelID && this.currentPlan.name === name)
return;
this.storeCameraPosition();
this.hidePreviousClippingPlane();
this.getCurrentPlan(modelID, name);
this.activateCurrentPlan();
if (!this.active) {
await this.moveCameraTo2DPlanPosition(animate);
this.active = true;
}
}
async exitPlanView(animate = false) {
if (!this.active)
return;
this.active = false;
this.cacheFloorplanView();
this.context.ifcCamera.setNavigationMode(NavigationModes.Orbit);
this.context.ifcCamera.projection = this.previousProjection;
if (this.currentPlan && this.currentPlan.plane) {
this.currentPlan.plane.active = false;
}
this.currentPlan = undefined;
await this.context.ifcCamera.cameraControls.setLookAt(this.previousCamera.x, this.previousCamera.y, this.previousCamera.z, this.previousTarget.x, this.previousTarget.y, this.previousTarget.z, animate);
}
async computeAllPlanViews(modelID) {
var _a;
await this.getCurrentStoreys(modelID);
const unitsScale = await this.ifc.units.getUnits(modelID, UnitType.LENGTHUNIT);
const siteCoords = await this.getSiteCoords(modelID);
const transformHeight = await this.getTransformHeight(modelID);
const storeys = this.storeys[modelID];
for (let i = 0; i < storeys.length; i++) {
if (storeys[i]) {
const baseHeight = ((_a = storeys[i].Elevation) === null || _a === void 0 ? void 0 : _a.value) || 0;
const elevation = (baseHeight + siteCoords[2]) * unitsScale + transformHeight;
const expressID = storeys[i].expressID;
// eslint-disable-next-line no-await-in-loop
await this.create({
modelID,
name: this.getFloorplanName(storeys[i]),
point: new Vector3(0, elevation + this.defaultSectionOffset, 0),
normal: new Vector3(0, -1, 0),
rotation: 0,
ortho: true,
expressID
});
}
}
}
storeCameraPosition() {
if (this.active) {
this.cacheFloorplanView();
}
else {
this.store3dCameraPosition();
}
}
async createClippingPlane(config, plan) {
if (config.normal && config.point) {
const { normal, point } = config;
const plane = this.clipper.createFromNormalAndCoplanarPoint(normal, point, true);
plane.visible = false;
plane.active = false;
plan.plane = plane;
await plane.edges.updateEdges();
plane.edges.visible = false;
}
}
async getTransformHeight(modelID) {
const transformMatrix = await this.ifc.loader.ifcManager.ifcAPI.GetCoordinationMatrix(modelID);
return transformMatrix[13];
}
async getCurrentStoreys(modelID) {
if (!this.storeys[modelID]) {
this.storeys[modelID] = await this.ifc.getAllItemsOfType(modelID, IFCBUILDINGSTOREY, true);
}
}
async getSiteCoords(modelID) {
const building = await this.getBuilding(modelID);
const sitePlace = building.ObjectPlacement.PlacementRelTo.RelativePlacement.Location;
return sitePlace.Coordinates.map((coord) => coord.value);
}
async getBuilding(modelID) {
const allBuildingsIDs = await this.ifc.getAllItemsOfType(modelID, IFCBUILDING, false);
const buildingID = allBuildingsIDs[0];
return this.ifc.getProperties(modelID, buildingID, false, true);
}
cacheFloorplanView() {
this.floorPlanViewCached = true;
this.context.ifcCamera.cameraControls.saveState();
}
async moveCameraTo2DPlanPosition(animate) {
if (this.floorPlanViewCached)
await this.context.ifcCamera.cameraControls.reset(animate);
else
await this.context.ifcCamera.cameraControls.setLookAt(0, 100, 0, 0, 0, 0, animate);
}
activateCurrentPlan() {
if (!this.currentPlan)
throw new Error('Current plan is not defined.');
if (this.currentPlan.plane)
this.currentPlan.plane.active = true;
this.context.ifcCamera.setNavigationMode(NavigationModes.Plan);
this.context.ifcCamera.projection = this.currentPlan.ortho
? CameraProjections.Orthographic
: CameraProjections.Perspective;
}
store3dCameraPosition() {
this.context.getCamera().getWorldPosition(this.previousCamera);
this.context.ifcCamera.cameraControls.getTarget(this.previousTarget);
this.previousProjection = this.context.ifcCamera.projection;
}
getCurrentPlan(modelID, name) {
if (this.planLists[modelID] === undefined)
throw new Error('The specified plan is undefined!');
const currentPlanList = this.planLists[modelID];
if (currentPlanList[name] === undefined)
throw new Error('The specified plan is undefined!');
if (!currentPlanList[name])
throw new Error('The specified plan name does not exist!');
this.currentPlan = currentPlanList[name];
}
hidePreviousClippingPlane() {
var _a;
const plane = (_a = this.currentPlan) === null || _a === void 0 ? void 0 : _a.plane;
if (plane)
plane.active = false;
}
getFloorplanName(floorplan) {
var _a, _b, _c, _d;
if ((_b = (_a = floorplan === null || floorplan === void 0 ? void 0 : floorplan.Name) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.length) {
return floorplan.Name.value;
}
if ((_d = (_c = floorplan === null || floorplan === void 0 ? void 0 : floorplan.LongName) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.length) {
return floorplan.LongName.value;
}
return floorplan.GlobalId.value;
}
}
//# sourceMappingURL=plan-manager.js.map