Пример #1
0
  public CoverageResponse update(CoverageUpdateRequest writeRequest, ProgressListener progress) {
    ensureNotDisposed();
    access.globalLock.writeLock().lock();

    final DefaultCoverageResponseImpl response = new DefaultCoverageResponseImpl();
    response.setRequest(writeRequest);
    try {
      // reader
      final GeoTiffWriter writer = new GeoTiffWriter(this.access.input);

      // get the data
      final GridCoverage2D coverage = (GridCoverage2D) writeRequest.getData().iterator().next();
      writer.write(coverage, null);
      writer.dispose();
      response.addResult(coverage);
      response.setStatus(Status.SUCCESS);

      // update the access
      Info info = getInfo(null);
      info.setExtent((GeneralEnvelope) coverage.getGridGeometry().getEnvelope());
      info.setGeometry(coverage.getGridGeometry());
    } catch (Throwable e) {
      response.addException(new GeoTiffException(null, "IO error", e));
    } finally {
      this.access.globalLock.writeLock().unlock();
    }

    return response;
  }
Пример #2
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]);
  }
Пример #3
0
  /**
   * Tests the "Resample" operation with a stereographic coordinate system.
   *
   * @throws FactoryException
   * @throws NoSuchAuthorityCodeException
   */
  @Test
  public void testReproject() throws NoSuchAuthorityCodeException, FactoryException {

    // do it again, make sure the image does not turn black since
    GridCoverage2D coverage_ =
        project(ushortCoverage, CRS.parseWKT(GOOGLE_MERCATOR_WKT), null, "nearest", null, true);

    // reproject the ushort and check that things did not go bad, that is it turned black
    coverage_ = (GridCoverage2D) Operations.DEFAULT.extrema(coverage_);
    Object minimums = coverage_.getProperty(Extrema.GT_SYNTHETIC_PROPERTY_MINIMUM);
    Assert.assertTrue(minimums instanceof double[]);
    final double[] mins = (double[]) minimums;
    Object maximums = coverage_.getProperty(Extrema.GT_SYNTHETIC_PROPERTY_MAXIMUM);
    Assert.assertTrue(maximums instanceof double[]);
    final double[] max = (double[]) maximums;
    boolean fail = true;
    for (int i = 0; i < mins.length; i++) if (mins[i] != max[i] && max[i] > 0) fail = false;
    Assert.assertFalse("Reprojection failed", fail);

    // exception in case the target crs does not comply with the target gg crs
    try {
      // we supplied both crs and target gg in different crs, we get an exception backS
      assertEquals(
          "Warp",
          showProjected(
              coverage, CRS.parseWKT(GOOGLE_MERCATOR_WKT), coverage.getGridGeometry(), null, true));
      Assert.assertTrue(
          "We should not be allowed to set different crs for target crs and target gg", false);
    } catch (Exception e) {
      // ok!
    }
  }
  public static HashMap<String, Double> getRegionParamsFromGridCoverage(
      GridCoverage2D gridCoverage) {
    HashMap<String, Double> envelopeParams = new HashMap<String, Double>();

    Envelope envelope = gridCoverage.getEnvelope();

    DirectPosition lowerCorner = envelope.getLowerCorner();
    double[] westSouth = lowerCorner.getCoordinate();
    DirectPosition upperCorner = envelope.getUpperCorner();
    double[] eastNorth = upperCorner.getCoordinate();

    GridGeometry2D gridGeometry = gridCoverage.getGridGeometry();
    GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
    int height = gridRange.height;
    int width = gridRange.width;

    AffineTransform gridToCRS = (AffineTransform) gridGeometry.getGridToCRS();
    double xRes = XAffineTransform.getScaleX0(gridToCRS);
    double yRes = XAffineTransform.getScaleY0(gridToCRS);

    envelopeParams.put(NORTH, eastNorth[1]);
    envelopeParams.put(SOUTH, westSouth[1]);
    envelopeParams.put(WEST, westSouth[0]);
    envelopeParams.put(EAST, eastNorth[0]);
    envelopeParams.put(XRES, xRes);
    envelopeParams.put(YRES, yRes);
    envelopeParams.put(ROWS, (double) height);
    envelopeParams.put(COLS, (double) width);

    return envelopeParams;
  }
