@aibee/crc-bmap 0.0.9 → 0.0.10

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 Vector36,
377
+ Vector2 as Vector23,
378
+ Raycaster as Raycaster2,
379
+ Box3 as Box33,
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,11 @@ 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";
1065
781
 
1066
782
  // src/layer/layer.ts
1067
- import { Object3D as Object3D6 } from "three";
1068
- var Layer = class extends Object3D6 {
783
+ import { Object3D as Object3D5 } from "three";
784
+ var Layer = class extends Object3D5 {
1069
785
  constructor(context) {
1070
786
  super();
1071
787
  this.context = context;
@@ -1214,7 +930,7 @@ var PoiLayer = class extends Layer {
1214
930
  // src/elements/heatmap.ts
1215
931
  import {
1216
932
  MeshBasicMaterial,
1217
- Object3D as Object3D7,
933
+ Object3D as Object3D6,
1218
934
  PlaneGeometry as PlaneGeometry2,
1219
935
  Texture,
1220
936
  DoubleSide as DoubleSide2,
@@ -1224,7 +940,7 @@ import {
1224
940
  } from "three";
1225
941
  import { create } from "@mars3d/heatmap.js";
1226
942
  import { featureCollection as featureCollection2, point as point2, bbox, center as getCenter2 } from "@turf/turf";
1227
- var HeatmapElement = class extends Object3D7 {
943
+ var HeatmapElement = class extends Object3D6 {
1228
944
  constructor(context) {
1229
945
  super();
1230
946
  this.context = context;
@@ -1308,7 +1024,7 @@ var HeatmapElement = class extends Object3D7 {
1308
1024
  };
1309
1025
 
1310
1026
  // src/elements/floor.ts
1311
- var Floor = class extends Object3D8 {
1027
+ var Floor = class extends Object3D7 {
1312
1028
  constructor(context) {
1313
1029
  super();
1314
1030
  this.context = context;
@@ -1376,8 +1092,8 @@ var Floor = class extends Object3D8 {
1376
1092
  };
1377
1093
 
1378
1094
  // src/elements/base-svg.ts
1379
- import { EventDispatcher as EventDispatcher3, Raycaster as Raycaster3, Vector2 as Vector23 } from "three";
1380
- var BaseSvg = class extends EventDispatcher3 {
1095
+ import { EventDispatcher as EventDispatcher2, Vector3 as Vector34 } from "three";
1096
+ var BaseSvg = class extends EventDispatcher2 {
1381
1097
  constructor(context) {
1382
1098
  super();
1383
1099
  this.context = context;
@@ -1396,18 +1112,13 @@ var BaseSvg = class extends EventDispatcher3 {
1396
1112
  }
1397
1113
  }
1398
1114
  getIntersectByPointerEvent(e) {
1399
- var _a;
1400
- if (!((_a = this.context.currentFloor) == null ? void 0 : _a.ground)) {
1401
- return;
1402
- }
1115
+ const { camera, renderer } = this.context;
1403
1116
  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];
1117
+ const { clientWidth, clientHeight } = renderer.domElement;
1118
+ const nx = x / clientWidth * 2 - 1;
1119
+ const ny = 1 - y / clientHeight * 2;
1120
+ const v = new Vector34(nx, ny, 0);
1121
+ return v.unproject(camera);
1411
1122
  }
1412
1123
  getSvgCoordinate(vector) {
1413
1124
  const { camera, container } = this.context;
@@ -1443,223 +1154,823 @@ var SvgLine = class extends BaseSvg {
1443
1154
  if (this.points.length !== 1) {
1444
1155
  return;
1445
1156
  }
1446
- this.line.style.display = "block";
1447
- setLineStartEnd(this.line, void 0, { x: e.offsetX, y: e.offsetY });
1157
+ this.line.style.display = "block";
1158
+ setLineStartEnd(this.line, void 0, { x: e.offsetX, y: e.offsetY });
1159
+ });
1160
+ __publicField(this, "onPointerleave", () => {
1161
+ if (this.points[1]) {
1162
+ return;
1163
+ }
1164
+ this.line.style.display = "none";
1165
+ });
1166
+ __publicField(this, "onPointerdown", (e) => {
1167
+ if (this.points[1]) {
1168
+ return;
1169
+ }
1170
+ const point3 = this.getIntersectByPointerEvent(e);
1171
+ if (point3) {
1172
+ const { offsetX: x, offsetY: y } = e;
1173
+ const circle = this.circles[this.points.length];
1174
+ setCirclePosition(circle, x, y);
1175
+ if (!this.points.length) {
1176
+ setLineStartEnd(this.line, { x, y }, { x, y });
1177
+ }
1178
+ this.addPoint(point3);
1179
+ }
1180
+ });
1181
+ const { config: { svg: { circle, line } } } = context;
1182
+ this.circles = [createCircle(circle.radius, circle.fill), createCircle(circle.radius, circle.fill)];
1183
+ this.line = createLine(line.stroke);
1184
+ this.svg.appendChild(this.circles[0]);
1185
+ this.svg.appendChild(this.circles[1]);
1186
+ this.svg.appendChild(this.line);
1187
+ this.registryEvent();
1188
+ }
1189
+ setEnable(enable) {
1190
+ super.setEnable(enable);
1191
+ if (enable) {
1192
+ this.registryEvent();
1193
+ } else {
1194
+ this.unRegistryEvent();
1195
+ }
1196
+ }
1197
+ registryEvent() {
1198
+ this.context.container.addEventListener("pointerenter", this.onPointermove);
1199
+ this.context.container.addEventListener("pointermove", this.onPointermove);
1200
+ this.context.container.addEventListener("pointerleave", this.onPointerleave);
1201
+ this.context.container.addEventListener("pointerdown", this.onPointerdown);
1202
+ this.context.addEventListener("update", this.onUpdate);
1203
+ }
1204
+ unRegistryEvent() {
1205
+ this.context.container.removeEventListener("pointerenter", this.onPointermove);
1206
+ this.context.container.removeEventListener("pointermove", this.onPointermove);
1207
+ this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1208
+ this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1209
+ this.context.removeEventListener("update", this.onUpdate);
1210
+ }
1211
+ addPoint(vector) {
1212
+ this.points.push(vector);
1213
+ if (this.points.length >= 2) {
1214
+ const distance = this.calculatedDistance();
1215
+ this.dispatchEvent({ type: "distance", distance });
1216
+ }
1217
+ }
1218
+ /**
1219
+ * 计算两个点之间的距离
1220
+ */
1221
+ calculatedDistance() {
1222
+ const [{ x: x1, y: y1 }, { x: x2, y: y2 }] = this.points;
1223
+ return Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
1224
+ }
1225
+ dispose() {
1226
+ super.dispose();
1227
+ this.unRegistryEvent();
1228
+ this.line = null;
1229
+ this.circles = [];
1230
+ }
1231
+ };
1232
+
1233
+ // src/elements/svg-polygon.ts
1234
+ var SvgPolygon = class extends BaseSvg {
1235
+ constructor(context) {
1236
+ super(context);
1237
+ __publicField(this, "circles", []);
1238
+ __publicField(this, "lines", []);
1239
+ __publicField(this, "isClose", false);
1240
+ __publicField(this, "onUpdate", () => {
1241
+ if (this.points.length) {
1242
+ this.points.forEach((point3, index) => {
1243
+ const devicePoint = this.getSvgCoordinate(point3);
1244
+ if (this.circles[index]) {
1245
+ setCirclePosition(this.circles[index], devicePoint.x, devicePoint.y);
1246
+ }
1247
+ if (index !== 0) {
1248
+ setLineStartEnd(this.lines[index - 1], void 0, devicePoint);
1249
+ }
1250
+ if (this.lines[index]) {
1251
+ setLineStartEnd(this.lines[index], devicePoint);
1252
+ }
1253
+ });
1254
+ }
1255
+ });
1256
+ __publicField(this, "onPointermove", (e) => {
1257
+ if (!this.lastLine || this.isClose) {
1258
+ return;
1259
+ }
1260
+ this.lastLine.style.display = "block";
1261
+ setLineStartEnd(this.lastLine, void 0, { x: e.offsetX, y: e.offsetY });
1262
+ });
1263
+ __publicField(this, "onPointerleave", () => {
1264
+ if (this.isClose) {
1265
+ return;
1266
+ }
1267
+ this.lastLine.style.display = "none";
1268
+ });
1269
+ __publicField(this, "onPointerdown", (e) => {
1270
+ if (this.isClose) {
1271
+ return;
1272
+ }
1273
+ const point3 = this.getIntersectByPointerEvent(e);
1274
+ if (point3) {
1275
+ const { offsetX: x, offsetY: y } = e;
1276
+ if (this.checkAdsorb(x, y)) {
1277
+ this.isClose = true;
1278
+ this.addPoint(this.points[0]);
1279
+ } else {
1280
+ this.addPoint(point3);
1281
+ }
1282
+ const { circle: { fill, radius }, line: { stroke } } = this.context.config.svg;
1283
+ if (!this.isClose) {
1284
+ const circle = createCircle(radius, fill);
1285
+ setCirclePosition(circle, x, y);
1286
+ this.addCircle(circle);
1287
+ }
1288
+ if (this.lines.length) {
1289
+ setLineStartEnd(this.lastLine, void 0, { x, y });
1290
+ }
1291
+ if (!this.isClose) {
1292
+ const line = createLine(stroke);
1293
+ setLineStartEnd(line, { x, y }, { x, y });
1294
+ this.addLine(line);
1295
+ }
1296
+ }
1297
+ });
1298
+ this.registryEvent();
1299
+ }
1300
+ setEnable(enable) {
1301
+ super.setEnable(enable);
1302
+ if (enable) {
1303
+ this.registryEvent();
1304
+ } else {
1305
+ this.unRegistryEvent();
1306
+ }
1307
+ }
1308
+ get lastLine() {
1309
+ return this.lines.slice(-1)[0];
1310
+ }
1311
+ addCircle(circle) {
1312
+ this.circles.push(circle);
1313
+ this.svg.appendChild(circle);
1314
+ }
1315
+ addLine(line) {
1316
+ this.lines.push(line);
1317
+ this.svg.appendChild(line);
1318
+ }
1319
+ registryEvent() {
1320
+ this.context.container.addEventListener("pointerenter", this.onPointermove);
1321
+ this.context.container.addEventListener("pointermove", this.onPointermove);
1322
+ this.context.container.addEventListener("pointerleave", this.onPointerleave);
1323
+ this.context.container.addEventListener("pointerdown", this.onPointerdown);
1324
+ this.context.addEventListener("update", this.onUpdate);
1325
+ }
1326
+ unRegistryEvent() {
1327
+ this.context.container.removeEventListener("pointerenter", this.onPointermove);
1328
+ this.context.container.removeEventListener("pointermove", this.onPointermove);
1329
+ this.context.container.removeEventListener("pointerleave", this.onPointerleave);
1330
+ this.context.container.removeEventListener("pointerdown", this.onPointerdown);
1331
+ this.context.removeEventListener("update", this.onUpdate);
1332
+ }
1333
+ /**
1334
+ * 检测是否可以吸附
1335
+ * 坐标点最少3个 传入的坐标点和第一个坐标的像素相差不超过5个像素
1336
+ */
1337
+ checkAdsorb(x, y) {
1338
+ if (this.points.length < 3) {
1339
+ return false;
1340
+ }
1341
+ const circle = this.circles[0];
1342
+ const cx = +circle.getAttribute("cx");
1343
+ const cy = +circle.getAttribute("cy");
1344
+ return Math.sqrt(__pow(x - cx, 2) + __pow(y - cy, 2)) <= 5;
1345
+ }
1346
+ addPoint(vector) {
1347
+ this.points.push(vector);
1348
+ if (this.isClose) {
1349
+ const area = this.calculatedArea();
1350
+ this.dispatchEvent({ type: "area", area });
1351
+ }
1352
+ }
1353
+ // 计算面积
1354
+ calculatedArea() {
1355
+ const cds = this.points.map((item) => [item.x, item.y]);
1356
+ let area = 0;
1357
+ const numPoints = cds.length;
1358
+ for (let i = 0; i < numPoints; i++) {
1359
+ const j = (i + 1) % numPoints;
1360
+ area += cds[i][0] * cds[j][1] - cds[j][0] * cds[i][1];
1361
+ }
1362
+ return Math.abs(area / 2);
1363
+ }
1364
+ dispose() {
1365
+ super.dispose();
1366
+ this.unRegistryEvent();
1367
+ this.lines = [];
1368
+ this.circles = [];
1369
+ }
1370
+ };
1371
+
1372
+ // src/operations/selection/box-selection.ts
1373
+ import { Frustum } from "three";
1374
+ var BoxSelection = class extends BaseSvg {
1375
+ constructor(context) {
1376
+ super(context);
1377
+ __publicField(this, "startPoint");
1378
+ __publicField(this, "endPoint");
1379
+ __publicField(this, "rect");
1380
+ __publicField(this, "frustum", new Frustum());
1381
+ __publicField(this, "onPointerDown", (e) => {
1382
+ if (!this.enable) {
1383
+ return;
1384
+ }
1385
+ const point3 = this.getIntersectByPointerEvent(e);
1386
+ if (point3) {
1387
+ this.startPoint = point3;
1388
+ }
1389
+ this.endPoint = void 0;
1448
1390
  });
1449
- __publicField(this, "onPointerleave", () => {
1450
- if (this.points[1]) {
1391
+ __publicField(this, "onPointerMove", (e) => {
1392
+ if (!this.enable || !this.startPoint) {
1451
1393
  return;
1452
1394
  }
1453
- this.line.style.display = "none";
1395
+ const point3 = this.getIntersectByPointerEvent(e);
1396
+ if (point3) {
1397
+ this.endPoint = point3;
1398
+ }
1454
1399
  });
1455
- __publicField(this, "onPointerdown", (e) => {
1456
- if (this.points[1]) {
1400
+ __publicField(this, "onPointerUp", (e) => {
1401
+ if (!this.enable) {
1457
1402
  return;
1458
1403
  }
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 });
1404
+ const point3 = this.getIntersectByPointerEvent(e);
1405
+ if (point3) {
1406
+ this.endPoint = point3;
1407
+ }
1408
+ this.doSelect();
1409
+ this.startPoint = void 0;
1410
+ });
1411
+ __publicField(this, "onUpdate", () => {
1412
+ if (this.startPoint) {
1413
+ const startPoint = this.getSvgCoordinate(this.startPoint);
1414
+ let endPoint = __spreadValues({}, startPoint);
1415
+ if (this.endPoint) {
1416
+ endPoint = this.getSvgCoordinate(this.endPoint);
1466
1417
  }
1467
- this.addPoint(intersect.point);
1418
+ const leftTop = { x: Math.min(startPoint.x, endPoint.x), y: Math.min(startPoint.y, endPoint.y) };
1419
+ const width = Math.abs(endPoint.x - startPoint.x);
1420
+ const height = Math.abs(endPoint.y - startPoint.y);
1421
+ setRectPosition(this.rect, leftTop.x, leftTop.y, width, height);
1468
1422
  }
1469
1423
  });
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);
1424
+ const { config: { selectBox: { fill, stroke } } } = context;
1425
+ this.rect = createRect(stroke, fill);
1426
+ this.svg.appendChild(this.rect);
1476
1427
  this.registryEvent();
1477
1428
  }
1478
1429
  setEnable(enable) {
1479
1430
  super.setEnable(enable);
1480
- if (enable) {
1481
- this.registryEvent();
1482
- } else {
1483
- this.unRegistryEvent();
1484
- }
1431
+ setRectPosition(this.rect, 0, 0, 0, 0);
1485
1432
  }
1486
1433
  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);
1434
+ this.context.container.addEventListener("pointerdown", this.onPointerDown);
1435
+ this.context.container.addEventListener("pointermove", this.onPointerMove);
1436
+ this.context.container.addEventListener("pointerup", this.onPointerUp);
1491
1437
  this.context.addEventListener("update", this.onUpdate);
1492
1438
  }
1493
1439
  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);
1440
+ this.context.container.removeEventListener("pointerdown", this.onPointerDown);
1441
+ this.context.container.removeEventListener("pointermove", this.onPointerMove);
1442
+ this.context.container.removeEventListener("pointerup", this.onPointerUp);
1498
1443
  this.context.removeEventListener("update", this.onUpdate);
1499
1444
  }
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 });
1445
+ doSelect() {
1446
+ if (this.startPoint && this.endPoint) {
1447
+ const dis = this.startPoint.distanceTo(this.endPoint);
1448
+ if (dis < 0.1) {
1449
+ return;
1450
+ }
1451
+ const { context: { camera, container: { clientWidth: w, clientHeight: h } } } = this;
1452
+ const startDevice = vector3ToDevice(this.startPoint, camera, w, h);
1453
+ const endDevice = vector3ToDevice(this.endPoint, camera, w, h);
1454
+ const leftTop = { x: Math.min(startDevice.x, endDevice.x), y: Math.min(startDevice.y, endDevice.y) };
1455
+ const rightBottom = { x: Math.max(startDevice.x, endDevice.x), y: Math.max(startDevice.y, endDevice.y) };
1456
+ const list = this.searchMapInFrustum(leftTop, rightBottom);
1457
+ this.dispatchEvent({ type: "selected", list });
1505
1458
  }
1506
1459
  }
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));
1460
+ searchMapInFrustum(leftTop, rightBottom) {
1461
+ var _a;
1462
+ const { context } = this;
1463
+ return ((_a = context.currentFloor) == null ? void 0 : _a.graphicLayer.children.filter((item) => {
1464
+ return item instanceof Graphic && this.searchChildInFrustum(item, leftTop, rightBottom);
1465
+ })) || [];
1466
+ }
1467
+ searchChildInFrustum(object, leftTop, rightBottom) {
1468
+ const { context: { camera, container: { clientWidth: w, clientHeight: h } } } = this;
1469
+ if (!object)
1470
+ return false;
1471
+ if (!object.mesh.geometry.boundingBox) {
1472
+ object.mesh.geometry.computeBoundingBox();
1473
+ }
1474
+ const box = object.mesh.geometry.boundingBox;
1475
+ if (!box) {
1476
+ return false;
1477
+ }
1478
+ const { min, max } = box;
1479
+ const minDevice = vector3ToDevice(min, camera, w, h);
1480
+ const maxDevice = vector3ToDevice(max, camera, w, h);
1481
+ if (!isContain(minDevice, leftTop, rightBottom)) {
1482
+ return false;
1483
+ }
1484
+ if (!isContain(maxDevice, leftTop, rightBottom)) {
1485
+ return false;
1486
+ }
1487
+ return true;
1513
1488
  }
1514
1489
  dispose() {
1515
- super.dispose();
1516
1490
  this.unRegistryEvent();
1517
- this.line = null;
1518
- this.circles = [];
1519
1491
  }
1520
1492
  };
1521
1493
 
1522
- // src/elements/svg-polygon.ts
1523
- var SvgPolygon = class extends BaseSvg {
1494
+ // src/operations/selection/selection.ts
1495
+ var Selection = class extends EventDispatcher3 {
1524
1496
  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
- });
1497
+ super();
1498
+ this.context = context;
1499
+ __publicField(this, "_list", /* @__PURE__ */ new Set());
1500
+ __publicField(this, "boxSelection");
1501
+ __publicField(this, "prevPanStatus");
1502
+ __publicField(this, "onPointerDown", (e) => {
1503
+ const { graphics } = this.context.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1504
+ if (!e.ctrlKey) {
1505
+ this._list.clear();
1543
1506
  }
1507
+ graphics.forEach((item) => this._list.add(item));
1508
+ this.selectEnd();
1544
1509
  });
1545
- __publicField(this, "onPointermove", (e) => {
1546
- if (!this.lastLine || this.isClose) {
1547
- return;
1510
+ __publicField(this, "onKeyDown", (e) => {
1511
+ if (e.key === "Control") {
1512
+ this.boxSelection.setEnable(true);
1513
+ this.prevPanStatus = this.context.control.enablePan;
1514
+ this.context.control.enablePan = false;
1548
1515
  }
1549
- this.lastLine.style.display = "block";
1550
- setLineStartEnd(this.lastLine, void 0, { x: e.offsetX, y: e.offsetY });
1551
1516
  });
1552
- __publicField(this, "onPointerleave", () => {
1553
- if (this.isClose) {
1554
- return;
1517
+ __publicField(this, "onKeyUp", (e) => {
1518
+ if (e.key === "Control") {
1519
+ this.boxSelection.setEnable(false);
1520
+ this.context.control.enablePan = !!this.prevPanStatus;
1555
1521
  }
1556
- this.lastLine.style.display = "none";
1557
1522
  });
1558
- __publicField(this, "onPointerdown", (e) => {
1559
- if (this.isClose) {
1523
+ __publicField(this, "onBoxSelected", ({ list }) => {
1524
+ this._list.clear();
1525
+ list.forEach((item) => {
1526
+ this._list.add(item);
1527
+ });
1528
+ this.selectEnd();
1529
+ });
1530
+ this.boxSelection = new BoxSelection(context);
1531
+ this.boxSelection.setEnable(false);
1532
+ this.registryEvent();
1533
+ }
1534
+ get list() {
1535
+ return this._list;
1536
+ }
1537
+ selectEnd() {
1538
+ this.dispatchEvent({ type: "select", graphics: [...this._list] });
1539
+ }
1540
+ registryEvent() {
1541
+ this.context.container.addEventListener("pointerdown", this.onPointerDown);
1542
+ window.addEventListener("keydown", this.onKeyDown);
1543
+ window.addEventListener("keyup", this.onKeyUp);
1544
+ this.boxSelection.addEventListener("selected", this.onBoxSelected);
1545
+ }
1546
+ unRegistryEvent() {
1547
+ this.context.container.removeEventListener("pointerdown", this.onPointerDown);
1548
+ window.removeEventListener("keydown", this.onKeyDown);
1549
+ window.removeEventListener("keyup", this.onKeyUp);
1550
+ this.boxSelection.removeEventListener("selected", this.onBoxSelected);
1551
+ }
1552
+ dispose() {
1553
+ this.unRegistryEvent();
1554
+ }
1555
+ };
1556
+
1557
+ // src/operations/hover/hover-helper.ts
1558
+ import { EventDispatcher as EventDispatcher4 } from "three";
1559
+ var HoverHelper = class extends EventDispatcher4 {
1560
+ constructor(context) {
1561
+ super();
1562
+ this.context = context;
1563
+ __publicField(this, "curGraphics", /* @__PURE__ */ new Set());
1564
+ __publicField(this, "timer", new Timer());
1565
+ __publicField(this, "graphicTimerMap", /* @__PURE__ */ new Map());
1566
+ __publicField(this, "onPointerMove", ({ graphics }) => {
1567
+ if (!graphics.length && this.curGraphics.size) {
1568
+ this.curGraphics.clear();
1569
+ this.handleHoverGraphicsChange();
1560
1570
  return;
1561
1571
  }
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);
1572
+ const { time } = this.context.config.hover;
1573
+ graphics.forEach((graphic) => {
1574
+ if (this.graphicTimerMap.get(graphic)) {
1575
+ return;
1570
1576
  }
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);
1577
+ if (this.curGraphics.has(graphic)) {
1578
+ return;
1576
1579
  }
1577
- if (this.lines.length) {
1578
- setLineStartEnd(this.lastLine, void 0, { x, y });
1580
+ const timer = this.timer.setTimeout(() => {
1581
+ this.curGraphics.add(graphic);
1582
+ this.handleHoverGraphicsChange();
1583
+ }, time);
1584
+ this.graphicTimerMap.set(graphic, timer);
1585
+ });
1586
+ this.graphicTimerMap.forEach((timer, graphic) => {
1587
+ if (!graphics.includes(graphic)) {
1588
+ this.timer.clearTimeout(timer);
1589
+ this.graphicTimerMap.delete(graphic);
1579
1590
  }
1580
- if (!this.isClose) {
1581
- const line = createLine(stroke);
1582
- setLineStartEnd(line, { x, y }, { x, y });
1583
- this.addLine(line);
1591
+ });
1592
+ const size = this.curGraphics.size;
1593
+ this.curGraphics.forEach((graphic) => {
1594
+ if (!graphics.includes(graphic)) {
1595
+ this.curGraphics.delete(graphic);
1584
1596
  }
1597
+ });
1598
+ if (size !== this.curGraphics.size) {
1599
+ this.handleHoverGraphicsChange();
1585
1600
  }
1586
1601
  });
1602
+ __publicField(this, "onPointerLevel", () => {
1603
+ this.curGraphics.clear();
1604
+ this.handleHoverGraphicsChange();
1605
+ });
1587
1606
  this.registryEvent();
1588
1607
  }
1589
- setEnable(enable) {
1590
- super.setEnable(enable);
1591
- if (enable) {
1592
- this.registryEvent();
1593
- } else {
1594
- this.unRegistryEvent();
1608
+ handleHoverGraphicsChange(graphics = this.curGraphics) {
1609
+ this.dispatchEvent({ type: "hover-change", graphics: Array.from(this.curGraphics) });
1610
+ }
1611
+ registryEvent() {
1612
+ this.context.addEventListener("pointer-over", this.onPointerMove);
1613
+ this.context.addEventListener("pointer-move", this.onPointerMove);
1614
+ this.context.addEventListener("pointer-level", this.onPointerLevel);
1615
+ }
1616
+ unRegistryEvent() {
1617
+ this.context.removeEventListener("pointer-over", this.onPointerMove);
1618
+ this.context.removeEventListener("pointer-move", this.onPointerMove);
1619
+ this.context.removeEventListener("pointer-level", this.onPointerLevel);
1620
+ }
1621
+ dispose() {
1622
+ this.unRegistryEvent();
1623
+ this.timer.dispose();
1624
+ }
1625
+ };
1626
+
1627
+ // src/context.ts
1628
+ var Context = class extends EventDispatcher5 {
1629
+ // zoom=1的时候,100M对应的像素个数
1630
+ constructor(container, config) {
1631
+ super();
1632
+ this.container = container;
1633
+ this.config = config;
1634
+ __publicField(this, "scene", initScene());
1635
+ __publicField(this, "renderer", initRenderer());
1636
+ __publicField(this, "camera");
1637
+ __publicField(this, "control");
1638
+ __publicField(this, "lights", initLight());
1639
+ // 管理任务,防止内存泄漏
1640
+ __publicField(this, "timer", new Timer());
1641
+ __publicField(this, "tweenGroup", new TweenGroup());
1642
+ __publicField(this, "currentFloor");
1643
+ __publicField(this, "selection");
1644
+ __publicField(this, "hoverHelper");
1645
+ __publicField(this, "basicRatio");
1646
+ __publicField(this, "onWindowResize", () => {
1647
+ const { container, camera, renderer } = this;
1648
+ const { clientWidth: w, clientHeight: h } = container;
1649
+ camera.left = -w / 2;
1650
+ camera.right = w / 2;
1651
+ camera.top = h / 2;
1652
+ camera.bottom = -h / 2;
1653
+ camera.updateProjectionMatrix();
1654
+ renderer.setSize(window.innerWidth, window.innerHeight);
1655
+ });
1656
+ __publicField(this, "onClick", (e) => {
1657
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1658
+ if (graphics.length) {
1659
+ this.dispatchEvent({
1660
+ type: "graphic-click",
1661
+ graphics,
1662
+ position
1663
+ });
1664
+ }
1665
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1666
+ if (pois.length) {
1667
+ this.dispatchEvent({ type: "poi-click", pois });
1668
+ }
1669
+ });
1670
+ __publicField(this, "onPointerover", (e) => {
1671
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1672
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1673
+ this.dispatchEvent({ type: "pointer-over", graphics, pois, position });
1674
+ });
1675
+ __publicField(this, "onPointermove", (e) => {
1676
+ const { graphics, position } = this.getGraphicsByDeviceXy(e.offsetX, e.offsetY);
1677
+ const pois = this.getPoisByDeviceXy(e.clientX, e.clientY);
1678
+ this.dispatchEvent({ type: "pointer-move", graphics, pois, position });
1679
+ });
1680
+ __publicField(this, "onPointerleave", () => {
1681
+ this.dispatchEvent({ type: "pointer-level" });
1682
+ });
1683
+ __publicField(this, "onSelectionSelect", ({ graphics }) => {
1684
+ this.dispatchEvent({ type: "select-graphic", graphics });
1685
+ });
1686
+ __publicField(this, "onHoverChange", ({ graphics }) => {
1687
+ this.dispatchEvent({ type: "hover", graphics });
1688
+ });
1689
+ this.container.style.position = "relative";
1690
+ this.container.style.overflow = "hidden";
1691
+ this.init();
1692
+ this.selection = new Selection(this);
1693
+ this.hoverHelper = new HoverHelper(this);
1694
+ this.registryEvent();
1695
+ }
1696
+ init() {
1697
+ const { clientWidth: w, clientHeight: h } = this.container;
1698
+ this.camera = initCamera(w, h);
1699
+ this.renderer.setSize(w, h);
1700
+ this.control = initControl(this.camera, this.renderer.domElement);
1701
+ this.container.appendChild(this.renderer.domElement);
1702
+ this.scene.add(this.lights);
1703
+ this.basicRatio = this.getRatio();
1704
+ this.control.addEventListener("change", () => {
1705
+ var _a;
1706
+ const polarAngle = this.control.getPolarAngle();
1707
+ (_a = this.currentFloor) == null ? void 0 : _a.setShadowOpacity(polarAngle / this.config.control.maxPolar);
1708
+ this.dispatchEvent({ type: "change-ratio", px: (this.basicRatio || 0) * this.camera.zoom });
1709
+ });
1710
+ }
1711
+ /**
1712
+ * 获取两个点之间的像素数
1713
+ */
1714
+ getRatio(point1 = new Vector36(0, 0, 0), point22 = new Vector36(100, 0, 0)) {
1715
+ const { clientWidth, clientHeight } = this.container;
1716
+ const device1 = vector3ToDevice(point1, this.camera, clientWidth, clientHeight);
1717
+ const device2 = vector3ToDevice(point22, this.camera, clientWidth, clientHeight);
1718
+ return Math.ceil(Math.sqrt(__pow(device2.x - device1.x, 2) + __pow(device2.y - device1.y, 2)));
1719
+ }
1720
+ changeAmbientLightColor(color) {
1721
+ this.lights.children.forEach((item) => {
1722
+ if (item instanceof AmbientLight2) {
1723
+ item.color = new Color4(color);
1724
+ }
1725
+ });
1726
+ }
1727
+ switchFloor(floor) {
1728
+ var _a;
1729
+ if (this.currentFloor) {
1730
+ this.scene.remove(this.currentFloor);
1731
+ this.currentFloor.dispose();
1732
+ }
1733
+ this.currentFloor = floor;
1734
+ this.scene.add(floor);
1735
+ const position = (_a = floor.ground) == null ? void 0 : _a.getCenter();
1736
+ if (position) {
1737
+ this.lights.position.x = position.x;
1738
+ this.lights.position.y = position.y;
1595
1739
  }
1596
1740
  }
1597
- get lastLine() {
1598
- return this.lines.slice(-1)[0];
1599
- }
1600
- addCircle(circle) {
1601
- this.circles.push(circle);
1602
- this.svg.appendChild(circle);
1741
+ /**
1742
+ * 获取屏幕坐标对应的graphic
1743
+ * @param x
1744
+ * @param y
1745
+ * @returns
1746
+ */
1747
+ getGraphicsByDeviceXy(x, y) {
1748
+ var _a;
1749
+ const point3 = new Vector23();
1750
+ point3.x = x / this.container.clientWidth * 2 - 1;
1751
+ point3.y = y / this.container.clientHeight * -2 + 1;
1752
+ const raycaster = new Raycaster2();
1753
+ raycaster.setFromCamera(point3, this.camera);
1754
+ const res = (_a = this.currentFloor) == null ? void 0 : _a.graphicLayer.getGraphicByRaycaster(raycaster);
1755
+ return res || { graphics: [], position: null };
1603
1756
  }
1604
- addLine(line) {
1605
- this.lines.push(line);
1606
- this.svg.appendChild(line);
1757
+ /**
1758
+ * 获取屏幕坐标对应的poi
1759
+ * @param x
1760
+ * @param y
1761
+ * @returns
1762
+ */
1763
+ getPoisByDeviceXy(x, y) {
1764
+ var _a;
1765
+ const pois = (_a = this.currentFloor) == null ? void 0 : _a.poiLayer.getPoiByDeviceXy(x, y);
1766
+ return pois || [];
1607
1767
  }
1608
1768
  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);
1769
+ window.addEventListener("resize", this.onWindowResize);
1770
+ this.container.addEventListener("click", this.onClick);
1771
+ this.container.addEventListener("pointerover", this.onPointerover);
1772
+ this.container.addEventListener("pointermove", this.onPointermove);
1773
+ this.container.addEventListener("pointerleave", this.onPointerleave);
1774
+ this.selection.addEventListener("select", this.onSelectionSelect);
1775
+ this.hoverHelper.addEventListener("hover-change", this.onHoverChange);
1614
1776
  }
1615
1777
  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);
1778
+ window.removeEventListener("resize", this.onWindowResize);
1779
+ this.container.removeEventListener("click", this.onClick);
1780
+ this.container.removeEventListener("pointerover", this.onPointerover);
1781
+ this.container.removeEventListener("pointermove", this.onPointermove);
1782
+ this.container.removeEventListener("pointerleave", this.onPointerleave);
1783
+ this.selection.removeEventListener("select", this.onSelectionSelect);
1784
+ this.hoverHelper.removeEventListener("hover-change", this.onHoverChange);
1621
1785
  }
1622
1786
  /**
1623
- * 检测是否可以吸附
1624
- * 坐标点最少3个 传入的坐标点和第一个坐标的像素相差不超过5个像素
1787
+ * 设置纵向旋转角度
1788
+ * @param polar 弧度
1625
1789
  */
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;
1790
+ setPolarAngle(polar, duration = 500) {
1791
+ return timeoutPromise(
1792
+ new Promise((resolve) => {
1793
+ const start = { polar: this.control.getPolarAngle() };
1794
+ const end = { polar };
1795
+ const tween = new Tween(start, this.tweenGroup).to(end, duration).onUpdate(() => {
1796
+ this.control.maxPolarAngle = start.polar;
1797
+ this.control.minPolarAngle = start.polar;
1798
+ this.control.update();
1799
+ }).onComplete(() => {
1800
+ this.control.enabled = true;
1801
+ this.tweenGroup.remove(tween);
1802
+ resolve(true);
1803
+ }).onStart(() => {
1804
+ this.control.enabled = false;
1805
+ }).start();
1806
+ }),
1807
+ duration + 500
1808
+ );
1634
1809
  }
1635
- addPoint(vector) {
1636
- this.points.push(vector);
1637
- if (this.isClose) {
1638
- const area = this.calculatedArea();
1639
- this.dispatchEvent({ type: "area", area });
1640
- }
1810
+ getCameraLookAt() {
1811
+ return new Vector36().subVectors(this.control.target, this.camera.position);
1641
1812
  }
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];
1813
+ /**
1814
+ * 按照一个中心点设置相机的放大缩小
1815
+ * @param zoom
1816
+ * @param center
1817
+ * @returns
1818
+ */
1819
+ setZoom(zoom, center2, duration = 500) {
1820
+ return timeoutPromise(
1821
+ new Promise((resolve) => {
1822
+ const start = {
1823
+ zoom: this.camera.zoom,
1824
+ target: this.control.target.clone()
1825
+ };
1826
+ const lookAtVector = this.getCameraLookAt();
1827
+ const tween = new Tween(start, this.tweenGroup).to(
1828
+ {
1829
+ zoom,
1830
+ target: center2
1831
+ },
1832
+ duration
1833
+ ).onUpdate(() => {
1834
+ this.camera.position.copy(start.target.clone().sub(lookAtVector));
1835
+ this.control.target.copy(start.target);
1836
+ this.camera.zoom = start.zoom;
1837
+ this.control.update();
1838
+ }).onComplete(() => {
1839
+ this.tweenGroup.remove(tween);
1840
+ this.control.enabled = true;
1841
+ resolve(true);
1842
+ }).onStart(() => {
1843
+ this.control.enabled = false;
1844
+ }).start();
1845
+ }),
1846
+ duration + 500
1847
+ );
1848
+ }
1849
+ /**
1850
+ * 放大相机到物体占全屏
1851
+ * @param object
1852
+ * @param padding
1853
+ * @param duration
1854
+ * @returns
1855
+ */
1856
+ fitCameraToObject(object, padding = [20, 20, 20, 20], duration = 500) {
1857
+ const [top, right, bottom, left] = padding;
1858
+ const { clientWidth, clientHeight } = this.container;
1859
+ const boundingBox = new Box33().setFromObject(object);
1860
+ const { max, min } = boundingBox;
1861
+ const max2d = vector3ToDevice(max, this.camera, clientWidth, clientHeight);
1862
+ const min2d = vector3ToDevice(min, this.camera, clientWidth, clientHeight);
1863
+ const boundingBox2d = new Box2().setFromPoints([
1864
+ new Vector23(max2d.x, max2d.y),
1865
+ new Vector23(min2d.x, min2d.y)
1866
+ ]);
1867
+ const size = boundingBox2d.getSize(new Vector23());
1868
+ const xScale = (clientWidth - right - left) / size.x;
1869
+ const yScale = (clientHeight - top - bottom) / size.y;
1870
+ const scale = Math.min(xScale, yScale);
1871
+ const center2 = new Vector36((max.x + min.x) / 2, (max.y + min.y) / 2, max.z);
1872
+ return this.setZoom(scale * this.camera.zoom, center2, duration);
1873
+ }
1874
+ fitCameraToGround(padding = [20, 20, 20, 20], duration = 500) {
1875
+ if (this.currentFloor) {
1876
+ return this.fitCameraToObject(this.currentFloor.graphicLayer, padding, duration);
1877
+ } else {
1878
+ return Promise.resolve(false);
1650
1879
  }
1651
- return Math.abs(area / 2);
1880
+ }
1881
+ /**
1882
+ * 修改相机位置
1883
+ * @param position 修改后的相机的位置
1884
+ * @param duration 动画持续时间
1885
+ */
1886
+ setCameraPosition(position, duration) {
1887
+ return timeoutPromise(
1888
+ new Promise((resolve) => {
1889
+ const start = this.camera.position.clone();
1890
+ const lookAtVector = this.getCameraLookAt();
1891
+ const tween = new Tween(start, this.tweenGroup).to(position, duration).onUpdate(() => {
1892
+ this.camera.position.copy(start);
1893
+ this.control.target.copy(position.clone().add(lookAtVector));
1894
+ }).onComplete(() => {
1895
+ this.tweenGroup.remove(tween);
1896
+ this.control.update();
1897
+ this.control.enabled = true;
1898
+ resolve(true);
1899
+ }).onStart(() => {
1900
+ this.control.enabled = false;
1901
+ }).start();
1902
+ }),
1903
+ duration + 500
1904
+ );
1905
+ }
1906
+ render() {
1907
+ this.renderer.render(this.scene, this.camera);
1908
+ this.dispatchEvent({ type: "update" });
1909
+ this.timer.requestAnimationFrame(() => {
1910
+ this.render();
1911
+ });
1912
+ this.tweenGroup.update();
1652
1913
  }
1653
1914
  dispose() {
1654
- super.dispose();
1915
+ this.selection.dispose();
1916
+ this.hoverHelper.dispose();
1917
+ this.tweenGroup.getAll().forEach((item) => item.stop());
1918
+ this.tweenGroup.removeAll();
1655
1919
  this.unRegistryEvent();
1656
- this.lines = [];
1657
- this.circles = [];
1920
+ this.container.removeChild(this.renderer.domElement);
1921
+ this.timer.dispose();
1922
+ this.renderer.dispose();
1923
+ this.lights.children.forEach(
1924
+ (light) => light.dispose()
1925
+ );
1926
+ dispose(this.scene);
1927
+ }
1928
+ };
1929
+
1930
+ // src/config.ts
1931
+ import { merge as merge3 } from "lodash";
1932
+ var defaultConfig = {
1933
+ apiDomain: "",
1934
+ apiInfo: {},
1935
+ apiPath: {
1936
+ floorGraphic: "/api/inception-map/floor/get",
1937
+ floorRange: "/api/inception-map/range/get"
1938
+ },
1939
+ heatMap: {
1940
+ radius: 50,
1941
+ gradient: {
1942
+ 0: "#8F9FCD",
1943
+ 0.5: "#6284FF",
1944
+ 1: "#F95D5D"
1945
+ }
1946
+ },
1947
+ useFloorCache: true,
1948
+ control: {
1949
+ maxPolar: 1.2
1950
+ },
1951
+ svg: {
1952
+ circle: {
1953
+ radius: "2",
1954
+ fill: "#1CADFF"
1955
+ },
1956
+ line: {
1957
+ stroke: "#1CADFF"
1958
+ }
1959
+ },
1960
+ selectBox: {
1961
+ stroke: "#1CADFF",
1962
+ fill: "rgba(28, 173, 255, 0.3)"
1963
+ },
1964
+ hover: {
1965
+ time: 500
1658
1966
  }
1659
1967
  };
1968
+ function getConfig(config) {
1969
+ return merge3({}, defaultConfig, config);
1970
+ }
1660
1971
 
1661
1972
  // src/bmap.ts
1662
- var BMap = class extends EventDispatcher4 {
1973
+ var BMap = class extends EventDispatcher6 {
1663
1974
  constructor(container, config = {}) {
1664
1975
  super();
1665
1976
  this.container = container;
@@ -1669,6 +1980,7 @@ var BMap = class extends EventDispatcher4 {
1669
1980
  __publicField(this, "azimuthalKeys", []);
1670
1981
  __publicField(this, "svgLine");
1671
1982
  __publicField(this, "svgPolygon");
1983
+ __publicField(this, "basicZoom", 1);
1672
1984
  __publicField(this, "floorDataMap", /* @__PURE__ */ new Map());
1673
1985
  __publicField(this, "onKeydown", (e) => {
1674
1986
  if (this.polarKeys.includes(e.code)) {
@@ -1703,7 +2015,7 @@ var BMap = class extends EventDispatcher4 {
1703
2015
  const url = `${apiDomain}${floorGraphic}?brand=${brand}&project=${project}&phase=${phase}&building=${building}&floor=${floor}&ts=${ts}&resource_type_list=`;
1704
2016
  const data = yield fetch(url, apiInfo).then((res) => res.json()).then((res) => res.data).then((res) => {
1705
2017
  (res || []).map((item) => item.info = JSON.parse(item.info));
1706
- return res;
2018
+ return res || [];
1707
2019
  });
1708
2020
  return data;
1709
2021
  });
@@ -1713,10 +2025,13 @@ var BMap = class extends EventDispatcher4 {
1713
2025
  const { apiDomain, apiPath: { floorRange }, apiInfo } = this.config;
1714
2026
  const url = `${apiDomain}${floorRange}?brand=${brand}&project=${project}&phase=${phase}&building=${building}`;
1715
2027
  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;
2028
+ const data2 = (res || [])[0];
2029
+ if (data2) {
2030
+ data2.info = JSON.parse(data2.info);
2031
+ }
2032
+ return data2;
1718
2033
  });
1719
- return data[0];
2034
+ return data;
1720
2035
  });
1721
2036
  }
1722
2037
  load(_0) {
@@ -1728,17 +2043,19 @@ var BMap = class extends EventDispatcher4 {
1728
2043
  this.loadGraphics({ brand, project, phase, building, floor, ts }),
1729
2044
  this.loadBuildingGround({ brand, project, phase, building })
1730
2045
  ]);
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
- }
2046
+ if (buildGround) {
2047
+ const center2 = getCenter(buildGround.info.geometry.cds[0]);
2048
+ data.forEach((item) => {
2049
+ item.info.geometry.cds.map((cds) => {
2050
+ if (Array.isArray(cds)) {
2051
+ cds.forEach((coord) => {
2052
+ coord[0] -= center2[0];
2053
+ coord[1] -= center2[1];
2054
+ });
2055
+ }
2056
+ });
1740
2057
  });
1741
- });
2058
+ }
1742
2059
  if (!this.config.useFloorCache) {
1743
2060
  this.floorDataMap.clear();
1744
2061
  }
@@ -1747,17 +2064,18 @@ var BMap = class extends EventDispatcher4 {
1747
2064
  });
1748
2065
  }
1749
2066
  createFloor(data) {
1750
- const curFloor = new Floor(this.context);
1751
- let groundIndex = data.findIndex((item) => item.info.group === "floor");
1752
- if (groundIndex === -1) {
1753
- groundIndex = 0;
2067
+ if (!data.length) {
2068
+ return null;
1754
2069
  }
1755
- const ground = data[groundIndex];
1756
- console.log(ground.info.height, ground.info.airHeight);
2070
+ const curFloor = new Floor(this.context);
1757
2071
  const list = [...data];
1758
- list.splice(groundIndex, 1);
1759
- const groundGraphic = new Graphic(this.context, ground.info);
1760
- curFloor.addGround(groundGraphic);
2072
+ let groundIndex = data.findIndex((item) => item.info.group === "ground");
2073
+ if (groundIndex !== -1) {
2074
+ const ground = data[groundIndex];
2075
+ const groundGraphic = new Graphic(this.context, ground.info);
2076
+ curFloor.addGround(groundGraphic);
2077
+ list.splice(groundIndex, 1);
2078
+ }
1761
2079
  const legacyToGraphicMap = /* @__PURE__ */ new Map();
1762
2080
  const graphics = list.map((item) => {
1763
2081
  const graphic = curFloor.addGraphic(item.info);
@@ -1766,14 +2084,19 @@ var BMap = class extends EventDispatcher4 {
1766
2084
  return graphic;
1767
2085
  });
1768
2086
  curFloor.userData.legacyToGraphicMap = legacyToGraphicMap;
1769
- return { curFloor, ground: groundGraphic, graphics };
2087
+ return { curFloor, graphics };
1770
2088
  }
1771
2089
  switchFloor(floor) {
1772
2090
  const curFloorData = this.floorDataMap.get(floor);
1773
2091
  if (curFloorData) {
1774
- const { curFloor } = this.createFloor(curFloorData);
1775
- this.context.switchFloor(curFloor);
1776
- this.context.fitCameraToGround(void 0, 0);
2092
+ const createdFloor = this.createFloor(curFloorData);
2093
+ if (createdFloor) {
2094
+ this.context.switchFloor(createdFloor.curFloor);
2095
+ this.context.fitCameraToGround(void 0, 0);
2096
+ this.basicZoom = this.context.camera.zoom;
2097
+ } else {
2098
+ console.warn("[switchFloor error] [" + floor + "] \u697C\u5C42\u6CA1\u6709\u6570\u636E");
2099
+ }
1777
2100
  } else {
1778
2101
  console.warn("[switchFloor error] \u6CA1\u6709\u8FD9\u4E2A\u697C\u5C42\uFF0C\u8BF7\u5148\u8C03\u7528load\u65B9\u6CD5\u52A0\u8F7D\u697C\u5C42");
1779
2102
  }
@@ -1786,6 +2109,14 @@ var BMap = class extends EventDispatcher4 {
1786
2109
  var _a;
1787
2110
  return ((_a = this.context.currentFloor) == null ? void 0 : _a.userData.legacyToGraphicMap) || /* @__PURE__ */ new Map();
1788
2111
  }
2112
+ /**
2113
+ * 获取当前楼层全部的graphic
2114
+ * @returns
2115
+ */
2116
+ getFloorAllGraphics() {
2117
+ var _a;
2118
+ return ((_a = this.context.currentFloor) == null ? void 0 : _a.graphicLayer.children.filter((item) => item instanceof Graphic)) || [];
2119
+ }
1789
2120
  createGraphicPoi(graphic, options) {
1790
2121
  if (this.context.currentFloor) {
1791
2122
  const poi = this.context.currentFloor.addPoi(options);
@@ -1954,15 +2285,18 @@ var BMap = class extends EventDispatcher4 {
1954
2285
  };
1955
2286
  export {
1956
2287
  BMap,
2288
+ BaseSvg,
1957
2289
  Context,
1958
2290
  Floor,
1959
2291
  Graphic,
1960
2292
  GraphicLayer,
1961
2293
  HeatmapElement,
2294
+ HoverHelper,
1962
2295
  Layer,
1963
2296
  Overlay,
1964
2297
  Poi,
1965
2298
  PoiLayer,
2299
+ Selection,
1966
2300
  Shadow,
1967
2301
  SvgLine,
1968
2302
  SvgPolygon,
@@ -1972,6 +2306,7 @@ export {
1972
2306
  createCanvas,
1973
2307
  createCircle,
1974
2308
  createLine,
2309
+ createRect,
1975
2310
  createSvg,
1976
2311
  createSvgElement,
1977
2312
  defaultConfig,
@@ -1988,9 +2323,11 @@ export {
1988
2323
  initRenderer,
1989
2324
  initScene,
1990
2325
  initShape,
2326
+ isContain,
1991
2327
  proxyOptions,
1992
2328
  setCirclePosition,
1993
2329
  setLineStartEnd,
2330
+ setRectPosition,
1994
2331
  timeoutPromise,
1995
2332
  vector3ToDevice
1996
2333
  };