Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix ground polygon rectangles #7518

Merged
merged 2 commits into from
Jan 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,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