@itwin/editor-frontend 4.0.0-dev.8 → 4.0.0-dev.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/lib/cjs/CreateElementTool.d.ts +100 -100
- package/lib/cjs/CreateElementTool.js +325 -327
- package/lib/cjs/CreateElementTool.js.map +1 -1
- package/lib/cjs/DeleteElementsTool.d.ts +13 -13
- package/lib/cjs/DeleteElementsTool.js +38 -38
- package/lib/cjs/DeleteElementsTool.js.map +1 -1
- package/lib/cjs/EditTool.d.ts +38 -38
- package/lib/cjs/EditTool.js +80 -81
- package/lib/cjs/EditTool.js.map +1 -1
- package/lib/cjs/EditToolIpc.d.ts +18 -18
- package/lib/cjs/EditToolIpc.js +28 -28
- package/lib/cjs/ElementGeometryTool.d.ts +147 -147
- package/lib/cjs/ElementGeometryTool.js +704 -709
- package/lib/cjs/ElementGeometryTool.js.map +1 -1
- package/lib/cjs/ModifyCurveTools.d.ts +139 -139
- package/lib/cjs/ModifyCurveTools.js +776 -784
- package/lib/cjs/ModifyCurveTools.js.map +1 -1
- package/lib/cjs/ModifyElementTool.d.ts +47 -47
- package/lib/cjs/ModifyElementTool.js +177 -177
- package/lib/cjs/ModifyElementTool.js.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.d.ts +135 -135
- package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js +822 -822
- package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectGeolocation.d.ts +135 -135
- package/lib/cjs/ProjectLocation/ProjectGeolocation.js +532 -532
- package/lib/cjs/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/cjs/SketchTools.d.ts +304 -304
- package/lib/cjs/SketchTools.js +1704 -1705
- package/lib/cjs/SketchTools.js.map +1 -1
- package/lib/cjs/SolidModelingTools.d.ts +380 -380
- package/lib/cjs/SolidModelingTools.js +1452 -1462
- package/lib/cjs/SolidModelingTools.js.map +1 -1
- package/lib/cjs/SolidPrimitiveTools.d.ts +318 -318
- package/lib/cjs/SolidPrimitiveTools.js +1372 -1378
- package/lib/cjs/SolidPrimitiveTools.js.map +1 -1
- package/lib/cjs/TransformElementsTool.d.ts +164 -164
- package/lib/cjs/TransformElementsTool.js +652 -652
- package/lib/cjs/TransformElementsTool.js.map +1 -1
- package/lib/cjs/UndoRedoTool.d.ts +16 -16
- package/lib/cjs/UndoRedoTool.js +41 -42
- package/lib/cjs/UndoRedoTool.js.map +1 -1
- package/lib/cjs/editor-frontend.d.ts +17 -17
- package/lib/cjs/editor-frontend.js +37 -33
- package/lib/cjs/editor-frontend.js.map +1 -1
- package/lib/esm/CreateElementTool.d.ts +100 -100
- package/lib/esm/CreateElementTool.js +317 -319
- package/lib/esm/CreateElementTool.js.map +1 -1
- package/lib/esm/DeleteElementsTool.d.ts +13 -13
- package/lib/esm/DeleteElementsTool.js +35 -34
- package/lib/esm/DeleteElementsTool.js.map +1 -1
- package/lib/esm/EditTool.d.ts +38 -38
- package/lib/esm/EditTool.js +77 -77
- package/lib/esm/EditTool.js.map +1 -1
- package/lib/esm/EditToolIpc.d.ts +18 -18
- package/lib/esm/EditToolIpc.js +24 -24
- package/lib/esm/ElementGeometryTool.d.ts +147 -147
- package/lib/esm/ElementGeometryTool.js +696 -701
- package/lib/esm/ElementGeometryTool.js.map +1 -1
- package/lib/esm/ModifyCurveTools.d.ts +139 -139
- package/lib/esm/ModifyCurveTools.js +771 -775
- package/lib/esm/ModifyCurveTools.js.map +1 -1
- package/lib/esm/ModifyElementTool.d.ts +47 -47
- package/lib/esm/ModifyElementTool.js +172 -172
- package/lib/esm/ModifyElementTool.js.map +1 -1
- package/lib/esm/ProjectLocation/ProjectExtentsDecoration.d.ts +135 -135
- package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js +818 -814
- package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
- package/lib/esm/ProjectLocation/ProjectGeolocation.d.ts +135 -135
- package/lib/esm/ProjectLocation/ProjectGeolocation.js +529 -526
- package/lib/esm/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/esm/SketchTools.d.ts +304 -304
- package/lib/esm/SketchTools.js +1700 -1695
- package/lib/esm/SketchTools.js.map +1 -1
- package/lib/esm/SolidModelingTools.d.ts +380 -380
- package/lib/esm/SolidModelingTools.js +1444 -1437
- package/lib/esm/SolidModelingTools.js.map +1 -1
- package/lib/esm/SolidPrimitiveTools.d.ts +318 -318
- package/lib/esm/SolidPrimitiveTools.js +1368 -1367
- package/lib/esm/SolidPrimitiveTools.js.map +1 -1
- package/lib/esm/TransformElementsTool.d.ts +164 -164
- package/lib/esm/TransformElementsTool.js +647 -644
- package/lib/esm/TransformElementsTool.js.map +1 -1
- package/lib/esm/UndoRedoTool.d.ts +16 -16
- package/lib/esm/UndoRedoTool.js +38 -36
- package/lib/esm/UndoRedoTool.js.map +1 -1
- package/lib/esm/editor-frontend.d.ts +17 -17
- package/lib/esm/editor-frontend.js +21 -21
- package/package.json +20 -20
|
@@ -1,823 +1,823 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*---------------------------------------------------------------------------------------------
|
|
3
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
-
*--------------------------------------------------------------------------------------------*/
|
|
6
|
-
/** @packageDocumentation
|
|
7
|
-
* @module Editing
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.ProjectLocationSaveTool = exports.ProjectLocationCancelTool = exports.ProjectLocationHideTool = exports.ProjectLocationShowTool = exports.ProjectExtentsClipDecoration = exports.ProjectLocationChanged = void 0;
|
|
11
|
-
const core_bentley_1 = require("@itwin/core-bentley");
|
|
12
|
-
const core_common_1 = require("@itwin/core-common");
|
|
13
|
-
const core_frontend_1 = require("@itwin/core-frontend");
|
|
14
|
-
const core_geometry_1 = require("@itwin/core-geometry");
|
|
15
|
-
const editor_common_1 = require("@itwin/editor-common");
|
|
16
|
-
const EditTool_1 = require("../EditTool");
|
|
17
|
-
const EditToolIpc_1 = require("../EditToolIpc");
|
|
18
|
-
const ProjectGeolocation_1 = require("./ProjectGeolocation");
|
|
19
|
-
function translateMessage(key) {
|
|
20
|
-
return EditTool_1.EditTools.translate(`ProjectLocation:Message.${key}`);
|
|
21
|
-
}
|
|
22
|
-
function translateMessageBold(key) {
|
|
23
|
-
return `<b>${translateMessage(key)}:</b> `;
|
|
24
|
-
}
|
|
25
|
-
function translateCoreMeasureBold(key) {
|
|
26
|
-
return `<b>${core_frontend_1.CoreTools.translate(`Measure.Labels.${key}`)}:</b> `;
|
|
27
|
-
}
|
|
28
|
-
function clearViewClip(vp) {
|
|
29
|
-
if (!core_frontend_1.ViewClipTool.doClipClear(vp))
|
|
30
|
-
return false;
|
|
31
|
-
core_frontend_1.ViewClipDecorationProvider.create().onClearClip(vp); // Send clear event...
|
|
32
|
-
core_frontend_1.ViewClipDecorationProvider.clear();
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
function clipToProjectExtents(vp) {
|
|
36
|
-
clearViewClip(vp); // Clear any existing view clip and send clear event...
|
|
37
|
-
core_frontend_1.ViewClipTool.enableClipVolume(vp);
|
|
38
|
-
return core_frontend_1.ViewClipTool.doClipToRange(vp, vp.iModel.projectExtents, core_geometry_1.Transform.createIdentity());
|
|
39
|
-
}
|
|
40
|
-
function enableBackgroundMap(viewport, onOff) {
|
|
41
|
-
if (onOff === viewport.viewFlags.backgroundMap)
|
|
42
|
-
return false;
|
|
43
|
-
viewport.viewFlags = viewport.viewFlags.with("backgroundMap", onOff);
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
function updateMapDisplay(vp, turnOnMap) {
|
|
47
|
-
if (!turnOnMap || !enableBackgroundMap(vp, true))
|
|
48
|
-
vp.invalidateRenderPlan();
|
|
49
|
-
}
|
|
50
|
-
class ProjectExtentsControlArrow extends core_frontend_1.ViewClipControlArrow {
|
|
51
|
-
constructor() {
|
|
52
|
-
super(...arguments);
|
|
53
|
-
this.extentValid = true;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/** Values for [[ProjectExtentsClipDecoration.onChanged] event.
|
|
57
|
-
* @beta
|
|
58
|
-
*/
|
|
59
|
-
var ProjectLocationChanged;
|
|
60
|
-
(function (ProjectLocationChanged) {
|
|
61
|
-
/** Extents has been modified (unsaved changes) */
|
|
62
|
-
ProjectLocationChanged[ProjectLocationChanged["Extents"] = 0] = "Extents";
|
|
63
|
-
/** Geolocation has been modified (unsaved changes) */
|
|
64
|
-
ProjectLocationChanged[ProjectLocationChanged["Geolocation"] = 1] = "Geolocation";
|
|
65
|
-
/** Abandon unsaved changes to extents */
|
|
66
|
-
ProjectLocationChanged[ProjectLocationChanged["ResetExtents"] = 2] = "ResetExtents";
|
|
67
|
-
/** Abandon unsaved changes to geolocation */
|
|
68
|
-
ProjectLocationChanged[ProjectLocationChanged["ResetGeolocation"] = 3] = "ResetGeolocation";
|
|
69
|
-
/** Decoration hidden (unsaved changes preserved) */
|
|
70
|
-
ProjectLocationChanged[ProjectLocationChanged["Hide"] = 4] = "Hide";
|
|
71
|
-
/** Decoration shown (unsaved changes restored) */
|
|
72
|
-
ProjectLocationChanged[ProjectLocationChanged["Show"] = 5] = "Show";
|
|
73
|
-
/** Save changes to extents and geolocation */
|
|
74
|
-
ProjectLocationChanged[ProjectLocationChanged["Save"] = 6] = "Save";
|
|
75
|
-
})(ProjectLocationChanged = exports.ProjectLocationChanged || (exports.ProjectLocationChanged = {}));
|
|
76
|
-
/** Controls to modify project extents shown using view clip
|
|
77
|
-
* @beta
|
|
78
|
-
*/
|
|
79
|
-
class ProjectExtentsClipDecoration extends core_frontend_1.EditManipulator.HandleProvider {
|
|
80
|
-
constructor(viewport) {
|
|
81
|
-
super(viewport.iModel);
|
|
82
|
-
this.viewport = viewport;
|
|
83
|
-
this._extentsLengthValid = true;
|
|
84
|
-
this._extentsWidthValid = true;
|
|
85
|
-
this._extentsHeightValid = true;
|
|
86
|
-
this._allowEcefLocationChange = false;
|
|
87
|
-
this._controlIds = [];
|
|
88
|
-
this._controls = [];
|
|
89
|
-
this._suspendDecorator = false;
|
|
90
|
-
this.suspendGeolocationDecorations = false;
|
|
91
|
-
/** Called when project extents or geolocation is modified */
|
|
92
|
-
this.onChanged = new core_bentley_1.BeEvent();
|
|
93
|
-
if (!this.init())
|
|
94
|
-
return;
|
|
95
|
-
this._monumentId = this.iModel.transientIds.getNext();
|
|
96
|
-
this._northId = this.iModel.transientIds.getNext();
|
|
97
|
-
this._clipId = this.iModel.transientIds.getNext();
|
|
98
|
-
this.start();
|
|
99
|
-
}
|
|
100
|
-
start() {
|
|
101
|
-
this.updateDecorationListener(true);
|
|
102
|
-
this._removeViewCloseListener = core_frontend_1.IModelApp.viewManager.onViewClose.addListener((vp) => this.onViewClose(vp));
|
|
103
|
-
this.iModel.selectionSet.replace(this._clipId); // Always select decoration on create...
|
|
104
|
-
}
|
|
105
|
-
stop() {
|
|
106
|
-
const selectedId = (undefined !== this._clipId && this.iModel.selectionSet.has(this._clipId)) ? this._clipId : undefined;
|
|
107
|
-
this._clipId = undefined; // Invalidate id so that decorator will be dropped...
|
|
108
|
-
super.stop();
|
|
109
|
-
if (undefined !== selectedId)
|
|
110
|
-
this.iModel.selectionSet.remove(selectedId); // Don't leave decorator id in selection set...
|
|
111
|
-
if (undefined !== this._removeViewCloseListener) {
|
|
112
|
-
this._removeViewCloseListener();
|
|
113
|
-
this._removeViewCloseListener = undefined;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
init() {
|
|
117
|
-
if (!this.getClipData())
|
|
118
|
-
return false;
|
|
119
|
-
this._ecefLocation = this.iModel.ecefLocation;
|
|
120
|
-
this._monumentPoint = this.getMonumentPoint();
|
|
121
|
-
this._northDirection = this.getNorthDirection();
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
onViewClose(vp) {
|
|
125
|
-
if (this.viewport === vp)
|
|
126
|
-
ProjectExtentsClipDecoration.clear();
|
|
127
|
-
}
|
|
128
|
-
getClipData() {
|
|
129
|
-
this._clip = this._clipShape = this._clipShapeExtents = this._clipRange = undefined;
|
|
130
|
-
const clip = this.viewport.view.getViewClip();
|
|
131
|
-
if (undefined === clip)
|
|
132
|
-
return false;
|
|
133
|
-
const clipShape = core_frontend_1.ViewClipTool.isSingleClipShape(clip);
|
|
134
|
-
if (undefined === clipShape)
|
|
135
|
-
return false;
|
|
136
|
-
if (5 !== clipShape.polygon.length || undefined === clipShape.zLow || undefined === clipShape.zHigh)
|
|
137
|
-
return false; // Not a box, can't be project extents clip...
|
|
138
|
-
if (undefined !== clipShape.transformFromClip && !clipShape.transformFromClip.isIdentity)
|
|
139
|
-
return false; // Not axis aligned, can't be project extents clip...
|
|
140
|
-
this._clipShapeExtents = core_geometry_1.Range1d.createXX(clipShape.zLow, clipShape.zHigh);
|
|
141
|
-
this._clipShape = clipShape;
|
|
142
|
-
this._clip = clip;
|
|
143
|
-
this._clipRange = core_geometry_1.Range3d.create();
|
|
144
|
-
const shapePtsLo = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.low);
|
|
145
|
-
const shapePtsHi = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.high);
|
|
146
|
-
this._clipRange.extendArray(shapePtsLo);
|
|
147
|
-
this._clipRange.extendArray(shapePtsHi);
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
ensureNumControls(numReqControls) {
|
|
151
|
-
const numCurrent = this._controlIds.length;
|
|
152
|
-
if (numCurrent < numReqControls) {
|
|
153
|
-
const transientIds = this.iModel.transientIds;
|
|
154
|
-
for (let i = numCurrent; i < numReqControls; i++)
|
|
155
|
-
this._controlIds[i] = transientIds.getNext();
|
|
156
|
-
}
|
|
157
|
-
else if (numCurrent > numReqControls) {
|
|
158
|
-
this._controlIds.length = numReqControls;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
createClipShapeControls() {
|
|
162
|
-
if (undefined === this._clipShape)
|
|
163
|
-
return false;
|
|
164
|
-
const shapePtsLo = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.low);
|
|
165
|
-
const shapePtsHi = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.high);
|
|
166
|
-
const shapeArea = core_geometry_1.PolygonOps.centroidAreaNormal(shapePtsLo);
|
|
167
|
-
if (undefined === shapeArea)
|
|
168
|
-
return false;
|
|
169
|
-
const numControls = shapePtsLo.length + 1; // Number of edge midpoints plus zLow and zHigh...
|
|
170
|
-
this.ensureNumControls(numControls);
|
|
171
|
-
for (let i = 0; i < numControls - 2; i++) {
|
|
172
|
-
const midPtLo = shapePtsLo[i].interpolate(0.5, shapePtsLo[i + 1]);
|
|
173
|
-
const midPtHi = shapePtsHi[i].interpolate(0.5, shapePtsHi[i + 1]);
|
|
174
|
-
const faceCenter = midPtLo.interpolate(0.5, midPtHi);
|
|
175
|
-
const edgeTangent = core_geometry_1.Vector3d.createStartEnd(shapePtsLo[i], shapePtsLo[i + 1]);
|
|
176
|
-
const faceNormal = edgeTangent.crossProduct(shapeArea.direction);
|
|
177
|
-
faceNormal.normalizeInPlace();
|
|
178
|
-
this._controls[i] = new ProjectExtentsControlArrow(faceCenter, faceNormal, 0.75);
|
|
179
|
-
this._controls[i].extentValid = (faceNormal.isParallelTo(core_geometry_1.Vector3d.unitX(), true) ? this._extentsLengthValid : this._extentsWidthValid);
|
|
180
|
-
}
|
|
181
|
-
const zFillColor = core_common_1.ColorDef.from(150, 150, 250);
|
|
182
|
-
this._controls[numControls - 2] = new ProjectExtentsControlArrow(shapeArea.origin, core_geometry_1.Vector3d.unitZ(-1.0), 0.75, zFillColor, undefined, "zLow");
|
|
183
|
-
this._controls[numControls - 1] = new ProjectExtentsControlArrow(shapeArea.origin.plusScaled(core_geometry_1.Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), core_geometry_1.Vector3d.unitZ(), 0.75, zFillColor, undefined, "zHigh");
|
|
184
|
-
this._controls[numControls - 2].extentValid = this._extentsHeightValid;
|
|
185
|
-
this._controls[numControls - 1].extentValid = this._extentsHeightValid;
|
|
186
|
-
return true;
|
|
187
|
-
}
|
|
188
|
-
/** Allow project extents for map projections to be larger since curvature of the earth is accounted for. */
|
|
189
|
-
get maxExtentLength() { return ((this._allowEcefLocationChange ? 20 : 350) * core_geometry_1.Constant.oneKilometer); }
|
|
190
|
-
/** Impose some reasonable height limit for project extents. */
|
|
191
|
-
get maxExtentHeight() { return (2 * core_geometry_1.Constant.oneKilometer); }
|
|
192
|
-
hasValidGCS() {
|
|
193
|
-
if (!this.iModel.isGeoLocated || this.iModel.noGcsDefined)
|
|
194
|
-
return false;
|
|
195
|
-
const gcs = this.iModel.geographicCoordinateSystem;
|
|
196
|
-
if (undefined === gcs || undefined === gcs.horizontalCRS)
|
|
197
|
-
return false; // A valid GCS ought to have horizontalCR defined...
|
|
198
|
-
// Check for approximate GCS (such as from MicroStation's "From Placemark" tool) and allow it to be replaced...
|
|
199
|
-
const hasValidId = (undefined !== gcs.horizontalCRS.id && 0 !== gcs.horizontalCRS.id.length);
|
|
200
|
-
const hasValidDescr = (undefined !== gcs.horizontalCRS.description && 0 !== gcs.horizontalCRS.description.length);
|
|
201
|
-
const hasValidProjection = (undefined !== gcs.horizontalCRS.projection && "AzimuthalEqualArea" !== gcs.horizontalCRS.projection.method);
|
|
202
|
-
return hasValidId || hasValidDescr || hasValidProjection;
|
|
203
|
-
}
|
|
204
|
-
async createControls() {
|
|
205
|
-
// Always update to current view clip to handle post-modify, etc.
|
|
206
|
-
if (undefined === this._clipId || !this.getClipData())
|
|
207
|
-
return false;
|
|
208
|
-
this._allowEcefLocationChange = !this.hasValidGCS();
|
|
209
|
-
if (undefined !== this._clipRange) {
|
|
210
|
-
this._extentsLengthValid = (this._clipRange.xLength() < this.maxExtentLength);
|
|
211
|
-
this._extentsWidthValid = (this._clipRange.yLength() < this.maxExtentLength);
|
|
212
|
-
this._extentsHeightValid = (this._clipRange.zLength() < this.maxExtentHeight);
|
|
213
|
-
}
|
|
214
|
-
// Show controls if only range box and it's controls are selected, selection set doesn't include any other elements...
|
|
215
|
-
let showControls = false;
|
|
216
|
-
if (this.iModel.selectionSet.size <= this._controlIds.length + 1 && this.iModel.selectionSet.has(this._clipId)) {
|
|
217
|
-
showControls = true;
|
|
218
|
-
if (this.iModel.selectionSet.size > 1) {
|
|
219
|
-
this.iModel.selectionSet.elements.forEach((val) => {
|
|
220
|
-
if (this._clipId !== val && !this._controlIds.includes(val))
|
|
221
|
-
showControls = false;
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (!showControls)
|
|
226
|
-
return false; // Don't clear decoration on de-select...
|
|
227
|
-
return this.createClipShapeControls();
|
|
228
|
-
}
|
|
229
|
-
clearControls() {
|
|
230
|
-
this.iModel.selectionSet.remove(this._controlIds); // Remove any selected controls as they won't continue to be displayed...
|
|
231
|
-
super.clearControls();
|
|
232
|
-
}
|
|
233
|
-
async modifyControls(hit, _ev) {
|
|
234
|
-
if (undefined === this._clip || hit.sourceId === this._clipId)
|
|
235
|
-
return false;
|
|
236
|
-
const saveQualifiers = core_frontend_1.IModelApp.toolAdmin.currentInputState.qualifiers;
|
|
237
|
-
if (undefined !== this._clipShape) {
|
|
238
|
-
const clipShapeModifyTool = new core_frontend_1.ViewClipShapeModifyTool(this, this._clip, this.viewport, hit.sourceId, this._controlIds, this._controls);
|
|
239
|
-
this._suspendDecorator = await clipShapeModifyTool.run();
|
|
240
|
-
}
|
|
241
|
-
if (this._suspendDecorator)
|
|
242
|
-
core_frontend_1.IModelApp.toolAdmin.currentInputState.qualifiers = saveQualifiers; // onInstallTool cleared qualifiers, preserve for "modify all" behavior when shift was held and drag started...
|
|
243
|
-
return this._suspendDecorator;
|
|
244
|
-
}
|
|
245
|
-
async onRightClick(_hit, _ev) { return core_frontend_1.EventHandled.No; }
|
|
246
|
-
async onTouchTap(hit, ev) { return (hit.sourceId === this._clipId ? core_frontend_1.EventHandled.No : super.onTouchTap(hit, ev)); }
|
|
247
|
-
async onDecorationButtonEvent(hit, ev) {
|
|
248
|
-
if (hit.sourceId === this._monumentId) {
|
|
249
|
-
if (core_frontend_1.BeButton.Data === ev.button && !ev.isDown && !ev.isDragging)
|
|
250
|
-
await ProjectGeolocation_1.ProjectGeolocationPointTool.startTool();
|
|
251
|
-
return core_frontend_1.EventHandled.Yes; // Only pickable for tooltip, don't allow selection...
|
|
252
|
-
}
|
|
253
|
-
if (hit.sourceId === this._northId) {
|
|
254
|
-
if (core_frontend_1.BeButton.Data === ev.button && !ev.isDown && !ev.isDragging)
|
|
255
|
-
await ProjectGeolocation_1.ProjectGeolocationNorthTool.startTool();
|
|
256
|
-
return core_frontend_1.EventHandled.Yes; // Only pickable for tooltip, don't allow selection...
|
|
257
|
-
}
|
|
258
|
-
return super.onDecorationButtonEvent(hit, ev);
|
|
259
|
-
}
|
|
260
|
-
onManipulatorEvent(eventType) {
|
|
261
|
-
if (core_frontend_1.EditManipulator.EventType.Accept === eventType)
|
|
262
|
-
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.Extents);
|
|
263
|
-
this._suspendDecorator = false;
|
|
264
|
-
super.onManipulatorEvent(eventType);
|
|
265
|
-
}
|
|
266
|
-
async getDecorationToolTip(hit) {
|
|
267
|
-
const quantityFormatter = core_frontend_1.IModelApp.quantityFormatter;
|
|
268
|
-
const toolTip = document.createElement("div");
|
|
269
|
-
let toolTipHtml = "";
|
|
270
|
-
if (hit.sourceId === this._monumentId) {
|
|
271
|
-
toolTipHtml += `${translateMessage("ModifyGeolocation")}<br>`;
|
|
272
|
-
const coordFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Coordinate);
|
|
273
|
-
if (undefined !== coordFormatterSpec) {
|
|
274
|
-
const pointAdjusted = this._monumentPoint.minus(this.iModel.globalOrigin);
|
|
275
|
-
const formattedPointX = quantityFormatter.formatQuantity(pointAdjusted.x, coordFormatterSpec);
|
|
276
|
-
const formattedPointY = quantityFormatter.formatQuantity(pointAdjusted.y, coordFormatterSpec);
|
|
277
|
-
const formattedPointZ = quantityFormatter.formatQuantity(pointAdjusted.z, coordFormatterSpec);
|
|
278
|
-
toolTipHtml += `${translateCoreMeasureBold("Coordinate") + formattedPointX}, ${formattedPointY}, ${formattedPointZ}<br>`;
|
|
279
|
-
}
|
|
280
|
-
const latLongFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.LatLong);
|
|
281
|
-
if (undefined !== latLongFormatterSpec && undefined !== coordFormatterSpec && this.iModel.isGeoLocated) {
|
|
282
|
-
const cartographic = this.iModel.spatialToCartographicFromEcef(this._monumentPoint);
|
|
283
|
-
const formattedLat = quantityFormatter.formatQuantity(Math.abs(cartographic.latitude), latLongFormatterSpec);
|
|
284
|
-
const formattedLong = quantityFormatter.formatQuantity(Math.abs(cartographic.longitude), latLongFormatterSpec);
|
|
285
|
-
const formattedHeight = quantityFormatter.formatQuantity(cartographic.height, coordFormatterSpec);
|
|
286
|
-
const latDir = core_frontend_1.CoreTools.translate(cartographic.latitude < 0 ? "Measure.Labels.S" : "Measure.Labels.N");
|
|
287
|
-
const longDir = core_frontend_1.CoreTools.translate(cartographic.longitude < 0 ? "Measure.Labels.W" : "Measure.Labels.E");
|
|
288
|
-
toolTipHtml += `${translateCoreMeasureBold("LatLong") + formattedLat + latDir}, ${formattedLong}${longDir}<br>`;
|
|
289
|
-
toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedHeight}<br>`;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
else if (hit.sourceId === this._northId) {
|
|
293
|
-
toolTipHtml += `${translateMessage("ModifyNorthDirection")}<br>`;
|
|
294
|
-
const angleFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Angle);
|
|
295
|
-
if (undefined !== angleFormatterSpec) {
|
|
296
|
-
const formattedAngle = quantityFormatter.formatQuantity(this.getClockwiseAngleToNorth().radians, angleFormatterSpec);
|
|
297
|
-
toolTipHtml += `${translateMessageBold("Angle") + formattedAngle}<br>`;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
else if (hit.sourceId === this._clipId) {
|
|
301
|
-
const extentsValid = (this._extentsLengthValid && this._extentsWidthValid && this._extentsHeightValid);
|
|
302
|
-
toolTipHtml += `${translateMessage(extentsValid ? "ProjectExtents" : "LargeProjectExtents")}<br>`;
|
|
303
|
-
const distanceFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
|
|
304
|
-
if (undefined !== distanceFormatterSpec && undefined !== this._clipRange) {
|
|
305
|
-
const formattedLength = quantityFormatter.formatQuantity(this._clipRange.xLength(), distanceFormatterSpec);
|
|
306
|
-
const formattedWidth = quantityFormatter.formatQuantity(this._clipRange.yLength(), distanceFormatterSpec);
|
|
307
|
-
const formattedHeight = quantityFormatter.formatQuantity(this._clipRange.zLength(), distanceFormatterSpec);
|
|
308
|
-
toolTipHtml += `${translateMessageBold("Length") + formattedLength}<br>`;
|
|
309
|
-
toolTipHtml += `${translateMessageBold("Width") + formattedWidth}<br>`;
|
|
310
|
-
toolTipHtml += `${translateMessageBold("Height") + formattedHeight}<br>`;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
const arrowIndex = this._controlIds.indexOf(hit.sourceId);
|
|
315
|
-
if (-1 !== arrowIndex) {
|
|
316
|
-
toolTipHtml += `${translateMessage("ModifyProjectExtents")}<br>`;
|
|
317
|
-
const distanceFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
|
|
318
|
-
if (undefined !== distanceFormatterSpec && undefined !== this._clipRange) {
|
|
319
|
-
const arrowControl = this._controls[arrowIndex];
|
|
320
|
-
let arrowLabel = "";
|
|
321
|
-
let arrowLength = 0.0;
|
|
322
|
-
let arrowLengthMax = 0.0;
|
|
323
|
-
if (arrowControl.direction.isParallelTo(core_geometry_1.Vector3d.unitX(), true)) {
|
|
324
|
-
arrowLabel = "Length";
|
|
325
|
-
arrowLength = this._clipRange.xLength();
|
|
326
|
-
if (!this._extentsLengthValid)
|
|
327
|
-
arrowLengthMax = this.maxExtentLength;
|
|
328
|
-
}
|
|
329
|
-
else if (arrowControl.direction.isParallelTo(core_geometry_1.Vector3d.unitY(), true)) {
|
|
330
|
-
arrowLabel = "Width";
|
|
331
|
-
arrowLength = this._clipRange.yLength();
|
|
332
|
-
if (!this._extentsWidthValid)
|
|
333
|
-
arrowLengthMax = this.maxExtentLength;
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
arrowLabel = "Height";
|
|
337
|
-
arrowLength = this._clipRange.zLength();
|
|
338
|
-
if (!this._extentsHeightValid)
|
|
339
|
-
arrowLengthMax = this.maxExtentHeight;
|
|
340
|
-
const coordFormatterSpec = (this.iModel.isGeoLocated ? quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Coordinate) : undefined);
|
|
341
|
-
if (undefined !== coordFormatterSpec) {
|
|
342
|
-
const heightPt = ("zLow" === arrowControl.name ? this._clipRange.low : this._clipRange.high);
|
|
343
|
-
const cartographic = this.iModel.spatialToCartographicFromEcef(heightPt);
|
|
344
|
-
const formattedAltitude = quantityFormatter.formatQuantity(cartographic.height, coordFormatterSpec);
|
|
345
|
-
toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedAltitude}<br>`;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
const formattedLength = quantityFormatter.formatQuantity(arrowLength, distanceFormatterSpec);
|
|
349
|
-
toolTipHtml += `${translateMessageBold(arrowLabel) + formattedLength}<br>`;
|
|
350
|
-
if (0.0 !== arrowLengthMax) {
|
|
351
|
-
const formattedMaxLength = quantityFormatter.formatQuantity(arrowLengthMax, distanceFormatterSpec);
|
|
352
|
-
toolTipHtml += `${translateMessageBold("MaxExtent") + formattedMaxLength}<br>`;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
toolTip.innerHTML = toolTipHtml;
|
|
358
|
-
return toolTip;
|
|
359
|
-
}
|
|
360
|
-
testDecorationHit(id) { return (id === this._monumentId || id === this._northId || id === this._clipId || this._controlIds.includes(id)); }
|
|
361
|
-
updateDecorationListener(_add) { super.updateDecorationListener(undefined !== this._clipId); } // Decorator isn't just for resize controls...
|
|
362
|
-
getMonumentPoint() {
|
|
363
|
-
const origin = core_geometry_1.Point3d.createZero();
|
|
364
|
-
if (this.iModel.ecefLocation && this.iModel.ecefLocation.cartographicOrigin)
|
|
365
|
-
return this.iModel.cartographicToSpatialFromEcef(this.iModel.ecefLocation.cartographicOrigin, origin);
|
|
366
|
-
origin.setFrom(this.iModel.projectExtents.low);
|
|
367
|
-
if (0.0 > this.iModel.projectExtents.low.z && 0.0 < this.iModel.projectExtents.high.z)
|
|
368
|
-
origin.z = 0.0;
|
|
369
|
-
return origin;
|
|
370
|
-
}
|
|
371
|
-
getClockwiseAngleToNorth() {
|
|
372
|
-
const angle = this.getNorthAngle();
|
|
373
|
-
angle.setRadians(core_geometry_1.Angle.adjustRadians0To2Pi(angle.radians));
|
|
374
|
-
return angle;
|
|
375
|
-
}
|
|
376
|
-
getNorthAngle() {
|
|
377
|
-
const northDirection = (undefined !== this._northDirection ? this._northDirection : this.getNorthDirection());
|
|
378
|
-
return northDirection.direction.angleToXY(core_geometry_1.Vector3d.unitY());
|
|
379
|
-
}
|
|
380
|
-
getNorthDirection(refOrigin) {
|
|
381
|
-
const origin = (undefined !== refOrigin ? refOrigin : this.iModel.projectExtents.center);
|
|
382
|
-
if (!this.iModel.isGeoLocated)
|
|
383
|
-
return core_geometry_1.Ray3d.create(origin, core_geometry_1.Vector3d.unitY());
|
|
384
|
-
const cartographic = this.iModel.spatialToCartographicFromEcef(origin);
|
|
385
|
-
cartographic.latitude += core_geometry_1.Angle.createDegrees(0.01).radians;
|
|
386
|
-
const pt2 = this.iModel.cartographicToSpatialFromEcef(cartographic);
|
|
387
|
-
const northVec = core_geometry_1.Vector3d.createStartEnd(origin, pt2);
|
|
388
|
-
northVec.z = 0.0;
|
|
389
|
-
northVec.normalizeInPlace();
|
|
390
|
-
return core_geometry_1.Ray3d.create(origin, northVec);
|
|
391
|
-
}
|
|
392
|
-
drawNorthArrow(context, northDir, id) {
|
|
393
|
-
const vp = context.viewport;
|
|
394
|
-
const pixelSize = vp.pixelsFromInches(0.55);
|
|
395
|
-
const scale = vp.viewingSpace.getPixelSizeAtPoint(northDir.origin) * pixelSize;
|
|
396
|
-
const matrix = core_geometry_1.Matrix3d.createRigidFromColumns(northDir.direction, core_geometry_1.Vector3d.unitZ(), core_geometry_1.AxisOrder.YZX);
|
|
397
|
-
if (undefined === matrix)
|
|
398
|
-
return;
|
|
399
|
-
matrix.scaleColumnsInPlace(scale, scale, scale);
|
|
400
|
-
const arrowTrans = core_geometry_1.Transform.createRefs(northDir.origin, matrix);
|
|
401
|
-
const northArrowBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, arrowTrans, id);
|
|
402
|
-
const color = core_common_1.ColorDef.white;
|
|
403
|
-
const arrowOutline = [];
|
|
404
|
-
arrowOutline[0] = core_geometry_1.Point3d.create(0.0, 0.65);
|
|
405
|
-
arrowOutline[1] = core_geometry_1.Point3d.create(-0.45, -0.5);
|
|
406
|
-
arrowOutline[2] = core_geometry_1.Point3d.create(0.0, -0.2);
|
|
407
|
-
arrowOutline[3] = core_geometry_1.Point3d.create(0.45, -0.5);
|
|
408
|
-
arrowOutline[4] = arrowOutline[0].clone();
|
|
409
|
-
const arrowLeftFill = [];
|
|
410
|
-
arrowLeftFill[0] = arrowOutline[0].clone();
|
|
411
|
-
arrowLeftFill[1] = arrowOutline[1].clone();
|
|
412
|
-
arrowLeftFill[2] = arrowOutline[2].clone();
|
|
413
|
-
arrowLeftFill[3] = arrowLeftFill[0].clone();
|
|
414
|
-
const arrowRightFill = [];
|
|
415
|
-
arrowRightFill[0] = arrowOutline[0].clone();
|
|
416
|
-
arrowRightFill[1] = arrowOutline[3].clone();
|
|
417
|
-
arrowRightFill[2] = arrowOutline[2].clone();
|
|
418
|
-
arrowRightFill[3] = arrowRightFill[0].clone();
|
|
419
|
-
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.from(0, 0, 0, 200), 1);
|
|
420
|
-
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.6), true, true);
|
|
421
|
-
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.create(0.0, 0.85), 0.2), true, true);
|
|
422
|
-
northArrowBuilder.setSymbology(color, color, 2);
|
|
423
|
-
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.5), false, false);
|
|
424
|
-
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(0.6, 0.0), core_geometry_1.Point3d.create(-0.6, 0.0)]);
|
|
425
|
-
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(0.0, 0.6), core_geometry_1.Point3d.create(0.0, -0.6)]);
|
|
426
|
-
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.from(150, 150, 150), 1);
|
|
427
|
-
northArrowBuilder.addShape(arrowLeftFill);
|
|
428
|
-
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.black, 1);
|
|
429
|
-
northArrowBuilder.addShape(arrowRightFill);
|
|
430
|
-
northArrowBuilder.setSymbology(color, color, 1);
|
|
431
|
-
northArrowBuilder.addLineString(arrowOutline);
|
|
432
|
-
northArrowBuilder.setSymbology(color, color, 3);
|
|
433
|
-
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(-0.1, 0.75), core_geometry_1.Point3d.create(-0.1, 0.95), core_geometry_1.Point3d.create(0.1, 0.75), core_geometry_1.Point3d.create(0.1, 0.95)]);
|
|
434
|
-
context.addDecorationFromBuilder(northArrowBuilder);
|
|
435
|
-
}
|
|
436
|
-
drawMonumentPoint(context, point, scaleFactor, id) {
|
|
437
|
-
const vp = context.viewport;
|
|
438
|
-
const pixelSize = vp.pixelsFromInches(0.25) * scaleFactor;
|
|
439
|
-
const scale = vp.viewingSpace.getPixelSizeAtPoint(point) * pixelSize;
|
|
440
|
-
const matrix = core_geometry_1.Matrix3d.createRotationAroundAxisIndex(core_geometry_1.AxisIndex.Z, core_geometry_1.Angle.createDegrees(45.0));
|
|
441
|
-
matrix.scaleColumnsInPlace(scale, scale, scale);
|
|
442
|
-
const monumentTrans = core_geometry_1.Transform.createRefs(point, matrix);
|
|
443
|
-
const monumentPointBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, monumentTrans, id);
|
|
444
|
-
const color = core_common_1.ColorDef.white;
|
|
445
|
-
monumentPointBuilder.setSymbology(color, core_common_1.ColorDef.from(0, 0, 0, 150), 1);
|
|
446
|
-
monumentPointBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.7), true, true);
|
|
447
|
-
monumentPointBuilder.setSymbology(color, color, 2);
|
|
448
|
-
monumentPointBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.5), false, false);
|
|
449
|
-
monumentPointBuilder.addLineString([core_geometry_1.Point3d.create(0.5, 0.0), core_geometry_1.Point3d.create(-0.5, 0.0)]);
|
|
450
|
-
monumentPointBuilder.addLineString([core_geometry_1.Point3d.create(0.0, 0.5), core_geometry_1.Point3d.create(0.0, -0.5)]);
|
|
451
|
-
context.addDecorationFromBuilder(monumentPointBuilder);
|
|
452
|
-
}
|
|
453
|
-
drawAreaTooLargeIndicator(context) {
|
|
454
|
-
if ((this._extentsLengthValid && this._extentsWidthValid) || undefined === this._clipRange)
|
|
455
|
-
return;
|
|
456
|
-
const corners = this._clipRange.corners();
|
|
457
|
-
const indices = core_geometry_1.Range3d.faceCornerIndices(5);
|
|
458
|
-
const points = [];
|
|
459
|
-
for (const index of indices)
|
|
460
|
-
points.push(corners[index]);
|
|
461
|
-
const areaWarnColor = core_common_1.ColorDef.red.withAlpha(50);
|
|
462
|
-
const areaWarnBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldDecoration);
|
|
463
|
-
areaWarnBuilder.setSymbology(areaWarnColor, areaWarnColor, 1);
|
|
464
|
-
areaWarnBuilder.addShape(points);
|
|
465
|
-
context.addDecorationFromBuilder(areaWarnBuilder);
|
|
466
|
-
}
|
|
467
|
-
drawExtentTooLargeIndicator(context, worldPoint, sizePixels) {
|
|
468
|
-
const position = context.viewport.worldToView(worldPoint);
|
|
469
|
-
position.x = Math.floor(position.x) + 0.5;
|
|
470
|
-
position.y = Math.floor(position.y) + 0.5;
|
|
471
|
-
const drawDecoration = (ctx) => {
|
|
472
|
-
ctx.lineWidth = 4;
|
|
473
|
-
ctx.lineCap = "round";
|
|
474
|
-
ctx.strokeStyle = "rgba(255,0,0,.75)";
|
|
475
|
-
ctx.fillStyle = "rgba(255,255,255,.75)";
|
|
476
|
-
ctx.shadowColor = "black";
|
|
477
|
-
ctx.shadowBlur = 5;
|
|
478
|
-
ctx.beginPath();
|
|
479
|
-
ctx.moveTo(0, -sizePixels);
|
|
480
|
-
ctx.lineTo(-sizePixels, sizePixels);
|
|
481
|
-
ctx.lineTo(sizePixels, sizePixels);
|
|
482
|
-
ctx.lineTo(0, -sizePixels);
|
|
483
|
-
ctx.fill();
|
|
484
|
-
ctx.shadowBlur = 0;
|
|
485
|
-
ctx.beginPath();
|
|
486
|
-
ctx.moveTo(0, -sizePixels);
|
|
487
|
-
ctx.lineTo(-sizePixels, sizePixels);
|
|
488
|
-
ctx.lineTo(sizePixels, sizePixels);
|
|
489
|
-
ctx.lineTo(0, -sizePixels);
|
|
490
|
-
ctx.stroke();
|
|
491
|
-
ctx.strokeStyle = "black";
|
|
492
|
-
ctx.lineWidth = 3;
|
|
493
|
-
ctx.beginPath();
|
|
494
|
-
ctx.moveTo(0, -sizePixels * 0.2);
|
|
495
|
-
ctx.lineTo(0, sizePixels * 0.3);
|
|
496
|
-
ctx.moveTo(0, (sizePixels * 0.3) + 4);
|
|
497
|
-
ctx.lineTo(0, (sizePixels * 0.3) + 4.5);
|
|
498
|
-
ctx.stroke();
|
|
499
|
-
};
|
|
500
|
-
context.addCanvasDecoration({ position, drawDecoration });
|
|
501
|
-
}
|
|
502
|
-
decorate(context) {
|
|
503
|
-
if (this._suspendDecorator)
|
|
504
|
-
return;
|
|
505
|
-
if (undefined === this._clipId || undefined === this._clipShape || undefined === this._clipRange)
|
|
506
|
-
return;
|
|
507
|
-
const vp = context.viewport;
|
|
508
|
-
if (this.viewport !== vp)
|
|
509
|
-
return;
|
|
510
|
-
if (!this.suspendGeolocationDecorations && undefined !== this._northDirection && this.iModel.isGeoLocated)
|
|
511
|
-
this.drawNorthArrow(context, this._northDirection, this._allowEcefLocationChange ? this._northId : undefined); // Show north, but don't make pickable if it shouldn't be modified...
|
|
512
|
-
const maxSizeInches = ((this._clipRange.maxLength() / vp.viewingSpace.getPixelSizeAtPoint(this._clipRange.center)) / vp.pixelsPerInch) * 0.5; // Display size limit when zooming out...
|
|
513
|
-
if (maxSizeInches < 0.5)
|
|
514
|
-
return;
|
|
515
|
-
if (!this.suspendGeolocationDecorations && undefined !== this._monumentPoint && this._allowEcefLocationChange)
|
|
516
|
-
this.drawMonumentPoint(context, this._monumentPoint, 1.0, this._monumentId);
|
|
517
|
-
core_frontend_1.ViewClipTool.drawClipShape(context, this._clipShape, this._clipShapeExtents, core_common_1.ColorDef.white.adjustedForContrast(context.viewport.view.backgroundColor), 3, this._clipId);
|
|
518
|
-
this.drawAreaTooLargeIndicator(context);
|
|
519
|
-
if (!this._isActive)
|
|
520
|
-
return;
|
|
521
|
-
const outlineColor = core_common_1.ColorDef.from(0, 0, 0, 50).adjustedForContrast(vp.view.backgroundColor);
|
|
522
|
-
const fillVisColor = core_common_1.ColorDef.from(150, 250, 200, 225).adjustedForContrast(vp.view.backgroundColor);
|
|
523
|
-
const fillHidColor = fillVisColor.withAlpha(200);
|
|
524
|
-
const fillSelColor = fillVisColor.inverse().withAlpha(75);
|
|
525
|
-
const shapePts = core_frontend_1.EditManipulator.HandleUtils.getArrowShape(0.0, 0.15, 0.55, 1.0, 0.3, 0.5, 0.1);
|
|
526
|
-
for (let iFace = 0; iFace < this._controlIds.length; iFace++) {
|
|
527
|
-
const sizeInches = Math.min(this._controls[iFace].sizeInches, maxSizeInches);
|
|
528
|
-
if (0.0 === sizeInches)
|
|
529
|
-
continue;
|
|
530
|
-
const anchorRay = core_frontend_1.ViewClipTool.getClipRayTransformed(this._controls[iFace].origin, this._controls[iFace].direction, undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined);
|
|
531
|
-
const transform = core_frontend_1.EditManipulator.HandleUtils.getArrowTransform(vp, anchorRay.origin, anchorRay.direction, sizeInches);
|
|
532
|
-
if (undefined === transform)
|
|
533
|
-
continue;
|
|
534
|
-
// deep copies because we're using a builder transform w/addLineString...
|
|
535
|
-
const visPts = shapePts.map((pt) => pt.clone());
|
|
536
|
-
const hidPts = shapePts.map((pt) => pt.clone());
|
|
537
|
-
const arrowVisBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, transform, this._controlIds[iFace]);
|
|
538
|
-
const arrowHidBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldDecoration, transform);
|
|
539
|
-
const isSelected = this.iModel.selectionSet.has(this._controlIds[iFace]);
|
|
540
|
-
let outlineColorOvr = this._controls[iFace].outline;
|
|
541
|
-
if (undefined !== outlineColorOvr) {
|
|
542
|
-
outlineColorOvr = outlineColorOvr.adjustedForContrast(vp.view.backgroundColor);
|
|
543
|
-
outlineColorOvr = outlineColorOvr.withAlpha(outlineColor.getAlpha());
|
|
544
|
-
}
|
|
545
|
-
else {
|
|
546
|
-
outlineColorOvr = outlineColor;
|
|
547
|
-
}
|
|
548
|
-
let fillVisColorOvr = this._controls[iFace].fill;
|
|
549
|
-
let fillHidColorOvr = fillHidColor;
|
|
550
|
-
let fillSelColorOvr = fillSelColor;
|
|
551
|
-
if (undefined !== fillVisColorOvr) {
|
|
552
|
-
fillVisColorOvr = fillVisColorOvr.adjustedForContrast(vp.view.backgroundColor);
|
|
553
|
-
fillVisColorOvr = fillVisColorOvr.withAlpha(fillVisColor.getAlpha());
|
|
554
|
-
fillHidColorOvr = fillVisColorOvr.withAlpha(fillHidColor.getAlpha());
|
|
555
|
-
fillSelColorOvr = fillVisColorOvr.inverse().withAlpha(fillSelColor.getAlpha());
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
fillVisColorOvr = fillVisColor;
|
|
559
|
-
}
|
|
560
|
-
arrowVisBuilder.setSymbology(outlineColorOvr, outlineColorOvr, isSelected ? 4 : 2);
|
|
561
|
-
arrowVisBuilder.addLineString(visPts);
|
|
562
|
-
arrowVisBuilder.setBlankingFill(isSelected ? fillSelColorOvr : fillVisColorOvr);
|
|
563
|
-
arrowVisBuilder.addShape(visPts);
|
|
564
|
-
context.addDecorationFromBuilder(arrowVisBuilder);
|
|
565
|
-
arrowHidBuilder.setSymbology(fillHidColorOvr, fillHidColorOvr, 1);
|
|
566
|
-
arrowHidBuilder.addShape(hidPts);
|
|
567
|
-
context.addDecorationFromBuilder(arrowHidBuilder);
|
|
568
|
-
if (this._controls[iFace].extentValid)
|
|
569
|
-
continue;
|
|
570
|
-
const warnPixels = 15.0;
|
|
571
|
-
const warnOffset = vp.viewingSpace.getPixelSizeAtPoint(anchorRay.origin) * warnPixels * 1.5;
|
|
572
|
-
const warnOrigin = anchorRay.origin.plusScaled(anchorRay.direction, -warnOffset);
|
|
573
|
-
this.drawExtentTooLargeIndicator(context, warnOrigin, warnPixels);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
resetViewClip() {
|
|
577
|
-
if (!clearViewClip(this.viewport))
|
|
578
|
-
return false;
|
|
579
|
-
if (undefined !== this.getModifiedExtents())
|
|
580
|
-
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.ResetExtents);
|
|
581
|
-
return true;
|
|
582
|
-
}
|
|
583
|
-
resetGeolocation() {
|
|
584
|
-
if (!this._allowEcefLocationChange)
|
|
585
|
-
return false;
|
|
586
|
-
if (undefined === this.getModifiedEcefLocation())
|
|
587
|
-
return false; // Wasn't changed...
|
|
588
|
-
this.iModel.disableGCS(false);
|
|
589
|
-
this.iModel.ecefLocation = this._ecefLocation;
|
|
590
|
-
this._monumentPoint = this.getMonumentPoint();
|
|
591
|
-
this._northDirection = this.getNorthDirection();
|
|
592
|
-
updateMapDisplay(this.viewport, false);
|
|
593
|
-
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.ResetGeolocation);
|
|
594
|
-
return true;
|
|
595
|
-
}
|
|
596
|
-
updateEcefLocation(origin, point, angle) {
|
|
597
|
-
if (!this._allowEcefLocationChange)
|
|
598
|
-
return false;
|
|
599
|
-
const newEcefLocation = core_common_1.EcefLocation.createFromCartographicOrigin(origin, point, (undefined !== angle ? angle : this.getNorthAngle())); // Preserve modified north direction...
|
|
600
|
-
const ecefLocation = this.iModel.ecefLocation;
|
|
601
|
-
if (undefined !== ecefLocation && ecefLocation.isAlmostEqual(newEcefLocation))
|
|
602
|
-
return false;
|
|
603
|
-
this.iModel.disableGCS(true); // Map display will ignore change to ecef location when GCS is present...
|
|
604
|
-
this.iModel.setEcefLocation(newEcefLocation);
|
|
605
|
-
this._monumentPoint = this.getMonumentPoint();
|
|
606
|
-
this._northDirection = this.getNorthDirection(undefined !== this._northDirection ? this._northDirection.origin : undefined); // Preserve modified north reference point...
|
|
607
|
-
updateMapDisplay(this.viewport, true);
|
|
608
|
-
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.Geolocation);
|
|
609
|
-
return true;
|
|
610
|
-
}
|
|
611
|
-
updateNorthDirection(northDir) {
|
|
612
|
-
if (!this._allowEcefLocationChange || !this.iModel.isGeoLocated)
|
|
613
|
-
return false;
|
|
614
|
-
const point = (undefined !== this._monumentPoint ? this._monumentPoint : this.getMonumentPoint()); // Preserve modified monument point...
|
|
615
|
-
const origin = this.iModel.spatialToCartographicFromEcef(point);
|
|
616
|
-
const saveDirection = this._northDirection;
|
|
617
|
-
this._northDirection = northDir; // Change reference point to input location...
|
|
618
|
-
const angle = this.getNorthAngle();
|
|
619
|
-
if (!this.updateEcefLocation(origin, point, angle)) {
|
|
620
|
-
this._northDirection = saveDirection;
|
|
621
|
-
return false;
|
|
622
|
-
}
|
|
623
|
-
return true;
|
|
624
|
-
}
|
|
625
|
-
getModifiedEcefLocation() {
|
|
626
|
-
const ecefLocation = this.iModel.ecefLocation;
|
|
627
|
-
if (undefined === ecefLocation)
|
|
628
|
-
return undefined; // geolocation wasn't added...
|
|
629
|
-
if (undefined === this._ecefLocation)
|
|
630
|
-
return ecefLocation; // geolocation didn't exist previously...
|
|
631
|
-
if (this._ecefLocation.isAlmostEqual(ecefLocation))
|
|
632
|
-
return undefined;
|
|
633
|
-
return ecefLocation;
|
|
634
|
-
}
|
|
635
|
-
getModifiedExtents() {
|
|
636
|
-
if (undefined === this._clipRange)
|
|
637
|
-
return undefined;
|
|
638
|
-
return this._clipRange.isAlmostEqual(this.iModel.projectExtents) ? undefined : this._clipRange;
|
|
639
|
-
}
|
|
640
|
-
static allowEcefLocationChange(requireExisting, outputError = true) {
|
|
641
|
-
if (undefined === ProjectExtentsClipDecoration._decorator) {
|
|
642
|
-
if (outputError)
|
|
643
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotActive")));
|
|
644
|
-
return false;
|
|
645
|
-
}
|
|
646
|
-
else if (!ProjectExtentsClipDecoration._decorator._allowEcefLocationChange) {
|
|
647
|
-
if (outputError)
|
|
648
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotAllowed")));
|
|
649
|
-
return false;
|
|
650
|
-
}
|
|
651
|
-
else if (requireExisting && !ProjectExtentsClipDecoration._decorator.iModel.isGeoLocated) {
|
|
652
|
-
if (outputError)
|
|
653
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotGeolocated")));
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
return true;
|
|
657
|
-
}
|
|
658
|
-
fitExtents() {
|
|
659
|
-
if (undefined === this._clipRange)
|
|
660
|
-
return undefined;
|
|
661
|
-
const options = { animateFrustumChange: true, animationTime: core_bentley_1.BeDuration.fromSeconds(2).milliseconds };
|
|
662
|
-
const aspect = this.viewport.viewRect.aspect;
|
|
663
|
-
this.viewport.view.lookAtVolume(this._clipRange, aspect);
|
|
664
|
-
this.viewport.synchWithView(options);
|
|
665
|
-
this.viewport.viewCmdTargetCenter = undefined;
|
|
666
|
-
}
|
|
667
|
-
static get() {
|
|
668
|
-
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
669
|
-
return undefined;
|
|
670
|
-
return ProjectExtentsClipDecoration._decorator;
|
|
671
|
-
}
|
|
672
|
-
static show(vp, fitExtents = true) {
|
|
673
|
-
if (!vp.view.isSpatialView())
|
|
674
|
-
return false;
|
|
675
|
-
if (undefined !== ProjectExtentsClipDecoration._decorator) {
|
|
676
|
-
const deco = ProjectExtentsClipDecoration._decorator;
|
|
677
|
-
if (vp === deco.viewport && undefined !== deco._clipId && undefined !== deco._clip) {
|
|
678
|
-
if (deco._clip !== vp.view.getViewClip()) {
|
|
679
|
-
clearViewClip(vp);
|
|
680
|
-
core_frontend_1.ViewClipTool.enableClipVolume(vp);
|
|
681
|
-
core_frontend_1.ViewClipTool.setViewClip(vp, deco._clip);
|
|
682
|
-
}
|
|
683
|
-
if (undefined === deco._removeManipulatorToolListener) {
|
|
684
|
-
deco._removeManipulatorToolListener = core_frontend_1.IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => deco.onManipulatorToolEvent(tool, event));
|
|
685
|
-
deco.start();
|
|
686
|
-
deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Show);
|
|
687
|
-
}
|
|
688
|
-
return true;
|
|
689
|
-
}
|
|
690
|
-
ProjectExtentsClipDecoration.clear();
|
|
691
|
-
}
|
|
692
|
-
if (!clipToProjectExtents(vp))
|
|
693
|
-
return false;
|
|
694
|
-
ProjectExtentsClipDecoration._decorator = new ProjectExtentsClipDecoration(vp);
|
|
695
|
-
if (fitExtents)
|
|
696
|
-
ProjectExtentsClipDecoration._decorator.fitExtents();
|
|
697
|
-
vp.onChangeView.addOnce(() => this.clear(false, true));
|
|
698
|
-
return (undefined !== ProjectExtentsClipDecoration._decorator._clipId);
|
|
699
|
-
}
|
|
700
|
-
static hide() {
|
|
701
|
-
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
702
|
-
return;
|
|
703
|
-
const saveClipId = ProjectExtentsClipDecoration._decorator._clipId; // cleared by stop to trigger decorator removal...
|
|
704
|
-
ProjectExtentsClipDecoration._decorator.stop();
|
|
705
|
-
ProjectExtentsClipDecoration._decorator._clipId = saveClipId;
|
|
706
|
-
ProjectExtentsClipDecoration._decorator.onChanged.raiseEvent(ProjectExtentsClipDecoration._decorator.iModel, ProjectLocationChanged.Hide);
|
|
707
|
-
}
|
|
708
|
-
static clear(clearClip = true, resetGeolocation = true) {
|
|
709
|
-
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
710
|
-
return;
|
|
711
|
-
if (clearClip)
|
|
712
|
-
ProjectExtentsClipDecoration._decorator.resetViewClip(); // Clear project extents view clip...
|
|
713
|
-
if (resetGeolocation)
|
|
714
|
-
ProjectExtentsClipDecoration._decorator.resetGeolocation(); // Restore modified geolocation back to create state...
|
|
715
|
-
ProjectExtentsClipDecoration._decorator.stop();
|
|
716
|
-
ProjectExtentsClipDecoration._decorator = undefined;
|
|
717
|
-
}
|
|
718
|
-
static async update() {
|
|
719
|
-
const deco = ProjectExtentsClipDecoration._decorator;
|
|
720
|
-
if (undefined === deco)
|
|
721
|
-
return;
|
|
722
|
-
clipToProjectExtents(deco.viewport);
|
|
723
|
-
deco.init();
|
|
724
|
-
return deco.updateControls();
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
exports.ProjectExtentsClipDecoration = ProjectExtentsClipDecoration;
|
|
728
|
-
/** Show project location decoration. Project extents represented by view clip.
|
|
729
|
-
* @beta
|
|
730
|
-
*/
|
|
731
|
-
class ProjectLocationShowTool extends core_frontend_1.Tool {
|
|
732
|
-
async run() {
|
|
733
|
-
const vp = core_frontend_1.IModelApp.viewManager.selectedView;
|
|
734
|
-
if (undefined === vp || !ProjectExtentsClipDecoration.show(vp))
|
|
735
|
-
return false;
|
|
736
|
-
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
737
|
-
return true;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
ProjectLocationShowTool
|
|
742
|
-
/** Hide project location decoration. Preserves changes to project extents view clip and geolocation.
|
|
743
|
-
* @beta
|
|
744
|
-
*/
|
|
745
|
-
class ProjectLocationHideTool extends core_frontend_1.Tool {
|
|
746
|
-
async run() {
|
|
747
|
-
ProjectExtentsClipDecoration.hide();
|
|
748
|
-
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
749
|
-
return true;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
ProjectLocationHideTool
|
|
754
|
-
/** Clear project location decoration. Restore modified geolocation and remove view clip.
|
|
755
|
-
* @beta
|
|
756
|
-
*/
|
|
757
|
-
class ProjectLocationCancelTool extends core_frontend_1.Tool {
|
|
758
|
-
async run() {
|
|
759
|
-
ProjectExtentsClipDecoration.clear();
|
|
760
|
-
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
761
|
-
return true;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
ProjectLocationCancelTool
|
|
766
|
-
/** Save modified project extents and geolocation. Updates decoration to reflect saved state.
|
|
767
|
-
* @note Allowing this change to be undone is both problematic and undesirable.
|
|
768
|
-
* Warns the user if called with previous changes to cancel restarting the TxnManager session.
|
|
769
|
-
* @beta
|
|
770
|
-
*/
|
|
771
|
-
class ProjectLocationSaveTool extends core_frontend_1.Tool {
|
|
772
|
-
async allowRestartTxnSession(iModel) {
|
|
773
|
-
if (!await iModel.txns.isUndoPossible())
|
|
774
|
-
return true;
|
|
775
|
-
// NOTE: Default if openMessageBox isn't implemented is MessageBoxValue.Ok, so we'll check No instead of Yes...
|
|
776
|
-
if (core_frontend_1.MessageBoxValue.No === await core_frontend_1.IModelApp.notifications.openMessageBox(core_frontend_1.MessageBoxType.YesNo, translateMessage("RestartTxn"), core_frontend_1.MessageBoxIconType.Question))
|
|
777
|
-
return false;
|
|
778
|
-
return true;
|
|
779
|
-
}
|
|
780
|
-
async saveChanges(deco, extents, ecefLocation) {
|
|
781
|
-
if (!deco.iModel.isBriefcaseConnection())
|
|
782
|
-
return;
|
|
783
|
-
if (!await this.allowRestartTxnSession(deco.iModel))
|
|
784
|
-
return;
|
|
785
|
-
try {
|
|
786
|
-
await EditTool_1.EditTools.startCommand({ commandId: editor_common_1.editorBuiltInCmdIds.cmdBasicManipulation, iModelKey: deco.iModel.key });
|
|
787
|
-
if (undefined !== extents)
|
|
788
|
-
await EditToolIpc_1.basicManipulationIpc.updateProjectExtents(extents);
|
|
789
|
-
if (undefined !== ecefLocation)
|
|
790
|
-
await EditToolIpc_1.basicManipulationIpc.updateEcefLocation(ecefLocation);
|
|
791
|
-
await deco.iModel.saveChanges(this.toolId);
|
|
792
|
-
await deco.iModel.txns.restartTxnSession();
|
|
793
|
-
}
|
|
794
|
-
catch (err) {
|
|
795
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, core_bentley_1.BentleyError.getErrorMessage(err) || "An unknown error occurred."));
|
|
796
|
-
}
|
|
797
|
-
deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Save);
|
|
798
|
-
await ProjectExtentsClipDecoration.update();
|
|
799
|
-
return core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
800
|
-
}
|
|
801
|
-
async run() {
|
|
802
|
-
const deco = ProjectExtentsClipDecoration.get();
|
|
803
|
-
if (undefined === deco) {
|
|
804
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotActive")));
|
|
805
|
-
return false;
|
|
806
|
-
}
|
|
807
|
-
if (deco.iModel.isReadonly) {
|
|
808
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("Readonly")));
|
|
809
|
-
return true;
|
|
810
|
-
}
|
|
811
|
-
const extents = deco.getModifiedExtents();
|
|
812
|
-
const ecefLocation = deco.getModifiedEcefLocation();
|
|
813
|
-
if (undefined === extents && undefined === ecefLocation) {
|
|
814
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NoChanges")));
|
|
815
|
-
return true;
|
|
816
|
-
}
|
|
817
|
-
await this.saveChanges(deco, extents, ecefLocation);
|
|
818
|
-
return true;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
ProjectLocationSaveTool
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
/** @packageDocumentation
|
|
7
|
+
* @module Editing
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.ProjectLocationSaveTool = exports.ProjectLocationCancelTool = exports.ProjectLocationHideTool = exports.ProjectLocationShowTool = exports.ProjectExtentsClipDecoration = exports.ProjectLocationChanged = void 0;
|
|
11
|
+
const core_bentley_1 = require("@itwin/core-bentley");
|
|
12
|
+
const core_common_1 = require("@itwin/core-common");
|
|
13
|
+
const core_frontend_1 = require("@itwin/core-frontend");
|
|
14
|
+
const core_geometry_1 = require("@itwin/core-geometry");
|
|
15
|
+
const editor_common_1 = require("@itwin/editor-common");
|
|
16
|
+
const EditTool_1 = require("../EditTool");
|
|
17
|
+
const EditToolIpc_1 = require("../EditToolIpc");
|
|
18
|
+
const ProjectGeolocation_1 = require("./ProjectGeolocation");
|
|
19
|
+
function translateMessage(key) {
|
|
20
|
+
return EditTool_1.EditTools.translate(`ProjectLocation:Message.${key}`);
|
|
21
|
+
}
|
|
22
|
+
function translateMessageBold(key) {
|
|
23
|
+
return `<b>${translateMessage(key)}:</b> `;
|
|
24
|
+
}
|
|
25
|
+
function translateCoreMeasureBold(key) {
|
|
26
|
+
return `<b>${core_frontend_1.CoreTools.translate(`Measure.Labels.${key}`)}:</b> `;
|
|
27
|
+
}
|
|
28
|
+
function clearViewClip(vp) {
|
|
29
|
+
if (!core_frontend_1.ViewClipTool.doClipClear(vp))
|
|
30
|
+
return false;
|
|
31
|
+
core_frontend_1.ViewClipDecorationProvider.create().onClearClip(vp); // Send clear event...
|
|
32
|
+
core_frontend_1.ViewClipDecorationProvider.clear();
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
function clipToProjectExtents(vp) {
|
|
36
|
+
clearViewClip(vp); // Clear any existing view clip and send clear event...
|
|
37
|
+
core_frontend_1.ViewClipTool.enableClipVolume(vp);
|
|
38
|
+
return core_frontend_1.ViewClipTool.doClipToRange(vp, vp.iModel.projectExtents, core_geometry_1.Transform.createIdentity());
|
|
39
|
+
}
|
|
40
|
+
function enableBackgroundMap(viewport, onOff) {
|
|
41
|
+
if (onOff === viewport.viewFlags.backgroundMap)
|
|
42
|
+
return false;
|
|
43
|
+
viewport.viewFlags = viewport.viewFlags.with("backgroundMap", onOff);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
function updateMapDisplay(vp, turnOnMap) {
|
|
47
|
+
if (!turnOnMap || !enableBackgroundMap(vp, true))
|
|
48
|
+
vp.invalidateRenderPlan();
|
|
49
|
+
}
|
|
50
|
+
class ProjectExtentsControlArrow extends core_frontend_1.ViewClipControlArrow {
|
|
51
|
+
constructor() {
|
|
52
|
+
super(...arguments);
|
|
53
|
+
this.extentValid = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Values for [[ProjectExtentsClipDecoration.onChanged] event.
|
|
57
|
+
* @beta
|
|
58
|
+
*/
|
|
59
|
+
var ProjectLocationChanged;
|
|
60
|
+
(function (ProjectLocationChanged) {
|
|
61
|
+
/** Extents has been modified (unsaved changes) */
|
|
62
|
+
ProjectLocationChanged[ProjectLocationChanged["Extents"] = 0] = "Extents";
|
|
63
|
+
/** Geolocation has been modified (unsaved changes) */
|
|
64
|
+
ProjectLocationChanged[ProjectLocationChanged["Geolocation"] = 1] = "Geolocation";
|
|
65
|
+
/** Abandon unsaved changes to extents */
|
|
66
|
+
ProjectLocationChanged[ProjectLocationChanged["ResetExtents"] = 2] = "ResetExtents";
|
|
67
|
+
/** Abandon unsaved changes to geolocation */
|
|
68
|
+
ProjectLocationChanged[ProjectLocationChanged["ResetGeolocation"] = 3] = "ResetGeolocation";
|
|
69
|
+
/** Decoration hidden (unsaved changes preserved) */
|
|
70
|
+
ProjectLocationChanged[ProjectLocationChanged["Hide"] = 4] = "Hide";
|
|
71
|
+
/** Decoration shown (unsaved changes restored) */
|
|
72
|
+
ProjectLocationChanged[ProjectLocationChanged["Show"] = 5] = "Show";
|
|
73
|
+
/** Save changes to extents and geolocation */
|
|
74
|
+
ProjectLocationChanged[ProjectLocationChanged["Save"] = 6] = "Save";
|
|
75
|
+
})(ProjectLocationChanged = exports.ProjectLocationChanged || (exports.ProjectLocationChanged = {}));
|
|
76
|
+
/** Controls to modify project extents shown using view clip
|
|
77
|
+
* @beta
|
|
78
|
+
*/
|
|
79
|
+
class ProjectExtentsClipDecoration extends core_frontend_1.EditManipulator.HandleProvider {
|
|
80
|
+
constructor(viewport) {
|
|
81
|
+
super(viewport.iModel);
|
|
82
|
+
this.viewport = viewport;
|
|
83
|
+
this._extentsLengthValid = true;
|
|
84
|
+
this._extentsWidthValid = true;
|
|
85
|
+
this._extentsHeightValid = true;
|
|
86
|
+
this._allowEcefLocationChange = false;
|
|
87
|
+
this._controlIds = [];
|
|
88
|
+
this._controls = [];
|
|
89
|
+
this._suspendDecorator = false;
|
|
90
|
+
this.suspendGeolocationDecorations = false;
|
|
91
|
+
/** Called when project extents or geolocation is modified */
|
|
92
|
+
this.onChanged = new core_bentley_1.BeEvent();
|
|
93
|
+
if (!this.init())
|
|
94
|
+
return;
|
|
95
|
+
this._monumentId = this.iModel.transientIds.getNext();
|
|
96
|
+
this._northId = this.iModel.transientIds.getNext();
|
|
97
|
+
this._clipId = this.iModel.transientIds.getNext();
|
|
98
|
+
this.start();
|
|
99
|
+
}
|
|
100
|
+
start() {
|
|
101
|
+
this.updateDecorationListener(true);
|
|
102
|
+
this._removeViewCloseListener = core_frontend_1.IModelApp.viewManager.onViewClose.addListener((vp) => this.onViewClose(vp));
|
|
103
|
+
this.iModel.selectionSet.replace(this._clipId); // Always select decoration on create...
|
|
104
|
+
}
|
|
105
|
+
stop() {
|
|
106
|
+
const selectedId = (undefined !== this._clipId && this.iModel.selectionSet.has(this._clipId)) ? this._clipId : undefined;
|
|
107
|
+
this._clipId = undefined; // Invalidate id so that decorator will be dropped...
|
|
108
|
+
super.stop();
|
|
109
|
+
if (undefined !== selectedId)
|
|
110
|
+
this.iModel.selectionSet.remove(selectedId); // Don't leave decorator id in selection set...
|
|
111
|
+
if (undefined !== this._removeViewCloseListener) {
|
|
112
|
+
this._removeViewCloseListener();
|
|
113
|
+
this._removeViewCloseListener = undefined;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
init() {
|
|
117
|
+
if (!this.getClipData())
|
|
118
|
+
return false;
|
|
119
|
+
this._ecefLocation = this.iModel.ecefLocation;
|
|
120
|
+
this._monumentPoint = this.getMonumentPoint();
|
|
121
|
+
this._northDirection = this.getNorthDirection();
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
onViewClose(vp) {
|
|
125
|
+
if (this.viewport === vp)
|
|
126
|
+
ProjectExtentsClipDecoration.clear();
|
|
127
|
+
}
|
|
128
|
+
getClipData() {
|
|
129
|
+
this._clip = this._clipShape = this._clipShapeExtents = this._clipRange = undefined;
|
|
130
|
+
const clip = this.viewport.view.getViewClip();
|
|
131
|
+
if (undefined === clip)
|
|
132
|
+
return false;
|
|
133
|
+
const clipShape = core_frontend_1.ViewClipTool.isSingleClipShape(clip);
|
|
134
|
+
if (undefined === clipShape)
|
|
135
|
+
return false;
|
|
136
|
+
if (5 !== clipShape.polygon.length || undefined === clipShape.zLow || undefined === clipShape.zHigh)
|
|
137
|
+
return false; // Not a box, can't be project extents clip...
|
|
138
|
+
if (undefined !== clipShape.transformFromClip && !clipShape.transformFromClip.isIdentity)
|
|
139
|
+
return false; // Not axis aligned, can't be project extents clip...
|
|
140
|
+
this._clipShapeExtents = core_geometry_1.Range1d.createXX(clipShape.zLow, clipShape.zHigh);
|
|
141
|
+
this._clipShape = clipShape;
|
|
142
|
+
this._clip = clip;
|
|
143
|
+
this._clipRange = core_geometry_1.Range3d.create();
|
|
144
|
+
const shapePtsLo = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.low);
|
|
145
|
+
const shapePtsHi = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.high);
|
|
146
|
+
this._clipRange.extendArray(shapePtsLo);
|
|
147
|
+
this._clipRange.extendArray(shapePtsHi);
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
ensureNumControls(numReqControls) {
|
|
151
|
+
const numCurrent = this._controlIds.length;
|
|
152
|
+
if (numCurrent < numReqControls) {
|
|
153
|
+
const transientIds = this.iModel.transientIds;
|
|
154
|
+
for (let i = numCurrent; i < numReqControls; i++)
|
|
155
|
+
this._controlIds[i] = transientIds.getNext();
|
|
156
|
+
}
|
|
157
|
+
else if (numCurrent > numReqControls) {
|
|
158
|
+
this._controlIds.length = numReqControls;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
createClipShapeControls() {
|
|
162
|
+
if (undefined === this._clipShape)
|
|
163
|
+
return false;
|
|
164
|
+
const shapePtsLo = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.low);
|
|
165
|
+
const shapePtsHi = core_frontend_1.ViewClipTool.getClipShapePoints(this._clipShape, this._clipShapeExtents.high);
|
|
166
|
+
const shapeArea = core_geometry_1.PolygonOps.centroidAreaNormal(shapePtsLo);
|
|
167
|
+
if (undefined === shapeArea)
|
|
168
|
+
return false;
|
|
169
|
+
const numControls = shapePtsLo.length + 1; // Number of edge midpoints plus zLow and zHigh...
|
|
170
|
+
this.ensureNumControls(numControls);
|
|
171
|
+
for (let i = 0; i < numControls - 2; i++) {
|
|
172
|
+
const midPtLo = shapePtsLo[i].interpolate(0.5, shapePtsLo[i + 1]);
|
|
173
|
+
const midPtHi = shapePtsHi[i].interpolate(0.5, shapePtsHi[i + 1]);
|
|
174
|
+
const faceCenter = midPtLo.interpolate(0.5, midPtHi);
|
|
175
|
+
const edgeTangent = core_geometry_1.Vector3d.createStartEnd(shapePtsLo[i], shapePtsLo[i + 1]);
|
|
176
|
+
const faceNormal = edgeTangent.crossProduct(shapeArea.direction);
|
|
177
|
+
faceNormal.normalizeInPlace();
|
|
178
|
+
this._controls[i] = new ProjectExtentsControlArrow(faceCenter, faceNormal, 0.75);
|
|
179
|
+
this._controls[i].extentValid = (faceNormal.isParallelTo(core_geometry_1.Vector3d.unitX(), true) ? this._extentsLengthValid : this._extentsWidthValid);
|
|
180
|
+
}
|
|
181
|
+
const zFillColor = core_common_1.ColorDef.from(150, 150, 250);
|
|
182
|
+
this._controls[numControls - 2] = new ProjectExtentsControlArrow(shapeArea.origin, core_geometry_1.Vector3d.unitZ(-1.0), 0.75, zFillColor, undefined, "zLow");
|
|
183
|
+
this._controls[numControls - 1] = new ProjectExtentsControlArrow(shapeArea.origin.plusScaled(core_geometry_1.Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), core_geometry_1.Vector3d.unitZ(), 0.75, zFillColor, undefined, "zHigh");
|
|
184
|
+
this._controls[numControls - 2].extentValid = this._extentsHeightValid;
|
|
185
|
+
this._controls[numControls - 1].extentValid = this._extentsHeightValid;
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
/** Allow project extents for map projections to be larger since curvature of the earth is accounted for. */
|
|
189
|
+
get maxExtentLength() { return ((this._allowEcefLocationChange ? 20 : 350) * core_geometry_1.Constant.oneKilometer); }
|
|
190
|
+
/** Impose some reasonable height limit for project extents. */
|
|
191
|
+
get maxExtentHeight() { return (2 * core_geometry_1.Constant.oneKilometer); }
|
|
192
|
+
hasValidGCS() {
|
|
193
|
+
if (!this.iModel.isGeoLocated || this.iModel.noGcsDefined)
|
|
194
|
+
return false;
|
|
195
|
+
const gcs = this.iModel.geographicCoordinateSystem;
|
|
196
|
+
if (undefined === gcs || undefined === gcs.horizontalCRS)
|
|
197
|
+
return false; // A valid GCS ought to have horizontalCR defined...
|
|
198
|
+
// Check for approximate GCS (such as from MicroStation's "From Placemark" tool) and allow it to be replaced...
|
|
199
|
+
const hasValidId = (undefined !== gcs.horizontalCRS.id && 0 !== gcs.horizontalCRS.id.length);
|
|
200
|
+
const hasValidDescr = (undefined !== gcs.horizontalCRS.description && 0 !== gcs.horizontalCRS.description.length);
|
|
201
|
+
const hasValidProjection = (undefined !== gcs.horizontalCRS.projection && "AzimuthalEqualArea" !== gcs.horizontalCRS.projection.method);
|
|
202
|
+
return hasValidId || hasValidDescr || hasValidProjection;
|
|
203
|
+
}
|
|
204
|
+
async createControls() {
|
|
205
|
+
// Always update to current view clip to handle post-modify, etc.
|
|
206
|
+
if (undefined === this._clipId || !this.getClipData())
|
|
207
|
+
return false;
|
|
208
|
+
this._allowEcefLocationChange = !this.hasValidGCS();
|
|
209
|
+
if (undefined !== this._clipRange) {
|
|
210
|
+
this._extentsLengthValid = (this._clipRange.xLength() < this.maxExtentLength);
|
|
211
|
+
this._extentsWidthValid = (this._clipRange.yLength() < this.maxExtentLength);
|
|
212
|
+
this._extentsHeightValid = (this._clipRange.zLength() < this.maxExtentHeight);
|
|
213
|
+
}
|
|
214
|
+
// Show controls if only range box and it's controls are selected, selection set doesn't include any other elements...
|
|
215
|
+
let showControls = false;
|
|
216
|
+
if (this.iModel.selectionSet.size <= this._controlIds.length + 1 && this.iModel.selectionSet.has(this._clipId)) {
|
|
217
|
+
showControls = true;
|
|
218
|
+
if (this.iModel.selectionSet.size > 1) {
|
|
219
|
+
this.iModel.selectionSet.elements.forEach((val) => {
|
|
220
|
+
if (this._clipId !== val && !this._controlIds.includes(val))
|
|
221
|
+
showControls = false;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!showControls)
|
|
226
|
+
return false; // Don't clear decoration on de-select...
|
|
227
|
+
return this.createClipShapeControls();
|
|
228
|
+
}
|
|
229
|
+
clearControls() {
|
|
230
|
+
this.iModel.selectionSet.remove(this._controlIds); // Remove any selected controls as they won't continue to be displayed...
|
|
231
|
+
super.clearControls();
|
|
232
|
+
}
|
|
233
|
+
async modifyControls(hit, _ev) {
|
|
234
|
+
if (undefined === this._clip || hit.sourceId === this._clipId)
|
|
235
|
+
return false;
|
|
236
|
+
const saveQualifiers = core_frontend_1.IModelApp.toolAdmin.currentInputState.qualifiers;
|
|
237
|
+
if (undefined !== this._clipShape) {
|
|
238
|
+
const clipShapeModifyTool = new core_frontend_1.ViewClipShapeModifyTool(this, this._clip, this.viewport, hit.sourceId, this._controlIds, this._controls);
|
|
239
|
+
this._suspendDecorator = await clipShapeModifyTool.run();
|
|
240
|
+
}
|
|
241
|
+
if (this._suspendDecorator)
|
|
242
|
+
core_frontend_1.IModelApp.toolAdmin.currentInputState.qualifiers = saveQualifiers; // onInstallTool cleared qualifiers, preserve for "modify all" behavior when shift was held and drag started...
|
|
243
|
+
return this._suspendDecorator;
|
|
244
|
+
}
|
|
245
|
+
async onRightClick(_hit, _ev) { return core_frontend_1.EventHandled.No; }
|
|
246
|
+
async onTouchTap(hit, ev) { return (hit.sourceId === this._clipId ? core_frontend_1.EventHandled.No : super.onTouchTap(hit, ev)); }
|
|
247
|
+
async onDecorationButtonEvent(hit, ev) {
|
|
248
|
+
if (hit.sourceId === this._monumentId) {
|
|
249
|
+
if (core_frontend_1.BeButton.Data === ev.button && !ev.isDown && !ev.isDragging)
|
|
250
|
+
await ProjectGeolocation_1.ProjectGeolocationPointTool.startTool();
|
|
251
|
+
return core_frontend_1.EventHandled.Yes; // Only pickable for tooltip, don't allow selection...
|
|
252
|
+
}
|
|
253
|
+
if (hit.sourceId === this._northId) {
|
|
254
|
+
if (core_frontend_1.BeButton.Data === ev.button && !ev.isDown && !ev.isDragging)
|
|
255
|
+
await ProjectGeolocation_1.ProjectGeolocationNorthTool.startTool();
|
|
256
|
+
return core_frontend_1.EventHandled.Yes; // Only pickable for tooltip, don't allow selection...
|
|
257
|
+
}
|
|
258
|
+
return super.onDecorationButtonEvent(hit, ev);
|
|
259
|
+
}
|
|
260
|
+
onManipulatorEvent(eventType) {
|
|
261
|
+
if (core_frontend_1.EditManipulator.EventType.Accept === eventType)
|
|
262
|
+
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.Extents);
|
|
263
|
+
this._suspendDecorator = false;
|
|
264
|
+
super.onManipulatorEvent(eventType);
|
|
265
|
+
}
|
|
266
|
+
async getDecorationToolTip(hit) {
|
|
267
|
+
const quantityFormatter = core_frontend_1.IModelApp.quantityFormatter;
|
|
268
|
+
const toolTip = document.createElement("div");
|
|
269
|
+
let toolTipHtml = "";
|
|
270
|
+
if (hit.sourceId === this._monumentId) {
|
|
271
|
+
toolTipHtml += `${translateMessage("ModifyGeolocation")}<br>`;
|
|
272
|
+
const coordFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Coordinate);
|
|
273
|
+
if (undefined !== coordFormatterSpec) {
|
|
274
|
+
const pointAdjusted = this._monumentPoint.minus(this.iModel.globalOrigin);
|
|
275
|
+
const formattedPointX = quantityFormatter.formatQuantity(pointAdjusted.x, coordFormatterSpec);
|
|
276
|
+
const formattedPointY = quantityFormatter.formatQuantity(pointAdjusted.y, coordFormatterSpec);
|
|
277
|
+
const formattedPointZ = quantityFormatter.formatQuantity(pointAdjusted.z, coordFormatterSpec);
|
|
278
|
+
toolTipHtml += `${translateCoreMeasureBold("Coordinate") + formattedPointX}, ${formattedPointY}, ${formattedPointZ}<br>`;
|
|
279
|
+
}
|
|
280
|
+
const latLongFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.LatLong);
|
|
281
|
+
if (undefined !== latLongFormatterSpec && undefined !== coordFormatterSpec && this.iModel.isGeoLocated) {
|
|
282
|
+
const cartographic = this.iModel.spatialToCartographicFromEcef(this._monumentPoint);
|
|
283
|
+
const formattedLat = quantityFormatter.formatQuantity(Math.abs(cartographic.latitude), latLongFormatterSpec);
|
|
284
|
+
const formattedLong = quantityFormatter.formatQuantity(Math.abs(cartographic.longitude), latLongFormatterSpec);
|
|
285
|
+
const formattedHeight = quantityFormatter.formatQuantity(cartographic.height, coordFormatterSpec);
|
|
286
|
+
const latDir = core_frontend_1.CoreTools.translate(cartographic.latitude < 0 ? "Measure.Labels.S" : "Measure.Labels.N");
|
|
287
|
+
const longDir = core_frontend_1.CoreTools.translate(cartographic.longitude < 0 ? "Measure.Labels.W" : "Measure.Labels.E");
|
|
288
|
+
toolTipHtml += `${translateCoreMeasureBold("LatLong") + formattedLat + latDir}, ${formattedLong}${longDir}<br>`;
|
|
289
|
+
toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedHeight}<br>`;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else if (hit.sourceId === this._northId) {
|
|
293
|
+
toolTipHtml += `${translateMessage("ModifyNorthDirection")}<br>`;
|
|
294
|
+
const angleFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Angle);
|
|
295
|
+
if (undefined !== angleFormatterSpec) {
|
|
296
|
+
const formattedAngle = quantityFormatter.formatQuantity(this.getClockwiseAngleToNorth().radians, angleFormatterSpec);
|
|
297
|
+
toolTipHtml += `${translateMessageBold("Angle") + formattedAngle}<br>`;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else if (hit.sourceId === this._clipId) {
|
|
301
|
+
const extentsValid = (this._extentsLengthValid && this._extentsWidthValid && this._extentsHeightValid);
|
|
302
|
+
toolTipHtml += `${translateMessage(extentsValid ? "ProjectExtents" : "LargeProjectExtents")}<br>`;
|
|
303
|
+
const distanceFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
|
|
304
|
+
if (undefined !== distanceFormatterSpec && undefined !== this._clipRange) {
|
|
305
|
+
const formattedLength = quantityFormatter.formatQuantity(this._clipRange.xLength(), distanceFormatterSpec);
|
|
306
|
+
const formattedWidth = quantityFormatter.formatQuantity(this._clipRange.yLength(), distanceFormatterSpec);
|
|
307
|
+
const formattedHeight = quantityFormatter.formatQuantity(this._clipRange.zLength(), distanceFormatterSpec);
|
|
308
|
+
toolTipHtml += `${translateMessageBold("Length") + formattedLength}<br>`;
|
|
309
|
+
toolTipHtml += `${translateMessageBold("Width") + formattedWidth}<br>`;
|
|
310
|
+
toolTipHtml += `${translateMessageBold("Height") + formattedHeight}<br>`;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
const arrowIndex = this._controlIds.indexOf(hit.sourceId);
|
|
315
|
+
if (-1 !== arrowIndex) {
|
|
316
|
+
toolTipHtml += `${translateMessage("ModifyProjectExtents")}<br>`;
|
|
317
|
+
const distanceFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Length);
|
|
318
|
+
if (undefined !== distanceFormatterSpec && undefined !== this._clipRange) {
|
|
319
|
+
const arrowControl = this._controls[arrowIndex];
|
|
320
|
+
let arrowLabel = "";
|
|
321
|
+
let arrowLength = 0.0;
|
|
322
|
+
let arrowLengthMax = 0.0;
|
|
323
|
+
if (arrowControl.direction.isParallelTo(core_geometry_1.Vector3d.unitX(), true)) {
|
|
324
|
+
arrowLabel = "Length";
|
|
325
|
+
arrowLength = this._clipRange.xLength();
|
|
326
|
+
if (!this._extentsLengthValid)
|
|
327
|
+
arrowLengthMax = this.maxExtentLength;
|
|
328
|
+
}
|
|
329
|
+
else if (arrowControl.direction.isParallelTo(core_geometry_1.Vector3d.unitY(), true)) {
|
|
330
|
+
arrowLabel = "Width";
|
|
331
|
+
arrowLength = this._clipRange.yLength();
|
|
332
|
+
if (!this._extentsWidthValid)
|
|
333
|
+
arrowLengthMax = this.maxExtentLength;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
arrowLabel = "Height";
|
|
337
|
+
arrowLength = this._clipRange.zLength();
|
|
338
|
+
if (!this._extentsHeightValid)
|
|
339
|
+
arrowLengthMax = this.maxExtentHeight;
|
|
340
|
+
const coordFormatterSpec = (this.iModel.isGeoLocated ? quantityFormatter.findFormatterSpecByQuantityType(core_frontend_1.QuantityType.Coordinate) : undefined);
|
|
341
|
+
if (undefined !== coordFormatterSpec) {
|
|
342
|
+
const heightPt = ("zLow" === arrowControl.name ? this._clipRange.low : this._clipRange.high);
|
|
343
|
+
const cartographic = this.iModel.spatialToCartographicFromEcef(heightPt);
|
|
344
|
+
const formattedAltitude = quantityFormatter.formatQuantity(cartographic.height, coordFormatterSpec);
|
|
345
|
+
toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedAltitude}<br>`;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const formattedLength = quantityFormatter.formatQuantity(arrowLength, distanceFormatterSpec);
|
|
349
|
+
toolTipHtml += `${translateMessageBold(arrowLabel) + formattedLength}<br>`;
|
|
350
|
+
if (0.0 !== arrowLengthMax) {
|
|
351
|
+
const formattedMaxLength = quantityFormatter.formatQuantity(arrowLengthMax, distanceFormatterSpec);
|
|
352
|
+
toolTipHtml += `${translateMessageBold("MaxExtent") + formattedMaxLength}<br>`;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
toolTip.innerHTML = toolTipHtml;
|
|
358
|
+
return toolTip;
|
|
359
|
+
}
|
|
360
|
+
testDecorationHit(id) { return (id === this._monumentId || id === this._northId || id === this._clipId || this._controlIds.includes(id)); }
|
|
361
|
+
updateDecorationListener(_add) { super.updateDecorationListener(undefined !== this._clipId); } // Decorator isn't just for resize controls...
|
|
362
|
+
getMonumentPoint() {
|
|
363
|
+
const origin = core_geometry_1.Point3d.createZero();
|
|
364
|
+
if (this.iModel.ecefLocation && this.iModel.ecefLocation.cartographicOrigin)
|
|
365
|
+
return this.iModel.cartographicToSpatialFromEcef(this.iModel.ecefLocation.cartographicOrigin, origin);
|
|
366
|
+
origin.setFrom(this.iModel.projectExtents.low);
|
|
367
|
+
if (0.0 > this.iModel.projectExtents.low.z && 0.0 < this.iModel.projectExtents.high.z)
|
|
368
|
+
origin.z = 0.0;
|
|
369
|
+
return origin;
|
|
370
|
+
}
|
|
371
|
+
getClockwiseAngleToNorth() {
|
|
372
|
+
const angle = this.getNorthAngle();
|
|
373
|
+
angle.setRadians(core_geometry_1.Angle.adjustRadians0To2Pi(angle.radians));
|
|
374
|
+
return angle;
|
|
375
|
+
}
|
|
376
|
+
getNorthAngle() {
|
|
377
|
+
const northDirection = (undefined !== this._northDirection ? this._northDirection : this.getNorthDirection());
|
|
378
|
+
return northDirection.direction.angleToXY(core_geometry_1.Vector3d.unitY());
|
|
379
|
+
}
|
|
380
|
+
getNorthDirection(refOrigin) {
|
|
381
|
+
const origin = (undefined !== refOrigin ? refOrigin : this.iModel.projectExtents.center);
|
|
382
|
+
if (!this.iModel.isGeoLocated)
|
|
383
|
+
return core_geometry_1.Ray3d.create(origin, core_geometry_1.Vector3d.unitY());
|
|
384
|
+
const cartographic = this.iModel.spatialToCartographicFromEcef(origin);
|
|
385
|
+
cartographic.latitude += core_geometry_1.Angle.createDegrees(0.01).radians;
|
|
386
|
+
const pt2 = this.iModel.cartographicToSpatialFromEcef(cartographic);
|
|
387
|
+
const northVec = core_geometry_1.Vector3d.createStartEnd(origin, pt2);
|
|
388
|
+
northVec.z = 0.0;
|
|
389
|
+
northVec.normalizeInPlace();
|
|
390
|
+
return core_geometry_1.Ray3d.create(origin, northVec);
|
|
391
|
+
}
|
|
392
|
+
drawNorthArrow(context, northDir, id) {
|
|
393
|
+
const vp = context.viewport;
|
|
394
|
+
const pixelSize = vp.pixelsFromInches(0.55);
|
|
395
|
+
const scale = vp.viewingSpace.getPixelSizeAtPoint(northDir.origin) * pixelSize;
|
|
396
|
+
const matrix = core_geometry_1.Matrix3d.createRigidFromColumns(northDir.direction, core_geometry_1.Vector3d.unitZ(), core_geometry_1.AxisOrder.YZX);
|
|
397
|
+
if (undefined === matrix)
|
|
398
|
+
return;
|
|
399
|
+
matrix.scaleColumnsInPlace(scale, scale, scale);
|
|
400
|
+
const arrowTrans = core_geometry_1.Transform.createRefs(northDir.origin, matrix);
|
|
401
|
+
const northArrowBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, arrowTrans, id);
|
|
402
|
+
const color = core_common_1.ColorDef.white;
|
|
403
|
+
const arrowOutline = [];
|
|
404
|
+
arrowOutline[0] = core_geometry_1.Point3d.create(0.0, 0.65);
|
|
405
|
+
arrowOutline[1] = core_geometry_1.Point3d.create(-0.45, -0.5);
|
|
406
|
+
arrowOutline[2] = core_geometry_1.Point3d.create(0.0, -0.2);
|
|
407
|
+
arrowOutline[3] = core_geometry_1.Point3d.create(0.45, -0.5);
|
|
408
|
+
arrowOutline[4] = arrowOutline[0].clone();
|
|
409
|
+
const arrowLeftFill = [];
|
|
410
|
+
arrowLeftFill[0] = arrowOutline[0].clone();
|
|
411
|
+
arrowLeftFill[1] = arrowOutline[1].clone();
|
|
412
|
+
arrowLeftFill[2] = arrowOutline[2].clone();
|
|
413
|
+
arrowLeftFill[3] = arrowLeftFill[0].clone();
|
|
414
|
+
const arrowRightFill = [];
|
|
415
|
+
arrowRightFill[0] = arrowOutline[0].clone();
|
|
416
|
+
arrowRightFill[1] = arrowOutline[3].clone();
|
|
417
|
+
arrowRightFill[2] = arrowOutline[2].clone();
|
|
418
|
+
arrowRightFill[3] = arrowRightFill[0].clone();
|
|
419
|
+
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.from(0, 0, 0, 200), 1);
|
|
420
|
+
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.6), true, true);
|
|
421
|
+
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.create(0.0, 0.85), 0.2), true, true);
|
|
422
|
+
northArrowBuilder.setSymbology(color, color, 2);
|
|
423
|
+
northArrowBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.5), false, false);
|
|
424
|
+
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(0.6, 0.0), core_geometry_1.Point3d.create(-0.6, 0.0)]);
|
|
425
|
+
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(0.0, 0.6), core_geometry_1.Point3d.create(0.0, -0.6)]);
|
|
426
|
+
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.from(150, 150, 150), 1);
|
|
427
|
+
northArrowBuilder.addShape(arrowLeftFill);
|
|
428
|
+
northArrowBuilder.setSymbology(color, core_common_1.ColorDef.black, 1);
|
|
429
|
+
northArrowBuilder.addShape(arrowRightFill);
|
|
430
|
+
northArrowBuilder.setSymbology(color, color, 1);
|
|
431
|
+
northArrowBuilder.addLineString(arrowOutline);
|
|
432
|
+
northArrowBuilder.setSymbology(color, color, 3);
|
|
433
|
+
northArrowBuilder.addLineString([core_geometry_1.Point3d.create(-0.1, 0.75), core_geometry_1.Point3d.create(-0.1, 0.95), core_geometry_1.Point3d.create(0.1, 0.75), core_geometry_1.Point3d.create(0.1, 0.95)]);
|
|
434
|
+
context.addDecorationFromBuilder(northArrowBuilder);
|
|
435
|
+
}
|
|
436
|
+
drawMonumentPoint(context, point, scaleFactor, id) {
|
|
437
|
+
const vp = context.viewport;
|
|
438
|
+
const pixelSize = vp.pixelsFromInches(0.25) * scaleFactor;
|
|
439
|
+
const scale = vp.viewingSpace.getPixelSizeAtPoint(point) * pixelSize;
|
|
440
|
+
const matrix = core_geometry_1.Matrix3d.createRotationAroundAxisIndex(core_geometry_1.AxisIndex.Z, core_geometry_1.Angle.createDegrees(45.0));
|
|
441
|
+
matrix.scaleColumnsInPlace(scale, scale, scale);
|
|
442
|
+
const monumentTrans = core_geometry_1.Transform.createRefs(point, matrix);
|
|
443
|
+
const monumentPointBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, monumentTrans, id);
|
|
444
|
+
const color = core_common_1.ColorDef.white;
|
|
445
|
+
monumentPointBuilder.setSymbology(color, core_common_1.ColorDef.from(0, 0, 0, 150), 1);
|
|
446
|
+
monumentPointBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.7), true, true);
|
|
447
|
+
monumentPointBuilder.setSymbology(color, color, 2);
|
|
448
|
+
monumentPointBuilder.addArc(core_geometry_1.Arc3d.createXY(core_geometry_1.Point3d.createZero(), 0.5), false, false);
|
|
449
|
+
monumentPointBuilder.addLineString([core_geometry_1.Point3d.create(0.5, 0.0), core_geometry_1.Point3d.create(-0.5, 0.0)]);
|
|
450
|
+
monumentPointBuilder.addLineString([core_geometry_1.Point3d.create(0.0, 0.5), core_geometry_1.Point3d.create(0.0, -0.5)]);
|
|
451
|
+
context.addDecorationFromBuilder(monumentPointBuilder);
|
|
452
|
+
}
|
|
453
|
+
drawAreaTooLargeIndicator(context) {
|
|
454
|
+
if ((this._extentsLengthValid && this._extentsWidthValid) || undefined === this._clipRange)
|
|
455
|
+
return;
|
|
456
|
+
const corners = this._clipRange.corners();
|
|
457
|
+
const indices = core_geometry_1.Range3d.faceCornerIndices(5);
|
|
458
|
+
const points = [];
|
|
459
|
+
for (const index of indices)
|
|
460
|
+
points.push(corners[index]);
|
|
461
|
+
const areaWarnColor = core_common_1.ColorDef.red.withAlpha(50);
|
|
462
|
+
const areaWarnBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldDecoration);
|
|
463
|
+
areaWarnBuilder.setSymbology(areaWarnColor, areaWarnColor, 1);
|
|
464
|
+
areaWarnBuilder.addShape(points);
|
|
465
|
+
context.addDecorationFromBuilder(areaWarnBuilder);
|
|
466
|
+
}
|
|
467
|
+
drawExtentTooLargeIndicator(context, worldPoint, sizePixels) {
|
|
468
|
+
const position = context.viewport.worldToView(worldPoint);
|
|
469
|
+
position.x = Math.floor(position.x) + 0.5;
|
|
470
|
+
position.y = Math.floor(position.y) + 0.5;
|
|
471
|
+
const drawDecoration = (ctx) => {
|
|
472
|
+
ctx.lineWidth = 4;
|
|
473
|
+
ctx.lineCap = "round";
|
|
474
|
+
ctx.strokeStyle = "rgba(255,0,0,.75)";
|
|
475
|
+
ctx.fillStyle = "rgba(255,255,255,.75)";
|
|
476
|
+
ctx.shadowColor = "black";
|
|
477
|
+
ctx.shadowBlur = 5;
|
|
478
|
+
ctx.beginPath();
|
|
479
|
+
ctx.moveTo(0, -sizePixels);
|
|
480
|
+
ctx.lineTo(-sizePixels, sizePixels);
|
|
481
|
+
ctx.lineTo(sizePixels, sizePixels);
|
|
482
|
+
ctx.lineTo(0, -sizePixels);
|
|
483
|
+
ctx.fill();
|
|
484
|
+
ctx.shadowBlur = 0;
|
|
485
|
+
ctx.beginPath();
|
|
486
|
+
ctx.moveTo(0, -sizePixels);
|
|
487
|
+
ctx.lineTo(-sizePixels, sizePixels);
|
|
488
|
+
ctx.lineTo(sizePixels, sizePixels);
|
|
489
|
+
ctx.lineTo(0, -sizePixels);
|
|
490
|
+
ctx.stroke();
|
|
491
|
+
ctx.strokeStyle = "black";
|
|
492
|
+
ctx.lineWidth = 3;
|
|
493
|
+
ctx.beginPath();
|
|
494
|
+
ctx.moveTo(0, -sizePixels * 0.2);
|
|
495
|
+
ctx.lineTo(0, sizePixels * 0.3);
|
|
496
|
+
ctx.moveTo(0, (sizePixels * 0.3) + 4);
|
|
497
|
+
ctx.lineTo(0, (sizePixels * 0.3) + 4.5);
|
|
498
|
+
ctx.stroke();
|
|
499
|
+
};
|
|
500
|
+
context.addCanvasDecoration({ position, drawDecoration });
|
|
501
|
+
}
|
|
502
|
+
decorate(context) {
|
|
503
|
+
if (this._suspendDecorator)
|
|
504
|
+
return;
|
|
505
|
+
if (undefined === this._clipId || undefined === this._clipShape || undefined === this._clipRange)
|
|
506
|
+
return;
|
|
507
|
+
const vp = context.viewport;
|
|
508
|
+
if (this.viewport !== vp)
|
|
509
|
+
return;
|
|
510
|
+
if (!this.suspendGeolocationDecorations && undefined !== this._northDirection && this.iModel.isGeoLocated)
|
|
511
|
+
this.drawNorthArrow(context, this._northDirection, this._allowEcefLocationChange ? this._northId : undefined); // Show north, but don't make pickable if it shouldn't be modified...
|
|
512
|
+
const maxSizeInches = ((this._clipRange.maxLength() / vp.viewingSpace.getPixelSizeAtPoint(this._clipRange.center)) / vp.pixelsPerInch) * 0.5; // Display size limit when zooming out...
|
|
513
|
+
if (maxSizeInches < 0.5)
|
|
514
|
+
return;
|
|
515
|
+
if (!this.suspendGeolocationDecorations && undefined !== this._monumentPoint && this._allowEcefLocationChange)
|
|
516
|
+
this.drawMonumentPoint(context, this._monumentPoint, 1.0, this._monumentId);
|
|
517
|
+
core_frontend_1.ViewClipTool.drawClipShape(context, this._clipShape, this._clipShapeExtents, core_common_1.ColorDef.white.adjustedForContrast(context.viewport.view.backgroundColor), 3, this._clipId);
|
|
518
|
+
this.drawAreaTooLargeIndicator(context);
|
|
519
|
+
if (!this._isActive)
|
|
520
|
+
return;
|
|
521
|
+
const outlineColor = core_common_1.ColorDef.from(0, 0, 0, 50).adjustedForContrast(vp.view.backgroundColor);
|
|
522
|
+
const fillVisColor = core_common_1.ColorDef.from(150, 250, 200, 225).adjustedForContrast(vp.view.backgroundColor);
|
|
523
|
+
const fillHidColor = fillVisColor.withAlpha(200);
|
|
524
|
+
const fillSelColor = fillVisColor.inverse().withAlpha(75);
|
|
525
|
+
const shapePts = core_frontend_1.EditManipulator.HandleUtils.getArrowShape(0.0, 0.15, 0.55, 1.0, 0.3, 0.5, 0.1);
|
|
526
|
+
for (let iFace = 0; iFace < this._controlIds.length; iFace++) {
|
|
527
|
+
const sizeInches = Math.min(this._controls[iFace].sizeInches, maxSizeInches);
|
|
528
|
+
if (0.0 === sizeInches)
|
|
529
|
+
continue;
|
|
530
|
+
const anchorRay = core_frontend_1.ViewClipTool.getClipRayTransformed(this._controls[iFace].origin, this._controls[iFace].direction, undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined);
|
|
531
|
+
const transform = core_frontend_1.EditManipulator.HandleUtils.getArrowTransform(vp, anchorRay.origin, anchorRay.direction, sizeInches);
|
|
532
|
+
if (undefined === transform)
|
|
533
|
+
continue;
|
|
534
|
+
// deep copies because we're using a builder transform w/addLineString...
|
|
535
|
+
const visPts = shapePts.map((pt) => pt.clone());
|
|
536
|
+
const hidPts = shapePts.map((pt) => pt.clone());
|
|
537
|
+
const arrowVisBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldOverlay, transform, this._controlIds[iFace]);
|
|
538
|
+
const arrowHidBuilder = context.createGraphicBuilder(core_frontend_1.GraphicType.WorldDecoration, transform);
|
|
539
|
+
const isSelected = this.iModel.selectionSet.has(this._controlIds[iFace]);
|
|
540
|
+
let outlineColorOvr = this._controls[iFace].outline;
|
|
541
|
+
if (undefined !== outlineColorOvr) {
|
|
542
|
+
outlineColorOvr = outlineColorOvr.adjustedForContrast(vp.view.backgroundColor);
|
|
543
|
+
outlineColorOvr = outlineColorOvr.withAlpha(outlineColor.getAlpha());
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
outlineColorOvr = outlineColor;
|
|
547
|
+
}
|
|
548
|
+
let fillVisColorOvr = this._controls[iFace].fill;
|
|
549
|
+
let fillHidColorOvr = fillHidColor;
|
|
550
|
+
let fillSelColorOvr = fillSelColor;
|
|
551
|
+
if (undefined !== fillVisColorOvr) {
|
|
552
|
+
fillVisColorOvr = fillVisColorOvr.adjustedForContrast(vp.view.backgroundColor);
|
|
553
|
+
fillVisColorOvr = fillVisColorOvr.withAlpha(fillVisColor.getAlpha());
|
|
554
|
+
fillHidColorOvr = fillVisColorOvr.withAlpha(fillHidColor.getAlpha());
|
|
555
|
+
fillSelColorOvr = fillVisColorOvr.inverse().withAlpha(fillSelColor.getAlpha());
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
fillVisColorOvr = fillVisColor;
|
|
559
|
+
}
|
|
560
|
+
arrowVisBuilder.setSymbology(outlineColorOvr, outlineColorOvr, isSelected ? 4 : 2);
|
|
561
|
+
arrowVisBuilder.addLineString(visPts);
|
|
562
|
+
arrowVisBuilder.setBlankingFill(isSelected ? fillSelColorOvr : fillVisColorOvr);
|
|
563
|
+
arrowVisBuilder.addShape(visPts);
|
|
564
|
+
context.addDecorationFromBuilder(arrowVisBuilder);
|
|
565
|
+
arrowHidBuilder.setSymbology(fillHidColorOvr, fillHidColorOvr, 1);
|
|
566
|
+
arrowHidBuilder.addShape(hidPts);
|
|
567
|
+
context.addDecorationFromBuilder(arrowHidBuilder);
|
|
568
|
+
if (this._controls[iFace].extentValid)
|
|
569
|
+
continue;
|
|
570
|
+
const warnPixels = 15.0;
|
|
571
|
+
const warnOffset = vp.viewingSpace.getPixelSizeAtPoint(anchorRay.origin) * warnPixels * 1.5;
|
|
572
|
+
const warnOrigin = anchorRay.origin.plusScaled(anchorRay.direction, -warnOffset);
|
|
573
|
+
this.drawExtentTooLargeIndicator(context, warnOrigin, warnPixels);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
resetViewClip() {
|
|
577
|
+
if (!clearViewClip(this.viewport))
|
|
578
|
+
return false;
|
|
579
|
+
if (undefined !== this.getModifiedExtents())
|
|
580
|
+
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.ResetExtents);
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
resetGeolocation() {
|
|
584
|
+
if (!this._allowEcefLocationChange)
|
|
585
|
+
return false;
|
|
586
|
+
if (undefined === this.getModifiedEcefLocation())
|
|
587
|
+
return false; // Wasn't changed...
|
|
588
|
+
this.iModel.disableGCS(false);
|
|
589
|
+
this.iModel.ecefLocation = this._ecefLocation;
|
|
590
|
+
this._monumentPoint = this.getMonumentPoint();
|
|
591
|
+
this._northDirection = this.getNorthDirection();
|
|
592
|
+
updateMapDisplay(this.viewport, false);
|
|
593
|
+
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.ResetGeolocation);
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
updateEcefLocation(origin, point, angle) {
|
|
597
|
+
if (!this._allowEcefLocationChange)
|
|
598
|
+
return false;
|
|
599
|
+
const newEcefLocation = core_common_1.EcefLocation.createFromCartographicOrigin(origin, point, (undefined !== angle ? angle : this.getNorthAngle())); // Preserve modified north direction...
|
|
600
|
+
const ecefLocation = this.iModel.ecefLocation;
|
|
601
|
+
if (undefined !== ecefLocation && ecefLocation.isAlmostEqual(newEcefLocation))
|
|
602
|
+
return false;
|
|
603
|
+
this.iModel.disableGCS(true); // Map display will ignore change to ecef location when GCS is present...
|
|
604
|
+
this.iModel.setEcefLocation(newEcefLocation);
|
|
605
|
+
this._monumentPoint = this.getMonumentPoint();
|
|
606
|
+
this._northDirection = this.getNorthDirection(undefined !== this._northDirection ? this._northDirection.origin : undefined); // Preserve modified north reference point...
|
|
607
|
+
updateMapDisplay(this.viewport, true);
|
|
608
|
+
this.onChanged.raiseEvent(this.iModel, ProjectLocationChanged.Geolocation);
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
updateNorthDirection(northDir) {
|
|
612
|
+
if (!this._allowEcefLocationChange || !this.iModel.isGeoLocated)
|
|
613
|
+
return false;
|
|
614
|
+
const point = (undefined !== this._monumentPoint ? this._monumentPoint : this.getMonumentPoint()); // Preserve modified monument point...
|
|
615
|
+
const origin = this.iModel.spatialToCartographicFromEcef(point);
|
|
616
|
+
const saveDirection = this._northDirection;
|
|
617
|
+
this._northDirection = northDir; // Change reference point to input location...
|
|
618
|
+
const angle = this.getNorthAngle();
|
|
619
|
+
if (!this.updateEcefLocation(origin, point, angle)) {
|
|
620
|
+
this._northDirection = saveDirection;
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
getModifiedEcefLocation() {
|
|
626
|
+
const ecefLocation = this.iModel.ecefLocation;
|
|
627
|
+
if (undefined === ecefLocation)
|
|
628
|
+
return undefined; // geolocation wasn't added...
|
|
629
|
+
if (undefined === this._ecefLocation)
|
|
630
|
+
return ecefLocation; // geolocation didn't exist previously...
|
|
631
|
+
if (this._ecefLocation.isAlmostEqual(ecefLocation))
|
|
632
|
+
return undefined;
|
|
633
|
+
return ecefLocation;
|
|
634
|
+
}
|
|
635
|
+
getModifiedExtents() {
|
|
636
|
+
if (undefined === this._clipRange)
|
|
637
|
+
return undefined;
|
|
638
|
+
return this._clipRange.isAlmostEqual(this.iModel.projectExtents) ? undefined : this._clipRange;
|
|
639
|
+
}
|
|
640
|
+
static allowEcefLocationChange(requireExisting, outputError = true) {
|
|
641
|
+
if (undefined === ProjectExtentsClipDecoration._decorator) {
|
|
642
|
+
if (outputError)
|
|
643
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotActive")));
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
else if (!ProjectExtentsClipDecoration._decorator._allowEcefLocationChange) {
|
|
647
|
+
if (outputError)
|
|
648
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotAllowed")));
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
else if (requireExisting && !ProjectExtentsClipDecoration._decorator.iModel.isGeoLocated) {
|
|
652
|
+
if (outputError)
|
|
653
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotGeolocated")));
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
fitExtents() {
|
|
659
|
+
if (undefined === this._clipRange)
|
|
660
|
+
return undefined;
|
|
661
|
+
const options = { animateFrustumChange: true, animationTime: core_bentley_1.BeDuration.fromSeconds(2).milliseconds };
|
|
662
|
+
const aspect = this.viewport.viewRect.aspect;
|
|
663
|
+
this.viewport.view.lookAtVolume(this._clipRange, aspect);
|
|
664
|
+
this.viewport.synchWithView(options);
|
|
665
|
+
this.viewport.viewCmdTargetCenter = undefined;
|
|
666
|
+
}
|
|
667
|
+
static get() {
|
|
668
|
+
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
669
|
+
return undefined;
|
|
670
|
+
return ProjectExtentsClipDecoration._decorator;
|
|
671
|
+
}
|
|
672
|
+
static show(vp, fitExtents = true) {
|
|
673
|
+
if (!vp.view.isSpatialView())
|
|
674
|
+
return false;
|
|
675
|
+
if (undefined !== ProjectExtentsClipDecoration._decorator) {
|
|
676
|
+
const deco = ProjectExtentsClipDecoration._decorator;
|
|
677
|
+
if (vp === deco.viewport && undefined !== deco._clipId && undefined !== deco._clip) {
|
|
678
|
+
if (deco._clip !== vp.view.getViewClip()) {
|
|
679
|
+
clearViewClip(vp);
|
|
680
|
+
core_frontend_1.ViewClipTool.enableClipVolume(vp);
|
|
681
|
+
core_frontend_1.ViewClipTool.setViewClip(vp, deco._clip);
|
|
682
|
+
}
|
|
683
|
+
if (undefined === deco._removeManipulatorToolListener) {
|
|
684
|
+
deco._removeManipulatorToolListener = core_frontend_1.IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => deco.onManipulatorToolEvent(tool, event));
|
|
685
|
+
deco.start();
|
|
686
|
+
deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Show);
|
|
687
|
+
}
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
ProjectExtentsClipDecoration.clear();
|
|
691
|
+
}
|
|
692
|
+
if (!clipToProjectExtents(vp))
|
|
693
|
+
return false;
|
|
694
|
+
ProjectExtentsClipDecoration._decorator = new ProjectExtentsClipDecoration(vp);
|
|
695
|
+
if (fitExtents)
|
|
696
|
+
ProjectExtentsClipDecoration._decorator.fitExtents();
|
|
697
|
+
vp.onChangeView.addOnce(() => this.clear(false, true));
|
|
698
|
+
return (undefined !== ProjectExtentsClipDecoration._decorator._clipId);
|
|
699
|
+
}
|
|
700
|
+
static hide() {
|
|
701
|
+
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
702
|
+
return;
|
|
703
|
+
const saveClipId = ProjectExtentsClipDecoration._decorator._clipId; // cleared by stop to trigger decorator removal...
|
|
704
|
+
ProjectExtentsClipDecoration._decorator.stop();
|
|
705
|
+
ProjectExtentsClipDecoration._decorator._clipId = saveClipId;
|
|
706
|
+
ProjectExtentsClipDecoration._decorator.onChanged.raiseEvent(ProjectExtentsClipDecoration._decorator.iModel, ProjectLocationChanged.Hide);
|
|
707
|
+
}
|
|
708
|
+
static clear(clearClip = true, resetGeolocation = true) {
|
|
709
|
+
if (undefined === ProjectExtentsClipDecoration._decorator)
|
|
710
|
+
return;
|
|
711
|
+
if (clearClip)
|
|
712
|
+
ProjectExtentsClipDecoration._decorator.resetViewClip(); // Clear project extents view clip...
|
|
713
|
+
if (resetGeolocation)
|
|
714
|
+
ProjectExtentsClipDecoration._decorator.resetGeolocation(); // Restore modified geolocation back to create state...
|
|
715
|
+
ProjectExtentsClipDecoration._decorator.stop();
|
|
716
|
+
ProjectExtentsClipDecoration._decorator = undefined;
|
|
717
|
+
}
|
|
718
|
+
static async update() {
|
|
719
|
+
const deco = ProjectExtentsClipDecoration._decorator;
|
|
720
|
+
if (undefined === deco)
|
|
721
|
+
return;
|
|
722
|
+
clipToProjectExtents(deco.viewport);
|
|
723
|
+
deco.init();
|
|
724
|
+
return deco.updateControls();
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
exports.ProjectExtentsClipDecoration = ProjectExtentsClipDecoration;
|
|
728
|
+
/** Show project location decoration. Project extents represented by view clip.
|
|
729
|
+
* @beta
|
|
730
|
+
*/
|
|
731
|
+
class ProjectLocationShowTool extends core_frontend_1.Tool {
|
|
732
|
+
async run() {
|
|
733
|
+
const vp = core_frontend_1.IModelApp.viewManager.selectedView;
|
|
734
|
+
if (undefined === vp || !ProjectExtentsClipDecoration.show(vp))
|
|
735
|
+
return false;
|
|
736
|
+
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
737
|
+
return true;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
ProjectLocationShowTool.toolId = "ProjectLocation.Show";
|
|
741
|
+
exports.ProjectLocationShowTool = ProjectLocationShowTool;
|
|
742
|
+
/** Hide project location decoration. Preserves changes to project extents view clip and geolocation.
|
|
743
|
+
* @beta
|
|
744
|
+
*/
|
|
745
|
+
class ProjectLocationHideTool extends core_frontend_1.Tool {
|
|
746
|
+
async run() {
|
|
747
|
+
ProjectExtentsClipDecoration.hide();
|
|
748
|
+
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
ProjectLocationHideTool.toolId = "ProjectLocation.Hide";
|
|
753
|
+
exports.ProjectLocationHideTool = ProjectLocationHideTool;
|
|
754
|
+
/** Clear project location decoration. Restore modified geolocation and remove view clip.
|
|
755
|
+
* @beta
|
|
756
|
+
*/
|
|
757
|
+
class ProjectLocationCancelTool extends core_frontend_1.Tool {
|
|
758
|
+
async run() {
|
|
759
|
+
ProjectExtentsClipDecoration.clear();
|
|
760
|
+
await core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
761
|
+
return true;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
ProjectLocationCancelTool.toolId = "ProjectLocation.Cancel";
|
|
765
|
+
exports.ProjectLocationCancelTool = ProjectLocationCancelTool;
|
|
766
|
+
/** Save modified project extents and geolocation. Updates decoration to reflect saved state.
|
|
767
|
+
* @note Allowing this change to be undone is both problematic and undesirable.
|
|
768
|
+
* Warns the user if called with previous changes to cancel restarting the TxnManager session.
|
|
769
|
+
* @beta
|
|
770
|
+
*/
|
|
771
|
+
class ProjectLocationSaveTool extends core_frontend_1.Tool {
|
|
772
|
+
async allowRestartTxnSession(iModel) {
|
|
773
|
+
if (!await iModel.txns.isUndoPossible())
|
|
774
|
+
return true;
|
|
775
|
+
// NOTE: Default if openMessageBox isn't implemented is MessageBoxValue.Ok, so we'll check No instead of Yes...
|
|
776
|
+
if (core_frontend_1.MessageBoxValue.No === await core_frontend_1.IModelApp.notifications.openMessageBox(core_frontend_1.MessageBoxType.YesNo, translateMessage("RestartTxn"), core_frontend_1.MessageBoxIconType.Question))
|
|
777
|
+
return false;
|
|
778
|
+
return true;
|
|
779
|
+
}
|
|
780
|
+
async saveChanges(deco, extents, ecefLocation) {
|
|
781
|
+
if (!deco.iModel.isBriefcaseConnection())
|
|
782
|
+
return;
|
|
783
|
+
if (!await this.allowRestartTxnSession(deco.iModel))
|
|
784
|
+
return;
|
|
785
|
+
try {
|
|
786
|
+
await EditTool_1.EditTools.startCommand({ commandId: editor_common_1.editorBuiltInCmdIds.cmdBasicManipulation, iModelKey: deco.iModel.key });
|
|
787
|
+
if (undefined !== extents)
|
|
788
|
+
await EditToolIpc_1.basicManipulationIpc.updateProjectExtents(extents);
|
|
789
|
+
if (undefined !== ecefLocation)
|
|
790
|
+
await EditToolIpc_1.basicManipulationIpc.updateEcefLocation(ecefLocation);
|
|
791
|
+
await deco.iModel.saveChanges(this.toolId);
|
|
792
|
+
await deco.iModel.txns.restartTxnSession();
|
|
793
|
+
}
|
|
794
|
+
catch (err) {
|
|
795
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, core_bentley_1.BentleyError.getErrorMessage(err) || "An unknown error occurred."));
|
|
796
|
+
}
|
|
797
|
+
deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Save);
|
|
798
|
+
await ProjectExtentsClipDecoration.update();
|
|
799
|
+
return core_frontend_1.IModelApp.toolAdmin.startDefaultTool();
|
|
800
|
+
}
|
|
801
|
+
async run() {
|
|
802
|
+
const deco = ProjectExtentsClipDecoration.get();
|
|
803
|
+
if (undefined === deco) {
|
|
804
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NotActive")));
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
if (deco.iModel.isReadonly) {
|
|
808
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("Readonly")));
|
|
809
|
+
return true;
|
|
810
|
+
}
|
|
811
|
+
const extents = deco.getModifiedExtents();
|
|
812
|
+
const ecefLocation = deco.getModifiedEcefLocation();
|
|
813
|
+
if (undefined === extents && undefined === ecefLocation) {
|
|
814
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, translateMessage("NoChanges")));
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
await this.saveChanges(deco, extents, ecefLocation);
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
ProjectLocationSaveTool.toolId = "ProjectLocation.Save";
|
|
822
|
+
exports.ProjectLocationSaveTool = ProjectLocationSaveTool;
|
|
823
823
|
//# sourceMappingURL=ProjectExtentsDecoration.js.map
|