@antv/l7-layers 2.23.2 → 2.23.3-beta.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.
Files changed (73) hide show
  1. package/es/{citybuliding → citybuilding}/models/build.js +4 -2
  2. package/es/core/BaseLayer.js +3 -3
  3. package/es/core/LayerPickService.js +3 -1
  4. package/es/core/shape/Path.d.ts +2 -1
  5. package/es/core/shape/Path.js +10 -4
  6. package/es/core/triangulation.js +51 -1
  7. package/es/earth/index.js +2 -3
  8. package/es/geometry/index.js +2 -3
  9. package/es/heatmap/index.js +6 -6
  10. package/es/heatmap/models/heatmap.js +2 -3
  11. package/es/index.d.ts +1 -1
  12. package/es/index.js +1 -1
  13. package/es/line/index.js +2 -3
  14. package/es/plugins/DataMappingPlugin.js +30 -10
  15. package/es/plugins/FeatureScalePlugin.js +21 -20
  16. package/es/plugins/ShaderUniformPlugin.js +62 -29
  17. package/es/plugins/index.d.ts +1 -1
  18. package/es/polygon/index.js +2 -3
  19. package/es/polygon/models/extrude.js +22 -7
  20. package/es/polygon/models/ocean.js +17 -6
  21. package/es/polygon/models/water.js +17 -6
  22. package/es/tile/core/BaseLayer.d.ts +4 -1
  23. package/es/tile/core/BaseLayer.js +19 -11
  24. package/es/tile/service/TileLayerService.d.ts +26 -1
  25. package/es/tile/service/TileLayerService.js +88 -16
  26. package/es/tile/service/TilePickService.js +15 -9
  27. package/es/tile/tile/Tile.d.ts +1 -1
  28. package/es/tile/tile/index.d.ts +1 -1
  29. package/es/tile/tile/util.d.ts +1 -1
  30. package/es/utils/scale.d.ts +87 -0
  31. package/es/utils/scale.js +588 -0
  32. package/lib/{citybuliding → citybuilding}/models/build.js +4 -2
  33. package/lib/core/BaseLayer.js +3 -3
  34. package/lib/core/LayerPickService.js +3 -1
  35. package/lib/core/shape/Path.d.ts +2 -1
  36. package/lib/core/shape/Path.js +10 -4
  37. package/lib/core/triangulation.js +50 -1
  38. package/lib/earth/index.js +2 -3
  39. package/lib/geometry/index.js +2 -3
  40. package/lib/heatmap/index.js +6 -6
  41. package/lib/heatmap/models/heatmap.js +2 -3
  42. package/lib/index.d.ts +1 -1
  43. package/lib/index.js +1 -1
  44. package/lib/line/index.js +2 -3
  45. package/lib/plugins/DataMappingPlugin.js +30 -10
  46. package/lib/plugins/FeatureScalePlugin.js +22 -23
  47. package/lib/plugins/ShaderUniformPlugin.js +62 -29
  48. package/lib/plugins/index.d.ts +1 -1
  49. package/lib/polygon/index.js +2 -3
  50. package/lib/polygon/models/extrude.js +22 -7
  51. package/lib/polygon/models/ocean.js +17 -6
  52. package/lib/polygon/models/water.js +17 -6
  53. package/lib/tile/core/BaseLayer.d.ts +4 -1
  54. package/lib/tile/core/BaseLayer.js +19 -11
  55. package/lib/tile/service/TileLayerService.d.ts +26 -1
  56. package/lib/tile/service/TileLayerService.js +88 -16
  57. package/lib/tile/service/TilePickService.js +15 -9
  58. package/lib/tile/tile/Tile.d.ts +1 -1
  59. package/lib/tile/tile/index.d.ts +1 -1
  60. package/lib/tile/tile/util.d.ts +1 -1
  61. package/lib/utils/scale.d.ts +87 -0
  62. package/lib/utils/scale.js +603 -0
  63. package/package.json +6 -17
  64. /package/es/{citybuliding → citybuilding}/building.d.ts +0 -0
  65. /package/es/{citybuliding → citybuilding}/building.js +0 -0
  66. /package/es/{citybuliding → citybuilding}/models/build.d.ts +0 -0
  67. /package/es/{citybuliding → citybuilding}/shaders/build_frag.glsl +0 -0
  68. /package/es/{citybuliding → citybuilding}/shaders/build_vert.glsl +0 -0
  69. /package/lib/{citybuliding → citybuilding}/building.d.ts +0 -0
  70. /package/lib/{citybuliding → citybuilding}/building.js +0 -0
  71. /package/lib/{citybuliding → citybuilding}/models/build.d.ts +0 -0
  72. /package/lib/{citybuliding → citybuilding}/shaders/build_frag.glsl +0 -0
  73. /package/lib/{citybuliding → citybuilding}/shaders/build_vert.glsl +0 -0
