@inweb/client 25.2.2 → 25.2.5

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.
Files changed (222) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +70 -70
  3. package/dist/client.js +12739 -12352
  4. package/dist/client.js.map +1 -1
  5. package/dist/client.min.js +1 -1
  6. package/dist/client.module.js +588 -157
  7. package/dist/client.module.js.map +1 -1
  8. package/lib/Api/Assembly.d.ts +338 -338
  9. package/lib/Api/ClashTest.d.ts +175 -175
  10. package/lib/Api/Client.d.ts +451 -451
  11. package/lib/Api/ClientEvents.d.ts +28 -28
  12. package/lib/Api/File.d.ts +567 -567
  13. package/lib/Api/HttpClient.d.ts +12 -12
  14. package/lib/Api/IAssembly.d.ts +13 -13
  15. package/lib/Api/IFile.d.ts +45 -45
  16. package/lib/Api/IHttpClient.d.ts +10 -10
  17. package/lib/Api/IUser.d.ts +10 -10
  18. package/lib/Api/Job.d.ts +141 -141
  19. package/lib/Api/Member.d.ts +84 -84
  20. package/lib/Api/Model.d.ts +146 -146
  21. package/lib/Api/Permission.d.ts +92 -92
  22. package/lib/Api/Project.d.ts +246 -246
  23. package/lib/Api/Role.d.ts +81 -81
  24. package/lib/Api/User.d.ts +196 -196
  25. package/lib/Api/impl/FetchError.d.ts +17 -17
  26. package/lib/Api/impl/Utils.d.ts +32 -32
  27. package/lib/Api/impl/http.d.ts +66 -66
  28. package/lib/ConvetMath.d.ts +28 -28
  29. package/lib/Viewer/CanvasEvents.d.ts +1 -1
  30. package/lib/Viewer/Commands/ApplyModelTransform.d.ts +1 -1
  31. package/lib/Viewer/Commands/ClearMarkup.d.ts +1 -1
  32. package/lib/Viewer/Commands/ClearSlices.d.ts +1 -1
  33. package/lib/Viewer/Commands/CreatePreview.d.ts +1 -1
  34. package/lib/Viewer/Commands/Explode.d.ts +1 -1
  35. package/lib/Viewer/Commands/GetDefaultViewPositions.d.ts +1 -1
  36. package/lib/Viewer/Commands/GetModels.d.ts +1 -1
  37. package/lib/Viewer/Commands/GetSelected.d.ts +1 -1
  38. package/lib/Viewer/Commands/HideSelected.d.ts +1 -1
  39. package/lib/Viewer/Commands/IsolateSelected.d.ts +1 -1
  40. package/lib/Viewer/Commands/RegenerateAll.d.ts +1 -1
  41. package/lib/Viewer/Commands/ResetView.d.ts +1 -1
  42. package/lib/Viewer/Commands/SelectModel.d.ts +1 -1
  43. package/lib/Viewer/Commands/SetActiveDragger.d.ts +1 -1
  44. package/lib/Viewer/Commands/SetDefaultViewPosition.d.ts +1 -1
  45. package/lib/Viewer/Commands/SetMarkupColor.d.ts +1 -1
  46. package/lib/Viewer/Commands/SetSelected.d.ts +1 -1
  47. package/lib/Viewer/Commands/ShowAll.d.ts +1 -1
  48. package/lib/Viewer/Commands/Unselect.d.ts +1 -1
  49. package/lib/Viewer/Commands/ZoomToExtents.d.ts +1 -1
  50. package/lib/Viewer/Commands/ZoomToObjects.d.ts +1 -1
  51. package/lib/Viewer/Commands/ZoomToSelected.d.ts +1 -1
  52. package/lib/Viewer/Commands.d.ts +2 -2
  53. package/lib/Viewer/Draggers/Actions/OrbitAction.d.ts +21 -21
  54. package/lib/Viewer/Draggers/Actions/PanAction.d.ts +17 -17
  55. package/lib/Viewer/Draggers/Actions/ZoomAction.d.ts +7 -7
  56. package/lib/Viewer/Draggers/Common/Geometry.d.ts +114 -114
  57. package/lib/Viewer/Draggers/Common/GestureManager.d.ts +40 -40
  58. package/lib/Viewer/Draggers/Common/OdBaseDragger.d.ts +53 -53
  59. package/lib/Viewer/Draggers/Common/OdaGeAction.d.ts +29 -29
  60. package/lib/Viewer/Draggers/MeasureLineDragger/MeasureLineItem.d.ts +30 -30
  61. package/lib/Viewer/Draggers/MeasureLineDragger/MeasureUtils.d.ts +19 -19
  62. package/lib/Viewer/Draggers/MeasureLineDragger/index.d.ts +23 -23
  63. package/lib/Viewer/Draggers/OdBaseCuttingPlaneDragger.d.ts +26 -26
  64. package/lib/Viewer/Draggers/OdCuttingPlaneXAxisDragger.d.ts +7 -7
  65. package/lib/Viewer/Draggers/OdCuttingPlaneYAxisDragger.d.ts +7 -7
  66. package/lib/Viewer/Draggers/OdCuttingPlaneZAxisDragger.d.ts +7 -7
  67. package/lib/Viewer/Draggers/OdOrbitDragger.d.ts +14 -14
  68. package/lib/Viewer/Draggers/OdPanDragger.d.ts +11 -11
  69. package/lib/Viewer/Draggers/OdZoomDragger.d.ts +11 -11
  70. package/lib/Viewer/Draggers/OdZoomWheelDragger.d.ts +10 -10
  71. package/lib/Viewer/Draggers/OdZoomWindowDragger/OdSelectionFrame.d.ts +18 -18
  72. package/lib/Viewer/Draggers/OdZoomWindowDragger/index.d.ts +13 -13
  73. package/lib/Viewer/Draggers/OdaLineDragger.d.ts +14 -14
  74. package/lib/Viewer/Draggers/OdaTextDragger.d.ts +15 -15
  75. package/lib/Viewer/Draggers/OdaWalkDragger.d.ts +29 -29
  76. package/lib/Viewer/Draggers/OrbitAroundBuildingDragger.d.ts +18 -18
  77. package/lib/Viewer/EventEmitter2.d.ts +53 -53
  78. package/lib/Viewer/ICommands.d.ts +24 -24
  79. package/lib/Viewer/IEventEmitter2.d.ts +12 -12
  80. package/lib/Viewer/IViewer.d.ts +26 -26
  81. package/lib/Viewer/Loaders/BaseLoader.d.ts +10 -10
  82. package/lib/Viewer/Loaders/LoaderFactory.d.ts +9 -9
  83. package/lib/Viewer/Loaders/TCSLoader.d.ts +4 -4
  84. package/lib/Viewer/Loaders/UpdaterController.d.ts +14 -14
  85. package/lib/Viewer/Loaders/VsfXLoader.d.ts +4 -4
  86. package/lib/Viewer/Loaders/VsfXPartialLoader.d.ts +4 -4
  87. package/lib/Viewer/Markup/Api/IMarkupArrow.d.ts +21 -11
  88. package/lib/Viewer/Markup/Api/IMarkupCloud.d.ts +15 -0
  89. package/lib/Viewer/Markup/Api/IMarkupColorable.d.ts +4 -4
  90. package/lib/Viewer/Markup/Api/IMarkupEllipse.d.ts +14 -14
  91. package/lib/Viewer/Markup/Api/IMarkupImage.d.ts +14 -14
  92. package/lib/Viewer/Markup/Api/IMarkupLine.d.ts +18 -10
  93. package/lib/Viewer/Markup/Api/IMarkupObject.d.ts +11 -11
  94. package/lib/Viewer/Markup/Api/IMarkupRectangle.d.ts +14 -14
  95. package/lib/Viewer/Markup/Api/IMarkupText.d.ts +12 -12
  96. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaArrow.d.ts +46 -31
  97. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaCloud.d.ts +36 -0
  98. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaEllipse.d.ts +40 -39
  99. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaImage.d.ts +36 -35
  100. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaLine.d.ts +35 -31
  101. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaRectangle.d.ts +38 -37
  102. package/lib/Viewer/Markup/Api/Impl/Konva/KonvaText.d.ts +37 -36
  103. package/lib/Viewer/Markup/IMarkup.d.ts +38 -37
  104. package/lib/Viewer/Markup/Impl/Konva/KonvaMarkup.d.ts +71 -62
  105. package/lib/Viewer/Markup/Impl/Konva/MarkupColor.d.ts +18 -18
  106. package/lib/Viewer/Markup/Impl/Visualize/VisualizeMarkup.d.ts +32 -32
  107. package/lib/Viewer/Markup/MarkupFactory.d.ts +6 -6
  108. package/lib/Viewer/Options.d.ts +227 -227
  109. package/lib/Viewer/OptionsEvents.d.ts +25 -25
  110. package/lib/Viewer/Viewer.d.ts +352 -352
  111. package/lib/Viewer/ViewerCommands.d.ts +22 -22
  112. package/lib/Viewer/ViewerEvents.d.ts +600 -600
  113. package/lib/Viewer/utils.d.ts +3 -3
  114. package/lib/index.d.ts +23 -23
  115. package/package.json +38 -32
  116. package/src/Api/Assembly.ts +678 -678
  117. package/src/Api/ClashTest.ts +290 -290
  118. package/src/Api/Client.ts +816 -816
  119. package/src/Api/ClientEvents.ts +31 -31
  120. package/src/Api/File.ts +962 -962
  121. package/src/Api/HttpClient.ts +73 -73
  122. package/src/Api/IAssembly.ts +37 -37
  123. package/src/Api/IFile.ts +74 -74
  124. package/src/Api/IHttpClient.ts +50 -50
  125. package/src/Api/IUser.ts +33 -33
  126. package/src/Api/Job.ts +253 -253
  127. package/src/Api/Member.ts +161 -161
  128. package/src/Api/Model.ts +259 -259
  129. package/src/Api/Permission.ts +173 -173
  130. package/src/Api/Project.ts +479 -479
  131. package/src/Api/Role.ts +158 -158
  132. package/src/Api/User.ts +357 -357
  133. package/src/Api/impl/FetchError.ts +48 -48
  134. package/src/Api/impl/Utils.ts +367 -367
  135. package/src/Api/impl/http.ts +92 -92
  136. package/src/ConvetMath.ts +372 -372
  137. package/src/Viewer/CanvasEvents.ts +41 -41
  138. package/src/Viewer/Commands/ApplyModelTransform.ts +70 -70
  139. package/src/Viewer/Commands/ClearMarkup.ts +28 -28
  140. package/src/Viewer/Commands/ClearSlices.ts +27 -27
  141. package/src/Viewer/Commands/CreatePreview.ts +33 -33
  142. package/src/Viewer/Commands/Explode.ts +38 -38
  143. package/src/Viewer/Commands/GetDefaultViewPositions.ts +36 -36
  144. package/src/Viewer/Commands/GetModels.ts +43 -43
  145. package/src/Viewer/Commands/GetSelected.ts +58 -58
  146. package/src/Viewer/Commands/HideSelected.ts +37 -37
  147. package/src/Viewer/Commands/IsolateSelected.ts +37 -37
  148. package/src/Viewer/Commands/RegenerateAll.ts +37 -37
  149. package/src/Viewer/Commands/ResetView.ts +43 -43
  150. package/src/Viewer/Commands/SelectModel.ts +52 -52
  151. package/src/Viewer/Commands/SetActiveDragger.ts +29 -29
  152. package/src/Viewer/Commands/SetDefaultViewPosition.ts +50 -50
  153. package/src/Viewer/Commands/SetMarkupColor.ts +29 -29
  154. package/src/Viewer/Commands/SetSelected.ts +47 -47
  155. package/src/Viewer/Commands/ShowAll.ts +37 -37
  156. package/src/Viewer/Commands/Unselect.ts +37 -37
  157. package/src/Viewer/Commands/ZoomToExtents.ts +43 -43
  158. package/src/Viewer/Commands/ZoomToObjects.ts +47 -47
  159. package/src/Viewer/Commands/ZoomToSelected.ts +39 -39
  160. package/src/Viewer/Commands.ts +81 -81
  161. package/src/Viewer/Draggers/Actions/OrbitAction.ts +250 -250
  162. package/src/Viewer/Draggers/Actions/PanAction.ts +102 -102
  163. package/src/Viewer/Draggers/Actions/ZoomAction.ts +45 -45
  164. package/src/Viewer/Draggers/Common/Geometry.ts +152 -152
  165. package/src/Viewer/Draggers/Common/GestureManager.ts +263 -263
  166. package/src/Viewer/Draggers/Common/OdBaseDragger.ts +270 -270
  167. package/src/Viewer/Draggers/Common/OdaGeAction.ts +146 -146
  168. package/src/Viewer/Draggers/MeasureLineDragger/MeasureLineItem.ts +248 -248
  169. package/src/Viewer/Draggers/MeasureLineDragger/MeasureUtils.ts +182 -182
  170. package/src/Viewer/Draggers/MeasureLineDragger/index.ts +166 -166
  171. package/src/Viewer/Draggers/OdBaseCuttingPlaneDragger.ts +182 -182
  172. package/src/Viewer/Draggers/OdCuttingPlaneXAxisDragger.ts +53 -53
  173. package/src/Viewer/Draggers/OdCuttingPlaneYAxisDragger.ts +53 -53
  174. package/src/Viewer/Draggers/OdCuttingPlaneZAxisDragger.ts +53 -53
  175. package/src/Viewer/Draggers/OdOrbitDragger.ts +70 -70
  176. package/src/Viewer/Draggers/OdPanDragger.ts +62 -62
  177. package/src/Viewer/Draggers/OdZoomDragger.ts +59 -59
  178. package/src/Viewer/Draggers/OdZoomWheelDragger.ts +103 -103
  179. package/src/Viewer/Draggers/OdZoomWindowDragger/OdSelectionFrame.ts +123 -123
  180. package/src/Viewer/Draggers/OdZoomWindowDragger/index.ts +75 -75
  181. package/src/Viewer/Draggers/OdaLineDragger.ts +80 -80
  182. package/src/Viewer/Draggers/OdaTextDragger.ts +118 -118
  183. package/src/Viewer/Draggers/OdaWalkDragger.ts +278 -278
  184. package/src/Viewer/Draggers/OrbitAroundBuildingDragger.ts +184 -184
  185. package/src/Viewer/EventEmitter2.ts +116 -116
  186. package/src/Viewer/ICommands.ts +53 -53
  187. package/src/Viewer/IEventEmitter2.ts +36 -36
  188. package/src/Viewer/IViewer.ts +55 -55
  189. package/src/Viewer/Loaders/BaseLoader.ts +40 -40
  190. package/src/Viewer/Loaders/LoaderFactory.ts +44 -44
  191. package/src/Viewer/Loaders/TCSLoader.ts +82 -82
  192. package/src/Viewer/Loaders/UpdaterController.ts +36 -36
  193. package/src/Viewer/Loaders/VsfXLoader.ts +87 -87
  194. package/src/Viewer/Loaders/VsfXPartialLoader.ts +208 -208
  195. package/src/Viewer/Markup/Api/IMarkupArrow.ts +12 -15
  196. package/src/Viewer/Markup/Api/IMarkupCloud.ts +15 -0
  197. package/src/Viewer/Markup/Api/IMarkupColorable.ts +4 -4
  198. package/src/Viewer/Markup/Api/IMarkupEllipse.ts +15 -15
  199. package/src/Viewer/Markup/Api/IMarkupImage.ts +15 -15
  200. package/src/Viewer/Markup/Api/IMarkupLine.ts +20 -10
  201. package/src/Viewer/Markup/Api/IMarkupObject.ts +15 -15
  202. package/src/Viewer/Markup/Api/IMarkupRectangle.ts +15 -15
  203. package/src/Viewer/Markup/Api/IMarkupText.ts +12 -12
  204. package/src/Viewer/Markup/Api/Impl/Konva/KonvaArrow.ts +117 -119
  205. package/src/Viewer/Markup/Api/Impl/Konva/KonvaCloud.ts +208 -0
  206. package/src/Viewer/Markup/Api/Impl/Konva/KonvaEllipse.ts +118 -113
  207. package/src/Viewer/Markup/Api/Impl/Konva/KonvaImage.ts +123 -121
  208. package/src/Viewer/Markup/Api/Impl/Konva/KonvaLine.ts +130 -99
  209. package/src/Viewer/Markup/Api/Impl/Konva/KonvaRectangle.ts +119 -113
  210. package/src/Viewer/Markup/Api/Impl/Konva/KonvaText.ts +110 -104
  211. package/src/Viewer/Markup/IMarkup.ts +40 -39
  212. package/src/Viewer/Markup/Impl/Konva/KonvaMarkup.ts +1208 -872
  213. package/src/Viewer/Markup/Impl/Konva/MarkupColor.ts +39 -39
  214. package/src/Viewer/Markup/Impl/Visualize/VisualizeMarkup.ts +273 -273
  215. package/src/Viewer/Markup/MarkupFactory.ts +32 -32
  216. package/src/Viewer/Options.ts +502 -502
  217. package/src/Viewer/OptionsEvents.ts +28 -28
  218. package/src/Viewer/Viewer.ts +1109 -1109
  219. package/src/Viewer/ViewerCommands.ts +45 -45
  220. package/src/Viewer/ViewerEvents.ts +700 -700
  221. package/src/Viewer/utils.ts +74 -74
  222. package/src/index.ts +48 -48
