@sapui5/sap.ui.vbm 1.144.0 → 1.145.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/ui/vbm/.library +1 -1
- package/src/sap/ui/vbm/Adapter.js +1 -1
- package/src/sap/ui/vbm/Adapter3D.js +1 -1
- package/src/sap/ui/vbm/ContainerBase.js +1 -1
- package/src/sap/ui/vbm/Viewport.js +1 -1
- package/src/sap/ui/vbm/adapter3d/ColladaBounds.js +1 -1
- package/src/sap/ui/vbm/adapter3d/DragDropHandler.js +1 -1
- package/src/sap/ui/vbm/adapter3d/ModelHandler.js +1 -1
- package/src/sap/ui/vbm/adapter3d/ObjectFactory.js +1 -1
- package/src/sap/ui/vbm/adapter3d/PolygonHandler.js +1 -1
- package/src/sap/ui/vbm/adapter3d/RectangleTracker.js +1 -1
- package/src/sap/ui/vbm/adapter3d/SceneBuilder.js +1 -1
- package/src/sap/ui/vbm/adapter3d/VBIJSONParser.js +1 -1
- package/src/sap/ui/vbm/library.js +2 -2
- package/src/sap/ui/vbm/vector/MapRenderer.js +2 -185
- package/src/sap/ui/vbm/vector/PayloadGenerator.js +1 -1
- package/src/sap/ui/vbm/vector/RectangularSelection.js +1 -1
- package/src/sap/ui/vbm/vector/VectorUtils.js +161 -0
package/package.json
CHANGED
package/src/sap/ui/vbm/.library
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<name>sap.ui.vbm</name>
|
|
4
4
|
<vendor>SAP SE</vendor>
|
|
5
5
|
<copyright>SAP UI development toolkit for HTML5 (SAPUI5) (c) Copyright 2009-2012 SAP AG. All rights reserved</copyright>
|
|
6
|
-
<version>1.
|
|
6
|
+
<version>1.145.0</version>
|
|
7
7
|
|
|
8
8
|
<documentation>SAP UI library: sap.ui.vbm</documentation>
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ sap.ui.define([
|
|
|
24
24
|
* @param {string} [sId] id for the new control, generated automatically if no id is given
|
|
25
25
|
* @param {object} [mSettings] initial settings for the new object
|
|
26
26
|
* @author SAP SE
|
|
27
|
-
* @version 1.
|
|
27
|
+
* @version 1.145.0
|
|
28
28
|
* @extends sap.ui.core.Element
|
|
29
29
|
* @constructor
|
|
30
30
|
* @public
|
|
@@ -47,7 +47,7 @@ sap.ui.define([
|
|
|
47
47
|
* @param {string} [sId] id for the new control, generated automatically if no id is given
|
|
48
48
|
* @param {object} [mSettings] initial settings for the new object
|
|
49
49
|
* @author SAP SE
|
|
50
|
-
* @version 1.
|
|
50
|
+
* @version 1.145.0
|
|
51
51
|
* @extends sap.ui.core.Element
|
|
52
52
|
* @constructor
|
|
53
53
|
* @public
|
|
@@ -561,7 +561,7 @@ sap.ui.define([
|
|
|
561
561
|
this._$overlay = jQuery("<div id='" + uid() + "'></div>");
|
|
562
562
|
this._$overlay.addClass("sapUiVkContainerBaseOverlay");
|
|
563
563
|
this._$overlay.append(this.$content);
|
|
564
|
-
this._oPopup.setContent(this._$overlay);
|
|
564
|
+
this._oPopup.setContent(this._$overlay[0]);
|
|
565
565
|
} else {
|
|
566
566
|
Log.warning("Overlay: content does not exist or contains more than one child");
|
|
567
567
|
}
|
|
@@ -22,7 +22,7 @@ sap.ui.define([
|
|
|
22
22
|
*
|
|
23
23
|
* @private
|
|
24
24
|
* @author SAP SE
|
|
25
|
-
* @version 1.
|
|
25
|
+
* @version 1.145.0
|
|
26
26
|
* @alias sap.ui.vbm.adapter3d.ColladaBounds
|
|
27
27
|
*/
|
|
28
28
|
var ColladaBounds = BaseObject.extend("sap.ui.vbm.adapter3d.ColladaBounds", /** @lends sap.ui.vbm.adapter3d.ColladaBounds.prototype */ {
|
|
@@ -83,7 +83,7 @@ sap.ui.define([
|
|
|
83
83
|
*
|
|
84
84
|
* @private
|
|
85
85
|
* @author SAP SE
|
|
86
|
-
* @version 1.
|
|
86
|
+
* @version 1.145.0
|
|
87
87
|
* @alias sap.ui.vbm.adapter3d.DragDropHandler
|
|
88
88
|
*/
|
|
89
89
|
var DragDropHandler = BaseObject.extend("sap.ui.vbm.adapter3d.DragDropHandler", /** @lends sap.ui.vbm.adapter3d.DragDropHandler.prototype */ {
|
|
@@ -29,7 +29,7 @@ sap.ui.define([
|
|
|
29
29
|
*
|
|
30
30
|
* @private
|
|
31
31
|
* @author SAP SE
|
|
32
|
-
* @version 1.
|
|
32
|
+
* @version 1.145.0
|
|
33
33
|
* @alias sap.ui.vbm.adapter3d.ModelHandler
|
|
34
34
|
*/
|
|
35
35
|
var ModelHandler = BaseObject.extend("sap.ui.vbm.adapter3d.ModelHandler", /** @lends sap.ui.vbm.adapter3d.ModelHandler.prototype */ {
|
|
@@ -377,7 +377,7 @@ sap.ui.define([
|
|
|
377
377
|
*
|
|
378
378
|
* @private
|
|
379
379
|
* @author SAP SE
|
|
380
|
-
* @version 1.
|
|
380
|
+
* @version 1.145.0
|
|
381
381
|
* @alias sap.ui.vbm.adapter3d.ObjectFactory
|
|
382
382
|
*/
|
|
383
383
|
var ObjectFactory = BaseObject.extend("sap.ui.vbm.adapter3d.ObjectFactory", /** @lends sap.ui.vbm.adapter3d.ObjectFactory.prototype */ {});
|
|
@@ -32,7 +32,7 @@ sap.ui.define([
|
|
|
32
32
|
*
|
|
33
33
|
* @private
|
|
34
34
|
* @author SAP SE
|
|
35
|
-
* @version 1.
|
|
35
|
+
* @version 1.145.0
|
|
36
36
|
* @alias sap.ui.vbm.adapter3d.PolygonHandler
|
|
37
37
|
*/
|
|
38
38
|
var PolygonHandler = BaseObject.extend("sap.ui.vbm.adapter3d.PolygonHandler", /** @lends sap.ui.vbm.adapter3d.PolygonHandler.prototype */ {
|
|
@@ -39,7 +39,7 @@ sap.ui.define([
|
|
|
39
39
|
*
|
|
40
40
|
* @private
|
|
41
41
|
* @author SAP SE
|
|
42
|
-
* @version 1.
|
|
42
|
+
* @version 1.145.0
|
|
43
43
|
* @alias sap.ui.vbm.adapter3d.RectangleTracker
|
|
44
44
|
*/
|
|
45
45
|
var RectangleTracker = BaseObject.extend("sap.ui.vbm.adapter3d.RectangleTracker", /** @lends sap.ui.vbm.adapter3d.RectangleTracker.prototype */ {
|
|
@@ -47,7 +47,7 @@ sap.ui.define([
|
|
|
47
47
|
*
|
|
48
48
|
* @private
|
|
49
49
|
* @author SAP SE
|
|
50
|
-
* @version 1.
|
|
50
|
+
* @version 1.145.0
|
|
51
51
|
* @alias sap.ui.vbm.adapter3d.SceneBuilder
|
|
52
52
|
*/
|
|
53
53
|
var SceneBuilder = BaseObject.extend("sap.ui.vbm.adapter3d.SceneBuilder", /** @lends sap.ui.vbm.adapter3d.SceneBuilder.prototype */ {
|
|
@@ -56,7 +56,7 @@ sap.ui.define([
|
|
|
56
56
|
*
|
|
57
57
|
* @private
|
|
58
58
|
* @author SAP SE
|
|
59
|
-
* @version 1.
|
|
59
|
+
* @version 1.145.0
|
|
60
60
|
* @alias sap.ui.vbm.adapter3d.VBIJSONParser
|
|
61
61
|
*/
|
|
62
62
|
var VBIJSONParser = BaseObject.extend("sap.ui.vbm.adapter3d.VBIJSONParser", /** @lends sap.ui.vbm.adapter3d.VBIJSONParser.prototype */ {
|
|
@@ -20,7 +20,7 @@ sap.ui.define([
|
|
|
20
20
|
* @namespace
|
|
21
21
|
* @alias sap.ui.vbm
|
|
22
22
|
* @author SAP SE
|
|
23
|
-
* @version 1.
|
|
23
|
+
* @version 1.145.0
|
|
24
24
|
* @public
|
|
25
25
|
*/
|
|
26
26
|
|
|
@@ -46,7 +46,7 @@ sap.ui.define([
|
|
|
46
46
|
"sap.ui.vbm.ClusterBase", "sap.ui.vbm.ClusterTree", "sap.ui.vbm.ClusterGrid", "sap.ui.vbm.ClusterDistance", "sap.ui.vbm.Heatmap",
|
|
47
47
|
"sap.ui.vbm.HeatPoint", "sap.ui.vbm.ClusterContainer", "sap.ui.vbm.Adapter", "sap.ui.vbm.Adapter3D"
|
|
48
48
|
],
|
|
49
|
-
version: "1.
|
|
49
|
+
version: "1.145.0"
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
sap.ui.loader.config({
|
|
@@ -518,7 +518,7 @@ sap.ui.define([
|
|
|
518
518
|
|
|
519
519
|
if (marker.properties.Label) {
|
|
520
520
|
const coords = marker.geometry.coordinates;
|
|
521
|
-
let midpoint = getVisualMidpoint(coords, map);
|
|
521
|
+
let midpoint = VectorUtils.getVisualMidpoint(coords, map);
|
|
522
522
|
|
|
523
523
|
const routeLabelEl = VectorUtils.createRouteLabel(
|
|
524
524
|
marker.properties.Label,
|
|
@@ -534,7 +534,7 @@ sap.ui.define([
|
|
|
534
534
|
|
|
535
535
|
map.on('move', () => {
|
|
536
536
|
try {
|
|
537
|
-
const newPos = getVisualMidpoint(coords, map);
|
|
537
|
+
const newPos = VectorUtils.getVisualMidpoint(coords, map);
|
|
538
538
|
labelMarker.setLngLat(newPos);
|
|
539
539
|
} catch (e) {
|
|
540
540
|
console.warn("Label update failed:", e);
|
|
@@ -641,189 +641,6 @@ sap.ui.define([
|
|
|
641
641
|
'filter': ['==', '$type', 'LineString']
|
|
642
642
|
});
|
|
643
643
|
|
|
644
|
-
function getVisualMidpoint(coords, map) {
|
|
645
|
-
|
|
646
|
-
if (!Array.isArray(coords) || coords.length < 2) {
|
|
647
|
-
console.warn("getVisualMidpoint(): invalid coords", coords);
|
|
648
|
-
return coords?.[0] || [0, 0];
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
const clean = coords.filter(c =>
|
|
652
|
-
Array.isArray(c) &&
|
|
653
|
-
typeof c[0] === "number" &&
|
|
654
|
-
typeof c[1] === "number" &&
|
|
655
|
-
isFinite(c[0]) &&
|
|
656
|
-
isFinite(c[1])
|
|
657
|
-
);
|
|
658
|
-
|
|
659
|
-
if (clean.length < 2) {
|
|
660
|
-
console.warn("getVisualMidpoint(): after cleaning, less than 2 coords", clean);
|
|
661
|
-
return clean[0] || [0, 0];
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
coords = clean;
|
|
665
|
-
let projected;
|
|
666
|
-
try {
|
|
667
|
-
projected = coords.map(c => map.project({ lng: c[0], lat: c[1] }));
|
|
668
|
-
} catch (e) {
|
|
669
|
-
console.warn("project() failed for coords:", coords, e);
|
|
670
|
-
return coords[0];
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
const mapSize = map.getContainer().getBoundingClientRect();
|
|
674
|
-
const screenBounds = {
|
|
675
|
-
left: 0,
|
|
676
|
-
right: mapSize.width,
|
|
677
|
-
top: 0,
|
|
678
|
-
bottom: mapSize.height
|
|
679
|
-
};
|
|
680
|
-
|
|
681
|
-
const clipped = clipLineToScreen(projected, screenBounds);
|
|
682
|
-
|
|
683
|
-
if (clipped && clipped.length >= 2) {
|
|
684
|
-
try {
|
|
685
|
-
let totalLength = 0;
|
|
686
|
-
const segmentLengths = [];
|
|
687
|
-
|
|
688
|
-
for (let i = 0; i < clipped.length - 1; i++) {
|
|
689
|
-
const dx = clipped[i + 1].x - clipped[i].x;
|
|
690
|
-
const dy = clipped[i + 1].y - clipped[i].y;
|
|
691
|
-
const len = Math.sqrt(dx * dx + dy * dy);
|
|
692
|
-
|
|
693
|
-
if (isFinite(len) && len > 0) {
|
|
694
|
-
segmentLengths.push(len);
|
|
695
|
-
totalLength += len;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
if (totalLength === 0) throw "Zero total length";
|
|
700
|
-
|
|
701
|
-
let half = totalLength / 2;
|
|
702
|
-
let acc = 0;
|
|
703
|
-
|
|
704
|
-
for (let i = 0; i < segmentLengths.length; i++) {
|
|
705
|
-
const seg = segmentLengths[i];
|
|
706
|
-
|
|
707
|
-
if (!seg || !isFinite(seg)) continue;
|
|
708
|
-
|
|
709
|
-
if (acc + seg >= half) {
|
|
710
|
-
const ratio = (half - acc) / seg;
|
|
711
|
-
|
|
712
|
-
const x = clipped[i].x + ratio * (clipped[i + 1].x - clipped[i].x);
|
|
713
|
-
const y = clipped[i].y + ratio * (clipped[i + 1].y - clipped[i].y);
|
|
714
|
-
|
|
715
|
-
if (!isFinite(x) || !isFinite(y)) throw "NaN midpoint";
|
|
716
|
-
|
|
717
|
-
const mid = map.unproject({ x, y });
|
|
718
|
-
return [mid.lng, mid.lat];
|
|
719
|
-
}
|
|
720
|
-
acc += seg;
|
|
721
|
-
}
|
|
722
|
-
} catch (err) {
|
|
723
|
-
console.warn("Midpoint visual calculation failed, using geographic midpoint", err);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
return computeGeographicMidpoint(coords);
|
|
728
|
-
}
|
|
729
|
-
function computeGeographicMidpoint(coords) {
|
|
730
|
-
const mid = Math.floor(coords.length / 2);
|
|
731
|
-
return coords[mid];
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
function clipLineToScreen(projectedCoords, bounds) {
|
|
737
|
-
const clipped = [];
|
|
738
|
-
|
|
739
|
-
for (let i = 0; i < projectedCoords.length - 1; i++) {
|
|
740
|
-
const p1 = projectedCoords[i];
|
|
741
|
-
const p2 = projectedCoords[i + 1];
|
|
742
|
-
|
|
743
|
-
if (!p1 || !p2) continue;
|
|
744
|
-
|
|
745
|
-
const seg = clipSegmentToRect(p1, p2, bounds);
|
|
746
|
-
|
|
747
|
-
if (seg) {
|
|
748
|
-
if (clipped.length === 0) clipped.push(seg[0]);
|
|
749
|
-
clipped.push(seg[1]);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
return clipped.length > 1 ? clipped : null;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
function clipSegmentToRect(p1, p2, rect) {
|
|
757
|
-
|
|
758
|
-
const INSIDE = 0, LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8;
|
|
759
|
-
|
|
760
|
-
const computeOutCode = (x, y) => {
|
|
761
|
-
let code = INSIDE;
|
|
762
|
-
if (x < rect.left) code |= LEFT;
|
|
763
|
-
else if (x > rect.right) code |= RIGHT;
|
|
764
|
-
if (y < rect.top) code |= TOP;
|
|
765
|
-
else if (y > rect.bottom) code |= BOTTOM;
|
|
766
|
-
return code;
|
|
767
|
-
};
|
|
768
|
-
|
|
769
|
-
let x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
|
|
770
|
-
|
|
771
|
-
if (![x1, x2, y1, y2].every(isFinite)) return null;
|
|
772
|
-
|
|
773
|
-
let outcode1 = computeOutCode(x1, y1);
|
|
774
|
-
let outcode2 = computeOutCode(x2, y2);
|
|
775
|
-
|
|
776
|
-
let accept = false;
|
|
777
|
-
|
|
778
|
-
while (true) {
|
|
779
|
-
if (!(outcode1 | outcode2)) {
|
|
780
|
-
accept = true;
|
|
781
|
-
break;
|
|
782
|
-
} else if (outcode1 & outcode2) {
|
|
783
|
-
break;
|
|
784
|
-
} else {
|
|
785
|
-
const out = outcode1 ? outcode1 : outcode2;
|
|
786
|
-
|
|
787
|
-
const dx = x2 - x1;
|
|
788
|
-
const dy = y2 - y1;
|
|
789
|
-
|
|
790
|
-
if (!isFinite(dx) || !isFinite(dy)) return null;
|
|
791
|
-
|
|
792
|
-
let x, y;
|
|
793
|
-
|
|
794
|
-
if (out & TOP) {
|
|
795
|
-
if (dy === 0) return null;
|
|
796
|
-
x = x1 + dx * (rect.top - y1) / dy;
|
|
797
|
-
y = rect.top;
|
|
798
|
-
} else if (out & BOTTOM) {
|
|
799
|
-
if (dy === 0) return null;
|
|
800
|
-
x = x1 + dx * (rect.bottom - y1) / dy;
|
|
801
|
-
y = rect.bottom;
|
|
802
|
-
} else if (out & RIGHT) {
|
|
803
|
-
if (dx === 0) return null;
|
|
804
|
-
y = y1 + dy * (rect.right - x1) / dx;
|
|
805
|
-
x = rect.right;
|
|
806
|
-
} else if (out & LEFT) {
|
|
807
|
-
if (dx === 0) return null;
|
|
808
|
-
y = y1 + dy * (rect.left - x1) / dx;
|
|
809
|
-
x = rect.left;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
if (!isFinite(x) || !isFinite(y)) return null;
|
|
813
|
-
|
|
814
|
-
if (out === outcode1) {
|
|
815
|
-
x1 = x; y1 = y;
|
|
816
|
-
outcode1 = computeOutCode(x1, y1);
|
|
817
|
-
} else {
|
|
818
|
-
x2 = x; y2 = y;
|
|
819
|
-
outcode2 = computeOutCode(x2, y2);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
return accept ? [{ x: x1, y: y1 }, { x: x2, y: y2 }] : null;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
644
|
// Create a new FeatureCollection for the points
|
|
828
645
|
const pointGeoJSON = {
|
|
829
646
|
'type': 'FeatureCollection',
|
|
@@ -580,6 +580,167 @@ VectorUtils.createRouteLabel = (label, labelcolor) => {
|
|
|
580
580
|
return rect;
|
|
581
581
|
};
|
|
582
582
|
|
|
583
|
+
VectorUtils.getVisualMidpoint = function (coords, map) {
|
|
584
|
+
|
|
585
|
+
if (!Array.isArray(coords) || coords.length < 2) {
|
|
586
|
+
console.warn("getVisualMidpoint(): invalid coords", coords);
|
|
587
|
+
return coords?.[0] || [0, 0];
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const clean = coords.filter(c =>
|
|
591
|
+
Array.isArray(c) &&
|
|
592
|
+
typeof c[0] === "number" &&
|
|
593
|
+
typeof c[1] === "number" &&
|
|
594
|
+
isFinite(c[0]) &&
|
|
595
|
+
isFinite(c[1])
|
|
596
|
+
);
|
|
597
|
+
|
|
598
|
+
if (clean.length < 2) {
|
|
599
|
+
console.warn("getVisualMidpoint(): after cleaning, less than 2 coords", clean);
|
|
600
|
+
return clean[0] || [0, 0];
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
let projected;
|
|
604
|
+
try {
|
|
605
|
+
projected = clean.map(c => map.project({ lng: c[0], lat: c[1] }));
|
|
606
|
+
} catch (e) {
|
|
607
|
+
console.warn("project() failed", e);
|
|
608
|
+
return clean[0];
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const mapSize = map.getContainer().getBoundingClientRect();
|
|
612
|
+
const screenBounds = {
|
|
613
|
+
left: 0,
|
|
614
|
+
right: mapSize.width,
|
|
615
|
+
top: 0,
|
|
616
|
+
bottom: mapSize.height
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
const clipped = VectorUtils._clipLineToScreen(projected, screenBounds);
|
|
620
|
+
|
|
621
|
+
if (clipped && clipped.length >= 2) {
|
|
622
|
+
try {
|
|
623
|
+
let totalLength = 0;
|
|
624
|
+
const segmentLengths = [];
|
|
625
|
+
|
|
626
|
+
for (let i = 0; i < clipped.length - 1; i++) {
|
|
627
|
+
const dx = clipped[i + 1].x - clipped[i].x;
|
|
628
|
+
const dy = clipped[i + 1].y - clipped[i].y;
|
|
629
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
630
|
+
|
|
631
|
+
if (len > 0 && isFinite(len)) {
|
|
632
|
+
segmentLengths.push(len);
|
|
633
|
+
totalLength += len;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (totalLength === 0) throw "Zero total length";
|
|
638
|
+
|
|
639
|
+
let half = totalLength / 2;
|
|
640
|
+
let acc = 0;
|
|
641
|
+
|
|
642
|
+
for (let i = 0; i < segmentLengths.length; i++) {
|
|
643
|
+
const seg = segmentLengths[i];
|
|
644
|
+
if (acc + seg >= half) {
|
|
645
|
+
const ratio = (half - acc) / seg;
|
|
646
|
+
|
|
647
|
+
const x = clipped[i].x + ratio * (clipped[i + 1].x - clipped[i].x);
|
|
648
|
+
const y = clipped[i].y + ratio * (clipped[i + 1].y - clipped[i].y);
|
|
649
|
+
|
|
650
|
+
const mid = map.unproject({ x, y });
|
|
651
|
+
return [mid.lng, mid.lat];
|
|
652
|
+
}
|
|
653
|
+
acc += seg;
|
|
654
|
+
}
|
|
655
|
+
} catch (err) {
|
|
656
|
+
console.warn("Visual midpoint failed, fallback to geographic", err);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return VectorUtils._computeGeographicMidpoint(clean);
|
|
661
|
+
};
|
|
662
|
+
VectorUtils._computeGeographicMidpoint = function (coords) {
|
|
663
|
+
const mid = Math.floor(coords.length / 2);
|
|
664
|
+
return coords[mid];
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
VectorUtils._clipLineToScreen = function (projectedCoords, bounds) {
|
|
668
|
+
const clipped = [];
|
|
669
|
+
|
|
670
|
+
for (let i = 0; i < projectedCoords.length - 1; i++) {
|
|
671
|
+
const seg = VectorUtils._clipSegmentToRect(
|
|
672
|
+
projectedCoords[i],
|
|
673
|
+
projectedCoords[i + 1],
|
|
674
|
+
bounds
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
if (seg) {
|
|
678
|
+
if (clipped.length === 0) clipped.push(seg[0]);
|
|
679
|
+
clipped.push(seg[1]);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return clipped.length > 1 ? clipped : null;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
VectorUtils._clipSegmentToRect = function (p1, p2, rect) {
|
|
687
|
+
|
|
688
|
+
const INSIDE = 0, LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8;
|
|
689
|
+
|
|
690
|
+
const computeOutCode = (x, y) => {
|
|
691
|
+
let code = INSIDE;
|
|
692
|
+
if (x < rect.left) code |= LEFT;
|
|
693
|
+
else if (x > rect.right) code |= RIGHT;
|
|
694
|
+
if (y < rect.top) code |= TOP;
|
|
695
|
+
else if (y > rect.bottom) code |= BOTTOM;
|
|
696
|
+
return code;
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
let x1 = p1.x, y1 = p1.y;
|
|
700
|
+
let x2 = p2.x, y2 = p2.y;
|
|
701
|
+
|
|
702
|
+
let outcode1 = computeOutCode(x1, y1);
|
|
703
|
+
let outcode2 = computeOutCode(x2, y2);
|
|
704
|
+
|
|
705
|
+
while (true) {
|
|
706
|
+
if (!(outcode1 | outcode2)) {
|
|
707
|
+
return [{ x: x1, y: y1 }, { x: x2, y: y2 }];
|
|
708
|
+
}
|
|
709
|
+
if (outcode1 & outcode2) {
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const out = outcode1 ? outcode1 : outcode2;
|
|
714
|
+
const dx = x2 - x1;
|
|
715
|
+
const dy = y2 - y1;
|
|
716
|
+
|
|
717
|
+
let x, y;
|
|
718
|
+
|
|
719
|
+
if (out & TOP) {
|
|
720
|
+
x = x1 + dx * (rect.top - y1) / dy;
|
|
721
|
+
y = rect.top;
|
|
722
|
+
} else if (out & BOTTOM) {
|
|
723
|
+
x = x1 + dx * (rect.bottom - y1) / dy;
|
|
724
|
+
y = rect.bottom;
|
|
725
|
+
} else if (out & RIGHT) {
|
|
726
|
+
y = y1 + dy * (rect.right - x1) / dx;
|
|
727
|
+
x = rect.right;
|
|
728
|
+
} else {
|
|
729
|
+
y = y1 + dy * (rect.left - x1) / dx;
|
|
730
|
+
x = rect.left;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
if (out === outcode1) {
|
|
734
|
+
x1 = x; y1 = y;
|
|
735
|
+
outcode1 = computeOutCode(x1, y1);
|
|
736
|
+
} else {
|
|
737
|
+
x2 = x; y2 = y;
|
|
738
|
+
outcode2 = computeOutCode(x2, y2);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
|
|
583
744
|
return VectorUtils;
|
|
584
745
|
|
|
585
746
|
});
|