@Test
  public void testWCS10GetCoverageDifferentCrs() throws Exception {
    // xMin,yMin 5988504.35,851278.90 : xMax,yMax 7585113.55,1950872.01
    // xMin,yMin -95.1193,42.2802 : xMax,yMax -71.295,53.73
    GetCoverageType gc = Wcs10Factory.eINSTANCE.createGetCoverageType();
    net.opengis.wcs10.SpatialSubsetType spatialSubset =
        Wcs10Factory.eINSTANCE.createSpatialSubsetType();

    CoordinateReferenceSystem crs = CRS.decode("EPSG:3348", false);
    CoordinateReferenceSystem logCrs = CRS.decode("EPSG:4326", false);
    GeneralEnvelope env =
        new GeneralEnvelope(
            new double[] {5988504.35, 851278.90}, new double[] {7585113.55, 1950872.01});
    env.setCoordinateReferenceSystem(crs);
    BoundingBox bbox = new ReferencedEnvelope(42.2802, 53.73, -95.1193, -71.295, logCrs);

    spatialSubset.getEnvelope().clear();
    spatialSubset.getEnvelope().add(env);
    net.opengis.wcs10.DomainSubsetType domainSubset =
        Wcs10Factory.eINSTANCE.createDomainSubsetType();
    domainSubset.setSpatialSubset(spatialSubset);

    gc.setSourceCoverage("acme:foo");
    gc.setDomainSubset(domainSubset);

    callback.operationDispatched(new Request(), op("GetCoverage", "WCS", "1.0.0", gc));

    assertEquals("acme:foo", data.getResources().get(0));
    BBoxAsserts.assertEqualsBbox(bbox, data.getBbox(), 0.1);
  }
  private GeneralEnvelope getResultEnvelope(
      final List<RasterQueryInfo> queryInfos, final GridEnvelope mosaicGeometry) {

    // use the same queryInfo used by setMosaicLocations
    final RasterQueryInfo baseQueryInfo = RasterUtils.findLowestResolution(queryInfos);

    GeneralEnvelope finalEnvelope = null;
    // if (queryInfos.size() == 1) {
    // finalEnvelope = queryInfos.get(0).getResultEnvelope();
    // } else {
    int rasterIndex = baseQueryInfo.getRasterIndex();
    int pyramidLevel = baseQueryInfo.getPyramidLevel();
    MathTransform rasterToModel = rasterInfo.getRasterToModel(rasterIndex, pyramidLevel);
    CoordinateReferenceSystem coverageCrs = rasterInfo.getCoverageCrs();
    GeneralEnvelope mosaicGeometryEnv = new GeneralEnvelope(coverageCrs);
    mosaicGeometryEnv.setEnvelope(
        mosaicGeometry.getLow(0),
        mosaicGeometry.getLow(1),
        1 + mosaicGeometry.getHigh(0),
        1 + mosaicGeometry.getHigh(1));
    try {
      finalEnvelope = CRS.transform(rasterToModel, mosaicGeometryEnv);
      finalEnvelope.setCoordinateReferenceSystem(coverageCrs);
    } catch (TransformException e) {
      throw new RuntimeException(e);
    }
    // }

    // double[] resolution = baseQueryInfo.getResolution();
    // finalEnvelope = toPixelCenter(resolution, finalEnvelope);
    return finalEnvelope;
  }
  @Test
  public void testWCS10GetCoverage() throws Exception {
    GetCoverageType gc = Wcs10Factory.eINSTANCE.createGetCoverageType();
    net.opengis.wcs10.SpatialSubsetType spatialSubset =
        Wcs10Factory.eINSTANCE.createSpatialSubsetType();

    CoordinateReferenceSystem crs = CRS.decode("EPSG:4326");
    GeneralEnvelope env =
        new GeneralEnvelope(new double[] {-123.4, 48.2}, new double[] {-120.9, 50.1});
    env.setCoordinateReferenceSystem(crs);
    BoundingBox bbox = new ReferencedEnvelope(env);

    spatialSubset.getEnvelope().clear();
    spatialSubset.getEnvelope().add(env);
    net.opengis.wcs10.DomainSubsetType domainSubset =
        Wcs10Factory.eINSTANCE.createDomainSubsetType();
    domainSubset.setSpatialSubset(spatialSubset);

    gc.setSourceCoverage("acme:foo");
    gc.setDomainSubset(domainSubset);

    callback.operationDispatched(new Request(), op("GetCoverage", "WCS", "1.0.0", gc));

    assertEquals("acme:foo", data.getResources().get(0));
    BBoxAsserts.assertEqualsBbox(bbox, data.getBbox(), 0.1);
  }
  @Test
  public void testWCS11GetCoverage() throws Exception {
    net.opengis.wcs11.GetCoverageType gc = Wcs11Factory.eINSTANCE.createGetCoverageType();

    CoordinateReferenceSystem crs = CRS.decode("EPSG:4326");
    GeneralEnvelope env =
        new GeneralEnvelope(new double[] {48.2, -123.4}, new double[] {50.1, -120.9});
    env.setCoordinateReferenceSystem(crs);
    BoundingBox bbox = new ReferencedEnvelope(env);
    net.opengis.ows11.BoundingBoxType wcsBbox =
        net.opengis.ows11.Ows11Factory.eINSTANCE.createBoundingBoxType();
    wcsBbox.setLowerCorner(Arrays.asList(48.2d, -123.4d));
    wcsBbox.setUpperCorner(Arrays.asList(50.1d, -120.9d));
    // wcsBbox.setCrs("urn:ogc:def:crs:OGC:1.3:CRS84");
    wcsBbox.setCrs("urn:ogc:def:crs:EPSG:4326");
    net.opengis.wcs11.DomainSubsetType domainSubset =
        Wcs11Factory.eINSTANCE.createDomainSubsetType();
    domainSubset.setBoundingBox(wcsBbox);

    gc.setDomainSubset(domainSubset);

    CodeType c = Ows11Factory.eINSTANCE.createCodeType();
    c.setValue("acme:bar");
    gc.setIdentifier(c);

    callback.operationDispatched(new Request(), op("GetCoverage", "WCS", "1.1.0", gc));
    assertEquals("acme:bar", data.getResources().get(0));
    BBoxAsserts.assertEqualsBbox(bbox, data.getBbox(), 0.1);
  }
 /**
  * This method is responsible for computing the resolutions in for the provided grid geometry in
  * the provided crs.
  *
  * <p>It is worth to note that the returned resolution array is of length of 2 and it always is
  * lon, lat for the moment.<br>
  * It might be worth to remove the axes reordering code when we are confident enough with the code
  * to handle the north-up crs.
  *
  * <p>TODO use orthodromic distance?
  *
  * @param envelope the GeneralEnvelope
  * @param dim
  * @param crs
  * @throws DataSourceException
  */
 protected static final double[] getResolution(
     GeneralEnvelope envelope, Rectangle2D dim, CoordinateReferenceSystem crs)
     throws DataSourceException {
   double[] requestedRes = null;
   try {
     if (dim != null && envelope != null && crs != null) {
       // do we need to transform the originalEnvelope?
       final CoordinateReferenceSystem envelopeCrs2D =
           CRS.getHorizontalCRS(envelope.getCoordinateReferenceSystem());
       if (envelopeCrs2D != null && !CRS.equalsIgnoreMetadata(crs, envelopeCrs2D)) {
         CoordinateOperationFactory operationFactory = CRS.getCoordinateOperationFactory(true);
         CoordinateOperation op = operationFactory.createOperation(envelopeCrs2D, crs);
         envelope = CRS.transform(op, envelope);
         envelope.setCoordinateReferenceSystem(crs);
       }
       requestedRes = new double[2];
       requestedRes[0] = envelope.getSpan(0) / dim.getWidth();
       requestedRes[1] = envelope.getSpan(1) / dim.getHeight();
     }
     return requestedRes;
   } catch (TransformException e) {
     throw new DataSourceException("Unable to get resolution", e);
   } catch (FactoryException e) {
     throw new DataSourceException("Unable to get resolution", e);
   }
 }
 public void appendLoggingGeometries(String geomName, GeneralEnvelope env) {
   if (LOGGER.isLoggable(GEOM_LEVEL)) {
     StringBuilder sb = getGeom(geomName);
     sb.append(
         "  (("
             + env.getMinimum(0)
             + " "
             + env.getMinimum(1)
             + ", "
             + env.getMaximum(0)
             + " "
             + env.getMinimum(1)
             + ", "
             + env.getMaximum(0)
             + " "
             + env.getMaximum(1)
             + ", "
             + env.getMinimum(0)
             + " "
             + env.getMaximum(1)
             + ", "
             + env.getMinimum(0)
             + " "
             + env.getMinimum(1)
             + ")),");
   }
 }
  private static ReferencedEnvelope toReferencedEnvelope(GeneralEnvelope envelope) {
    double minx = envelope.getMinimum(0);
    double maxx = envelope.getMaximum(0);
    double miny = envelope.getMinimum(1);
    double maxy = envelope.getMaximum(1);
    CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();

    ReferencedEnvelope refEnv = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
    return refEnv;
  }
 private GeneralEnvelope toPixelCenter(double[] resolution, GeneralEnvelope pixelCornerEnv) {
   double deltaX = resolution[0] / 2;
   double deltaY = resolution[1] / 2;
   GeneralEnvelope env = new GeneralEnvelope(pixelCornerEnv.getCoordinateReferenceSystem());
   env.setEnvelope(
       pixelCornerEnv.getMinimum(0) + deltaX,
       pixelCornerEnv.getMinimum(1) + deltaY,
       pixelCornerEnv.getMaximum(0) - deltaX,
       pixelCornerEnv.getMaximum(1) - deltaY);
   return env;
 }
