/***************************************************/

        public static bool IsContaining(this PolyCurve curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance)
        {
            // Todo:
            // - to be replaced with a general method for a nurbs curve?
            // - this is very problematic for edge cases (cutting line going through a sharp corner, to be superseded?

            BoundingBox box = curve.Bounds();

            if (points.Any(x => !box.IsContaining(x, true, tolerance)))
            {
                return(false);
            }

            if (!curve.IsClosed(tolerance))
            {
                return(false);
            }

            if (curve.Curves.Count == 1 && curve.Curves[0] is Circle)
            {
                return(IsContaining(curve.Curves[0] as Circle, points, acceptOnEdge, tolerance));
            }

            Plane  p     = curve.FitPlane(tolerance);
            double sqTol = tolerance * tolerance;

            if (p == null)
            {
                if (acceptOnEdge)
                {
                    foreach (Point pt in points)
                    {
                        if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol)
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            List <ICurve> subParts       = curve.SubParts();
            List <Vector> edgeDirections = subParts.Where(s => s is Line).Select(c => (c as Line).Direction()).ToList();

            foreach (Point pt in points)
            {
                Point pPt = pt.Project(p);
                if (pPt.SquareDistance(pt) > sqTol) // not on the same plane
                {
                    return(false);
                }

                Point  end       = p.Origin;                                                                                                 // Avrage of control points
                Vector direction = (end - pPt).Normalise();                                                                                  // Gets a line cutting through the curves and the point
                while (direction.SquareLength() <= 0.5 || edgeDirections.Any(e => 1 - Math.Abs(e.DotProduct(direction)) <= Tolerance.Angle)) // not zeroa or parallel to edges
                {
                    end       = end.Translate(Create.RandomVectorInPlane(p, true));
                    direction = (end - pPt).Normalise();
                }

                Line ray = new Line {
                    Start = pPt, End = end
                };
                ray.Infinite = true;
                List <Point> intersects      = new List <Point>();
                List <Point> extraIntersects = new List <Point>();

                foreach (ICurve subPart in subParts)
                {
                    List <Point> iPts = subPart.ILineIntersections(ray, false, tolerance);   // LineIntersection ignores the `false`
                    foreach (Point iPt in iPts)
                    {
                        double signedAngle = direction.SignedAngle(subPart.ITangentAtPoint(iPt, tolerance), p.Normal);
                        if ((subPart.IStartPoint().SquareDistance(iPt) <= sqTol)) // Keep intersections from beeing counted twice?
                        {
                            if (signedAngle >= -Tolerance.Angle)                  // tangent is to the left of the direction
                            {
                                intersects.Add(iPt);
                            }
                            else
                            {
                                extraIntersects.Add(iPt);
                            }
                        }
                        else if ((subPart.IEndPoint().SquareDistance(iPt) <= sqTol))
                        {
                            if (signedAngle <= Tolerance.Angle)     // tangent is to the rigth of the direction
                            {
                                intersects.Add(iPt);
                            }
                            else
                            {
                                extraIntersects.Add(iPt);
                            }
                        }
                        else if (Math.Abs(signedAngle) <= Tolerance.Angle)  // They are parallel
                        {
                            extraIntersects.Add(iPt);
                        }
                        else
                        {
                            intersects.Add(iPt);
                        }
                    }
                }

                if (intersects.Count == 0)  // did not intersect the curve (strange)
                {
                    return(false);
                }

                if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol)) // if any intersection point is the point
                {
                    if (acceptOnEdge)
                    {
                        continue;
                    }
                    else
                    {
                        return(false);
                    }
                }

                intersects.Add(pPt);
                intersects = intersects.SortCollinear(tolerance);
                for (int j = 0; j < intersects.Count; j++)  // Even indecies on a colinerar sort is outside the region
                {
                    if (j % 2 == 0 && intersects[j] == pPt)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Beispiel #2
0
        /***************************************************/

        public static bool IsContaining(this PolyCurve curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance)
        {
            // Todo:
            // - to be replaced with a general method for a nurbs curve?
            // - this is very problematic for edge cases (cutting line going through a sharp corner, to be superseded?

            if (curve.IsClosed(tolerance))
            {
                Plane  p     = curve.FitPlane(tolerance);
                double sqTol = tolerance * tolerance;

                if (p == null)
                {
                    if (acceptOnEdge)
                    {
                        foreach (Point pt in points)
                        {
                            if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol)
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    List <ICurve> subParts       = curve.SubParts();
                    List <Vector> edgeDirections = subParts.Where(s => s is Line).Select(c => (c as Line).Direction()).ToList();
                    foreach (Point pt in points)
                    {
                        Point pPt = pt.Project(p);
                        if (pPt.SquareDistance(pt) <= sqTol)
                        {
                            Point  end       = p.Origin;
                            Vector direction = (end - pPt).Normalise();
                            while (direction.SquareLength() <= sqTol || edgeDirections.Any(e => 1 - Math.Abs(e.DotProduct(direction)) <= Tolerance.Angle))
                            {
                                end       = end.Translate(Create.RandomVectorInPlane(p, true));
                                direction = (end - pPt).Normalise();
                            }

                            Line ray = new Line {
                                Start = pPt, End = end
                            };
                            ray.Infinite = true;
                            List <Point> intersects      = new List <Point>();
                            List <Point> extraIntersects = new List <Point>();

                            foreach (ICurve subPart in subParts)
                            {
                                List <Point> iPts = subPart.ILineIntersections(ray, false, tolerance);
                                foreach (Point iPt in iPts)
                                {
                                    double signedAngle = direction.SignedAngle(subPart.ITangentAtPoint(iPt, tolerance), p.Normal);
                                    if ((subPart.IStartPoint().SquareDistance(iPt) <= sqTol))
                                    {
                                        if (signedAngle >= -Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else if ((subPart.IEndPoint().SquareDistance(iPt) <= sqTol))
                                    {
                                        if (signedAngle <= Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else if (Math.Abs(signedAngle) <= Tolerance.Angle)
                                    {
                                        extraIntersects.Add(iPt);
                                    }
                                    else
                                    {
                                        intersects.Add(iPt);
                                    }
                                }
                            }

                            if (intersects.Count == 0)
                            {
                                return(false);
                            }

                            if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol))
                            {
                                if (acceptOnEdge)
                                {
                                    continue;
                                }
                                else
                                {
                                    return(false);
                                }
                            }

                            intersects.Add(pPt);
                            intersects = intersects.SortCollinear(tolerance);
                            for (int j = 0; j < intersects.Count; j++)
                            {
                                if (j % 2 == 0 && intersects[j] == pPt)
                                {
                                    return(false);
                                }
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            }
            return(false);
        }
        /***************************************************/

        public static bool IsContaining(this Polyline curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance)
        {
            // Todo:
            // check boundingBox/proximity at the beginning!
            // project to 2D & rewrite methods to 2D to improve performance
            // - to be replaced with a general method for a nurbs curve?
            // - could be done with a ray instead of an infinite line!

            if (curve.IsClosed(tolerance))
            {
                Plane  p     = curve.FitPlane(tolerance);
                double sqTol = tolerance * tolerance;

                if (p == null)
                {
                    if (acceptOnEdge)
                    {
                        foreach (Point pt in points)
                        {
                            if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol)
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    List <Line>   subParts       = curve.SubParts();
                    List <Vector> edgeDirections = subParts.Select(c => c.Direction()).ToList();
                    foreach (Point pt in points)
                    {
                        Point pPt = pt.Project(p);
                        if (pPt.SquareDistance(pt) <= sqTol)
                        {
                            Point  end       = p.Origin;
                            Vector direction = (end - pPt).Normalise();
                            while (direction.SquareLength() <= 0.5 || edgeDirections.Any(e => 1 - Math.Abs(e.DotProduct(direction)) <= Tolerance.Angle))
                            {
                                end       = end.Translate(Create.RandomVectorInPlane(p, true));
                                direction = (end - pPt).Normalise();
                            }

                            Line ray = new Line {
                                Start = pPt, End = end
                            };
                            ray.Infinite = true;
                            List <Point> intersects      = new List <Point>();
                            List <Point> extraIntersects = new List <Point>();

                            Func <double, double, double> ToFactor = (t, n) => (1 - t * t) / (1 - n * n);

                            Line   current       = subParts[1];
                            double prevTolFactor = ToFactor(subParts[0].Direction().DotProduct(direction), current.Direction().DotProduct(direction));

                            for (int i = 1; i < subParts.Count + 1; i++)
                            {
                                Line next = subParts[(i + 1) % subParts.Count];

                                double nextTolFactor = ToFactor(next.Direction().DotProduct(direction), current.Direction().DotProduct(direction));

                                Point iPt = current.LineIntersection(ray, false, tolerance);
                                if (iPt != null)
                                {
                                    double signedAngle = direction.SignedAngle(current.Direction(), p.Normal);
                                    if ((current.Start.SquareDistance(iPt) <= sqTol * prevTolFactor)) // Will we get a point on the previous line
                                    {
                                        if (signedAngle > Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else if ((current.End.SquareDistance(iPt) <= sqTol * nextTolFactor))  // Will we get a point on the next line
                                    {
                                        if (signedAngle < -Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else
                                    {
                                        intersects.Add(iPt);
                                    }
                                }
                                prevTolFactor = 1 / nextTolFactor;
                                current       = next;
                            }

                            if (intersects.Count == 0)
                            {
                                return(false);
                            }

                            if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol))
                            {
                                if (acceptOnEdge)
                                {
                                    continue;
                                }
                                else
                                {
                                    return(false);
                                }
                            }

                            intersects.Add(pPt);
                            intersects = intersects.SortCollinear(tolerance);
                            for (int j = 0; j < intersects.Count; j++)
                            {
                                if (j % 2 == 0 && intersects[j] == pPt)
                                {
                                    return(false);
                                }
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            }
            return(false);
        }
Beispiel #4
0
        /***************************************************/

        public static bool IsContaining(this Polyline curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance)
        {
            // Todo:
            // check boundingBox/proximity at the beginning!
            // project to 2D & rewrite methods to 2D to improve performance
            // - to be replaced with a general method for a nurbs curve?
            // - could be done with a ray instead of an infinite line!

            if (curve.IsClosed(tolerance))
            {
                Plane  p     = curve.FitPlane(tolerance);
                double sqTol = tolerance * tolerance;

                if (p == null)
                {
                    if (acceptOnEdge)
                    {
                        foreach (Point pt in points)
                        {
                            if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol)
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }

                else
                {
                    foreach (Point pt in points)
                    {
                        Point pPt = pt.Project(p);
                        if (pPt.SquareDistance(pt) <= sqTol)
                        {
                            Point end = p.Origin;
                            if (pPt.SquareDistance(end) <= sqTol)
                            {
                                end = end.Translate(Create.RandomVectorInPlane(p, true));
                            }

                            Line ray = new Line {
                                Start = pPt, End = end
                            };
                            ray.Infinite = true;
                            Vector       rayDir          = ray.Direction();
                            List <Line>  subParts        = curve.SubParts();
                            List <Point> intersects      = new List <Point>();
                            List <Point> extraIntersects = new List <Point>();

                            foreach (Line subPart in subParts)
                            {
                                Point iPt = subPart.LineIntersection(ray, false, tolerance);
                                if (iPt != null)
                                {
                                    double signedAngle = rayDir.SignedAngle(subPart.Direction(), p.Normal);
                                    if ((subPart.Start.SquareDistance(iPt) <= sqTol))
                                    {
                                        if (signedAngle > Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else if ((subPart.End.SquareDistance(iPt) <= sqTol))
                                    {
                                        if (signedAngle < -Tolerance.Angle)
                                        {
                                            intersects.Add(iPt);
                                        }
                                        else
                                        {
                                            extraIntersects.Add(iPt);
                                        }
                                    }
                                    else
                                    {
                                        intersects.Add(iPt);
                                    }
                                }
                            }

                            if (intersects.Count == 0)
                            {
                                return(false);
                            }
                            if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol))
                            {
                                if (acceptOnEdge)
                                {
                                    continue;
                                }
                                else
                                {
                                    return(false);
                                }
                            }

                            intersects.Add(pPt);
                            intersects = intersects.SortCollinear(tolerance);
                            for (int j = 0; j < intersects.Count; j++)
                            {
                                if (j % 2 == 0 && intersects[j] == pPt)
                                {
                                    return(false);
                                }
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            }
            return(false);
        }