Skip to content

Commit cabe02b

Browse files
committed
Revert example changes
1 parent 75d7b9e commit cabe02b

File tree

2 files changed

+11
-363
lines changed

2 files changed

+11
-363
lines changed

examples/get-started/pure-js/carto/app.js

Lines changed: 10 additions & 343 deletions
Original file line numberDiff line numberDiff line change
@@ -2,355 +2,22 @@
22
// SPDX-License-Identifier: MIT
33
// Copyright (c) vis.gl contributors
44

5+
import maplibregl from 'maplibre-gl';
56
import {Deck} from '@deck.gl/core';
6-
import {PathLayer} from '@deck.gl/layers';
7-
import {Tile3DLayer, TripsLayer} from '@deck.gl/geo-layers';
8-
import {colorContinuous, fetchMap} from '@deck.gl/carto';
9-
import {MapboxOverlay} from '@deck.gl/mapbox';
10-
import EdgedPathLayer, {ADDITIVE_BLEND_PARAMETERS} from './EdgedPathLayer';
7+
import {fetchMap} from '@deck.gl/carto';
118

12-
const cartoMapId = '72d126eb-c77e-4786-bd16-4acceeae72ba';
13-
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line
14-
15-
function deg2rad(deg) {
16-
return deg * (Math.PI / 180);
17-
}
18-
19-
function distanceBetweenPoints([lon1, lat1, lon2, lat2]) {
20-
const R = 6371000; // Radius of the earth in m
21-
const dLat = deg2rad(lat2 - lat1);
22-
const dLon = deg2rad(lon2 - lon1);
23-
const a =
24-
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
25-
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
26-
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
27-
}
28-
29-
function addAltitude(geometry) {
30-
// Convert to 3D data
31-
const {featureIds, numericProps, positions, properties} = geometry;
32-
const n = featureIds.value.length;
33-
34-
// Need to get the total length of each line
35-
const distanceAlong = new Float32Array(n);
36-
const segmentLengths = {};
37-
for (let i = 0; i < n; i++) {
38-
const delta = distanceBetweenPoints(positions.value.subarray(2 * i - 2, 2 * i + 2));
39-
distanceAlong[i] = delta + distanceAlong[i - 1];
40-
const featureId = featureIds.value[i];
41-
if (!(featureId in segmentLengths)) {
42-
segmentLengths[featureId] = 0;
43-
distanceAlong[i] = 0;
44-
}
45-
segmentLengths[featureId] = distanceAlong[i];
46-
}
47-
48-
// Normalize
49-
for (let i = 0; i < distanceAlong.length; i++) {
50-
const featureId = featureIds.value[i];
51-
const segmentLength = segmentLengths[featureId];
52-
distanceAlong[i] = distanceAlong[i] / segmentLength;
53-
}
54-
55-
// Parse JSON
56-
properties.forEach(property => {
57-
property.ticks = JSON.parse(property.ticks)[0];
58-
});
59-
60-
// Vertex colors
61-
const getAltitudeColor = colorContinuous({
62-
attr: d => d.altitude,
63-
domain: [1000, 1500, 2000, 2500, 3000, 3500, 4000],
64-
colors: 'TealRose'
65-
});
66-
const getSpeedColor = colorContinuous({
67-
attr: d => d.altitude,
68-
domain: [5, 7, 9, 11, 13, 15],
69-
colors: 'OrYel'
70-
});
71-
geometry.attributes = {
72-
...geometry.attributes,
73-
getColor: {value: new Uint8Array(4 * n), size: 4, normalized: true},
74-
getTimestamps: {value: new Float32Array(n), size: 1}
75-
};
76-
77-
function interpolatePoints(f, point, nextPoint) {
78-
const propertyNames = Object.keys(point);
79-
let interpolatedProperties = {};
80-
if (!nextPoint) {
81-
interpolatedProperties = point;
82-
} else {
83-
const g = (f - point.f) / (nextPoint.f - point.f);
84-
for (const propertyName of propertyNames) {
85-
const value = point[propertyName];
86-
const nextValue = nextPoint[propertyName];
87-
const interpolatedValue = value * (1 - g) + nextValue * g;
88-
interpolatedProperties[propertyName] = interpolatedValue;
89-
}
90-
}
91-
92-
return interpolatedProperties;
93-
}
94-
95-
function interpolateProperties(vertexId) {
96-
const f = distanceAlong[vertexId];
97-
const featureId = featureIds.value[vertexId];
98-
const points = properties[featureId].ticks;
99-
let point = points[0];
100-
let p = 0;
101-
102-
// TODO more efficent search?
103-
while (points[p]?.f <= f) {
104-
point = points[p++];
105-
}
106-
const nextPoint = points[p];
107-
const interpolatedProperties = interpolatePoints(f, point, nextPoint);
108-
109-
// DEBUG: Sanity
110-
// const seconds_min = numericProps.seconds_min[vertexId];
111-
// const seconds_max = numericProps.seconds_max[vertexId];
112-
// const {seconds} = point;
113-
// if (seconds_min > seconds || seconds_max < seconds) {
114-
// debugger;
115-
// }
116-
117-
if (Math.abs(point.f - f) > 0.1) debugger;
118-
119-
return interpolatedProperties;
120-
}
121-
122-
// Interpolate properties to match vertex data
123-
let interpolatedProperties = [];
124-
for (let i = 0; i < n; i++) {
125-
interpolatedProperties[i] = interpolateProperties(i);
126-
}
127-
128-
// Collect segments
129-
const chunks = [];
130-
const segmentCount = geometry.pathIndices.value.length - 1;
131-
for (let c = 0; c < segmentCount; c++) {
132-
const startIndex = geometry.pathIndices.value[c];
133-
// Remove last vertex to avoid double vertices in line
134-
// TODO this is wrong, we can have two disjoint segments in a single tile
135-
// for example when the line comes back later
136-
let endIndex = geometry.pathIndices.value[c + 1];
137-
const startT = interpolatedProperties[startIndex].t;
138-
const endT = interpolatedProperties[endIndex - 1].t; // TODO is this correct?
139-
const reverse = startT > endT;
140-
if (reverse) continue; // Skip reversed segments for now, no idea why they are there??
141-
142-
const {value, size} = geometry.positions;
143-
const TypedArray = value.constructor;
144-
const range = [];
145-
146-
let segment = value.subarray(startIndex * size, endIndex * size);
147-
let segmentProperties = interpolatedProperties.slice(startIndex, endIndex);
148-
if (reverse) {
149-
const segmentReversed = new TypedArray(segment.length);
150-
for (let v = 0; v < segment.length / size; v++) {
151-
segmentReversed.set(
152-
segment.subarray(v * size, (v + 1) * size),
153-
segment.length - (v + 1) * size
154-
);
155-
}
156-
segment = segmentReversed;
157-
segmentProperties.reverse();
158-
}
159-
chunks.push({
160-
segment,
161-
segmentProperties,
162-
timestamp: startT,
163-
range: [startIndex, endIndex],
164-
reverse
165-
});
166-
}
167-
chunks.sort(({timestamp: a}, {timestamp: b}) => a - b);
168-
169-
//chunks[chunks.length - 1].range[1] += 1;
170-
if (chunks[chunks.length - 1].reverse) debugger; // Shouldn't happen?
171-
172-
function sortChunks(chunks) {
173-
const {value, size} = geometry.positions;
174-
const TypedArray = value.constructor;
175-
const newPositions = new TypedArray(value.length);
176-
let newInterpolatedProperties = [];
177-
let offset = 0;
178-
const newPathIndices = [];
179-
for (const chunk of chunks) {
180-
let {
181-
segment,
182-
segmentProperties,
183-
range: [startIndex, endIndex]
184-
} = chunk;
185-
186-
try {
187-
// If last vertex in previous segment match first vertex in current segment, stitch line together
188-
let stitch = true;
189-
if (offset === 0) {
190-
stitch = false;
191-
} else {
192-
const lastVertex = newPositions.subarray((offset - 1) * size);
193-
for (let s = 0; s < size; s++) {
194-
if (segment[s] !== lastVertex[s]) stitch = false;
195-
}
196-
}
197-
if (stitch) {
198-
startIndex += 1;
199-
segment = segment.subarray(size);
200-
segmentProperties = segmentProperties.slice(1);
201-
} else {
202-
newPathIndices.push(offset);
203-
}
204-
205-
newPositions.set(segment, offset * size);
206-
newInterpolatedProperties = newInterpolatedProperties.concat(segmentProperties);
207-
} catch (e) {
208-
debugger;
209-
}
210-
offset += endIndex - startIndex;
211-
}
212-
213-
geometry.positions.value = newPositions.subarray(0, offset * size);
214-
interpolatedProperties = newInterpolatedProperties;
215-
newPathIndices.push(interpolatedProperties.length);
216-
geometry.pathIndices.value = new Uint32Array(newPathIndices);
217-
}
218-
219-
// Also need to sort properties
220-
sortChunks(chunks);
221-
222-
const stitchedN = interpolatedProperties.length;
223-
const size = 3;
224-
const value = new Float64Array(size * stitchedN);
225-
for (let i = 0; i < stitchedN; i++) {
226-
const {altitude, t} = interpolatedProperties[i];
227-
228-
// Populate 3D point data
229-
value[size * i] = geometry.positions.value[geometry.positions.size * i];
230-
value[size * i + 1] = geometry.positions.value[geometry.positions.size * i + 1];
231-
value[size * i + 2] = altitude;
232-
233-
// Add altitude color per vertex
234-
// const color = getFillColor({altitude});
235-
// geometry.attributes.getColor.value.set(color, 4 * i);
236-
geometry.attributes.getTimestamps.value[i] = t;
237-
}
238-
geometry.positions = {value, size};
239-
240-
let previousPosition;
241-
let maxS = 0;
242-
let previousSpeed = 0;
243-
for (let i = 0; i < stitchedN; i++) {
244-
// Calculate speed (only in 2D for now)
245-
let speed = 0;
246-
if (i < stitchedN) {
247-
const start = i === stitchedN - 1 ? i - 1 : i;
248-
const [lon1, lat1, alt1, lon2, lat2, alt2] = geometry.positions.value.subarray(
249-
3 * start,
250-
3 * start + 6
251-
);
252-
const deltaP = distanceBetweenPoints([lon1, lat1, lon2, lat2]);
253-
const [t1, t2] = geometry.attributes.getTimestamps.value.subarray(start, start + 2);
254-
let deltaT = t2 - t1;
255-
speed = deltaT > 0 ? deltaP / deltaT : 0;
256-
257-
if (deltaT === 0) {
258-
// rounding gives 0 time delta, use previous speed value or hard code half second
259-
speed = previousSpeed;
260-
}
261-
262-
maxS = Math.max(speed, maxS);
263-
previousSpeed = speed;
264-
}
265-
if (speed === 0) {
266-
console.log(speed, 'speed');
267-
speed = 100;
268-
}
269-
// Add speed color per vertex
270-
const color = getSpeedColor({altitude: speed});
271-
// color[3] = speed < 1 || speed > 50 ? 255 : 50;
272-
geometry.attributes.getColor.value.set(color, 4 * i);
273-
}
274-
275-
return geometry;
276-
}
9+
const cartoMapId = 'ff6ac53f-741a-49fb-b615-d040bc5a96b8';
27710