Example #9
0
  @Test
  public void testDomainSubsetRxRy() throws Exception {
    // get base  coverage
    final GridCoverage baseCoverage =
        catalog.getCoverageByName(TASMANIA_BM.getLocalPart()).getGridCoverage(null, null);
    final AffineTransform2D expectedTx =
        (AffineTransform2D) baseCoverage.getGridGeometry().getGridToCRS();
    final GeneralEnvelope originalEnvelope = (GeneralEnvelope) baseCoverage.getEnvelope();
    final GeneralEnvelope newEnvelope = new GeneralEnvelope(originalEnvelope);
    newEnvelope.setEnvelope(
        originalEnvelope.getMinimum(0),
        originalEnvelope.getMaximum(1) - originalEnvelope.getSpan(1) / 2,
        originalEnvelope.getMinimum(0) + originalEnvelope.getSpan(0) / 2,
        originalEnvelope.getMaximum(1));

    final MathTransform cornerWorldToGrid =
        PixelTranslation.translate(expectedTx, PixelInCell.CELL_CENTER, PixelInCell.CELL_CORNER);
    final GeneralGridEnvelope expectedGridEnvelope =
        new GeneralGridEnvelope(
            CRS.transform(cornerWorldToGrid.inverse(), newEnvelope),
            PixelInCell.CELL_CORNER,
            false);
    final StringBuilder envelopeBuilder = new StringBuilder();
    envelopeBuilder.append(newEnvelope.getMinimum(0)).append(",");
    envelopeBuilder.append(newEnvelope.getMinimum(1)).append(",");
    envelopeBuilder.append(newEnvelope.getMaximum(0)).append(",");
    envelopeBuilder.append(newEnvelope.getMaximum(1));

    Map<String, Object> raw = baseMap();
    final String layerID = getLayerId(TASMANIA_BM);
    raw.put("sourcecoverage", layerID);
    raw.put("version", "1.0.0");
    raw.put("format", "image/geotiff");
    raw.put("BBox", envelopeBuilder.toString());
    raw.put("crs", "EPSG:4326");
    raw.put("resx", Double.toString(expectedTx.getScaleX()));
    raw.put("resy", Double.toString(Math.abs(expectedTx.getScaleY())));

    final GridCoverage[] coverages = executeGetCoverageKvp(raw);
    final GridCoverage2D result = (GridCoverage2D) coverages[0];
    assertTrue(coverages.length == 1);
    final AffineTransform2D tx = (AffineTransform2D) result.getGridGeometry().getGridToCRS();
    assertEquals("resx", expectedTx.getScaleX(), tx.getScaleX(), 1E-6);
    assertEquals("resx", Math.abs(expectedTx.getScaleY()), Math.abs(tx.getScaleY()), 1E-6);

    final GridEnvelope gridEnvelope = result.getGridGeometry().getGridRange();
    assertEquals("w", 180, gridEnvelope.getSpan(0));
    assertEquals("h", 180, gridEnvelope.getSpan(1));
    assertEquals("grid envelope", expectedGridEnvelope, gridEnvelope);

    // dispose
    CoverageCleanerCallback.disposeCoverage(baseCoverage);
    CoverageCleanerCallback.disposeCoverage(coverages[0]);
  }
  /**
   * Transforms the referenced envelope to the specified coordinate reference system using the
   * specified amount of points.
   *
   * <p>This method can handle the case where the envelope contains the North or South pole, or when
   * it cross the &plusmn;180� longitude.
   *
   * @param targetCRS The target coordinate reference system.
   * @param lenient {@code true} if datum shift should be applied even if there is insuffisient
   *     information. Otherwise (if {@code false}), an exception is thrown in such case.
   * @param numPointsForTransformation The number of points to use for sampling the envelope.
   * @return The transformed envelope.
   * @throws FactoryException if the math transform can't be determined.
   * @throws TransformException if at least one coordinate can't be transformed.
   * @see CRS#transform(CoordinateOperation, org.opengis.geometry.Envelope)
   * @since 2.3
   */
  public ReferencedEnvelope transform(
      final CoordinateReferenceSystem targetCRS,
      final boolean lenient,
      final int numPointsForTransformation)
      throws TransformException, FactoryException {
    if (crs == null) {
      if (isEmpty()) {
        // We don't have a CRS yet because we are still empty, being empty is
        // something we can represent in the targetCRS
        return new ReferencedEnvelope(targetCRS);
      } else {
        // really this is a the code that created this ReferencedEnvelope
        throw new NullPointerException(
            "Unable to transform referenced envelope, crs has not yet been provided.");
      }
    }
    if (getDimension() != targetCRS.getCoordinateSystem().getDimension()) {
      if (lenient) {
        return JTS.transformTo3D(this, targetCRS, lenient, numPointsForTransformation);
      } else {
        throw new MismatchedDimensionException(
            Errors.format(
                ErrorKeys.MISMATCHED_DIMENSION_$3,
                crs.getName().getCode(),
                new Integer(getDimension()),
                new Integer(targetCRS.getCoordinateSystem().getDimension())));
      }
    }
    /*
     * Gets a first estimation using an algorithm capable to take singularity in account
     * (North pole, South pole, 180� longitude). We will expand this initial box later.
     */
    CoordinateOperationFactory coordinateOperationFactory =
        CRS.getCoordinateOperationFactory(lenient);

    final CoordinateOperation operation =
        coordinateOperationFactory.createOperation(crs, targetCRS);
    final GeneralEnvelope transformed = CRS.transform(operation, this);
    transformed.setCoordinateReferenceSystem(targetCRS);

    /*
     * Now expands the box using the usual utility methods.
     */
    final ReferencedEnvelope target = new ReferencedEnvelope(transformed);
    final MathTransform transform = operation.getMathTransform();
    JTS.transform(this, target, transform, numPointsForTransformation);

    return target;
  }
Example #11
0
 /**
  * Convert the crop envelope into a polygon and the use the world-to-grid transform to get a ROI
  * for the source coverage.
  */
 public static Polygon getPolygon(final GeneralEnvelope env, final GeometryFactory gf)
     throws IllegalStateException, MismatchedDimensionException {
   final Rectangle2D rect = env.toRectangle2D();
   final Coordinate[] coord =
       new Coordinate[] {
         new Coordinate(rect.getMinX(), rect.getMinY()),
         new Coordinate(rect.getMinX(), rect.getMaxY()),
         new Coordinate(rect.getMaxX(), rect.getMaxY()),
         new Coordinate(rect.getMaxX(), rect.getMinY()),
         new Coordinate(rect.getMinX(), rect.getMinY())
       };
   final LinearRing ring = gf.createLinearRing(coord);
   final Polygon modelSpaceROI = new Polygon(ring, null, gf);
   // check that we have the same thing here
   assert modelSpaceROI
       .getEnvelopeInternal()
       .equals(new ReferencedEnvelope(rect, env.getCoordinateReferenceSystem()));
   return modelSpaceROI;
 }
  private GridCoverage2D convertImageToGridCoverage(
      ReferencedEnvelope requestBBox, BufferedImage image) throws RenderException {
    Envelope env = requestBBox;
    GeneralEnvelope gtEnv =
        new GeneralEnvelope(
            new double[] {env.getMinX(), env.getMinY()},
            new double[] {env.getMaxX(), env.getMaxY()});

    try {
      gtEnv.setCoordinateReferenceSystem(requestBBox.getCoordinateReferenceSystem());
    } catch (Exception e) {
      throw wrapException(e);
    }

    GridCoverageFactory factory = new GridCoverageFactory();

    GridCoverage2D gc =
        (GridCoverage2D) factory.create("GridCoverage", image, gtEnv); // $NON-NLS-1$
    return gc;
  }
Example #13
0
  /**
   * Tests the transformations of an envelope when the two CRS have identify transforms but
   * different datum names
   */
  @Test
  public void testEnvelopeTransformation2() throws FactoryException, TransformException {
    final CoordinateReferenceSystem WGS84Altered = CRS.parseWKT(WKT.WGS84_ALTERED);
    final CoordinateReferenceSystem WGS84 = DefaultGeographicCRS.WGS84;
    final MathTransform crsTransform = CRS.findMathTransform(WGS84, WGS84Altered, true);
    assertTrue(crsTransform.isIdentity());

    final GeneralEnvelope firstEnvelope;
    firstEnvelope = new GeneralEnvelope(new double[] {-124, 42}, new double[] {-122, 43});
    firstEnvelope.setCoordinateReferenceSystem(WGS84);

    // this triggered a assertion error in GEOT-2934
    Envelope transformed = CRS.transform(firstEnvelope, WGS84Altered);

    // check the envelope is what we expect
    assertEquals(transformed.getCoordinateReferenceSystem(), WGS84Altered);
    double EPS = 1e-9;
    assertEquals(transformed.getMinimum(0), firstEnvelope.getMinimum(0), EPS);
    assertEquals(transformed.getMinimum(1), firstEnvelope.getMinimum(1), EPS);
    assertEquals(transformed.getMaximum(0), firstEnvelope.getMaximum(0), EPS);
    assertEquals(transformed.getMaximum(1), firstEnvelope.getMaximum(1), EPS);
  }
Example #14
0
  /** Tests the transformations of an envelope. */
  @Test
  public void testEnvelopeTransformation() throws FactoryException, TransformException {
    final CoordinateReferenceSystem mapCRS = CRS.parseWKT(WKT.UTM_10N);
    final CoordinateReferenceSystem WGS84 = DefaultGeographicCRS.WGS84;
    final MathTransform crsTransform = CRS.findMathTransform(WGS84, mapCRS, true);
    assertFalse(crsTransform.isIdentity());

    final GeneralEnvelope firstEnvelope, transformedEnvelope, oldEnvelope;
    firstEnvelope = new GeneralEnvelope(new double[] {-124, 42}, new double[] {-122, 43});
    firstEnvelope.setCoordinateReferenceSystem(WGS84);

    transformedEnvelope = CRS.transform(crsTransform, firstEnvelope);
    transformedEnvelope.setCoordinateReferenceSystem(mapCRS);

    oldEnvelope = CRS.transform(crsTransform.inverse(), transformedEnvelope);
    oldEnvelope.setCoordinateReferenceSystem(WGS84);

    assertTrue(oldEnvelope.contains(firstEnvelope, true));
    assertTrue(oldEnvelope.equals(firstEnvelope, 0.02, true));
  }
