/// <summary> /// Tries to merge ways to closed polygons. The ordering of waynodes is preserved during the merge process. /// </summary> /// <param name="ways"> /// An array of ways that should be merged. Ways may be given in any order and may already be closed. </param> internal virtual void mergePolygons(TDWay[] ways) { this.polygons = new List <>(); this.dangling = new List <>(); this.illegal = new List <>(); Deque <TDWay> ungroupedWays = new ArrayDeque <TDWay>(); // initially all ways are ungrouped foreach (TDWay tdWay in ways) { // reset reversed flag, may already be set when way is part of another relation tdWay.ReversedInRelation = false; // first extract all way that are closed polygons in their own right if (isClosedPolygon(tdWay)) { if (tdWay.WayNodes.length < MIN_NODES_POLYGON) { this.illegal.Add(tdWay); } else { Deque <TDWay> cluster = new ArrayDeque <TDWay>(); cluster.add(tdWay); this.polygons.Add(cluster); } } else { ungroupedWays.add(tdWay); } } // all ways have been polygons, nice! if (ungroupedWays.Empty) { return; } if (ungroupedWays.size() == 1) { this.dangling.Add(ungroupedWays.First); return; } bool startNewPolygon = true; while (true) { bool merge = false; if (startNewPolygon) { // we start a new polygon either during first iteration or when // the previous iterations merged ways to a closed polygon and there // are still ungrouped ways left Deque <TDWay> cluster = new ArrayDeque <TDWay>(); // get the first way of the yet ungrouped ways and form a new group cluster.add(ungroupedWays.removeFirst()); this.polygons.Add(cluster); startNewPolygon = false; } // test if we can merge the current polygon with an ungrouped way IEnumerator <TDWay> it = ungroupedWays.GetEnumerator(); while (it.MoveNext()) { TDWay current = it.Current; Deque <TDWay> currentPolygonSegments = this.polygons[this.polygons.Count - 1]; // first way in current polygon TDWay c1Start = currentPolygonSegments.First; // last way in current polygon TDWay c1End = currentPolygonSegments.Last; long startFirst = c1Start.ReversedInRelation ? c1Start.WayNodes[c1Start.WayNodes.length - 1].Id : c1Start.WayNodes[0].Id; long endLast = c1End.ReversedInRelation ? c1End.WayNodes[0].Id : c1End.WayNodes[c1End.WayNodes.length - 1].Id; long currentFirst = current.WayNodes[0].Id; long currentLast = current.WayNodes[current.WayNodes.length - 1].Id; // current way end connects to the start of the current polygon (correct direction) if (startFirst == currentLast) { merge = true; //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: it.remove(); // add way to start of current polygon currentPolygonSegments.offerFirst(current); } // // current way start connects to the start of the current polygon (reversed // direction) else if (startFirst == currentFirst) { current.ReversedInRelation = true; merge = true; //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: it.remove(); currentPolygonSegments.offerFirst(current); } // current way start connects to the end of the current polygon (correct direction) else if (endLast == currentFirst) { merge = true; //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: it.remove(); // add way to end of current polygon currentPolygonSegments.offerLast(current); } // // current way end connects to the end of the current polygon (reversed direction) else if (endLast == currentLast) { current.ReversedInRelation = true; merge = true; //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: it.remove(); // add way to end of current polygon currentPolygonSegments.offerLast(current); } } Deque <TDWay> currentCluster = this.polygons[this.polygons.Count - 1]; bool closed = isClosedPolygon(currentCluster); // not a closed polygon and no more ways to merge if (!closed) { if (ungroupedWays.Empty || !merge) { ((List <TDWay>) this.dangling).AddRange(this.polygons[this.polygons.Count - 1]); // may be a non operation when ungrouped is empty ((List <TDWay>) this.dangling).AddRange(ungroupedWays); this.polygons.Remove(this.polygons.Count - 1); return; } } else { // built a closed polygon and no more ways left --> we are finished if (ungroupedWays.Empty) { return; } startNewPolygon = true; } // if we are here, the polygon is not yet closed, but there are also some ungrouped ways // which may be merge-able in the next iteration } }