DefaultLineChartReducer implements LineChartReducer { @NotNull @Override public Path2D reducePath(@NotNull Path2D path, @NotNull LineConfig config) { if (path.getCurrentPoint() == null) { return path; } Path2D resultPath = new Path2D.Float(); float[] coords = new float[PATH_ITERATOR_COORDS_COUNT]; float pixel = -1; float minX = -1, minY = -1; float maxX = -1, maxY = -1; float curX = -1, curY = -1; int minIndex = -1, maxIndex = -1; int curIndex = 0; PathIterator iterator = path.getPathIterator(null); while (!iterator.isDone()) { int segType = iterator.currentSegment(coords); assert segType == PathIterator.SEG_MOVETO || segType == PathIterator.SEG_LINETO; float previousX = curX; float previousY = curY; curX = coords[0]; curY = coords[1]; if (curIndex > 0 && curX < previousX) { break; } if (curIndex == 0 || curX >= pixel) { if (curIndex > 0) { addMinMaxPoints(resultPath, config, minIndex, minX, minY, maxIndex, maxX, maxY); addToResultPath(resultPath, config, previousX, previousY); } pixel = (float)Math.floor(curX) + 1; minX = maxX = curX; minY = maxY = curY; minIndex = maxIndex = curIndex; addToResultPath(resultPath, config, curX, curY); } else { if (minY > curY) { minIndex = curIndex; minX = curX; minY = curY; } if (maxY <= curY) { maxIndex = curIndex; maxX = curX; maxY = curY; } } iterator.next(); curIndex++; } addMinMaxPoints(resultPath, config, minIndex, minX, minY, maxIndex, maxX, maxY); addToResultPath(resultPath, config, curX, curY); if (config.isStepped()) { if (resultPath.getCurrentPoint() == null || equals((float)resultPath.getCurrentPoint().getY(), curY)) { addToPath(resultPath, curX, curY); } } return resultPath; }  @Override List<SeriesData<Long>> reduceData(@NotNull List<SeriesData<Long>> dataList, @NotNull LineConfig config); @NotNull @Override Path2D reducePath(@NotNull Path2D path, @NotNull LineConfig config);  }
@Test public void simpleReducePath() { float[][] given = {{0, 0}, {0.1f, 1}, {0.2f, 6}, {0.3f, 4}, {1, 2}, {1.1f, 5}}; float[][] expected = {{0, 0}, {0.2f, 6}, {0.3f, 4}, {1, 2}, {1.1f, 5}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathForNegativeValues() { float[][] given = {{1, 5}, {2f, -1f}, {2f, 0}, {1, 0}}; float[][] expected = {{1, 5}, {2f, -1}, {2, 0}, {1, 0}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathWhenOnePointPerPixel() { float[][] given = {{1.2f, 2}, {2, 0}, {3, 5}}; float[][] expected = {{1.2f, 2}, {2, 0}, {3, 5}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathWhenNoPointInPixel() { float[][] given = {{6, 0}, {7, 5}}; float[][] expected = {{6, 0}, {7, 5}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathWhenSameY() { float[][] given = {{1, 4}, {1.2f, 4}, {1.3f, 4}, {1.5f, 4}, {1.6f, 4}, {1.7f, 4}}; float[][] expected = {{1, 4}, {1.7f, 4}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathFirstAndLastPointsShouldRemain() { float[][] given = {{1, 4}, {1.2f, 6}, {1.3f, 0}, {1.4f, 2}, {1.5f, 0}, {1.7f, 4}}; float[][] expected = {{1, 4}, {1.2f, 6}, {1.5f, 0}, {1.7f, 4}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathWhenClosedPolyLine() { float[][] given = {{0, 1}, {0.5f, 1}, {1, 3}, {1.5f, 4}, {2, 3}, {2, 0}, {0, 0}}; float[][] expected = {{0, 1}, {0.5f, 1}, {1, 3}, {1.5f, 4.0f}, {2, 3}, {2, 0}, {0, 0}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathClosedPolylineLastPointsShouldRemain() { float[][] given = {{0, 4}, {0.5f, 5}, {1.1f, 0}, {1.2f, 0}, {1.3f, 5}, {1.4f, 5}, {1.9f, 5}, {1.9f, 0}, {0, 0}}; float[][] expected = {{0, 4}, {0.5f, 5}, {1.1f, 0}, {1.3f, 5}, {1.9f, 0}, {0, 0}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }
@Test public void reducePathWhenSteppedLine() { float[][] given = {{0, 5}, {0.1f, 5}, {0.1f, 4}, {0.2f, 4}, {0.2f, 6}, {0.3f, 6}, {0.3f, 4.1f}, {0.5f, 4.1f}, {0.5f, 4.9f}, {3, 4.9f}, {3, 4.8f}}; float[][] expected = {{0, 5}, {0.2f, 5}, {0.2f, 4}, {0.2f, 6}, {0.5f, 6}, {0.5f, 4.9f}, {3, 4.9f}, {3, 4.8f}}; convertToScreenCoordinates(given); convertToScreenCoordinates(expected); myConfig.setStepped(true); float[][] result = convertToArray(myReducer.reducePath(convertToPath(given), myConfig)); assertPointsEquals(expected, result); }