Example #15
0
  /**
   * @param env GeneralEnvelope
   * @return Polygon object with the same boundary as env
   */
  protected Polygon polyFromEnvelope(GeneralEnvelope env) {
    GeometryFactory factory = new GeometryFactory();

    Coordinate[] coords =
        new Coordinate[] {
          new Coordinate(env.getMinimum(0), env.getMinimum(1)),
          new Coordinate(env.getMinimum(0), env.getMaximum(1)),
          new Coordinate(env.getMaximum(0), env.getMaximum(1)),
          new Coordinate(env.getMaximum(0), env.getMinimum(1)),
          new Coordinate(env.getMinimum(0), env.getMinimum(1))
        };

    return factory.createPolygon(factory.createLinearRing(coords), new LinearRing[0]);
  }
  /**
   * <strong>Cropping</strong><br>
   * The crop operation is responsible for selecting geographic subareas of the source coverage.
   *
   * @param coverage Coverage
   * @param sourceEnvelope GeneralEnvelope
   * @param sourceCRS CoordinateReferenceSystem
   * @param destinationEnvelopeInSourceCRS GeneralEnvelope
   * @return GridCoverage2D
   * @throws WcsException
   */
  public static GridCoverage2D crop(
      final Coverage coverage,
      final GeneralEnvelope sourceEnvelope,
      final CoordinateReferenceSystem sourceCRS,
      final GeneralEnvelope destinationEnvelopeInSourceCRS,
      final Boolean conserveEnvelope)
      throws WcsException {
    // ///////////////////////////////////////////////////////////////////
    //
    // CROP
    //
    //
    // ///////////////////////////////////////////////////////////////////
    final GridCoverage2D croppedGridCoverage;

    // intersect the envelopes
    final GeneralEnvelope intersectionEnvelope =
        new GeneralEnvelope(destinationEnvelopeInSourceCRS);
    intersectionEnvelope.setCoordinateReferenceSystem(sourceCRS);
    intersectionEnvelope.intersect((GeneralEnvelope) sourceEnvelope);

    // dow we have something to show?
    if (intersectionEnvelope.isEmpty()) {
      throw new WcsException("The Intersection is null. Check the requested BBOX!");
    }

    if (!intersectionEnvelope.equals((GeneralEnvelope) sourceEnvelope)) {
      // get the cropped grid geometry
      // final GridGeometry2D cropGridGeometry = getCroppedGridGeometry(
      // intersectionEnvelope, gridCoverage);

      /* Operations.DEFAULT.crop(coverage, intersectionEnvelope) */
      final ParameterValueGroup param = (ParameterValueGroup) cropParams.clone();
      param.parameter("Source").setValue(coverage);
      param.parameter("Envelope").setValue(intersectionEnvelope);
      // param.parameter("ConserveEnvelope").setValue(conserveEnvelope);

      croppedGridCoverage = (GridCoverage2D) cropFactory.doOperation(param, hints);
    } else {
      croppedGridCoverage = (GridCoverage2D) coverage;
    }

    // prefetch to be faster afterwards.
    // This step is important since at this stage we might be loading tiles
    // from disk
    croppedGridCoverage.prefetch(intersectionEnvelope.toRectangle2D());

    return croppedGridCoverage;
  }
