Skip to content

Commit 09b541b

Browse files
【fix】视频地图叠加矢量要素,范围外的进行裁剪避免要素乱飞
AI-GEN: 70% Cursor
1 parent 8b23526 commit 09b541b

6 files changed

Lines changed: 673 additions & 79 deletions

File tree

‎src/mapboxgl/mapping/CoordTransfer.js‎

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,26 @@ export default class CoordTransfer {
5858
if (this.rotationMatrix) {
5959
this.rotationMatrix.delete();
6060
}
61+
if (this.rotationMat3) {
62+
this.rotationMat3.delete();
63+
}
6164
if (this.translationMatrix) {
6265
this.translationMatrix.delete();
6366
}
6467
if (this.k) {
6568
this.k.delete();
6669
}
6770
this.rotationMatrix = this.toRotationMatrix(pitch, roll, yaw);
71+
this.rotationMat3 = new this.cv.Mat(3, 3, this.cv.CV_64FC1);
72+
this.cv.Rodrigues(this.rotationMatrix, this.rotationMat3);
6873
this.translationMatrix = this.toTranslationMatrix(x, y, z);
6974
this.k = this.toCameraMatrix(fx, fy, centerX, centerY);
75+
this._R = this.rotationMat3.data64F ? Array.from(this.rotationMat3.data64F) : null;
76+
this._t = this.translationMatrix.data64F ? Array.from(this.translationMatrix.data64F) : null;
77+
this._fx = fx;
78+
this._fy = fy;
79+
this._cx = centerX;
80+
this._cy = centerY;
7081
}
7182

