public void Add(Segment s) { // j iterates through the openPolygon chains. for (int j = 0; j < openPolygons.Count; j++) { PointChain chain = openPolygons [j]; if (!chain.LinkSegment(s)) { continue; } if (chain.closed) { if (chain.pointList.Count == 2) { // We tried linking the same segment (but flipped end and start) to // a chain. (i.e. chain was <p0, p1>, we tried linking Segment(p1, p0) // so the chain was closed illegally. chain.closed = false; return; } closedPolygons.Add(chain); openPolygons.RemoveAt(j); return; } int k = openPolygons.Count; for (int i = j + 1; i < k; i++) { // Try to connect this open link to the rest of the chains. // We won't be able to connect this to any of the chains preceding this one // because we know that linkSegment failed on those. if (chain.LinkPointChain(openPolygons [i])) { openPolygons.RemoveAt(i); return; } } return; } PointChain newChain = new PointChain(s); openPolygons.Add(newChain); }
/// <summary> /// Since polygons from countries and cells are not perfectly aligned in all cases, this method will take the largest contour and assume this is the resulting polygon /// (even if it's not closed...) /// </summary> public Polygon ToPolygonFromLargestLineStrip() { // Check for empty result if ((closedPolygons.Count == 0 || (closedPolygons.Count == 1 && closedPolygons[0].pointList.Count == 0)) && (openPolygons.Count == 0 || (openPolygons.Count == 1 && openPolygons[0].pointList.Count == 0))) { return(null); } // Get the largest contour (open or closed) int maxPoints = -1; PointChain largestPointChain = null; foreach (PointChain pointChain in closedPolygons) { if (pointChain.pointList.Count > maxPoints) { maxPoints = pointChain.pointList.Count; largestPointChain = pointChain; } } foreach (PointChain pointChain in openPolygons) { if (pointChain.pointList.Count > maxPoints) { maxPoints = pointChain.pointList.Count; largestPointChain = pointChain; } } // ... and create a new polygon of that if (maxPoints < 0) { return(null); } Polygon polygon = new Polygon(); Contour c = new Contour(); c.AddRange(largestPointChain.pointList); polygon.AddContour(c); FixOrientation(polygon); return(polygon); }
// Links another pointChain onto this point chain. public bool LinkPointChain(PointChain chain) { Point firstPoint = pointList[0]; Point lastPoint = pointList[pointList.Count - 1]; Point chainFront = chain.pointList[0]; Point chainBack = chain.pointList[chain.pointList.Count - 1]; if (Point.EqualsBoth(chainFront, lastPoint)) { List <Point> temp = new List <Point>(chain.pointList.Count); for (int k = 1; k < chain.pointList.Count; k++) { temp.Add(chain.pointList[k]); } // temp.RemoveAt(0); pointList.AddRange(temp); // if (pointList.Count>maxLen) { // maxLen = pointList.Count; // Debug.Log (maxLen); // } // chain.pointList.Clear(); return(true); } if (Point.EqualsBoth(chainBack, firstPoint)) { // pointList.RemoveAt (0); // Remove the first element, and join this list to chain.pointList. List <Point> temp = new List <Point>(chain.pointList); temp.Capacity += pointList.Count; for (int k = 1; k < pointList.Count; k++) { temp.Add(pointList[k]); } // temp.AddRange(pointList); pointList = temp; // if (pointList.Count>maxLen) { // maxLen = pointList.Count; // Debug.Log (maxLen); // } // chain.pointList.Clear(); return(true); } if (Point.EqualsBoth(chainFront, firstPoint)) { // pointList.RemoveAt (0); // Remove the first element, and join to reversed chain.pointList List <Point> temp = new List <Point>(chain.pointList); temp.Reverse(); temp.Capacity += pointList.Count; for (int k = 1; k < pointList.Count; k++) { temp.Add(pointList[k]); } // temp.AddRange(pointList); pointList = temp; // if (pointList.Count>maxLen) { // maxLen = pointList.Count; // Debug.Log (maxLen); // } // chain.pointList.Clear(); return(true); } if (Point.EqualsBoth(chainBack, lastPoint)) { pointList.RemoveAt(pointList.Count - 1); List <Point> temp = new List <Point>(chain.pointList); temp.Reverse(); pointList.AddRange(temp); // if (pointList.Count>maxLen) { // maxLen = pointList.Count; // Debug.Log (maxLen); // } // chain.pointList.Clear(); return(true); } return(false); }