docs: void mergePolygons(TDWay[] ways) {
          this.polygons = new ArrayList<>();
          this.dangling = new ArrayList<>();
          this.illegal = new ArrayList<>();
  
          Deque<TDWay> ungroupedWays = new ArrayDeque<>();
  
          // initially all ways are ungrouped
          for (TDWay tdWay : ways) {
              // reset reversed flag, may already be set when way is part of another relation
              tdWay.setReversedInRelation(false);
  
              // first extract all way that are closed polygons in their own right
              if (isClosedPolygon(tdWay)) {
                  if (tdWay.getWayNodes().length < MIN_NODES_POLYGON) {
                      this.illegal.add(tdWay);
                  } else {
                      Deque<TDWay> cluster = new ArrayDeque<>();
                      cluster.add(tdWay);
                      this.polygons.add(cluster);
                  }
              } else {
                  ungroupedWays.add(tdWay);
              }
          }
  
          // all ways have been polygons, nice!
          if (ungroupedWays.isEmpty()) {
              return;
          }
  
          if (ungroupedWays.size() == 1) {
              this.dangling.add(ungroupedWays.getFirst());
              return;
          }
  
          boolean startNewPolygon = true;
  
          while (true) {
              boolean 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<>();
                  // 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
              Iterator<TDWay> it = ungroupedWays.iterator();
              while (it.hasNext()) {
                  TDWay current = it.next();
  
                  Deque<TDWay> currentPolygonSegments = this.polygons.get(this.polygons.size() - 1);
                  // first way in current polygon
                  TDWay c1Start = currentPolygonSegments.getFirst();
                  // last way in current polygon
                  TDWay c1End = currentPolygonSegments.getLast();
  
                  long startFirst = c1Start.isReversedInRelation() ? c1Start.getWayNodes()[c1Start.getWayNodes().length - 1]
                          .getId() : c1Start.getWayNodes()[0].getId();
  
                  long endLast = c1End.isReversedInRelation() ? c1End.getWayNodes()[0].getId()
                          : c1End.getWayNodes()[c1End.getWayNodes().length - 1].getId();
  
                  long currentFirst = current.getWayNodes()[0].getId();
                  long currentLast = current.getWayNodes()[current.getWayNodes().length - 1].getId();
  
                  // current way end connects to the start of the current polygon (correct direction)
                  if (startFirst == currentLast) {
                      merge = true;
                      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.setReversedInRelation(true);
                      merge = true;
                      it.remove();
                      currentPolygonSegments.offerFirst(current);
                  }
                  // current way start connects to the end of the current polygon (correct direction)
                  else if (endLast == currentFirst) {
                      merge = true;
                      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.setReversedInRelation(true);
                      merge = true;
                      it.remove();
                      // add way to end of current polygon
                      currentPolygonSegments.offerLast(current);
                  }
              }
  
              Deque<TDWay> currentCluster = this.polygons.get(this.polygons.size() - 1);
              boolean closed = isClosedPolygon(currentCluster);
              // not a closed polygon and no more ways to merge
              if (!closed) {
                  if (ungroupedWays.isEmpty() || !merge) {
                      this.dangling.addAll(this.polygons.get(this.polygons.size() - 1));
                      // may be a non operation when ungrouped is empty
                      this.dangling.addAll(ungroupedWays);
                      this.polygons.remove(this.polygons.size() - 1);
                      return;
                  }
              } else {
                  // built a closed polygon and no more ways left --> we are finished
                  if (ungroupedWays.isEmpty()) {
                      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
          }
      }