Пример #5
0
  public static JGrassRegion getJGrassRegionFromGridCoverage(GridCoverage2D gridCoverage2D)
      throws InvalidGridGeometryException, TransformException {
    Envelope2D env = gridCoverage2D.getEnvelope2D();
    GridEnvelope2D worldToGrid = gridCoverage2D.getGridGeometry().worldToGrid(env);

    double xRes = env.getWidth() / worldToGrid.getWidth();
    double yRes = env.getHeight() / worldToGrid.getHeight();

    JGrassRegion region =
        new JGrassRegion(env.getMinX(), env.getMaxX(), env.getMinY(), env.getMaxY(), xRes, yRes);

    return region;
  }
  /**
   * Quick method for populating the {@link CUDABean} instance provided.
   *
   * @param bean
   * @param reference
   * @param coverage
   * @param geo
   * @param transform
   * @throws IOException
   * @throws MismatchedDimensionException
   * @throws TransformException
   */
  private void populateBean(
      CUDABean bean,
      boolean reference,
      GridCoverage2D coverage,
      Geometry geo,
      MathTransform transform,
      int buffer)
      throws IOException, MismatchedDimensionException, TransformException {

    RenderedImage image = coverage.getRenderedImage();

    // 0) Check if a buffer must be applied
    Geometry originalGeo = (Geometry) geo.clone();
    if (buffer > 0) {
      try {
        if (!"EPSG:4326"
            .equals(CRS.lookupIdentifier(coverage.getCoordinateReferenceSystem(), false))) {
          geo = geo.buffer(buffer);
        } else {
          geo = geo.buffer(buffer / 111.128);
        }
      } catch (FactoryException e) {
        geo = geo.buffer(buffer);
      }
    }

    // 1) Crop the two coverages with the selected Geometry
    GridCoverage2D crop = CROP.execute(coverage, geo, null);
    transform =
        ProjectiveTransform.create(
                (AffineTransform) crop.getGridGeometry().getGridToCRS(PixelInCell.CELL_CORNER))
            .inverse();

    // 2) Extract the BufferedImage from each image
    image = crop.getRenderedImage();

    Rectangle rectIMG =
        new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
    ImageWorker w = new ImageWorker(image);
    BufferedImage buf = w.getBufferedImage();
    if (image instanceof RenderedOp) {
      ((RenderedOp) image).dispose();
    }

    // 3) Generate an array of data from each image
    Raster data = buf.getData();
    final DataBufferByte db = (DataBufferByte) data.getDataBuffer();
    byte[] byteData = db.getData();

    if (reference) {
      // 4) Transform the Geometry to Raster space
      Geometry rs = JTS.transform(geo, transform);
      Geometry rsFilter = JTS.transform(geo.difference(originalGeo), transform);
      ROI roiGeo = new ROIGeometry(rs);
      ROI roiFilter = new ROIGeometry(rsFilter);

      // 5) Extract an array of data from the transformed ROI
      byte[] roiData = getROIData((buffer > 0 ? roiFilter : roiGeo), rectIMG);
      bean.setRoi(roiData);
      bean.setRoiObj(roiGeo);

      // 6) Setting the Coverage data array
      bean.setReferenceImage(byteData);

      // 7) Setting the Image dimensions
      bean.setHeight(rectIMG.height);
      bean.setWidth(rectIMG.width);
      bean.setMinX(rectIMG.x);
      bean.setMinY(rectIMG.y);
    } else {
      // 6) Setting the Coverage data array
      bean.setCurrentImage(byteData);
    }

    // 7) Store the Reference Covergae containing the geospatial info
    bean.setReferenceCoverage(coverage);
  }
  @DescribeResult(
      name = "UrbanGridCUDAProcess",
      description = "Urban Grid indexes calculated using CUDA",
      type = List.class)
  public List<StatisticContainer> execute(
      @DescribeParameter(name = "reference", description = "Name of the reference raster")
          GridCoverage2D referenceCoverage,
      @DescribeParameter(name = "now", description = "Name of the new raster")
          GridCoverage2D nowCoverage,
      @DescribeParameter(name = "index", min = 1, description = "Index to calculate") int index,
      @DescribeParameter(
              name = "subindex",
              min = 0,
              description = "String indicating which sub-index must be calculated")
          String subId,
      @DescribeParameter(name = "pixelarea", min = 0, description = "Pixel Area") Double pixelArea,
      @DescribeParameter(name = "rois", min = 1, description = "Administrative Areas")
          List<Geometry> rois,
      @DescribeParameter(name = "populations", min = 0, description = "Populations for each Area")
          List<List<Integer>> populations,
      @DescribeParameter(
              name = "coefficient",
              min = 0,
              description = "Multiplier coefficient for index 10")
          Double coeff,
      @DescribeParameter(name = "rural", min = 0, description = "Rural or Urban index")
          boolean rural,
      @DescribeParameter(name = "radius", min = 0, description = "Radius in meters") int radius)
      throws IOException {

    // Check on the index 7
    boolean nullSubId = subId == null || subId.isEmpty();
    boolean subIndexA = !nullSubId && subId.equalsIgnoreCase("a");
    boolean subIndexC = !nullSubId && subId.equalsIgnoreCase("c");
    boolean subIndexB = !nullSubId && subId.equalsIgnoreCase("b");
    if (index == SEVENTH_INDEX && (nullSubId || !(subIndexA || subIndexB || subIndexC))) {
      throw new IllegalArgumentException("Wrong subindex for index 7");
    }
    // Check if almost one coverage is present
    if (referenceCoverage == null && nowCoverage == null) {
      throw new IllegalArgumentException("No input Coverage provided");
    }

    double areaPx;
    if (pixelArea == null) {
      areaPx = PIXEL_AREA;
    } else {
      areaPx = pixelArea;
    }

    // Check if Geometry area or perimeter must be calculated
    boolean inRasterSpace = true;
    // Selection of the operation to do for each index
    switch (index) {
      case FIFTH_INDEX:
      case SIXTH_INDEX:
      case SEVENTH_INDEX:
      case ELEVENTH_INDEX:
      case TWELVE_INDEX:
        if (!subIndexA) {
          inRasterSpace = false;
        }
        break;
      default:
        break;
    }

    // If the index is 7a-8-9-10 then the input Geometries must be transformed to the Model Space
    List<Geometry> geoms = new ArrayList<Geometry>();
    final AffineTransform gridToWorldCorner =
        (AffineTransform)
            ((GridGeometry2D) referenceCoverage.getGridGeometry())
                .getGridToCRS2D(PixelOrientation.UPPER_LEFT);
    if (inRasterSpace) {
      for (Geometry geo : rois) {
        try {
          geoms.add(JTS.transform(geo, ProjectiveTransform.create(gridToWorldCorner)));
        } catch (MismatchedDimensionException e) {
          LOGGER.log(Level.SEVERE, e.getMessage(), e);
          throw new ProcessException(e);
        } catch (TransformException e) {
          LOGGER.log(Level.SEVERE, e.getMessage(), e);
          throw new ProcessException(e);
        }
      }
    } else {
      geoms.addAll(rois);
    }

    // Check if the Geometries must be reprojected
    /*        Object userData = geoms.get(0).getUserData();
            if (!inRasterSpace && userData instanceof CoordinateReferenceSystem) {
                CoordinateReferenceSystem geomCRS = (CoordinateReferenceSystem) userData;
                CoordinateReferenceSystem refCRS = referenceCoverage.getCoordinateReferenceSystem();
                MathTransform tr = null;
                try {
                    tr = CRS.findMathTransform(geomCRS, refCRS);

                    if (!(tr == null || tr.isIdentity())) {
                        int geosize = geoms.size();
                        for (int i = 0; i < geosize; i++) {
                            Geometry geo = geoms.get(i);
                            Geometry transform = JTS.transform(geo, tr);
                            transform.setUserData(refCRS);
                            geoms.set(i, transform);
                        }
                    }
                } catch (Exception e) {
                    LOGGER.log(Level.SEVERE, e.getMessage(), e);
                    throw new ProcessException(e);
                }
                // Otherwise only set the correct User_Data parameter
            } else if (inRasterSpace){
    */ int geosize = geoms.size();
    final CoordinateReferenceSystem refCrs = referenceCoverage.getCoordinateReferenceSystem();
    for (int i = 0; i < geosize; i++) {
      Geometry geo = geoms.get(i);

      geo.setUserData(refCrs);

      if (geo.getSRID() == 0) {
        try {
          geo.setSRID(CRS.lookupEpsgCode(refCrs, true));
        } catch (FactoryException e) {
          LOGGER.log(Level.WARNING, e.getMessage(), e);
        }
      }
    }
    //        }

    // Empty arrays containing the statistics results
    double[] statsRef = null;
    double[] statsNow = null;
    double[][][] statsComplex = null;

    // Create a new List of CUDA Bean objects
    List<CUDABean> beans = new ArrayList<CUDABean>();

    // Loop around all the Geometries and generate a new CUDA Bean object
    try {
      // MathTransform transform = ProjectiveTransform.create(gridToWorldCorner).inverse();
      int counter = 0;
      int buffer = (index == 12 ? radius : 0);
      for (Geometry geo : geoms) {
        // Create the CUDABean object
        CUDABean bean = new CUDABean();
        bean.setAreaPix(areaPx);

        // Populate it with Reference coverage parameters
        populateBean(bean, true, referenceCoverage, geo, null, buffer);

        // Set the population values if needed
        if (populations != null) {
          Integer popRef = populations.get(0).get(counter);
          bean.setPopRef(popRef);
        }

        // Do the same for the Current Coverage if present
        if (nowCoverage != null) {
          populateBean(bean, false, nowCoverage, geo, null, buffer);
          // Set the population values if needed
          if (populations != null) {
            Integer popCur = populations.get(1).get(counter);
            bean.setPopCur(popCur);
          }
        }
        // Add the bean to the list
        beans.add(bean);
        // Update counter
        counter++;
      }
    } catch (Exception e) {
      LOGGER.log(Level.SEVERE, e.getMessage(), e);
      throw new ProcessException(e);
    }

    // Calculate the index using CUDA
    //		System.out.println(
    // java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime()) );
    //      long startTime = System.currentTimeMillis();
    /**
     * Generalize: > isUrban = false/true ------------------------| > RADIUS [meters] = scalar
     * ---------------------------------|
     */
    Object output = null;
    try {
      output = calculateCUDAIndex(index, subId, beans, rural, radius);
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    //		long estimatedTime = System.currentTimeMillis() - startTime;
    //		System.out.println("Elapsed time calculateCUDAIndex()\t--> " + estimatedTime + " [ms]");
    Rectangle refRect =
        PlanarImage.wrapRenderedImage(referenceCoverage.getRenderedImage()).getBounds();

    // For index 8 calculate the final Image
    if (index == 8 || index == 9 || index == 12) {

      System.out.println("rural=" + rural + " -- radius/buffer=" + radius + " [m]");

      List<StatisticContainer> results = new ArrayList<CLCProcess.StatisticContainer>();
      StatisticContainer stats = new StatisticContainer();
      double[][][] images = (double[][][]) output;

      int numGeo = beans.size();
      // Images to mosaic
      RenderedImage[] refImgs = new RenderedImage[numGeo];
      ROI[] roiObjs = new ROI[numGeo];

      // Giuliano tested for 91 municipalities in NAPLES and it FAILED within the following FOR
      // loop!!
      for (int i = 0; i < numGeo; i++) {
        double[][] refData = images[i];
        CUDABean bean = beans.get(i);
        double[] data = refData[0];
        if (data != null) {
          Rectangle rect =
              new Rectangle(bean.getMinX(), bean.getMinY(), bean.getWidth(), bean.getHeight());
          refImgs[i] = createImage(rect, data);
          roiObjs[i] = bean.getRoiObj();
        }
      }
      ImageLayout layout = new ImageLayout2();
      layout.setMinX(refRect.x);
      layout.setMinY(refRect.y);
      layout.setWidth(refRect.width);
      layout.setHeight(refRect.height);

      RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);

      // Mosaic of the images
      double[] background = (index == 8 || index == 12 ? new double[] {-1.0} : new double[] {0.0});
      RenderedImage finalRef =
          MosaicDescriptor.create(
              refImgs,
              MosaicDescriptor.MOSAIC_TYPE_OVERLAY,
              null,
              roiObjs,
              null,
              background,
              hints);

      // RenderedImageBrowser.showChain(finalRef, false, false);

      // Upgrade of the statistics container
      stats.setReferenceImage(finalRef);
      // Check if the same calculations must be done for the Current coverage
      if (nowCoverage != null && index != 9) {
        RenderedImage[] currImgs = new RenderedImage[numGeo];
        RenderedImage[] diffImgs = new RenderedImage[numGeo];
        for (int i = 0; i < numGeo; i++) {
          CUDABean bean = beans.get(i);
          double[] data = images[i][1];
          double[] diff = images[i][2];
          Rectangle rect =
              new Rectangle(bean.getMinX(), bean.getMinY(), bean.getWidth(), bean.getHeight());
          currImgs[i] = createImage(rect, data);
          diffImgs[i] = createImage(rect, diff);
        }
        // Mosaic of the images
        RenderedImage finalCurr =
            MosaicDescriptor.create(
                currImgs,
                MosaicDescriptor.MOSAIC_TYPE_OVERLAY,
                null,
                roiObjs,
                null,
                background,
                hints);

        // Mosaic of the images
        RenderedImage finalDiff =
            MosaicDescriptor.create(
                diffImgs,
                MosaicDescriptor.MOSAIC_TYPE_OVERLAY,
                null,
                roiObjs,
                null,
                background,
                hints);
        // Update the statistics container
        stats.setNowImage(finalCurr);
        stats.setDiffImage(finalDiff);
      }
      results.add(stats);
      return results;
    }
    /*else if (index == 9) {// LAND TAKE
        double[][][] values = (double[][][]) output;
        statsRef = values[0][0];
        statsNow = values[0].length > 1 ? values[0][1] : null;
    }*/
    else if (index == 11) { // MODEL OF URBAN DEVELOPMENT
      statsComplex = (double[][][]) output;
    } else {
      double[][][] values = (double[][][]) output;
      statsRef = new double[values.length];
      statsNow = (values[0][0].length > 1 ? new double[values.length] : null);

      for (int v = 0; v < values.length; v++) {
        statsRef[v] = values[v][0][0];
        if (values[v][0].length > 1) {
          statsNow[v] = values[v][0][1];
        }
      }
    }

    // Result accumulation
    List<StatisticContainer> results = accumulateResults(rois, statsRef, statsNow, statsComplex);

    return results;
  }
