/** * Transform a raster to the target coordinate system. * * <p>This method transforms the whole raster into the target CRS of this RasterTransformer. The * size of the output raster will be calculated, so that the pixels keep the aspect ratio (i.e. * keep square pixels). * * <p>If the coordinate system of the source raster is <code>null</code> or equals the target crs, * the source raster will be returned unaltered. * * @param sourceRaster the raster to be transformed * @param interpolationType * @return the transformed raster * @throws IllegalArgumentException * @throws TransformationException * @throws UnknownCRSException */ public AbstractRaster transform(AbstractRaster sourceRaster, InterpolationType interpolationType) throws IllegalArgumentException, TransformationException, UnknownCRSException { ICRS srcCRS = sourceRaster.getCoordinateSystem(); if (srcCRS == null || srcCRS.equals(getTargetCRS())) { return sourceRaster; } GeometryTransformer gt = new GeometryTransformer(getTargetCRS()); Envelope dstEnvelope = gt.transform(sourceRaster.getEnvelope(), srcCRS).getEnvelope(); int srcWidth = sourceRaster.getColumns(); int srcHeight = sourceRaster.getRows(); // calculate the new size, consider the aspect ratio to get square pixels double deltaX = dstEnvelope.getSpan0(); double deltaY = dstEnvelope.getSpan1(); double diagSize = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // pixelSize for calculation of the new image size double pixelSize = diagSize / Math.sqrt(Math.pow(srcWidth, 2) + Math.pow(srcHeight, 2)); int dstHeight = (int) (deltaY / pixelSize + 0.5); int dstWidth = (int) (deltaX / pixelSize + 0.5); return transform(sourceRaster, dstEnvelope, dstWidth, dstHeight, interpolationType); }
/** * Create a new raster that contains all data we need for the transformation. * * @throws IllegalArgumentException */ private AbstractRaster getSubRaster( ICRS srcCRS, AbstractRaster sourceRaster, Envelope dstEnvelope) throws TransformationException, IllegalArgumentException { Envelope dataEnv = dstEnvelope; if (srcCRS != null && !srcCRS.equals(getTargetCRS())) { GeometryTransformer srcTransf = new GeometryTransformer(srcCRS); // the envelope from which we need data Envelope workEnv = srcTransf.transform(dstEnvelope, getTargetCRS()); Envelope dataEnvelope = sourceRaster.getEnvelope(); // the envelope from which we have data Geometry dataEnvGeom = workEnv.getIntersection(dataEnvelope); if (dataEnvGeom == null) { LOG.debug("no intersection for " + sourceRaster + " and " + dstEnvelope); // todo create subclass of TransformationException throw new TransformationException("no source data found"); } dataEnv = dataEnvGeom.getEnvelope(); } AbstractRaster source; try { source = sourceRaster.getSubRaster(dataEnv); } catch (IndexOutOfBoundsException ex) { throw new TransformationException("no source data found"); } // if ( LOG.isDebugEnabled() ) { // debugRasterFile( source ); // } return source; }
/** * Returns new RasterGeoReference with the origin set to the min[0],max[1] of the envelope and the * OriginLocation to the given one. Other values are taken from this instance. Attention, the * resulting origin is snapped to the location (center/outer) of the underlying grid, so the * min[0] and max[1] values are only approximations to the new origin! * * @param targetLocation * @param envelope to get the origin from. * @return new RasterGeoReference or <code>null</code> if the envelope is <code>null</code> */ public RasterGeoReference createRelocatedReference( OriginLocation targetLocation, Envelope envelope) { if (envelope != null) { OriginLocation tLoc = (targetLocation == null) ? location : targetLocation; Envelope transformedEnv = envelope; if (transformer != null) { try { transformedEnv = transformer.transform(envelope).getEnvelope(); } catch (IllegalArgumentException e) { // just don't transform and go ahead without. } catch (TransformationException e) { // just don't transform and go ahead without. } catch (UnknownCRSException e) { // just don't transform and go ahead without. } catch (ReferenceResolvingException e) { // just don't transform and go ahead without. } } double[] min = transformedEnv.getMin().getAsArray(); double[] max = transformedEnv.getMax().getAsArray(); int[] rasterCoordinate = getRasterCoordinate(min[0], max[1]); // take the 'upper' left raster position as the new origin, thus add a half pixel. double raster0 = rasterCoordinate[0] + (tLoc == CENTER ? 0.5 : 0); double raster1 = rasterCoordinate[1] + (tLoc == CENTER ? 0.5 : 0); // if ( location == CENTER ) { // raster0 += 0.5; // raster1 += 0.5; // } // if ( tLoc != location ) { // if ( tLoc == OUTER ) { // // this location is center, the above subtracted 0.5 will get the raster location of the // centered // // view, but to get an OUTER view we need to subtract another half a pixel. // raster0 -= 0.5; // raster1 -= 0.5; // } else { // // this location is OUTER, add 0.5 to get the center location // raster0 += 0.5; // raster1 += 0.5; // } // } double[] worldCoordinate = getWorldCoordinate(raster0, raster1); return new RasterGeoReference( tLoc, this.getResolutionX(), this.getResolutionY(), this.getRotationX(), this.getRotationY(), worldCoordinate[0], worldCoordinate[1], this.crs); } return null; }
/** * Converts an envelope in world coordinates to raster coordinates, note the envelope in world * coordinates is defined over min/max (lower left/upper right), whereas a RasterRect is defined * as min(upperleft) with a width and height. * * @param envelope envelope in world coordinates * @return RasterRect */ public RasterRect convertEnvelopeToRasterCRS(Envelope envelope) { RasterRect result = new RasterRect(); if (envelope != null) { Envelope transformedEnv = envelope; if (transformer != null) { try { transformedEnv = transformer.transform(envelope).getEnvelope(); } catch (IllegalArgumentException e) { // just don't transform and go ahead without. } catch (TransformationException e) { // just don't transform and go ahead without. } catch (UnknownCRSException e) { // just don't transform and go ahead without. } } double[] min = transformedEnv.getMin().getAsArray(); double[] max = transformedEnv.getMax().getAsArray(); // upper left point double ulX = min[0]; double ulY = max[1]; // lower right point double lrX = max[0]; double lrY = min[1]; // finding easting and northing ordinates is not necessary because the transform is aligned // with the defined // coordinatesystem. int[] rrUpperLeft = getRasterCoordinate(ulX, ulY); int[] rrLowerRight = getRasterCoordinate(lrX, lrY); // get the minimal raster x value. result.x = min(rrUpperLeft[0], rrLowerRight[0]); // and the minimal raster y value result.y = min(rrUpperLeft[1], rrLowerRight[1]); // find 'unrounded' location raster locations. double[] rrUL = getRasterCoordinateUnrounded(ulX, ulY); double[] rrLR = getRasterCoordinateUnrounded(lrX, lrY); // floor the unrounded min, ceil the unrounded max, this equals the outer representation, for // example the // point 1.1, 3.1 must result in a span of 1-4. (Draw it out :-) ) e.g a width of 3 result.width = (int) abs(floor(rrUL[0]) - ceil(rrLR[0])); result.height = (int) abs(floor(rrUL[1]) - ceil(rrLR[1])); } return result; }
/** * Relocates the given minimum and maximum points of the given envelope to the target origin * location definition. This method does nothing if the given location equals this {@link * RasterGeoReference}'s origin location. This method effectively adds or subtracts half a * resolution of the ordinates of the given Envelope. Different CRS's are supported. * * @param targetLocation the preferred location of the origin. * * @param envelope to relocate. * @return a new Envelope which is aligned with the target location or <code>null</code> if the * envelope is <code>null</code> */ public Envelope relocateEnvelope(OriginLocation targetLocation, Envelope envelope) { if (envelope == null) { return null; } if (targetLocation == location) { return envelope; } // rb: the envelope will not create copies, neither does the geometryfactory ;-) double[] orig = envelope.getMin().getAsArray(); double[] nMin = new double[orig.length]; System.arraycopy(orig, 0, nMin, 0, orig.length); orig = envelope.getMax().getAsArray(); double[] nMax = new double[orig.length]; System.arraycopy(orig, 0, nMax, 0, orig.length); Envelope transformedEnv = geomFactory.createEnvelope(nMin, nMax, envelope.getCoordinateSystem()); if (targetLocation != location) { if (transformer != null && envelope.getCoordinateSystem() != null) { try { transformedEnv = transformer.transform(envelope).getEnvelope(); } catch (IllegalArgumentException e) { // just don't transform and go ahead without. } catch (TransformationException e) { // just don't transform and go ahead without. } catch (UnknownCRSException e) { // just don't transform and go ahead without. } catch (ReferenceResolvingException e) { // just don't transform and go ahead without. } } double[] min = transformedEnv.getMin().getAsArray(); double[] max = transformedEnv.getMax().getAsArray(); double[] rasterCoordinateMin = getRasterCoordinateUnrounded(min[0], min[1]); double[] rasterCoordinateMax = getRasterCoordinateUnrounded(max[0], max[1]); double world0Min = rasterCoordinateMin[0]; double world1Min = rasterCoordinateMin[1]; double world0Max = rasterCoordinateMax[0]; double world1Max = rasterCoordinateMax[1]; if (location == CENTER) { // the targetlocation is OUTER // take the 'upper' left raster position as the new origin. world0Min -= 0.5; world1Min -= 0.5; world0Max -= 0.5; world1Max -= 0.5; } else { // the targetlocation is CENTER world0Min += 0.5; world1Min += 0.5; world0Max += 0.5; world1Max += 0.5; } double[] worldMinCoordinate = getWorldCoordinate(world0Min, world1Min); double[] worldMaxCoordinate = getWorldCoordinate(world0Max, world1Max); nMin[0] = worldMinCoordinate[0]; nMin[1] = worldMinCoordinate[1]; nMax[0] = worldMaxCoordinate[0]; nMax[1] = worldMaxCoordinate[1]; transformedEnv = geomFactory.createEnvelope(nMin, nMax, transformedEnv.getCoordinateSystem()); // no convert back to the requested crs if (transformer != null && envelope.getCoordinateSystem() != null) { try { GeometryTransformer invTrans = new GeometryTransformer(envelope.getCoordinateSystem()); transformedEnv = invTrans.transform(transformedEnv).getEnvelope(); } catch (IllegalArgumentException e) { // just don't transform and go ahead without. } catch (TransformationException e) { // just don't transform and go ahead without. } catch (UnknownCRSException e) { // just don't transform and go ahead without. } catch (ReferenceResolvingException e) { // just don't transform and go ahead without. } } } return transformedEnv; }
/** * Returns an Envelope for a raster with given size and given x,y raster location. * * <p>The calculation considers the origin and resolution of the raster. * * @param targetLocation of the origin, specifies if the the newly created envelope should * consider the origin located at the OUTER or CENTER of a pixel. * @param rasterRect defining the x,y raster coordinates (as integers) as well as the width and * height of the raster. * @param crs the coordinate system for the envelope * @return the calculated envelope */ public Envelope getEnvelope(OriginLocation targetLocation, RasterRect rasterRect, ICRS crs) { // if the targetlocation must be center, we add half a pixel, because we need to get the world // coordinate of the // center of the pixel. double nullX = rasterRect.x + (targetLocation == CENTER ? 0.5 : 0); double nullY = rasterRect.y + (targetLocation == CENTER ? 0.5 : 0); double tw = nullX + rasterRect.width; double th = nullY + rasterRect.height; // double tw = rasterRect.width; // double th = rasterRect.height; // if ( location == CENTER ) { // // if the targetlocation must be center, we add half a pixel, because we need to get the // world coordinate of // // the center of the pixel. // tw += 0.5; // th += 0.5; // } // // if ( location != targetLocation ) { // if ( targetLocation == OUTER ) { // // this location is center, the target location is outer, subtract 0.5 pixel from the // width|height. // // tw -= 0.5; // // th -= 0.5; // pixelAddUp -= 0.5; // } else { // // this location is outer, the target location is center, add 0.5 pixel to the width|height // // tw += 0.5; // // th += 0.5; // pixelAddUp += 0.5; // } // } // nullX += pixelAddUp; // nullY += pixelAddUp; // tw += pixelAddUp; // th += pixelAddUp; double[] widthHeightPos = getWorldCoordinate(tw, th); double[] origin = getWorldCoordinate(nullX, nullY); // double[] origin = getOrigin(); // if ( location != targetLocation ) { // if ( targetLocation == OUTER ) { // // this location is center, the target location is outer, subtract 0.5 res to the origin. // origin[0] -= resX * 0.5; // origin[1] -= resY * 0.5; // } else { // // this location is outer, the target location is center, add 0.5 resolution to the origin // origin[0] += resX * 0.5; // origin[1] += resY * 0.5; // } // } // convert to lower-left and upper-right for the envelope double min0 = min(widthHeightPos[0], origin[0]); double min1 = min(widthHeightPos[1], origin[1]); double max0 = max(widthHeightPos[0], origin[0]); double max1 = max(widthHeightPos[1], origin[1]); // coordinates are in the crs, so axis order is available. Envelope result = geomFactory.createEnvelope(min0, min1, max0, max1, this.crs); if (crs != null && this.crs != null) { GeometryTransformer trans = new GeometryTransformer(crs); try { result = trans.transform(result).getEnvelope(); } catch (Throwable e) { // let the envelope be. } } return result; }