UNPKG

@itwin/core-frontend

Version:
247 lines • 11.5 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module LocatingElements */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TentativePoint = void 0; const core_geometry_1 = require("@itwin/core-geometry"); const AccuSnap_1 = require("./AccuSnap"); const HitDetail_1 = require("./HitDetail"); const IModelApp_1 = require("./IModelApp"); const Tool_1 = require("./tools/Tool"); const ViewTool_1 = require("./tools/ViewTool"); /** * @public * @extensions */ class TentativePoint { isActive = false; currSnap; tpHits; get _hotDistanceInches() { return 0.21; } _point = new core_geometry_1.Point3d(); _rawPoint = new core_geometry_1.Point3d(); _viewPoint = new core_geometry_1.Point3d(); _tentativePromise; viewport; onInitialized() { } setHitList(list) { this.tpHits = list; } /** @return true if the tentative point is currently active and snapped to an element. */ get isSnapped() { return undefined !== this.currSnap; } /** @return The current snap path when TentativePoint.isSnapped or undefined. */ getCurrSnap() { return this.currSnap; } getPoint() { const snap = this.currSnap; return !snap ? this._point : snap.adjustedPoint; } setPoint(point) { this.setCurrSnap(undefined); this.tpHits = undefined; this._point.setFrom(point); } clear(doErase) { if (doErase) { this.removeTentative(); IModelApp_1.IModelApp.accuSnap.synchSnapMode(); } IModelApp_1.IModelApp.accuSnap.destroy(); this.isActive = false; this.setCurrSnap(undefined); this.tpHits = undefined; } removeTentative() { this._tentativePromise = undefined; if (!this.isActive) return; IModelApp_1.IModelApp.accuSnap.erase(); if (this.getCurrSnap()) IModelApp_1.IModelApp.viewManager.invalidateDecorationsAllViews(); else this.viewport.invalidateDecorations(); this.isActive = false; } setCurrSnap(newSnap) { if (newSnap) newSnap.setSnapPoint(newSnap.snapPoint, HitDetail_1.SnapHeat.InRange); // Reset adjustedPoint from pre-located snap and set SnapHeat... this.currSnap = newSnap; } showTentative() { if (this.isSnapped) { IModelApp_1.IModelApp.viewManager.invalidateDecorationsAllViews(); IModelApp_1.IModelApp.accuSnap.displayToolTip(this._viewPoint, this.viewport, undefined); } else { this.viewport.invalidateDecorations(); } this.isActive = true; } getHitAndList(holder) { const hit = this.currSnap; if (hit) { holder.setHitList(this.tpHits); this.tpHits = undefined; } return hit; } onButtonEvent(ev) { switch (ev.button) { case Tool_1.BeButton.Data: if (!ev.isDown) return; // cleared on down... break; case Tool_1.BeButton.Reset: if (ev.isDown) return; // cleared on up... break; case Tool_1.BeButton.Middle: return; } this.removeTentative(); IModelApp_1.IModelApp.accuSnap.synchSnapMode(); this.setCurrSnap(undefined); this.tpHits = undefined; } decorate(context) { const viewport = context.viewport; if (!this.isActive || !viewport) return; const tpSize = Math.floor(viewport.pixelsPerInch * 0.4) + 0.5; const toSizeOutline = tpSize + 1; const position = context.viewport.worldToView(this._point); position.x = Math.floor(position.x) + 0.5; position.y = Math.floor(position.y) + 0.5; const drawDecoration = (ctx) => { ctx.beginPath(); ctx.strokeStyle = "rgba(0,0,0,.5)"; ctx.lineWidth = 3; ctx.moveTo(-toSizeOutline, 0); ctx.lineTo(toSizeOutline, 0); ctx.moveTo(0, -toSizeOutline); ctx.lineTo(0, toSizeOutline); ctx.stroke(); ctx.beginPath(); ctx.strokeStyle = "white"; ctx.lineWidth = 1; if (!this.isSnapped) ctx.setLineDash([4, 1]); ctx.shadowColor = "black"; ctx.shadowBlur = 5; ctx.moveTo(-tpSize, 0); ctx.lineTo(tpSize, 0); ctx.moveTo(0, -tpSize); ctx.lineTo(0, tpSize); ctx.stroke(); }; context.addCanvasDecoration({ position, drawDecoration }); } async getSnap(newSearch) { // Use next hit from previous search when using tentative to cycle through hits... let thisHit = (!newSearch && undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined); // Use existing AccuSnap hit list if one exists... if (undefined === thisHit) { this.tpHits = undefined; thisHit = IModelApp_1.IModelApp.accuSnap.getHitAndList(this); } if (undefined === thisHit) { // search for elements around the current raw point (search should not be affected by locks!) const aperture = (2.0 * this.viewport.pixelsFromInches(IModelApp_1.IModelApp.locateManager.apertureInches) / 2.0) + 1.5; const options = IModelApp_1.IModelApp.locateManager.options.clone(); // Copy to avoid changing out from under active Tool... const picker = IModelApp_1.IModelApp.locateManager.picker; options.hitSource = HitDetail_1.HitSource.TentativeSnap; if (0 === picker.doPick(this.viewport, this._rawPoint, aperture, options)) return undefined; this.tpHits = picker.getHitList(true); thisHit = (undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined); } else if (thisHit instanceof HitDetail_1.SnapDetail) { // Make the current AccuSnap the TentativePoint snap... return thisHit; } if (undefined === thisHit) return undefined; const snapModes = IModelApp_1.IModelApp.accuSnap.getActiveSnapModes(); // Get the list of point snap modes to consider if (1 === snapModes.length && HitDetail_1.SnapMode.Intersection === snapModes[0]) snapModes.push(HitDetail_1.SnapMode.Nearest); // Add nearest when doing intersection by itself to support finding extended intersections... const thisSnap = await AccuSnap_1.AccuSnap.requestSnap(thisHit, snapModes, this._hotDistanceInches, IModelApp_1.IModelApp.accuSnap.keypointDivisor, this.tpHits); if (undefined !== thisSnap) IModelApp_1.IModelApp.accuDraw.onSnap(thisSnap); // AccuDraw can adjust nearest snap to intersection of circle (polar distance lock) or line (axis lock) with snapped to curve... return thisSnap; } static arePointsCloseEnough(pt1, pt2, pixelDistance) { return pt1.distance(pt2) < (pixelDistance + 1.5); } process(ev) { if (undefined !== this._tentativePromise) return; const currTool = IModelApp_1.IModelApp.toolAdmin.viewTool; if (currTool && currTool.inDynamicUpdate) return; // trying to tentative snap while view is changing isn't useful... const wasActive = this.isActive; this.removeTentative(); // remove the TP cross if it is already on the screen const lastPtView = this._viewPoint.clone(); this.viewport = ev.viewport; this._point.setFrom(ev.point); this._rawPoint.setFrom(ev.rawPoint); this._viewPoint.setFrom(ev.viewPoint); const newSearch = (!this.isSnapped || !TentativePoint.arePointsCloseEnough(lastPtView, this._viewPoint, this.viewport.pixelsFromInches(IModelApp_1.IModelApp.locateManager.apertureInches))); const promise = this.getSnap(newSearch); this._tentativePromise = promise; promise.then((newSnap) => { // Ignore response if we're no longer interested in this tentative. if (this._tentativePromise === promise) { this._tentativePromise = undefined; this.setCurrSnap(newSnap); // Adopt the snap as current IModelApp_1.IModelApp.accuSnap.clear(); // make sure there's no AccuSnap active after a tentative point (otherwise we continually snap to it). if (this.isSnapped) this._point.setFrom(this.currSnap.snapPoint); else if (wasActive && newSearch) this._point.setFrom(ev.rawPoint); this.showTentative(); // show the TP cross if (this.isSnapped) { IModelApp_1.IModelApp.toolAdmin.adjustSnapPoint(); } else if (IModelApp_1.IModelApp.accuDraw.isActive) { const point = this.getPoint().clone(); const vp = ev.viewport; if (vp.isSnapAdjustmentRequired) { IModelApp_1.IModelApp.toolAdmin.adjustPointToACS(point, vp, false); const hit = new HitDetail_1.HitDetail({ testPoint: point, viewport: vp, hitSource: HitDetail_1.HitSource.TentativeSnap, hitPoint: point, sourceId: "", priority: HitDetail_1.HitPriority.Unknown, distXY: 0, distFraction: 0, }); const snap = new HitDetail_1.SnapDetail(hit); this.setCurrSnap(snap); IModelApp_1.IModelApp.toolAdmin.adjustSnapPoint(); this.setPoint(this.getPoint()); } else { IModelApp_1.IModelApp.accuDraw.adjustPoint(point, vp, false); const savePoint = point.clone(); IModelApp_1.IModelApp.toolAdmin.adjustPointToGrid(point, vp); if (!point.isExactEqual(savePoint)) IModelApp_1.IModelApp.accuDraw.adjustPoint(point, vp, false); this.setPoint(point); } } else { IModelApp_1.IModelApp.toolAdmin.adjustPoint(this.getPoint(), ev.viewport); } IModelApp_1.IModelApp.accuDraw.onTentative(); if (currTool && currTool instanceof ViewTool_1.ViewManip && currTool.viewHandles.hasHandle(ViewTool_1.ViewHandleType.TargetCenter)) currTool.updateTargetCenter(); // Change target center to tentative location... else IModelApp_1.IModelApp.toolAdmin.updateDynamics(undefined, undefined, true); // Don't wait for motion to update dynamics... } }); } } exports.TentativePoint = TentativePoint; //# sourceMappingURL=TentativePoint.js.map