/**
  * Encode the interval range
  *
  * @param range
  */
 private boolean setRange(NumberRange<? extends Number> range) {
   if (range != null
       && !Double.isInfinite(range.getMaximum())
       && !Double.isInfinite(range.getMinimum())) {
     start("swe:interval");
     chars(range.getMinValue() + " " + range.getMaxValue());
     end("swe:interval");
     return true;
   }
   return false;
 }
    /**
     * Set additional dimension metadata to the DescribeCoverage element
     *
     * @param name the custom dimension name
     * @param dimension the custom dimension related {@link DimensionInfo} instance
     * @param helper the {@link WCSDimensionsHelper} instance to be used to parse domains
     * @throws IOException
     */
    private void setAdditionalDimensionMetadata(
        final String name, final DimensionInfo dimension, WCSDimensionsHelper helper)
        throws IOException {
      Utilities.ensureNonNull("helper", helper);
      final String startTag =
          initStartMetadataTag(TAG.ADDITIONAL_DIMENSION, name, dimension, helper);

      start(startTag);
      // Custom dimension only supports List presentation
      final List<String> domain = helper.getDomain(name);
      // TODO: check if we are in the list of instants case, or in the list of periods case

      // list case
      int i = 0;
      for (String item : domain) {
        Date date = WCSDimensionsValueParser.parseAsDate(item);
        if (date != null) {
          final String dimensionId = helper.getCoverageId() + "_dd_" + i;
          encodeDate(date, helper, dimensionId);
          continue;
        }

        Double number = WCSDimensionsValueParser.parseAsDouble(item);
        if (number != null) {
          element(TAG.SINGLE_VALUE, item.toString());
          continue;
        }

        NumberRange<Double> range = WCSDimensionsValueParser.parseAsDoubleRange(item);
        if (range != null) {
          encodeInterval(
              range.getMinValue().toString(), range.getMaxValue().toString(), null, null);
          continue;
        }

        // TODO: Add support for date Ranges
        if (item instanceof String) {
          element(TAG.SINGLE_VALUE, item.toString());
        }
        //                else if (item instanceof DateRange) {
        //                    final String dimensionId = helper.getCoverageId() + "_dd_" + i;
        //                    encodeDateRange((DateRange) item, helper, dimensionId);
        //                }

        // TODO: Add more cases
        i++;
      }
      end(TAG.ADDITIONAL_DIMENSION);
    }
Пример #3
0
 @Override
 public boolean equals(Object obj) {
   if (this == obj) return true;
   if (obj == null) return false;
   if (getClass() != obj.getClass()) return false;
   CoverageDimensionImpl other = (CoverageDimensionImpl) obj;
   if (description == null) {
     if (other.description != null) return false;
   } else if (!description.equals(other.description)) return false;
   if (dimensionType == null) {
     if (other.dimensionType != null) return false;
   } else if (!dimensionType.equals(other.dimensionType)) return false;
   if (id == null) {
     if (other.id != null) return false;
   } else if (!id.equals(other.id)) return false;
   if (name == null) {
     if (other.name != null) return false;
   } else if (!name.equals(other.name)) return false;
   if (nullValues == null) {
     if (other.nullValues != null) return false;
   } else if (!nullValues.equals(other.nullValues)) return false;
   if (range == null) {
     if (other.range != null) return false;
   } else if (!range.equals(other.range)) return false;
   if (unit == null) {
     if (other.unit != null) return false;
   } else if (!unit.equals(other.unit)) return false;
   return true;
 }
