private void layerGridSubSets(StringBuilder str, TileLayer layer) {
    Iterator<GridSubset> gridSubsets = layer.getGridSubsets().values().iterator();

    while (gridSubsets.hasNext()) {
      GridSubset gridSubset = gridSubsets.next();

      str.append("    <TileMatrixSetLink>");
      str.append("      <TileMatrixSet>" + gridSubset.getName() + "</TileMatrixSet>\n");

      if (!gridSubset.fullGridSetCoverage()) {
        String[] levelNames = gridSubset.getGridNames();
        long[][] wmtsLimits = gridSubset.getWMTSCoverages();

        str.append("      <TileMatrixSetLimits>\n");
        for (int i = 0; i < levelNames.length; i++) {
          str.append("        <TileMatrixLimits>\n");
          str.append("          <TileMatrix>" + levelNames[i] + "</TileMatrix>\n");
          str.append("          <MinTileRow>" + wmtsLimits[i][1] + "</MinTileRow>\n");
          str.append("          <MaxTileRow>" + wmtsLimits[i][3] + "</MaxTileRow>\n");
          str.append("          <MinTileCol>" + wmtsLimits[i][0] + "</MinTileCol>\n");
          str.append("          <MaxTileCol>" + wmtsLimits[i][2] + "</MaxTileCol>\n");
          str.append("        </TileMatrixLimits>\n");
        }
        str.append("      </TileMatrixSetLimits>\n");
      }
      str.append("    </TileMatrixSetLink>");
    }
  }
  private void capabilityVendorSpecificTileset(
      StringBuilder str, TileLayer layer, GridSubset grid, String formatStr, String styleName)
      throws GeoWebCacheException {

    String srsStr = grid.getSRS().toString();
    StringBuilder resolutionsStr = new StringBuilder();
    double[] res = grid.getResolutions();
    for (int i = 0; i < res.length; i++) {
      resolutionsStr.append(Double.toString(res[i]) + " ");
    }

    String[] bs = boundsPrep(grid.getCoverageBestFitBounds());

    str.append("    <TileSet>\n");
    str.append("      <SRS>" + srsStr + "</SRS>\n");
    str.append(
        "      <BoundingBox SRS=\""
            + srsStr
            + "\" minx=\""
            + bs[0]
            + "\" miny=\""
            + bs[1]
            + "\"  maxx=\""
            + bs[2]
            + "\"  maxy=\""
            + bs[3]
            + "\" />\n");
    str.append("      <Resolutions>" + resolutionsStr.toString() + "</Resolutions>\n");
    str.append("      <Width>" + grid.getTileWidth() + "</Width>\n");
    str.append("      <Height>" + grid.getTileHeight() + "</Height>\n");
    str.append("      <Format>" + formatStr + "</Format>\n");
    str.append("      <Layers>" + layer.getName() + "</Layers>\n");
    str.append("      <Styles>").append(ServletUtils.URLEncode(styleName)).append("</Styles>\n");
    str.append("    </TileSet>\n");
  }
  public void apply(ConveyorTile convTile) throws RequestFilterException {
    TileLayer tl = convTile.getLayer();
    // SRS srs = convTile.getSRS();
    GridSubset gridSubset = tl.getGridSubset(convTile.getGridSetId());

    int z = (int) convTile.getTileIndex()[2];
    long[] gridCoverage = gridSubset.getCoverage(z);

    // Figure out the radius
    long width = gridCoverage[2] - gridCoverage[0];
    long height = gridCoverage[3] - gridCoverage[1];

    // Rounding must always err on the side of
    // caution if you want to use KML hierarchies
    long maxRad = 0;
    if (width > height) {
      maxRad = (width / 4) + 1;
    } else {
      maxRad = (height / 4) + 1;
    }

    // Figure out how the requested bounds relate
    long midX = gridCoverage[0] + width / 2;
    long midY = gridCoverage[1] + height / 2;

    long xDist = midX - convTile.getTileIndex()[0];
    long yDist = midY - convTile.getTileIndex()[1];

    long rad = Math.round(Math.sqrt(xDist * xDist + yDist * yDist));

    if (rad > maxRad) {
      throw new BlankTileException(this);
    }
  }
 private void layerWGS84BoundingBox(StringBuilder str, TileLayer layer) {
   GridSubset subset = layer.getGridSubsetForSRS(SRS.getEPSG4326());
   if (subset != null) {
     double[] coords = subset.getOriginalExtent().getCoords();
     str.append("    <ows:WGS84BoundingBox>\n");
     str.append("      <ows:LowerCorner>" + coords[0] + " " + coords[1] + "</ows:LowerCorner>\n");
     str.append("      <ows:UpperCorner>" + coords[2] + " " + coords[3] + "</ows:UpperCorner>\n");
     str.append("    </ows:WGS84BoundingBox>\n");
   }
 }
  private void vendorSpecificTileset(
      final Translator tx, final TileLayer layer, final GridSubset grid, final String format) {

    String srsStr = grid.getSRS().toString();
    StringBuilder resolutionsStr = new StringBuilder();
    double[] res = grid.getResolutions();
    for (int i = 0; i < res.length; i++) {
      resolutionsStr.append(Double.toString(res[i]) + " ");
    }

    String[] bs = boundsPrep(grid.getCoverageBestFitBounds());

    tx.start("TileSet");

    tx.start("SRS");
    tx.chars(srsStr);
    tx.end("SRS");

    AttributesImpl atts;
    atts = new AttributesImpl();
    atts.addAttribute("", "SRS", "SRS", "", srsStr);
    atts.addAttribute("", "minx", "minx", "", bs[0]);
    atts.addAttribute("", "miny", "miny", "", bs[1]);
    atts.addAttribute("", "maxx", "maxx", "", bs[2]);
    atts.addAttribute("", "maxy", "maxy", "", bs[3]);

    tx.start("BoundingBox", atts);
    tx.end("BoundingBox");

    tx.start("Resolutions");
    tx.chars(resolutionsStr.toString());
    tx.end("Resolutions");

    tx.start("Width");
    tx.chars(String.valueOf(grid.getTileWidth()));
    tx.end("Width");

    tx.start("Height");
    tx.chars(String.valueOf(grid.getTileHeight()));
    tx.end("Height");

    tx.start("Format");
    tx.chars(format);
    tx.end("Format");

    tx.start("Layers");
    tx.chars(layer.getName());
    tx.end("Layers");

    // TODO ignoring styles for now
    tx.start("Styles");
    tx.end("Styles");

    tx.end("TileSet");
  }
  Envelope findTileBounds(GridSubset gridSubset, BoundingBox bbox, int z) {

    long[] i = gridSubset.getCoverageIntersection(z, bbox);

    BoundingBox b1 = gridSubset.boundsFromIndex(new long[] {i[0], i[1], i[4]});
    BoundingBox b2 = gridSubset.boundsFromIndex(new long[] {i[2], i[3], i[4]});
    return new Envelope(
        Math.min(b1.getMinX(), b2.getMinX()),
        Math.max(b1.getMaxX(), b2.getMaxX()),
        Math.min(b1.getMinY(), b2.getMinY()),
        Math.max(b1.getMaxY(), b2.getMaxY()));
  }
  Integer findMaxZoomAuto(GridSubset gridSubset, Integer minZoom, WMSMapContent map) {
    BoundingBox bbox = bbox(map);

    int zoom = minZoom;
    int ntiles = 0;

    while (ntiles < 256 && zoom < gridSubset.getGridSet().getNumLevels()) {
      long[] intersect = gridSubset.getCoverageIntersection(zoom, bbox);
      ntiles += (intersect[2] - intersect[0] + 1) * (intersect[3] - intersect[1] + 1);
      zoom++;
    }
    return zoom;
  }
