itowns 2.44.3-next.4 → 2.44.3-next.40

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.
Files changed (109) hide show
  1. package/CODING.md +1 -1
  2. package/CONTRIBUTORS.md +1 -0
  3. package/dist/debug.js +1 -1
  4. package/dist/debug.js.map +1 -1
  5. package/dist/itowns.js +1 -1
  6. package/dist/itowns.js.LICENSE.txt +0 -2
  7. package/dist/itowns.js.map +1 -1
  8. package/dist/itowns_widgets.js +1 -1
  9. package/dist/itowns_widgets.js.map +1 -1
  10. package/examples/3dtiles_loader.html +123 -48
  11. package/examples/config.json +3 -10
  12. package/examples/copc_simple_loader.html +15 -5
  13. package/examples/effects_stereo.html +2 -2
  14. package/examples/entwine_3d_loader.html +3 -1
  15. package/examples/entwine_simple_loader.html +1 -1
  16. package/examples/images/itowns_logo.svg +123 -0
  17. package/examples/js/plugins/COGParser.js +1 -1
  18. package/examples/jsm/OGC3DTilesHelper.js +6 -1
  19. package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
  20. package/examples/misc_collada.html +2 -2
  21. package/examples/source_file_geojson_3d.html +0 -1
  22. package/examples/source_file_kml_raster_usgs.html +0 -1
  23. package/examples/source_stream_wfs_raster.html +0 -7
  24. package/examples/vector_tile_mapbox_raster.html +91 -0
  25. package/examples/view_3d_map_webxr.html +3 -1
  26. package/examples/view_multi_25d.html +2 -2
  27. package/lib/Controls/GlobeControls.js +45 -28
  28. package/lib/Controls/StateControl.js +5 -2
  29. package/lib/Converter/Feature2Mesh.js +10 -4
  30. package/lib/Converter/Feature2Texture.js +6 -1
  31. package/lib/Converter/convertToTile.js +3 -8
  32. package/lib/Converter/textureConverter.js +4 -5
  33. package/lib/Core/Deprecated/Undeprecator.js +0 -1
  34. package/lib/Core/Feature.js +3 -4
  35. package/lib/Core/Geographic/Coordinates.js +143 -132
  36. package/lib/Core/Geographic/Crs.js +140 -145
  37. package/lib/Core/Geographic/Extent.js +221 -397
  38. package/lib/Core/Geographic/GeoidGrid.js +1 -1
  39. package/lib/Core/MainLoop.js +1 -3
  40. package/lib/Core/Math/Ellipsoid.js +62 -21
  41. package/lib/Core/Prefab/Globe/Atmosphere.js +4 -8
  42. package/lib/Core/Prefab/Globe/GlobeLayer.js +22 -15
  43. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +111 -0
  44. package/lib/Core/Prefab/GlobeView.js +2 -7
  45. package/lib/Core/Prefab/Planar/PlanarLayer.js +17 -11
  46. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +43 -43
  47. package/lib/Core/Prefab/TileBuilder.js +42 -40
  48. package/lib/Core/Prefab/computeBufferTileGeometry.js +195 -130
  49. package/lib/Core/Scheduler/Cache.js +1 -240
  50. package/lib/Core/Style.js +34 -495
  51. package/lib/Core/StyleOptions.js +486 -0
  52. package/lib/Core/Tile/Tile.js +207 -0
  53. package/lib/Core/Tile/TileGrid.js +49 -0
  54. package/lib/Core/TileGeometry.js +112 -28
  55. package/lib/Core/TileMesh.js +3 -3
  56. package/lib/Core/View.js +15 -8
  57. package/lib/Layer/C3DTilesLayer.js +20 -16
  58. package/lib/Layer/ColorLayer.js +35 -9
  59. package/lib/Layer/CopcLayer.js +7 -2
  60. package/lib/Layer/ElevationLayer.js +39 -7
  61. package/lib/Layer/EntwinePointTileLayer.js +14 -7
  62. package/lib/Layer/FeatureGeometryLayer.js +20 -6
  63. package/lib/Layer/GeometryLayer.js +42 -11
  64. package/lib/Layer/LabelLayer.js +45 -27
  65. package/lib/Layer/Layer.js +92 -61
  66. package/lib/Layer/OGC3DTilesLayer.js +212 -56
  67. package/lib/Layer/OrientedImageLayer.js +11 -5
  68. package/lib/Layer/PointCloudLayer.js +76 -30
  69. package/lib/Layer/Potree2Layer.js +9 -2
  70. package/lib/Layer/PotreeLayer.js +10 -3
  71. package/lib/Layer/RasterLayer.js +12 -2
  72. package/lib/Layer/TiledGeometryLayer.js +69 -13
  73. package/lib/Main.js +2 -2
  74. package/lib/Parser/GeoJsonParser.js +1 -1
  75. package/lib/Parser/VectorTileParser.js +42 -29
  76. package/lib/Parser/XbilParser.js +14 -2
  77. package/lib/Provider/Fetcher.js +5 -1
  78. package/lib/Provider/URLBuilder.js +22 -11
  79. package/lib/Renderer/Camera.js +1 -1
  80. package/lib/Renderer/Label2DRenderer.js +9 -7
  81. package/lib/Renderer/OBB.js +11 -13
  82. package/lib/Renderer/PointsMaterial.js +5 -5
  83. package/lib/Renderer/RasterTile.js +1 -2
  84. package/lib/Renderer/SphereHelper.js +0 -6
  85. package/lib/Source/CopcSource.js +13 -2
  86. package/lib/Source/EntwinePointTileSource.js +14 -4
  87. package/lib/Source/FileSource.js +9 -10
  88. package/lib/Source/OrientedImageSource.js +2 -2
  89. package/lib/Source/Source.js +26 -46
  90. package/lib/Source/TMSSource.js +10 -9
  91. package/lib/Source/VectorTilesSource.js +38 -34
  92. package/lib/Source/WFSSource.js +18 -13
  93. package/lib/Source/WMSSource.js +56 -18
  94. package/lib/Source/WMTSSource.js +13 -7
  95. package/lib/ThreeExtended/libs/ktx-parse.module.js +310 -274
  96. package/lib/ThreeExtended/loaders/DRACOLoader.js +3 -2
  97. package/lib/ThreeExtended/loaders/GLTFLoader.js +6 -3
  98. package/lib/ThreeExtended/loaders/KTX2Loader.js +144 -60
  99. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  100. package/lib/Utils/CameraUtils.js +1 -1
  101. package/lib/Utils/gui/C3DTilesStyle.js +2 -3
  102. package/lib/Utils/placeObjectOnGround.js +0 -1
  103. package/package.json +10 -8
  104. package/examples/3dtiles_25d.html +0 -120
  105. package/examples/3dtiles_basic.html +0 -94
  106. package/examples/3dtiles_batch_table.html +0 -86
  107. package/examples/3dtiles_ion.html +0 -126
  108. package/examples/3dtiles_pointcloud.html +0 -95
  109. package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
