UNPKG

@inweb/viewer-visualize

Version:

JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS

290 lines (251 loc) 9.18 kB
/////////////////////////////////////////////////////////////////////////////// // 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 { OdBaseDragger } from "../Common/OdBaseDragger"; import { MeasureLineItem } from "./MeasureLineItem"; import { IOptions } from "@inweb/viewer-core"; function renameUnit(table, unit) { return table[unit] || unit; } export class MeasureLineDragger extends OdBaseDragger { protected lineThickness: number; protected gripingRadius: number; protected firstPoint: number[]; protected secondPoint: number[]; protected items: MeasureLineItem[]; protected m_overlayElement: HTMLElement; protected previewMeasureLine: MeasureLineItem; protected conversionFactor: number; protected rulerUnitTable: any; protected rulerUnit: string; protected rulerPrecision: any; constructor(subject: Viewer) { super(subject); this.lineThickness = 2; this.press = false; this.gripingRadius = 5.0; this.firstPoint = null; this.secondPoint = null; this.rulerUnitTable = { Millimeters: "mm", Centimeters: "cm", Meters: "m", Feet: "ft", Inches: "in", Yards: "yd", Kilometers: "km", Miles: "mi", Micrometers: "µm", Mils: "mil", MicroInches: "µin", Default: "unit", }; this.rulerUnit = subject.options.rulerUnit ?? "Default"; this.rulerPrecision = subject.options.rulerPrecision ?? "Default"; this.items = []; this.canvasEvents.push("resize", "optionsChange"); } override initialize(): void { super.initialize(); this.m_overlayElement = document.createElement("div"); this.m_overlayElement.style.background = "rgba(0,0,0,0)"; this.m_overlayElement.style.position = "fixed"; this.m_overlayElement.style.zIndex = "1"; this.m_overlayElement.style.pointerEvents = "none"; document.body.appendChild(this.m_overlayElement); this.subject.addEventListener("optionschange", this.optionsChange); this.resize(); } override dispose(): void { super.dispose(); this.m_overlayElement.remove(); this.subject.removeEventListener("optionschange", this.optionsChange); } override updatePreview(): void { this.items.forEach((item) => item.update()); } resize(): void { const rect = this.m_module.canvas.getBoundingClientRect(); this.m_overlayElement.style.top = `${rect.top}px`; this.m_overlayElement.style.left = `${rect.left}px`; this.m_overlayElement.style.width = `${rect.width}px`; this.m_overlayElement.style.height = `${rect.height}px`; } getSnapPointRadius(): number { const view = this.getViewer().activeView; const corners = view.viewDcCorners(); const pt1 = corners.lowerLeft; const pt2 = corners.upperRight; pt2[0] -= pt1[0]; pt2[1] -= pt1[1]; return Math.min(pt2[0], pt2[1]) / 120; } override start(x: number, y: number): void { this.createNewMeasureIfNeed(); const point = this.getViewer().getSnapPoint(x, y, this.gripingRadius); if (point) { this.firstPoint = point; this.previewMeasureLine.setStartPoint(this.firstPoint); } } override drag(x: number, y: number): void { this.createNewMeasureIfNeed(); const point = this.getViewer().getSnapPoint(x, y, this.gripingRadius); if (this.isDragging) { if (point) { if (this.firstPoint) { this.secondPoint = point; this.previewMeasureLine.setStartPoint(this.firstPoint); this.previewMeasureLine.setEndPoint(this.secondPoint, true); } else { this.firstPoint = point; this.previewMeasureLine.setStartPoint(this.firstPoint); } } else { this.secondPoint = null; this.previewMeasureLine.clear(); this.previewMeasureLine.setStartPoint(this.firstPoint); this.previewMeasureLine.setEndPoint(this.getViewer().screenToWorld(x, y), false); } } else { if (point) { this.previewMeasureLine.setStartPoint(point); } else { this.previewMeasureLine.clear(); } } } override end(): void { if (this.firstPoint && this.secondPoint) { const newLineMeasure = this.createMeasureLine(); newLineMeasure.setStartPoint(this.firstPoint); newLineMeasure.setEndPoint(this.secondPoint, true); } this.firstPoint = null; this.secondPoint = null; this.previewMeasureLine.clear(); } createNewMeasureIfNeed(): void { if (!this.previewMeasureLine) { this.previewMeasureLine = this.createMeasureLine(); } } createMeasureLine(): MeasureLineItem { const viewer = this.m_module.getViewer(); const item = new MeasureLineItem(this.m_overlayElement, viewer, this.m_module); item.lineThickness = this.lineThickness || item.lineThickness; const isDefaultUnit = this.rulerUnit === "Default"; const isDefaultPrecision = this.rulerPrecision === "Default"; item.setUnit(renameUnit(this.rulerUnitTable, isDefaultUnit ? viewer.getUnit() : this.rulerUnit)); if (!isDefaultUnit) { const fromUnit = this.getKUnitByName(viewer.getUnit()); const toUnit = this.getKUnitByName(this.subject.options.rulerUnit); const multiplier = viewer.getUnitsConversionCoef(fromUnit, toUnit); this.conversionFactor = 1 / multiplier; item.setConversionFactor(this.conversionFactor); } else { item.setConversionFactor(1.0); } if (!isDefaultPrecision) { item.setPrecision(this.rulerPrecision); } else { item.setPrecision(2); } this.items.push(item); return item; } optionsChange(event): void { const options: IOptions = event.data; const toUnitName = options.rulerUnit ?? "Default"; const toPrecision = options.rulerPrecision ?? "Default"; const unitChanged = this.rulerUnit !== toUnitName; const precisionChanged = this.rulerPrecision !== toPrecision; if (!unitChanged && !precisionChanged) return; this.rulerUnit = toUnitName; this.rulerPrecision = toPrecision; const drawingUnit = this.m_module.getViewer().getUnit(); const eToUnit = this.getKUnitByName(toUnitName); const eFromUnit = this.getKUnitByName(drawingUnit); this.items.forEach((item) => { if (unitChanged) { if (toUnitName === "Default") { item.setUnit(renameUnit(this.rulerUnitTable, drawingUnit)); item.setConversionFactor(1.0); } else { item.setUnit(renameUnit(this.rulerUnitTable, toUnitName)); const multiplier = this.m_module.getViewer().getUnitsConversionCoef(eFromUnit, eToUnit); this.conversionFactor = 1 / multiplier; item.setConversionFactor(this.conversionFactor); } } if (precisionChanged) { if (toPrecision === "Default") { item.setPrecision(2); } else { item.setPrecision(toPrecision); } } }); } getKUnitByName(unitName: string): any { let eUnit = this.m_module.Units.kUserDefined; switch (unitName) { case "Millimeters": eUnit = this.m_module.Units.kMillimeters; break; case "Centimeters": eUnit = this.m_module.Units.kCentimeters; break; case "Meters": eUnit = this.m_module.Units.kMeters; break; case "Feet": eUnit = this.m_module.Units.kFeet; break; case "Inches": eUnit = this.m_module.Units.kInches; break; case "Yards": eUnit = this.m_module.Units.kYards; break; case "Kilometers": eUnit = this.m_module.Units.kKilometers; break; case "Miles": eUnit = this.m_module.Units.kMiles; break; case "Micrometers": eUnit = this.m_module.Units.kMicrometers; break; case "Mils": eUnit = this.m_module.Units.kMils; break; case "MicroInches": eUnit = this.m_module.Units.kMicroInches; break; default: break; } return eUnit; } }