diff --git a/Apps/Sandcastle/gallery/Polygon.html b/Apps/Sandcastle/gallery/Polygon.html
index e5052bbc06f5..d9fd0a94d3f1 100644
--- a/Apps/Sandcastle/gallery/Polygon.html
+++ b/Apps/Sandcastle/gallery/Polygon.html
@@ -125,6 +125,21 @@
}
});
+var purplePolygonUsingRhumbLines = viewer.entities.add({
+ name : 'Purple polygon using rhumb lines with outline',
+ polygon : {
+ hierarchy : Cesium.Cartesian3.fromDegreesArray([-120.0, 45.0,
+ -80.0, 45.0,
+ -80.0, 55.0,
+ -120.0, 55.0]),
+ extrudedHeight: 50000,
+ material : Cesium.Color.PURPLE,
+ outline : true,
+ outlineColor : Cesium.Color.MAGENTA,
+ arcType : Cesium.ArcType.RHUMB
+ }
+});
+
viewer.zoomTo(viewer.entities);//Sandcastle_End
Sandcastle.finishedLoading();
}
diff --git a/Apps/Sandcastle/gallery/Polyline.html b/Apps/Sandcastle/gallery/Polyline.html
index 6ae30db914c5..40e35964751c 100644
--- a/Apps/Sandcastle/gallery/Polyline.html
+++ b/Apps/Sandcastle/gallery/Polyline.html
@@ -40,6 +40,17 @@
}
});
+var greenRhumbLine = viewer.entities.add({
+ name : 'Green rhumb line',
+ polyline : {
+ positions : Cesium.Cartesian3.fromDegreesArray([-75, 35,
+ -125, 35]),
+ width : 5,
+ arcType : Cesium.ArcType.RHUMB,
+ material : Cesium.Color.GREEN
+ }
+});
+
var glowingLine = viewer.entities.add({
name : 'Glowing blue line on the surface',
polyline : {
@@ -73,7 +84,7 @@
positions : Cesium.Cartesian3.fromDegreesArrayHeights([-75, 43, 500000,
-125, 43, 500000]),
width : 10,
- followSurface : false,
+ arcType : Cesium.ArcType.NONE,
material : new Cesium.PolylineArrowMaterialProperty(Cesium.Color.PURPLE)
}
});
diff --git a/Apps/Sandcastle/gallery/development/Ground Primitive.html b/Apps/Sandcastle/gallery/development/Ground Primitive.html
index 7406c23b0225..936323c65b6f 100644
--- a/Apps/Sandcastle/gallery/development/Ground Primitive.html
+++ b/Apps/Sandcastle/gallery/development/Ground Primitive.html
@@ -31,6 +31,7 @@
terrainProvider: Cesium.createWorldTerrain()
});
var scene = viewer.scene;
+viewer.extend(Cesium.viewerCesiumInspectorMixin);
function offsetPositions(positions, degreeOffset) {
positions = scene.globe.ellipsoid.cartesianArrayToCartographicArray(positions);
@@ -325,6 +326,26 @@
}),
classificationType : Cesium.ClassificationType.TERRAIN
}));
+
+ // Rhumb line polygon geometry
+ scene.groundPrimitives.add(new Cesium.GroundPrimitive({
+ geometryInstances : new Cesium.GeometryInstance({
+ geometry : new Cesium.PolygonGeometry({
+ polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([
+ -130, 55,
+ -100, 55,
+ -100, 45,
+ -130, 45
+ ])),
+ arcType : Cesium.ArcType.RHUMB
+ }),
+ attributes: {
+ color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 0.0, 0.5))
+ },
+ id : 'rhumbPolygon'
+ }),
+ classificationType : Cesium.ClassificationType.TERRAIN
+ }));
});
Sandcastle.reset = function() {
diff --git a/Apps/Sandcastle/gallery/development/Polylines.html b/Apps/Sandcastle/gallery/development/Polylines.html
index 2f40bfaebf59..db16318e2ddc 100644
--- a/Apps/Sandcastle/gallery/development/Polylines.html
+++ b/Apps/Sandcastle/gallery/development/Polylines.html
@@ -119,6 +119,20 @@
})
});
Sandcastle.declare(fadingPolyline); // For highlighting on mouseover in Sandcastle.
+
+ // A rhumb line with two points.
+ var rhumbLine = polylines.add({
+ positions : Cesium.PolylinePipeline.generateCartesianRhumbArc({
+ positions : Cesium.Cartesian3.fromDegreesArray([-130.0, 30.0,
+ -75.0, 30.0])
+ }),
+ width: 5,
+ material : Cesium.Material.fromType('Color', {
+ color : new Cesium.Color(0.0, 1.0, 0.0, 1.0)
+ })
+ });
+ Sandcastle.declare(rhumbLine); // For highlighting on mouseover in Sandcastle.
+
}
var viewer = new Cesium.Viewer('cesiumContainer');
diff --git a/CHANGES.md b/CHANGES.md
index b49986abbbf2..b19c37bda547 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -9,6 +9,8 @@ Change Log
##### Deprecated :hourglass_flowing_sand:
* `Scene.clampToHeight` now takes an optional `width` argument before the `result` argument. The previous function definition will no longer work in 1.56. [#7287](https://github.com/AnalyticalGraphicsInc/cesium/pull/7287)
+* `PolylineGeometry.followSurface` has been superceded by `PolylineGeometry.arcType`. The previous definition will no longer work in 1.57. Replace `followSurface: false` with `arcType: Cesium.ArcType.NONE` and `followSurface: true` with `arcType: Cesium.ArcType.GEODESIC`. [#7492](https://github.com/AnalyticalGraphicsInc/cesium/pull/7492)
+* `SimplePolylineGeometry.followSurface` has been superceded by `SimplePolylineGeometry.arcType`. The previous definition will no longer work in 1.57. Replace `followSurface: false` with `arcType: Cesium.ArcType.NONE` and `followSurface: true` with `arcType: Cesium.ArcType.GEODESIC`. [#7492](https://github.com/AnalyticalGraphicsInc/cesium/pull/7492)
##### Additions :tada:
* Added support for textured ground entities (entities with unspecified `height`) and `GroundPrimitives` on 3D Tiles. [#7434](https://github.com/AnalyticalGraphicsInc/cesium/pull/7434)
@@ -17,6 +19,7 @@ Change Log
* Added the ability to specify the width of the intersection volume for `Scene.sampleHeight`, `Scene.clampToHeight`, `Scene.sampleHeightMostDetailed`, and `Scene.clampToHeightMostDetailed`. [#7287](https://github.com/AnalyticalGraphicsInc/cesium/pull/7287)
* Added a [new Sandcastle example](https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=Time%20Dynamic%20Wheels.html) on using `nodeTransformations` to rotate a model's wheels based on its velocity. [#7361](https://github.com/AnalyticalGraphicsInc/cesium/pull/7361)
* Added `EllipsoidRhumbLine` class as a rhumb line counterpart to `EllipsoidGeodesic`. [#7484](https://github.com/AnalyticalGraphicsInc/cesium/pull/7484)
+* Added rhumb line support to `PolygonGeometry`, `PolygonOutlineGeometry`, `PolylineGeometry`, `GroundPolylineGeometry`, and `SimplePolylineGeometry`. [#7492](https://github.com/AnalyticalGraphicsInc/cesium/pull/7492)
##### Fixes :wrench:
* Fixed 3D Tiles performance regression. [#7482](https://github.com/AnalyticalGraphicsInc/cesium/pull/7482)
@@ -28,6 +31,7 @@ Change Log
* Fixed Sandcastle's "Open in New Window" button not displaying imagery due to blob URI limitations. [#7250](https://github.com/AnalyticalGraphicsInc/cesium/pull/7250)
* 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)
### 1.53 - 2019-01-02
diff --git a/Source/Core/ArcType.js b/Source/Core/ArcType.js
new file mode 100644
index 000000000000..f4c54cc9305c
--- /dev/null
+++ b/Source/Core/ArcType.js
@@ -0,0 +1,39 @@
+define([
+ './freezeObject'
+ ], function(
+ freezeObject) {
+ 'use strict';
+
+ /**
+ * ArcType defines the path that should be taken connecting vertices.
+ *
+ * @exports ArcType
+ */
+ var ArcType = {
+ /**
+ * Straight line that does not conform to the surface of the ellipsoid.
+ *
+ * @type {Number}
+ * @constant
+ */
+ NONE : 0,
+
+ /**
+ * Follow geodesic path.
+ *
+ * @type {Number}
+ * @constant
+ */
+ GEODESIC : 1,
+
+ /**
+ * Follow rhumb or loxodrome path.
+ *
+ * @type {Number}
+ * @constant
+ */
+ RHUMB : 2
+ };
+
+ return freezeObject(ArcType);
+});
diff --git a/Source/Core/GroundPolylineGeometry.js b/Source/Core/GroundPolylineGeometry.js
index 938a2c08e001..d950f2296b27 100644
--- a/Source/Core/GroundPolylineGeometry.js
+++ b/Source/Core/GroundPolylineGeometry.js
@@ -1,5 +1,6 @@
define([
'./ApproximateTerrainHeights',
+ './ArcType',
'./arrayRemoveDuplicates',
'./BoundingSphere',
'./Cartesian3',
@@ -13,6 +14,7 @@ define([
'./defineProperties',
'./Ellipsoid',
'./EllipsoidGeodesic',
+ './EllipsoidRhumbLine',
'./EncodedCartesian3',
'./GeographicProjection',
'./Geometry',
@@ -25,6 +27,7 @@ define([
'./WebMercatorProjection'
], function(
ApproximateTerrainHeights,
+ ArcType,
arrayRemoveDuplicates,
BoundingSphere,
Cartesian3,
@@ -38,6 +41,7 @@ define([
defineProperties,
Ellipsoid,
EllipsoidGeodesic,
+ EllipsoidRhumbLine,
EncodedCartesian3,
GeographicProjection,
Geometry,
@@ -80,6 +84,7 @@ define([
* @param {Number} [options.width=1.0] The screen space width in pixels.
* @param {Number} [options.granularity=9999.0] The distance interval in meters used for interpolating options.points. Defaults to 9999.0 meters. Zero indicates no interpolation.
* @param {Boolean} [options.loop=false] Whether during geometry creation a line segment will be added between the last and first line positions to make this Polyline a loop.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
*
* @exception {DeveloperError} At least two positions are required.
*
@@ -104,6 +109,9 @@ define([
if ((!defined(positions)) || (positions.length < 2)) {
throw new DeveloperError('At least two positions are required.');
}
+ if (defined(options.arcType) && options.arcType !== ArcType.GEODESIC && options.arcType !== ArcType.RHUMB) {
+ throw new DeveloperError('Valid options for arcType are ArcType.GEODESIC and ArcType.RHUMB.');
+ }
//>>includeEnd('debug');
/**
@@ -130,6 +138,13 @@ define([
*/
this.loop = defaultValue(options.loop, false);
+ /**
+ * The type of path the polyline must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
+ * @type {ArcType}
+ * @default ArcType.GEODESIC
+ */
+ this.arcType = defaultValue(options.arcType, ArcType.GEODESIC);
+
this._ellipsoid = Ellipsoid.WGS84;
// MapProjections can't be packed, so store the index to a known MapProjection.
@@ -150,7 +165,7 @@ define([
*/
packedLength: {
get: function() {
- return 1.0 + this._positions.length * 3 + 1.0 + 1.0 + Ellipsoid.packedLength + 1.0 + 1.0;
+ return 1.0 + this._positions.length * 3 + 1.0 + 1.0 + 1.0 + Ellipsoid.packedLength + 1.0 + 1.0;
}
}
});
@@ -195,12 +210,19 @@ define([
var interpolatedBottomScratch = new Cartesian3();
var interpolatedTopScratch = new Cartesian3();
var interpolatedNormalScratch = new Cartesian3();
- function interpolateSegment(start, end, minHeight, maxHeight, granularity, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray) {
+ function interpolateSegment(start, end, minHeight, maxHeight, granularity, arcType, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray) {
if (granularity === 0.0) {
return;
}
- var ellipsoidGeodesic = new EllipsoidGeodesic(start, end, ellipsoid);
- var surfaceDistance = ellipsoidGeodesic.surfaceDistance;
+
+ var ellipsoidLine;
+ if (arcType === ArcType.GEODESIC) {
+ ellipsoidLine = new EllipsoidGeodesic(start, end, ellipsoid);
+ } else if (arcType === ArcType.RHUMB) {
+ ellipsoidLine = new EllipsoidRhumbLine(start, end, ellipsoid);
+ }
+
+ var surfaceDistance = ellipsoidLine.surfaceDistance;
if (surfaceDistance < granularity) {
return;
}
@@ -214,7 +236,7 @@ define([
var pointsToAdd = segments - 1;
var packIndex = normalsArray.length;
for (var i = 0; i < pointsToAdd; i++) {
- var interpolatedCartographic = ellipsoidGeodesic.interpolateUsingSurfaceDistance(distanceFromStart, interpolatedCartographicScratch);
+ var interpolatedCartographic = ellipsoidLine.interpolateUsingSurfaceDistance(distanceFromStart, interpolatedCartographicScratch);
var interpolatedBottom = getPosition(ellipsoid, interpolatedCartographic, minHeight, interpolatedBottomScratch);
var interpolatedTop = getPosition(ellipsoid, interpolatedCartographic, maxHeight, interpolatedTopScratch);
@@ -266,6 +288,7 @@ define([
array[index++] = value.granularity;
array[index++] = value.loop ? 1.0 : 0.0;
+ array[index++] = value.arcType;
Ellipsoid.pack(value._ellipsoid, array, index);
index += Ellipsoid.packedLength;
@@ -299,6 +322,7 @@ define([
var granularity = array[index++];
var loop = array[index++] === 1.0;
+ var arcType = array[index++];
var ellipsoid = Ellipsoid.unpack(array, index);
index += Ellipsoid.packedLength;
@@ -311,6 +335,7 @@ define([
positions : positions,
granularity : granularity,
loop : loop,
+ arcType : arcType,
ellipsoid : ellipsoid
});
geometry._projectionIndex = projectionIndex;
@@ -321,6 +346,7 @@ define([
result._positions = positions;
result.granularity = granularity;
result.loop = loop;
+ result.arcType = arcType;
result._ellipsoid = ellipsoid;
result._projectionIndex = projectionIndex;
result._scene3DOnly = scene3DOnly;
@@ -384,6 +410,9 @@ define([
var nextBottomScratch = new Cartesian3();
var vertexNormalScratch = new Cartesian3();
var intersectionScratch = new Cartesian3();
+ var cartographicScratch0 = new Cartographic();
+ var cartographicScratch1 = new Cartographic();
+ var cartographicIntersectionScratch = new Cartographic();
/**
* Computes shadow volumes for the ground polyline, consisting of its vertices, indices, and a bounding sphere.
* Vertices are "fat," packing all the data needed in each volume to describe a line on terrain or 3D Tiles.
@@ -397,6 +426,7 @@ define([
var loop = groundPolylineGeometry.loop;
var ellipsoid = groundPolylineGeometry._ellipsoid;
var granularity = groundPolylineGeometry.granularity;
+ var arcType = groundPolylineGeometry.arcType;
var projection = new PROJECTIONS[groundPolylineGeometry._projectionIndex](ellipsoid);
var minHeight = WALL_INITIAL_MIN_HEIGHT;
@@ -417,7 +447,12 @@ define([
// may get split by the plane of IDL + Prime Meridian.
var p0;
var p1;
+ var c0;
+ var c1;
+ var rhumbLine = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);
var intersection;
+ var intersectionCartographic;
+ var intersectionLongitude;
var splitPositions = [positions[0]];
for (i = 0; i < positionsLength - 1; i++) {
p0 = positions[i];
@@ -426,7 +461,21 @@ define([
if (defined(intersection) &&
!Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&
!Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)) {
- splitPositions.push(Cartesian3.clone(intersection));
+ if (groundPolylineGeometry.arcType === ArcType.GEODESIC) {
+ splitPositions.push(Cartesian3.clone(intersection));
+ } else if (groundPolylineGeometry.arcType === ArcType.RHUMB) {
+ intersectionLongitude = ellipsoid.cartesianToCartographic(intersection, cartographicScratch0).longitude;
+ c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);
+ c1 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);
+ rhumbLine.setEndPoints(c0, c1);
+ intersectionCartographic = rhumbLine.findIntersectionWithLongitude(intersectionLongitude, cartographicIntersectionScratch);
+ intersection = ellipsoid.cartographicToCartesian(intersectionCartographic, intersectionScratch);
+ if (defined(intersection) &&
+ !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&
+ !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)) {
+ splitPositions.push(Cartesian3.clone(intersection));
+ }
+ }
}
splitPositions.push(p1);
}
@@ -438,7 +487,21 @@ define([
if (defined(intersection) &&
!Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&
!Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)) {
- splitPositions.push(Cartesian3.clone(intersection));
+ if (groundPolylineGeometry.arcType === ArcType.GEODESIC) {
+ splitPositions.push(Cartesian3.clone(intersection));
+ } else if (groundPolylineGeometry.arcType === ArcType.RHUMB) {
+ intersectionLongitude = ellipsoid.cartesianToCartographic(intersection, cartographicScratch0).longitude;
+ c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);
+ c1 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);
+ rhumbLine.setEndPoints(c0, c1);
+ intersectionCartographic = rhumbLine.findIntersectionWithLongitude(intersectionLongitude, cartographicIntersectionScratch);
+ intersection = ellipsoid.cartographicToCartesian(intersectionCartographic, intersectionScratch);
+ if (defined(intersection) &&
+ !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&
+ !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)) {
+ splitPositions.push(Cartesian3.clone(intersection));
+ }
+ }
}
}
var cartographicsLength = splitPositions.length;
@@ -495,7 +558,7 @@ define([
cartographicsArray.push(startCartographic.latitude);
cartographicsArray.push(startCartographic.longitude);
- interpolateSegment(startCartographic, nextCartographic, minHeight, maxHeight, granularity, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
+ interpolateSegment(startCartographic, nextCartographic, minHeight, maxHeight, granularity, arcType, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
// All inbetween points
for (i = 1; i < cartographicsLength - 1; ++i) {
@@ -514,7 +577,7 @@ define([
cartographicsArray.push(vertexCartographic.latitude);
cartographicsArray.push(vertexCartographic.longitude);
- interpolateSegment(cartographics[i], cartographics[i + 1], minHeight, maxHeight, granularity, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
+ interpolateSegment(cartographics[i], cartographics[i + 1], minHeight, maxHeight, granularity, arcType, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
}
// Last point - either loop or attach a normal "perpendicular" to the wall.
@@ -542,7 +605,7 @@ define([
cartographicsArray.push(endCartographic.longitude);
if (loop) {
- interpolateSegment(endCartographic, startCartographic, minHeight, maxHeight, granularity, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
+ interpolateSegment(endCartographic, startCartographic, minHeight, maxHeight, granularity, arcType, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray);
index = normalsArray.length;
for (i = 0; i < 3; ++i) {
normalsArray[index + i] = normalsArray[i];
diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js
index c91026befa5c..b6cb3d35a7ee 100644
--- a/Source/Core/PolygonGeometry.js
+++ b/Source/Core/PolygonGeometry.js
@@ -1,4 +1,5 @@
define([
+ './ArcType',
'./arrayFill',
'./BoundingRectangle',
'./BoundingSphere',
@@ -29,6 +30,7 @@ define([
'./VertexFormat',
'./WindingOrder'
], function(
+ ArcType,
arrayFill,
BoundingRectangle,
BoundingSphere,
@@ -386,14 +388,14 @@ define([
var createGeometryFromPositionsExtrudedPositions = [];
- function createGeometryFromPositionsExtruded(ellipsoid, polygon, granularity, hierarchy, perPositionHeight, closeTop, closeBottom, vertexFormat) {
+ function createGeometryFromPositionsExtruded(ellipsoid, polygon, granularity, hierarchy, perPositionHeight, closeTop, closeBottom, vertexFormat, arcType) {
var geos = {
walls : []
};
var i;
if (closeTop || closeBottom) {
- var topGeo = PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, polygon, granularity, perPositionHeight, vertexFormat);
+ var topGeo = PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, polygon, granularity, perPositionHeight, vertexFormat, arcType);
var edgePoints = topGeo.attributes.position.values;
var indices = topGeo.indices;
@@ -455,7 +457,7 @@ define([
outerRing = outerRing.slice().reverse();
}
- var wallGeo = PolygonGeometryLibrary.computeWallGeometry(outerRing, ellipsoid, granularity, perPositionHeight);
+ var wallGeo = PolygonGeometryLibrary.computeWallGeometry(outerRing, ellipsoid, granularity, perPositionHeight, arcType);
geos.walls.push(new GeometryInstance({
geometry : wallGeo
}));
@@ -472,7 +474,7 @@ define([
hole = hole.slice().reverse();
}
- wallGeo = PolygonGeometryLibrary.computeWallGeometry(hole, ellipsoid, granularity);
+ wallGeo = PolygonGeometryLibrary.computeWallGeometry(hole, ellipsoid, granularity, perPositionHeight, arcType);
geos.walls.push(new GeometryInstance({
geometry : wallGeo
}));
@@ -498,6 +500,7 @@ define([
* @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
* @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.
* @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.
+ * @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}.
*
* @see PolygonGeometry#createGeometry
* @see PolygonGeometry#fromPositions
@@ -578,6 +581,9 @@ define([
if (defined(options.perPositionHeight) && options.perPositionHeight && defined(options.height)) {
throw new DeveloperError('Cannot use both options.perPositionHeight and options.height');
}
+ if (defined(options.arcType) && options.arcType !== ArcType.GEODESIC && options.arcType !== ArcType.RHUMB) {
+ throw new DeveloperError('Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.');
+ }
//>>includeEnd('debug');
var polygonHierarchy = options.polygonHierarchy;
@@ -610,6 +616,7 @@ define([
this._shadowVolume = defaultValue(options.shadowVolume, false);
this._workerName = 'createPolygonGeometry';
this._offsetAttribute = options.offsetAttribute;
+ this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);
this._rectangle = undefined;
this._textureCoordinateRotationPoints = undefined;
@@ -618,7 +625,7 @@ define([
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + 11;
+ this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + 12;
}
/**
@@ -635,6 +642,7 @@ define([
* @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
* @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.
* @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.
+ * @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}.
* @returns {PolygonGeometry}
*
*
@@ -673,7 +681,8 @@ define([
perPositionHeight : options.perPositionHeight,
closeTop : options.closeTop,
closeBottom : options.closeBottom,
- offsetAttribute : options.offsetAttribute
+ offsetAttribute : options.offsetAttribute,
+ arcType : options.arcType
};
return new PolygonGeometry(newOptions);
};
@@ -713,6 +722,7 @@ define([
array[startingIndex++] = value._closeBottom ? 1.0 : 0.0;
array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;
array[startingIndex++] = defaultValue(value._offsetAttribute, -1);
+ array[startingIndex++] = value._arcType;
array[startingIndex] = value.packedLength;
return array;
@@ -760,6 +770,7 @@ define([
var closeBottom = array[startingIndex++] === 1.0;
var shadowVolume = array[startingIndex++] === 1.0;
var offsetAttribute = array[startingIndex++];
+ var arcType = array[startingIndex++];
var packedLength = array[startingIndex];
if (!defined(result)) {
@@ -779,6 +790,7 @@ define([
result._closeBottom = closeBottom;
result._shadowVolume = shadowVolume;
result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
+ result._arcType = arcType;
result.packedLength = packedLength;
return result;
};
@@ -820,6 +832,7 @@ define([
var perPositionHeight = polygonGeometry._perPositionHeight;
var closeTop = polygonGeometry._closeTop;
var closeBottom = polygonGeometry._closeBottom;
+ var arcType = polygonGeometry._arcType;
var outerPositions = polygonHierarchy.positions;
if (outerPositions.length < 3) {
@@ -856,7 +869,8 @@ define([
bottom: false,
top: true,
wall: false,
- extrude: false
+ extrude: false,
+ arcType: arcType
};
var i;
@@ -868,7 +882,7 @@ define([
options.shadowVolume = polygonGeometry._shadowVolume;
options.offsetAttribute = polygonGeometry._offsetAttribute;
for (i = 0; i < polygons.length; i++) {
- var splitGeometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom, vertexFormat);
+ var splitGeometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom, vertexFormat, arcType);
var topAndBottom;
if (closeTop && closeBottom) {
@@ -901,7 +915,7 @@ define([
} else {
for (i = 0; i < polygons.length; i++) {
var geometryInstance = new GeometryInstance({
- geometry : PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, polygons[i], granularity, perPositionHeight, vertexFormat)
+ geometry : PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, polygons[i], granularity, perPositionHeight, vertexFormat, arcType)
});
geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometryInstance.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
options.geometry = geometryInstance.geometry;
@@ -962,7 +976,8 @@ define([
extrudedHeight : minHeight,
height : maxHeight,
vertexFormat : VertexFormat.POSITION_ONLY,
- shadowVolume: true
+ shadowVolume: true,
+ arcType : polygonGeometry._arcType
});
};
diff --git a/Source/Core/PolygonGeometryLibrary.js b/Source/Core/PolygonGeometryLibrary.js
index 7bdd83da721a..5d8142a450c1 100644
--- a/Source/Core/PolygonGeometryLibrary.js
+++ b/Source/Core/PolygonGeometryLibrary.js
@@ -1,11 +1,15 @@
define([
+ './ArcType',
'./arrayRemoveDuplicates',
'./Cartesian2',
'./Cartesian3',
+ './Cartographic',
'./ComponentDatatype',
'./defaultValue',
'./defined',
+ './DeveloperError',
'./Ellipsoid',
+ './EllipsoidRhumbLine',
'./Geometry',
'./GeometryAttribute',
'./GeometryAttributes',
@@ -19,13 +23,17 @@ define([
'./Queue',
'./WindingOrder'
], function(
+ ArcType,
arrayRemoveDuplicates,
Cartesian2,
Cartesian3,
+ Cartographic,
ComponentDatatype,
defaultValue,
defined,
+ DeveloperError,
Ellipsoid,
+ EllipsoidRhumbLine,
Geometry,
GeometryAttribute,
GeometryAttributes,
@@ -141,7 +149,20 @@ define([
PolygonGeometryLibrary.subdivideLineCount = function(p0, p1, minDistance) {
var distance = Cartesian3.distance(p0, p1);
var n = distance / minDistance;
- var countDivide = Math.max(0, Math.ceil(Math.log(n) / Math.log(2)));
+ var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
+ return Math.pow(2, countDivide);
+ };
+
+ var scratchCartographic0 = new Cartographic();
+ var scratchCartographic1 = new Cartographic();
+ var scratchCartographic2 = new Cartographic();
+ var scratchCartesian0 = new Cartesian3();
+ PolygonGeometryLibrary.subdivideRhumbLineCount = function(ellipsoid, p0, p1, minDistance) {
+ var c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
+ var c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
+ var rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
+ var n = rhumb.surfaceDistance / minDistance;
+ var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
return Math.pow(2, countDivide);
};
@@ -168,6 +189,35 @@ define([
return positions;
};
+ PolygonGeometryLibrary.subdivideRhumbLine = function(ellipsoid, p0, p1, minDistance, result) {
+ var c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
+ var c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
+ var rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
+
+ var n = rhumb.surfaceDistance / minDistance;
+ var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
+ var numVertices = Math.pow(2, countDivide);
+ var distanceBetweenVertices = rhumb.surfaceDistance / numVertices;
+
+ if (!defined(result)) {
+ result = [];
+ }
+
+ var positions = result;
+ positions.length = numVertices * 3;
+
+ var index = 0;
+ for ( var i = 0; i < numVertices; i++) {
+ var c = rhumb.interpolateUsingSurfaceDistance(i * distanceBetweenVertices, scratchCartographic2);
+ var p = ellipsoid.cartographicToCartesian(c, scratchCartesian0);
+ positions[index++] = p.x;
+ positions[index++] = p.y;
+ positions[index++] = p.z;
+ }
+
+ return positions;
+ };
+
var scaleToGeodeticHeightN1 = new Cartesian3();
var scaleToGeodeticHeightN2 = new Cartesian3();
var scaleToGeodeticHeightP1 = new Cartesian3();
@@ -403,7 +453,7 @@ define([
return result;
};
- PolygonGeometryLibrary.createGeometryFromPositions = function(ellipsoid, polygon, granularity, perPositionHeight, vertexFormat) {
+ PolygonGeometryLibrary.createGeometryFromPositions = function(ellipsoid, polygon, granularity, perPositionHeight, vertexFormat, arcType) {
var indices = PolygonPipeline.triangulate(polygon.positions2D, polygon.holes);
/* If polygon is completely unrenderable, just use the first three vertices */
@@ -442,14 +492,18 @@ define([
return geometry;
}
- return PolygonPipeline.computeSubdivision(ellipsoid, positions, indices, granularity);
+ if (arcType === ArcType.GEODESIC) {
+ return PolygonPipeline.computeSubdivision(ellipsoid, positions, indices, granularity);
+ } else if (arcType === ArcType.RHUMB) {
+ return PolygonPipeline.computeRhumbLineSubdivision(ellipsoid, positions, indices, granularity);
+ }
};
var computeWallIndicesSubdivided = [];
var p1Scratch = new Cartesian3();
var p2Scratch = new Cartesian3();
- PolygonGeometryLibrary.computeWallGeometry = function(positions, ellipsoid, granularity, perPositionHeight) {
+ PolygonGeometryLibrary.computeWallGeometry = function(positions, ellipsoid, granularity, perPositionHeight, arcType) {
var edgePositions;
var topEdgeLength;
var i;
@@ -463,8 +517,14 @@ define([
var minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
var numVertices = 0;
- for (i = 0; i < length; i++) {
- numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ if (arcType === ArcType.GEODESIC) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ }
+ } else if (arcType === ArcType.RHUMB) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(ellipsoid, positions[i], positions[(i + 1) % length], minDistance);
+ }
}
topEdgeLength = (numVertices + length) * 3;
@@ -473,7 +533,12 @@ define([
p1 = positions[i];
p2 = positions[(i + 1) % length];
- var tempPositions = PolygonGeometryLibrary.subdivideLine(p1, p2, minDistance, computeWallIndicesSubdivided);
+ var tempPositions;
+ if (arcType === ArcType.GEODESIC) {
+ tempPositions = PolygonGeometryLibrary.subdivideLine(p1, p2, minDistance, computeWallIndicesSubdivided);
+ } else if (arcType === ArcType.RHUMB) {
+ tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(ellipsoid, p1, p2, minDistance, computeWallIndicesSubdivided);
+ }
var tempPositionsLength = tempPositions.length;
for (var j = 0; j < tempPositionsLength; ++j, ++index) {
edgePositions[index] = tempPositions[j];
diff --git a/Source/Core/PolygonOutlineGeometry.js b/Source/Core/PolygonOutlineGeometry.js
index 8d7b404a5874..180c19e0dbec 100644
--- a/Source/Core/PolygonOutlineGeometry.js
+++ b/Source/Core/PolygonOutlineGeometry.js
@@ -1,4 +1,5 @@
define([
+ './ArcType',
'./arrayFill',
'./arrayRemoveDuplicates',
'./BoundingSphere',
@@ -24,6 +25,7 @@ define([
'./Queue',
'./WindingOrder'
], function(
+ ArcType,
arrayFill,
arrayRemoveDuplicates,
BoundingSphere,
@@ -52,7 +54,7 @@ define([
var createGeometryFromPositionsPositions = [];
var createGeometryFromPositionsSubdivided = [];
- function createGeometryFromPositions(ellipsoid, positions, minDistance, perPositionHeight) {
+ function createGeometryFromPositions(ellipsoid, positions, minDistance, perPositionHeight, arcType) {
var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);
var positions2D = tangentPlane.projectPointsOntoPlane(positions, createGeometryFromPositionsPositions);
@@ -70,12 +72,23 @@ define([
if (!perPositionHeight) {
var numVertices = 0;
- for (i = 0; i < length; i++) {
- numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ if (arcType === ArcType.GEODESIC) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ }
+ } else if (arcType === ArcType.RHUMB) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(ellipsoid, positions[i], positions[(i + 1) % length], minDistance);
+ }
}
subdividedPositions = new Float64Array(numVertices * 3);
for (i = 0; i < length; i++) {
- var tempPositions = PolygonGeometryLibrary.subdivideLine(positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ var tempPositions;
+ if (arcType === ArcType.GEODESIC) {
+ tempPositions = PolygonGeometryLibrary.subdivideLine(positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ } else if (arcType === ArcType.RHUMB) {
+ tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(ellipsoid, positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ }
var tempPositionsLength = tempPositions.length;
for (var j = 0; j < tempPositionsLength; ++j) {
subdividedPositions[index++] = tempPositions[j];
@@ -121,7 +134,7 @@ define([
});
}
- function createGeometryFromPositionsExtruded(ellipsoid, positions, minDistance, perPositionHeight) {
+ function createGeometryFromPositionsExtruded(ellipsoid, positions, minDistance, perPositionHeight, arcType) {
var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);
var positions2D = tangentPlane.projectPointsOntoPlane(positions, createGeometryFromPositionsPositions);
@@ -140,14 +153,25 @@ define([
if (!perPositionHeight) {
var numVertices = 0;
- for (i = 0; i < length; i++) {
- numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ if (arcType === ArcType.GEODESIC) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance);
+ }
+ } else if (arcType === ArcType.RHUMB) {
+ for (i = 0; i < length; i++) {
+ numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(ellipsoid, positions[i], positions[(i + 1) % length], minDistance);
+ }
}
subdividedPositions = new Float64Array(numVertices * 3 * 2);
for (i = 0; i < length; ++i) {
corners[i] = index / 3;
- var tempPositions = PolygonGeometryLibrary.subdivideLine(positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ var tempPositions;
+ if (arcType === ArcType.GEODESIC) {
+ tempPositions = PolygonGeometryLibrary.subdivideLine(positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ } else if (arcType === ArcType.RHUMB) {
+ tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(ellipsoid, positions[i], positions[(i + 1) % length], minDistance, createGeometryFromPositionsSubdivided);
+ }
var tempPositionsLength = tempPositions.length;
for (var j = 0; j < tempPositionsLength; ++j) {
subdividedPositions[index++] = tempPositions[j];
@@ -218,6 +242,7 @@ define([
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
* @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
* @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
*
* @see PolygonOutlineGeometry#createGeometry
* @see PolygonOutlineGeometry#fromPositions
@@ -297,6 +322,9 @@ define([
if (options.perPositionHeight && defined(options.height)) {
throw new DeveloperError('Cannot use both options.perPositionHeight and options.height');
}
+ if (defined(options.arcType) && options.arcType !== ArcType.GEODESIC && options.arcType !== ArcType.RHUMB) {
+ throw new DeveloperError('Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.');
+ }
//>>includeEnd('debug');
var polygonHierarchy = options.polygonHierarchy;
@@ -304,6 +332,7 @@ define([
var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
var perPositionHeight = defaultValue(options.perPositionHeight, false);
var perPositionHeightExtrude = perPositionHeight && defined(options.extrudedHeight);
+ var arcType = defaultValue(options.arcType, ArcType.GEODESIC);
var height = defaultValue(options.height, 0.0);
var extrudedHeight = defaultValue(options.extrudedHeight, height);
@@ -318,6 +347,7 @@ define([
this._granularity = granularity;
this._height = height;
this._extrudedHeight = extrudedHeight;
+ this._arcType = arcType;
this._polygonHierarchy = polygonHierarchy;
this._perPositionHeight = perPositionHeight;
this._perPositionHeightExtrude = perPositionHeightExtrude;
@@ -328,7 +358,7 @@ define([
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + 7;
+ this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + 8;
}
/**
@@ -358,6 +388,7 @@ define([
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;
array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;
+ array[startingIndex++] = value._arcType;
array[startingIndex++] = defaultValue(value._offsetAttribute, -1);
array[startingIndex] = value.packedLength;
@@ -396,6 +427,7 @@ define([
var granularity = array[startingIndex++];
var perPositionHeightExtrude = array[startingIndex++] === 1.0;
var perPositionHeight = array[startingIndex++] === 1.0;
+ var arcType = array[startingIndex++];
var offsetAttribute = array[startingIndex++];
var packedLength = array[startingIndex];
@@ -410,6 +442,7 @@ define([
result._granularity = granularity;
result._perPositionHeight = perPositionHeight;
result._perPositionHeightExtrude = perPositionHeightExtrude;
+ result._arcType = arcType;
result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
result.packedLength = packedLength;
@@ -426,6 +459,7 @@ define([
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
* @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
* @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link LinkType.GEODESIC} and {@link ArcType.RHUMB}.
* @returns {PolygonOutlineGeometry}
*
*
@@ -460,6 +494,7 @@ define([
ellipsoid : options.ellipsoid,
granularity : options.granularity,
perPositionHeight : options.perPositionHeight,
+ arcType: options.arcType,
offsetAttribute : options.offsetAttribute
};
return new PolygonOutlineGeometry(newOptions);
@@ -476,6 +511,7 @@ define([
var granularity = polygonGeometry._granularity;
var polygonHierarchy = polygonGeometry._polygonHierarchy;
var perPositionHeight = polygonGeometry._perPositionHeight;
+ var arcType = polygonGeometry._arcType;
var polygons = PolygonGeometryLibrary.polygonOutlinesFromHierarchy(polygonHierarchy, !perPositionHeight, ellipsoid);
@@ -494,7 +530,7 @@ define([
var i;
if (extrude) {
for (i = 0; i < polygons.length; i++) {
- geometryInstance = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], minDistance, perPositionHeight);
+ geometryInstance = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], minDistance, perPositionHeight, arcType);
geometryInstance.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(geometryInstance.geometry, height, extrudedHeight, ellipsoid, perPositionHeight);
if (defined(polygonGeometry._offsetAttribute)) {
var size = geometryInstance.geometry.attributes.position.values.length / 3;
@@ -516,7 +552,7 @@ define([
}
} else {
for (i = 0; i < polygons.length; i++) {
- geometryInstance = createGeometryFromPositions(ellipsoid, polygons[i], minDistance, perPositionHeight);
+ geometryInstance = createGeometryFromPositions(ellipsoid, polygons[i], minDistance, perPositionHeight, arcType);
geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometryInstance.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
if (defined(polygonGeometry._offsetAttribute)) {
diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js
index 00b3849b00e4..cd59af0c3530 100644
--- a/Source/Core/PolygonPipeline.js
+++ b/Source/Core/PolygonPipeline.js
@@ -2,6 +2,7 @@ define([
'../ThirdParty/earcut-2.1.1',
'./Cartesian2',
'./Cartesian3',
+ './Cartographic',
'./Check',
'./ComponentDatatype',
'./defaultValue',
@@ -16,6 +17,7 @@ define([
earcut,
Cartesian2,
Cartesian3,
+ Cartographic,
Check,
ComponentDatatype,
defaultValue,
@@ -227,6 +229,158 @@ define([
});
};
+ var subdivisionC0Scratch = new Cartographic();
+ var subdivisionC1Scratch = new Cartographic();
+ var subdivisionC2Scratch = new Cartographic();
+ var subdivisionCart2Scratch0 = new Cartesian2();
+ var subdivisionCart2Scratch1 = new Cartesian2();
+ var subdivisionCart2Scratch2 = new Cartesian2();
+ var subdivisionMidCart2Scratch = new Cartesian2();
+
+ /**
+ * Subdivides positions on rhumb lines and raises points to the surface of the ellipsoid.
+ *
+ * @param {Ellipsoid} ellipsoid The ellipsoid the polygon in on.
+ * @param {Cartesian3[]} positions An array of {@link Cartesian3} positions of the polygon.
+ * @param {Number[]} indices An array of indices that determines the triangles in the polygon.
+ * @param {Number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
+ *
+ * @exception {DeveloperError} At least three indices are required.
+ * @exception {DeveloperError} The number of indices must be divisable by three.
+ * @exception {DeveloperError} Granularity must be greater than zero.
+ */
+ PolygonPipeline.computeRhumbLineSubdivision = function(ellipsoid, positions, indices, granularity) {
+ granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE);
+
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ Check.defined('positions', positions);
+ Check.defined('indices', indices);
+ Check.typeOf.number.greaterThanOrEquals('indices.length', indices.length, 3);
+ Check.typeOf.number.equals('indices.length % 3', '0', indices.length % 3, 0);
+ Check.typeOf.number.greaterThan('granularity', granularity, 0.0);
+ //>>includeEnd('debug');
+
+ // triangles that need (or might need) to be subdivided.
+ var triangles = indices.slice(0);
+
+ // New positions due to edge splits are appended to the positions list.
+ var i;
+ var length = positions.length;
+ var subdividedPositions = new Array(length * 3);
+ var q = 0;
+ for (i = 0; i < length; i++) {
+ var item = positions[i];
+ subdividedPositions[q++] = item.x;
+ subdividedPositions[q++] = item.y;
+ subdividedPositions[q++] = item.z;
+ }
+
+ var subdividedIndices = [];
+
+ // Used to make sure shared edges are not split more than once.
+ var edges = {};
+
+ var granularitySqrd = granularity * granularity;
+
+ while (triangles.length > 0) {
+ var i2 = triangles.pop();
+ var i1 = triangles.pop();
+ var i0 = triangles.pop();
+
+ var v0 = Cartesian3.fromArray(subdividedPositions, i0 * 3, subdivisionV0Scratch);
+ var v1 = Cartesian3.fromArray(subdividedPositions, i1 * 3, subdivisionV1Scratch);
+ var v2 = Cartesian3.fromArray(subdividedPositions, i2 * 3, subdivisionV2Scratch);
+
+ var c0 = ellipsoid.cartesianToCartographic(v0, subdivisionC0Scratch);
+ var c1 = ellipsoid.cartesianToCartographic(v1, subdivisionC1Scratch);
+ var c2 = ellipsoid.cartesianToCartographic(v2, subdivisionC2Scratch);
+
+ var c0Cart2 = Cartesian2.fromElements(c0.longitude, c0.latitude, subdivisionCart2Scratch0);
+ var c1Cart2 = Cartesian2.fromElements(c1.longitude, c1.latitude, subdivisionCart2Scratch1);
+ var c2Cart2 = Cartesian2.fromElements(c2.longitude, c2.latitude, subdivisionCart2Scratch2);
+
+ var g0 = Cartesian2.distanceSquared(c0Cart2, c1Cart2);
+ var g1 = Cartesian2.distanceSquared(c1Cart2, c2Cart2);
+ var g2 = Cartesian2.distanceSquared(c2Cart2, c0Cart2);
+
+ var max = Math.max(g0, g1, g2);
+ var edge;
+ var mid;
+ var midHeight;
+ var midCartesian3;
+
+ // if the max length squared of a triangle edge is greater than squared granularity, subdivide the triangle
+ if (max > granularitySqrd) {
+ if (g0 === max) {
+ edge = Math.min(i0, i1) + ' ' + Math.max(i0, i1);
+
+ i = edges[edge];
+ if (!defined(i)) {
+ mid = Cartesian2.add(c0Cart2, c1Cart2, subdivisionMidCart2Scratch);
+ Cartesian2.multiplyByScalar(mid, 0.5, mid);
+ midHeight = (c0.height + c1.height) * 0.5;
+ midCartesian3 = Cartesian3.fromRadians(mid.x, mid.y, midHeight, ellipsoid, subdivisionMidScratch);
+ subdividedPositions.push(midCartesian3.x, midCartesian3.y, midCartesian3.z);
+ i = subdividedPositions.length / 3 - 1;
+ edges[edge] = i;
+ }
+
+ triangles.push(i0, i, i2);
+ triangles.push(i, i1, i2);
+ } else if (g1 === max) {
+ edge = Math.min(i1, i2) + ' ' + Math.max(i1, i2);
+
+ i = edges[edge];
+ if (!defined(i)) {
+ mid = Cartesian2.add(c1Cart2, c2Cart2, subdivisionMidCart2Scratch);
+ Cartesian2.multiplyByScalar(mid, 0.5, mid);
+ midHeight = (c1.height + c2.height) * 0.5;
+ midCartesian3 = Cartesian3.fromRadians(mid.x, mid.y, midHeight, ellipsoid, subdivisionMidScratch);
+ subdividedPositions.push(midCartesian3.x, midCartesian3.y, midCartesian3.z);
+ i = subdividedPositions.length / 3 - 1;
+ edges[edge] = i;
+ }
+
+ triangles.push(i1, i, i0);
+ triangles.push(i, i2, i0);
+ } else if (g2 === max) {
+ edge = Math.min(i2, i0) + ' ' + Math.max(i2, i0);
+
+ i = edges[edge];
+ if (!defined(i)) {
+ mid = Cartesian2.add(c2Cart2, c0Cart2, subdivisionMidCart2Scratch);
+ Cartesian2.multiplyByScalar(mid, 0.5, mid);
+ midHeight = (c2.height + c0.height) * 0.5;
+ midCartesian3 = Cartesian3.fromRadians(mid.x, mid.y, midHeight, ellipsoid, subdivisionMidScratch);
+ subdividedPositions.push(midCartesian3.x, midCartesian3.y, midCartesian3.z);
+ i = subdividedPositions.length / 3 - 1;
+ edges[edge] = i;
+ }
+
+ triangles.push(i2, i, i1);
+ triangles.push(i, i0, i1);
+ }
+ } else {
+ subdividedIndices.push(i0);
+ subdividedIndices.push(i1);
+ subdividedIndices.push(i2);
+ }
+ }
+
+ return new Geometry({
+ attributes : {
+ position : new GeometryAttribute({
+ componentDatatype : ComponentDatatype.DOUBLE,
+ componentsPerAttribute : 3,
+ values : subdividedPositions
+ })
+ },
+ indices : subdividedIndices,
+ primitiveType : PrimitiveType.TRIANGLES
+ });
+ };
+
/**
* Scales each position of a geometry's position attribute to a height, in place.
*
diff --git a/Source/Core/PolylineGeometry.js b/Source/Core/PolylineGeometry.js
index c2c76de00730..a4232b8833e4 100644
--- a/Source/Core/PolylineGeometry.js
+++ b/Source/Core/PolylineGeometry.js
@@ -1,4 +1,5 @@
define([
+ './ArcType',
'./arrayRemoveDuplicates',
'./BoundingSphere',
'./Cartesian3',
@@ -6,6 +7,7 @@ define([
'./ComponentDatatype',
'./defaultValue',
'./defined',
+ './deprecationWarning',
'./DeveloperError',
'./Ellipsoid',
'./Geometry',
@@ -18,6 +20,7 @@ define([
'./PrimitiveType',
'./VertexFormat'
], function(
+ ArcType,
arrayRemoveDuplicates,
BoundingSphere,
Cartesian3,
@@ -25,6 +28,7 @@ define([
ComponentDatatype,
defaultValue,
defined,
+ deprecationWarning,
DeveloperError,
Ellipsoid,
Geometry,
@@ -87,8 +91,8 @@ define([
* @param {Number} [options.width=1.0] The width in pixels.
* @param {Color[]} [options.colors] An Array of {@link Color} defining the per vertex or per segment colors.
* @param {Boolean} [options.colorsPerVertex=false] A boolean that determines whether the colors will be flat across each segment of the line or interpolated across the vertices.
- * @param {Boolean} [options.followSurface=true] A boolean that determines whether positions will be adjusted to the surface of the ellipsoid via a great arc.
- * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.followSurface=true. Determines the number of positions in the buffer.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.
+ * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.arcType is not ArcType.NONE. Determines the number of positions in the buffer.
* @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
*
@@ -136,7 +140,15 @@ define([
this._width = width;
this._colorsPerVertex = colorsPerVertex;
this._vertexFormat = VertexFormat.clone(defaultValue(options.vertexFormat, VertexFormat.DEFAULT));
+
this._followSurface = defaultValue(options.followSurface, true);
+ if (defined(options.followSurface)) {
+ deprecationWarning('PolylineGeometry.followSurface', 'PolylineGeometry.followSurface is deprecated and will be removed in Cesium 1.55. Use PolylineGeometry.arcType instead.');
+ options.arcType = options.followSurface ? ArcType.GEODESIC : ArcType.NONE;
+ }
+ this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);
+ this._followSurface = (this._arcType !== ArcType.NONE);
+
this._granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
this._ellipsoid = Ellipsoid.clone(defaultValue(options.ellipsoid, Ellipsoid.WGS84));
this._workerName = 'createPolylineGeometry';
@@ -198,7 +210,7 @@ define([
array[startingIndex++] = value._width;
array[startingIndex++] = value._colorsPerVertex ? 1.0 : 0.0;
- array[startingIndex++] = value._followSurface ? 1.0 : 0.0;
+ array[startingIndex++] = value._arcType;
array[startingIndex] = value._granularity;
return array;
@@ -213,7 +225,7 @@ define([
vertexFormat : scratchVertexFormat,
width : undefined,
colorsPerVertex : undefined,
- followSurface : undefined,
+ arcType : undefined,
granularity : undefined
};
@@ -258,7 +270,7 @@ define([
var width = array[startingIndex++];
var colorsPerVertex = array[startingIndex++] === 1.0;
- var followSurface = array[startingIndex++] === 1.0;
+ var arcType = array[startingIndex++];
var granularity = array[startingIndex];
if (!defined(result)) {
@@ -266,7 +278,7 @@ define([
scratchOptions.colors = colors;
scratchOptions.width = width;
scratchOptions.colorsPerVertex = colorsPerVertex;
- scratchOptions.followSurface = followSurface;
+ scratchOptions.arcType = arcType;
scratchOptions.granularity = granularity;
return new PolylineGeometry(scratchOptions);
}
@@ -277,7 +289,7 @@ define([
result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);
result._width = width;
result._colorsPerVertex = colorsPerVertex;
- result._followSurface = followSurface;
+ result._arcType = arcType;
result._granularity = granularity;
return result;
@@ -299,7 +311,7 @@ define([
var vertexFormat = polylineGeometry._vertexFormat;
var colors = polylineGeometry._colors;
var colorsPerVertex = polylineGeometry._colorsPerVertex;
- var followSurface = polylineGeometry._followSurface;
+ var arcType = polylineGeometry._arcType;
var granularity = polylineGeometry._granularity;
var ellipsoid = polylineGeometry._ellipsoid;
@@ -316,14 +328,23 @@ define([
return undefined;
}
- if (followSurface) {
+ if (arcType === ArcType.GEODESIC || arcType === ArcType.RHUMB) {
+ var subdivisionSize;
+ var numberOfPointsFunction;
+ if (arcType === ArcType.GEODESIC) {
+ subdivisionSize = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
+ numberOfPointsFunction = PolylinePipeline.numberOfPoints;
+ } else {
+ subdivisionSize = granularity;
+ numberOfPointsFunction = PolylinePipeline.numberOfPointsRhumbLine;
+ }
+
var heights = PolylinePipeline.extractHeights(positions, ellipsoid);
- var minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
if (defined(colors)) {
var colorLength = 1;
for (i = 0; i < positionsLength - 1; ++i) {
- colorLength += PolylinePipeline.numberOfPoints(positions[i], positions[i+1], minDistance);
+ colorLength += numberOfPointsFunction(positions[i], positions[i + 1], subdivisionSize);
}
var newColors = new Array(colorLength);
@@ -331,12 +352,12 @@ define([
for (i = 0; i < positionsLength - 1; ++i) {
var p0 = positions[i];
- var p1 = positions[i+1];
+ var p1 = positions[i + 1];
var c0 = colors[i];
- var numColors = PolylinePipeline.numberOfPoints(p0, p1, minDistance);
+ var numColors = numberOfPointsFunction(p0, p1, subdivisionSize);
if (colorsPerVertex && i < colorLength) {
- var c1 = colors[i+1];
+ var c1 = colors[i + 1];
var interpolatedColors = interpolateColors(p0, p1, c0, c1, numColors);
var interpolatedColorsLength = interpolatedColors.length;
for (j = 0; j < interpolatedColorsLength; ++j) {
@@ -349,18 +370,27 @@ define([
}
}
- newColors[newColorIndex] = Color.clone(colors[colors.length-1]);
+ newColors[newColorIndex] = Color.clone(colors[colors.length - 1]);
colors = newColors;
scratchInterpolateColorsArray.length = 0;
}
- positions = PolylinePipeline.generateCartesianArc({
- positions: positions,
- minDistance: minDistance,
- ellipsoid: ellipsoid,
- height: heights
- });
+ if (arcType === ArcType.GEODESIC) {
+ positions = PolylinePipeline.generateCartesianArc({
+ positions: positions,
+ minDistance: subdivisionSize,
+ ellipsoid: ellipsoid,
+ height: heights
+ });
+ } else {
+ positions = PolylinePipeline.generateCartesianRhumbArc({
+ positions: positions,
+ granularity: subdivisionSize,
+ ellipsoid: ellipsoid,
+ height: heights
+ });
+ }
}
positionsLength = positions.length;
diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js
index d1da46883445..4c54a8d2c6cc 100644
--- a/Source/Core/PolylinePipeline.js
+++ b/Source/Core/PolylinePipeline.js
@@ -6,6 +6,7 @@ define([
'./DeveloperError',
'./Ellipsoid',
'./EllipsoidGeodesic',
+ './EllipsoidRhumbLine',
'./IntersectionTests',
'./isArray',
'./Math',
@@ -19,6 +20,7 @@ define([
DeveloperError,
Ellipsoid,
EllipsoidGeodesic,
+ EllipsoidRhumbLine,
IntersectionTests,
isArray,
CesiumMath,
@@ -36,6 +38,11 @@ define([
return Math.ceil(distance / minDistance);
};
+ PolylinePipeline.numberOfPointsRhumbLine = function(p0, p1, granularity) {
+ var radiansDistanceSquared = Math.pow((p0.longitude - p1.longitude), 2) + Math.pow((p0.latitude - p1.latitude), 2);
+ return Math.ceil(Math.sqrt(radiansDistanceSquared / (granularity * granularity)));
+ };
+
var cartoScratch = new Cartographic();
PolylinePipeline.extractHeights = function(positions, ellipsoid) {
var length = positions.length;
@@ -87,6 +94,7 @@ define([
var scaleFirst = new Cartesian3();
var scaleLast = new Cartesian3();
var ellipsoidGeodesic = new EllipsoidGeodesic();
+ var ellipsoidRhumb = new EllipsoidRhumbLine();
//Returns subdivided line scaled to ellipsoid surface starting at p1 and ending at p2.
//Result includes p1, but not include p2. This function is called for a sequence of line segments,
@@ -119,6 +127,41 @@ define([
return index;
}
+ //Returns subdivided line scaled to ellipsoid surface starting at p1 and ending at p2.
+ //Result includes p1, but not include p2. This function is called for a sequence of line segments,
+ //and this prevents duplication of end point.
+ function generateCartesianRhumbArc(p0, p1, granularity, ellipsoid, h0, h1, array, offset) {
+ var first = ellipsoid.scaleToGeodeticSurface(p0, scaleFirst);
+ var last = ellipsoid.scaleToGeodeticSurface(p1, scaleLast);
+ var start = ellipsoid.cartesianToCartographic(first, carto1);
+ var end = ellipsoid.cartesianToCartographic(last, carto2);
+
+ var numPoints = PolylinePipeline.numberOfPointsRhumbLine(start, end, granularity);
+ var heights = subdivideHeights(numPoints, h0, h1);
+
+ if (!ellipsoidRhumb.ellipsoid.equals(ellipsoid)) {
+ ellipsoidRhumb = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);
+ }
+ ellipsoidRhumb.setEndPoints(start, end);
+ var surfaceDistanceBetweenPoints = ellipsoidRhumb.surfaceDistance / numPoints;
+
+ var index = offset;
+ start.height = h0;
+ var cart = ellipsoid.cartographicToCartesian(start, cartesian);
+ Cartesian3.pack(cart, array, index);
+ index += 3;
+
+ for (var i = 1; i < numPoints; i++) {
+ var carto = ellipsoidRhumb.interpolateUsingSurfaceDistance(i * surfaceDistanceBetweenPoints, carto2);
+ carto.height = heights[i];
+ cart = ellipsoid.cartographicToCartesian(carto, cartesian);
+ Cartesian3.pack(cart, array, index);
+ index += 3;
+ }
+
+ return index;
+ }
+
/**
* Breaks a {@link Polyline} into segments such that it does not cross the ±180 degree meridian of an ellipsoid.
*
@@ -287,6 +330,97 @@ define([
return newPositions;
};
+ var scratchCartographic0 = new Cartographic();
+ var scratchCartographic1 = new Cartographic();
+
+ /**
+ * Subdivides polyline and raises all points to the specified height using Rhumb lines. Returns an array of numbers to represent the positions.
+ * @param {Object} options Object with the following properties:
+ * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.
+ * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.
+ * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
+ * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.
+ * @returns {Number[]} A new array of positions of type {Number} that have been subdivided and raised to the surface of the ellipsoid.
+ *
+ * @example
+ * var positions = Cesium.Cartesian3.fromDegreesArray([
+ * -105.0, 40.0,
+ * -100.0, 38.0,
+ * -105.0, 35.0,
+ * -100.0, 32.0
+ * ]);
+ * var surfacePositions = Cesium.PolylinePipeline.generateRhumbArc({
+ * positons: positions
+ * });
+ */
+ PolylinePipeline.generateRhumbArc = function(options) {
+ if (!defined(options)) {
+ options = {};
+ }
+ var positions = options.positions;
+ //>>includeStart('debug', pragmas.debug);
+ if (!defined(positions)) {
+ throw new DeveloperError('options.positions is required.');
+ }
+ //>>includeEnd('debug');
+
+ var length = positions.length;
+ var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
+ var height = defaultValue(options.height, 0);
+ var hasHeightArray = isArray(height);
+
+ if (length < 1) {
+ return [];
+ } else if (length === 1) {
+ var p = ellipsoid.scaleToGeodeticSurface(positions[0], scaleFirst);
+ height = hasHeightArray ? height[0] : height;
+ if (height !== 0) {
+ var n = ellipsoid.geodeticSurfaceNormal(p, cartesian);
+ Cartesian3.multiplyByScalar(n, height, n);
+ Cartesian3.add(p, n, p);
+ }
+
+ return [p.x, p.y, p.z];
+ }
+
+ var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
+
+ var numPoints = 0;
+ var i;
+
+ var c0 = ellipsoid.cartesianToCartographic(positions[0], scratchCartographic0);
+ var c1;
+ for (i = 0; i < length - 1; i++) {
+ c1 = ellipsoid.cartesianToCartographic(positions[i + 1], scratchCartographic1);
+ numPoints += PolylinePipeline.numberOfPointsRhumbLine(c0, c1, granularity);
+ c0 = Cartographic.clone(c1, scratchCartographic0);
+ }
+
+ var arrayLength = (numPoints + 1) * 3;
+ var newPositions = new Array(arrayLength);
+ var offset = 0;
+
+ for (i = 0; i < length - 1; i++) {
+ var p0 = positions[i];
+ var p1 = positions[i + 1];
+
+ var h0 = hasHeightArray ? height[i] : height;
+ var h1 = hasHeightArray ? height[i + 1] : height;
+
+ offset = generateCartesianRhumbArc(p0, p1, granularity, ellipsoid, h0, h1, newPositions, offset);
+ }
+
+ subdivideHeightsScratchArray.length = 0;
+
+ var lastPoint = positions[length - 1];
+ var carto = ellipsoid.cartesianToCartographic(lastPoint, carto1);
+ carto.height = hasHeightArray ? height[length - 1] : height;
+ var cart = ellipsoid.cartographicToCartesian(carto, cartesian);
+ Cartesian3.pack(cart, newPositions, arrayLength - 3);
+
+ return newPositions;
+ };
+
/**
* Subdivides polyline and raises all points to the specified height. Returns an array of new {Cartesian3} positions.
* @param {Object} options Object with the following properties:
@@ -317,5 +451,35 @@ define([
return newPositions;
};
+ /**
+ * Subdivides polyline and raises all points to the specified height using Rhumb Lines. Returns an array of new {Cartesian3} positions.
+ * @param {Object} options Object with the following properties:
+ * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.
+ * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.
+ * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
+ * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.
+ * @returns {Cartesian3[]} A new array of cartesian3 positions that have been subdivided and raised to the surface of the ellipsoid.
+ *
+ * @example
+ * var positions = Cesium.Cartesian3.fromDegreesArray([
+ * -105.0, 40.0,
+ * -100.0, 38.0,
+ * -105.0, 35.0,
+ * -100.0, 32.0
+ * ]);
+ * var surfacePositions = Cesium.PolylinePipeline.generateCartesianRhumbArc({
+ * positons: positions
+ * });
+ */
+ PolylinePipeline.generateCartesianRhumbArc = function(options) {
+ var numberArray = PolylinePipeline.generateRhumbArc(options);
+ var size = numberArray.length/3;
+ var newPositions = new Array(size);
+ for (var i = 0; i < size; i++) {
+ newPositions[i] = Cartesian3.unpack(numberArray, i*3);
+ }
+ return newPositions;
+ };
+
return PolylinePipeline;
});
diff --git a/Source/Core/SimplePolylineGeometry.js b/Source/Core/SimplePolylineGeometry.js
index c384ede5125d..65187d9d6c6c 100644
--- a/Source/Core/SimplePolylineGeometry.js
+++ b/Source/Core/SimplePolylineGeometry.js
@@ -1,10 +1,12 @@
define([
+ './ArcType',
'./BoundingSphere',
'./Cartesian3',
'./Color',
'./ComponentDatatype',
'./defaultValue',
'./defined',
+ './deprecationWarning',
'./DeveloperError',
'./Ellipsoid',
'./Geometry',
@@ -15,12 +17,14 @@ define([
'./PolylinePipeline',
'./PrimitiveType'
], function(
+ ArcType,
BoundingSphere,
Cartesian3,
Color,
ComponentDatatype,
defaultValue,
defined,
+ deprecationWarning,
DeveloperError,
Ellipsoid,
Geometry,
@@ -83,8 +87,8 @@ define([
* @param {Cartesian3[]} options.positions An array of {@link Cartesian3} defining the positions in the polyline as a line strip.
* @param {Color[]} [options.colors] An Array of {@link Color} defining the per vertex or per segment colors.
* @param {Boolean} [options.colorsPerVertex=false] A boolean that determines whether the colors will be flat across each segment of the line or interpolated across the vertices.
- * @param {Boolean} [options.followSurface=true] A boolean that determines whether positions will be adjusted to the surface of the ellipsoid via a great arc.
- * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.followSurface=true. Determines the number of positions in the buffer.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.
+ * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.arcType is not ArcType.NONE. Determines the number of positions in the buffer.
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
*
* @exception {DeveloperError} At least two positions are required.
@@ -121,7 +125,15 @@ define([
this._positions = positions;
this._colors = colors;
this._colorsPerVertex = colorsPerVertex;
+
this._followSurface = defaultValue(options.followSurface, true);
+ if (defined(options.followSurface)) {
+ deprecationWarning('PolylineGeometry.followSurface', 'PolylineGeometry.followSurface is deprecated and will be removed in Cesium 1.55. Use PolylineGeometry.arcType instead.');
+ options.arcType = options.followSurface ? ArcType.GEODESIC : ArcType.NONE;
+ }
+ this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);
+ this._followSurface = this._arcType === ArcType.NONE;
+
this._granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE);
this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
this._workerName = 'createSimplePolylineGeometry';
@@ -179,7 +191,7 @@ define([
startingIndex += Ellipsoid.packedLength;
array[startingIndex++] = value._colorsPerVertex ? 1.0 : 0.0;
- array[startingIndex++] = value._followSurface ? 1.0 : 0.0;
+ array[startingIndex++] = value._arcType;
array[startingIndex] = value._granularity;
return array;
@@ -222,7 +234,7 @@ define([
startingIndex += Ellipsoid.packedLength;
var colorsPerVertex = array[startingIndex++] === 1.0;
- var followSurface = array[startingIndex++] === 1.0;
+ var arcType = array[startingIndex++];
var granularity = array[startingIndex];
if (!defined(result)) {
@@ -231,7 +243,7 @@ define([
colors : colors,
ellipsoid : ellipsoid,
colorsPerVertex : colorsPerVertex,
- followSurface : followSurface,
+ arcType : arcType,
granularity : granularity
});
}
@@ -240,7 +252,7 @@ define([
result._colors = colors;
result._ellipsoid = ellipsoid;
result._colorsPerVertex = colorsPerVertex;
- result._followSurface = followSurface;
+ result._arcType = arcType;
result._granularity = granularity;
return result;
@@ -252,7 +264,8 @@ define([
positions : scratchArray1,
height: scratchArray2,
ellipsoid: undefined,
- minDistance : undefined
+ minDistance : undefined,
+ granularity : undefined
};
/**
@@ -265,7 +278,7 @@ define([
var positions = simplePolylineGeometry._positions;
var colors = simplePolylineGeometry._colors;
var colorsPerVertex = simplePolylineGeometry._colorsPerVertex;
- var followSurface = simplePolylineGeometry._followSurface;
+ var arcType = simplePolylineGeometry._arcType;
var granularity = simplePolylineGeometry._granularity;
var ellipsoid = simplePolylineGeometry._ellipsoid;
@@ -281,16 +294,34 @@ define([
var color;
var offset = 0;
- if (followSurface) {
+ if (arcType === ArcType.GEODESIC || arcType === ArcType.RHUMB) {
+ var subdivisionSize;
+ var numberOfPointsFunction;
+ var generateArcFunction;
+ if (arcType === ArcType.GEODESIC) {
+ subdivisionSize = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
+ numberOfPointsFunction = PolylinePipeline.numberOfPoints;
+ generateArcFunction = PolylinePipeline.generateArc;
+ } else {
+ subdivisionSize = granularity;
+ numberOfPointsFunction = PolylinePipeline.numberOfPointsRhumbLine;
+ generateArcFunction = PolylinePipeline.generateRhumbArc;
+ }
+
var heights = PolylinePipeline.extractHeights(positions, ellipsoid);
+
var generateArcOptions = generateArcOptionsScratch;
- generateArcOptions.minDistance = minDistance;
+ if (arcType === ArcType.GEODESIC) {
+ generateArcOptions.minDistance = minDistance;
+ } else {
+ generateArcOptions.granularity = granularity;
+ }
generateArcOptions.ellipsoid = ellipsoid;
if (perSegmentColors) {
var positionCount = 0;
for (i = 0; i < length - 1; i++) {
- positionCount += PolylinePipeline.numberOfPoints(positions[i], positions[i+1], minDistance) + 1;
+ positionCount += numberOfPointsFunction(positions[i], positions[i+1], subdivisionSize) + 1;
}
positionValues = new Float64Array(positionCount * 3);
@@ -307,7 +338,7 @@ define([
scratchArray2[0] = heights[i];
scratchArray2[1] = heights[i + 1];
- var pos = PolylinePipeline.generateArc(generateArcOptions);
+ var pos = generateArcFunction(generateArcOptions);
if (defined(colors)) {
var segLen = pos.length / 3;
@@ -326,7 +357,7 @@ define([
} else {
generateArcOptions.positions = positions;
generateArcOptions.height= heights;
- positionValues = new Float64Array(PolylinePipeline.generateArc(generateArcOptions));
+ positionValues = new Float64Array(generateArcFunction(generateArcOptions));
if (defined(colors)) {
colorValues = new Uint8Array(positionValues.length / 3 * 4);
diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js
index dae9820c5d4d..04be1bef39b7 100644
--- a/Source/DataSources/Entity.js
+++ b/Source/DataSources/Entity.js
@@ -678,7 +678,7 @@ define([
/**
* Checks if the given Scene supports polylines clamped to terrain or 3D Tiles.
* If this feature is not supported, Entities with PolylineGraphics will be rendered with vertices at
- * the provided heights and using the `followSurface` parameter instead of clamped to the ground.
+ * the provided heights and using the `arcType` parameter instead of clamped to the ground.
*
* @param {Scene} scene The current scene.
* @returns {Boolean} Whether or not the current scene supports polylines on terrain or 3D TIles.
diff --git a/Source/DataSources/GeoJsonDataSource.js b/Source/DataSources/GeoJsonDataSource.js
index cb96f4419cb9..c0f090ac9794 100644
--- a/Source/DataSources/GeoJsonDataSource.js
+++ b/Source/DataSources/GeoJsonDataSource.js
@@ -1,4 +1,5 @@
define([
+ '../Core/ArcType',
'../Core/Cartesian3',
'../Core/Color',
'../Core/createGuid',
@@ -27,6 +28,7 @@ define([
'./PolygonGraphics',
'./PolylineGraphics'
], function(
+ ArcType,
Cartesian3,
Color,
createGuid,
@@ -365,6 +367,7 @@ define([
polylineGraphics.material = material;
polylineGraphics.width = widthProperty;
polylineGraphics.positions = new ConstantProperty(coordinatesArrayToCartesianArray(coordinates, crsFunction));
+ polylineGraphics.arcType = ArcType.RHUMB;
}
function processLineString(dataSource, geoJson, geometry, crsFunction, options) {
@@ -434,6 +437,7 @@ define([
polygon.outlineColor = outlineColorProperty;
polygon.outlineWidth = widthProperty;
polygon.material = material;
+ polygon.arcType = ArcType.RHUMB;
var holes = [];
for (var i = 1, len = coordinates.length; i < len; i++) {
diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js
index e0e2cc9c918c..dc3d160eb289 100644
--- a/Source/DataSources/PolygonGeometryUpdater.js
+++ b/Source/DataSources/PolygonGeometryUpdater.js
@@ -1,5 +1,6 @@
define([
'../Core/ApproximateTerrainHeights',
+ '../Core/ArcType',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Check',
@@ -33,6 +34,7 @@ define([
'./Property'
], function(
ApproximateTerrainHeights,
+ ArcType,
Cartesian2,
Cartesian3,
Check,
@@ -88,6 +90,7 @@ define([
this.granularity = undefined;
this.stRotation = undefined;
this.offsetAttribute = undefined;
+ this.arcType = undefined;
}
/**
@@ -275,6 +278,7 @@ define([
!Property.isConstant(polygon.closeTop) || //
!Property.isConstant(polygon.closeBottom) || //
!Property.isConstant(polygon.zIndex) || //
+ !Property.isConstant(polygon.arcType) || //
(this._onTerrain && !Property.isConstant(this._materialProperty));
};
@@ -322,6 +326,7 @@ define([
options.closeBottom = Property.getValueOrDefault(polygon.closeBottom, Iso8601.MINIMUM_VALUE, true);
options.offsetAttribute = offsetAttribute;
options.height = heightValue;
+ options.arcType = Property.getValueOrDefault(polygon.arcType, Iso8601.MINIMUM_VALUE, ArcType.GEODESIC);
extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(extrudedHeightValue, extrudedHeightReferenceValue);
if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {
@@ -399,6 +404,7 @@ define([
options.closeBottom = Property.getValueOrDefault(polygon.closeBottom, time, true);
options.offsetAttribute = offsetAttribute;
options.height = heightValue;
+ options.arcType = Property.getValueOrDefault(polygon.arcType, time, ArcType.GEODESIC);
extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(extrudedHeightValue, extrudedHeightReferenceValue);
if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {
diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js
index fb65382cb61e..ede07748796f 100644
--- a/Source/DataSources/PolygonGraphics.js
+++ b/Source/DataSources/PolygonGraphics.js
@@ -44,6 +44,7 @@ define([
* @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polygon casts or receives shadows from each light source.
* @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polygon will be displayed.
* @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground.
+ * @param {Property} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow.
* @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex used for ordering ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified.
*
* @see Entity
@@ -88,6 +89,8 @@ define([
this._distanceDisplayConditionSubscription = undefined;
this._classificationType = undefined;
this._classificationTypeSubscription = undefined;
+ this._arcType = undefined;
+ this._arcTypeSubscription = undefined;
this._zIndex = undefined;
this._zIndexSubscription = undefined;
this._definitionChanged = new Event();
@@ -260,6 +263,14 @@ define([
*/
classificationType : createPropertyDescriptor('classificationType'),
+ /**
+ * Gets or sets the {@link ArcType} Property specifying the type of lines the polygon edges use.
+ * @memberof PolygonGraphics.prototype
+ * @type {Property}
+ * @default ArcType.GEODESIC
+ */
+ arcType : createPropertyDescriptor('arcType'),
+
/**
* Gets or sets the zIndex Prperty specifying the ordering of ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified.
* @memberof PolygonGraphics.prototype
@@ -298,6 +309,7 @@ define([
result.shadows = this.shadows;
result.distanceDisplayCondition = this.distanceDisplayCondition;
result.classificationType = this.classificationType;
+ result.arcType = this.arcType;
result.zIndex = this.zIndex;
return result;
@@ -335,6 +347,7 @@ define([
this.shadows = defaultValue(this.shadows, source.shadows);
this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition);
this.classificationType = defaultValue(this.classificationType, source.classificationType);
+ this.arcType = defaultValue(this.arcType, source.arcType);
this.zIndex = defaultValue(this.zIndex, source.zIndex);
};
diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js
index a7aa2b5fd20a..4dfbea77392d 100644
--- a/Source/DataSources/PolylineGeometryUpdater.js
+++ b/Source/DataSources/PolylineGeometryUpdater.js
@@ -1,4 +1,5 @@
define([
+ '../Core/ArcType',
'../Core/BoundingSphere',
'../Core/Check',
'../Core/Color',
@@ -31,6 +32,7 @@ define([
'./MaterialProperty',
'./Property'
], function(
+ ArcType,
BoundingSphere,
Check,
Color,
@@ -81,12 +83,15 @@ define([
this.positions = undefined;
this.width = undefined;
this.followSurface = undefined;
+ this.arcType = undefined;
this.granularity = undefined;
}
function GroundGeometryOptions() {
this.positions = undefined;
this.width = undefined;
+ this.arcType = undefined;
+ this.granularity = undefined;
}
/**
@@ -309,6 +314,19 @@ define([
}
},
+ /**
+ * Gets a value indicating if the path of the line.
+ * @memberof PolylineGeometryUpdater.prototype
+ *
+ * @type {ArcType}
+ * @readonly
+ */
+ arcType : {
+ get : function() {
+ return this._arcType;
+ }
+ },
+
/**
* Gets a value indicating if the geometry is clamped to the ground.
* Returns false if polylines on terrain is not supported.
@@ -498,11 +516,12 @@ define([
var width = polyline.width;
var followSurface = polyline.followSurface;
+ var arcType = polyline.arcType;
var clampToGround = polyline.clampToGround;
var granularity = polyline.granularity;
if (!positionsProperty.isConstant || !Property.isConstant(width) ||
- !Property.isConstant(followSurface) || !Property.isConstant(granularity) ||
+ !Property.isConstant(followSurface) || !Property.isConstant(arcType) || !Property.isConstant(granularity) ||
!Property.isConstant(clampToGround) || !Property.isConstant(zIndex)) {
if (!this._dynamic) {
this._dynamic = true;
@@ -533,11 +552,14 @@ define([
geometryOptions.positions = positions;
geometryOptions.width = defined(width) ? width.getValue(Iso8601.MINIMUM_VALUE) : undefined;
geometryOptions.followSurface = defined(followSurface) ? followSurface.getValue(Iso8601.MINIMUM_VALUE) : undefined;
+ geometryOptions.arcType = defined(arcType) ? arcType.getValue(Iso8601.MINIMUM_VALUE) : undefined;
geometryOptions.granularity = defined(granularity) ? granularity.getValue(Iso8601.MINIMUM_VALUE) : undefined;
var groundGeometryOptions = this._groundGeometryOptions;
groundGeometryOptions.positions = positions;
groundGeometryOptions.width = geometryOptions.width;
+ groundGeometryOptions.arcType = geometryOptions.arcType;
+ groundGeometryOptions.granularity = geometryOptions.granularity;
this._clampToGround = defined(clampToGround) ? clampToGround.getValue(Iso8601.MINIMUM_VALUE) : false;
@@ -626,6 +648,8 @@ define([
geometryUpdater._clampToGround = Property.getValueOrDefault(polyline._clampToGround, time, false);
geometryUpdater._groundGeometryOptions.positions = positions;
geometryUpdater._groundGeometryOptions.width = Property.getValueOrDefault(polyline._width, time, 1);
+ geometryUpdater._groundGeometryOptions.arcType = Property.getValueOrDefault(polyline._arcType, time, ArcType.GEODESIC);
+ geometryUpdater._groundGeometryOptions.granularity = Property.getValueOrDefault(polyline._granularity, time, 9999);
var groundPrimitives = this._groundPrimitives;
@@ -682,9 +706,15 @@ define([
return;
}
- var followSurface = Property.getValueOrDefault(polyline._followSurface, time, true);
+ var followSurface = Property.getValueOrUndefined(polyline._followSurface, time);
+ var arcType = ArcType.GEODESIC;
+ if (defined(followSurface)) {
+ arcType = followSurface ? ArcType.GEODESIC : ArcType.NONE;
+ }
+ arcType = Property.getValueOrDefault(polyline._arcType, time, arcType);
+
var globe = geometryUpdater._scene.globe;
- if (followSurface && defined(globe)) {
+ if (arcType !== ArcType.NONE && defined(globe)) {
generateCartesianArcOptions.ellipsoid = globe.ellipsoid;
generateCartesianArcOptions.positions = positions;
generateCartesianArcOptions.granularity = Property.getValueOrUndefined(polyline._granularity, time);
diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js
index 8f1e912d3cfc..775ee15b2437 100644
--- a/Source/DataSources/PolylineGraphics.js
+++ b/Source/DataSources/PolylineGraphics.js
@@ -1,4 +1,5 @@
define([
+ '../Core/ArcType',
'../Core/defaultValue',
'../Core/defined',
'../Core/defineProperties',
@@ -7,6 +8,7 @@ define([
'./createMaterialPropertyDescriptor',
'./createPropertyDescriptor'
], function(
+ ArcType,
defaultValue,
defined,
defineProperties,
@@ -26,13 +28,13 @@ define([
*
* @param {Object} [options] Object with the following properties:
* @param {Property} [options.positions] A Property specifying the array of {@link Cartesian3} positions that define the line strip.
- * @param {Property} [options.followSurface=true] A boolean Property specifying whether the line segments should be great arcs or linearly connected.
+ * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.
* @param {Property} [options.clampToGround=false] A boolean Property specifying whether the Polyline should be clamped to the ground.
* @param {Property} [options.width=1.0] A numeric Property specifying the width in pixels.
* @param {Property} [options.show=true] A boolean Property specifying the visibility of the polyline.
* @param {MaterialProperty} [options.material=Color.WHITE] A Property specifying the material used to draw the polyline.
* @param {MaterialProperty} [options.depthFailMaterial] A property specifying the material used to draw the polyline when it is below the terrain.
- * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if followSurface is true.
+ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if arcType is not ArcType.NONE.
* @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polyline casts or receives shadows from each light source.
* @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polyline will be displayed.
* @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground.
@@ -52,6 +54,8 @@ define([
this._positionsSubscription = undefined;
this._followSurface = undefined;
this._followSurfaceSubscription = undefined;
+ this._arcType = undefined;
+ this._arcTypeSubscription = undefined;
this._clampToGround = undefined;
this._clampToGroundSubscription = undefined;
this._granularity = undefined;
@@ -136,10 +140,20 @@ define([
* should be great arcs or linearly connected.
* @memberof PolylineGraphics.prototype
* @type {Property}
+ * @deprecated This property has been deprecated. Use {@link PolylineGraphics#arcType} instead.
* @default true
*/
followSurface : createPropertyDescriptor('followSurface'),
+ /**
+ * Gets or sets the {@link ArcType} Property specifying whether the line segments should be great arcs, rhumb lines or linearly connected.
+ * @memberof PolylineGraphics.prototype
+ * @type {Property}
+ * @deprecated This property has been deprecated. Use {@link PolylineGraphics#arcType} instead.
+ * @default ArcType.GEODESIC
+ */
+ arcType : createPropertyDescriptor('arcType'),
+
/**
* Gets or sets the boolean Property specifying whether the polyline
* should be clamped to the ground.
@@ -150,7 +164,7 @@ define([
clampToGround : createPropertyDescriptor('clampToGround'),
/**
- * Gets or sets the numeric Property specifying the angular distance between each latitude and longitude if followSurface is true and clampToGround is false.
+ * Gets or sets the numeric Property specifying the angular distance between each latitude and longitude if arcType is not ArcType.NONE and clampToGround is false.
* @memberof PolylineGraphics.prototype
* @type {Property}
* @default Cesium.Math.RADIANS_PER_DEGREE
@@ -206,6 +220,7 @@ define([
result.positions = this.positions;
result.width = this.width;
result.followSurface = this.followSurface;
+ result.arcType = this.arcType;
result.clampToGround = this.clampToGround;
result.granularity = this.granularity;
result.shadows = this.shadows;
@@ -235,6 +250,7 @@ define([
this.positions = defaultValue(this.positions, source.positions);
this.width = defaultValue(this.width, source.width);
this.followSurface = defaultValue(this.followSurface, source.followSurface);
+ this.arcType = defaultValue(this.arcType, source.arcType);
this.clampToGround = defaultValue(this.clampToGround, source.clampToGround);
this.granularity = defaultValue(this.granularity, source.granularity);
this.shadows = defaultValue(this.shadows, source.shadows);
diff --git a/Source/Scene/DebugModelMatrixPrimitive.js b/Source/Scene/DebugModelMatrixPrimitive.js
index 633324e66a05..671be07456ec 100644
--- a/Source/Scene/DebugModelMatrixPrimitive.js
+++ b/Source/Scene/DebugModelMatrixPrimitive.js
@@ -1,4 +1,5 @@
define([
+ '../Core/ArcType',
'../Core/Cartesian3',
'../Core/Color',
'../Core/defaultValue',
@@ -10,6 +11,7 @@ define([
'./PolylineColorAppearance',
'./Primitive'
], function(
+ ArcType,
Cartesian3,
Color,
defaultValue,
@@ -142,7 +144,7 @@ define([
Color.RED,
Color.RED
],
- followSurface: false
+ arcType: ArcType.NONE
}),
modelMatrix : Matrix4.multiplyByUniformScale(this.modelMatrix, this.length, new Matrix4()),
id : this.id,
@@ -160,7 +162,7 @@ define([
Color.GREEN,
Color.GREEN
],
- followSurface: false
+ arcType: ArcType.NONE
}),
modelMatrix : Matrix4.multiplyByUniformScale(this.modelMatrix, this.length, new Matrix4()),
id : this.id,
@@ -178,7 +180,7 @@ define([
Color.BLUE,
Color.BLUE
],
- followSurface: false
+ arcType: ArcType.NONE
}),
modelMatrix : Matrix4.multiplyByUniformScale(this.modelMatrix, this.length, new Matrix4()),
id : this.id,
diff --git a/Specs/Core/GroundPolylineGeometrySpec.js b/Specs/Core/GroundPolylineGeometrySpec.js
index 9fdcc6f2e00a..b41332a997f3 100644
--- a/Specs/Core/GroundPolylineGeometrySpec.js
+++ b/Specs/Core/GroundPolylineGeometrySpec.js
@@ -1,23 +1,25 @@
defineSuite([
'Core/GroundPolylineGeometry',
'Core/ApproximateTerrainHeights',
+ 'Core/ArcType',
'Core/arraySlice',
'Core/Cartesian3',
'Core/Cartographic',
- 'Core/Math',
'Core/Ellipsoid',
'Core/GeographicProjection',
+ 'Core/Math',
'Core/WebMercatorProjection',
'Specs/createPackableSpecs'
], function(
GroundPolylineGeometry,
ApproximateTerrainHeights,
+ ArcType,
arraySlice,
Cartesian3,
Cartographic,
- CesiumMath,
Ellipsoid,
GeographicProjection,
+ CesiumMath,
WebMercatorProjection,
createPackableSpecs) {
'use strict';
@@ -364,6 +366,58 @@ defineSuite([
expect(geometry.attributes.position.values.length).toEqual(24 * 3);
});
+ it('interpolates long polyline segments for rhumb lines', function() {
+ // rhumb distance = 289020, geodesic distance = 288677
+ var positions = Cartesian3.fromDegreesArray([
+ 10, 75,
+ 20, 75
+ ]);
+
+ var rhumbGroundPolylineGeometry = new GroundPolylineGeometry({
+ positions : positions,
+ granularity : 2890.0,
+ arcType: ArcType.RHUMB
+ });
+ var geodesicGroundPolylineGeometry = new GroundPolylineGeometry({
+ positions : positions,
+ granularity : 2890.0,
+ arcType: ArcType.GEODESIC
+ });
+
+ var rhumbGeometry = GroundPolylineGeometry.createGeometry(rhumbGroundPolylineGeometry);
+ var geodesicGeometry = GroundPolylineGeometry.createGeometry(geodesicGroundPolylineGeometry);
+
+ expect(rhumbGeometry.indices.length).toEqual(3636);
+ expect(geodesicGeometry.indices.length).toEqual(3600);
+ expect(geodesicGeometry.attributes.position.values.length).toEqual(2400);
+ expect(rhumbGeometry.attributes.position.values.length).toEqual(2424);
+
+ // Interpolate one segment but not the other
+ positions = Cartesian3.fromDegreesArray([
+ 10, 75,
+ 20, 75,
+ 20.01, 75
+ ]);
+ rhumbGroundPolylineGeometry = new GroundPolylineGeometry({
+ positions : positions,
+ granularity : 2890.0,
+ arcType: ArcType.RHUMB
+ });
+ geodesicGroundPolylineGeometry = new GroundPolylineGeometry({
+ positions : positions,
+ granularity : 2890.0,
+ arcType: ArcType.GEODESIC
+ });
+
+ rhumbGeometry = GroundPolylineGeometry.createGeometry(rhumbGroundPolylineGeometry);
+ geodesicGeometry = GroundPolylineGeometry.createGeometry(geodesicGroundPolylineGeometry);
+
+ expect(rhumbGeometry.indices.length).toEqual(3636 + 36);
+ expect(geodesicGeometry.indices.length).toEqual(3600 + 36);
+ expect(geodesicGeometry.attributes.position.values.length).toEqual(2400 + 24);
+ expect(rhumbGeometry.attributes.position.values.length).toEqual(2424 + 24);
+ });
+
it('loops when there are enough positions and loop is specified', function() {
var groundPolylineGeometry = new GroundPolylineGeometry({
positions : Cartesian3.fromDegreesArray([
@@ -564,6 +618,7 @@ defineSuite([
Cartesian3.pack(positions[2], packedInstance, packedInstance.length);
packedInstance.push(polyline.granularity);
packedInstance.push(polyline.loop ? 1.0 : 0.0);
+ packedInstance.push(polyline.arcType);
Ellipsoid.pack(Ellipsoid.WGS84, packedInstance, packedInstance.length);
diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js
index 15601a327dc1..935473324227 100644
--- a/Specs/Core/PolygonGeometrySpec.js
+++ b/Specs/Core/PolygonGeometrySpec.js
@@ -1,5 +1,6 @@
defineSuite([
'Core/PolygonGeometry',
+ 'Core/ArcType',
'Core/arrayFill',
'Core/BoundingSphere',
'Core/Cartesian3',
@@ -12,6 +13,7 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
PolygonGeometry,
+ ArcType,
arrayFill,
BoundingSphere,
Cartesian3,
@@ -59,6 +61,17 @@ defineSuite([
}))).toBeUndefined();
});
+ it('throws if arcType is not valid', function() {
+ expect(function() {
+ return new PolygonGeometry({
+ positions : [Cartesian3.fromDegrees(0, 0),
+ Cartesian3.fromDegrees(1, 0),
+ Cartesian3.fromDegrees(1, 1)],
+ arcType: ArcType.NONE
+ });
+ }).toThrowDeveloperError();
+ });
+
it('createGeometry returns undefined due to duplicate positions', function() {
var geometry = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
@@ -176,6 +189,82 @@ defineSuite([
expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 3)).height).toEqualEpsilon(0, CesiumMath.EPSILON6);
});
+ it('create geometry creates with rhumb lines', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(p.attributes.position.values.length).toEqual(13 * 3); // 8 around edge + 5 in the middle
+ expect(p.indices.length).toEqual(16 * 3); //4 squares * 4 triangles per square
+ });
+
+ it('create geometry throws if arcType is STRAIGHT', function() {
+ expect(function() {
+ PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat: VertexFormat.POSITION_ONLY,
+ positions: Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ granularity: CesiumMath.RADIANS_PER_DEGREE,
+ arcType: ArcType.NONE
+ }));
+ }).toThrowDeveloperError();
+ });
+
+ it('create geometry creates with lines with different number of subdivisions for geodesic and rhumb', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ -30.0, -30.0,
+ 30.0, -30.0,
+ 30.0, 30.0,
+ -30.0, 30.0
+ ]);
+ var geodesic = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : positions,
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.GEODESIC
+ }));
+ var rhumb = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : positions,
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(geodesic.attributes.position.values.length).not.toEqual(rhumb.attributes.position.values.length);
+ expect(geodesic.indices.length).not.toEqual(rhumb.indices.length);
+ });
+
+ it('computes positions with per position heights for rhumb lines', function() {
+ var ellipsoid = Ellipsoid.WGS84;
+ var height = 100.0;
+ var positions = Cartesian3.fromDegreesArrayHeights([
+ -1.0, -1.0, height,
+ 1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0
+ ]);
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ positions : positions,
+ perPositionHeight : true,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 0)).height).toEqualEpsilon(height, CesiumMath.EPSILON6);
+ expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 3)).height).toEqualEpsilon(0, CesiumMath.EPSILON6);
+ });
+
it('computes all attributes', function() {
var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
vertexFormat : VertexFormat.ALL,
@@ -233,6 +322,43 @@ defineSuite([
expect(p.indices.length).toEqual(10 * 3);
});
+ it('creates a polygon from hierarchy with rhumb lines', function() {
+ var hierarchy = {
+ positions : Cartesian3.fromDegreesArray([
+ -124.0, 35.0,
+ -110.0, 35.0,
+ -110.0, 40.0,
+ -124.0, 40.0
+ ]),
+ holes : [{
+ positions : Cartesian3.fromDegreesArray([
+ -122.0, 36.0,
+ -122.0, 39.0,
+ -112.0, 39.0,
+ -112.0, 36.0
+ ]),
+ holes : [{
+ positions : Cartesian3.fromDegreesArray([
+ -120.0, 36.5,
+ -114.0, 36.5,
+ -114.0, 38.5,
+ -120.0, 38.5
+ ])
+ }]
+ }]
+ };
+
+ var p = PolygonGeometry.createGeometry(new PolygonGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ polygonHierarchy : hierarchy,
+ granularity : CesiumMath.PI_OVER_THREE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(p.attributes.position.values.length).toEqual(12 * 3); // 4 points * 3 rectangles
+ expect(p.indices.length).toEqual(10 * 3);
+ });
+
it('removes duplicates in polygon hierarchy', function() {
var hierarchy = {
positions : Cartesian3.fromDegreesArray([
@@ -1067,6 +1193,6 @@ defineSuite([
addPositions(packedInstance, holePositions1);
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
- packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 0, -1, 53);
+ packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 0, -1, ArcType.GEODESIC, 54);
createPackableSpecs(PolygonGeometry, polygon, packedInstance);
});
diff --git a/Specs/Core/PolygonOutlineGeometrySpec.js b/Specs/Core/PolygonOutlineGeometrySpec.js
index 013329d16c0b..1c9965c5ae52 100644
--- a/Specs/Core/PolygonOutlineGeometrySpec.js
+++ b/Specs/Core/PolygonOutlineGeometrySpec.js
@@ -1,5 +1,6 @@
defineSuite([
'Core/PolygonOutlineGeometry',
+ 'Core/ArcType',
'Core/arrayFill',
'Core/BoundingSphere',
'Core/Cartesian3',
@@ -9,6 +10,7 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
PolygonOutlineGeometry,
+ ArcType,
arrayFill,
BoundingSphere,
Cartesian3,
@@ -53,6 +55,17 @@ defineSuite([
}))).toBeUndefined();
});
+ it('throws if arcType is not valid', function() {
+ expect(function() {
+ return new PolygonOutlineGeometry({
+ positions : [Cartesian3.fromDegrees(0, 0),
+ Cartesian3.fromDegrees(1, 0),
+ Cartesian3.fromDegrees(1, 1)],
+ arcType: ArcType.NONE
+ });
+ }).toThrowDeveloperError();
+ });
+
it('createGeometry returns undefined due to duplicate positions', function() {
var geometry = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
@@ -168,6 +181,78 @@ defineSuite([
expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 3)).height).toEqualEpsilon(0, CesiumMath.EPSILON6);
});
+ it('create geometry creates with rhumb lines', function() {
+ var p = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(p.attributes.position.values.length).toEqual(8 * 3); // 8 around edge
+ expect(p.indices.length).toEqual(16); // 4 squares
+ });
+
+ it('create geometry throws if arcType is STRAIGHT', function() {
+ expect(function() {
+ PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions: Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ granularity: CesiumMath.RADIANS_PER_DEGREE,
+ arcType: ArcType.NONE
+ }));
+ }).toThrowDeveloperError();
+ });
+
+ it('create geometry creates with lines with different number of subdivisions for geodesic and rhumb', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ -80.0, 75.0,
+ 80.0, 75.0,
+ 80.0, 45.0,
+ -80.0, 45.0
+ ]);
+ var geodesic = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : positions,
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.GEODESIC
+ }));
+ var rhumb = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : positions,
+ granularity : CesiumMath.RADIANS_PER_DEGREE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(geodesic.attributes.position.values.length).not.toEqual(rhumb.attributes.position.values.length);
+ expect(geodesic.indices.length).not.toEqual(rhumb.indices.length);
+ });
+
+ it('computes positions with per position heights for rhumb lines', function() {
+ var ellipsoid = Ellipsoid.WGS84;
+ var height = 100.0;
+ var positions = Cartesian3.fromDegreesArrayHeights([
+ -1.0, -1.0, height,
+ 1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0
+ ]);
+ var p = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : positions,
+ perPositionHeight : true,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 0)).height).toEqualEpsilon(height, CesiumMath.EPSILON6);
+ expect(ellipsoid.cartesianToCartographic(Cartesian3.fromArray(p.attributes.position.values, 3)).height).toEqualEpsilon(0, CesiumMath.EPSILON6);
+ });
+
it('uses correct value with extrudedHeight and perPositionHeight', function() {
var ellipsoid = Ellipsoid.WGS84;
var maxHeight = 100.0;
@@ -524,6 +609,6 @@ defineSuite([
packedInstance.push(3.0, 0.0);
addPositions(packedInstance, holePositions1);
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
- packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 1.0, -1, 43);
+ packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 1.0, ArcType.GEODESIC, -1, 44);
createPackableSpecs(PolygonOutlineGeometry, polygon, packedInstance);
});
diff --git a/Specs/Core/PolygonPipelineSpec.js b/Specs/Core/PolygonPipelineSpec.js
index 47e5bc747db4..cb343750e8ff 100644
--- a/Specs/Core/PolygonPipelineSpec.js
+++ b/Specs/Core/PolygonPipelineSpec.js
@@ -193,4 +193,79 @@ defineSuite([
expect(subdivision.indices[1]).toEqual(1);
expect(subdivision.indices[2]).toEqual(2);
});
+
+ ///////////////////////////////////////////////////////////////////////
+
+ it('computeRhumbLineSubdivision throws without ellipsoid', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision();
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision throws without positions', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84);
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision throws without indices', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, []);
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision throws with less than 3 indices', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, [], [1, 2]);
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision throws without a multiple of 3 indices', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, [], [1, 2, 3, 4]);
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision throws with negative granularity', function() {
+ expect(function() {
+ PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, [], [1, 2, 3], -1.0);
+ }).toThrowDeveloperError();
+ });
+
+ it('computeRhumbLineSubdivision', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ 0, 0,
+ 1, 0,
+ 1, 1
+ ]);
+ var indices = [0, 1, 2];
+ var subdivision = PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, positions, indices, 2 * CesiumMath.RADIANS_PER_DEGREE);
+
+ expect(subdivision.attributes.position.values[0]).toEqual(positions[0].x);
+ expect(subdivision.attributes.position.values[1]).toEqual(positions[0].y);
+ expect(subdivision.attributes.position.values[2]).toEqual(positions[0].y);
+ expect(subdivision.attributes.position.values[3]).toEqual(positions[1].x);
+ expect(subdivision.attributes.position.values[4]).toEqual(positions[1].y);
+ expect(subdivision.attributes.position.values[5]).toEqual(positions[1].z);
+ expect(subdivision.attributes.position.values[6]).toEqual(positions[2].x);
+ expect(subdivision.attributes.position.values[7]).toEqual(positions[2].y);
+ expect(subdivision.attributes.position.values[8]).toEqual(positions[2].z);
+
+ expect(subdivision.indices[0]).toEqual(0);
+ expect(subdivision.indices[1]).toEqual(1);
+ expect(subdivision.indices[2]).toEqual(2);
+ });
+
+ it('computeRhumbLineSubdivision with subdivisions', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ 0, 0,
+ 1, 0,
+ 1, 1
+ ]);
+ var indices = [0, 1, 2];
+ var subdivision = PolygonPipeline.computeRhumbLineSubdivision(Ellipsoid.WGS84, positions, indices, 0.5 * CesiumMath.RADIANS_PER_DEGREE);
+
+ expect(subdivision.attributes.position.values.length).toEqual(30); // 10 vertices
+ expect(subdivision.indices.length).toEqual(27); // 9 triangles
+ });
});
diff --git a/Specs/Core/PolylineGeometrySpec.js b/Specs/Core/PolylineGeometrySpec.js
index 8a2f9d43651d..4f85c0561f22 100644
--- a/Specs/Core/PolylineGeometrySpec.js
+++ b/Specs/Core/PolylineGeometrySpec.js
@@ -1,5 +1,6 @@
defineSuite([
'Core/PolylineGeometry',
+ 'Core/ArcType',
'Core/Cartesian3',
'Core/Color',
'Core/Ellipsoid',
@@ -7,6 +8,7 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
PolylineGeometry,
+ ArcType,
Cartesian3,
Color,
Ellipsoid,
@@ -37,6 +39,24 @@ defineSuite([
}).toThrowDeveloperError();
});
+ it('constructor converts followSurface to arcType', function() {
+ var line = new PolylineGeometry({
+ positions: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y],
+ followSurface: false
+ });
+
+ expect(line._followSurface).toBe(false);
+ expect(line._arcType).toBe(ArcType.NONE);
+
+ line = new PolylineGeometry({
+ positions: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y],
+ followSurface: true
+ });
+
+ expect(line._followSurface).toBe(true);
+ expect(line._arcType).toBe(ArcType.GEODESIC);
+ });
+
it('constructor returns undefined when line width is negative', function() {
var positions = [new Cartesian3(1.0, 0.0, 0.0), new Cartesian3(0.0, 1.0, 0.0), new Cartesian3(0.0, 0.0, 1.0)];
var line = PolylineGeometry.createGeometry(new PolylineGeometry({
@@ -75,6 +95,36 @@ defineSuite([
expect(line.indices.length).toEqual(positions.length * 6 - 6);
});
+ it('constructor computes all vertex attributes for rhumb lines', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ 30, 30,
+ 30, 60,
+ 60, 60
+ ]);
+ var line = PolylineGeometry.createGeometry(new PolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ vertexFormat : VertexFormat.ALL,
+ granularity : Math.PI,
+ ellipsoid : Ellipsoid.UNIT_SPHERE,
+ arcType : ArcType.RHUMB
+ }));
+
+ expect(line.attributes.position).toBeDefined();
+ expect(line.attributes.prevPosition).toBeDefined();
+ expect(line.attributes.nextPosition).toBeDefined();
+ expect(line.attributes.expandAndWidth).toBeDefined();
+ expect(line.attributes.st).toBeDefined();
+
+ var numVertices = (positions.length * 4 - 4);
+ expect(line.attributes.position.values.length).toEqual(numVertices * 3);
+ expect(line.attributes.prevPosition.values.length).toEqual(numVertices * 3);
+ expect(line.attributes.nextPosition.values.length).toEqual(numVertices * 3);
+ expect(line.attributes.expandAndWidth.values.length).toEqual(numVertices * 2);
+ expect(line.attributes.st.values.length).toEqual(numVertices * 2);
+ expect(line.indices.length).toEqual(positions.length * 6 - 6);
+ });
+
it('constructor computes per segment colors', function() {
var positions = [new Cartesian3(1.0, 0.0, 0.0), new Cartesian3(0.0, 1.0, 0.0), new Cartesian3(0.0, 0.0, 1.0)];
var colors = [new Color(1.0, 0.0, 0.0, 1.0), new Color(0.0, 1.0, 0.0, 1.0), new Color(0.0, 0.0, 1.0, 1.0)];
@@ -120,7 +170,7 @@ defineSuite([
positions : positions,
width : 10.0,
vertexFormat : VertexFormat.POSITION_ONLY,
- followSurface : false
+ arcType : ArcType.NONE
}));
expect(geometry).not.toBeDefined();
});
@@ -131,7 +181,7 @@ defineSuite([
width : 10.0,
colors : [Color.RED, Color.LIME, Color.BLUE],
colorsPerVertex : true,
- followSurface : false,
+ arcType : ArcType.NONE,
granularity : 11,
vertexFormat : VertexFormat.POSITION_ONLY,
ellipsoid : new Ellipsoid(12, 13, 14)
@@ -143,11 +193,35 @@ defineSuite([
positions : positions,
width : 10.0,
colorsPerVertex : false,
- followSurface : false,
+ arcType : ArcType.NONE,
granularity : 11,
vertexFormat : VertexFormat.POSITION_ONLY,
ellipsoid : new Ellipsoid(12, 13, 14)
});
packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 1, 0, 0, 0, 0, 0, 10, 0, 0, 11];
- createPackableSpecs(PolylineGeometry, line, packedInstance);
+ createPackableSpecs(PolylineGeometry, line, packedInstance, 'straight line');
+
+ line = new PolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ colorsPerVertex : false,
+ arcType : ArcType.GEODESIC,
+ granularity : 11,
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ ellipsoid : new Ellipsoid(12, 13, 14)
+ });
+ packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 1, 0, 0, 0, 0, 0, 10, 0, 1, 11];
+ createPackableSpecs(PolylineGeometry, line, packedInstance, 'geodesic line');
+
+ line = new PolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ colorsPerVertex : false,
+ arcType : ArcType.RHUMB,
+ granularity : 11,
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ ellipsoid : new Ellipsoid(12, 13, 14)
+ });
+ packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 1, 0, 0, 0, 0, 0, 10, 0, 2, 11];
+ createPackableSpecs(PolylineGeometry, line, packedInstance, 'rhumb line');
});
diff --git a/Specs/Core/PolylinePipelineSpec.js b/Specs/Core/PolylinePipelineSpec.js
index e0024afbfba0..6f62ec382a52 100644
--- a/Specs/Core/PolylinePipelineSpec.js
+++ b/Specs/Core/PolylinePipelineSpec.js
@@ -108,4 +108,61 @@ defineSuite([
expect(newPositions).toEqual([0,0,1]);
});
+ it('generateRhumbArc throws without positions', function() {
+ expect(function() {
+ PolylinePipeline.generateRhumbArc();
+ }).toThrowDeveloperError();
+ });
+
+ it('generateRhumbArc accepts a height array for single value', function() {
+ var positions = [Cartesian3.fromDegrees(0, 0)];
+ var height = [30];
+
+ var newPositions = PolylinePipeline.generateRhumbArc({
+ positions: positions,
+ height: height
+ });
+
+ expect(newPositions.length).toEqual(3);
+ expect(Cartesian3.fromArray(newPositions, 0)).toEqualEpsilon(Cartesian3.fromDegrees(0, 0, 30), CesiumMath.EPSILON6);
+ });
+
+ it('generateRhumbArc subdivides in half', function() {
+ var p1 = Cartesian3.fromDegrees(0, 30);
+ var p2 = Cartesian3.fromDegrees(90, 30);
+ var p3 = Cartesian3.fromDegrees(45, 30);
+ var positions = [p1, p2];
+
+ var newPositions = PolylinePipeline.generateRhumbArc({
+ positions: positions,
+ granularity: CesiumMath.PI_OVER_FOUR,
+ ellipsoid: Ellipsoid.WGS84
+ });
+
+ expect(newPositions.length).toEqual(3*3);
+ var p1n = Cartesian3.fromArray(newPositions, 0);
+ var p3n = Cartesian3.fromArray(newPositions, 3);
+ var p2n = Cartesian3.fromArray(newPositions, 6);
+ expect(Cartesian3.equalsEpsilon(p1, p1n, CesiumMath.EPSILON4)).toEqual(true);
+ expect(Cartesian3.equalsEpsilon(p2, p2n, CesiumMath.EPSILON4)).toEqual(true);
+ expect(Cartesian3.equalsEpsilon(p3, p3n, CesiumMath.EPSILON4)).toEqual(true);
+ });
+
+ it('generateRhumbArc works with empty array', function() {
+ var newPositions = PolylinePipeline.generateRhumbArc({
+ positions: []
+ });
+
+ expect(newPositions.length).toEqual(0);
+ });
+
+ it('generateRhumbArc works one position', function() {
+ var newPositions = PolylinePipeline.generateRhumbArc({
+ positions: [Cartesian3.UNIT_Z],
+ ellipsoid: Ellipsoid.UNIT_SPHERE
+ });
+
+ expect(newPositions.length).toEqual(3);
+ expect(newPositions).toEqual([0,0,1]);
+ });
});
diff --git a/Specs/Core/SimplePolylineGeometrySpec.js b/Specs/Core/SimplePolylineGeometrySpec.js
index dee7e598eff7..193136e948e6 100644
--- a/Specs/Core/SimplePolylineGeometrySpec.js
+++ b/Specs/Core/SimplePolylineGeometrySpec.js
@@ -1,5 +1,6 @@
defineSuite([
'Core/SimplePolylineGeometry',
+ 'Core/ArcType',
'Core/BoundingSphere',
'Core/Cartesian3',
'Core/Color',
@@ -9,6 +10,7 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
SimplePolylineGeometry,
+ ArcType,
BoundingSphere,
Cartesian3,
Color,
@@ -55,6 +57,28 @@ defineSuite([
expect(line.boundingSphere).toEqual(BoundingSphere.fromPoints(positions));
});
+ it('constructor computes all vertex attributes for rhumb lines', function() {
+ var positions = Cartesian3.fromDegreesArray([
+ 30, 30,
+ 30, 60,
+ 60, 60
+ ]);
+ var line = SimplePolylineGeometry.createGeometry(new SimplePolylineGeometry({
+ positions: positions,
+ granularity: Math.PI,
+ ellipsoid: Ellipsoid.UNIT_SPHERE,
+ arcType: ArcType.RHUMB
+ }));
+
+ var cartesian3Array = [];
+ Cartesian3.packArray(positions, cartesian3Array);
+
+ expect(line.attributes.position.values).toEqualEpsilon(cartesian3Array, CesiumMath.EPSILON8);
+ expect(line.indices).toEqual([0, 1, 1, 2]);
+ expect(line.primitiveType).toEqual(PrimitiveType.LINES);
+ expect(line.boundingSphere).toEqual(BoundingSphere.fromPoints(positions));
+ });
+
it('constructor computes per segment colors', function() {
var positions = [new Cartesian3(1.0, 0.0, 0.0), new Cartesian3(0.0, 1.0, 0.0), new Cartesian3(0.0, 0.0, 1.0)];
var colors = [new Color(1.0, 0.0, 0.0, 1.0), new Color(0.0, 1.0, 0.0, 1.0), new Color(0.0, 0.0, 1.0, 1.0)];
@@ -153,4 +177,37 @@ defineSuite([
});
packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 0, 0, 11];
createPackableSpecs(SimplePolylineGeometry, line, packedInstance);
+
+ line = new SimplePolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ colorsPerVertex : false,
+ arcType : ArcType.GEODESIC,
+ granularity : 11,
+ ellipsoid : new Ellipsoid(12, 13, 14)
+ });
+ packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 0, 1, 11];
+ createPackableSpecs(SimplePolylineGeometry, line, packedInstance, 'geodesic line');
+
+ line = new SimplePolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ colorsPerVertex : false,
+ arcType : ArcType.RHUMB,
+ granularity : 11,
+ ellipsoid : new Ellipsoid(12, 13, 14)
+ });
+ packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 0, 2, 11];
+ createPackableSpecs(SimplePolylineGeometry, line, packedInstance, 'rhumb line');
+
+ line = new SimplePolylineGeometry({
+ positions : positions,
+ width : 10.0,
+ colorsPerVertex : false,
+ arcType : ArcType.NONE,
+ granularity : 11,
+ ellipsoid : new Ellipsoid(12, 13, 14)
+ });
+ packedInstance = [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 12, 13, 14, 0, 0, 11];
+ createPackableSpecs(SimplePolylineGeometry, line, packedInstance, 'straight line');
});
diff --git a/Specs/DataSources/GeoJsonDataSourceSpec.js b/Specs/DataSources/GeoJsonDataSourceSpec.js
index 135e6a4d0279..4ae059cbdc05 100644
--- a/Specs/DataSources/GeoJsonDataSourceSpec.js
+++ b/Specs/DataSources/GeoJsonDataSourceSpec.js
@@ -761,7 +761,6 @@ defineSuite([
expect(entity.polygon.outlineWidth.getValue(time)).toEqual(GeoJsonDataSource.strokeWidth);
expect(entity.polygon.outlineColor.getValue(time)).toEqual(GeoJsonDataSource.stroke);
expect(entity.polygon.height).toBeUndefined();
-
});
});
diff --git a/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/Specs/DataSources/PolygonGeometryUpdaterSpec.js
index 52814aaf77a2..6b14ca626485 100644
--- a/Specs/DataSources/PolygonGeometryUpdaterSpec.js
+++ b/Specs/DataSources/PolygonGeometryUpdaterSpec.js
@@ -1,6 +1,7 @@
defineSuite([
'DataSources/PolygonGeometryUpdater',
'Core/ApproximateTerrainHeights',
+ 'Core/ArcType',
'Core/Cartesian3',
'Core/Color',
'Core/Ellipsoid',
@@ -30,6 +31,7 @@ defineSuite([
], function(
PolygonGeometryUpdater,
ApproximateTerrainHeights,
+ ArcType,
Cartesian3,
Color,
Ellipsoid,
@@ -227,6 +229,16 @@ defineSuite([
expect(updater.isDynamic).toBe(true);
});
+ it('A time-varying arcType causes geometry to be dynamic', function() {
+ var entity = createBasicPolygon();
+ var updater = new PolygonGeometryUpdater(entity, scene);
+ entity.polygon.arcType = new SampledProperty(Number);
+ entity.polygon.arcType.addSample(time, 1);
+ updater._onEntityPropertyChanged(entity, 'polygon');
+
+ expect(updater.isDynamic).toBe(true);
+ });
+
it('Creates geometry with expected properties', function() {
var options = {
height : 431,
@@ -234,8 +246,9 @@ defineSuite([
granularity : 0.97,
stRotation : 12,
perPositionHeight : false,
- closeTop: true,
- closeBottom: false
+ closeTop : true,
+ closeBottom : false,
+ arcType : ArcType.GEODESIC
};
var entity = createBasicPolygon();
@@ -249,6 +262,7 @@ defineSuite([
polygon.height = new ConstantProperty(options.height);
polygon.extrudedHeight = new ConstantProperty(options.extrudedHeight);
polygon.granularity = new ConstantProperty(options.granularity);
+ polygon.arcType = new ConstantProperty(options.arcType);
var updater = new PolygonGeometryUpdater(entity, scene);
@@ -263,6 +277,7 @@ defineSuite([
expect(geometry._extrudedHeight).toEqual(options.extrudedHeight);
expect(geometry._closeTop).toEqual(options.closeTop);
expect(geometry._closeBottom).toEqual(options.closeBottom);
+ expect(geometry._arcType).toEqual(options.arcType);
expect(geometry._offsetAttribute).toBeUndefined();
instance = updater.createOutlineGeometryInstance(time);
@@ -358,6 +373,7 @@ defineSuite([
polygon.stRotation = createDynamicProperty(1);
polygon.closeTop = createDynamicProperty(false);
polygon.closeBottom = createDynamicProperty(false);
+ polygon.arcType = createDynamicProperty(ArcType.RHUMB);
var entity = new Entity();
entity.polygon = polygon;
@@ -376,6 +392,7 @@ defineSuite([
expect(options.stRotation).toEqual(polygon.stRotation.getValue());
expect(options.closeTop).toEqual(polygon.closeTop.getValue());
expect(options.closeBottom).toEqual(polygon.closeBottom.getValue());
+ expect(options.arcType).toEqual(polygon.arcType.getValue());
expect(options.offsetAttribute).toBeUndefined();
});
diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js
index a313822e45b6..615556dbdfb7 100644
--- a/Specs/DataSources/PolygonGraphicsSpec.js
+++ b/Specs/DataSources/PolygonGraphicsSpec.js
@@ -1,5 +1,6 @@
defineSuite([
'DataSources/PolygonGraphics',
+ 'Core/ArcType',
'Core/Color',
'Core/DistanceDisplayCondition',
'Core/PolygonHierarchy',
@@ -11,6 +12,7 @@ defineSuite([
'Specs/testMaterialDefinitionChanged'
], function(
PolygonGraphics,
+ ArcType,
Color,
DistanceDisplayCondition,
PolygonHierarchy,
@@ -41,6 +43,7 @@ defineSuite([
shadows : ShadowMode.DISABLED,
distanceDisplayCondition : new DistanceDisplayCondition(),
classificationType : ClassificationType.TERRAIN,
+ arcType: ArcType.GEODESIC,
zIndex: 22
};
@@ -62,6 +65,7 @@ defineSuite([
expect(polygon.shadows).toBeInstanceOf(ConstantProperty);
expect(polygon.distanceDisplayCondition).toBeInstanceOf(ConstantProperty);
expect(polygon.classificationType).toBeInstanceOf(ConstantProperty);
+ expect(polygon.arcType).toBeInstanceOf(ConstantProperty);
expect(polygon.zIndex).toBeInstanceOf(ConstantProperty);
expect(polygon.material.color.getValue()).toEqual(options.material);
@@ -81,6 +85,7 @@ defineSuite([
expect(polygon.shadows.getValue()).toEqual(options.shadows);
expect(polygon.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition);
expect(polygon.classificationType.getValue()).toEqual(options.classificationType);
+ expect(polygon.arcType.getValue()).toEqual(options.arcType);
expect(polygon.zIndex.getValue()).toEqual(22);
});
@@ -103,6 +108,7 @@ defineSuite([
source.shadows = new ConstantProperty(ShadowMode.ENABLED);
source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition());
source.classificationType = new ConstantProperty(ClassificationType.TERRAIN);
+ source.arcType = new ConstantProperty(ArcType.RHUMB);
source.zIndex = new ConstantProperty(30);
var target = new PolygonGraphics();
@@ -125,6 +131,7 @@ defineSuite([
expect(target.shadows).toBe(source.shadows);
expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition);
expect(target.classificationType).toBe(source.classificationType);
+ expect(target.arcType).toBe(source.arcType);
expect(target.zIndex).toBe(source.zIndex);
});
@@ -148,6 +155,7 @@ defineSuite([
var shadows = new ConstantProperty();
var distanceDisplayCondition = new ConstantProperty();
var classificationType = new ConstantProperty();
+ var arcType = new ConstantProperty();
var zIndex = new ConstantProperty();
var target = new PolygonGraphics();
@@ -168,6 +176,7 @@ defineSuite([
target.shadows = shadows;
target.distanceDisplayCondition = distanceDisplayCondition;
target.classificationType = classificationType;
+ target.arcType = arcType;
target.zIndex = zIndex;
target.merge(source);
@@ -189,6 +198,7 @@ defineSuite([
expect(target.shadows).toBe(shadows);
expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition);
expect(target.classificationType).toBe(classificationType);
+ expect(target.arcType).toBe(arcType);
expect(target.zIndex).toBe(zIndex);
});
@@ -211,6 +221,7 @@ defineSuite([
source.shadows = new ConstantProperty();
source.distanceDisplayCondition = new ConstantProperty();
source.classificationType = new ConstantProperty();
+ source.arcType = new ConstantProperty();
source.zIndex = new ConstantProperty();
var result = source.clone();
@@ -231,6 +242,7 @@ defineSuite([
expect(result.shadows).toBe(source.shadows);
expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition);
expect(result.classificationType).toBe(source.classificationType);
+ expect(result.arcType).toBe(source.arcType);
expect(result.zIndex).toBe(source.zIndex);
});
@@ -260,6 +272,7 @@ defineSuite([
testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED);
testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0));
testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN, ClassificationType.BOTH);
+ testDefinitionChanged(property, 'arcType', ArcType.GEODESIC, ArcType.RHUMB);
testDefinitionChanged(property, 'zIndex', 54, 3);
});
});
diff --git a/Specs/DataSources/PolylineGeometryUpdaterSpec.js b/Specs/DataSources/PolylineGeometryUpdaterSpec.js
index 67f2e43daff3..9d3ec2ca8179 100644
--- a/Specs/DataSources/PolylineGeometryUpdaterSpec.js
+++ b/Specs/DataSources/PolylineGeometryUpdaterSpec.js
@@ -1,10 +1,12 @@
defineSuite([
'DataSources/PolylineGeometryUpdater',
'Core/ApproximateTerrainHeights',
+ 'Core/ArcType',
'Core/BoundingSphere',
'Core/Cartesian3',
'Core/Color',
'Core/ColorGeometryInstanceAttribute',
+ 'Core/defined',
'Core/DistanceDisplayCondition',
'Core/DistanceDisplayConditionGeometryInstanceAttribute',
'Core/GroundPolylineGeometry',
@@ -33,10 +35,12 @@ defineSuite([
], function(
PolylineGeometryUpdater,
ApproximateTerrainHeights,
+ ArcType,
BoundingSphere,
Cartesian3,
Color,
ColorGeometryInstanceAttribute,
+ defined,
DistanceDisplayCondition,
DistanceDisplayConditionGeometryInstanceAttribute,
GroundPolylineGeometry,
@@ -115,6 +119,7 @@ defineSuite([
expect(updater.distanceDisplayConditionProperty).toBe(undefined);
expect(updater.isDynamic).toBe(false);
expect(updater.clampToGround).toBe(false);
+ expect(updater.arcType).toBe(undefined);
expect(updater.zIndex).toBe(0);
expect(updater.isOutlineVisible(time)).toBe(false);
@@ -159,6 +164,7 @@ defineSuite([
expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition()));
expect(updater.isDynamic).toBe(false);
expect(updater.clampToGround).toBe(false);
+ expect(updater.arcType).toBe(undefined);
expect(updater.zIndex).toEqual(new ConstantProperty(0));
});
@@ -229,6 +235,14 @@ defineSuite([
expect(updater.isDynamic).toBe(true);
});
+ it('A time-varying arcType causes geometry to be dynamic', function() {
+ var entity = createBasicPolyline();
+ var updater = new PolylineGeometryUpdater(entity, scene);
+ entity.polyline.arcType = new SampledProperty(Number);
+ entity.polyline.arcType.addSample(time, 1);
+ expect(updater.isDynamic).toBe(true);
+ });
+
it('A time-varying zIndex causes geometry to be dynamic', function() {
var entity = createBasicPolyline();
var updater = new PolylineGeometryUpdater(entity, scene);
@@ -251,6 +265,7 @@ defineSuite([
polyline.granularity = new ConstantProperty(options.granularity);
polyline.distanceDisplayCondition = options.distanceDisplayCondition;
polyline.clampToGround = new ConstantProperty(clampToGround);
+ polyline.arcType = new ConstantProperty(options.arcType);
var updater = new PolylineGeometryUpdater(entity, scene);
@@ -265,7 +280,12 @@ defineSuite([
expect(geometry.width).toEqual(options.width);
} else {
expect(geometry._width).toEqual(options.width);
- expect(geometry._followSurface).toEqual(options.followSurface);
+ if (defined(options.followSurface)) {
+ expect(geometry._followSurface).toEqual(options.followSurface);
+ }
+ if (defined(options.arcType)) {
+ expect(geometry._arcType).toEqual(options.arcType);
+ }
expect(geometry._granularity).toEqual(options.granularity);
if (options.depthFailMaterial && options.depthFailMaterial instanceof ColorMaterialProperty) {
@@ -293,7 +313,8 @@ defineSuite([
width : 3,
followSurface : false,
clampToGround : false,
- granularity : 1.0
+ granularity : 1.0,
+ arcType : ArcType.NONE
});
if (!Entity.supportsPolylinesOnTerrain(scene)) {
@@ -307,7 +328,8 @@ defineSuite([
width : 3,
followSurface : false,
clampToGround : true,
- granularity : 1.0
+ granularity : 1.0,
+ arcType : ArcType.GEODESIC
});
});
@@ -317,9 +339,10 @@ defineSuite([
material : new ColorMaterialProperty(Color.RED),
depthFailMaterial : new ColorMaterialProperty(Color.BLUE),
width : 3,
- followSurface : false,
+ followSurface : true,
clampToGround : false,
- granularity : 1.0
+ granularity : 1.0,
+ arcType : ArcType.GEODESIC
});
});
@@ -329,9 +352,9 @@ defineSuite([
material : new ColorMaterialProperty(Color.RED),
depthFailMaterial : new GridMaterialProperty(),
width : 3,
- followSurface : false,
clampToGround : false,
- granularity : 1.0
+ granularity : 1.0,
+ arcType : ArcType.RHUMB
});
});
@@ -342,7 +365,8 @@ defineSuite([
width : 4,
followSurface : true,
clampToGround : false,
- granularity : 0.5
+ granularity : 0.5,
+ arcType: ArcType.GEODESIC
});
if (!Entity.supportsPolylinesOnTerrain(scene)) {
@@ -356,7 +380,8 @@ defineSuite([
width : 4,
followSurface : true,
clampToGround : true,
- granularity : 0.5
+ granularity : 0.5,
+ arcType: ArcType.GEODESIC
});
});
@@ -477,6 +502,7 @@ defineSuite([
polyline.material = new ColorMaterialProperty(Color.RED);
polyline.followSurface = new ConstantProperty(false);
polyline.granularity = new ConstantProperty(0.001);
+ polyline.ArcType = new ConstantProperty(ArcType.NONE);
var updater = new PolylineGeometryUpdater(entity, scene);
@@ -499,6 +525,7 @@ defineSuite([
expect(primitive.positions.length).toEqual(2);
polyline.followSurface = new ConstantProperty(true);
+ polyline.arcType = new ConstantProperty(ArcType.GEODESIC);
dynamicUpdater.update(time3);
expect(primitive.width).toEqual(3);
@@ -561,6 +588,59 @@ defineSuite([
updater.destroy();
});
+ it('arcType can be dynamic', function() {
+ var entity = new Entity();
+ var polyline = new PolylineGraphics();
+ entity.polyline = polyline;
+
+ var time = new JulianDate(0, 0);
+
+ var arcTypeVar = ArcType.GEODESIC;
+ var arcType = new CallbackProperty(function() {
+ return arcTypeVar;
+ }, false);
+
+ polyline.show = new ConstantProperty(true);
+ polyline.width = new ConstantProperty(1.0);
+ polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0, 0, 0), Cartesian3.fromDegrees(0, 1, 0)]);
+ polyline.material = new ColorMaterialProperty(Color.RED);
+ polyline.followSurface = new ConstantProperty(true);
+ polyline.granularity = new ConstantProperty(0.001);
+ polyline.clampToGround = new ConstantProperty(false);
+ polyline.arcType = arcType;
+
+ var updater = new PolylineGeometryUpdater(entity, scene);
+
+ var primitives = scene.primitives;
+ expect(primitives.length).toBe(0);
+
+ var dynamicUpdater = updater.createDynamicUpdater(primitives, scene.groundPrimitives);
+ expect(dynamicUpdater.isDestroyed()).toBe(false);
+ expect(primitives.length).toBe(0);
+
+ dynamicUpdater.update(time);
+
+ expect(primitives.length).toBe(1);
+ var polylineCollection = primitives.get(0);
+ var polylineObject = polylineCollection.get(0);
+
+ expect(polylineObject.show).toEqual(true);
+
+ var geodesicPolylinePositionsLength = polylineObject.positions.length;
+
+ arcTypeVar = ArcType.NONE;
+ dynamicUpdater.update(time);
+
+ expect(polylineObject.positions.length).not.toEqual(geodesicPolylinePositionsLength);
+
+ dynamicUpdater.destroy();
+
+ expect(scene.primitives.length).toBe(0);
+ expect(primitives.length).toBe(0);
+
+ updater.destroy();
+ });
+
it('geometryChanged event is raised when expected', function() {
var entity = createBasicPolyline();
var updater = new PolylineGeometryUpdater(entity, scene);
@@ -767,6 +847,32 @@ defineSuite([
});
it('followSurface true with undefined globe does not call generateCartesianArc', function() {
+ if (!Entity.supportsPolylinesOnTerrain(scene)) {
+ return;
+ }
+
+ var entity = createBasicPolyline();
+ entity.polyline.width = createDynamicProperty(1);
+ scene.globe = undefined;
+ var updater = new PolylineGeometryUpdater(entity, scene);
+ var dynamicUpdater = updater.createDynamicUpdater(scene.primitives, scene.groundPrimitives);
+ spyOn(PolylinePipeline, 'generateCartesianArc').and.callThrough();
+ dynamicUpdater.update(time);
+ expect(PolylinePipeline.generateCartesianArc).not.toHaveBeenCalled();
+ dynamicUpdater.destroy();
+ updater.destroy();
+
+ expect(scene.primitives.length).toBe(0);
+ expect(scene.groundPrimitives.length).toBe(0);
+
+ scene.globe = new Globe();
+ });
+
+ it('arcType GEODESIC with undefined globe does not call generateCartesianArc', function() {
+ if (!Entity.supportsPolylinesOnTerrain(scene)) {
+ return;
+ }
+
var entity = createBasicPolyline();
entity.polyline.width = createDynamicProperty(1);
scene.globe = undefined;
diff --git a/Specs/DataSources/PolylineGraphicsSpec.js b/Specs/DataSources/PolylineGraphicsSpec.js
index b44bb4244dfe..993af95a53ef 100644
--- a/Specs/DataSources/PolylineGraphicsSpec.js
+++ b/Specs/DataSources/PolylineGraphicsSpec.js
@@ -1,5 +1,6 @@
defineSuite([
'DataSources/PolylineGraphics',
+ 'Core/ArcType',
'Core/Color',
'Core/DistanceDisplayCondition',
'DataSources/ColorMaterialProperty',
@@ -10,6 +11,7 @@ defineSuite([
'Specs/testMaterialDefinitionChanged'
], function(
PolylineGraphics,
+ ArcType,
Color,
DistanceDisplayCondition,
ColorMaterialProperty,
@@ -33,6 +35,7 @@ defineSuite([
shadows : ShadowMode.DISABLED,
distanceDisplayCondition : new DistanceDisplayCondition(),
classificationType : ClassificationType.TERRAIN,
+ arcType: ArcType.GEODESIC,
zIndex : 0
};
@@ -48,6 +51,7 @@ defineSuite([
expect(polyline.shadows).toBeInstanceOf(ConstantProperty);
expect(polyline.distanceDisplayCondition).toBeInstanceOf(ConstantProperty);
expect(polyline.classificationType).toBeInstanceOf(ConstantProperty);
+ expect(polyline.arcType).toBeInstanceOf(ConstantProperty);
expect(polyline.zIndex).toBeInstanceOf(ConstantProperty);
expect(polyline.material.color.getValue()).toEqual(options.material);
@@ -61,6 +65,7 @@ defineSuite([
expect(polyline.shadows.getValue()).toEqual(options.shadows);
expect(polyline.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition);
expect(polyline.classificationType.getValue()).toEqual(options.classificationType);
+ expect(polyline.arcType.getValue()).toEqual(options.arcType);
expect(polyline.zIndex.getValue()).toEqual(options.zIndex);
});
@@ -77,6 +82,7 @@ defineSuite([
source.shadows = new ConstantProperty(ShadowMode.ENABLED);
source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition());
source.classificationType = new ConstantProperty(ClassificationType.TERRAIN);
+ source.arcType = new ConstantProperty(ArcType.GEODESIC);
source.zIndex = new ConstantProperty();
var target = new PolylineGraphics();
@@ -92,6 +98,7 @@ defineSuite([
expect(target.shadows).toBe(source.shadows);
expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition);
expect(target.classificationType).toBe(source.classificationType);
+ expect(target.arcType).toBe(source.arcType);
expect(target.zIndex).toBe(source.zIndex);
});
@@ -108,6 +115,7 @@ defineSuite([
source.shadows = new ConstantProperty();
source.distanceDisplayCondition = new ConstantProperty();
source.classificationType = new ConstantProperty();
+ source.arcType = new ConstantProperty();
source.zIndex = new ConstantProperty();
var color = new ColorMaterialProperty();
@@ -121,6 +129,7 @@ defineSuite([
var shadows = new ConstantProperty();
var distanceDisplayCondition = new ConstantProperty();
var classificationType = new ConstantProperty();
+ var arcType = new ConstantProperty();
var zIndex = new ConstantProperty();
var target = new PolylineGraphics();
@@ -135,6 +144,7 @@ defineSuite([
target.shadows = shadows;
target.distanceDisplayCondition = distanceDisplayCondition;
target.classificationType = classificationType;
+ target.arcType = arcType;
target.zIndex = zIndex;
target.merge(source);
@@ -149,6 +159,7 @@ defineSuite([
expect(target.shadows).toBe(shadows);
expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition);
expect(target.classificationType).toBe(classificationType);
+ expect(target.arcType).toBe(arcType);
expect(target.zIndex).toBe(zIndex);
});
@@ -165,6 +176,7 @@ defineSuite([
source.shadows = new ConstantProperty();
source.distanceDisplayCondition = new ConstantProperty();
source.classificationType = new ConstantProperty();
+ source.arcType = new ConstantProperty();
source.zIndex = new ConstantProperty();
var result = source.clone();
@@ -179,6 +191,7 @@ defineSuite([
expect(result.shadows).toBe(source.shadows);
expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition);
expect(result.classificationType).toBe(source.classificationType);
+ expect(result.arcType).toBe(source.arcType);
expect(result.zIndex).toBe(source.zIndex);
});
@@ -202,6 +215,7 @@ defineSuite([
testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED);
testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 20.0));
testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN);
+ testDefinitionChanged(property, 'arcType', ArcType.GEODESIC, ArcType.RHUMB);
testDefinitionChanged(property, 'zIndex', 20, 5);
});
});