@inweb/viewer-visualize
Version:
JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS
185 lines (141 loc) • 5.7 kB
text/typescript
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
// This application incorporates Open Design Alliance software pursuant to a
// license agreement with Open Design Alliance.
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
// All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////
import { Viewer } from "../Viewer";
import { Point2d } from "./Common/Geometry";
import { ViewParams } from "./Common/OdaGeAction";
import { OdBaseDragger } from "./Common/OdBaseDragger";
export class OrbitAroundBuildingDragger extends OdBaseDragger {
protected maxPolarAngle: number;
protected minPolarAngle: number;
protected m_viewCenter: any;
protected m_startPoint: Point2d;
protected startCameraParams: ViewParams;
protected m_delta: number;
constructor(viewer: Viewer) {
super(viewer);
this.autoSelect = true;
this.press = false;
this.maxPolarAngle = Math.PI / 2;
this.minPolarAngle = 0; // radians
}
override start(x: number, y: number): void {
this.press = true;
this.m_viewCenter = this.getCenter();
this.m_startPoint = { x, y };
const view = this.getViewer().activeView;
this.startCameraParams = this.getViewParams();
const corners = view.vportRect;
this.m_delta = Math.max(corners[1] - corners[0], corners[2] - corners[3]);
this.beginInteractivity();
}
setDefaultViewParams(): void {
this.setViewParams(this.startCameraParams);
}
override drag(x: number, y: number): void {
if (this.press) {
let dX = x - this.m_startPoint.x;
let dY = y - this.m_startPoint.y;
dX *= Math.PI / this.m_delta;
dY *= Math.PI / this.m_delta;
this.setDefaultViewParams();
const { Vector3d, Matrix3d } = this.m_module;
const target = Vector3d.createFromArray(this.startCameraParams.target);
const offset = Vector3d.createFromArray(this.startCameraParams.position).sub(target);
const dir = offset.normalize();
const zMatrix = new Matrix3d();
zMatrix.setToIdentity();
const xMatrix = new Matrix3d();
xMatrix.setToIdentity();
// ---- restore start rotation ----
const yAxis = Vector3d.createFromArray([dir.x, dir.y, dir.z]);
const zAxis = Vector3d.createFromArray(this.startCameraParams.upVector);
const xAxis = yAxis.crossProduct(zAxis);
// ----------- zAxis rotation restore -----------
let xyDir = Vector3d.createFromArray([yAxis.x, yAxis.y, 0]);
if (xyDir.length() <= 0.00001) {
xyDir.set(-xAxis.y, xAxis.x, 0);
} else {
xyDir = xyDir.normalize();
}
const xyAngle =
Math.sign(xyDir.dotProduct(Vector3d.createFromArray([-1, 0, 0]))) *
xyDir.angleTo(Vector3d.createFromArray([0, 1, 0]));
dX -= xyAngle;
// ----------- zAxis rotation restore -----------
// ----------- xAxis rotation restore -----------
let yzDir = Vector3d.createFromArray([dir.x, dir.y, 0]);
let yzAngle = 0;
if (yzDir.length() <= 0.00001) {
yzAngle = (-dir.z * Math.PI) / 2;
} else {
yzDir = yzDir.normalize();
yzAngle = -yzDir.angleTo(dir);
}
dY -= yzAngle;
// ----------- xAxis rotation restore -----------
// ---- restore start rotation ----
zMatrix.setToRotation(-dX, [0, 0, 1], [0, 0, 0]);
const xAngle = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, dY));
xMatrix.setToRotation(xAngle, [1, 0, 0], [0, 0, 0]);
const endMatrix = zMatrix.postMultBy(xMatrix);
let pos = Vector3d.createFromArray([0, 1, 0]).transformBy(endMatrix);
const up = Vector3d.createFromArray([0, 0, 1]).transformBy(endMatrix);
pos.setLength(offset.length());
pos = target.add(pos);
const current = this.getViewParams();
current.position = pos.toArray();
current.upVector = up.toArray();
this.setViewParams(current);
}
}
override end(): void {
this.press = false;
this.endInteractivity();
}
getCenter(): any {
const viewer = this.getViewer();
let ext = viewer.getActiveExtents();
const pSet = viewer.getSelected();
if (!pSet.isNull() && pSet.numItems() !== 0) {
const itr = pSet.getIterator();
const entId = itr.getEntity();
if (entId.getType() === 1) {
const obj = entId.openObject();
ext.delete();
ext = obj.getExtents();
obj.delete();
} else if (entId.getType() === 2) {
const obj = entId.openObjectAsInsert();
const extTuple = obj.getExtents();
ext.delete();
ext = extTuple.ext;
extTuple.delete();
obj.delete();
}
itr.delete();
}
const center = ext.center();
ext.delete();
return center;
}
}