@inweb/viewer-visualize
Version:
JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS
183 lines (152 loc) • 5.92 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 } from "../Common/Geometry";
export function createHtmlElementIfNeed(
element: HTMLElement,
targetElement: HTMLElement,
dataTestId: string
): HTMLElement {
if (!element) {
element = document.createElement("div");
element.setAttribute("data-testid", dataTestId);
targetElement.appendChild(element);
}
return element;
}
export function destroyHtmlElement(element: HTMLElement, targetElement: HTMLElement) {
if (element) {
targetElement.removeChild(element);
}
return null;
}
export function worldToScreen(gePoint: number[], moduleInstance, viewer): Point2d {
const worldPoint = moduleInstance.Point3d.createFromArray(gePoint);
const avp = viewer.activeView;
const mtx = avp.worldToDeviceMatrix;
const devicePoint = worldPoint.transformBy(mtx);
const res = { x: devicePoint.x / window.devicePixelRatio, y: devicePoint.y / window.devicePixelRatio };
mtx.delete();
worldPoint.delete();
devicePoint.delete();
avp.delete();
return res;
}
export function getDistance(gePoint1: number[], gePoint2: number[], moduleInstance: any) {
const tvPoint1 = moduleInstance.Point3d.createFromArray(gePoint1);
const tvPoint2 = moduleInstance.Point3d.createFromArray(gePoint2);
const distance = tvPoint1.distanceTo(tvPoint2).toFixed(2);
tvPoint1.delete();
tvPoint2.delete();
return distance;
}
export function getAngle(geStart: number[], geOrigin: number[], geEnd: number[], moduleInstance: any): number {
const tvStart = moduleInstance.Point3d.createFromArray(geStart);
const tvOrigin = moduleInstance.Point3d.createFromArray(geOrigin);
const tvEnd = moduleInstance.Point3d.createFromArray(geEnd);
const s1 = tvStart.sub(tvOrigin);
const s2 = tvEnd.sub(tvOrigin);
const v1 = s1.asVector();
const v2 = s2.asVector();
const angle = (180 * v1.angleTo(v2)) / Math.PI;
return angle;
}
export function getDataForDrawLine(p1: Point2d, p2: Point2d) {
const dx = p2.x - p1.x;
const dy = p2.y - p1.y;
let angle = (180 * Math.atan(dy / dx)) / Math.PI;
if (dx < 0) {
angle -= 180;
}
const width = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
return { angle, width };
}
function normalizeFloat(value: number): number {
return value < 0 ? Math.ceil(value) : Math.floor(value);
}
const lineSegmentsIntersect = (p1: Point2d, p2: Point2d, p3: Point2d, p4: Point2d): false | Point2d => {
const a_dx = p2.x - p1.x;
const a_dy = p2.y - p1.y;
const b_dx = p4.x - p3.x;
const b_dy = p4.y - p3.y;
const s = (-a_dy * (p1.x - p3.x) + a_dx * (p1.y - p3.y)) / (-b_dx * a_dy + a_dx * b_dy);
const t = (+b_dx * (p1.y - p3.y) - b_dy * (p1.x - p3.x)) / (-b_dx * a_dy + a_dx * b_dy);
return s >= 0 && s <= 1 && t >= 0 && t <= 1
? {
x: normalizeFloat(p1.x + t * a_dx),
y: normalizeFloat(p1.y + t * a_dy),
}
: false;
};
function checkSegmentsIntersect(p1: Point2d, p2: Point2d, p3: Point2d, p4: Point2d, res: Point2d[]): void {
const r = lineSegmentsIntersect(p1, p2, p3, p4);
if (r) {
res.push(r);
}
}
export function isInsideRect(p: Point2d, width: number, height: number): boolean {
return p.x <= width && p.x >= 0 && p.y <= height && p.y >= 0;
}
export function getDataForDrawLineWithFixed(p1: Point2d, p2: Point2d, width: number, height: number) {
const pLU = { x: 0, y: 0 };
const pRU = { x: width, y: 0 };
const pLB = { x: 0, y: height };
const pRB = { x: width, y: height };
const intersects: Point2d[] = [];
checkSegmentsIntersect(p1, p2, pLU, pRU, intersects);
checkSegmentsIntersect(p1, p2, pLU, pLB, intersects);
checkSegmentsIntersect(p1, p2, pLB, pRB, intersects);
checkSegmentsIntersect(p1, p2, pRB, pRU, intersects);
let fixedP1: Point2d = null;
let fixedP2: Point2d = null;
if (intersects.length === 0) {
fixedP1 = p1;
fixedP2 = p2;
} else if (intersects.length === 1) {
if (isInsideRect(p1, width, height)) {
fixedP1 = p1;
fixedP2 = intersects[0];
} else {
fixedP1 = intersects[0];
fixedP2 = p2;
}
} else {
fixedP1 = intersects[0];
fixedP2 = intersects[1];
}
const dx = fixedP2.x - fixedP1.x;
const dy = fixedP2.y - fixedP1.y;
let angle = (180 * Math.atan(dy / dx)) / Math.PI;
if (dx < 0) {
angle -= 180;
}
const size = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
return { angle, width: size, p1: fixedP1, p2: fixedP2 };
}
export function onSetCallback(element: HTMLElement, cb: () => void): void {
if (element) {
element.onclick = cb ? () => cb() : () => {};
}
}
export function onSetSelectivity(element: HTMLElement, enable: boolean): void {
element.style.pointerEvents = enable ? "auto" : "none";
}