view gnv-artifacts/src/main/java/de/intevation/gnv/raster/Palette.java @ 469:62fc63d0f71d

Added a new State in Product Verticalprofile in Timeseriespoints. Now it will be displayed the Years where measurements happened and than only the dates of the chosen Year will be fetched and displayed. gnv-artifacts/trunk@532 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Tue, 12 Jan 2010 12:42:53 +0000
parents c7ca2fce041f
children c8089cd7d777
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 double from;
        private double to;

        private String description;

        private Color  color;

        public Entry() {
        }

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

        public Entry(
            int    index, 
            double from, 
            double to, 
            Color  color,
            String description
        ) {
            this.index       = index;
            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 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"));
            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, 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 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