81 lines
2.3 KiB
C#
81 lines
2.3 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Assets.Common
|
|
{
|
|
public static class PointUtils
|
|
{
|
|
public static Point Mean(IEnumerable<Point> points)
|
|
{
|
|
var result = new Point(0, 0);
|
|
var i = 0;
|
|
|
|
foreach (var point in points)
|
|
{
|
|
result.x = (result.x * i + point.x) / (i + 1);
|
|
result.y = (result.y * i + point.y) / (i + 1);
|
|
|
|
i++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static IEnumerable<Point> CalculateNormals(IEnumerable<Point> points)
|
|
{
|
|
var pairs = points.RotateRight().Zip(points, (a, b) => (a, b));
|
|
var thirds = pairs.Zip(points.RotateLeft(), (pair, c) => (pair.a, pair.b, c));
|
|
|
|
return thirds.Select(third =>
|
|
{
|
|
var left = (third.a - third.b).Direction;
|
|
var right = (third.c - third.b).Direction;
|
|
|
|
return ((left + right) / 2).Direction * (IsClockwise(third.a, third.b, third.c) ? -1 : 1);
|
|
});
|
|
}
|
|
|
|
public static double AngleBetween(Point center, Point a, Point b)
|
|
{
|
|
a = a - center;
|
|
b = b - center;
|
|
|
|
var dot = a.x * b.x + a.y * b.y;
|
|
var det = a.x * b.y - a.y * b.x;
|
|
|
|
var angle = Math.Atan2(det, dot);
|
|
|
|
return angle > 0 ? angle : 2*Math.PI + angle;
|
|
}
|
|
|
|
public static bool IsClockwise(Point center, Point a, Point b)
|
|
{
|
|
var xa = a.x - center.x;
|
|
var xb = b.x - center.x;
|
|
var ya = a.y - center.y;
|
|
var yb = b.y - center.y;
|
|
|
|
return xa * yb - xb * ya < 0;
|
|
}
|
|
|
|
public static bool IsPointInside(Point point, Point[] polygon)
|
|
{
|
|
var j = polygon.Length - 1;
|
|
var inside = false;
|
|
|
|
for (int i = 0; i < polygon.Length; j = i++)
|
|
{
|
|
var pi = polygon[i];
|
|
var pj = polygon[j];
|
|
|
|
if (((pi.y <= point.y && point.y < pj.y) || (pj.y <= point.y && point.y < pi.y)) &&
|
|
(point.x < (pj.x - pi.x) * (point.y - pi.y) / (pj.y - pi.y) + pi.x))
|
|
inside = !inside;
|
|
}
|
|
|
|
return inside;
|
|
}
|
|
}
|
|
} |