Я использую .NET API для Autocad, у меня есть алгоритм (который я не писал) для определения того, находится ли точка внутри многоугольника (только прямые линии).
Я неоднократно тестировал свою команду на одном и том же 51 полигоне. 99% будет работать идеально. Время от времени он дает сбой на одном или нескольких полигонах, возвращая false для более чем 2000 точек, которые я создаю внутри ограничивающей рамки полилинии. Я видел, как это терпит неудачу, когда полилиния представляет собой простой прямоугольник, и все точки распределены по сетке внутри полилинии. В этом случае он должен был вернуть true более 2000 раз. Он никогда не подведет только по одному из пунктов, он подведет все. Я подтвердил, что точки создаются правильно там, где я их ожидаю, и что вершины многоугольника находятся там, где я их ожидаю. Когда это не удается, последняя угловая переменная для последней точки находится точно в двойном PI.
Я не занимаюсь многопоточностью. Единственная, возможно, «забавная» вещь, которую я делаю, - это COM-взаимодействие с Excel. Это происходит после того, как транзакция была зафиксирована для части с этим алгоритмом, и я уверен, что очищаю все свои COM-объекты. Мне не удалось воспроизвести сбой без части COM-взаимодействия, но я не думаю, что протестировал ее достаточно, чтобы иметь достаточно доказательств отсутствия.
Есть идеи, что может быть не так?
bool IsInsidePolygon(Polyline polygon, Point3d pt)
{
int n = polygon.NumberOfVertices;
double angle = 0;
Point pt1, pt2;
for (int i = 0; i < n; i++)
{
pt1.X = polygon.GetPoint2dAt(i).X - pt.X;
pt1.Y = polygon.GetPoint2dAt(i).Y - pt.Y;
pt2.X = polygon.GetPoint2dAt((i + 1) % n).X - pt.X;
pt2.Y = polygon.GetPoint2dAt((i + 1) % n).Y - pt.Y;
angle += Angle2D(pt1.X, pt1.Y, pt2.X, pt2.Y);
}
if (Math.Abs(angle) < Math.PI)
return false;
else
return true;
}
public struct Point
{
public double X, Y;
};
public static double Angle2D(double x1, double y1, double x2, double y2)
{
double dtheta, theta1, theta2;
theta1 = Math.Atan2(y1, x1);
theta2 = Math.Atan2(y2, x2);
dtheta = theta2 - theta1;
while (dtheta > Math.PI)
dtheta -= (Math.PI * 2);
while (dtheta < -Math.PI)
dtheta += (Math.PI * 2);
return (dtheta);
}