Пример #4
0
  /**
   * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using the {@link
   * #raster2Model} that was provided for this coverage.
   *
   * <p>This method is vital when working with coverages that have a raster to model transformation
   * that is not a simple scale and translate.
   *
   * @param image contains the data for the coverage to create.
   * @param raster2Model is the {@link MathTransform} that maps from the raster space to the model
   *     space.
   * @return a {@link GridCoverage}
   * @throws IOException
   */
  protected final GridCoverage2D createCoverage(PlanarImage image, MathTransform raster2Model)
      throws IOException {

    // creating bands
    final SampleModel sm = image.getSampleModel();
    final ColorModel cm = image.getColorModel();
    final int numBands = sm.getNumBands();
    final GridSampleDimension[] bands = new GridSampleDimension[numBands];
    // setting bands names.

    Category noDataCategory = null;
    final Map<String, Double> properties = new HashMap<String, Double>();
    if (!Double.isNaN(noData)) {
      noDataCategory =
          new Category(
              Vocabulary.formatInternational(VocabularyKeys.NODATA),
              new Color[] {new Color(0, 0, 0, 0)},
              NumberRange.create(noData, noData),
              NumberRange.create(noData, noData));

      properties.put("GC_NODATA", new Double(noData));
    }

    Set<String> bandNames = new HashSet<String>();
    for (int i = 0; i < numBands; i++) {
      final ColorInterpretation colorInterpretation = TypeMap.getColorInterpretation(cm, i);
      if (colorInterpretation == null) throw new IOException("Unrecognized sample dimension type");
      Category[] categories = null;
      if (noDataCategory != null) {
        categories = new Category[] {noDataCategory};
      }
      String bandName = colorInterpretation.name();
      // make sure we create no duplicate band names
      if (colorInterpretation == ColorInterpretation.UNDEFINED || bandNames.contains(bandName)) {
        bandName = "Band" + (i + 1);
      }
      bands[i] = new GridSampleDimension(bandName, categories, null).geophysics(true);
    }
    // creating coverage
    if (raster2Model != null) {
      return coverageFactory.create(
          coverageName, image, crs, raster2Model, bands, null, properties);
    }
    return coverageFactory.create(
        coverageName, image, new GeneralEnvelope(originalEnvelope), bands, null, properties);
  }
 /** Add a metadata element to the FileGroup metadata map */
 private void addMetadaElement(
     String name, Comparable min, Comparable max, Map<String, Object> metadataMap) {
   if (Utils.TIME_DOMAIN.equalsIgnoreCase(name) || min instanceof Date) {
     metadataMap.put(name.toUpperCase(), new DateRange((Date) min, (Date) max));
   } else if (Utils.ELEVATION_DOMAIN.equalsIgnoreCase(name) || min instanceof Number) {
     metadataMap.put(
         name.toUpperCase(),
         NumberRange.create(
             ((Number) min).doubleValue(), true, ((Number) max).doubleValue(), true));
   } else {
     metadataMap.put(name, new Range(String.class, (String) min, (String) max));
   }
 }