Пример #8
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);
    }
  }
Пример #9
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;
    }
  }
  /**
   * Executes the raster to vector process.
   *
   * @param coverage the input grid coverage
   * @param band the coverage band to process; defaults to 0 if {@code null}
   * @param insideEdges whether boundaries between raster regions with data values (ie. not NODATA)
   *     should be returned; defaults to {@code true} if {@code null}
   * @param roi optional polygonal {@code Geometry} to define a sub-area within which vectorizing
   *     will be done
   * @param noDataValues optional list of values to treat as NODATA; regions with these values will
   *     not be represented in the returned features; if {@code null}, 0 is used as the single
   *     NODATA value; ignored if {@code classificationRanges} is provided
   * @param classificationRanges optional list of {@code Range} objects to pre-classify the input
   *     coverage prior to vectorizing; values not included in the list will be treated as NODATA;
   *     values in the first {@code Range} are classified to 1, those in the second {@code Range} to
   *     2 etc.
   * @param progressListener an optional listener
   * @return a feature collection where each feature has a {@code Polygon} ("the_geom") and an
   *     attribute "value" with value of the corresponding region in either {@code coverage} or the
   *     classified coverage (when {@code classificationRanges} is used)
   * @throws ProcessException
   */
  @DescribeResult(name = "result", description = "The polygon feature collection")
  public SimpleFeatureCollection execute(
      @DescribeParameter(name = "data", description = "The raster to be used as the source")
          GridCoverage2D coverage,
      @DescribeParameter(
              name = "band",
              description = "(Integer, default=0) the source image band to process",
              min = 0)
          Integer band,
      @DescribeParameter(
              name = "insideEdges",
              description =
                  "(Boolean, default=true) whether to vectorize boundaries between adjacent regions with non-outside values",
              min = 0)
          Boolean insideEdges,
      @DescribeParameter(
              name = "roi",
              description = "The geometry used to delineate the area of interest in model space",
              min = 0)
          Geometry roi,
      @DescribeParameter(
              name = "nodata",
              description = "Collection<Number>, default={0}) values to treat as NODATA",
              collectionType = Number.class,
              min = 0)
          Collection<Number> noDataValues,
      @DescribeParameter(
              name = "ranges",
              description =
                  "The list of ranges to be applied. \n"
                      + "Each range is expressed as 'OPEN START ; END CLOSE'\n"
                      + "where 'OPEN:=(|[, CLOSE=)|]',\n "
                      + "START is the low value, or nothing to imply -INF,\n"
                      + "CLOSE is the biggest value, or nothing to imply +INF",
              collectionType = Range.class,
              min = 0)
          List<Range> classificationRanges,
      ProgressListener progressListener)
      throws ProcessException {

    //
    // initial checks
    //
    if (coverage == null) {
      throw new ProcessException("Invalid input, source grid coverage should be not null");
    }

    if (band == null) {
      band = 0;
    } else if (band < 0 || band >= coverage.getNumSampleDimensions()) {
      throw new ProcessException("Invalid input, invalid band number:" + band);
    }

    // do we have classification ranges?
    boolean hasClassificationRanges =
        classificationRanges != null && classificationRanges.size() > 0;

    // apply the classification by setting 0 as the default value and using 1, ..., numClasses for
    // the other classes.
    // we use 0 also as the noData for the resulting coverage.
    if (hasClassificationRanges) {

      final RangeLookupProcess lookup = new RangeLookupProcess();
      coverage = lookup.execute(coverage, band, classificationRanges, progressListener);
    }

    // Use noDataValues to set the "outsideValues" parameter of the Vectorize
    // operation unless classificationRanges are in use, in which case the
    // noDataValues arg is ignored.
    List<Number> outsideValues = new ArrayList<Number>();
    if (noDataValues != null && !hasClassificationRanges) {
      outsideValues.addAll(noDataValues);
    } else {
      outsideValues.add(0);
    }

    //
    // GRID TO WORLD preparation
    //
    final AffineTransform mt2D =
        (AffineTransform) coverage.getGridGeometry().getGridToCRS2D(PixelOrientation.UPPER_LEFT);

    // get the rendered image
    final RenderedImage raster = coverage.getRenderedImage();

    // perform jai operation
    ParameterBlockJAI pb = new ParameterBlockJAI("Vectorize");
    pb.setSource("source0", raster);

    if (roi != null) {
      pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D));
    }
    pb.setParameter("band", band);
    pb.setParameter("outsideValues", outsideValues);
    if (insideEdges != null) {
      pb.setParameter("insideEdges", insideEdges);
    }
    // pb.setParameter("removeCollinear", false);

    final RenderedOp dest = JAI.create("Vectorize", pb);
    @SuppressWarnings("unchecked")
    final Collection<Polygon> prop =
        (Collection<Polygon>) dest.getProperty(VectorizeDescriptor.VECTOR_PROPERTY_NAME);

    // wrap as a feature collection and return
    final SimpleFeatureType featureType =
        CoverageUtilities.createFeatureType(coverage, Polygon.class);
    final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(featureType);
    int i = 0;
    final ListFeatureCollection featureCollection = new ListFeatureCollection(featureType);
    final AffineTransformation jtsTransformation =
        new AffineTransformation(
            mt2D.getScaleX(),
            mt2D.getShearX(),
            mt2D.getTranslateX(),
            mt2D.getShearY(),
            mt2D.getScaleY(),
            mt2D.getTranslateY());
    for (Polygon polygon : prop) {
      // get value
      Double value = (Double) polygon.getUserData();
      polygon.setUserData(null);
      // filter coordinates in place
      polygon.apply(jtsTransformation);

      // create feature and add to list
      builder.set("the_geom", polygon);
      builder.set("value", value);

      featureCollection.add(builder.buildFeature(String.valueOf(i++)));
    }

    // return value
    return featureCollection;
  }
  @DescribeResult(name = "result", description = "The contours feature collection")
  public SimpleFeatureCollection execute(
      @DescribeParameter(name = "data", description = "The raster to be used as the source")
          GridCoverage2D gc2d,
      @DescribeParameter(
              name = "band",
              description = "The source image band to process",
              min = 0,
              max = 1)
          Integer band,
      @DescribeParameter(name = "levels", description = "Values for which to generate contours")
          double[] levels,
      @DescribeParameter(
              name = "interval",
              description = "Interval between contour values (ignored if levels arg is supplied)",
              min = 0)
          Double interval,
      @DescribeParameter(
              name = "simplify",
              description = "Values for which to generate contours",
              min = 0)
          Boolean simplify,
      @DescribeParameter(
              name = "smooth",
              description = "Values for which to generate contours",
              min = 0)
          Boolean smooth,
      @DescribeParameter(
              name = "roi",
              description = "The geometry used to delineate the area of interest in model space",
              min = 0)
          Geometry roi,
      ProgressListener progressListener)
      throws ProcessException {

    //
    // initial checks
    //
    if (gc2d == null) {
      throw new ProcessException("Invalid input, source grid coverage should be not null");
    }
    if (band != null && (band < 0 || band >= gc2d.getNumSampleDimensions())) {
      throw new ProcessException("Invalid input, invalid band number:" + band);
    }
    boolean hasValues = !(levels == null || levels.length == 0);
    if (!hasValues && interval == null) {
      throw new ProcessException("One between interval and values must be valid");
    }

    // switch to geophisics if necessary
    gc2d = gc2d.view(ViewType.GEOPHYSICS);

    //
    // GRID TO WORLD preparation
    //
    final AffineTransform mt2D =
        (AffineTransform) gc2d.getGridGeometry().getGridToCRS2D(PixelOrientation.CENTER);

    // get the list of nodata, if any
    List<Object> noDataList = new ArrayList<Object>();
    for (GridSampleDimension sd : gc2d.getSampleDimensions()) {
      // grab all the explicit nodata
      final double[] sdNoData = sd.getNoDataValues();
      if (sdNoData != null) {
        for (double nodata : sdNoData) {
          noDataList.add(nodata);
        }
      }

      // handle also readers setting up nodata in a category with a specific name
      if (sd.getCategories() != null) {
        for (Category cat : sd.getCategories()) {
          if (cat.getName().equals(NO_DATA)) {
            final NumberRange<? extends Number> catRange = cat.getRange();
            if (catRange.getMinimum() == catRange.getMaximum()) {
              noDataList.add(catRange.getMinimum());
            } else {
              Range<Double> noData =
                  new Range<Double>(
                      catRange.getMinimum(),
                      catRange.isMinIncluded(),
                      catRange.getMaximum(),
                      catRange.isMaxIncluded());
              noDataList.add(noData);
            }
          }
        }
      }
    }

    // get the rendered image
    final RenderedImage raster = gc2d.getRenderedImage();

    // perform jai operation
    ParameterBlockJAI pb = new ParameterBlockJAI("Contour");
    pb.setSource("source0", raster);

    if (roi != null) {
      pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D));
    }
    if (band != null) {
      pb.setParameter("band", band);
    }
    if (interval != null) {
      pb.setParameter("interval", interval);
    } else {
      final ArrayList<Double> elements = new ArrayList<Double>(levels.length);
      for (double level : levels) elements.add(level);
      pb.setParameter("levels", elements);
    }
    if (simplify != null) {
      pb.setParameter("simplify", simplify);
    }
    if (smooth != null) {
      pb.setParameter("smooth", smooth);
    }
    if (noDataList != null) {
      pb.setParameter("nodata", noDataList);
    }

    final RenderedOp dest = JAI.create("Contour", pb);
    @SuppressWarnings("unchecked")
    final Collection<LineString> prop =
        (Collection<LineString>) dest.getProperty(ContourDescriptor.CONTOUR_PROPERTY_NAME);

    // wrap as a feature collection and return
    final SimpleFeatureType schema = CoverageUtilities.createFeatureType(gc2d, LineString.class);
    final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema);
    int i = 0;
    final ListFeatureCollection featureCollection = new ListFeatureCollection(schema);
    final AffineTransformation jtsTransformation =
        new AffineTransformation(
            mt2D.getScaleX(),
            mt2D.getShearX(),
            mt2D.getTranslateX(),
            mt2D.getShearY(),
            mt2D.getScaleY(),
            mt2D.getTranslateY());
    for (LineString line : prop) {

      // get value
      Double value = (Double) line.getUserData();
      line.setUserData(null);
      // filter coordinates in place
      line.apply(jtsTransformation);

      // create feature and add to list
      builder.set("the_geom", line);
      builder.set("value", value);

      featureCollection.add(builder.buildFeature(String.valueOf(i++)));
    }

    // return value

    return featureCollection;
  }
