DefaultHTreeChartReducer implements HTreeChartReducer<N> { @Override public void reduce(@NotNull List<Rectangle2D.Float> rectangles, @NotNull List<N> nodes) { assert nodes.size() == rectangles.size(); int n = nodes.size(); int index = 0; int keepIndex = 0; while (index < n) { Rectangle2D.Float rect = rectangles.get(index); N node = nodes.get(index); if (Math.floor(rect.getMinX()) < Math.floor(rect.getMaxX())) { rectangles.set(keepIndex, rect); nodes.set(keepIndex, node); ++keepIndex; ++index; continue; } int pixel = (int)Math.floor(rect.getMaxX()); int curDepth = node.getDepth(); N keepNode = node; Rectangle2D.Float keepRect = rect; while (index < n) { rect = rectangles.get(index); node = nodes.get(index); if (node.getDepth() != curDepth || Math.floor(rect.getMaxX()) != pixel) { break; } keepRect.width = (float)(rect.getMaxX() - keepRect.getMinX()); ++index; } rectangles.set(keepIndex, keepRect); nodes.set(keepIndex, keepNode); ++keepIndex; } rectangles.subList(keepIndex, rectangles.size()).clear(); nodes.subList(keepIndex, nodes.size()).clear(); }  @Override void reduce(@NotNull List<Rectangle2D.Float> rectangles, @NotNull List<N> nodes);  }
@Test public void testReducer() { List<Rectangle2D.Float> expectedRectangles = Arrays.asList( new Rectangle2D.Float(0, 0, 10, 5), new Rectangle2D.Float(0, 5, 5, 5), new Rectangle2D.Float(6, 5, 4, 5), new Rectangle2D.Float(0, 10, 0.9f, 5), new Rectangle2D.Float(2.1f, 10, 0.3f, 5), new Rectangle2D.Float(7.9f, 10, 0.1f, 5) ); List<String> expectedNodes = Arrays.asList("A", "B", "C", "D", "F", "H"); HTreeChartReducer<DefaultHNode<String>> reducer = new DefaultHTreeChartReducer<>(); List<DefaultHNode<String>> nodes = new ArrayList<>(); List<Rectangle2D.Float> rectangles = new ArrayList<>(); addNode("A", 0, 10, 0, nodes, rectangles); addNode("B", 0, 5, 1, nodes, rectangles); addNode("C", 6, 10, 1, nodes, rectangles); addNode("D", 0, 0.5f, 2, nodes, rectangles); addNode("E", 0.7f, 0.9f, 2, nodes, rectangles); addNode("F", 2.1f, 2.2f, 2, nodes, rectangles); addNode("G", 2.2f, 2.4f, 2, nodes, rectangles); addNode("H", 7.9f, 8.0f, 2, nodes, rectangles); reducer.reduce(rectangles, nodes); checkRectanglesEqual(expectedRectangles, rectangles); assertEquals(expectedNodes.size(), nodes.size()); for (int i = 0; i < nodes.size(); ++i) { assertEquals(expectedNodes.get(i), nodes.get(i).getData()); } }