Пример #6
0
 @Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + ((description == null) ? 0 : description.hashCode());
   result = prime * result + ((dimensionType == null) ? 0 : dimensionType.hashCode());
   result = prime * result + ((id == null) ? 0 : id.hashCode());
   result = prime * result + ((name == null) ? 0 : name.hashCode());
   result = prime * result + ((nullValues == null) ? 0 : nullValues.hashCode());
   result = prime * result + ((range == null) ? 0 : range.hashCode());
   result = prime * result + ((unit == null) ? 0 : unit.hashCode());
   return result;
 }
    /**
     * Set the elevationDomain metadata in case the dimensionsHelper instance has an
     * elevationDimension
     *
     * @param helper
     * @throws IOException
     */
    private void handleElevationMetadata(WCSDimensionsHelper helper) throws IOException {
      // Null check has been performed in advance
      final DimensionInfo elevationDimension = helper.getElevationDimension();
      if (elevationDimension != null) {
        start(initStartMetadataTag(TAG.ELEVATION_DOMAIN, null, elevationDimension, helper));
        final DimensionPresentation presentation = elevationDimension.getPresentation();
        switch (presentation) {
            // Where _er_ means elevation range
          case CONTINUOUS_INTERVAL:
            encodeInterval(helper.getBeginElevation(), helper.getEndElevation(), null, null);
            break;
          case DISCRETE_INTERVAL:
            encodeInterval(
                helper.getBeginElevation(),
                helper.getEndElevation(),
                helper.getElevationResolutionUnit(),
                helper.getElevationResolutionValue());
            break;
          default:
            // TODO: check if we are in the list of instants case, or in the list of periods case

            // list case
            final TreeSet<Object> domain = helper.getElevationDomain();
            for (Object item : domain) {
              if (item instanceof Number) {
                element(TAG.SINGLE_VALUE, item.toString());
              } else if (item instanceof NumberRange) {
                NumberRange range = (NumberRange) item;
                encodeInterval(
                    range.getMinValue().toString(), range.getMaxValue().toString(), null, null);
              }
            }
            break;
        }
        end(TAG.ELEVATION_DOMAIN);
      }
    }
  @Override
  protected void setBoundedByElement(SpatioTemporalImageReader reader) {
    Map<String, String> map = getAttributesMap(reader);
    BoundedBy bb = getBoundedBy();
    if (bb == null) throw new IllegalArgumentException("Provided BoundedBy element is null");

    final String typeS = map.get(GRIB1ImageMetadata.GRID_TYPE);
    // TODO: Add more check on grid types

    // ////////////////////////////////////////////////////////////////////
    //
    // Setting Envelope
    //
    // ////////////////////////////////////////////////////////////////////
    if (typeS != null) {
      final int type = Integer.parseInt(typeS);
      final String lat1s = map.get(GRIB1ImageMetadata.GRID_LAT_1);
      final String lat2s = map.get(GRIB1ImageMetadata.GRID_LAT_2);
      final String lon1s = map.get(GRIB1ImageMetadata.GRID_LON_1);
      final String lon2s = map.get(GRIB1ImageMetadata.GRID_LON_2);
      if (lat1s != null && lat2s != null && lon1s != null && lon2s != null) {
        double[] lc = new double[] {Double.parseDouble(lon1s), Double.parseDouble(lat1s)};
        double[] uc = new double[] {Double.parseDouble(lon2s), Double.parseDouble(lat2s)};

        switch (type) {
          case 10:
            final String deltaX = map.get(GRIB1ImageMetadata.GRID_DELTA_X);
            final String deltaY = map.get(GRIB1ImageMetadata.GRID_DELTA_Y);
            final String latSP = map.get(GRIB1ImageMetadata.GRID_LAT_SP);
            final String lonSP = map.get(GRIB1ImageMetadata.GRID_LON_SP);
            final String nX = map.get(GRIB1ImageMetadata.GRID_N_X);
            final String nY = map.get(GRIB1ImageMetadata.GRID_N_Y);
            if (deltaX != null
                && deltaY != null
                && lonSP != null
                && latSP != null
                && nY != null
                && nX != null) {
              final double lonSp = Double.parseDouble(lonSP);
              final double latSp = Double.parseDouble(latSP);
              final double dX = Double.parseDouble(deltaX);
              final double dY = Double.parseDouble(deltaY);
              final double x = Double.parseDouble(nX);
              final double y = Double.parseDouble(nY);

              uc = getGridCoords(x * dX, y * dY, lc[0], lc[1], lonSp, latSp);
              lc = getGridCoords(0, 0, lc[0], lc[1], lonSp, latSp);
            }
            // TODO: Fix this
          case 0:
            if (lc[0] > uc[0]) {
              final double temp = lc[0];
              lc[0] = uc[0];
              uc[0] = temp;
            }
            if (lc[1] > uc[1]) {
              final double temp = lc[1];
              lc[1] = uc[1];
              uc[1] = temp;
            }
        }
        bb.setLowerCorner(lc);
        bb.setUpperCorner(uc);
      }
    }
    if (isHasVerticalCRS()) {
      final String pdsValues = map.get(GRIB1ImageMetadata.PDSL_VALUES);
      final String isNumeric = map.get(GRIB1ImageMetadata.PDSL_ISNUMERIC);
      if (isNumeric != null && Boolean.parseBoolean(isNumeric)) {
        final String[] values = pdsValues.split(GRIB1Utilities.VALUES_SEPARATOR);
        if (values != null) {
          if (values.length == 1) bb.setVerticalExtent(Double.parseDouble(values[0]));
          else if (values.length == 2) {
            final double d1 = Double.parseDouble(values[0]);
            final double d2 = Double.parseDouble(values[1]);
            if (d1 != d2) bb.setVerticalExtent(NumberRange.create(d1, d2));
            else bb.setVerticalExtent(d1);
          } else {
            throw new IllegalArgumentException("Unable to set a proper Vertical Extent");
          }
        }
      } else {
        bb.setVerticalExtent(0);
      }
    }

    if (isHasTemporalCRS()) {
      // //
      //
      // Setting temporal Extent
      //
      // //
      final String time = map.get(GRIB1ImageMetadata.PROD_TIME);
      if (Utilities.ensureValidString(time)) {
        //                if (time.contains(GRIB1Utilities.DATE_SEPARATOR)) {
        //                    String beginEnd[] = time
        //                            .split(GRIB1Utilities.DATE_SEPARATOR);
        //                    bb.setTemporalExtent(beginEnd);
        //                } else
        //                    bb.setTemporalExtent(time);
      }
    }
  }
  /**
   * Takes a GetLegendGraphicRequest and produces a BufferedImage that then can be used by a
   * subclass to encode it to the appropriate output format.
   *
   * @param request the "parsed" request, where "parsed" means that it's values are already
   *     validated so this method must not take care of verifying the requested layer exists and the
   *     like.
   * @throws ServiceException if there are problems creating a "sample" feature instance for the
   *     FeatureType <code>request</code> returns as the required layer (which should not occur).
   */
  public BufferedImage buildLegendGraphic(GetLegendGraphicRequest request) throws ServiceException {
    // list of images to be rendered for the layers (more than one if
    // a layer group is given)
    List<RenderedImage> layersImages = new ArrayList<RenderedImage>();

    List<LegendRequest> layers = request.getLegends();
    // List<FeatureType> layers=request.getLayers();
    // List<Style> styles=request.getStyles();
    // List<String> rules=request.getRules();

    boolean forceLabelsOn = false;
    boolean forceLabelsOff = false;
    if (request.getLegendOptions().get("forceLabels") instanceof String) {
      String forceLabelsOpt = (String) request.getLegendOptions().get("forceLabels");
      if (forceLabelsOpt.equalsIgnoreCase("on")) {
        forceLabelsOn = true;
      } else if (forceLabelsOpt.equalsIgnoreCase("off")) {
        forceLabelsOff = true;
      }
    }

    boolean forceTitlesOff = false;
    if (request.getLegendOptions().get("forceTitles") instanceof String) {
      String forceTitlesOpt = (String) request.getLegendOptions().get("forceTitles");
      if (forceTitlesOpt.equalsIgnoreCase("off")) {
        forceTitlesOff = true;
      }
    }

    for (LegendRequest legend : layers) {
      FeatureType layer = legend.getFeatureType();

      // style and rule to use for the current layer
      Style gt2Style = legend.getStyle();
      if (gt2Style == null) {
        throw new NullPointerException("request.getStyle()");
      }

      // get rule corresponding to the layer index
      // normalize to null for NO RULE
      String ruleName = legend.getRule(); // was null

      // width and height, we might have to rescale those in case of DPI usage
      int w = request.getWidth();
      int h = request.getHeight();

      // apply dpi rescale
      double dpi = RendererUtilities.getDpi(request.getLegendOptions());
      double standardDpi = RendererUtilities.getDpi(Collections.emptyMap());
      if (dpi != standardDpi) {
        double scaleFactor = dpi / standardDpi;
        w = (int) Math.round(w * scaleFactor);
        h = (int) Math.round(h * scaleFactor);
        DpiRescaleStyleVisitor dpiVisitor = new DpiRescaleStyleVisitor(scaleFactor);
        dpiVisitor.visit(gt2Style);
        gt2Style = (Style) dpiVisitor.getCopy();
      }
      // apply UOM rescaling if we have a scale
      if (request.getScale() > 0) {
        double pixelsPerMeters =
            RendererUtilities.calculatePixelsPerMeterRatio(
                request.getScale(), request.getLegendOptions());
        UomRescaleStyleVisitor rescaleVisitor = new UomRescaleStyleVisitor(pixelsPerMeters);
        rescaleVisitor.visit(gt2Style);
        gt2Style = (Style) rescaleVisitor.getCopy();
      }

      boolean strict = request.isStrict();

      final boolean transparent = request.isTransparent();
      RenderedImage titleImage = null;
      // if we have more than one layer, we put a title on top of each layer legend
      if (layers.size() > 1 && !forceTitlesOff) {
        titleImage = getLayerTitle(legend, w, h, transparent, request);
      }

      // Check for rendering transformation
      boolean hasVectorTransformation = false;
      boolean hasRasterTransformation = false;
      List<FeatureTypeStyle> ftsList = gt2Style.featureTypeStyles();
      for (int i = 0; i < ftsList.size(); i++) {
        FeatureTypeStyle fts = ftsList.get(i);
        Expression exp = fts.getTransformation();
        if (exp != null) {
          ProcessFunction processFunction = (ProcessFunction) exp;
          Name processName = processFunction.getProcessName();
          Map<String, Parameter<?>> outputs = Processors.getResultInfo(processName, null);
          if (outputs.isEmpty()) {
            continue;
          }
          Parameter<?> output =
              outputs.values().iterator().next(); // we assume there is only one output
          if (SimpleFeatureCollection.class.isAssignableFrom(output.getType())) {
            hasVectorTransformation = true;
            break;
          } else if (GridCoverage2D.class.isAssignableFrom(output.getType())) {
            hasRasterTransformation = true;
            break;
          }
        }
      }

      final boolean buildRasterLegend =
          (!strict && layer == null && LegendUtils.checkRasterSymbolizer(gt2Style))
              || (LegendUtils.checkGridLayer(layer) && !hasVectorTransformation)
              || hasRasterTransformation;

      // Just checks LegendInfo currently, should check gtStyle
      final boolean useProvidedLegend = layer != null && legend.getLayerInfo() != null;

      RenderedImage legendImage = null;
      if (useProvidedLegend) {
        legendImage = getLayerLegend(legend, w, h, transparent, request);
      }

      if (buildRasterLegend) {
        final RasterLayerLegendHelper rasterLegendHelper =
            new RasterLayerLegendHelper(request, gt2Style, ruleName);
        final BufferedImage image = rasterLegendHelper.getLegend();
        if (image != null) {
          if (titleImage != null) {
            layersImages.add(titleImage);
          }
          layersImages.add(image);
        }
      } else if (useProvidedLegend && legendImage != null) {
        if (titleImage != null) {
          layersImages.add(titleImage);
        }
        layersImages.add(legendImage);
      } else {
        final Feature sampleFeature;
        if (layer == null || hasVectorTransformation) {
          sampleFeature = createSampleFeature();
        } else {
          sampleFeature = createSampleFeature(layer);
        }
        final FeatureTypeStyle[] ftStyles =
            gt2Style.featureTypeStyles().toArray(new FeatureTypeStyle[0]);
        final double scaleDenominator = request.getScale();

        final Rule[] applicableRules;

        if (ruleName != null) {
          Rule rule = LegendUtils.getRule(ftStyles, ruleName);
          if (rule == null) {
            throw new ServiceException(
                "Specified style does not contains a rule named " + ruleName);
          }
          applicableRules = new Rule[] {rule};
        } else {
          applicableRules = LegendUtils.getApplicableRules(ftStyles, scaleDenominator);
        }

        final NumberRange<Double> scaleRange =
            NumberRange.create(scaleDenominator, scaleDenominator);
        final int ruleCount = applicableRules.length;

        /**
         * A legend graphic is produced for each applicable rule. They're being held here until the
         * process is done and then painted on a "stack" like legend.
         */
        final List<RenderedImage> legendsStack = new ArrayList<RenderedImage>(ruleCount);

        final SLDStyleFactory styleFactory = new SLDStyleFactory();

        double minimumSymbolSize = MINIMUM_SYMBOL_SIZE;
        // get minSymbolSize from LEGEND_OPTIONS, if defined
        if (request.getLegendOptions().get("minSymbolSize") instanceof String) {
          String minSymbolSizeOpt = (String) request.getLegendOptions().get("minSymbolSize");
          try {
            minimumSymbolSize = Double.parseDouble(minSymbolSizeOpt);
          } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid minSymbolSize value: should be a number");
          }
        }
        // calculate the symbols rescaling factor necessary for them to be
        // drawn inside the icon box
        double symbolScale =
            calcSymbolScale(w, h, layer, sampleFeature, applicableRules, minimumSymbolSize);

        for (int i = 0; i < ruleCount; i++) {

          final RenderedImage image =
              ImageUtils.createImage(w, h, (IndexColorModel) null, transparent);
          final Map<RenderingHints.Key, Object> hintsMap =
              new HashMap<RenderingHints.Key, Object>();
          final Graphics2D graphics =
              ImageUtils.prepareTransparency(
                  transparent, LegendUtils.getBackgroundColor(request), image, hintsMap);
          graphics.setRenderingHint(
              RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

          Feature sample = getSampleFeatureForRule(layer, sampleFeature, applicableRules[i]);

          FilterFactory ff = CommonFactoryFinder.getFilterFactory();
          final Symbolizer[] symbolizers = applicableRules[i].getSymbolizers();
          final GraphicLegend graphic = applicableRules[i].getLegend();

          // If this rule has a legend graphic defined in the SLD, use it
          if (graphic != null) {
            if (this.samplePoint == null) {
              Coordinate coord = new Coordinate(w / 2, h / 2);

              try {
                this.samplePoint = new LiteShape2(geomFac.createPoint(coord), null, null, false);
              } catch (Exception e) {
                this.samplePoint = null;
              }
            }
            shapePainter.paint(graphics, this.samplePoint, graphic, scaleDenominator, false);

          } else {

            for (int sIdx = 0; sIdx < symbolizers.length; sIdx++) {
              Symbolizer symbolizer = symbolizers[sIdx];

              if (symbolizer instanceof RasterSymbolizer) {
                // skip it
              } else {
                // rescale symbols if needed
                if (symbolScale > 1.0 && symbolizer instanceof PointSymbolizer) {
                  PointSymbolizer pointSymbolizer = cloneSymbolizer(symbolizer);
                  if (pointSymbolizer.getGraphic() != null) {
                    double size =
                        getPointSymbolizerSize(sample, pointSymbolizer, Math.min(w, h) - 4);
                    pointSymbolizer
                        .getGraphic()
                        .setSize(ff.literal(size / symbolScale + minimumSymbolSize));

                    symbolizer = pointSymbolizer;
                  }
                }

                Style2D style2d = styleFactory.createStyle(sample, symbolizer, scaleRange);
                LiteShape2 shape = getSampleShape(symbolizer, w, h);

                if (style2d != null) {
                  shapePainter.paint(graphics, shape, style2d, scaleDenominator);
                }
              }
            }
          }
          if (image != null && titleImage != null) {
            layersImages.add(titleImage);
            titleImage = null;
          }
          legendsStack.add(image);
          graphics.dispose();
        }

        // JD: changed legend behavior, see GEOS-812
        // this.legendGraphic = scaleImage(mergeLegends(legendsStack), request);
        BufferedImage image =
            mergeLegends(legendsStack, applicableRules, request, forceLabelsOn, forceLabelsOff);
        if (image != null) {
          layersImages.add(image);
        }
      }
    }
    // all legend graphics are merged if we have a layer group
    BufferedImage finalLegend =
        mergeLegends(layersImages, null, request, forceLabelsOn, forceLabelsOff);
    if (finalLegend == null) {
      throw new IllegalArgumentException("no legend passed");
    }
    return finalLegend;
  }
  @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;
  }
