@pirireis/webglobeplugins 0.16.7 → 0.17.1
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/Math/angle-calculation.js +1 -0
- package/Math/contour/quadtreecontours.js +300 -0
- package/Math/finite-line-2d.js +58 -0
- package/Math/methods.js +6 -0
- package/Math/tessellation/hybrid-triangle-tessellation-meta.js +123 -0
- package/Math/tessellation/tile-merger.js +298 -0
- package/Math/tessellation/triangle-tessellation-meta.js +195 -42
- package/Math/tessellation/triangle-tessellation.js +5 -1
- package/compass-rose/compass-text-writer.js +39 -33
- package/constants.js +3 -0
- package/{util/heatwavedatamanager → heatwave}/datamanager.js +1 -1
- package/heatwave/{plugins/heatwaveglobeshell.js → heatwave.js} +8 -6
- package/heatwave/index.js +5 -3
- package/heatwave/{isobar/plugin.js → isobar.js} +6 -5
- package/{util/heatwavedatamanager → heatwave}/texture-point-sampler.js +24 -3
- package/investigation-tools/draw/tiles/adapters.js +67 -0
- package/investigation-tools/draw/tiles/tiles.js +128 -0
- package/package.json +4 -2
- package/programs/arrowfield/{object.js → arrow-field.js} +1 -1
- package/programs/arrowfield/logic.js +1 -1
- package/programs/data2legend/density-to-legend.js +24 -29
- package/programs/data2legend/point-to-density-texture.js +14 -17
- package/programs/float2legendwithratio/logic.js +2 -2
- package/programs/float2legendwithratio/object.js +1 -1
- package/programs/helpers/{blender/program.js → blender.js} +1 -1
- package/programs/helpers/{fadeaway/logic.js → fadeaway.js} +11 -2
- package/programs/index.js +20 -9
- package/programs/line-on-globe/circle-accurate-3d.js +12 -14
- package/programs/line-on-globe/circle-accurate-flat.js +0 -1
- package/programs/line-on-globe/degree-padding-around-circle-3d.js +13 -15
- package/programs/line-on-globe/lines-color-instanced-flat.js +15 -18
- package/programs/line-on-globe/naive-accurate-flexible.js +0 -1
- package/programs/picking/pickable-polygon-renderer.js +1 -1
- package/programs/picking/pickable-renderer.js +2 -2
- package/programs/point-on-globe/element-globe-surface-glow.js +2 -2
- package/programs/point-on-globe/element-point-glow.js +1 -1
- package/programs/point-on-globe/square-pixel-point.js +1 -1
- package/programs/polygon-on-globe/texture-dem-triangle-test-plugin-triangle.js +180 -30
- package/programs/polygon-on-globe/texture-dem-triangles.js +93 -34
- package/programs/rings/partial-ring/piece-of-pie.js +26 -29
- package/programs/totems/camerauniformblock.js +31 -42
- package/programs/two-d/pixel-padding-for-compass.js +14 -24
- package/programs/vectorfields/logics/drawrectangleparticles.js +9 -8
- package/programs/vectorfields/logics/drawrectangleparticles1.js +112 -0
- package/programs/vectorfields/logics/pixelbased.js +1 -2
- package/programs/vectorfields/pingpongbuffermanager.js +1 -1
- package/range-tools-on-terrain/bearing-line/adapters.js +1 -1
- package/range-tools-on-terrain/circle-line-chain/adapters.js +0 -5
- package/range-tools-on-terrain/circle-line-chain/plugin.js +1 -1
- package/range-tools-on-terrain/range-ring/plugin.js +4 -6
- package/semiplugins/lightweight/line-plugin.js +0 -1
- package/semiplugins/shape-on-terrain/arc-plugin.js +9 -2
- package/semiplugins/shape-on-terrain/circle-plugin.js +2 -2
- package/semiplugins/shape-on-terrain/padding-1-degree.js +1 -1
- package/semiplugins/shell/bbox-renderer/index.js +2 -0
- package/{programs/globeshell/wiggle → semiplugins/shell/bbox-renderer}/logic.js +101 -102
- package/{programs/globeshell/wiggle → semiplugins/shell/bbox-renderer}/object.js +6 -7
- package/semiplugins/utility/container-plugin.js +94 -0
- package/semiplugins/utility/object-pass-container-plugin.js +80 -0
- package/{point-heat-map → tracks/point-heat-map}/adaptors/timetracksplugin-format-to-this.js +1 -1
- package/{point-heat-map → tracks/point-heat-map}/plugin-webworker.js +3 -3
- package/{point-heat-map → tracks/point-heat-map}/point-to-heat-map-flow.js +11 -14
- package/{point-tracks → tracks/point-tracks}/plugin.js +6 -5
- package/{timetracks → tracks/timetracks}/adaptors-line-strip.js +1 -1
- package/{timetracks → tracks/timetracks}/program-line-strip.js +49 -49
- package/{timetracks → tracks/timetracks}/programpoint-line-strip.js +16 -13
- package/types.js +6 -0
- package/util/account/bufferoffsetmanager.js +1 -1
- package/util/account/single-attribute-buffer-management/buffer-orchestrator.js +9 -95
- package/util/gl-util/uniform-block/manager.js +0 -1
- package/util/gl-util/uniform-block/types.js +0 -7
- package/util/index.js +10 -13
- package/util/picking/fence.js +16 -18
- package/util/picking/picker-displayer.js +6 -8
- package/util/programs/{shapesonglobe.js → draw-from-pixel-coords.js} +4 -7
- package/util/programs/draw-texture-on-canvas.js +1 -1
- package/util/programs/texturetoglobe.js +3 -3
- package/util/shaderfunctions/geometrytransformations.js +1 -1
- package/vectorfield/arrowfield/index.js +3 -0
- package/{arrowfield → vectorfield/arrowfield}/plugin.js +2 -2
- package/{waveparticles → vectorfield/waveparticles}/plugin.js +12 -12
- package/{wind → vectorfield/wind}/index.js +1 -1
- package/{wind → vectorfield/wind}/plugin.js +65 -51
- package/write-text/context-text3.js +0 -1
- package/write-text/context-text4.js +2 -1
- package/write-text/objectarraylabels/index.js +2 -0
- package/Math/tessellation/tessellation-algorithm.js +0 -67
- package/arrowfield/index.js +0 -3
- package/bearing-line/index.js +0 -2
- package/bearing-line/plugin.js +0 -444
- package/circle-line-chain/chain-list-map.js +0 -201
- package/circle-line-chain/init.js +0 -1
- package/circle-line-chain/plugin.js +0 -411
- package/circle-line-chain/util.js +0 -1
- package/compassrose/compassrose.js +0 -293
- package/compassrose/index.js +0 -2
- package/index.js +0 -12
- package/partialrings/buffer-manager.js +0 -75
- package/partialrings/index.js +0 -2
- package/partialrings/plugin.js +0 -128
- package/partialrings/program.js +0 -279
- package/programs/arrowfield/index.js +0 -2
- package/programs/globe-util/is-globe-moved.js +0 -19
- package/programs/globeshell/index.js +0 -2
- package/programs/globeshell/wiggle/index.js +0 -2
- package/programs/helpers/blender/index.js +0 -1
- package/programs/helpers/fadeaway/index.js +0 -2
- package/programs/helpers/fadeaway/object.js +0 -14
- package/programs/helpers/index.js +0 -2
- package/programs/polygon-on-globe/texture-dem-triangle-test-plugin.js +0 -118
- package/programs/rings/distancering/circleflatprogram.js +0 -116
- package/programs/rings/distancering/circlepaddingfreeangleprogram.js +0 -326
- package/programs/rings/distancering/circlepaddysharedbuffer.js +0 -368
- package/programs/rings/distancering/index.js +0 -6
- package/programs/rings/distancering/paddyflatprogram.js +0 -127
- package/programs/rings/distancering/paddyflatprogram2d.js +0 -129
- package/programs/rings/distancering/paddyflatprogram3d.js +0 -128
- package/programs/two-d/pixel-circle.js +0 -1
- package/programs/vectorfields/index.js +0 -3
- package/rangerings/enum.js +0 -2
- package/rangerings/index.js +0 -5
- package/rangerings/plugin.js +0 -543
- package/rangerings/rangeringangletext.js +0 -326
- package/rangerings/ring-account.js +0 -112
- package/timetracks/index.js +0 -1
- package/util/build-strategy/general-strategy.js +0 -62
- package/util/gl-util/uniform-block/shader.js +0 -1
- package/util/heatwavedatamanager/index.js +0 -2
- package/util/heatwavedatamanager/pointcoordsmeta.js +0 -22
- package/util/jshelpers/data-filler.js +0 -17
- package/util/jshelpers/equality.js +0 -18
- package/util/jshelpers/index.js +0 -2
- package/util/jshelpers/timefilters.js +0 -30
- package/util/programs/index.js +0 -1
- package/util/surface-line-data/arc-bboxes.js +0 -25
- package/util/surface-line-data/arcs-to-cuts.js +0 -50
- package/util/surface-line-data/cut-arc.js +0 -1
- package/util/surface-line-data/flow.js +0 -28
- package/util/surface-line-data/rbush-manager.js +0 -1
- package/util/surface-line-data/types.js +0 -1
- package/util/surface-line-data/web-worker.js +0 -1
- package/util/webglobe/rasteroverlay.js +0 -75
- package/write-text/attached-text-writer.js +0 -87
- package/write-text/context-text3old.js +0 -152
- package/write-text/index.js +0 -1
- package/write-text/writer-plugin.js +0 -8
- /package/{heatwave/isobar/quadtreecontours.js → Math/contour/quadtreecontours1.js} +0 -0
- /package/pin/{pin-object-array.js → pin-object-array1.js} +0 -0
- /package/pin/{pin-point-totem.js → pin-point-totem1.js} +0 -0
- /package/{point-heat-map → tracks/point-heat-map}/index.js +0 -0
- /package/{point-tracks → tracks/point-tracks}/key-methods.js +0 -0
- /package/{timetracks → tracks/timetracks}/plugin-line-strip.js +0 -0
- /package/{arrowfield → vectorfield/arrowfield}/adaptor.js +0 -0
- /package/{waveparticles → vectorfield/waveparticles}/adaptor.js +0 -0
- /package/{waveparticles → vectorfield/waveparticles}/index.js +0 -0
- /package/{wind → vectorfield/wind}/imagetovectorfieldandmagnitude.js +0 -0
- /package/{wind → vectorfield/wind}/vectorfieldimage.js +0 -0
- /package/write-text/{context-text.js → context-textDELETE.js} +0 -0
- /package/{heatwave/isobar → write-text/objectarraylabels}/objectarraylabels.js +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
function displayTileMetaData(tilesMetaData) {
|
|
2
|
+
// show maxZoom minZoom
|
|
3
|
+
console.log(`Max Level: ${tilesMetaData.maxLevel}
|
|
4
|
+
Min Level: ${tilesMetaData.minLevel}`);
|
|
5
|
+
}
|
|
6
|
+
function keyMethod(row, column, level) {
|
|
7
|
+
return `${level}_${row}_${column}`;
|
|
8
|
+
}
|
|
9
|
+
function calculateParentTile(row, column, level) {
|
|
10
|
+
return {
|
|
11
|
+
row: Math.floor(row / 2),
|
|
12
|
+
column: Math.floor(column / 2),
|
|
13
|
+
level: level - 1
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function createMapAndMetaData(tiles) {
|
|
17
|
+
const tileMap = new Map();
|
|
18
|
+
let maxLevel = -Infinity;
|
|
19
|
+
let minLevel = Infinity;
|
|
20
|
+
const tileLimitsByZoom = new Map();
|
|
21
|
+
for (const tile of tiles) {
|
|
22
|
+
const key = keyMethod(tile.row, tile.column, tile.level);
|
|
23
|
+
tileMap.set(key, tile);
|
|
24
|
+
if (tile.level > maxLevel) {
|
|
25
|
+
maxLevel = tile.level;
|
|
26
|
+
}
|
|
27
|
+
if (tile.level < minLevel) {
|
|
28
|
+
minLevel = tile.level;
|
|
29
|
+
}
|
|
30
|
+
if (!tileLimitsByZoom.has(tile.level)) {
|
|
31
|
+
tileLimitsByZoom.set(tile.level, {
|
|
32
|
+
minRow: tile.row,
|
|
33
|
+
maxRow: tile.row,
|
|
34
|
+
minCol: tile.column,
|
|
35
|
+
maxCol: tile.column
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const limits = tileLimitsByZoom.get(tile.level);
|
|
40
|
+
if (tile.row < limits.minRow)
|
|
41
|
+
limits.minRow = tile.row;
|
|
42
|
+
if (tile.row > limits.maxRow)
|
|
43
|
+
limits.maxRow = tile.row;
|
|
44
|
+
if (tile.column < limits.minCol)
|
|
45
|
+
limits.minCol = tile.column;
|
|
46
|
+
if (tile.column > limits.maxCol)
|
|
47
|
+
limits.maxCol = tile.column;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
tileMap,
|
|
52
|
+
maxLevel,
|
|
53
|
+
minLevel,
|
|
54
|
+
tileLimitsByZoom
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function populateTileIntoHigherZoomLevel(tileMesh, tileDimensionLength, targetDimensionLength) {
|
|
58
|
+
const newMesh = new Array(targetDimensionLength).fill(0).map(() => new Float32Array(targetDimensionLength));
|
|
59
|
+
// use linear interpolation to populate
|
|
60
|
+
for (let row = 0; row < targetDimensionLength; row++) {
|
|
61
|
+
for (let col = 0; col < targetDimensionLength; col++) {
|
|
62
|
+
const srcRow = row * (tileDimensionLength - 1) / (targetDimensionLength - 1);
|
|
63
|
+
const srcCol = col * (tileDimensionLength - 1) / (targetDimensionLength - 1);
|
|
64
|
+
const srcRowLow = Math.floor(srcRow);
|
|
65
|
+
const srcRowHigh = Math.min(Math.ceil(srcRow), tileDimensionLength - 1);
|
|
66
|
+
const srcColLow = Math.floor(srcCol);
|
|
67
|
+
const srcColHigh = Math.min(Math.ceil(srcCol), tileDimensionLength - 1);
|
|
68
|
+
const topLeft = tileMesh[srcRowLow][srcColLow];
|
|
69
|
+
const topRight = tileMesh[srcRowLow][srcColHigh];
|
|
70
|
+
const bottomLeft = tileMesh[srcRowHigh][srcColLow];
|
|
71
|
+
const bottomRight = tileMesh[srcRowHigh][srcColHigh];
|
|
72
|
+
const top = topLeft + (topRight - topLeft) * (srcCol - srcColLow);
|
|
73
|
+
const bottom = bottomLeft + (bottomRight - bottomLeft) * (srcCol - srcColLow);
|
|
74
|
+
newMesh[row][col] = top + (bottom - top) * (srcRow - srcRowLow);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return newMesh;
|
|
78
|
+
}
|
|
79
|
+
// This function is correct, assuming its inputs are prepared properly.
|
|
80
|
+
// This function is correct, assuming its inputs are prepared properly.
|
|
81
|
+
function moveMeshToMergedMesh(targetMesh, targetDimensionLength, sourceMesh, sourceDimensionLength, startX, startY) {
|
|
82
|
+
for (let row = 0; row < sourceDimensionLength; row++) {
|
|
83
|
+
for (let col = 0; col < sourceDimensionLength; col++) {
|
|
84
|
+
const targetIndex = (startY + row) * targetDimensionLength + (startX + col);
|
|
85
|
+
// Check if source value exists
|
|
86
|
+
if (sourceMesh[row] === undefined || sourceMesh[row][col] === undefined) {
|
|
87
|
+
console.warn(`Source data missing at [${row}][${col}]`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const value = sourceMesh[row][col];
|
|
91
|
+
if (isNaN(value)) {
|
|
92
|
+
console.warn(`NaN value found in source mesh at row: ${row}, col: ${col}`);
|
|
93
|
+
}
|
|
94
|
+
;
|
|
95
|
+
if (targetIndex >= targetMesh.length) {
|
|
96
|
+
console.warn(`⚠️ Target index out of bounds: ${targetIndex} >= ${targetMesh.length}`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
targetMesh[targetIndex] = value;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function limitCheck(limit, limitRange = 12) {
|
|
104
|
+
const rowRange = limit.maxRow - limit.minRow + 1;
|
|
105
|
+
const colRange = limit.maxCol - limit.minCol + 1;
|
|
106
|
+
if (rowRange > limitRange || colRange > limitRange) {
|
|
107
|
+
console.warn(`Tile limit range exceeded: Row Range = ${rowRange}, Col Range = ${colRange}, Limit Range = ${limitRange}`);
|
|
108
|
+
throw new Error("Tile limit range exceeded");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function mergeTiles(tilesMetaData, mergeCount = 8, tileDimensionLength = 5, processLimit = 6) {
|
|
112
|
+
const mergedMeshDimLength = tileDimensionLength * mergeCount - (mergeCount - 1);
|
|
113
|
+
const processedTiles = new Set();
|
|
114
|
+
const result = [];
|
|
115
|
+
for (let zoom = tilesMetaData.maxLevel; zoom >= tilesMetaData.minLevel; zoom--) {
|
|
116
|
+
let processedTileCountFromCurrentLevel = 0;
|
|
117
|
+
let processedTileCountFromParentLevel = 0;
|
|
118
|
+
if (tilesMetaData.maxLevel - zoom >= processLimit) {
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
const limits = tilesMetaData.tileLimitsByZoom.get(zoom);
|
|
122
|
+
const mergedMesh = new Float32Array(mergedMeshDimLength * mergedMeshDimLength).fill(0);
|
|
123
|
+
const bboxLimit = {
|
|
124
|
+
ur: { x: -Infinity, y: -Infinity },
|
|
125
|
+
ll: { x: Infinity, y: Infinity }
|
|
126
|
+
};
|
|
127
|
+
if (!limits)
|
|
128
|
+
continue;
|
|
129
|
+
limitCheck(limits, 12);
|
|
130
|
+
for (let row = limits.minRow; row <= limits.maxRow; row++) {
|
|
131
|
+
for (let col = limits.minCol; col <= limits.maxCol; col++) {
|
|
132
|
+
const key = keyMethod(row, col, zoom);
|
|
133
|
+
if (processedTiles.has(key)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const tile = tilesMetaData.tileMap.get(key);
|
|
137
|
+
if (tile) {
|
|
138
|
+
// move tile mesh to merged mesh
|
|
139
|
+
moveMeshToMergedMesh(mergedMesh, mergedMeshDimLength, tile.mesh, tileDimensionLength, (row - limits.minRow) * (tileDimensionLength - 1), (col - limits.minCol) * (tileDimensionLength - 1));
|
|
140
|
+
// moveMeshToMergedMesh2(
|
|
141
|
+
// mergedMesh, mergedMeshDimLength,
|
|
142
|
+
// (row + col) % 2 === 0 ? 0.1 : 0,
|
|
143
|
+
// tileDimensionLength,
|
|
144
|
+
// (row - limits.minRow) * (tileDimensionLength - 1), (col - limits.minCol) * (tileDimensionLength - 1)
|
|
145
|
+
// );
|
|
146
|
+
processedTiles.add(key);
|
|
147
|
+
processedTileCountFromCurrentLevel++;
|
|
148
|
+
// update bbox
|
|
149
|
+
if (tile.bbox.ll.x < bboxLimit.ll.x)
|
|
150
|
+
bboxLimit.ll.x = tile.bbox.ll.x;
|
|
151
|
+
if (tile.bbox.ll.y < bboxLimit.ll.y)
|
|
152
|
+
bboxLimit.ll.y = tile.bbox.ll.y;
|
|
153
|
+
if (tile.bbox.ur.x > bboxLimit.ur.x)
|
|
154
|
+
bboxLimit.ur.x = tile.bbox.ur.x;
|
|
155
|
+
if (tile.bbox.ur.y > bboxLimit.ur.y)
|
|
156
|
+
bboxLimit.ur.y = tile.bbox.ur.y;
|
|
157
|
+
/**
|
|
158
|
+
} else {
|
|
159
|
+
// try to find parent tile
|
|
160
|
+
const parent = calculateParentTile(row, col, zoom);
|
|
161
|
+
const parentKey = keyMethod(parent.row, parent.column, parent.level);
|
|
162
|
+
const parentTile = tilesMetaData.tileMap.get(parentKey);
|
|
163
|
+
|
|
164
|
+
if (parentTile) {
|
|
165
|
+
// Parent's 4 children at current zoom level
|
|
166
|
+
const parentTopLeftChildRow = parent.row * 2;
|
|
167
|
+
const parentTopLeftChildCol = parent.column * 2;
|
|
168
|
+
const topLeftChildKey = keyMethod(parentTopLeftChildRow, parentTopLeftChildCol, zoom);
|
|
169
|
+
|
|
170
|
+
// Only process parent once
|
|
171
|
+
if (!processedTiles.has(topLeftChildKey)) {
|
|
172
|
+
// Check if parent's area is within or overlaps the current limits
|
|
173
|
+
const parentBottomRightChildRow = parentTopLeftChildRow + 1;
|
|
174
|
+
const parentBottomRightChildCol = parentTopLeftChildCol + 1;
|
|
175
|
+
|
|
176
|
+
// Check if parent's children overlap with current zoom's limits
|
|
177
|
+
if (parentTopLeftChildRow > limits.maxRow ||
|
|
178
|
+
parentBottomRightChildRow < limits.minRow ||
|
|
179
|
+
parentTopLeftChildCol > limits.maxCol ||
|
|
180
|
+
parentBottomRightChildCol < limits.minCol) {
|
|
181
|
+
// Parent doesn't overlap, skip
|
|
182
|
+
processedTiles.add(key);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Upscale parent to cover all 4 children
|
|
187
|
+
const parentTileUpscaledMesh = populateTileIntoHigherZoomLevel(
|
|
188
|
+
parentTile.mesh,
|
|
189
|
+
tileDimensionLength,
|
|
190
|
+
tileDimensionLength * 2 - 1
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// Calculate destination position (parent's top-left child position)
|
|
194
|
+
// Clamp to limits to handle edge cases
|
|
195
|
+
const actualStartRow = Math.max(parentTopLeftChildRow, limits.minRow);
|
|
196
|
+
const actualStartCol = Math.max(parentTopLeftChildCol, limits.minCol);
|
|
197
|
+
|
|
198
|
+
const destRow = (actualStartRow - limits.minRow) * (tileDimensionLength - 1);
|
|
199
|
+
const destCol = (actualStartCol - limits.minCol) * (tileDimensionLength - 1);
|
|
200
|
+
|
|
201
|
+
// Calculate source offset if parent starts before limits
|
|
202
|
+
const srcRowOffset = (actualStartRow - parentTopLeftChildRow) * (tileDimensionLength - 1);
|
|
203
|
+
const srcColOffset = (actualStartCol - parentTopLeftChildCol) * (tileDimensionLength - 1);
|
|
204
|
+
|
|
205
|
+
// Calculate how much to copy
|
|
206
|
+
const actualEndRow = Math.min(parentBottomRightChildRow, limits.maxRow);
|
|
207
|
+
const actualEndCol = Math.min(parentBottomRightChildCol, limits.maxCol);
|
|
208
|
+
|
|
209
|
+
const copyRows = (actualEndRow - actualStartRow + 1) * (tileDimensionLength - 1);
|
|
210
|
+
const copyCols = (actualEndCol - actualStartCol + 1) * (tileDimensionLength - 1);
|
|
211
|
+
|
|
212
|
+
// Copy only the visible portion
|
|
213
|
+
moveMeshToMergedMeshPartial(
|
|
214
|
+
mergedMesh,
|
|
215
|
+
mergedMeshDimLength,
|
|
216
|
+
parentTileUpscaledMesh,
|
|
217
|
+
tileDimensionLength * 2 - 1,
|
|
218
|
+
destRow,
|
|
219
|
+
destCol,
|
|
220
|
+
srcRowOffset,
|
|
221
|
+
srcColOffset,
|
|
222
|
+
copyRows,
|
|
223
|
+
copyCols
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Mark all 4 child positions as processed (even if out of bounds)
|
|
227
|
+
for (let dr = 0; dr < 2; dr++) {
|
|
228
|
+
for (let dc = 0; dc < 2; dc++) {
|
|
229
|
+
const childRow = parentTopLeftChildRow + dr;
|
|
230
|
+
const childCol = parentTopLeftChildCol + dc;
|
|
231
|
+
const childKey = keyMethod(childRow, childCol, zoom);
|
|
232
|
+
processedTiles.add(childKey);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
processedTileCountFromParentLevel++;
|
|
237
|
+
|
|
238
|
+
// Update bbox (use actual parent bbox, not child bbox)
|
|
239
|
+
if (parentTile.bbox.ll.x < bboxLimit.ll.x) bboxLimit.ll.x = parentTile.bbox.ll.x;
|
|
240
|
+
if (parentTile.bbox.ll.y < bboxLimit.ll.y) bboxLimit.ll.y = parentTile.bbox.ll.y;
|
|
241
|
+
if (parentTile.bbox.ur.x > bboxLimit.ur.x) bboxLimit.ur.x = parentTile.bbox.ur.x;
|
|
242
|
+
if (parentTile.bbox.ur.y > bboxLimit.ur.y) bboxLimit.ur.y = parentTile.bbox.ur.y;
|
|
243
|
+
} else {
|
|
244
|
+
// Already processed via parent
|
|
245
|
+
processedTiles.add(key);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
// No parent available
|
|
249
|
+
processedTiles.add(key);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
*/
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const rowRatio = (limits.maxRow - limits.minRow + 1) / mergeCount;
|
|
257
|
+
const colRatio = (limits.maxCol - limits.minCol + 1) / mergeCount;
|
|
258
|
+
// console.log(`Zoom ${zoom}: Processed ${processedTileCountFromCurrentLevel} from current level, ${processedTileCountFromParentLevel} from parent level. Coverage: ${(rowRatio * 100).toFixed(1)}% x ${(colRatio * 100).toFixed(1)}%`);
|
|
259
|
+
result.push({ mesh: mergedMesh, bbox: bboxLimit, zoom: zoom, coverRatio: { x: rowRatio, y: colRatio } });
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
export function mergeMeshes(tiles, mergeCount = 12, tileDimensionLength = 5, processLimit = 6) {
|
|
264
|
+
// filter out tiles with NaN values
|
|
265
|
+
// return returnTop6tiles(tiles);
|
|
266
|
+
const tilesMetaData = createMapAndMetaData(tiles);
|
|
267
|
+
const mergedTiles = mergeTiles(tilesMetaData, mergeCount, tileDimensionLength, processLimit);
|
|
268
|
+
return mergedTiles;
|
|
269
|
+
}
|
|
270
|
+
function returnTop6tiles(tiles) {
|
|
271
|
+
const tilesMetaData = createMapAndMetaData(tiles);
|
|
272
|
+
const hightestZoom = tilesMetaData.maxLevel;
|
|
273
|
+
const result = [];
|
|
274
|
+
let counter = 6;
|
|
275
|
+
function tileToMergedTileInfo(tile) {
|
|
276
|
+
const mesh = new Float32Array(tile.mesh[0].length * tile.mesh[0].length);
|
|
277
|
+
for (let row = 0; row < tile.mesh[0].length; row++) {
|
|
278
|
+
for (let col = 0; col < tile.mesh[0].length; col++) {
|
|
279
|
+
mesh[row * tile.mesh[0].length + col] = tile.mesh[0][row * tile.mesh[0].length + col];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
mesh: mesh,
|
|
284
|
+
zoom: tile.level,
|
|
285
|
+
bbox: tile.bbox,
|
|
286
|
+
coverRatio: { x: 1, y: 1 },
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
for (const tile of tiles) {
|
|
290
|
+
if (counter === 0)
|
|
291
|
+
break;
|
|
292
|
+
if (tile.level === hightestZoom) {
|
|
293
|
+
result.push(tileToMergedTileInfo(tile));
|
|
294
|
+
counter--;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return result;
|
|
298
|
+
}
|
|
@@ -8,6 +8,7 @@ import { pointsOnArc } from "../juction/arc-plane";
|
|
|
8
8
|
import { latToTileY, tileYtoLat } from "./methods";
|
|
9
9
|
import { isOnTileEdge } from "./methods";
|
|
10
10
|
import Delaunator from "delaunator";
|
|
11
|
+
import { radianToMercatorXY } from "../methods";
|
|
11
12
|
// TODO:get rid of embedded lists. always flat list
|
|
12
13
|
const TILE_DEM_VERTEX_COUNT = 5; // 5x5 grid for DEM
|
|
13
14
|
const TILE_DEM_STEPCOUNT = TILE_DEM_VERTEX_COUNT - 1; // 4 inner divisions in each dimension
|
|
@@ -118,7 +119,7 @@ function showMeta(triangleMeta) {
|
|
|
118
119
|
* @param angle
|
|
119
120
|
* @param dimension false for longitude (meridian) true for latitude (parallel)
|
|
120
121
|
*/
|
|
121
|
-
function getPoints(triangleMeta, angle, dimension) {
|
|
122
|
+
export function getPoints(triangleMeta, angle, dimension) {
|
|
122
123
|
// console.log("getPoints called with angle:", angle * 180 / Math.PI, "dimension:", dimension ? 'latitude' : 'longitude');
|
|
123
124
|
// find which arcs are cut by plane
|
|
124
125
|
const radians = angle;
|
|
@@ -147,12 +148,12 @@ function getPoints(triangleMeta, angle, dimension) {
|
|
|
147
148
|
}
|
|
148
149
|
const count = pointsOnArc(arc, _plane, _resultPoints);
|
|
149
150
|
if (count === 1) {
|
|
150
|
-
result.push([..._resultPoints[0]]);
|
|
151
|
+
result.push([[..._resultPoints[0]], vec3ToLongLatRadians(_resultPoints[0])]);
|
|
151
152
|
}
|
|
152
153
|
else if (count === 2) {
|
|
153
154
|
// throw new Error('Unexpected 2 cut points on arc, should be max 1'); // TODO DELETE this line later
|
|
154
|
-
result.push([..._resultPoints[0]]);
|
|
155
|
-
result.push([..._resultPoints[1]]); // TODO: this is a fix for a bug, need to investigate later
|
|
155
|
+
result.push([[..._resultPoints[0]], vec3ToLongLatRadians(_resultPoints[0])]);
|
|
156
|
+
result.push([[..._resultPoints[1]], vec3ToLongLatRadians(_resultPoints[1])]); // TODO: this is a fix for a bug, need to investigate later
|
|
156
157
|
}
|
|
157
158
|
resultsFromDistinctArcs += 1;
|
|
158
159
|
}
|
|
@@ -168,7 +169,7 @@ function getPoints(triangleMeta, angle, dimension) {
|
|
|
168
169
|
"bbox:" + triangleMeta.bbox.min[0] * 180 / Math.PI + ", " + triangleMeta.bbox.min[1] * 180 / Math.PI + ", " + triangleMeta.bbox.max[0] * 180 / Math.PI + ", " + triangleMeta.bbox.max[1] * 180 / Math.PI + "\n";
|
|
169
170
|
showMeta(triangleMeta);
|
|
170
171
|
for (let res of result) {
|
|
171
|
-
const ll =
|
|
172
|
+
const ll = res[1];
|
|
172
173
|
console.log("Point: " + ll[0] * 180 / Math.PI + ", " + ll[1] * 180 / Math.PI + "\n");
|
|
173
174
|
}
|
|
174
175
|
throw new Error(`Unexpected cut count for tile cut, got: ${result.length}, angle: ${angle * 180 / Math.PI}, dimension: ${dimension ? 'latitude' : 'longitude'} \n` + text);
|
|
@@ -179,10 +180,10 @@ function getPoints(triangleMeta, angle, dimension) {
|
|
|
179
180
|
}
|
|
180
181
|
result.sort((a, b) => {
|
|
181
182
|
if (dimension) {
|
|
182
|
-
return a[1] - b[1]; // sort by y for longitude cuts
|
|
183
|
+
return a[0][1] - b[0][1]; // sort by y for longitude cuts
|
|
183
184
|
}
|
|
184
185
|
else {
|
|
185
|
-
return a[0] - b[0]; // sort by x for latitude cuts
|
|
186
|
+
return a[1][0] - b[1][0]; // sort by x for latitude cuts
|
|
186
187
|
}
|
|
187
188
|
});
|
|
188
189
|
return result;
|
|
@@ -239,15 +240,13 @@ export function getAllPoints(triangleMeta, zoom, innerCuts = TILE_DEM_STEPCOUNT)
|
|
|
239
240
|
for (let i = 0; i < concurances.length; i += 2) {
|
|
240
241
|
const p0 = concurances[i];
|
|
241
242
|
const p1 = concurances[i + 1];
|
|
242
|
-
points.push(...p0);
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
longLatPoints.push(...
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (length(p0) < 0.99 || length(p1) < 0.99 || length(p0) > 1.01 || length(p1) > 1.01) {
|
|
250
|
-
console.warn("Warning: Cut point is not on unit sphere!", length(p0), length(p1));
|
|
243
|
+
points.push(...p0[0]);
|
|
244
|
+
longLatPoints.push(...p0[1]);
|
|
245
|
+
fillBetweenInParallels(lat, p0[1], p1[1], lonLengthRadian, points, longLatPoints);
|
|
246
|
+
points.push(...p1[0]);
|
|
247
|
+
longLatPoints.push(...p1[1]);
|
|
248
|
+
if (length(p0[0]) < 0.99 || length(p1[0]) < 0.99 || length(p0[0]) > 1.01 || length(p1[0]) > 1.01) {
|
|
249
|
+
console.warn("Warning: Cut point is not on unit sphere!", length(p0[0]), length(p1[0]));
|
|
251
250
|
}
|
|
252
251
|
}
|
|
253
252
|
currentY -= latInnerStep;
|
|
@@ -258,15 +257,13 @@ export function getAllPoints(triangleMeta, zoom, innerCuts = TILE_DEM_STEPCOUNT)
|
|
|
258
257
|
currentLong += lonLengthRadian; // since start point is already added
|
|
259
258
|
while (currentLong < endMeridianRadian) {
|
|
260
259
|
const [p0, p1] = getPoints(triangleMeta, currentLong, false);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
points.push(...p0);
|
|
265
|
-
longLatPoints.push(...p0LongLat);
|
|
260
|
+
if (!isOnTileEdge(p0[1], zoom)) {
|
|
261
|
+
points.push(...p0[0]);
|
|
262
|
+
longLatPoints.push(...p0[1]);
|
|
266
263
|
}
|
|
267
|
-
if (!isOnTileEdge(
|
|
268
|
-
points.push(...p1);
|
|
269
|
-
longLatPoints.push(...
|
|
264
|
+
if (!isOnTileEdge(p1[1], zoom)) {
|
|
265
|
+
points.push(...p1[0]);
|
|
266
|
+
longLatPoints.push(...p1[1]);
|
|
270
267
|
}
|
|
271
268
|
currentLong += lonLengthRadian;
|
|
272
269
|
}
|
|
@@ -274,7 +271,12 @@ export function getAllPoints(triangleMeta, zoom, innerCuts = TILE_DEM_STEPCOUNT)
|
|
|
274
271
|
let indices = delaunator.triangles;
|
|
275
272
|
const edgeIndexes = shellPoints.map((e, index) => index * 2); // edge points are always first points in list
|
|
276
273
|
indices = filteroutEdgeConnections(indices, edgeIndexes);
|
|
277
|
-
rotateIndices(indices);
|
|
274
|
+
// rotateIndices(indices);
|
|
275
|
+
// for (let i = 0; i < longLatPoints.length / 2; i++) {
|
|
276
|
+
// const xy = radianToMercatorXY([longLatPoints[i * 2], longLatPoints[i * 2 + 1]]);
|
|
277
|
+
// longLatPoints[i * 2] = xy[0];
|
|
278
|
+
// longLatPoints[i * 2 + 1] = xy[1];
|
|
279
|
+
// }
|
|
278
280
|
return { vec3s: new Float32Array(points), longLats: new Float32Array(longLatPoints), indices: indices };
|
|
279
281
|
}
|
|
280
282
|
function fillBetweenInParallels(lat, p1, p2, step, fillVec3Arr, longLatPoints) {
|
|
@@ -292,18 +294,18 @@ function fillBetweenInParallels(lat, p1, p2, step, fillVec3Arr, longLatPoints) {
|
|
|
292
294
|
current += step;
|
|
293
295
|
}
|
|
294
296
|
}
|
|
295
|
-
function filterDuplicate(
|
|
296
|
-
const result = [];
|
|
297
|
+
function filterDuplicate(points) {
|
|
298
|
+
const result = [points[0]];
|
|
297
299
|
let dublicate = false;
|
|
298
|
-
for (let i =
|
|
300
|
+
for (let i = 1; i < points.length; i++) {
|
|
299
301
|
for (let j = 0; j < result.length; j++) {
|
|
300
|
-
if (equals(
|
|
302
|
+
if (equals(points[i][0], result[j][0])) {
|
|
301
303
|
dublicate = true;
|
|
302
304
|
break;
|
|
303
305
|
}
|
|
304
306
|
}
|
|
305
307
|
if (!dublicate) {
|
|
306
|
-
result.push(
|
|
308
|
+
result.push(points[i]);
|
|
307
309
|
}
|
|
308
310
|
}
|
|
309
311
|
return result;
|
|
@@ -311,16 +313,6 @@ function filterDuplicate(vec3s) {
|
|
|
311
313
|
function showLongLatRadian(longLat) {
|
|
312
314
|
return `(${(longLat[0] * 180 / Math.PI).toFixed(2)}°, ${(longLat[1] * 180 / Math.PI).toFixed(2)}°)`;
|
|
313
315
|
}
|
|
314
|
-
function rotateIndices(indices) {
|
|
315
|
-
const len = indices.length / 3;
|
|
316
|
-
let hold;
|
|
317
|
-
for (let i = 0; i < len; i++) {
|
|
318
|
-
hold = indices[i * 3];
|
|
319
|
-
indices[i * 3] = indices[i * 3 + 1];
|
|
320
|
-
indices[i * 3 + 1] = hold;
|
|
321
|
-
}
|
|
322
|
-
return indices;
|
|
323
|
-
}
|
|
324
316
|
// This method for removing external edge connections. The connections are unnecessary and cause a veil descending to the center of sphere from the edges
|
|
325
317
|
function filteroutEdgeConnections(indexes, filterOutIndexes) {
|
|
326
318
|
const length = indexes.length / 3;
|
|
@@ -366,5 +358,166 @@ function shredTriangleTessellationMeta(triangleMeta, zoomLevel) {
|
|
|
366
358
|
*
|
|
367
359
|
* still all triangles should have some sort of cached tessellation to fast render on rapit earth rotation
|
|
368
360
|
*/
|
|
369
|
-
|
|
370
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Creates a mesh for a spherical triangle, tessellated only within the
|
|
363
|
+
* regions specified by the `limits` array.
|
|
364
|
+
*
|
|
365
|
+
* @param triangleMeta The metadata for the spherical triangle.
|
|
366
|
+
* @param limits An array of bounding boxes and their associated zoom levels to tessellate.
|
|
367
|
+
* @param innerCuts The number of subdivisions within each tile (e.g., TILE_DEM_STEPCOUNT).
|
|
368
|
+
* @returns A set of arrays (vec3s, longLats, indices) representing the partial mesh.
|
|
369
|
+
*/
|
|
370
|
+
export function partialTessellation(triangleMeta, limits, innerCuts) {
|
|
371
|
+
// TODO: pointMap can be local variable and cleaned after function call to avoid reinitialization overhead
|
|
372
|
+
const pointMap = new Map(); // Key: "lon|lat", Value: index
|
|
373
|
+
const allVec3s = [];
|
|
374
|
+
const allLongLats = [];
|
|
375
|
+
let pointCounter = 0;
|
|
376
|
+
const stepCount = innerCuts - 1; //
|
|
377
|
+
/**
|
|
378
|
+
* Precision for coordinate keys in the map. 1e-12 radians is
|
|
379
|
+
* extremely small (sub-millimeter on Earth's surface) and avoids
|
|
380
|
+
* floating point inaccuracies causing duplicate points.
|
|
381
|
+
*/
|
|
382
|
+
const KEY_PRECISION = 10;
|
|
383
|
+
/**
|
|
384
|
+
* Adds a point to the vertex arrays if it doesn't already exist.
|
|
385
|
+
* Returns the index of the point (new or existing).
|
|
386
|
+
*/
|
|
387
|
+
const addPoint = (longLat, vec3) => {
|
|
388
|
+
const key = `${longLat[0].toPrecision(KEY_PRECISION)}|${longLat[1].toPrecision(KEY_PRECISION)}`;
|
|
389
|
+
let index = pointMap.get(key);
|
|
390
|
+
if (index !== undefined) {
|
|
391
|
+
return index; // Point already exists
|
|
392
|
+
}
|
|
393
|
+
// Point is new, add it
|
|
394
|
+
const v3 = vec3 || createUnitVectorFromLongLat(longLat);
|
|
395
|
+
allVec3s.push(...v3);
|
|
396
|
+
allLongLats.push(...longLat);
|
|
397
|
+
index = pointCounter++;
|
|
398
|
+
pointMap.set(key, index);
|
|
399
|
+
return index;
|
|
400
|
+
};
|
|
401
|
+
// 1. Add triangle's "shell" (for Delaunay) and "edge" (vertices/limits) points
|
|
402
|
+
// These points constrain the triangulation.
|
|
403
|
+
const shellPointIndices = [];
|
|
404
|
+
const edgePoints = getEdgePoints(triangleMeta);
|
|
405
|
+
// Assuming shellPoints and edgePoints have the same length and correspond
|
|
406
|
+
const shellPointCount = Math.min(triangleMeta.shellPoints.length, edgePoints.length);
|
|
407
|
+
for (let i = 0; i < shellPointCount; i++) {
|
|
408
|
+
// Add the "shell" point (for Delaunay stability)
|
|
409
|
+
shellPointIndices.push(addPoint(triangleMeta.shellPoints[i]));
|
|
410
|
+
// Add the actual "edge" point (triangle vertex or limit point)
|
|
411
|
+
addPoint(vec3ToLongLatRadians(edgePoints[i]), edgePoints[i]);
|
|
412
|
+
}
|
|
413
|
+
// 2. Iterate through each tile limit
|
|
414
|
+
for (const { bbox: tileBBox, zoom } of limits) {
|
|
415
|
+
// 2a. Calculate the intersection BBOX (the area we'll work on)
|
|
416
|
+
const workBBox = {
|
|
417
|
+
min: [
|
|
418
|
+
Math.max(triangleMeta.bbox.min[0], tileBBox.min[0]),
|
|
419
|
+
Math.max(triangleMeta.bbox.min[1], tileBBox.min[1])
|
|
420
|
+
],
|
|
421
|
+
max: [
|
|
422
|
+
Math.min(triangleMeta.bbox.max[0], tileBBox.max[0]),
|
|
423
|
+
Math.min(triangleMeta.bbox.max[1], tileBBox.max[1])
|
|
424
|
+
],
|
|
425
|
+
};
|
|
426
|
+
// If the intersection is invalid (no overlap), skip this tile
|
|
427
|
+
if (workBBox.min[0] >= workBBox.max[0] || workBBox.min[1] >= workBBox.max[1]) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
// 2b. Calculate grid steps for this tile's zoom
|
|
431
|
+
const tileCount = TILE_COUNTS[zoom];
|
|
432
|
+
const lonStep = (2 * Math.PI) / tileCount / stepCount;
|
|
433
|
+
const latStep = 1.0 / stepCount; // This is in tileY units
|
|
434
|
+
// 2c. Generate Latitude (Parallel) Points
|
|
435
|
+
const startTileY = latToTileY(workBBox.max[1], zoom); // max lat -> min tileY
|
|
436
|
+
const endTileY = latToTileY(workBBox.min[1], zoom); // min lat -> max tileY
|
|
437
|
+
// let currentY = Math.ceil(startTileY / latStep) * latStep;
|
|
438
|
+
let currentY = startTileY - Math.abs(startTileY % latStep);
|
|
439
|
+
// if (currentY < startTileY - 1e-9) currentY += latStep; // Ensure we start inside or on edge
|
|
440
|
+
if (currentY === startTileY)
|
|
441
|
+
currentY -= latStep; // since start point is already added
|
|
442
|
+
while (currentY <= endTileY + 1e-9) {
|
|
443
|
+
const lat = tileYtoLat(currentY, zoom);
|
|
444
|
+
// Skip if rounding put us slightly outside the work box
|
|
445
|
+
if (lat < workBBox.min[1] - 1e-9 || lat > workBBox.max[1] + 1e-9) {
|
|
446
|
+
currentY += latStep;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
// Find where this latitude line intersects the triangle
|
|
450
|
+
const intersections = getPoints(triangleMeta, lat, true);
|
|
451
|
+
for (let i = 0; i < intersections.length; i += 2) {
|
|
452
|
+
const p0 = intersections[i]; // [Vec3, LongLatRadian]
|
|
453
|
+
const p1 = intersections[i + 1];
|
|
454
|
+
// Find the segment of this latitude line that is *inside* both
|
|
455
|
+
// the triangle (p0-p1) AND the tile BBOX (workBBox)
|
|
456
|
+
const triMinLon = Math.min(p0[1][0], p1[1][0]);
|
|
457
|
+
const triMaxLon = Math.max(p0[1][0], p1[1][0]);
|
|
458
|
+
const segMinLon = Math.max(workBBox.min[0], triMinLon);
|
|
459
|
+
const segMaxLon = Math.min(workBBox.max[0], triMaxLon);
|
|
460
|
+
// If this clipped segment is valid, generate points
|
|
461
|
+
if (segMinLon < segMaxLon - 1e-9) {
|
|
462
|
+
// Add the exact start and end points of the clipped segment
|
|
463
|
+
addPoint([segMinLon, lat]);
|
|
464
|
+
addPoint([segMaxLon, lat]);
|
|
465
|
+
// Add fill points *between* them
|
|
466
|
+
let currentLon = Math.ceil(segMinLon / lonStep) * lonStep;
|
|
467
|
+
if (currentLon < segMinLon - 1e-9)
|
|
468
|
+
currentLon += lonStep;
|
|
469
|
+
while (currentLon < segMaxLon - 1e-9) {
|
|
470
|
+
addPoint([currentLon, lat]);
|
|
471
|
+
currentLon += lonStep;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
currentY += latStep;
|
|
476
|
+
}
|
|
477
|
+
// 2d. Generate Longitude (Meridian) Points
|
|
478
|
+
const startLon = workBBox.min[0];
|
|
479
|
+
const endLon = workBBox.max[0];
|
|
480
|
+
let currentLon = Math.ceil(startLon / lonStep) * lonStep;
|
|
481
|
+
if (currentLon < startLon - 1e-9)
|
|
482
|
+
currentLon += lonStep;
|
|
483
|
+
while (currentLon <= endLon + 1e-9) {
|
|
484
|
+
// Find where this longitude line intersects the triangle
|
|
485
|
+
const intersections = getPoints(triangleMeta, currentLon, false);
|
|
486
|
+
for (const p of intersections) {
|
|
487
|
+
const pLongLat = p[1];
|
|
488
|
+
// Check if this point is inside the *workBBox*
|
|
489
|
+
if (pLongLat[1] >= workBBox.min[1] - 1e-9 &&
|
|
490
|
+
pLongLat[1] <= workBBox.max[1] + 1e-9) {
|
|
491
|
+
addPoint(pLongLat, p[0]);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
currentLon += lonStep;
|
|
495
|
+
}
|
|
496
|
+
} // End loop over limits
|
|
497
|
+
// 3. Triangulate
|
|
498
|
+
// We must have at least 3 points to make a triangle
|
|
499
|
+
if (pointCounter < 3) {
|
|
500
|
+
return {
|
|
501
|
+
vec3s: new Float32Array(),
|
|
502
|
+
longLats: new Float32Array(),
|
|
503
|
+
indices: new Uint32Array(),
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
const delaunator = new Delaunator(allLongLats);
|
|
507
|
+
let indices = delaunator.triangles;
|
|
508
|
+
// 4. Filter out triangles connected to the "shell" points
|
|
509
|
+
indices = filteroutEdgeConnections(indices, shellPointIndices);
|
|
510
|
+
// console.log(...allLongLats.slice(0, 10));
|
|
511
|
+
for (let i = 0; i < allLongLats.length / 2; i++) {
|
|
512
|
+
const xy = radianToMercatorXY([allLongLats[i * 2], allLongLats[i * 2 + 1]]);
|
|
513
|
+
allLongLats[i * 2] = xy[0];
|
|
514
|
+
allLongLats[i * 2 + 1] = xy[1];
|
|
515
|
+
}
|
|
516
|
+
// show first 5
|
|
517
|
+
// console.log(...allLongLats.slice(0, 10));
|
|
518
|
+
return {
|
|
519
|
+
vec3s: new Float32Array(allVec3s),
|
|
520
|
+
longLats: new Float32Array(allLongLats),
|
|
521
|
+
indices: indices,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* @author Toprak Ozturk
|
|
3
3
|
*
|
|
4
4
|
*/
|
|
5
|
-
import { createTriangleTessellationMeta, getAllPoints } from "./triangle-tessellation-meta";
|
|
5
|
+
import { createTriangleTessellationMeta, getAllPoints, partialTessellation } from "./triangle-tessellation-meta";
|
|
6
6
|
export function test1(zoomLevel, p1, p2, p3) {
|
|
7
7
|
const triangleMeta = createTriangleTessellationMeta(p1, p2, p3);
|
|
8
8
|
const { vec3s, longLats, indices } = getAllPoints(triangleMeta, zoomLevel);
|
|
9
9
|
return { vec3s, longLats, indices };
|
|
10
10
|
}
|
|
11
|
+
export function partialTest(bboxZooms, p1, p2, p3) {
|
|
12
|
+
const triangleMeta = createTriangleTessellationMeta(p1, p2, p3);
|
|
13
|
+
return partialTessellation(triangleMeta, bboxZooms, 5);
|
|
14
|
+
}
|