@aibee/crc-bmap 0.0.9 → 0.0.12

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/lib/bmap.esm.js CHANGED
@@ -41,7 +41,7 @@ var __async = (__this, __arguments, generator) => {
41
41
  };
42
42
 
43
43
  // src/bmap.ts
44
- import { EventDispatcher as EventDispatcher4 } from "three";
44
+ import { EventDispatcher as EventDispatcher6 } from "three";
45
45
 
46
46
  // src/utils/timer.ts
47
47
  var Timer = class {
@@ -115,7 +115,9 @@ import {
115
115
  Group,
116
116
  Color,
117
117
  DirectionalLight,
118
- AmbientLight
118
+ AmbientLight,
119
+ Path,
120
+ Vector2
119
121
  } from "three";
120
122
  import { MapControls } from "three/examples/jsm/controls/MapControls";
121
123
  function initScene() {
@@ -157,15 +159,17 @@ function initControl(camera, domElement) {
157
159
  control.minPolarAngle = 0;
158
160
  control.maxAzimuthAngle = 0;
159
161
  control.minAzimuthAngle = 0;
162
+ control.minZoom = 1;
163
+ control.maxZoom = 100;
160
164
  return control;
161
165
  }
162
- function initShape(path) {
163
- const shape = new Shape();
164
- if (Array.isArray(path[0])) {
165
- shape.moveTo(...path[0]);
166
- for (let i = 1; i < path.length; i++) {
167
- shape.lineTo(...path[i]);
168
- }
166
+ function initShape(path, holePath = []) {
167
+ const shape = new Shape(path.map((item) => new Vector2(...item)));
168
+ if (holePath.length) {
169
+ holePath.forEach((cur) => {
170
+ var hole = new Path(cur.map((item) => new Vector2(...item)));
171
+ shape.holes.push(hole);
172
+ });
169
173
  }
170
174
  return shape;
171
175
  }
@@ -288,6 +292,9 @@ function getCenter(coordinates) {
288
292
  const cent = center(features);
289
293
  return cent.geometry.coordinates;
290
294
  }
295
+ function isContain(point3, start, end) {
296
+ return point3.x >= start.x && point3.x <= end.x && point3.y >= start.y && point3.y <= end.y;
297
+ }
291
298
 
292
299
  // src/utils/proxy.ts
293
300
  function proxyOptions(target, master) {
@@ -335,6 +342,12 @@ function createLine(stroke) {
335
342
  line.setAttribute("stroke", stroke);
336
343
  return line;
337
344
  }
345
+ function createRect(stroke, fill) {
346
+ const rect = createSvgElement("rect");
347
+ rect.setAttribute("stroke", stroke);
348
+ rect.setAttribute("fill", fill);
349
+ return rect;
350
+ }
338
351
  function setCirclePosition(circle, x, y) {
339
352
  circle.setAttribute("cx", `${x}`);
340
353
  circle.setAttribute("cy", `${y}`);
@@ -349,512 +362,203 @@ function setLineStartEnd(line, start, end) {
349
362
  line.setAttribute("y2", `${end.y}`);
350
363
  }
351
364
  }
365
+ function setRectPosition(rect, x, y, w, h) {
366
+ rect.setAttribute("x", `${x}`);
367
+ rect.setAttribute("y", `${y}`);
368
+ rect.setAttribute("width", `${w}`);
369
+ rect.setAttribute("height", `${h}`);
370
+ }
352
371
 
353
372
  // src/context.ts
354
373
  import {
355
- EventDispatcher,
374
+ EventDispatcher as EventDispatcher5,
356
375
  Box2,
357
- Vector3,
358
- Vector2,
359
- Raycaster,
360
- Box3,
361
- Color as Color2,
376
+ Vector3 as Vector37,
377
+ Vector2 as Vector23,
378
+ Raycaster as Raycaster3,
379
+ Box3 as Box34,
380
+ Color as Color4,
362
381
  AmbientLight as AmbientLight2
363
382
  } from "three";
364
383
  import { Group as TweenGroup, Tween } from "@tweenjs/tween.js";
365
- var Context = class extends EventDispatcher {
366
- // zoom=1的时候,100M对应的像素个数
367
- constructor(container, config) {
384
+
385
+ // src/operations/selection/selection.ts
386
+ import { EventDispatcher as EventDispatcher3 } from "three";
387
+
388
+ // src/elements/graphic.ts
389
+ import {
390
+ Object3D,
391
+ ExtrudeGeometry,
392
+ MeshStandardMaterial,
393
+ Mesh,
394
+ Color as Color2,
395
+ Box3,
396
+ LineSegments,
397
+ EdgesGeometry,
398
+ LineBasicMaterial,
399
+ Vector3
400
+ } from "three";
401
+ import { merge } from "lodash";
402
+ var defaultOptions = {
403
+ id: "",
404
+ // 图形id
405
+ height: 0.1,
406
+ // 图形高度
407
+ airHeight: 0,
408
+ // 悬空高度
409
+ area: 0,
410
+ // 面积
411
+ group: "",
412
+ // 分组
413
+ fillColor: "#EFF4FB",
414
+ // 颜色
415
+ strokeColor: "#ffffff",
416
+ // 边框
417
+ fillOpacity: 1,
418
+ // 透明度
419
+ strokeOpacity: 1,
420
+ // 描边透明度
421
+ doors: [],
422
+ // 门配置
423
+ locked: false,
424
+ visible: true,
425
+ geometry: {
426
+ type: "polygon",
427
+ cds: [],
428
+ curveCpt: [],
429
+ curveIndex: []
430
+ },
431
+ layerType: "",
432
+ zIndex: 0
433
+ };
434
+ var Graphic = class extends Object3D {
435
+ constructor(context, options) {
368
436
  super();
369
- this.container = container;
370
- this.config = config;
371
- __publicField(this, "scene", initScene());
372
- __publicField(this, "renderer", initRenderer());
373
- __publicField(this, "camera");
374
- __publicField(this, "control");
375
- __publicField(this, "lights", initLight());
376
- // 管理任务,防止内存泄漏
377
- __publicField(this, "timer", new Timer());
378
- __publicField(this, "tweenGroup", new TweenGroup());
379
- __publicField(this, "currentFloor");
380
- __publicField(this, "basicRatio");
381
- __publicField(this, "onWindowResize", () => {
382
- const { container, camera, renderer } = this;
383
- const { clientWidth: w, clientHeight: h } = container;
384
- camera.left = -w / 2;
385
- camera.right = w / 2;
386
- camera.top = h / 2;
387
- camera.bottom = -h / 2;
388
- camera.updateProjectionMatrix();
389
- renderer.setSize(window.innerWidth, window.innerHeight);
437
+ this.context = context;
438
+ __publicField(this, "geometry");
439
+ __publicField(this, "material");
440
+ __publicField(this, "mesh");
441
+ __publicField(this, "line");
442
+ __publicField(this, "options");
443
+ this.options = proxyOptions(merge({}, defaultOptions, options), this);
444
+ this.init();
445
+ this.visible = this.options.visible;
446
+ this.addEventListener("change-fillColor", ({ value }) => {
447
+ this.material.color = new Color2(value);
390
448
  });
391
- __publicField(this, "onClick", (e) => {
392
- const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
393
- if (graphics.length) {
394
- this.dispatchEvent({
395
- type: "graphic-click",
396
- graphics,
397
- position
398
- });
399
- }
400
- const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
401
- if (pois.length) {
402
- this.dispatchEvent({ type: "poi-click", pois });
403
- }
449
+ this.addEventListener("change-fillOpacity", ({ value }) => {
450
+ this.material.opacity = value;
404
451
  });
405
- __publicField(this, "onPointerover", (e) => {
406
- const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
407
- const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
408
- this.dispatchEvent({ type: "pointer-over", graphics, pois, position });
452
+ this.addEventListener("change-height", ({ value }) => {
453
+ this.dispose();
454
+ this.init();
409
455
  });
410
- __publicField(this, "onPointermove", (e) => {
411
- const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
412
- const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
413
- this.dispatchEvent({ type: "pointer-move", graphics, pois, position });
456
+ this.addEventListener("change-strokeColor", ({ value }) => {
457
+ this.line.material.color = new Color2(value);
414
458
  });
415
- __publicField(this, "onPointerleave", () => {
416
- this.dispatchEvent({ type: "pointer-level" });
459
+ this.addEventListener("change-strokeOpacity", ({ value }) => {
460
+ this.line.material.opacity = value;
417
461
  });
418
- this.container.style.position = "relative";
419
- this.container.style.overflow = "hidden";
420
- this.init();
421
- this.registryEvent();
462
+ this.addEventListener("change-airHeight", ({ value }) => {
463
+ this.position.z = value;
464
+ });
465
+ this.addEventListener("change-visible", ({ value }) => {
466
+ this.visible = value;
467
+ });
468
+ }
469
+ getCenter() {
470
+ const center2 = new Vector3();
471
+ const box = new Box3();
472
+ box.setFromObject(this);
473
+ box.getCenter(center2);
474
+ return center2;
475
+ }
476
+ getSize() {
477
+ const box = new Box3();
478
+ const size = new Vector3();
479
+ box.setFromObject(this);
480
+ box.getSize(size);
481
+ return size;
482
+ }
483
+ getPosition() {
484
+ return this.getCenter();
422
485
  }
423
486
  init() {
424
- const { clientWidth: w, clientHeight: h } = this.container;
425
- this.camera = initCamera(w, h);
426
- this.renderer.setSize(w, h);
427
- this.control = initControl(this.camera, this.renderer.domElement);
428
- this.container.appendChild(this.renderer.domElement);
429
- this.scene.add(this.lights);
430
- this.basicRatio = this.getRatio();
431
- this.control.addEventListener("change", () => {
432
- var _a;
433
- const polarAngle = this.control.getPolarAngle();
434
- (_a = this.currentFloor) == null ? void 0 : _a.setShadowOpacity(polarAngle / this.config.control.maxPolar);
435
- this.dispatchEvent({ type: "change-ratio", px: (this.basicRatio || 0) * this.camera.zoom });
487
+ this.geometry = this.initGeometry();
488
+ this.material = this.initMaterial();
489
+ this.mesh = this.initMesh();
490
+ this.mesh.position.z = this.options.airHeight + this.options.height / 2;
491
+ this.mesh.castShadow = true;
492
+ this.add(this.mesh);
493
+ this.line = this.createBorder();
494
+ this.add(this.line);
495
+ }
496
+ initGeometry() {
497
+ const shape = initShape(this.options.geometry.cds[0], this.options.geometry.cds.slice(1));
498
+ const geometry = new ExtrudeGeometry(shape, {
499
+ steps: 1,
500
+ bevelEnabled: false,
501
+ depth: this.options.height,
502
+ curveSegments: 4
436
503
  });
504
+ return geometry;
437
505
  }
438
- /**
439
- * 获取两个点之间的像素数
440
- */
441
- getRatio(point1 = new Vector3(0, 0, 0), point22 = new Vector3(100, 0, 0)) {
442
- const { clientWidth, clientHeight } = this.container;
443
- const device1 = vector3ToDevice(point1, this.camera, clientWidth, clientHeight);
444
- const device2 = vector3ToDevice(point22, this.camera, clientWidth, clientHeight);
445
- return Math.ceil(Math.sqrt(__pow(device2.x - device1.x, 2) + __pow(device2.y - device1.y, 2)));
506
+ initMaterial() {
507
+ const material = new MeshStandardMaterial({
508
+ color: this.options.fillColor,
509
+ roughness: 1,
510
+ transparent: true,
511
+ opacity: this.options.fillOpacity,
512
+ depthWrite: true
513
+ });
514
+ return material;
446
515
  }
447
- changeAmbientLightColor(color) {
448
- this.lights.children.forEach((item) => {
449
- if (item instanceof AmbientLight2) {
450
- item.color = new Color2(color);
451
- }
516
+ initLineMaterial() {
517
+ const lineMaterial = new LineBasicMaterial({
518
+ color: this.options.strokeColor,
519
+ opacity: this.options.strokeOpacity,
520
+ transparent: true,
521
+ depthWrite: true
452
522
  });
523
+ return lineMaterial;
453
524
  }
454
- switchFloor(floor) {
455
- var _a;
456
- if (this.currentFloor) {
457
- this.scene.remove(floor);
458
- floor.dispose();
459
- }
460
- this.currentFloor = floor;
461
- this.scene.add(floor);
462
- const position = (_a = floor.ground) == null ? void 0 : _a.getCenter();
463
- if (position) {
464
- this.lights.position.x = position.x;
465
- this.lights.position.y = position.y;
466
- }
525
+ initMesh() {
526
+ return new Mesh(this.geometry, this.material);
467
527
  }
468
- /**
469
- * 获取屏幕坐标对应的graphic
470
- * @param x
471
- * @param y
472
- * @returns
473
- */
474
- getGraphicsByDeviceXy(x, y) {
475
- var _a;
476
- const point3 = new Vector2();
477
- point3.x = x / this.container.clientWidth * 2 - 1;
478
- point3.y = y / this.container.clientHeight * -2 + 1;
479
- const raycaster = new Raycaster();
480
- raycaster.setFromCamera(point3, this.camera);
481
- const res = (_a = this.currentFloor) == null ? void 0 : _a.graphicLayer.getGraphicByRaycaster(raycaster);
482
- return res || { graphics: [], position: null };
528
+ createBorder() {
529
+ const material = this.initLineMaterial();
530
+ const geometry = new EdgesGeometry(this.geometry);
531
+ const line = new LineSegments(geometry, material);
532
+ line.position.z = this.options.airHeight + this.options.height / 2;
533
+ return line;
483
534
  }
484
- /**
485
- * 获取屏幕坐标对应的poi
486
- * @param x
487
- * @param y
488
- * @returns
489
- */
490
- getPoisByDeviceXy(x, y) {
491
- var _a;
492
- const pois = (_a = this.currentFloor) == null ? void 0 : _a.poiLayer.getPoiByDeviceXy(x, y);
493
- return pois || [];
535
+ raycast(raycaster) {
536
+ if (!this.visible) {
537
+ return false;
538
+ }
539
+ const intersects = raycaster.intersectObject(this.mesh);
540
+ if (intersects[0]) {
541
+ const position = intersects[0].point;
542
+ return position;
543
+ }
544
+ return false;
494
545
  }
495
- registryEvent() {
496
- window.addEventListener("resize", this.onWindowResize);
497
- this.container.addEventListener("click", this.onClick);
498
- this.container.addEventListener("pointerover", this.onPointerover);
499
- this.container.addEventListener("pointermove", this.onPointermove);
500
- this.container.addEventListener("pointerleave", this.onPointerleave);
501
- }
502
- unRegistryEvent() {
503
- window.removeEventListener("resize", this.onWindowResize);
504
- this.container.removeEventListener("click", this.onClick);
505
- this.container.removeEventListener("pointerover", this.onPointerover);
506
- this.container.removeEventListener("pointermove", this.onPointermove);
507
- this.container.removeEventListener("pointerleave", this.onPointerleave);
508
- }
509
- /**
510
- * 设置纵向旋转角度
511
- * @param polar 弧度
512
- */
513
- setPolarAngle(polar, duration = 500) {
514
- return timeoutPromise(
515
- new Promise((resolve) => {
516
- const start = { polar: this.control.getPolarAngle() };
517
- const end = { polar };
518
- const tween = new Tween(start, this.tweenGroup).to(end, duration).onUpdate(() => {
519
- this.control.maxPolarAngle = start.polar;
520
- this.control.minPolarAngle = start.polar;
521
- this.control.update();
522
- }).onComplete(() => {
523
- this.control.enabled = true;
524
- this.tweenGroup.remove(tween);
525
- resolve(true);
526
- }).onStart(() => {
527
- this.control.enabled = false;
528
- }).start();
529
- }),
530
- duration + 500
531
- );
532
- }
533
- getCameraLookAt() {
534
- return new Vector3().subVectors(this.control.target, this.camera.position);
535
- }
536
- /**
537
- * 按照一个中心点设置相机的放大缩小
538
- * @param zoom
539
- * @param center
540
- * @returns
541
- */
542
- setZoom(zoom, center2, duration = 500) {
543
- return timeoutPromise(
544
- new Promise((resolve) => {
545
- const start = {
546
- zoom: this.camera.zoom,
547
- target: this.control.target.clone()
548
- };
549
- const lookAtVector = this.getCameraLookAt();
550
- const tween = new Tween(start, this.tweenGroup).to(
551
- {
552
- zoom,
553
- target: center2
554
- },
555
- duration
556
- ).onUpdate(() => {
557
- this.camera.position.copy(start.target.clone().sub(lookAtVector));
558
- this.control.target.copy(start.target);
559
- this.camera.zoom = start.zoom;
560
- this.control.update();
561
- }).onComplete(() => {
562
- this.tweenGroup.remove(tween);
563
- this.control.enabled = true;
564
- resolve(true);
565
- }).onStart(() => {
566
- this.control.enabled = false;
567
- }).start();
568
- }),
569
- duration + 500
570
- );
571
- }
572
- /**
573
- * 放大相机到物体占全屏
574
- * @param object
575
- * @param padding
576
- * @param duration
577
- * @returns
578
- */
579
- fitCameraToObject(object, padding = [20, 20, 20, 20], duration = 500) {
580
- const [top, right, bottom, left] = padding;
581
- const { clientWidth, clientHeight } = this.container;
582
- const boundingBox = new Box3().setFromObject(object);
583
- const { max, min } = boundingBox;
584
- const max2d = vector3ToDevice(max, this.camera, clientWidth, clientHeight);
585
- const min2d = vector3ToDevice(min, this.camera, clientWidth, clientHeight);
586
- const boundingBox2d = new Box2().setFromPoints([
587
- new Vector2(max2d.x, max2d.y),
588
- new Vector2(min2d.x, min2d.y)
589
- ]);
590
- const size = boundingBox2d.getSize(new Vector2());
591
- const xScale = (clientWidth - right - left) / size.x;
592
- const yScale = (clientHeight - top - bottom) / size.y;
593
- const scale = Math.min(xScale, yScale);
594
- const center2 = new Vector3((max.x + min.x) / 2, (max.y + min.y) / 2, max.z);
595
- return this.setZoom(scale * this.camera.zoom, center2, duration);
596
- }
597
- fitCameraToGround(padding = [20, 20, 20, 20], duration = 500) {
598
- var _a;
599
- const ground = (_a = this.currentFloor) == null ? void 0 : _a.ground;
600
- if (ground) {
601
- return this.fitCameraToObject(ground, padding, duration);
602
- } else {
603
- return Promise.resolve(false);
604
- }
605
- }
606
- /**
607
- * 修改相机位置
608
- * @param position 修改后的相机的位置
609
- * @param duration 动画持续时间
610
- */
611
- setCameraPosition(position, duration) {
612
- return timeoutPromise(
613
- new Promise((resolve) => {
614
- const start = this.camera.position.clone();
615
- const lookAtVector = this.getCameraLookAt();
616
- const tween = new Tween(start, this.tweenGroup).to(position, duration).onUpdate(() => {
617
- this.camera.position.copy(start);
618
- this.control.target.copy(position.clone().add(lookAtVector));
619
- }).onComplete(() => {
620
- this.tweenGroup.remove(tween);
621
- this.control.update();
622
- this.control.enabled = true;
623
- resolve(true);
624
- }).onStart(() => {
625
- this.control.enabled = false;
626
- }).start();
627
- }),
628
- duration + 500
629
- );
630
- }
631
- render() {
632
- this.renderer.render(this.scene, this.camera);
633
- this.dispatchEvent({ type: "update" });
634
- this.timer.requestAnimationFrame(() => {
635
- this.render();
636
- });
637
- this.tweenGroup.update();
638
- }
639
- dispose() {
640
- this.tweenGroup.getAll().forEach((item) => item.stop());
641
- this.tweenGroup.removeAll();
642
- this.unRegistryEvent();
643
- this.container.removeChild(this.renderer.domElement);
644
- this.timer.dispose();
645
- this.renderer.dispose();
646
- this.lights.children.forEach(
647
- (light) => light.dispose()
648
- );
649
- dispose(this.scene);
650
- }
651
- };
652
-
653
- // src/config.ts
654
- import { merge } from "lodash";
655
- var defaultConfig = {
656
- apiDomain: "",
657
- apiInfo: {},
658
- apiPath: {
659
- floorGraphic: "/api/inception-map/floor/get",
660
- floorRange: "/api/inception-map/range/get"
661
- },
662
- heatMap: {
663
- radius: 50,
664
- gradient: {
665
- 0: "#8F9FCD",
666
- 0.5: "#6284FF",
667
- 1: "#F95D5D"
668
- }
669
- },
670
- useFloorCache: true,
671
- control: {
672
- maxPolar: 1.2
673
- },
674
- svg: {
675
- circle: {
676
- radius: "2",
677
- fill: "#EFF4FB"
678
- },
679
- line: {
680
- stroke: "#EFF4FB"
681
- }
682
- }
683
- };
684
- function getConfig(config) {
685
- return merge({}, defaultConfig, config);
686
- }
687
-
688
- // src/elements/graphic.ts
689
- import {
690
- Object3D as Object3D2,
691
- ExtrudeGeometry,
692
- MeshStandardMaterial,
693
- Mesh,
694
- Color as Color3,
695
- Box3 as Box32,
696
- LineSegments,
697
- EdgesGeometry,
698
- LineBasicMaterial,
699
- Vector3 as Vector32
700
- } from "three";
701
- import { merge as merge2 } from "lodash";
702
- var defaultOptions = {
703
- id: "",
704
- // 图形id
705
- height: 0.1,
706
- // 图形高度
707
- airHeight: 0,
708
- // 悬空高度
709
- area: 0,
710
- // 面积
711
- group: "",
712
- // 分组
713
- fillColor: "#EFF4FB",
714
- // 颜色
715
- strokeColor: "#ffffff",
716
- // 边框
717
- fillOpacity: 1,
718
- // 透明度
719
- strokeOpacity: 1,
720
- // 描边透明度
721
- doors: [],
722
- // 门配置
723
- locked: false,
724
- visible: true,
725
- geometry: {
726
- type: "polygon",
727
- cds: [],
728
- curveCpt: [],
729
- curveIndex: []
730
- },
731
- layerType: "",
732
- zIndex: 0
733
- };
734
- var Graphic = class extends Object3D2 {
735
- constructor(context, options) {
736
- super();
737
- this.context = context;
738
- __publicField(this, "geometry");
739
- __publicField(this, "material");
740
- __publicField(this, "mesh");
741
- __publicField(this, "line");
742
- __publicField(this, "options");
743
- this.options = proxyOptions(merge2({}, defaultOptions, options), this);
744
- this.init();
745
- this.visible = this.options.visible;
746
- this.addEventListener("change-fillColor", ({ value }) => {
747
- this.material.color = new Color3(value);
748
- });
749
- this.addEventListener("change-fillOpacity", ({ value }) => {
750
- this.material.opacity = value;
751
- });
752
- this.addEventListener("change-height", ({ value }) => {
753
- this.dispose();
754
- this.init();
755
- });
756
- this.addEventListener("change-strokeColor", ({ value }) => {
757
- this.line.material.color = new Color3(value);
758
- });
759
- this.addEventListener("change-strokeOpacity", ({ value }) => {
760
- this.line.material.opacity = value;
761
- });
762
- this.addEventListener("change-airHeight", ({ value }) => {
763
- this.position.z = value;
764
- });
765
- this.addEventListener("change-visible", ({ value }) => {
766
- this.visible = value;
767
- });
768
- }
769
- getCenter() {
770
- const center2 = new Vector32();
771
- const box = new Box32();
772
- box.setFromObject(this);
773
- box.getCenter(center2);
774
- return center2;
775
- }
776
- getSize() {
777
- const box = new Box32();
778
- const size = new Vector32();
779
- box.setFromObject(this);
780
- box.getSize(size);
781
- return size;
782
- }
783
- init() {
784
- this.geometry = this.initGeometry();
785
- this.material = this.initMaterial();
786
- this.mesh = this.initMesh();
787
- this.mesh.position.z = this.options.airHeight + this.options.height / 2;
788
- this.mesh.castShadow = true;
789
- this.add(this.mesh);
790
- this.line = this.createBorder();
791
- this.add(this.line);
792
- }
793
- initGeometry() {
794
- const shape = initShape(this.options.geometry.cds[0]);
795
- const geometry = new ExtrudeGeometry(shape, {
796
- steps: 1,
797
- bevelEnabled: false,
798
- depth: this.options.height,
799
- curveSegments: 4
800
- });
801
- return geometry;
802
- }
803
- initMaterial() {
804
- const material = new MeshStandardMaterial({
805
- color: this.options.fillColor,
806
- roughness: 1,
807
- transparent: true,
808
- opacity: this.options.fillOpacity,
809
- depthWrite: true
810
- });
811
- return material;
812
- }
813
- initLineMaterial() {
814
- const lineMaterial = new LineBasicMaterial({
815
- color: this.options.strokeColor,
816
- opacity: this.options.strokeOpacity,
817
- transparent: true,
818
- depthWrite: true
819
- });
820
- return lineMaterial;
821
- }
822
- initMesh() {
823
- return new Mesh(this.geometry, this.material);
824
- }
825
- createBorder() {
826
- const material = this.initLineMaterial();
827
- const geometry = new EdgesGeometry(this.geometry);
828
- const line = new LineSegments(geometry, material);
829
- return line;
830
- }
831
- raycast(raycaster) {
832
- if (!this.visible) {
833
- return false;
834
- }
835
- const intersects = raycaster.intersectObject(this.mesh);
836
- if (intersects[0]) {
837
- const position = intersects[0].point;
838
- return position;
839
- }
840
- return false;
841
- }
842
- dispose() {
843
- dispose(this);
844
- this.clear();
546
+ dispose() {
547
+ dispose(this);
548
+ this.clear();
845
549
  }
846
550
  };
847
551
 
848
552
  // src/elements/shadow.ts
849
553
  import {
850
- Object3D as Object3D3,
554
+ Object3D as Object3D2,
851
555
  PlaneGeometry,
852
556
  Mesh as Mesh2,
853
557
  ShadowMaterial,
854
- Color as Color4,
558
+ Color as Color3,
855
559
  DoubleSide
856
560
  } from "three";
857
- var Shadow = class extends Object3D3 {
561
+ var Shadow = class extends Object3D2 {
858
562
  constructor() {
859
563
  super();
860
564
  __publicField(this, "directionalLight");
@@ -881,7 +585,7 @@ var Shadow = class extends Object3D3 {
881
585
  this.directionalLight.shadow.camera.far = Math.max(x, y);
882
586
  }
883
587
  changeLightColor(color) {
884
- this.directionalLight.color = new Color4(color);
588
+ this.directionalLight.color = new Color3(color);
885
589
  }
886
590
  // 创建平面白色
887
591
  initPlane(width = 1e4, height = 1e4) {
@@ -893,7 +597,7 @@ var Shadow = class extends Object3D3 {
893
597
  });
894
598
  const mesh = new Mesh2(geometry, material);
895
599
  mesh.receiveShadow = true;
896
- mesh.position.z = -20;
600
+ mesh.position.z = -5;
897
601
  this.add(mesh);
898
602
  this.plane = mesh;
899
603
  return mesh;
@@ -913,18 +617,18 @@ var Shadow = class extends Object3D3 {
913
617
  };
914
618
 
915
619
  // src/elements/poi.ts
916
- import { Object3D as Object3D5 } from "three";
917
- import { merge as merge3 } from "lodash";
620
+ import { Object3D as Object3D4 } from "three";
621
+ import { merge as merge2 } from "lodash";
918
622
 
919
623
  // src/elements/overlay.ts
920
- import { EventDispatcher as EventDispatcher2, Vector3 as Vector34 } from "three";
921
- var Overlay = class extends EventDispatcher2 {
624
+ import { Box3 as Box32, EventDispatcher, Vector3 as Vector33 } from "three";
625
+ var Overlay = class extends EventDispatcher {
922
626
  constructor(context) {
923
627
  super();
924
628
  this.context = context;
925
629
  __publicField(this, "div");
926
630
  __publicField(this, "element");
927
- __publicField(this, "position", new Vector34());
631
+ __publicField(this, "position", new Vector33());
928
632
  __publicField(this, "onUpdate", () => {
929
633
  const vector = this.getPosition();
930
634
  const { clientWidth, clientHeight } = this.context.container;
@@ -951,7 +655,16 @@ var Overlay = class extends EventDispatcher2 {
951
655
  this.div.style.display = visible ? display : "none";
952
656
  }
953
657
  getPosition() {
954
- return this.element ? this.element.position.clone().setFromMatrixPosition(this.element.matrixWorld) : this.position;
658
+ if (this.element) {
659
+ if (typeof this.element.getPosition === "function") {
660
+ return this.element.getPosition();
661
+ }
662
+ const box = new Box32().setFromObject(this.element);
663
+ const center2 = box.getCenter(new Vector33());
664
+ return center2;
665
+ } else {
666
+ return this.position;
667
+ }
955
668
  }
956
669
  registryEvent() {
957
670
  this.context.addEventListener("update", this.onUpdate);
@@ -973,7 +686,7 @@ var defaultOptions2 = {
973
686
  level: 1,
974
687
  collision_enable: true
975
688
  };
976
- var Poi = class extends Object3D5 {
689
+ var Poi = class extends Object3D4 {
977
690
  constructor(context, options) {
978
691
  super();
979
692
  this.context = context;
@@ -984,7 +697,7 @@ var Poi = class extends Object3D5 {
984
697
  __publicField(this, "_changePosition", () => {
985
698
  this.overlay.div.style.transform = `translate3d(-50%, ${this.options.icon ? "-100%" : "-50%"}, 0)`;
986
699
  });
987
- this.options = proxyOptions(merge3({}, defaultOptions2, options), this);
700
+ this.options = proxyOptions(merge2({}, defaultOptions2, options), this);
988
701
  this.overlay = new Overlay(this.context);
989
702
  this.overlay.bindElement(this);
990
703
  this._changePosition();
@@ -1020,6 +733,9 @@ var Poi = class extends Object3D5 {
1020
733
  div.style.pointerEvents = `none`;
1021
734
  return div;
1022
735
  }
736
+ getPosition() {
737
+ return this.position;
738
+ }
1023
739
  initText() {
1024
740
  const span = document.createElement("span");
1025
741
  span.style.whiteSpace = "nowrap";
@@ -1061,11 +777,14 @@ var Poi = class extends Object3D5 {
1061
777
  };
1062
778
 
1063
779
  // src/elements/floor.ts
1064
- import { Object3D as Object3D8 } from "three";
780
+ import { Object3D as Object3D7 } from "three";
781
+
782
+ // src/layer/graphic-layer.ts
783
+ import { Box3 as Box33, Vector3 as Vector34 } from "three";
1065
784
 
1066
785
  // src/layer/layer.ts
1067
- import { Object3D as Object3D6 } from "three";
1068
- var Layer = class extends Object3D6 {
786
+ import { Object3D as Object3D5 } from "three";
787
+ var Layer = class extends Object3D5 {
1069
788
  constructor(context) {
1070
789
  super();
1071
790
  this.context = context;
@@ -1081,6 +800,10 @@ var GraphicLayer = class extends Layer {
1081
800
  constructor(context) {
1082
801
  super(context);
1083
802
  }
803
+ getCenter() {
804
+ const box = new Box33().setFromObject(this);
805
+ return box.getCenter(new Vector34());
806
+ }
1084
807
  createGraphic(options) {
1085
808
  const graphic = new Graphic(this.context, options);
1086
809
  this.add(graphic);
@@ -1214,7 +937,7 @@ var PoiLayer = class extends Layer {
1214
937
  // src/elements/heatmap.ts
1215
938
  import {
1216
939
  MeshBasicMaterial,
1217
- Object3D as Object3D7,
940
+ Object3D as Object3D6,
1218
941
  PlaneGeometry as PlaneGeometry2,
1219
942
  Texture,
1220
943
  DoubleSide as DoubleSide2,
@@ -1224,7 +947,7 @@ import {
1224
947
  } from "three";
1225
948
  import { create } from "@mars3d/heatmap.js";
1226
949
  import { featureCollection as featureCollection2, point as point2, bbox, center as getCenter2 } from "@turf/turf";
1227
- var HeatmapElement = class extends Object3D7 {
950
+ var HeatmapElement = class extends Object3D6 {
1228
951
  constructor(context) {
1229
952
  super();
1230
953
  this.context = context;
@@ -1308,7 +1031,7 @@ var HeatmapElement = class extends Object3D7 {
1308
1031
  };
1309
1032
 
1310
1033
  // src/elements/floor.ts
1311
- var Floor = class extends Object3D8 {
1034
+ var Floor = class extends Object3D7 {
1312
1035
  constructor(context) {
1313
1036
  super();
1314
1037
  this.context = context;
@@ -1376,8 +1099,8 @@ var Floor = class extends Object3D8 {
1376
1099
  };
1377
1100
 
1378
1101
  // src/elements/base-svg.ts
1379
- import { EventDispatcher as EventDispatcher3, Raycaster as Raycaster3, Vector2 as Vector23 } from "three";
1380
- var BaseSvg = class extends EventDispatcher3 {
1102
+ import { EventDispatcher as EventDispatcher2, Vector3 as Vector35 } from "three";
1103
+ var BaseSvg = class extends EventDispatcher2 {
1381
1104
  constructor(context) {
1382
1105
  super();
1383
1106
  this.context = context;
@@ -1396,18 +1119,13 @@ var BaseSvg = class extends EventDispatcher3 {
1396
1119
  }
1397
1120
  }
1398
1121
  getIntersectByPointerEvent(e) {
1399
- var _a;
1400
- if (!((_a = this.context.currentFloor) == null ? void 0 : _a.ground)) {
1401
- return;
1402
- }
1122
+ const { camera, renderer } = this.context;
1403
1123
  const { offsetX: x, offsetY: y } = e;
1404
- const point3 = new Vector23();
1405
- point3.x = x / this.context.container.clientWidth * 2 - 1;
1406
- point3.y = y / this.context.container.clientHeight * -2 + 1;
1407
- const raycaster = new Raycaster3();
1408
- raycaster.setFromCamera(point3, this.context.camera);
1409
- const intersects = raycaster.intersectObjects(this.context.currentFloor.ground.children, true);
1410
- return intersects[0];
1124
+ const { clientWidth, clientHeight } = renderer.domElement;
1125
+ const nx = x / clientWidth * 2 - 1;
1126
+ const ny = 1 - y / clientHeight * 2;
1127
+ const v = new Vector35(nx, ny, 0);
1128
+ return v.unproject(camera);
1411
1129
  }
1412
1130
  getSvgCoordinate(vector) {
1413
1131
  const { camera, container } = this.context;
@@ -1443,223 +1161,823 @@ var SvgLine = class extends BaseSvg {
1443
1161
  if (this.points.length !== 1) {
1444
1162
  return;
1445
1163
  }
1446
- this.line.style.display = "block";
1447
- setLineStartEnd(this.line, void 0, { x: e.offsetX, y: e.offsetY });
1164
+ this.line.style.display = "block";
1165
+ setLineStartEnd(this.line, void 0, { x: e.offsetX, y: e.offsetY });
1166
+ });
1167
+ __publicField(this, "onPointerleave", () => {
1168
+ if (this.points[1]) {
1169
+ return;
1170
+ }
1171
+ this.line.style.display = "none";
1172
+ });
1173
+ __publicField(this, "onPointerdown", (e) => {
1174
+ if (this.points[1]) {
1175
+ return;
1176
+ }
1177
+ const point3 = this.getIntersectByPointerEvent(e);
1178
+ if (point3) {
1179
+ const { offsetX: x, offsetY: y } = e;
1180
+ const circle = this.circles[this.points.length];
1181
+ setCirclePosition(circle, x, y);
1182
+ if (!this.points.length) {
1183
+ setLineStartEnd(this.line, { x, y }, { x, y });
1184
+ }
1185
+ this.addPoint(point3);
1186
+ }
1187
+ });
1188
+ const { config: { svg: { circle, line } } } = context;
1189
+ this.circles = [createCircle(circle.radius, circle.fill), createCircle(circle.radius, circle.fill)];
1190
+ this.line = createLine(line.stroke);
1191
+ this.svg.appendChild(this.circles[0]);
1192
+ this.svg.appendChild(this.circles[1]);
1193
+ this.svg.appendChild(this.line);
1194
+ this.registryEvent();
1195
+ }
1196
+ setEnable(enable) {
1197
+ super.setEnable(enable);
1198
+ if (enable) {
1199
+ this.registryEvent();
1200
+ } else {
1201
+ this.unRegistryEvent();
1202
+ }
1203
+ }
1204
+ registryEvent() {
1205
+ this.context.container.addEventListener("pointerenter", this.onPointermove);
1206
+ this.context.container.addEventListener("pointermove", this.onPointermove);
1207
+ this.context.container.addEventListener("pointerleave", this.onPointerleave);
1208
+ this.context.container.addEventListener("pointerdown", this.onPointerdown);
1209
+ this.context.addEventListener("update", this.onUpdate);
1210
+ }
1211
+ unRegistryEvent() {
1212
+ this.context.container.removeEventListener("pointerenter", this.onPointermove);
1213
+ this.context.container.removeEventListener("pointermove", this.onPointermove);
1214
+ this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1215
+ this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1216
+ this.context.removeEventListener("update", this.onUpdate);
1217
+ }
1218
+ addPoint(vector) {
1219
+ this.points.push(vector);
1220
+ if (this.points.length >= 2) {
1221
+ const distance = this.calculatedDistance();
1222
+ this.dispatchEvent({ type: "distance", distance });
1223
+ }
1224
+ }
1225
+ /**
1226
+ * 计算两个点之间的距离
1227
+ */
1228
+ calculatedDistance() {
1229
+ const [{ x: x1, y: y1 }, { x: x2, y: y2 }] = this.points;
1230
+ return Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
1231
+ }
1232
+ dispose() {
1233
+ super.dispose();
1234
+ this.unRegistryEvent();
1235
+ this.line = null;
1236
+ this.circles = [];
1237
+ }
1238
+ };
1239
+
1240
+ // src/elements/svg-polygon.ts
1241
+ var SvgPolygon = class extends BaseSvg {
1242
+ constructor(context) {
1243
+ super(context);
1244
+ __publicField(this, "circles", []);
1245
+ __publicField(this, "lines", []);
1246
+ __publicField(this, "isClose", false);
1247
+ __publicField(this, "onUpdate", () => {
1248
+ if (this.points.length) {
1249
+ this.points.forEach((point3, index) => {
1250
+ const devicePoint = this.getSvgCoordinate(point3);
1251
+ if (this.circles[index]) {
1252
+ setCirclePosition(this.circles[index], devicePoint.x, devicePoint.y);
1253
+ }
1254
+ if (index !== 0) {
1255
+ setLineStartEnd(this.lines[index - 1], void 0, devicePoint);
1256
+ }
1257
+ if (this.lines[index]) {
1258
+ setLineStartEnd(this.lines[index], devicePoint);
1259
+ }
1260
+ });
1261
+ }
1262
+ });
1263
+ __publicField(this, "onPointermove", (e) => {
1264
+ if (!this.lastLine || this.isClose) {
1265
+ return;
1266
+ }
1267
+ this.lastLine.style.display = "block";
1268
+ setLineStartEnd(this.lastLine, void 0, { x: e.offsetX, y: e.offsetY });
1269
+ });
1270
+ __publicField(this, "onPointerleave", () => {
1271
+ if (this.isClose) {
1272
+ return;
1273
+ }
1274
+ this.lastLine.style.display = "none";
1275
+ });
1276
+ __publicField(this, "onPointerdown", (e) => {
1277
+ if (this.isClose) {
1278
+ return;
1279
+ }
1280
+ const point3 = this.getIntersectByPointerEvent(e);
1281
+ if (point3) {
1282
+ const { offsetX: x, offsetY: y } = e;
1283
+ if (this.checkAdsorb(x, y)) {
1284
+ this.isClose = true;
1285
+ this.addPoint(this.points[0]);
1286
+ } else {
1287
+ this.addPoint(point3);
1288
+ }
1289
+ const { circle: { fill, radius }, line: { stroke } } = this.context.config.svg;
1290
+ if (!this.isClose) {
1291
+ const circle = createCircle(radius, fill);
1292
+ setCirclePosition(circle, x, y);
1293
+ this.addCircle(circle);
1294
+ }
1295
+ if (this.lines.length) {
1296
+ setLineStartEnd(this.lastLine, void 0, { x, y });
1297
+ }
1298
+ if (!this.isClose) {
1299
+ const line = createLine(stroke);
1300
+ setLineStartEnd(line, { x, y }, { x, y });
1301
+ this.addLine(line);
1302
+ }
1303
+ }
1304
+ });
1305
+ this.registryEvent();
1306
+ }
1307
+ setEnable(enable) {
1308
+ super.setEnable(enable);
1309
+ if (enable) {
1310
+ this.registryEvent();
1311
+ } else {
1312
+ this.unRegistryEvent();
1313
+ }
1314
+ }
1315
+ get lastLine() {
1316
+ return this.lines.slice(-1)[0];
1317
+ }
1318
+ addCircle(circle) {
1319
+ this.circles.push(circle);
1320
+ this.svg.appendChild(circle);
1321
+ }
1322
+ addLine(line) {
1323
+ this.lines.push(line);
1324
+ this.svg.appendChild(line);
1325
+ }
1326
+ registryEvent() {
1327
+ this.context.container.addEventListener("pointerenter", this.onPointermove);
1328
+ this.context.container.addEventListener("pointermove", this.onPointermove);
1329
+ this.context.container.addEventListener("pointerleave", this.onPointerleave);
1330
+ this.context.container.addEventListener("pointerdown", this.onPointerdown);
1331
+ this.context.addEventListener("update", this.onUpdate);
1332
+ }
1333
+ unRegistryEvent() {
1334
+ this.context.container.removeEventListener("pointerenter", this.onPointermove);
1335
+ this.context.container.removeEventListener("pointermove", this.onPointermove);
1336
+ this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1337
+ this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1338
+ this.context.removeEventListener("update", this.onUpdate);
1339
+ }
1340
+ /**
1341
+ * 检测是否可以吸附
1342
+ * 坐标点最少3个 传入的坐标点和第一个坐标的像素相差不超过5个像素
1343
+ */
1344
+ checkAdsorb(x, y) {
1345
+ if (this.points.length < 3) {
1346
+ return false;
1347
+ }
1348
+ const circle = this.circles[0];
1349
+ const cx = +circle.getAttribute("cx");
1350
+ const cy = +circle.getAttribute("cy");
1351
+ return Math.sqrt(__pow(x - cx, 2) + __pow(y - cy, 2)) <= 5;
1352
+ }
1353
+ addPoint(vector) {
1354
+ this.points.push(vector);
1355
+ if (this.isClose) {
1356
+ const area = this.calculatedArea();
1357
+ this.dispatchEvent({ type: "area", area });
1358
+ }
1359
+ }
1360
+ // 计算面积
1361
+ calculatedArea() {
1362
+ const cds = this.points.map((item) => [item.x, item.y]);
1363
+ let area = 0;
1364
+ const numPoints = cds.length;
1365
+ for (let i = 0; i < numPoints; i++) {
1366
+ const j = (i + 1) % numPoints;
1367
+ area += cds[i][0] * cds[j][1] - cds[j][0] * cds[i][1];
1368
+ }
1369
+ return Math.abs(area / 2);
1370
+ }
1371
+ dispose() {
1372
+ super.dispose();
1373
+ this.unRegistryEvent();
1374
+ this.lines = [];
1375
+ this.circles = [];
1376
+ }
1377
+ };
1378
+
1379
+ // src/operations/selection/box-selection.ts
1380
+ import { Frustum } from "three";
1381
+ var BoxSelection = class extends BaseSvg {
1382
+ constructor(context) {
1383
+ super(context);
1384
+ __publicField(this, "startPoint");
1385
+ __publicField(this, "endPoint");
1386
+ __publicField(this, "rect");
1387
+ __publicField(this, "frustum", new Frustum());
1388
+ __publicField(this, "onPointerDown", (e) => {
1389
+ if (!this.enable) {
1390
+ return;
1391
+ }
1392
+ const point3 = this.getIntersectByPointerEvent(e);
1393
+ if (point3) {
1394
+ this.startPoint = point3;
1395
+ }
1396
+ this.endPoint = void 0;
1448
1397
  });
1449
- __publicField(this, "onPointerleave", () => {
1450
- if (this.points[1]) {
1398
+ __publicField(this, "onPointerMove", (e) => {
1399
+ if (!this.enable || !this.startPoint) {
1451
1400
  return;
1452
1401
  }
1453
- this.line.style.display = "none";
1402
+ const point3 = this.getIntersectByPointerEvent(e);
1403
+ if (point3) {
1404
+ this.endPoint = point3;
1405
+ }
1454
1406
  });
1455
- __publicField(this, "onPointerdown", (e) => {
1456
- if (this.points[1]) {
1407
+ __publicField(this, "onPointerUp", (e) => {
1408
+ if (!this.enable) {
1457
1409
  return;
1458
1410
  }
1459
- const intersect = this.getIntersectByPointerEvent(e);
1460
- if (intersect == null ? void 0 : intersect.point) {
1461
- const { offsetX: x, offsetY: y } = e;
1462
- const circle = this.circles[this.points.length];
1463
- setCirclePosition(circle, x, y);
1464
- if (!this.points.length) {
1465
- setLineStartEnd(this.line, { x, y }, { x, y });
1411
+ const point3 = this.getIntersectByPointerEvent(e);
1412
+ if (point3) {
1413
+ this.endPoint = point3;
1414
+ }
1415
+ this.doSelect();
1416
+ this.startPoint = void 0;
1417
+ });
1418
+ __publicField(this, "onUpdate", () => {
1419
+ if (this.startPoint) {
1420
+ const startPoint = this.getSvgCoordinate(this.startPoint);
1421
+ let endPoint = __spreadValues({}, startPoint);
1422
+ if (this.endPoint) {
1423
+ endPoint = this.getSvgCoordinate(this.endPoint);
1466
1424
  }
1467
- this.addPoint(intersect.point);
1425
+ const leftTop = { x: Math.min(startPoint.x, endPoint.x), y: Math.min(startPoint.y, endPoint.y) };
1426
+ const width = Math.abs(endPoint.x - startPoint.x);
1427
+ const height = Math.abs(endPoint.y - startPoint.y);
1428
+ setRectPosition(this.rect, leftTop.x, leftTop.y, width, height);
1468
1429
  }
1469
1430
  });
1470
- const { config: { svg: { circle, line } } } = context;
1471
- this.circles = [createCircle(circle.radius, circle.fill), createCircle(circle.radius, circle.fill)];
1472
- this.line = createLine(line.stroke);
1473
- this.svg.appendChild(this.circles[0]);
1474
- this.svg.appendChild(this.circles[1]);
1475
- this.svg.appendChild(this.line);
1431
+ const { config: { selectBox: { fill, stroke } } } = context;
1432
+ this.rect = createRect(stroke, fill);
1433
+ this.svg.appendChild(this.rect);
1476
1434
  this.registryEvent();
1477
1435
  }
1478
1436
  setEnable(enable) {
1479
1437
  super.setEnable(enable);
1480
- if (enable) {
1481
- this.registryEvent();
1482
- } else {
1483
- this.unRegistryEvent();
1484
- }
1438
+ setRectPosition(this.rect, 0, 0, 0, 0);
1485
1439
  }
1486
1440
  registryEvent() {
1487
- this.context.container.addEventListener("pointerenter", this.onPointermove);
1488
- this.context.container.addEventListener("pointermove", this.onPointermove);
1489
- this.context.container.addEventListener("pointerleave", this.onPointerleave);
1490
- this.context.container.addEventListener("pointerdown", this.onPointerdown);
1441
+ this.context.container.addEventListener("pointerdown", this.onPointerDown);
1442
+ this.context.container.addEventListener("pointermove", this.onPointerMove);
1443
+ this.context.container.addEventListener("pointerup", this.onPointerUp);
1491
1444
  this.context.addEventListener("update", this.onUpdate);
1492
1445
  }
1493
1446
  unRegistryEvent() {
1494
- this.context.container.removeEventListener("pointerenter", this.onPointermove);
1495
- this.context.container.removeEventListener("pointermove", this.onPointermove);
1496
- this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1497
- this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1447
+ this.context.container.removeEventListener("pointerdown", this.onPointerDown);
1448
+ this.context.container.removeEventListener("pointermove", this.onPointerMove);
1449
+ this.context.container.removeEventListener("pointerup", this.onPointerUp);
1498
1450
  this.context.removeEventListener("update", this.onUpdate);
1499
1451
  }
1500
- addPoint(vector) {
1501
- this.points.push(vector);
1502
- if (this.points.length >= 2) {
1503
- const distance = this.calculatedDistance();
1504
- this.dispatchEvent({ type: "distance", distance });
1452
+ doSelect() {
1453
+ if (this.startPoint && this.endPoint) {
1454
+ const dis = this.startPoint.distanceTo(this.endPoint);
1455
+ if (dis < 0.1) {
1456
+ return;
1457
+ }
1458
+ const { context: { camera, container: { clientWidth: w, clientHeight: h } } } = this;
1459
+ const startDevice = vector3ToDevice(this.startPoint, camera, w, h);
1460
+ const endDevice = vector3ToDevice(this.endPoint, camera, w, h);
1461
+ const leftTop = { x: Math.min(startDevice.x, endDevice.x), y: Math.min(startDevice.y, endDevice.y) };
1462
+ const rightBottom = { x: Math.max(startDevice.x, endDevice.x), y: Math.max(startDevice.y, endDevice.y) };
1463
+ const list = this.searchMapInFrustum(leftTop, rightBottom);
1464
+ this.dispatchEvent({ type: "selected", list });
1505
1465
  }
1506
1466
  }
1507
- /**
1508
- * 计算两个点之间的距离
1509
- */
1510
- calculatedDistance() {
1511
- const [{ x: x1, y: y1 }, { x: x2, y: y2 }] = this.points;
1512
- return Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
1467
+ searchMapInFrustum(leftTop, rightBottom) {
1468
+ var _a;
1469
+ const { context } = this;
1470
+ return ((_a = context.currentFloor) == null ? void 0 : _a.graphicLayer.children.filter((item) => {
1471
+ return item instanceof Graphic && this.searchChildInFrustum(item, leftTop, rightBottom);
1472
+ })) || [];
1473
+ }
1474
+ searchChildInFrustum(object, leftTop, rightBottom) {
1475
+ const { context: { camera, container: { clientWidth: w, clientHeight: h } } } = this;
1476
+ if (!object)
1477
+ return false;
1478
+ if (!object.mesh.geometry.boundingBox) {
1479
+ object.mesh.geometry.computeBoundingBox();
1480
+ }
1481
+ const box = object.mesh.geometry.boundingBox;
1482
+ if (!box) {
1483
+ return false;
1484
+ }
1485
+ const { min, max } = box;
1486
+ const minDevice = vector3ToDevice(min, camera, w, h);
1487
+ const maxDevice = vector3ToDevice(max, camera, w, h);
1488
+ if (!isContain(minDevice, leftTop, rightBottom)) {
1489
+ return false;
1490
+ }
1491
+ if (!isContain(maxDevice, leftTop, rightBottom)) {
1492
+ return false;
1493
+ }
1494
+ return true;
1513
1495
  }
1514
1496
  dispose() {
1515
- super.dispose();
1516
1497
  this.unRegistryEvent();
1517
- this.line = null;
1518
- this.circles = [];
1519
1498
  }
1520
1499
  };
1521
1500
 
1522
- // src/elements/svg-polygon.ts
1523
- var SvgPolygon = class extends BaseSvg {
1501
+ // src/operations/selection/selection.ts
1502
+ var Selection = class extends EventDispatcher3 {
1524
1503
  constructor(context) {
1525
- super(context);
1526
- __publicField(this, "circles", []);
1527
- __publicField(this, "lines", []);
1528
- __publicField(this, "isClose", false);
1529
- __publicField(this, "onUpdate", () => {
1530
- if (this.points.length) {
1531
- this.points.forEach((point3, index) => {
1532
- const devicePoint = this.getSvgCoordinate(point3);
1533
- if (this.circles[index]) {
1534
- setCirclePosition(this.circles[index], devicePoint.x, devicePoint.y);
1535
- }
1536
- if (index !== 0) {
1537
- setLineStartEnd(this.lines[index - 1], void 0, devicePoint);
1538
- }
1539
- if (this.lines[index]) {
1540
- setLineStartEnd(this.lines[index], devicePoint);
1541
- }
1542
- });
1504
+ super();
1505
+ this.context = context;
1506
+ __publicField(this, "_list", /* @__PURE__ */ new Set());
1507
+ __publicField(this, "boxSelection");
1508
+ __publicField(this, "prevPanStatus");
1509
+ __publicField(this, "onPointerDown", (e) => {
1510
+ const { graphics } = this.context.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1511
+ if (!e.ctrlKey) {
1512
+ this._list.clear();
1543
1513
  }
1514
+ graphics.forEach((item) => this._list.add(item));
1515
+ this.selectEnd();
1544
1516
  });
1545
- __publicField(this, "onPointermove", (e) => {
1546
- if (!this.lastLine || this.isClose) {
1547
- return;
1517
+ __publicField(this, "onKeyDown", (e) => {
1518
+ if (e.key === "Control") {
1519
+ this.boxSelection.setEnable(true);
1520
+ this.prevPanStatus = this.context.control.enablePan;
1521
+ this.context.control.enablePan = false;
1548
1522
  }
1549
- this.lastLine.style.display = "block";
1550
- setLineStartEnd(this.lastLine, void 0, { x: e.offsetX, y: e.offsetY });
1551
1523
  });
1552
- __publicField(this, "onPointerleave", () => {
1553
- if (this.isClose) {
1554
- return;
1524
+ __publicField(this, "onKeyUp", (e) => {
1525
+ if (e.key === "Control") {
1526
+ this.boxSelection.setEnable(false);
1527
+ this.context.control.enablePan = !!this.prevPanStatus;
1555
1528
  }
1556
- this.lastLine.style.display = "none";
1557
1529
  });
1558
- __publicField(this, "onPointerdown", (e) => {
1559
- if (this.isClose) {
1530
+ __publicField(this, "onBoxSelected", ({ list }) => {
1531
+ this._list.clear();
1532
+ list.forEach((item) => {
1533
+ this._list.add(item);
1534
+ });
1535
+ this.selectEnd();
1536
+ });
1537
+ this.boxSelection = new BoxSelection(context);
1538
+ this.boxSelection.setEnable(false);
1539
+ this.registryEvent();
1540
+ }
1541
+ get list() {
1542
+ return this._list;
1543
+ }
1544
+ selectEnd() {
1545
+ this.dispatchEvent({ type: "select", graphics: [...this._list] });
1546
+ }
1547
+ registryEvent() {
1548
+ this.context.container.addEventListener("pointerdown", this.onPointerDown);
1549
+ window.addEventListener("keydown", this.onKeyDown);
1550
+ window.addEventListener("keyup", this.onKeyUp);
1551
+ this.boxSelection.addEventListener("selected", this.onBoxSelected);
1552
+ }
1553
+ unRegistryEvent() {
1554
+ this.context.container.removeEventListener("pointerdown", this.onPointerDown);
1555
+ window.removeEventListener("keydown", this.onKeyDown);
1556
+ window.removeEventListener("keyup", this.onKeyUp);
1557
+ this.boxSelection.removeEventListener("selected", this.onBoxSelected);
1558
+ }
1559
+ dispose() {
1560
+ this.unRegistryEvent();
1561
+ }
1562
+ };
1563
+
1564
+ // src/operations/hover/hover-helper.ts
1565
+ import { EventDispatcher as EventDispatcher4 } from "three";
1566
+ var HoverHelper = class extends EventDispatcher4 {
1567
+ constructor(context) {
1568
+ super();
1569
+ this.context = context;
1570
+ __publicField(this, "curGraphics", /* @__PURE__ */ new Set());
1571
+ __publicField(this, "timer", new Timer());
1572
+ __publicField(this, "graphicTimerMap", /* @__PURE__ */ new Map());
1573
+ __publicField(this, "onPointerMove", ({ graphics }) => {
1574
+ if (!graphics.length && this.curGraphics.size) {
1575
+ this.curGraphics.clear();
1576
+ this.handleHoverGraphicsChange();
1560
1577
  return;
1561
1578
  }
1562
- const intersect = this.getIntersectByPointerEvent(e);
1563
- if (intersect == null ? void 0 : intersect.point) {
1564
- const { offsetX: x, offsetY: y } = e;
1565
- if (this.checkAdsorb(x, y)) {
1566
- this.isClose = true;
1567
- this.addPoint(this.points[0]);
1568
- } else {
1569
- this.addPoint(intersect.point);
1579
+ const { time } = this.context.config.hover;
1580
+ graphics.forEach((graphic) => {
1581
+ if (this.graphicTimerMap.get(graphic)) {
1582
+ return;
1570
1583
  }
1571
- const { circle: { fill, radius }, line: { stroke } } = this.context.config.svg;
1572
- if (!this.isClose) {
1573
- const circle = createCircle(radius, fill);
1574
- setCirclePosition(circle, x, y);
1575
- this.addCircle(circle);
1584
+ if (this.curGraphics.has(graphic)) {
1585
+ return;
1576
1586
  }
1577
- if (this.lines.length) {
1578
- setLineStartEnd(this.lastLine, void 0, { x, y });
1587
+ const timer = this.timer.setTimeout(() => {
1588
+ this.curGraphics.add(graphic);
1589
+ this.handleHoverGraphicsChange();
1590
+ }, time);
1591
+ this.graphicTimerMap.set(graphic, timer);
1592
+ });
1593
+ this.graphicTimerMap.forEach((timer, graphic) => {
1594
+ if (!graphics.includes(graphic)) {
1595
+ this.timer.clearTimeout(timer);
1596
+ this.graphicTimerMap.delete(graphic);
1579
1597
  }
1580
- if (!this.isClose) {
1581
- const line = createLine(stroke);
1582
- setLineStartEnd(line, { x, y }, { x, y });
1583
- this.addLine(line);
1598
+ });
1599
+ const size = this.curGraphics.size;
1600
+ this.curGraphics.forEach((graphic) => {
1601
+ if (!graphics.includes(graphic)) {
1602
+ this.curGraphics.delete(graphic);
1584
1603
  }
1604
+ });
1605
+ if (size !== this.curGraphics.size) {
1606
+ this.handleHoverGraphicsChange();
1585
1607
  }
1586
1608
  });
1609
+ __publicField(this, "onPointerLevel", () => {
1610
+ this.curGraphics.clear();
1611
+ this.handleHoverGraphicsChange();
1612
+ });
1587
1613
  this.registryEvent();
1588
1614
  }
1589
- setEnable(enable) {
1590
- super.setEnable(enable);
1591
- if (enable) {
1592
- this.registryEvent();
1593
- } else {
1594
- this.unRegistryEvent();
1615
+ handleHoverGraphicsChange(graphics = this.curGraphics) {
1616
+ this.dispatchEvent({ type: "hover-change", graphics: Array.from(this.curGraphics) });
1617
+ }
1618
+ registryEvent() {
1619
+ this.context.addEventListener("pointer-over", this.onPointerMove);
1620
+ this.context.addEventListener("pointer-move", this.onPointerMove);
1621
+ this.context.addEventListener("pointer-level", this.onPointerLevel);
1622
+ }
1623
+ unRegistryEvent() {
1624
+ this.context.removeEventListener("pointer-over", this.onPointerMove);
1625
+ this.context.removeEventListener("pointer-move", this.onPointerMove);
1626
+ this.context.removeEventListener("pointer-level", this.onPointerLevel);
1627
+ }
1628
+ dispose() {
1629
+ this.unRegistryEvent();
1630
+ this.timer.dispose();
1631
+ }
1632
+ };
1633
+
1634
+ // src/context.ts
1635
+ var Context = class extends EventDispatcher5 {
1636
+ // zoom=1的时候,100M对应的像素个数
1637
+ constructor(container, config) {
1638
+ super();
1639
+ this.container = container;
1640
+ this.config = config;
1641
+ __publicField(this, "scene", initScene());
1642
+ __publicField(this, "renderer", initRenderer());
1643
+ __publicField(this, "camera");
1644
+ __publicField(this, "control");
1645
+ __publicField(this, "lights", initLight());
1646
+ // 管理任务,防止内存泄漏
1647
+ __publicField(this, "timer", new Timer());
1648
+ __publicField(this, "tweenGroup", new TweenGroup());
1649
+ __publicField(this, "currentFloor");
1650
+ __publicField(this, "selection");
1651
+ __publicField(this, "hoverHelper");
1652
+ __publicField(this, "basicRatio");
1653
+ __publicField(this, "onWindowResize", () => {
1654
+ const { container, camera, renderer } = this;
1655
+ const { clientWidth: w, clientHeight: h } = container;
1656
+ camera.left = -w / 2;
1657
+ camera.right = w / 2;
1658
+ camera.top = h / 2;
1659
+ camera.bottom = -h / 2;
1660
+ camera.updateProjectionMatrix();
1661
+ renderer.setSize(window.innerWidth, window.innerHeight);
1662
+ });
1663
+ __publicField(this, "onClick", (e) => {
1664
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1665
+ if (graphics.length) {
1666
+ this.dispatchEvent({
1667
+ type: "graphic-click",
1668
+ graphics,
1669
+ position
1670
+ });
1671
+ }
1672
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1673
+ if (pois.length) {
1674
+ this.dispatchEvent({ type: "poi-click", pois });
1675
+ }
1676
+ });
1677
+ __publicField(this, "onPointerover", (e) => {
1678
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1679
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1680
+ this.dispatchEvent({ type: "pointer-over", graphics, pois, position });
1681
+ });
1682
+ __publicField(this, "onPointermove", (e) => {
1683
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1684
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1685
+ this.dispatchEvent({ type: "pointer-move", graphics, pois, position });
1686
+ });
1687
+ __publicField(this, "onPointerleave", () => {
1688
+ this.dispatchEvent({ type: "pointer-level" });
1689
+ });
1690
+ __publicField(this, "onSelectionSelect", ({ graphics }) => {
1691
+ this.dispatchEvent({ type: "select-graphic", graphics });
1692
+ });
1693
+ __publicField(this, "onHoverChange", ({ graphics }) => {
1694
+ this.dispatchEvent({ type: "hover", graphics });
1695
+ });
1696
+ this.container.style.position = "relative";
1697
+ this.container.style.overflow = "hidden";
1698
+ this.init();
1699
+ this.selection = new Selection(this);
1700
+ this.hoverHelper = new HoverHelper(this);
1701
+ this.registryEvent();
1702
+ }
1703
+ init() {
1704
+ const { clientWidth: w, clientHeight: h } = this.container;
1705
+ this.camera = initCamera(w, h);
1706
+ this.renderer.setSize(w, h);
1707
+ this.control = initControl(this.camera, this.renderer.domElement);
1708
+ this.container.appendChild(this.renderer.domElement);
1709
+ this.scene.add(this.lights);
1710
+ this.basicRatio = this.getRatio();
1711
+ this.control.addEventListener("change", () => {
1712
+ var _a;
1713
+ const polarAngle = this.control.getPolarAngle();
1714
+ (_a = this.currentFloor) == null ? void 0 : _a.setShadowOpacity(polarAngle / this.config.control.maxPolar);
1715
+ this.dispatchEvent({ type: "change-ratio", px: (this.basicRatio || 0) * this.camera.zoom });
1716
+ });
1717
+ }
1718
+ /**
1719
+ * 获取两个点之间的像素数
1720
+ */
1721
+ getRatio(point1 = new Vector37(0, 0, 0), point22 = new Vector37(100, 0, 0)) {
1722
+ const { clientWidth, clientHeight } = this.container;
1723
+ const device1 = vector3ToDevice(point1, this.camera, clientWidth, clientHeight);
1724
+ const device2 = vector3ToDevice(point22, this.camera, clientWidth, clientHeight);
1725
+ return Math.ceil(Math.sqrt(__pow(device2.x - device1.x, 2) + __pow(device2.y - device1.y, 2)));
1726
+ }
1727
+ changeAmbientLightColor(color) {
1728
+ this.lights.children.forEach((item) => {
1729
+ if (item instanceof AmbientLight2) {
1730
+ item.color = new Color4(color);
1731
+ }
1732
+ });
1733
+ }
1734
+ switchFloor(floor) {
1735
+ var _a;
1736
+ if (this.currentFloor) {
1737
+ this.scene.remove(this.currentFloor);
1738
+ this.currentFloor.dispose();
1739
+ }
1740
+ this.currentFloor = floor;
1741
+ this.scene.add(floor);
1742
+ const position = (_a = floor.graphicLayer) == null ? void 0 : _a.getCenter();
1743
+ if (position) {
1744
+ this.lights.position.x = position.x;
1745
+ this.lights.position.y = position.y;
1595
1746
  }
1596
1747
  }
1597
- get lastLine() {
1598
- return this.lines.slice(-1)[0];
1599
- }
1600
- addCircle(circle) {
1601
- this.circles.push(circle);
1602
- this.svg.appendChild(circle);
1748
+ /**
1749
+ * 获取屏幕坐标对应的graphic
1750
+ * @param x
1751
+ * @param y
1752
+ * @returns
1753
+ */
1754
+ getGraphicsByDeviceXy(x, y) {
1755
+ var _a;
1756
+ const point3 = new Vector23();
1757
+ point3.x = x / this.container.clientWidth * 2 - 1;
1758
+ point3.y = y / this.container.clientHeight * -2 + 1;
1759
+ const raycaster = new Raycaster3();
1760
+ raycaster.setFromCamera(point3, this.camera);
1761
+ const res = (_a = this.currentFloor) == null ? void 0 : _a.graphicLayer.getGraphicByRaycaster(raycaster);
1762
+ return res || { graphics: [], position: null };
1603
1763
  }
1604
- addLine(line) {
1605
- this.lines.push(line);
1606
- this.svg.appendChild(line);
1764
+ /**
1765
+ * 获取屏幕坐标对应的poi
1766
+ * @param x
1767
+ * @param y
1768
+ * @returns
1769
+ */
1770
+ getPoisByDeviceXy(x, y) {
1771
+ var _a;
1772
+ const pois = (_a = this.currentFloor) == null ? void 0 : _a.poiLayer.getPoiByDeviceXy(x, y);
1773
+ return pois || [];
1607
1774
  }
1608
1775
  registryEvent() {
1609
- this.context.container.addEventListener("pointerenter", this.onPointermove);
1610
- this.context.container.addEventListener("pointermove", this.onPointermove);
1611
- this.context.container.addEventListener("pointerleave", this.onPointerleave);
1612
- this.context.container.addEventListener("pointerdown", this.onPointerdown);
1613
- this.context.addEventListener("update", this.onUpdate);
1776
+ window.addEventListener("resize", this.onWindowResize);
1777
+ this.container.addEventListener("click", this.onClick);
1778
+ this.container.addEventListener("pointerover", this.onPointerover);
1779
+ this.container.addEventListener("pointermove", this.onPointermove);
1780
+ this.container.addEventListener("pointerleave", this.onPointerleave);
1781
+ this.selection.addEventListener("select", this.onSelectionSelect);
1782
+ this.hoverHelper.addEventListener("hover-change", this.onHoverChange);
1614
1783
  }
1615
1784
  unRegistryEvent() {
1616
- this.context.container.removeEventListener("pointerenter", this.onPointermove);
1617
- this.context.container.removeEventListener("pointermove", this.onPointermove);
1618
- this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1619
- this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1620
- this.context.removeEventListener("update", this.onUpdate);
1785
+ window.removeEventListener("resize", this.onWindowResize);
1786
+ this.container.removeEventListener("click", this.onClick);
1787
+ this.container.removeEventListener("pointerover", this.onPointerover);
1788
+ this.container.removeEventListener("pointermove", this.onPointermove);
1789
+ this.container.removeEventListener("pointerleave", this.onPointerleave);
1790
+ this.selection.removeEventListener("select", this.onSelectionSelect);
1791
+ this.hoverHelper.removeEventListener("hover-change", this.onHoverChange);
1621
1792
  }
1622
1793
  /**
1623
- * 检测是否可以吸附
1624
- * 坐标点最少3个 传入的坐标点和第一个坐标的像素相差不超过5个像素
1794
+ * 设置纵向旋转角度
1795
+ * @param polar 弧度
1625
1796
  */
1626
- checkAdsorb(x, y) {
1627
- if (this.points.length < 3) {
1628
- return false;
1629
- }
1630
- const circle = this.circles[0];
1631
- const cx = +circle.getAttribute("cx");
1632
- const cy = +circle.getAttribute("cy");
1633
- return Math.sqrt(__pow(x - cx, 2) + __pow(y - cy, 2)) <= 5;
1797
+ setPolarAngle(polar, duration = 500) {
1798
+ return timeoutPromise(
1799
+ new Promise((resolve) => {
1800
+ const start = { polar: this.control.getPolarAngle() };
1801
+ const end = { polar };
1802
+ const tween = new Tween(start, this.tweenGroup).to(end, duration).onUpdate(() => {
1803
+ this.control.maxPolarAngle = start.polar;
1804
+ this.control.minPolarAngle = start.polar;
1805
+ this.control.update();
1806
+ }).onComplete(() => {
1807
+ this.control.enabled = true;
1808
+ this.tweenGroup.remove(tween);
1809
+ resolve(true);
1810
+ }).onStart(() => {
1811
+ this.control.enabled = false;
1812
+ }).start();
1813
+ }),
1814
+ duration + 500
1815
+ );
1634
1816
  }
1635
- addPoint(vector) {
1636
- this.points.push(vector);
1637
- if (this.isClose) {
1638
- const area = this.calculatedArea();
1639
- this.dispatchEvent({ type: "area", area });
1640
- }
1817
+ getCameraLookAt() {
1818
+ return new Vector37().subVectors(this.control.target, this.camera.position);
1641
1819
  }
1642
- // 计算面积
1643
- calculatedArea() {
1644
- const cds = this.points.map((item) => [item.x, item.y]);
1645
- let area = 0;
1646
- const numPoints = cds.length;
1647
- for (let i = 0; i < numPoints; i++) {
1648
- const j = (i + 1) % numPoints;
1649
- area += cds[i][0] * cds[j][1] - cds[j][0] * cds[i][1];
1820
+ /**
1821
+ * 按照一个中心点设置相机的放大缩小
1822
+ * @param zoom
1823
+ * @param center
1824
+ * @returns
1825
+ */
1826
+ setZoom(zoom, center2, duration = 500) {
1827
+ return timeoutPromise(
1828
+ new Promise((resolve) => {
1829
+ const start = {
1830
+ zoom: this.camera.zoom,
1831
+ target: this.control.target.clone()
1832
+ };
1833
+ const lookAtVector = this.getCameraLookAt();
1834
+ const tween = new Tween(start, this.tweenGroup).to(
1835
+ {
1836
+ zoom,
1837
+ target: center2
1838
+ },
1839
+ duration
1840
+ ).onUpdate(() => {
1841
+ this.camera.position.copy(start.target.clone().sub(lookAtVector));
1842
+ this.control.target.copy(start.target);
1843
+ this.camera.zoom = start.zoom;
1844
+ this.control.update();
1845
+ }).onComplete(() => {
1846
+ this.tweenGroup.remove(tween);
1847
+ this.control.enabled = true;
1848
+ resolve(true);
1849
+ }).onStart(() => {
1850
+ this.control.enabled = false;
1851
+ }).start();
1852
+ }),
1853
+ duration + 500
1854
+ );
1855
+ }
1856
+ /**
1857
+ * 放大相机到物体占全屏
1858
+ * @param object
1859
+ * @param padding
1860
+ * @param duration
1861
+ * @returns
1862
+ */
1863
+ fitCameraToObject(object, padding = [20, 20, 20, 20], duration = 500) {
1864
+ const [top, right, bottom, left] = padding;
1865
+ const { clientWidth, clientHeight } = this.container;
1866
+ const boundingBox = new Box34().setFromObject(object);
1867
+ const { max, min } = boundingBox;
1868
+ const max2d = vector3ToDevice(max, this.camera, clientWidth, clientHeight);
1869
+ const min2d = vector3ToDevice(min, this.camera, clientWidth, clientHeight);
1870
+ const boundingBox2d = new Box2().setFromPoints([
1871
+ new Vector23(max2d.x, max2d.y),
1872
+ new Vector23(min2d.x, min2d.y)
1873
+ ]);
1874
+ const size = boundingBox2d.getSize(new Vector23());
1875
+ const xScale = (clientWidth - right - left) / size.x;
1876
+ const yScale = (clientHeight - top - bottom) / size.y;
1877
+ const scale = Math.min(xScale, yScale);
1878
+ const center2 = new Vector37((max.x + min.x) / 2, (max.y + min.y) / 2, max.z);
1879
+ return this.setZoom(scale * this.camera.zoom, center2, duration);
1880
+ }
1881
+ fitCameraToGround(padding = [20, 20, 20, 20], duration = 500) {
1882
+ if (this.currentFloor) {
1883
+ return this.fitCameraToObject(this.currentFloor.graphicLayer, padding, duration);
1884
+ } else {
1885
+ return Promise.resolve(false);
1650
1886
  }
1651
- return Math.abs(area / 2);
1887
+ }
1888
+ /**
1889
+ * 修改相机位置
1890
+ * @param position 修改后的相机的位置
1891
+ * @param duration 动画持续时间
1892
+ */
1893
+ setCameraPosition(position, duration) {
1894
+ return timeoutPromise(
1895
+ new Promise((resolve) => {
1896
+ const start = this.camera.position.clone();
1897
+ const lookAtVector = this.getCameraLookAt();
1898
+ const tween = new Tween(start, this.tweenGroup).to(position, duration).onUpdate(() => {
1899
+ this.camera.position.copy(start);
1900
+ this.control.target.copy(position.clone().add(lookAtVector));
1901
+ }).onComplete(() => {
1902
+ this.tweenGroup.remove(tween);
1903
+ this.control.update();
1904
+ this.control.enabled = true;
1905
+ resolve(true);
1906
+ }).onStart(() => {
1907
+ this.control.enabled = false;
1908
+ }).start();
1909
+ }),
1910
+ duration + 500
1911
+ );
1912
+ }
1913
+ render() {
1914
+ this.renderer.render(this.scene, this.camera);
1915
+ this.dispatchEvent({ type: "update" });
1916
+ this.timer.requestAnimationFrame(() => {
1917
+ this.render();
1918
+ });
1919
+ this.tweenGroup.update();
1652
1920
  }
1653
1921
  dispose() {
1654
- super.dispose();
1922
+ this.selection.dispose();
1923
+ this.hoverHelper.dispose();
1924
+ this.tweenGroup.getAll().forEach((item) => item.stop());
1925
+ this.tweenGroup.removeAll();
1655
1926
  this.unRegistryEvent();
1656
- this.lines = [];
1657
- this.circles = [];
1927
+ this.container.removeChild(this.renderer.domElement);
1928
+ this.timer.dispose();
1929
+ this.renderer.dispose();
1930
+ this.lights.children.forEach(
1931
+ (light) => light.dispose()
1932
+ );
1933
+ dispose(this.scene);
1934
+ }
1935
+ };
1936
+
1937
+ // src/config.ts
1938
+ import { merge as merge3 } from "lodash";
1939
+ var defaultConfig = {
1940
+ apiDomain: "",
1941
+ apiInfo: {},
1942
+ apiPath: {
1943
+ floorGraphic: "/api/inception-map/floor/get",
1944
+ floorRange: "/api/inception-map/range/get"
1945
+ },
1946
+ heatMap: {
1947
+ radius: 50,
1948
+ gradient: {
1949
+ 0: "#8F9FCD",
1950
+ 0.5: "#6284FF",
1951
+ 1: "#F95D5D"
1952
+ }
1953
+ },
1954
+ useFloorCache: true,
1955
+ control: {
1956
+ maxPolar: 1.2
1957
+ },
1958
+ svg: {
1959
+ circle: {
1960
+ radius: "2",
1961
+ fill: "#1CADFF"
1962
+ },
1963
+ line: {
1964
+ stroke: "#1CADFF"
1965
+ }
1966
+ },
1967
+ selectBox: {
1968
+ stroke: "#1CADFF",
1969
+ fill: "rgba(28, 173, 255, 0.3)"
1970
+ },
1971
+ hover: {
1972
+ time: 500
1658
1973
  }
1659
1974
  };
1975
+ function getConfig(config) {
1976
+ return merge3({}, defaultConfig, config);
1977
+ }
1660
1978
 
1661
1979
  // src/bmap.ts
1662
- var BMap = class extends EventDispatcher4 {
1980
+ var BMap = class extends EventDispatcher6 {
1663
1981
  constructor(container, config = {}) {
1664
1982
  super();
1665
1983
  this.container = container;
@@ -1669,6 +1987,7 @@ var BMap = class extends EventDispatcher4 {
1669
1987
  __publicField(this, "azimuthalKeys", []);
1670
1988
  __publicField(this, "svgLine");
1671
1989
  __publicField(this, "svgPolygon");
1990
+ __publicField(this, "basicZoom", 1);
1672
1991
  __publicField(this, "floorDataMap", /* @__PURE__ */ new Map());
1673
1992
  __publicField(this, "onKeydown", (e) => {
1674
1993
  if (this.polarKeys.includes(e.code)) {
@@ -1703,7 +2022,7 @@ var BMap = class extends EventDispatcher4 {
1703
2022
  const url = `${apiDomain}${floorGraphic}?brand=${brand}&project=${project}&phase=${phase}&building=${building}&floor=${floor}&ts=${ts}&resource_type_list=`;
1704
2023
  const data = yield fetch(url, apiInfo).then((res) => res.json()).then((res) => res.data).then((res) => {
1705
2024
  (res || []).map((item) => item.info = JSON.parse(item.info));
1706
- return res;
2025
+ return res || [];
1707
2026
  });
1708
2027
  return data;
1709
2028
  });
@@ -1713,10 +2032,13 @@ var BMap = class extends EventDispatcher4 {
1713
2032
  const { apiDomain, apiPath: { floorRange }, apiInfo } = this.config;
1714
2033
  const url = `${apiDomain}${floorRange}?brand=${brand}&project=${project}&phase=${phase}&building=${building}`;
1715
2034
  const data = yield fetch(url, apiInfo).then((res) => res.json()).then((res) => res.data).then((res) => {
1716
- (res || []).map((item) => item.info = JSON.parse(item.info));
1717
- return res;
2035
+ const data2 = (res || [])[0];
2036
+ if (data2) {
2037
+ data2.info = JSON.parse(data2.info);
2038
+ }
2039
+ return data2;
1718
2040
  });
1719
- return data[0];
2041
+ return data;
1720
2042
  });
1721
2043
  }
1722
2044
  load(_0) {
@@ -1728,17 +2050,19 @@ var BMap = class extends EventDispatcher4 {
1728
2050
  this.loadGraphics({ brand, project, phase, building, floor, ts }),
1729
2051
  this.loadBuildingGround({ brand, project, phase, building })
1730
2052
  ]);
1731
- const center2 = getCenter(buildGround.info.geometry.cds[0]);
1732
- data.forEach((item) => {
1733
- item.info.geometry.cds.map((cds) => {
1734
- if (Array.isArray(cds)) {
1735
- cds.forEach((coord) => {
1736
- coord[0] -= center2[0];
1737
- coord[1] -= center2[1];
1738
- });
1739
- }
2053
+ if (buildGround) {
2054
+ const center2 = getCenter(buildGround.info.geometry.cds[0]);
2055
+ data.forEach((item) => {
2056
+ item.info.geometry.cds.map((cds) => {
2057
+ if (Array.isArray(cds)) {
2058
+ cds.forEach((coord) => {
2059
+ coord[0] -= center2[0];
2060
+ coord[1] -= center2[1];
2061
+ });
2062
+ }
2063
+ });
1740
2064
  });
1741
- });
2065
+ }
1742
2066
  if (!this.config.useFloorCache) {
1743
2067
  this.floorDataMap.clear();
1744
2068
  }
@@ -1748,16 +2072,17 @@ var BMap = class extends EventDispatcher4 {
1748
2072
  }
1749
2073
  createFloor(data) {
1750
2074
  const curFloor = new Floor(this.context);
1751
- let groundIndex = data.findIndex((item) => item.info.group === "floor");
1752
- if (groundIndex === -1) {
1753
- groundIndex = 0;
2075
+ if (!data.length) {
2076
+ return { curFloor, graphics: [] };
1754
2077
  }
1755
- const ground = data[groundIndex];
1756
- console.log(ground.info.height, ground.info.airHeight);
1757
2078
  const list = [...data];
1758
- list.splice(groundIndex, 1);
1759
- const groundGraphic = new Graphic(this.context, ground.info);
1760
- curFloor.addGround(groundGraphic);
2079
+ let groundIndex = data.findIndex((item) => item.info.group === "ground");
2080
+ if (groundIndex !== -1) {
2081
+ const ground = data[groundIndex];
2082
+ const groundGraphic = new Graphic(this.context, ground.info);
2083
+ curFloor.addGround(groundGraphic);
2084
+ list.splice(groundIndex, 1);
2085
+ }
1761
2086
  const legacyToGraphicMap = /* @__PURE__ */ new Map();
1762
2087
  const graphics = list.map((item) => {
1763
2088
  const graphic = curFloor.addGraphic(item.info);
@@ -1766,14 +2091,19 @@ var BMap = class extends EventDispatcher4 {
1766
2091
  return graphic;
1767
2092
  });
1768
2093
  curFloor.userData.legacyToGraphicMap = legacyToGraphicMap;
1769
- return { curFloor, ground: groundGraphic, graphics };
2094
+ return { curFloor, graphics };
1770
2095
  }
1771
2096
  switchFloor(floor) {
1772
2097
  const curFloorData = this.floorDataMap.get(floor);
1773
2098
  if (curFloorData) {
1774
- const { curFloor } = this.createFloor(curFloorData);
1775
- this.context.switchFloor(curFloor);
1776
- this.context.fitCameraToGround(void 0, 0);
2099
+ const createdFloor = this.createFloor(curFloorData);
2100
+ if (createdFloor) {
2101
+ this.context.switchFloor(createdFloor.curFloor);
2102
+ this.context.fitCameraToGround(void 0, 0);
2103
+ this.basicZoom = this.context.camera.zoom;
2104
+ } else {
2105
+ console.warn("[switchFloor error] [" + floor + "] \u697C\u5C42\u6CA1\u6709\u6570\u636E");
2106
+ }
1777
2107
  } else {
1778
2108
  console.warn("[switchFloor error] \u6CA1\u6709\u8FD9\u4E2A\u697C\u5C42\uFF0C\u8BF7\u5148\u8C03\u7528load\u65B9\u6CD5\u52A0\u8F7D\u697C\u5C42");
1779
2109
  }
@@ -1786,6 +2116,14 @@ var BMap = class extends EventDispatcher4 {
1786
2116
  var _a;
1787
2117
  return ((_a = this.context.currentFloor) == null ? void 0 : _a.userData.legacyToGraphicMap) || /* @__PURE__ */ new Map();
1788
2118
  }
2119
+ /**
2120
+ * 获取当前楼层全部的graphic
2121
+ * @returns
2122
+ */
2123
+ getFloorAllGraphics() {
2124
+ var _a;
2125
+ return ((_a = this.context.currentFloor) == null ? void 0 : _a.graphicLayer.children.filter((item) => item instanceof Graphic)) || [];
2126
+ }
1789
2127
  createGraphicPoi(graphic, options) {
1790
2128
  if (this.context.currentFloor) {
1791
2129
  const poi = this.context.currentFloor.addPoi(options);
@@ -1954,15 +2292,18 @@ var BMap = class extends EventDispatcher4 {
1954
2292
  };
1955
2293
  export {
1956
2294
  BMap,
2295
+ BaseSvg,
1957
2296
  Context,
1958
2297
  Floor,
1959
2298
  Graphic,
1960
2299
  GraphicLayer,
1961
2300
  HeatmapElement,
2301
+ HoverHelper,
1962
2302
  Layer,
1963
2303
  Overlay,
1964
2304
  Poi,
1965
2305
  PoiLayer,
2306
+ Selection,
1966
2307
  Shadow,
1967
2308
  SvgLine,
1968
2309
  SvgPolygon,
@@ -1972,6 +2313,7 @@ export {
1972
2313
  createCanvas,
1973
2314
  createCircle,
1974
2315
  createLine,
2316
+ createRect,
1975
2317
  createSvg,
1976
2318
  createSvgElement,
1977
2319
  defaultConfig,
@@ -1988,9 +2330,11 @@ export {
1988
2330
  initRenderer,
1989
2331
  initScene,
1990
2332
  initShape,
2333
+ isContain,
1991
2334
  proxyOptions,
1992
2335
  setCirclePosition,
1993
2336
  setLineStartEnd,
2337
+ setRectPosition,
1994
2338
  timeoutPromise,
1995
2339
  vector3ToDevice
1996
2340
  };