/// <summary> /// Получить точку нормали (проходящую через заданную точку С) и лежащую на окружности. Точка может лежать внутри/снаружи и на границе. /// </summary> /// <returns></returns> public static PointF GetNormalPointForCircle(PointF c, float r, PointF pnt) { var a1 = pnt.Y * pnt.Y * c.X - 2 * c.X * c.X * pnt.X + c.X * c.X * c.X + c.Y * c.Y * c.X - 2 * c.Y * c.X * pnt.Y + c.X * pnt.X * pnt.X; var s1 = (float)Math.Sqrt(4 * c.Y * pnt.Y * r * r * pnt.X * c.X - 2 * c.Y * c.Y * r * r * pnt.X * c.X - 2 * c.Y * pnt.Y * r * r * pnt.X * pnt.X - 2 * c.Y * pnt.Y * r * r * c.X * c.X - 2 * pnt.Y * pnt.Y * r * r * pnt.X * c.X + c.Y * c.Y * r * r * pnt.X * pnt.X + c.Y * c.Y * r * r * c.X * c.X + pnt.Y * pnt.Y * r * r * pnt.X * pnt.X + pnt.Y * pnt.Y * r * r * c.X * c.X - 4 * pnt.X * pnt.X * pnt.X * c.X * r * r - 4 * pnt.X * c.X * c.X * c.X * r * r + 6 * pnt.X * pnt.X * c.X * c.X * r * r + c.X * c.X * c.X * c.X * r * r + pnt.X * pnt.X * pnt.X * pnt.X * r * r); var denom = c.Y * c.Y - 2 * c.Y * pnt.Y + pnt.Y * pnt.Y - 2 * pnt.X * c.X + c.X * c.X + pnt.X * pnt.X; var p = new[] { new PointF((a1 + s1) / denom, 0), new PointF(-(-a1 + s1) / denom, 0) }; p[0].Y = (p[0].X * c.Y - p[0].X * pnt.Y + c.X * pnt.Y - pnt.X * c.Y) / (-pnt.X + c.X); p[1].Y = (p[1].X * c.Y - p[1].X * pnt.Y + c.X * pnt.Y - pnt.X * c.Y) / (-pnt.X + c.X); return pnt.DistancePow2(p[0]) < pnt.DistancePow2(p[1]) ? p[0] : p[1]; //var cosinus = Cosinus(NormalizeVector(x1, y1, x1 + r, y1), NormalizeVector(x1, y1, xc, yc)); //var sinus = Sinus(NormalizeVector(x1, y1, x1 + r, y1), NormalizeVector(x1, y1, xc, yc)); //return new PointF(r * cosinus + x1, r * sinus + y1); }
public override float DistanceTo2(PointF pnt) { var cnt = GetCenter(); return pnt.DistancePow2(cnt) - 2 * pnt.Distance(cnt) * Radius + Radius * Radius; }
/// <summary> /// Принадлежность точки вектору /// </summary> /// <param name="pnt"></param> /// <returns></returns> public bool IsOwnPoint(PointF pnt) { return Math.Abs((LengthPow2() - pnt.DistancePow2(Begin) - pnt.DistancePow2(End)) - 0) < EPSILON; }
/// <summary> /// Квадратное растояние до точки (для ускореных вычислений) /// </summary> /// <param name="pnt">Заданная точка</param> /// <returns></returns> public float DistancePow2ToPoint(PointF pnt) { return pnt.DistancePow2(GetNormal(pnt)); }
/// <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; }
/// <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; }