示例#8
0
  protected void determineSourceResolution() {
    xResolution = reqBounds.getWidth() / reqWidth;
    yResolution = reqBounds.getHeight() / reqHeight;

    double tmpResolution;
    // We use the smallest one
    if (yResolution < xResolution) {
      tmpResolution = yResolution;
    } else {
      tmpResolution = xResolution;
    }

    log.debug(
        "x res: " + xResolution + " y res: " + yResolution + " tmpResolution: " + tmpResolution);

    // Cut ourselves 0.5% slack
    double compResolution = 1.005 * tmpResolution;

    double[] resArray = gridSubset.getResolutions();

    for (srcIdx = 0; srcIdx < resArray.length; srcIdx++) {
      srcResolution = resArray[srcIdx];
      if (srcResolution < compResolution) {
        break;
      }
    }

    if (srcIdx >= resArray.length) {
      srcIdx = resArray.length - 1;
    }

    log.debug("z: " + srcIdx + " , resolution: " + srcResolution + " (" + tmpResolution + ")");

    // At worst, we have the best resolution possible
  }
  @Test
  public void testParseMaplinkAndLayersWithGeoJSONFromJsonTest()
      throws IOException, ParseException, com.vividsolutions.jts.io.ParseException {

    XMLConfiguration config = shared.getConfig();

    TileLayer tileLayer = config.getTileLayer(layerTemplate);
    GridSubset gridSubset = tileLayer.getGridSubset(gridSubsetName);

    MapLayerJSONParser layerJsonParser = new MapLayerJSONParser(props);

    MaplinkGeoJsonParser parser = new MaplinkGeoJsonParser();
    parser.setDebug(true);

    InputStream inp = MapProducer.class.getResourceAsStream("geojsPrintTest.json");

    try {

      assertTrue(MapLinkGeoJsonParseContext.Default.getPm().buildMap);

      Map<String, ?> root = parser.parse(inp);

      assertTrue(root.size() != 0);
      assertTrue(root.get("layers") != null);
      assertTrue(root.get("maplink") != null);
      assertTrue(root.get("state") != null);

      assertTrue(root.get("layers") != null);

      MapLink mapLink =
          layerJsonParser.parseMapLinkJSON(root, shared.getGf(), gridSubset.getResolutions());

      assertTrue(mapLink != null);

    } finally {
      inp.close();
    }
  }
  int[] findMinMaxZoom(GridSubset gridSubset, WMSMapContent map) {
    GridSet gridSet = gridSubset.getGridSet();
    Map formatOpts = map.getRequest().getFormatOptions();

    Integer minZoom = null;
    if (formatOpts.containsKey("min_zoom")) {
      minZoom = Integer.parseInt(formatOpts.get("min_zoom").toString());
    }
    if (minZoom == null) {
      minZoom = findClosestZoom(gridSet, map);
    }

    Integer maxZoom = null;
    if (formatOpts.containsKey("max_zoom")) {
      maxZoom = Integer.parseInt(formatOpts.get("max_zoom").toString());
    } else if (formatOpts.containsKey("num_zooms")) {
      maxZoom = minZoom + Integer.parseInt(formatOpts.get("num_zooms").toString());
    }

    if (maxZoom == null) {
      // walk down until we hit too many tiles
      maxZoom = findMaxZoomAuto(gridSubset, minZoom, map);
    }

    if (maxZoom < minZoom) {
      throw new ServiceException(
          format("maxZoom (%d) can not be less than minZoom (%d)", maxZoom, minZoom));
    }

    // end index
    if (maxZoom > gridSet.getNumLevels()) {
      LOGGER.warning(
          format(
              "Max zoom (%d) can't be greater than number of zoom levels (%d)",
              maxZoom, gridSet.getNumLevels()));
      maxZoom = gridSet.getNumLevels();
    }

    return new int[] {minZoom, maxZoom};
  }
