/** * Called by the framework in order to compute the stack of tiles for the given target bands. * * <p>The default implementation throws a runtime exception with the message "not implemented". * * @param targetTiles The current tiles to be computed for each target band. * @param targetRectangle The area in pixel coordinates to be computed (same for all rasters in * <code>targetRasters</code>). * @param pm A progress monitor which should be used to determine computation cancelation * requests. * @throws OperatorException if an error occurs during computation of the target rasters. */ @Override public void computeTileStack( Map<Band, Tile> targetTiles, Rectangle targetRectangle, ProgressMonitor pm) throws OperatorException { final int x0 = targetRectangle.x; final int y0 = targetRectangle.y; final int w = targetRectangle.width; final int h = targetRectangle.height; // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h); double[] tileOverlapPercentage = {0.0, 0.0}; try { if (!isElevationModelAvailable) { getElevationModel(); } computeTileOverlapPercentage(x0, y0, w, h, tileOverlapPercentage); // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h + // ", tileOverlapPercentageMin = " + tileOverlapPercentage[0] + // ", tileOverlapPercentageMax = " + tileOverlapPercentage[1]); } catch (Exception e) { throw new OperatorException(e); } final Tile latTile = targetTiles.get(targetProduct.getBand(LATITUDE_BAND_NAME)); final Tile lonTile = targetTiles.get(targetProduct.getBand(LONGITUDE_BAND_NAME)); final ProductData latData = latTile.getDataBuffer(); final ProductData lonData = lonTile.getDataBuffer(); final double[][] latArray = new double[h][w]; final double[][] lonArray = new double[h][w]; for (int r = 0; r < h; r++) { Arrays.fill(latArray[r], noDataValue); Arrays.fill(lonArray[r], noDataValue); } final int ymin = Math.max(y0 - (int) (tileSize * tileOverlapPercentage[1]), 0); final int ymax = y0 + h + (int) (tileSize * Math.abs(tileOverlapPercentage[0])); final int xmax = x0 + w; final PositionData posData = new PositionData(); final GeoPos geoPos = new GeoPos(); try { if (reGridMethod) { final double[] latLonMinMax = new double[4]; computeImageGeoBoundary(x0, xmax, ymin, ymax, latLonMinMax); final double latMin = latLonMinMax[0]; final double latMax = latLonMinMax[1]; final double lonMin = latLonMinMax[2]; final double lonMax = latLonMinMax[3]; final int nLat = (int) ((latMax - latMin) / delLat) + 1; final int nLon = (int) ((lonMax - lonMin) / delLon) + 1; final double[][] tileDEM = new double[nLat + 1][nLon + 1]; double alt; for (int i = 0; i < nLat; i++) { final double lat = latMin + i * delLat; for (int j = 0; j < nLon; j++) { double lon = lonMin + j * delLon; if (lon >= 180.0) { lon -= 360.0; } geoPos.setLocation(lat, lon); alt = dem.getElevation(geoPos); if (alt == demNoDataValue) { continue; } tileDEM[i][j] = alt; if (!getPosition(lat, lon, alt, x0, y0, w, h, posData)) { continue; } final int ri = (int) Math.round(posData.rangeIndex); final int ai = (int) Math.round(posData.azimuthIndex); if (ri < x0 || ri >= x0 + w || ai < y0 || ai >= y0 + h) { continue; } latArray[ai - y0][ri - x0] = lat; lonArray[ai - y0][ri - x0] = lon; } } } else { final double[][] localDEM = new double[ymax - ymin + 2][w + 2]; final TileGeoreferencing tileGeoRef = new TileGeoreferencing(sourceProduct, x0, ymin, w, ymax - ymin); final boolean valid = DEMFactory.getLocalDEM( dem, demNoDataValue, demResamplingMethod, tileGeoRef, x0, ymin, w, ymax - ymin, sourceProduct, true, localDEM); if (!valid) { return; } for (int y = ymin; y < ymax; y++) { final int yy = y - ymin; for (int x = x0; x < xmax; x++) { final int xx = x - x0; double alt = localDEM[yy + 1][xx + 1]; if (alt == demNoDataValue) { continue; } tileGeoRef.getGeoPos(x, y, geoPos); if (!geoPos.isValid()) { continue; } double lat = geoPos.lat; double lon = geoPos.lon; if (lon >= 180.0) { lon -= 360.0; } if (orbitMethod) { double[] latlon = jOrbit.lp2ell(new Point(x + 0.5, y + 0.5), meta); lat = latlon[0] * Constants.RTOD; lon = latlon[1] * Constants.RTOD; alt = dem.getElevation(new GeoPos(lat, lon)); } if (!getPosition(lat, lon, alt, x0, y0, w, h, posData)) { continue; } final int ri = (int) Math.round(posData.rangeIndex); final int ai = (int) Math.round(posData.azimuthIndex); if (ri < x0 || ri >= x0 + w || ai < y0 || ai >= y0 + h) { continue; } latArray[ai - y0][ri - x0] = lat; lonArray[ai - y0][ri - x0] = lon; } } } // todo should replace the following code with Delaunay interpolation final TileIndex trgIndex = new TileIndex(latTile); for (int y = y0; y < y0 + h; y++) { final int yy = y - y0; trgIndex.calculateStride(y); for (int x = x0; x < x0 + w; x++) { final int xx = x - x0; final int index = trgIndex.getIndex(x); if (latArray[yy][xx] == noDataValue) { latData.setElemDoubleAt(index, fillHole(xx, yy, latArray)); } else { latData.setElemDoubleAt(index, latArray[yy][xx]); } if (lonArray[yy][xx] == noDataValue) { lonData.setElemDoubleAt(index, fillHole(xx, yy, lonArray)); } else { lonData.setElemDoubleAt(index, lonArray[yy][xx]); } } } } catch (Throwable e) { OperatorUtils.catchOperatorException(getId(), e); } }
/** * Compute source image geodetic boundary (minimum/maximum latitude/longitude) from the its corner * latitude/longitude. * * @throws Exception The exceptions. */ private void computeImageGeoBoundary( final int xmin, final int xmax, final int ymin, final int ymax, double[] latLonMinMax) throws Exception { final GeoCoding geoCoding = sourceProduct.getSceneGeoCoding(); if (geoCoding == null) { throw new OperatorException("Product does not contain a geocoding"); } final GeoPos geoPosFirstNear = geoCoding.getGeoPos(new PixelPos(xmin, ymin), null); final GeoPos geoPosFirstFar = geoCoding.getGeoPos(new PixelPos(xmax, ymin), null); final GeoPos geoPosLastNear = geoCoding.getGeoPos(new PixelPos(xmin, ymax), null); final GeoPos geoPosLastFar = geoCoding.getGeoPos(new PixelPos(xmax, ymax), null); final double[] lats = { geoPosFirstNear.getLat(), geoPosFirstFar.getLat(), geoPosLastNear.getLat(), geoPosLastFar.getLat() }; final double[] lons = { geoPosFirstNear.getLon(), geoPosFirstFar.getLon(), geoPosLastNear.getLon(), geoPosLastFar.getLon() }; double latMin = 90.0; double latMax = -90.0; for (double lat : lats) { if (lat < latMin) { latMin = lat; } if (lat > latMax) { latMax = lat; } } double lonMin = 180.0; double lonMax = -180.0; for (double lon : lons) { if (lon < lonMin) { lonMin = lon; } if (lon > lonMax) { lonMax = lon; } } latLonMinMax[0] = latMin; latLonMinMax[1] = latMax; latLonMinMax[2] = lonMin; latLonMinMax[3] = lonMax; }
private void computeTileOverlapPercentage( final int x0, final int y0, final int w, final int h, double[] overlapPercentages) throws Exception { final PixelPos pixPos = new PixelPos(); final GeoPos geoPos = new GeoPos(); final PosVector earthPoint = new PosVector(); final PosVector sensorPos = new PosVector(); double tileOverlapPercentageMax = -Double.MAX_VALUE; double tileOverlapPercentageMin = Double.MAX_VALUE; for (int y = y0; y < y0 + h; y += 20) { for (int x = x0; x < x0 + w; x += 20) { pixPos.setLocation(x, y); sourceGeoCoding.getGeoPos(pixPos, geoPos); final double alt = dem.getElevation(geoPos); GeoUtils.geo2xyzWGS84(geoPos.getLat(), geoPos.getLon(), alt, earthPoint); final double zeroDopplerTime = SARGeocoding.getEarthPointZeroDopplerTime( firstLineUTC, lineTimeInterval, wavelength, earthPoint, orbit.sensorPosition, orbit.sensorVelocity); if (zeroDopplerTime == SARGeocoding.NonValidZeroDopplerTime) { continue; } final double slantRange = SARGeocoding.computeSlantRange(zeroDopplerTime, orbit, earthPoint, sensorPos); final double zeroDopplerTimeWithoutBias = zeroDopplerTime + slantRange / Constants.lightSpeedInMetersPerDay; final int azimuthIndex = (int) ((zeroDopplerTimeWithoutBias - firstLineUTC) / lineTimeInterval + 0.5); double tileOverlapPercentage = (double) (azimuthIndex - y) / (double) tileSize; if (tileOverlapPercentage > tileOverlapPercentageMax) { tileOverlapPercentageMax = tileOverlapPercentage; } if (tileOverlapPercentage < tileOverlapPercentageMin) { tileOverlapPercentageMin = tileOverlapPercentage; } } } if (tileOverlapPercentageMin != Double.MAX_VALUE && tileOverlapPercentageMin < 0.0) { overlapPercentages[0] = tileOverlapPercentageMin - 0.5; } else { overlapPercentages[0] = 0.0; } if (tileOverlapPercentageMax != -Double.MAX_VALUE && tileOverlapPercentageMax > 0.0) { overlapPercentages[1] = tileOverlapPercentageMax + 0.5; } else { overlapPercentages[1] = 0.0; } }