geojs 1.7.1 → 1.8.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/.github/workflows/main.yml +20 -0
- package/CHANGELOG.md +18 -0
- package/geo.js +732 -149
- package/geo.lean.js +731 -148
- package/geo.lean.min.js +3 -3
- package/geo.min.js +5 -5
- package/package.json +18 -16
- package/src/annotation.js +300 -33
- package/src/annotationLayer.js +18 -23
- package/src/event.js +10 -0
- package/src/geojsonReader.js +68 -1
- package/src/layer.js +1 -1
- package/src/map.js +1 -2
- package/src/mapInteractor.js +21 -6
- package/src/markerFeature.js +21 -6
- package/src/tileLayer.js +10 -5
- package/src/trackFeature.js +1 -1
- package/src/ui/colorLegendWidget.js +1 -1
- package/src/ui/scaleWidget.js +1 -1
- package/src/webgl/markerFeature.js +3 -2
- package/src/webgl/webglRenderer.js +4 -3
package/src/geojsonReader.js
CHANGED
|
@@ -31,6 +31,8 @@ var geojsonReader = function (arg) {
|
|
|
31
31
|
|
|
32
32
|
var $ = require('jquery');
|
|
33
33
|
var convertColor = require('./util').convertColor;
|
|
34
|
+
var markerFeature = require('./markerFeature');
|
|
35
|
+
var transform = require('./transform');
|
|
34
36
|
|
|
35
37
|
var m_this = this,
|
|
36
38
|
m_options = {
|
|
@@ -309,6 +311,22 @@ var geojsonReader = function (arg) {
|
|
|
309
311
|
*/
|
|
310
312
|
this.read = function (file, done, progress) {
|
|
311
313
|
var promise = new Promise(function (resolve, reject) {
|
|
314
|
+
/**
|
|
315
|
+
* Check if a feature is a circle or an ellipse.
|
|
316
|
+
*
|
|
317
|
+
* @param {geojson.object} f A geojson feature.
|
|
318
|
+
* @returns {boolean} true if this should be rendered as an ellipse or
|
|
319
|
+
* circle.
|
|
320
|
+
*/
|
|
321
|
+
function _isEllipse(f) {
|
|
322
|
+
if (f.geometry.type !== 'Polygon' || f.geometry.coordinates.length !== 1 || f.geometry.coordinates[0].length !== 5) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
return (
|
|
326
|
+
(f.properties || {}).annotationType === 'ellipse' ||
|
|
327
|
+
(f.properties || {}).annotationType === 'circle');
|
|
328
|
+
}
|
|
329
|
+
|
|
312
330
|
/**
|
|
313
331
|
* Given a parsed GeoJSON object, convert it into features on the
|
|
314
332
|
* reader's layer.
|
|
@@ -384,7 +402,7 @@ var geojsonReader = function (arg) {
|
|
|
384
402
|
}
|
|
385
403
|
|
|
386
404
|
// process polygons
|
|
387
|
-
const polygons = features.filter(f => f.geometry.type === 'Polygon');
|
|
405
|
+
const polygons = features.filter(f => f.geometry.type === 'Polygon' && !_isEllipse(f));
|
|
388
406
|
if (polygons.length) {
|
|
389
407
|
feature = m_this.layer().createFeature('polygon');
|
|
390
408
|
if (feature) {
|
|
@@ -410,6 +428,55 @@ var geojsonReader = function (arg) {
|
|
|
410
428
|
allFeatures.push(feature);
|
|
411
429
|
}
|
|
412
430
|
}
|
|
431
|
+
// handle ellipses and circle
|
|
432
|
+
const ellipses = features.filter(_isEllipse);
|
|
433
|
+
if (ellipses.length) {
|
|
434
|
+
feature = m_this.layer().createFeature('marker');
|
|
435
|
+
if (feature) {
|
|
436
|
+
ellipses.forEach((d) => {
|
|
437
|
+
const map = m_this.layer().map();
|
|
438
|
+
const coord = transform.transformCoordinates(map.ingcs(), map.gcs(), d.geometry.coordinates[0]);
|
|
439
|
+
const w = ((coord[0][0] - coord[1][0]) ** 2 + (coord[0][1] - coord[1][1]) ** 2) ** 0.5;
|
|
440
|
+
const h = ((coord[0][0] - coord[3][0]) ** 2 + (coord[0][1] - coord[3][1]) ** 2) ** 0.5;
|
|
441
|
+
const radius = Math.max(w, h) / 2 / map.unitsPerPixel(0);
|
|
442
|
+
const aspect = w ? h / w : 1e20;
|
|
443
|
+
const rotation = -Math.atan2(coord[1][1] - coord[0][1], coord[1][0] - coord[0][0]);
|
|
444
|
+
const pos = transform.transformCoordinates(map.gcs(), map.ingcs(), {
|
|
445
|
+
x: (coord[0][0] + coord[1][0] + coord[2][0] + coord[3][0]) / 4,
|
|
446
|
+
y: (coord[0][1] + coord[1][1] + coord[2][1] + coord[3][1]) / 4
|
|
447
|
+
});
|
|
448
|
+
d._props = {
|
|
449
|
+
pos: pos,
|
|
450
|
+
radius: radius,
|
|
451
|
+
aspect: aspect,
|
|
452
|
+
rotation: rotation
|
|
453
|
+
};
|
|
454
|
+
});
|
|
455
|
+
feature
|
|
456
|
+
.data(ellipses)
|
|
457
|
+
.position((d) => d._props.pos)
|
|
458
|
+
// create an object with each property in m_options.polygonStyle,
|
|
459
|
+
// mapping the values through the _style function.
|
|
460
|
+
.style(
|
|
461
|
+
[{}].concat(Object.keys(m_options.polygonStyle)).reduce(
|
|
462
|
+
(styleObj, key) => ({
|
|
463
|
+
[key]: ellipses.some(d => d.properties && d.properties[key] !== undefined) ?
|
|
464
|
+
m_this._style(key, m_options.polygonStyle[key]) :
|
|
465
|
+
m_options.polygonStyle[key],
|
|
466
|
+
radius: (d) => d._props.radius,
|
|
467
|
+
radiusIncludesStroke: false,
|
|
468
|
+
symbolValue: (d) => d._props.aspect,
|
|
469
|
+
rotation: (d) => d._props.rotation,
|
|
470
|
+
strokeOffset: 0,
|
|
471
|
+
rotateWithMap: true,
|
|
472
|
+
scaleWithZoom: markerFeature.scaleMode.fill,
|
|
473
|
+
...styleObj
|
|
474
|
+
}
|
|
475
|
+
))
|
|
476
|
+
);
|
|
477
|
+
allFeatures.push(feature);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
413
480
|
if (done) {
|
|
414
481
|
done(allFeatures);
|
|
415
482
|
}
|
package/src/layer.js
CHANGED
package/src/map.js
CHANGED
|
@@ -569,8 +569,7 @@ var map = function (arg) {
|
|
|
569
569
|
};
|
|
570
570
|
|
|
571
571
|
/**
|
|
572
|
-
*
|
|
573
|
-
* current center. Uses bare objects {x: 0, y: 0}.
|
|
572
|
+
* Get or set the center of the map in the given geographic coordinates.
|
|
574
573
|
*
|
|
575
574
|
* @param {geo.geoPosition} coordinates If specified, the new center of the
|
|
576
575
|
* map.
|
package/src/mapInteractor.js
CHANGED
|
@@ -181,6 +181,11 @@ var mapInteractor = function (args) {
|
|
|
181
181
|
* selectionRectangle: truthy if a selection rectangle should be shown
|
|
182
182
|
* during the action. This can be the name of an event that will be
|
|
183
183
|
* triggered when the selection is complete.
|
|
184
|
+
* selectionConstraint: if a function and a selection rectangle is being
|
|
185
|
+
* drawn, this is a function that takes (mousexy, originxy, state)
|
|
186
|
+
* with the coordinates objects with x, y in display coordinates.
|
|
187
|
+
* The function returns a modified x, y for the mouse coordinates, or
|
|
188
|
+
* undefined for no change.
|
|
184
189
|
* name: a string that can be used to reference this action.
|
|
185
190
|
* owner: a string that can be used to reference this action.
|
|
186
191
|
*/
|
|
@@ -781,7 +786,7 @@ var mapInteractor = function (args) {
|
|
|
781
786
|
};
|
|
782
787
|
|
|
783
788
|
/**
|
|
784
|
-
*
|
|
789
|
+
* Get or set the map for this interactor, adds draw region layer if needed.
|
|
785
790
|
*
|
|
786
791
|
* @param {geo.map} [val] Either a new map object for `undefined` to return
|
|
787
792
|
* the current map object.
|
|
@@ -912,16 +917,26 @@ var mapInteractor = function (args) {
|
|
|
912
917
|
map = m_this.map(),
|
|
913
918
|
display = {}, gcs = {};
|
|
914
919
|
|
|
915
|
-
|
|
920
|
+
let mousexy = mouse.map;
|
|
921
|
+
if (m_state.actionRecord && util.isFunction(m_state.actionRecord.selectionConstraint)) {
|
|
922
|
+
const constraint = m_state.actionRecord.selectionConstraint(mouse.mapgcs, origin.mapgcs);
|
|
923
|
+
mousexy = constraint ? map.gcsToDisplay(constraint.pos, null) : mousexy;
|
|
924
|
+
} else if (mouse.modifiers.shift) {
|
|
925
|
+
const width = Math.abs((mousexy.x - origin.map.x) * (mousexy.y - origin.map.y)) ** 0.5;
|
|
926
|
+
mousexy = {
|
|
927
|
+
x: origin.map.x + Math.sign(mousexy.x - origin.map.x) * width,
|
|
928
|
+
y: origin.map.y + Math.sign(mousexy.y - origin.map.y) * width
|
|
929
|
+
};
|
|
930
|
+
}
|
|
916
931
|
// Get the display coordinates
|
|
917
932
|
display.upperLeft = {
|
|
918
|
-
x: Math.min(origin.map.x,
|
|
919
|
-
y: Math.min(origin.map.y,
|
|
933
|
+
x: Math.min(origin.map.x, mousexy.x),
|
|
934
|
+
y: Math.min(origin.map.y, mousexy.y)
|
|
920
935
|
};
|
|
921
936
|
|
|
922
937
|
display.lowerRight = {
|
|
923
|
-
x: Math.max(origin.map.x,
|
|
924
|
-
y: Math.max(origin.map.y,
|
|
938
|
+
x: Math.max(origin.map.x, mousexy.x),
|
|
939
|
+
y: Math.max(origin.map.y, mousexy.y)
|
|
925
940
|
};
|
|
926
941
|
|
|
927
942
|
display.upperRight = {
|
package/src/markerFeature.js
CHANGED
|
@@ -21,7 +21,8 @@ var pointFeature = require('./pointFeature');
|
|
|
21
21
|
* @property {number|function} [radius=5] Radius of each marker in pixels.
|
|
22
22
|
* This includes the stroke width if `strokeOffset` is -1, excludes it if
|
|
23
23
|
* `strokeOffset` is 1, and includes half the stroke width if `strokeOffset`
|
|
24
|
-
* is 0.
|
|
24
|
+
* is 0. Note that is `radiusIncludesStroke` is `false`, this never
|
|
25
|
+
* includes the stroke width.
|
|
25
26
|
* @property {geo.geoColor|function} [strokeColor] Color to stroke each marker.
|
|
26
27
|
* @property {number|function} [strokeOpacity=1] Opacity for each marker's
|
|
27
28
|
* stroke. Opacity is on a [0-1] scale. Set this or `strokeWidth` to zero
|
|
@@ -32,6 +33,10 @@ var pointFeature = require('./pointFeature');
|
|
|
32
33
|
* @property {number|function} [strokeOffset=-1] The position of the stroke
|
|
33
34
|
* compared to the radius. This can only be -1, 0, or 1 (the sign of the
|
|
34
35
|
* value is used).
|
|
36
|
+
* @property {boolean|function} [radiusIncludeStroke=true] If truthy or
|
|
37
|
+
* undefined, the `radius` includes the `strokeWidth` based on the
|
|
38
|
+
* `strokeOffset`. If defined and falsy, the radius does not include the
|
|
39
|
+
* `strokeWidth`.
|
|
35
40
|
* @property {geo.geoColor|function} [fillColor] Color to fill each marker.
|
|
36
41
|
* @property {number|function} [fillOpacity=1] Opacity for each marker.
|
|
37
42
|
* Opacity is on a [0-1] scale. Set to zero to have no fill.
|
|
@@ -47,7 +52,7 @@ var pointFeature = require('./pointFeature');
|
|
|
47
52
|
* @property {boolean|function} [rotateWithMap=false] If truthy, rotate symbols
|
|
48
53
|
* with the map. If falsy, symbol orientation is absolute.
|
|
49
54
|
* @property {number[]|function} [origin] Origin in map gcs coordinates used
|
|
50
|
-
*
|
|
55
|
+
* to ensure high precision drawing in this location. When called as a
|
|
51
56
|
* function, this is passed the maker positions as a single continuous array
|
|
52
57
|
* in map gcs coordinates. It defaults to the first marker's position.
|
|
53
58
|
*/
|
|
@@ -98,6 +103,7 @@ var markerFeature = function (arg) {
|
|
|
98
103
|
var pts, position,
|
|
99
104
|
radius = m_this.style.get('radius'),
|
|
100
105
|
strokeWidth = m_this.style.get('strokeWidth'),
|
|
106
|
+
radiusIncludesStroke = m_this.style.get('radiusIncludesStroke'),
|
|
101
107
|
strokeOffset = m_this.style.get('strokeOffset'),
|
|
102
108
|
scaleWithZoom = m_this.style.get('scaleWithZoom');
|
|
103
109
|
|
|
@@ -115,8 +121,10 @@ var markerFeature = function (arg) {
|
|
|
115
121
|
const r = radius(d, i),
|
|
116
122
|
s = strokeWidth(d, i),
|
|
117
123
|
so = Math.sign(strokeOffset(d, i));
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
let ris = radiusIncludesStroke(d, i);
|
|
125
|
+
ris = ris === undefined ? true : ris;
|
|
126
|
+
const rwiths = ris ? r + s * (so + 1) / 2 : r + s, // radius with stroke
|
|
127
|
+
rwos = ris ? r + s * (so - 1) / 2 : r; // radius without stroke
|
|
120
128
|
swz = markerFeature.scaleMode[swz] || (swz >= 1 && swz <= 3 ? swz : 0);
|
|
121
129
|
switch (swz) {
|
|
122
130
|
case markerFeature.scaleMode.stroke:
|
|
@@ -174,6 +182,7 @@ var markerFeature = function (arg) {
|
|
|
174
182
|
corners,
|
|
175
183
|
radius = m_this.style.get('radius'),
|
|
176
184
|
strokeWidth = m_this.style.get('strokeWidth'),
|
|
185
|
+
radiusIncludesStroke = m_this.style.get('radiusIncludesStroke'),
|
|
177
186
|
strokeOffset = m_this.style.get('strokeOffset'),
|
|
178
187
|
scaleWithZoom = m_this.style.get('scaleWithZoom');
|
|
179
188
|
|
|
@@ -223,7 +232,9 @@ var markerFeature = function (arg) {
|
|
|
223
232
|
swz = scaleWithZoom(data[i], i),
|
|
224
233
|
so = strokeOffset(data[i], i),
|
|
225
234
|
s = swz ? strokeWidth(data[i], i) : 0;
|
|
226
|
-
|
|
235
|
+
let ris = radiusIncludesStroke(d, i);
|
|
236
|
+
ris = ris === undefined ? true : ris;
|
|
237
|
+
var rwos = ris ? rad + s * (so - 1) / 2 : rad; // radius without stroke
|
|
227
238
|
rad = rwos + s;
|
|
228
239
|
var p = m_this.position()(d, i),
|
|
229
240
|
dx, dy, rad2;
|
|
@@ -287,6 +298,7 @@ var markerFeature = function (arg) {
|
|
|
287
298
|
data = m_this.data(),
|
|
288
299
|
radius = m_this.style.get('radius'),
|
|
289
300
|
strokeWidth = m_this.style.get('strokeWidth'),
|
|
301
|
+
radiusIncludesStroke = m_this.style.get('radiusIncludesStroke'),
|
|
290
302
|
strokeOffset = m_this.style.get('strokeOffset'),
|
|
291
303
|
scaleWithZoom = m_this.style.get('scaleWithZoom'),
|
|
292
304
|
idx, min, max, corners,
|
|
@@ -347,7 +359,9 @@ var markerFeature = function (arg) {
|
|
|
347
359
|
swz = scaleWithZoom(data[i], i);
|
|
348
360
|
const so = strokeOffset(data[i], i),
|
|
349
361
|
s = swz ? strokeWidth(data[i], i) : 0;
|
|
350
|
-
|
|
362
|
+
let ris = radiusIncludesStroke(d, i);
|
|
363
|
+
ris = ris === undefined ? true : ris;
|
|
364
|
+
const rwos = ris ? rad + s * (so - 1) / 2 : rad; // radius without stroke
|
|
351
365
|
swz = markerFeature.scaleMode[swz] || (swz >= 1 && swz <= 3 ? swz : 0);
|
|
352
366
|
rad = rwos + s;
|
|
353
367
|
switch (swz) {
|
|
@@ -393,6 +407,7 @@ var markerFeature = function (arg) {
|
|
|
393
407
|
{},
|
|
394
408
|
{
|
|
395
409
|
radius: 6.25,
|
|
410
|
+
radiusIncludesStroke: true,
|
|
396
411
|
strokeColor: { r: 0.851, g: 0.604, b: 0.0 },
|
|
397
412
|
strokeOffset: -1.0,
|
|
398
413
|
strokeOpacity: 1.0,
|
package/src/tileLayer.js
CHANGED
|
@@ -676,7 +676,10 @@ var tileLayer = function (arg) {
|
|
|
676
676
|
this._getTiles = function (maxLevel, bounds, sorted, onlyIfChanged) {
|
|
677
677
|
var i, j, tiles = [], index, nTilesLevel,
|
|
678
678
|
start, end, indexRange, source, center, changed = false, old, level,
|
|
679
|
-
minLevel = (
|
|
679
|
+
minLevel = (
|
|
680
|
+
m_this._options.keepLower ?
|
|
681
|
+
m_this._options.minLevel :
|
|
682
|
+
Math.min(Math.max(maxLevel, m_this._options.minLevel), m_this._options.maxLevel));
|
|
680
683
|
if (maxLevel < minLevel) {
|
|
681
684
|
maxLevel = minLevel;
|
|
682
685
|
}
|
|
@@ -1533,7 +1536,9 @@ var tileLayer = function (arg) {
|
|
|
1533
1536
|
* semi-transparent layers. */
|
|
1534
1537
|
if ((doneLoading || m_this._isCovered(tile)) &&
|
|
1535
1538
|
zoom !== tile.index.level &&
|
|
1536
|
-
(zoom >= m_this._options.minLevel || tile.index.level !== m_this._options.minLevel)
|
|
1539
|
+
(zoom >= m_this._options.minLevel || tile.index.level !== m_this._options.minLevel) &&
|
|
1540
|
+
(zoom < m_this._options.maxLevel || tile.index.level !== m_this._options.maxLevel)
|
|
1541
|
+
) {
|
|
1537
1542
|
return true;
|
|
1538
1543
|
}
|
|
1539
1544
|
}
|
|
@@ -1667,9 +1672,9 @@ var tileLayer = function (arg) {
|
|
|
1667
1672
|
/**
|
|
1668
1673
|
* Get/set the baseQuad.
|
|
1669
1674
|
*
|
|
1670
|
-
* @property {object} [baseQuad] A quad feature element to draw
|
|
1671
|
-
*
|
|
1672
|
-
*
|
|
1675
|
+
* @property {object} [baseQuad] A quad feature element to draw below any
|
|
1676
|
+
* tile layers. If specified, this uses the quad defaults, so this is a
|
|
1677
|
+
* ``geo.quadFeature.position`` object with, typically, an ``image``
|
|
1673
1678
|
* property added to it. The quad positions are in the map gcs
|
|
1674
1679
|
* coordinates.
|
|
1675
1680
|
* @name geo.tileLayer.baseQuad
|
package/src/trackFeature.js
CHANGED
|
@@ -451,7 +451,7 @@ var trackFeature = function (arg) {
|
|
|
451
451
|
};
|
|
452
452
|
|
|
453
453
|
/**
|
|
454
|
-
*
|
|
454
|
+
* Get or set style.
|
|
455
455
|
*
|
|
456
456
|
* @param {string|object} [arg1] If `undefined`, return the current style
|
|
457
457
|
* object. If a string and `arg2` is undefined, return the style
|
|
@@ -125,7 +125,7 @@ var colorLegendWidget = function (arg) {
|
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
*
|
|
128
|
+
* Get or set categories.
|
|
129
129
|
* @param {geo.gui.colorLegendWidget.category[]} [categories] If `undefined`,
|
|
130
130
|
* return the current legend categories array. If an array is provided,
|
|
131
131
|
* remove current legends and recreate with the new categories.
|
package/src/ui/scaleWidget.js
CHANGED
|
@@ -298,7 +298,7 @@ var scaleWidget = function (arg) {
|
|
|
298
298
|
};
|
|
299
299
|
|
|
300
300
|
/**
|
|
301
|
-
*
|
|
301
|
+
* Get or set options.
|
|
302
302
|
*
|
|
303
303
|
* @param {string|object} [arg1] If `undefined`, return the options object.
|
|
304
304
|
* If a string, either set or return the option of that name. If an
|
|
@@ -120,7 +120,8 @@ var webgl_markerFeature = function (arg) {
|
|
|
120
120
|
symbolValue: 1,
|
|
121
121
|
rotation: 1,
|
|
122
122
|
scaleWithZoom: 0,
|
|
123
|
-
rotateWithMap: 0
|
|
123
|
+
rotateWithMap: 0,
|
|
124
|
+
radiusIncludesStroke: 0
|
|
124
125
|
},
|
|
125
126
|
vpf = m_this.verticesPerFeature(),
|
|
126
127
|
data = m_this.data(),
|
|
@@ -191,7 +192,7 @@ var webgl_markerFeature = function (arg) {
|
|
|
191
192
|
styleVal.scaleWithZoom +
|
|
192
193
|
(styleVal.rotateWithMap ? 4 : 0) +
|
|
193
194
|
// bit 3 reserved
|
|
194
|
-
((Math.sign(styleVal.strokeOffset) + 1) * 16) +
|
|
195
|
+
((Math.sign(styleVal.radiusIncludesStroke !== undefined && styleVal.radiusIncludesStroke ? styleVal.strokeOffset : 1) + 1) * 16) +
|
|
195
196
|
styleVal.symbol * 64);
|
|
196
197
|
if (styleVal.symbolValue && styleVal.symbol >= markerFeature.symbols.arrow && styleVal.symbol < markerFeature.symbols.arrow + markerFeature.symbols.arrowMax) {
|
|
197
198
|
styleVal.symbolValue = packFloats(styleVal.symbolValue);
|
|
@@ -184,11 +184,12 @@ var webglRenderer = function (arg) {
|
|
|
184
184
|
renderState.m_renderer = m_viewer;
|
|
185
185
|
renderState.m_context = m_this._glContext();
|
|
186
186
|
m_viewer.exit(renderState);
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
const context = m_this._glContext();
|
|
188
|
+
if (context !== vgl.GL && context.getExtension('WEBGL_lose_context') && context.getExtension('WEBGL_lose_context').loseContext) {
|
|
189
|
+
context.getExtension('WEBGL_lose_context').loseContext();
|
|
189
190
|
}
|
|
190
191
|
}
|
|
191
|
-
// make sure we clear shaders associated with the
|
|
192
|
+
// make sure we clear shaders associated with the generated context, too
|
|
192
193
|
vgl.clearCachedShaders(vgl.GL);
|
|
193
194
|
m_viewer = null;
|
|
194
195
|
s_exit();
|