diff --git a/CHANGES.md b/CHANGES.md index 69cbe7cbb323..b1c51f218504 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Change Log * * Added `ClippingPlaneCollection.isSupported` function for checking if rendering with clipping planes is supported. * Improved CZML Custom Properties sandcastle example [#6086](https://github.com/AnalyticalGraphicsInc/cesium/pull/6086) +* Added `Plane.projectPointOntoPlane` for projecting a `Cartesian3` position onto a `Plane` [#6092](https://github.com/AnalyticalGraphicsInc/cesium/pull/6092) * Added `Cartesian3.vectorProjection` for projecting one vector to another [#6093](https://github.com/AnalyticalGraphicsInc/cesium/pull/6093) ### 1.41 - 2018-01-02 diff --git a/Source/Core/Plane.js b/Source/Core/Plane.js index 421e19512baf..1a688eced55d 100644 --- a/Source/Core/Plane.js +++ b/Source/Core/Plane.js @@ -156,6 +156,30 @@ define([ return Cartesian3.dot(plane.normal, point) + plane.distance; }; + var scratchCartesian = new Cartesian3(); + /** + * Projects a point onto the plane. + * @param {Plane} plane The plane to project the point onto + * @param {Cartesian3} point The point to project onto the plane + * @param {Cartesian3} [result] The result point. If undefined, a new Cartesian3 will be created. + */ + Plane.projectPointOntoPlane = function(plane, point, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.object('plane', plane); + Check.typeOf.object('point', point); + //>>includeEnd('debug'); + + if (!defined(result)) { + result = new Cartesian3(); + } + + // projectedPoint = point - (normal.point + scale) * normal + var pointDistance = Plane.getPointDistance(plane, point); + var scaledNormal = Cartesian3.multiplyByScalar(plane.normal, pointDistance, scratchCartesian); + + return Cartesian3.subtract(point, scaledNormal, result); + }; + var scratchPosition = new Cartesian3(); /** * Transforms the plane by the given transformation matrix. diff --git a/Specs/Core/PlaneSpec.js b/Specs/Core/PlaneSpec.js index 5d258c5c18b3..01f9aed36084 100644 --- a/Specs/Core/PlaneSpec.js +++ b/Specs/Core/PlaneSpec.js @@ -129,6 +129,36 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('projects a point onto the plane', function() { + var plane = new Plane(Cartesian3.UNIT_X, 0.0); + var point = new Cartesian3(1.0, 1.0, 0.0); + var result = Plane.projectPointOntoPlane(plane, point); + expect(result).toEqual(new Cartesian3(0.0, 1.0, 0.0)); + + plane = new Plane(Cartesian3.UNIT_Y, 0.0); + result = Plane.projectPointOntoPlane(plane, point); + expect(result).toEqual(new Cartesian3(1.0, 0.0, 0.0)); + }); + + it('projectPointOntoPlane uses result parameter', function() { + var plane = new Plane(Cartesian3.UNIT_X, 0.0); + var point = new Cartesian3(1.0, 1.0, 0.0); + var result = new Cartesian3(); + var returnedResult = Plane.projectPointOntoPlane(plane, point, result); + expect(result).toBe(returnedResult); + expect(result).toEqual(new Cartesian3(0.0, 1.0, 0.0)); + }); + + it('projectPointOntoPlane requires the plane and point parameters', function() { + expect(function() { + return Plane.projectPointOntoPlane(new Plane(Cartesian3.UNIT_X, 0), undefined); + }).toThrowDeveloperError(); + + expect(function() { + return Plane.projectPointOntoPlane(undefined, new Cartesian3()); + }).toThrowDeveloperError(); + }); + it('clone throws without a plane', function() { expect(function() { Plane.clone(undefined);