示例#11
0
  protected void renderCanvas() throws OutsideCoverageException, GeoWebCacheException, IOException {
    // Now we loop over all the relevant tiles and write them to the canvas,
    // Starting at the bottom, moving to the right and up

    // Bottom row of tiles, in tile coordinates
    long starty = srcRectangle[1];

    // gridy is the tile row index
    for (long gridy = starty; gridy <= srcRectangle[3]; gridy++) {

      int tiley = 0;
      int canvasy = (int) (srcRectangle[3] - gridy) * gridSubset.getTileHeight();
      int tileHeight = gridSubset.getTileHeight();

      if (canvOfs.top > 0) {
        // Add padding
        canvasy += canvOfs.top;
      } else {
        // Top tile is cut off
        if (gridy == srcRectangle[3]) {
          // This one starts at the top, so canvasy remains 0
          tileHeight = tileHeight + canvOfs.top;
          tiley = -canvOfs.top;
        } else {
          // Offset that the first tile contributed,
          // rather, we subtract what it did not contribute
          canvasy += canvOfs.top;
        }
      }

      if (gridy == srcRectangle[1] && canvOfs.bottom < 0) {
        // Check whether we only use part of the first tiles (bottom row)
        // Offset is negative, slice the bottom off the tile
        tileHeight += canvOfs.bottom;
      }

      long startx = srcRectangle[0];
      for (long gridx = startx; gridx <= srcRectangle[2]; gridx++) {

        long[] gridLoc = {gridx, gridy, srcIdx};

        ConveyorTile tile =
            new ConveyorTile(
                sb,
                layer.getName(),
                gridSubset.getName(),
                gridLoc,
                ImageMime.png,
                fullParameters,
                null,
                null);

        // Check whether this tile is to be rendered at all
        try {
          layer.applyRequestFilters(tile);
        } catch (RequestFilterException e) {
          log.debug(e.getMessage());
          continue;
        }

        layer.getTile(tile);

        BufferedImage tileImg = ImageIO.read(tile.getBlob().getInputStream());

        int tilex = 0;
        int canvasx = (int) (gridx - startx) * gridSubset.getTileWidth();
        int tileWidth = gridSubset.getTileWidth();

        if (canvOfs.left > 0) {
          // Add padding
          canvasx += canvOfs.left;
        } else {
          // Leftmost tile is cut off
          if (gridx == srcRectangle[0]) {
            // This one starts to the left top, so canvasx remains 0
            tileWidth = tileWidth + canvOfs.left;
            tilex = -canvOfs.left;
          } else {
            // Offset that the first tile contributed,
            // rather, we subtract what it did not contribute
            canvasx += canvOfs.left;
          }
        }

        if (gridx == srcRectangle[2] && canvOfs.right < 0) {
          // Check whether we only use part of the first tiles (bottom row)
          // Offset is negative, slice the bottom off the tile
          tileWidth = tileWidth + canvOfs.right;
        }

        // TODO We should really ensure we can never get here
        if (tileWidth == 0 || tileHeight == 0) {
          log.debug("tileWidth: " + tileWidth + " tileHeight: " + tileHeight);
          continue;
        }

        // Cut down the tile to the part we want
        if (tileWidth != gridSubset.getTileWidth() || tileHeight != gridSubset.getTileHeight()) {
          log.debug(
              "tileImg.getSubimage("
                  + tilex
                  + ","
                  + tiley
                  + ","
                  + tileWidth
                  + ","
                  + tileHeight
                  + ")");
          tileImg = tileImg.getSubimage(tilex, tiley, tileWidth, tileHeight);
        }

        // Render the tile on the big canvas
        log.debug(
            "drawImage(subtile," + canvasx + "," + canvasy + ",null) " + Arrays.toString(gridLoc));
        gfx.drawImage(tileImg, canvasx, canvasy, null); // imageObserver
      }
    }

    gfx.dispose();
  }
