diff --git a/CHANGES.md b/CHANGES.md index 8a0a833427dd..77259ebefb55 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Change Log ##### Additions :tada: * Added `Scene.invertClassificationSupported` for checking if invert classification is supported. +* Added `computeLineSegmentLineSegmentIntersection` to `Intersections2D`. [#7228](https://github.com/AnalyticalGraphicsInc/Cesium/pull/7228) ##### Fixes :wrench: * Fixed issue causing polyline to look wavy depending on the position of the camera [#7209](https://github.com/AnalyticalGraphicsInc/cesium/pull/7209) diff --git a/Source/Core/Intersections2D.js b/Source/Core/Intersections2D.js index 36f88b1eb673..5c7ddbc7ccdb 100644 --- a/Source/Core/Intersections2D.js +++ b/Source/Core/Intersections2D.js @@ -1,9 +1,13 @@ define([ + './Cartesian2', './Cartesian3', + './Check', './defined', './DeveloperError' ], function( + Cartesian2, Cartesian3, + Check, defined, DeveloperError) { 'use strict'; @@ -278,5 +282,60 @@ define([ return new Cartesian3(l1, l2, l3); }; + /** + * Compute the intersection between 2 line segments + * + * @param {Number} x00 The x coordinate of the first line's first vertex. + * @param {Number} y00 The y coordinate of the first line's first vertex. + * @param {Number} x01 The x coordinate of the first line's second vertex. + * @param {Number} y01 The y coordinate of the first line's second vertex. + * @param {Number} x10 The x coordinate of the second line's first vertex. + * @param {Number} y10 The y coordinate of the second line's first vertex. + * @param {Number} x11 The x coordinate of the second line's second vertex. + * @param {Number} y11 The y coordinate of the second line's second vertex. + * @param {Cartesian2} [result] The instance into to which to copy the result. If this parameter + * is undefined, a new instance is created and returned. + * @returns {Cartesian2} The intersection point, undefined if there is no intersection point or lines are coincident. + * + * @example + * var result = Cesium.Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, -1, 1, 1, 1); + * // result === new Cesium.Cartesian2(0.0, 1.0); + */ + Intersections2D.computeLineSegmentLineSegmentIntersection = function(x00, y00, x01, y01, x10, y10, x11, y11, result) { + //>>includeStart('debug', pragmas.debug); + Check.typeOf.number('x00', x00); + Check.typeOf.number('y00', y00); + Check.typeOf.number('x01', x01); + Check.typeOf.number('y01', y01); + Check.typeOf.number('x10', x10); + Check.typeOf.number('y10', y10); + Check.typeOf.number('x11', x11); + Check.typeOf.number('y11', y11); + //>>includeEnd('debug'); + + var numerator1A = (x11 - x10) * (y00 - y10) - (y11 - y10) * (x00 - x10); + var numerator1B = (x01 - x00) * (y00 - y10) - (y01 - y00) * (x00 - x10); + var denominator1 = (y11 - y10) * (x01 - x00) - (x11 - x10) * (y01 - y00); + + // If denominator = 0, then lines are parallel. If denominator = 0 and both numerators are 0, then coincident + if (denominator1 === 0) { + return; + } + + var ua1 = numerator1A / denominator1; + var ub1 = numerator1B / denominator1; + + if (ua1 >= 0 && ua1 <= 1 && ub1 >= 0 && ub1 <= 1) { + if (!defined(result)) { + result = new Cartesian2(); + } + + result.x = x00 + ua1 * (x01 - x00); + result.y = y00 + ua1 * (y01 - y00); + + return result; + } + }; + return Intersections2D; }); diff --git a/Specs/Core/Intersections2DSpec.js b/Specs/Core/Intersections2DSpec.js index 5b4b34dc452c..0dd49009d51d 100644 --- a/Specs/Core/Intersections2DSpec.js +++ b/Specs/Core/Intersections2DSpec.js @@ -288,4 +288,58 @@ defineSuite([ expect(result3.z).toBeGreaterThan(0.0); }); }); + + describe('computeLineSegmentLineSegmentIntersection', function() { + it('returns the correct result for intersection point', function() { + var intersection0 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, -1.0, 1.0, 1.0, 1.0); + expect(intersection0.x).toEqualEpsilon(0.0, 1e-15); + expect(intersection0.y).toEqualEpsilon(1.0, 1e-15); + + var intersection1 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 10.0, 5.0, 0.0, 5.0, 10.0, 0.0); + expect(intersection1.x).toEqualEpsilon(5.0, 1e-15); + expect(intersection1.y).toEqualEpsilon(2.5, 1e-15); + + var intersection2 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, -5.0, 4.0, 3.0, -2.0, 1.0, 4.0, -2.0); + expect(intersection2.x).toEqualEpsilon(2.0, 1e-15); + expect(intersection2.y).toEqualEpsilon(-1.0, 1e-15); + }); + + it('returns the correct result for intersection point on a vertex', function() { + var intersection0 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, -1.0, 0.0, 1.0, 0.0); + expect(intersection0.x).toEqualEpsilon(0.0, 1e-15); + expect(intersection0.y).toEqualEpsilon(0.0, 1e-15); + + var intersection1 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 0.0); + expect(intersection1.x).toEqualEpsilon(1.0, 1e-15); + expect(intersection1.y).toEqualEpsilon(1.0, 1e-15); + + var intersection2 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 4.0, 3.0, 5.0, 0.0, 4.0, 3.0); + expect(intersection2.x).toEqualEpsilon(4.0, 1e-15); + expect(intersection2.y).toEqualEpsilon(3.0, 1e-15); + }); + + it('returns undefined for non-intersecting lines', function() { + var intersection0 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 5.0, 0.1, 4.8, 5.0, 0.0); + expect(intersection0).toBeUndefined(); + + var intersection1 = Intersections2D.computeLineSegmentLineSegmentIntersection(10.0, 0.0, 0.0, -10.0, 0.0, 0.0, -8.0, -8.0); + expect(intersection1).toBeUndefined(); + }); + + it('returns undefined for parallel lines', function() { + var intersection0 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, 1.0, 1.0, 1.0, 4.0); + expect(intersection0).toBeUndefined(); + + var intersection1 = Intersections2D.computeLineSegmentLineSegmentIntersection(1.0, 1.0, 4.0, 4.0, 0.0, 0.0, 3.0, 3.0); + expect(intersection1).toBeUndefined(); + }); + + it('returns undefined for coincident lines', function() { + var intersection0 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0, 4.0); + expect(intersection0).toBeUndefined(); + + var intersection1 = Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0); + expect(intersection1).toBeUndefined(); + }); + }); });