@@ -35,6 +35,55 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
35
35
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
36
36
  // @ts-ignore
37
37
 
38
+ /**
39
+ * 质心计算缓存
40
+ * 避免对相同坐标的重复计算
41
+ */
42
+
43
+ const centroidCache = {};
44
+ const CENTROID_CACHE_MAX_SIZE = 500;
45
+
46
+ /**
47
+ * 生成坐标的缓存键
48
+ */
49
+ function getCoordinateKey(coordinates) {
50
+ if (typeof coordinates === 'number') {
51
+ return String(coordinates);
52
+ }
53
+ if (Array.isArray(coordinates)) {
54
+ if (typeof coordinates[0] === 'number') {
55
+ return coordinates.slice(0, 2).join(',');
56
+ }
57
+ // 对于嵌套数组,取第一个点
58
+ return getCoordinateKey(coordinates[0]);
59
+ }
60
+ return '';
61
+ }
62
+
63
+ /**
64
+ * 带缓存的质心计算
65
+ */
66
+ function cachedCalculateCentroid(coordinates) {
67
+ const key = getCoordinateKey(coordinates);
68
+ if (key && centroidCache[key]) {
69
+ return centroidCache[key].slice();
70
+ }
71
+ const centroid = (0, _l7Utils.calculateCentroid)(coordinates);
72
+
73
+ // 限制缓存大小
74
+ const keys = Object.keys(centroidCache);
75
+ if (keys.length >= CENTROID_CACHE_MAX_SIZE) {
76
+ // 删除一半的缓存
77
+ const deleteCount = Math.floor(CENTROID_CACHE_MAX_SIZE / 2);
78
+ for (let i = 0; i < deleteCount; i++) {
79
+ delete centroidCache[keys[i]];
80
+ }
81
+ }
82
+ if (key) {
83
+ centroidCache[key] = centroid.slice();
84
+ }
85
+ return centroid;
86
+ }
38
87
  const GeometryCache = {};
39
88
 
40
89
  /**
@@ -43,7 +92,7 @@ const GeometryCache = {};
43
92
  */
44
93
 
45
94
  function PointFillTriangulation(feature) {
46
- const coordinates = (0, _l7Utils.calculateCentroid)(feature.coordinates);
95
+ const coordinates = cachedCalculateCentroid(feature.coordinates);
47
96
  return {
48
97
  vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates],
49
98
  indices: [0, 1, 2, 2, 3, 0],
@@ -51,9 +51,8 @@ class EarthLayer extends _BaseLayer.default {
51
51
  }
52
52
  }