27811
// Get map info from CARTO and update deck
279-
fetchMap({cartoMapId}).then(({initialViewState, basemap, layers: _baseLayers}) => {
280-
const showTrips = false;
281-
const props = {
282-
getWidth: 4,
283-
widthUnits: 'pixels',
284-
opacity: 0.8, // Best to use full opacity to hide segment joins
285-
billboard: true,
286-
jointRounded: true,
287-
capRounded: true,
288-
_pathType: 'open'
289-
// parameters: ADDITIVE_BLEND_PARAMETERS
290-
};
291-
const layers = [
292-
_baseLayers[3].clone({
293-
dataTransform: d => {
294-
addAltitude(d.lines);
295-
return d;
296-
},
297-
// tileSize: 256,
298-
zRange: [0, 4000],
299-
// refinementStrategy: 'no-overlap',
300-
_subLayerProps: {
301-
linestrings: showTrips
302-
? {
303-
type: TripsLayer,
304-
getTimestamps: (d, info) => info.index,
305-
fadeTrail: true,
306-
currentTime: 20500,
307-
trailLength: 600,
308-
...props
309-
}
310-
: {
311-
type: EdgedPathLayer,
312-
...props
313-
}
314-
}
315-
})
316-
];
317-
318-
const {bearing, latitude, longitude, pitch, zoom} = initialViewState;
12+
fetchMap({cartoMapId}).then(({initialViewState, basemap, layers}) => {
13+
const deck = new Deck({canvas: 'deck-canvas', controller: true, initialViewState, layers});
31914

32015
// Add Mapbox GL for the basemap. It's not a requirement if you don't need a basemap.
321-
// const map = new maplibregl.Map({container: 'map', ...basemap?.props, interactive: false});
322-
mapboxgl.accessToken = MAPBOX_TOKEN;
323-
const map = new mapboxgl.Map({
324-
container: 'map',
325-
style: 'mapbox://styles/mapbox/satellite-streets-v12',
326-
interactive: true, // Have Mapbox control control for better 3D orientation
327-
328-
// View state
329-
bearing,
330-
center: [longitude, latitude],
331-
pitch,
332-
zoom,
333-
boxZoom: false,
334-
maxPitch: 50
335-
});
336-
map.on('style.load', () => {
337-
map.addSource('mapbox-dem', {
338-
type: 'raster-dem',
339-
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
340-
tileSize: 512,
341-
maxzoom: 14
342-
});
343-
// Do not exaggerate, so deck layers match elevation
344-
map.setTerrain({source: 'mapbox-dem', exaggeration: 1});
345-
});
346-
347-
const overlay = new MapboxOverlay({
348-
layers: layers,
349-
onAfterRender: () => {
350-
const isLoading = layers.every(layer => layer.isLoaded);
351-
document.getElementById('loading-indicator').style.transition = isLoading ? 'opacity 1s' : '';
352-
document.getElementById('loading-indicator').style.opacity = isLoading ? 0 : 1;
16+
const map = new maplibregl.Map({container: 'map', ...basemap?.props, interactive: false});
17+
deck.setProps({
18+
onViewStateChange: ({viewState}) => {
19+
const {longitude, latitude, ...rest} = viewState;
20+
map.jumpTo({center: [longitude, latitude], ...rest});
35321
}
35422
});
355-
map.addControl(overlay);
35623
});

0 commit comments

Comments
 (0)