Пример #11
0
 /** Returns the expected range of values for the resulting image. */
 protected NumberRange deriveRange(final NumberRange[] ranges, final Parameters parameters) {
   final NumberRange range = ranges[0];
   final double min = Math.log(range.getMinimum());
   final double max = Math.log(range.getMaximum());
   return NumberRange.create(min, max);
 }
  /**
   * Complex test for Postgis indexing on db.
   *
   * @throws Exception
   */
  @Test
  public void testPostgisIndexing() throws Exception {
    final File workDir = new File(TestData.file(this, "."), "watertemp4");
    assertTrue(workDir.mkdir());
    FileUtils.copyFile(TestData.file(this, "watertemp.zip"), new File(workDir, "watertemp.zip"));
    TestData.unzipFile(this, "watertemp4/watertemp.zip");
    final URL timeElevURL = TestData.url(this, "watertemp4");

    // place datastore.properties file in the dir for the indexing
    FileWriter out = null;
    try {
      out = new FileWriter(new File(TestData.file(this, "."), "/watertemp4/datastore.properties"));

      final Set<Object> keyset = fixture.keySet();
      for (Object key : keyset) {
        final String key_ = (String) key;
        final String value = fixture.getProperty(key_);

        out.write(key_.replace(" ", "\\ ") + "=" + value.replace(" ", "\\ ") + "\n");
      }
      out.flush();
    } finally {
      if (out != null) {
        IOUtils.closeQuietly(out);
      }
    }

    // now start the test
    final AbstractGridFormat format = TestUtils.getFormat(timeElevURL);
    assertNotNull(format);
    ImageMosaicReader reader = TestUtils.getReader(timeElevURL, format);
    assertNotNull(reader);

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

    assertEquals("true", reader.getMetadataValue("HAS_TIME_DOMAIN"));
    final String timeMetadata = reader.getMetadataValue("TIME_DOMAIN");
    assertNotNull(timeMetadata);
    assertEquals(2, timeMetadata.split(",").length);
    assertEquals(timeMetadata.split(",")[0], reader.getMetadataValue("TIME_DOMAIN_MINIMUM"));
    assertEquals(timeMetadata.split(",")[1], reader.getMetadataValue("TIME_DOMAIN_MAXIMUM"));

    assertEquals("true", reader.getMetadataValue("HAS_ELEVATION_DOMAIN"));
    final String elevationMetadata = reader.getMetadataValue("ELEVATION_DOMAIN");
    assertNotNull(elevationMetadata);
    assertEquals(2, elevationMetadata.split(",").length);
    assertEquals(
        Double.parseDouble(elevationMetadata.split(",")[0]),
        Double.parseDouble(reader.getMetadataValue("ELEVATION_DOMAIN_MINIMUM")),
        1E-6);
    assertEquals(
        Double.parseDouble(elevationMetadata.split(",")[1]),
        Double.parseDouble(reader.getMetadataValue("ELEVATION_DOMAIN_MAXIMUM")),
        1E-6);

    // limit yourself to reading just a bit of it
    final ParameterValue<GridGeometry2D> gg = AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
    final GeneralEnvelope envelope = reader.getOriginalEnvelope();
    final Dimension dim = new Dimension();
    dim.setSize(
        reader.getOriginalGridRange().getSpan(0) / 2.0,
        reader.getOriginalGridRange().getSpan(1) / 2.0);
    final Rectangle rasterArea = ((GridEnvelope2D) reader.getOriginalGridRange());
    rasterArea.setSize(dim);
    final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
    gg.setValue(new GridGeometry2D(range, envelope));

    // use imageio with defined tiles
    final ParameterValue<List> time = ImageMosaicFormat.TIME.createValue();
    final List<Date> timeValues = new ArrayList<Date>();
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
    Date date = sdf.parse("2008-10-31T00:00:00.000Z");
    timeValues.add(date);
    time.setValue(timeValues);

    final ParameterValue<double[]> bkg = ImageMosaicFormat.BACKGROUND_VALUES.createValue();
    bkg.setValue(new double[] {-9999.0});

    final ParameterValue<Boolean> direct = ImageMosaicFormat.USE_JAI_IMAGEREAD.createValue();
    direct.setValue(false);

    final ParameterValue<List> elevation = ImageMosaicFormat.ELEVATION.createValue();
    elevation.setValue(Arrays.asList(100.0));

    // Test the output coverage
    TestUtils.checkCoverage(
        reader,
        new GeneralParameterValue[] {gg, time, bkg, elevation, direct},
        "Time-Elevation Test");

    reader = TestUtils.getReader(timeElevURL, format);
    elevation.setValue(Arrays.asList(NumberRange.create(0.0, 10.0)));

    // Test the output coverage
    TestUtils.checkCoverage(
        reader,
        new GeneralParameterValue[] {gg, time, bkg, elevation, direct},
        "Time-Elevation Test");
  }
