diff --git a/Apps/Sandcastle/gallery/CZML Polygon.html b/Apps/Sandcastle/gallery/CZML Polygon.html index f1a22a65f027..e8d819ad0ba3 100644 --- a/Apps/Sandcastle/gallery/CZML Polygon.html +++ b/Apps/Sandcastle/gallery/CZML Polygon.html @@ -72,7 +72,9 @@ } } }, - "extrudedHeight" : 500000.0 + "extrudedHeight" : 500000.0, + "closeTop" : false, + "closeBottom" : false } }, { "id" : "orangePolygon", diff --git a/Apps/Sandcastle/gallery/Polygon.html b/Apps/Sandcastle/gallery/Polygon.html index fcd13e32abde..2d094d77f01c 100644 --- a/Apps/Sandcastle/gallery/Polygon.html +++ b/Apps/Sandcastle/gallery/Polygon.html @@ -48,7 +48,9 @@ -100.0, 42.0, -104.0, 40.0]), extrudedHeight: 500000.0, - material : Cesium.Color.GREEN + material : Cesium.Color.GREEN, + closeTop : false, + closeBottom : false } }); diff --git a/CHANGES.md b/CHANGES.md index 5b0aa11c0bec..d7b755eae8a7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Change Log * * Fixed issue causing the sun not to render. [#3801](https://github.com/AnalyticalGraphicsInc/cesium/pull/3801) * Added ability to import and export Sandcastle example using GitHub Gists. [#3795](https://github.com/AnalyticalGraphicsInc/cesium/pull/3795) +* Added `PolygonGraphics.closeTop`, `PolygonGraphics.closeBottom`, and `PolygonGeometry` options for creating an extruded polygon without a top or bottom. * Fixed issue where `Camera.flyTo` does not go to the rectangle. [#3688](https://github.com/AnalyticalGraphicsInc/cesium/issues/3688) * Fixed issue causing the fog to go dark and the atmosphere to flicker when the camera clips the globe. [#3178](https://github.com/AnalyticalGraphicsInc/cesium/issues/3178) * Fixed a bug that caused an exception and rendering to stop when using `ArcGisMapServerImageryProvider` to connect to a MapServer specifying the Web Mercator projection and a fullExtent bigger than the valid extent of the projection. [#3854](https://github.com/AnalyticalGraphicsInc/cesium/pull/3854) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 4b8558179edd..b0033ed68428 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -109,8 +109,8 @@ define([ var tangentPlane = options.tangentPlane; var ellipsoid = options.ellipsoid; var stRotation = options.stRotation; - var bottom = options.bottom; - var wall = options.wall; + var top = options.top || options.wall; + var bottom = options.bottom || options.wall; var origin = appendTextureCoordinatesOrigin; origin.x = boundingRectangle.x; @@ -135,10 +135,13 @@ define([ var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, stRotation, appendTextureCoordinatesQuaternion); var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); - var bottomOffset = length / 2; - var bottomOffset2 = length / 3; + var bottomOffset = 0; + var bottomOffset2 = 0; + + if (top && bottom) { + bottomOffset = length / 2; + bottomOffset2 = length / 3; - if (bottom) { length /= 2; } @@ -157,9 +160,10 @@ define([ textureCoordinates[textureCoordIndex + bottomOffset2] = stx; textureCoordinates[textureCoordIndex + 1 + bottomOffset2] = sty; } - - textureCoordinates[textureCoordIndex] = stx; - textureCoordinates[textureCoordIndex + 1] = sty; + if (top) { + textureCoordinates[textureCoordIndex] = stx; + textureCoordinates[textureCoordIndex + 1] = sty; + } textureCoordIndex += 2; } @@ -168,7 +172,7 @@ define([ var attrIndex1 = attrIndex + 1; var attrIndex2 = attrIndex + 2; - if (wall) { + if (options.wall) { if (i + 3 < length) { var p1 = Cartesian3.fromArray(flatPositions, i + 3, p1Scratch); @@ -191,7 +195,6 @@ define([ tangent = Cartesian3.normalize(Cartesian3.cross(binormal, normal, tangent), tangent); } } - } else { normal = ellipsoid.geodeticSurfaceNormal(position, normal); if (vertexFormat.tangent || vertexFormat.binormal) { @@ -204,35 +207,38 @@ define([ } if (vertexFormat.normal) { - if (bottom && !wall) { - normals[attrIndex + bottomOffset] = -normal.x; - normals[attrIndex1 + bottomOffset] = -normal.y; - normals[attrIndex2 + bottomOffset] = -normal.z; - } else { + if (options.wall) { normals[attrIndex + bottomOffset] = normal.x; normals[attrIndex1 + bottomOffset] = normal.y; normals[attrIndex2 + bottomOffset] = normal.z; + } else if (bottom){ + normals[attrIndex + bottomOffset] = -normal.x; + normals[attrIndex1 + bottomOffset] = -normal.y; + normals[attrIndex2 + bottomOffset] = -normal.z; + } + if (top) { + normals[attrIndex] = normal.x; + normals[attrIndex1] = normal.y; + normals[attrIndex2] = normal.z; } - - normals[attrIndex] = normal.x; - normals[attrIndex1] = normal.y; - normals[attrIndex2] = normal.z; } if (vertexFormat.tangent) { - if (bottom && !wall) { - tangents[attrIndex + bottomOffset] = -tangent.x; - tangents[attrIndex1 + bottomOffset] = -tangent.y; - tangents[attrIndex2 + bottomOffset] = -tangent.z; - } else { + if (options.wall) { tangents[attrIndex + bottomOffset] = tangent.x; tangents[attrIndex1 + bottomOffset] = tangent.y; tangents[attrIndex2 + bottomOffset] = tangent.z; + } else if (bottom) { + tangents[attrIndex + bottomOffset] = -tangent.x; + tangents[attrIndex1 + bottomOffset] = -tangent.y; + tangents[attrIndex2 + bottomOffset] = -tangent.z; } - tangents[attrIndex] = tangent.x; - tangents[attrIndex1] = tangent.y; - tangents[attrIndex2] = tangent.z; + if(top) { + tangents[attrIndex] = tangent.x; + tangents[attrIndex1] = tangent.y; + tangents[attrIndex2] = tangent.z; + } } if (vertexFormat.binormal) { @@ -241,10 +247,11 @@ define([ binormals[attrIndex1 + bottomOffset] = binormal.y; binormals[attrIndex2 + bottomOffset] = binormal.z; } - - binormals[attrIndex] = binormal.x; - binormals[attrIndex1] = binormal.y; - binormals[attrIndex2] = binormal.z; + if (top) { + binormals[attrIndex] = binormal.x; + binormals[attrIndex1] = binormal.y; + binormals[attrIndex2] = binormal.z; + } } attrIndex += 3; } @@ -287,50 +294,61 @@ define([ var createGeometryFromPositionsExtrudedPositions = []; - function createGeometryFromPositionsExtruded(ellipsoid, positions, granularity, hierarchy, perPositionHeight) { - var topGeo = PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, positions, granularity, perPositionHeight); + function createGeometryFromPositionsExtruded(ellipsoid, positions, granularity, hierarchy, perPositionHeight, closeTop, closeBottom) { + var geos = { + walls : [] + }; + var i; - var edgePoints = topGeo.attributes.position.values; - var indices = topGeo.indices; + if (closeTop || closeBottom) { + var topGeo = PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, positions, granularity, perPositionHeight); - var topBottomPositions = edgePoints.concat(edgePoints); - var numPositions = topBottomPositions.length / 3; + var edgePoints = topGeo.attributes.position.values; + var indices = topGeo.indices; + var numPositions; + var newIndices; - var newIndices = IndexDatatype.createTypedArray(numPositions, indices.length * 2); - newIndices.set(indices); - var ilength = indices.length; + if (closeTop && closeBottom) { + var topBottomPositions = edgePoints.concat(edgePoints); + numPositions = topBottomPositions.length / 3; - var i; - var length = numPositions / 2; + newIndices = IndexDatatype.createTypedArray(numPositions, indices.length * 2); + newIndices.set(indices); + var ilength = indices.length; - for (i = 0; i < ilength; i += 3) { - var i0 = newIndices[i] + length; - var i1 = newIndices[i + 1] + length; - var i2 = newIndices[i + 2] + length; - newIndices[i + ilength] = i2; - newIndices[i + 1 + ilength] = i1; - newIndices[i + 2 + ilength] = i0; - } + var length = numPositions / 2; - var topAndBottomGeo = new Geometry({ - attributes : new GeometryAttributes({ - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : topBottomPositions - }) - }), - indices : newIndices, - primitiveType : topGeo.primitiveType - }); + for (i = 0; i < ilength; i += 3) { + var i0 = newIndices[i] + length; + var i1 = newIndices[i + 1] + length; + var i2 = newIndices[i + 2] + length; - var geos = { - topAndBottom : new GeometryInstance({ - geometry : topAndBottomGeo - }), - walls : [] - }; + newIndices[i + ilength] = i2; + newIndices[i + 1 + ilength] = i1; + newIndices[i + 2 + ilength] = i0; + } + + topGeo.attributes.position.values = topBottomPositions; + topGeo.indices = newIndices; + } else if (closeBottom) { + numPositions = edgePoints.length / 3; + newIndices = IndexDatatype.createTypedArray(numPositions, indices.length); + + for (i = 0; i < indices.length; i += 3) { + newIndices[i] = indices[i + 2]; + newIndices[i + 1] = indices[i + 1]; + newIndices[i + 2] = indices[i]; + } + + topGeo.indices = newIndices; + } + + geos.topAndBottom = new GeometryInstance({ + geometry : topGeo + }); + + } var outerRing = hierarchy.outerRing; var tangentPlane = EllipsoidTangentPlane.fromPoints(outerRing, ellipsoid); @@ -382,6 +400,8 @@ 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 {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. * * @see PolygonGeometry#createGeometry * @see PolygonGeometry#fromPositions @@ -492,6 +512,8 @@ define([ this._height = height; this._extrudedHeight = defaultValue(extrudedHeight, 0.0); this._extrude = extrude; + this._closeTop = defaultValue(options.closeTop, true); + this._closeBottom = defaultValue(options.closeBottom, true); this._polygonHierarchy = polygonHierarchy; this._perPositionHeight = perPositionHeight; this._workerName = 'createPolygonGeometry'; @@ -500,7 +522,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 + 7; + this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + 9; } /** @@ -515,6 +537,8 @@ 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 {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. * @returns {PolygonGeometry} * * @@ -552,7 +576,9 @@ define([ stRotation : options.stRotation, ellipsoid : options.ellipsoid, granularity : options.granularity, - perPositionHeight : options.perPositionHeight + perPositionHeight : options.perPositionHeight, + closeTop : options.closeTop, + closeBottom: options.closeBottom }; return new PolygonGeometry(newOptions); }; @@ -590,6 +616,8 @@ define([ array[startingIndex++] = value._stRotation; array[startingIndex++] = value._extrude ? 1.0 : 0.0; array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0; + array[startingIndex++] = value._closeTop ? 1.0 : 0.0; + array[startingIndex++] = value._closeBottom ? 1.0 : 0.0; array[startingIndex] = value.packedLength; }; @@ -633,6 +661,8 @@ define([ var stRotation = array[startingIndex++]; var extrude = array[startingIndex++] === 1.0; var perPositionHeight = array[startingIndex++] === 1.0; + var closeTop = array[startingIndex++] === 1.0; + var closeBottom = array[startingIndex++] === 1.0; var packedLength = array[startingIndex]; if (!defined(result)) { @@ -648,6 +678,8 @@ define([ result._stRotation = stRotation; result._extrude = extrude; result._perPositionHeight = perPositionHeight; + result._closeTop = closeTop; + result._closeBottom = closeBottom; result.packedLength = packedLength; return result; }; @@ -668,6 +700,8 @@ define([ var extrude = polygonGeometry._extrude; var polygonHierarchy = polygonGeometry._polygonHierarchy; var perPositionHeight = polygonGeometry._perPositionHeight; + var closeTop = polygonGeometry._closeTop; + var closeBottom = polygonGeometry._closeBottom; var walls; var topAndBottom; @@ -705,16 +739,31 @@ define([ ellipsoid: ellipsoid, stRotation: stRotation, bottom: false, + top: true, wall: false }; if (extrude) { - options.bottom = true; + options.top = closeTop; + options.bottom = closeBottom; for (i = 0; i < polygons.length; i++) { - geometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight); - topAndBottom = geometry.topAndBottom; - options.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(topAndBottom.geometry, height, extrudedHeight, ellipsoid, perPositionHeight); - topAndBottom.geometry = computeAttributes(options); - geometries.push(topAndBottom); + geometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom); + if (closeTop && closeBottom) { + topAndBottom = geometry.topAndBottom; + options.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(topAndBottom.geometry, height, extrudedHeight, ellipsoid, perPositionHeight); + } else if (closeTop) { + topAndBottom = geometry.topAndBottom; + topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(topAndBottom.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight); + options.geometry = topAndBottom.geometry; + } else if (closeBottom) { + topAndBottom = geometry.topAndBottom; + topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(topAndBottom.geometry.attributes.position.values, extrudedHeight, ellipsoid, true); + options.geometry = topAndBottom.geometry; + } + if (closeTop || closeBottom) { + options.wall = false; + topAndBottom.geometry = computeAttributes(options); + geometries.push(topAndBottom); + } walls = geometry.walls; options.wall = true; diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index 8ee31cf7c84e..3976b27fd081 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -1319,6 +1319,8 @@ define([ processPacketData(Color, polygon, 'outlineColor', polygonData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'outlineWidth', polygonData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'perPositionHeight', polygonData.perPositionHeight, interval, sourceUri, entityCollection); + processPacketData(Boolean, polygon, 'closeTop', polygonData.closeTop, interval, sourceUri, entityCollection); + processPacketData(Boolean, polygon, 'closeBottom', polygonData.closeBottom, interval, sourceUri, entityCollection); processPositions(polygon, 'hierarchy', polygonData.positions, entityCollection); } diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index 7bc0615ffbca..8bb71ebcb9bf 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -61,6 +61,8 @@ define([ this.vertexFormat = undefined; this.polygonHierarchy = undefined; this.perPositionHeight = undefined; + this.closeTop = undefined; + this.closeBottom = undefined; this.height = undefined; this.extrudedHeight = undefined; this.granularity = undefined; @@ -453,6 +455,8 @@ define([ var stRotation = polygon.stRotation; var outlineWidth = polygon.outlineWidth; var perPositionHeight = polygon.perPositionHeight; + var closeTop = polygon.closeTop; + var closeBottom = polygon.closeBottom; this._fillEnabled = fillEnabled; this._outlineEnabled = outlineEnabled; @@ -463,7 +467,9 @@ define([ !Property.isConstant(granularity) || // !Property.isConstant(stRotation) || // !Property.isConstant(outlineWidth) || // - !Property.isConstant(perPositionHeight)) { + !Property.isConstant(perPositionHeight) || // + !Property.isConstant(closeTop) || // + !Property.isConstant(closeBottom)) { if (!this._dynamic) { this._dynamic = true; this._geometryChanged.raiseEvent(this); @@ -477,17 +483,21 @@ define([ hierarchyValue = new PolygonHierarchy(hierarchyValue); } - var heightValue = defined(height) ? height.getValue(Iso8601.MINIMUM_VALUE) : undefined; - var extrudedHeightValue = defined(extrudedHeight) ? extrudedHeight.getValue(Iso8601.MINIMUM_VALUE) : undefined; + var heightValue = Property.getValueOrUndefined(height, Iso8601.MINIMUM_VALUE); + var closeTopValue = Property.getValueOrDefault(closeTop, Iso8601.MINIMUM_VALUE, true); + var closeBottomValue = Property.getValueOrDefault(closeBottom, Iso8601.MINIMUM_VALUE, true); + var extrudedHeightValue = Property.getValueOrUndefined(extrudedHeight, Iso8601.MINIMUM_VALUE); options.polygonHierarchy = hierarchyValue; options.height = heightValue; options.extrudedHeight = extrudedHeightValue; - options.granularity = defined(granularity) ? granularity.getValue(Iso8601.MINIMUM_VALUE) : undefined; - options.stRotation = defined(stRotation) ? stRotation.getValue(Iso8601.MINIMUM_VALUE) : undefined; - options.perPositionHeight = defined(perPositionHeight) ? perPositionHeight.getValue(Iso8601.MINIMUM_VALUE) : undefined; - this._outlineWidth = defined(outlineWidth) ? outlineWidth.getValue(Iso8601.MINIMUM_VALUE) : 1.0; - this._isClosed = defined(extrudedHeightValue) && extrudedHeightValue !== heightValue; + options.granularity = Property.getValueOrUndefined(granularity, Iso8601.MINIMUM_VALUE); + options.stRotation = Property.getValueOrUndefined(stRotation, Iso8601.MINIMUM_VALUE); + options.perPositionHeight = Property.getValueOrUndefined(perPositionHeight, Iso8601.MINIMUM_VALUE); + options.closeTop = closeTopValue; + options.closeBottom = closeBottomValue; + this._outlineWidth = Property.getValueOrDefault(outlineWidth, Iso8601.MINIMUM_VALUE, 1.0); + this._isClosed = defined(extrudedHeightValue) && extrudedHeightValue !== heightValue && closeTopValue && closeBottomValue; this._dynamic = false; this._geometryChanged.raiseEvent(this); } @@ -525,6 +535,7 @@ define([ this._geometryUpdater = geometryUpdater; this._options = new GeometryOptions(geometryUpdater._entity); } + DynamicGeometryUpdater.prototype.update = function(time) { //>>includeStart('debug', pragmas.debug); if (!defined(time)) { @@ -557,11 +568,16 @@ define([ options.polygonHierarchy = hierarchy; } + var closeTopValue = Property.getValueOrDefault(polygon.closeTop, time, true); + var closeBottomValue = Property.getValueOrDefault(polygon.closeBottom, time, true); + options.height = Property.getValueOrUndefined(polygon.height, time); options.extrudedHeight = Property.getValueOrUndefined(polygon.extrudedHeight, time); options.granularity = Property.getValueOrUndefined(polygon.granularity, time); options.stRotation = Property.getValueOrUndefined(polygon.stRotation, time); options.perPositionHeight = Property.getValueOrUndefined(polygon.perPositionHeight, time); + options.closeTop = closeTopValue; + options.closeBottom = closeBottomValue; if (Property.getValueOrDefault(polygon.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); @@ -570,7 +586,7 @@ define([ var appearance = new MaterialAppearance({ material : material, translucent : material.isTranslucent(), - closed : defined(options.extrudedHeight) && options.extrudedHeight !== options.height + closed : defined(options.extrudedHeight) && options.extrudedHeight !== options.height && closeTopValue && closeBottomValue }); options.vertexFormat = appearance.vertexFormat; diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index 13d6d196596b..bf0e6f6562d9 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -38,6 +38,8 @@ define([ * @param {Property} [options.stRotation=0.0] A numeric property specifying the rotation of the polygon texture counter-clockwise from north. * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point. * @param {Property} [options.perPositionHeight=false] A boolean specifying whether or not the the height of each position is used. + * @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. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo} @@ -68,6 +70,10 @@ define([ this._definitionChanged = new Event(); this._fill = undefined; this._fillSubscription = undefined; + this._closeTop = undefined; + this._closeTopSubscription = undefined; + this._closeBottom = undefined; + this._closeBottomSubscription = undefined; this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); } @@ -181,7 +187,21 @@ define([ * @memberof PolygonGraphics.prototype * @type {Property} */ - perPositionHeight : createPropertyDescriptor('perPositionHeight') + perPositionHeight : createPropertyDescriptor('perPositionHeight'), + + /** + * Gets or sets a boolean specifying whether or not the top of an extruded polygon is included. + * @memberof PolygonGraphics.prototype + * @type {Property} + */ + closeTop : createPropertyDescriptor('closeTop'), + + /** + * Gets or sets a boolean specifying whether or not the bottom of an extruded polygon is included. + * @memberof PolygonGraphics.prototype + * @type {Property} + */ + closeBottom : createPropertyDescriptor('closeBottom') }); /** @@ -206,6 +226,8 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.perPositionHeight = this.perPositionHeight; + result.closeTop = this.closeTop; + result.closeBottom = this.closeBottom; return result; }; @@ -234,6 +256,8 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.perPositionHeight = defaultValue(this.perPositionHeight, source.perPositionHeight); + this.closeTop = defaultValue(this.closeTop, source.closeTop); + this.closeBottom = defaultValue(this.closeBottom, source.closeBottom); }; return PolygonGraphics; diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index 985df7e98fe1..0acdf647fe20 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -378,6 +378,64 @@ defineSuite([ expect(p.indices.length).toEqual(numTriangles * 3); }); + it('computes positions extruded and not closeTop', 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 + ]), + extrudedHeight: 30000, + closeTop: false + })); + + var numVertices = 37; // 13 bottom + 8 top edge + 8 bottom edge + 4 top corner + 4 bottom corner + var numTriangles = 32; // 16 bottom fill + 2 triangles * 4 sides + expect(p.attributes.position.values.length).toEqual(numVertices * 3); + expect(p.indices.length).toEqual(numTriangles * 3); + }); + + it('computes positions extruded and not closeBottom', 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 + ]), + extrudedHeight: 30000, + closeBottom: false + })); + + var numVertices = 37; // 13 top + 8 top edge + 8 bottom edge + 4 top corner + 4 bottom corner + var numTriangles = 32; // 16 top fill + 2 triangles * 4 sides + expect(p.attributes.position.values.length).toEqual(numVertices * 3); + expect(p.indices.length).toEqual(numTriangles * 3); + }); + + it('computes positions extruded and not closeBottom or closeTop', 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 + ]), + extrudedHeight: 30000, + closeTop: false, + closeBottom: false + })); + + var numVertices = 24; // 8 top edge + 8 bottom edge + 4 top corner + 4 bottom corner + var numTriangles = 16; // 2 triangles * 4 sides + expect(p.attributes.position.values.length).toEqual(numVertices * 3); + expect(p.indices.length).toEqual(numTriangles * 3); + }); + it('removes duplicates extruded', function() { var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({ vertexFormat : VertexFormat.POSITION_ONLY, @@ -559,7 +617,9 @@ defineSuite([ vertexFormat : VertexFormat.POSITION_ONLY, polygonHierarchy : hierarchy, granularity : CesiumMath.PI_OVER_THREE, - perPositionHeight : true + perPositionHeight : true, + closeTop : false, + closeBottom : true }); function addPositions(array, positions) { @@ -574,6 +634,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(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 49); + packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 51); createPackableSpecs(PolygonGeometry, polygon, packedInstance); }); diff --git a/Specs/DataSources/CzmlDataSourceSpec.js b/Specs/DataSources/CzmlDataSourceSpec.js index 60181de7c087..a8eb94edf323 100644 --- a/Specs/DataSources/CzmlDataSourceSpec.js +++ b/Specs/DataSources/CzmlDataSourceSpec.js @@ -1403,7 +1403,9 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + closeTop : false, + closeBottom : false } }; @@ -1421,6 +1423,8 @@ defineSuite([ expect(entity.polygon.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.polygon.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.polygon.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.polygon.closeTop.getValue(Iso8601.MINIMUM_VALUE)).toEqual(false); + expect(entity.polygon.closeBottom.getValue(Iso8601.MINIMUM_VALUE)).toEqual(false); }); it('CZML adds data for constrained polygon.', function() { diff --git a/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/Specs/DataSources/PolygonGeometryUpdaterSpec.js index e2e5b3e074fe..ff6823f5823e 100644 --- a/Specs/DataSources/PolygonGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolygonGeometryUpdaterSpec.js @@ -143,6 +143,22 @@ defineSuite([ expect(updater.isClosed).toBe(true); }); + it('Settings extrudedHeight and closeTop false causes geometry to be open.', function() { + var entity = createBasicPolygon(); + var updater = new PolygonGeometryUpdater(entity, scene); + entity.polygon.extrudedHeight = new ConstantProperty(1000); + entity.polygon.closeTop = false; + expect(updater.isClosed).toBe(false); + }); + + it('Settings extrudedHeight and closeBottom false causes geometry to be open.', function() { + var entity = createBasicPolygon(); + var updater = new PolygonGeometryUpdater(entity, scene); + entity.polygon.extrudedHeight = new ConstantProperty(1000); + entity.polygon.closeBottom = false; + expect(updater.isClosed).toBe(false); + }); + it('A time-varying outlineWidth causes geometry to be dynamic', function() { var entity = createBasicPolygon(); var updater = new PolygonGeometryUpdater(entity, scene); @@ -216,6 +232,8 @@ defineSuite([ polygon.outline = new ConstantProperty(options.outline); polygon.outlineColor = new ConstantProperty(options.outlineColor); polygon.perPositionHeight = new ConstantProperty(options.perPositionHeight); + polygon.closeTop = new ConstantProperty(options.closeTop); + polygon.closeBottom = new ConstantProperty(options.closeBottom); polygon.stRotation = new ConstantProperty(options.stRotation); polygon.height = new ConstantProperty(options.height); @@ -234,6 +252,8 @@ defineSuite([ expect(geometry._height).toEqual(options.height); expect(geometry._granularity).toEqual(options.granularity); expect(geometry._extrudedHeight).toEqual(options.extrudedHeight); + expect(geometry._closeTop).toEqual(options.closeTop); + expect(geometry._closeBottom).toEqual(options.closeBottom); attributes = instance.attributes; if (options.material instanceof ColorMaterialProperty) { @@ -269,7 +289,9 @@ defineSuite([ fill : true, outline : true, outlineColor : Color.BLUE, - perPositionHeight : true + perPositionHeight : true, + closeTop: true, + closeBottom: false }); }); @@ -284,7 +306,9 @@ defineSuite([ fill : true, outline : true, outlineColor : Color.BLUE, - perPositionHeight : false + perPositionHeight : false, + closeTop: false, + closeBottom: true }); }); @@ -392,6 +416,8 @@ defineSuite([ polygon.perPositionHeight = createDynamicProperty(false); polygon.granularity = createDynamicProperty(2); polygon.stRotation = createDynamicProperty(1); + polygon.closeTop = createDynamicProperty(false); + polygon.closeBottom = createDynamicProperty(false); var entity = new Entity(); entity.polygon = polygon; @@ -413,6 +439,8 @@ defineSuite([ expect(options.perPositionHeight).toEqual(polygon.perPositionHeight.getValue()); expect(options.granularity).toEqual(polygon.granularity.getValue()); expect(options.stRotation).toEqual(polygon.stRotation.getValue()); + expect(options.closeTop).toEqual(polygon.closeTop.getValue()); + expect(options.closeBottom).toEqual(polygon.closeBottom.getValue()); entity.show = false; dynamicUpdater.update(JulianDate.now()); diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js index 9e2ef7e1186b..1e6632fe2199 100644 --- a/Specs/DataSources/PolygonGraphicsSpec.js +++ b/Specs/DataSources/PolygonGraphicsSpec.js @@ -30,7 +30,9 @@ defineSuite([ fill : false, outline : false, outlineColor : Color.RED, - outlineWidth : 7 + outlineWidth : 7, + closeTop : true, + closeBottom : true }; var polygon = new PolygonGraphics(options); @@ -46,6 +48,8 @@ defineSuite([ expect(polygon.outline).toBeInstanceOf(ConstantProperty); expect(polygon.outlineColor).toBeInstanceOf(ConstantProperty); expect(polygon.outlineWidth).toBeInstanceOf(ConstantProperty); + expect(polygon.closeTop).toBeInstanceOf(ConstantProperty); + expect(polygon.closeBottom).toBeInstanceOf(ConstantProperty); expect(polygon.material.color.getValue()).toEqual(options.material); expect(polygon.show.getValue()).toEqual(options.show); @@ -59,6 +63,8 @@ defineSuite([ expect(polygon.outline.getValue()).toEqual(options.outline); expect(polygon.outlineColor.getValue()).toEqual(options.outlineColor); expect(polygon.outlineWidth.getValue()).toEqual(options.outlineWidth); + expect(polygon.closeTop.getValue()).toEqual(options.closeTop); + expect(polygon.closeBottom.getValue()).toEqual(options.closeBottom); }); it('merge assigns unassigned properties', function() { @@ -75,6 +81,8 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.perPositionHeight = new ConstantProperty(); + source.closeTop = new ConstantProperty(); + source.closeBottom = new ConstantProperty(); var target = new PolygonGraphics(); target.merge(source); @@ -91,6 +99,8 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.perPositionHeight).toBe(source.perPositionHeight); + expect(target.closeTop).toBe(source.closeTop); + expect(target.closeBottom).toBe(source.closeBottom); }); it('merge does not assign assigned properties', function() { @@ -108,6 +118,8 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var perPositionHeight = new ConstantProperty(); + var closeTop = new ConstantProperty(); + var closeBottom = new ConstantProperty(); var target = new PolygonGraphics(); target.material = material; @@ -122,6 +134,8 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.perPositionHeight = perPositionHeight; + target.closeTop = closeTop; + target.closeBottom = closeBottom; target.merge(source); @@ -137,6 +151,8 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.perPositionHeight).toBe(perPositionHeight); + expect(target.closeTop).toBe(closeTop); + expect(target.closeBottom).toBe(closeBottom); }); it('clone works', function() { @@ -153,6 +169,8 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.perPositionHeight = new ConstantProperty(); + source.closeTop = new ConstantProperty(); + source.closeBottom = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -167,6 +185,8 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.perPositionHeight).toBe(source.perPositionHeight); + expect(result.closeTop).toBe(source.closeTop); + expect(result.closeBottom).toBe(source.closeBottom); }); it('merge throws if source undefined', function() { @@ -190,5 +210,7 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'perPositionHeight', false, true); + testDefinitionChanged(property, 'closeTop', true, false); + testDefinitionChanged(property, 'closeBottom', true, false); }); });