public void render(Graphics2D g2d, IProgressMonitor monitor) throws RenderException { try { final IRenderContext currentContext = getContext(); currentContext.setStatus(ILayer.WAIT); CoordinateReferenceSystem destinationCRS = currentContext.getCRS(); // the bounds of the visible area in world coordinates // get the envelope and the screen extent Envelope envelope = getRenderBounds(); if (envelope == null || envelope.isNull()) { envelope = context.getImageBounds(); } Point upperLeft = currentContext.worldToPixel(new Coordinate(envelope.getMinX(), envelope.getMinY())); Point bottomRight = currentContext.worldToPixel(new Coordinate(envelope.getMaxX(), envelope.getMaxY())); Rectangle screenSize = new Rectangle(upperLeft); screenSize.add(bottomRight); final IGeoResource resource = getContext().getGeoResource(); if (resource == null || !resource.canResolve(JGrassMapGeoResource.class)) { return; } JGrassMapGeoResource grassMapGeoResource = resource.resolve(JGrassMapGeoResource.class, monitor); JGrassRegion fileWindow = new JGrassRegion(grassMapGeoResource.getFileWindow()); JGrassMapsetGeoResource parent = (JGrassMapsetGeoResource) grassMapGeoResource.parent(new NullProgressMonitor()); CoordinateReferenceSystem grassCrs = parent.getLocationCrs(); JGrassRegion screenDrawWindow = new JGrassRegion( envelope.getMinX(), envelope.getMaxX(), envelope.getMinY(), envelope.getMaxY(), fileWindow.getRows(), fileWindow.getCols()); // to intersect with the data window, we transform the screen window JGrassRegion reprojectedScreenDrawWindow = screenDrawWindow; if (!CRS.equalsIgnoreMetadata(destinationCRS, grassCrs)) { reprojectedScreenDrawWindow = screenDrawWindow.reproject(destinationCRS, grassCrs, true); } /* * if the map is not visible, do not render it */ // JGrassRegion fileWindow = grassMapGeoResource.getFileWindow(); Rectangle2D.Double fileRectDouble = fileWindow.getRectangle(); Double reprojScreenRectangle = reprojectedScreenDrawWindow.getRectangle(); if (!reprojScreenRectangle.intersects(fileRectDouble)) { getContext().setStatus(ILayer.DONE); getContext().setStatusMessage(THE_MAP_IS_OUTSIDE_OF_THE_VISIBLE_REGION); System.out.println(THE_MAP_IS_OUTSIDE_OF_THE_VISIBLE_REGION); return; } /* * we will draw only the intersection of the map in the display system = part of visible map */ Rectangle2D drawMapRectangle = reprojectedScreenDrawWindow.getRectangle().createIntersection(fileRectDouble); // Rectangle2D drawMapRectangle = fileRectDouble.getBounds2D(); // resolution is that of the file window double ewRes = fileWindow.getWEResolution(); double nsRes = fileWindow.getNSResolution(); if (fileRectDouble.getWidth() < ewRes || fileRectDouble.getHeight() < nsRes) { getContext().setStatus(ILayer.DONE); getContext().setStatusMessage(THE_MAP_IS_OUTSIDE_OF_THE_VISIBLE_REGION); System.out.println(THE_MAP_IS_OUTSIDE_OF_THE_VISIBLE_REGION); return; } MathTransform transform = CRS.findMathTransform(destinationCRS, grassCrs, true); Coordinate pixelSize = getContext().getPixelSize(); Coordinate c1 = new Coordinate(envelope.getMinX(), envelope.getMinY()); Coordinate c2 = new Coordinate(envelope.getMinX() + pixelSize.x, envelope.getMinY() + pixelSize.y); Envelope envy = new Envelope(c1, c2); Envelope envyTrans = JTS.transform(envy, transform); pixelSize = new Coordinate(envyTrans.getWidth(), envyTrans.getHeight()); /* * if the resolution is higher of that of the screen, it doesn't make much sense to draw it * all. So for visualization we just use the screen resolution to do things faster. */ if (ewRes < pixelSize.x) { ewRes = pixelSize.x; } if (nsRes < pixelSize.y) { nsRes = pixelSize.y; } fileWindow.setNSResolution(nsRes); fileWindow.setWEResolution(ewRes); nsRes = fileWindow.getNSResolution(); ewRes = fileWindow.getWEResolution(); /* * redefine the region of the map to be drawn */ /* * snap the screen to fit into the active region grid. This is mandatory for the exactness * of the query of the pixels (ex. d.what.rast). */ JGrassRegion activeWindow = grassMapGeoResource.getActiveWindow(); Coordinate minXY = JGrassRegion.snapToNextHigherInRegionResolution( drawMapRectangle.getMinX(), drawMapRectangle.getMinY(), activeWindow); Coordinate maxXY = JGrassRegion.snapToNextHigherInRegionResolution( drawMapRectangle.getMaxX(), drawMapRectangle.getMaxY(), activeWindow); JGrassRegion drawMapRegion = new JGrassRegion(minXY.x, maxXY.x, minXY.y, maxXY.y, ewRes, nsRes); // JGrassRegion drawMapRegion = new JGrassRegion(drawMapRectangle.getMinX(), // drawMapRectangle.getMaxX(), drawMapRectangle.getMinY(), drawMapRectangle // .getMaxY(), ewRes, nsRes); JGrassMapEnvironment grassMapEnvironment = grassMapGeoResource.getjGrassMapEnvironment(); GridCoverage2D coverage = JGrassCatalogUtilities.getGridcoverageFromGrassraster(grassMapEnvironment, drawMapRegion); coverage = coverage.view(ViewType.RENDERED); if (coverage != null) { // setting rendering hints RenderingHints hints = new RenderingHints(Collections.EMPTY_MAP); hints.add( new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED)); hints.add( new RenderingHints(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE)); hints.add( new RenderingHints( RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)); hints.add( new RenderingHints( RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED)); hints.add( new RenderingHints( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)); hints.add( new RenderingHints( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE)); hints.add( new RenderingHints( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF)); hints.add(new RenderingHints(JAI.KEY_INTERPOLATION, new InterpolationNearest())); g2d.addRenderingHints(hints); final TileCache tempCache = JAI.createTileCache(); tempCache.setMemoryCapacity(16 * 1024 * 1024); tempCache.setMemoryThreshold(1.0f); hints.add(new RenderingHints(JAI.KEY_TILE_CACHE, tempCache)); // draw AffineTransform worldToScreen = RendererUtilities.worldToScreenTransform(envelope, screenSize, destinationCRS); final GridCoverageRenderer paint = new GridCoverageRenderer(destinationCRS, envelope, screenSize, worldToScreen, hints); RasterSymbolizer rasterSymbolizer = CommonFactoryFinder.getStyleFactory(null).createRasterSymbolizer(); paint.paint(g2d, coverage, rasterSymbolizer); tempCache.flush(); // IBlackboard blackboard = context.getMap().getBlackboard(); // String legendString = coverageReader.getLegendString(); // String name = grassMapGeoResource.getTitle(); // blackboard.putString(JGrassMapGeoResource.READERID + "#" + name, legendString); } } catch (Exception e) { e.printStackTrace(); } finally { getContext().setStatus(ILayer.DONE); getContext().setStatusMessage(null); } }
@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; }