docs: void inPlaceNodeRemove(int removeNodeCount) {
          // Prepare edge-update of nodes which are connected to deleted nodes
          int toMoveNodes = getNodes();
          int itemsToMove = 0;
  
          // sorted map when we access it via keyAt and valueAt - see below!
          final SparseIntIntArray oldToNewMap = new SparseIntIntArray(removeNodeCount);
          GHBitSet toRemoveSet = new GHBitSetImpl(removeNodeCount);
          removedNodes.copyTo(toRemoveSet);
  
          if (removeNodeCount > getNodes() / 2.0)
              LoggerFactory.getLogger(getClass()).warn("More than a half of the network should be removed!? "
                      + "Nodes:" + getNodes() + ", remove:" + removeNodeCount);
  
          EdgeExplorer delExplorer = createEdgeExplorer();
          // create map of old node ids pointing to new ids
          for (int removeNode = removedNodes.next(0);
               removeNode >= 0;
               removeNode = removedNodes.next(removeNode + 1)) {
              EdgeIterator delEdgesIter = delExplorer.setBaseNode(removeNode);
              while (delEdgesIter.next()) {
                  toRemoveSet.add(delEdgesIter.getAdjNode());
              }
  
              toMoveNodes--;
              // move only nodes that are not removed
              for (; toMoveNodes >= 0; toMoveNodes--) {
                  if (!removedNodes.contains(toMoveNodes))
                      break;
              }
  
              if (toMoveNodes >= removeNode)
                  oldToNewMap.put(toMoveNodes, removeNode);
  
              itemsToMove++;
          }
  
          EdgeIterable adjNodesToDelIter = (EdgeIterable) createEdgeExplorer();
          // now similar process to disconnectEdges but only for specific nodes
          // all deleted nodes could be connected to existing. remove the connections
          for (int removeNode = toRemoveSet.next(0);
               removeNode >= 0;
               removeNode = toRemoveSet.next(removeNode + 1)) {
              // remove all edges connected to the deleted nodes
              adjNodesToDelIter.setBaseNode(removeNode);
              long prevPointer = EdgeIterator.NO_EDGE;
              while (adjNodesToDelIter.next()) {
                  int nodeId = adjNodesToDelIter.getAdjNode();
                  // already invalidated
                  if (!EdgeAccess.isInvalidNodeB(nodeId) && removedNodes.contains(nodeId)) {
                      int edgeToRemove = adjNodesToDelIter.getEdge();
                      long edgeToRemovePointer = edgeAccess.toPointer(edgeToRemove);
                      edgeAccess.internalEdgeDisconnect(edgeToRemove, prevPointer, removeNode);
                      edgeAccess.invalidateEdge(edgeToRemovePointer);
                  } else {
                      prevPointer = adjNodesToDelIter.edgePointer;
                  }
              }
          }
  
          GHBitSet toMoveSet = new GHBitSetImpl(removeNodeCount * 3);
          EdgeExplorer movedEdgeExplorer = createEdgeExplorer();
          // marks connected nodes to rewrite the edges
          for (int i = 0; i < itemsToMove; i++) {
              int oldI = oldToNewMap.keyAt(i);
              EdgeIterator movedEdgeIter = movedEdgeExplorer.setBaseNode(oldI);
              while (movedEdgeIter.next()) {
                  int nodeId = movedEdgeIter.getAdjNode();
                  if (EdgeAccess.isInvalidNodeB(nodeId))
                      continue;
  
                  if (removedNodes.contains(nodeId))
                      throw new IllegalStateException("shouldn't happen as the edge to the node "
                              + nodeId + " should be already deleted. " + oldI);
  
                  toMoveSet.add(nodeId);
              }
          }
  
          // move nodes into deleted nodes
          for (int i = 0; i < itemsToMove; i++) {
              int oldI = oldToNewMap.keyAt(i);
              int newI = oldToNewMap.valueAt(i);
              long newOffset = (long) newI * nodeEntryBytes;
              long oldOffset = (long) oldI * nodeEntryBytes;
              for (long j = 0; j < nodeEntryBytes; j += 4) {
                  nodes.setInt(newOffset + j, nodes.getInt(oldOffset + j));
              }
          }
  
          // *rewrites* all edges connected to moved nodes
          // go through all edges and pick the necessary <- this is easier to implement than
          // a more efficient (?) breadth-first search
          EdgeIterator iter = getAllEdges();
          while (iter.next()) {
              int nodeA = iter.getBaseNode();
              int nodeB = iter.getAdjNode();
              if (!toMoveSet.contains(nodeA) && !toMoveSet.contains(nodeB))
                  continue;
  
              // now overwrite exiting edge with new node ids
              int updatedA = oldToNewMap.get(nodeA);
              if (updatedA < 0)
                  updatedA = nodeA;
  
              int updatedB = oldToNewMap.get(nodeB);
              if (updatedB < 0)
                  updatedB = nodeB;
  
              // no need to rewrite flags or other properties as they are independent of the node order unlike in <= 0.11
              int edgeId = iter.getEdge();
              long edgePointer = edgeAccess.toPointer(edgeId);
              int linkA = edgeAccess.getLinkA(edgePointer);
              int linkB = edgeAccess.getLinkB(edgePointer);
              edgeAccess.writeEdge(edgeId, updatedA, updatedB, linkA, linkB);
          }
  
          if (removeNodeCount >= nodeCount)
              throw new IllegalStateException("graph is empty after in-place removal but was " + removeNodeCount);
  
          // clear N_EDGE_REF
          initNodeRefs(((long) nodeCount - removeNodeCount) * nodeEntryBytes, (long) nodeCount * nodeEntryBytes);
  
          // we do not remove the invalid edges => edgeCount stays the same!
          nodeCount -= removeNodeCount;
  
          // health check
          if (isTestingEnabled()) {
              EdgeExplorer explorer = createEdgeExplorer();
              iter = getAllEdges();
              while (iter.next()) {
                  int base = iter.getBaseNode();
                  int adj = iter.getAdjNode();
                  String str = iter.getEdge()
                          + ", r.contains(" + base + "):" + removedNodes.contains(base)
                          + ", r.contains(" + adj + "):" + removedNodes.contains(adj)
                          + ", tr.contains(" + base + "):" + toRemoveSet.contains(base)
                          + ", tr.contains(" + adj + "):" + toRemoveSet.contains(adj)
                          + ", base:" + base + ", adj:" + adj + ", nodeCount:" + nodeCount;
                  if (adj >= nodeCount)
                      throw new RuntimeException("Adj.node problem with edge " + str);
  
                  if (base >= nodeCount)
                      throw new RuntimeException("Base node problem with edge " + str);
  
                  try {
                      explorer.setBaseNode(adj).toString();
                  } catch (Exception ex) {
                      org.slf4j.LoggerFactory.getLogger(getClass()).error("adj:" + adj);
                  }
                  try {
                      explorer.setBaseNode(base).toString();
                  } catch (Exception ex) {
                      org.slf4j.LoggerFactory.getLogger(getClass()).error("base:" + base);
                  }
              }
              // access last node -> no error
              explorer.setBaseNode(nodeCount - 1).toString();
          }
          removedNodes = null;
      }