@inweb/viewer-visualize
Version:
JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS
254 lines (219 loc) • 10.4 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 * as utils from "./MeasureUtils";
export class MeasureLineItem {
protected htmlElemStartPoint: HTMLElement;
protected htmlElemEndPoint: HTMLElement;
protected htmlElemLine: HTMLElement;
protected htmlElemTitle: HTMLElement;
protected startPoint: number[];
protected endPoint: number[];
protected unit: string;
protected scale: number;
protected size: number;
protected style: CSSStyleDeclaration;
protected viewer: any;
protected moduleInstance: any;
protected targetElement: HTMLElement;
protected isFinishDraw: boolean;
public lineThickness: number;
constructor(targetElement: HTMLElement, viewer: any, moduleInstance: any) {
this.htmlElemStartPoint = null;
this.htmlElemEndPoint = null;
this.htmlElemLine = null;
this.htmlElemTitle = null;
this.startPoint = null;
this.endPoint = null;
this.unit = "";
this.scale = 1.0;
this.size = 10.0;
this.lineThickness = 2;
this.style = {
border: "2px solid #FFFFFF",
background: "#009bff",
color: "white",
boxShadow: "0 0 10px rgba(0,0,0,0.5)",
} as CSSStyleDeclaration;
this.htmlElemStartPoint = utils.createHtmlElementIfNeed(this.htmlElemStartPoint, targetElement, "ruler-start");
this.htmlElemEndPoint = utils.createHtmlElementIfNeed(this.htmlElemEndPoint, targetElement, "ruler-end");
this.htmlElemLine = utils.createHtmlElementIfNeed(this.htmlElemLine, targetElement, "ruler-line");
this.htmlElemTitle = utils.createHtmlElementIfNeed(this.htmlElemTitle, targetElement, "ruler-value");
this.viewer = viewer;
this.moduleInstance = moduleInstance;
this.targetElement = targetElement;
this.isFinishDraw = false;
}
drawMeasureLine(): void {
const pointSize = this.size;
const rect = this.moduleInstance.canvas.getBoundingClientRect();
// draw start point
if (this.startPoint) {
this.htmlElemStartPoint = utils.createHtmlElementIfNeed(
this.htmlElemStartPoint,
this.targetElement,
"ruler-start"
);
const pScreenStart = utils.worldToScreen(this.startPoint, this.moduleInstance, this.viewer);
if (utils.isInsideRect(pScreenStart, rect.width, rect.height)) {
this.htmlElemStartPoint.style.display = "block";
this.htmlElemStartPoint.style.cursor = "pointer";
this.htmlElemStartPoint.style.position = "absolute";
this.htmlElemStartPoint.style.top = `${pScreenStart.y - pointSize / 2}px`;
this.htmlElemStartPoint.style.left = `${pScreenStart.x - pointSize / 2}px`;
this.htmlElemStartPoint.style.borderRadius = `${pointSize}px`;
this.htmlElemStartPoint.style.border = this.style.border;
this.htmlElemStartPoint.style.background = this.style.background;
this.htmlElemStartPoint.style.zIndex = "2";
this.htmlElemStartPoint.style.width = `${pointSize}px`;
this.htmlElemStartPoint.style.height = `${pointSize}px`;
this.htmlElemStartPoint.style.boxShadow = this.style.boxShadow;
} else {
this.htmlElemStartPoint.style.display = "none";
}
}
// draw end point
if (this.endPoint && this.isFinishDraw) {
this.htmlElemEndPoint = utils.createHtmlElementIfNeed(this.htmlElemEndPoint, this.targetElement, "ruler-end");
const pScreenEnd = utils.worldToScreen(this.endPoint, this.moduleInstance, this.viewer);
if (utils.isInsideRect(pScreenEnd, rect.width, rect.height)) {
this.htmlElemEndPoint.style.display = "block";
this.htmlElemEndPoint.style.cursor = "pointer";
this.htmlElemEndPoint.style.position = "absolute";
this.htmlElemEndPoint.style.top = `${pScreenEnd.y - pointSize / 2}px`;
this.htmlElemEndPoint.style.left = `${pScreenEnd.x - pointSize / 2}px`;
this.htmlElemEndPoint.style.borderRadius = `${pointSize}px`;
this.htmlElemEndPoint.style.border = this.style.border;
this.htmlElemEndPoint.style.background = this.style.background;
this.htmlElemEndPoint.style.zIndex = "2";
this.htmlElemEndPoint.style.width = `${pointSize}px`;
this.htmlElemEndPoint.style.height = `${pointSize}px`;
this.htmlElemEndPoint.style.boxShadow = this.style.boxShadow;
} else {
this.htmlElemEndPoint.style.display = "none";
}
}
if (this.endPoint && this.startPoint) {
const point1 = utils.worldToScreen(this.startPoint, this.moduleInstance, this.viewer);
const point2 = utils.worldToScreen(this.endPoint, this.moduleInstance, this.viewer);
const { p1, p2, angle, width } = utils.getDataForDrawLineWithFixed(point1, point2, rect.width, rect.height);
const dx = p2.x - p1.x;
const dy = p2.y - p1.y;
const height = this.lineThickness;
if (utils.isInsideRect(p1, rect.width, rect.height) && utils.isInsideRect(p2, rect.width, rect.height)) {
this.htmlElemLine = utils.createHtmlElementIfNeed(this.htmlElemLine, this.targetElement, "ruler-line");
this.htmlElemLine.style.display = "block";
this.htmlElemLine.style.cursor = "pointer";
this.htmlElemLine.style.position = "absolute";
this.htmlElemLine.style.top = `${p1.y}px`;
this.htmlElemLine.style.left = `${p1.x}px`;
this.htmlElemLine.style.width = `${width}px`;
this.htmlElemLine.style.transform = `rotate(${angle}deg)`;
this.htmlElemLine.style.transformOrigin = `0px ${height / 2}px`;
this.htmlElemLine.style.boxShadow = this.style.boxShadow;
this.htmlElemLine.style.border = "none";
this.htmlElemLine.style.background = this.style.background;
this.htmlElemLine.style.zIndex = "1";
this.htmlElemLine.style.height = `${height}px`;
const distance = `${this.getDistance()} ${this.unit}`;
const pX = p1.x + dx / 2;
const pY = p1.y + dy / 2;
const widthTitle = distance.length * 10;
this.htmlElemTitle = utils.createHtmlElementIfNeed(this.htmlElemTitle, this.targetElement, "ruler-value");
this.htmlElemTitle.style.display = "block";
this.htmlElemTitle.style.cursor = "pointer";
this.htmlElemTitle.style.font = "10px";
this.htmlElemTitle.style.color = "white";
this.htmlElemTitle.style.position = "Absolute";
this.htmlElemTitle.style.top = `${pY}px`;
this.htmlElemTitle.style.left = `${pX - widthTitle / 2}px`;
this.htmlElemTitle.style.width = `${widthTitle}px`;
this.htmlElemTitle.style.transformOrigin = "0px 0px";
this.htmlElemTitle.style.borderRadius = "5px";
this.htmlElemTitle.style.boxShadow = this.style.boxShadow;
this.htmlElemTitle.style.border = "none";
this.htmlElemTitle.style.background = this.style.background;
this.htmlElemTitle.style.zIndex = "3";
this.htmlElemTitle.style.padding = "2px";
this.htmlElemTitle.style.textAlign = "center";
this.htmlElemTitle.innerHTML = `${distance}`;
} else {
this.htmlElemLine.style.display = "none";
this.htmlElemTitle.style.display = "none";
}
}
}
getDistance(): number {
let distance = utils.getDistance(this.startPoint, this.endPoint, this.moduleInstance);
if (Math.abs(this.scale - 1.0) > 10e-5) {
distance = (distance / this.scale).toFixed(2);
}
return distance;
}
setStartPoint(gePoint: number[]): void {
this.startPoint = gePoint;
this.drawMeasureLine();
}
setEndPoint(gePoint: number[], isFinish: boolean): void {
this.isFinishDraw = isFinish === undefined ? true : isFinish;
this.endPoint = gePoint;
this.drawMeasureLine();
}
update(): void {
this.drawMeasureLine();
}
setSize(size: number): void {
this.size = size;
this.drawMeasureLine();
}
clear(): void {
this.endPoint = null;
this.startPoint = null;
this.htmlElemStartPoint = utils.destroyHtmlElement(this.htmlElemStartPoint, this.targetElement);
this.htmlElemEndPoint = utils.destroyHtmlElement(this.htmlElemEndPoint, this.targetElement);
this.htmlElemLine = utils.destroyHtmlElement(this.htmlElemLine, this.targetElement);
this.htmlElemTitle = utils.destroyHtmlElement(this.htmlElemTitle, this.targetElement);
}
setUnit(unit: string): void {
this.unit = unit;
this.drawMeasureLine();
}
setConversionFactor(scale: number): void {
this.scale = scale;
this.drawMeasureLine();
}
setStyle(style: CSSStyleDeclaration): void {
this.style = style;
this.drawMeasureLine();
}
setSelectionReactor(reactor: any): void {
utils.onSetCallback(this.htmlElemStartPoint, reactor ? reactor.onStartPoint : null);
utils.onSetCallback(this.htmlElemEndPoint, reactor ? reactor.onEndPoint : null);
utils.onSetCallback(this.htmlElemTitle, reactor ? reactor.onTitle : null);
}
setSelectability(enable: boolean): void {
utils.onSetSelectivity(this.htmlElemStartPoint, enable);
utils.onSetSelectivity(this.htmlElemEndPoint, enable);
utils.onSetSelectivity(this.htmlElemLine, enable);
utils.onSetSelectivity(this.htmlElemTitle, enable);
}
}