示例#12
0
  private static String generateHTML(
      TileLayer layer, String gridSetStr, String formatStr, boolean asPlugin)
      throws GeoWebCacheException {
    String layerName = layer.getName();

    GridSubset gridSubset = layer.getGridSubset(gridSetStr);

    BoundingBox bbox = gridSubset.getGridSetBounds();
    BoundingBox zoomBounds = gridSubset.getOriginalExtent();

    String res = "resolutions: " + Arrays.toString(gridSubset.getResolutions()) + ",\n";

    String units = "units: \"" + gridSubset.getGridSet().guessMapUnits() + "\",\n";

    String openLayersPath;
    if (asPlugin) {
      openLayersPath = "../openlayers/OpenLayers.js";
    } else {
      openLayersPath = "../openlayers/OpenLayers.js";
    }

    String page =
        "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\n"
            + "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n"
            + "<title>"
            + layerName
            + " "
            + gridSubset.getName()
            + " "
            + formatStr
            + "</title>\n"
            + "<style type=\"text/css\">\n"
            + "body { font-family: sans-serif; font-weight: bold; font-size: .8em; }\n"
            + "body { border: 0px; margin: 0px; padding: 0px; }\n"
            + "#map { width: 85%; height: 85%; border: 0px; padding: 0px; }\n"
            + "</style>\n"
            + "<script src=\""
            + openLayersPath
            + "\"></script>    \n"
            + "<script type=\"text/javascript\">               \n"
            + "var map, demolayer;                               \n"
            + "  // sets the chosen modifiable parameter        \n"
            + "  function setParam(name, value){                \n"
            + "   str = \"demolayer.mergeNewParams({\" + name + \": '\" + value + \"'})\" \n"
            + "   // alert(str);                                   \n"
            + "   eval(str);                                    \n"
            + "  }                                              \n"
            + "OpenLayers.DOTS_PER_INCH = "
            + gridSubset.getDotsPerInch()
            + ";\n"
            + "OpenLayers.Util.onImageLoadErrorColor = 'transparent';\n"
            + "function init(){\n"
            + "var mapOptions = { \n"
            + res
            + "projection: new OpenLayers.Projection('"
            + gridSubset.getSRS().toString()
            + "'),\n"
            + "maxExtent: new OpenLayers.Bounds("
            + bbox.toString()
            + "),\n"
            + units
            + "controls: []\n"
            + "};\n"
            + "map = new OpenLayers.Map('map', mapOptions );\n"
            + "map.addControl(new OpenLayers.Control.PanZoomBar({\n"
            + "		position: new OpenLayers.Pixel(2, 15)\n"
            + "}));\n"
            + "map.addControl(new OpenLayers.Control.Navigation());\n"
            + "map.addControl(new OpenLayers.Control.Scale($('scale')));\n"
            + "map.addControl(new OpenLayers.Control.MousePosition({element: $('location')}));\n"
            + "demolayer = new OpenLayers.Layer.WMS(\n"
            + "\""
            + layerName
            + "\",\"../service/wms\",\n"
            + "{layers: '"
            + layerName
            + "', format: '"
            + formatStr
            + "' },\n"
            + "{ tileSize: new OpenLayers.Size("
            + gridSubset.getTileWidth()
            + ","
            + gridSubset.getTileHeight()
            + ")";

    /*
     * If the gridset has a top left tile origin, lets tell that to open layers. Otherwise it'll
     * calculate tile bounds based on the bbox bottom left corner, leading to misaligned
     * requests.
     */
    GridSet gridSet = gridSubset.getGridSet();
    if (gridSet.isTopLeftAligned()) {
      page +=
          ",\n tileOrigin: new OpenLayers.LonLat(" + bbox.getMinX() + ", " + bbox.getMaxY() + ")";
    }

    page +=
        "});\n"
            + "map.addLayer(demolayer);\n"
            + "map.zoomToExtent(new OpenLayers.Bounds("
            + zoomBounds.toString()
            + "));\n"
            + "// The following is just for GetFeatureInfo, which is not cached. Most people do not need this \n"
            + "map.events.register('click', map, function (e) {\n"
            + "  document.getElementById('nodelist').innerHTML = \"Loading... please wait...\";\n"
            + "  var params = {\n"
            + "    REQUEST: \"GetFeatureInfo\",\n"
            + "    EXCEPTIONS: \"application/vnd.ogc.se_xml\",\n"
            + "    BBOX: map.getExtent().toBBOX(),\n"
            + "    X: e.xy.x,\n"
            + "    Y: e.xy.y,\n"
            + "    INFO_FORMAT: 'text/html',\n"
            + "    QUERY_LAYERS: map.layers[0].params.LAYERS,\n"
            + "    FEATURE_COUNT: 50,\n"
            + "    Layers: '"
            + layerName
            + "',\n"
            + "    Styles: '',\n"
            + "    Srs: '"
            + gridSubset.getSRS().toString()
            + "',\n"
            + "    WIDTH: map.size.w,\n"
            + "    HEIGHT: map.size.h,\n"
            + "    format: \""
            + formatStr
            + "\" };\n"
            + "  OpenLayers.loadURL(\"../service/wms\", params, this, setHTML, setHTML);\n"
            + "  OpenLayers.Event.stop(e);\n"
            + "  });\n"
            + "}\n"
            + "function setHTML(response){\n"
            + "    document.getElementById('nodelist').innerHTML = response.responseText;\n"
            + "};\n"
            + "</script>\n"
            + "</head>\n"
            + "<body onload=\"init()\">\n"
            + "<div id=\"params\">"
            + makeModifiableParameters(layer)
            + "</div>\n"
            + "<div id=\"map\"></div>\n"
            + "<div id=\"nodelist\"></div>\n"
            + "</body>\n"
            + "</html>";
    return page;
  }
