@sapui5/sap.ui.vbm 1.145.0 → 1.146.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 +4 -4
- package/src/sap/ui/vbm/Adapter3D.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/themes/base/AnalyticMap.less +5 -5
- package/src/sap/ui/vbm/themes/base/Cluster.less +41 -48
- package/src/sap/ui/vbm/themes/base/ContainerBase.less +14 -14
- package/src/sap/ui/vbm/themes/base/ContainerLegendItem.less +12 -27
- package/src/sap/ui/vbm/themes/base/DetailWindow.less +12 -8
- package/src/sap/ui/vbm/themes/base/ListPanel.less +17 -18
- package/src/sap/ui/vbm/themes/base/ListPanelStack.less +9 -10
- package/src/sap/ui/vbm/themes/base/MapContainer.less +49 -41
- package/src/sap/ui/vbm/themes/base/VBI.less +356 -491
- package/src/sap/ui/vbm/themes/base/Viewport.less +5 -1
- package/src/sap/ui/vbm/themes/base/library.source.less +1 -2
- package/src/sap/ui/vbm/themes/sap_fiori_3_dark/VBI.less +46 -55
- package/src/sap/ui/vbm/themes/sap_fiori_3_dark/library.source.less +1 -2
- package/src/sap/ui/vbm/themes/sap_fiori_3_hcb/VBI.less +46 -55
- package/src/sap/ui/vbm/themes/sap_fiori_3_hcb/library.source.less +1 -2
- package/src/sap/ui/vbm/themes/sap_horizon_dark/VBI.less +45 -54
- package/src/sap/ui/vbm/themes/sap_horizon_dark/library.source.less +1 -2
- package/src/sap/ui/vbm/themes/sap_horizon_hcb/VBI.less +45 -54
- package/src/sap/ui/vbm/themes/sap_horizon_hcb/library.source.less +1 -3
- package/src/sap/ui/vbm/themes/sap_horizon_hcw/VBI.less +45 -54
- package/src/sap/ui/vbm/themes/sap_horizon_hcw/library.source.less +1 -2
- package/src/sap/ui/vbm/vector/MapRenderer.js +497 -416
- 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/VBITransformer.js +19 -4
- package/src/sap/ui/vbm/themes/base/GeoMap.less +0 -8
- package/src/sap/ui/vbm/themes/sap_fiori_3_dark/AnalyticMap.less +0 -4
- package/src/sap/ui/vbm/themes/sap_fiori_3_hcb/AnalyticMap.less +0 -4
- package/src/sap/ui/vbm/themes/sap_horizon_dark/AnalyticMap.less +0 -3
- package/src/sap/ui/vbm/themes/sap_horizon_hcb/AnalyticMap.less +0 -3
- package/src/sap/ui/vbm/themes/sap_horizon_hcw/AnalyticMap.less +0 -3
|
@@ -12,21 +12,14 @@ sap.ui.define([
|
|
|
12
12
|
"./SAPNavControl",
|
|
13
13
|
"./SAPAutomationManager",
|
|
14
14
|
"sap/ui/core/Lib",
|
|
15
|
-
//"../lib/sapscene",
|
|
16
15
|
"./thirdparty/maplibregl",
|
|
17
16
|
"./VBITransformer"
|
|
18
|
-
], function (vb, visualobjects, actions, VBIRenderer, VectorUtils, MaplibreStyles, PayloadGenerator, RectangularSelection, LassoSelection, SAPMapNavControl, SAPAutomationManager, Lib) {
|
|
17
|
+
], function (vb, visualobjects, actions, VBIRenderer, VectorUtils, MaplibreStyles, PayloadGenerator, RectangularSelection, LassoSelection, SAPMapNavControl, SAPAutomationManager, Lib) {
|
|
19
18
|
'use strict';
|
|
20
19
|
visualobjects = {};
|
|
21
20
|
VBI.MapRenderer = {};
|
|
22
21
|
actions = {};
|
|
23
22
|
var map_container = "";
|
|
24
|
-
//let isDragging = false;
|
|
25
|
-
//let startY;
|
|
26
|
-
//let startYpx;
|
|
27
|
-
// let isDrawing = false;
|
|
28
|
-
// let isCtrlPressed = false;
|
|
29
|
-
// let lassoPoints = [];
|
|
30
23
|
let predefinedMarkers = [];
|
|
31
24
|
let allMarkers = [];
|
|
32
25
|
let lineDrag = false;
|
|
@@ -35,12 +28,15 @@ sap.ui.define([
|
|
|
35
28
|
let dropItems = {};
|
|
36
29
|
let dragInstance = {};
|
|
37
30
|
VBI.MapRenderer.name = undefined;
|
|
31
|
+
VBI.MapRenderer.allMarkers = undefined;
|
|
38
32
|
let spotid = 0;
|
|
39
33
|
let fixedBounds;
|
|
40
34
|
var containerID;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
let geoJSON;
|
|
36
|
+
var map;
|
|
37
|
+
let mapCanvas;
|
|
38
|
+
const renderedSpots = new Map();
|
|
39
|
+
const renderedRouteLabels = new Map();
|
|
44
40
|
|
|
45
41
|
|
|
46
42
|
VBI.MapRenderer.setAdapter = (adapter) => {
|
|
@@ -48,120 +44,147 @@ sap.ui.define([
|
|
|
48
44
|
this._payloadGenerator = new PayloadGenerator(this._adapter);
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
VBI.MapRenderer.renderMap = () => {
|
|
48
|
+
|
|
49
|
+
// if (this.map) {
|
|
50
|
+
// previousCenter = this.map.getCenter();
|
|
51
|
+
// previousZoom = this.map.getZoom();
|
|
52
|
+
// this.map.remove();
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
geoJSON = VBI.VBITransformer.getTransformedJSON();
|
|
56
|
+
|
|
57
|
+
map_container = VBIRenderer.getId();
|
|
58
|
+
|
|
59
|
+
var styleSheet = document.createElement("style");
|
|
60
|
+
|
|
61
|
+
styleSheet.textContent = MaplibreStyles.loadStyles();
|
|
62
|
+
document.head.appendChild(styleSheet);
|
|
63
|
+
if (!window._maplibreMap) {
|
|
64
|
+
window._maplibreMap = VectorUtils.createMap(geoJSON, map_container);
|
|
65
|
+
}
|
|
66
|
+
map = window._maplibreMap;
|
|
67
|
+
const canvas = map.getCanvasContainer();
|
|
68
|
+
const rectangularSelection = new RectangularSelection(map);
|
|
69
|
+
const lassoSelection = new LassoSelection(map);
|
|
70
|
+
const popupLink = new maplibregl.Popup({
|
|
71
|
+
closeButton: false,
|
|
72
|
+
closeOnClick: false
|
|
73
|
+
});
|
|
74
|
+
// Set `true` to dispatch the event before other functions
|
|
75
|
+
// call it. This is necessary for disabling the default map
|
|
76
|
+
// dragging behaviour.
|
|
77
|
+
canvas.addEventListener('mousedown', (e) => rectangularSelection.mouseDown(e, this.Rpressed), true);
|
|
78
|
+
canvas.addEventListener('mousedown', (e) => lassoSelection.mouseDown(e, this.Apressed), true);
|
|
79
|
+
map.touchZoomRotate.enable();
|
|
80
|
+
mapCanvas = map.getCanvas();
|
|
81
|
+
mapCanvas.id = VectorUtils._setcanvasid();
|
|
82
|
+
mapCanvas.oncontextmenu = (e) => {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
// Get the mouse coordinates within the map container
|
|
85
|
+
const rect = canvas.getBoundingClientRect(); // Get map container position
|
|
86
|
+
const x = e.clientX - rect.left; // Relative to map
|
|
87
|
+
const y = e.clientY - rect.top;
|
|
88
|
+
const lngLat = map.unproject([x, y]);
|
|
89
|
+
// Check if the right-click happened on the 'geojson-source-route' layer
|
|
90
|
+
const features = map.queryRenderedFeatures([x, y], { layers: ['geojson-source-route'] });
|
|
53
91
|
|
|
92
|
+
if (features.length > 0) {
|
|
93
|
+
e.features = features;
|
|
94
|
+
// The context menu is for the 'geojson-source-route' layer
|
|
95
|
+
triggerPayloadRoute(e, 'CONTEXT_MENU_REQUEST');
|
|
96
|
+
} else {
|
|
97
|
+
// Get the mouse coordinates within the map container
|
|
98
|
+
const offsetX = e.offsetX;
|
|
99
|
+
const offsetY = e.offsetY;
|
|
100
|
+
const lngLat = map.unproject([offsetX, offsetY]);
|
|
101
|
+
// The context menu is for the map
|
|
102
|
+
const coords = lngLat.lng + ";" + lngLat.lat + ";0.0";
|
|
103
|
+
const currentZoom = map.getZoom();
|
|
104
|
+
const center = map.getCenter();
|
|
105
|
+
const currentCenter = center.lng + ";" + center.lat;
|
|
106
|
+
const xyobj = VectorUtils.GetEventVPCoordsObj(e, map_container);
|
|
107
|
+
const screenX = xyobj.x;
|
|
108
|
+
const screenY = xyobj.y;
|
|
109
|
+
PayloadGenerator.onMapContextMenu(coords, currentZoom, currentCenter, screenX, screenY);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
map.on('load', () => {
|
|
114
|
+
|
|
115
|
+
map.getCanvas().style.cursor = 'default';
|
|
116
|
+
map.on('mouseup', function () {
|
|
117
|
+
map.getCanvas().style.cursor = 'default';
|
|
118
|
+
});
|
|
119
|
+
map.getCanvas().addEventListener('mousemove', function () {
|
|
120
|
+
map.getCanvas().style.cursor = 'default';
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (VBI.mapFlags.isLegendExists) {
|
|
124
|
+
// Legend control
|
|
125
|
+
VBI.VBITransformer._createLegend(map_container);
|
|
126
|
+
}
|
|
127
|
+
// Custom attribution/copyright control
|
|
128
|
+
map.addControl(new maplibregl.AttributionControl({
|
|
129
|
+
customAttribution: '<span>' + geoJSON[0].copyright + '</span>',
|
|
130
|
+
compact: false
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
//validate scale visiblity
|
|
134
|
+
var scaleControl = new maplibregl.ScaleControl({
|
|
135
|
+
maxWidth: 80,
|
|
136
|
+
unit: geoJSON[0].scaleType
|
|
137
|
+
})
|
|
138
|
+
if (VBI.mapFlags.scaleVisible) {
|
|
139
|
+
// Scale control in mi,km or nm
|
|
140
|
+
map.addControl(scaleControl);
|
|
141
|
+
} else if (!VBI.mapFlags.scaleVisible && map.hasControl(scaleControl)) {
|
|
142
|
+
map.removeControl(scaleControl);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Parsing GeoJSON for each type of object
|
|
146
|
+
|
|
147
|
+
map.addSource('geojson-source', {
|
|
148
|
+
'type': 'geojson',
|
|
149
|
+
'data': geoJSON[1]
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
let sapNavControl = new SAPMapNavControl(VBI.mapFlags.moveDisable, VBI.mapFlags.zoomDisable);
|
|
153
|
+
if (VBI.mapFlags.navControlVisible) {
|
|
154
|
+
map.addControl(sapNavControl, 'top-left');
|
|
155
|
+
} else if (!VBI.mapFlags.navControlVisible && map.hasControl(sapNavControl)) {
|
|
156
|
+
map.removeControl(sapNavControl);
|
|
157
|
+
}
|
|
158
|
+
// Create a popup, but don't add it to the map yet.
|
|
159
|
+
const popup = new maplibregl.Popup({
|
|
160
|
+
closeButton: false,
|
|
161
|
+
closeOnClick: false,
|
|
162
|
+
offset: {
|
|
163
|
+
'top': [0, 0],
|
|
164
|
+
'bottom': [0, -25]
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
54
168
|
}
|
|
55
169
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
170
|
+
VBI.MapRenderer._processAutomation = () => {
|
|
171
|
+
let automations = new SAPAutomationManager(map, maplibregl.LngLatBounds);
|
|
172
|
+
automations.load(VBI.mapFlags.automations);
|
|
59
173
|
}
|
|
60
174
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (this.map) {
|
|
64
|
-
previousCenter = this.map.getCenter();
|
|
65
|
-
previousZoom = this.map.getZoom();
|
|
66
|
-
this.map.remove();
|
|
67
|
-
}
|
|
175
|
+
VBI.MapRenderer._processGeoSpot = () => {
|
|
68
176
|
|
|
69
|
-
let geoJSON = VBI.VBITransformer.getTransformedJSON();
|
|
70
|
-
|
|
71
|
-
map_container = VBIRenderer.getId();
|
|
72
|
-
|
|
73
|
-
var styleSheet = document.createElement("style");
|
|
74
|
-
|
|
75
|
-
styleSheet.textContent = MaplibreStyles.loadStyles();
|
|
76
|
-
document.head.appendChild(styleSheet);
|
|
77
|
-
|
|
78
|
-
const map = VectorUtils.createMap(geoJSON, map_container);
|
|
79
|
-
map.doubleClickZoom.disable();
|
|
80
|
-
|
|
81
|
-
if (previousCenter && previousZoom !== null) {
|
|
82
|
-
map.jumpTo({
|
|
83
|
-
center: [previousCenter.lng, previousCenter.lat],
|
|
84
|
-
zoom: previousZoom
|
|
85
|
-
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const canvas = map.getCanvasContainer();
|
|
90
|
-
const rectangularSelection = new RectangularSelection(map);
|
|
91
|
-
const lassoSelection = new LassoSelection(map);
|
|
92
|
-
const mapCanvas = map.getCanvas();
|
|
93
|
-
const popupLink = new maplibregl.Popup({
|
|
94
|
-
closeButton: false,
|
|
95
|
-
closeOnClick: false
|
|
96
|
-
});
|
|
97
|
-
mapCanvas.id = VectorUtils._setcanvasid();
|
|
98
|
-
// Set `true` to dispatch the event before other functions
|
|
99
|
-
// call it. This is necessary for disabling the default map
|
|
100
|
-
// dragging behaviour.
|
|
101
|
-
canvas.addEventListener('mousedown', (e) => rectangularSelection.mouseDown(e, this.Rpressed), true);
|
|
102
|
-
canvas.addEventListener('mousedown', (e) => lassoSelection.mouseDown(e, this.Apressed), true);
|
|
103
|
-
map.touchZoomRotate.enable();
|
|
104
|
-
this.map = map;
|
|
105
|
-
map.on('load', () => {
|
|
106
|
-
|
|
107
|
-
map.getCanvas().style.cursor = 'default';
|
|
108
|
-
map.on('mouseup', function () {
|
|
109
|
-
map.getCanvas().style.cursor = 'default';
|
|
110
|
-
});
|
|
111
|
-
map.getCanvas().addEventListener('mousemove', function () {
|
|
112
|
-
map.getCanvas().style.cursor = 'default';
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
if (VBI.mapFlags.isLegendExists) {
|
|
116
|
-
// Legend control
|
|
117
|
-
VBI.VBITransformer._createLegend(map_container);
|
|
118
|
-
}
|
|
119
|
-
// Custom attribution/copyright control
|
|
120
|
-
map.addControl(new maplibregl.AttributionControl({
|
|
121
|
-
customAttribution: '<span>' + geoJSON[0].copyright + '</span>',
|
|
122
|
-
compact: false
|
|
123
|
-
})
|
|
124
|
-
);
|
|
125
|
-
//validate scale visiblity
|
|
126
|
-
var scaleControl = new maplibregl.ScaleControl({
|
|
127
|
-
maxWidth: 80,
|
|
128
|
-
unit: geoJSON[0].scaleType
|
|
129
|
-
})
|
|
130
|
-
if (VBI.mapFlags.scaleVisible) {
|
|
131
|
-
// Scale control in mi,km or nm
|
|
132
|
-
map.addControl(scaleControl);
|
|
133
|
-
} else if (!VBI.mapFlags.scaleVisible && map.hasControl(scaleControl)) {
|
|
134
|
-
map.removeControl(scaleControl);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Parsing GeoJSON for each type of object
|
|
138
|
-
map.addSource('geojson-source', {
|
|
139
|
-
'type': 'geojson',
|
|
140
|
-
'data': geoJSON[1]
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
let sapNavControl = new SAPMapNavControl(VBI.mapFlags.moveDisable, VBI.mapFlags.zoomDisable);
|
|
144
|
-
if (VBI.mapFlags.navControlVisible) {
|
|
145
|
-
map.addControl(sapNavControl, 'top-left');
|
|
146
|
-
} else if (!VBI.mapFlags.navControlVisible && map.hasControl(sapNavControl)) {
|
|
147
|
-
map.removeControl(sapNavControl);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// map.addControl(new SAPMAPLgndControl(), 'top-right');
|
|
151
|
-
// Create a popup, but don't add it to the map yet.
|
|
152
|
-
const popup = new maplibregl.Popup({
|
|
153
|
-
closeButton: false,
|
|
154
|
-
closeOnClick: false,
|
|
155
|
-
offset: {
|
|
156
|
-
'top': [0, 0],
|
|
157
|
-
'bottom': [0, -25]
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
177
|
// add markers to map only for Points
|
|
161
178
|
const pointFeatures = [];
|
|
179
|
+
geoJSON = VBI.VBITransformer.getTransformedJSON();
|
|
162
180
|
geoJSON[1].features.forEach((marker) => {
|
|
163
181
|
let markerCoordinates = marker.geometry.coordinates;
|
|
164
182
|
if (marker.geometry.type === 'Point') {
|
|
183
|
+
const key = marker.properties.Key;
|
|
184
|
+
// Skip if this spot already exists
|
|
185
|
+
if (renderedSpots.has(key)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
165
188
|
// create a DOM element for the marker (parent div)
|
|
166
189
|
let createdSpot = VectorUtils.createSpotElement(marker, spotid);
|
|
167
190
|
const el = createdSpot.spotEl;
|
|
@@ -178,107 +201,17 @@ sap.ui.define([
|
|
|
178
201
|
// Append the icon inside the marker
|
|
179
202
|
el.appendChild(child_el);
|
|
180
203
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
allMarkers.push(spot);
|
|
192
|
-
function calculateBBox(featureCollection) {
|
|
193
|
-
let minLon = Infinity, minLat = Infinity;
|
|
194
|
-
let maxLon = -Infinity, maxLat = -Infinity;
|
|
195
|
-
featureCollection.features.forEach(feature => {
|
|
196
|
-
const featureCoordsStr = feature.properties.GeoPosition;
|
|
197
|
-
const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
198
|
-
const lon = featureCoords[0];
|
|
199
|
-
const lat = featureCoords[1];
|
|
200
|
-
if (lon < minLon) minLon = lon;
|
|
201
|
-
if (lon > maxLon) maxLon = lon;
|
|
202
|
-
if (lat < minLat) minLat = lat;
|
|
203
|
-
if (lat > maxLat) maxLat = lat;
|
|
204
|
-
});
|
|
205
|
-
return { minLon, minLat, maxLon, maxLat };
|
|
206
|
-
}
|
|
207
|
-
function isSpotInsideBBox(pos, bbox, tolerance = 0.05) {
|
|
208
|
-
const [lon, lat] = [parseFloat(pos.lng), parseFloat(pos.lat)];
|
|
209
|
-
return (
|
|
210
|
-
lon >= bbox.minLon - tolerance &&
|
|
211
|
-
lon <= bbox.maxLon + tolerance &&
|
|
212
|
-
lat >= bbox.minLat - tolerance &&
|
|
213
|
-
lat <= bbox.maxLat + tolerance
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
function findDropSpots(pos, featureCollection, tolerance = 0.05) {
|
|
217
|
-
let bbox = calculateBBox(featureCollection);
|
|
218
|
-
|
|
219
|
-
if (!isSpotInsideBBox(pos, bbox, tolerance = 0.05)) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
let dropSpots = featureCollection.features.filter(feature => {
|
|
224
|
-
const featureCoordsStr = feature.properties.GeoPosition;
|
|
225
|
-
const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
226
|
-
return isSpotInsideBBox({ lng: featureCoords[0], lat: featureCoords[1] }, bbox);
|
|
227
|
-
});
|
|
228
|
-
return dropSpots.length > 0 ? dropSpots : null;
|
|
229
|
-
}
|
|
230
|
-
VBI.MapRenderer.findNearestSpot = (pos, features1) => {
|
|
231
|
-
let dropInstance = null;
|
|
232
|
-
let minDistance = 100000;
|
|
233
|
-
if (!Array.isArray(pos)) {
|
|
234
|
-
pos = [parseFloat(pos.lng), parseFloat(pos.lat)];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
features1.forEach(feature => {
|
|
238
|
-
|
|
239
|
-
const featureCoordsStr = feature.properties.GeoPosition;
|
|
240
|
-
const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
241
|
-
|
|
242
|
-
let distance = VBI.MapRenderer.haversineDistance(pos, featureCoords);
|
|
243
|
-
|
|
244
|
-
// Check if this is the nearest spot
|
|
245
|
-
if (distance < minDistance) {
|
|
246
|
-
minDistance = distance;
|
|
247
|
-
dropInstance = feature;
|
|
248
|
-
}
|
|
204
|
+
const onDragEnd = (e) => {
|
|
205
|
+
map.getCanvas().style.cursor = 'default';
|
|
206
|
+
let dragItems = [];
|
|
207
|
+
let dropItems = [];
|
|
208
|
+
const key = e.target.customProperties;
|
|
209
|
+
const pos = e.target._lngLat;
|
|
210
|
+
try {
|
|
211
|
+
// Query all features from the layer "geojson-source-point"
|
|
212
|
+
const features1 = map.queryRenderedFeatures({
|
|
213
|
+
layers: ['geojson-source-point']
|
|
249
214
|
});
|
|
250
|
-
return dropInstance;
|
|
251
|
-
}
|
|
252
|
-
VBI.MapRenderer.haversineDistance = (pos, featureCoords) => {
|
|
253
|
-
const R = 6371000;
|
|
254
|
-
const lat1 = pos[0]
|
|
255
|
-
const lon1 = pos[1]
|
|
256
|
-
const lat2 = featureCoords[0]
|
|
257
|
-
const lon2 = featureCoords[1];
|
|
258
|
-
const dLat = VBI.MapRenderer.toRad(lat2 - lat1);
|
|
259
|
-
const dLon = VBI.MapRenderer.toRad(lon2 - lon1);
|
|
260
|
-
const a =
|
|
261
|
-
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
262
|
-
Math.cos(VBI.MapRenderer.toRad(lat1)) * Math.cos(VBI.MapRenderer.toRad(lat2)) *
|
|
263
|
-
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
264
|
-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
265
|
-
return R * c;
|
|
266
|
-
}
|
|
267
|
-
// Helper function to convert degrees to radians
|
|
268
|
-
VBI.MapRenderer.toRad = (value) => {
|
|
269
|
-
return value * Math.PI / 180;
|
|
270
|
-
}
|
|
271
|
-
function onDragEnd(e) {
|
|
272
|
-
map.getCanvas().style.cursor = 'default';
|
|
273
|
-
let dragItems = [];
|
|
274
|
-
let dropItems = [];
|
|
275
|
-
const key = e.target.customProperties;
|
|
276
|
-
const pos = e.target._lngLat;
|
|
277
|
-
try {
|
|
278
|
-
// Query all features from the layer "geojson-source-point"
|
|
279
|
-
const features1 = map.queryRenderedFeatures({
|
|
280
|
-
layers: ['geojson-source-point']
|
|
281
|
-
});
|
|
282
215
|
|
|
283
216
|
features1.forEach((feature, index) => {
|
|
284
217
|
if (feature.properties && typeof feature.properties.Key !== 'undefined') {
|
|
@@ -366,18 +299,118 @@ sap.ui.define([
|
|
|
366
299
|
var dragInsId = VBI.VBITransformer.findObject(dragInstance.properties.type);
|
|
367
300
|
var dropInsId = VBI.VBITransformer.findObject(dropInstance.properties.type);
|
|
368
301
|
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
} catch (error) {
|
|
372
|
-
console.error('Error in onDragEnd:', error);
|
|
373
|
-
}
|
|
374
|
-
// Reset the dragged spot position if needed
|
|
375
|
-
const lngLat = spot.getLngLat();
|
|
376
|
-
if (lngLat.lng !== 0 && lngLat.lat !== 0) {
|
|
377
|
-
spot.setLngLat(originalpos);
|
|
302
|
+
PayloadGenerator.triggerPayloaddnd(dragInsId, dropInsId, dragInstance, dropInstance, containerID);
|
|
378
303
|
}
|
|
379
|
-
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error('Error in onDragEnd:', error);
|
|
306
|
+
}
|
|
307
|
+
// Reset the dragged spot position if needed
|
|
308
|
+
const lngLat = spot.getLngLat();
|
|
309
|
+
if (lngLat.lng !== 0 && lngLat.lat !== 0) {
|
|
310
|
+
spot.setLngLat(originalpos);
|
|
380
311
|
}
|
|
312
|
+
map.getCanvas().style.cursor = 'default';
|
|
313
|
+
}
|
|
314
|
+
// add marker to map
|
|
315
|
+
let spot = new maplibregl.Marker({
|
|
316
|
+
element: el,
|
|
317
|
+
draggable: true,
|
|
318
|
+
anchor: 'bottom'
|
|
319
|
+
}).setLngLat(marker.geometry.coordinates)
|
|
320
|
+
.on('dragend', onDragEnd)
|
|
321
|
+
.addTo(map);
|
|
322
|
+
let originalpos = spot.getLngLat();
|
|
323
|
+
spot.customProperties = { Key: marker.properties.Key };
|
|
324
|
+
allMarkers.push(spot);
|
|
325
|
+
VBI.MapRenderer.allMarkers = allMarkers;
|
|
326
|
+
function calculateBBox(featureCollection) {
|
|
327
|
+
let minLon = Infinity, minLat = Infinity;
|
|
328
|
+
let maxLon = -Infinity, maxLat = -Infinity;
|
|
329
|
+
featureCollection.features.forEach(feature => {
|
|
330
|
+
const featureCoordsStr = feature.properties.GeoPosition;
|
|
331
|
+
const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
332
|
+
const lon = featureCoords[0];
|
|
333
|
+
const lat = featureCoords[1];
|
|
334
|
+
if (lon < minLon) minLon = lon;
|
|
335
|
+
if (lon > maxLon) maxLon = lon;
|
|
336
|
+
if (lat < minLat) minLat = lat;
|
|
337
|
+
if (lat > maxLat) maxLat = lat;
|
|
338
|
+
});
|
|
339
|
+
return { minLon, minLat, maxLon, maxLat };
|
|
340
|
+
}
|
|
341
|
+
function isSpotInsideBBox(pos, bbox, tolerance = 0.05) {
|
|
342
|
+
const [lon, lat] = [parseFloat(pos.lng), parseFloat(pos.lat)];
|
|
343
|
+
return (
|
|
344
|
+
lon >= bbox.minLon - tolerance &&
|
|
345
|
+
lon <= bbox.maxLon + tolerance &&
|
|
346
|
+
lat >= bbox.minLat - tolerance &&
|
|
347
|
+
lat <= bbox.maxLat + tolerance
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
function findDropSpots(pos, featureCollection, tolerance = 0.05) {
|
|
351
|
+
let bbox = calculateBBox(featureCollection);
|
|
352
|
+
|
|
353
|
+
// if (!isSpotInsideBBox(pos, bbox, tolerance = 0.05)) {
|
|
354
|
+
// return null;
|
|
355
|
+
// }
|
|
356
|
+
|
|
357
|
+
// let dropSpots = featureCollection.features.filter(feature => {
|
|
358
|
+
// const featureCoordsStr = feature.properties.GeoPosition;
|
|
359
|
+
// const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
360
|
+
// return isSpotInsideBBox({ lng: featureCoords[0], lat: featureCoords[1] }, bbox);
|
|
361
|
+
// });
|
|
362
|
+
// return dropSpots.length > 0 ? dropSpots : null;
|
|
363
|
+
// }
|
|
364
|
+
VBI.MapRenderer.findNearestSpot = (pos, features1) => {
|
|
365
|
+
let dropInstance = null;
|
|
366
|
+
let minDistance = Infinity;
|
|
367
|
+
|
|
368
|
+
var zoom = window._maplibreMap.getZoom();
|
|
369
|
+
const tolerance = getToleranceMeters(zoom);
|
|
370
|
+
|
|
371
|
+
function getToleranceMeters(zoom) {
|
|
372
|
+
return Math.max(2, Math.pow(1.6, zoom - 6));
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
if (!Array.isArray(pos)) {
|
|
377
|
+
pos = [parseFloat(pos.lng), parseFloat(pos.lat)];
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
features1.forEach(feature => {
|
|
381
|
+
|
|
382
|
+
const featureCoordsStr = feature.properties.GeoPosition;
|
|
383
|
+
const featureCoords = featureCoordsStr.split(";").slice(0, 2).map(Number);
|
|
384
|
+
|
|
385
|
+
let distance = VBI.MapRenderer.haversineDistance(pos, featureCoords);
|
|
386
|
+
|
|
387
|
+
// Check if this is the nearest spot
|
|
388
|
+
if (distance < tolerance && distance < minDistance) {
|
|
389
|
+
minDistance = distance;
|
|
390
|
+
dropInstance = feature;
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
return dropInstance;
|
|
394
|
+
}
|
|
395
|
+
VBI.MapRenderer.haversineDistance = (pos, featureCoords) => {
|
|
396
|
+
const R = 6371000;
|
|
397
|
+
const lat1 = pos[0]
|
|
398
|
+
const lon1 = pos[1]
|
|
399
|
+
const lat2 = featureCoords[0]
|
|
400
|
+
const lon2 = featureCoords[1];
|
|
401
|
+
const dLat = VBI.MapRenderer.toRad(lat2 - lat1);
|
|
402
|
+
const dLon = VBI.MapRenderer.toRad(lon2 - lon1);
|
|
403
|
+
const a =
|
|
404
|
+
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
405
|
+
Math.cos(VBI.MapRenderer.toRad(lat1)) * Math.cos(VBI.MapRenderer.toRad(lat2)) *
|
|
406
|
+
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
407
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
408
|
+
return R * c;
|
|
409
|
+
}
|
|
410
|
+
// Helper function to convert degrees to radians
|
|
411
|
+
VBI.MapRenderer.toRad = (value) => {
|
|
412
|
+
return value * Math.PI / 180;
|
|
413
|
+
}
|
|
381
414
|
|
|
382
415
|
// Function to return a promise that resolves when the map is clicked
|
|
383
416
|
function getClickCoordinates() {
|
|
@@ -514,185 +547,220 @@ sap.ui.define([
|
|
|
514
547
|
if (!exists) {
|
|
515
548
|
predefinedMarkers.push(markerCoordinates);
|
|
516
549
|
}
|
|
517
|
-
} else if (marker.geometry.type == "LineString") {
|
|
518
550
|
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
anchor: 'left',
|
|
530
|
-
offset: [10, 0]
|
|
531
|
-
})
|
|
532
|
-
.setLngLat(midpoint)
|
|
533
|
-
.addTo(map);
|
|
534
|
-
|
|
535
|
-
map.on('move', () => {
|
|
536
|
-
try {
|
|
537
|
-
const newPos = VectorUtils.getVisualMidpoint(coords, map);
|
|
538
|
-
labelMarker.setLngLat(newPos);
|
|
539
|
-
} catch (e) {
|
|
540
|
-
console.warn("Label update failed:", e);
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const coords = marker.geometry.coordinates;
|
|
546
|
-
const startCoord = coords[0]; // First coordinate
|
|
547
|
-
const endCoord = coords[coords.length - 1]; // Last coordinate
|
|
548
|
-
|
|
549
|
-
// Calculate angle between the two points
|
|
550
|
-
const angle = VectorUtils.calculateBearing(startCoord, endCoord);
|
|
551
|
-
|
|
552
|
-
// Determine the arrow rotations
|
|
553
|
-
const normalizedStartRotation = VectorUtils.normalizeAngle(90 + angle); // Adjust for start arrow
|
|
554
|
-
const normalizedEndRotation = angle > 90 ? VectorUtils.normalizeAngle(270 + angle) : VectorUtils.normalizeAngle(90 - angle); // Adjust for end arrow
|
|
555
|
-
|
|
556
|
-
if (coords.length > 1) {
|
|
557
|
-
// Create start point
|
|
558
|
-
const startPoint = {
|
|
559
|
-
'type': 'Feature',
|
|
560
|
-
'geometry': {
|
|
561
|
-
'type': 'Point',
|
|
562
|
-
'coordinates': coords[0] // First coordinate
|
|
563
|
-
},
|
|
564
|
-
'properties': {
|
|
565
|
-
'Color': marker.properties.Color,
|
|
566
|
-
'BorderColor': marker.properties.BorderColor,
|
|
567
|
-
'arrowRotation': normalizedStartRotation,
|
|
568
|
-
'size': 0.07 * parseFloat(marker.properties.LineWidth),
|
|
569
|
-
'borderSize': 0.07 * (parseFloat(marker.properties.LineWidth) + 1)
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
// Create end point
|
|
574
|
-
const endPoint = {
|
|
575
|
-
'type': 'Feature',
|
|
576
|
-
'geometry': {
|
|
577
|
-
'type': 'Point',
|
|
578
|
-
'coordinates': coords[coords.length - 1] // Last coordinate
|
|
579
|
-
},
|
|
580
|
-
'properties': {
|
|
581
|
-
'Color': marker.properties.Color,
|
|
582
|
-
'BorderColor': marker.properties.BorderColor,
|
|
583
|
-
'arrowRotation': normalizedEndRotation,
|
|
584
|
-
'size': 0.07 * parseFloat(marker.properties.LineWidth),
|
|
585
|
-
'borderSize': 0.07 * (parseFloat(marker.properties.LineWidth) + 1)
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
|
|
589
|
-
// Add the points only if the arrow is supposed to be shown
|
|
590
|
-
if (marker.properties.StartStyle === '1') {
|
|
591
|
-
pointFeatures.push(startPoint);
|
|
592
|
-
}
|
|
593
|
-
if (marker.properties.EndStyle === '1') {
|
|
594
|
-
pointFeatures.push(endPoint);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
551
|
+
if (!map.getLayer('geojson-source-point')){
|
|
552
|
+
map.addLayer({
|
|
553
|
+
'id': 'geojson-source-point',
|
|
554
|
+
'type': 'circle',
|
|
555
|
+
'source': 'geojson-source',
|
|
556
|
+
'paint': {
|
|
557
|
+
'circle-opacity': 0 // Hide points by making them fully transparent
|
|
558
|
+
},
|
|
559
|
+
'filter': ['==', '$type', 'Point']
|
|
560
|
+
});
|
|
597
561
|
}
|
|
598
|
-
|
|
599
|
-
});
|
|
600
|
-
if (VBI.mapFlags.automations) {
|
|
601
|
-
let automations = new SAPAutomationManager(map, maplibregl.LngLatBounds);
|
|
602
|
-
automations.load(VBI.mapFlags.automations);
|
|
603
562
|
}
|
|
604
|
-
map.addLayer({
|
|
605
|
-
'id': 'geojson-source-point',
|
|
606
|
-
'type': 'circle',
|
|
607
|
-
'source': 'geojson-source',
|
|
608
|
-
'paint': {
|
|
609
|
-
'circle-opacity': 0 // Hide points by making them fully transparent
|
|
610
|
-
},
|
|
611
|
-
'filter': ['==', '$type', 'Point']
|
|
612
|
-
});
|
|
613
|
-
|
|
614
|
-
// First layer for the border (wider line)
|
|
615
|
-
map.addLayer({
|
|
616
|
-
'id': 'geojson-source-route-border',
|
|
617
|
-
'type': 'line',
|
|
618
|
-
'source': 'geojson-source',
|
|
619
|
-
'layout': {
|
|
620
|
-
'line-join': 'round',
|
|
621
|
-
'line-cap': 'butt'
|
|
622
|
-
},
|
|
623
|
-
'paint': {
|
|
624
|
-
'line-color': ['get', 'BorderColor'],
|
|
625
|
-
'line-width': ['get', 'BorderWidth'] // Slightly wider for border effect
|
|
626
|
-
},
|
|
627
|
-
'filter': ['==', '$type', 'LineString']
|
|
628
|
-
});
|
|
629
|
-
map.addLayer({
|
|
630
|
-
'id': 'geojson-source-route',
|
|
631
|
-
'type': 'line',
|
|
632
|
-
'source': 'geojson-source',
|
|
633
|
-
'layout': {
|
|
634
|
-
'line-join': 'round',
|
|
635
|
-
'line-cap': 'butt'
|
|
636
|
-
},
|
|
637
|
-
'paint': {
|
|
638
|
-
'line-color': ['get', 'Color'],
|
|
639
|
-
'line-width': ['get', 'LineWidth']
|
|
640
|
-
},
|
|
641
|
-
'filter': ['==', '$type', 'LineString']
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
// Create a new FeatureCollection for the points
|
|
645
|
-
const pointGeoJSON = {
|
|
646
|
-
'type': 'FeatureCollection',
|
|
647
|
-
'features': pointFeatures
|
|
648
563
|
};
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
VBI.MapRenderer._processGeoRoutes = () => {
|
|
567
|
+
const pointFeatures = [];
|
|
568
|
+
let geoJSON = VBI.VBITransformer.getTransformedJSON();
|
|
569
|
+
if (map.getSource('geojson-source')) {
|
|
570
|
+
map.getSource('geojson-source').setData(geoJSON[1]);
|
|
571
|
+
} else {
|
|
572
|
+
map.addSource('geojson-source', {
|
|
573
|
+
'type': 'geojson',
|
|
574
|
+
'data': geoJSON[1]
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
geoJSON[1].features.forEach((marker) => {
|
|
578
|
+
if (marker.geometry.type == "LineString") {
|
|
579
|
+
|
|
580
|
+
const routeKey = marker.properties.Key;
|
|
581
|
+
|
|
582
|
+
if (marker.properties.Label) {
|
|
583
|
+
|
|
584
|
+
if (!renderedRouteLabels.has(routeKey)) {
|
|
585
|
+
|
|
586
|
+
const midpoint = VectorUtils.getVisualMidpoint(marker.geometry.coordinates, map);
|
|
587
|
+
|
|
588
|
+
const routeLabelEl = VectorUtils.createRouteLabel(
|
|
589
|
+
marker.properties.Label,
|
|
590
|
+
marker.properties.LabelBGColor
|
|
591
|
+
);
|
|
592
|
+
|
|
593
|
+
const labelMarker = new maplibregl.Marker({
|
|
594
|
+
element: routeLabelEl,
|
|
595
|
+
anchor: 'left',
|
|
596
|
+
offset: [10, 0]
|
|
597
|
+
})
|
|
598
|
+
.setLngLat(midpoint)
|
|
599
|
+
.addTo(map);
|
|
600
|
+
|
|
601
|
+
renderedRouteLabels.set(routeKey, labelMarker);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const coords = marker.geometry.coordinates;
|
|
606
|
+
const startCoord = coords[0]; // First coordinate
|
|
607
|
+
const endCoord = coords[coords.length - 1]; // Last coordinate
|
|
608
|
+
|
|
609
|
+
// Calculate angle between the two points
|
|
610
|
+
const angle = VectorUtils.calculateBearing(startCoord, endCoord);
|
|
611
|
+
|
|
612
|
+
// Determine the arrow rotations
|
|
613
|
+
const normalizedStartRotation = VectorUtils.normalizeAngle(90 + angle); // Adjust for start arrow
|
|
614
|
+
const normalizedEndRotation = angle > 90 ? VectorUtils.normalizeAngle(270 + angle) : VectorUtils.normalizeAngle(90 - angle); // Adjust for end arrow
|
|
615
|
+
|
|
616
|
+
if (coords.length > 1) {
|
|
617
|
+
// Create start point
|
|
618
|
+
const startPoint = {
|
|
619
|
+
'type': 'Feature',
|
|
620
|
+
'geometry': {
|
|
621
|
+
'type': 'Point',
|
|
622
|
+
'coordinates': coords[0] // First coordinate
|
|
623
|
+
},
|
|
624
|
+
'properties': {
|
|
625
|
+
'Color': marker.properties.Color,
|
|
626
|
+
'BorderColor': marker.properties.BorderColor,
|
|
627
|
+
'arrowRotation': normalizedStartRotation,
|
|
628
|
+
'size': 0.07 * parseFloat(marker.properties.LineWidth),
|
|
629
|
+
'borderSize': 0.07 * (parseFloat(marker.properties.LineWidth) + 1)
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// Create end point
|
|
634
|
+
const endPoint = {
|
|
635
|
+
'type': 'Feature',
|
|
636
|
+
'geometry': {
|
|
637
|
+
'type': 'Point',
|
|
638
|
+
'coordinates': coords[coords.length - 1] // Last coordinate
|
|
639
|
+
},
|
|
640
|
+
'properties': {
|
|
641
|
+
'Color': marker.properties.Color,
|
|
642
|
+
'BorderColor': marker.properties.BorderColor,
|
|
643
|
+
'arrowRotation': normalizedEndRotation,
|
|
644
|
+
'size': 0.07 * parseFloat(marker.properties.LineWidth),
|
|
645
|
+
'borderSize': 0.07 * (parseFloat(marker.properties.LineWidth) + 1)
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
// Add the points only if the arrow is supposed to be shown
|
|
650
|
+
if (marker.properties.StartStyle === '1') {
|
|
651
|
+
pointFeatures.push(startPoint);
|
|
652
|
+
}
|
|
653
|
+
if (marker.properties.EndStyle === '1') {
|
|
654
|
+
pointFeatures.push(endPoint);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
// });
|
|
658
|
+
} })
|
|
659
|
+
// Create a new FeatureCollection for the points
|
|
660
|
+
const pointGeoJSON = {
|
|
661
|
+
'type': 'FeatureCollection',
|
|
662
|
+
'features': pointFeatures
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
// Update the GeoJSON source for the points
|
|
666
|
+
if (map.getSource('line-end-points')) {
|
|
667
|
+
map.getSource('line-end-points').setData(pointGeoJSON);
|
|
668
|
+
} else {
|
|
669
|
+
map.addSource('line-end-points', {
|
|
670
|
+
'type': 'geojson',
|
|
671
|
+
'data': pointGeoJSON
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
if (!map.getLayer('geojson-source-point')) {
|
|
675
|
+
map.addLayer({
|
|
676
|
+
'id': 'geojson-source-point',
|
|
677
|
+
'type': 'circle',
|
|
678
|
+
'source': 'geojson-source',
|
|
679
|
+
'paint': {
|
|
680
|
+
'circle-opacity': 0 // Hide points by making them fully transparent
|
|
681
|
+
},
|
|
682
|
+
'filter': ['==', '$type', 'Point']
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
if (!map.getLayer('geojson-source-route-border')) {
|
|
686
|
+
// First layer for the border (wider line)
|
|
687
|
+
map.addLayer({
|
|
688
|
+
'id': 'geojson-source-route-border',
|
|
689
|
+
'type': 'line',
|
|
690
|
+
'source': 'geojson-source',
|
|
691
|
+
'layout': {
|
|
692
|
+
'line-join': 'round',
|
|
693
|
+
'line-cap': 'butt'
|
|
694
|
+
},
|
|
695
|
+
'paint': {
|
|
696
|
+
'line-color': ['get', 'BorderColor'],
|
|
697
|
+
'line-width': ['get', 'BorderWidth'] // Slightly wider for border effect
|
|
698
|
+
},
|
|
699
|
+
'filter': ['==', '$type', 'LineString']
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
if (!map.getLayer('geojson-source-route')) {
|
|
703
|
+
map.addLayer({
|
|
704
|
+
'id': 'geojson-source-route',
|
|
705
|
+
'type': 'line',
|
|
706
|
+
'source': 'geojson-source',
|
|
707
|
+
'layout': {
|
|
708
|
+
'line-join': 'round',
|
|
709
|
+
'line-cap': 'butt'
|
|
710
|
+
},
|
|
711
|
+
'paint': {
|
|
712
|
+
'line-color': ['get', 'Color'],
|
|
713
|
+
'line-width': ['get', 'LineWidth']
|
|
714
|
+
},
|
|
715
|
+
'filter': ['==', '$type', 'LineString']
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Add a layer to display the arrows at the start/end points
|
|
720
|
+
if (!map.getLayer('route-end-arrows')){
|
|
659
721
|
map.addLayer({
|
|
660
|
-
'id': 'route-end-arrows
|
|
722
|
+
'id': 'route-end-arrows',
|
|
661
723
|
'type': 'symbol',
|
|
662
724
|
'source': 'line-end-points',
|
|
663
725
|
'layout': {
|
|
664
|
-
'icon-image': 'arrow-icon', // base64 arrow icon
|
|
665
|
-
'icon-size': ['get', '
|
|
726
|
+
'icon-image': 'arrow-icon', // Use your base64 arrow icon
|
|
727
|
+
'icon-size': ['get', 'size'],
|
|
666
728
|
'icon-allow-overlap': true,
|
|
667
729
|
'icon-rotation-alignment': 'map',
|
|
668
730
|
'icon-rotate': ['get', 'arrowRotation'], // Rotate based on calculated angle
|
|
669
731
|
'icon-offset': [-12, 4]
|
|
670
732
|
},
|
|
671
733
|
'paint': {
|
|
672
|
-
'icon-color': ['get', '
|
|
734
|
+
'icon-color': ['get', 'Color'] // Match the arrow color with the line color
|
|
673
735
|
}
|
|
674
736
|
});
|
|
737
|
+
}
|
|
675
738
|
|
|
676
|
-
|
|
739
|
+
VectorUtils.getArrowHead((image) => {
|
|
740
|
+
if (!map.hasImage('arrow-icon')) {
|
|
741
|
+
map.addImage('arrow-icon', image, { sdf: true });
|
|
742
|
+
}
|
|
743
|
+
// Add a layer to display the arrows borders at the start/end points
|
|
744
|
+
if (!map.getLayer('route-end-arrows-border')){
|
|
677
745
|
map.addLayer({
|
|
678
|
-
'id': 'route-end-arrows',
|
|
746
|
+
'id': 'route-end-arrows-border',
|
|
679
747
|
'type': 'symbol',
|
|
680
748
|
'source': 'line-end-points',
|
|
681
749
|
'layout': {
|
|
682
|
-
'icon-image': 'arrow-icon', //
|
|
683
|
-
'icon-size': ['get', '
|
|
750
|
+
'icon-image': 'arrow-icon', // base64 arrow icon
|
|
751
|
+
'icon-size': ['get', 'borderSize'],
|
|
684
752
|
'icon-allow-overlap': true,
|
|
685
753
|
'icon-rotation-alignment': 'map',
|
|
686
754
|
'icon-rotate': ['get', 'arrowRotation'], // Rotate based on calculated angle
|
|
687
755
|
'icon-offset': [-12, 4]
|
|
688
756
|
},
|
|
689
757
|
'paint': {
|
|
690
|
-
'icon-color': ['get', '
|
|
758
|
+
'icon-color': ['get', 'BorderColor'] // Match the arrow color with the line color
|
|
691
759
|
}
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
|
|
760
|
+
}, 'route-end-arrows');
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
|
|
696
764
|
// Change mouse cursor when hovering over the line
|
|
697
765
|
map.on('mouseenter', 'geojson-source-route', function (event) {
|
|
698
766
|
if (!that.Apressed && !that.Rpressed) {
|
|
@@ -900,40 +968,8 @@ sap.ui.define([
|
|
|
900
968
|
}
|
|
901
969
|
}
|
|
902
970
|
}
|
|
903
|
-
|
|
904
|
-
mapCanvas.oncontextmenu = (e) => {
|
|
905
|
-
e.preventDefault();
|
|
906
|
-
// Get the mouse coordinates within the map container
|
|
907
|
-
const rect = canvas.getBoundingClientRect(); // Get map container position
|
|
908
|
-
const x = e.clientX - rect.left; // Relative to map
|
|
909
|
-
const y = e.clientY - rect.top;
|
|
910
|
-
const lngLat = map.unproject([x, y]);
|
|
911
|
-
// Check if the right-click happened on the 'geojson-source-route' layer
|
|
912
|
-
const features = map.queryRenderedFeatures([x, y], { layers: ['geojson-source-route'] });
|
|
913
|
-
|
|
914
|
-
if (features.length > 0) {
|
|
915
|
-
e.features = features;
|
|
916
|
-
// The context menu is for the 'geojson-source-route' layer
|
|
917
|
-
triggerPayloadRoute(e, 'CONTEXT_MENU_REQUEST');
|
|
918
|
-
} else {
|
|
919
|
-
// Get the mouse coordinates within the map container
|
|
920
|
-
const offsetX = e.offsetX;
|
|
921
|
-
const offsetY = e.offsetY;
|
|
922
|
-
const lngLat = map.unproject([offsetX, offsetY]);
|
|
923
|
-
// The context menu is for the map
|
|
924
|
-
const coords = lngLat.lng + ";" + lngLat.lat + ";0.0";
|
|
925
|
-
const currentZoom = map.getZoom();
|
|
926
|
-
const center = map.getCenter();
|
|
927
|
-
const currentCenter = center.lng + ";" + center.lat;
|
|
928
|
-
const xyobj = VectorUtils.GetEventVPCoordsObj(e, map_container);
|
|
929
|
-
const screenX = xyobj.x;
|
|
930
|
-
const screenY = xyobj.y;
|
|
931
|
-
PayloadGenerator.onMapContextMenu(coords, currentZoom, currentCenter, screenX, screenY);
|
|
932
|
-
}
|
|
933
|
-
};
|
|
934
|
-
|
|
935
971
|
var that = this;
|
|
936
|
-
|
|
972
|
+
map.on('idle', () => {
|
|
937
973
|
const container = map.getContainer();
|
|
938
974
|
containerID = container.id;
|
|
939
975
|
console.log("Map container ID:", containerID);
|
|
@@ -978,10 +1014,57 @@ sap.ui.define([
|
|
|
978
1014
|
}
|
|
979
1015
|
//Always trigger
|
|
980
1016
|
PayloadGenerator.KeyboardHandler(event, VBI.MapRenderer.name);
|
|
981
|
-
|
|
982
|
-
|
|
1017
|
+
});
|
|
1018
|
+
}) ;
|
|
1019
|
+
}
|
|
1020
|
+
VBI.MapRenderer._processDeletion = (featureCollection) => {
|
|
1021
|
+
|
|
1022
|
+
const geoJSON = VBI.VBITransformer.getTransformedJSON();
|
|
1023
|
+
if (!geoJSON[1].features || !geoJSON[1].features.length) {
|
|
1024
|
+
geoJSON[1].features = featureCollection;
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const oldFeatures = geoJSON[1].features;
|
|
1028
|
+
|
|
1029
|
+
// Collect IDs that still exist
|
|
1030
|
+
const remainingIds = {};
|
|
1031
|
+
for (let i = 0; i < featureCollection.length; i++) {
|
|
1032
|
+
remainingIds[featureCollection[i].properties.Key] = true;
|
|
1033
|
+
}
|
|
983
1034
|
|
|
1035
|
+
// Find deleted feature IDs
|
|
1036
|
+
const deletedIds = [];
|
|
1037
|
+
for (let i = 0; i < oldFeatures.length; i++) {
|
|
1038
|
+
const oldId = oldFeatures[i].properties.Key;
|
|
1039
|
+
if (!remainingIds[oldId]) {
|
|
1040
|
+
deletedIds.push(oldId);
|
|
1041
|
+
}
|
|
984
1042
|
}
|
|
1043
|
+
|
|
1044
|
+
const deletedIds1 = new Set(deletedIds.map(id => String(id).trim()));
|
|
1045
|
+
// Remove all matching markers
|
|
1046
|
+
for (let i = VBI.MapRenderer.allMarkers.length - 1; i >= 0; i--) {
|
|
1047
|
+
const marker = VBI.MapRenderer.allMarkers[i];
|
|
1048
|
+
const key = marker.customProperties?.Key;
|
|
1049
|
+
if (!key) continue;
|
|
1050
|
+
if (deletedIds1.has(String(key).trim())) {
|
|
1051
|
+
marker.getElement().remove();
|
|
1052
|
+
VBI.MapRenderer.allMarkers.splice(i, 1);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// Update GeoJSON source
|
|
1057
|
+
geoJSON[1].features = featureCollection;
|
|
1058
|
+
map.getSource('geojson-source').setData(geoJSON [1]);
|
|
1059
|
+
if (map.getSource('line-end-points')) {
|
|
1060
|
+
map.getSource('line-end-points').setData({
|
|
1061
|
+
type: 'FeatureCollection',
|
|
1062
|
+
features: []
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
VBI.MapRenderer._processGeoRoutes();
|
|
1066
|
+
}
|
|
1067
|
+
|
|
985
1068
|
VBI.MapRenderer.actionName = (obj) => {
|
|
986
1069
|
const actions = Array.isArray(obj?.SAPVB?.Actions?.Set?.Action)
|
|
987
1070
|
? obj.SAPVB.Actions.Set.Action
|
|
@@ -1033,18 +1116,18 @@ sap.ui.define([
|
|
|
1033
1116
|
offset: [19, 15]
|
|
1034
1117
|
}).setLngLat(lngLat)
|
|
1035
1118
|
.setDOMContent(htmlContent)
|
|
1036
|
-
.addTo(
|
|
1119
|
+
.addTo(map);
|
|
1037
1120
|
}
|
|
1038
1121
|
|
|
1039
1122
|
VBI.MapRenderer.closePopup = () => {
|
|
1040
1123
|
this.popup?.remove();
|
|
1041
1124
|
}
|
|
1042
1125
|
VBI.MapRenderer.setRefMapLayerStack = (style, header) => {
|
|
1043
|
-
|
|
1126
|
+
map.setStyle(style);
|
|
1044
1127
|
// Add the headers only for the specific types of requests
|
|
1045
1128
|
if (Object.keys(header).length != 0) {
|
|
1046
1129
|
// Use transformRequest to modify requests for specific maps
|
|
1047
|
-
|
|
1130
|
+
map.transformRequest = (url, resourceType) => {
|
|
1048
1131
|
return {
|
|
1049
1132
|
url: url,
|
|
1050
1133
|
headers: header // Add the header
|
|
@@ -1068,9 +1151,7 @@ sap.ui.define([
|
|
|
1068
1151
|
contextMenuHandler.m_scene = xyparam[i]["#"];
|
|
1069
1152
|
}
|
|
1070
1153
|
}
|
|
1071
|
-
Menu.findMenuByID(data.refID).open(true, 0, "begin top", "begin top",
|
|
1154
|
+
Menu.findMenuByID(data.refID).open(true, 0, "begin top", "begin top", map._container, "" + contextMenuHandler.m_x + " " + contextMenuHandler.m_y + "", "fit");
|
|
1072
1155
|
}
|
|
1073
1156
|
|
|
1074
1157
|
});
|
|
1075
|
-
|
|
1076
|
-
|