1 using Microsoft.Xna.Framework;
3 using System.Collections.Generic;
20 static class MathUtils
22 public static Vector2 DiscardZ(
this Vector3 vector)
23 =>
new Vector2(vector.X, vector.Y);
25 public static float Percentage(
float portion,
float total)
27 return portion / total * 100;
30 public static int PositiveModulo(
int i,
int n)
32 return (i % n + n) % n;
35 public static float PositiveModulo(
float i,
float n)
37 return (i % n + n) % n;
40 public static double Distance(
double x1,
double y1,
double x2,
double y2)
44 return Math.Sqrt(dX * dX + dY * dY);
47 public static double DistanceSquared(
double x1,
double y1,
double x2,
double y2)
51 return dX * dX + dY * dY;
54 public static int DistanceSquared(
int x1,
int y1,
int x2,
int y2)
58 return dX * dX + dY * dY;
61 public static Vector2 SmoothStep(Vector2 v1, Vector2 v2,
float amount)
64 MathHelper.SmoothStep(v1.X, v2.X, amount),
65 MathHelper.SmoothStep(v1.Y, v2.Y, amount));
68 public static float SmoothStep(
float t)
70 return t * t * (3f - 2f * t);
73 public static float SmootherStep(
float t)
75 return t * t * t * (t * (6f * t - 15f) + 10f);
78 public static float EaseIn(
float t)
80 return 1f - (float)Math.Cos(t * MathHelper.PiOver2);
83 public static float EaseOut(
float t)
85 return (
float)Math.Sin(t * MathHelper.PiOver2);
88 public static Vector2 ClampLength(
this Vector2 v,
float length)
90 float currLength = v.Length();
91 if (currLength > length)
93 return v / currLength * length;
98 public static bool Contains(
this Rectangle rect,
double x,
double y)
100 return x > rect.X && x < rect.Right && y > rect.Y && y < rect.Bottom;
103 public static float Round(
float value,
float div)
105 return (value < 0.0f) ?
106 (float)Math.Ceiling(value / div) * div :
107 (float)Math.Floor(value / div) * div;
110 public static int RoundToInt(
float v) => (int)MathF.Round(v);
112 public static float RoundTowardsClosest(
float value,
float div)
114 return (
float)Math.Round(value / div) * div;
117 public static float VectorToAngle(Vector2 vector)
119 return (
float)Math.Atan2(vector.Y, vector.X);
122 public static Point ToPoint(Vector2 vector)
124 return new Point((
int)vector.X,(
int)vector.Y);
127 public static bool IsValid(
float value)
129 return (!
float.IsInfinity(value) && !
float.IsNaN(value));
132 public static bool IsValid(Vector2 vector)
134 return (IsValid(vector.X) && IsValid(vector.Y));
137 public static Rectangle ExpandRect(Rectangle rect,
int amount)
139 return new Rectangle(rect.X - amount, rect.Y + amount, rect.Width + amount * 2, rect.Height + amount * 2);
148 public static int VectorOrientation(Vector2 pointA, Vector2 pointB, Vector2 pointC)
150 float determinant = (pointB.X - pointA.X) * (pointC.Y - pointA.Y) - (pointC.X - pointA.X) * (pointB.Y - pointA.Y);
152 return -Math.Sign(determinant);
156 public static float CurveAngle(
float from,
float to,
float step)
158 from = WrapAngleTwoPi(from);
159 to = WrapAngleTwoPi(to);
161 if (Math.Abs(from - to) < MathHelper.Pi)
164 return MathHelper.Lerp(from, to, step);
170 from += MathHelper.TwoPi;
172 to += MathHelper.TwoPi;
174 float retVal = MathHelper.Lerp(from, to, step);
177 if (retVal >= MathHelper.TwoPi)
178 retVal -= MathHelper.TwoPi;
185 public static float WrapAngleTwoPi(
float angle)
187 if (
float.IsInfinity(angle) ||
float.IsNegativeInfinity(angle) ||
float.IsNaN(angle))
191 return PositiveModulo(angle, MathHelper.TwoPi);
197 public static float WrapAnglePi(
float angle)
199 if (
float.IsInfinity(angle) ||
float.IsNegativeInfinity(angle) ||
float.IsNaN(angle))
203 float min = -MathHelper.Pi;
204 float diffFromMin = angle - min;
205 return diffFromMin - (MathF.Floor(diffFromMin / MathHelper.TwoPi) * MathHelper.TwoPi) + min;
208 public static float GetShortestAngle(
float from,
float to)
211 from = WrapAngleTwoPi(from);
212 to = WrapAngleTwoPi(to);
214 if (Math.Abs(from - to) < MathHelper.Pi)
222 from += MathHelper.TwoPi;
224 to += MathHelper.TwoPi;
232 public static float GetMidAngle(
float from,
float to)
234 float max = Math.Max(from, to);
235 float min = Math.Min(from, to);
236 float diff = max - min;
240 return from + diff / 2;
245 return from - diff / 2;
252 public static float SolveTriangleSSS(
float a,
float b,
float c)
254 float A = (float)Math.Acos((b * b + c * c - a * a) / (2 * b * c));
256 if (
float.IsNaN(A)) A = 1.0f;
261 public static byte AngleToByte(
float angle)
263 angle = WrapAngleTwoPi(angle);
264 angle = angle * (255.0f / MathHelper.TwoPi);
265 return Convert.ToByte(angle);
268 public static float ByteToAngle(
byte b)
270 float angle = (float)b;
271 angle = angle * (MathHelper.TwoPi / 255.0f);
278 public static bool LineSegmentsIntersect(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
280 float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));
281 float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));
282 float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));
284 if (denominator == 0)
return numerator1 == 0 && numerator2 == 0;
286 float r = numerator1 / denominator;
287 float s = numerator2 / denominator;
289 return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
295 public static bool GetLineSegmentIntersection(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, out Vector2 intersection)
297 return GetLineIntersection(a1, a2, b1, b2, areLinesInfinite:
false, out intersection);
303 public static bool GetLineIntersection(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2,
bool areLinesInfinite, out Vector2 intersection)
305 intersection = Vector2.Zero;
309 float bDotDPerp = b.X * d.Y - b.Y * d.X;
312 if (bDotDPerp == 0)
return false;
315 float t = (c.X * d.Y - c.Y * d.X) / bDotDPerp;
317 if (!areLinesInfinite)
319 if (t < 0 || t > 1) {
return false; }
320 float u = (c.X * b.Y - c.Y * b.X) / bDotDPerp;
321 if (u < 0 || u > 1) {
return false; }
324 intersection = a1 + t * b;
328 public static bool GetAxisAlignedLineIntersection(Vector2 a1, Vector2 a2, Vector2 axisAligned1, Vector2 axisAligned2,
bool isHorizontal, out Vector2 intersection)
330 intersection = Vector2.Zero;
334 float xDiff = axisAligned1.X - a1.X;
335 if (Math.Sign(xDiff) == Math.Sign(axisAligned1.X - a2.X)) {
return false; }
337 float s = (a2.Y - a1.Y) / (a2.X - a1.X);
338 float y = a1.Y + xDiff * s;
340 if (axisAligned1.Y < axisAligned2.Y)
342 if (y < axisAligned1.Y) {
return false; }
343 if (y > axisAligned2.Y) {
return false; }
347 if (y > axisAligned1.Y) {
return false; }
348 if (y < axisAligned2.Y) {
return false; }
351 intersection =
new Vector2(axisAligned1.X, y);
356 float yDiff = axisAligned1.Y - a1.Y;
357 if (Math.Sign(yDiff) == Math.Sign(axisAligned1.Y - a2.Y)) {
return false; }
359 float s = (a2.X - a1.X) / (a2.Y - a1.Y);
360 float x = a1.X + yDiff * s;
362 if (axisAligned1.X < axisAligned2.X)
364 if (x < axisAligned1.X) {
return false; }
365 if (x > axisAligned2.X) {
return false; }
369 if (x > axisAligned1.X) {
return false; }
370 if (x < axisAligned2.X) {
return false; }
373 intersection =
new Vector2(x, axisAligned1.Y);
378 public static bool GetLineRectangleIntersection(Vector2 a1, Vector2 a2, Rectangle rect, out Vector2 intersection)
380 if (GetAxisAlignedLineIntersection(a1, a2,
381 new Vector2(rect.X, rect.Y),
382 new Vector2(rect.Right, rect.Y),
383 true, out intersection))
388 if (GetAxisAlignedLineIntersection(a1, a2,
389 new Vector2(rect.X, rect.Y - rect.Height),
390 new Vector2(rect.Right, rect.Y - rect.Height),
391 true, out intersection))
396 if (GetAxisAlignedLineIntersection(a1, a2,
397 new Vector2(rect.X, rect.Y),
398 new Vector2(rect.X, rect.Y - rect.Height),
399 false, out intersection))
404 if (GetAxisAlignedLineIntersection(a1, a2,
405 new Vector2(rect.Right, rect.Y),
406 new Vector2(rect.Right, rect.Y - rect.Height),
407 false, out intersection))
415 public static Vector2 FlipX(
this Vector2 vector)
416 =>
new Vector2(-vector.X, vector.Y);
418 public static Vector2 FlipY(
this Vector2 vector)
419 =>
new Vector2(vector.X, -vector.Y);
421 public static Vector2 YX(
this Vector2 vector)
422 =>
new Vector2(x: vector.Y, y: vector.X);
424 public static Point FlipY(
this Point point)
425 =>
new Point(point.X, -point.Y);
427 public static Point YX(
this Point point)
428 =>
new Point(x: point.Y, y: point.X);
430 public static Vector2 RotatedUnitXRadians(
float radians)
431 =>
new Vector2(MathF.Cos(radians), MathF.Sin(radians));
433 public static Vector2 RotatedUnitYRadians(
float radians)
434 => RotatedUnitXRadians(radians).YX().FlipX();
436 public static Vector2 Round(
this Vector2 vector)
437 =>
new Vector2((
int)MathF.Round(vector.X), (
int)MathF.Round(vector.Y));
448 public static int GetLineCircleIntersections(Vector2 circlePos,
float radius,
449 Vector2 point1, Vector2 point2,
bool isLineSegment, out Vector2? intersection1, out Vector2? intersection2)
451 float dx, dy, A, B, C, det;
453 dx = point2.X - point1.X;
454 dy = point2.Y - point1.Y;
456 A = dx * dx + dy * dy;
457 B = 2 * (dx * (point1.X - circlePos.X) + dy * (point1.Y - circlePos.Y));
458 C = (point1.X - circlePos.X) * (point1.X - circlePos.X) + (point1.Y - circlePos.Y) * (point1.Y - circlePos.Y) - radius * radius;
460 det = B * B - 4 * A * C;
461 if ((A <= 0.0000001) || (det < 0))
464 intersection1 =
null;
465 intersection2 =
null;
471 float t = -B / (2 * A);
472 intersection1 =
new Vector2(point1.X + t * dx, point1.Y + t * dy);
473 intersection2 =
null;
479 float t1 = (float)((-B + Math.Sqrt(det)) / (2 * A));
480 float t2 = (float)((-B - Math.Sqrt(det)) / (2 * A));
485 if (t1 >= 0 && t1 <= 1.0f)
487 intersection1 = point1 +
new Vector2(dx, dy) * t1;
488 if (t2 >= 0 && t2 <= 1.0f)
491 intersection2 = point1 +
new Vector2(dx, dy) * t2;
496 intersection2 =
null;
499 else if (t2 >= 0 && t2 <= 1.0f)
502 intersection1 = point1 +
new Vector2(dx, dy) * t2;
503 intersection2 =
null;
509 intersection1 =
null;
510 intersection2 =
null;
516 intersection1 = point1 +
new Vector2(dx, dy) * t1;
517 intersection2 = point1 +
new Vector2(dx, dy) * t2;
523 public static float LineToPointDistance(Vector2 lineA, Vector2 lineB, Vector2 point)
525 float xDiff = lineB.X - lineA.X;
526 float yDiff = lineB.Y - lineA.Y;
528 if (xDiff == 0 && yDiff == 0)
530 return Vector2.Distance(lineA, point);
533 return (
float)(Math.Abs(xDiff * (lineA.Y - point.Y) - yDiff * (lineA.X - point.X)) /
534 Math.Sqrt(xDiff * xDiff + yDiff * yDiff));
537 public static float LineToPointDistanceSquared(Vector2 lineA, Vector2 lineB, Vector2 point)
539 float xDiff = lineB.X - lineA.X;
540 float yDiff = lineB.Y - lineA.Y;
542 if (xDiff == 0 && yDiff == 0)
544 return Vector2.DistanceSquared(lineA, point);
547 float numerator = xDiff * (lineA.Y - point.Y) - yDiff * (lineA.X - point.X);
548 return (numerator * numerator) / (xDiff * xDiff + yDiff * yDiff);
551 public static double LineSegmentToPointDistanceSquared(Point lineA, Point lineB, Point point)
553 return LineSegmentToPointDistanceSquared(lineA.X, lineA.Y, lineB.X, lineB.Y, point.X, point.Y);
556 public static float LineSegmentToPointDistanceSquared(Vector2 lineA, Vector2 lineB, Vector2 point)
558 return (
float)LineSegmentToPointDistanceSquared(lineA.X, lineA.Y, lineB.X, lineB.Y, point.X, point.Y);
561 private static double LineSegmentToPointDistanceSquared(
double line1X,
double line1Y,
double line2X,
double line2Y,
double pointX,
double pointY)
563 double xDiff = line2X - line1X;
564 double yDiff = line2Y - line1Y;
566 if (xDiff == 0 && yDiff == 0)
568 double v1 = line1X - pointX;
569 double v2 = line1Y - pointY;
570 return (v1 * v1) + (v2 * v2);
574 double t = ((pointX - line1X) * xDiff + (pointY - line1Y) * yDiff) / (xDiff * xDiff + yDiff * yDiff);
580 xDiff = pointX - line1X;
581 yDiff = pointY - line1Y;
585 xDiff = pointX - line2X;
586 yDiff = pointY - line2Y;
590 xDiff = pointX - (line1X + t * xDiff);
591 yDiff = pointY - (line1Y + t * yDiff);
594 return xDiff * xDiff + yDiff * yDiff;
597 public static Vector2 GetClosestPointOnLineSegment(Vector2 lineA, Vector2 lineB, Vector2 point)
599 float xDiff = lineB.X - lineA.X;
600 float yDiff = lineB.Y - lineA.Y;
602 if (xDiff == 0 && yDiff == 0)
608 float t = ((point.X - lineA.X) * xDiff + (point.Y - lineA.Y) * yDiff) / (xDiff * xDiff + yDiff * yDiff);
622 return new Vector2(lineA.X + t * xDiff, lineA.Y + t * yDiff);
626 public static bool CircleIntersectsRectangle(Vector2 circlePos,
float radius, Rectangle rect)
628 int halfWidth = rect.Width / 2;
629 float xDist = Math.Abs(circlePos.X - (rect.X + halfWidth));
630 if (xDist > halfWidth + radius) {
return false; }
632 int halfHeight = rect.Height / 2;
633 float yDist = Math.Abs(circlePos.Y - (rect.Y + halfHeight));
634 if (yDist > halfHeight + radius) {
return false; }
636 if (xDist <= halfWidth || yDist <= halfHeight) {
return true; }
638 float distSqX = xDist - halfWidth;
639 float distSqY = yDist - halfHeight;
641 return distSqX * distSqX + distSqY * distSqY <= radius * radius;
651 public static Vector2 GetPointOnCircumference(Vector2 center,
float radius,
float angle)
654 center.X + radius * (
float)Math.Cos(angle),
655 center.Y + radius * (
float)Math.Sin(angle));
666 public static Vector2[] GetPointsOnCircumference(Vector2 center,
float radius,
int points,
float firstAngle = 0.0f)
668 var maxAngle = (float)(2 * Math.PI);
669 var angleStep = maxAngle / points;
670 var coordinates =
new Vector2[points];
671 for (
int i = 0; i < points; i++)
673 var angle = firstAngle + (i * angleStep);
674 if (angle > maxAngle) { angle -= maxAngle; }
675 coordinates[i] = GetPointOnCircumference(center, radius, angle);
684 public static List<Vector2[]> TriangulateConvexHull(List<Vector2> vertices, Vector2 center)
686 List<Vector2[]> triangles =
new List<Vector2[]>();
687 vertices.Sort(
new CompareCCW(center));
688 for (
int i = 0; i < vertices.Count; i++)
690 triangles.Add(
new Vector2[3] { center, vertices[i], vertices[(i + 1) % vertices.Count] });
695 public static List<Vector2> GiftWrap(List<Vector2> points)
697 if (points.Count == 0)
return points;
699 Vector2 leftMost = points[0];
700 foreach (Vector2 point
in points)
702 if (point.X < leftMost.X) leftMost = point;
705 List<Vector2> wrappedPoints =
new List<Vector2>();
707 Vector2 currPoint = leftMost;
711 wrappedPoints.Add(currPoint);
712 endPoint = points[0];
714 for (
int i = 1; i < points.Count; i++)
716 if (points[i].NearlyEquals(currPoint))
continue;
717 if (currPoint == endPoint ||
718 MathUtils.VectorOrientation(currPoint, endPoint, points[i]) == -1)
720 endPoint = points[i];
724 currPoint = endPoint;
727 while (endPoint != leftMost);
729 return wrappedPoints;
732 public static List<Vector2[]> GenerateJaggedLine(Vector2 start, Vector2 end,
int iterations,
float offsetAmount, Rectangle? bounds =
null)
734 List<Vector2[]> segments =
new List<Vector2[]>
736 new Vector2[] { start, end }
739 for (
int n = 0; n < iterations; n++)
741 for (
int i = 0; i < segments.Count; i++)
743 Vector2 startSegment = segments[i][0];
744 Vector2 endSegment = segments[i][1];
746 segments.RemoveAt(i);
748 Vector2 midPoint = (startSegment + endSegment) / 2.0f;
750 Vector2 normal = Vector2.Normalize(endSegment - startSegment);
751 normal =
new Vector2(-normal.Y, normal.X);
752 midPoint += normal * Rand.Range(-offsetAmount, offsetAmount, Rand.RandSync.ServerAndClient);
756 if (midPoint.X < bounds.Value.X)
758 midPoint.X = bounds.Value.X + (bounds.Value.X - midPoint.X);
760 else if (midPoint.X > bounds.Value.Right)
762 midPoint.X = bounds.Value.Right - (midPoint.X - bounds.Value.Right);
764 if (midPoint.Y < bounds.Value.Y)
766 midPoint.Y = bounds.Value.Y + (bounds.Value.Y - midPoint.Y);
768 else if (midPoint.Y > bounds.Value.Bottom)
770 midPoint.Y = bounds.Value.Bottom - (midPoint.Y - bounds.Value.Bottom);
774 segments.Insert(i,
new Vector2[] { startSegment, midPoint });
775 segments.Insert(i + 1,
new Vector2[] { midPoint, endSegment });
780 offsetAmount *= 0.5f;
788 public static string GetBytesReadable(
long i)
791 long absolute_i = (i < 0 ? -i : i);
795 if (absolute_i >= 0x1000000000000000)
798 readable = (i >> 50);
800 else if (absolute_i >= 0x4000000000000)
803 readable = (i >> 40);
805 else if (absolute_i >= 0x10000000000)
808 readable = (i >> 30);
810 else if (absolute_i >= 0x40000000)
813 readable = (i >> 20);
815 else if (absolute_i >= 0x100000)
818 readable = (i >> 10);
820 else if (absolute_i >= 0x400)
827 return i.ToString(
"0 B");
830 readable = (readable / 1024);
832 return readable.ToString(
"0.# ") + suffix;
835 public static void SplitRectanglesHorizontal(List<Rectangle> rects, Vector2 point)
837 for (
int i = 0; i < rects.Count; i++)
839 if (point.Y > rects[i].Y && point.Y < rects[i].Y + rects[i].Height)
841 Rectangle rect1 = rects[i];
842 Rectangle rect2 = rects[i];
844 rect1.Height = (int)(point.Y - rects[i].Y);
846 rect2.Height = rects[i].Height - rect1.Height;
847 rect2.Y = rect1.Y + rect1.Height;
849 rects.Insert(i + 1, rect2); i++;
854 public static void SplitRectanglesVertical(List<Rectangle> rects, Vector2 point)
856 for (
int i = 0; i < rects.Count; i++)
858 if (point.X>rects[i].X && point.X<rects[i].X+rects[i].Width)
860 Rectangle rect1 = rects[i];
861 Rectangle rect2 = rects[i];
863 rect1.Width = (int)(point.X-rects[i].X);
865 rect2.Width = rects[i].Width - rect1.Width;
866 rect2.X = rect1.X + rect1.Width;
868 rects.Insert(i + 1, rect2); i++;
887 public static bool NearlyEqual(
float a,
float b,
float epsilon = 0.0001f)
895 if (a == 0 || b == 0)
898 return Math.Abs(a - b) < epsilon;
901 float absA = Math.Abs(a);
902 float absB = Math.Abs(b);
903 float absAB = absA + absB;
910 float diff = Math.Abs(a - b);
912 return diff / absAB < epsilon;
918 public static bool NearlyEqual(Vector2 a, Vector2 b,
float epsilon = 0.0001f)
920 return NearlyEqual(a.X, b.X, epsilon) && NearlyEqual(a.Y, b.Y, epsilon);
926 public static Vector2 Bezier(Vector2 start, Vector2 control, Vector2 end,
float t)
928 return Pow(1 - t, 2) * start + 2 * t * (1 - t) * control + Pow(t, 2) * end;
931 public static float Pow(
float f,
float p)
933 return (
float)Math.Pow(f, p);
936 public static float Pow2(
float f) => f * f;
941 public static Vector2 ToVector2(
this Alignment alignment)
943 Vector2 vector =
new Vector2(0.0f,0.0f);
948 else if (alignment.HasFlag(
Alignment.Right))
956 else if (alignment.HasFlag(
Alignment.Bottom))
968 public static Vector2 RotatePointAroundTarget(Vector2 point, Vector2 target,
float radians,
bool clockWise =
true)
970 var sin = Math.Sin(radians);
971 var cos = Math.Cos(radians);
976 Vector2 dir = point - target;
977 var x = (cos * dir.X) - (sin * dir.Y) + target.X;
978 var y = (sin * dir.X) + (cos * dir.Y) + target.Y;
979 return new Vector2((
float)x, (
float)y);
985 public static Vector2 RotatePoint(Vector2 point,
float radians)
987 var sin = Math.Sin(radians);
988 var cos = Math.Cos(radians);
989 var x = (cos * point.X) - (sin * point.Y);
990 var y = (sin * point.X) + (cos * point.Y);
991 return new Vector2((
float)x, (
float)y);
998 public static Vector2[] GetImaginaryRect(Vector2 up, Vector2 center, Vector2 size)
1000 return GetImaginaryRect(
new Vector2[4], up, center, size);
1007 public static Vector2[] GetImaginaryRect(Vector2[] corners, Vector2 up, Vector2 center, Vector2 size)
1009 if (corners.Length != 4)
1011 throw new Exception(
"Invalid length for the corners array. Must be 4.");
1013 Vector2 halfSize = size / 2;
1014 Vector2 left = up.Right();
1015 corners[0] = center + up * halfSize.Y + left * halfSize.X;
1016 corners[1] = center + up * halfSize.Y - left * halfSize.X;
1017 corners[2] = center - up * halfSize.Y - left * halfSize.X;
1018 corners[3] = center - up * halfSize.Y + left * halfSize.X;
1027 public static bool RectangleContainsPoint(Vector2[] corners, Vector2 point)
1029 if (corners.Length != 4)
1031 throw new Exception(
"Invalid length of the corners array! Must be 4");
1033 return RectangleContainsPoint(corners[0], corners[1], corners[2], corners[3], point);
1041 public static bool RectangleContainsPoint(Vector2 c1, Vector2 c2, Vector2 c3, Vector2 c4, Vector2 point)
1043 return TriangleContainsPoint(c1, c2, c3, point) || TriangleContainsPoint(c1, c3, c4, point);
1049 public static bool TriangleContainsPoint(Vector2 c1, Vector2 c2, Vector2 c3, Vector2 point)
1052 Vector2 v0 = c3 - c1;
1053 Vector2 v1 = c2 - c1;
1054 Vector2 v2 = point - c1;
1057 float dot00 = Vector2.Dot(v0, v0);
1058 float dot01 = Vector2.Dot(v0, v1);
1059 float dot02 = Vector2.Dot(v0, v2);
1060 float dot11 = Vector2.Dot(v1, v1);
1061 float dot12 = Vector2.Dot(v1, v2);
1064 float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
1065 float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
1066 float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
1069 return u >= 0 && v >= 0 && (u + v) < 1;
1075 public static float InverseLerp(
float min,
float max,
float v)
1077 float diff = max - min;
1079 if (diff == 0) {
return v >= max ? 1f : 0f; }
1080 return MathHelper.Clamp((v - min) / diff, 0f, 1f);
1083 public static float Min(params
float[] vals)
1088 public static float Max(params
float[] vals)
1096 private Vector2 center;
1100 this.center = center;
1107 public static int Compare(Vector2 a, Vector2 b, Vector2 center)
1109 if (a == b) {
return 0; }
1110 if (a.X - center.X >= 0 && b.X - center.X < 0) {
return 1; }
1111 if (a.X - center.X < 0 && b.X - center.X >= 0) {
return -1; }
1112 if (a.X - center.X == 0 && b.X - center.X == 0)
1114 if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) {
return Math.Sign(a.Y - b.Y); }
1115 return Math.Sign(a.Y - b.Y);
1119 float det = (a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y);
1120 if (det < 0) {
return 1; }
1121 if (det > 0) {
return -1; }
1125 float d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y);
1126 float d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y);
1127 return Math.Sign(d1 - d2);
1133 private Vector2 center;
1137 this.center = center;
1143 public static int Compare(Vector2 a, Vector2 b, Vector2 center)
CompareCCW(Vector2 center)
static int Compare(Vector2 a, Vector2 b, Vector2 center)
int Compare(Vector2 a, Vector2 b)
static int Compare(Vector2 a, Vector2 b, Vector2 center)
int Compare(Vector2 a, Vector2 b)
CompareCW(Vector2 center)