public List<OrderedCanvasIdPair> getSortedNeighborPairs() throws IOException, InterruptedException { LOG.info("getSortedNeighborPairs: entry"); final List<Double> zValues = renderDataClient.getStackZValues(parameters.stack, parameters.minZ, parameters.maxZ); final Map<Double, TileBoundsRTree> zToTreeMap = buildRTrees(zValues); final Set<OrderedCanvasIdPair> existingPairs = getExistingPairs(); final Set<OrderedCanvasIdPair> neighborPairs = new TreeSet<>(); Double z; Double neighborZ; TileBoundsRTree currentZTree; List<TileBoundsRTree> neighborTreeList; Set<OrderedCanvasIdPair> currentNeighborPairs; for (int zIndex = 0; zIndex < zValues.size(); zIndex++) { z = zValues.get(zIndex); currentZTree = zToTreeMap.get(z); neighborTreeList = new ArrayList<>(); final double maxNeighborZ = Math.min(parameters.maxZ, z + parameters.zNeighborDistance); for (int neighborZIndex = zIndex + 1; neighborZIndex < zValues.size(); neighborZIndex++) { neighborZ = zValues.get(neighborZIndex); if (neighborZ > maxNeighborZ) { break; } neighborTreeList.add(zToTreeMap.get(neighborZ)); } currentNeighborPairs = currentZTree.getCircleNeighbors( neighborTreeList, parameters.xyNeighborFactor, parameters.excludeCornerNeighbors, parameters.excludeSameLayerNeighbors, parameters.excludeSameSectionNeighbors); if (existingPairs.size() > 0) { final int beforeSize = currentNeighborPairs.size(); currentNeighborPairs.removeAll(existingPairs); final int afterSize = currentNeighborPairs.size(); LOG.info("removed {} existing pairs for z {}", (beforeSize - afterSize), z); } neighborPairs.addAll(currentNeighborPairs); } LOG.info("getSortedNeighborPairs: exit, returning {} pairs", neighborPairs.size()); return new ArrayList<>(neighborPairs); }