53
53
  getModelType() {
54
- var _shapeAttribute$scale;
55
- const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute('shape');
56
- let shape = (shapeAttribute === null || shapeAttribute === void 0 || (_shapeAttribute$scale = shapeAttribute.scale) === null || _shapeAttribute$scale === void 0 ? void 0 : _shapeAttribute$scale.field) || 'base';
54
+ var _this$shapeOption;
55
+ let shape = ((_this$shapeOption = this.shapeOption) === null || _this$shapeOption === void 0 ? void 0 : _this$shapeOption.field) || 'base';
57
56
  if (earthLayerTypes.indexOf(shape) < 0) {
58
57
  shape = 'base';
59
58
  }
@@ -45,9 +45,8 @@ class GeometryLayer extends _BaseLayer.default {
45
45
  return defaultConfig[type];
46
46
  }
47
47
  getModelType() {
48
- var _shapeAttribute$scale;
49
- const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute('shape');
50
- const shape = shapeAttribute === null || shapeAttribute === void 0 || (_shapeAttribute$scale = shapeAttribute.scale) === null || _shapeAttribute$scale === void 0 ? void 0 : _shapeAttribute$scale.field;
48
+ var _this$shapeOption;
49
+ const shape = (_this$shapeOption = this.shapeOption) === null || _this$shapeOption === void 0 ? void 0 : _this$shapeOption.field;
51
50
  if (shape === 'plane') {
52
51
  return 'plane';
53
52
  } else if (shape === 'sprite') {
@@ -59,22 +59,22 @@ class HeatMapLayer extends _BaseLayer.default {
59
59
  }
60
60
  }
61
61
  getModelType() {
62
- var _shapeAttribute$scale;
63
- const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute('shape');
62
+ var _source$data, _this$shapeOption;
64
63
  const {
65
64
  shape3d
66
65
  } = this.getLayerConfig();
67
66
  const source = this.getSource();
68
- const sourceType = source.data.type;
69
- const shape = (shapeAttribute === null || shapeAttribute === void 0 || (_shapeAttribute$scale = shapeAttribute.scale) === null || _shapeAttribute$scale === void 0 ? void 0 : _shapeAttribute$scale.field) || 'heatmap';
67
+ const sourceType = source === null || source === void 0 || (_source$data = source.data) === null || _source$data === void 0 ? void 0 : _source$data.type;
68
+ const shape = ((_this$shapeOption = this.shapeOption) === null || _this$shapeOption === void 0 ? void 0 : _this$shapeOption.field) || 'heatmap';
69
+ const isShape3D = Array.isArray(shape3d) && shape3d.includes(shape);
70
70
  if (shape === 'heatmap' || shape === 'heatmap3d') {
71
71
  return 'heatmap';
72
72
  }
73
73
  if (sourceType === 'hexagon') {
74
- return (shape3d === null || shape3d === void 0 ? void 0 : shape3d.indexOf(shape)) === -1 ? 'hexagon' : 'grid3d';
74
+ return isShape3D ? 'grid3d' : 'hexagon';
75
75
  }
76
76
  if (sourceType === 'grid') {
77
- return (shape3d === null || shape3d === void 0 ? void 0 : shape3d.indexOf(shape)) === -1 ? 'grid' : 'grid3d';
77
+ return isShape3D ? 'grid3d' : 'grid';
78
78
  }
79
79
  return 'heatmap';
80
80
  }
@@ -82,14 +82,13 @@ class HeatMapModel extends _BaseModel.default {
82
82
  initModels() {
83
83
  var _this = this;
84
84
  return (0, _asyncToGenerator2.default)(function* () {
85
- var _shapeAttr$scale;
85
+ var _this$layer$shapeOpti;
86
86
  const {
87
87
  createFramebuffer,
88
88
  getViewportSize,
89
89
  createTexture2D
90
90
  } = _this.rendererService;
91
- const shapeAttr = _this.styleAttributeService.getLayerStyleAttribute('shape');
92
- const shapeType = (shapeAttr === null || shapeAttr === void 0 || (_shapeAttr$scale = shapeAttr.scale) === null || _shapeAttr$scale === void 0 ? void 0 : _shapeAttr$scale.field) || 'heatmap';
91
+ const shapeType = ((_this$layer$shapeOpti = _this.layer.shapeOption) === null || _this$layer$shapeOpti === void 0 ? void 0 : _this$layer$shapeOpti.field) || 'heatmap';
93
92
  _this.shapeType = shapeType;
94
93
  // 生成热力图密度图
95
94
  _this.intensityModel = yield _this.buildHeatMapIntensity();
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import CanvasLayer from './canvas';
2
- import CityBuildingLayer from './citybuliding/building';
2
+ import CityBuildingLayer from './citybuilding/building';
3
3
  import BaseLayer from './core/BaseLayer';
4
4
  import BaseModel from './core/BaseModel';
5
5
  import GeometryLayer from './geometry';
package/lib/index.js CHANGED
@@ -119,7 +119,7 @@ Object.defineProperty(exports, "WindLayer", {
119
119
  }
120
120
  });
121
121
  var _canvas = _interopRequireDefault(require("./canvas"));
122
- var _building = _interopRequireDefault(require("./citybuliding/building"));
122
+ var _building = _interopRequireDefault(require("./citybuilding/building"));
123
123
  var _BaseLayer = _interopRequireDefault(require("./core/BaseLayer"));
124
124
  var _BaseModel = _interopRequireDefault(require("./core/BaseModel"));
125
125
  var _geometry = _interopRequireDefault(require("./geometry"));
package/lib/line/index.js CHANGED
@@ -67,12 +67,11 @@ class LineLayer extends _BaseLayer.default {
67
67
  return defaultConfig[type];
68
68
  }
69
69
  getModelType() {
70
- var _shapeAttribute$scale;
70
+ var _this$shapeOption;
71
71
  if (this.layerType) {
72
72
  return this.layerType;
73
73
  }
74
- const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute('shape');
75
- const shape = shapeAttribute === null || shapeAttribute === void 0 || (_shapeAttribute$scale = shapeAttribute.scale) === null || _shapeAttribute$scale === void 0 ? void 0 : _shapeAttribute$scale.field;
74
+ const shape = (_this$shapeOption = this.shapeOption) === null || _this$shapeOption === void 0 ? void 0 : _this$shapeOption.field;
76
75
  return shape || 'line';
77
76
  }
78
77
  processData(filterData) {
@@ -92,19 +92,39 @@ class DataMappingPlugin {
92
92
  const {
93
93
  dataArray
94
94
  } = layer.getSource().data;
95
- let filterData = dataArray;
96
- // 数据过滤完 再执行数据映射
97
- if (filter !== null && filter !== void 0 && filter.scale) {
98
- filterData = dataArray.filter(record => {
99
- return this.applyAttributeMapping(filter, record)[0];
100
- });
95
+
96
+ // 优化:合并过滤和准备阶段为单次遍历
97
+ const usedAttributes = attributes.filter(attribute => attribute.scale !== undefined).filter(attribute => attribute.name !== 'filter');
98
+ const hasFilter = filter === null || filter === void 0 ? void 0 : filter.scale;
99
+
100
+ // 第一阶段:过滤原始数据(需要在 processData 之前)
101
+ let filterData = [];
102
+ if (hasFilter) {
103
+ for (let i = 0; i < dataArray.length; i++) {
104
+ const record = dataArray[i];
105
+ const filterResult = this.applyAttributeMapping(filter, record);
106
+ if (filterResult[0]) {
107
+ filterData.push(record);
108
+ }
109
+ }
110
+ } else {
111
+ filterData = dataArray;
101
112
  }
102
- // Tip: layer 对数据做处理
113
+
114
+ // Tip: layer 对数据做处理(需要处理原始数据格式)
103
115
  // 数据处理 在数据进行 mapping 生成 encodeData 之前对数据进行处理
104
- // 在各个 layer 中继承
116
+ const processedFilterData = layer.processData(filterData);
117
+
118
+ // 第二阶段:数据映射
119
+ const encodeData = this.mapping(layer, usedAttributes, processedFilterData, undefined);
105
120
 
106
- filterData = layer.processData(filterData); // 目前只有简单线需要处理
107
- const encodeData = this.mapping(layer, attributes, filterData, undefined);
121
+ // 重置属性状态
122
+ attributes.forEach(attribute => {
123
+ attribute.needRemapping = false;
124
+ });
125
+
126
+ // 调整数据兼容 SimpleCoordinates
127
+ this.adjustData2SimpleCoordinates(encodeData);
108
128
  layer.setEncodedData(encodeData);
109
129
 
110
130
  // 对外暴露事件
@@ -10,30 +10,27 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _l7Core = require("@antv/l7-core");
12
12
  var _l7Utils = require("@antv/l7-utils");
13
- var _d3Array = require("d3-array");
14
- var d3interpolate = _interopRequireWildcard(require("d3-interpolate"));
15
- var d3 = _interopRequireWildcard(require("d3-scale"));
16
13
  var _identityScale = _interopRequireDefault(require("../utils/identityScale"));
17
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
14
+ var _scale = require("../utils/scale");
19
15
  const {
20
16
  isNil,
21
17
  isString,
22
- uniq
18
+ uniq,
19
+ extent
23
20
  } = _l7Utils.lodashUtil;
24
21
  const dateRegex = /^(?:(?!0000)[0-9]{4}([-/.]+)(?:(?:0?[1-9]|1[0-2])\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\1(?:29|30)|(?:0?[13578]|1[02])\1(?:31))|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)([-/.]?)0?2\2(?:29))(\s+([01]|([01][0-9]|2[0-3])):([0-9]|[0-5][0-9]):([0-9]|[0-5][0-9]))?$/;
25
22
  const scaleMap = {
26
- [_l7Core.ScaleTypes.LINEAR]: d3.scaleLinear,
27
- [_l7Core.ScaleTypes.POWER]: d3.scalePow,
28
- [_l7Core.ScaleTypes.LOG]: d3.scaleLog,
23
+ [_l7Core.ScaleTypes.LINEAR]: _scale.scaleLinear,
24
+ [_l7Core.ScaleTypes.POWER]: _scale.scalePow,
25
+ [_l7Core.ScaleTypes.LOG]: _scale.scaleLog,
29
26
  [_l7Core.ScaleTypes.IDENTITY]: _identityScale.default,
30
- [_l7Core.ScaleTypes.SEQUENTIAL]: d3.scaleSequential,
31
- [_l7Core.ScaleTypes.TIME]: d3.scaleTime,
32
- [_l7Core.ScaleTypes.QUANTILE]: d3.scaleQuantile,
33
- [_l7Core.ScaleTypes.QUANTIZE]: d3.scaleQuantize,
34
- [_l7Core.ScaleTypes.THRESHOLD]: d3.scaleThreshold,
35
- [_l7Core.ScaleTypes.CAT]: d3.scaleOrdinal,
36
- [_l7Core.ScaleTypes.DIVERGING]: d3.scaleDiverging
27
+ [_l7Core.ScaleTypes.SEQUENTIAL]: _scale.scaleSequential,
28
+ [_l7Core.ScaleTypes.TIME]: _scale.scaleTime,
29
+ [_l7Core.ScaleTypes.QUANTILE]: _scale.scaleQuantile,
30
+ [_l7Core.ScaleTypes.QUANTIZE]: _scale.scaleQuantize,
31
+ [_l7Core.ScaleTypes.THRESHOLD]: _scale.scaleThreshold,
32
+ [_l7Core.ScaleTypes.CAT]: _scale.scaleOrdinal,
33
+ [_l7Core.ScaleTypes.DIVERGING]: _scale.scaleDiverging
37
34
  };
38
35
  /**
39
36
  * 根据 Source 原始数据为指定字段创建 Scale,保存在 StyleAttribute 上,供下游插件使用
@@ -108,7 +105,6 @@ class FeatureScalePlugin {
108
105
  if (attribute.scale) {
109
106
  // 创建Scale
110
107
  const attributeScale = attribute.scale;
111
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
112
108
  const fieldValue = attribute.scale.field;
113
109
  attributeScale.names = this.parseFields(isNil(fieldValue) ? [] : fieldValue);
114
110
  const scales = [];
@@ -150,7 +146,7 @@ class FeatureScalePlugin {
150
146
  case _l7Core.ScaleTypes.SEQUENTIAL:
151
147
  scale.scale.interpolator(
152
148
  // @ts-ignore
153
- d3interpolate.interpolateRgbBasis(attributeScale.values));
149
+ (0, _l7Utils.interpolateRgbBasis)(attributeScale.values));
154
150
  break;
155
151
  }
156
152
  }
@@ -207,16 +203,15 @@ class FeatureScalePlugin {
207
203
  if (scaleOption && scaleOption.type) {
208
204
  styleScale.scale = this.createDefaultScale(scaleOption);
209
205
  } else {
210
- styleScale.scale = d3.scaleOrdinal([field]);
206
+ styleScale.scale = (0, _scale.scaleOrdinal)([field]);
211
207
  styleScale.type = _l7Core.StyleScaleType.CONSTANT;
212
208
  }
213
209
  return styleScale;
214
210
  }
215
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
216
211
  const firstValue = (_find = data.find(d => !isNil(d[field]))) === null || _find === void 0 ? void 0 : _find[field];
217
212
  // 常量 Scale
218
213
  if (this.isNumber(field) || isNil(firstValue) && !scaleOption) {
219
- styleScale.scale = d3.scaleOrdinal([field]);
214
+ styleScale.scale = (0, _scale.scaleOrdinal)([field]);
220
215
  styleScale.type = _l7Core.StyleScaleType.CONSTANT;
221
216
  } else {
222
217
  // 根据数据类型判断 默认等分位,时间,和枚举类型
@@ -228,6 +223,10 @@ class FeatureScalePlugin {
228
223
  if (values === undefined) {
229
224
  type = _l7Core.ScaleTypes.IDENTITY;
230
225
  }
226
+ if (name === 'color' && Array.isArray(values) && values.length && values.every(value => isString(value)) && (type === _l7Core.ScaleTypes.LINEAR || type === _l7Core.ScaleTypes.POWER || type === _l7Core.ScaleTypes.LOG)) {
227
+ // Color ramps should use interpolated scales to avoid numeric-only ranges.
228
+ type = _l7Core.ScaleTypes.SEQUENTIAL;
229
+ }
231
230
  const cfg = this.createScaleConfig(type, field, scaleOption, data);
232
231
  styleScale.scale = this.createDefaultScale(cfg);
233
232
  styleScale.option = cfg;
@@ -265,12 +264,12 @@ class FeatureScalePlugin {
265
264
  } else if (type === _l7Core.ScaleTypes.QUANTILE) {
266
265
  cfg.domain = values;
267
266
  } else if (type === _l7Core.ScaleTypes.DIVERGING) {
268
- const minMax = (0, _d3Array.extent)(values);
267
+ const minMax = extent(values);
269
268
  const neutral = (scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.neutral) !== undefined ? scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.neutral : (minMax[0] + minMax[1]) / 2;
270
269
  cfg.domain = [minMax[0], neutral, minMax[1]];
271
270
  } else {
272
271
  // linear/Power/log
273
- cfg.domain = (0, _d3Array.extent)(values);
272
+ cfg.domain = extent(values);
274
273
  }
275
274
  return cfg;
276
275
  }
@@ -38,7 +38,7 @@ class ShaderUniformPlugin {
38
38
  let uniformBuffer;
39
39
  if (!this.rendererService.uniformBuffers[0]) {
40
40
  // Create a Uniform Buffer Object(UBO).
41
- // Size calculation: 4 mat4 (64) + 1 vec4 (4) + 4 vec3->vec4 (16) + 3 vec4 packed (12) = 96 floats
41
+ // Total size: 93 floats, round up to 96 for safety
42
42
  uniformBuffer = this.rendererService.createBuffer({
43
43
  data: new Float32Array(96),
44
44
  isUBO: true,
@@ -111,34 +111,67 @@ class ShaderUniformPlugin {
111
111
  const u_ViewportSize = [width, height];
112
112
  const u_FocalDistance = this.cameraService.getFocalDistance();
113
113
  const u_RelativeOrigin = offset && offset.length >= 2 ? [offset[0], offset[1]] : [0, 0];
114
- const data = [...u_ViewMatrix,
115
- // 16
116
- ...u_ProjectionMatrix,
117
- // 16
118
- ...u_ViewProjectionMatrix,
119
- // 16
120
- ...u_ModelMatrix,
121
- // 16
122
- ...u_ViewportCenterProjection,
123
- // 4
124
- ...u_PixelsPerDegree,
125
- // 4
126
- u_Zoom, ...u_PixelsPerDegree2,
127
- // 4
128
- u_ZoomScale, ...u_PixelsPerMeter,
129
- // 4
130
- u_CoordinateSystem, ...u_CameraPosition,
131
- // 4
132
- u_DevicePixelRatio,
133
- // 4
134
- ...u_ViewportCenter, ...u_ViewportSize,
135
- // 4
136
- u_FocalDistance,
137
- // 1
138
- ...u_RelativeOrigin,
139
- // 2
140
- 0 // padding
141
- ];
114
+
115
+ // Build UBO data array matching GLSL std140 layout
116
+ // std140 rules:
117
+ // - mat4: 16-byte aligned, size 64 bytes (16 floats)
118
+ // - vec4: 16-byte aligned, size 16 bytes (4 floats)
119
+ // - vec3: 16-byte aligned, size 12 bytes (3 floats) - next member can follow if aligned
120
+ // - vec2: 8-byte aligned, size 8 bytes (2 floats)
121
+ // - float: 4-byte aligned, size 4 bytes (1 float)
122
+ // Key: vec3 only occupies 3 floats, NOT 4. The alignment requirement is for START position.
123
+ const floats = [];
124
+
125
+ // mat4 x 4: each 16 floats, all start at multiples of 4 floats (16-byte aligned)
126
+ floats.push(...u_ViewMatrix); // floats 0-15
127
+ floats.push(...u_ProjectionMatrix); // floats 16-31
128
+ floats.push(...u_ViewProjectionMatrix); // floats 32-47
129
+ floats.push(...u_ModelMatrix); // floats 48-63
130
+
131
+ // vec4: 4 floats, starts at float 64 (64 % 4 = 0 ✓)
132
+ floats.push(...u_ViewportCenterProjection); // floats 64-67
133
+
134
+ // vec3: 3 floats only, starts at float 68 (68 % 4 = 0 ✓)
135
+ floats.push(...u_PixelsPerDegree); // floats 68-70 (NOT 68-71!)
136
+
137
+ // float: starts at float 71, any position is fine for 4-byte alignment
138
+ floats.push(u_Zoom); // float 71
139
+
140
+ // vec3: needs 4-float alignment, 72 % 4 = 0
141
+ floats.push(...u_PixelsPerDegree2); // floats 72-74
142
+
143
+ // float: starts at float 75
144
+ floats.push(u_ZoomScale); // float 75
145
+
146
+ // vec3: needs 4-float alignment, 76 % 4 = 0 ✓
147
+ floats.push(...u_PixelsPerMeter); // floats 76-78
148
+
149
+ // float: starts at float 79
150
+ floats.push(u_CoordinateSystem); // float 79
151
+
152
+ // vec3: needs 4-float alignment, 80 % 4 = 0 ✓
153
+ floats.push(...u_CameraPosition); // floats 80-82
154
+
155
+ // float: starts at float 83
156
+ floats.push(u_DevicePixelRatio); // float 83
157
+
158
+ // vec2: needs 2-float alignment, 84 % 2 = 0 ✓
159
+ floats.push(...u_ViewportCenter); // floats 84-85
160
+
161
+ // vec2: needs 2-float alignment, 86 % 2 = 0 ✓
162
+ floats.push(...u_ViewportSize); // floats 86-87
163
+
164
+ // float: starts at float 88
165
+ floats.push(u_FocalDistance); // float 88
166
+
167
+ // vec2: needs 2-float alignment, 89 % 2 = 1, NOT aligned!
168
+ floats.push(0); // padding float 89
169
+ floats.push(...u_RelativeOrigin); // floats 90-91
170
+
171
+ // float u_Reserved3
172
+ floats.push(0); // float 92
173
+
174
+ const data = floats;
142
175
  return {
143
176
  data,
144
177
  uniforms: {
@@ -12,4 +12,4 @@ import RegisterStyleAttributePlugin from './RegisterStyleAttributePlugin';
12
12
  import ShaderUniformPlugin from './ShaderUniformPlugin';
13
13
  import UpdateModelPlugin from './UpdateModelPlugin';
14
14
  import UpdateStyleAttributePlugin from './UpdateStyleAttributePlugin';
15
- export declare function createPlugins(): (DataMappingPlugin | DataSourcePlugin | FeatureScalePlugin | LayerAnimateStylePlugin | LayerMaskPlugin | LayerModelPlugin | LayerStylePlugin | LightingPlugin | MultiPassRendererPlugin | PixelPickingPlugin | RegisterStyleAttributePlugin | ShaderUniformPlugin | UpdateModelPlugin | UpdateStyleAttributePlugin)[];
15
+ export declare function createPlugins(): (DataSourcePlugin | RegisterStyleAttributePlugin | FeatureScalePlugin | DataMappingPlugin | LayerStylePlugin | LayerMaskPlugin | UpdateStyleAttributePlugin | UpdateModelPlugin | MultiPassRendererPlugin | ShaderUniformPlugin | LayerAnimateStylePlugin | LightingPlugin | PixelPickingPlugin | LayerModelPlugin)[];
@@ -26,9 +26,8 @@ class PolygonLayer extends _BaseLayer.default {
26
26
  })();
27
27
  }
28
28
  getModelType() {
29
- var _shapeAttribute$scale;
30
- const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute('shape');
31
- const shape = shapeAttribute === null || shapeAttribute === void 0 || (_shapeAttribute$scale = shapeAttribute.scale) === null || _shapeAttribute$scale === void 0 ? void 0 : _shapeAttribute$scale.field;
29
+ var _this$shapeOption;
30
+ const shape = (_this$shapeOption = this.shapeOption) === null || _this$shapeOption === void 0 ? void 0 : _this$shapeOption.field;
32
31
  if (shape === 'fill' || !shape) {
33
32
  return 'fill';
34
33
  } else if (shape === 'extrude') {
@@ -144,10 +144,6 @@ class ExtrudeModel extends _BaseModel.default {
144
144
  this.textures = [];
145
145
  }
146
146
  registerBuiltinAttributes() {
147
- const bounds = this.layer.getSource().extent;
148
- const lngLen = bounds[2] - bounds[0];
149
- const latLen = bounds[3] - bounds[1];
150
-
151
147
  // 注册 Position 属性 64 位地位部分,经纬度数据开启双精度,避免大于 22 层级以上出现数据偏移
152
148
  this.registerPosition64LowAttribute();
153
149
  this.styleAttributeService.registerStyleAttribute({
@@ -164,10 +160,29 @@ class ExtrudeModel extends _BaseModel.default {
164
160
  },
165
161
  size: 3,
166
162
  update: (feature, featureIdx, vertex) => {
167
- const lng = vertex[0];
168
- const lat = vertex[1];
163
+ // 当启用 enableRelativeCoordinates 时:
164
+ // - vertex 是相对坐标(相对于 relativeOrigin 的偏移)
165
+ // - 需要将相对坐标转换回绝对坐标后,用 originalExtent 计算 UV
166
+ const originalExtent = this.layer.getOriginalExtent();
167
+ const relativeOrigin = this.layer.getRelativeOrigin();
168
+ const isRelativeCoordinates = originalExtent[0] !== 0 || originalExtent[2] !== 0;
169
+ let lng, lat;
170
+ let minLng, minLat, maxLng, maxLat;
171
+ if (isRelativeCoordinates && relativeOrigin) {
172
+ // 相对坐标模式:转换回绝对坐标
173
+ lng = vertex[0] + relativeOrigin[0];
174
+ lat = vertex[1] + relativeOrigin[1];
175
+ [minLng, minLat, maxLng, maxLat] = originalExtent;
176
+ } else {
177
+ // 绝对坐标模式
178
+ lng = vertex[0];
179
+ lat = vertex[1];
180
+ [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
181
+ }
182
+ const lngLen = maxLng - minLng;
183
+ const latLen = maxLat - minLat;
169
184
  // 临时 兼容高德V2
170
- return [(lng - bounds[0]) / lngLen, (lat - bounds[1]) / latLen, vertex[4]];
185
+ return [(lng - minLng) / lngLen, (lat - minLat) / latLen, vertex[4]];
171
186
  }
172
187
  }
173
188
  });
@@ -92,10 +92,6 @@ class OceanModel extends _BaseModel.default {
92
92
  (_this$texture3 = this.texture3) === null || _this$texture3 === void 0 || _this$texture3.destroy();
93
93
  }
94
94
  registerBuiltinAttributes() {
95
- const bbox = this.layer.getSource().extent;
96
- const [minLng, minLat, maxLng, maxLat] = bbox;
97
- const lngLen = maxLng - minLng;
98
- const latLen = maxLat - minLat;
99
95
  this.styleAttributeService.registerStyleAttribute({
100
96
  name: 'oceanUv',
101
97
  type: _l7Core.AttributeType.Attribute,
@@ -103,14 +99,29 @@ class OceanModel extends _BaseModel.default {
103
99
  name: 'a_uv',
104
100
  shaderLocation: this.attributeLocation.UV,
105
101
  buffer: {
106
- // give the WebGL driver a hint that this buffer may change
107
102
  usage: _l7Core.gl.STATIC_DRAW,
108
103
  data: [],
109
104
  type: _l7Core.gl.FLOAT
110
105
  },
111
106
  size: 2,
112
107
  update: (feature, featureIdx, vertex) => {
113
- const [lng, lat] = vertex;
108
+ // 当启用 enableRelativeCoordinates 时:需要将相对坐标转换回绝对坐标
109
+ const originalExtent = this.layer.getOriginalExtent();
110
+ const relativeOrigin = this.layer.getRelativeOrigin();
111
+ const isRelativeCoordinates = originalExtent[0] !== 0 || originalExtent[2] !== 0;
112
+ let lng, lat;
113
+ let minLng, minLat, maxLng, maxLat;
114
+ if (isRelativeCoordinates && relativeOrigin) {
115
+ lng = vertex[0] + relativeOrigin[0];
116
+ lat = vertex[1] + relativeOrigin[1];
117
+ [minLng, minLat, maxLng, maxLat] = originalExtent;
118
+ } else {
119
+ lng = vertex[0];
120
+ lat = vertex[1];
121
+ [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
122
+ }
123
+ const lngLen = maxLng - minLng;
124
+ const latLen = maxLat - minLat;
114
125
  return [(lng - minLng) / lngLen, (lat - minLat) / latLen];
115
126
  }
116
127
  }
@@ -85,10 +85,6 @@ class WaterModel extends _BaseModel.default {
85
85
  (_this$texture = this.texture) === null || _this$texture === void 0 || _this$texture.destroy();
86
86
  }
87
87
  registerBuiltinAttributes() {
88
- const bbox = this.layer.getSource().extent;
89
- const [minLng, minLat, maxLng, maxLat] = bbox;
90
- const lngLen = maxLng - minLng;
91
- const latLen = maxLat - minLat;
92
88
  this.styleAttributeService.registerStyleAttribute({
93
89
  name: 'waterUv',
94
90
  type: _l7Core.AttributeType.Attribute,
@@ -96,14 +92,29 @@ class WaterModel extends _BaseModel.default {
96
92
  name: 'a_uv',
97
93
  shaderLocation: this.attributeLocation.UV,
98
94
  buffer: {
99
- // give the WebGL driver a hint that this buffer may change
100
95
  usage: _l7Core.gl.STATIC_DRAW,
101
96
  data: [],
102
97
  type: _l7Core.gl.FLOAT
103
98
  },
104
99
  size: 2,
105
100
  update: (feature, featureIdx, vertex) => {
106
- const [lng, lat] = vertex;
101
+ // 当启用 enableRelativeCoordinates 时:需要将相对坐标转换回绝对坐标
102
+ const originalExtent = this.layer.getOriginalExtent();
103
+ const relativeOrigin = this.layer.getRelativeOrigin();
104
+ const isRelativeCoordinates = originalExtent[0] !== 0 || originalExtent[2] !== 0;
105
+ let lng, lat;
106
+ let minLng, minLat, maxLng, maxLat;
107
+ if (isRelativeCoordinates && relativeOrigin) {
108
+ lng = vertex[0] + relativeOrigin[0];
109
+ lat = vertex[1] + relativeOrigin[1];
110
+ [minLng, minLat, maxLng, maxLat] = originalExtent;
111
+ } else {
112
+ lng = vertex[0];
113
+ lat = vertex[1];
114
+ [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
115
+ }
116
+ const lngLen = maxLng - minLng;
117
+ const latLen = maxLat - minLat;
107
118
  return [(lng - minLng) / lngLen, (lat - minLat) / latLen];
108
119
  }
109
120
  }
@@ -14,7 +14,10 @@ export default class BaseTileLayer {
14
14
  initedTileset: boolean;
15
15
  protected lastViewStates: {
16
16
  zoom: number;
17
- latLonBounds: [number, number, number, number];
17
+ minLng: number;
18
+ minLat: number;
19
+ maxLng: number;
20
+ maxLat: number;
18
21
  };
19
22
  constructor(parent: ILayer);
20
23
  protected initTileSetManager(): void;