Example #17
0
  @SuppressWarnings({"rawtypes", "unchecked"})
  @Test
  @Ignore
  public void IASI() throws Exception {

    final URL testURL = TestData.url(this, "IASI_C_EUMP_20121120062959_31590_eps_o_l2.nc");
    final Hints hints =
        new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, CRS.decode("EPSG:4326", true));
    // Get format
    final AbstractGridFormat format =
        (AbstractGridFormat) GridFormatFinder.findFormat(testURL, hints);
    final NetCDFReader reader = (NetCDFReader) format.getReader(testURL, hints);
    assertNotNull(format);
    assertNotNull(reader);
    try {
      String[] names = reader.getGridCoverageNames();
      assertNotNull(names);
      assertEquals(names.length, 20);

      // surface_emissivity
      final String coverageName = "surface_emissivity";
      final String[] metadataNames = reader.getMetadataNames(coverageName);
      assertNotNull(metadataNames);
      assertEquals(14, metadataNames.length);

      // Parsing metadata values
      assertEquals("false", reader.getMetadataValue(coverageName, "HAS_TIME_DOMAIN"));
      assertEquals("false", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
      assertEquals("true", reader.getMetadataValue(coverageName, "HAS_NEW_DOMAIN"));

      // additional domains
      final String newDomain = reader.getMetadataValue(coverageName, "NEW_DOMAIN");
      assertNotNull(metadataNames);
      final String[] newDomainValues = newDomain.split(",");
      assertNotNull(newDomainValues);
      assertEquals(12, newDomainValues.length);
      assertEquals(13.063399669990758, Double.valueOf(newDomainValues[11]), 1E-6);
      assertEquals(3.6231999084702693, Double.valueOf(newDomainValues[0]), 1E-6);

      // subsetting the envelope
      final ParameterValue<GridGeometry2D> gg =
          AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
      final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope(coverageName);
      final GeneralEnvelope reducedEnvelope =
          new GeneralEnvelope(
              new double[] {
                originalEnvelope.getLowerCorner().getOrdinate(0),
                originalEnvelope.getLowerCorner().getOrdinate(1)
              },
              new double[] {
                originalEnvelope.getMedian().getOrdinate(0),
                originalEnvelope.getMedian().getOrdinate(1)
              });
      reducedEnvelope.setCoordinateReferenceSystem(
          reader.getCoordinateReferenceSystem(coverageName));

      // Selecting bigger gridRange for a zoomed result
      final Dimension dim = new Dimension();
      GridEnvelope gridRange = reader.getOriginalGridRange(coverageName);
      dim.setSize(gridRange.getSpan(0) * 4.0, gridRange.getSpan(1) * 2.0);
      final Rectangle rasterArea = ((GridEnvelope2D) gridRange);
      rasterArea.setSize(dim);
      final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
      gg.setValue(new GridGeometry2D(range, reducedEnvelope));

      // specify additional Dimensions
      Set<ParameterDescriptor<List>> params = reader.getDynamicParameters(coverageName);
      ParameterValue<List> new_ = null;
      for (ParameterDescriptor param : params) {
        if (param.getName().getCode().equalsIgnoreCase("NEW")) {
          new_ = param.createValue();
          new_.setValue(
              new ArrayList() {
                {
                  add(Double.valueOf(newDomainValues[11]));
                }
              });
        }
      }

      GeneralParameterValue[] values = new GeneralParameterValue[] {gg, new_};
      GridCoverage2D coverage = reader.read(coverageName, values);
      assertNotNull(coverage);
      if (TestData.isInteractiveTest()) {
        coverage.show();
      } else {
        PlanarImage.wrapRenderedImage(coverage.getRenderedImage()).getTiles();
      }
    } finally {
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }
Example #18
0
  /*
   * (non-Javadoc)
   *
   * @see org.geotools.gce.imagemosaic.jdbc.JDBCAccess#startTileDecoders(java.awt.Rectangle,
   *      org.geotools.geometry.GeneralEnvelope,
   *      org.geotools.gce.imagemosaic.jdbc.ImageLevelInfo,
   *      java.util.concurrent.LinkedBlockingQueue)
   */
  public void startTileDecoders(
      Rectangle pixelDimension,
      GeneralEnvelope requestEnvelope,
      ImageLevelInfo levelInfo,
      LinkedBlockingQueue<TileQueueElement> tileQueue,
      GridCoverageFactory coverageFactory)
      throws IOException {
    Date start = new Date();
    Connection con = null;
    List<ImageDecoderThread> threads = new ArrayList<ImageDecoderThread>();
    ExecutorService pool = getExecutorServivicePool();

    String statementString = getGridSelectStatement(levelInfo);

    try {
      con = dataSource.getConnection();

      PreparedStatement s = con.prepareStatement(statementString);
      setGridSelectParams(s, requestEnvelope, levelInfo);

      ResultSet r = s.executeQuery();

      while (r.next()) {
        byte[] tileBytes = getTileBytes(r);
        Envelope env = getEnvelopeFromResultSet(r);
        String location = r.getString(config.getKeyAttributeNameInSpatialTable());

        Rectangle2D tmp =
            new Rectangle2D.Double(env.getMinX(), env.getMinY(), env.getWidth(), env.getHeight());
        GeneralEnvelope tileGeneralEnvelope = new GeneralEnvelope(tmp);
        tileGeneralEnvelope.setCoordinateReferenceSystem(
            requestEnvelope.getCoordinateReferenceSystem());

        ImageDecoderThread thread =
            new ImageDecoderThread(
                tileBytes,
                location,
                tileGeneralEnvelope,
                pixelDimension,
                requestEnvelope,
                levelInfo,
                tileQueue,
                config);
        //				thread.start();
        threads.add(thread);
        pool.execute(thread);
      }

      ;
      r.close();
      s.close();

      // if (con.getAutoCommit() == false) {
      // con.commit();
      // }

      con.close();
    } catch (SQLException e) {
      try {
        // if (con.getAutoCommit() == false) {
        // con.rollback();
        // }

        con.close();
      } catch (SQLException e1) {
      }

      LOGGER.log(Level.SEVERE, e.getMessage(), e);
      throw new IOException(e);
    }

    if (LOGGER.isLoggable(Level.INFO))
      LOGGER.info(
          "Getting "
              + threads.size()
              + " Tiles needs "
              + ((new Date()).getTime() - start.getTime())
              + " millisecs");

    // wait for all threads dto finish and write end marker
    pool.shutdown();
    try {
      pool.awaitTermination(3600, TimeUnit.SECONDS); // wait for one hour
    } catch (InterruptedException e) {
      throw new RuntimeException(e.getLocalizedMessage());
    }

    //		for (AbstractThread thread : threads) {
    //			try {
    //				thread.join();
    //			} catch (InterruptedException e) {
    //				throw new RuntimeException(e.getLocalizedMessage());
    //			}
    //		}

    tileQueue.add(TileQueueElement.ENDELEMENT);

    if (LOGGER.isLoggable(Level.INFO))
      LOGGER.info(
          "Getting and decoding  "
              + threads.size()
              + " Tiles needs "
              + ((new Date()).getTime() - start.getTime())
              + " millisecs");
  }
Example #19
0
  @Test
  public void NetCDFTestOn4DcoveragesWithImposedSchemas()
      throws NoSuchAuthorityCodeException, FactoryException, IOException, ParseException {
    File mosaic = new File(TestData.file(this, "."), "NetCDFTestOn4DcoveragesWithImposedSchemas");
    if (mosaic.exists()) {
      FileUtils.deleteDirectory(mosaic);
    }
    assertTrue(mosaic.mkdirs());

    File file = TestData.file(this, "O3NO2-noZ.nc");
    File auxFile = TestData.file(this, "O3NO2-noZ.xml");
    FileUtils.copyFileToDirectory(file, mosaic);
    FileUtils.copyFileToDirectory(auxFile, mosaic);
    file = new File(mosaic, "O3NO2-noZ.nc");

    final Hints hints =
        new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, CRS.decode("EPSG:4326", true));
    hints.put(
        Utils.AUXILIARY_FILES_PATH,
        new File(mosaic, "O3NO2-noZ.xml").getAbsolutePath()); // impose def

    // Get format
    final AbstractGridFormat format =
        (AbstractGridFormat) GridFormatFinder.findFormat(file.toURI().toURL(), hints);
    final NetCDFReader reader = (NetCDFReader) format.getReader(file.toURI().toURL(), hints);

    assertNotNull(format);
    try {
      String[] names = reader.getGridCoverageNames();
      for (String coverageName : names) {

        final String[] metadataNames = reader.getMetadataNames(coverageName);
        assertNotNull(metadataNames);
        assertEquals(metadataNames.length, 12);

        // Parsing metadata values
        assertEquals("true", reader.getMetadataValue(coverageName, "HAS_TIME_DOMAIN"));
        final String timeMetadata = reader.getMetadataValue(coverageName, "TIME_DOMAIN");
        assertEquals(
            "2012-04-01T00:00:00.000Z/2012-04-01T00:00:00.000Z,2012-04-01T01:00:00.000Z/2012-04-01T01:00:00.000Z",
            timeMetadata);
        assertNotNull(timeMetadata);
        assertEquals(
            "2012-04-01T00:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MINIMUM"));
        assertEquals(
            "2012-04-01T01:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MAXIMUM"));

        if (coverageName.equalsIgnoreCase("O3")) {
          assertEquals("true", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
          final String elevationMetadata =
              reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN");
          assertNotNull(elevationMetadata);
          assertEquals("10.0/10.0,450.0/450.0", elevationMetadata);
          assertEquals(2, elevationMetadata.split(",").length);
          assertEquals("10.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MINIMUM"));
          assertEquals("450.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MAXIMUM"));
        } else {
          // Note that This sample doesn't have elevation for NO2
          assertEquals("false", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
          final String elevationMetadata =
              reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN");
          assertNull(elevationMetadata);
        }

        // subsetting the envelope
        final ParameterValue<GridGeometry2D> gg =
            AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope(coverageName);
        final GeneralEnvelope reducedEnvelope =
            new GeneralEnvelope(
                new double[] {
                  originalEnvelope.getLowerCorner().getOrdinate(0),
                  originalEnvelope.getLowerCorner().getOrdinate(1)
                },
                new double[] {
                  originalEnvelope.getMedian().getOrdinate(0),
                  originalEnvelope.getMedian().getOrdinate(1)
                });
        reducedEnvelope.setCoordinateReferenceSystem(
            reader.getCoordinateReferenceSystem(coverageName));

        // Selecting bigger gridRange for a zoomed result
        final Dimension dim = new Dimension();
        GridEnvelope gridRange = reader.getOriginalGridRange(coverageName);
        dim.setSize(gridRange.getSpan(0) * 4.0, gridRange.getSpan(1) * 2.0);
        final Rectangle rasterArea = ((GridEnvelope2D) gridRange);
        rasterArea.setSize(dim);
        final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
        gg.setValue(new GridGeometry2D(range, reducedEnvelope));

        final ParameterValue<List> time = ImageMosaicFormat.TIME.createValue();
        final SimpleDateFormat formatD = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        formatD.setTimeZone(TimeZone.getTimeZone("GMT"));
        final Date timeD = formatD.parse("2012-04-01T00:00:00.000Z");
        time.setValue(
            new ArrayList() {
              {
                add(timeD);
              }
            });

        final ParameterValue<List> elevation = ImageMosaicFormat.ELEVATION.createValue();
        elevation.setValue(
            new ArrayList() {
              {
                add(450d); // Elevation
              }
            });

        GeneralParameterValue[] values =
            coverageName.equalsIgnoreCase("O3")
                ? new GeneralParameterValue[] {gg, time, elevation}
                : new GeneralParameterValue[] {gg, time};

        GridCoverage2D coverage = reader.read(coverageName, values);
        assertNotNull(coverage);
        if (TestData.isInteractiveTest()) {
          coverage.show();
        } else {
          PlanarImage.wrapRenderedImage(coverage.getRenderedImage()).getTiles();
        }
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }
Example #20
0
  /**
   * Applies the band select operation to a grid coverage.
   *
   * @param cropEnvelope the target envelope; always not null
   * @param cropROI the target ROI shape; nullable
   * @param roiTolerance; as read from op's params
   * @param sourceCoverage is the source {@link GridCoverage2D} that we want to crop.
   * @param hints A set of rendering hints, or {@code null} if none.
   * @param sourceGridToWorldTransform is the 2d grid-to-world transform for the source coverage.
   * @return The result as a grid coverage.
   */
  private static GridCoverage2D buildResult(
      final GeneralEnvelope cropEnvelope,
      final Geometry cropROI,
      final double roiTolerance,
      final boolean forceMosaic,
      final Hints hints,
      final GridCoverage2D sourceCoverage,
      final AffineTransform sourceGridToWorldTransform) {

    //
    // Getting the source coverage and its child geolocation objects
    //
    final RenderedImage sourceImage = sourceCoverage.getRenderedImage();
    final GridGeometry2D sourceGridGeometry = ((GridGeometry2D) sourceCoverage.getGridGeometry());
    final GridEnvelope2D sourceGridRange = sourceGridGeometry.getGridRange2D();

    //
    // Now we try to understand if we have a simple scale and translate or a
    // more elaborated grid-to-world transformation n which case a simple
    // crop could not be enough, but we may need a more elaborated chain of
    // operation in order to do a good job. As an instance if we
    // have a rotation which is not multiple of PI/2 we have to use
    // the mosaic with a ROI
    //
    final boolean isSimpleTransform =
        CoverageUtilities.isSimpleGridToWorldTransform(sourceGridToWorldTransform, EPS);

    // Do we need to explode the Palette to RGB(A)?
    //
    int actionTaken = 0;

    // //
    //
    // Layout
    //
    // //
    final RenderingHints targetHints = new RenderingHints(null);
    if (hints != null) targetHints.add(hints);
    final ImageLayout layout = initLayout(sourceImage, targetHints);
    targetHints.put(JAI.KEY_IMAGE_LAYOUT, layout);

    //
    // prepare the processor to use for this operation
    //
    final JAI processor = OperationJAI.getJAI(targetHints);
    final boolean useProvidedProcessor = !processor.equals(JAI.getDefaultInstance());

    try {

      if (cropROI != null) {
        // replace the cropEnvelope with the envelope of the intersection
        // of the ROI and the cropEnvelope.
        // Remember that envelope(intersection(roi,cropEnvelope)) != intersection(cropEnvelope,
        // envelope(roi))
        final Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY);
        Geometry intersection = IntersectUtils.intersection(cropROI, modelSpaceROI);
        Envelope2D e2d =
            JTS.getEnvelope2D(
                intersection.getEnvelopeInternal(), cropEnvelope.getCoordinateReferenceSystem());
        GeneralEnvelope ge = new GeneralEnvelope((org.opengis.geometry.Envelope) e2d);
        cropEnvelope.setEnvelope(ge);
      }

      // //
      //
      // Build the new range by keeping into
      // account translation of grid geometry constructor for respecting
      // OGC PIXEL-IS-CENTER ImageDatum assumption.
      //
      // //
      final AffineTransform sourceWorldToGridTransform = sourceGridToWorldTransform.createInverse();

      // //
      //
      // finalRasterArea will hold the smallest rectangular integer raster area that contains the
      // floating point raster
      // area which we obtain when applying the world-to-grid transform to the cropEnvelope. Note
      // that we need to intersect
      // such an area with the area covered by the source coverage in order to be sure we do not try
      // to crop outside the
      // bounds of the source raster.
      //
      // //
      final Rectangle2D finalRasterAreaDouble =
          XAffineTransform.transform(
              sourceWorldToGridTransform, cropEnvelope.toRectangle2D(), null);
      final Rectangle finalRasterArea = finalRasterAreaDouble.getBounds();

      // intersection with the original range in order to not try to crop outside the image bounds
      Rectangle.intersect(finalRasterArea, sourceGridRange, finalRasterArea);
      if (finalRasterArea.isEmpty())
        throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));

      // //
      //
      // It is worth to point out that doing a crop the G2W transform
      // should not change while the envelope might change as
      // a consequence of the rounding of the underlying image datum
      // which uses integer factors or in case the G2W is very
      // complex. Note that we will always strive to
      // conserve the original grid-to-world transform.
      //
      // //

      // we do not have to crop in this case (should not really happen at
      // this time)
      if (finalRasterArea.equals(sourceGridRange) && isSimpleTransform && cropROI == null)
        return sourceCoverage;

      // //
      //
      // if I get here I have something to crop
      // using the world-to-grid transform for going from envelope to the
      // new grid range.
      //
      // //
      final double minX = finalRasterArea.getMinX();
      final double minY = finalRasterArea.getMinY();
      final double width = finalRasterArea.getWidth();
      final double height = finalRasterArea.getHeight();

      // //
      //
      // Check if we need to use mosaic or crop
      //
      // //
      final PlanarImage croppedImage;
      final ParameterBlock pbj = new ParameterBlock();
      pbj.addSource(sourceImage);
      java.awt.Polygon rasterSpaceROI = null;
      String operatioName = null;
      if (!isSimpleTransform || cropROI != null) {
        // /////////////////////////////////////////////////////////////////////
        //
        // We don't have a simple scale and translate transform, JAI
        // crop MAY NOT suffice. Let's decide whether or not we'll use
        // the Mosaic.
        //
        // /////////////////////////////////////////////////////////////////////
        Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY);

        // //
        //
        // Now convert this polygon back into a shape for the source
        // raster space.
        //
        // //
        final List<Point2D> points = new ArrayList<Point2D>(5);
        rasterSpaceROI =
            FeatureUtilities.convertPolygonToPointArray(
                modelSpaceROI, ProjectiveTransform.create(sourceWorldToGridTransform), points);
        if (rasterSpaceROI == null || rasterSpaceROI.getBounds().isEmpty())
          if (finalRasterArea.isEmpty())
            throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));
        final boolean doMosaic =
            forceMosaic
                ? true
                : decideJAIOperation(roiTolerance, rasterSpaceROI.getBounds2D(), points);
        if (doMosaic || cropROI != null) {
          // prepare the params for the mosaic
          final ROI[] roiarr;
          try {
            if (cropROI != null) {
              final LiteShape2 cropRoiLS2 =
                  new LiteShape2(
                      cropROI, ProjectiveTransform.create(sourceWorldToGridTransform), null, false);
              ROI cropRS = new ROIShape(cropRoiLS2);
              Rectangle2D rt = cropRoiLS2.getBounds2D();
              if (!hasIntegerBounds(rt)) {
                // Approximate Geometry
                Geometry geo = (Geometry) cropRoiLS2.getGeometry().clone();
                transformGeometry(geo);
                cropRS = new ROIShape(new LiteShape2(geo, null, null, false));
              }
              roiarr = new ROI[] {cropRS};
            } else {
              final ROIShape roi = new ROIShape(rasterSpaceROI);
              roiarr = new ROI[] {roi};
            }
          } catch (FactoryException ex) {
            throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), ex);
          }
          pbj.add(MosaicDescriptor.MOSAIC_TYPE_OVERLAY);
          pbj.add(null);
          pbj.add(roiarr);
          pbj.add(null);
          pbj.add(CoverageUtilities.getBackgroundValues(sourceCoverage));

          // prepare the final layout
          final Rectangle bounds = rasterSpaceROI.getBounds2D().getBounds();
          Rectangle.intersect(bounds, sourceGridRange, bounds);
          if (bounds.isEmpty()) throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));

          // we do not have to crop in this case (should not really happen at
          // this time)
          if (!doMosaic && bounds.getBounds().equals(sourceGridRange) && isSimpleTransform)
            return sourceCoverage;

          // nice trick, we use the layout to do the actual crop
          final Rectangle boundsInt = bounds.getBounds();
          layout.setMinX(boundsInt.x);
          layout.setWidth(boundsInt.width);
          layout.setMinY(boundsInt.y);
          layout.setHeight(boundsInt.height);
          operatioName = "Mosaic";
        }
      }

      // do we still have to set the operation name? If so that means we have to go for crop.
      if (operatioName == null) {
        // executing the crop
        pbj.add((float) minX);
        pbj.add((float) minY);
        pbj.add((float) width);
        pbj.add((float) height);
        operatioName = "GTCrop";
      }
      // //
      //
      // Apply operation
      //
      // //
      if (!useProvidedProcessor) {
        croppedImage = JAI.create(operatioName, pbj, targetHints);
      } else {
        croppedImage = processor.createNS(operatioName, pbj, targetHints);
      }

      // conserve the input grid to world transformation
      Map sourceProperties = sourceCoverage.getProperties();
      Map properties = null;
      if (sourceProperties != null && !sourceProperties.isEmpty()) {
        properties = new HashMap(sourceProperties);
      }
      if (rasterSpaceROI != null) {
        if (properties != null) {
          properties.put("GC_ROI", rasterSpaceROI);
        } else {
          properties = Collections.singletonMap("GC_ROI", rasterSpaceROI);
        }
      }

      return new GridCoverageFactory(hints)
          .create(
              sourceCoverage.getName(),
              croppedImage,
              new GridGeometry2D(
                  new GridEnvelope2D(croppedImage.getBounds()),
                  sourceGridGeometry.getGridToCRS2D(PixelOrientation.CENTER),
                  sourceCoverage.getCoordinateReferenceSystem()),
              (GridSampleDimension[])
                  (actionTaken == 1 ? null : sourceCoverage.getSampleDimensions().clone()),
              new GridCoverage[] {sourceCoverage},
              properties);

    } catch (TransformException e) {
      throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e);
    } catch (NoninvertibleTransformException e) {
      throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e);
    }
  }