示例#13
0
  private static String tableRows(
      TileLayerDispatcher tileLayerDispatcher, GridSetBroker gridSetBroker)
      throws GeoWebCacheException {
    StringBuffer buf = new StringBuffer();

    Set<String> layerList = new TreeSet<String>(tileLayerDispatcher.getLayerNames());
    for (String layerName : layerList) {
      TileLayer layer = tileLayerDispatcher.getTileLayer(layerName);
      buf.append(
          "<tr><td style=\"min-width: 100px;\"><strong>" + layer.getName() + "</strong><br />\n");
      buf.append("<a href=\"rest/seed/" + layer.getName() + "\">Seed this layer</a>\n");
      buf.append("</td><td>" + layer.isEnabled() + "</td>");
      buf.append("<td><table width=\"100%\">");

      int count = 0;
      for (String gridSetId : layer.getGridSubsets()) {
        GridSubset gridSubset = layer.getGridSubset(gridSetId);
        String gridSetName = gridSubset.getName();
        if (gridSetName.length() > 20) {
          gridSetName = gridSetName.substring(0, 20) + "...";
        }
        buf.append("<tr><td style=\"width: 170px;\">").append(gridSetName);

        buf.append("</td><td>OpenLayers: [");
        Iterator<MimeType> mimeIter = layer.getMimeTypes().iterator();
        boolean prependComma = false;
        while (mimeIter.hasNext()) {
          MimeType mime = mimeIter.next();
          if (mime instanceof ImageMime) {
            if (prependComma) {
              buf.append(", ");
            } else {
              prependComma = true;
            }
            buf.append(generateDemoUrl(layer.getName(), gridSubset.getName(), (ImageMime) mime));
          }
        }
        buf.append("]</td><td>\n");

        if (gridSubset.getName().equals(gridSetBroker.WORLD_EPSG4326.getName())) {
          buf.append(" &nbsp; KML: [");
          String prefix = "";
          prependComma = false;
          Iterator<MimeType> kmlIter = layer.getMimeTypes().iterator();
          while (kmlIter.hasNext()) {
            MimeType mime = kmlIter.next();
            if (mime instanceof ImageMime || mime == XMLMime.kml) {
              if (prependComma) {
                buf.append(", ");
              } else {
                prependComma = true;
              }
              buf.append(
                  "<a href=\""
                      + prefix
                      + "service/kml/"
                      + layer.getName()
                      + "."
                      + mime.getFileExtension()
                      + ".kml\">"
                      + mime.getFileExtension()
                      + "</a>");
            } else if (mime == XMLMime.kmz) {
              if (prependComma) {
                buf.append(", ");
              } else {
                prependComma = true;
              }
              buf.append(
                  "<a href=\"" + prefix + "service/kml/" + layer.getName() + ".kml.kmz\">kmz</a>");
            }
          }
          buf.append("]");
        } else {
          // No Google Earth support
        }
        buf.append("</td></tr>");
        count++;
      }

      // if(count == 0) {
      // buf.append("<tr><td colspan=\"2\"><i>None</i></td></tr>\n");
      // }

      buf.append("</table></td>\n");
      buf.append("</tr>\n");
    }

    return buf.toString();
  }
  GridSubset findBestGridSubset(WMSMapContent map) {
    GetMapRequest req = map.getRequest();
    Map formatOpts = req.getFormatOptions();

    GridSetBroker gridSetBroker = gwc.getGridSetBroker();
    GridSet gridSet = null;

    // first check format options to see if explicitly specified
    if (formatOpts.containsKey("gridset")) {
      gridSet = gridSetBroker.get(formatOpts.get("gridset").toString());
    }

    // next check srs
    if (gridSet == null) {
      gridSet = gridSetBroker.get(req.getSRS().toUpperCase());
    }

    if (gridSet != null) {
      return GridSubsetFactory.createGridSubSet(gridSet);
    }

    CoordinateReferenceSystem crs = map.getCoordinateReferenceSystem();

    // look up epsg code
    Integer epsgCode = null;
    try {
      epsgCode = CRS.lookupEpsgCode(crs, false);
    } catch (Exception e) {
      throw new ServiceException("Unable to determine epsg code for " + crs, e);
    }
    if (epsgCode == null) {
      throw new ServiceException("Unable to determine epsg code for " + crs);
    }

    SRS srs = SRS.getSRS(epsgCode);

    // figure out the appropriate grid sub set
    Set<GridSubset> gridSubsets = new LinkedHashSet<GridSubset>();
    for (MapLayerInfo l : req.getLayers()) {
      TileLayer tl = gwc.getTileLayerByName(l.getName());
      if (tl == null) {
        throw new ServiceException("No tile layer for " + l.getName());
      }

      List<GridSubset> theseGridSubsets = tl.getGridSubsetsForSRS(srs);
      if (gridSubsets.isEmpty()) {
        gridSubsets.addAll(theseGridSubsets);
      } else {
        gridSubsets.retainAll(theseGridSubsets);
      }

      if (gridSubsets.isEmpty()) {
        throw new ServiceException(
            "No suitable " + epsgCode + " grid subset for " + req.getLayers());
      }
    }

    if (gridSubsets.size() > 1) {
      if (LOGGER.isLoggable(Level.WARNING)) {
        StringBuilder msg = new StringBuilder("Found multiple grid subsets: ");
        for (GridSubset gs : gridSubsets) {
          msg.append(gs.getName()).append(", ");
        }
        msg.setLength(msg.length() - 2);
        msg.append(". Choosing first.");
        LOGGER.warning(msg.toString());
      }
    }

    return gridSubsets.iterator().next();
  }
  /**
   * Make sure when seeding a given zoom level, the correct tiles are sent to the {@link
   * StorageBroker}
   *
   * @throws Exception
   */
  @SuppressWarnings("serial")
  public void testSeedStoredTiles() throws Exception {

    WMSLayer tl = createWMSLayer("image/png");

    // create an image to be returned by the mock WMSSourceHelper
    // / final byte[] fakeWMSResponse = createFakeSourceImage(tl);
    // WMSSourceHelper that on makeRequest() returns always the saqme fake image
    WMSSourceHelper mockSourceHelper =
        new MockWMSSourceHelper(); // EasyMock.createMock(WMSSourceHelper.class);
    // expect(mockSourceHelper.makeRequest((WMSMetaTile)
    // anyObject())).andReturn(fakeWMSResponse)
    // .anyTimes();
    // replay(mockSourceHelper);
    tl.setSourceHelper(mockSourceHelper);

    final String gridSetId = tl.getGridSubsets().iterator().next();
    final int zoomLevel = 2;
    SeedRequest req = createRequest(tl, TYPE.SEED, zoomLevel, zoomLevel);

    /*
     * Create a mock storage broker that has never an image in its blob store and that captures
     * the TileObject the seeder requests it to store for further test validation
     */
    final StorageBroker mockStorageBroker = EasyMock.createMock(StorageBroker.class);
    Capture<TileObject> storedObjects =
        new Capture<TileObject>() {
          /** Override because setValue with anyTimes() resets the list of values */
          @Override
          public void setValue(TileObject o) {
            super.getValues().add(o);
          }
        };
    expect(mockStorageBroker.put(capture(storedObjects))).andReturn(true).anyTimes();
    expect(mockStorageBroker.get((TileObject) anyObject())).andReturn(false).anyTimes();
    replay(mockStorageBroker);

    TileRange tr = TileBreeder.createTileRange(req, tl);
    TileRangeIterator trIter = new TileRangeIterator(tr, tl.getMetaTilingFactors());

    boolean reseed = false;
    SeedTask task = new SeedTask(mockStorageBroker, trIter, tl, reseed, false);
    task.setTaskId(1L);
    task.setThreadInfo(new AtomicInteger(), 0);
    /*
     * HACK: avoid SeedTask.getCurrentThreadArrayIndex failure.
     */
    Thread.currentThread().setName("pool-fake-thread-1");

    /*
     * Call the seed process
     */
    task.doAction();

    final GridSubset gridSubset = tl.getGridSubset(gridSetId);

    /*
     * Make sure the seed process asked for the expected tiles to be stored
     */
    final long expectedSavedTileCount;

    final long[] coveredGridLevels = gridSubset.getCoverage(zoomLevel);

    // seeding should not include edge tiles produced by the meta tiling that don't fall into
    // the gridsubset's coverage
    long starty = coveredGridLevels[1];
    long startx = coveredGridLevels[0];

    expectedSavedTileCount =
        (coveredGridLevels[2] - startx + 1) * (coveredGridLevels[3] - starty + 1);

    List<TileObject> storedTiles = storedObjects.getValues();
    final int seededTileCount = storedTiles.size();

    assertEquals(expectedSavedTileCount, seededTileCount);

    Set<Tuple<Long>> tileKeys = new TreeSet<Tuple<Long>>();
    Set<Tuple<Long>> expectedTiles = new TreeSet<Tuple<Long>>();
    for (long x = startx; x <= coveredGridLevels[2]; x++) {
      for (long y = starty; y <= coveredGridLevels[3]; y++) {
        expectedTiles.add(new Tuple<Long>(x, y, (long) zoomLevel));
      }
    }
    for (TileObject obj : storedTiles) {
      tileKeys.add(new Tuple<Long>(obj.getXYZ()[0], obj.getXYZ()[1], obj.getXYZ()[2]));
    }

    assertEquals(expectedTiles, tileKeys);
  }
