public static Envelope2 <T> EnvelopeFor <T>(Envelope2 <T> env, Coordinate2 <T> p)
            where T : IEquatable <T>, IComparable <T>
        {
            if (env == null || p == null)
            {
                return(null);
            }
            T minX = env.MinX;
            T maxX = env.MaxX;
            T minY = env.MinY;
            T maxY = env.MaxY;

            if (minX.CompareTo(p.X) > 0)
            {
                minX = p.X;
            }
            else if (maxX.CompareTo(p.X) < 0)
            {
                maxX = p.X;
            }
            if (minY.CompareTo(p.Y) > 0)
            {
                minY = p.Y;
            }
            else if (maxY.CompareTo(p.Y) < 0)
            {
                maxY = p.Y;
            }
            return(new Envelope2 <T>(minX, minY, maxX, maxY));
        }
Beispiel #2
0
        public static Envelope2 <T> EnvelopeFor <T>(IGeometry2 <T> a, IGeometry2 <T> b, IGeometry2 <T> c)
            where T : IEquatable <T>, IComparable <T>
        {
            if (a == null)
            {
                if (b == null)
                {
                    if (c == null)
                    {
                        return(null);
                    }
                    return(c.Envelope);
                }
            }
            else if (b == null)
            {
                if (c == null)
                {
                    return(a.Envelope);
                }
                return(EnvelopeFor <T>(a, c));
            }
            else if (c == null)
            {
                return(EnvelopeFor <T>(a, b));
            }

            Envelope2 <T> envCur = a.Envelope;

            envCur = Envelope2 <T> .Bound(envCur, b.Envelope);

            return(Envelope2 <T> .Bound(envCur, c.Envelope));
        }
Beispiel #3
0
        public static Envelope2 <T> EnvelopeFor <T>(IEnumerable <IGeometry2 <T> > shapes)
            where T : IEquatable <T>, IComparable <T>
        {
            if (shapes == null)
            {
                return(null);
            }
            IEnumerator <IGeometry2 <T> > en = shapes.GetEnumerator();
            Envelope2 <T> curEnv             = null;

            if (en.MoveNext())
            {
                IGeometry2 <T> cur = en.Current;
                Envelope2 <T>  env = null;
                if (cur != null)
                {
                    env = cur.Envelope;
                }
                curEnv = env;
                while (en.MoveNext())
                {
                    cur = en.Current;
                    if (cur != null)
                    {
                        env = cur.Envelope;
                    }
                    curEnv = Envelope2 <T> .Bound(curEnv, env);
                }
                return(curEnv);
            }
            return(null);
        }
Beispiel #4
0
 public Polygon2 <T> ConstructPolygon(Envelope2 <T> bounds)
 {
     if (bounds == null)
     {
         return(null);
     }
     return(ConstructRing(bounds));
 }
Beispiel #5
0
 public static Envelope2 <T> EnvelopeFor <T>(Envelope2 <T> env, IGeometry2 <T> p)
     where T : IEquatable <T>, IComparable <T>
 {
     if (env == null)
     {
         if (p == null)
         {
             return(null);
         }
         return(p.Envelope);
     }
     return(Envelope2 <T> .Bound(env, p.Envelope));
 }
Beispiel #6
0
 public Ring2 <T> ConstructRing(Envelope2 <T> bounds)
 {
     if (bounds != null)
     {
         return(new Ring2 <T>(new Point2 <T>[] {
             new Point2 <T>(bounds.MinX, bounds.MinY),
             new Point2 <T>(bounds.MaxX, bounds.MinY),
             new Point2 <T>(bounds.MaxX, bounds.MaxY),
             new Point2 <T>(bounds.MinX, bounds.MaxY),
         }, false, Orientation.Counterclockwise));
     }
     return(null);
 }
Beispiel #7
0
        public static Envelope2 <T> EnvelopeFor <T>(IGeometry2 <T> a, IGeometry2 <T> b)
            where T : IEquatable <T>, IComparable <T>
        {
            if (a == null)
            {
                if (b == null)
                {
                    return(null);
                }
                return(a.Envelope);
            }
            else if (b == null)
            {
                return(a.Envelope);
            }

            return(Envelope2 <T> .Bound(a.Envelope, b.Envelope));
        }