Example #21
0
  /**
   * Applies a crop operation to a coverage.
   *
   * @see
   *     org.geotools.coverage.processing.AbstractOperation#doOperation(org.opengis.parameter.ParameterValueGroup,
   *     org.geotools.factory.Hints)
   */
  @SuppressWarnings("unchecked")
  public Coverage doOperation(ParameterValueGroup parameters, Hints hints) {

    final Geometry cropRoi; // extracted from parameters
    GeneralEnvelope cropEnvelope = null; // extracted from parameters
    final GridCoverage2D source; // extracted from parameters
    final double roiTolerance = parameters.parameter(Crop.PARAMNAME_ROITOLERANCE).doubleValue();
    final boolean forceMosaic = parameters.parameter(Crop.PARAMNAME_FORCEMOSAIC).booleanValue();

    // /////////////////////////////////////////////////////////////////////
    //
    // Assigning and checking input parameters
    //
    // ///////////////////////////////////////////////////////////////////

    // source coverage
    final ParameterValue sourceParameter = parameters.parameter("Source");
    if (sourceParameter == null || !(sourceParameter.getValue() instanceof GridCoverage2D)) {
      throw new CannotCropException(
          Errors.format(ErrorKeys.NULL_PARAMETER_$2, "Source", GridCoverage2D.class.toString()));
    }
    source = (GridCoverage2D) sourceParameter.getValue();

    // Check Envelope and ROI existence - we need at least one of them
    final ParameterValue envelopeParameter = parameters.parameter(PARAMNAME_ENVELOPE);
    final ParameterValue roiParameter = parameters.parameter(PARAMNAME_ROI);

    if ((envelopeParameter == null || envelopeParameter.getValue() == null)
        && (roiParameter == null || roiParameter.getValue() == null))
      throw new CannotCropException(
          Errors.format(
              ErrorKeys.NULL_PARAMETER_$2, PARAMNAME_ENVELOPE, GeneralEnvelope.class.toString()));

    Object envelope = envelopeParameter.getValue();
    if (envelope != null) {
      if (envelope instanceof GeneralEnvelope) {
        cropEnvelope = (GeneralEnvelope) envelope;
      } else if (envelope instanceof Envelope) {
        cropEnvelope = new GeneralEnvelope((Envelope) envelope);
      }
    }
    // may be null

    // Check crop ROI
    try {
      cropRoi =
          IntersectUtils.unrollGeometries(
              (Geometry) roiParameter.getValue()); // may throw if format not correct
    } catch (IllegalArgumentException ex) {
      throw new CannotCropException(
          Errors.format(ErrorKeys.ILLEGAL_ARGUMENT_$2, PARAMNAME_ROI, ex.getMessage()), ex);
    }

    // Setting a GeneralEnvelope from ROI if needed
    if (cropRoi != null && cropEnvelope == null) {
      Envelope e2d =
          JTS.getEnvelope2D(cropRoi.getEnvelopeInternal(), source.getCoordinateReferenceSystem());
      cropEnvelope = new GeneralEnvelope(e2d);
    }

    // /////////////////////////////////////////////////////////////////////
    //
    // Initialization
    //
    // We take the crop envelope and the source envelope then we check their
    // crs and we also check if they ever overlap.
    //
    // /////////////////////////////////////////////////////////////////////
    // envelope of the source coverage
    final Envelope2D sourceEnvelope = source.getEnvelope2D();
    // crop envelope
    Envelope2D destinationEnvelope = new Envelope2D(cropEnvelope);
    CoordinateReferenceSystem sourceCRS = sourceEnvelope.getCoordinateReferenceSystem();
    CoordinateReferenceSystem destinationCRS = destinationEnvelope.getCoordinateReferenceSystem();
    if (destinationCRS == null) {
      // Do not change the user provided object - clone it first.
      final Envelope2D ge = new Envelope2D(destinationEnvelope);
      destinationCRS = source.getCoordinateReferenceSystem2D();
      ge.setCoordinateReferenceSystem(destinationCRS);
      destinationEnvelope = ge;
    }

    // //
    //
    // Source and destination crs must be equals
    //
    // //
    if (!CRS.equalsIgnoreMetadata(sourceCRS, destinationCRS)) {
      throw new CannotCropException(
          Errors.format(
              ErrorKeys.MISMATCHED_ENVELOPE_CRS_$2,
              sourceCRS.getName().getCode(),
              destinationCRS.getName().getCode()));
    }

    if (cropRoi != null) {
      // TODO: check ROI SRID
    }

    // //
    //
    // Check the intersection and, if needed, do the crop operation.
    //
    // //
    final GeneralEnvelope intersectionEnvelope =
        new GeneralEnvelope((Envelope) destinationEnvelope);
    intersectionEnvelope.setCoordinateReferenceSystem(source.getCoordinateReferenceSystem());
    // intersect the envelopes
    intersectionEnvelope.intersect(sourceEnvelope);
    if (intersectionEnvelope.isEmpty())
      throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));

    // intersect the ROI with the intersection envelope and throw an error if they do not intersect
    if (cropRoi != null) {
      final Geometry jis =
          JTS.toGeometry(
              (com.vividsolutions.jts.geom.Envelope) new ReferencedEnvelope(intersectionEnvelope));
      if (!IntersectUtils.intersects(cropRoi, jis))
        throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));
    }

    // //
    //
    // Get the grid-to-world transform by keeping into account translation
    // of grid geometry constructor for respecting OGC PIXEL-IS-CENTER
    // ImageDatum assumption.
    //
    // //
    final AffineTransform sourceCornerGridToWorld =
        (AffineTransform)
            ((GridGeometry2D) source.getGridGeometry()).getGridToCRS(PixelInCell.CELL_CORNER);

    // //
    //
    // I set the tolerance as half the scale factor of the grid-to-world
    // transform. This should more or less means in most cases "don't bother
    // to crop if the new envelope is as close to the old one that we go
    // deep under pixel size."
    //
    // //
    final double tolerance = XAffineTransform.getScale(sourceCornerGridToWorld);
    if (cropRoi != null || !intersectionEnvelope.equals(sourceEnvelope, tolerance / 2.0, false)) {
      cropEnvelope = intersectionEnvelope.clone();
      return buildResult(
          cropEnvelope,
          cropRoi,
          roiTolerance,
          forceMosaic,
          (hints instanceof Hints) ? (Hints) hints : new Hints(hints),
          source,
          sourceCornerGridToWorld);
    } else {
      // //
      //
      // Note that in case we don't crop at all, WE DO NOT UPDATE the
      // envelope. If we did we might end up doing multiple successive
      // crop without actually cropping the image but, still, we would
      // shrink the envelope each time. Just think about having a loop
      // that crops recursively the same coverage specifying each time an
      // envelope whose URC is only a a scale quarter close to the LLC of
      // the old one. We would never crop the raster but we would modify
      // the grid-to-world transform each time.
      //
      // //
      return source;
    }
  }
