@SuppressWarnings("unchecked")
@Override
public final Output execute(final Input values, final ExecutionContext context) throws Exception {
final MapAttributeValues map = values.map;
final PagingAttribute.PagingProcessorValues paging = values.paging;
CoordinateReferenceSystem projection = map.getMapBounds().getProjection();
final Rectangle paintArea = new Rectangle(map.getMapSize());
final double dpi = map.getRequestorDPI();
final DistanceUnit projectionUnit = DistanceUnit.fromProjection(projection);
AreaOfInterest areaOfInterest = map.areaOfInterest;
if (areaOfInterest == null) {
areaOfInterest = new AreaOfInterest();
areaOfInterest.display = AreaOfInterest.AoiDisplay.NONE;
ReferencedEnvelope mapBBox = map.getMapBounds().toReferencedEnvelope(paintArea, dpi);
areaOfInterest.setPolygon((Polygon) this.geometryFactory.toGeometry(mapBBox));
}
Envelope aoiBBox = areaOfInterest.getArea().getEnvelopeInternal();
final double paintAreaWidthIn = paintArea.getWidth() * paging.scale / dpi;
final double paintAreaHeightIn = paintArea.getHeight() * paging.scale / dpi;
final double paintAreaWidth = DistanceUnit.IN.convertTo(paintAreaWidthIn, projectionUnit);
final double paintAreaHeight = DistanceUnit.IN.convertTo(paintAreaHeightIn, projectionUnit);
final int nbWidth = (int) Math.ceil(aoiBBox.getWidth() / (paintAreaWidth - paging.overlap));
final int nbHeight = (int) Math.ceil(aoiBBox.getHeight() / (paintAreaHeight - paging.overlap));
final double marginWidth = (paintAreaWidth * nbWidth - aoiBBox.getWidth()) / 2;
final double marginHeight = (paintAreaHeight * nbHeight - aoiBBox.getHeight()) / 2;
final double minX = aoiBBox.getMinX() - marginWidth - paging.overlap / 2;
final double minY = aoiBBox.getMinY() - marginHeight - paging.overlap / 2;
LOGGER.info("Paging generate a grid of " + nbWidth + "x" + nbHeight + " potential maps.");
final int[][] mapIndexes = new int[nbWidth][nbHeight];
final Envelope[][] mapsBounds = new Envelope[nbWidth][nbHeight];
int mapIndex = 0;
for (int j = 0; j < nbHeight; j++) {
for (int i = 0; i < nbWidth; i++) {
final double x1 = minX + i * (paintAreaWidth - paging.overlap);
final double x2 = x1 + paintAreaWidth;
final double y1 = minY + j * (paintAreaHeight - paging.overlap);
final double y2 = y1 + paintAreaHeight;
Coordinate[] coords = new Coordinate[] {
new Coordinate(x1, y1),
new Coordinate(x1, y2),
new Coordinate(x2, y2),
new Coordinate(x2, y1),
new Coordinate(x1, y1)
};
LinearRing ring = this.geometryFactory.createLinearRing(coords);
final Polygon bbox = this.geometryFactory.createPolygon(ring);
if (areaOfInterest.getArea().intersects(bbox)) {
mapsBounds[i][j] = bbox.getEnvelopeInternal();
mapIndexes[i][j] = mapIndex;
mapIndex++;
} else {
mapIndexes[i][j] = DO_NOT_RENDER_BBOX_INDEX;
}
}
}
final List<Map<String, Object>> mapList = Lists.newArrayList();
for (int j = 0; j < nbHeight; j++) {
for (int i = 0; i < nbWidth; i++) {
if (mapIndexes[i][j] != DO_NOT_RENDER_BBOX_INDEX) {
Map<String, Object> mapValues = new HashMap<String, Object>();
mapValues.put("name", mapIndexes[i][j]);
mapValues.put("left", i != 0 ? mapIndexes[i - 1][j] : DO_NOT_RENDER_BBOX_INDEX);
mapValues.put("bottom", j != 0 ? mapIndexes[i][j - 1] : DO_NOT_RENDER_BBOX_INDEX);
mapValues.put("right", i != nbWidth - 1 ? mapIndexes[i + 1][j] : DO_NOT_RENDER_BBOX_INDEX);
mapValues.put("top", j != nbHeight - 1 ? mapIndexes[i][j + 1] : DO_NOT_RENDER_BBOX_INDEX);
final Coordinate center = mapsBounds[i][j].centre();
MapAttributeValues theMap = map.copy(map.getMapSize(), new Function<MapAttributeValues, Void>() {
@Nullable
@Override
public Void apply(@Nonnull final MapAttributeValues input) {
input.center = new double[]{center.x, center.y};
input.scale = paging.scale;