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)); }
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)); }
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); }
public Polygon2 <T> ConstructPolygon(Envelope2 <T> bounds) { if (bounds == null) { return(null); } return(ConstructRing(bounds)); }
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)); }
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); }
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)); }
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); }