Example #22
0
  @Test
  public void NetCDFTestAscatL1()
      throws NoSuchAuthorityCodeException, FactoryException, IOException, ParseException {
    File mosaic = new File(TestData.file(this, "."), "NetCDFTestAscatL1");
    if (mosaic.exists()) {
      FileUtils.deleteDirectory(mosaic);
    }
    assertTrue(mosaic.mkdirs());
    File file = TestData.file(this, "ascatl1.nc");
    FileUtils.copyFileToDirectory(file, mosaic);
    file = new File(mosaic, "ascatl1.nc");

    final Hints hints =
        new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, CRS.decode("EPSG:4326", true));
    hints.add(new Hints(Utils.EXCLUDE_MOSAIC, true));

    // Get format
    final AbstractGridFormat format =
        (AbstractGridFormat) GridFormatFinder.findFormat(file.toURI().toURL(), hints);
    final NetCDFReader reader = (NetCDFReader) format.getReader(file.toURI().toURL(), hints);

    assertNotNull(format);
    try {
      String[] names = reader.getGridCoverageNames();
      names = new String[] {names[1]};

      for (String coverageName : names) {

        final String[] metadataNames = reader.getMetadataNames(coverageName);
        assertNotNull(metadataNames);
        assertEquals(17, metadataNames.length);

        // Parsing metadata values
        assertEquals("false", reader.getMetadataValue(coverageName, "HAS_TIME_DOMAIN"));

        assertEquals("false", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));

        assertEquals("true", reader.getMetadataValue(coverageName, "HAS_NUMSIGMA_DOMAIN"));
        final String sigmaMetadata = reader.getMetadataValue(coverageName, "NUMSIGMA_DOMAIN");
        assertNotNull(sigmaMetadata);
        assertEquals("0,1,2", sigmaMetadata);
        assertEquals(3, sigmaMetadata.split(",").length);

        // subsetting the envelope
        final ParameterValue<GridGeometry2D> gg =
            AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope(coverageName);
        final GeneralEnvelope reducedEnvelope =
            new GeneralEnvelope(
                new double[] {
                  originalEnvelope.getLowerCorner().getOrdinate(0),
                  originalEnvelope.getLowerCorner().getOrdinate(1)
                },
                new double[] {
                  originalEnvelope.getMedian().getOrdinate(0),
                  originalEnvelope.getMedian().getOrdinate(1)
                });
        reducedEnvelope.setCoordinateReferenceSystem(
            reader.getCoordinateReferenceSystem(coverageName));

        // Selecting bigger gridRange for a zoomed result
        final Dimension dim = new Dimension();
        GridEnvelope gridRange = reader.getOriginalGridRange(coverageName);
        dim.setSize(gridRange.getSpan(0) * 4.0, gridRange.getSpan(1) * 2.0);
        final Rectangle rasterArea = ((GridEnvelope2D) gridRange);
        rasterArea.setSize(dim);
        final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
        gg.setValue(new GridGeometry2D(range, reducedEnvelope));

        ParameterValue<List<String>> sigmaValue = null;
        final String selectedSigma = "1";
        Set<ParameterDescriptor<List>> params = reader.getDynamicParameters(coverageName);
        for (ParameterDescriptor param : params) {
          if (param.getName().getCode().equalsIgnoreCase("NUMSIGMA")) {
            sigmaValue = param.createValue();
            sigmaValue.setValue(
                new ArrayList<String>() {
                  {
                    add(selectedSigma);
                  }
                });
          }
        }

        GeneralParameterValue[] values = new GeneralParameterValue[] {gg, sigmaValue};
        GridCoverage2D coverage = reader.read(coverageName, values);
        assertNotNull(coverage);
        if (TestData.isInteractiveTest()) {
          coverage.show();
        } else {
          PlanarImage.wrapRenderedImage(coverage.getRenderedImage()).getTiles();
        }
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }
  private ArcSDEGridCoverage2DReaderJAI.ReadParameters parseReadParams(
      final GeneralParameterValue[] params) throws IllegalArgumentException {
    if (params == null) {
      throw new IllegalArgumentException("No GeneralParameterValue given to read operation");
    }

    GeneralEnvelope reqEnvelope = null;
    GridEnvelope dim = null;
    OverviewPolicy overviewPolicy = null;

    // /////////////////////////////////////////////////////////////////////
    //
    // Checking params
    //
    // /////////////////////////////////////////////////////////////////////
    for (int i = 0; i < params.length; i++) {
      final ParameterValue<?> param = (ParameterValue<?>) params[i];
      final String name = param.getDescriptor().getName().getCode();
      if (name.equals(AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString())) {
        final GridGeometry2D gg = (GridGeometry2D) param.getValue();
        reqEnvelope = new GeneralEnvelope((Envelope) gg.getEnvelope2D());

        final GeneralEnvelope coverageEnvelope = getOriginalEnvelope();
        CoordinateReferenceSystem nativeCrs = coverageEnvelope.getCoordinateReferenceSystem();
        CoordinateReferenceSystem requestCrs = reqEnvelope.getCoordinateReferenceSystem();
        if (!CRS.equalsIgnoreMetadata(nativeCrs, requestCrs)) {
          LOGGER.fine(
              "Request CRS and native CRS differ, "
                  + "reprojecting request envelope to native CRS");
          ReferencedEnvelope nativeCrsEnv;
          nativeCrsEnv = toNativeCrs(reqEnvelope, nativeCrs);
          reqEnvelope = new GeneralEnvelope(nativeCrsEnv);
        }

        dim = gg.getGridRange2D();
        continue;
      }
      if (name.equals(AbstractGridFormat.OVERVIEW_POLICY.getName().toString())) {
        overviewPolicy = (OverviewPolicy) param.getValue();
        continue;
      }
    }

    if (reqEnvelope == null && dim == null) {
      reqEnvelope = getOriginalEnvelope();
      dim = getOriginalGridRange();
    }

    if (reqEnvelope == null) {
      reqEnvelope = getOriginalEnvelope();
    }
    if (dim == null) {
      final GeneralEnvelope adjustedGRange;
      try {
        MathTransform gridToWorld = getOriginalGridToWorld(PixelInCell.CELL_CENTER);
        MathTransform worldToGrid = gridToWorld.inverse();
        adjustedGRange = CRS.transform(worldToGrid, reqEnvelope);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
      int xmin = (int) Math.floor(adjustedGRange.getMinimum(0));
      int ymin = (int) Math.floor(adjustedGRange.getMinimum(1));
      int xmax = (int) Math.ceil(adjustedGRange.getMaximum(0));
      int ymax = (int) Math.ceil(adjustedGRange.getMaximum(1));
      dim = new GridEnvelope2D(xmin, ymin, xmax - xmin, ymax - ymin);
    }

    if (!reqEnvelope.intersects(getOriginalEnvelope(), true)) {
      throw new IllegalArgumentException(
          "The requested extend does not overlap the coverage extent: " + getOriginalEnvelope());
    }

    if (dim.getSpan(0) <= 0 || dim.getSpan(1) <= 0) {
      throw new IllegalArgumentException("The requested coverage dimension can't be null: " + dim);
    }

    if (overviewPolicy == null) {
      overviewPolicy = OverviewPolicy.NEAREST;
      LOGGER.finer("No overview policy requested, defaulting to " + overviewPolicy);
    }
    LOGGER.fine("Overview policy is " + overviewPolicy);

    ArcSDEGridCoverage2DReaderJAI.ReadParameters parsedParams =
        new ArcSDEGridCoverage2DReaderJAI.ReadParameters();
    parsedParams.requestedEnvelope = reqEnvelope;
    parsedParams.dim = dim;
    parsedParams.overviewPolicy = overviewPolicy;
    return parsedParams;
  }
  /**
   * @see GridCoverageReader#read(GeneralParameterValue[])
   * @return A new {@linkplain GridCoverage grid coverage} from the input source, or {@code null} if
   *     the requested envelope is outside the data bounds
   */
  public GridCoverage2D read(GeneralParameterValue[] params) throws IOException {
    final GeneralEnvelope requestedEnvelope;
    final GridEnvelope requestedDim;
    final OverviewPolicy overviewPolicy;
    {
      final ReadParameters opParams = parseReadParams(params);
      overviewPolicy = opParams.overviewPolicy;
      requestedEnvelope = opParams.requestedEnvelope;
      requestedDim = opParams.dim;
    }

    /*
     * For each raster in the raster dataset, obtain the tiles, pixel range, and resulting
     * envelope
     */
    final List<RasterQueryInfo> queries;
    queries = findMatchingRasters(requestedEnvelope, requestedDim, overviewPolicy);
    if (queries.isEmpty()) {
      if (requestedEnvelope.intersects(getOriginalEnvelope(), true)) {
        /*
         * No matching rasters but envelopes intersect, meaning it's a raster catalog with
         * irregular coverage and the request lies on an area with no coverage
         */
        ImageTypeSpecifier imageTypeSpecifier;
        imageTypeSpecifier = RasterUtils.createFullImageTypeSpecifier(rasterInfo, 0);
        SampleModel sampleModel = imageTypeSpecifier.getSampleModel();
        Point location = new Point(0, 0);
        WritableRaster raster = Raster.createWritableRaster(sampleModel, location);
        GridCoverage2D emptyCoverage;
        emptyCoverage = coverageFactory.create(coverageName, raster, requestedEnvelope);
        return emptyCoverage;
      }
      /*
       * none of the rasters match the requested envelope.
       */
      return null;
    }

    final LoggingHelper log = new LoggingHelper();

    /*
     * Once we collected the matching rasters and their image subsets, find out where in the
     * overall resulting mosaic they fit. If the rasters does not share the spatial resolution,
     * the QueryInfo.resultDimension and QueryInfo.mosaicLocation width or height won't match
     */
    final GridEnvelope mosaicGeometry;
    mosaicGeometry = RasterUtils.setMosaicLocations(rasterInfo, queries);

    if (mosaicGeometry.getSpan(0) == 0 || mosaicGeometry.getSpan(1) == 0) {
      LOGGER.finer(
          "Mosaic geometry width or height is zero,"
              + " returning fake coverage for pixels "
              + mosaicGeometry);
      return null;
    }
    /*
     * Gather the rendered images for each of the rasters that match the requested envelope
     */
    final TiledRasterReader rasterReader = rasterReaderFactory.create(rasterInfo);

    try {
      readAllTiledRasters(queries, rasterReader, log);
    } finally {
      // rasterReader.dispose();
    }

    log.log(LoggingHelper.REQ_ENV);
    log.log(LoggingHelper.RES_ENV);
    log.log(LoggingHelper.MOSAIC_ENV);
    log.log(LoggingHelper.MOSAIC_EXPECTED);

    final RenderedImage coverageRaster = createMosaic(queries, mosaicGeometry, log);

    assert mosaicGeometry.getSpan(0) == coverageRaster.getWidth();
    assert mosaicGeometry.getSpan(1) == coverageRaster.getHeight();

    /*
     * BUILDING COVERAGE
     */
    GridSampleDimension[] bands = getSampleDimensions(coverageRaster);

    final GeneralEnvelope resultEnvelope = getResultEnvelope(queries, mosaicGeometry);
    log.appendLoggingGeometries(LoggingHelper.REQ_ENV, requestedEnvelope);
    log.appendLoggingGeometries(LoggingHelper.RES_ENV, resultEnvelope);

    GridCoverage2D resultCoverage =
        coverageFactory.create(coverageName, coverageRaster, resultEnvelope, bands, null, null);

    // MathTransform gridToCRS = rasterInfo.getRasterToModel(queries.get(0).getRasterIndex(),
    // queries.get(0).getPyramidLevel());
    //
    // GridGeometry2D gridGeometry = new GridGeometry2D(PixelInCell.CELL_CORNER, gridToCRS,
    // resultEnvelope, hints);
    //
    // GridCoverage[] sources = null;
    // Map<?, ?> properties = null;
    // GridCoverage2D resultCoverage = coverageFactory.create(coverageName, coverageRaster,
    // gridGeometry, bands, sources, properties);
    return resultCoverage;
  }
  public boolean extractTiffMetadata(File tifFile, TiffMeta surface)
      throws UnknownCRSException, FactoryException, TransformException, IOException {

    Preconditions.checkArgument(tifFile != null, "File is null.");

    GeoTiffReader gtr = new GeoTiffReader(tifFile);

    try {

      CoordinateReferenceSystem crs = gtr.getCoordinateReferenceSystem();
      surface.setCRS(crs);
      Integer epsgCode = CRS.lookupEpsgCode(crs, true);

      if (epsgCode == null) {
        ReferenceIdentifier name = crs.getName();
        String crsName = "Unknown";
        if (name != null) {
          crsName = name.toString();
        }
        throw new UnknownCRSException(crsName);
      }

      String srid = "EPSG:" + epsgCode;
      surface.setSrid(srid);

      //
      // extremaOp(surface, gtr.read(null));

      /*
       * Build the envelope and set to WGS84
       */
      GeneralEnvelope origEnv = gtr.getOriginalEnvelope();
      DirectPosition ll = origEnv.getLowerCorner();
      DirectPosition ur = origEnv.getUpperCorner();

      Envelope e = new Envelope();
      e.expandToInclude(ll.getOrdinate(0), ll.getOrdinate(1));
      e.expandToInclude(ur.getOrdinate(0), ur.getOrdinate(1));

      Geometry poly = envelopeToWgs84(epsgCode, e);

      if (poly instanceof Polygon) {
        surface.setEnvelope((Polygon) poly);
      }

      /*
       * Figure out the pixel size
       */
      ImageLayout imageLayout = gtr.getImageLayout();
      int imageWidth = imageLayout.getWidth(null);
      int imageHeight = imageLayout.getHeight(null);

      double pixelSizeX = e.getWidth() / imageWidth;
      double pixelSizeY = e.getHeight() / imageHeight;

      surface.setPixelSizeX(pixelSizeX);
      surface.setPixelSizeY(pixelSizeY);

      surface.setMinVal(0d);
      surface.setMaxVal(100d);

      GridCoverage2D gridCoverage2D = gtr.read(null);

      try {
        int nDims = gridCoverage2D.getNumSampleDimensions();
        surface.setNumSampleDimensions(nDims);

        extremaOp(surface, gridCoverage2D);

      } finally {
        gridCoverage2D.dispose(false);
      }

    } finally {

      gtr.dispose();
    }

    return true;
  }
  private void computeCropBBOX() throws DataSourceException {

    // get the crs for the requested bbox
    if (requestCRS == null)
      requestCRS = CRS.getHorizontalCRS(requestedBBox.getCoordinateReferenceSystem());
    try {

      //
      // The destination to source transform has been computed (and eventually erased) already
      // by inspectCoordinateSystem()

      // now transform the requested envelope to source crs
      if (destinationToSourceTransform != null && !destinationToSourceTransform.isIdentity()) {
        final GeneralEnvelope temp =
            new GeneralEnvelope(CRS.transform(requestedBBox, coverageProperties.crs2D));
        temp.setCoordinateReferenceSystem(coverageProperties.crs2D);
        cropBBox = new ReferencedEnvelope(temp);
        needsReprojection = true;

      } else {
        // we do not need to do anything, but we do this in order to aboid problems with the
        // envelope checks
        cropBBox =
            new ReferencedEnvelope(
                requestedBBox.getMinX(),
                requestedBBox.getMaxX(),
                requestedBBox.getMinY(),
                requestedBBox.getMaxY(),
                coverageProperties.crs2D);
      }

      // intersect requested BBox in native CRS with coverage native bbox to get the crop bbox
      // intersect the requested area with the bounds of this layer in native crs
      if (!cropBBox.intersects((BoundingBox) coverageProperties.bbox)) {
        if (LOGGER.isLoggable(Level.FINE)) {
          LOGGER.fine(
              new StringBuilder("The computed CropBoundingBox ")
                  .append(cropBBox)
                  .append(" Doesn't intersect the coverage BoundingBox ")
                  .append(coverageProperties.bbox)
                  .append(" resulting in an empty request")
                  .toString());
        }
        cropBBox = null;
        empty = true;
        return;
      }
      // TODO XXX Optimize when referenced envelope has intersection method that actually retains
      // the CRS, this is the JTS one
      cropBBox =
          new ReferencedEnvelope(
              ((ReferencedEnvelope) cropBBox).intersection(coverageProperties.bbox),
              coverageProperties.crs2D);

      return;
    } catch (TransformException te) {
      // something bad happened while trying to transform this
      // envelope. let's try with wgs84
      if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, te.getLocalizedMessage(), te);
    }

    try {
      // can we proceed? Do we have geo stuff to do all these operations?
      if (coverageProperties.geographicCRS2D != null && coverageProperties.geographicBBox != null) {

        //
        // If we can not reproject the requested envelope to the native CRS,
        // we go back to reproject in the geographic crs of the native
        // coverage since this usually happens for conversions between CRS
        // whose area of definition is different
        //

        // STEP 1 reproject the requested envelope to the coverage geographic bbox
        if (!CRS.equalsIgnoreMetadata(coverageProperties.geographicCRS2D, requestCRS)) {
          // try to convert the requested bbox to the coverage geocrs
          requestCRSToCoverageGeographicCRS2D =
              CRS.findMathTransform(requestCRS, coverageProperties.geographicCRS2D, true);
          if (!requestCRSToCoverageGeographicCRS2D.isIdentity()) {
            requestedBBOXInCoverageGeographicCRS =
                CRS.transform(requestedBBox, coverageProperties.geographicCRS2D);
            requestedBBOXInCoverageGeographicCRS.setCoordinateReferenceSystem(
                coverageProperties.geographicCRS2D);
          }
        }
        if (requestedBBOXInCoverageGeographicCRS == null) {
          requestedBBOXInCoverageGeographicCRS = new GeneralEnvelope(requestCRS);
        }

        // STEP 2 intersection with the geographic bbox for this coverage
        if (!requestedBBOXInCoverageGeographicCRS.intersects(
            coverageProperties.geographicBBox, true)) {
          cropBBox = null;
          empty = true;
          return;
        }
        // intersect with the coverage native geographic bbox
        // note that for the moment we got to use general envelope since there is no intersection
        // otherwise
        requestedBBOXInCoverageGeographicCRS.intersect(coverageProperties.geographicBBox);
        requestedBBOXInCoverageGeographicCRS.setCoordinateReferenceSystem(
            coverageProperties.geographicCRS2D);

        // now go back to the coverage native CRS in order to compute an approximate requested
        // resolution
        approximateRequestedBBoInNativeCRS =
            CRS.transform(requestedBBOXInCoverageGeographicCRS, coverageProperties.crs2D);
        approximateRequestedBBoInNativeCRS.setCoordinateReferenceSystem(coverageProperties.crs2D);
        cropBBox = new ReferencedEnvelope(approximateRequestedBBoInNativeCRS);
        return;
      }

    } catch (TransformException te) {
      // something bad happened while trying to transform this
      // envelope. let's try with wgs84
      if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, te.getLocalizedMessage(), te);
    } catch (FactoryException fe) {
      // something bad happened while trying to transform this
      // envelope. let's try with wgs84
      if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, fe.getLocalizedMessage(), fe);
    }

    LOGGER.log(
        Level.INFO,
        "We did not manage to crop the requested envelope, we fall back onto loading the whole coverage.");
    cropBBox = null;
  }
  /**
   * Return a crop region from a specified envelope, leveraging on the grid to world transformation.
   *
   * @param refinedRequestedBBox the crop envelope
   * @return a {@code Rectangle} representing the crop region.
   * @throws TransformException in case a problem occurs when going back to raster space.
   * @throws DataSourceException
   */
  private void computeCropRasterArea() throws DataSourceException {

    // we have nothing to crop
    if (cropBBox == null) {
      destinationRasterArea = null;
      return;
    }

    //
    // We need to invert the requested gridToWorld and then adjust the requested raster area are
    // accordingly
    //

    // invert the requested grid to world keeping into account the fact that it is related to cell
    // center
    // while the raster is related to cell corner
    MathTransform2D requestedWorldToGrid;
    try {
      requestedWorldToGrid =
          (MathTransform2D)
              PixelTranslation.translate(
                      ProjectiveTransform.create(requestedGridToWorld),
                      PixelInCell.CELL_CENTER,
                      PixelInCell.CELL_CORNER)
                  .inverse();
    } catch (NoninvertibleTransformException e) {
      throw new DataSourceException(e);
    }

    if (destinationToSourceTransform == null || destinationToSourceTransform.isIdentity()) {

      // now get the requested bbox which have been already adjusted and project it back to raster
      // space
      try {
        destinationRasterArea =
            new GeneralGridEnvelope(
                    CRS.transform(requestedWorldToGrid, new GeneralEnvelope(cropBBox)),
                    PixelInCell.CELL_CORNER,
                    false)
                .toRectangle();
      } catch (IllegalStateException e) {
        throw new DataSourceException(e);
      } catch (TransformException e) {
        throw new DataSourceException(e);
      }
    } else {
      //
      // reproject the crop bbox back and then crop, notice that we are imposing
      //
      try {
        final GeneralEnvelope cropBBOXInRequestCRS =
            CRS.transform(cropBBox, requestedBBox.getCoordinateReferenceSystem());
        cropBBOXInRequestCRS.setCoordinateReferenceSystem(
            requestedBBox.getCoordinateReferenceSystem());
        // make sure it falls within the requested envelope
        cropBBOXInRequestCRS.intersect(requestedBBox);

        // now go back to raster space
        destinationRasterArea =
            new GeneralGridEnvelope(
                    CRS.transform(requestedWorldToGrid, cropBBOXInRequestCRS),
                    PixelInCell.CELL_CORNER,
                    false)
                .toRectangle();
        // intersect with the original requested raster space to be sure that we stay within the
        // requested raster area
        XRectangle2D.intersect(destinationRasterArea, requestedRasterArea, destinationRasterArea);
      } catch (NoninvertibleTransformException e) {
        throw new DataSourceException(e);
      } catch (TransformException e) {
        throw new DataSourceException(e);
      }
    }
    // is it empty??
    if (destinationRasterArea.isEmpty()) {
      if (LOGGER.isLoggable(Level.FINE))
        LOGGER.log(
            Level.FINE,
            "Requested envelope too small resulting in empty cropped raster region. cropBbox:"
                + cropBBox);
      // TODO: Future versions may define a 1x1 rectangle starting
      // from the lower coordinate
      empty = true;
      return;
    }
  }
    /**
     * Encodes the boundedBy element
     *
     * <p>e.g.:
     *
     * <pre>{@code
     * <gml:boundedBy>
     *    <gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/4326" axisLabels="Lat Long" uomLabels="deg deg" srsDimension="2">
     *       <gml:lowerCorner>1 1</gml:lowerCorner>
     *       <gml:upperCorner>5 3</gml:upperCorner>
     *    </gml:Envelope>
     * </gml:boundedBy>
     * }</pre>
     *
     * @param ci
     * @param gc2d
     * @param ePSGCode
     * @param axisSwap
     * @param srsName
     * @param axesNames
     * @param axisLabels
     * @throws IOException
     */
    public void handleBoundedBy(
        final GeneralEnvelope envelope,
        boolean axisSwap,
        String srsName,
        String axisLabels,
        WCSDimensionsHelper dimensionHelper)
        throws IOException {
      final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
      final CoordinateSystem cs = crs.getCoordinateSystem();

      // TODO time
      String uomLabels =
          extractUoM(crs, cs.getAxis(axisSwap ? 1 : 0).getUnit())
              + " "
              + extractUoM(crs, cs.getAxis(axisSwap ? 0 : 1).getUnit());

      // time and elevation dimensions management
      boolean hasElevation = false;
      boolean hasTime = false;
      if (dimensionHelper != null) {
        if (dimensionHelper.getElevationDimension() != null) {
          uomLabels = uomLabels + " m"; // TODO: Check elevation uom
          hasElevation = true;
        }
        if (dimensionHelper.getTimeDimension() != null) {
          uomLabels = uomLabels + " s";
          hasTime = true;
        }
      }
      final int srsDimension = cs.getDimension() + (hasElevation ? 1 : 0);

      // Setting up envelope bounds (including elevation)
      final String lower =
          new StringBuilder()
              .append(envelope.getLowerCorner().getOrdinate(axisSwap ? 1 : 0))
              .append(" ")
              .append(envelope.getLowerCorner().getOrdinate(axisSwap ? 0 : 1))
              .append(hasElevation ? " " + dimensionHelper.getBeginElevation() : "")
              .toString();

      final String upper =
          new StringBuilder()
              .append(envelope.getUpperCorner().getOrdinate(axisSwap ? 1 : 0))
              .append(" ")
              .append(envelope.getUpperCorner().getOrdinate(axisSwap ? 0 : 1))
              .append(hasElevation ? " " + dimensionHelper.getEndElevation() : "")
              .toString();

      // build the fragment
      final AttributesImpl envelopeAttrs = new AttributesImpl();
      envelopeAttrs.addAttribute("", "srsName", "srsName", "", srsName);
      envelopeAttrs.addAttribute("", "axisLabels", "axisLabels", "", axisLabels);
      envelopeAttrs.addAttribute("", "uomLabels", "uomLabels", "", uomLabels);
      envelopeAttrs.addAttribute(
          "", "srsDimension", "srsDimension", "", String.valueOf(srsDimension));
      start("gml:boundedBy");
      String envelopeName;
      if (dimensionHelper != null && (hasTime || hasElevation)) {
        envelopeName = "gml:EnvelopeWithTimePeriod";
      } else {
        envelopeName = "gml:Envelope";
      }
      start(envelopeName, envelopeAttrs);

      element("gml:lowerCorner", lower);
      element("gml:upperCorner", upper);

      if (dimensionHelper != null && hasTime) {
        element("gml:beginPosition", dimensionHelper.getBeginTime());
        element("gml:endPosition", dimensionHelper.getEndTime());
      }

      end(envelopeName);
      end("gml:boundedBy");
    }
