Пример #1
0
        /// <summary>
        /// Попадает ли точка внутрь полилинии.
        /// Предполагается, что полилиния имеет замкнутый контур.
        /// Подходит для полилиний с дуговыми сегментами.
        /// Работает медленнее чем IsPointInsidePolygon(), примерно в 10 раз.
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="onIsInside">Если исходная точка лежит на полилинии, то считать, что она внутри или нет: True - внутри, False - снаружи.</param>
        /// <param name="pl"></param>
        /// <exception cref="Exceptions.ErrorException">Не удалось определить за несколько попыток.</exception>
        public static bool IsPointInsidePolyline([NotNull] this Polyline pl, Point3d pt, bool onIsInside = false)
        {
            using (var ray = new Ray())
            {
                ray.BasePoint = pt;
                var vec = new Vector3d(0, 1, pt.Z);
                ray.SecondPoint = pt + vec;
                using (var ptsIntersects = new Point3dCollection())
                {
                    bool isContinue;
                    var  isPtOnPolyline = false;
                    var  countWhile     = 0;
                    do
                    {
                        using (var plane = new Plane())
                        {
                            pl.IntersectWith(ray, Intersect.OnBothOperands, plane, ptsIntersects, IntPtr.Zero, IntPtr.Zero);
                        }

                        isContinue = ptsIntersects.Cast <Point3d>().Any(p =>
                        {
                            if (pt.IsEqualTo(p))
                            {
                                isPtOnPolyline = true;
                                return(true);
                            }
                            var param = pl.GetParameterAtPointTry(p);
                            return(Math.Abs(param % 1) < 0.0001);
                        });

                        if (isPtOnPolyline)
                        {
                            return(onIsInside);
                        }

                        if (isContinue)
                        {
                            vec             = vec.RotateBy(0.01, Vector3d.ZAxis);
                            ray.SecondPoint = pt + vec;
                            ptsIntersects.Clear();
                            countWhile++;
                            if (countWhile > 3)
                            {
                                throw new ErrorException(new Errors.Error(
                                                             "Не определено попадает ли точка внутрь полилинии.",
                                                             pt.GetRectangleFromCenter(3), Matrix3d.Identity,
                                                             System.Drawing.SystemIcons.Error));
                            }
                        }
                    } while (isContinue);
                    return(NetLib.MathExt.IsOdd(ptsIntersects.Count));
                }
            }
        }