private static void FillAreas(Relation relation, List <CoordinateSequence> rings, List <Area> areas) { while (rings.Any()) { // find an outer ring CoordinateSequence outer = null; foreach (CoordinateSequence candidate in rings) { bool containedInOtherRings = false; foreach (CoordinateSequence other in rings) { if (other != candidate && other.ContainsRing(candidate)) { containedInOtherRings = true; break; } } if (containedInOtherRings) { continue; } outer = candidate; break; } // find inner rings of that ring var inners = new List <CoordinateSequence>(); foreach (CoordinateSequence ring in rings) { if (ring != outer && outer.ContainsRing(ring)) { bool containedInOthers = false; foreach (CoordinateSequence other in rings) { if (other != ring && other != outer && other.ContainsRing(ring)) { containedInOthers = true; break; } } if (!containedInOthers) { inners.Add(ring); } } } // create a new area and remove the used rings var holes = new List <List <GeoCoordinate> >(inners.Count); foreach (CoordinateSequence innerRing in inners) { holes.Add(innerRing.Coordinates); } // TODO investigate case of null/empty tags var tags = GetTags(relation, outer); if (tags != null && tags.Any()) { areas.Add(new Area() { Id = outer.Id, Tags = tags.AsReadOnly(), Points = outer.Coordinates, Holes = holes }); } rings.Remove(outer); // remove all innerRings foreach (var nodeSequence in inners) { rings.Remove(nodeSequence); } } }