Skip to content

Commit 7f59971

Browse files
authored
Merge pull request #12460 from CesiumGS/fix-rhumb-subdivide
Fix geojson `EllipsoidRhumbLine` error for duplicated points
2 parents 82e59ed + 130106e commit 7f59971

File tree

4 files changed

+87
-6
lines changed

4 files changed

+87
-6
lines changed

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Change Log
22

3+
## 1.127 - 2025-03-03
4+
5+
### @cesium/engine
6+
7+
#### Fixes :wrench:
8+
9+
- Fixed error when there are duplicated points in polygon/polyline geometries with `ArcType.RHUMB` [#12460](https://github.com/CesiumGS/cesium/pull/12460)
10+
311
## 1.126 - 2025-02-03
412

513
### @cesium/engine

packages/engine/Source/Core/EllipsoidRhumbLine.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ EllipsoidRhumbLine.prototype.interpolateUsingFraction = function (
562562
/**
563563
* Provides the location of a point at the indicated distance along the rhumb line.
564564
*
565-
* @param {number} distance The distance from the inital point to the point of interest along the rhumbLine.
565+
* @param {number} distance The distance from the initial point to the point of interest along the rhumbLine.
566566
* @param {Cartographic} [result] The object in which to store the result.
567567
* @returns {Cartographic} The location of the point along the rhumb line.
568568
*

packages/engine/Source/Core/PolygonGeometryLibrary.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,18 @@ PolygonGeometryLibrary.subdivideTexcoordRhumbLine = function (
312312
return texcoords;
313313
};
314314

315+
/**
316+
* Subdivide the line between 2 points every minDistance length
317+
* If the points are already closer than minDistance the first will be returned
318+
*
319+
* @private
320+
* @param {Ellipsoid} ellipsoid
321+
* @param {Cartesian3} p0 start point
322+
* @param {Cartesian3} p1 end point
323+
* @param {number} minDistance minimum distance between points in radians
324+
* @param {number[]} [result] if provided positions will be packed into this array starting at index 0
325+
* @returns {number[]} Cartesian3 positions packed into an array
326+
*/
315327
PolygonGeometryLibrary.subdivideRhumbLine = function (
316328
ellipsoid,
317329
p0,
@@ -323,15 +335,25 @@ PolygonGeometryLibrary.subdivideRhumbLine = function (
323335
const c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
324336
const rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
325337

338+
if (!defined(result)) {
339+
result = [];
340+
}
341+
342+
if (rhumb.surfaceDistance <= minDistance) {
343+
// no need to try and subdivide a line that's already shorter than the min distance
344+
// this also inherently handles duplicated points which would have 0 distance
345+
result.length = 3;
346+
result[0] = p0.x;
347+
result[1] = p0.y;
348+
result[2] = p0.z;
349+
return result;
350+
}
351+
326352
const n = rhumb.surfaceDistance / minDistance;
327353
const countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
328354
const numVertices = Math.pow(2, countDivide);
329355
const distanceBetweenVertices = rhumb.surfaceDistance / numVertices;
330356

331-
if (!defined(result)) {
332-
result = [];
333-
}
334-
335357
const positions = result;
336358
positions.length = numVertices * 3;
337359

packages/engine/Specs/Core/PolygonGeometryLibrarySpec.js

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,58 @@ import {
77
} from "../../index.js";
88

99
describe("Core/PolygonGeometryLibrary", function () {
10-
describe("splitPolygonByPlane", function () {
10+
describe("subdivideRhumbLine", () => {
11+
it("returns first point if both points are the same", function () {
12+
const p0 = new Cartesian3(3813220.0, -5085291.0, 527179.0);
13+
const p1 = new Cartesian3(3813220.0, -5085291.0, 527179.0);
14+
const positions = PolygonGeometryLibrary.subdivideRhumbLine(
15+
Ellipsoid.WGS84,
16+
p0,
17+
p1,
18+
2,
19+
);
20+
expect(positions.length).toEqual(3);
21+
expect(positions).toEqual([3813220.0, -5085291.0, 527179.0]);
22+
});
23+
24+
it("returns first point if the points are closer than minDistance", function () {
25+
const p0 = new Cartesian3(3813220.0, -5085291.0, 527179.0);
26+
const p1 = new Cartesian3(3813220.0, -5085291.0, 527179.0 + 1);
27+
// actual surface distance is ~0.997
28+
const positions = PolygonGeometryLibrary.subdivideRhumbLine(
29+
Ellipsoid.WGS84,
30+
p0,
31+
p1,
32+
2,
33+
);
34+
expect(positions.length).toEqual(3);
35+
expect(positions).toEqual([3813220.0, -5085291.0, 527179.0]);
36+
});
37+
38+
it("subdivides the line between 2 points", function () {
39+
const p0 = new Cartesian3(3813220.0, -5085291.0, 527179.0);
40+
const p1 = new Cartesian3(3813220.0, -5085291.0, 527179.0 + 5);
41+
// actual surface distance is ~4.983
42+
const positions = PolygonGeometryLibrary.subdivideRhumbLine(
43+
Ellipsoid.WGS84,
44+
p0,
45+
p1,
46+
2,
47+
);
48+
expect(positions.length).toEqual(12);
49+
expect(positions).toEqualEpsilon(
50+
[
51+
3813220.447295841, -5085291.596511482, 527179.0622555692,
52+
3813220.3851130935, -5085291.513584885, 527180.3036009098,
53+
3813220.3229302, -5085291.430658091, 527181.5449462304,
54+
3813220.2607471617, -5085291.347731101, 527182.7862915307,
55+
],
56+
CesiumMath.EPSILON7,
57+
);
58+
});
59+
});
60+
61+
describe("splitPolygonsOnEquator", function () {
1162
it("splits a simple polygon at the equator", function () {
1263
const positions = Cartesian3.unpackArray([
1364
3813220.0, -5085291.0, 527179.0, 3701301.0, -5097773.0, -993503.0,

0 commit comments

Comments
 (0)