aurea-eden 1.25.11 → 1.26.0
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/dist/bpmn-diagram.es.js +1178 -1184
- package/dist/bpmn-diagram.umd.js +1 -1
- package/package.json +12 -7
package/dist/bpmn-diagram.es.js
CHANGED
|
@@ -40288,569 +40288,6 @@ class RenderOutputNode extends TempNode {
|
|
|
40288
40288
|
}
|
|
40289
40289
|
const renderOutput = (color2, toneMapping2 = null, outputColorSpace = null) => nodeObject(new RenderOutputNode(nodeObject(color2), toneMapping2, outputColorSpace));
|
|
40290
40290
|
addMethodChaining("renderOutput", renderOutput);
|
|
40291
|
-
class Diagram {
|
|
40292
|
-
/**
|
|
40293
|
-
* Creates a new Diagram instance.
|
|
40294
|
-
* @param {HTMLElement} container - The HTML container element for the diagram.
|
|
40295
|
-
*/
|
|
40296
|
-
constructor(container) {
|
|
40297
|
-
this.elements = [];
|
|
40298
|
-
this.connectors = [];
|
|
40299
|
-
this.mode = "VIEW";
|
|
40300
|
-
this.helpers = false;
|
|
40301
|
-
this.container = container;
|
|
40302
|
-
this.initScene();
|
|
40303
|
-
this.initCamera();
|
|
40304
|
-
this.setHelpers();
|
|
40305
|
-
this.initRenderer();
|
|
40306
|
-
this.initLighting();
|
|
40307
|
-
this.initControls();
|
|
40308
|
-
this.addEventListeners();
|
|
40309
|
-
this.animate();
|
|
40310
|
-
console.log("THREE", THREE);
|
|
40311
|
-
console.log(this);
|
|
40312
|
-
}
|
|
40313
|
-
/**
|
|
40314
|
-
* Initializes the THREE.js scene.
|
|
40315
|
-
*/
|
|
40316
|
-
initScene() {
|
|
40317
|
-
this.scene = new Scene();
|
|
40318
|
-
this.scene.background = new Color$1(15790320);
|
|
40319
|
-
}
|
|
40320
|
-
/**
|
|
40321
|
-
* Initializes the camera with a perspective projection.
|
|
40322
|
-
*/
|
|
40323
|
-
initCamera() {
|
|
40324
|
-
const aspectRatio = window.innerWidth / window.innerHeight;
|
|
40325
|
-
this.camera = new PerspectiveCamera(75, aspectRatio, 0.1, 2e3);
|
|
40326
|
-
this.camera.position.set(0, 0, 500);
|
|
40327
|
-
this.camera.updateProjectionMatrix();
|
|
40328
|
-
}
|
|
40329
|
-
// initCamera() { // Orthographic
|
|
40330
|
-
// // const aspectRatio = this.container.clientWidth / window.innerHeight;
|
|
40331
|
-
// const aspectRatio = window.innerWidth / window.innerHeight;
|
|
40332
|
-
// const frustumSize = 100;
|
|
40333
|
-
// this.camera = new THREE.OrthographicCamera(
|
|
40334
|
-
// frustumSize * aspectRatio / -2,
|
|
40335
|
-
// frustumSize * aspectRatio / 2,
|
|
40336
|
-
// frustumSize / 2,
|
|
40337
|
-
// frustumSize / -2,
|
|
40338
|
-
// 0.1,
|
|
40339
|
-
// 1000
|
|
40340
|
-
// );
|
|
40341
|
-
// this.camera.position.set(0, 0, 50);
|
|
40342
|
-
// }
|
|
40343
|
-
/**
|
|
40344
|
-
* Sets up helpers (axes, grid, etc.) for the scene.
|
|
40345
|
-
*/
|
|
40346
|
-
setHelpers() {
|
|
40347
|
-
this.axesHelper = new AxesHelper(100);
|
|
40348
|
-
this.cameraHelper = new CameraHelper(this.camera);
|
|
40349
|
-
const size = 400;
|
|
40350
|
-
const divisions = 50;
|
|
40351
|
-
this.gridHelper = new GridHelper(size, divisions);
|
|
40352
|
-
this.cameraDirection = new Vector3$1();
|
|
40353
|
-
this.camPositionSpan = document.querySelector("#position");
|
|
40354
|
-
this.camLookAtSpan = document.querySelector("#lookingAt");
|
|
40355
|
-
this.helpers = false;
|
|
40356
|
-
}
|
|
40357
|
-
/**
|
|
40358
|
-
* Shows the helpers in the scene.
|
|
40359
|
-
*/
|
|
40360
|
-
showHelpers() {
|
|
40361
|
-
if (!this.helpers) {
|
|
40362
|
-
this.scene.add(this.axesHelper);
|
|
40363
|
-
this.scene.add(this.cameraHelper);
|
|
40364
|
-
this.scene.add(this.gridHelper);
|
|
40365
|
-
this.helpers = true;
|
|
40366
|
-
}
|
|
40367
|
-
}
|
|
40368
|
-
/**
|
|
40369
|
-
* Hides the helpers in the scene.
|
|
40370
|
-
*/
|
|
40371
|
-
hideHelpers() {
|
|
40372
|
-
if (this.helpers) {
|
|
40373
|
-
this.scene.remove(this.axesHelper);
|
|
40374
|
-
this.scene.remove(this.cameraHelper);
|
|
40375
|
-
this.scene.remove(this.gridHelper);
|
|
40376
|
-
this.helpers = false;
|
|
40377
|
-
}
|
|
40378
|
-
}
|
|
40379
|
-
/**
|
|
40380
|
-
* Initializes the renderer and attaches it to the container.
|
|
40381
|
-
*/
|
|
40382
|
-
initRenderer() {
|
|
40383
|
-
this.renderer = new WebGLRenderer({ antialias: true });
|
|
40384
|
-
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
40385
|
-
document.body.appendChild(this.renderer.domElement);
|
|
40386
|
-
console.log("initRenderer", this.container, this.renderer.domElement);
|
|
40387
|
-
}
|
|
40388
|
-
/**
|
|
40389
|
-
* Initializes the lighting for the scene.
|
|
40390
|
-
*/
|
|
40391
|
-
initLighting() {
|
|
40392
|
-
let mainLightColor = 16777215;
|
|
40393
|
-
let mainLightIntensity = 4;
|
|
40394
|
-
let mainLightDistance = 0;
|
|
40395
|
-
let mainLightDecay = 0;
|
|
40396
|
-
const mainLight = new PointLight(mainLightColor, mainLightIntensity, mainLightDistance, mainLightDecay);
|
|
40397
|
-
let mainLightPosX = -1 * (580 / 2) + 1 / 3 * 580;
|
|
40398
|
-
let mainLightPosY = -1 * 209 * 4;
|
|
40399
|
-
let mainLightPosZ = Math.abs(mainLightPosY);
|
|
40400
|
-
mainLight.position.set(mainLightPosX, mainLightPosY, mainLightPosZ);
|
|
40401
|
-
this.scene.add(mainLight);
|
|
40402
|
-
this.spotLight = new PointLight(16777215, 4, 0, 0);
|
|
40403
|
-
this.spotLightPosX = 0;
|
|
40404
|
-
this.spotLightPosY = -1 * 209 - 300;
|
|
40405
|
-
this.spotLightPosZ = 70;
|
|
40406
|
-
this.scene.add(this.spotLight);
|
|
40407
|
-
this.spotLightDirection = 1;
|
|
40408
|
-
}
|
|
40409
|
-
/**
|
|
40410
|
-
* Initializes the controls for the camera.
|
|
40411
|
-
*/
|
|
40412
|
-
initControls() {
|
|
40413
|
-
this.controls = new MapControls(this.camera, this.renderer.domElement);
|
|
40414
|
-
this.controls.enableDamping = true;
|
|
40415
|
-
this.controls.dampingFactor = 0.1;
|
|
40416
|
-
this.controls.screenSpacePanning = true;
|
|
40417
|
-
this.controls.zoomToCursor = true;
|
|
40418
|
-
this.controls.saveState();
|
|
40419
|
-
}
|
|
40420
|
-
/**
|
|
40421
|
-
* Adds event listeners for window resize and other interactions.
|
|
40422
|
-
*/
|
|
40423
|
-
addEventListeners() {
|
|
40424
|
-
window.addEventListener("resize", this.onWindowResize.bind(this), false);
|
|
40425
|
-
}
|
|
40426
|
-
// onDocumentMouseDown(event) {
|
|
40427
|
-
// this.isDragging = true;
|
|
40428
|
-
// this.previousMousePosition = { x: event.offsetX, y: event.offsetY };
|
|
40429
|
-
// }
|
|
40430
|
-
// onDocumentMouseMove(event) {
|
|
40431
|
-
// if (this.isDragging && this.mugGroup) {
|
|
40432
|
-
// const deltaMove = {
|
|
40433
|
-
// x: event.offsetX - this.previousMousePosition.x,
|
|
40434
|
-
// y: event.offsetY - this.previousMousePosition.y
|
|
40435
|
-
// };
|
|
40436
|
-
// let rotateAngleX = this.toRadians(deltaMove.y * 1);
|
|
40437
|
-
// let rotateAngleY = this.toRadians(deltaMove.x * 1);
|
|
40438
|
-
// this.currentRotation = this.currentRotation || { x: 0, y: 0 };
|
|
40439
|
-
// this.currentRotation.x += rotateAngleX;
|
|
40440
|
-
// this.currentRotation.y += rotateAngleY;
|
|
40441
|
-
// const maxRotation = Math.PI / 2;
|
|
40442
|
-
// this.currentRotation.x = Math.min(Math.max(this.currentRotation.x, -maxRotation), maxRotation);
|
|
40443
|
-
// this.pivotGroup.rotation.x = this.currentRotation.x;
|
|
40444
|
-
// this.pivotGroup.rotation.y = this.currentRotation.y;
|
|
40445
|
-
// this.previousMousePosition = { x: event.offsetX, y: event.offsetY };
|
|
40446
|
-
// }
|
|
40447
|
-
// }
|
|
40448
|
-
// onDocumentMouseUp() {
|
|
40449
|
-
// this.isDragging = false;
|
|
40450
|
-
// }
|
|
40451
|
-
// toRadians(angle) {
|
|
40452
|
-
// return angle * (Math.PI / 180);
|
|
40453
|
-
// }
|
|
40454
|
-
/**
|
|
40455
|
-
* Handles window resize events to update the camera and renderer.
|
|
40456
|
-
*/
|
|
40457
|
-
onWindowResize() {
|
|
40458
|
-
this.camera.aspect = window.innerWidth / window.innerHeight;
|
|
40459
|
-
this.camera.updateProjectionMatrix();
|
|
40460
|
-
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
40461
|
-
}
|
|
40462
|
-
/**
|
|
40463
|
-
* Animates the scene and updates controls.
|
|
40464
|
-
*/
|
|
40465
|
-
animate() {
|
|
40466
|
-
if (this.tween) this.tween.update();
|
|
40467
|
-
requestAnimationFrame(this.animate.bind(this));
|
|
40468
|
-
this.controls.update();
|
|
40469
|
-
this.renderer.render(this.scene, this.camera);
|
|
40470
|
-
if (this.spotLightPosX > 500) {
|
|
40471
|
-
this.spotLightDirection = -1;
|
|
40472
|
-
this.spotLightPosX = 500;
|
|
40473
|
-
}
|
|
40474
|
-
if (this.spotLightPosX < -500) {
|
|
40475
|
-
this.spotLightDirection = 1;
|
|
40476
|
-
this.spotLightPosX = -500;
|
|
40477
|
-
}
|
|
40478
|
-
this.spotLightPosX += 10 * this.spotLightDirection;
|
|
40479
|
-
this.spotLight.position.set(this.spotLightPosX, this.spotLightPosY, this.spotLightPosZ);
|
|
40480
|
-
}
|
|
40481
|
-
reset() {
|
|
40482
|
-
this.hideHelpers();
|
|
40483
|
-
this.controls.reset();
|
|
40484
|
-
this.setMode("VIEW");
|
|
40485
|
-
this.fitScreen();
|
|
40486
|
-
}
|
|
40487
|
-
// ================================================================
|
|
40488
|
-
// Diagram arrangement
|
|
40489
|
-
// ================================================================
|
|
40490
|
-
arrange() {
|
|
40491
|
-
if (this.scene.children.length === 0) {
|
|
40492
|
-
console.warn("Scene is empty. Cannot calculate center.");
|
|
40493
|
-
return;
|
|
40494
|
-
}
|
|
40495
|
-
const box = new Box3().setFromObject(this.scene);
|
|
40496
|
-
const center = box.getCenter(new Vector3$1());
|
|
40497
|
-
const translation = new Vector3$1(-center.x, -center.y, -center.z);
|
|
40498
|
-
this.scene.children.forEach((child) => {
|
|
40499
|
-
if (child instanceof Object3D) {
|
|
40500
|
-
child.position.add(translation);
|
|
40501
|
-
}
|
|
40502
|
-
});
|
|
40503
|
-
}
|
|
40504
|
-
/**
|
|
40505
|
-
* Calculates the optimal zoom distance for the camera to ensure the entire scene is visible.
|
|
40506
|
-
*
|
|
40507
|
-
* @returns {number} The optimal distance for the camera to fit the scene within the viewport.
|
|
40508
|
-
*/
|
|
40509
|
-
calculateOptimalZoom() {
|
|
40510
|
-
const box = new Box3().setFromObject(this.scene);
|
|
40511
|
-
const size = box.getSize(new Vector3$1());
|
|
40512
|
-
const aspect2 = window.innerWidth / window.innerHeight;
|
|
40513
|
-
const fovRad = MathUtils$1.degToRad(this.camera.fov);
|
|
40514
|
-
const distanceForWidth = size.x / 2 / (Math.tan(fovRad / 2) * aspect2);
|
|
40515
|
-
const distanceForHeight = size.y / 2 / Math.tan(fovRad / 2);
|
|
40516
|
-
return Math.max(distanceForWidth, distanceForHeight);
|
|
40517
|
-
}
|
|
40518
|
-
/**
|
|
40519
|
-
* Adjusts the camera to fit the entire scene within the screen.
|
|
40520
|
-
*
|
|
40521
|
-
* This method calculates the optimal zoom level and positions the camera
|
|
40522
|
-
* at a distance that ensures the entire scene is visible, with a small margin.
|
|
40523
|
-
* It also updates the camera's orientation to look at the center of the scene
|
|
40524
|
-
* and saves the current camera state for later restoration.
|
|
40525
|
-
*/
|
|
40526
|
-
fitScreen() {
|
|
40527
|
-
const minZDistance = this.calculateOptimalZoom();
|
|
40528
|
-
const margin = 1.05;
|
|
40529
|
-
const cameraZ = minZDistance * margin;
|
|
40530
|
-
this.camera.position.set(0, 0, cameraZ);
|
|
40531
|
-
this.camera.lookAt(0, 0, 0);
|
|
40532
|
-
this.camera.updateProjectionMatrix();
|
|
40533
|
-
this.controls.saveState();
|
|
40534
|
-
this.initialCameraPosition = this.camera.position.clone();
|
|
40535
|
-
this.initialTarget = this.controls.target.clone();
|
|
40536
|
-
}
|
|
40537
|
-
/**
|
|
40538
|
-
* Centers the diagram by moving the camera to its initial position and target.
|
|
40539
|
-
* This method uses the Tween.js library to animate the camera movement.
|
|
40540
|
-
*
|
|
40541
|
-
* Preconditions:
|
|
40542
|
-
* - `this.initialCameraPosition` and `this.initialTarget` must be defined.
|
|
40543
|
-
*
|
|
40544
|
-
* Behavior:
|
|
40545
|
-
* - If the initial camera position or target is not defined, a warning is logged, and the method exits.
|
|
40546
|
-
* - Animates the camera's position and the controls' target to their initial states over 1200 milliseconds.
|
|
40547
|
-
* - Uses a Quartic easing function for smooth animation.
|
|
40548
|
-
*
|
|
40549
|
-
* Dependencies:
|
|
40550
|
-
* - Tween.js library for animation.
|
|
40551
|
-
*
|
|
40552
|
-
* @returns {void}
|
|
40553
|
-
*/
|
|
40554
|
-
center() {
|
|
40555
|
-
if (!this.initialCameraPosition || !this.initialTarget) {
|
|
40556
|
-
console.warn("Initial camera position or target is not defined.");
|
|
40557
|
-
return;
|
|
40558
|
-
}
|
|
40559
|
-
const from = {
|
|
40560
|
-
cameraPositionX: this.camera.position.x,
|
|
40561
|
-
cameraPositionY: this.camera.position.y,
|
|
40562
|
-
cameraPositionZ: this.camera.position.z,
|
|
40563
|
-
controlsTargetX: this.controls.target.x,
|
|
40564
|
-
controlsTargetY: this.controls.target.y,
|
|
40565
|
-
controlsTargetZ: this.controls.target.z
|
|
40566
|
-
};
|
|
40567
|
-
const to = {
|
|
40568
|
-
cameraPositionX: this.initialCameraPosition.x,
|
|
40569
|
-
cameraPositionY: this.initialCameraPosition.y,
|
|
40570
|
-
cameraPositionZ: this.initialCameraPosition.z,
|
|
40571
|
-
controlsTargetX: this.initialTarget.x,
|
|
40572
|
-
controlsTargetY: this.initialTarget.y,
|
|
40573
|
-
controlsTargetZ: this.initialTarget.z
|
|
40574
|
-
};
|
|
40575
|
-
const camera = this.camera;
|
|
40576
|
-
const controls = this.controls;
|
|
40577
|
-
this.tween = new Tween$1(from).to(to, 1200).easing(Easing.Quartic.Out).onUpdate(function() {
|
|
40578
|
-
camera.position.set(
|
|
40579
|
-
from.cameraPositionX,
|
|
40580
|
-
from.cameraPositionY,
|
|
40581
|
-
from.cameraPositionZ
|
|
40582
|
-
);
|
|
40583
|
-
controls.target.set(
|
|
40584
|
-
from.controlsTargetX,
|
|
40585
|
-
from.controlsTargetY,
|
|
40586
|
-
from.controlsTargetZ
|
|
40587
|
-
);
|
|
40588
|
-
}).onComplete(function() {
|
|
40589
|
-
}).start();
|
|
40590
|
-
}
|
|
40591
|
-
/**
|
|
40592
|
-
* Rotates the diagram around the Y axis by a specified angle in degrees.
|
|
40593
|
-
* The method ensures the diagram is centered and calculates the new camera
|
|
40594
|
-
* and target positions based on the provided angle.
|
|
40595
|
-
*
|
|
40596
|
-
* @param {number} targetAngle - The angle in degrees to rotate the diagram (e.g., 60).
|
|
40597
|
-
* @returns {void} - Does not return a value.
|
|
40598
|
-
*
|
|
40599
|
-
* @throws {Error} Logs a warning if the initial camera position or target is not defined.
|
|
40600
|
-
*
|
|
40601
|
-
* @example
|
|
40602
|
-
* // Rotate the diagram by 60 degrees
|
|
40603
|
-
* diagram.rotate(60);
|
|
40604
|
-
*/
|
|
40605
|
-
rotate(targetAngle) {
|
|
40606
|
-
if (!this.initialCameraPosition || !this.initialTarget) {
|
|
40607
|
-
console.warn("Initial camera position or target is not defined.");
|
|
40608
|
-
return;
|
|
40609
|
-
}
|
|
40610
|
-
const radius = Math.sqrt(
|
|
40611
|
-
this.initialCameraPosition.y * this.initialCameraPosition.y + this.initialCameraPosition.z * this.initialCameraPosition.z
|
|
40612
|
-
);
|
|
40613
|
-
const from = {
|
|
40614
|
-
cameraPositionX: this.camera.position.x,
|
|
40615
|
-
cameraPositionY: this.camera.position.y,
|
|
40616
|
-
cameraPositionZ: this.camera.position.z,
|
|
40617
|
-
controlsTargetX: this.controls.target.x,
|
|
40618
|
-
controlsTargetY: this.controls.target.y,
|
|
40619
|
-
controlsTargetZ: this.controls.target.z
|
|
40620
|
-
};
|
|
40621
|
-
const targetAngleRad = MathUtils$1.degToRad(targetAngle);
|
|
40622
|
-
const to = {
|
|
40623
|
-
cameraPositionX: this.initialCameraPosition.x,
|
|
40624
|
-
cameraPositionY: radius * Math.sin(targetAngleRad),
|
|
40625
|
-
cameraPositionZ: radius * Math.cos(targetAngleRad),
|
|
40626
|
-
controlsTargetX: this.initialTarget.x,
|
|
40627
|
-
controlsTargetY: this.initialTarget.y,
|
|
40628
|
-
controlsTargetZ: this.initialTarget.z
|
|
40629
|
-
};
|
|
40630
|
-
console.log("rotate() -> from:", from);
|
|
40631
|
-
console.log("rotate() -> to:", to);
|
|
40632
|
-
const camera = this.camera;
|
|
40633
|
-
const controls = this.controls;
|
|
40634
|
-
this.tween = new Tween$1(from).to(to, 1200).easing(Easing.Quartic.Out).onUpdate(function() {
|
|
40635
|
-
camera.position.set(
|
|
40636
|
-
from.cameraPositionX,
|
|
40637
|
-
from.cameraPositionY,
|
|
40638
|
-
from.cameraPositionZ
|
|
40639
|
-
);
|
|
40640
|
-
controls.target.set(
|
|
40641
|
-
from.controlsTargetX,
|
|
40642
|
-
from.controlsTargetY,
|
|
40643
|
-
from.controlsTargetZ
|
|
40644
|
-
);
|
|
40645
|
-
}).start();
|
|
40646
|
-
}
|
|
40647
|
-
// ================================================================
|
|
40648
|
-
// Diagram modes
|
|
40649
|
-
// ================================================================
|
|
40650
|
-
/**
|
|
40651
|
-
* Removes all elements of type 'ValueBarShape' from the diagram.
|
|
40652
|
-
* Iterates through the `elements` array in reverse order to safely remove
|
|
40653
|
-
* elements without affecting the iteration process. For each matching element,
|
|
40654
|
-
* it removes the element from its parent (and thus from the scene) and also
|
|
40655
|
-
* removes it from the `elements` array.
|
|
40656
|
-
*/
|
|
40657
|
-
removeValueBars() {
|
|
40658
|
-
for (let i = this.elements.length - 1; i >= 0; i--) {
|
|
40659
|
-
const element2 = this.elements[i];
|
|
40660
|
-
if (element2.type === "ValueBarShape") {
|
|
40661
|
-
if (element2.parent) {
|
|
40662
|
-
element2.parent.remove(element2);
|
|
40663
|
-
}
|
|
40664
|
-
this.scene.remove(element2);
|
|
40665
|
-
this.elements.splice(i, 1);
|
|
40666
|
-
}
|
|
40667
|
-
}
|
|
40668
|
-
}
|
|
40669
|
-
/**
|
|
40670
|
-
* Adds value bars to the diagram to visualize the elements' parameters.
|
|
40671
|
-
*
|
|
40672
|
-
* This method processes the elements in the diagram, calculates the height
|
|
40673
|
-
* of the bars based on their parameter values, and assigns a color to each
|
|
40674
|
-
* bar based on a normalized value. The bars are then added to the scene.
|
|
40675
|
-
*
|
|
40676
|
-
* @method
|
|
40677
|
-
* @memberof Diagram
|
|
40678
|
-
* @description
|
|
40679
|
-
* - Filters elements to include only those with a defined `parameters.value`.
|
|
40680
|
-
* - Calculates the range of parameter values to normalize them.
|
|
40681
|
-
* - Assigns a color to each bar using an HSL color scale (green to red).
|
|
40682
|
-
* - Calls the `valueBar` method on each element to set the bar's height and color.
|
|
40683
|
-
*
|
|
40684
|
-
* @example
|
|
40685
|
-
* // Assuming `diagram` is an instance of Diagram with elements having parameters:
|
|
40686
|
-
* diagram.addValueBars();
|
|
40687
|
-
*
|
|
40688
|
-
* @throws {Error} If no elements with `parameters.value` are found.
|
|
40689
|
-
*/
|
|
40690
|
-
addValueBars() {
|
|
40691
|
-
const elements = this.elements.filter((el) => el.parameters && el.parameters.value !== void 0);
|
|
40692
|
-
if (elements.length === 0) {
|
|
40693
|
-
throw new Error("No elements with `parameters.value` found.");
|
|
40694
|
-
}
|
|
40695
|
-
const max2 = Math.max(...elements.map((el) => el.parameters.value));
|
|
40696
|
-
const min2 = 0;
|
|
40697
|
-
const range = max2 - min2;
|
|
40698
|
-
elements.forEach((element2, i) => {
|
|
40699
|
-
const value = element2.parameters.value;
|
|
40700
|
-
const normalizedValue = (value - min2) / range;
|
|
40701
|
-
const color2 = new Color$1(`hsl(${(normalizedValue * 120).toString(10)}, 100%, 50%)`);
|
|
40702
|
-
element2.addValueBar(normalizedValue * 100, color2);
|
|
40703
|
-
});
|
|
40704
|
-
}
|
|
40705
|
-
/**
|
|
40706
|
-
* Sets the mode of the diagram and adjusts its state accordingly.
|
|
40707
|
-
*
|
|
40708
|
-
* @param {string} mode - The mode to set. Possible values are:
|
|
40709
|
-
* - 'EDIT': Sets the diagram to edit mode and resets rotation.
|
|
40710
|
-
* - 'VIEW': Sets the diagram to view mode and resets rotation.
|
|
40711
|
-
* - 'ANALYZE': Sets the diagram to analyze mode, rotates it to -60 degrees,
|
|
40712
|
-
* and adds value bars.
|
|
40713
|
-
* - Any other value will log a warning about an unknown mode.
|
|
40714
|
-
*/
|
|
40715
|
-
setMode(mode) {
|
|
40716
|
-
this.removeValueBars();
|
|
40717
|
-
this.mode = mode;
|
|
40718
|
-
switch (mode) {
|
|
40719
|
-
case "EDIT":
|
|
40720
|
-
case "VIEW":
|
|
40721
|
-
this.rotate(0);
|
|
40722
|
-
break;
|
|
40723
|
-
case "ANALYZE":
|
|
40724
|
-
this.rotate(-65);
|
|
40725
|
-
this.addValueBars();
|
|
40726
|
-
break;
|
|
40727
|
-
default:
|
|
40728
|
-
console.warn(`Unknown mode: ${mode}`);
|
|
40729
|
-
}
|
|
40730
|
-
}
|
|
40731
|
-
// ================================================================
|
|
40732
|
-
// Diagram elements
|
|
40733
|
-
// ================================================================
|
|
40734
|
-
/**
|
|
40735
|
-
* Adds an element to the diagram.
|
|
40736
|
-
* @param {Object3D} element - The element to add.
|
|
40737
|
-
* @param {Vector3} [position] - The position to place the element.
|
|
40738
|
-
* @returns {Object3D} The added element.
|
|
40739
|
-
*/
|
|
40740
|
-
addElement(element2, position) {
|
|
40741
|
-
this.elements.push(element2);
|
|
40742
|
-
this.scene.add(element2);
|
|
40743
|
-
if (position) element2.position.set(position.x, position.y, 0);
|
|
40744
|
-
element2.setDiagram(this);
|
|
40745
|
-
return element2;
|
|
40746
|
-
}
|
|
40747
|
-
/**
|
|
40748
|
-
* Removes an element from the diagram by its ID.
|
|
40749
|
-
* @param {string} elementId - The ID of the element to remove.
|
|
40750
|
-
*/
|
|
40751
|
-
removeElement(elementId) {
|
|
40752
|
-
const element2 = this.elements.find((el) => el.id === elementId);
|
|
40753
|
-
if (element2) {
|
|
40754
|
-
this.scene.remove(element2);
|
|
40755
|
-
this.elements = this.elements.filter((el) => el.id !== elementId);
|
|
40756
|
-
}
|
|
40757
|
-
}
|
|
40758
|
-
/**
|
|
40759
|
-
* Retrieves an element from the `elements` array by its unique `elementId`.
|
|
40760
|
-
*
|
|
40761
|
-
* @param {string} elementId - The unique identifier of the element to find.
|
|
40762
|
-
* @returns {Object|undefined} The element with the matching `elementId`, or `undefined` if not found.
|
|
40763
|
-
*/
|
|
40764
|
-
getElementById(elementId) {
|
|
40765
|
-
return this.elements.find((el) => el.elementId === elementId);
|
|
40766
|
-
}
|
|
40767
|
-
/**
|
|
40768
|
-
* Retrieves the elements of the diagram.
|
|
40769
|
-
*
|
|
40770
|
-
* @returns {Array} The array of elements in the diagram.
|
|
40771
|
-
*/
|
|
40772
|
-
getElements() {
|
|
40773
|
-
return this.elements;
|
|
40774
|
-
}
|
|
40775
|
-
// ================================================================
|
|
40776
|
-
// Diagram Connectors
|
|
40777
|
-
// ================================================================
|
|
40778
|
-
/**
|
|
40779
|
-
* Adds a connector to the diagram, registers it with the diagram,
|
|
40780
|
-
* and adds it to the scene for rendering.
|
|
40781
|
-
*
|
|
40782
|
-
* @param {Object} connector - The connector object to be added to the diagram.
|
|
40783
|
-
* @returns {Object} The connector that was added.
|
|
40784
|
-
*/
|
|
40785
|
-
addConnector(connector) {
|
|
40786
|
-
this.connectors.push(connector);
|
|
40787
|
-
this.scene.add(connector);
|
|
40788
|
-
connector.setDiagram(this);
|
|
40789
|
-
return connector;
|
|
40790
|
-
}
|
|
40791
|
-
// ================================================================
|
|
40792
|
-
// Clear diagram
|
|
40793
|
-
// ================================================================
|
|
40794
|
-
/**
|
|
40795
|
-
* Clears all elements and connectors from the diagram.
|
|
40796
|
-
*/
|
|
40797
|
-
clear() {
|
|
40798
|
-
this.elements = [];
|
|
40799
|
-
this.connectors = [];
|
|
40800
|
-
this.scene.children = this.scene.children.filter((child) => child instanceof AmbientLight);
|
|
40801
|
-
}
|
|
40802
|
-
// ================================================================
|
|
40803
|
-
// Diagram JSON
|
|
40804
|
-
// ================================================================
|
|
40805
|
-
toJSON() {
|
|
40806
|
-
return JSON.stringify(this.elements);
|
|
40807
|
-
}
|
|
40808
|
-
fromJSON(json) {
|
|
40809
|
-
this.elements = JSON.parse(json);
|
|
40810
|
-
}
|
|
40811
|
-
// ================================================================
|
|
40812
|
-
// Diagram export and import to/from file
|
|
40813
|
-
// ================================================================
|
|
40814
|
-
/**
|
|
40815
|
-
* Exports the diagram to a JSON file.
|
|
40816
|
-
*/
|
|
40817
|
-
export() {
|
|
40818
|
-
const data = JSON.stringify(this.scene.toJSON());
|
|
40819
|
-
const blob = new Blob([data], { type: "application/json" });
|
|
40820
|
-
const url = URL.createObjectURL(blob);
|
|
40821
|
-
const a = document.createElement("a");
|
|
40822
|
-
a.href = url;
|
|
40823
|
-
a.download = "diagram.json";
|
|
40824
|
-
a.click();
|
|
40825
|
-
URL.revokeObjectURL(url);
|
|
40826
|
-
}
|
|
40827
|
-
/**
|
|
40828
|
-
* Placeholder for importing a diagram from a file.
|
|
40829
|
-
* This method should be implemented by subclasses.
|
|
40830
|
-
* @param {File} file - The file to import.
|
|
40831
|
-
* @throws {Error} If the method is not implemented.
|
|
40832
|
-
* @returns {Promise<void>}
|
|
40833
|
-
*/
|
|
40834
|
-
import(file) {
|
|
40835
|
-
console.error("Import method should be implemented by subclasses.");
|
|
40836
|
-
}
|
|
40837
|
-
}
|
|
40838
|
-
const DiagramDimensions = {
|
|
40839
|
-
DISTANCE_BETWEEN_ELEMENTS: 48
|
|
40840
|
-
};
|
|
40841
|
-
const ExtrusionParameters$1 = {
|
|
40842
|
-
steps: 2,
|
|
40843
|
-
depth: 0.6,
|
|
40844
|
-
bevelEnabled: true,
|
|
40845
|
-
bevelThickness: 0.2,
|
|
40846
|
-
bevelSize: 0.4,
|
|
40847
|
-
bevelOffset: 0,
|
|
40848
|
-
bevelSegments: 4
|
|
40849
|
-
};
|
|
40850
|
-
const Colors = {
|
|
40851
|
-
ELEMENT_STROKE: 26265,
|
|
40852
|
-
ELEMENT_TEXT: 26265
|
|
40853
|
-
};
|
|
40854
40291
|
class Shape2 {
|
|
40855
40292
|
constructor(geometry, material) {
|
|
40856
40293
|
this.geometry = geometry;
|
|
@@ -40882,6 +40319,22 @@ class BoxShape extends Shape2 {
|
|
|
40882
40319
|
super(new BoxGeometry(1, 1, 1), new DiagramEditMaterial(color2));
|
|
40883
40320
|
}
|
|
40884
40321
|
}
|
|
40322
|
+
const DiagramDimensions = {
|
|
40323
|
+
DISTANCE_BETWEEN_ELEMENTS: 48
|
|
40324
|
+
};
|
|
40325
|
+
const ExtrusionParameters$1 = {
|
|
40326
|
+
steps: 2,
|
|
40327
|
+
depth: 0.6,
|
|
40328
|
+
bevelEnabled: true,
|
|
40329
|
+
bevelThickness: 0.2,
|
|
40330
|
+
bevelSize: 0.4,
|
|
40331
|
+
bevelOffset: 0,
|
|
40332
|
+
bevelSegments: 4
|
|
40333
|
+
};
|
|
40334
|
+
const Colors = {
|
|
40335
|
+
ELEMENT_STROKE: 26265,
|
|
40336
|
+
ELEMENT_TEXT: 26265
|
|
40337
|
+
};
|
|
40885
40338
|
class FontLoader extends Loader {
|
|
40886
40339
|
constructor(manager) {
|
|
40887
40340
|
super(manager);
|
|
@@ -43120,60 +42573,29 @@ const ExtrusionParameters = {
|
|
|
43120
42573
|
bevelOffset: 0,
|
|
43121
42574
|
bevelSegments: 1
|
|
43122
42575
|
};
|
|
43123
|
-
const ColorPalette = [
|
|
43124
|
-
new Color$1(16007990),
|
|
43125
|
-
// red
|
|
43126
|
-
new Color$1(15277667),
|
|
43127
|
-
// pink
|
|
43128
|
-
new Color$1(10233776),
|
|
43129
|
-
// purple
|
|
43130
|
-
new Color$1(6765239),
|
|
43131
|
-
// deep purple
|
|
43132
|
-
new Color$1(4149685),
|
|
43133
|
-
// indigo
|
|
43134
|
-
new Color$1(2201331),
|
|
43135
|
-
// blue
|
|
43136
|
-
new Color$1(240116),
|
|
43137
|
-
// light blue
|
|
43138
|
-
new Color$1(48340),
|
|
43139
|
-
// cyan
|
|
43140
|
-
new Color$1(38536),
|
|
43141
|
-
// teal
|
|
43142
|
-
new Color$1(5025616),
|
|
43143
|
-
// green
|
|
43144
|
-
new Color$1(9159498),
|
|
43145
|
-
// light green
|
|
43146
|
-
new Color$1(13491257),
|
|
43147
|
-
// lime
|
|
43148
|
-
new Color$1(16771899),
|
|
43149
|
-
// yellow
|
|
43150
|
-
new Color$1(16761095),
|
|
43151
|
-
// amber
|
|
43152
|
-
new Color$1(16750592),
|
|
43153
|
-
// orange
|
|
43154
|
-
new Color$1(16733986),
|
|
43155
|
-
// deep orange
|
|
43156
|
-
new Color$1(7951688),
|
|
43157
|
-
// brown
|
|
43158
|
-
new Color$1(10395294),
|
|
43159
|
-
// grey
|
|
43160
|
-
new Color$1(6323595)
|
|
43161
|
-
// blue grey
|
|
43162
|
-
];
|
|
43163
42576
|
class ValueBarShape extends Shape2 {
|
|
42577
|
+
/**
|
|
42578
|
+
* Creates a new ValueBarShape.
|
|
42579
|
+
* This is a simple component that receives a pre-calculated height and color.
|
|
42580
|
+
* @param {THREE.Shape} shape The 2D base shape of the bar.
|
|
42581
|
+
* @param {number} height The final, normalized height of the bar.
|
|
42582
|
+
* @param {THREE.Color} color The final, pre-calculated color for the bar.
|
|
42583
|
+
*/
|
|
43164
42584
|
constructor(shape, height, color2) {
|
|
43165
42585
|
if (!(shape instanceof Shape$1)) {
|
|
43166
42586
|
throw new TypeError("shape must be an instance of THREE.Shape");
|
|
43167
42587
|
}
|
|
43168
|
-
|
|
43169
|
-
|
|
43170
|
-
|
|
43171
|
-
|
|
43172
|
-
|
|
42588
|
+
if (typeof height !== "number") {
|
|
42589
|
+
throw new TypeError("height must be a number.");
|
|
42590
|
+
}
|
|
42591
|
+
if (!(color2 instanceof Color$1)) {
|
|
42592
|
+
throw new TypeError("color must be an instance of THREE.Color.");
|
|
42593
|
+
}
|
|
42594
|
+
const extrusionParameters = { ...ExtrusionParameters, depth: height };
|
|
42595
|
+
const barGeometry = new ExtrudeGeometry(shape, extrusionParameters);
|
|
42596
|
+
super(barGeometry, new BarMaterial(color2));
|
|
42597
|
+
this.type = "ValueBarShape";
|
|
43173
42598
|
}
|
|
43174
|
-
// draw(ctx, x, y, width) {
|
|
43175
|
-
// ctx.fillRect(x, y - this.barHeight, width, this.barHeight);
|
|
43176
|
-
// }
|
|
43177
42599
|
}
|
|
43178
42600
|
const ConnectorDimensions = {
|
|
43179
42601
|
CONNECTOR_LINE_WIDTH: 1,
|
|
@@ -43547,766 +42969,1338 @@ class Element extends Mesh {
|
|
|
43547
42969
|
return size;
|
|
43548
42970
|
}
|
|
43549
42971
|
/**
|
|
43550
|
-
* Positions the element and its decorations at the specified coordinates.
|
|
43551
|
-
* @param {Object} position - The position coordinates
|
|
43552
|
-
* @param {number} position.x - X coordinate
|
|
43553
|
-
* @param {number} position.y - Y coordinate
|
|
43554
|
-
* @param {number} [position.z] - Optional Z coordinate
|
|
42972
|
+
* Positions the element and its decorations at the specified coordinates.
|
|
42973
|
+
* @param {Object} position - The position coordinates
|
|
42974
|
+
* @param {number} position.x - X coordinate
|
|
42975
|
+
* @param {number} position.y - Y coordinate
|
|
42976
|
+
* @param {number} [position.z] - Optional Z coordinate
|
|
42977
|
+
* @returns {Element} This element for method chaining
|
|
42978
|
+
*/
|
|
42979
|
+
positionAt(position) {
|
|
42980
|
+
if (position.z !== void 0) {
|
|
42981
|
+
this.position.set(position.x, position.y, position.z);
|
|
42982
|
+
} else {
|
|
42983
|
+
this.position.set(position.x, position.y, 0);
|
|
42984
|
+
}
|
|
42985
|
+
this.texts.forEach((text) => {
|
|
42986
|
+
const offset = text.positionOffset;
|
|
42987
|
+
if (position.z !== void 0) {
|
|
42988
|
+
text.element.position.set(position.x + offset.x, position.y + offset.y, position.z + offset.z);
|
|
42989
|
+
} else {
|
|
42990
|
+
text.element.position.set(position.x + offset.x, position.y + offset.y, offset.z);
|
|
42991
|
+
}
|
|
42992
|
+
});
|
|
42993
|
+
this.icons.forEach((icon) => {
|
|
42994
|
+
const offset = icon.positionOffset;
|
|
42995
|
+
if (position.z !== void 0) {
|
|
42996
|
+
icon.element.position.set(position.x + offset.x, position.y + offset.y, position.z + offset.z);
|
|
42997
|
+
} else {
|
|
42998
|
+
icon.element.position.set(position.x + offset.x, position.y + offset.y, offset.z);
|
|
42999
|
+
}
|
|
43000
|
+
});
|
|
43001
|
+
this.valueBars.forEach((bar) => {
|
|
43002
|
+
const offset = bar.positionOffset;
|
|
43003
|
+
if (position.z !== void 0) {
|
|
43004
|
+
bar.element.position.set(position.x + offset.x, position.y + offset.y, position.z + offset.z);
|
|
43005
|
+
} else {
|
|
43006
|
+
bar.element.position.set(position.x + offset.x, position.y + offset.y, offset.z);
|
|
43007
|
+
}
|
|
43008
|
+
});
|
|
43009
|
+
return this;
|
|
43010
|
+
}
|
|
43011
|
+
/**
|
|
43012
|
+
* Sets the position of the element using individual coordinates.
|
|
43013
|
+
* @param {number} x - X coordinate
|
|
43014
|
+
* @param {number} y - Y coordinate
|
|
43015
|
+
* @param {number} z - Z coordinate
|
|
43016
|
+
* @returns {Element} This element for method chaining
|
|
43017
|
+
*/
|
|
43018
|
+
setPosition(x, y, z) {
|
|
43019
|
+
const pos = new Vector3$1(x, y, z);
|
|
43020
|
+
this.positionAt(pos);
|
|
43021
|
+
return this;
|
|
43022
|
+
}
|
|
43023
|
+
/**
|
|
43024
|
+
* Gets the current position of the element.
|
|
43025
|
+
* @returns {THREE.Vector3} The position vector
|
|
43026
|
+
*/
|
|
43027
|
+
getPosition() {
|
|
43028
|
+
return this.position;
|
|
43029
|
+
}
|
|
43030
|
+
/**
|
|
43031
|
+
* Positions this element to the right of another element.
|
|
43032
|
+
* @param {string} elementId - ID of the reference element
|
|
43033
|
+
* @returns {Element} This element for method chaining
|
|
43034
|
+
*/
|
|
43035
|
+
positionRightOf(elementId) {
|
|
43036
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43037
|
+
const elementWidth = element2.getSize().x;
|
|
43038
|
+
const thisWidth = this.getSize().x;
|
|
43039
|
+
this.setPosition(
|
|
43040
|
+
element2.position.x + elementWidth / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisWidth / 2,
|
|
43041
|
+
// x
|
|
43042
|
+
element2.position.y,
|
|
43043
|
+
// y
|
|
43044
|
+
0
|
|
43045
|
+
);
|
|
43046
|
+
return this;
|
|
43047
|
+
}
|
|
43048
|
+
/**
|
|
43049
|
+
* Positions this element to the left of another element.
|
|
43050
|
+
* @param {string} elementId - ID of the reference element
|
|
43051
|
+
* @returns {Element} This element for method chaining
|
|
43052
|
+
*/
|
|
43053
|
+
positionLeftOf(elementId) {
|
|
43054
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43055
|
+
const elementWidth = element2.getSize().x;
|
|
43056
|
+
const thisWidth = this.getSize().x;
|
|
43057
|
+
this.setPosition(
|
|
43058
|
+
element2.position.x - elementWidth / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisWidth / 2,
|
|
43059
|
+
// x
|
|
43060
|
+
element2.position.y,
|
|
43061
|
+
// y
|
|
43062
|
+
0
|
|
43063
|
+
);
|
|
43064
|
+
return this;
|
|
43065
|
+
}
|
|
43066
|
+
/**
|
|
43067
|
+
* Positions this element above another element.
|
|
43068
|
+
* @param {string} elementId - ID of the reference element
|
|
43069
|
+
* @returns {Element} This element for method chaining
|
|
43070
|
+
*/
|
|
43071
|
+
positionUpOf(elementId) {
|
|
43072
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43073
|
+
const elementHeight = element2.getSize().y;
|
|
43074
|
+
const thisHeight = this.getSize().y;
|
|
43075
|
+
this.setPosition(
|
|
43076
|
+
element2.position.x,
|
|
43077
|
+
// x
|
|
43078
|
+
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43079
|
+
// y
|
|
43080
|
+
0
|
|
43081
|
+
);
|
|
43082
|
+
return this;
|
|
43083
|
+
}
|
|
43084
|
+
/**
|
|
43085
|
+
* Positions this element below another element.
|
|
43086
|
+
* @param {string} elementId - ID of the reference element
|
|
43087
|
+
* @returns {Element} This element for method chaining
|
|
43088
|
+
*/
|
|
43089
|
+
positionDownOf(elementId) {
|
|
43090
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43091
|
+
const elementHeight = element2.getSize().y;
|
|
43092
|
+
const thisHeight = this.getSize().y;
|
|
43093
|
+
this.setPosition(
|
|
43094
|
+
element2.position.x,
|
|
43095
|
+
// x
|
|
43096
|
+
element2.position.y - elementHeight / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisHeight / 2,
|
|
43097
|
+
// y
|
|
43098
|
+
0
|
|
43099
|
+
);
|
|
43100
|
+
return this;
|
|
43101
|
+
}
|
|
43102
|
+
/**
|
|
43103
|
+
* Positions this element above and to the left of another element.
|
|
43104
|
+
* @param {string} elementId - ID of the reference element
|
|
43555
43105
|
* @returns {Element} This element for method chaining
|
|
43556
43106
|
*/
|
|
43557
|
-
|
|
43558
|
-
|
|
43559
|
-
|
|
43560
|
-
|
|
43561
|
-
|
|
43562
|
-
|
|
43563
|
-
this.
|
|
43564
|
-
|
|
43565
|
-
|
|
43566
|
-
|
|
43567
|
-
|
|
43568
|
-
|
|
43569
|
-
|
|
43570
|
-
});
|
|
43571
|
-
this.icons.forEach((icon) => {
|
|
43572
|
-
const offset = icon.positionOffset;
|
|
43573
|
-
if (position.z !== void 0) {
|
|
43574
|
-
icon.element.position.set(position.x + offset.x, position.y + offset.y, position.z + offset.z);
|
|
43575
|
-
} else {
|
|
43576
|
-
icon.element.position.set(position.x + offset.x, position.y + offset.y, offset.z);
|
|
43577
|
-
}
|
|
43578
|
-
});
|
|
43579
|
-
this.valueBars.forEach((bar) => {
|
|
43580
|
-
const offset = bar.positionOffset;
|
|
43581
|
-
if (position.z !== void 0) {
|
|
43582
|
-
bar.element.position.set(position.x + offset.x, position.y + offset.y, position.z + offset.z);
|
|
43583
|
-
} else {
|
|
43584
|
-
bar.element.position.set(position.x + offset.x, position.y + offset.y, offset.z);
|
|
43585
|
-
}
|
|
43586
|
-
});
|
|
43107
|
+
positionUpLeftOf(elementId) {
|
|
43108
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43109
|
+
const elementWidth = element2.getSize().x;
|
|
43110
|
+
const elementHeight = element2.getSize().y;
|
|
43111
|
+
const thisWidth = this.getSize().x;
|
|
43112
|
+
const thisHeight = this.getSize().y;
|
|
43113
|
+
this.setPosition(
|
|
43114
|
+
element2.position.x - elementWidth / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisWidth / 2,
|
|
43115
|
+
// x
|
|
43116
|
+
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43117
|
+
// y
|
|
43118
|
+
0
|
|
43119
|
+
);
|
|
43587
43120
|
return this;
|
|
43588
43121
|
}
|
|
43589
43122
|
/**
|
|
43590
|
-
*
|
|
43591
|
-
* @param {
|
|
43592
|
-
* @param {number} y - Y coordinate
|
|
43593
|
-
* @param {number} z - Z coordinate
|
|
43123
|
+
* Positions this element below and to the left of another element.
|
|
43124
|
+
* @param {string} elementId - ID of the reference element
|
|
43594
43125
|
* @returns {Element} This element for method chaining
|
|
43595
43126
|
*/
|
|
43596
|
-
|
|
43597
|
-
const
|
|
43598
|
-
|
|
43127
|
+
positionDownLeftOf(elementId) {
|
|
43128
|
+
const element2 = this.diagram.getElementById(elementId);
|
|
43129
|
+
const elementWidth = element2.getSize().x;
|
|
43130
|
+
const elementHeight = element2.getSize().y;
|
|
43131
|
+
const thisWidth = this.getSize().x;
|
|
43132
|
+
const thisHeight = this.getSize().y;
|
|
43133
|
+
this.setPosition(
|
|
43134
|
+
element2.position.x - elementWidth / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisWidth / 2,
|
|
43135
|
+
// x
|
|
43136
|
+
element2.position.y - elementHeight / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisHeight / 2,
|
|
43137
|
+
// y
|
|
43138
|
+
0
|
|
43139
|
+
);
|
|
43599
43140
|
return this;
|
|
43600
43141
|
}
|
|
43601
43142
|
/**
|
|
43602
|
-
*
|
|
43603
|
-
* @returns {THREE.Vector3} The position vector
|
|
43604
|
-
*/
|
|
43605
|
-
getPosition() {
|
|
43606
|
-
return this.position;
|
|
43607
|
-
}
|
|
43608
|
-
/**
|
|
43609
|
-
* Positions this element to the right of another element.
|
|
43143
|
+
* Positions this element above and to the right of another element.
|
|
43610
43144
|
* @param {string} elementId - ID of the reference element
|
|
43611
43145
|
* @returns {Element} This element for method chaining
|
|
43612
43146
|
*/
|
|
43613
|
-
|
|
43147
|
+
positionUpRightOf(elementId) {
|
|
43614
43148
|
const element2 = this.diagram.getElementById(elementId);
|
|
43615
43149
|
const elementWidth = element2.getSize().x;
|
|
43150
|
+
const elementHeight = element2.getSize().y;
|
|
43616
43151
|
const thisWidth = this.getSize().x;
|
|
43152
|
+
const thisHeight = this.getSize().y;
|
|
43617
43153
|
this.setPosition(
|
|
43618
43154
|
element2.position.x + elementWidth / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisWidth / 2,
|
|
43619
43155
|
// x
|
|
43620
|
-
element2.position.y,
|
|
43156
|
+
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43621
43157
|
// y
|
|
43622
43158
|
0
|
|
43623
43159
|
);
|
|
43624
43160
|
return this;
|
|
43625
43161
|
}
|
|
43626
43162
|
/**
|
|
43627
|
-
* Positions this element to the
|
|
43163
|
+
* Positions this element below and to the right of another element.
|
|
43628
43164
|
* @param {string} elementId - ID of the reference element
|
|
43629
43165
|
* @returns {Element} This element for method chaining
|
|
43630
43166
|
*/
|
|
43631
|
-
|
|
43167
|
+
positionDownRightOf(elementId) {
|
|
43632
43168
|
const element2 = this.diagram.getElementById(elementId);
|
|
43633
43169
|
const elementWidth = element2.getSize().x;
|
|
43170
|
+
const elementHeight = element2.getSize().y;
|
|
43634
43171
|
const thisWidth = this.getSize().x;
|
|
43172
|
+
const thisHeight = this.getSize().y;
|
|
43635
43173
|
this.setPosition(
|
|
43636
|
-
element2.position.x
|
|
43174
|
+
element2.position.x + elementWidth / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisWidth / 2,
|
|
43637
43175
|
// x
|
|
43638
|
-
element2.position.y,
|
|
43176
|
+
element2.position.y - elementHeight / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisHeight / 2,
|
|
43639
43177
|
// y
|
|
43640
43178
|
0
|
|
43641
43179
|
);
|
|
43642
|
-
return this;
|
|
43180
|
+
return this;
|
|
43181
|
+
}
|
|
43182
|
+
// =================================================================
|
|
43183
|
+
// Determine connecting points positions in geographical manner
|
|
43184
|
+
// (N, S, E, W, NNE, NNW, NEE, NWW, SEE, SWW, SSE, SSW)
|
|
43185
|
+
// for connectors to connect to
|
|
43186
|
+
// ================================================================
|
|
43187
|
+
/**
|
|
43188
|
+
* Gets the north connection point of the element.
|
|
43189
|
+
* The point is positioned at the middle of the element's top edge.
|
|
43190
|
+
* @returns {THREE.Vector2} A 2D vector representing the north point coordinates
|
|
43191
|
+
* where x is the element's center x-coordinate
|
|
43192
|
+
* and y is the element's top edge y-coordinate
|
|
43193
|
+
*/
|
|
43194
|
+
getNorthPoint() {
|
|
43195
|
+
return new Vector2$1(
|
|
43196
|
+
this.position.x,
|
|
43197
|
+
this.position.y + this.getSize().y / 2
|
|
43198
|
+
);
|
|
43199
|
+
}
|
|
43200
|
+
/**
|
|
43201
|
+
* Gets the south connection point of the element.
|
|
43202
|
+
* The point is positioned at the middle of the element's bottom edge.
|
|
43203
|
+
* @returns {THREE.Vector2} A 2D vector representing the south point coordinates
|
|
43204
|
+
* where x is the element's center x-coordinate
|
|
43205
|
+
* and y is the element's bottom edge y-coordinate
|
|
43206
|
+
*/
|
|
43207
|
+
getSouthPoint() {
|
|
43208
|
+
return new Vector2$1(
|
|
43209
|
+
this.position.x,
|
|
43210
|
+
this.position.y - this.getSize().y / 2
|
|
43211
|
+
);
|
|
43212
|
+
}
|
|
43213
|
+
/**
|
|
43214
|
+
* Gets the east connection point of the element.
|
|
43215
|
+
* The point is positioned at the middle of the element's right edge.
|
|
43216
|
+
* @returns {THREE.Vector2} A 2D vector representing the east point coordinates
|
|
43217
|
+
* where x is the element's right edge x-coordinate
|
|
43218
|
+
* and y is the element's center y-coordinate
|
|
43219
|
+
*/
|
|
43220
|
+
getEastPoint() {
|
|
43221
|
+
return new Vector2$1(
|
|
43222
|
+
this.position.x + this.getSize().x / 2,
|
|
43223
|
+
this.position.y
|
|
43224
|
+
);
|
|
43225
|
+
}
|
|
43226
|
+
/**
|
|
43227
|
+
* Gets the west connection point of the element.
|
|
43228
|
+
* The point is positioned at the middle of the element's left edge.
|
|
43229
|
+
* @returns {THREE.Vector2} A 2D vector representing the west point coordinates
|
|
43230
|
+
* where x is the element's left edge x-coordinate
|
|
43231
|
+
* and y is the element's center y-coordinate
|
|
43232
|
+
*/
|
|
43233
|
+
getWestPoint() {
|
|
43234
|
+
return new Vector2$1(
|
|
43235
|
+
this.position.x - this.getSize().x / 2,
|
|
43236
|
+
this.position.y
|
|
43237
|
+
);
|
|
43238
|
+
}
|
|
43239
|
+
/**
|
|
43240
|
+
* Gets the north-east connection point of the element.
|
|
43241
|
+
* The point is positioned at the top-right corner of the element.
|
|
43242
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-east point coordinates
|
|
43243
|
+
* where x is the element's right edge x-coordinate
|
|
43244
|
+
* and y is the element's top edge y-coordinate
|
|
43245
|
+
*/
|
|
43246
|
+
getNorthEastPoint() {
|
|
43247
|
+
return new Vector2$1(
|
|
43248
|
+
this.position.x + this.getSize().x / 2,
|
|
43249
|
+
this.position.y + this.getSize().y / 2
|
|
43250
|
+
);
|
|
43251
|
+
}
|
|
43252
|
+
/**
|
|
43253
|
+
* Gets the north-west connection point of the element.
|
|
43254
|
+
* The point is positioned at the top-left corner of the element.
|
|
43255
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-west point coordinates
|
|
43256
|
+
* where x is the element's left edge x-coordinate
|
|
43257
|
+
* and y is the element's top edge y-coordinate
|
|
43258
|
+
*/
|
|
43259
|
+
getNorthWestPoint() {
|
|
43260
|
+
return new Vector2$1(
|
|
43261
|
+
this.position.x - this.getSize().x / 2,
|
|
43262
|
+
this.position.y + this.getSize().y / 2
|
|
43263
|
+
);
|
|
43264
|
+
}
|
|
43265
|
+
/**
|
|
43266
|
+
* Gets the south-east connection point of the element.
|
|
43267
|
+
* The point is positioned at the bottom-right corner of the element.
|
|
43268
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-east point coordinates
|
|
43269
|
+
* where x is the element's right edge x-coordinate
|
|
43270
|
+
* and y is the element's bottom edge y-coordinate
|
|
43271
|
+
*/
|
|
43272
|
+
getSouthEastPoint() {
|
|
43273
|
+
return new Vector2$1(
|
|
43274
|
+
this.position.x + this.getSize().x / 2,
|
|
43275
|
+
this.position.y - this.getSize().y / 2
|
|
43276
|
+
);
|
|
43277
|
+
}
|
|
43278
|
+
/**
|
|
43279
|
+
* Gets the south-west connection point of the element.
|
|
43280
|
+
* The point is positioned at the bottom-left corner of the element.
|
|
43281
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-west point coordinates
|
|
43282
|
+
* where x is the element's left edge x-coordinate
|
|
43283
|
+
* and y is the element's bottom edge y-coordinate
|
|
43284
|
+
*/
|
|
43285
|
+
getSouthWestPoint() {
|
|
43286
|
+
return new Vector2$1(
|
|
43287
|
+
this.position.x - this.getSize().x / 2,
|
|
43288
|
+
this.position.y - this.getSize().y / 2
|
|
43289
|
+
);
|
|
43290
|
+
}
|
|
43291
|
+
/**
|
|
43292
|
+
* Gets the north-north-east connection point of the element.
|
|
43293
|
+
* The point is positioned on the top edge, one-quarter of the width from the center towards the right.
|
|
43294
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-north-east point coordinates
|
|
43295
|
+
* where x is the element's center x-coordinate plus one-quarter of the width
|
|
43296
|
+
* and y is the element's top edge y-coordinate
|
|
43297
|
+
*/
|
|
43298
|
+
getNorthNorthEastPoint() {
|
|
43299
|
+
return new Vector2$1(
|
|
43300
|
+
this.position.x + this.getSize().x / 4,
|
|
43301
|
+
this.position.y + this.getSize().y / 2
|
|
43302
|
+
);
|
|
43303
|
+
}
|
|
43304
|
+
/**
|
|
43305
|
+
* Gets the north-north-west connection point of the element.
|
|
43306
|
+
* The point is positioned on the top edge, one-quarter of the width from the center towards the left.
|
|
43307
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-north-west point coordinates
|
|
43308
|
+
* where x is the element's center x-coordinate minus one-quarter of the width
|
|
43309
|
+
* and y is the element's top edge y-coordinate
|
|
43310
|
+
*/
|
|
43311
|
+
getNorthNorthWestPoint() {
|
|
43312
|
+
return new Vector2$1(
|
|
43313
|
+
this.position.x - this.getSize().x / 4,
|
|
43314
|
+
this.position.y + this.getSize().y / 2
|
|
43315
|
+
);
|
|
43316
|
+
}
|
|
43317
|
+
/**
|
|
43318
|
+
* Gets the north-east-east connection point of the element.
|
|
43319
|
+
* The point is positioned on the right edge, one-quarter of the height from the top.
|
|
43320
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-east-east point coordinates
|
|
43321
|
+
* where x is the element's right edge x-coordinate
|
|
43322
|
+
* and y is the element's top edge y-coordinate plus one-quarter of the height
|
|
43323
|
+
*/
|
|
43324
|
+
getNorthEastEastPoint() {
|
|
43325
|
+
return new Vector2$1(
|
|
43326
|
+
this.position.x + this.getSize().x / 2,
|
|
43327
|
+
this.position.y + this.getSize().y / 4
|
|
43328
|
+
);
|
|
43329
|
+
}
|
|
43330
|
+
/**
|
|
43331
|
+
* Gets the north-west-west connection point of the element.
|
|
43332
|
+
* The point is positioned on the left edge, one-quarter of the height from the top.
|
|
43333
|
+
* @returns {THREE.Vector2} A 2D vector representing the north-west-west point coordinates
|
|
43334
|
+
* where x is the element's left edge x-coordinate
|
|
43335
|
+
* and y is the element's top edge y-coordinate plus one-quarter of the height
|
|
43336
|
+
*/
|
|
43337
|
+
getNorthWestWestPoint() {
|
|
43338
|
+
return new Vector2$1(
|
|
43339
|
+
this.position.x - this.getSize().x / 2,
|
|
43340
|
+
this.position.y + this.getSize().y / 4
|
|
43341
|
+
);
|
|
43643
43342
|
}
|
|
43644
43343
|
/**
|
|
43645
|
-
*
|
|
43646
|
-
*
|
|
43647
|
-
* @returns {
|
|
43344
|
+
* Gets the south-south-east connection point of the element.
|
|
43345
|
+
* The point is positioned on the bottom edge, one-quarter of the width from the center towards the right.
|
|
43346
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-south-east point coordinates
|
|
43347
|
+
* where x is the element's center x-coordinate plus one-quarter of the width
|
|
43348
|
+
* and y is the element's bottom edge y-coordinate
|
|
43648
43349
|
*/
|
|
43649
|
-
|
|
43650
|
-
|
|
43651
|
-
|
|
43652
|
-
|
|
43653
|
-
this.setPosition(
|
|
43654
|
-
element2.position.x,
|
|
43655
|
-
// x
|
|
43656
|
-
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43657
|
-
// y
|
|
43658
|
-
0
|
|
43350
|
+
getSouthSouthEastPoint() {
|
|
43351
|
+
return new Vector2$1(
|
|
43352
|
+
this.position.x + this.getSize().x / 4,
|
|
43353
|
+
this.position.y - this.getSize().y / 2
|
|
43659
43354
|
);
|
|
43660
|
-
return this;
|
|
43661
43355
|
}
|
|
43662
43356
|
/**
|
|
43663
|
-
*
|
|
43664
|
-
*
|
|
43665
|
-
* @returns {
|
|
43357
|
+
* Gets the south-south-west connection point of the element.
|
|
43358
|
+
* The point is positioned on the bottom edge, one-quarter of the width from the center towards the left.
|
|
43359
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-south-west point coordinates
|
|
43360
|
+
* where x is the element's center x-coordinate minus one-quarter of the width
|
|
43361
|
+
* and y is the element's bottom edge y-coordinate
|
|
43666
43362
|
*/
|
|
43667
|
-
|
|
43668
|
-
|
|
43669
|
-
|
|
43670
|
-
|
|
43671
|
-
this.setPosition(
|
|
43672
|
-
element2.position.x,
|
|
43673
|
-
// x
|
|
43674
|
-
element2.position.y - elementHeight / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisHeight / 2,
|
|
43675
|
-
// y
|
|
43676
|
-
0
|
|
43363
|
+
getSouthSouthWestPoint() {
|
|
43364
|
+
return new Vector2$1(
|
|
43365
|
+
this.position.x - this.getSize().x / 4,
|
|
43366
|
+
this.position.y - this.getSize().y / 2
|
|
43677
43367
|
);
|
|
43678
|
-
return this;
|
|
43679
43368
|
}
|
|
43680
43369
|
/**
|
|
43681
|
-
*
|
|
43682
|
-
*
|
|
43683
|
-
* @returns {
|
|
43370
|
+
* Gets the south-east-east connection point of the element.
|
|
43371
|
+
* The point is positioned on the right edge, one-quarter of the height from the bottom.
|
|
43372
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-east-east point coordinates
|
|
43373
|
+
* where x is the element's right edge x-coordinate
|
|
43374
|
+
* and y is the element's bottom edge y-coordinate plus one-quarter of the height
|
|
43684
43375
|
*/
|
|
43685
|
-
|
|
43686
|
-
|
|
43687
|
-
|
|
43688
|
-
|
|
43689
|
-
const thisWidth = this.getSize().x;
|
|
43690
|
-
const thisHeight = this.getSize().y;
|
|
43691
|
-
this.setPosition(
|
|
43692
|
-
element2.position.x - elementWidth / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisWidth / 2,
|
|
43693
|
-
// x
|
|
43694
|
-
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43695
|
-
// y
|
|
43696
|
-
0
|
|
43376
|
+
getSouthEastEastPoint() {
|
|
43377
|
+
return new Vector2$1(
|
|
43378
|
+
this.position.x + this.getSize().x / 2,
|
|
43379
|
+
this.position.y - this.getSize().y / 4
|
|
43697
43380
|
);
|
|
43698
|
-
return this;
|
|
43699
43381
|
}
|
|
43700
43382
|
/**
|
|
43701
|
-
*
|
|
43702
|
-
*
|
|
43703
|
-
* @returns {
|
|
43383
|
+
* Gets the south-west-west connection point of the element.
|
|
43384
|
+
* The point is positioned on the left edge, one-quarter of the height from the bottom.
|
|
43385
|
+
* @returns {THREE.Vector2} A 2D vector representing the south-west-west point coordinates
|
|
43386
|
+
* where x is the element's left edge x-coordinate
|
|
43387
|
+
* and y is the element's bottom edge y-coordinate plus one-quarter of the height
|
|
43704
43388
|
*/
|
|
43705
|
-
|
|
43706
|
-
|
|
43707
|
-
|
|
43708
|
-
|
|
43709
|
-
const thisWidth = this.getSize().x;
|
|
43710
|
-
const thisHeight = this.getSize().y;
|
|
43711
|
-
this.setPosition(
|
|
43712
|
-
element2.position.x - elementWidth / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisWidth / 2,
|
|
43713
|
-
// x
|
|
43714
|
-
element2.position.y - elementHeight / 2 - DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS - thisHeight / 2,
|
|
43715
|
-
// y
|
|
43716
|
-
0
|
|
43389
|
+
getSouthWestWestPoint() {
|
|
43390
|
+
return new Vector2$1(
|
|
43391
|
+
this.position.x - this.getSize().x / 2,
|
|
43392
|
+
this.position.y - this.getSize().y / 4
|
|
43717
43393
|
);
|
|
43718
|
-
return this;
|
|
43719
43394
|
}
|
|
43720
43395
|
/**
|
|
43721
|
-
*
|
|
43722
|
-
* @param {string}
|
|
43396
|
+
* Gets the position of a connection point on the element.
|
|
43397
|
+
* @param {string} position - Position identifier (N, S, E, W, NE, NW, etc.)
|
|
43398
|
+
* @returns {THREE.Vector2} The connection point coordinates
|
|
43399
|
+
* @throws {Error} If the position identifier is invalid
|
|
43400
|
+
*/
|
|
43401
|
+
getPointPosition(position) {
|
|
43402
|
+
switch (position) {
|
|
43403
|
+
case "N":
|
|
43404
|
+
case "north":
|
|
43405
|
+
return this.getNorthPoint();
|
|
43406
|
+
case "S":
|
|
43407
|
+
case "south":
|
|
43408
|
+
return this.getSouthPoint();
|
|
43409
|
+
case "E":
|
|
43410
|
+
case "east":
|
|
43411
|
+
return this.getEastPoint();
|
|
43412
|
+
case "W":
|
|
43413
|
+
case "west":
|
|
43414
|
+
return this.getWestPoint();
|
|
43415
|
+
case "NE":
|
|
43416
|
+
case "northeast":
|
|
43417
|
+
return this.getNorthEastPoint();
|
|
43418
|
+
case "NW":
|
|
43419
|
+
case "northwest":
|
|
43420
|
+
return this.getNorthWestPoint();
|
|
43421
|
+
case "SE":
|
|
43422
|
+
case "southeast":
|
|
43423
|
+
return this.getSouthEastPoint();
|
|
43424
|
+
case "SW":
|
|
43425
|
+
case "southwest":
|
|
43426
|
+
return this.getSouthWestPoint();
|
|
43427
|
+
case "NNE":
|
|
43428
|
+
case "northnortheast":
|
|
43429
|
+
return this.getNorthNorthEastPoint();
|
|
43430
|
+
case "NNW":
|
|
43431
|
+
case "northnorthwest":
|
|
43432
|
+
return this.getNorthNorthWestPoint();
|
|
43433
|
+
case "NEE":
|
|
43434
|
+
case "northeast":
|
|
43435
|
+
return this.getNorthEastEastPoint();
|
|
43436
|
+
case "NWW":
|
|
43437
|
+
case "northwest":
|
|
43438
|
+
return this.getNorthWestWestPoint();
|
|
43439
|
+
case "SSE":
|
|
43440
|
+
case "southsoutheast":
|
|
43441
|
+
return this.getSouthSouthEastPoint();
|
|
43442
|
+
case "SSW":
|
|
43443
|
+
case "southsouthwest":
|
|
43444
|
+
return this.getSouthSouthWestPoint();
|
|
43445
|
+
case "SEE":
|
|
43446
|
+
case "southeast":
|
|
43447
|
+
return this.getSouthEastEastPoint();
|
|
43448
|
+
case "SWW":
|
|
43449
|
+
case "southwest":
|
|
43450
|
+
return this.getSouthWestWestPoint();
|
|
43451
|
+
default:
|
|
43452
|
+
throw new Error(`Unknown position: ${position}`);
|
|
43453
|
+
}
|
|
43454
|
+
}
|
|
43455
|
+
// ================================================================
|
|
43456
|
+
// Add Text methods
|
|
43457
|
+
// ================================================================
|
|
43458
|
+
/**
|
|
43459
|
+
* Adds text to the element.
|
|
43460
|
+
* @param {string} text - The text to add
|
|
43723
43461
|
* @returns {Element} This element for method chaining
|
|
43724
43462
|
*/
|
|
43725
|
-
|
|
43726
|
-
const
|
|
43727
|
-
|
|
43728
|
-
|
|
43729
|
-
const thisWidth = this.getSize().x;
|
|
43730
|
-
const thisHeight = this.getSize().y;
|
|
43731
|
-
this.setPosition(
|
|
43732
|
-
element2.position.x + elementWidth / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisWidth / 2,
|
|
43733
|
-
// x
|
|
43734
|
-
element2.position.y + elementHeight / 2 + DiagramDimensions.DISTANCE_BETWEEN_ELEMENTS + thisHeight / 2,
|
|
43735
|
-
// y
|
|
43736
|
-
0
|
|
43737
|
-
);
|
|
43463
|
+
addText(text) {
|
|
43464
|
+
const textElement = new Element(this.elementId + "_text", new TextShape(text));
|
|
43465
|
+
this.diagram.addElement(textElement).positionAt(this.position);
|
|
43466
|
+
this.texts.push({ element: textElement, positionOffset: new Vector3$1(0, 0, 0) });
|
|
43738
43467
|
return this;
|
|
43739
43468
|
}
|
|
43740
43469
|
/**
|
|
43741
|
-
*
|
|
43742
|
-
* @param {string}
|
|
43470
|
+
* Adds wrapped text that fits within the element's bounds.
|
|
43471
|
+
* @param {string} text - The text to add and wrap
|
|
43472
|
+
* @param {THREE.Vector3} [offset=new THREE.Vector3(0, 0, 3)] - Optional offset for the text position
|
|
43743
43473
|
* @returns {Element} This element for method chaining
|
|
43744
43474
|
*/
|
|
43745
|
-
|
|
43746
|
-
|
|
43747
|
-
|
|
43748
|
-
|
|
43749
|
-
|
|
43750
|
-
|
|
43751
|
-
this.
|
|
43752
|
-
|
|
43753
|
-
|
|
43754
|
-
|
|
43755
|
-
|
|
43756
|
-
|
|
43757
|
-
|
|
43475
|
+
addWrappedText(text, offset = new Vector3$1(0, 0, 3)) {
|
|
43476
|
+
if (!text) {
|
|
43477
|
+
console.warn("addWrappedText: text is null or undefined");
|
|
43478
|
+
return this;
|
|
43479
|
+
}
|
|
43480
|
+
let wrappedText = text.replace(/\s+/g, "\n");
|
|
43481
|
+
let wrappedTextElement = new Element(this.elementId + "_text", new TextShape(wrappedText));
|
|
43482
|
+
let candidateTextElement;
|
|
43483
|
+
while (true) {
|
|
43484
|
+
let words = wrappedText.split("\n");
|
|
43485
|
+
let minLength = Infinity;
|
|
43486
|
+
let minIndex = -1;
|
|
43487
|
+
for (let i = 0; i < words.length - 1; i++) {
|
|
43488
|
+
let combinedLength = words[i].length + words[i + 1].length;
|
|
43489
|
+
if (combinedLength < minLength) {
|
|
43490
|
+
minLength = combinedLength;
|
|
43491
|
+
minIndex = i;
|
|
43492
|
+
}
|
|
43493
|
+
}
|
|
43494
|
+
if (minIndex === -1) break;
|
|
43495
|
+
words[minIndex] = words[minIndex] + " " + words[minIndex + 1];
|
|
43496
|
+
words.splice(minIndex + 1, 1);
|
|
43497
|
+
wrappedText = words.join("\n");
|
|
43498
|
+
candidateTextElement = new Element(this.elementId + "_text", new TextShape(wrappedText));
|
|
43499
|
+
if (candidateTextElement.getSize().x <= this.getSize().x * 0.9) {
|
|
43500
|
+
wrappedTextElement = candidateTextElement;
|
|
43501
|
+
} else {
|
|
43502
|
+
break;
|
|
43503
|
+
}
|
|
43504
|
+
}
|
|
43505
|
+
this.diagram.addElement(wrappedTextElement).positionAt({
|
|
43506
|
+
x: this.position.x + offset.x,
|
|
43507
|
+
y: this.position.y + offset.y,
|
|
43508
|
+
z: this.position.z + offset.z
|
|
43509
|
+
});
|
|
43510
|
+
this.texts.push({ element: wrappedTextElement, positionOffset: offset });
|
|
43758
43511
|
return this;
|
|
43759
43512
|
}
|
|
43760
|
-
//
|
|
43761
|
-
//
|
|
43762
|
-
// (N, S, E, W, NNE, NNW, NEE, NWW, SEE, SWW, SSE, SSW)
|
|
43763
|
-
// for connectors to connect to
|
|
43513
|
+
// ================================================================
|
|
43514
|
+
// Add icons methods
|
|
43764
43515
|
// ================================================================
|
|
43765
43516
|
/**
|
|
43766
|
-
* Gets the
|
|
43767
|
-
* The
|
|
43768
|
-
*
|
|
43517
|
+
* Gets the placeholder position for an icon at the top of the element.
|
|
43518
|
+
* The position is calculated by taking the element's top edge and offsetting it inward
|
|
43519
|
+
* by half the icon size plus padding.
|
|
43520
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43769
43521
|
* where x is the element's center x-coordinate
|
|
43770
|
-
* and y is the element's top edge y-coordinate
|
|
43522
|
+
* and y is the element's top edge y-coordinate minus (icon size/2 + padding)
|
|
43771
43523
|
*/
|
|
43772
|
-
|
|
43524
|
+
getTopIconPlaceholder() {
|
|
43773
43525
|
return new Vector2$1(
|
|
43774
43526
|
this.position.x,
|
|
43775
|
-
this.position.y + this.getSize().y / 2
|
|
43527
|
+
this.position.y + this.getSize().y / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING
|
|
43776
43528
|
);
|
|
43777
43529
|
}
|
|
43778
43530
|
/**
|
|
43779
|
-
* Gets the
|
|
43780
|
-
* The
|
|
43781
|
-
*
|
|
43531
|
+
* Gets the placeholder position for an icon at the bottom of the element.
|
|
43532
|
+
* The position is calculated by taking the element's bottom edge and offsetting it inward
|
|
43533
|
+
* by half the icon size plus padding.
|
|
43534
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43782
43535
|
* where x is the element's center x-coordinate
|
|
43783
|
-
* and y is the element's bottom edge y-coordinate
|
|
43536
|
+
* and y is the element's bottom edge y-coordinate plus (icon size/2 + padding)
|
|
43784
43537
|
*/
|
|
43785
|
-
|
|
43538
|
+
getBottomIconPlaceholder() {
|
|
43786
43539
|
return new Vector2$1(
|
|
43787
43540
|
this.position.x,
|
|
43788
|
-
this.position.y - this.getSize().y / 2
|
|
43541
|
+
this.position.y - this.getSize().y / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING
|
|
43789
43542
|
);
|
|
43790
43543
|
}
|
|
43791
43544
|
/**
|
|
43792
|
-
* Gets the
|
|
43793
|
-
* The
|
|
43794
|
-
*
|
|
43795
|
-
*
|
|
43545
|
+
* Gets the placeholder position for an icon at the left of the element.
|
|
43546
|
+
* The position is calculated by taking the element's left edge and offsetting it inward
|
|
43547
|
+
* by half the icon size plus padding.
|
|
43548
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43549
|
+
* where x is the element's left edge x-coordinate plus (icon size/2 + padding)
|
|
43796
43550
|
* and y is the element's center y-coordinate
|
|
43797
43551
|
*/
|
|
43798
|
-
|
|
43552
|
+
getLeftIconPlaceholder() {
|
|
43799
43553
|
return new Vector2$1(
|
|
43800
|
-
this.position.x
|
|
43554
|
+
this.position.x - this.getSize().x / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING,
|
|
43801
43555
|
this.position.y
|
|
43802
43556
|
);
|
|
43803
43557
|
}
|
|
43804
43558
|
/**
|
|
43805
|
-
* Gets the
|
|
43806
|
-
* The
|
|
43807
|
-
*
|
|
43808
|
-
*
|
|
43559
|
+
* Gets the placeholder position for an icon at the right of the element.
|
|
43560
|
+
* The position is calculated by taking the element's right edge and offsetting it inward
|
|
43561
|
+
* by half the icon size plus padding.
|
|
43562
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43563
|
+
* where x is the element's right edge x-coordinate minus (icon size/2 + padding)
|
|
43809
43564
|
* and y is the element's center y-coordinate
|
|
43810
43565
|
*/
|
|
43811
|
-
|
|
43566
|
+
getRightIconPlaceholder() {
|
|
43812
43567
|
return new Vector2$1(
|
|
43813
|
-
this.position.x
|
|
43568
|
+
this.position.x + this.getSize().x / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING,
|
|
43814
43569
|
this.position.y
|
|
43815
43570
|
);
|
|
43816
43571
|
}
|
|
43817
43572
|
/**
|
|
43818
|
-
* Gets the
|
|
43819
|
-
* The
|
|
43820
|
-
*
|
|
43821
|
-
*
|
|
43822
|
-
*
|
|
43573
|
+
* Gets the placeholder position for an icon at the top-left corner of the element.
|
|
43574
|
+
* The position is calculated by taking the element's top-left corner and offsetting it inward
|
|
43575
|
+
* by half the icon size plus padding along both axes.
|
|
43576
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43577
|
+
* where x is the element's left edge x-coordinate plus (icon size/2 + padding)
|
|
43578
|
+
* and y is the element's top edge y-coordinate minus (icon size/2 + padding)
|
|
43823
43579
|
*/
|
|
43824
|
-
|
|
43580
|
+
getTopLeftIconPlaceholder() {
|
|
43825
43581
|
return new Vector2$1(
|
|
43826
|
-
this.position.x
|
|
43827
|
-
this.position.y + this.getSize().y / 2
|
|
43582
|
+
this.position.x - this.getSize().x / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING,
|
|
43583
|
+
this.position.y + this.getSize().y / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING
|
|
43828
43584
|
);
|
|
43829
43585
|
}
|
|
43830
43586
|
/**
|
|
43831
|
-
* Gets the
|
|
43832
|
-
* The
|
|
43833
|
-
*
|
|
43834
|
-
*
|
|
43835
|
-
*
|
|
43587
|
+
* Gets the placeholder position for an icon at the top-right corner of the element.
|
|
43588
|
+
* The position is calculated by taking the element's top-right corner and offsetting it inward
|
|
43589
|
+
* by half the icon size plus padding along both axes.
|
|
43590
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43591
|
+
* where x is the element's right edge x-coordinate minus (icon size/2 + padding)
|
|
43592
|
+
* and y is the element's top edge y-coordinate minus (icon size/2 + padding)
|
|
43836
43593
|
*/
|
|
43837
|
-
|
|
43594
|
+
getTopRightIconPlaceholder() {
|
|
43838
43595
|
return new Vector2$1(
|
|
43839
|
-
this.position.x
|
|
43840
|
-
this.position.y + this.getSize().y / 2
|
|
43596
|
+
this.position.x + this.getSize().x / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING,
|
|
43597
|
+
this.position.y + this.getSize().y / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING
|
|
43841
43598
|
);
|
|
43842
43599
|
}
|
|
43843
43600
|
/**
|
|
43844
|
-
* Gets the
|
|
43845
|
-
* The
|
|
43846
|
-
*
|
|
43847
|
-
*
|
|
43848
|
-
*
|
|
43601
|
+
* Gets the placeholder position for an icon at the bottom-left corner of the element.
|
|
43602
|
+
* The position is calculated by taking the element's bottom-left corner and offsetting it inward
|
|
43603
|
+
* by half the icon size plus padding along both axes.
|
|
43604
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43605
|
+
* where x is the element's left edge x-coordinate plus (icon size/2 + padding)
|
|
43606
|
+
* and y is the element's bottom edge y-coordinate plus (icon size/2 + padding)
|
|
43849
43607
|
*/
|
|
43850
|
-
|
|
43608
|
+
getBottomLeftIconPlaceholder() {
|
|
43851
43609
|
return new Vector2$1(
|
|
43852
|
-
this.position.x
|
|
43853
|
-
this.position.y - this.getSize().y / 2
|
|
43610
|
+
this.position.x - this.getSize().x / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING,
|
|
43611
|
+
this.position.y - this.getSize().y / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING
|
|
43854
43612
|
);
|
|
43855
43613
|
}
|
|
43856
43614
|
/**
|
|
43857
|
-
* Gets the
|
|
43858
|
-
* The
|
|
43859
|
-
*
|
|
43860
|
-
*
|
|
43861
|
-
*
|
|
43615
|
+
* Gets the placeholder position for an icon at the bottom-right corner of the element.
|
|
43616
|
+
* The position is calculated by taking the element's bottom-right corner and offsetting it inward
|
|
43617
|
+
* by half the icon size plus padding along both axes.
|
|
43618
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43619
|
+
* where x is the element's right edge x-coordinate minus (icon size/2 + padding)
|
|
43620
|
+
* and y is the element's bottom edge y-coordinate plus (icon size/2 + padding)
|
|
43862
43621
|
*/
|
|
43863
|
-
|
|
43622
|
+
getBottomRightIconPlaceholder() {
|
|
43864
43623
|
return new Vector2$1(
|
|
43865
|
-
this.position.x
|
|
43866
|
-
this.position.y - this.getSize().y / 2
|
|
43624
|
+
this.position.x + this.getSize().x / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING,
|
|
43625
|
+
this.position.y - this.getSize().y / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING
|
|
43867
43626
|
);
|
|
43868
43627
|
}
|
|
43869
43628
|
/**
|
|
43870
|
-
* Gets the
|
|
43871
|
-
* The
|
|
43872
|
-
* @returns {THREE.Vector2} A 2D vector representing the
|
|
43873
|
-
* where x is the element's center x-coordinate
|
|
43874
|
-
* and y is the element's
|
|
43629
|
+
* Gets the placeholder position for an icon at the center of the element.
|
|
43630
|
+
* The position is at the element's center.
|
|
43631
|
+
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
43632
|
+
* where x is the element's center x-coordinate
|
|
43633
|
+
* and y is the element's center y-coordinate
|
|
43634
|
+
*/
|
|
43635
|
+
getCenterIconPlaceholder() {
|
|
43636
|
+
return new Vector2$1(this.position.x, this.position.y);
|
|
43637
|
+
}
|
|
43638
|
+
/**
|
|
43639
|
+
* Gets the position for an icon placeholder.
|
|
43640
|
+
* @param {string} position - Position identifier (top, bottom, left, right, etc.)
|
|
43641
|
+
* @returns {THREE.Vector2} The placeholder position
|
|
43642
|
+
* @throws {Error} If the position identifier is invalid
|
|
43643
|
+
*/
|
|
43644
|
+
getIconPlaceholder(position) {
|
|
43645
|
+
switch (position) {
|
|
43646
|
+
case "top":
|
|
43647
|
+
return this.getTopIconPlaceholder();
|
|
43648
|
+
case "bottom":
|
|
43649
|
+
return this.getBottomIconPlaceholder();
|
|
43650
|
+
case "left":
|
|
43651
|
+
return this.getLeftIconPlaceholder();
|
|
43652
|
+
case "right":
|
|
43653
|
+
return this.getRightIconPlaceholder();
|
|
43654
|
+
case "top-left":
|
|
43655
|
+
return this.getTopLeftIconPlaceholder();
|
|
43656
|
+
case "top-right":
|
|
43657
|
+
return this.getTopRightIconPlaceholder();
|
|
43658
|
+
case "bottom-left":
|
|
43659
|
+
return this.getBottomLeftIconPlaceholder();
|
|
43660
|
+
case "bottom-right":
|
|
43661
|
+
return this.getBottomRightIconPlaceholder();
|
|
43662
|
+
case "center":
|
|
43663
|
+
return this.getCenterIconPlaceholder();
|
|
43664
|
+
default:
|
|
43665
|
+
throw new Error(`Unknown icon position: ${position}`);
|
|
43666
|
+
}
|
|
43667
|
+
}
|
|
43668
|
+
/**
|
|
43669
|
+
* Adds an icon to the element.
|
|
43670
|
+
* @param {string} icon - The icon identifier
|
|
43671
|
+
* @param {string} [placeholder='center'] - Position of the icon
|
|
43672
|
+
* @param {number} [size=IconDimensions.ICON_SIZE_MEDIUM] - Size of the icon
|
|
43673
|
+
* @returns {Element} This element for method chaining
|
|
43674
|
+
*/
|
|
43675
|
+
addIcon(icon, placeholder = "center", size = IconDimensions.ICON_SIZE_MEDIUM) {
|
|
43676
|
+
let position;
|
|
43677
|
+
if (typeof placeholder === "string") {
|
|
43678
|
+
position = this.getIconPlaceholder(placeholder);
|
|
43679
|
+
}
|
|
43680
|
+
const iconElement = new Element(this.elementId + "_icon_placeholder", new IconShape(icon, size));
|
|
43681
|
+
this.diagram.addElement(iconElement).positionAt(position);
|
|
43682
|
+
this.icons.push({ element: iconElement, positionOffset: new Vector3$1(position.x - this.position.x, position.y - this.position.y, 0) });
|
|
43683
|
+
return this;
|
|
43684
|
+
}
|
|
43685
|
+
// ================================================================
|
|
43686
|
+
// Add Analysis methods
|
|
43687
|
+
// ================================================================
|
|
43688
|
+
/**
|
|
43689
|
+
* Adds a value bar for analysis mode.
|
|
43690
|
+
* @param {number} value - The value to represent (must be positive)
|
|
43691
|
+
* @returns {Element} This element for method chaining
|
|
43692
|
+
*/
|
|
43693
|
+
addValueBar(value) {
|
|
43694
|
+
this.parameters["value"] = value;
|
|
43695
|
+
return this;
|
|
43696
|
+
}
|
|
43697
|
+
// ================================================================
|
|
43698
|
+
// Add connecting methods
|
|
43699
|
+
// ================================================================
|
|
43700
|
+
/**
|
|
43701
|
+
* Creates a connector from another element to this element.
|
|
43702
|
+
* @param {string} sourceElementId - ID of the source element
|
|
43703
|
+
* @param {string} sourcePosition - Connection point on the source element
|
|
43704
|
+
* @param {string} targetPosition - Connection point on this element
|
|
43705
|
+
* @returns {Element} This element for method chaining
|
|
43706
|
+
* @throws {Error} If the diagram is not set or source element is not found
|
|
43707
|
+
*/
|
|
43708
|
+
connectFrom(sourceElementId, sourcePosition, targetPosition) {
|
|
43709
|
+
if (!this.diagram) {
|
|
43710
|
+
throw new Error("Diagram is not set for this element.");
|
|
43711
|
+
}
|
|
43712
|
+
const targetElement = this;
|
|
43713
|
+
const sourceElement = this.diagram.getElementById(sourceElementId);
|
|
43714
|
+
if (!sourceElement) {
|
|
43715
|
+
throw new Error(`Element with ID ${sourceElementId} not found.`);
|
|
43716
|
+
}
|
|
43717
|
+
const sourcePoint = sourceElement.getPointPosition(sourcePosition);
|
|
43718
|
+
const targetPoint = targetElement.getPointPosition(targetPosition);
|
|
43719
|
+
const points = Connector.determinePoints(sourcePoint, targetPoint, sourcePosition, targetPosition);
|
|
43720
|
+
this.diagram.addConnector(new Connector(
|
|
43721
|
+
`connector-${sourceElement.elementId}-${targetElement.elementId}`,
|
|
43722
|
+
new RoundedCornerOrthogonalConnectorShape(points)
|
|
43723
|
+
));
|
|
43724
|
+
return this;
|
|
43725
|
+
}
|
|
43726
|
+
}
|
|
43727
|
+
function getColorForValue(value, min2, max2) {
|
|
43728
|
+
console.log(`Calculating color for: value=${value}, min=${min2}, max=${max2}`);
|
|
43729
|
+
const color2 = new Color$1();
|
|
43730
|
+
if (min2 === max2) {
|
|
43731
|
+
color2.setHSL(0.25, 1, 0.5);
|
|
43732
|
+
return color2;
|
|
43733
|
+
}
|
|
43734
|
+
let ratio = (value - min2) / (max2 - min2);
|
|
43735
|
+
ratio = Math.max(0, Math.min(ratio, 1));
|
|
43736
|
+
console.log(`Calculated Ratio: ${ratio}`);
|
|
43737
|
+
const hue = ratio * (120 / 360);
|
|
43738
|
+
color2.setHSL(hue, 1, 0.5);
|
|
43739
|
+
return color2;
|
|
43740
|
+
}
|
|
43741
|
+
class Diagram {
|
|
43742
|
+
/**
|
|
43743
|
+
* Creates a new Diagram instance.
|
|
43744
|
+
* @param {HTMLElement} container - The HTML container element for the diagram.
|
|
43745
|
+
*/
|
|
43746
|
+
constructor(container) {
|
|
43747
|
+
this.elements = [];
|
|
43748
|
+
this.connectors = [];
|
|
43749
|
+
this.mode = "VIEW";
|
|
43750
|
+
this.helpers = false;
|
|
43751
|
+
this.container = container;
|
|
43752
|
+
this.initScene();
|
|
43753
|
+
this.initCamera();
|
|
43754
|
+
this.setHelpers();
|
|
43755
|
+
this.initRenderer();
|
|
43756
|
+
this.initLighting();
|
|
43757
|
+
this.initControls();
|
|
43758
|
+
this.addEventListeners();
|
|
43759
|
+
this.animate();
|
|
43760
|
+
console.log("THREE", THREE);
|
|
43761
|
+
console.log(this);
|
|
43762
|
+
}
|
|
43763
|
+
/**
|
|
43764
|
+
* Initializes the THREE.js scene.
|
|
43765
|
+
*/
|
|
43766
|
+
initScene() {
|
|
43767
|
+
this.scene = new Scene();
|
|
43768
|
+
this.scene.background = new Color$1(15790320);
|
|
43769
|
+
}
|
|
43770
|
+
/**
|
|
43771
|
+
* Initializes the camera with a perspective projection.
|
|
43772
|
+
*/
|
|
43773
|
+
initCamera() {
|
|
43774
|
+
const aspectRatio = this.container.clientWidth / this.container.clientHeight;
|
|
43775
|
+
this.camera = new PerspectiveCamera(75, aspectRatio, 0.1, 2e3);
|
|
43776
|
+
this.camera.position.set(0, 0, 500);
|
|
43777
|
+
this.camera.updateProjectionMatrix();
|
|
43778
|
+
}
|
|
43779
|
+
// initCamera() { // Orthographic
|
|
43780
|
+
// // const aspectRatio = this.container.clientWidth / window.innerHeight;
|
|
43781
|
+
// const aspectRatio = window.innerWidth / window.innerHeight;
|
|
43782
|
+
// const frustumSize = 100;
|
|
43783
|
+
// this.camera = new THREE.OrthographicCamera(
|
|
43784
|
+
// frustumSize * aspectRatio / -2,
|
|
43785
|
+
// frustumSize * aspectRatio / 2,
|
|
43786
|
+
// frustumSize / 2,
|
|
43787
|
+
// frustumSize / -2,
|
|
43788
|
+
// 0.1,
|
|
43789
|
+
// 1000
|
|
43790
|
+
// );
|
|
43791
|
+
// this.camera.position.set(0, 0, 50);
|
|
43792
|
+
// }
|
|
43793
|
+
/**
|
|
43794
|
+
* Sets up helpers (axes, grid, etc.) for the scene.
|
|
43875
43795
|
*/
|
|
43876
|
-
|
|
43877
|
-
|
|
43878
|
-
|
|
43879
|
-
|
|
43880
|
-
|
|
43796
|
+
setHelpers() {
|
|
43797
|
+
this.axesHelper = new AxesHelper(100);
|
|
43798
|
+
this.cameraHelper = new CameraHelper(this.camera);
|
|
43799
|
+
const size = 400;
|
|
43800
|
+
const divisions = 50;
|
|
43801
|
+
this.gridHelper = new GridHelper(size, divisions);
|
|
43802
|
+
this.cameraDirection = new Vector3$1();
|
|
43803
|
+
this.camPositionSpan = document.querySelector("#position");
|
|
43804
|
+
this.camLookAtSpan = document.querySelector("#lookingAt");
|
|
43805
|
+
this.helpers = false;
|
|
43881
43806
|
}
|
|
43882
43807
|
/**
|
|
43883
|
-
*
|
|
43884
|
-
* The point is positioned on the top edge, one-quarter of the width from the center towards the left.
|
|
43885
|
-
* @returns {THREE.Vector2} A 2D vector representing the north-north-west point coordinates
|
|
43886
|
-
* where x is the element's center x-coordinate minus one-quarter of the width
|
|
43887
|
-
* and y is the element's top edge y-coordinate
|
|
43808
|
+
* Shows the helpers in the scene.
|
|
43888
43809
|
*/
|
|
43889
|
-
|
|
43890
|
-
|
|
43891
|
-
this.
|
|
43892
|
-
this.
|
|
43893
|
-
|
|
43810
|
+
showHelpers() {
|
|
43811
|
+
if (!this.helpers) {
|
|
43812
|
+
this.scene.add(this.axesHelper);
|
|
43813
|
+
this.scene.add(this.cameraHelper);
|
|
43814
|
+
this.scene.add(this.gridHelper);
|
|
43815
|
+
this.helpers = true;
|
|
43816
|
+
}
|
|
43894
43817
|
}
|
|
43895
43818
|
/**
|
|
43896
|
-
*
|
|
43897
|
-
* The point is positioned on the right edge, one-quarter of the height from the top.
|
|
43898
|
-
* @returns {THREE.Vector2} A 2D vector representing the north-east-east point coordinates
|
|
43899
|
-
* where x is the element's right edge x-coordinate
|
|
43900
|
-
* and y is the element's top edge y-coordinate plus one-quarter of the height
|
|
43819
|
+
* Hides the helpers in the scene.
|
|
43901
43820
|
*/
|
|
43902
|
-
|
|
43903
|
-
|
|
43904
|
-
this.
|
|
43905
|
-
this.
|
|
43906
|
-
|
|
43821
|
+
hideHelpers() {
|
|
43822
|
+
if (this.helpers) {
|
|
43823
|
+
this.scene.remove(this.axesHelper);
|
|
43824
|
+
this.scene.remove(this.cameraHelper);
|
|
43825
|
+
this.scene.remove(this.gridHelper);
|
|
43826
|
+
this.helpers = false;
|
|
43827
|
+
}
|
|
43907
43828
|
}
|
|
43908
43829
|
/**
|
|
43909
|
-
*
|
|
43910
|
-
* The point is positioned on the left edge, one-quarter of the height from the top.
|
|
43911
|
-
* @returns {THREE.Vector2} A 2D vector representing the north-west-west point coordinates
|
|
43912
|
-
* where x is the element's left edge x-coordinate
|
|
43913
|
-
* and y is the element's top edge y-coordinate plus one-quarter of the height
|
|
43830
|
+
* Initializes the renderer and attaches it to the container.
|
|
43914
43831
|
*/
|
|
43915
|
-
|
|
43916
|
-
|
|
43917
|
-
|
|
43918
|
-
|
|
43919
|
-
);
|
|
43832
|
+
initRenderer() {
|
|
43833
|
+
this.renderer = new WebGLRenderer({ antialias: true });
|
|
43834
|
+
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
|
|
43835
|
+
this.container.appendChild(this.renderer.domElement);
|
|
43836
|
+
console.log("initRenderer", this.container, this.renderer.domElement);
|
|
43920
43837
|
}
|
|
43921
43838
|
/**
|
|
43922
|
-
*
|
|
43923
|
-
* The point is positioned on the bottom edge, one-quarter of the width from the center towards the right.
|
|
43924
|
-
* @returns {THREE.Vector2} A 2D vector representing the south-south-east point coordinates
|
|
43925
|
-
* where x is the element's center x-coordinate plus one-quarter of the width
|
|
43926
|
-
* and y is the element's bottom edge y-coordinate
|
|
43839
|
+
* Initializes the lighting for the scene.
|
|
43927
43840
|
*/
|
|
43928
|
-
|
|
43929
|
-
|
|
43930
|
-
|
|
43931
|
-
|
|
43932
|
-
|
|
43841
|
+
initLighting() {
|
|
43842
|
+
let mainLightColor = 16777215;
|
|
43843
|
+
let mainLightIntensity = 4;
|
|
43844
|
+
let mainLightDistance = 0;
|
|
43845
|
+
let mainLightDecay = 0;
|
|
43846
|
+
const mainLight = new PointLight(mainLightColor, mainLightIntensity, mainLightDistance, mainLightDecay);
|
|
43847
|
+
let mainLightPosX = -1 * (580 / 2) + 1 / 3 * 580;
|
|
43848
|
+
let mainLightPosY = -1 * 209 * 4;
|
|
43849
|
+
let mainLightPosZ = Math.abs(mainLightPosY);
|
|
43850
|
+
mainLight.position.set(mainLightPosX, mainLightPosY, mainLightPosZ);
|
|
43851
|
+
this.scene.add(mainLight);
|
|
43852
|
+
this.spotLight = new PointLight(16777215, 4, 0, 0);
|
|
43853
|
+
this.spotLightPosX = 0;
|
|
43854
|
+
this.spotLightPosY = -1 * 209 - 300;
|
|
43855
|
+
this.spotLightPosZ = 70;
|
|
43856
|
+
this.scene.add(this.spotLight);
|
|
43857
|
+
this.spotLightDirection = 1;
|
|
43933
43858
|
}
|
|
43934
43859
|
/**
|
|
43935
|
-
*
|
|
43936
|
-
* The point is positioned on the bottom edge, one-quarter of the width from the center towards the left.
|
|
43937
|
-
* @returns {THREE.Vector2} A 2D vector representing the south-south-west point coordinates
|
|
43938
|
-
* where x is the element's center x-coordinate minus one-quarter of the width
|
|
43939
|
-
* and y is the element's bottom edge y-coordinate
|
|
43860
|
+
* Initializes the controls for the camera.
|
|
43940
43861
|
*/
|
|
43941
|
-
|
|
43942
|
-
|
|
43943
|
-
|
|
43944
|
-
|
|
43945
|
-
|
|
43862
|
+
initControls() {
|
|
43863
|
+
this.controls = new MapControls(this.camera, this.renderer.domElement);
|
|
43864
|
+
this.controls.enableDamping = true;
|
|
43865
|
+
this.controls.dampingFactor = 0.1;
|
|
43866
|
+
this.controls.screenSpacePanning = true;
|
|
43867
|
+
this.controls.zoomToCursor = true;
|
|
43868
|
+
this.controls.saveState();
|
|
43946
43869
|
}
|
|
43947
43870
|
/**
|
|
43948
|
-
*
|
|
43949
|
-
* The point is positioned on the right edge, one-quarter of the height from the bottom.
|
|
43950
|
-
* @returns {THREE.Vector2} A 2D vector representing the south-east-east point coordinates
|
|
43951
|
-
* where x is the element's right edge x-coordinate
|
|
43952
|
-
* and y is the element's bottom edge y-coordinate plus one-quarter of the height
|
|
43871
|
+
* Adds event listeners for window resize and other interactions.
|
|
43953
43872
|
*/
|
|
43954
|
-
|
|
43955
|
-
|
|
43956
|
-
this.position.x + this.getSize().x / 2,
|
|
43957
|
-
this.position.y - this.getSize().y / 4
|
|
43958
|
-
);
|
|
43873
|
+
addEventListeners() {
|
|
43874
|
+
window.addEventListener("resize", this.onWindowResize.bind(this), false);
|
|
43959
43875
|
}
|
|
43876
|
+
// onDocumentMouseDown(event) {
|
|
43877
|
+
// this.isDragging = true;
|
|
43878
|
+
// this.previousMousePosition = { x: event.offsetX, y: event.offsetY };
|
|
43879
|
+
// }
|
|
43880
|
+
// onDocumentMouseMove(event) {
|
|
43881
|
+
// if (this.isDragging && this.mugGroup) {
|
|
43882
|
+
// const deltaMove = {
|
|
43883
|
+
// x: event.offsetX - this.previousMousePosition.x,
|
|
43884
|
+
// y: event.offsetY - this.previousMousePosition.y
|
|
43885
|
+
// };
|
|
43886
|
+
// let rotateAngleX = this.toRadians(deltaMove.y * 1);
|
|
43887
|
+
// let rotateAngleY = this.toRadians(deltaMove.x * 1);
|
|
43888
|
+
// this.currentRotation = this.currentRotation || { x: 0, y: 0 };
|
|
43889
|
+
// this.currentRotation.x += rotateAngleX;
|
|
43890
|
+
// this.currentRotation.y += rotateAngleY;
|
|
43891
|
+
// const maxRotation = Math.PI / 2;
|
|
43892
|
+
// this.currentRotation.x = Math.min(Math.max(this.currentRotation.x, -maxRotation), maxRotation);
|
|
43893
|
+
// this.pivotGroup.rotation.x = this.currentRotation.x;
|
|
43894
|
+
// this.pivotGroup.rotation.y = this.currentRotation.y;
|
|
43895
|
+
// this.previousMousePosition = { x: event.offsetX, y: event.offsetY };
|
|
43896
|
+
// }
|
|
43897
|
+
// }
|
|
43898
|
+
// onDocumentMouseUp() {
|
|
43899
|
+
// this.isDragging = false;
|
|
43900
|
+
// }
|
|
43901
|
+
// toRadians(angle) {
|
|
43902
|
+
// return angle * (Math.PI / 180);
|
|
43903
|
+
// }
|
|
43960
43904
|
/**
|
|
43961
|
-
*
|
|
43962
|
-
* The point is positioned on the left edge, one-quarter of the height from the bottom.
|
|
43963
|
-
* @returns {THREE.Vector2} A 2D vector representing the south-west-west point coordinates
|
|
43964
|
-
* where x is the element's left edge x-coordinate
|
|
43965
|
-
* and y is the element's bottom edge y-coordinate plus one-quarter of the height
|
|
43905
|
+
* Handles window resize events to update the camera and renderer.
|
|
43966
43906
|
*/
|
|
43967
|
-
|
|
43968
|
-
|
|
43969
|
-
|
|
43970
|
-
|
|
43971
|
-
);
|
|
43907
|
+
onWindowResize() {
|
|
43908
|
+
const width = this.container.clientWidth;
|
|
43909
|
+
const height = this.container.clientHeight;
|
|
43910
|
+
this.camera.aspect = width / height;
|
|
43911
|
+
this.camera.updateProjectionMatrix();
|
|
43912
|
+
this.renderer.setSize(width, height);
|
|
43972
43913
|
}
|
|
43973
43914
|
/**
|
|
43974
|
-
*
|
|
43975
|
-
* @param {string} position - Position identifier (N, S, E, W, NE, NW, etc.)
|
|
43976
|
-
* @returns {THREE.Vector2} The connection point coordinates
|
|
43977
|
-
* @throws {Error} If the position identifier is invalid
|
|
43915
|
+
* Animates the scene and updates controls.
|
|
43978
43916
|
*/
|
|
43979
|
-
|
|
43980
|
-
|
|
43981
|
-
|
|
43982
|
-
|
|
43983
|
-
|
|
43984
|
-
|
|
43985
|
-
|
|
43986
|
-
|
|
43987
|
-
|
|
43988
|
-
|
|
43989
|
-
|
|
43990
|
-
|
|
43991
|
-
|
|
43992
|
-
|
|
43993
|
-
|
|
43994
|
-
|
|
43995
|
-
|
|
43996
|
-
|
|
43997
|
-
|
|
43998
|
-
|
|
43999
|
-
|
|
44000
|
-
|
|
44001
|
-
|
|
44002
|
-
|
|
44003
|
-
|
|
44004
|
-
|
|
44005
|
-
|
|
44006
|
-
|
|
44007
|
-
|
|
44008
|
-
case "NNW":
|
|
44009
|
-
case "northnorthwest":
|
|
44010
|
-
return this.getNorthNorthWestPoint();
|
|
44011
|
-
case "NEE":
|
|
44012
|
-
case "northeast":
|
|
44013
|
-
return this.getNorthEastEastPoint();
|
|
44014
|
-
case "NWW":
|
|
44015
|
-
case "northwest":
|
|
44016
|
-
return this.getNorthWestWestPoint();
|
|
44017
|
-
case "SSE":
|
|
44018
|
-
case "southsoutheast":
|
|
44019
|
-
return this.getSouthSouthEastPoint();
|
|
44020
|
-
case "SSW":
|
|
44021
|
-
case "southsouthwest":
|
|
44022
|
-
return this.getSouthSouthWestPoint();
|
|
44023
|
-
case "SEE":
|
|
44024
|
-
case "southeast":
|
|
44025
|
-
return this.getSouthEastEastPoint();
|
|
44026
|
-
case "SWW":
|
|
44027
|
-
case "southwest":
|
|
44028
|
-
return this.getSouthWestWestPoint();
|
|
44029
|
-
default:
|
|
44030
|
-
throw new Error(`Unknown position: ${position}`);
|
|
43917
|
+
animate() {
|
|
43918
|
+
if (this.tween) this.tween.update();
|
|
43919
|
+
requestAnimationFrame(this.animate.bind(this));
|
|
43920
|
+
this.controls.update();
|
|
43921
|
+
this.renderer.render(this.scene, this.camera);
|
|
43922
|
+
if (this.spotLightPosX > 500) {
|
|
43923
|
+
this.spotLightDirection = -1;
|
|
43924
|
+
this.spotLightPosX = 500;
|
|
43925
|
+
}
|
|
43926
|
+
if (this.spotLightPosX < -500) {
|
|
43927
|
+
this.spotLightDirection = 1;
|
|
43928
|
+
this.spotLightPosX = -500;
|
|
43929
|
+
}
|
|
43930
|
+
this.spotLightPosX += 10 * this.spotLightDirection;
|
|
43931
|
+
this.spotLight.position.set(this.spotLightPosX, this.spotLightPosY, this.spotLightPosZ);
|
|
43932
|
+
}
|
|
43933
|
+
reset() {
|
|
43934
|
+
this.hideHelpers();
|
|
43935
|
+
this.controls.reset();
|
|
43936
|
+
this.setMode("VIEW");
|
|
43937
|
+
this.fitScreen();
|
|
43938
|
+
}
|
|
43939
|
+
// ================================================================
|
|
43940
|
+
// Diagram arrangement
|
|
43941
|
+
// ================================================================
|
|
43942
|
+
arrange() {
|
|
43943
|
+
if (this.scene.children.length === 0) {
|
|
43944
|
+
console.warn("Scene is empty. Cannot calculate center.");
|
|
43945
|
+
return;
|
|
44031
43946
|
}
|
|
43947
|
+
const box = new Box3().setFromObject(this.scene);
|
|
43948
|
+
const center = box.getCenter(new Vector3$1());
|
|
43949
|
+
const translation = new Vector3$1(-center.x, -center.y, -center.z);
|
|
43950
|
+
this.scene.children.forEach((child) => {
|
|
43951
|
+
if (child instanceof Object3D) {
|
|
43952
|
+
child.position.add(translation);
|
|
43953
|
+
}
|
|
43954
|
+
});
|
|
44032
43955
|
}
|
|
44033
|
-
// ================================================================
|
|
44034
|
-
// Add Text methods
|
|
44035
|
-
// ================================================================
|
|
44036
43956
|
/**
|
|
44037
|
-
*
|
|
44038
|
-
*
|
|
44039
|
-
* @returns {
|
|
43957
|
+
* Calculates the optimal zoom distance for the camera to ensure the entire scene is visible.
|
|
43958
|
+
*
|
|
43959
|
+
* @returns {number} The optimal distance for the camera to fit the scene within the viewport.
|
|
44040
43960
|
*/
|
|
44041
|
-
|
|
44042
|
-
const
|
|
44043
|
-
|
|
44044
|
-
this.
|
|
44045
|
-
|
|
43961
|
+
calculateOptimalZoom() {
|
|
43962
|
+
const box = new Box3().setFromObject(this.scene);
|
|
43963
|
+
const size = box.getSize(new Vector3$1());
|
|
43964
|
+
const aspect2 = this.container.clientWidth / this.container.clientHeight;
|
|
43965
|
+
const fovRad = MathUtils$1.degToRad(this.camera.fov);
|
|
43966
|
+
const distanceForWidth = size.x / 2 / (Math.tan(fovRad / 2) * aspect2);
|
|
43967
|
+
const distanceForHeight = size.y / 2 / Math.tan(fovRad / 2);
|
|
43968
|
+
return Math.max(distanceForWidth, distanceForHeight);
|
|
44046
43969
|
}
|
|
44047
43970
|
/**
|
|
44048
|
-
*
|
|
44049
|
-
*
|
|
44050
|
-
*
|
|
43971
|
+
* Adjusts the camera to fit the entire scene within the screen.
|
|
43972
|
+
*
|
|
43973
|
+
* This method calculates the optimal zoom level and positions the camera
|
|
43974
|
+
* at a distance that ensures the entire scene is visible, with a small margin.
|
|
43975
|
+
* It also updates the camera's orientation to look at the center of the scene
|
|
43976
|
+
* and saves the current camera state for later restoration.
|
|
44051
43977
|
*/
|
|
44052
|
-
|
|
44053
|
-
|
|
44054
|
-
|
|
44055
|
-
|
|
44056
|
-
|
|
44057
|
-
|
|
44058
|
-
|
|
44059
|
-
|
|
44060
|
-
|
|
44061
|
-
|
|
44062
|
-
let minLength = Infinity;
|
|
44063
|
-
let minIndex = -1;
|
|
44064
|
-
for (let i = 0; i < words.length - 1; i++) {
|
|
44065
|
-
let combinedLength = words[i].length + words[i + 1].length;
|
|
44066
|
-
if (combinedLength < minLength) {
|
|
44067
|
-
minLength = combinedLength;
|
|
44068
|
-
minIndex = i;
|
|
44069
|
-
}
|
|
44070
|
-
}
|
|
44071
|
-
if (minIndex === -1) break;
|
|
44072
|
-
words[minIndex] = words[minIndex] + " " + words[minIndex + 1];
|
|
44073
|
-
words.splice(minIndex + 1, 1);
|
|
44074
|
-
wrappedText = words.join("\n");
|
|
44075
|
-
candidateTextElement = new Element(this.elementId + "_text", new TextShape(wrappedText));
|
|
44076
|
-
if (candidateTextElement.getSize().x <= this.getSize().x * 0.9) {
|
|
44077
|
-
wrappedTextElement = candidateTextElement;
|
|
44078
|
-
} else {
|
|
44079
|
-
break;
|
|
44080
|
-
}
|
|
44081
|
-
}
|
|
44082
|
-
this.diagram.addElement(wrappedTextElement).positionAt({ x: this.position.x, y: this.position.y, z: 3 });
|
|
44083
|
-
this.texts.push({ element: wrappedTextElement, positionOffset: new Vector3$1(0, 0, 3) });
|
|
44084
|
-
return this;
|
|
43978
|
+
fitScreen() {
|
|
43979
|
+
const minZDistance = this.calculateOptimalZoom();
|
|
43980
|
+
const margin = 1.05;
|
|
43981
|
+
const cameraZ = minZDistance * margin;
|
|
43982
|
+
this.camera.position.set(0, 0, cameraZ);
|
|
43983
|
+
this.camera.lookAt(0, 0, 0);
|
|
43984
|
+
this.camera.updateProjectionMatrix();
|
|
43985
|
+
this.controls.saveState();
|
|
43986
|
+
this.initialCameraPosition = this.camera.position.clone();
|
|
43987
|
+
this.initialTarget = this.controls.target.clone();
|
|
44085
43988
|
}
|
|
44086
|
-
// ================================================================
|
|
44087
|
-
// Add icons methods
|
|
44088
|
-
// ================================================================
|
|
44089
43989
|
/**
|
|
44090
|
-
*
|
|
44091
|
-
*
|
|
44092
|
-
*
|
|
44093
|
-
*
|
|
44094
|
-
*
|
|
44095
|
-
*
|
|
43990
|
+
* Centers the diagram by moving the camera to its initial position and target.
|
|
43991
|
+
* This method uses the Tween.js library to animate the camera movement.
|
|
43992
|
+
*
|
|
43993
|
+
* Preconditions:
|
|
43994
|
+
* - `this.initialCameraPosition` and `this.initialTarget` must be defined.
|
|
43995
|
+
*
|
|
43996
|
+
* Behavior:
|
|
43997
|
+
* - If the initial camera position or target is not defined, a warning is logged, and the method exits.
|
|
43998
|
+
* - Animates the camera's position and the controls' target to their initial states over 1200 milliseconds.
|
|
43999
|
+
* - Uses a Quartic easing function for smooth animation.
|
|
44000
|
+
*
|
|
44001
|
+
* Dependencies:
|
|
44002
|
+
* - Tween.js library for animation.
|
|
44003
|
+
*
|
|
44004
|
+
* @returns {void}
|
|
44096
44005
|
*/
|
|
44097
|
-
|
|
44098
|
-
|
|
44099
|
-
|
|
44100
|
-
|
|
44101
|
-
|
|
44006
|
+
center() {
|
|
44007
|
+
if (!this.initialCameraPosition || !this.initialTarget) {
|
|
44008
|
+
console.warn("Initial camera position or target is not defined.");
|
|
44009
|
+
return;
|
|
44010
|
+
}
|
|
44011
|
+
const from = {
|
|
44012
|
+
cameraPositionX: this.camera.position.x,
|
|
44013
|
+
cameraPositionY: this.camera.position.y,
|
|
44014
|
+
cameraPositionZ: this.camera.position.z,
|
|
44015
|
+
controlsTargetX: this.controls.target.x,
|
|
44016
|
+
controlsTargetY: this.controls.target.y,
|
|
44017
|
+
controlsTargetZ: this.controls.target.z
|
|
44018
|
+
};
|
|
44019
|
+
const to = {
|
|
44020
|
+
cameraPositionX: this.initialCameraPosition.x,
|
|
44021
|
+
cameraPositionY: this.initialCameraPosition.y,
|
|
44022
|
+
cameraPositionZ: this.initialCameraPosition.z,
|
|
44023
|
+
controlsTargetX: this.initialTarget.x,
|
|
44024
|
+
controlsTargetY: this.initialTarget.y,
|
|
44025
|
+
controlsTargetZ: this.initialTarget.z
|
|
44026
|
+
};
|
|
44027
|
+
const camera = this.camera;
|
|
44028
|
+
const controls = this.controls;
|
|
44029
|
+
this.tween = new Tween$1(from).to(to, 1200).easing(Easing.Quartic.Out).onUpdate(function() {
|
|
44030
|
+
camera.position.set(
|
|
44031
|
+
from.cameraPositionX,
|
|
44032
|
+
from.cameraPositionY,
|
|
44033
|
+
from.cameraPositionZ
|
|
44034
|
+
);
|
|
44035
|
+
controls.target.set(
|
|
44036
|
+
from.controlsTargetX,
|
|
44037
|
+
from.controlsTargetY,
|
|
44038
|
+
from.controlsTargetZ
|
|
44039
|
+
);
|
|
44040
|
+
}).onComplete(function() {
|
|
44041
|
+
}).start();
|
|
44102
44042
|
}
|
|
44103
44043
|
/**
|
|
44104
|
-
*
|
|
44105
|
-
* The
|
|
44106
|
-
*
|
|
44107
|
-
*
|
|
44108
|
-
*
|
|
44109
|
-
*
|
|
44044
|
+
* Rotates the diagram around the Y axis by a specified angle in degrees.
|
|
44045
|
+
* The method ensures the diagram is centered and calculates the new camera
|
|
44046
|
+
* and target positions based on the provided angle.
|
|
44047
|
+
*
|
|
44048
|
+
* @param {number} targetAngle - The angle in degrees to rotate the diagram (e.g., 60).
|
|
44049
|
+
* @returns {void} - Does not return a value.
|
|
44050
|
+
*
|
|
44051
|
+
* @throws {Error} Logs a warning if the initial camera position or target is not defined.
|
|
44052
|
+
*
|
|
44053
|
+
* @example
|
|
44054
|
+
* // Rotate the diagram by 60 degrees
|
|
44055
|
+
* diagram.rotate(60);
|
|
44110
44056
|
*/
|
|
44111
|
-
|
|
44112
|
-
|
|
44113
|
-
|
|
44114
|
-
|
|
44057
|
+
rotate(targetAngle) {
|
|
44058
|
+
if (!this.initialCameraPosition || !this.initialTarget) {
|
|
44059
|
+
console.warn("Initial camera position or target is not defined.");
|
|
44060
|
+
return;
|
|
44061
|
+
}
|
|
44062
|
+
const radius = Math.sqrt(
|
|
44063
|
+
this.initialCameraPosition.y * this.initialCameraPosition.y + this.initialCameraPosition.z * this.initialCameraPosition.z
|
|
44115
44064
|
);
|
|
44065
|
+
const from = {
|
|
44066
|
+
cameraPositionX: this.camera.position.x,
|
|
44067
|
+
cameraPositionY: this.camera.position.y,
|
|
44068
|
+
cameraPositionZ: this.camera.position.z,
|
|
44069
|
+
controlsTargetX: this.controls.target.x,
|
|
44070
|
+
controlsTargetY: this.controls.target.y,
|
|
44071
|
+
controlsTargetZ: this.controls.target.z
|
|
44072
|
+
};
|
|
44073
|
+
const targetAngleRad = MathUtils$1.degToRad(targetAngle);
|
|
44074
|
+
const to = {
|
|
44075
|
+
cameraPositionX: this.initialCameraPosition.x,
|
|
44076
|
+
cameraPositionY: radius * Math.sin(targetAngleRad),
|
|
44077
|
+
cameraPositionZ: radius * Math.cos(targetAngleRad),
|
|
44078
|
+
controlsTargetX: this.initialTarget.x,
|
|
44079
|
+
controlsTargetY: this.initialTarget.y,
|
|
44080
|
+
controlsTargetZ: this.initialTarget.z
|
|
44081
|
+
};
|
|
44082
|
+
console.log("rotate() -> from:", from);
|
|
44083
|
+
console.log("rotate() -> to:", to);
|
|
44084
|
+
const camera = this.camera;
|
|
44085
|
+
const controls = this.controls;
|
|
44086
|
+
this.tween = new Tween$1(from).to(to, 1200).easing(Easing.Quartic.Out).onUpdate(function() {
|
|
44087
|
+
camera.position.set(
|
|
44088
|
+
from.cameraPositionX,
|
|
44089
|
+
from.cameraPositionY,
|
|
44090
|
+
from.cameraPositionZ
|
|
44091
|
+
);
|
|
44092
|
+
controls.target.set(
|
|
44093
|
+
from.controlsTargetX,
|
|
44094
|
+
from.controlsTargetY,
|
|
44095
|
+
from.controlsTargetZ
|
|
44096
|
+
);
|
|
44097
|
+
}).start();
|
|
44116
44098
|
}
|
|
44099
|
+
// ================================================================
|
|
44100
|
+
// Diagram modes
|
|
44101
|
+
// ================================================================
|
|
44117
44102
|
/**
|
|
44118
|
-
*
|
|
44119
|
-
*
|
|
44120
|
-
*
|
|
44121
|
-
*
|
|
44122
|
-
*
|
|
44123
|
-
* and y is the element's center y-coordinate
|
|
44103
|
+
* Removes all elements of type 'ValueBarShape' from the diagram.
|
|
44104
|
+
* Iterates through the `elements` array in reverse order to safely remove
|
|
44105
|
+
* elements without affecting the iteration process. For each matching element,
|
|
44106
|
+
* it removes the element from its parent (and thus from the scene) and also
|
|
44107
|
+
* removes it from the `elements` array.
|
|
44124
44108
|
*/
|
|
44125
|
-
|
|
44126
|
-
|
|
44127
|
-
|
|
44128
|
-
|
|
44129
|
-
|
|
44109
|
+
removeValueBars() {
|
|
44110
|
+
for (let i = this.elements.length - 1; i >= 0; i--) {
|
|
44111
|
+
const element2 = this.elements[i];
|
|
44112
|
+
if (element2.type === "ValueBarShape") {
|
|
44113
|
+
if (element2.parent) {
|
|
44114
|
+
element2.parent.remove(element2);
|
|
44115
|
+
}
|
|
44116
|
+
this.scene.remove(element2);
|
|
44117
|
+
this.elements.splice(i, 1);
|
|
44118
|
+
}
|
|
44119
|
+
}
|
|
44130
44120
|
}
|
|
44131
44121
|
/**
|
|
44132
|
-
*
|
|
44133
|
-
*
|
|
44134
|
-
*
|
|
44135
|
-
*
|
|
44136
|
-
*
|
|
44137
|
-
*
|
|
44122
|
+
* Adds value bars to the diagram to visualize the elements' parameters.
|
|
44123
|
+
*
|
|
44124
|
+
* This method processes the elements in the diagram, calculates the height
|
|
44125
|
+
* of the bars based on their parameter values, and assigns a color to each
|
|
44126
|
+
* bar based on a normalized value. The bars are then added to the scene.
|
|
44127
|
+
*
|
|
44128
|
+
* @method
|
|
44129
|
+
* @memberof Diagram
|
|
44130
|
+
* @description
|
|
44131
|
+
* - Filters elements to include only those with a defined `parameters.value`.
|
|
44132
|
+
* - Calculates the range of parameter values to normalize them.
|
|
44133
|
+
* - Assigns a color to each bar using an HSL color scale (green to red).
|
|
44134
|
+
* - Calls the `valueBar` method on each element to set the bar's height and color.
|
|
44135
|
+
*
|
|
44136
|
+
* @example
|
|
44137
|
+
* // Assuming `diagram` is an instance of Diagram with elements having parameters:
|
|
44138
|
+
* diagram.addValueBars();
|
|
44139
|
+
*
|
|
44140
|
+
* @throws {Error} If no elements with `parameters.value` are found.
|
|
44138
44141
|
*/
|
|
44139
|
-
|
|
44140
|
-
|
|
44141
|
-
|
|
44142
|
-
|
|
44143
|
-
|
|
44142
|
+
addValueBars() {
|
|
44143
|
+
const elements = this.elements.filter((el) => el.parameters && el.parameters.value !== void 0);
|
|
44144
|
+
if (elements.length === 0) {
|
|
44145
|
+
throw new Error("No elements with `parameters.value` found.");
|
|
44146
|
+
}
|
|
44147
|
+
const max2 = Math.max(...elements.map((el) => el.parameters.value));
|
|
44148
|
+
const min2 = 0;
|
|
44149
|
+
const range = max2 - min2;
|
|
44150
|
+
elements.forEach((element2, i) => {
|
|
44151
|
+
const value = element2.parameters.value;
|
|
44152
|
+
const normalizedValue = (value - min2) / range;
|
|
44153
|
+
const color2 = new Color$1(`hsl(${(normalizedValue * 120).toString(10)}, 100%, 50%)`);
|
|
44154
|
+
element2.addValueBar(normalizedValue * 100, color2);
|
|
44155
|
+
});
|
|
44144
44156
|
}
|
|
44145
44157
|
/**
|
|
44146
|
-
*
|
|
44147
|
-
*
|
|
44148
|
-
*
|
|
44149
|
-
*
|
|
44150
|
-
*
|
|
44151
|
-
*
|
|
44158
|
+
* Sets the mode of the diagram and adjusts its state accordingly.
|
|
44159
|
+
*
|
|
44160
|
+
* @param {string} mode - The mode to set. Possible values are:
|
|
44161
|
+
* - 'EDIT': Sets the diagram to edit mode and resets rotation.
|
|
44162
|
+
* - 'VIEW': Sets the diagram to view mode and resets rotation.
|
|
44163
|
+
* - 'ANALYZE': Sets the diagram to analyze mode, rotates it to -60 degrees,
|
|
44164
|
+
* and adds value bars.
|
|
44165
|
+
* - Any other value will log a warning about an unknown mode.
|
|
44152
44166
|
*/
|
|
44153
|
-
|
|
44154
|
-
|
|
44155
|
-
|
|
44156
|
-
|
|
44157
|
-
|
|
44167
|
+
setMode(mode) {
|
|
44168
|
+
this.removeValueBars();
|
|
44169
|
+
this.mode = mode;
|
|
44170
|
+
switch (mode) {
|
|
44171
|
+
case "EDIT":
|
|
44172
|
+
case "VIEW":
|
|
44173
|
+
this.rotate(0);
|
|
44174
|
+
break;
|
|
44175
|
+
case "ANALYZE":
|
|
44176
|
+
this.rotate(-65);
|
|
44177
|
+
const elementsWithValue = this.elements.filter((el) => el.parameters && el.parameters.value !== void 0);
|
|
44178
|
+
if (elementsWithValue.length === 0) {
|
|
44179
|
+
break;
|
|
44180
|
+
}
|
|
44181
|
+
const values = elementsWithValue.map((el) => el.parameters.value);
|
|
44182
|
+
const dataMax = Math.max(...values);
|
|
44183
|
+
const dataMin = Math.min(...values);
|
|
44184
|
+
console.log(`[Diagram.js] Coloring Range | Min: ${dataMin}, Max: ${dataMax}`);
|
|
44185
|
+
elementsWithValue.forEach((element2) => {
|
|
44186
|
+
const originalValue = element2.parameters.value;
|
|
44187
|
+
const normalizedHeight = dataMax === 0 ? 0 : originalValue / dataMax * 100;
|
|
44188
|
+
const color2 = getColorForValue(originalValue, dataMin, dataMax);
|
|
44189
|
+
const barShape = new ValueBarShape(element2.shape.getOuterShape(), normalizedHeight, color2);
|
|
44190
|
+
const barElement = new Element(element2.elementId + "_bar", barShape);
|
|
44191
|
+
this.addElement(barElement).positionAt(element2.getPosition());
|
|
44192
|
+
element2.valueBars.push({ element: barElement, positionOffset: new Vector3$1(0, 0, 0) });
|
|
44193
|
+
});
|
|
44194
|
+
break;
|
|
44195
|
+
default:
|
|
44196
|
+
console.warn(`Unknown mode: ${mode}`);
|
|
44197
|
+
}
|
|
44158
44198
|
}
|
|
44199
|
+
// ================================================================
|
|
44200
|
+
// Diagram elements
|
|
44201
|
+
// ================================================================
|
|
44159
44202
|
/**
|
|
44160
|
-
*
|
|
44161
|
-
*
|
|
44162
|
-
*
|
|
44163
|
-
* @returns {
|
|
44164
|
-
* where x is the element's right edge x-coordinate minus (icon size/2 + padding)
|
|
44165
|
-
* and y is the element's top edge y-coordinate minus (icon size/2 + padding)
|
|
44203
|
+
* Adds an element to the diagram.
|
|
44204
|
+
* @param {Object3D} element - The element to add.
|
|
44205
|
+
* @param {Vector3} [position] - The position to place the element.
|
|
44206
|
+
* @returns {Object3D} The added element.
|
|
44166
44207
|
*/
|
|
44167
|
-
|
|
44168
|
-
|
|
44169
|
-
|
|
44170
|
-
|
|
44171
|
-
);
|
|
44208
|
+
addElement(element2, position) {
|
|
44209
|
+
this.elements.push(element2);
|
|
44210
|
+
this.scene.add(element2);
|
|
44211
|
+
if (position) element2.position.set(position.x, position.y, 0);
|
|
44212
|
+
element2.setDiagram(this);
|
|
44213
|
+
return element2;
|
|
44172
44214
|
}
|
|
44173
44215
|
/**
|
|
44174
|
-
*
|
|
44175
|
-
*
|
|
44176
|
-
* by half the icon size plus padding along both axes.
|
|
44177
|
-
* @returns {THREE.Vector2} A 2D vector representing the placeholder coordinates
|
|
44178
|
-
* where x is the element's left edge x-coordinate plus (icon size/2 + padding)
|
|
44179
|
-
* and y is the element's bottom edge y-coordinate plus (icon size/2 + padding)
|
|
44216
|
+
* Removes an element from the diagram by its ID.
|
|
44217
|
+
* @param {string} elementId - The ID of the element to remove.
|
|
44180
44218
|
*/
|
|
44181
|
-
|
|
44182
|
-
|
|
44183
|
-
|
|
44184
|
-
this.
|
|
44185
|
-
|
|
44219
|
+
removeElement(elementId) {
|
|
44220
|
+
const element2 = this.elements.find((el) => el.id === elementId);
|
|
44221
|
+
if (element2) {
|
|
44222
|
+
this.scene.remove(element2);
|
|
44223
|
+
this.elements = this.elements.filter((el) => el.id !== elementId);
|
|
44224
|
+
}
|
|
44186
44225
|
}
|
|
44187
44226
|
/**
|
|
44188
|
-
*
|
|
44189
|
-
*
|
|
44190
|
-
*
|
|
44191
|
-
* @returns {
|
|
44192
|
-
* where x is the element's right edge x-coordinate minus (icon size/2 + padding)
|
|
44193
|
-
* and y is the element's bottom edge y-coordinate plus (icon size/2 + padding)
|
|
44227
|
+
* Retrieves an element from the `elements` array by its unique `elementId`.
|
|
44228
|
+
*
|
|
44229
|
+
* @param {string} elementId - The unique identifier of the element to find.
|
|
44230
|
+
* @returns {Object|undefined} The element with the matching `elementId`, or `undefined` if not found.
|
|
44194
44231
|
*/
|
|
44195
|
-
|
|
44196
|
-
return
|
|
44197
|
-
this.position.x + this.getSize().x / 2 - IconDimensions.ICON_SIZE_SMALL / 2 - IconDimensions.ICON_PADDING,
|
|
44198
|
-
this.position.y - this.getSize().y / 2 + IconDimensions.ICON_SIZE_SMALL / 2 + IconDimensions.ICON_PADDING
|
|
44199
|
-
);
|
|
44232
|
+
getElementById(elementId) {
|
|
44233
|
+
return this.elements.find((el) => el.elementId === elementId);
|
|
44200
44234
|
}
|
|
44201
44235
|
/**
|
|
44202
|
-
*
|
|
44203
|
-
*
|
|
44204
|
-
* @returns {
|
|
44205
|
-
* where x is the element's center x-coordinate
|
|
44206
|
-
* and y is the element's center y-coordinate
|
|
44236
|
+
* Retrieves the elements of the diagram.
|
|
44237
|
+
*
|
|
44238
|
+
* @returns {Array} The array of elements in the diagram.
|
|
44207
44239
|
*/
|
|
44208
|
-
|
|
44209
|
-
return
|
|
44240
|
+
getElements() {
|
|
44241
|
+
return this.elements;
|
|
44210
44242
|
}
|
|
44243
|
+
// ================================================================
|
|
44244
|
+
// Diagram Connectors
|
|
44245
|
+
// ================================================================
|
|
44211
44246
|
/**
|
|
44212
|
-
*
|
|
44213
|
-
*
|
|
44214
|
-
*
|
|
44215
|
-
* @
|
|
44247
|
+
* Adds a connector to the diagram, registers it with the diagram,
|
|
44248
|
+
* and adds it to the scene for rendering.
|
|
44249
|
+
*
|
|
44250
|
+
* @param {Object} connector - The connector object to be added to the diagram.
|
|
44251
|
+
* @returns {Object} The connector that was added.
|
|
44216
44252
|
*/
|
|
44217
|
-
|
|
44218
|
-
|
|
44219
|
-
|
|
44220
|
-
|
|
44221
|
-
|
|
44222
|
-
return this.getBottomIconPlaceholder();
|
|
44223
|
-
case "left":
|
|
44224
|
-
return this.getLeftIconPlaceholder();
|
|
44225
|
-
case "right":
|
|
44226
|
-
return this.getRightIconPlaceholder();
|
|
44227
|
-
case "top-left":
|
|
44228
|
-
return this.getTopLeftIconPlaceholder();
|
|
44229
|
-
case "top-right":
|
|
44230
|
-
return this.getTopRightIconPlaceholder();
|
|
44231
|
-
case "bottom-left":
|
|
44232
|
-
return this.getBottomLeftIconPlaceholder();
|
|
44233
|
-
case "bottom-right":
|
|
44234
|
-
return this.getBottomRightIconPlaceholder();
|
|
44235
|
-
case "center":
|
|
44236
|
-
return this.getCenterIconPlaceholder();
|
|
44237
|
-
default:
|
|
44238
|
-
throw new Error(`Unknown icon position: ${position}`);
|
|
44239
|
-
}
|
|
44253
|
+
addConnector(connector) {
|
|
44254
|
+
this.connectors.push(connector);
|
|
44255
|
+
this.scene.add(connector);
|
|
44256
|
+
connector.setDiagram(this);
|
|
44257
|
+
return connector;
|
|
44240
44258
|
}
|
|
44259
|
+
// ================================================================
|
|
44260
|
+
// Clear diagram
|
|
44261
|
+
// ================================================================
|
|
44241
44262
|
/**
|
|
44242
|
-
*
|
|
44243
|
-
* @param {string} icon - The icon identifier
|
|
44244
|
-
* @param {string} [placeholder='center'] - Position of the icon
|
|
44245
|
-
* @param {number} [size=IconDimensions.ICON_SIZE_MEDIUM] - Size of the icon
|
|
44246
|
-
* @returns {Element} This element for method chaining
|
|
44263
|
+
* Clears all elements and connectors from the diagram.
|
|
44247
44264
|
*/
|
|
44248
|
-
|
|
44249
|
-
|
|
44250
|
-
|
|
44251
|
-
|
|
44252
|
-
}
|
|
44253
|
-
const iconElement = new Element(this.elementId + "_icon_placeholder", new IconShape(icon, size));
|
|
44254
|
-
this.diagram.addElement(iconElement).positionAt(position);
|
|
44255
|
-
this.icons.push({ element: iconElement, positionOffset: new Vector3$1(position.x - this.position.x, position.y - this.position.y, 0) });
|
|
44256
|
-
return this;
|
|
44265
|
+
clear() {
|
|
44266
|
+
this.elements = [];
|
|
44267
|
+
this.connectors = [];
|
|
44268
|
+
this.scene.children = this.scene.children.filter((child) => child instanceof AmbientLight);
|
|
44257
44269
|
}
|
|
44258
44270
|
// ================================================================
|
|
44259
|
-
//
|
|
44271
|
+
// Diagram JSON
|
|
44260
44272
|
// ================================================================
|
|
44261
|
-
|
|
44262
|
-
|
|
44263
|
-
|
|
44264
|
-
|
|
44265
|
-
|
|
44266
|
-
addValueBar(value) {
|
|
44267
|
-
if (value < 0) {
|
|
44268
|
-
console.warn("valueBar: Value must be positive");
|
|
44269
|
-
return this;
|
|
44270
|
-
}
|
|
44271
|
-
this.parameters["value"] = value;
|
|
44272
|
-
console.log("valueBar added:", this);
|
|
44273
|
-
if (this.diagram.mode !== "ANALYZE") {
|
|
44274
|
-
console.warn("valueBar: Diagram mode is not ANALYZE");
|
|
44275
|
-
return this;
|
|
44276
|
-
}
|
|
44277
|
-
const barElement = new Element(this.elementId + "_bar", new ValueBarShape(this.shape.getOuterShape(), value));
|
|
44278
|
-
this.diagram.addElement(barElement).positionAt(this.position);
|
|
44279
|
-
this.valueBars.push({ element: barElement, positionOffset: new Vector3$1(0, 0, 0) });
|
|
44280
|
-
return this;
|
|
44273
|
+
toJSON() {
|
|
44274
|
+
return JSON.stringify(this.elements);
|
|
44275
|
+
}
|
|
44276
|
+
fromJSON(json) {
|
|
44277
|
+
this.elements = JSON.parse(json);
|
|
44281
44278
|
}
|
|
44282
44279
|
// ================================================================
|
|
44283
|
-
//
|
|
44280
|
+
// Diagram export and import to/from file
|
|
44284
44281
|
// ================================================================
|
|
44285
44282
|
/**
|
|
44286
|
-
*
|
|
44287
|
-
* @param {string} sourceElementId - ID of the source element
|
|
44288
|
-
* @param {string} sourcePosition - Connection point on the source element
|
|
44289
|
-
* @param {string} targetPosition - Connection point on this element
|
|
44290
|
-
* @returns {Element} This element for method chaining
|
|
44291
|
-
* @throws {Error} If the diagram is not set or source element is not found
|
|
44283
|
+
* Exports the diagram to a JSON file.
|
|
44292
44284
|
*/
|
|
44293
|
-
|
|
44294
|
-
|
|
44295
|
-
|
|
44296
|
-
|
|
44297
|
-
const
|
|
44298
|
-
|
|
44299
|
-
|
|
44300
|
-
|
|
44301
|
-
|
|
44302
|
-
|
|
44303
|
-
|
|
44304
|
-
|
|
44305
|
-
|
|
44306
|
-
|
|
44307
|
-
|
|
44308
|
-
|
|
44309
|
-
|
|
44285
|
+
export() {
|
|
44286
|
+
const data = JSON.stringify(this.scene.toJSON());
|
|
44287
|
+
const blob = new Blob([data], { type: "application/json" });
|
|
44288
|
+
const url = URL.createObjectURL(blob);
|
|
44289
|
+
const a = document.createElement("a");
|
|
44290
|
+
a.href = url;
|
|
44291
|
+
a.download = "diagram.json";
|
|
44292
|
+
a.click();
|
|
44293
|
+
URL.revokeObjectURL(url);
|
|
44294
|
+
}
|
|
44295
|
+
/**
|
|
44296
|
+
* Placeholder for importing a diagram from a file.
|
|
44297
|
+
* This method should be implemented by subclasses.
|
|
44298
|
+
* @param {File} file - The file to import.
|
|
44299
|
+
* @throws {Error} If the method is not implemented.
|
|
44300
|
+
* @returns {Promise<void>}
|
|
44301
|
+
*/
|
|
44302
|
+
import(file) {
|
|
44303
|
+
console.error("Import method should be implemented by subclasses.");
|
|
44310
44304
|
}
|
|
44311
44305
|
}
|
|
44312
44306
|
const RoundedRectangleDimensions = {
|