package/lib/Core/Style.js CHANGED
@@ -1,16 +1,15 @@
1
- import { FEATURE_TYPES } from "./Feature.js";
2
- import Cache from "./Scheduler/Cache.js";
1
+ import { LRUCache } from 'lru-cache';
3
2
  import Fetcher from "../Provider/Fetcher.js";
4
- import * as mapbox from '@mapbox/mapbox-gl-style-spec';
5
3
  import { Color } from 'three';
6
4
  import { deltaE } from "../Renderer/Color.js";
7
5
  import Coordinates from "./Geographic/Coordinates.js";
8
6
  /* babel-plugin-inline-import './StyleChunk/itowns_stroke_single_before.css' */
9
7
  const itowns_stroke_single_before = ".itowns-stroke-single:before {\n display: var(--text_stroke_display);\n content: attr(data-before);\n opacity: 1;\n position: absolute;\n -webkit-text-stroke-width: var(--text_stroke_width);\n -webkit-text-stroke-color: var(--text_stroke_color);\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: -1;\n white-space: inherit;\n overflow-wrap: inherit;\n letter-spacing: inherit;\n text-align: inherit;\n padding: inherit;\n font-family: inherit;\n text-transform: inherit;\n max-width: inherit;\n font-size: inherit;\n}\n";
10
- const cacheStyle = new Cache();
8
+ const cachedImg = new LRUCache({
9
+ max: 500
10
+ });
11
11
  const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
12
12
  const canvas = document.createElement('canvas');
13
- const inv255 = 1 / 255;
14
13
  function baseAltitudeDefault(properties, ctx) {
15
14
  return ctx?.coordinates?.z || 0;
16
15
  }
@@ -40,74 +39,35 @@ export function readExpression(property, ctx) {
40
39
  }
41
40
  return property;
42
41
  }