Пример #13
0
  @Test
  public void testFileInfo()
      throws NoSuchAuthorityCodeException, FactoryException, IOException, ParseException {
    File nc2 = new File(TestData.file(this, "."), "nc2");
    if (nc2.exists()) {
      FileUtils.deleteDirectory(nc2);
    }
    assertTrue(nc2.mkdirs());

    File file = TestData.file(this, "O3-NO2.nc");
    FileUtils.copyFileToDirectory(file, nc2);
    file = new File(nc2, "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);
    CloseableIterator<FileGroup> files = null;
    try {
      String[] names = reader.getGridCoverageNames();
      names = new String[] {names[1]};

      for (String coverageName : names) {

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

        ResourceInfo info = reader.getInfo(coverageName);
        assertTrue(info instanceof FileResourceInfo);
        FileResourceInfo fileInfo = (FileResourceInfo) info;
        files = fileInfo.getFiles(null);

        int fileGroups = 0;
        FileGroup fg = null;
        while (files.hasNext()) {
          fg = files.next();
          fileGroups++;
        }
        assertEquals(1, fileGroups);
        File mainFile = fg.getMainFile();
        assertEquals("O3-NO2", FilenameUtils.getBaseName(mainFile.getAbsolutePath()));
        Map<String, Object> metadata = fg.getMetadata();
        assertNotNull(metadata);
        assertFalse(metadata.isEmpty());
        Set<String> keys = metadata.keySet();

        // envelope, time, elevation = 3 elements
        assertEquals(3, keys.size());

        // Check time
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
        Date start = sdf.parse("2012-04-01T00:00:00.000Z");
        Date end = sdf.parse("2012-04-01T01:00:00.000Z");
        DateRange timeRange = new DateRange(start, end);
        assertEquals(timeRange, metadata.get(Utils.TIME_DOMAIN));

        // Check elevation
        NumberRange<Double> elevationRange = NumberRange.create(10.0, 450.0);
        assertEquals(elevationRange, metadata.get(Utils.ELEVATION_DOMAIN));
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (files != null) {
        files.close();
      }
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }