view gnv-artifacts/src/main/java/de/intevation/gnv/raster/Raster.java @ 522:c896282c2601

Issue 156 solved. Added width, height and points as parameter to svg and pdf output mode. Width and height have an effact on the width and height of the export, points is a boolean property which enables/disables the drawing of data points. gnv-artifacts/trunk@616 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 25 Jan 2010 09:18:31 +0000
parents 6e8364e766fa
children c4156275c1e1
line wrap: on
line source
package de.intevation.gnv.raster;

/**
 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
 */
public class Raster
{
    public static class Kernel {

        public static final class Coeff {
            public int    di;
            public int    dj;
            public double c;

            public Coeff() {
            }

            public Coeff(int di, int dj, double c) {
                this.di = di;
                this.dj = dj;
                this.c  = c;
            }

            public String toString() {
                return String.valueOf(c);
            }

        } // class Coeff

        protected Coeff [] coeffs;
        protected int      width;

        public Kernel() {
        }

        public Kernel(Coeff [] coeffs, int width) {
            this.coeffs = coeffs;
            this.width  = width;
        }

        public static double gauss(double x, double y, double sigma) {
            double s2 = sigma*sigma;
            return 1.0d/(2.0d*Math.PI*s2)*Math.exp(-(x*x + y*y)/(2.0d*s2));
        }

        public static Kernel createGauss() {
            return createGauss(1.0d, 5);
        }

        public static Kernel createGauss(double sigma, int width) {
            Coeff [] coeffs = new Coeff[width*width];
            double sum = 0d;
            for (int j = 0; j < width; ++j) {
                int y = -width/2 + j;
                for (int i = 0; i < width; ++i) {
                    int x = -width/2 + i;
                    double c = gauss(x, y, sigma);
                    coeffs[j*width + i] = new Coeff(x, y, c);
                    sum += c;
                }
            }
            sum = 1.0/sum;
            for (int i = 0; i < coeffs.length; ++i) {
                coeffs[i].c *= sum;
            }
            return new Kernel(coeffs, width);
        }

        public double fold(Access access, int i, int j) {

            double s = 0.0d;

            double unused = 0d;

            for (int k = 0; k < coeffs.length; ++k) {
                Coeff coeff = coeffs[k];
                double v = access.get(i + coeff.di, j + coeff.dj);
                if (Double.isNaN(v)) {
                    unused += coeff.c;
                }
                else {
                    s += v * coeff.c;
                }
            }

            return s*(1.0d - unused);
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();

            int height = coeffs.length/width;

            for (int j = 0; j < height; ++j) {
                if (j > 0) {
                    sb.append(System.getProperty("line.separator"));
                }
                for (int i = 0; i < width; ++i) {
                    if (i > 0) {
                        sb.append("\t");
                    }
                    sb.append(coeffs[j*width + i]);
                }
            }

            return sb.toString();
        }
    } // class Kernel

    public interface Access {

        double get(int i, int j);

    } // interface Access

    public interface ValueToIndex {

        int toIndex(double value);

    } // interface ValueToIndex;

    public static class IsoClasses
    implements          ValueToIndex
    {
        protected double m;
        protected double b;
        protected int    numClasses;

        public IsoClasses(Raster raster, int numClasses) {

            this.numClasses = numClasses;

            double min =  Double.MAX_VALUE;
            double max = -Double.MAX_VALUE;

            double [] src = raster.raster;

            for (int i = 0; i < src.length; ++i) {
                double x = src[i];
                if (!Double.isNaN(x)) {
                    if (x < min) min = x;
                    if (x > max) max = x;
                }
            }

            /* f(min) = 0, f(max) = numClasses - 1

               I:  0              = m*min + b
               II: numClasses - 1 = m*max + b

               II - I:
               numClasses - 1 = m*(max - min)

               m = (numClasses - 1)/(max - min)
               b = m*min
            */

            if (max == min) {
                m = 0;
                b = 0;
            }
            else {
                m = (numClasses - 1)/(max - min);
                b = m*min;
            }
        }

        public int toIndex(double value) {
            return Double.isNaN(value)
                ? -1
                : Math.min(Math.max(0, (int)Math.round(m*value + b)), numClasses-1);
        }
    } // class IsoClasses

    protected double [] raster;
    protected int       width;

    public Raster() {
        this(new double[0], 0);
    }

    public Raster(double [] raster, int width) {
        this.raster = raster;
        this.width  = width;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return raster.length / width;
    }

    public double [] getValues() {
        return raster;
    }

    public int [] toIndexed(ValueToIndex valueToIndex) {
        int [] dst = new int[raster.length];
        for (int i = 0; i < raster.length; ++i) {
            dst[i] = valueToIndex.toIndex(raster[i]);
        }
        return dst;
    }

    public Raster create(Kernel kernel) {
        double [] dst = new double[raster.length];
        Raster r = new Raster(dst, width);
        r.apply(kernel, continueBorder());
        return r;
    }

    public void apply(Kernel kernel, Access access) {
        int height = getHeight();
        for (int j = 0; j < height; ++j) {
            int row = j*width;
            for (int i = 0; i < width; ++i) {
                raster[row + i] = kernel.fold(access, i, j);
            }
        }
    }

    public Access continueBorder() {
        return new Access() {
            int height = getHeight()-1;
            public double get(int i, int j) {
                     if (i < 0)      i = 0;
                else if (i >= width) i = width-1;
                     if (j < 0)      j = 0;
                else if (j > height) j = height;
                return raster[j*width + i];
            }
        };
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org