view gnv-artifacts/src/main/java/de/intevation/gnv/raster/Palette.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 c8089cd7d777
children 9a828e5a2390
line wrap: on
line source
package de.intevation.gnv.raster;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.util.Arrays;

import java.awt.Color;

import org.apache.log4j.Logger;

import de.intevation.gnv.raster.Raster.ValueToIndex;

/**
 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
 */
public class Palette
implements   ValueToIndex
{   
	private static Logger log = Logger.getLogger(Palette.class);

    public static final class Entry 
    implements                Comparable
    {
        private Entry  left;
        private Entry  right;

        private int    index;

        private int    externalIndex;

        private double from;
        private double to;

        private String description;

        private Color  color;

        public Entry() {
        }

        public Entry(Entry other) {
            index         = other.index;
            externalIndex = other.externalIndex;
            from          = other.from;
            to            = other.to;
            description   = other.description;
            color         = other.color;
        }

        public Entry(
            int    index, 
            int    externalIndex,
            double from, 
            double to, 
            Color  color,
            String description
        ) {
            this.index         = index;
            this.externalIndex = externalIndex;
            this.from          = from;
            this.to            = to;
            this.color         = color;
            this.description   = description;
        }

        public int compareTo(Object other) {
            Entry e = (Entry)other;
            if (from < e.from) return -1;
            if (from > e.from) return +1;
            return 0;
        }

        public double getFrom() {
            return from;
        }

        public double getTo() {
            return to;
        }

        public Color getColor() {
            return color;
        }

        public int getExternalIndex() {
            return externalIndex;
        }

        public Entry locateEntry(double value) {
            Entry current = this;
            while (current != null) {
                boolean b = value >= current.from;
                if (b && value <= current.to) {
                    return current;
                }
                current = b
                    ? current.right
                    : current.left;
            }
            return null;
        }

        public int locate(double value) {
            Entry entry = locateEntry(value);
            return entry != null
                ? entry.index
                : -1;
        }

        public Entry findByIndex(int index) {
            Entry current = this;
            while (current != null) {
                if (current.index == index) {
                    break;
                }
                current = index < current.index
                    ? current.left
                    : current.right;
            }
            return current;
        }

        public String getDescription() {
            return description;
        }

        public boolean isInfinity() {
            return from == -Double.MAX_VALUE
              ||   to   ==  Double.MAX_VALUE;
        }
    } // class Entry

    protected Entry [] entries;
    protected Entry    lookup;
    protected Color [] rgbs;

    private Entry buildLookup(Entry [] entries, int lo, int hi) {
        if (lo > hi) {
            return null;
        }
        int mid = (lo + hi)/2;
        Entry entry = entries[mid];
        entry.left  = buildLookup(entries, lo, mid-1);
        entry.right = buildLookup(entries, mid+1, hi);
        return entry;
    }

    public Palette() {
    }

    public Palette(Document document) {

        NodeList rangeNodes = document.getElementsByTagName("range");

        entries = new Entry[rangeNodes.getLength()];
        rgbs    = new Color[entries.length];

        for (int i = 0; i < entries.length; ++i) {
            Element rangeElement = (Element)rangeNodes.item(i);
            double from     = doubleValue(rangeElement.getAttribute("from"));
            double to       = doubleValue(rangeElement.getAttribute("to"));
            int    extIndex = intValue(rangeElement.getAttribute("index"), i);
            Color  color    = color(rangeElement.getAttribute("rgb"));
            String desc     = rangeElement.getAttribute("description");
            if (from > to) { double t = from; from = to; to = t; }
            entries[i] = new Entry(i, extIndex, from, to, color, desc);
            rgbs[i] = color;
        }

        buildLookup();
    }

    public Palette(Palette original, int N) {
        if (N < 2)  {
            throw new IllegalArgumentException("N < 2");
        }

        Entry [] origEntries = original.entries;

        int newSize = 0;
        for (int i = 0; i < origEntries.length; ++i) {
            // cannot split infinity intervals
            newSize += origEntries[i].isInfinity() ? 1 : N;
        }

        entries = new Entry[newSize];
        rgbs    = new Color[newSize];

        for (int i = 0, j = 0; i < origEntries.length; ++i) {
            Entry origEntry = origEntries[i];
            if (origEntry.isInfinity()) {
                // infinity intervals are just copied
                Entry nEntry = new Entry(origEntry);
                entries[j] = nEntry;
                rgbs[j]    = nEntry.color;
                nEntry.index = j++;
            }
            else {
                // split interval into N parts
                double from  = origEntry.from;
                double to    = origEntry.to;
                double delta = (to - from)/N;
				for (int k = 0; k < N; ++k) {
                    Entry nEntry = new Entry(origEntry);
                    nEntry.from = from;
                    nEntry.to   = from + delta;
                    from += delta;
                    entries[j] = nEntry;
                    rgbs[j]    = nEntry.color;
                    nEntry.index = j++;
                }
            } // limited interval
        } // for all original entries

        buildLookup();
    }

    private static final int intValue(String s, int def) {
        if (s == null || (s = s.trim()).length() == 0) {
            return def;
        }
        try {
            return Integer.parseInt(s);
        }
        catch (NumberFormatException nfe) {
            log.error(nfe.getLocalizedMessage(), nfe);
        }
        return def;
    }

    private static final double doubleValue(String s) {
        if (s == null || (s = s.trim()).length() == 0) {
            return 0d;
        }
        if ((s = s.toLowerCase()).startsWith("-inf")) {
            return -Double.MAX_VALUE; // XXX: Not using Double.NEGATIVE_INFINITY!
        }

        if (s.startsWith("inf")) {
            return Double.MAX_VALUE; // XXX: Not using Double.NEGATIVE_INFINITY!
        }

        return Double.parseDouble(s);
    }

    private static final Color color(String s) {
        if (s == null || (s = s.trim()).length() == 0) {
            return null;
        }
        return Color.decode(s);
    }


    protected void buildLookup() {
        Arrays.sort(entries);
        lookup = buildLookup(entries, 0, entries.length-1);
    }

    public Palette subdivide(int N) {
        return new Palette(this, N);
    }

    public int getSize() {
        return rgbs.length;
    }

    public Color getColor(int index) {
        return rgbs[index];
    }

    public int indexToRGB(int index) {
        return rgbs[index].getRGB();
    }

    public int toIndex(double value) {
        return lookup.locate(value);
    }

    public Entry getEntry(double value) {
        return lookup.locateEntry(value);
    }

    public Entry getEntryByIndex(int index) {
        return lookup.findByIndex(index);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org