7283
/**
@@ -170,25 +181,65 @@ export default class CoordTransfer {
170181
toCameraMatrix(fx, fy, centerX, centerY) {
171182
return this.cv.matFromArray(3, 3, this.cv.CV_64FC1, [fx, 0, centerX, 0, fy, centerY, 0, 0, 1]);
172183
}
184+
/**
185+
* @function CoordTransfer.prototype.toCameraCoordinate
186+
* @description 将空间坐标转换到相机坐标系。Z > 0 表示在相机前方。
187+
* @param {Array<number>} coord - 空间坐标 [x, y] 或 [x, y, z](EPSG:3857)。
188+
* @returns {Array<number>|null} 相机坐标 [Xc, Yc, Zc]。
189+
*/
190+
toCameraCoordinate(coord) {
191+
if (!this._R || this._R.length < 9 || !this._t || this._t.length < 3 || !coord || coord.length < 2) {
192+
return null;
193+
}
194+
const x = coord[0];
195+
const y = coord[1];
196+
const z = coord.length > 2 ? coord[2] : 0;
197+
const R = this._R;
198+
const t = this._t;
199+
return [
200+
R[0] * x + R[1] * y + R[2] * z + t[0],
201+
R[3] * x + R[4] * y + R[5] * z + t[1],
202+
R[6] * x + R[7] * y + R[8] * z + t[2]
203+
];
204+
}
205+
206+
/**
207+
* @function CoordTransfer.prototype.projectCameraToVideo
208+
* @description 将相机坐标投影为视频像素坐标。相机后方的点返回 null。
209+
* @param {Array<number>} camera - 相机坐标 [Xc, Yc, Zc]。
210+
* @param {number} [zNear=0.01] - 近裁剪面,单位与空间坐标一致。
211+
* @returns {Array<number>|null} 视频像素坐标 [u, v]。
212+
*/
213+
projectCameraToVideo(camera, zNear = 0.01) {
214+
if (!camera || this._fx == null || this._fy == null) {
215+
return null;
216+
}
217+
const depth = camera[2];
218+
if (!(depth > zNear)) {
219+
return null;
220+
}
221+
return [
222+
this._fx * camera[0] / depth + this._cx,
223+
this._fy * camera[1] / depth + this._cy
224+
];
225+
}
226+
173227
/**
174228
* @function CoordTransfer.prototype.toVideoCoordinate
175-
* @description 转换视频像素坐标到空间地理坐标。
229+
* @description 将空间地理坐标转换为视频像素坐标。相机后方的点 data64F 为空数组。
176230
* @param {Array} coord - 空间坐标。
177-
* @returns {Array} 视频像素坐标。
231+
* @returns {{data64F: Array<number>, depth: (number|null)}} 视频像素坐标及相机深度。
178232
*/
179233
toVideoCoordinate(coord) {
180-
if (!this.cv || !this.cv.Mat) {
181-
return { data64F: [] };
234+
const camera = this.toCameraCoordinate(coord);
235+
if (!camera) {
236+
return { data64F: [], depth: null };
182237
}
183-
let emptyMat = new this.cv.Mat();
184-
let point3 = this.cv.matFromArray(3, 1, this.cv.CV_64FC1, [coord[0], coord[1], 0]);
185-
let point2 = new this.cv.Mat(2, 1, this.cv.CV_64FC1);
186-
this.cv.projectPoints(point3, this.rotationMatrix, this.translationMatrix, this.k, emptyMat, point2);
187-
const data64F = point2.data64F.length ? [point2.data64F[0], point2.data64F[1]] : [];
188-
emptyMat.delete();
189-
point3.delete();
190-
point2.delete();
191-
return { data64F };
238+
const uv = this.projectCameraToVideo(camera);
239+
return {
240+
data64F: uv || [],
241+
depth: camera[2]
242+
};
192243
}
193244
/**
194245
* @function CoordTransfer.prototype.toSpatialCoordinate

‎src/mapboxgl/mapping/GeojsonSource.js‎

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { featureEach, coordEach } from '@turf/meta';
21
import cloneDeep from 'lodash.clonedeep';
3-
import { transformCoord } from './utils/VideoMapUtil';
4-
import proj4 from 'proj4';
2+
import { transformVideoMapGeoJSON } from './utils/clipVideoMapGeometry';
53

64
/**
75
* @class GeojsonSource
@@ -13,13 +11,7 @@ import proj4 from 'proj4';
1311
export default class GeojsonSource {
1412
constructor(videoMap) {
1513
this.videoMap = videoMap;
16-
const { coordTransfer, originCoordsRightBottom, originCoordsLeftTop, videoWidth, videoHeight, map } = videoMap;
17-
this.map = map;
18-
this.coordTransfer = coordTransfer;
19-
this.originCoordsRightBottom = originCoordsRightBottom;
20-
this.originCoordsLeftTop = originCoordsLeftTop;
21-
this.videoWidth = videoWidth;
22-
this.videoHeight = videoHeight;
14+
this.map = videoMap.map;
2315
}
2416

2517
/**
@@ -49,31 +41,13 @@ export default class GeojsonSource {
4941
}
5042

5143
_transformData(data) {
52-
const { coordTransfer, originCoordsRightBottom, originCoordsLeftTop, videoWidth, videoHeight } = this.videoMap;
53-
const newData = cloneDeep(data);
54-
featureEach(newData, (currentFeature) => {
55-
coordEach(currentFeature, (curCoords) => {
56-
let transCurCoords = proj4('EPSG:4326', 'EPSG:3857', curCoords);
57-
let transCoords = coordTransfer.toVideoCoordinate(transCurCoords);
58-
curCoords.length = 0;
59-
curCoords.push(
60-
...transformCoord({
61-
videoPoint: transCoords.data64F,
62-
videoWidth,
63-
videoHeight,
64-
originCoordsRightBottom,
65-
originCoordsLeftTop
66-
})
67-
);
68-
});
69-
});
70-
return newData;
44+
return transformVideoMapGeoJSON(data, this.videoMap);
7145
}
46+
7247
/**
7348
* @function GeojsonSource.prototype.remove
7449
* @description 移除数据源。
7550
* @param {Object} id - 数据源 id。
76-
* @param {Object} source
7751
*/
7852
remove() {
7953
if (this.id && this.map.getSource(this.id)) {
Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { featureEach, coordEach } from '@turf/meta';
2-
import cloneDeep from 'lodash.clonedeep';
3-
import { transformCoord } from '../utils/VideoMapUtil';
4-
import proj4 from 'proj4';
1+
import { transformVideoMapGeoJSON } from '../utils/clipVideoMapGeometry';
2+
53
/**
64
* @class GeojsonLayer
75
* @version 11.2.0
@@ -11,14 +9,9 @@ import proj4 from 'proj4';
119
*/
1210
export default class GeojsonLayer {
1311
constructor(videoMap) {
14-
const { coordTransfer, originCoordsRightBottom, originCoordsLeftTop, videoWidth, videoHeight, map } = videoMap;
15-
this.map = map;
16-
this.coordTransfer = coordTransfer;
12+
this.videoMap = videoMap;
13+
this.map = videoMap.map;
1714
this.layerId = null;
18-
this.originCoordsRightBottom = originCoordsRightBottom;
19-
this.originCoordsLeftTop = originCoordsLeftTop;
20-
this.videoWidth = videoWidth;
21-
this.videoHeight = videoHeight;
2215
}
2316

2417
/**
@@ -33,8 +26,7 @@ export default class GeojsonLayer {
3326
return;
3427
}
3528
if (typeof source === 'object') {
36-
const newData = this.eachData(cloneDeep(source.data));
37-
layer.source.data = newData;
29+
layer.source.data = this.eachData(source.data);
3830
}
3931

4032
this.map.addLayer(layer, beforeId);
@@ -52,31 +44,13 @@ export default class GeojsonLayer {
5244
}
5345

5446
/**
55-
* @function GeojsonLayer.prototype.add
56-
* @param {Array} features - Mapbox layer 地图对象。
47+
* @function GeojsonLayer.prototype.eachData
48+
* @param {Object} features - GeoJSON 数据。
5749
*/
5850
eachData(features) {
59-
if (!this.coordTransfer) {
60-
return [];
51+
if (!this.videoMap || !this.videoMap.coordTransfer) {
52+
return features;
6153
}
62-
featureEach(features, (currentFeature) => {
63-
coordEach(currentFeature, (curCoords) => {
64-
let transCurCoords = proj4('EPSG:4326', 'EPSG:3857', curCoords);
65-
let transCoords = this.coordTransfer.toVideoCoordinate(transCurCoords);
66-
curCoords.length = 0;
67-
if (transCoords.data64F.length) {
68-
curCoords.push(
69-
...transformCoord({
70-
videoPoint: transCoords.data64F,
71-
videoWidth: this.videoWidth,
72-
videoHeight: this.videoHeight,
73-
originCoordsRightBottom: this.originCoordsRightBottom,
74-
originCoordsLeftTop: this.originCoordsLeftTop
75-
})
76-
);
77-
}
78-
});
79-
});
80-
return features;
54+
return transformVideoMapGeoJSON(features, this.videoMap);
8155
}
8256
}

0 commit comments

Comments
 (0)