Beispiel #8
0
        public void NestedClassesShouldPopulate()
        {
            Envelope expect = new Envelope
            {
                Item1 = "Howdy"
            };

            //expect.CriticalStops.Any = true;
            expect.CriticalStops.IsPlcCommError   = true;
            expect.CriticalStops.IsMahloCommError = true;

            string   json   = JsonConvert.SerializeObject(expect);
            Envelope actual = JsonConvert.DeserializeObject <Envelope>(json);

            Envelope2 populated = new Envelope2();

            Assert.False(populated.CriticalStops.IsMahloCommError);
            JToken token = JToken.Parse(json);

            token.Populate(populated);
            Assert.True(populated.CriticalStops.IsPlcCommError);
            Assert.True(populated.CriticalStops.IsMahloCommError);
            Assert.Equal("Howdy", populated.Item1);
        }
        public static bool ValidPolygon(Ring2 <double> outer, RingSet2 <double> inner)
        {
            if (outer == null || inner == null)
            {
                return(false);
            }
            HashSet <Ring2 <double> > ringHash = new HashSet <Ring2 <double> >(); //check for the silly condition of multiple references to the same ring

            ringHash.Add(outer);

            Envelope2 <double> outerEnv = outer.Envelope;

            PlanarChainGraph <double> gr = new PlanarChainGraph <double>();

            foreach (Ring2 <double> r in inner.Rings)
            {
                if (!ringHash.Add(r))
                {
                    return(false);                                              //oops, duplicate reference
                }
                if (!Envelope2 <double> .EnvelopeContain(outerEnv, r.Envelope)) //all inner rings must be contained by outer ring, so the envelopes must overlap
                {
                    return(false);
                }
                gr.Add(r);
            }
            ringHash.Clear();
            ringHash = null;

            gr.Add(outer);

            SegmentGroup <double>        activeEdges = new SegmentGroup <double>();
            IEnumerator <Node <double> > points      = gr.GetEnumerator(); //walk through the points in xy sorted order

            Node <double> nd;
            LeakyResizableArray <Edge <double> > localEdges;

            int           localCt;
            int           activeCt = 0;
            Edge <double> localEdge;
            LineSegment2IntersectionResult <double> intersects;
            Point2 <double>      localStart;
            Point2 <double>      localEnd;
            Point2 <double>      activeStart;
            Point2 <double>      activeEnd;
            Point2 <double>      intPoint;
            SimpleGraph <object> touchingRings     = new SimpleGraph <object>();
            HashSet <object>     outerRingTouching = new HashSet <object>();

            //new point event in the moving front
            while (points.MoveNext())
            {
                nd         = points.Current;
                localEdges = nd.Edges; //edges connected to this point

                localCt = (int)localEdges.Count;

                //compute intersections with other edges in the scan area
                for (int i = 0; i < localCt; i++)
                {
                    localEdge  = localEdges.Data[i];
                    localStart = localEdge.Start.Point;
                    localEnd   = localEdge.End.Point;
                    activeCt   = activeEdges.Edges.Count;

                    foreach (Edge <double> activeEdge in activeEdges.Edges)
                    {
                        if (object.ReferenceEquals(localEdge, activeEdge) || object.ReferenceEquals(localEdge.Start.ParentShape, activeEdge.Start.ParentShape))
                        {
                            continue; //exiting edge || 2 edges on same ring
                        }
                        activeStart = activeEdge.Start.Point;
                        activeEnd   = activeEdge.End.Point;

                        intersects = SegmentUtils.ComputeIntersection(localStart, localEnd, activeStart, activeEnd);
                        if (intersects.IntersectionType != LineIntersectionType.NoIntersection)
                        {
                            if (intersects.IntersectionType == LineIntersectionType.CollinearIntersection)
                            {
                                return(false); // there's a full segment of intersection - must be between outer ring and an inner ring
                            }
                            //ok, we have an intersection that is a point between 2 different rings
                            intPoint = intersects.BasePoint;

                            if (object.ReferenceEquals(localEdge.Start.ParentShape, outer)) //localEdge is on the shell
                            {
                                if (PointUtilsDouble.PointsEqual(intPoint, activeStart))
                                {
                                    //only add the shell touching for segment intersection at segment start point - prevents recounting point
                                    if (!PointUtilsDouble.PointsEqual(intPoint, localEnd))
                                    {
                                        if (!outerRingTouching.Add(activeEdge.Start.ParentShape))
                                        {
                                            return(false); //same ring touches outer ring at multiple non-adjacent points
                                        }
                                    }
                                    if (!RingUtils.PointInteriorToRing(outer, activeEnd))
                                    {
                                        return(false); //ring is outside of shell or crosses shell at a vertex
                                    }
                                }
                                else if (PointUtilsDouble.PointsEqual(intPoint, activeEnd))
                                {
                                    //only add the shell touching for segment intersection at segment start point - prevents recounting point
                                    if (!PointUtilsDouble.PointsEqual(intPoint, localEnd))
                                    {
                                        if (!outerRingTouching.Add(activeEdge.Start.ParentShape))
                                        {
                                            return(false); //same ring touches outer ring at multiple non-adjacent points
                                        }
                                    }
                                    if (!RingUtils.PointInteriorToRing(outer, activeStart))
                                    {
                                        return(false); //ring is outside of shell or crosses shell at a vertex
                                    }
                                }
                                else
                                {
                                    return(false); //we have a mid-segment intersection between the outer ring and an inner ring
                                }
                            }
                            else if (object.ReferenceEquals(activeEdge.Start.ParentShape, outer)) //activeEdge is on the shell
                            {
                                if (PointUtilsDouble.PointsEqual(intPoint, localStart))
                                {
                                    //only add the shell touching for segment intersection at segment start point - prevents recounting point
                                    if (!PointUtilsDouble.PointsEqual(intPoint, activeEnd))
                                    {
                                        if (!outerRingTouching.Add(localEdge.Start.ParentShape))
                                        {
                                            return(false); //same ring touches outer ring at multiple non-adjacent points
                                        }
                                    }
                                    if (!RingUtils.PointInteriorToRing(outer, localEnd))
                                    {
                                        return(false); //ring is outside of shell or crosses shell at a vertex
                                    }
                                }
                                else if (PointUtilsDouble.PointsEqual(intPoint, localEnd))
                                {
                                    //only add the shell touching for segment intersection at segment start point - prevents recounting point
                                    if (!PointUtilsDouble.PointsEqual(intPoint, activeEnd))
                                    {
                                        if (!outerRingTouching.Add(localEdge.Start.ParentShape))
                                        {
                                            return(false); //same ring touches outer ring at multiple non-adjacent points
                                        }
                                    }
                                    if (!RingUtils.PointInteriorToRing(outer, localStart))
                                    {
                                        return(false); //ring is outside of shell or crosses shell at a vertex
                                    }
                                }
                                else
                                {
                                    return(false); //we have a mid-segment intersection between the outer ring and an inner ring
                                }
                            }
                            else //both are on inner rings
                            {
                                //since the ringset is valid, we just need to map the connectivity of rings
                                if (!touchingRings.Contains(localEdge.Start.ParentShape))
                                {
                                    touchingRings.AddNode(localEdge.Start.ParentShape);
                                }
                                if (!touchingRings.Contains(activeEdge.Start.ParentShape))
                                {
                                    touchingRings.AddNode(activeEdge.Start.ParentShape);
                                }
                                touchingRings.AddEdge(localEdge.Start.ParentShape, activeEdge.Start.ParentShape);
                            }
                        } //end !nointersection
                    }     //end foreach
                }         //end for

                //remove all exiting segments and add all starting segments
                //Action gets called exactly twice per edge -- once to add it, once to remove it
                for (int i = 0; i < localCt; i++)
                {
                    activeEdges.Action(localEdges.Data[i]);
                }
            }

            //we now know all the rings of the ringset are "legally" connected wrt the shell -- but --
            //inner rings may be adjacent to both the shell and other inner rings to form a "path" cutting the shell
            //any ring COULD be outside the shell -- we did already do the quick envelope check, so just do singular point-in-ring checks

            //shell cutting test (quick)
            object[] shellTouchers = outerRingTouching.ToArray();
            for (int i = shellTouchers.Length - 1; i > 0; i--)
            {
                object adjacentRingA = shellTouchers[i];
                if (touchingRings.Contains(adjacentRingA))
                {
                    for (int j = 0; j < i; j++)
                    {
                        object adjacentRingB = shellTouchers[j];
                        if (touchingRings.Contains(adjacentRingB))
                        {
                            if (HasPath(adjacentRingA, adjacentRingB, touchingRings))
                            {
                                return(false); //path exists between shell touching inner rings
                            }
                        }
                    }
                }
            }

            //ring inside shell testing
            foreach (Ring2 <double> innerR in inner.Rings)
            {
                if (!(RingUtils.PointInteriorToRing(outer, innerR.Points[0]) || RingUtils.PointInteriorToRing(outer, innerR.Points[1]))) //at least one of 2 adjacent points must be interior
                {
                    return(false);
                }
            }

            return(true);
        }