@inweb/viewer-visualize
Version:
JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS
251 lines (190 loc) • 7.63 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 { Point2d, Point3d, Vector3d } from "../Common/Geometry";
import { Viewer } from "../../Viewer";
export class OrbitAction {
private _m_module: any;
private _subject: Viewer;
private _beginInteractivity: () => void;
private _endInteractivity: () => void;
private m_viewCenter: any;
private m_startPoint: Point2d;
constructor(m_module: any, subject: Viewer, beginInteractivity: () => void, endInteractivity: () => void) {
this._m_module = m_module;
this._subject = subject;
this._beginInteractivity = beginInteractivity;
this._endInteractivity = endInteractivity;
}
public beginAction(x: number, y: number) {
this.m_viewCenter = this.getCenter();
this.m_startPoint = { x, y };
const view = this.getViewer().activeView;
view.delete();
this._beginInteractivity();
}
public action(x: number, y: number) {
const view = this.getViewer().activeView;
const corners = view.vportRect;
const size = Math.max(Math.abs(corners[2] - corners[0]), Math.abs(corners[3] - corners[1]));
const distX = ((this.m_startPoint.x - x) * Math.PI) / size;
const distY = ((this.m_startPoint.y - y) * Math.PI) / size;
this.m_startPoint.x = x;
this.m_startPoint.y = y;
const xOrbit = distY;
const yOrbit = distX;
const viewParams = {
position: view.viewPosition,
target: view.viewTarget,
upVector: view.upVector,
viewFieldWidth: view.viewFieldWidth,
viewFieldHeight: view.viewFieldHeight,
perspective: view.perspective,
};
view.delete();
const sideVector = this.getSideVector(viewParams);
if (xOrbit !== 0.0) {
this.calculateXOrbit(viewParams, -xOrbit, sideVector);
}
if (yOrbit !== 0.0) {
this.calculateYOrbit(viewParams, yOrbit, sideVector);
}
sideVector.delete();
const extView = this.getViewer().getActiveTvExtendedView();
extView.setView(
viewParams.position,
viewParams.target,
viewParams.upVector,
viewParams.viewFieldWidth,
viewParams.viewFieldHeight,
viewParams.perspective
);
extView.delete();
this._subject.activeDragger()?.updatePreview?.();
}
public endAction() {
this._endInteractivity();
}
private getSideVector(viewParams: any): any {
const pUpV = this.toVector(viewParams.upVector);
const pTarget = this.toPoint(viewParams.target);
const pPosition = this.toPoint(viewParams.position);
const direct = pTarget.sub(pPosition);
const vDirect = direct.asVector();
const vCross = pUpV.crossProduct(vDirect);
const sideVector = vCross.normalize();
this.deleteAll([direct, pUpV, pTarget, pPosition, vDirect, vCross]);
return sideVector;
}
private calculateXOrbit(viewParams: any, delta: number, sideVector: Vector3d): void {
{
const pPoint = this.toPoint(viewParams.position);
const pCenter = this.toPoint(this.m_viewCenter);
const rotatePoint = pPoint.rotateByBasePoint(delta, sideVector, pCenter);
viewParams.position = rotatePoint.toArray();
this.deleteAll([pPoint, pCenter, rotatePoint]);
}
{
const pTarget = this.toPoint(viewParams.target);
const pCenter = this.toPoint(this.m_viewCenter);
const rotatePoint = pTarget.rotateByBasePoint(delta, sideVector, pCenter);
viewParams.target = rotatePoint.toArray();
this.deleteAll([pTarget, pCenter, rotatePoint]);
}
{
const pPoint = this.toPoint(viewParams.position);
const pTarget = this.toPoint(viewParams.target);
const pCenter = this.toPoint(this.m_viewCenter);
const pUp = pTarget.sub(pPoint);
const vUp = pUp.asVector();
const crossProduct = vUp.crossProduct(sideVector);
const crossProductNormal = crossProduct.normalize();
viewParams.upVector = crossProductNormal.toArray();
this.deleteAll([pPoint, pTarget, pCenter, pUp, vUp, crossProduct, crossProductNormal]);
}
}
private calculateYOrbit(viewParams: any, delta: number, sideVector: any): void {
{
const pPoint = this.toPoint(viewParams.position);
const pCenter = this.toPoint(this.m_viewCenter);
const zAxis = this.toVector(this._m_module.Vector3d.kZAxis);
const rotatePoint = pPoint.rotateByBasePoint(delta, zAxis, pCenter);
viewParams.position = rotatePoint.toArray();
this.deleteAll([zAxis, pPoint, pCenter, rotatePoint]);
}
{
const pTarget = this.toPoint(viewParams.target);
const pCenter = this.toPoint(this.m_viewCenter);
const zAxis = this.toVector(this._m_module.Vector3d.kZAxis);
const rotatePoint = pTarget.rotateByBasePoint(delta, zAxis, pCenter);
viewParams.target = rotatePoint.toArray();
this.deleteAll([zAxis, pTarget, pCenter, rotatePoint]);
}
{
const zAxis = this.toVector(this._m_module.Vector3d.kZAxis);
const pTarget = this.toPoint(viewParams.target);
const pPoint = this.toPoint(viewParams.position);
const side = sideVector.rotateBy(delta, zAxis);
const pUp = pTarget.sub(pPoint);
const vUp = pUp.asVector();
const cross = vUp.crossProduct(side);
const crossNormal = cross.normalize();
viewParams.upVector = crossNormal.toArray();
this.deleteAll([zAxis, pTarget, pPoint, side, pUp, vUp, cross, crossNormal]);
}
}
private getCenter(): any {
const viewer = this.getViewer();
let center;
const pSet = viewer.getSelected();
if (!pSet.isNull() && pSet.numItems() !== 0) {
const itr = pSet.getIterator();
let ext, entId, extSelected;
for (; !itr.done(); itr.step()) {
entId = itr.getEntity();
ext = entId.getWCSExtents();
if (extSelected) extSelected.addExt(ext);
else extSelected = ext;
}
center = extSelected.center();
extSelected.delete();
itr.delete();
} else {
center = viewer.getActiveExtents().center();
}
return center;
}
private getViewer(): any {
return this._m_module.getViewer();
}
private toVector(geVector): Vector3d {
return this._m_module.Vector3d.createFromArray(geVector);
}
private toPoint(gePoint: number[]): Point3d {
return this._m_module.Point3d.createFromArray(gePoint);
}
private deleteAll(objects): void {
for (const obj of objects) {
obj?.delete?.();
}
}
}