/* * Copyright (C) 2009 Camptocamp * * This file is part of MapFish Server * * MapFish Server is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MapFish Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MapFish Server. If not, see <http://www.gnu.org/licenses/>. */ package org.mapfish.print.map.readers; import org.mapfish.print.InvalidValueException; import org.mapfish.print.utils.PJsonArray; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Holds the information we need to manage a tilecache layer. */ public class TileCacheLayerInfo { /** * Tolerance we accept when trying to determine the nearest resolution. */ protected static final double RESOLUTION_TOLERANCE = 1.05; protected static final Pattern FORMAT_REGEXP = Pattern.compile("^[^/]+/([^/]+)$"); protected static final Pattern RESOLUTIONS_REGEXP = Pattern.compile("\\s+"); protected final int width; protected final int height; protected final float[] resolutions; protected final float minX; protected final float minY; protected final float maxX; protected final float maxY; protected String extension; public TileCacheLayerInfo(String resolutions, int width, int height, float minX, float minY, float maxX, float maxY, String format) { String[] resolutionsTxt = RESOLUTIONS_REGEXP.split(resolutions); this.resolutions = new float[resolutionsTxt.length]; for (int i = 0; i < resolutionsTxt.length; ++i) { this.resolutions[i] = Float.parseFloat(resolutionsTxt[i]); } sortResolutions(); this.width = width; this.height = height; this.minX = minX; this.minY = minY; this.maxX = maxX; this.maxY = maxY; Matcher formatMatcher = FORMAT_REGEXP.matcher(format); if (formatMatcher.matches()) { extension = formatMatcher.group(1).toLowerCase(); if (extension.equals("jpg")) { extension = "jpeg"; } } else { throw new InvalidValueException("format", format); } } public TileCacheLayerInfo(PJsonArray resolutions, int width, int height, float minX, float minY, float maxX, float maxY, String extension) { this.resolutions = new float[resolutions.size()]; for (int i = 0; i < resolutions.size(); ++i) { this.resolutions[i] = resolutions.getFloat(i); } sortResolutions(); this.width = width; this.height = height; this.minX = minX; this.minY = minY; this.maxX = maxX; this.maxY = maxY; this.extension = extension; } public int getWidth() { return width; } public int getHeight() { return height; } public ResolutionInfo getNearestResolution(float targetResolution) { int pos = resolutions.length - 1; float result = resolutions[pos]; for (int i = resolutions.length - 1; i >= 0; --i) { float cur = resolutions[i]; if (cur <= targetResolution * RESOLUTION_TOLERANCE) { result = cur; pos = i; } } return new ResolutionInfo(pos, result); } public float[] getResolutions() { return resolutions; } public String getExtension() { return extension; } public static class ResolutionInfo { public final int index; public final float value; public ResolutionInfo(int index, float value) { this.index = index; this.value = value; } public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ResolutionInfo that = (ResolutionInfo) o; return index == that.index && Float.compare(that.value, value) == 0; } public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("ResolutionInfo"); sb.append("{index=").append(index); sb.append(", result=").append(value); sb.append('}'); return sb.toString(); } } public float getMinX() { return minX; } public float getMinY() { return minY; } public float getMaxY() { return maxY; } public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("TileCacheLayerInfo"); sb.append("{width=").append(width); sb.append(", height=").append(height); sb.append(", minX=").append(minX); sb.append(", minY=").append(minY); sb.append(", maxX=").append(maxX); sb.append(", maxY=").append(maxY); sb.append(", extension='").append(extension).append('\''); sb.append(", resolutions=").append(resolutions == null ? "null" : ""); for (int i = 0; resolutions != null && i < resolutions.length; ++i) { sb.append(i == 0 ? "" : ", ").append(resolutions[i]); } sb.append('}'); return sb.toString(); } /** * Receives the extent of a tile and checks that tilecache has it. */ @SuppressWarnings({"UnusedDeclaration"}) public boolean isVisible(float x1, float y1, float x2, float y2) { return x1 >= minX && x1 <= maxX && y1 >= minY && y1 <= maxY /*&& x2 >= minX && x2 <= maxX && y2 >= minY && y2 <= maxY*/; //we don't use x2 and y2 since tilecache doesn't seems to care about those... } /** * The resolutions must be sorted in descending order. */ private void sortResolutions() { Arrays.sort(this.resolutions); int right = this.resolutions.length - 1; for (int left = 0; left < right; left++, right--) { float temp = this.resolutions[left]; this.resolutions[left] = this.resolutions[right]; this.resolutions[right] = temp; } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TileCacheLayerInfo that = (TileCacheLayerInfo) o; if (height != that.height) return false; if (Float.compare(that.maxX, maxX) != 0) return false; if (Float.compare(that.maxY, maxY) != 0) return false; if (Float.compare(that.minX, minX) != 0) return false; if (Float.compare(that.minY, minY) != 0) return false; if (width != that.width) return false; if (!extension.equals(that.extension)) return false; if (!Arrays.equals(resolutions, that.resolutions)) return false; return true; } }