43
- function rgba2rgb(orig) {
44
- if (!orig) {
45
- return {};
46
- } else if (orig.stops || orig.expression) {
47
- return {
48
- color: orig
49
- };
50
- } else if (typeof orig == 'string') {
51
- const result = orig.match(/(?:((hsl|rgb)a? *\(([\d.%]+(?:deg|g?rad|turn)?)[ ,]*([\d.%]+)[ ,]*([\d.%]+)[ ,/]*([\d.%]*)\))|(#((?:[\d\w]{3}){1,2})([\d\w]{1,2})?))/i);
52
- if (result === null) {
53
- return {
54
- color: orig,
55
- opacity: 1.0
56
- };
57
- } else if (result[7]) {
58
- let opacity = 1.0;
59
- if (result[9]) {
60
- opacity = parseInt(result[9].length == 1 ? `${result[9]}${result[9]}` : result[9], 16) * inv255;
61
- }
62
- return {
63
- color: `#${result[8]}`,
64
- opacity
65
- };
66
- } else if (result[1]) {
67
- return {
68
- color: `${result[2]}(${result[3]},${result[4]},${result[5]})`,
69
- opacity: result[6] ? Number(result[6]) : 1.0
70
- };
71
- }
72
- }
73
- }
74
- function readVectorProperty(property, options) {
75
- if (property != undefined) {
76
- if (mapbox.expression.isExpression(property)) {
77
- return mapbox.expression.createExpression(property, options).value;
78
- } else {
79
- return property;
80
- }
81
- }
82
- }
83
- async function loadImage(source) {
84
- let promise = cacheStyle.get(source, 'null');
42
+ async function loadImage(url) {
43
+ const imgUrl = url.split('?')[0];
44
+ let promise = cachedImg.get(imgUrl);
85
45
  if (!promise) {
86
- promise = Fetcher.texture(source, {
46
+ promise = Fetcher.texture(url, {
87
47
  crossOrigin: 'anonymous'
88
48
  });
89
- cacheStyle.set(promise, source, 'null');
49
+ cachedImg.set(imgUrl, promise);
90
50
  }
91
51
  return (await promise).image;
92
52
  }
93
- function cropImage(img) {
94
- let cropValues = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
95
- width: img.naturalWidth,
96
- height: img.naturalHeight
97
- };
98
- canvas.width = cropValues.width;
99
- canvas.height = cropValues.height;
53
+ function cropImage(img, cropValues) {
54
+ const x = cropValues.x || 0;
55
+ const y = cropValues.y || 0;
56
+ const width = cropValues.width || img.naturalWidth;
57
+ const height = cropValues.height || img.naturalHeight;
58
+ canvas.width = width;
59
+ canvas.height = height;
100
60
  const ctx = canvas.getContext('2d', {
101
61
  willReadFrequently: true
102
62
  });
103
- ctx.drawImage(img, cropValues.x || 0, cropValues.y || 0, cropValues.width, cropValues.height, 0, 0, cropValues.width, cropValues.height);
104
- return ctx.getImageData(0, 0, cropValues.width, cropValues.height);
63
+ ctx.drawImage(img, x, y, width, height, 0, 0, width, height);
64
+ return ctx.getImageData(0, 0, width, height);
105
65
  }
106
66
  function replaceWhitePxl(imgd, color, id) {
107
67
  if (!color) {
108
68
  return imgd;
109
69
  }
110
- const imgdColored = cacheStyle.get(id, color);
70
+ const imgdColored = cachedImg.get(`${id}_${color}`);
111
71
  if (!imgdColored) {
112
72
  const pix = imgd.data;
113
73
  const newColor = new Color(color);
@@ -118,7 +78,7 @@ function replaceWhitePxl(imgd, color, id) {
118
78
  pix[i + 1] = pix[i + 1] * d + newColor.g * 255 * (1 - d);
119
79
  pix[i + 2] = pix[i + 2] * d + newColor.b * 255 * (1 - d);
120
80
  }
121
- cacheStyle.set(imgd, id, color);
81
+ cachedImg.set(`${id}_${color}`, imgd);
122
82
  return imgd;
123
83
  }
124
84
  return imgdColored;
@@ -166,7 +126,7 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
166
126
  return readExpression(dataValue, style.context);
167
127
  }
168
128
  if (defaultValue instanceof Function) {
169
- return defaultValue(style.context.properties, style.context);
129
+ return defaultValue(style.context.properties, style.context) ?? defaultValue;
170
130
  }
171
131
  return defaultValue;
172
132
  },
@@ -293,153 +253,6 @@ function _addIcon(icon, domElement, opt) {
293
253
  return cIcon;
294
254
  }
295
255
 
296
- /**
297
- * An object that can contain any properties (order, zoom, fill, stroke, point,
298
- * text or/and icon) and sub properties of a Style.<br/>
299
- * Used for the instanciation of a {@link Style}.
300
- *
301
- * @typedef {Object} StyleOptions
302
- *
303
- * @property {Number} [order] - Order of the features that will be associated to
304
- * the style. It can helps sorting and prioritizing features if needed.
305
- *
306
- * @property {Object} [zoom] - Level on which to display the feature
307
- * @property {Number} [zoom.max] - max level
308
- * @property {Number} [zoom.min] - min level
309
- *
310
- * @property {Object} [fill] - Fill style for polygons.
311
- * @property {String|Function|THREE.Color} [fill.color] - Defines the main fill color. Can be
312
- * any [valid color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
313
- * Default is no value, which means no fill.
314
- * If the `Layer` is a `GeometryLayer` you can use `THREE.Color`.
315
- * @property {Image|Canvas|String|Object|Function} [fill.pattern] - Defines a pattern to fill the
316
- * surface with. It can be an `Image` to use directly, an url to fetch the pattern or an object containing
317
- * the url of the image to fetch and the transformation to apply.
318
- * from. See [this example](http://www.itowns-project.org/itowns/examples/#source_file_geojson_raster)
319
- * for how to use.
320
- * @property {Image|String} [fill.pattern.source] - The image or the url to fetch the pattern image
321
- * @property {Object} [fill.pattern.cropValues] - The x, y, width and height (in pixel) of the sub image to use.
322
- * @property {THREE.Color} [fill.pattern.color] - Can be any
323
- * [valid color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
324
- * It will change the color of the white pixels of the source image.
325
- * @property {Number|Function} [fill.opacity] - The opacity of the color or of the
326
- * pattern. Can be between `0.0` and `1.0`. Default is `1.0`.
327
- * For a `GeometryLayer`, this opacity property isn't used.
328
- * @property {Number|Function} [fill.base_altitude] - `GeometryLayer` style option, defines altitude
329
- * for each coordinate.
330
- * If `base_altitude` is `undefined`, the original altitude is kept, and if it doesn't exist
331
- * then the altitude value is set to 0.
332
- * @property {Number|Function} [fill.extrusion_height] - `GeometryLayer` style option, if defined,
333
- * polygons will be extruded by the specified amount
334
- *
335
- * @property {Object} [stroke] - Lines and polygons edges.
336
- * @property {String|Function|THREE.Color} [stroke.color] The color of the line. Can be any [valid
337
- * color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
338
- * Default is no value, which means no stroke.
339
- * If the `Layer` is a `GeometryLayer` you can use `THREE.Color`.
340
- * @property {Number|Function} [stroke.opacity] - The opacity of the line. Can be between
341
- * `0.0` and `1.0`. Default is `1.0`.
342
- * For a `GeometryLayer`, this opacity property isn't used.
343
- * @property {Number|Function} [stroke.width] - The width of the line. Default is `1.0`.
344
- * @property {Number|Function} [stroke.base_altitude] - `GeometryLayer` style option, defines altitude
345
- * for each coordinate.
346
- * If `base_altitude` is `undefined`, the original altitude is kept, and if it doesn't exist
347
- * then the altitude value is set to 0.
348
- *
349
- * @property {Object} [point] - Point style.
350
- * @property {String|Function} [point.color] - The color of the point. Can be any [valid
351
- * color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
352
- * Default is no value, which means points won't be displayed.
353
- * @property {Number|Function} [point.radius] - The radius of the point, in pixel. Default
354
- * is `2.0`.
355
- * @property {String|Function} [point.line] - The color of the border of the point. Can be
356
- * any [valid color
357
- * string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
358
- * Not supported for a `GeometryLayer`.
359
- * @property {Number|Function} [point.width] - The width of the border, in pixel. Default
360
- * is `0.0` (no border).
361
- * @property {Number|Function} [point.opacity] - The opacity of the point. Can be between
362
- * `0.0` and `1.0`. Default is `1.0`.
363
- * Not supported for `GeometryLayer`.
364
- * @property {Number|Function} [point.base_altitude] - `GeometryLayer` style option, defines altitude
365
- * for each coordinate.
366
- * If `base_altitude` is `undefined`, the original altitude is kept, and if it doesn't exist
367
- * then the altitude value is set to 0.
368
- * @property {Object} [point.model] - 3D model to instantiate at each point position.
369
- *
370
- * @property {Object} [text] - All things {@link Label} related. (Supported for Points features, not yet
371
- * for Lines and Polygons features.)
372
- * @property {String|Function} [text.field] - A string representing a property key of
373
- * a `FeatureGeometry` enclosed in brackets, that will be replaced by the value of the
374
- * property for each geometry. For example, if each geometry contains a `name` property,
375
- * `text.field` can be set to `{name}`. Default is no value, indicating that no
376
- * text will be displayed.
377
- *
378
- * It's also possible to create more complex expressions. For example, you can combine
379
- * text that will always be displayed (e.g. `foo`) and variable properties (e.g. `{bar}`)
380
- * like the following: `foo {bar}`. You can also use multiple variables in one field.
381
- * Let's say for instance that you have two properties latin name and local name of a
382
- * place, you can write something like `{name_latin} - {name_local}` which can result
383
- * in `Marrakesh - مراكش` for example.
384
- * @property {String|Function} [text.color] - The color of the text. Can be any [valid
385
- * color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
386
- * Default is `#000000`.
387
- * @property {String|Number[]|Function} [text.anchor] - The anchor of the text compared to its
388
- * position (see {@link Label} for the position). Can be one of the following values: `top`,
389
- * `left`, `bottom`, `right`, `center`, `top-left`, `top-right`, `bottom-left`
390
- * or `bottom-right`. Default is `center`.
391
- *
392
- * It can also be defined as an Array of two numbers. Each number defines an offset (in
393
- * fraction of the label width and height) between the label position and the top-left
394
- * corner of the text. The first value is the horizontal offset, and the second is the
395
- * vertical offset. For example, `[-0.5, -0.5]` will be equivalent to `center`.
396
- * @property {Array|Function} [text.offset] - The offset of the text, depending on its
397
- * anchor, in pixels. First value is from `left`, second is from `top`. Default
398
- * is `[0, 0]`.
399
- * @property {Number|Function} [text.padding] - The padding outside the text, in pixels.
400
- * Default is `2`.
401
- * @property {Number|Function} [text.size] - The size of the font, in pixels. Default is
402
- * `16`.
403
- * @property {Number|Function} [text.wrap] - The maximum width, in pixels, before the text
404
- * is wrapped, because the string is too long. Default is `10`.
405
- * @property {Number|Function} [text.spacing] - The spacing between the letters, in `em`.
406
- * Default is `0`.
407
- * @property {String|Function} [text.transform] - A value corresponding to the [CSS
408
- * property
409
- * `text-transform`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform).
410
- * Default is `none`.
411
- * @property {String|Function} [text.justify] - A value corresponding to the [CSS property
412
- * `text-align`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align).
413
- * Default is `center`.
414
- * @property {Number|Function} [text.opacity] - The opacity of the text. Can be between
415
- * `0.0` and `1.0`. Default is `1.0`.
416
- * @property {Array|Function} [text.font] - A list (as an array of string) of font family
417
- * names, prioritized in the order it is set. Default is `Open Sans Regular,
418
- * Arial Unicode MS Regular, sans-serif`.
419
- * @property {String|Function} [text.haloColor] - The color of the halo. Can be any [valid
420
- * color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
421
- * Default is `#000000`.
422
- * @property {Number|Function} [text.haloWidth] - The width of the halo, in pixels.
423
- * Default is `0`.
424
- * @property {Number|Function} [text.haloBlur] - The blur value of the halo, in pixels.
425
- * Default is `0`.
426
- *
427
- * @property {Object} [icon] - Defines the appearance of icons attached to label.
428
- * @property {String} [icon.source] - The url of the icons' image file.
429
- * @property {String} [icon.id] - The id of the icons' sub-image in a vector tile data set.
430
- * @property {String} [icon.cropValues] - the x, y, width and height (in pixel) of the sub image to use.
431
- * @property {String} [icon.anchor] - The anchor of the icon compared to the label position.
432
- * Can be `left`, `bottom`, `right`, `center`, `top-left`, `top-right`, `bottom-left`
433
- * or `bottom-right`. Default is `center`.
434
- * @property {Number} [icon.size] - If the icon's image is passed with `icon.source` and/or
435
- * `icon.id`, its size when displayed on screen is multiplied by `icon.size`. Default is `1`.
436
- * @property {String|Function} [icon.color] - The color of the icon. Can be any [valid
437
- * color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
438
- * It will change the color of the white pixels of the icon source image.
439
- * @property {Number|Function} [icon.opacity] - The opacity of the icon. Can be between
440
- * `0.0` and `1.0`. Default is `1.0`.
441
- */
442
-
443
256
  /**
444
257
  * A Style is a class that defines the visual appearance of {@link
445
258
  * FeatureCollection} and {@link Feature}. It is taken into account when drawing
@@ -460,8 +273,6 @@ function _addIcon(icon, domElement, opt) {
460
273
  * The first parameter of functions used to set `Style` properties is always an object containing
461
274
  * the properties of the features displayed with the current `Style` instance.
462
275
  *
463
- * @property {Number} order - Order of the features that will be associated to
464
- * the style. It can helps sorting and prioritizing features if needed.
465
276
  * @property {Object} fill - Polygons and fillings style.
466
277
  * @property {String|Function|THREE.Color} fill.color - Defines the main color of the filling. Can be
467
278
  * any [valid color
@@ -611,14 +422,13 @@ function _addIcon(icon, domElement, opt) {
611
422
  class Style {
612
423
  /**
613
424
  * @param {StyleOptions} [params={}] An object that contain any properties
614
- * (order, zoom, fill, stroke, point, text or/and icon)
425
+ * (zoom, fill, stroke, point, text or/and icon)
615
426
  * and sub properties of a Style ({@link StyleOptions}).
616
427
  */
617
428
  constructor() {
618
429
  let params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
619
430
  this.isStyle = true;
620
431
  this.context = new StyleContext();
621
- this.order = params.order || 0;
622
432
  params.zoom = params.zoom || {};
623
433
  params.fill = params.fill || {};
624
434
  params.stroke = params.stroke || {};
@@ -688,280 +498,6 @@ class Style {
688
498
  this.context = ctx;
689
499
  }
690
500
 
691
- /**
692
- * set Style from (geojson-like) properties.
693
- * @param {Object} properties (geojson-like) properties.
694
- * @param {FeatureContext} featCtx the context of the feature
695
- *
696
- * @returns {StyleOptions} containing all properties for itowns.Style
697
- */
698
- static setFromProperties(properties, featCtx) {
699
- const type = featCtx.type;
700
- const style = {};
701
- if (type === FEATURE_TYPES.POINT) {
702
- const point = {
703
- ...(properties.fill !== undefined && {
704
- color: properties.fill
705
- }),
706
- ...(properties['fill-opacity'] !== undefined && {
707
- opacity: properties['fill-opacity']
708
- }),
709
- ...(properties.stroke !== undefined && {
710
- line: properties.stroke
711
- }),
712
- ...(properties.radius !== undefined && {
713
- radius: properties.radius
714
- })
715
- };
716
- if (Object.keys(point).length) {
717
- style.point = point;
718
- }
719
- const text = {
720
- ...(properties['label-color'] !== undefined && {
721
- color: properties['label-color']
722
- }),
723
- ...(properties['label-opacity'] !== undefined && {
724
- opacity: properties['label-opacity']
725
- }),
726
- ...(properties['label-size'] !== undefined && {
727
- size: properties['label-size']
728
- })
729
- };
730
- if (Object.keys(point).length) {
731
- style.text = text;
732
- }
733
- const icon = {
734
- ...(properties.icon !== undefined && {
735
- source: properties.icon
736
- }),
737
- ...(properties['icon-scale'] !== undefined && {
738
- size: properties['icon-scale']
739
- }),
740
- ...(properties['icon-opacity'] !== undefined && {
741
- opacity: properties['icon-opacity']
742
- }),
743
- ...(properties['icon-color'] !== undefined && {
744
- color: properties['icon-color']
745
- })
746
- };
747
- if (Object.keys(icon).length) {
748
- style.icon = icon;
749
- }
750
- } else {
751
- const stroke = {
752
- ...(properties.stroke !== undefined && {
753
- color: properties.stroke
754
- }),
755
- ...(properties['stroke-width'] !== undefined && {
756
- width: properties['stroke-width']
757
- }),
758
- ...(properties['stroke-opacity'] !== undefined && {
759
- opacity: properties['stroke-opacity']
760
- })
761
- };
762
- if (Object.keys(stroke).length) {
763
- style.stroke = stroke;
764
- }
765
- if (type !== FEATURE_TYPES.LINE) {
766
- const fill = {
767
- ...(properties.fill !== undefined && {
768
- color: properties.fill
769
- }),
770
- ...(properties['fill-opacity'] !== undefined && {
771
- opacity: properties['fill-opacity']
772
- })
773
- };
774
- if (Object.keys(fill).length) {
775
- style.fill = fill;
776
- }
777
- }
778
- }
779
- return style;
780
- }
781
-
782
- /**
783
- * set Style from vector tile layer properties.
784
- * @param {Object} layer vector tile layer.
785
- * @param {Object} sprites vector tile layer.
786
- * @param {Number} [order=0]
787
- * @param {Boolean} [symbolToCircle=false]
788
- *
789
- * @returns {StyleOptions} containing all properties for itowns.Style
790
- */
791
- static setFromVectorTileLayer(layer, sprites) {
792
- let order = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
793
- let symbolToCircle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
794
- const style = {
795
- fill: {},
796
- stroke: {},
797
- point: {},
798
- text: {},
799
- icon: {}
800
- };
801
- layer.layout = layer.layout || {};
802
- layer.paint = layer.paint || {};
803
- style.order = order;
804
- if (layer.type === 'fill') {
805
- const {
806
- color,
807
- opacity
808
- } = rgba2rgb(readVectorProperty(layer.paint['fill-color'] || layer.paint['fill-pattern'], {
809
- type: 'color'
810
- }));
811
- style.fill.color = color;
812
- style.fill.opacity = readVectorProperty(layer.paint['fill-opacity']) || opacity;
813
- if (layer.paint['fill-pattern']) {
814
- try {
815
- style.fill.pattern = {
816
- id: layer.paint['fill-pattern'],
817
- source: sprites.source,
818
- cropValues: sprites[layer.paint['fill-pattern']]
819
- };
820
- } catch (err) {
821
- err.message = `VTlayer '${layer.id}': argument sprites must not be null when using layer.paint['fill-pattern']`;
822
- throw err;
823
- }
824
- }
825
- if (layer.paint['fill-outline-color']) {
826
- const {
827
- color,
828
- opacity
829
- } = rgba2rgb(readVectorProperty(layer.paint['fill-outline-color'], {
830
- type: 'color'
831
- }));
832
- style.stroke.color = color;
833
- style.stroke.opacity = opacity;
834
- style.stroke.width = 1.0;
835
- style.stroke.dasharray = [];
836
- }
837
- } else if (layer.type === 'line') {
838
- const prepare = readVectorProperty(layer.paint['line-color'], {
839
- type: 'color'
840
- });
841
- const {
842
- color,
843
- opacity
844
- } = rgba2rgb(prepare);
845
- style.stroke.dasharray = readVectorProperty(layer.paint['line-dasharray']);
846
- style.stroke.color = color;
847
- style.stroke.lineCap = layer.layout['line-cap'];
848
- style.stroke.width = readVectorProperty(layer.paint['line-width']);
849
- style.stroke.opacity = readVectorProperty(layer.paint['line-opacity']) || opacity;
850
- } else if (layer.type === 'circle' || symbolToCircle) {
851
- const {
852
- color,
853
- opacity
854
- } = rgba2rgb(readVectorProperty(layer.paint['circle-color'], {
855
- type: 'color'
856
- }));
857
- style.point.color = color;
858
- style.point.opacity = opacity;
859
- style.point.radius = readVectorProperty(layer.paint['circle-radius']);
860
- } else if (layer.type === 'symbol') {
861
- // overlapping order
862
- style.text.zOrder = readVectorProperty(layer.layout['symbol-z-order']);
863
- if (style.text.zOrder == 'auto') {
864
- style.text.zOrder = readVectorProperty(layer.layout['symbol-sort-key']) || 'Y';
865
- } else if (style.text.zOrder == 'viewport-y') {
866
- style.text.zOrder = 'Y';
867
- } else if (style.text.zOrder == 'source') {
868
- style.text.zOrder = 0;
869
- }
870
-
871
- // position
872
- style.text.anchor = readVectorProperty(layer.layout['text-anchor']);
873
- style.text.offset = readVectorProperty(layer.layout['text-offset']);
874
- style.text.padding = readVectorProperty(layer.layout['text-padding']);
875
- style.text.size = readVectorProperty(layer.layout['text-size']);
876
- style.text.placement = readVectorProperty(layer.layout['symbol-placement']);
877
- style.text.rotation = readVectorProperty(layer.layout['text-rotation-alignment']);
878
-
879
- // content
880
- style.text.field = readVectorProperty(layer.layout['text-field']);
881
- style.text.wrap = readVectorProperty(layer.layout['text-max-width']);
882
- style.text.spacing = readVectorProperty(layer.layout['text-letter-spacing']);
883
- style.text.transform = readVectorProperty(layer.layout['text-transform']);
884
- style.text.justify = readVectorProperty(layer.layout['text-justify']);
885
-
886
- // appearance
887
- const {
888
- color,
889
- opacity
890
- } = rgba2rgb(readVectorProperty(layer.paint['text-color'], {
891
- type: 'color'
892
- }));
893
- style.text.color = color;
894
- style.text.opacity = readVectorProperty(layer.paint['text-opacity']) || opacity !== undefined && opacity;
895
- style.text.font = readVectorProperty(layer.layout['text-font']);
896
- const haloColor = readVectorProperty(layer.paint['text-halo-color'], {
897
- type: 'color'
898
- });
899
- if (haloColor) {
900
- style.text.haloColor = haloColor.color || haloColor;
901
- style.text.haloWidth = readVectorProperty(layer.paint['text-halo-width']);
902
- style.text.haloBlur = readVectorProperty(layer.paint['text-halo-blur']);
903
- }
904
-
905
- // additional icon
906
- const iconImg = readVectorProperty(layer.layout['icon-image']);
907
- if (iconImg) {
908
- try {
909
- style.icon.id = iconImg;
910
- if (iconImg.stops) {
911
- const iconCropValue = {
912
- ...(iconImg.base !== undefined && {
913
- base: iconImg.base
914
- }),
915
- stops: iconImg.stops.map(stop => {
916
- let cropValues = sprites[stop[1]];
917
- if (stop[1].includes('{')) {
918
- cropValues = function (p) {
919
- const id = stop[1].replace(/\{(.+?)\}/g, (a, b) => p[b] || '').trim();
920
- cropValues = sprites[id];
921
- return sprites[id];
922
- };
923
- }
924
- return [stop[0], cropValues];
925
- })
926
- };
927
- style.icon.cropValues = iconCropValue;
928
- } else {
929
- style.icon.cropValues = sprites[iconImg];
930
- if (iconImg[0].includes('{')) {
931
- style.icon.cropValues = function (p) {
932
- const id = iconImg.replace(/\{(.+?)\}/g, (a, b) => p[b] || '').trim();
933
- style.icon.cropValues = sprites[id];
934
- return sprites[id];
935
- };
936
- }
937
- }
938
- style.icon.source = sprites.source;
939
- style.icon.size = readVectorProperty(layer.layout['icon-size']) || 1;
940
- const {
941
- color,
942
- opacity
943
- } = rgba2rgb(readVectorProperty(layer.paint['icon-color'], {
944
- type: 'color'
945
- }));
946
- style.icon.color = color;
947
- style.icon.opacity = readVectorProperty(layer.paint['icon-opacity']) || opacity !== undefined && opacity;
948
- } catch (err) {
949
- err.message = `VTlayer '${layer.id}': argument sprites must not be null when using layer.layout['icon-image']`;
950
- throw err;
951
- }
952
- }
953
- }
954
- // VectorTileSet: by default minZoom = 0 and maxZoom = 24
955
- // https://docs.mapbox.com/style-spec/reference/layers/#maxzoom and #minzoom
956
- // Should be move to layer properties, when (if) one mapBox layer will be considered as several itowns layers.
957
- // issue https://github.com/iTowns/itowns/issues/2153 (last point)
958
- style.zoom = {
959
- min: layer.minzoom || 0,
960
- max: layer.maxzoom || 24
961
- };
962
- return style;
963
- }
964
-
965
501
  /**
966
502
  * Applies the style.fill to a polygon of the texture canvas.
967
503
  * @param {CanvasRenderingContext2D} txtrCtx The Context 2D of the texture canvas.
@@ -970,28 +506,27 @@ class Style {
970
506
  * @param {Boolean} canBeFilled - true if feature.type == FEATURE_TYPES.POLYGON.
971
507
  */
972
508
  applyToCanvasPolygon(txtrCtx, polygon, invCtxScale, canBeFilled) {
973
- const context = this.context;
974
509
  // draw line or edge of polygon
975
- if (this.stroke) {
510
+ if (this.stroke.width > 0) {
976
511
  // TO DO add possibility of using a pattern (https://github.com/iTowns/itowns/issues/2210)
977
- this._applyStrokeToPolygon(txtrCtx, invCtxScale, polygon, context);
512
+ this._applyStrokeToPolygon(txtrCtx, invCtxScale, polygon);
978
513
  }
979
514
 
980
515
  // fill inside of polygon
981
- if (canBeFilled && this.fill) {
516
+ if (canBeFilled && (this.fill.pattern || this.fill.color)) {
982
517
  // canBeFilled can be move to StyleContext in the later PR
983
- this._applyFillToPolygon(txtrCtx, invCtxScale, polygon, context);
518
+ this._applyFillToPolygon(txtrCtx, invCtxScale, polygon);
984
519
  }
985
520
  }
986
521
  _applyStrokeToPolygon(txtrCtx, invCtxScale, polygon) {
987
522
  if (txtrCtx.strokeStyle !== this.stroke.color) {
988
523
  txtrCtx.strokeStyle = this.stroke.color;
989
524
  }
990
- const width = (this.stroke.width || 2.0) * invCtxScale;
525
+ const width = this.stroke.width * invCtxScale;
991
526
  if (txtrCtx.lineWidth !== width) {
992
527
  txtrCtx.lineWidth = width;
993
528
  }
994
- const alpha = this.stroke.opacity == undefined ? 1.0 : this.stroke.opacity;
529
+ const alpha = this.stroke.opacity;
995
530
  if (alpha !== txtrCtx.globalAlpha && typeof alpha == 'number') {
996
531
  txtrCtx.globalAlpha = alpha;
997
532
  }
@@ -1006,7 +541,9 @@ class Style {
1006
541
  // need doc for the txtrCtx.fillStyle.src that seems to always be undefined
1007
542
  if (this.fill.pattern) {
1008
543
  let img = this.fill.pattern;
1009
- const cropValues = this.fill.pattern.cropValues;
544
+ const cropValues = {
545
+ ...this.fill.pattern.cropValues
546
+ };
1010
547
  if (this.fill.pattern.source) {
1011
548
  img = await loadImage(this.fill.pattern.source);
1012
549
  }
@@ -1074,7 +611,9 @@ class Style {
1074
611
  if (!this.icon.cropValues && !this.icon.color) {
1075
612
  icon.src = this.icon.source;
1076
613
  } else {
1077
- const cropValues = this.icon.cropValues;
614
+ const cropValues = {
615
+ ...this.icon.cropValues
616
+ };
1078
617
  const color = this.icon.color;
1079
618
  const id = this.icon.id || this.icon.source;
1080
619
  const img = await loadImage(this.icon.source);