buffereddataraster.java

来自「world wind java sdk 源码」· Java 代码 · 共 340 行

JAVA
340
字号
/*Copyright (C) 2001, 2008 United States Government as represented bythe Administrator of the National Aeronautics and Space Administration.All Rights Reserved.*/package gov.nasa.worldwind.data;import gov.nasa.worldwind.geom.Sector;import gov.nasa.worldwind.util.Logging;/** * @author dcollins * @version $Id: BufferedDataRaster.java 8245 2008-12-22 20:35:39Z dcollins $ */public abstract class BufferedDataRaster implements DataRaster{    private int width;    private int height;    private Sector sector;    private double transparentValue = Double.MAX_VALUE;    public BufferedDataRaster(int width, int height, Sector sector)    {        if (width < 0)        {            String message = Logging.getMessage("generic.ArgumentOutOfRange", "width < 0");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (height < 0)        {            String message = Logging.getMessage("generic.ArgumentOutOfRange", "height < 0");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (sector == null)        {            String message = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.width = width;        this.height = height;        this.sector = sector;    }    public int getWidth()    {        return this.width;    }    public int getHeight()    {        return this.height;    }    public Sector getSector()    {        return this.sector;    }        public double getTransparentValue()    {        return this.transparentValue;    }    public void setTransparentValue(double transparentValue)    {        this.transparentValue = transparentValue;    }    public void drawOnCanvas(DataRaster canvas)    {        if (canvas == null)        {            String message = Logging.getMessage("nullValue.DestinationIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (!(canvas instanceof BufferedDataRaster))        {            String message = Logging.getMessage("DataRaster.IncompatibleRaster", canvas);            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.doDrawOnCanvas((BufferedDataRaster) canvas);    }    public void fill(double value)    {        int width = this.getWidth();        int height = this.getHeight();        double[] samples = new double[width];        java.util.Arrays.fill(samples, value);        // Fill each row of this raster with the clear color.        for (int j = 0; j < height; j++)        {            this.put(0, j, samples, 0, width);        }    }    protected abstract void get(int x, int y, int length, double[] buffer, int pos);    protected abstract void put(int x, int y, double[] buffer, int pos, int length);        protected void doDrawOnCanvas(BufferedDataRaster canvas)    {        if (!this.getSector().intersects(canvas.getSector()))            return;        int thisWidth = this.getWidth();        int thisHeight = this.getHeight();        int canvasWidth = canvas.getWidth();        int canvasHeight = canvas.getHeight();        double thisTransparentValue = this.getTransparentValue();        // Compute the transform from the canvas' coordinate system to this raster's coordinate system.        java.awt.geom.AffineTransform canvasToThis = this.computeDataTransform(            canvasWidth, canvasHeight, canvas.getSector(),            thisWidth, thisHeight, this.getSector());        // Precompute the interpolation values for each transformed x- and y-coordinate.        InterpolantLookupTable lut = this.createLookupTable(            canvasWidth, canvasHeight,           // lookup table dimensions            0, thisWidth - 1, 0, thisHeight - 1, // lookup table xMin, xMax, yMin, yMax            canvasToThis);                       // lookup transform        // Allocate space to hold the lookup table parameters.        double[] xParams = new double[3];        double[] yParams = new double[3];        // Compute the range of x-values in this raster that will be needed during rendering.        lut.computeRangeX(xParams);        int xParamMin = (int) Math.floor(xParams[0]);        int xParamMax = (int) Math.ceil(xParams[1]);        int xParamWidth = xParamMax - xParamMin + 1;        // Allocate a buffer for two rows of samples from this raster, and allocate a buffer for one row of samples        // from the canvas.        double[] thisSamples = new double[2 * xParamWidth];        double[] canvasSamples = new double[canvasWidth];        int x1, x2, y1, y2;        double xf, yf;                // / Iterate over each canvas row, filling canvas pixels with samples from this raster.        for (int j = 0; j < canvasHeight; j++)        {            // If the interpolant lookup table has an entry for "j", then process this row.            if (lut.getInterpolantY(j, yParams))            {                y1 = (int) yParams[0];                y2 = (int) yParams[1];                yf = yParams[2];                // Read the two rows of image samples that straddle yf.                this.get(xParamMin, y1, xParamWidth, thisSamples, 0);                this.get(xParamMin, y2, xParamWidth, thisSamples, xParamWidth);                // Read the canvas row samples.                canvas.get(0, j, canvasWidth, canvasSamples, 0);                // Iterate over each canvas column, sampling canvas pixels.                for (int i = 0; i < canvasWidth; i++)                {                    // If the interpolant lookup table has an entry for "i", then process this column.                    if (lut.getInterpolantX(i, xParams))                    {                        x1 = (int) xParams[0] - xParamMin;                        x2 = (int) xParams[1] - xParamMin;                        xf = xParams[2];                        // Sample this raster with the interpolated coordinates. This produces a bi-linear mix                        // of the four values surrounding the canvas pixel. Place the output in the canvas sample array.                        sample(thisSamples, x1, x2, xf, 0, 1, yf, xParamWidth, thisTransparentValue, canvasSamples, i);                    }                }                // Write the canvas row samples.                canvas.put(0, j, canvasSamples, 0, canvasWidth);            }        }    }    protected java.awt.geom.AffineTransform computeDataTransform(int sourceWidth, int sourceHeight, Sector sourceSector,                                                                 int destWidth, int destHeight, Sector destSector)    {        // Compute the the transform from source to destination coordinates. In this computation a pixel is assumed        // to have no dimension. We measure the distance between pixels rather than some pixel dimension.        double ty = (destHeight - 1) * -(sourceSector.getMaxLatitude().degrees - destSector.getMaxLatitude().degrees)                  / destSector.getDeltaLatDegrees();        double tx = (destWidth  - 1) * (sourceSector.getMinLongitude().degrees - destSector.getMinLongitude().degrees)                  / destSector.getDeltaLonDegrees();        double sy = ((double) (destHeight - 1) / (double) (sourceHeight - 1))                  * (sourceSector.getDeltaLatDegrees() / destSector.getDeltaLatDegrees());        double sx = ((double) (destWidth  - 1) / (double) (sourceWidth  - 1))                  * (sourceSector.getDeltaLonDegrees() /  destSector.getDeltaLonDegrees());        java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform();        transform.translate(tx, ty);        transform.scale(sx, sy);        return transform;    }    private static void sample(double[] source, int x1, int x2, double xf, int y1, int y2, double yf, int width,                               double transparent, double[] dest, int destPos)    {        double ul = source[x1 + y1 * width];        double ll = source[x1 + y2 * width];        double lr = source[x2 + y2 * width];        double ur = source[x2 + y1 * width];        // If all four sample values are not transparent (or missing), then write the interpolated value to the        // destination buffer.        if ((ul != transparent) && (ur != transparent) && (lr != transparent) && (ll != transparent))        {            dest[destPos] =                  ((1.0 - xf) * (1.0 - yf) * ul)                + ((1.0 - xf) * (yf)       * ll)                + ((xf)       * (yf)       * lr)                + ((xf)       * (1.0 - yf) * ur);        }    }    private static class InterpolantLookupTable    {        private int width;        private int height;        private double[] xParams;        private double[] yParams;        public InterpolantLookupTable(int width, int height)        {            this.width = width;            this.height = height;            this.xParams = new double[3 * width];            this.yParams = new double[3 * height];            java.util.Arrays.fill(this.xParams, -1d);            java.util.Arrays.fill(this.yParams, -1d);        }        public final boolean getInterpolantX(int x, double[] params)        {            params[0] = this.xParams[3 * x];            params[1] = this.xParams[3 * x + 1];            params[2] = this.xParams[3 * x + 2];            return params[0] != -1d;        }        public final boolean getInterpolantY(int y, double[] params)        {            params[0] = this.yParams[3 * y];            params[1] = this.yParams[3 * y + 1];            params[2] = this.yParams[3 * y + 2];            return params[0] != -1d;        }        public final void computeRangeX(double[] params)        {            computeInterpolantRange(this.xParams, this.width, params);        }        public final void computeRangeY(double[] params)        {            computeInterpolantRange(this.yParams, this.height, params);        }        private static void computeInterpolantRange(double[] params, int size, double[] result)        {            double min = Double.MAX_VALUE;            double max = -Double.MIN_VALUE;            int index;            for (int i = 0; i < size; i++)            {                index = 3 * i;                if (params[index] != -1d)                {                    // Compute the minimum first parameter (x1 or y1).                    if (params[index] < min)                        min = params[index];                    // Compute the maximum second parameters (x2 or y2).                    if (params[index + 1] > max)                        max = params[index + 1];                }            }            result[0] = min;            result[1] = max;        }    }    private InterpolantLookupTable createLookupTable(int width, int height,        double xMin, double xMax, double yMin, double yMax, java.awt.geom.AffineTransform lookupTransform)    {        // Compute the interpolation values for each transformed x- and y-coordinate. This assumes that the transform        // is composed of translations and scales (no rotations or shears). Therefore the transformed coordinates of        // each row or column would be identical.        InterpolantLookupTable lut = new InterpolantLookupTable(width, height);        double threshold = -1e-6; // Numerical roundoff error threshold.        java.awt.geom.Point2D thisPoint = new java.awt.geom.Point2D.Double();        java.awt.geom.Point2D canvasPoint = new java.awt.geom.Point2D.Double();        double x, y;        int index;        for (int i = 0; i < width; i++)        {            canvasPoint.setLocation(i, 0);            lookupTransform.transform(canvasPoint, thisPoint);            x = thisPoint.getX();            if (((x - xMin) > threshold) && ((xMax - x) > threshold))            {                x = (x < xMin) ? xMin : ((x > xMax) ? xMax : x);                index = 3 * i;                lut.xParams[index]     = Math.floor(x);                lut.xParams[index + 1] = Math.ceil(x);                lut.xParams[index + 2] = x - lut.xParams[index];            }        }        for (int j = 0; j < height; j++)        {            canvasPoint.setLocation(0, j);            lookupTransform.transform(canvasPoint, thisPoint);            y = thisPoint.getY();            if (((y - yMin) > threshold) && ((yMax - y) > threshold))            {                y = (y < yMin) ? yMin : ((y > yMax) ? yMax : y);                index = 3 * j;                lut.yParams[index]     = Math.floor(y);                lut.yParams[index + 1] = Math.ceil(y);                lut.yParams[index + 2] = y - lut.yParams[index];            }        }        return lut;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?