Example #29
0
  @Test
  public void NetCDFTestOnFilter()
      throws NoSuchAuthorityCodeException, FactoryException, IOException, ParseException {
    File mosaic = new File(TestData.file(this, "."), "NetCDFTestOnFilter");
    if (mosaic.exists()) {
      FileUtils.deleteDirectory(mosaic);
    }
    assertTrue(mosaic.mkdirs());

    File file = TestData.file(this, "O3-NO2.nc");
    FileUtils.copyFileToDirectory(file, mosaic);
    file = new File(mosaic, "O3-NO2.nc");

    final Hints hints =
        new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, CRS.decode("EPSG:4326", true));
    // Get format
    final AbstractGridFormat format =
        (AbstractGridFormat) GridFormatFinder.findFormat(file.toURI().toURL(), hints);
    final NetCDFReader reader = (NetCDFReader) format.getReader(file.toURI().toURL(), hints);

    assertNotNull(format);
    try {
      String[] names = reader.getGridCoverageNames();
      names = new String[] {names[1]};

      for (String coverageName : names) {

        final String[] metadataNames = reader.getMetadataNames(coverageName);
        assertNotNull(metadataNames);
        assertEquals(12, metadataNames.length);

        // Parsing metadata values
        assertEquals("true", reader.getMetadataValue(coverageName, "HAS_TIME_DOMAIN"));
        final String timeMetadata = reader.getMetadataValue(coverageName, "TIME_DOMAIN");
        assertEquals(
            "2012-04-01T00:00:00.000Z/2012-04-01T00:00:00.000Z,2012-04-01T01:00:00.000Z/2012-04-01T01:00:00.000Z",
            timeMetadata);
        assertNotNull(timeMetadata);
        assertEquals(
            "2012-04-01T00:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MINIMUM"));
        assertEquals(
            "2012-04-01T01:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MAXIMUM"));

        assertEquals("true", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
        final String elevationMetadata = reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN");
        assertNotNull(elevationMetadata);
        assertEquals("10.0/10.0,450.0/450.0", elevationMetadata);
        assertEquals(2, elevationMetadata.split(",").length);
        assertEquals("10.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MINIMUM"));
        assertEquals("450.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MAXIMUM"));

        // subsetting the envelope
        final ParameterValue<GridGeometry2D> gg =
            AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope(coverageName);
        final GeneralEnvelope reducedEnvelope =
            new GeneralEnvelope(
                new double[] {
                  originalEnvelope.getLowerCorner().getOrdinate(0),
                  originalEnvelope.getLowerCorner().getOrdinate(1)
                },
                new double[] {
                  originalEnvelope.getMedian().getOrdinate(0),
                  originalEnvelope.getMedian().getOrdinate(1)
                });
        reducedEnvelope.setCoordinateReferenceSystem(
            reader.getCoordinateReferenceSystem(coverageName));

        // Selecting bigger gridRange for a zoomed result
        final Dimension dim = new Dimension();
        GridEnvelope gridRange = reader.getOriginalGridRange(coverageName);
        dim.setSize(gridRange.getSpan(0) * 4.0, gridRange.getSpan(1) * 2.0);
        final Rectangle rasterArea = ((GridEnvelope2D) gridRange);
        rasterArea.setSize(dim);
        final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
        gg.setValue(new GridGeometry2D(range, reducedEnvelope));

        final ParameterValue<Filter> filterParam = NetCDFFormat.FILTER.createValue();
        FilterFactory2 FF = FeatureUtilities.DEFAULT_FILTER_FACTORY;
        Filter filter = FF.equals(FF.property("z"), FF.literal(450.0));
        filterParam.setValue(filter);

        GeneralParameterValue[] values = new GeneralParameterValue[] {filterParam};
        GridCoverage2D coverage = reader.read(coverageName, values);
        assertNotNull(coverage);
        if (TestData.isInteractiveTest()) {
          coverage.show();
        } else {
          PlanarImage.wrapRenderedImage(coverage.getRenderedImage()).getTiles();
        }
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }