Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs =================================================================== diff -u -r1974 -r3079 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs (.../Routines2D.cs) (revision 1974) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs (.../Routines2D.cs) (revision 3079) @@ -21,6 +21,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using Deltares.DamEngine.Data.Standard; namespace Deltares.DamEngine.Data.Geometry { @@ -63,6 +65,17 @@ } /// + /// Enum for the clockwise options + /// + public enum Clockwise + { + IsClockwise = 0, + AntiClockwise = 1, + NotEnoughUniquePoints = 2, + PointsOnLine = 3 + } + + /// /// Static class Routines2D /// public static class Routines2D @@ -74,7 +87,7 @@ public double Z; } - private const double cEpsilon = 1.0e-4; + private const double CEpsilon = 1.0e-4; /// /// Checks if the 2D Lines strictly intersect. Strictly means that the intersection point must be part of both lines so @@ -99,12 +112,51 @@ double point3X, double point3Z, double point4X, double point4Z, out Point2D intersectionPoint) { return DetermineIf2DLinesIntersectStrickly(point1X, point1Z, point2X, point2Z, point3X, point3Z, point4X, point4Z, - out intersectionPoint, cEpsilon); + out intersectionPoint, CEpsilon); } + /// + /// Determines the point (aResultX, aResultY) on the line (aLine1X, aLine1Y, aLine2X, aLine2Y) with the + /// shortest possible distance to a point (aPointX, aPointY). + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void GetPointOnLineClosestTo(double aPointX, double aPointY, double aLine1X, double aLine1Y, double aLine2X, double aLine2Y, out double aResultX, out double aResultY) + { + + var lAb = Compute2DDistance(aLine1X, aLine1Y, aLine2X, aLine2Y); + var lAc = Compute2DDistance(aLine1X, aLine1Y, aPointX, aPointY); + var lBc = Compute2DDistance(aLine2X, aLine2Y, aPointX, aPointY); + var lAClose = (Math.Pow(lAc, 2) - Math.Pow(lBc, 2) + Math.Pow(lAb, 2)) / (2 * lAb); + if (lAClose <= 0) + { + aResultX = aLine1X; + aResultY = aLine1Y; + } + else + { + if (lAClose >= lAb) + { + aResultX = aLine2X; + aResultY = aLine2Y; + } + else + { + aResultX = aLine1X + ((lAClose / lAb) * (aLine2X - aLine1X)); + aResultY = aLine1Y + ((lAClose / lAb) * (aLine2Y - aLine1Y)); + } + } + } + /// - /// Doeses the point exist in line. + /// Does the point exist in line. /// /// The line point1 x. /// The line point1 z. @@ -164,6 +216,41 @@ } /// + /// To check if the points of the polygon are clock-wise + /// + /// + /// + public static Clockwise IsClockWise(IEnumerable aPolygon) + { + var distinctPoints = aPolygon.Distinct().ToArray(); + if (distinctPoints.Length < 3) + { + return Clockwise.NotEnoughUniquePoints; + } + + double sumClockwise = 0; + double clockwise; + for (int ii = 0; ii < distinctPoints.Length - 1; ii++) + { + clockwise = (distinctPoints[ii + 1].X - distinctPoints[ii].X) * + (distinctPoints[ii + 1].Z + distinctPoints[ii].Z); + sumClockwise += clockwise; + } + clockwise = (distinctPoints[0].X - distinctPoints[distinctPoints.Length - 1].X) * + (distinctPoints[0].Z + distinctPoints[distinctPoints.Length - 1].Z); + + sumClockwise += clockwise; + var result = Math.Sign(sumClockwise); + + if (result == 0) + { + return Clockwise.PointsOnLine; + } + + return result > 0.0 ? Clockwise.IsClockwise : Clockwise.AntiClockwise; + } + + /// /// Find if points Ax,ay are between a boundary polygon. /// /// The polygon. @@ -321,8 +408,38 @@ return result; } - /// + /// Determines angle between 2 lines. + /// Clockwise Input: point1, commonpoint, point2, commonpoint, normalvect(ex <0,0,-1>), validate + /// + /// + /// + /// + /// + /// + public static double FindAngle(Point2D line1Point1, Point2D line1Point2, Point2D line2Point1, + Point2D line2Point2) + { + var x1 = line1Point2.X - line1Point1.X; + var z1 = line1Point2.Z - line1Point1.Z; + + var x2 = line2Point2.X - line2Point1.X; + var z2 = line2Point2.Z - line2Point1.Z; + + var angle1 = GeneralMathRoutines.RadianToDegree(Math.Atan2(z1, x1)); + var angle2 = GeneralMathRoutines.RadianToDegree(Math.Atan2(z2, x2)); + + var angle = angle2 - angle1; + + if (angle < 0) + { + angle += 360; + } + + return angle; + } + + /// /// Checks if values are equal /// /// @@ -382,7 +499,16 @@ } - public static LineIntersection DetermineIf2DLinesIntersectWithExtrapolation(Point2D aPoint1, Point2D aPoint2, Point2D aPoint3, Point2D aPoint4, ref Point2D aIntersectionPoint) + /// + /// Determines the if 2D lines intersect using extrapolation when needed. + /// + /// a point1. + /// a point2. + /// a point3. + /// a point4. + /// a intersection point. + /// + public static LineIntersection DetermineIf2DLinesIntersectWithExtrapolation(Point2D aPoint1, Point2D aPoint2, Point2D aPoint3, Point2D aPoint4, out Point2D aIntersectionPoint) { var lLineConstant1 = CalculateNormalLineConstants(aPoint1.X, aPoint1.Z, aPoint2.X, aPoint2.Z); var lLineConstant2 = CalculateNormalLineConstants(aPoint3.X, aPoint3.Z, aPoint4.X, aPoint4.Z); @@ -412,7 +538,7 @@ var lB2 = aLine2Constant.Y; var lC2 = aLine2Constant.Z; - if (AreLinesParallel(lA1, lA2, lB1, lB2, cEpsilon)) + if (AreLinesParallel(lA1, lA2, lB1, lB2, CEpsilon)) { aIntersectionPoint = null; return LineIntersection.Parallel; @@ -594,7 +720,7 @@ { double q = Math.Sqrt(pointX * pointX + pointY * pointY); - if (q != 0) + if (!q.AlmostEquals(0, 1e-8)) { pointX = pointX / q; pointY = pointY / q; @@ -610,7 +736,7 @@ /// The point2 z. /// The tolerance. /// - private static bool DetermineIfPointsCoincide(double point1X, double point1Z, double point2X, double point2Z, double tolerance) + public static bool DetermineIfPointsCoincide(double point1X, double point1Z, double point2X, double point2Z, double tolerance) { if ((Math.Abs(point1X - point2X)) < tolerance && Math.Abs(point1Z - point2Z) < tolerance) {