DefaultStateChartReducer implements StateChartReducer<T> { @Override public void reduce(@NotNull List<Rectangle2D.Float> rectangles, @NotNull List<T> values) { int index = 0, keepIndex = 0; Map<T, Float> occurrenceWidth = new HashMap<>(); while (index < rectangles.size()) { T value = values.get(index); Rectangle2D.Float rect = rectangles.get(index); if (Math.floor(rect.x) < Math.floor(rect.x + rect.width)) { rectangles.set(keepIndex, rect); values.set(keepIndex, value); ++keepIndex; ++index; continue; } occurrenceWidth.clear(); float pixelStart = (float)Math.floor(rect.x); float pixelEnd = pixelStart + 1.0f; float minX = rect.x; float maxX = Float.MIN_VALUE; float minY = rect.y; float height = rect.height; while (index < rectangles.size()) { rect = rectangles.get(index); if (rect.x < pixelStart || rect.x > pixelEnd || rect.x + rect.width > pixelEnd) { break; } maxX = rect.x + rect.width; value = values.get(index); Float width = occurrenceWidth.get(value); occurrenceWidth.put(value, (width == null ? 0 : width) + rect.width); ++index; } T mostOccurred = null; float mostOccurredWidth = -1; for (Map.Entry<T, Float> entry : occurrenceWidth.entrySet()) { if (entry.getValue() > mostOccurredWidth) { mostOccurredWidth = entry.getValue().floatValue(); mostOccurred = entry.getKey(); } } if (mostOccurred != null) { values.set(keepIndex, mostOccurred); rectangles.set(keepIndex, new Rectangle2D.Float(minX, minY, maxX - minX, height)); ++keepIndex; } } rectangles.subList(keepIndex, rectangles.size()).clear(); values.subList(keepIndex, values.size()).clear(); }  @Override void reduce(@NotNull List<Rectangle2D.Float> rectangles, @NotNull List<T> values);  }
@Test public void testReduce() { float[][] given = {{0, 0, 5.1f, 10}, {5.1f, 0, 5.3f, 10}, {5.3f, 0, 5.9f, 10}, {5.9f, 0, 6.1f, 10}}; ColorState[] givenValues = {ColorState.BLACK, ColorState.RED, ColorState.YELLOW, ColorState.BLACK}; float[][] expected = {{0, 0, 5.1f, 10}, {5.1f, 0, 5.9f, 10}, {5.9f, 0, 6.1f, 10}}; ColorState[] expectedValues = {ColorState.BLACK, ColorState.YELLOW, ColorState.BLACK}; check(given, givenValues, expected, expectedValues); }