示例#16
0
  protected void determineCanvasLayout() {
    // Find the spatial extent of the tiles needed to cover the desired extent
    srcRectangle = gridSubset.getCoverageIntersection(srcIdx, reqBounds);
    srcBounds = gridSubset.boundsFromRectangle(srcRectangle);

    // We now have the complete area, lets figure out our offsets
    // Positive means that there is blank space to the first tile,
    // negative means we will not use the entire tile
    boundOfs.left = srcBounds.getMinX() - reqBounds.getMinX();
    boundOfs.bottom = srcBounds.getMinY() - reqBounds.getMinY();
    boundOfs.right = reqBounds.getMaxX() - srcBounds.getMaxX();
    boundOfs.top = reqBounds.getMaxY() - srcBounds.getMaxY();

    canvasSize[0] = (int) Math.round(reqBounds.getWidth() / this.srcResolution);
    canvasSize[1] = (int) Math.round(reqBounds.getHeight() / this.srcResolution);

    PixelOffsets naiveOfs = new PixelOffsets();
    // Calculate the corresponding pixel offsets. We'll stick to sane,
    // i.e. bottom left, coordinates at this point
    naiveOfs.left = (int) Math.round(boundOfs.left / this.srcResolution);
    naiveOfs.bottom = (int) Math.round(boundOfs.bottom / this.srcResolution);
    naiveOfs.right = (int) Math.round(boundOfs.right / this.srcResolution);
    naiveOfs.top = (int) Math.round(boundOfs.top / this.srcResolution);

    // Find the offsets on the opposite sides.  This is dependent of how the first two were rounded.

    // First, find a tile boundary near the canvas edge, then make sure it's on the correct
    // side to match the corresponding boundOfs, then take the modulo of the naive rounding
    // based on the boundOfs, then subtract the two and apply the difference to the boundOfs.
    int tileWidth = this.gridSubset.getTileWidth();
    int tileHeight = this.gridSubset.getTileHeight();

    canvOfs.left = naiveOfs.left;
    canvOfs.bottom = naiveOfs.bottom;

    canvOfs.right = (canvasSize[0] - canvOfs.left) % tileWidth; // Find nearby tile boundary
    canvOfs.right =
        (Integer.signum(naiveOfs.right) * tileWidth + canvOfs.right)
            % tileWidth; // Ensure same sign as naive calculation
    canvOfs.right =
        canvOfs.right
            - (naiveOfs.right % tileWidth)
            + naiveOfs.right; // Find adjustment from naive and apply to naive calculation
    canvOfs.top = (canvasSize[1] - canvOfs.bottom) % tileHeight; // Find nearby tile boundary
    canvOfs.top =
        (Integer.signum(naiveOfs.top) * tileHeight + canvOfs.top)
            % tileHeight; // Ensure same sign as naive calculation
    canvOfs.top =
        canvOfs.top
            - (naiveOfs.top % tileHeight)
            + naiveOfs.top; // Find adjustment from naive and apply to naive calculation

    // postconditions
    assert Math.abs(canvOfs.left - naiveOfs.left) <= 1;
    assert Math.abs(canvOfs.bottom - naiveOfs.bottom) <= 1;
    assert Math.abs(canvOfs.right - naiveOfs.right) <= 1;
    assert Math.abs(canvOfs.top - naiveOfs.top) <= 1;

    if (log.isDebugEnabled()) {
      log.debug("intersection rectangle: " + Arrays.toString(srcRectangle));
      log.debug("intersection bounds: " + srcBounds + " (" + reqBounds + ")");
      log.debug(
          "Bound offsets: "
              + Arrays.toString(
                  new double[] {boundOfs.left, boundOfs.bottom, boundOfs.right, boundOfs.top}));
      log.debug(
          "Canvas size: " + Arrays.toString(canvasSize) + "(" + reqWidth + "," + reqHeight + ")");
      log.debug(
          "Canvas offsets: "
              + Arrays.toString(
                  new int[] {canvOfs.left, canvOfs.bottom, canvOfs.right, canvOfs.top}));
    }
  }
  /**
   * Initializes the layer, creating internal structures for calculating grid location and so forth.
   *
   * <p>Subclasses shall implement {@link #initializeInternal(GridSetBroker)} for anything else
   */
  @Override
  public final boolean initialize(GridSetBroker gridSetBroker) {

    if (this.expireCacheList == null) {
      this.expireCacheList = new ArrayList<ExpirationRule>(1);

      if (this.expireCache == null) {
        expireCacheList.add(new ExpirationRule(0, GWCVars.CACHE_NEVER_EXPIRE));
      } else {
        int expireCacheInt = Integer.parseInt(expireCache);
        if (expireCacheInt == GWCVars.CACHE_USE_WMS_BACKEND_VALUE) {
          saveExpirationHeaders = true;
        }
        expireCacheList.add(new ExpirationRule(0, expireCacheInt));
      }
    }

    if (this.expireClientsList == null) {
      this.expireClientsList = new ArrayList<ExpirationRule>(1);

      if (this.expireClients == null) {
        expireClientsList.add(new ExpirationRule(0, 7200));
      } else {
        int expireClientsInt = Integer.parseInt(expireClients);

        if (expireClientsInt == GWCVars.CACHE_USE_WMS_BACKEND_VALUE) {
          saveExpirationHeaders = true;
        } else if (expireClientsInt == GWCVars.CACHE_NEVER_EXPIRE) {
          // One year should do
          expireClientsInt = 3600 * 24 * 365;
        }
        expireClientsList.add(new ExpirationRule(0, expireClientsInt));
      }
    }

    try {
      // mimetypes
      this.formats = new ArrayList<MimeType>();
      if (mimeFormats != null) {
        for (String fmt : mimeFormats) {
          formats.add(MimeType.createFromFormat(fmt));
        }
      }
      if (formats.size() == 0) {
        formats.add(0, MimeType.createFromFormat("image/png"));
        formats.add(1, MimeType.createFromFormat("image/jpeg"));
      }
    } catch (GeoWebCacheException gwce) {
      log.error(gwce.getMessage());
      gwce.printStackTrace();
    }

    if (subSets == null) {
      subSets = new HashMap<String, GridSubset>();
    }

    if (this.gridSubsets != null) {
      Iterator<XMLGridSubset> iter = gridSubsets.iterator();
      while (iter.hasNext()) {
        XMLGridSubset xmlGridSubset = iter.next();
        GridSubset gridSubset = xmlGridSubset.getGridSubSet(gridSetBroker);

        if (gridSubset == null) {
          log.error(
              xmlGridSubset.getGridSetName()
                  + " is not known by the GridSetBroker, skipping for layer "
                  + name);
        } else {
          subSets.put(gridSubset.getName(), gridSubset);
        }
      }

      this.gridSubsets = null;
    }

    // Convert version 1.1.x and 1.0.x grid objects
    if (grids != null && !grids.isEmpty()) {
      Iterator<XMLOldGrid> iter = grids.values().iterator();
      while (iter.hasNext()) {
        GridSubset converted = iter.next().convertToGridSubset(gridSetBroker);
        subSets.put(converted.getSRS().toString(), converted);
      }

      // Null it for the garbage collector
      grids = null;
    }

    if (this.subSets.size() == 0) {
      subSets.put(
          gridSetBroker.WORLD_EPSG4326.getName(),
          GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG4326));
      subSets.put(
          gridSetBroker.WORLD_EPSG3857.getName(),
          GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG3857));
    }

    return initializeInternal(gridSetBroker);
  }
