diff --git a/CHANGES.md b/CHANGES.md
index ad81c175673f..69cbe7cbb323 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 `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/Cartesian3.js b/Source/Core/Cartesian3.js
index 6775785c09c0..7b0c9bb239fb 100644
--- a/Source/Core/Cartesian3.js
+++ b/Source/Core/Cartesian3.js
@@ -682,6 +682,24 @@ define([
return result;
};
+ /**
+ * Projects vector a onto vector b
+ * @param {Cartesian3} a The vector that needs projecting
+ * @param {Cartesian3} b The vector to project onto
+ * @param {Cartesian3} result The result cartesian
+ * @returns {Cartesian3} The modified result parameter
+ */
+ Cartesian3.vectorProjection = function(a, b, result) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined('a', a);
+ Check.defined('b', b);
+ Check.defined('result', result);
+ //>>includeEnd('debug');
+
+ var scalar = Cartesian3.dot(a, b) / Cartesian3.dot(b, b);
+ return Cartesian3.multiplyByScalar(b, scalar, result);
+ };
+
/**
* Compares the provided Cartesians componentwise and returns
* true
if they are equal, false
otherwise.
diff --git a/Specs/Core/Cartesian3Spec.js b/Specs/Core/Cartesian3Spec.js
index e66ef04aeda5..833091a53c84 100644
--- a/Specs/Core/Cartesian3Spec.js
+++ b/Specs/Core/Cartesian3Spec.js
@@ -1241,6 +1241,30 @@ defineSuite([
}).toThrowDeveloperError();
});
+ it('projects vector a onto vector b', function() {
+ var a = new Cartesian3(0.0, 1.0, 0.0);
+ var b = new Cartesian3(1.0, 0.0, 0.0);
+ var result = Cartesian3.vectorProjection(a, b, new Cartesian3());
+ expect(result).toEqual(new Cartesian3(0.0, 0.0, 0.0));
+
+ a = new Cartesian3(1.0, 1.0, 0.0);
+ b = new Cartesian3(1.0, 0.0, 0.0);
+ result = Cartesian3.vectorProjection(a, b, new Cartesian3());
+ expect(result).toEqual(new Cartesian3(1.0, 0.0, 0.0));
+ });
+
+ it('vectorProjection throws when missing parameters', function() {
+ expect(function() {
+ return Cartesian3.vectorProjection(undefined, new Cartesian3(), new Cartesian3());
+ }).toThrowDeveloperError();
+ expect(function() {
+ return Cartesian3.vectorProjection(new Cartesian3(), undefined, new Cartesian3());
+ }).toThrowDeveloperError();
+ expect(function() {
+ return Cartesian3.vectorProjection(new Cartesian3(), new Cartesian3(), undefined);
+ }).toThrowDeveloperError();
+ });
+
createPackableSpecs(Cartesian3, new Cartesian3(1, 2, 3), [1, 2, 3]);
createPackableArraySpecs(Cartesian3, [new Cartesian3(1, 2, 3), new Cartesian3(4, 5, 6)], [1, 2, 3, 4, 5, 6]);
});