Skip to content

Commit

Permalink
Merge pull request #7518 from AnalyticalGraphicsInc/fixPolygonRectangle
Browse files Browse the repository at this point in the history
fix ground polygon rectangles
  • Loading branch information
Hannah authored Jan 29, 2019
2 parents 1f780d1 + 8c680e9 commit 63b06f4
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Change Log
* Fixed an issue where setting `scene.globe.cartographicLimitRectangle` to `undefined` would cause a crash. [#7477](https://github.com/AnalyticalGraphicsInc/cesium/issues/7477)
* Fixed `PrimitiveCollection.removeAll` to no longer `contain` removed primitives. [#7491](https://github.com/AnalyticalGraphicsInc/cesium/pull/7491)
* Fixed `GeoJsonDataSource` to use polygons and polylines that use rhumb lines. [#7492](https://github.com/AnalyticalGraphicsInc/cesium/pull/7492)
* Fixed an issue where some ground polygons would be cut off along circles of latitude. [#7507](https://github.com/AnalyticalGraphicsInc/cesium/issues/7507)

### 1.53 - 2019-01-02

Expand Down
99 changes: 92 additions & 7 deletions Source/Core/PolygonGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ define([
'./defineProperties',
'./DeveloperError',
'./Ellipsoid',
'./EllipsoidGeodesic',
'./EllipsoidRhumbLine',
'./EllipsoidTangentPlane',
'./Geometry',
'./GeometryAttribute',
Expand Down Expand Up @@ -44,6 +46,8 @@ define([
defineProperties,
DeveloperError,
Ellipsoid,
EllipsoidGeodesic,
EllipsoidRhumbLine,
EllipsoidTangentPlane,
Geometry,
GeometryAttribute,
Expand Down Expand Up @@ -372,18 +376,89 @@ define([
return geometry;
}

function computeRectangle(positions, ellipsoid, result) {
var startCartographicScratch = new Cartographic();
var endCartographicScratch = new Cartographic();
var idlCross = {
west : 0.0,
east : 0.0
};
var ellipsoidGeodesic = new EllipsoidGeodesic();
function computeRectangle(positions, ellipsoid, arcType, granularity, result) {
result = defaultValue(result, new Rectangle());
if (!defined(positions) || positions.length < 3) {
if (!defined(result)) {
return new Rectangle();
}
result.west = 0.0;
result.north = 0.0;
result.south = 0.0;
result.east = 0.0;
return result;
}
return Rectangle.fromCartesianArray(positions, ellipsoid, result);

if (arcType === ArcType.RHUMB) {
return Rectangle.fromCartesianArray(positions, ellipsoid, result);
}

if (!ellipsoidGeodesic.ellipsoid.equals(ellipsoid)) {
ellipsoidGeodesic = new EllipsoidGeodesic(undefined, undefined, ellipsoid);
}

result.west = Number.POSITIVE_INFINITY;
result.east = Number.NEGATIVE_INFINITY;
result.south = Number.POSITIVE_INFINITY;
result.north = Number.NEGATIVE_INFINITY;

idlCross.west = Number.POSITIVE_INFINITY;
idlCross.east = Number.NEGATIVE_INFINITY;

var inverseChordLength = 1.0 / CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
var positionsLength = positions.length;
var endCartographic = ellipsoid.cartesianToCartographic(positions[0], endCartographicScratch);
var startCartographic = startCartographicScratch;
var swap;

for (var i = 1; i < positionsLength; i++) {
swap = startCartographic;
startCartographic = endCartographic;
endCartographic = ellipsoid.cartesianToCartographic(positions[i], swap);
ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);
interpolateAndGrowRectangle(ellipsoidGeodesic, inverseChordLength, result, idlCross);
}

swap = startCartographic;
startCartographic = endCartographic;
endCartographic = ellipsoid.cartesianToCartographic(positions[0], swap);
ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);
interpolateAndGrowRectangle(ellipsoidGeodesic, inverseChordLength, result, idlCross);

if (result.east - result.west > idlCross.west - idlCross.east) {
result.east = idlCross.east;
result.west = idlCross.west;
}

return result;
}

var interpolatedCartographicScratch = new Cartographic();
function interpolateAndGrowRectangle(ellipsoidGeodesic, inverseChordLength, result, idlCross) {
var segmentLength = ellipsoidGeodesic.surfaceDistance;

var numPoints = Math.ceil(segmentLength * inverseChordLength);
var subsegmentDistance = numPoints > 0 ? segmentLength / (numPoints - 1) : Number.POSITIVE_INFINITY;
var interpolationDistance = 0.0;

for (var i = 0; i < numPoints; i++) {
var interpolatedCartographic = ellipsoidGeodesic.interpolateUsingSurfaceDistance(interpolationDistance, interpolatedCartographicScratch);
interpolationDistance += subsegmentDistance;
var longitude = interpolatedCartographic.longitude;
var latitude = interpolatedCartographic.latitude;

result.west = Math.min(result.west, longitude);
result.east = Math.max(result.east, longitude);
result.south = Math.min(result.south, latitude);
result.north = Math.max(result.north, latitude);

idlCross.west = longitude > 0.0 ? Math.min(longitude, idlCross.west) : idlCross.west;
idlCross.east = longitude < 0.0 ? Math.max(longitude, idlCross.east) : idlCross.east;
}
}

var createGeometryFromPositionsExtrudedPositions = [];
Expand Down Expand Up @@ -800,6 +875,8 @@ define([
*
* @param {Object} options Object with the following properties:
* @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.
* @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions sampled.
* @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
* @param {Rectangle} [result] An object in which to store the result.
*
Expand All @@ -811,10 +888,18 @@ define([
Check.typeOf.object('options.polygonHierarchy', options.polygonHierarchy);
//>>includeEnd('debug');

var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
var arcType = defaultValue(options.arcType, ArcType.GEODESIC);
//>>includeStart('debug', pragmas.debug);
if (arcType !== ArcType.GEODESIC && arcType !== ArcType.RHUMB) {
throw new DeveloperError('Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.');
}
//>>includeEnd('debug');

var polygonHierarchy = options.polygonHierarchy;
var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);

return computeRectangle(polygonHierarchy.positions, ellipsoid, result);
return computeRectangle(polygonHierarchy.positions, ellipsoid, arcType, granularity, result);
};

/**
Expand Down Expand Up @@ -1000,7 +1085,7 @@ define([
get : function() {
if (!defined(this._rectangle)) {
var positions = this._polygonHierarchy.positions;
this._rectangle = computeRectangle(positions, this._ellipsoid);
this._rectangle = computeRectangle(positions, this._ellipsoid, this._arcType, this._granularity);
}

return this._rectangle;
Expand Down
61 changes: 61 additions & 0 deletions Specs/Core/PolygonGeometrySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,67 @@ defineSuite([
expect(CesiumMath.toDegrees(r.west)).toEqualEpsilon(-100.5, CesiumMath.EPSILON13);
});

it('computes rectangle according to arctype', function() {
var pGeodesic = new PolygonGeometry({
vertexFormat : VertexFormat.POSITION_AND_ST,
polygonHierarchy: {
positions : Cartesian3.fromDegreesArrayHeights([
-90.0, 30.0, 0,
-80.0, 30.0, 0,
-80.0, 40.0, 0,
-90.0, 40.0, 0
])},
granularity: CesiumMath.RADIANS_PER_DEGREE,
arcType : ArcType.GEODESIC
});

var boundingGeodesic = pGeodesic.rectangle;
expect(CesiumMath.toDegrees(boundingGeodesic.north)).toBeGreaterThan(40.0);
expect(CesiumMath.toDegrees(boundingGeodesic.south)).toEqualEpsilon(30.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingGeodesic.east)).toEqualEpsilon(-80.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingGeodesic.west)).toEqualEpsilon(-90.0, CesiumMath.EPSILON10);

var pRhumb = new PolygonGeometry({
vertexFormat : VertexFormat.POSITION_AND_ST,
polygonHierarchy: {
positions : Cartesian3.fromDegreesArrayHeights([
-90.0, 30.0, 0,
-80.0, 30.0, 0,
-80.0, 40.0, 0,
-90.0, 40.0, 0
])},
granularity: CesiumMath.RADIANS_PER_DEGREE,
arcType : ArcType.RHUMB
});

var boundingRhumb = pRhumb.rectangle;
expect(CesiumMath.toDegrees(boundingRhumb.north)).toEqualEpsilon(40.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.south)).toEqualEpsilon(30.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.east)).toEqualEpsilon(-80.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.west)).toEqualEpsilon(-90.0, CesiumMath.EPSILON10);
});

it('computes rectangles that cross the IDL', function() {
var pRhumb = new PolygonGeometry({
vertexFormat : VertexFormat.POSITION_AND_ST,
polygonHierarchy: {
positions : Cartesian3.fromDegreesArray([
175, 30,
-170, 30,
-170, 40,
175, 40
])},
granularity: CesiumMath.RADIANS_PER_DEGREE,
arcType : ArcType.RHUMB
});

var boundingRhumb = pRhumb.rectangle;
expect(CesiumMath.toDegrees(boundingRhumb.north)).toEqualEpsilon(40.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.south)).toEqualEpsilon(30.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.east)).toEqualEpsilon(-170.0, CesiumMath.EPSILON10);
expect(CesiumMath.toDegrees(boundingRhumb.west)).toEqualEpsilon(175.0, CesiumMath.EPSILON10);
});

it('computeRectangle', function() {
var options = {
vertexFormat : VertexFormat.POSITION_AND_ST,
Expand Down

0 comments on commit 63b06f4

Please sign in to comment.