Example #1
0
 /// <summary>
 /// Принадлежность точки выпуклому многоугольнику
 /// </summary>
 /// <param name="pnt">Проверяямая точка</param>
 /// <param name="sideIsJoint">Стороны принадлежат многоугольнику</param>
 /// <returns></returns>
 public bool JointPointConvex(PointF pnt, bool sideIsJoint)
 {
     var s = 0f;
     var dirs = new int[3];
     var v = new Vector();
     for (var i = 0; i < pnts.Count; i++)
     {
         v.Begin = pnts[i];
         v.End = pnts[(i + 1) % pnts.Count];
         dirs[v.LocatePointDir(pnt) + 1]++; // суммируются направления
     }
     // кол-во направлений == кол-во сторон
     return Math.Max(dirs[0], dirs[2]) // макс кол-во слева или справа
            + (sideIsJoint ? dirs[1] : 0) == pnts.Count;
 }
Example #2
0
        /// <summary>
        /// Определение самопересечения многоугольника
        /// </summary>
        /// <returns></returns>
        public bool IsSelfIntersection()
        {
            if (pnts.Count < 3) throw new Exception("Точек в полигоне должно быть минимум 3");
            if (pnts.Count == 3) return false;
            Vector v1 = new Vector(), v2 = new Vector();
            for (var i = 0; i < pnts.Count - 2; i++)
            {
                v1.Begin = pnts[i];
                v2.End = pnts[i + 1];

                for (var j = i + 2; j < pnts.Count; j++)
                {
                    if (i == 0 && j == pnts.Count - 1) continue;// исключение пересечения первого вектора с последним
                    v2.Begin = pnts[j];
                    v2.End = pnts[(j + 1) % pnts.Count];
                    if (v1.IsCross(v2))
                        return true;
                }
            }
            return false;
        }
Example #3
0
 /// <summary>
 /// Угол между векторами в радианах
 /// </summary>
 /// <param name="v2">Второй вектор</param>
 /// <returns></returns>
 public float GetAngle(Vector v2)
 {
     var a = ToOrigin();
     var b = v2.ToOrigin();
     return (float)Math.Atan2(a.X * b.Y - b.X * a.Y, a.X * b.X + a.Y * b.Y);
 }
Example #4
0
 /// <summary>
 /// Параллельность (коллинеарность) векторов
 /// </summary>
 /// <param name="a">Правый вектор</param>
 /// <param name="mathError">Погрешность</param>
 public bool IsVectorCollinear(Vector a, float mathError = float.Epsilon)
 {
     return Math.Abs(X * a.Y - a.X * Y) <= mathError;
 }
Example #5
0
        /// <summary>
        /// Нахождение точки пересечения двух отрезков (если есть)
        /// </summary>
        /// <param name="b"> </param>
        /// <param name="crs">Точка пересечения</param>
        /// <returns>Пересекаются или нет</returns>
        public bool JointVectors(Vector b, out PointF crs)
        {
            crs = new PointF(float.NaN, float.NaN);

            var w = (End.Y - Begin.Y) * (b.End.X - b.Begin.X) - (b.End.Y - b.Begin.Y) * (End.X - Begin.X);
            if (Math.Abs(w) > EPSILON)
            {
                var w1 = (b.Begin.Y - Begin.Y) * (b.End.X - b.Begin.X) * (End.X - Begin.X)
                    + Begin.X * (End.Y - Begin.Y) * (b.End.X - b.Begin.X)
                    - b.Begin.X * (b.End.Y - b.Begin.Y) * (End.X - Begin.X);
                var w2 = (b.Begin.X - Begin.X) * (b.End.Y - b.Begin.Y) * (End.Y - Begin.Y)
                    + Begin.Y * (End.X - Begin.X) * (b.End.Y - b.Begin.Y)
                    - b.Begin.Y * (b.End.X - b.Begin.X) * (End.Y - Begin.Y);
                crs.X = w1 / w;
                crs.Y = -w2 / w;
                return IsOwnPoint(crs) && b.IsOwnPoint(crs);
            }
            else
                return false;
        }
Example #6
0
 /// <summary>
 /// Определение факта пересечения двух векторов
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool IsCross(Vector other)
 {
     var pp = new[]{
                      LocatePointDir(other.Begin),
                      LocatePointDir(other.End),
                      other.LocatePointDir(Begin),
                      other.LocatePointDir(End)
                  };
     return (Math.Abs(pp[0] + pp[1]) != 2 && Math.Abs(pp[2] + pp[3]) != 2 && pp.Any(s => s != 0)) // на случай канонического пересечения
            || pp[0] == 0 && IsOwnPoint(other.Begin) // начало другого вектора лежит на этом отрезке
            || pp[1] == 0 && IsOwnPoint(other.End) // конец другого вектора лежит на этом отрезке
            || pp[2] == 0 && other.IsOwnPoint(Begin) // начало этого вектора лежит на другом отрезке
            || pp[3] == 0 && other.IsOwnPoint(End); // конец этого вектора лежит на другом отрезке
 }
Example #7
0
 /// <summary>
 /// Расстояние от точки до полигона
 /// </summary>
 /// <param name="pnt">Точка</param>
 /// <returns></returns>
 public float DistancePoint(PointF pnt)
 {
     if (pnts.Count < 3) throw new Exception("Точек в полигоне должно быть минимум 3");
     var v1 = new Vector();
     float minDistPow2 = float.MaxValue, distPow2;
     PointF curr;
     for (var i = 0; i < pnts.Count; i++)
     {
         v1.Begin = pnts[i];
         v1.End = pnts[(i + 1) % pnts.Count];
         curr = v1.GetNormal(pnt);
         distPow2 = pnt.DistancePow2(curr);
         if (distPow2 < minDistPow2)
             minDistPow2 = distPow2;
     }
     minDistPow2 = (float)Math.Sqrt(minDistPow2);
     return JointPoint(pnt) ? -minDistPow2 : minDistPow2;
 }
Example #8
0
 /// <summary>
 /// Точка нормали лежащая на границе полигона
 /// </summary>
 /// <param name="pnt">Внешняя точка</param>
 /// <returns></returns>
 public PointF GetNormalPoint(PointF pnt)
 {
     if (pnts.Count < 3) throw new Exception("Точек в полигоне должно быть минимум 3");
     var v1 = new Vector();
     float minDistPow2 = float.MaxValue, distPow2;
     PointF curr, res = new PointF();
     for (var i = 0; i < pnts.Count; i++)
     {
         v1.Begin = pnts[i];
         v1.End = pnts[(i + 1) % pnts.Count];
         curr = v1.GetNormal(pnt);
         distPow2 = pnt.DistancePow2(curr);
         if (distPow2 < minDistPow2)
         {
             res = curr;
             minDistPow2 = distPow2;
         }
     }
     return res;
 }