@@ -1,1109 +1,1109 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2002-2023, Open Design Alliance (the "Alliance").
3
- // All rights reserved.
4
- //
5
- // This software and its documentation and related materials are owned by
6
- // the Alliance. The software may only be incorporated into application
7
- // programs owned by members of the Alliance, subject to a signed
8
- // Membership Agreement and Supplemental Software License Agreement with the
9
- // Alliance. The structure and organization of this software are the valuable
10
- // trade secrets of the Alliance and its suppliers. The software is also
11
- // protected by copyright law and international treaty provisions. Application
12
- // programs incorporating this software must include the following statement
13
- // with their copyright notices:
14
- //
15
- // This application incorporates Open Design Alliance software pursuant to a
16
- // license agreement with Open Design Alliance.
17
- // Open Design Alliance Copyright (C) 2002-2021 by Open Design Alliance.
18
- // All rights reserved.
19
- //
20
- // By use of this software, its documentation or related materials, you
21
- // acknowledge and accept the above terms.
22
- ///////////////////////////////////////////////////////////////////////////////
23
-
24
- import { IViewer } from "./IViewer";
25
- import { commands } from "./Commands";
26
- import { EventEmitter2 } from "./EventEmitter2";
27
- import { ViewerEventMap } from "./ViewerEvents";
28
- import { OptionsEventMap, OptionsChangeEvent } from "./OptionsEvents";
29
- import { CANVAS_EVENTS } from "./CanvasEvents";
30
-
31
- import { OdBaseDragger } from "./Draggers/Common/OdBaseDragger";
32
- import { MeasureLineDragger } from "./Draggers/MeasureLineDragger/index";
33
- import { OdaWalkDragger } from "./Draggers/OdaWalkDragger";
34
- import { OdCuttingPlaneXAxisDragger } from "./Draggers/OdCuttingPlaneXAxisDragger";
35
- import { OdCuttingPlaneYAxisDragger } from "./Draggers/OdCuttingPlaneYAxisDragger";
36
- import { OdCuttingPlaneZAxisDragger } from "./Draggers/OdCuttingPlaneZAxisDragger";
37
- import { OdOrbitDragger } from "./Draggers/OdOrbitDragger";
38
- import { OdPanDragger } from "./Draggers/OdPanDragger";
39
- import { OdZoomDragger } from "./Draggers/OdZoomDragger";
40
- import { OdZoomWheelDragger } from "./Draggers/OdZoomWheelDragger";
41
- import { OdZoomWindowDragger } from "./Draggers/OdZoomWindowDragger/index";
42
- import { OrbitAroundBuildingDragger } from "./Draggers/OrbitAroundBuildingDragger";
43
- import { GestureManager } from "./Draggers/Common/GestureManager";
44
-
45
- import { loadVisualizeJs } from "./utils";
46
-
47
- import { Client } from "../Api/Client";
48
- import { File } from "../Api/File";
49
- import { Assembly } from "../Api/Assembly";
50
- import { Model } from "../Api/Model";
51
- import { Options, OptionsData } from "./Options";
52
- import { LoaderFactory } from "./Loaders/LoaderFactory";
53
- import { MarkupFactory } from "./Markup/MarkupFactory";
54
- import { IMarkup, MarkupType } from "./Markup/IMarkup";
55
-
56
- const OVERLAY_VIEW_NAME = "$OVERLAY_VIEW_NAME";
57
-
58
- const isExist = (value) => value !== undefined && value !== null;
59
-
60
- /**
61
- * The `Client.js` library class that provides methods to integrate with the
62
- * [VisualizeJS](https://cloud.opendesign.com/docs/index.html#/visualizejs) library.
63
- */
64
-
65
- export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> implements IViewer {
66
- private _activeDragger: OdBaseDragger | null;
67
- private _zoomWheelDragger: OdZoomWheelDragger | null;
68
- private _gestureManager: GestureManager | null;
69
- private _enableAutoUpdate: boolean;
70
- private _isNeedRender: boolean;
71
- private _isRunAsyncUpdate: boolean;
72
- private _renderTime: DOMHighResTimeStamp;
73
-
74
- protected _options: Options;
75
- protected _visualizeJsUrl: string;
76
- protected _abortControllerForReferences: AbortController | undefined;
77
-
78
- private clientoptionschange: (event: OptionsChangeEvent) => void;
79
- private canvaseventlistener: (event: Event) => void;
80
-
81
- public draggerFactory: Map<string, typeof OdBaseDragger>;
82
- public canvasEvents: string[];
83
- private frameId: number;
84
- private _resizeObserver: ResizeObserver | undefined;
85
- public canvas: HTMLCanvasElement | undefined;
86
- public markup: IMarkup;
87
-
88
- public visualizeJs: any;
89
- public _abortController: AbortController | undefined;
90
- public _abortControllerForRequestMap: Map<string, AbortController> | undefined;
91
- public client: Client;
92
-
93
- /**
94
- * @param client - The `Client` instance that provides access to a server. Do not specify
95
- * `Client` if you need a standalone viewer instance without access to server models.
96
- * @param params - An object containing viewer configuration parameters.
97
- * @param params.visualizeJsUrl - `VisualizeJS` library URL. Set this URL to use your own
98
- * library instance, or leave it undefined or blank to use the default URL defined by
99
- * `Client.js` you are using.
100
- *
101
- * _Note: Your own `VisualizeJS` library version must match the version of the `Client.js`
102
- * you are using._
103
- * @param params.enableAutoUpdate - Enable auto-update of the viewer after any changes. If
104
- * the auto-update is disabled, you need to update the `VisualizeJS` viewer and the active
105
- * dragger manually using the `update` event. Default is `true`.
106
- */
107
- constructor(
108
- client?: Client,
109
- params: { visualizeJsUrl?: string; enableAutoUpdate?: boolean; markupType?: MarkupType } = {
110
- markupType: MarkupType.Konva,
111
- }
112
- ) {
113
- super();
114
- this.configure(params);
115
-
116
- this._options = new Options(this);
117
-
118
- this.client = client;
119
- this.clientoptionschange = (event: OptionsChangeEvent) => (this._options.data = event.data.data);
120
-
121
- this._activeDragger = null;
122
- this._renderTime = 0;
123
-
124
- this.markup = MarkupFactory.createMarkup(params.markupType ?? MarkupType.Konva);
125
-
126
- this.draggerFactory = new Map<string, typeof OdBaseDragger>();
127
- this.registerDragger("Pan", OdPanDragger);
128
- this.registerDragger("Orbit", OdOrbitDragger);
129
- this.registerDragger("Zoom", OdZoomDragger);
130
- this.registerDragger("ZoomWindow", OdZoomWindowDragger);
131
- this.registerDragger("OrbitAroundBuilding", OrbitAroundBuildingDragger);
132
- this.registerDragger("MeasureLine", MeasureLineDragger);
133
- this.registerDragger("CuttingPlaneXAxis", OdCuttingPlaneXAxisDragger);
134
- this.registerDragger("CuttingPlaneYAxis", OdCuttingPlaneYAxisDragger);
135
- this.registerDragger("CuttingPlaneZAxis", OdCuttingPlaneZAxisDragger);
136
- this.registerDragger("Walk", OdaWalkDragger);
137
-
138
- const markupDraggers = this.markup.getDraggers();
139
- markupDraggers?.forEach((value, key) => {
140
- this.registerDragger(key, value);
141
- });
142
-
143
- this.canvasEvents = CANVAS_EVENTS;
144
- this.canvaseventlistener = (event: Event) => this.emit(event);
145
-
146
- this._enableAutoUpdate = params.enableAutoUpdate ?? true;
147
- this._isNeedRender = false;
148
- this._isRunAsyncUpdate = false;
149
-
150
- this.render = this.render.bind(this);
151
- this.resize = this.resize.bind(this);
152
- }
153
-
154
- /**
155
- * `VisualizeJS` parameters.
156
- *
157
- * Use this only for standalone viewer instances. Use {@link Client#options | Client.options}
158
- * instead if the viewer was created with a `Client` reference using
159
- * {@link Viewer | Viewer.create(client)}. Changes in client options will be automatically
160
- * applied to the viewer options.
161
- */
162
- get options(): Options {
163
- return this._options;
164
- }
165
-
166
- /**
167
- * `VisualizeJS` library URL. Use {@link Viewer#configure | configure()} to change library URL.
168
- *
169
- * @readonly
170
- */
171
- get visualizeJsUrl(): string {
172
- return this._visualizeJsUrl;
173
- }
174
-
175
- /**
176
- * Change the viewer configuration parameters.
177
- *
178
- * @param params - An object containing new configuration parameters.
179
- * @param params.visualizeJsUrl - `VisualizeJS` library URL. Set this URL to use your own
180
- * library instance or leave it blank to use the default URL defined by `Client.js`.
181
- */
182
- configure(params: { visualizeJsUrl?: string }): this {
183
- this._visualizeJsUrl = params.visualizeJsUrl || "VISUALIZE_JS_URL";
184
- return this;
185
- }
186
-
187
- /**
188
- * A [Viewer]{@link Viewer} event measuring progress of loading a `VisualizeJS` library.
189
- *
190
- * @property {string} type - `visualizeprogress`
191
- * @property {number} loaded - A 64-bit unsigned integer value indicating the amount of work
192
- * already performed by the underlying process. The ratio of work done can be calculated by
193
- * dividing total by the value of this property.
194
- * @property {number} total - A 64-bit unsigned integer representing the total amount of work
195
- * that the underlying process is in the progress of performing.
196
- * @event visualizeprogress
197
- */
198
-
199
- /**
200
- * Load `VisualizeJS` module and initialize it with the specified canvas. Call
201
- * {@link Viewer#dispose | dispose()} to release allocated resources.
202
- *
203
- * @async
204
- * @param canvas - HTML `<canvas>` element for `VisualizeJS`.
205
- * @param onProgress - A callback function that handles events measuring progress of loading
206
- * of the `VisualizeJS` library. Retrieves {@link event:visualizeprogress | visualizeprogress} event.
207
- */
208
- async initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent) => void): Promise<this> {
209
- if (this.client) {
210
- this.client.addEventListener("optionschange", this.clientoptionschange);
211
- this.options.data = this.client.options.data;
212
- }
213
- this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
214
-
215
- if (canvas.style.width === "" && canvas.style.height === "") {
216
- canvas.style.width = "100%";
217
- canvas.style.height = "100%";
218
- }
219
- canvas.style.touchAction = "none";
220
-
221
- canvas.width = canvas.clientWidth * window.devicePixelRatio;
222
- canvas.height = canvas.clientHeight * window.devicePixelRatio;
223
-
224
- const visualizeJs: any = await loadVisualizeJs(this.visualizeJsUrl, (ev) => {
225
- const { loaded, timeStamp, total, lengthComputable } = ev;
226
- const event = { loaded, timeStamp, total, lengthComputable, type: "visualizeprogress" } as ProgressEvent;
227
- onProgress?.(event);
228
- });
229
-
230
- this.visualizeJs = visualizeJs;
231
- this.visualizeJs.canvas = canvas;
232
- this.visualizeJs.Viewer.create();
233
-
234
- this.canvas = canvas;
235
- this.canvasEvents.forEach((x) => canvas.addEventListener(x, this.canvaseventlistener));
236
-
237
- this.markup.initialize(this, canvas, this.canvasEvents);
238
-
239
- this._resizeObserver = new ResizeObserver(this.resize);
240
- this._resizeObserver.observe(canvas.parentElement);
241
- this.resize();
242
-
243
- this._zoomWheelDragger = new OdZoomWheelDragger(this);
244
- this._zoomWheelDragger.name = "ZoomWheel";
245
- this._zoomWheelDragger.initialize();
246
-
247
- this._gestureManager = new GestureManager(this);
248
- this._gestureManager.initialize();
249
-
250
- this.syncOpenCloudVisualStyle(true);
251
- this.syncOptions();
252
-
253
- this._renderTime = performance.now();
254
- this.render(this._renderTime);
255
-
256
- return this;
257
- }
258
-
259
- /**
260
- * Releases all resources allocated by this `Viewer` instance. Call this method before
261
- * release the `Viewer` instance.
262
- */
263
- dispose(): this {
264
- this.cancel();
265
- this.emitEvent({ type: "dispose" });
266
-
267
- if (this.frameId) cancelAnimationFrame(this.frameId);
268
- this.frameId = 0;
269
-
270
- this.setActiveDragger("");
271
-
272
- this._zoomWheelDragger?.dispose();
273
- this._gestureManager?.dispose();
274
-
275
- this.removeAllListeners();
276
-
277
- this._resizeObserver?.disconnect();
278
- this._resizeObserver = undefined;
279
-
280
- this.markup.dispose();
281
-
282
- this.canvasEvents.forEach((x) => this.canvas?.removeEventListener(x, this.canvaseventlistener));
283
- this.canvas = undefined;
284
-
285
- this.visualizeJs?.getViewer().clear();
286
- this.visualizeJs = undefined;
287
-
288
- this.client?.removeEventListener("optionschange", this.clientoptionschange);
289
-
290
- return this;
291
- }
292
-
293
- /**
294
- * Returns `true` if `VisualizeJS` module has been loaded andinitialized.
295
- */
296
- isInitialized(): boolean {
297
- return !!this.visualizeJs;
298
- }
299
-
300
- // internal render/resize routines
301
-
302
- private render(time: DOMHighResTimeStamp) {
303
- this.frameId = requestAnimationFrame(this.render);
304
-
305
- if (!this.visualizeJs) return;
306
-
307
- if (this._isRunAsyncUpdate) return;
308
-
309
- const visViewer = this.visualizeJs.getViewer();
310
- if (visViewer.isRunningAnimation() || this._isNeedRender) {
311
- visViewer.update();
312
- this._activeDragger?.updatePreview();
313
- this._isNeedRender = !visViewer.getActiveDevice().isValid();
314
-
315
- const deltaTime = (time - this._renderTime) / 1000;
316
- this._renderTime = time;
317
- this.emitEvent({ type: "render", time, deltaTime });
318
- }
319
- }
320
-
321
- public resize(): this {
322
- if (!this.visualizeJs) return this;
323
-
324
- const { clientWidth, clientHeight } = this.canvas;
325
- this.canvas.width = clientWidth * window.devicePixelRatio;
326
- this.canvas.height = clientHeight * window.devicePixelRatio;
327
-
328
- const visViewer = this.visualizeJs.getViewer();
329
- visViewer.resize(0, this.canvas.width, this.canvas.height, 0);
330
-
331
- this.update(true);
332
- this.emitEvent({ type: "resize", width: clientWidth, height: clientHeight });
333
-
334
- return this;
335
- }
336
-
337
- /**
338
- * Updates the viewer. Do nothing if the auto-update mode is disabled in the constructor (use
339
- * the `update` event to update viewer manually).
340
- *
341
- * Fires:
342
- *
343
- * - {@link UpdateEvent | update}
344
- *
345
- * @param force - If `true` updates the viewer immidietly. Otherwise updates on next
346
- * animation frame. Default is `false`.
347
- */
348
- update(force?: boolean) {
349
- if (this._enableAutoUpdate) {
350
- if (force) {
351
- this.visViewer()?.update();
352
- this.activeDragger()?.updatePreview();
353
- } else {
354
- this._isNeedRender = true;
355
- }
356
- }
357
- this.emitEvent({ type: "update", data: force });
358
- }
359
-
360
- /**
361
- * Update with internal schedule, need after change operation when have long update for
362
- * update without lock UI
363
- *
364
- * @param maxScheduleUpdateTimeInMs - Maximum time for one update, by default 30 ms
365
- * @param maxScheduleUpdateCount - Maximum count of schedule update
366
- * @returns return void Promise
367
- */
368
-
369
- private scheduleUpdateAsync(maxScheduleUpdateTimeInMs = 50): Promise<void> {
370
- return new Promise<void>((resolve, reject) => {
371
- setTimeout(() => {
372
- try {
373
- this.visViewer()?.update(maxScheduleUpdateTimeInMs);
374
- this.activeDragger()?.updatePreview();
375
- resolve();
376
- } catch (e) {
377
- console.error(e);
378
- reject();
379
- }
380
- }, 0);
381
- });
382
- }
383
-
384
- async updateAsync(maxScheduleUpdateTimeInMs = 50, maxScheduleUpdateCount = 50): Promise<void> {
385
- this._isRunAsyncUpdate = true;
386
- const device = this.visViewer().getActiveDevice();
387
- try {
388
- for (let iterationCount = 0; !device.isValid() && iterationCount < maxScheduleUpdateCount; iterationCount++) {
389
- await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
390
- }
391
- await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
392
- } catch (e) {
393
- console.error(e);
394
- } finally {
395
- this._isRunAsyncUpdate = false;
396
- }
397
- }
398
-
399
- /**
400
- * Returns `VisualizeJS`
401
- * {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module} instance.
402
- */
403
- visLib(): any {
404
- return this.visualizeJs;
405
- }
406
-
407
- /**
408
- * Returns `VisualizeJS`
409
- * {@link https://cloud.opendesign.com/docs/index.html#/vis/Viewer | Viewer} instance.
410
- */
411
- visViewer(): any {
412
- return this.visualizeJs?.getViewer();
413
- }
414
-
415
- // update the VisualizeJS options
416
-
417
- syncOpenCloudVisualStyle(isInitializing: boolean): this {
418
- if (!this.visualizeJs) return this;
419
-
420
- const visLib = this.visLib();
421
- const visViewer = visLib.getViewer();
422
-
423
- const device = visViewer.getActiveDevice();
424
- if (device.isNull()) return this;
425
-
426
- const view = device.getActiveView();
427
-
428
- // setup light
429
- view.enableDefaultLighting(true, visLib.DefaultLightingType.kTwoLights);
430
- view.setDefaultLightingIntensity(1.25);
431
-
432
- let visualStyleId;
433
- try {
434
- visualStyleId = visViewer.findVisualStyle("OpenCloud");
435
- } catch (e) {
436
- if (!isInitializing) {
437
- console.log("OpenCloud visual style not found, creating it on client side");
438
- }
439
- visualStyleId = visViewer.createVisualStyle("OpenCloud");
440
-
441
- const colorDef = new visLib.OdTvColorDef(66, 66, 66);
442
- const shadedVsId = visViewer.findVisualStyle("Realistic");
443
-
444
- const visualStylePtr = visualStyleId.openObject();
445
- visualStylePtr.copyFrom(shadedVsId);
446
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kFaceModifiers, 0, visLib.VisualStyleOperations.kSet);
447
- //visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 1, visLib.VisualStyleOperations.kSet);
448
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 2, visLib.VisualStyleOperations.kSet);
449
- visualStylePtr.setOptionDouble(visLib.VisualStyleOptions.kEdgeCreaseAngle, 60, visLib.VisualStyleOperations.kSet);
450
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeStyles, 0, visLib.VisualStyleOperations.kSet);
451
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModifiers, 8, visLib.VisualStyleOperations.kSet);
452
- visualStylePtr.setOptionColor(
453
- visLib.VisualStyleOptions.kEdgeColorValue,
454
- colorDef,
455
- visLib.VisualStyleOperations.kSet
456
- );
457
- visualStylePtr.delete();
458
- }
459
-
460
- view.visualStyle = visualStyleId;
461
-
462
- view.delete();
463
- device.delete();
464
-
465
- return this;
466
- }
467
-
468
- syncOptions(options: OptionsData = this.options.data): this {
469
- if (!this.visualizeJs) return this;
470
-
471
- const visLib = this.visLib();
472
- const visViewer = visLib.getViewer();
473
-
474
- const device = visViewer.getActiveDevice();
475
- if (device.isNull()) return this;
476
-
477
- if (options.showWCS !== visViewer.getEnableWCS()) {
478
- visViewer.setEnableWCS(options.showWCS);
479
- }
480
- if (options.cameraAnimation !== visViewer.getEnableAnimation()) {
481
- visViewer.setEnableAnimation(options.cameraAnimation);
482
- }
483
- if (options.antialiasing !== visViewer.fxaaAntiAliasing3d) {
484
- visViewer.fxaaAntiAliasing3d = options.antialiasing;
485
- visViewer.fxaaQuality = 5;
486
- }
487
-
488
- if (options.shadows !== visViewer.shadows) {
489
- visViewer.shadows = options.shadows;
490
-
491
- const canvas = visLib.canvas;
492
- device.invalidate([0, canvas.clientWidth, canvas.clientHeight, 0]);
493
- }
494
-
495
- if (options.groundShadow !== visViewer.groundShadow) {
496
- visViewer.groundShadow = options.groundShadow;
497
- }
498
-
499
- if (options.ambientOcclusion !== device.getOptionBool(visLib.DeviceOptions.kSSAOEnable)) {
500
- device.setOptionBool(visLib.DeviceOptions.kSSAOEnable, options.ambientOcclusion);
501
- device.setOptionBool(visLib.DeviceOptions.kSSAODynamicRadius, true);
502
- device.setOptionDouble(visLib.DeviceOptions.kSSAORadius, 1);
503
- device.setOptionInt32(visLib.DeviceOptions.kSSAOLoops, 32);
504
- device.setOptionDouble(visLib.DeviceOptions.kSSAOPower, 2);
505
- device.setOptionInt32(visLib.DeviceOptions.kSSAOBlurRadius, 2);
506
-
507
- const activeView = visViewer.activeView;
508
- activeView.setSSAOEnabled(options.ambientOcclusion);
509
- activeView.delete();
510
- }
511
-
512
- if (isExist(options.edgeModel)) {
513
- const activeView = device.getActiveView();
514
-
515
- const visualStyleId = visViewer.findVisualStyle("OpenCloud");
516
- const visualStylePtr = visualStyleId.openObject();
517
-
518
- visualStylePtr.setOptionInt32(
519
- visLib.VisualStyleOptions.kEdgeModel,
520
- options.edgeModel ? 2 : 0,
521
- visLib.VisualStyleOperations.kSet
522
- );
523
-
524
- activeView.visualStyle = visualStyleId;
525
-
526
- visualStylePtr.delete();
527
- visualStyleId.delete();
528
- activeView.delete();
529
- }
530
-
531
- device.delete();
532
-
533
- this.syncHighlightingOptions(options);
534
- this.update();
535
-
536
- return this;
537
- }
538
-
539
- syncHighlightingOptions(options: OptionsData = this.options.data): this {
540
- if (!this.visualizeJs) return this;
541
-
542
- const params = options.enableCustomHighlight ? options : Options.defaults();
543
-
544
- const visLib = this.visLib();
545
- const visViewer = visLib.getViewer();
546
- const { Entry, OdTvRGBColorDef } = visLib;
547
-
548
- const highlightStyleId = visViewer.findHighlightStyle("Web_Default");
549
- const highlightStylePtr = highlightStyleId.openObject();
550
-
551
- if (isExist(params.facesColor)) {
552
- const color = new OdTvRGBColorDef(params.facesColor.r, params.facesColor.g, params.facesColor.b);
553
- highlightStylePtr.setFacesColor(Entry.k3D.value | Entry.k3DTop.value, color);
554
- color.delete();
555
- }
556
-
557
- if (isExist(params.facesOverlap)) {
558
- highlightStylePtr.setFacesVisibility(Entry.k3DTop.value, params.facesOverlap);
559
- }
560
- if (isExist(params.facesTransparancy)) {
561
- highlightStylePtr.setFacesTransparency(Entry.k3D.value | Entry.k3DTop.value, params.facesTransparancy);
562
- }
563
-
564
- if (isExist(params.edgesColor)) {
565
- const color = new OdTvRGBColorDef(params.edgesColor.r, params.edgesColor.g, params.edgesColor.b);
566
- highlightStylePtr.setEdgesColor(
567
- Entry.k3DTop.value | Entry.k3D.value | Entry.k2D.value | Entry.k2DTop.value,
568
- color
569
- );
570
- color.delete();
571
- }
572
-
573
- if (isExist(params.edgesVisibility)) {
574
- highlightStylePtr.setEdgesVisibility(
575
- Entry.k2D.value | Entry.k2DTop.value | Entry.k3DTop.value | Entry.k3D.value,
576
- params.edgesVisibility
577
- );
578
- }
579
- if (isExist(params.edgesOverlap)) {
580
- const visibility = !isExist(params.edgesVisibility) ? true : params.edgesVisibility;
581
- highlightStylePtr.setEdgesVisibility(Entry.k2DTop.value | Entry.k3DTop.value, params.edgesOverlap && visibility);
582
- }
583
-
584
- const device = visViewer.getActiveDevice();
585
- if (!device.isNull()) {
586
- const canvas = visLib.canvas;
587
-
588
- device.invalidate([0, canvas.clientWidth, canvas.clientHeight, 0]);
589
- device.delete();
590
- }
591
-
592
- return this;
593
- }
594
-
595
- /**
596
- * List of names of available draggers:
597
- *
598
- * - `Line`
599
- * - `Text`
600
- * - `Pan`
601
- * - `Orbit`
602
- * - `Zoom`
603
- * - `ZoomWindow`
604
- * - `OrbitAroundBuilding`
605
- * - `MeasureLine`
606
- * - `CuttingPlaneXAxis`
607
- * - `CuttingPlaneYAxis`
608
- * - `CuttingPlaneZAxis`
609
- * - `Walk`
610
- *
611
- * @readonly
612
- */
613
- get draggers(): string[] {
614
- return [...this.draggerFactory.keys()];
615
- }
616
-
617
- /**
618
- * Register dragger on draggerFactory.
619
- *
620
- * @param name - Dragger name.
621
- * @param dragger - Dragger class.
622
- */
623
- public registerDragger(name: string, dragger: typeof OdBaseDragger): void {
624
- this.draggerFactory.set(name, dragger);
625
- }
626
-
627
- /**
628
- * Returns active dragger instance or `null` if there is no active dragger.
629
- */
630
- activeDragger(): any | null {
631
- return this._activeDragger;
632
- }
633
-
634
- /**
635
- * Set active dragger. `Viewer` must be {@link Viewer#initialize | initialized} before enable
636
- * dragger or exception is thrown.
637
- *
638
- * Fires:
639
- *
640
- * - {@link ChangeActiveDragger | changeactivedragger}
641
- *
642
- * @param name - Dragger name. Can be one of the {@link Viewer#draggers | draggers} list.
643
- * @returns Returns active dragger instance or `null` if there is no dragger with the given name.
644
- */
645
- setActiveDragger(name: string): OdBaseDragger | null {
646
- if (this._activeDragger?.name !== name) {
647
- if (this._activeDragger) {
648
- this._activeDragger.dispose();
649
- this._activeDragger = null;
650
- }
651
- const Constructor = this.draggerFactory.get(name);
652
- if (Constructor) {
653
- this._activeDragger = new Constructor(this);
654
- this._activeDragger.name = name;
655
- this._activeDragger.initialize();
656
- }
657
- const canvas = this.canvas;
658
- if (canvas) {
659
- canvas.className = canvas.className
660
- .split(" ")
661
- .filter((x) => !x.startsWith("oda-cursor-"))
662
- .filter((x) => x)
663
- .concat(`oda-cursor-${name.toLowerCase()}`)
664
- .join(" ");
665
- }
666
- this.emitEvent({ type: "changeactivedragger", data: name });
667
- }
668
- return this._activeDragger;
669
- }
670
-
671
- /**
672
- * Reset the state of the active dragger.
673
- */
674
- resetActiveDragger(): void {
675
- const dragger = this._activeDragger;
676
- if (dragger) {
677
- this.setActiveDragger("");
678
- this.setActiveDragger(dragger.name);
679
- }
680
- }
681
-
682
- /**
683
- * Remove all cutting planes.
684
- */
685
- clearSlices(): void {
686
- if (!this.visualizeJs) return;
687
-
688
- const visViewer = this.visViewer();
689
- const activeView = visViewer.activeView;
690
- activeView.removeCuttingPlanes();
691
- activeView.delete();
692
-
693
- this.update();
694
- }
695
-
696
- /**
697
- * Remove markup overlay.
698
- */
699
- clearOverlay(): void {
700
- this.markup.clearOverlay();
701
- }
702
-
703
- /**
704
- * Synchronize markup overlay.
705
- */
706
- syncOverlay(): any {
707
- if (!this.visualizeJs) return;
708
-
709
- const visViewer = this.visViewer();
710
- const activeView = visViewer.activeView;
711
-
712
- let overlayView = visViewer.getViewByName(OVERLAY_VIEW_NAME);
713
- if (!overlayView) {
714
- const overlayModel = visViewer.getMarkupModel();
715
- const pDevice = visViewer.getActiveDevice();
716
-
717
- overlayView = pDevice.createView(OVERLAY_VIEW_NAME, false);
718
- overlayView.addModel(overlayModel);
719
-
720
- activeView.addSibling(overlayView);
721
- pDevice.addView(overlayView);
722
- }
723
-
724
- overlayView.viewPosition = activeView.viewPosition;
725
- overlayView.viewTarget = activeView.viewTarget;
726
- overlayView.upVector = activeView.upVector;
727
- overlayView.viewFieldWidth = activeView.viewFieldWidth;
728
- overlayView.viewFieldHeight = activeView.viewFieldHeight;
729
-
730
- const viewPort = overlayView.getViewport();
731
- overlayView.setViewport(viewPort.lowerLeft, viewPort.upperRight);
732
- overlayView.vportRect = activeView.vportRect;
733
-
734
- this.update();
735
-
736
- return overlayView;
737
- }
738
-
739
- /**
740
- * Returns `true` if current drawing is 3D drawing.
741
- */
742
- is3D(): boolean {
743
- if (!this.visualizeJs) return false;
744
-
745
- const visViewer = this.visViewer();
746
- const ext = visViewer.getActiveExtents();
747
- const min = ext.min();
748
- const max = ext.max();
749
- const extHeight = max[2] - min[2];
750
- return extHeight !== 0;
751
-
752
- //return visViewer.activeView.upVector[1] >= 0.95;
753
- }
754
-
755
- /**
756
- * Returns a list of original handles for the selected entities.
757
- */
758
- getSelected(): string[] {
759
- return this.executeCommand("getSelected");
760
- }
761
-
762
- /**
763
- * Select model entities by original handles that are obtained using
764
- * {@link File.getProperties | File.getProperties()} or
765
- * {@link File.searchProperties | File.searchProperties()} methods.
766
- *
767
- * Fires:
768
- *
769
- * - {@link SelectEvent | select}
770
- *
771
- * @param handles - The list of original handles.
772
- */
773
- setSelected(handles?: string[]): void {
774
- this.executeCommand("setSelected", handles);
775
- }
776
-
777
- /**
778
- * Load model references into the viewer. References are images, fonts, or any other files to
779
- * correct rendering of the model.
780
- *
781
- * @async
782
- * @param model - Instance of model with references. If a `File` instance is specified
783
- * instead of a model, the file references will be loaded.
784
- */
785
- async loadReferences(model: Model | File | Assembly): Promise<this> {
786
- if (!this.visualizeJs) return this;
787
-
788
- const abortController = new AbortController();
789
- this._abortControllerForReferences?.abort();
790
- this._abortControllerForReferences = abortController;
791
-
792
- let references = [];
793
- await model
794
- .getReferences(abortController.signal)
795
- .then((data) => (references = data.references))
796
- .catch((e) => console.error("Cannot load model references.", e));
797
-
798
- for (const file of references) {
799
- await this.client
800
- .downloadFile(file.id, undefined, abortController.signal)
801
- .then((arrayBuffer) => this.visualizeJs?.getViewer().addEmbeddedFile(file.name, new Uint8Array(arrayBuffer)))
802
- .catch((e) => console.error(`Cannot load reference file ${file.name}.`, e));
803
- }
804
-
805
- return this;
806
- }
807
-
808
- // Internal loading routines
809
-
810
- applyModelTransformMatrix(model: Model | Assembly) {
811
- this.executeCommand("applyModelTransform", model);
812
- }
813
-
814
- applySceneGraphSettings(options = this.options) {
815
- if (!this.visualizeJs) return;
816
-
817
- const visLib = this.visLib();
818
- const visViewer = visLib.getViewer();
819
-
820
- const device = visViewer.getActiveDevice();
821
- if (isExist(options.sceneGraph)) {
822
- device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, !options.sceneGraph);
823
- }
824
- // if (options.enablePartialMode && visLib.HpTrc.Usd >= visViewer.memoryLimit) {
825
- // device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, true);
826
- // }
827
- device.delete();
828
-
829
- this.update();
830
- }
831
-
832
- /**
833
- * Loads a model of a file or assembly into the viewer.
834
- *
835
- * This method requires a [Client]{@link Client | Client} instance to work. For standalone
836
- * viewer instance use {@link Viewer#openVsfFile | openVsfFile()} or
837
- * {@link Viewer#openVsfxFile | openVsfxFile()}.
838
- *
839
- * Fires:
840
- *
841
- * - {@link OpenEvent | open}
842
- * - {@link GeometryStartEvent | geometrystart}
843
- * - {@link GeometryProgressEvent | geometryprogress}
844
- * - {@link DatabaseChunkEvent | databasechunk}
845
- * - {@link GeometryChunkEvent | geometrychunk}
846
- * - {@link GeometryEndEvent | geometryend}
847
- * - {@link GeometryErrorEvent | geometryerror}
848
- *
849
- * @async
850
- * @param model - Model instance to load. If a `File` instance with multiple models is
851
- * specified, the default model will be loaded. If there is no default model, first
852
- * availiable model will be loaded.
853
- */
854
- async open(model: Model | File | Assembly): Promise<this> {
855
- if (!this.visualizeJs) return this;
856
-
857
- this.cancel();
858
- this.clear();
859
-
860
- this.emitEvent({ type: "open", model });
861
-
862
- if (model instanceof File || model instanceof Assembly) {
863
- const models = (await model.getModels()) ?? [];
864
- model = models.find((model) => model.default) ?? models[0];
865
- }
866
- if (!model) throw new Error("No default model found");
867
-
868
- await this.loadReferences(model);
869
-
870
- const overrideOptions = new Options();
871
- overrideOptions.data = this.options.data;
872
- if (model.file.type === ".rcs") {
873
- console.log("Partial load mode is forced for RCS file");
874
- overrideOptions.enablePartialMode = true;
875
- }
876
-
877
- const loaderFactory = new LoaderFactory();
878
- const loader = loaderFactory.create(this, model, overrideOptions.data);
879
- await loader.load();
880
-
881
- if (this.visualizeJs) {
882
- this.applyModelTransformMatrix(model);
883
- this.applySceneGraphSettings();
884
- }
885
-
886
- return this;
887
- }
888
-
889
- /**
890
- * Loads a VSF file into the viewer.
891
- *
892
- * Fires:
893
- *
894
- * - {@link OpenEvent | open}
895
- * - {@link GeometryStartEvent | geometrystart}
896
- * - {@link GeometryProgressEvent | geometryprogress}
897
- * - {@link DatabaseChunkEvent | databasechunk}
898
- * - {@link GeometryEndEvent | geometryend}
899
- * - {@link GeometryErrorEvent | geometryerror}
900
- *
901
- * @param buffer - Binary data buffer to load.
902
- */
903
- openVsfFile(buffer: Uint8Array | ArrayBuffer): this {
904
- if (!this.visualizeJs) return this;
905
-
906
- this.cancel();
907
- this.clear();
908
-
909
- this.emitEvent({ type: "open", buffer });
910
-
911
- try {
912
- this.emitEvent({ type: "geometrystart", buffer });
913
-
914
- const visLib = this.visLib();
915
- const visViewer = visLib.getViewer();
916
-
917
- const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
918
- visViewer.parseFile(data);
919
-
920
- this.syncOpenCloudVisualStyle(false);
921
- this.syncOptions();
922
- this.resize();
923
-
924
- this.emitEvent({ type: "geometryprogress", data: 1, buffer });
925
- this.emitEvent({ type: "databasechunk", data, buffer });
926
- this.emitEvent({ type: "geometryend", buffer });
927
- } catch (error) {
928
- this.emitEvent({ type: "geometryerror", data: error, buffer });
929
- throw error;
930
- }
931
-
932
- return this;
933
- }
934
-
935
- /**
936
- * Loads a VSFX file into the viewer.
937
- *
938
- * Fires:
939
- *
940
- * - {@link OpenEvent | open}
941
- * - {@link GeometryStartEvent | geometrystart}
942
- * - {@link GeometryProgressEvent | geometryprogress}
943
- * - {@link DatabaseChunkEvent | databasechunk}
944
- * - {@link GeometryEndEvent | geometryend}
945
- * - {@link GeometryErrorEvent | geometryerror}
946
- *
947
- * @param buffer - Binary data buffer to load.
948
- */
949
- openVsfxFile(buffer: Uint8Array | ArrayBuffer): this {
950
- if (!this.visualizeJs) return this;
951
-
952
- this.cancel();
953
- this.clear();
954
-
955
- this.emitEvent({ type: "open", buffer });
956
-
957
- try {
958
- this.emitEvent({ type: "geometrystart", buffer });
959
-
960
- const visLib = this.visLib();
961
- const visViewer = visLib.getViewer();
962
-
963
- const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
964
- visViewer.parseVsfx(data);
965
-
966
- this.syncOpenCloudVisualStyle(false);
967
- this.syncOptions();
968
- this.resize();
969
-
970
- this.emitEvent({ type: "geometryprogress", data: 1, buffer });
971
- this.emitEvent({ type: "databasechunk", data, buffer });
972
- this.emitEvent({ type: "geometryend", buffer });
973
- } catch (error) {
974
- this.emitEvent({ type: "geometryerror", data: error, buffer });
975
- throw error;
976
- }
977
-
978
- return this;
979
- }
980
-
981
- /**
982
- * Cancels asynchronous model loading started by {@link Viewer#open | open()}.
983
- */
984
- cancel(): this {
985
- this._abortControllerForReferences?.abort();
986
- this._abortControllerForReferences = undefined;
987
-
988
- this._abortController?.abort();
989
- this._abortController = undefined;
990
-
991
- this._abortControllerForRequestMap?.forEach((controller) => controller.abort());
992
- this._abortControllerForRequestMap = undefined;
993
-
994
- this.emitEvent({ type: "cancel" });
995
-
996
- return this;
997
- }
998
-
999
- /**
1000
- * Unloads the model and clears the viewer.
1001
- */
1002
- clear(): this {
1003
- if (!this.visualizeJs) return this;
1004
-
1005
- const visLib = this.visLib();
1006
- const visViewer = visLib.getViewer();
1007
-
1008
- this.clearOverlay();
1009
-
1010
- visViewer.clear();
1011
- visViewer.createLocalDatabase();
1012
-
1013
- this.syncOpenCloudVisualStyle(true);
1014
- this.syncOptions();
1015
- this.resize();
1016
-
1017
- this.emitEvent({ type: "clear" });
1018
-
1019
- return this;
1020
- }
1021
-
1022
- /**
1023
- * Get markup color.
1024
- *
1025
- * @returns Color with `RGB` values.
1026
- */
1027
- getMarkupColor(): { r: number; g: number; b: number } {
1028
- return this.markup.getMarkupColor();
1029
- }
1030
-
1031
- /**
1032
- * Set markup color.
1033
- *
1034
- * @param r - `Red` part of color.
1035
- * @param g - `Green` part of color.
1036
- * @param b - `Blue` part of color.
1037
- */
1038
- setMarkupColor(r = 255, g = 0, b = 0): void {
1039
- this.markup.setMarkupColor(r, g, b);
1040
- const color = { r, g, b };
1041
- this.emitEvent({ type: "changemarkupcolor", data: color });
1042
- }
1043
-
1044
- /**
1045
- * Colorize all markup entities with the specified color.
1046
- *
1047
- * @param r - `Red` part of color.
1048
- * @param g - `Green` part of color.
1049
- * @param b - `Blue` part of color.
1050
- */
1051
- colorizeAllMarkup(r = 255, g = 0, b = 0): void {
1052
- this.markup.colorizeAllMarkup(r, g, b);
1053
- }
1054
-
1055
- /**
1056
- * Add an empty markup entity to the overlay.
1057
- */
1058
- addMarkupEntity(entityName: string) {
1059
- if (!this.visualizeJs) return null;
1060
-
1061
- this.syncOverlay();
1062
-
1063
- const visViewer = this.visViewer();
1064
- const model = visViewer.getMarkupModel();
1065
- const entityId = model.appendEntity(entityName);
1066
- const entityPtr = entityId.openObject();
1067
-
1068
- const color = this.getMarkupColor();
1069
- entityPtr.setColor(color.r, color.g, color.b);
1070
- entityPtr.setLineWeight(2);
1071
- entityPtr.delete();
1072
-
1073
- this.update();
1074
-
1075
- return entityId;
1076
- }
1077
-
1078
- /**
1079
- * Draw a viewpoint. To get a list of available model viewpoints, use the
1080
- * {@link Model#getViewpoints | Model.getViewpoints()} or
1081
- * {@link File#getViewpoints | File.getViewpoints()}.
1082
- *
1083
- * @param viewpoint - Viewpoint.
1084
- */
1085
- drawViewpoint(viewpoint: any): void {
1086
- this.markup.drawViewpoint(viewpoint);
1087
- }
1088
-
1089
- /**
1090
- * Create a viewpoint. To add a viewpoint to the list of model viewpoints, use the
1091
- * {@link Model#saveViewpoint | Model.saveViewpoint()} or
1092
- * {@link File#saveViewpoint | File.saveViewpoint()}.
1093
- */
1094
- createViewpoint(): object {
1095
- const vp = this.markup.createViewpoint();
1096
- return vp;
1097
- }
1098
-
1099
- /**
1100
- * Executes the command denoted by the given command identifier.
1101
- *
1102
- * @param id - Identifier of the command to execute.
1103
- * @param args - Parameters passed to the command function.
1104
- * @returns A returned value of the given command. Returns `undefined` when the command doesn't exists.
1105
- */
1106
- executeCommand(id: string, ...args: any[]): any {
1107
- return commands("VisualizeJS").executeCommand(id, this, ...args);
1108
- }
1109
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2023, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2021 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { IViewer } from "./IViewer";
25
+ import { commands } from "./Commands";
26
+ import { EventEmitter2 } from "./EventEmitter2";
27
+ import { ViewerEventMap } from "./ViewerEvents";
28
+ import { OptionsEventMap, OptionsChangeEvent } from "./OptionsEvents";
29
+ import { CANVAS_EVENTS } from "./CanvasEvents";
30
+
31
+ import { OdBaseDragger } from "./Draggers/Common/OdBaseDragger";
32
+ import { MeasureLineDragger } from "./Draggers/MeasureLineDragger/index";
33
+ import { OdaWalkDragger } from "./Draggers/OdaWalkDragger";
34
+ import { OdCuttingPlaneXAxisDragger } from "./Draggers/OdCuttingPlaneXAxisDragger";
35
+ import { OdCuttingPlaneYAxisDragger } from "./Draggers/OdCuttingPlaneYAxisDragger";
36
+ import { OdCuttingPlaneZAxisDragger } from "./Draggers/OdCuttingPlaneZAxisDragger";
37
+ import { OdOrbitDragger } from "./Draggers/OdOrbitDragger";
38
+ import { OdPanDragger } from "./Draggers/OdPanDragger";
39
+ import { OdZoomDragger } from "./Draggers/OdZoomDragger";
40
+ import { OdZoomWheelDragger } from "./Draggers/OdZoomWheelDragger";
41
+ import { OdZoomWindowDragger } from "./Draggers/OdZoomWindowDragger/index";
42
+ import { OrbitAroundBuildingDragger } from "./Draggers/OrbitAroundBuildingDragger";
43
+ import { GestureManager } from "./Draggers/Common/GestureManager";
44
+
45
+ import { loadVisualizeJs } from "./utils";
46
+
47
+ import { Client } from "../Api/Client";
48
+ import { File } from "../Api/File";
49
+ import { Assembly } from "../Api/Assembly";
50
+ import { Model } from "../Api/Model";
51
+ import { Options, OptionsData } from "./Options";
52
+ import { LoaderFactory } from "./Loaders/LoaderFactory";
53
+ import { MarkupFactory } from "./Markup/MarkupFactory";
54
+ import { IMarkup, MarkupType } from "./Markup/IMarkup";
55
+
56
+ const OVERLAY_VIEW_NAME = "$OVERLAY_VIEW_NAME";
57
+
58
+ const isExist = (value) => value !== undefined && value !== null;
59
+
60
+ /**
61
+ * The `Client.js` library class that provides methods to integrate with the
62
+ * [VisualizeJS](https://cloud.opendesign.com/docs/index.html#/visualizejs) library.
63
+ */
64
+
65
+ export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> implements IViewer {
66
+ private _activeDragger: OdBaseDragger | null;
67
+ private _zoomWheelDragger: OdZoomWheelDragger | null;
68
+ private _gestureManager: GestureManager | null;
69
+ private _enableAutoUpdate: boolean;
70
+ private _isNeedRender: boolean;
71
+ private _isRunAsyncUpdate: boolean;
72
+ private _renderTime: DOMHighResTimeStamp;
73
+
74
+ protected _options: Options;
75
+ protected _visualizeJsUrl: string;
76
+ protected _abortControllerForReferences: AbortController | undefined;
77
+
78
+ private clientoptionschange: (event: OptionsChangeEvent) => void;
79
+ private canvaseventlistener: (event: Event) => void;
80
+
81
+ public draggerFactory: Map<string, typeof OdBaseDragger>;
82
+ public canvasEvents: string[];
83
+ private frameId: number;
84
+ private _resizeObserver: ResizeObserver | undefined;
85
+ public canvas: HTMLCanvasElement | undefined;
86
+ public markup: IMarkup;
87
+
88
+ public visualizeJs: any;
89
+ public _abortController: AbortController | undefined;
90
+ public _abortControllerForRequestMap: Map<string, AbortController> | undefined;
91
+ public client: Client;
92
+
93
+ /**
94
+ * @param client - The `Client` instance that provides access to a server. Do not specify
95
+ * `Client` if you need a standalone viewer instance without access to server models.
96
+ * @param params - An object containing viewer configuration parameters.
97
+ * @param params.visualizeJsUrl - `VisualizeJS` library URL. Set this URL to use your own
98
+ * library instance, or leave it undefined or blank to use the default URL defined by
99
+ * `Client.js` you are using.
100
+ *
101
+ * _Note: Your own `VisualizeJS` library version must match the version of the `Client.js`
102
+ * you are using._
103
+ * @param params.enableAutoUpdate - Enable auto-update of the viewer after any changes. If
104
+ * the auto-update is disabled, you need to update the `VisualizeJS` viewer and the active
105
+ * dragger manually using the `update` event. Default is `true`.
106
+ */
107
+ constructor(
108
+ client?: Client,
109
+ params: { visualizeJsUrl?: string; enableAutoUpdate?: boolean; markupType?: MarkupType } = {
110
+ markupType: MarkupType.Konva,
111
+ }
112
+ ) {
113
+ super();
114
+ this.configure(params);
115
+
116
+ this._options = new Options(this);
117
+
118
+ this.client = client;
119
+ this.clientoptionschange = (event: OptionsChangeEvent) => (this._options.data = event.data.data);
120
+
121
+ this._activeDragger = null;
122
+ this._renderTime = 0;
123
+
124
+ this.markup = MarkupFactory.createMarkup(params.markupType ?? MarkupType.Konva);
125
+
126
+ this.draggerFactory = new Map<string, typeof OdBaseDragger>();
127
+ this.registerDragger("Pan", OdPanDragger);
128
+ this.registerDragger("Orbit", OdOrbitDragger);
129
+ this.registerDragger("Zoom", OdZoomDragger);
130
+ this.registerDragger("ZoomWindow", OdZoomWindowDragger);
131
+ this.registerDragger("OrbitAroundBuilding", OrbitAroundBuildingDragger);
132
+ this.registerDragger("MeasureLine", MeasureLineDragger);
133
+ this.registerDragger("CuttingPlaneXAxis", OdCuttingPlaneXAxisDragger);
134
+ this.registerDragger("CuttingPlaneYAxis", OdCuttingPlaneYAxisDragger);
135
+ this.registerDragger("CuttingPlaneZAxis", OdCuttingPlaneZAxisDragger);
136
+ this.registerDragger("Walk", OdaWalkDragger);
137
+
138
+ const markupDraggers = this.markup.getDraggers();
139
+ markupDraggers?.forEach((value, key) => {
140
+ this.registerDragger(key, value);
141
+ });
142
+
143
+ this.canvasEvents = CANVAS_EVENTS;
144
+ this.canvaseventlistener = (event: Event) => this.emit(event);
145
+
146
+ this._enableAutoUpdate = params.enableAutoUpdate ?? true;
147
+ this._isNeedRender = false;
148
+ this._isRunAsyncUpdate = false;
149
+
150
+ this.render = this.render.bind(this);
151
+ this.resize = this.resize.bind(this);
152
+ }
153
+
154
+ /**
155
+ * `VisualizeJS` parameters.
156
+ *
157
+ * Use this only for standalone viewer instances. Use {@link Client#options | Client.options}
158
+ * instead if the viewer was created with a `Client` reference using
159
+ * {@link Viewer | Viewer.create(client)}. Changes in client options will be automatically
160
+ * applied to the viewer options.
161
+ */
162
+ get options(): Options {
163
+ return this._options;
164
+ }
165
+
166
+ /**
167
+ * `VisualizeJS` library URL. Use {@link Viewer#configure | configure()} to change library URL.
168
+ *
169
+ * @readonly
170
+ */
171
+ get visualizeJsUrl(): string {
172
+ return this._visualizeJsUrl;
173
+ }
174
+
175
+ /**
176
+ * Change the viewer configuration parameters.
177
+ *
178
+ * @param params - An object containing new configuration parameters.
179
+ * @param params.visualizeJsUrl - `VisualizeJS` library URL. Set this URL to use your own
180
+ * library instance or leave it blank to use the default URL defined by `Client.js`.
181
+ */
182
+ configure(params: { visualizeJsUrl?: string }): this {
183
+ this._visualizeJsUrl = params.visualizeJsUrl || "VISUALIZE_JS_URL";
184
+ return this;
185
+ }
186
+
187
+ /**
188
+ * A [Viewer]{@link Viewer} event measuring progress of loading a `VisualizeJS` library.
189
+ *
190
+ * @property {string} type - `visualizeprogress`
191
+ * @property {number} loaded - A 64-bit unsigned integer value indicating the amount of work
192
+ * already performed by the underlying process. The ratio of work done can be calculated by
193
+ * dividing total by the value of this property.
194
+ * @property {number} total - A 64-bit unsigned integer representing the total amount of work
195
+ * that the underlying process is in the progress of performing.
196
+ * @event visualizeprogress
197
+ */
198
+
199
+ /**
200
+ * Load `VisualizeJS` module and initialize it with the specified canvas. Call
201
+ * {@link Viewer#dispose | dispose()} to release allocated resources.
202
+ *
203
+ * @async
204
+ * @param canvas - HTML `<canvas>` element for `VisualizeJS`.
205
+ * @param onProgress - A callback function that handles events measuring progress of loading
206
+ * of the `VisualizeJS` library. Retrieves {@link event:visualizeprogress | visualizeprogress} event.
207
+ */
208
+ async initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent) => void): Promise<this> {
209
+ if (this.client) {
210
+ this.client.addEventListener("optionschange", this.clientoptionschange);
211
+ this.options.data = this.client.options.data;
212
+ }
213
+ this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
214
+
215
+ if (canvas.style.width === "" && canvas.style.height === "") {
216
+ canvas.style.width = "100%";
217
+ canvas.style.height = "100%";
218
+ }
219
+ canvas.style.touchAction = "none";
220
+
221
+ canvas.width = canvas.clientWidth * window.devicePixelRatio;
222
+ canvas.height = canvas.clientHeight * window.devicePixelRatio;
223
+
224
+ const visualizeJs: any = await loadVisualizeJs(this.visualizeJsUrl, (ev) => {
225
+ const { loaded, timeStamp, total, lengthComputable } = ev;
226
+ const event = { loaded, timeStamp, total, lengthComputable, type: "visualizeprogress" } as ProgressEvent;
227
+ onProgress?.(event);
228
+ });
229
+
230
+ this.visualizeJs = visualizeJs;
231
+ this.visualizeJs.canvas = canvas;
232
+ this.visualizeJs.Viewer.create();
233
+
234
+ this.canvas = canvas;
235
+ this.canvasEvents.forEach((x) => canvas.addEventListener(x, this.canvaseventlistener));
236
+
237
+ this.markup.initialize(this, canvas, this.canvasEvents);
238
+
239
+ this._resizeObserver = new ResizeObserver(this.resize);
240
+ this._resizeObserver.observe(canvas.parentElement);
241
+ this.resize();
242
+
243
+ this._zoomWheelDragger = new OdZoomWheelDragger(this);
244
+ this._zoomWheelDragger.name = "ZoomWheel";
245
+ this._zoomWheelDragger.initialize();
246
+
247
+ this._gestureManager = new GestureManager(this);
248
+ this._gestureManager.initialize();
249
+
250
+ this.syncOpenCloudVisualStyle(true);
251
+ this.syncOptions();
252
+
253
+ this._renderTime = performance.now();
254
+ this.render(this._renderTime);
255
+
256
+ return this;
257
+ }
258
+
259
+ /**
260
+ * Releases all resources allocated by this `Viewer` instance. Call this method before
261
+ * release the `Viewer` instance.
262
+ */
263
+ dispose(): this {
264
+ this.cancel();
265
+ this.emitEvent({ type: "dispose" });
266
+
267
+ if (this.frameId) cancelAnimationFrame(this.frameId);
268
+ this.frameId = 0;
269
+
270
+ this.setActiveDragger("");
271
+
272
+ this._zoomWheelDragger?.dispose();
273
+ this._gestureManager?.dispose();
274
+
275
+ this.removeAllListeners();
276
+
277
+ this._resizeObserver?.disconnect();
278
+ this._resizeObserver = undefined;
279
+
280
+ this.markup.dispose();
281
+
282
+ this.canvasEvents.forEach((x) => this.canvas?.removeEventListener(x, this.canvaseventlistener));
283
+ this.canvas = undefined;
284
+
285
+ this.visualizeJs?.getViewer().clear();
286
+ this.visualizeJs = undefined;
287
+
288
+ this.client?.removeEventListener("optionschange", this.clientoptionschange);
289
+
290
+ return this;
291
+ }
292
+
293
+ /**
294
+ * Returns `true` if `VisualizeJS` module has been loaded andinitialized.
295
+ */
296
+ isInitialized(): boolean {
297
+ return !!this.visualizeJs;
298
+ }
299
+
300
+ // internal render/resize routines
301
+
302
+ private render(time: DOMHighResTimeStamp) {
303
+ this.frameId = requestAnimationFrame(this.render);
304
+
305
+ if (!this.visualizeJs) return;
306
+
307
+ if (this._isRunAsyncUpdate) return;
308
+
309
+ const visViewer = this.visualizeJs.getViewer();
310
+ if (visViewer.isRunningAnimation() || this._isNeedRender) {
311
+ visViewer.update();
312
+ this._activeDragger?.updatePreview();
313
+ this._isNeedRender = !visViewer.getActiveDevice().isValid();
314
+
315
+ const deltaTime = (time - this._renderTime) / 1000;
316
+ this._renderTime = time;
317
+ this.emitEvent({ type: "render", time, deltaTime });
318
+ }
319
+ }
320
+
321
+ public resize(): this {
322
+ if (!this.visualizeJs) return this;
323
+
324
+ const { clientWidth, clientHeight } = this.canvas;
325
+ this.canvas.width = clientWidth * window.devicePixelRatio;
326
+ this.canvas.height = clientHeight * window.devicePixelRatio;
327
+
328
+ const visViewer = this.visualizeJs.getViewer();
329
+ visViewer.resize(0, this.canvas.width, this.canvas.height, 0);
330
+
331
+ this.update(true);
332
+ this.emitEvent({ type: "resize", width: clientWidth, height: clientHeight });
333
+
334
+ return this;
335
+ }
336
+
337
+ /**
338
+ * Updates the viewer. Do nothing if the auto-update mode is disabled in the constructor (use
339
+ * the `update` event to update viewer manually).
340
+ *
341
+ * Fires:
342
+ *
343
+ * - {@link UpdateEvent | update}
344
+ *
345
+ * @param force - If `true` updates the viewer immidietly. Otherwise updates on next
346
+ * animation frame. Default is `false`.
347
+ */
348
+ update(force?: boolean) {
349
+ if (this._enableAutoUpdate) {
350
+ if (force) {
351
+ this.visViewer()?.update();
352
+ this.activeDragger()?.updatePreview();
353
+ } else {
354
+ this._isNeedRender = true;
355
+ }
356
+ }
357
+ this.emitEvent({ type: "update", data: force });
358
+ }
359
+
360
+ /**
361
+ * Update with internal schedule, need after change operation when have long update for
362
+ * update without lock UI
363
+ *
364
+ * @param maxScheduleUpdateTimeInMs - Maximum time for one update, by default 30 ms
365
+ * @param maxScheduleUpdateCount - Maximum count of schedule update
366
+ * @returns return void Promise
367
+ */
368
+
369
+ private scheduleUpdateAsync(maxScheduleUpdateTimeInMs = 50): Promise<void> {
370
+ return new Promise<void>((resolve, reject) => {
371
+ setTimeout(() => {
372
+ try {
373
+ this.visViewer()?.update(maxScheduleUpdateTimeInMs);
374
+ this.activeDragger()?.updatePreview();
375
+ resolve();
376
+ } catch (e) {
377
+ console.error(e);
378
+ reject();
379
+ }
380
+ }, 0);
381
+ });
382
+ }
383
+
384
+ async updateAsync(maxScheduleUpdateTimeInMs = 50, maxScheduleUpdateCount = 50): Promise<void> {
385
+ this._isRunAsyncUpdate = true;
386
+ const device = this.visViewer().getActiveDevice();
387
+ try {
388
+ for (let iterationCount = 0; !device.isValid() && iterationCount < maxScheduleUpdateCount; iterationCount++) {
389
+ await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
390
+ }
391
+ await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
392
+ } catch (e) {
393
+ console.error(e);
394
+ } finally {
395
+ this._isRunAsyncUpdate = false;
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Returns `VisualizeJS`
401
+ * {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module} instance.
402
+ */
403
+ visLib(): any {
404
+ return this.visualizeJs;
405
+ }
406
+
407
+ /**
408
+ * Returns `VisualizeJS`
409
+ * {@link https://cloud.opendesign.com/docs/index.html#/vis/Viewer | Viewer} instance.
410
+ */
411
+ visViewer(): any {
412
+ return this.visualizeJs?.getViewer();
413
+ }
414
+
415
+ // update the VisualizeJS options
416
+
417
+ syncOpenCloudVisualStyle(isInitializing: boolean): this {
418
+ if (!this.visualizeJs) return this;
419
+
420
+ const visLib = this.visLib();
421
+ const visViewer = visLib.getViewer();
422
+
423
+ const device = visViewer.getActiveDevice();
424
+ if (device.isNull()) return this;
425
+
426
+ const view = device.getActiveView();
427
+
428
+ // setup light
429
+ view.enableDefaultLighting(true, visLib.DefaultLightingType.kTwoLights);
430
+ view.setDefaultLightingIntensity(1.25);
431
+
432
+ let visualStyleId;
433
+ try {
434
+ visualStyleId = visViewer.findVisualStyle("OpenCloud");
435
+ } catch (e) {
436
+ if (!isInitializing) {
437
+ console.log("OpenCloud visual style not found, creating it on client side");
438
+ }
439
+ visualStyleId = visViewer.createVisualStyle("OpenCloud");
440
+
441
+ const colorDef = new visLib.OdTvColorDef(66, 66, 66);
442
+ const shadedVsId = visViewer.findVisualStyle("Realistic");
443
+
444
+ const visualStylePtr = visualStyleId.openObject();
445
+ visualStylePtr.copyFrom(shadedVsId);
446
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kFaceModifiers, 0, visLib.VisualStyleOperations.kSet);
447
+ //visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 1, visLib.VisualStyleOperations.kSet);
448
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 2, visLib.VisualStyleOperations.kSet);
449
+ visualStylePtr.setOptionDouble(visLib.VisualStyleOptions.kEdgeCreaseAngle, 60, visLib.VisualStyleOperations.kSet);
450
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeStyles, 0, visLib.VisualStyleOperations.kSet);
451
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModifiers, 8, visLib.VisualStyleOperations.kSet);
452
+ visualStylePtr.setOptionColor(
453
+ visLib.VisualStyleOptions.kEdgeColorValue,
454
+ colorDef,
455
+ visLib.VisualStyleOperations.kSet
456
+ );
457
+ visualStylePtr.delete();
458
+ }
459
+
460
+ view.visualStyle = visualStyleId;
461
+
462
+ view.delete();
463
+ device.delete();
464
+
465
+ return this;
466
+ }
467
+
468
+ syncOptions(options: OptionsData = this.options.data): this {
469
+ if (!this.visualizeJs) return this;
470
+
471
+ const visLib = this.visLib();
472
+ const visViewer = visLib.getViewer();
473
+
474
+ const device = visViewer.getActiveDevice();
475
+ if (device.isNull()) return this;
476
+
477
+ if (options.showWCS !== visViewer.getEnableWCS()) {
478
+ visViewer.setEnableWCS(options.showWCS);
479
+ }
480
+ if (options.cameraAnimation !== visViewer.getEnableAnimation()) {
481
+ visViewer.setEnableAnimation(options.cameraAnimation);
482
+ }
483
+ if (options.antialiasing !== visViewer.fxaaAntiAliasing3d) {
484
+ visViewer.fxaaAntiAliasing3d = options.antialiasing;
485
+ visViewer.fxaaQuality = 5;
486
+ }
487
+
488
+ if (options.shadows !== visViewer.shadows) {
489
+ visViewer.shadows = options.shadows;
490
+
491
+ const canvas = visLib.canvas;
492
+ device.invalidate([0, canvas.clientWidth, canvas.clientHeight, 0]);
493
+ }
494
+
495
+ if (options.groundShadow !== visViewer.groundShadow) {
496
+ visViewer.groundShadow = options.groundShadow;
497
+ }
498
+
499
+ if (options.ambientOcclusion !== device.getOptionBool(visLib.DeviceOptions.kSSAOEnable)) {
500
+ device.setOptionBool(visLib.DeviceOptions.kSSAOEnable, options.ambientOcclusion);
501
+ device.setOptionBool(visLib.DeviceOptions.kSSAODynamicRadius, true);
502
+ device.setOptionDouble(visLib.DeviceOptions.kSSAORadius, 1);
503
+ device.setOptionInt32(visLib.DeviceOptions.kSSAOLoops, 32);
504
+ device.setOptionDouble(visLib.DeviceOptions.kSSAOPower, 2);
505
+ device.setOptionInt32(visLib.DeviceOptions.kSSAOBlurRadius, 2);
506
+
507
+ const activeView = visViewer.activeView;
508
+ activeView.setSSAOEnabled(options.ambientOcclusion);
509
+ activeView.delete();
510
+ }
511
+
512
+ if (isExist(options.edgeModel)) {
513
+ const activeView = device.getActiveView();
514
+
515
+ const visualStyleId = visViewer.findVisualStyle("OpenCloud");
516
+ const visualStylePtr = visualStyleId.openObject();
517
+
518
+ visualStylePtr.setOptionInt32(
519
+ visLib.VisualStyleOptions.kEdgeModel,
520
+ options.edgeModel ? 2 : 0,
521
+ visLib.VisualStyleOperations.kSet
522
+ );
523
+
524
+ activeView.visualStyle = visualStyleId;
525
+
526
+ visualStylePtr.delete();
527
+ visualStyleId.delete();
528
+ activeView.delete();
529
+ }
530
+
531
+ device.delete();
532
+
533
+ this.syncHighlightingOptions(options);
534
+ this.update();
535
+
536
+ return this;
537
+ }
538
+
539
+ syncHighlightingOptions(options: OptionsData = this.options.data): this {
540
+ if (!this.visualizeJs) return this;
541
+
542
+ const params = options.enableCustomHighlight ? options : Options.defaults();
543
+
544
+ const visLib = this.visLib();
545
+ const visViewer = visLib.getViewer();
546
+ const { Entry, OdTvRGBColorDef } = visLib;
547
+
548
+ const highlightStyleId = visViewer.findHighlightStyle("Web_Default");
549
+ const highlightStylePtr = highlightStyleId.openObject();
550
+
551
+ if (isExist(params.facesColor)) {
552
+ const color = new OdTvRGBColorDef(params.facesColor.r, params.facesColor.g, params.facesColor.b);
553
+ highlightStylePtr.setFacesColor(Entry.k3D.value | Entry.k3DTop.value, color);
554
+ color.delete();
555
+ }
556
+
557
+ if (isExist(params.facesOverlap)) {
558
+ highlightStylePtr.setFacesVisibility(Entry.k3DTop.value, params.facesOverlap);
559
+ }
560
+ if (isExist(params.facesTransparancy)) {
561
+ highlightStylePtr.setFacesTransparency(Entry.k3D.value | Entry.k3DTop.value, params.facesTransparancy);
562
+ }
563
+
564
+ if (isExist(params.edgesColor)) {
565
+ const color = new OdTvRGBColorDef(params.edgesColor.r, params.edgesColor.g, params.edgesColor.b);
566
+ highlightStylePtr.setEdgesColor(
567
+ Entry.k3DTop.value | Entry.k3D.value | Entry.k2D.value | Entry.k2DTop.value,
568
+ color
569
+ );
570
+ color.delete();
571
+ }
572
+
573
+ if (isExist(params.edgesVisibility)) {
574
+ highlightStylePtr.setEdgesVisibility(
575
+ Entry.k2D.value | Entry.k2DTop.value | Entry.k3DTop.value | Entry.k3D.value,
576
+ params.edgesVisibility
577
+ );
578
+ }
579
+ if (isExist(params.edgesOverlap)) {
580
+ const visibility = !isExist(params.edgesVisibility) ? true : params.edgesVisibility;
581
+ highlightStylePtr.setEdgesVisibility(Entry.k2DTop.value | Entry.k3DTop.value, params.edgesOverlap && visibility);
582
+ }
583
+
584
+ const device = visViewer.getActiveDevice();
585
+ if (!device.isNull()) {
586
+ const canvas = visLib.canvas;
587
+
588
+ device.invalidate([0, canvas.clientWidth, canvas.clientHeight, 0]);
589
+ device.delete();
590
+ }
591
+
592
+ return this;
593
+ }
594
+
595
+ /**
596
+ * List of names of available draggers:
597
+ *
598
+ * - `Line`
599
+ * - `Text`
600
+ * - `Pan`
601
+ * - `Orbit`
602
+ * - `Zoom`
603
+ * - `ZoomWindow`
604
+ * - `OrbitAroundBuilding`
605
+ * - `MeasureLine`
606
+ * - `CuttingPlaneXAxis`
607
+ * - `CuttingPlaneYAxis`
608
+ * - `CuttingPlaneZAxis`
609
+ * - `Walk`
610
+ *
611
+ * @readonly
612
+ */
613
+ get draggers(): string[] {
614
+ return [...this.draggerFactory.keys()];
615
+ }
616
+
617
+ /**
618
+ * Register dragger on draggerFactory.
619
+ *
620
+ * @param name - Dragger name.
621
+ * @param dragger - Dragger class.
622
+ */
623
+ public registerDragger(name: string, dragger: typeof OdBaseDragger): void {
624
+ this.draggerFactory.set(name, dragger);
625
+ }
626
+
627
+ /**
628
+ * Returns active dragger instance or `null` if there is no active dragger.
629
+ */
630
+ activeDragger(): any | null {
631
+ return this._activeDragger;
632
+ }
633
+
634
+ /**
635
+ * Set active dragger. `Viewer` must be {@link Viewer#initialize | initialized} before enable
636
+ * dragger or exception is thrown.
637
+ *
638
+ * Fires:
639
+ *
640
+ * - {@link ChangeActiveDragger | changeactivedragger}
641
+ *
642
+ * @param name - Dragger name. Can be one of the {@link Viewer#draggers | draggers} list.
643
+ * @returns Returns active dragger instance or `null` if there is no dragger with the given name.
644
+ */
645
+ setActiveDragger(name: string): OdBaseDragger | null {
646
+ if (this._activeDragger?.name !== name) {
647
+ if (this._activeDragger) {
648
+ this._activeDragger.dispose();
649
+ this._activeDragger = null;
650
+ }
651
+ const Constructor = this.draggerFactory.get(name);
652
+ if (Constructor) {
653
+ this._activeDragger = new Constructor(this);
654
+ this._activeDragger.name = name;
655
+ this._activeDragger.initialize();
656
+ }
657
+ const canvas = this.canvas;
658
+ if (canvas) {
659
+ canvas.className = canvas.className
660
+ .split(" ")
661
+ .filter((x) => !x.startsWith("oda-cursor-"))
662
+ .filter((x) => x)
663
+ .concat(`oda-cursor-${name.toLowerCase()}`)
664
+ .join(" ");
665
+ }
666
+ this.emitEvent({ type: "changeactivedragger", data: name });
667
+ }
668
+ return this._activeDragger;
669
+ }
670
+
671
+ /**
672
+ * Reset the state of the active dragger.
673
+ */
674
+ resetActiveDragger(): void {
675
+ const dragger = this._activeDragger;
676
+ if (dragger) {
677
+ this.setActiveDragger("");
678
+ this.setActiveDragger(dragger.name);
679
+ }
680
+ }
681
+
682
+ /**
683
+ * Remove all cutting planes.
684
+ */
685
+ clearSlices(): void {
686
+ if (!this.visualizeJs) return;
687
+
688
+ const visViewer = this.visViewer();
689
+ const activeView = visViewer.activeView;
690
+ activeView.removeCuttingPlanes();
691
+ activeView.delete();
692
+
693
+ this.update();
694
+ }
695
+
696
+ /**
697
+ * Remove markup overlay.
698
+ */
699
+ clearOverlay(): void {
700
+ this.markup.clearOverlay();
701
+ }
702
+
703
+ /**
704
+ * Synchronize markup overlay.
705
+ */
706
+ syncOverlay(): any {
707
+ if (!this.visualizeJs) return;
708
+
709
+ const visViewer = this.visViewer();
710
+ const activeView = visViewer.activeView;
711
+
712
+ let overlayView = visViewer.getViewByName(OVERLAY_VIEW_NAME);
713
+ if (!overlayView) {
714
+ const overlayModel = visViewer.getMarkupModel();
715
+ const pDevice = visViewer.getActiveDevice();
716
+
717
+ overlayView = pDevice.createView(OVERLAY_VIEW_NAME, false);
718
+ overlayView.addModel(overlayModel);
719
+
720
+ activeView.addSibling(overlayView);
721
+ pDevice.addView(overlayView);
722
+ }
723
+
724
+ overlayView.viewPosition = activeView.viewPosition;
725
+ overlayView.viewTarget = activeView.viewTarget;
726
+ overlayView.upVector = activeView.upVector;
727
+ overlayView.viewFieldWidth = activeView.viewFieldWidth;
728
+ overlayView.viewFieldHeight = activeView.viewFieldHeight;
729
+
730
+ const viewPort = overlayView.getViewport();
731
+ overlayView.setViewport(viewPort.lowerLeft, viewPort.upperRight);
732
+ overlayView.vportRect = activeView.vportRect;
733
+
734
+ this.update();
735
+
736
+ return overlayView;
737
+ }
738
+
739
+ /**
740
+ * Returns `true` if current drawing is 3D drawing.
741
+ */
742
+ is3D(): boolean {
743
+ if (!this.visualizeJs) return false;
744
+
745
+ const visViewer = this.visViewer();
746
+ const ext = visViewer.getActiveExtents();
747
+ const min = ext.min();
748
+ const max = ext.max();
749
+ const extHeight = max[2] - min[2];
750
+ return extHeight !== 0;
751
+
752
+ //return visViewer.activeView.upVector[1] >= 0.95;
753
+ }
754
+
755
+ /**
756
+ * Returns a list of original handles for the selected entities.
757
+ */
758
+ getSelected(): string[] {
759
+ return this.executeCommand("getSelected");
760
+ }
761
+
762
+ /**
763
+ * Select model entities by original handles that are obtained using
764
+ * {@link File.getProperties | File.getProperties()} or
765
+ * {@link File.searchProperties | File.searchProperties()} methods.
766
+ *
767
+ * Fires:
768
+ *
769
+ * - {@link SelectEvent | select}
770
+ *
771
+ * @param handles - The list of original handles.
772
+ */
773
+ setSelected(handles?: string[]): void {
774
+ this.executeCommand("setSelected", handles);
775
+ }
776
+
777
+ /**
778
+ * Load model references into the viewer. References are images, fonts, or any other files to
779
+ * correct rendering of the model.
780
+ *
781
+ * @async
782
+ * @param model - Instance of model with references. If a `File` instance is specified
783
+ * instead of a model, the file references will be loaded.
784
+ */
785
+ async loadReferences(model: Model | File | Assembly): Promise<this> {
786
+ if (!this.visualizeJs) return this;
787
+
788
+ const abortController = new AbortController();
789
+ this._abortControllerForReferences?.abort();
790
+ this._abortControllerForReferences = abortController;
791
+
792
+ let references = [];
793
+ await model
794
+ .getReferences(abortController.signal)
795
+ .then((data) => (references = data.references))
796
+ .catch((e) => console.error("Cannot load model references.", e));
797
+
798
+ for (const file of references) {
799
+ await this.client
800
+ .downloadFile(file.id, undefined, abortController.signal)
801
+ .then((arrayBuffer) => this.visualizeJs?.getViewer().addEmbeddedFile(file.name, new Uint8Array(arrayBuffer)))
802
+ .catch((e) => console.error(`Cannot load reference file ${file.name}.`, e));
803
+ }
804
+
805
+ return this;
806
+ }
807
+
808
+ // Internal loading routines
809
+
810
+ applyModelTransformMatrix(model: Model | Assembly) {
811
+ this.executeCommand("applyModelTransform", model);
812
+ }
813
+
814
+ applySceneGraphSettings(options = this.options) {
815
+ if (!this.visualizeJs) return;
816
+
817
+ const visLib = this.visLib();
818
+ const visViewer = visLib.getViewer();
819
+
820
+ const device = visViewer.getActiveDevice();
821
+ if (isExist(options.sceneGraph)) {
822
+ device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, !options.sceneGraph);
823
+ }
824
+ // if (options.enablePartialMode && visLib.HpTrc.Usd >= visViewer.memoryLimit) {
825
+ // device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, true);
826
+ // }
827
+ device.delete();
828
+
829
+ this.update();
830
+ }
831
+
832
+ /**
833
+ * Loads a model of a file or assembly into the viewer.
834
+ *
835
+ * This method requires a [Client]{@link Client | Client} instance to work. For standalone
836
+ * viewer instance use {@link Viewer#openVsfFile | openVsfFile()} or
837
+ * {@link Viewer#openVsfxFile | openVsfxFile()}.
838
+ *
839
+ * Fires:
840
+ *
841
+ * - {@link OpenEvent | open}
842
+ * - {@link GeometryStartEvent | geometrystart}
843
+ * - {@link GeometryProgressEvent | geometryprogress}
844
+ * - {@link DatabaseChunkEvent | databasechunk}
845
+ * - {@link GeometryChunkEvent | geometrychunk}
846
+ * - {@link GeometryEndEvent | geometryend}
847
+ * - {@link GeometryErrorEvent | geometryerror}
848
+ *
849
+ * @async
850
+ * @param model - Model instance to load. If a `File` instance with multiple models is
851
+ * specified, the default model will be loaded. If there is no default model, first
852
+ * availiable model will be loaded.
853
+ */
854
+ async open(model: Model | File | Assembly): Promise<this> {
855
+ if (!this.visualizeJs) return this;
856
+
857
+ this.cancel();
858
+ this.clear();
859
+
860
+ this.emitEvent({ type: "open", model });
861
+
862
+ if (model instanceof File || model instanceof Assembly) {
863
+ const models = (await model.getModels()) ?? [];
864
+ model = models.find((model) => model.default) ?? models[0];
865
+ }
866
+ if (!model) throw new Error("No default model found");
867
+
868
+ await this.loadReferences(model);
869
+
870
+ const overrideOptions = new Options();
871
+ overrideOptions.data = this.options.data;
872
+ if (model.file.type === ".rcs") {
873
+ console.log("Partial load mode is forced for RCS file");
874
+ overrideOptions.enablePartialMode = true;
875
+ }
876
+
877
+ const loaderFactory = new LoaderFactory();
878
+ const loader = loaderFactory.create(this, model, overrideOptions.data);
879
+ await loader.load();
880
+
881
+ if (this.visualizeJs) {
882
+ this.applyModelTransformMatrix(model);
883
+ this.applySceneGraphSettings();
884
+ }
885
+
886
+ return this;
887
+ }
888
+
889
+ /**
890
+ * Loads a VSF file into the viewer.
891
+ *
892
+ * Fires:
893
+ *
894
+ * - {@link OpenEvent | open}
895
+ * - {@link GeometryStartEvent | geometrystart}
896
+ * - {@link GeometryProgressEvent | geometryprogress}
897
+ * - {@link DatabaseChunkEvent | databasechunk}
898
+ * - {@link GeometryEndEvent | geometryend}
899
+ * - {@link GeometryErrorEvent | geometryerror}
900
+ *
901
+ * @param buffer - Binary data buffer to load.
902
+ */
903
+ openVsfFile(buffer: Uint8Array | ArrayBuffer): this {
904
+ if (!this.visualizeJs) return this;
905
+
906
+ this.cancel();
907
+ this.clear();
908
+
909
+ this.emitEvent({ type: "open", buffer });
910
+
911
+ try {
912
+ this.emitEvent({ type: "geometrystart", buffer });
913
+
914
+ const visLib = this.visLib();
915
+ const visViewer = visLib.getViewer();
916
+
917
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
918
+ visViewer.parseFile(data);
919
+
920
+ this.syncOpenCloudVisualStyle(false);
921
+ this.syncOptions();
922
+ this.resize();
923
+
924
+ this.emitEvent({ type: "geometryprogress", data: 1, buffer });
925
+ this.emitEvent({ type: "databasechunk", data, buffer });
926
+ this.emitEvent({ type: "geometryend", buffer });
927
+ } catch (error) {
928
+ this.emitEvent({ type: "geometryerror", data: error, buffer });
929
+ throw error;
930
+ }
931
+
932
+ return this;
933
+ }
934
+
935
+ /**
936
+ * Loads a VSFX file into the viewer.
937
+ *
938
+ * Fires:
939
+ *
940
+ * - {@link OpenEvent | open}
941
+ * - {@link GeometryStartEvent | geometrystart}
942
+ * - {@link GeometryProgressEvent | geometryprogress}
943
+ * - {@link DatabaseChunkEvent | databasechunk}
944
+ * - {@link GeometryEndEvent | geometryend}
945
+ * - {@link GeometryErrorEvent | geometryerror}
946
+ *
947
+ * @param buffer - Binary data buffer to load.
948
+ */
949
+ openVsfxFile(buffer: Uint8Array | ArrayBuffer): this {
950
+ if (!this.visualizeJs) return this;
951
+
952
+ this.cancel();
953
+ this.clear();
954
+
955
+ this.emitEvent({ type: "open", buffer });
956
+
957
+ try {
958
+ this.emitEvent({ type: "geometrystart", buffer });
959
+
960
+ const visLib = this.visLib();
961
+ const visViewer = visLib.getViewer();
962
+
963
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
964
+ visViewer.parseVsfx(data);
965
+
966
+ this.syncOpenCloudVisualStyle(false);
967
+ this.syncOptions();
968
+ this.resize();
969
+
970
+ this.emitEvent({ type: "geometryprogress", data: 1, buffer });
971
+ this.emitEvent({ type: "databasechunk", data, buffer });
972
+ this.emitEvent({ type: "geometryend", buffer });
973
+ } catch (error) {
974
+ this.emitEvent({ type: "geometryerror", data: error, buffer });
975
+ throw error;
976
+ }
977
+
978
+ return this;
979
+ }
980
+
981
+ /**
982
+ * Cancels asynchronous model loading started by {@link Viewer#open | open()}.
983
+ */
984
+ cancel(): this {
985
+ this._abortControllerForReferences?.abort();
986
+ this._abortControllerForReferences = undefined;
987
+
988
+ this._abortController?.abort();
989
+ this._abortController = undefined;
990
+
991
+ this._abortControllerForRequestMap?.forEach((controller) => controller.abort());
992
+ this._abortControllerForRequestMap = undefined;
993
+
994
+ this.emitEvent({ type: "cancel" });
995
+
996
+ return this;
997
+ }
998
+
999
+ /**
1000
+ * Unloads the model and clears the viewer.
1001
+ */
1002
+ clear(): this {
1003
+ if (!this.visualizeJs) return this;
1004
+
1005
+ const visLib = this.visLib();
1006
+ const visViewer = visLib.getViewer();
1007
+
1008
+ this.clearOverlay();
1009
+
1010
+ visViewer.clear();
1011
+ visViewer.createLocalDatabase();
1012
+
1013
+ this.syncOpenCloudVisualStyle(true);
1014
+ this.syncOptions();
1015
+ this.resize();
1016
+
1017
+ this.emitEvent({ type: "clear" });
1018
+
1019
+ return this;
1020
+ }
1021
+
1022
+ /**
1023
+ * Get markup color.
1024
+ *
1025
+ * @returns Color with `RGB` values.
1026
+ */
1027
+ getMarkupColor(): { r: number; g: number; b: number } {
1028
+ return this.markup.getMarkupColor();
1029
+ }
1030
+
1031
+ /**
1032
+ * Set markup color.
1033
+ *
1034
+ * @param r - `Red` part of color.
1035
+ * @param g - `Green` part of color.
1036
+ * @param b - `Blue` part of color.
1037
+ */
1038
+ setMarkupColor(r = 255, g = 0, b = 0): void {
1039
+ this.markup.setMarkupColor(r, g, b);
1040
+ const color = { r, g, b };
1041
+ this.emitEvent({ type: "changemarkupcolor", data: color });
1042
+ }
1043
+
1044
+ /**
1045
+ * Colorize all markup entities with the specified color.
1046
+ *
1047
+ * @param r - `Red` part of color.
1048
+ * @param g - `Green` part of color.
1049
+ * @param b - `Blue` part of color.
1050
+ */
1051
+ colorizeAllMarkup(r = 255, g = 0, b = 0): void {
1052
+ this.markup.colorizeAllMarkup(r, g, b);
1053
+ }
1054
+
1055
+ /**
1056
+ * Add an empty markup entity to the overlay.
1057
+ */
1058
+ addMarkupEntity(entityName: string) {
1059
+ if (!this.visualizeJs) return null;
1060
+
1061
+ this.syncOverlay();
1062
+
1063
+ const visViewer = this.visViewer();
1064
+ const model = visViewer.getMarkupModel();
1065
+ const entityId = model.appendEntity(entityName);
1066
+ const entityPtr = entityId.openObject();
1067
+
1068
+ const color = this.getMarkupColor();
1069
+ entityPtr.setColor(color.r, color.g, color.b);
1070
+ entityPtr.setLineWeight(2);
1071
+ entityPtr.delete();
1072
+
1073
+ this.update();
1074
+
1075
+ return entityId;
1076
+ }
1077
+
1078
+ /**
1079
+ * Draw a viewpoint. To get a list of available model viewpoints, use the
1080
+ * {@link Model#getViewpoints | Model.getViewpoints()} or
1081
+ * {@link File#getViewpoints | File.getViewpoints()}.
1082
+ *
1083
+ * @param viewpoint - Viewpoint.
1084
+ */
1085
+ drawViewpoint(viewpoint: any): void {
1086
+ this.markup.drawViewpoint(viewpoint);
1087
+ }
1088
+
1089
+ /**
1090
+ * Create a viewpoint. To add a viewpoint to the list of model viewpoints, use the
1091
+ * {@link Model#saveViewpoint | Model.saveViewpoint()} or
1092
+ * {@link File#saveViewpoint | File.saveViewpoint()}.
1093
+ */
1094
+ createViewpoint(): object {
1095
+ const vp = this.markup.createViewpoint();
1096
+ return vp;
1097
+ }
1098
+
1099
+ /**
1100
+ * Executes the command denoted by the given command identifier.
1101
+ *
1102
+ * @param id - Identifier of the command to execute.
1103
+ * @param args - Parameters passed to the command function.
1104
+ * @returns A returned value of the given command. Returns `undefined` when the command doesn't exists.
1105
+ */
1106
+ executeCommand(id: string, ...args: any[]): any {
1107
+ return commands("VisualizeJS").executeCommand(id, this, ...args);
1108
+ }
1109
+ }