示例#18
0
  private void capabilityLayerInner(StringBuilder str, TileLayer layer)
      throws GeoWebCacheException {
    if (layer.isQueryable()) {
      str.append("    <Layer queryable=\"1\">\n");
    } else {
      str.append("    <Layer>\n");
    }

    str.append("      <Name>" + layer.getName() + "</Name>\n");

    if (layer.getMetaInformation() != null) {
      LayerMetaInformation metaInfo = layer.getMetaInformation();
      str.append("      <Title>" + metaInfo.getTitle() + "</Title>\n");
      str.append("      <Abstract>" + metaInfo.getDescription() + "</Abstract>\n");
    } else {
      str.append("      <Title>" + layer.getName() + "</Title>\n");
    }

    TreeSet<SRS> srsSet = new TreeSet<SRS>();
    StringBuilder boundingBoxStr = new StringBuilder();
    for (String gridSetId : layer.getGridSubsets()) {
      GridSubset curGridSubSet = layer.getGridSubset(gridSetId);
      SRS curSRS = curGridSubSet.getSRS();
      if (!srsSet.contains(curSRS)) {
        str.append("      <SRS>" + curSRS.toString() + "</SRS>\n");

        // Save bounding boxes for later
        String[] bs = boundsPrep(curGridSubSet.getCoverageBestFitBounds());
        boundingBoxStr.append(
            "      <BoundingBox SRS=\""
                + curGridSubSet.getSRS().toString()
                + "\" minx=\""
                + bs[0]
                + "\" miny=\""
                + bs[1]
                + "\" maxx=\""
                + bs[2]
                + "\" maxy=\""
                + bs[3]
                + "\"/>\n");

        srsSet.add(curSRS);
      }
    }

    GridSubset epsg4326GridSubSet = layer.getGridSubsetForSRS(SRS.getEPSG4326());
    if (null != epsg4326GridSubSet) {
      String[] bs = boundsPrep(epsg4326GridSubSet.getCoverageBestFitBounds());
      str.append(
          "      <LatLonBoundingBox minx=\""
              + bs[0]
              + "\" miny=\""
              + bs[1]
              + "\" maxx=\""
              + bs[2]
              + "\" maxy=\""
              + bs[3]
              + "\"/>\n");
    }

    // Bounding boxes gathered earlier
    str.append(boundingBoxStr);

    // WMS 1.1 Dimensions
    if (layer.getParameterFilters() != null) {
      StringBuilder dims = new StringBuilder();
      StringBuilder extents = new StringBuilder();
      for (ParameterFilter parameterFilter : layer.getParameterFilters()) {
        if (parameterFilter instanceof WMSDimensionProvider) {
          ((WMSDimensionProvider) parameterFilter).appendDimensionElement(dims, "      ");
          ((WMSDimensionProvider) parameterFilter).appendExtentElement(extents, "      ");
        }
      }

      if (dims.length() > 0 && extents.length() > 0) {
        str.append(dims);
        str.append(extents);
      }
    }

    // TODO style?
    str.append("    </Layer>\n");
  }
  @Test
  @SuppressWarnings({"rawtypes", "unchecked"})
  public void testParseMaplinkAndLayersWithGeoJSONFromJsonEmbedded()
      throws IOException, ParseException, com.vividsolutions.jts.io.ParseException {

    XMLConfiguration config = shared.getConfig();

    TileLayer tileLayer = config.getTileLayer(layerTemplate);
    GridSubset gridSubset = tileLayer.getGridSubset(gridSubsetName);

    MapLayerJSONParser layerJsonParser = new MapLayerJSONParser(props);

    MaplinkGeoJsonParser parser = new MaplinkGeoJsonParser();
    parser.setDebug(true);

    InputStream inp = MapProducer.class.getResourceAsStream("action_route_parcel.json");

    try {

      assertTrue(MapLinkGeoJsonParseContext.Default.getPm().buildMap);

      Map<String, ?> root = parser.parse(inp);

      assertTrue(root.size() != 0);
      assertTrue(root.get("layers") != null);
      assertTrue(root.get("maplink") != null);
      assertTrue(root.get("state") != null);

      assertTrue(root.get("layers") != null);
      assertTrue(((List<Map<String, Object>>) root.get("layers")).size() == 11);
      assertTrue(
          "geojson".equals(((List<Map<String, Object>>) root.get("layers")).get(10).get("type")));
      assertTrue(
          ((List<Map<String, Object>>) root.get("layers")).get(10).get(".data")
              instanceof FeatureCollection);
      FeatureCollection fc10 =
          (FeatureCollection) ((List<Map<String, Object>>) root.get("layers")).get(10).get(".data");
      FeatureIterator fi = fc10.features();

      assertTrue(fi.hasNext());

      Feature f = fc10.features().next();
      assertTrue(f != null);
      assertTrue(f.getProperty("prop0") != null);
      assertTrue(f.getProperty("prop0").getValue() != null);
      Object pv = f.getProperty("prop0").getValue();
      assertTrue(pv instanceof String);
      assertTrue("value0forPoints".equals(pv));
      assertTrue(f.getDefaultGeometryProperty() != null);
      GeometryAttribute g = f.getDefaultGeometryProperty();
      assertTrue(g.getValue() != null);
      Object gv = g.getValue();
      assertTrue(gv instanceof Point);
      Point pt = (Point) gv;

      System.out.println(pt.toText());

      Style style = null;
      new FeatureLayer(fc10, style);

      MapLink mapLink =
          layerJsonParser.parseMapLinkJSON(root, shared.getGf(), gridSubset.getResolutions());

      /* assertions */
      assertTrue(mapLink != null);
      assertTrue(mapLink.getScale() != null);

      assertTrue(mapLink.getCentre() != null);
      assertTrue(Double.valueOf(530163).equals(mapLink.getCentre().getX()));
      assertTrue(Double.valueOf(6754057).equals(mapLink.getCentre().getY()));

      assertTrue(Integer.valueOf(11).equals(mapLink.getZoom()));

      assertTrue(mapLink.getMapLinkLayers() != null);
      assertTrue(mapLink.getMapLinkLayers().size() == 4);

      assertTrue("base_35".equals(mapLink.getMapLinkLayers().get(0).getLayerid()));

      assertTrue(mapLink.getMapLinkLayers().get(0).getGeom() == null);

    } finally {
      inp.close();
    }
  }
 @Override
 public synchronized void addGridSubset(GridSubset gridSubset) {
   removeGridSubset(gridSubset.getName());
   gridSubsets.add(new XMLGridSubset(gridSubset));
   subSets.put(gridSubset.getName(), gridSubset);
 }
  void addTileLayers(GeoPackage geopkg, List<MapLayerInfo> mapLayers, WMSMapContent map)
      throws IOException {

    if (mapLayers.isEmpty()) {
      return;
    }

    // figure out a name for the file entry
    String tileEntryName = null;
    Map formatOpts = map.getRequest().getFormatOptions();
    if (formatOpts.containsKey("tileset_name")) {
      tileEntryName = (String) formatOpts.get("tileset_name");
    }
    if (tileEntryName == null) {
      tileEntryName = map.getTitle();
    }
    if (tileEntryName == null && mapLayers.size() == 1) {
      Iterator<MapLayerInfo> it = mapLayers.iterator();
      tileEntryName = it.next().getLayerInfo().getName();
    }

    GridSubset gridSubset = findBestGridSubset(map);
    int[] minmax = findMinMaxZoom(gridSubset, map);

    BoundingBox bbox = bbox(map);

    TileEntry e = new TileEntry();
    e.setTableName(tileEntryName);

    if (mapLayers.size() == 1) {
      ResourceInfo r = mapLayers.get(0).getResource();
      e.setIdentifier(r.getTitle());
      e.setDescription(r.getAbstract());
    }
    e.setBounds(
        new ReferencedEnvelope(
            findTileBounds(gridSubset, bbox, minmax[0]), map.getCoordinateReferenceSystem()));
    e.setSrid(srid(map));

    GridSet gridSet = gridSubset.getGridSet();
    for (int z = minmax[0]; z < minmax[1]; z++) {
      Grid g = gridSet.getGrid(z);

      TileMatrix m = new TileMatrix();
      m.setZoomLevel(z);
      m.setMatrixWidth((int) g.getNumTilesWide());
      m.setMatrixHeight((int) g.getNumTilesHigh());
      m.setTileWidth(gridSubset.getTileWidth());
      m.setTileHeight(gridSubset.getTileHeight());

      // TODO: not sure about this
      m.setXPixelSize(g.getResolution());
      m.setYPixelSize(g.getResolution());
      // m.setXPixelSize(gridSet.getPixelSize());
      // m.setYPixelSize(gridSet.getPixelSize());

      e.getTileMatricies().add(m);
    }

    // figure out the actual bounds of the tiles to be renderered
    LOGGER.fine("Creating tile entry" + e.getTableName());
    geopkg.create(e);

    // create a prototype getmap request
    GetMapRequest req = new GetMapRequest();
    OwsUtils.copy(map.getRequest(), req, GetMapRequest.class);
    req.setLayers(mapLayers);

    String imageFormat =
        formatOpts.containsKey("format") ? parseFormatFromOpts(formatOpts) : findBestFormat(map);

    req.setFormat(imageFormat);
    req.setWidth(gridSubset.getTileWidth());
    req.setHeight(gridSubset.getTileHeight());

    // count tiles as we generate them
    int ntiles = 0;

    // flag determining if tile row indexes we store in database should be inverted
    boolean flipy = Boolean.valueOf((String) formatOpts.get("flipy"));
    for (int z = minmax[0]; z < minmax[1]; z++) {
      long[] intersect = gridSubset.getCoverageIntersection(z, bbox);
      for (long x = intersect[0]; x <= intersect[2]; x++) {
        for (long y = intersect[1]; y <= intersect[3]; y++) {
          BoundingBox box = gridSubset.boundsFromIndex(new long[] {x, y, z});
          req.setBbox(new Envelope(box.getMinX(), box.getMaxX(), box.getMinY(), box.getMaxY()));

          Tile t = new Tile();
          t.setZoom(z);
          t.setColumn((int) x);
          t.setRow((int) (flipy ? gridSubset.getNumTilesHigh(z) - (y + 1) : y));

          WebMap result = webMapService.getMap(req);
          t.setData(toBytes(result));

          geopkg.add(e, t);

          // images we encode are actually kept around, we need to clean them up
          if (ntiles++ == TILE_CLEANUP_INTERVAL) {
            cleanUpImages();
            ntiles = 0;
          }
        }
      }
    }
  }