From 86e29d5151aeb9bd5bed211c9ebab69a9184265c Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 3 Jul 2018 17:57:13 -0400 Subject: [PATCH 1/3] coplanar polygon --- .../development/Coplanar Polygon Outline.html | 69 ++++ .../development/Coplanar Polygon Outline.jpg | Bin 0 -> 15944 bytes .../gallery/development/Coplanar Polygon.html | 69 ++++ .../gallery/development/Coplanar Polygon.jpg | Bin 0 -> 18682 bytes CHANGES.md | 5 + Source/Core/CoplanarPolygonGeometry.js | 318 ++++++++++++++++++ Source/Core/CoplanarPolygonGeometryLibrary.js | 131 ++++++++ Source/Core/CoplanarPolygonOutlineGeometry.js | 200 +++++++++++ .../Workers/createCoplanarPolygonGeometry.js | 17 + .../createCoplanarPolygonOutlineGeometry.js | 17 + Specs/Core/CoplanarPolygonGeometrySpec.js | 90 +++++ .../CoplanarPolygonOutlineGeometrySpec.js | 64 ++++ Specs/Scene/GeometryRenderingSpec.js | 45 +++ 13 files changed, 1025 insertions(+) create mode 100644 Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html create mode 100644 Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.jpg create mode 100644 Apps/Sandcastle/gallery/development/Coplanar Polygon.html create mode 100644 Apps/Sandcastle/gallery/development/Coplanar Polygon.jpg create mode 100644 Source/Core/CoplanarPolygonGeometry.js create mode 100644 Source/Core/CoplanarPolygonGeometryLibrary.js create mode 100644 Source/Core/CoplanarPolygonOutlineGeometry.js create mode 100644 Source/Workers/createCoplanarPolygonGeometry.js create mode 100644 Source/Workers/createCoplanarPolygonOutlineGeometry.js create mode 100644 Specs/Core/CoplanarPolygonGeometrySpec.js create mode 100644 Specs/Core/CoplanarPolygonOutlineGeometrySpec.js diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html b/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html new file mode 100644 index 000000000000..de4001368246 --- /dev/null +++ b/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html @@ -0,0 +1,69 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.jpg b/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.jpg new file mode 100644 index 0000000000000000000000000000000000000000..af7488de99168a0035244614d503ea5a4df539e9 GIT binary patch literal 15944 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 B(VGAO literal 0 HcmV?d00001 diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon.html b/Apps/Sandcastle/gallery/development/Coplanar Polygon.html new file mode 100644 index 000000000000..2ab41f309fad --- /dev/null +++ b/Apps/Sandcastle/gallery/development/Coplanar Polygon.html @@ -0,0 +1,69 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon.jpg b/Apps/Sandcastle/gallery/development/Coplanar Polygon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2bb5ae4334dd52e7a038cfa4c4969253e9e8470e GIT binary patch literal 18682 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'debug', pragmas.debug); + Check.defined('options.positions', positions); + //>>includeEnd('debug'); + + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + this._vertexFormat = VertexFormat.clone(vertexFormat); + this._positions = positions; + this._workerName = 'createCoplanarPolygonGeometry'; + + /** + * The number of elements used to pack the object into an array. + * @type {Number} + */ + this.packedLength = 1 + positions.length * Cartesian3.packedLength + VertexFormat.packedLength; + } + + /** + * Stores the provided instance into the provided array. + * + * @param {CoplanarPolygonGeometry} value The value to pack. + * @param {Number[]} array The array to pack into. + * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements. + * + * @returns {Number[]} The array that was packed into + */ + CoplanarPolygonGeometry.pack = function(value, array, startingIndex) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object('value', value); + Check.defined('array', array); + //>>includeEnd('debug'); + + startingIndex = defaultValue(startingIndex, 0); + + var positions = value._positions; + var length = positions.length; + array[startingIndex++] = length; + + for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) { + Cartesian3.pack(positions[i], array, startingIndex); + } + + VertexFormat.pack(value._vertexFormat, array, startingIndex); + + return array; + }; + + var scratchVertexFormat = new VertexFormat(); + var scratchOptions = { + positions : undefined, + vertexFormat : scratchVertexFormat + }; + /** + * Retrieves an instance from a packed array. + * + * @param {Number[]} array The packed array. + * @param {Number} [startingIndex=0] The starting index of the element to be unpacked. + * @param {CoplanarPolygonGeometry} [result] The object into which to store the result. + * @returns {CoplanarPolygonGeometry} The modified result parameter or a new CoplanarPolygonGeometry instance if one was not provided. + */ + CoplanarPolygonGeometry.unpack = function(array, startingIndex, result) { + //>>includeStart('debug', pragmas.debug); + Check.defined('array', array); + //>>includeEnd('debug'); + + startingIndex = defaultValue(startingIndex, 0); + + var i; + + var length = array[startingIndex++]; + var positions = new Array(length); + + for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) { + positions[i] = Cartesian3.unpack(array, startingIndex); + } + + var vertexFormat = VertexFormat.unpack(array, startingIndex, scratchVertexFormat); + + if (!defined(result)) { + scratchOptions.positions = positions; + scratchOptions.vertexFormat = vertexFormat; + return new CoplanarPolygonGeometry(scratchOptions); + } + + result._positions = positions; + result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat); + + return result; + }; + + /** + * Computes the geometric representation of an arbitrary coplanar polygon, including its vertices, indices, and a bounding sphere. + * + * @param {CoplanarPolygonGeometry} polygonGeometry A description of the polygon. + * @returns {Geometry|undefined} The computed vertices and indices. + */ + CoplanarPolygonGeometry.createGeometry = function(polygonGeometry) { + var vertexFormat = polygonGeometry._vertexFormat; + var positions = polygonGeometry._positions; + positions = arrayRemoveDuplicates(positions, Cartesian3.equalsEpsilon, true); + if (positions.length < 3) { + return; + } + var bs = BoundingSphere.fromPoints(positions); + + var normal; + var tangent; + var bitangent; + if (vertexFormat.normal) { + normal = scratchNormal; + } + if (vertexFormat.tangent) { + tangent = scratchTangent; + } + if (vertexFormat.bitangent) { + bitangent = scratchBitangent; + } + var positions2D = CoplanarPolygonGeometryLibrary.projectTo2D(positions, scratchPositions2D, normal, tangent, bitangent); + if (!defined(positions2D)) { + return; + } + + if (PolygonPipeline.computeWindingOrder2D(positions2D) === WindingOrder.CLOCKWISE) { + positions2D.reverse(); + positions = positions.slice().reverse(); + } + + var indices = PolygonPipeline.triangulate(positions2D); + if (indices.length < 3) { + return; + } + var newIndices = IndexDatatype.createTypedArray(positions.length, indices.length); + newIndices.set(indices); + + var boundingRectangle; + var stOrigin = textureCoordinatesOrigin; + if (vertexFormat.st) { + boundingRectangle = BoundingRectangle.fromPoints(positions2D, scratchBR); + stOrigin.x = boundingRectangle.x; + stOrigin.y = boundingRectangle.y; + } + + var length = positions.length; + var size = length * 3; + var flatPositions = new Float64Array(size); + var normals = vertexFormat.normal ? new Float32Array(size) : undefined; + var tangents = vertexFormat.tangent ? new Float32Array(size) : undefined; + var bitangents = vertexFormat.bitangent ? new Float32Array(size) : undefined; + var textureCoordinates = vertexFormat.st ? new Float32Array(length * 2) : undefined; + + var positionIndex = 0; + var normalIndex = 0; + var bitangentIndex = 0; + var tangentIndex = 0; + var stIndex = 0; + + for (var i = 0; i < length; i++) { + var position = positions[i]; + flatPositions[positionIndex++] = position.x; + flatPositions[positionIndex++] = position.y; + flatPositions[positionIndex++] = position.z; + + if (vertexFormat.st) { + var st = positions2D[i]; + st = Cartesian2.subtract(st, stOrigin, st); + + var stx = CesiumMath.clamp(st.x / boundingRectangle.width, 0, 1); + var sty = CesiumMath.clamp(st.y / boundingRectangle.height, 0, 1); + textureCoordinates[stIndex++] = stx; + textureCoordinates[stIndex++] = sty; + } + + if (vertexFormat.normal) { + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + } + + if (vertexFormat.tangent) { + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + } + + if (vertexFormat.bitangent) { + bitangents[bitangentIndex++] = bitangent.x; + bitangents[bitangentIndex++] = bitangent.y; + bitangents[bitangentIndex++] = bitangent.z; + } + } + + var attributes = new GeometryAttributes(); + + if (vertexFormat.position) { + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : flatPositions + }); + } + + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.bitangent) { + attributes.bitangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : bitangents + }); + } + + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + } + + return new Geometry({ + attributes : attributes, + indices : newIndices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : bs + }); + }; + + return CoplanarPolygonGeometry; +}); diff --git a/Source/Core/CoplanarPolygonGeometryLibrary.js b/Source/Core/CoplanarPolygonGeometryLibrary.js new file mode 100644 index 000000000000..b893fcfe30bd --- /dev/null +++ b/Source/Core/CoplanarPolygonGeometryLibrary.js @@ -0,0 +1,131 @@ +define([ + './defined', + './Cartesian2', + './Cartesian3', + './Check', + './IntersectionTests', + './Math', + './Matrix3', + './OrientedBoundingBox', + './Plane', + './Ray' + ], function( + defined, + Cartesian2, + Cartesian3, + Check, + IntersectionTests, + CesiumMath, + Matrix3, + OrientedBoundingBox, + Plane, + Ray + ) { + 'use strict'; + + /** + * @private + */ + var PolygonGeometryLibrary = {}; + + var scratchIntersectionPoint = new Cartesian3(); + var scratchXAxis = new Cartesian3(); + var scratchYAxis = new Cartesian3(); + var scratchZAxis = new Cartesian3(); + var scratchOrigin = new Cartesian3(); + var scratchNormal = new Cartesian3(); + var scratchRay = new Ray(); + var scratchPlane = new Plane(Cartesian3.UNIT_X, 0); + var obbScratch = new OrientedBoundingBox(); + + // call after removeDuplicates + PolygonGeometryLibrary.projectTo2D = function(positions, positionsResult, normalResult, tangentResult, bitangentResult) { + //>>includeStart('debug', pragmas.debug); + Check.defined('positions', positions); + Check.defined('positionsResult', positionsResult); + //>>includeEnd('debug'); + + var obb = OrientedBoundingBox.fromPoints(positions, obbScratch); + var halfAxes = obb.halfAxes; + var xAxis = Matrix3.getColumn(halfAxes, 0, scratchXAxis); + var yAxis = Matrix3.getColumn(halfAxes, 1, scratchYAxis); + var zAxis = Matrix3.getColumn(halfAxes, 2, scratchZAxis); + + var xMag = Cartesian3.magnitude(xAxis); + var yMag = Cartesian3.magnitude(yAxis); + var zMag = Cartesian3.magnitude(zAxis); + var min = Math.min(xMag, yMag, zMag); + + var i; + // If all the points are on a line, just remove one of the zero dimensions + if ((xMag === 0 && (yMag === 0 || zMag === 0)) || (yMag === 0 && zMag === 0)) { + return; + } + var center = obb.center; + var planeXAxis; + var planeYAxis; + var origin = Cartesian3.clone(center, scratchOrigin); + var normal; + if (min === xMag) { + if (min !== 0) { + origin = Cartesian3.add(origin, xAxis, origin); + normal = Cartesian3.normalize(xAxis, scratchNormal); + } + planeXAxis = Cartesian3.normalize(yAxis, yAxis); + planeYAxis = Cartesian3.normalize(zAxis, zAxis); + } else if (min === yMag) { + if (min !== 0) { + origin = Cartesian3.add(origin, yAxis, origin); + normal = Cartesian3.normalize(yAxis, scratchNormal); + } + planeXAxis = Cartesian3.normalize(xAxis, xAxis); + planeYAxis = Cartesian3.normalize(zAxis, zAxis); + } else { + if (min !== 0) { + origin = Cartesian3.add(origin, zAxis, origin); + normal = Cartesian3.normalize(zAxis, scratchNormal); + } + planeXAxis = Cartesian3.normalize(xAxis, xAxis); + planeYAxis = Cartesian3.normalize(yAxis, yAxis); + } + + if (min === 0) { + normal = Cartesian3.cross(planeXAxis, planeYAxis, scratchNormal); + normal = Cartesian3.normalize(normal, normal); + } + + if (defined(normalResult)) { + Cartesian3.clone(normal, normalResult); + } + if (defined(tangentResult)) { + Cartesian3.clone(planeXAxis, tangentResult); + } + if (defined(bitangentResult)) { + Cartesian3.clone(planeYAxis, bitangentResult); + } + + var plane = Plane.fromPointNormal(origin, normal, scratchPlane); + var ray = scratchRay; + ray.direction = Cartesian3.clone(normal, ray.direction); + + for (i = 0; i < positions.length; i++) { + ray.origin = Cartesian3.clone(positions[i], ray.origin); + + var intersectionPoint = IntersectionTests.rayPlane(ray, plane, scratchIntersectionPoint); + + if (!defined(intersectionPoint)) { + ray.direction = Cartesian3.negate(ray.direction, ray.direction); + intersectionPoint = IntersectionTests.rayPlane(ray, plane, scratchIntersectionPoint); + } + var v = Cartesian3.subtract(intersectionPoint, origin, intersectionPoint); + var x = Cartesian3.dot(planeXAxis, v); + var y = Cartesian3.dot(planeYAxis, v); + + positionsResult[i] = Cartesian2.fromElements(x, y, positionsResult[i]); + } + + return positionsResult; + }; + + return PolygonGeometryLibrary; +}); diff --git a/Source/Core/CoplanarPolygonOutlineGeometry.js b/Source/Core/CoplanarPolygonOutlineGeometry.js new file mode 100644 index 000000000000..b635dc400c97 --- /dev/null +++ b/Source/Core/CoplanarPolygonOutlineGeometry.js @@ -0,0 +1,200 @@ +/*global define*/ +define([ + './arrayRemoveDuplicates', + './BoundingSphere', + './Cartesian3', + './Check', + './ComponentDatatype', + './CoplanarPolygonGeometryLibrary', + './defaultValue', + './defined', + './Geometry', + './GeometryAttribute', + './GeometryAttributes', + './IndexDatatype', + './PolygonPipeline', + './PrimitiveType', + './WindingOrder' +], function( + arrayRemoveDuplicates, + BoundingSphere, + Cartesian3, + Check, + ComponentDatatype, + CoplanarPolygonGeometryLibrary, + defaultValue, + defined, + Geometry, + GeometryAttribute, + GeometryAttributes, + IndexDatatype, + PolygonPipeline, + PrimitiveType, + WindingOrder) { + 'use strict'; + + var scratchPositions2D = []; + + /** + * A description of the outline of a polygon composed of arbitrary coplanar positions. + * + * @alias CoplanarPolygonOutlineGeometry + * @constructor + * + * @param {Object} options Object with the following properties: + * @param {Cartesian3[]} options.positions The positions of the polygon + * + * @see CoplanarPolygonOutlineGeometry.createGeometry + * + * @example + * var polygonOutline = new Cesium.CoplanarPolygonOutlineGeometry({ + * positions : Cesium.Cartesian3.fromDegreesArrayHeights([ + * -90.0, 30.0, 0.0, + * -90.0, 30.0, 1000.0, + * -80.0, 30.0, 1000.0, + * -80.0, 30.0, 0.0 + * ]) + * }); + * var geometry = Cesium.CoplanarPolygonOutlineGeometry.createGeometry(polygonOutline); + */ + function CoplanarPolygonOutlineGeometry(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var positions = options.positions; + //>>includeStart('debug', pragmas.debug); + Check.defined('options.positions', positions); + //>>includeEnd('debug'); + + this._positions = positions; + this._workerName = 'createCoplanarPolygonOutlineGeometry'; + + /** + * The number of elements used to pack the object into an array. + * @type {Number} + */ + this.packedLength = 1 + positions.length * Cartesian3.packedLength; + } + + /** + * Stores the provided instance into the provided array. + * + * @param {CoplanarPolygonOutlineGeometry} value The value to pack. + * @param {Number[]} array The array to pack into. + * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements. + * + * @returns {Number[]} The array that was packed into + */ + CoplanarPolygonOutlineGeometry.pack = function(value, array, startingIndex) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object('value', value); + Check.defined('array', array); + //>>includeEnd('debug'); + + startingIndex = defaultValue(startingIndex, 0); + + var positions = value._positions; + var length = positions.length; + array[startingIndex++] = length; + + for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) { + Cartesian3.pack(positions[i], array, startingIndex); + } + + return array; + }; + + var scratchOptions = { + positions : undefined + }; + /** + * Retrieves an instance from a packed array. + * + * @param {Number[]} array The packed array. + * @param {Number} [startingIndex=0] The starting index of the element to be unpacked. + * @param {CoplanarPolygonOutlineGeometry} [result] The object into which to store the result. + * @returns {CoplanarPolygonOutlineGeometry} The modified result parameter or a new CoplanarPolygonOutlineGeometry instance if one was not provided. + */ + CoplanarPolygonOutlineGeometry.unpack = function(array, startingIndex, result) { + //>>includeStart('debug', pragmas.debug); + Check.defined('array', array); + //>>includeEnd('debug'); + + startingIndex = defaultValue(startingIndex, 0); + + var i; + + var length = array[startingIndex++]; + var positions = new Array(length); + + for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) { + positions[i] = Cartesian3.unpack(array, startingIndex); + } + + if (!defined(result)) { + scratchOptions.positions = positions; + return new CoplanarPolygonOutlineGeometry(scratchOptions); + } + + result._positions = positions; + + return result; + }; + + /** + * Computes the geometric representation of an arbitrary coplanar polygon, including its vertices, indices, and a bounding sphere. + * + * @param {CoplanarPolygonOutlineGeometry} polygonGeometry A description of the polygon. + * @returns {Geometry|undefined} The computed vertices and indices. + */ + CoplanarPolygonOutlineGeometry.createGeometry = function(polygonGeometry) { + var positions = polygonGeometry._positions; + positions = arrayRemoveDuplicates(positions, Cartesian3.equalsEpsilon, true); + if (positions.length < 3) { + return; + } + var bs = BoundingSphere.fromPoints(positions); + + var positions2D = CoplanarPolygonGeometryLibrary.projectTo2D(positions, scratchPositions2D); + if (!defined(positions2D)) { + return; + } + + if (PolygonPipeline.computeWindingOrder2D(positions2D) === WindingOrder.CLOCKWISE) { + positions2D.reverse(); + positions = positions.slice().reverse(); + } + + var length = positions.length; + var flatPositions = new Float64Array(length * 3); + var indices = IndexDatatype.createTypedArray(length, length * 2); + + var positionIndex = 0; + var index = 0; + + for (var i = 0; i < length; i++) { + var position = positions[i]; + flatPositions[positionIndex++] = position.x; + flatPositions[positionIndex++] = position.y; + flatPositions[positionIndex++] = position.z; + + indices[index++] = i; + indices[index++] = (i + 1) % length; + } + + var attributes = new GeometryAttributes({ + position: new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : flatPositions + }) + }); + + return new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.LINES, + boundingSphere : bs + }); + }; + + return CoplanarPolygonOutlineGeometry; +}); diff --git a/Source/Workers/createCoplanarPolygonGeometry.js b/Source/Workers/createCoplanarPolygonGeometry.js new file mode 100644 index 000000000000..1e76b76c23c8 --- /dev/null +++ b/Source/Workers/createCoplanarPolygonGeometry.js @@ -0,0 +1,17 @@ +define([ + '../Core/defined', + '../Core/CoplanarPolygonGeometry' +], function( + defined, + CoplanarPolygonGeometry) { + 'use strict'; + + function createCoplanarPolygonGeometry(polygonGeometry, offset) { + if (defined(offset)) { + polygonGeometry = CoplanarPolygonGeometry.unpack(polygonGeometry, offset); + } + return CoplanarPolygonGeometry.createGeometry(polygonGeometry); + } + + return createCoplanarPolygonGeometry; +}); diff --git a/Source/Workers/createCoplanarPolygonOutlineGeometry.js b/Source/Workers/createCoplanarPolygonOutlineGeometry.js new file mode 100644 index 000000000000..d989368e9e87 --- /dev/null +++ b/Source/Workers/createCoplanarPolygonOutlineGeometry.js @@ -0,0 +1,17 @@ +define([ + '../Core/defined', + '../Core/CoplanarPolygonOutlineGeometry' +], function( + defined, + CoplanarPolygonOutlineGeometry) { + 'use strict'; + + function createCoplanarPolygonOutlineGeometry(polygonGeometry, offset) { + if (defined(offset)) { + polygonGeometry = CoplanarPolygonOutlineGeometry.unpack(polygonGeometry, offset); + } + return CoplanarPolygonOutlineGeometry.createGeometry(polygonGeometry); + } + + return createCoplanarPolygonOutlineGeometry; +}); diff --git a/Specs/Core/CoplanarPolygonGeometrySpec.js b/Specs/Core/CoplanarPolygonGeometrySpec.js new file mode 100644 index 000000000000..6e69043fa18e --- /dev/null +++ b/Specs/Core/CoplanarPolygonGeometrySpec.js @@ -0,0 +1,90 @@ +defineSuite([ + 'Core/CoplanarPolygonGeometry', + 'Core/Cartesian3', + 'Core/Ellipsoid', + 'Core/Math', + 'Core/VertexFormat', + 'Specs/createPackableSpecs' +], function( + CoplanarPolygonGeometry, + Cartesian3, + Ellipsoid, + CesiumMath, + VertexFormat, + createPackableSpecs) { + 'use strict'; + + it('throws with no positions', function() { + expect(function() { + return new CoplanarPolygonGeometry(); + }).toThrowDeveloperError(); + }); + + it('returns undefined with less than 3 unique positions', function() { + var geometry = CoplanarPolygonGeometry.createGeometry(new CoplanarPolygonGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + 49.0, 18.0, 1000.0, + 49.0, 18.0, 5000.0, + 49.0, 18.0, 5000.0, + 49.0, 18.0, 1000.0 + ]) + })); + expect(geometry).toBeUndefined(); + }); + + it('returns undefined when positions are linear', function() { + var geometry = CoplanarPolygonGeometry.createGeometry(new CoplanarPolygonGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + 0.0, 0.0, 1.0, + 0.0, 0.0, 2.0, + 0.0, 0.0, 3.0 + ]) + })); + expect(geometry).toBeUndefined(); + }); + + it('computes positions', function() { + var p = CoplanarPolygonGeometry.createGeometry(new CoplanarPolygonGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + positions : Cartesian3.fromDegreesArrayHeights([ + -1.0, -1.0, 0.0, + -1.0, 0.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 2.0, 0.0 + ]) + })); + + expect(p.attributes.position.values.length).toEqual(4 * 3); + expect(p.indices.length).toEqual(2 * 3); + }); + + it('computes all attributes', function() { + var p = CoplanarPolygonGeometry.createGeometry(new CoplanarPolygonGeometry({ + vertexFormat : VertexFormat.ALL, + positions : Cartesian3.fromDegreesArrayHeights([ + -1.0, -1.0, 0.0, + -1.0, 0.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 2.0, 0.0 + ]) + })); + + var numVertices = 4; + var numTriangles = 2; + expect(p.attributes.position.values.length).toEqual(numVertices * 3); + expect(p.attributes.st.values.length).toEqual(numVertices * 2); + expect(p.attributes.normal.values.length).toEqual(numVertices * 3); + expect(p.attributes.tangent.values.length).toEqual(numVertices * 3); + expect(p.attributes.bitangent.values.length).toEqual(numVertices * 3); + expect(p.indices.length).toEqual(numTriangles * 3); + }); + + var positions = [new Cartesian3(-1.0, 0.0, 0.0), new Cartesian3(0.0, 0.0, 1.0), new Cartesian3(-1.0, 0.0, 0.0)]; + var polygon = new CoplanarPolygonGeometry({ + positions : positions, + vertexFormat : VertexFormat.POSITION_ONLY + }); + var packedInstance = [3.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]; + createPackableSpecs(CoplanarPolygonGeometry, polygon, packedInstance); +}); + diff --git a/Specs/Core/CoplanarPolygonOutlineGeometrySpec.js b/Specs/Core/CoplanarPolygonOutlineGeometrySpec.js new file mode 100644 index 000000000000..576be81b9fd0 --- /dev/null +++ b/Specs/Core/CoplanarPolygonOutlineGeometrySpec.js @@ -0,0 +1,64 @@ +defineSuite([ + 'Core/CoplanarPolygonOutlineGeometry', + 'Core/Cartesian3', + 'Core/Ellipsoid', + 'Core/Math', + 'Specs/createPackableSpecs' +], function( + CoplanarPolygonOutlineGeometry, + Cartesian3, + Ellipsoid, + CesiumMath, + createPackableSpecs) { + 'use strict'; + + it('throws with no positions', function() { + expect(function() { + return new CoplanarPolygonOutlineGeometry(); + }).toThrowDeveloperError(); + }); + + it('returns undefined with less than 3 unique positions', function() { + var geometry = CoplanarPolygonOutlineGeometry.createGeometry(new CoplanarPolygonOutlineGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + 49.0, 18.0, 1000.0, + 49.0, 18.0, 5000.0, + 49.0, 18.0, 5000.0, + 49.0, 18.0, 1000.0 + ]) + })); + expect(geometry).toBeUndefined(); + }); + + it('returns undefined when positions are linear', function() { + var geometry = CoplanarPolygonOutlineGeometry.createGeometry(new CoplanarPolygonOutlineGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + 0.0, 0.0, 1.0, + 0.0, 0.0, 2.0, + 0.0, 0.0, 3.0 + ]) + })); + expect(geometry).toBeUndefined(); + }); + + it('creates positions', function() { + var geometry = CoplanarPolygonOutlineGeometry.createGeometry(new CoplanarPolygonOutlineGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + -1.0, -1.0, 0.0, + -1.0, 0.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 2.0, 0.0 + ]) + })); + + expect(geometry.attributes.position.values.length).toEqual(4 * 3); + expect(geometry.indices.length).toEqual(4 * 2); + }); + + var positions = [new Cartesian3(-1.0, 0.0, 0.0), new Cartesian3(0.0, 0.0, 1.0), new Cartesian3(-1.0, 0.0, 0.0)]; + var polygon = new CoplanarPolygonOutlineGeometry({ + positions : positions + }); + var packedInstance = [3.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0]; + createPackableSpecs(CoplanarPolygonOutlineGeometry, polygon, packedInstance); +}); diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index a066fdc64b1f..20dfedb08ea5 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/CircleGeometry', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/CoplanarPolygonGeometry', 'Core/ComponentDatatype', 'Core/CornerType', 'Core/CorridorGeometry', @@ -46,6 +47,7 @@ defineSuite([ CircleGeometry, Color, ColorGeometryInstanceAttribute, + CoplanarPolygonGeometry, ComponentDatatype, CornerType, CorridorGeometry, @@ -332,6 +334,49 @@ defineSuite([ }); }, 'WebGL'); + describe('CoplanarPolygonGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new CoplanarPolygonGeometry({ + positions : Cartesian3.fromDegreesArrayHeights([ + 71.0, -10.0, 0.0, + 70.0, 0.0, 20000.0, + 69.0, 0.0, 20000.0, + 68.0, -10.0, 0.0 + ]), + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT + }), + id: 'coplanar polygon', + attributes : { + color : new ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 0.5) + } + }); + geometry = CoplanarPolygonGeometry.createGeometry(instance.geometry); + geometry.boundingSphereWC = BoundingSphere.transform(geometry.boundingSphere, instance.modelMatrix); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + + it('async', function() { + return renderAsync(instance); + }); + }); + describe('CylinderGeometry', function() { var instance; beforeAll(function() { From 992c25060f9f632dc3be33ac6a5130dda24ac992 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 6 Jul 2018 17:59:12 -0400 Subject: [PATCH 2/3] cleanup --- .../development/Coplanar Polygon Outline.html | 2 +- .../gallery/development/Coplanar Polygon.html | 2 +- Source/Core/CoplanarPolygonGeometry.js | 4 +- Source/Core/CoplanarPolygonGeometryLibrary.js | 88 +++++++------------ Source/Core/CoplanarPolygonOutlineGeometry.js | 4 +- 5 files changed, 37 insertions(+), 63 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html b/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html index de4001368246..cd2422717461 100644 --- a/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html +++ b/Apps/Sandcastle/gallery/development/Coplanar Polygon Outline.html @@ -4,7 +4,7 @@ - + Cesium Demo diff --git a/Apps/Sandcastle/gallery/development/Coplanar Polygon.html b/Apps/Sandcastle/gallery/development/Coplanar Polygon.html index 2ab41f309fad..8cfce4882ae8 100644 --- a/Apps/Sandcastle/gallery/development/Coplanar Polygon.html +++ b/Apps/Sandcastle/gallery/development/Coplanar Polygon.html @@ -4,7 +4,7 @@ - + Cesium Demo diff --git a/Source/Core/CoplanarPolygonGeometry.js b/Source/Core/CoplanarPolygonGeometry.js index d68b7d71e310..3957cb66e3c9 100644 --- a/Source/Core/CoplanarPolygonGeometry.js +++ b/Source/Core/CoplanarPolygonGeometry.js @@ -176,7 +176,7 @@ define([ if (positions.length < 3) { return; } - var bs = BoundingSphere.fromPoints(positions); + var boundingSphere = BoundingSphere.fromPoints(positions); var normal; var tangent; @@ -310,7 +310,7 @@ define([ attributes : attributes, indices : newIndices, primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : bs + boundingSphere : boundingSphere }); }; diff --git a/Source/Core/CoplanarPolygonGeometryLibrary.js b/Source/Core/CoplanarPolygonGeometryLibrary.js index b893fcfe30bd..bfa1e01d7b36 100644 --- a/Source/Core/CoplanarPolygonGeometryLibrary.js +++ b/Source/Core/CoplanarPolygonGeometryLibrary.js @@ -6,9 +6,7 @@ define([ './IntersectionTests', './Math', './Matrix3', - './OrientedBoundingBox', - './Plane', - './Ray' + './OrientedBoundingBox' ], function( defined, Cartesian2, @@ -17,9 +15,7 @@ define([ IntersectionTests, CesiumMath, Matrix3, - OrientedBoundingBox, - Plane, - Ray + OrientedBoundingBox ) { 'use strict'; @@ -34,8 +30,6 @@ define([ var scratchZAxis = new Cartesian3(); var scratchOrigin = new Cartesian3(); var scratchNormal = new Cartesian3(); - var scratchRay = new Ray(); - var scratchPlane = new Plane(Cartesian3.UNIT_X, 0); var obbScratch = new OrientedBoundingBox(); // call after removeDuplicates @@ -45,8 +39,8 @@ define([ Check.defined('positionsResult', positionsResult); //>>includeEnd('debug'); - var obb = OrientedBoundingBox.fromPoints(positions, obbScratch); - var halfAxes = obb.halfAxes; + var orientedBoundingBox = OrientedBoundingBox.fromPoints(positions, obbScratch); + var halfAxes = orientedBoundingBox.halfAxes; var xAxis = Matrix3.getColumn(halfAxes, 0, scratchXAxis); var yAxis = Matrix3.getColumn(halfAxes, 1, scratchYAxis); var zAxis = Matrix3.getColumn(halfAxes, 2, scratchZAxis); @@ -56,74 +50,54 @@ define([ var zMag = Cartesian3.magnitude(zAxis); var min = Math.min(xMag, yMag, zMag); - var i; - // If all the points are on a line, just remove one of the zero dimensions + // If all the points are on a line return undefined because we can't draw a polygon if ((xMag === 0 && (yMag === 0 || zMag === 0)) || (yMag === 0 && zMag === 0)) { return; } - var center = obb.center; - var planeXAxis; - var planeYAxis; + var center = orientedBoundingBox.center; var origin = Cartesian3.clone(center, scratchOrigin); var normal; + var planeAxis1; + var planeAxis2; + + if (min === yMag || min === zMag) { + planeAxis1 = xAxis; + } if (min === xMag) { - if (min !== 0) { - origin = Cartesian3.add(origin, xAxis, origin); - normal = Cartesian3.normalize(xAxis, scratchNormal); - } - planeXAxis = Cartesian3.normalize(yAxis, yAxis); - planeYAxis = Cartesian3.normalize(zAxis, zAxis); - } else if (min === yMag) { - if (min !== 0) { - origin = Cartesian3.add(origin, yAxis, origin); - normal = Cartesian3.normalize(yAxis, scratchNormal); - } - planeXAxis = Cartesian3.normalize(xAxis, xAxis); - planeYAxis = Cartesian3.normalize(zAxis, zAxis); - } else { - if (min !== 0) { - origin = Cartesian3.add(origin, zAxis, origin); - normal = Cartesian3.normalize(zAxis, scratchNormal); - } - planeXAxis = Cartesian3.normalize(xAxis, xAxis); - planeYAxis = Cartesian3.normalize(yAxis, yAxis); + planeAxis1 = yAxis; + } else if (min === zMag) { + planeAxis2 = yAxis; } - - if (min === 0) { - normal = Cartesian3.cross(planeXAxis, planeYAxis, scratchNormal); - normal = Cartesian3.normalize(normal, normal); + if (min === xMag || min === yMag) { + planeAxis2 = zAxis; } + planeAxis1 = Cartesian3.normalize(planeAxis1, planeAxis1); + planeAxis2 = Cartesian3.normalize(planeAxis2, planeAxis2); + normal = Cartesian3.cross(planeAxis1, planeAxis2, scratchNormal); + normal = Cartesian3.normalize(normal, normal); + if (defined(normalResult)) { Cartesian3.clone(normal, normalResult); } if (defined(tangentResult)) { - Cartesian3.clone(planeXAxis, tangentResult); + Cartesian3.clone(planeAxis1, tangentResult); } if (defined(bitangentResult)) { - Cartesian3.clone(planeYAxis, bitangentResult); + Cartesian3.clone(planeAxis2, bitangentResult); } - var plane = Plane.fromPointNormal(origin, normal, scratchPlane); - var ray = scratchRay; - ray.direction = Cartesian3.clone(normal, ray.direction); - - for (i = 0; i < positions.length; i++) { - ray.origin = Cartesian3.clone(positions[i], ray.origin); - - var intersectionPoint = IntersectionTests.rayPlane(ray, plane, scratchIntersectionPoint); - - if (!defined(intersectionPoint)) { - ray.direction = Cartesian3.negate(ray.direction, ray.direction); - intersectionPoint = IntersectionTests.rayPlane(ray, plane, scratchIntersectionPoint); - } - var v = Cartesian3.subtract(intersectionPoint, origin, intersectionPoint); - var x = Cartesian3.dot(planeXAxis, v); - var y = Cartesian3.dot(planeYAxis, v); + for (var i = 0; i < positions.length; i++) { + var position = positions[i]; + var v = Cartesian3.subtract(position, origin, scratchIntersectionPoint); + var x = Cartesian3.dot(planeAxis1, v); + var y = Cartesian3.dot(planeAxis2, v); positionsResult[i] = Cartesian2.fromElements(x, y, positionsResult[i]); } + positionsResult.length = positions.length; + return positionsResult; }; diff --git a/Source/Core/CoplanarPolygonOutlineGeometry.js b/Source/Core/CoplanarPolygonOutlineGeometry.js index b635dc400c97..1ea4495b59aa 100644 --- a/Source/Core/CoplanarPolygonOutlineGeometry.js +++ b/Source/Core/CoplanarPolygonOutlineGeometry.js @@ -151,7 +151,7 @@ define([ if (positions.length < 3) { return; } - var bs = BoundingSphere.fromPoints(positions); + var boundingSphere = BoundingSphere.fromPoints(positions); var positions2D = CoplanarPolygonGeometryLibrary.projectTo2D(positions, scratchPositions2D); if (!defined(positions2D)) { @@ -192,7 +192,7 @@ define([ attributes : attributes, indices : indices, primitiveType : PrimitiveType.LINES, - boundingSphere : bs + boundingSphere : boundingSphere }); }; From 6c2f9be90751f6e0df96a04ac3b2ab6c533f560e Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 10 Jul 2018 10:49:39 -0400 Subject: [PATCH 3/3] cleanup --- Source/Core/CoplanarPolygonGeometryLibrary.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Source/Core/CoplanarPolygonGeometryLibrary.js b/Source/Core/CoplanarPolygonGeometryLibrary.js index bfa1e01d7b36..8942e138e4af 100644 --- a/Source/Core/CoplanarPolygonGeometryLibrary.js +++ b/Source/Core/CoplanarPolygonGeometryLibrary.js @@ -28,8 +28,6 @@ define([ var scratchXAxis = new Cartesian3(); var scratchYAxis = new Cartesian3(); var scratchZAxis = new Cartesian3(); - var scratchOrigin = new Cartesian3(); - var scratchNormal = new Cartesian3(); var obbScratch = new OrientedBoundingBox(); // call after removeDuplicates @@ -54,9 +52,7 @@ define([ if ((xMag === 0 && (yMag === 0 || zMag === 0)) || (yMag === 0 && zMag === 0)) { return; } - var center = orientedBoundingBox.center; - var origin = Cartesian3.clone(center, scratchOrigin); - var normal; + var planeAxis1; var planeAxis2; @@ -74,11 +70,10 @@ define([ planeAxis1 = Cartesian3.normalize(planeAxis1, planeAxis1); planeAxis2 = Cartesian3.normalize(planeAxis2, planeAxis2); - normal = Cartesian3.cross(planeAxis1, planeAxis2, scratchNormal); - normal = Cartesian3.normalize(normal, normal); if (defined(normalResult)) { - Cartesian3.clone(normal, normalResult); + normalResult = Cartesian3.cross(planeAxis1, planeAxis2, normalResult); + normalResult = Cartesian3.normalize(normalResult, normalResult); } if (defined(tangentResult)) { Cartesian3.clone(planeAxis1, tangentResult); @@ -89,7 +84,7 @@ define([ for (var i = 0; i < positions.length; i++) { var position = positions[i]; - var v = Cartesian3.subtract(position, origin, scratchIntersectionPoint); + var v = Cartesian3.subtract(position, orientedBoundingBox.center, scratchIntersectionPoint); var x = Cartesian3.dot(planeAxis1, v); var y = Cartesian3.dot(planeAxis2, v);