Пример #12
0
    @Override
    public void encode(Object o) throws IllegalArgumentException {
      // register namespaces provided by extended capabilities
      NamespaceSupport namespaces = getNamespaceSupport();
      namespaces.declarePrefix("wcscrs", "http://www.opengis.net/wcs/service-extension/crs/1.0");
      namespaces.declarePrefix(
          "int", "http://www.opengis.net/WCS_service-extension_interpolation/1.0");
      namespaces.declarePrefix("gml", "http://www.opengis.net/gml/3.2");
      namespaces.declarePrefix("gmlcov", "http://www.opengis.net/gmlcov/1.0");
      namespaces.declarePrefix("swe", "http://www.opengis.net/swe/2.0");
      namespaces.declarePrefix("xlink", "http://www.w3.org/1999/xlink");
      namespaces.declarePrefix("xsi", "http://www.w3.org/2001/XMLSchema-instance");

      for (WCS20CoverageMetadataProvider cp : extensions) {
        cp.registerNamespaces(namespaces);
      }

      // is this a GridCoverage?
      if (!(o instanceof GridCoverage2D)) {
        throw new IllegalArgumentException(
            "Provided object is not a GridCoverage2D:"
                + (o != null ? o.getClass().toString() : "null"));
      }
      final GridCoverage2D gc2d = (GridCoverage2D) o;
      // we are going to use this name as an ID
      final String gcName = gc2d.getName().toString(Locale.getDefault());

      // get the crs and look for an EPSG code
      final CoordinateReferenceSystem crs = gc2d.getCoordinateReferenceSystem2D();
      List<String> axesNames =
          GMLTransformer.this.envelopeDimensionsMapper.getAxesNames(gc2d.getEnvelope2D(), true);

      // lookup EPSG code
      Integer EPSGCode = null;
      try {
        EPSGCode = CRS.lookupEpsgCode(crs, false);
      } catch (FactoryException e) {
        throw new IllegalStateException("Unable to lookup epsg code for this CRS:" + crs, e);
      }
      if (EPSGCode == null) {
        throw new IllegalStateException("Unable to lookup epsg code for this CRS:" + crs);
      }
      final String srsName = GetCoverage.SRS_STARTER + EPSGCode;
      // handle axes swap for geographic crs
      final boolean axisSwap = CRS.getAxisOrder(crs).equals(AxisOrder.EAST_NORTH);

      final AttributesImpl attributes = new AttributesImpl();
      helper.registerNamespaces(getNamespaceSupport(), attributes);

      // using Name as the ID
      attributes.addAttribute(
          "", "gml:id", "gml:id", "", gc2d.getName().toString(Locale.getDefault()));
      start("gml:RectifiedGridCoverage", attributes);

      // handle domain
      final StringBuilder builder = new StringBuilder();
      for (String axisName : axesNames) {
        builder.append(axisName).append(" ");
      }
      String axesLabel = builder.substring(0, builder.length() - 1);
      try {
        GeneralEnvelope envelope = new GeneralEnvelope(gc2d.getEnvelope());
        handleBoundedBy(envelope, axisSwap, srsName, axesLabel, null);
      } catch (IOException ex) {
        throw new WCS20Exception(ex);
      }

      // handle domain
      builder.setLength(0);
      axesNames =
          GMLTransformer.this.envelopeDimensionsMapper.getAxesNames(gc2d.getEnvelope2D(), false);
      for (String axisName : axesNames) {
        builder.append(axisName).append(" ");
      }
      axesLabel = builder.substring(0, builder.length() - 1);
      handleDomainSet(gc2d.getGridGeometry(), gc2d.getDimension(), gcName, srsName, axisSwap);

      // handle rangetype
      handleRangeType(gc2d);

      // handle coverage function
      final GridEnvelope2D ge2D = gc2d.getGridGeometry().getGridRange2D();
      handleCoverageFunction(ge2D, axisSwap);

      // handle range
      handleRange(gc2d);

      // handle metadata OPTIONAL
      try {
        handleMetadata(null, null);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      end("gml:RectifiedGridCoverage");
    }