view gnv-artifacts/src/main/java/de/intevation/gnv/utils/IndexBuffer.java @ 605:e8ebdbc7f1e3

First step of removing the cache blob. The static part of the describe document will be created by using the input data stored at each state. Some TODOs left (see ChangeLog). gnv-artifacts/trunk@671 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 09 Feb 2010 14:27:55 +0000
parents 555483213f78
children b1f5f2a8840f
line wrap: on
line source
package de.intevation.gnv.utils;

import java.awt.geom.Point2D;

import java.awt.Point;

import java.util.List;

/**
 * Create buffers around integer pairs (i_1..n), j_1..n).
 *
 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
 */
public class IndexBuffer
{
    public static final double EPSILON = 1e-6d;
    public static final double OFFSET  = 1.0d;

    public static final String I_COLUMN = "IPOSITION";
    public static final String J_COLUMN = "JPOSITION";

    public static final class Segment {

        private Segment next;

        private Point2D.Double n;
        private double         d1;
        private double         d2;

        private int iMin;
        private int iMax;

        private int jMin;
        private int jMax;

        public Segment(Point a, Point b, Segment next) {

            this.next = next;

            iMin = Math.min(a.x, b.x)-1;
            iMax = Math.max(a.x, b.x)+1;

            jMin = Math.min(a.y, b.y)-1;
            jMax = Math.max(a.y, b.y)+1;

            if (a.x > b.x) {
                Point p = a; a = b; b = p;
            }

            Point2D.Double p1, p2, p3;

            if (a.y < b.y) {
                p1 = new Point2D.Double(a.x -     OFFSET, a.y + 1 + OFFSET);
                p2 = new Point2D.Double(b.x -     OFFSET, b.y + 1 + OFFSET);
                p3 = new Point2D.Double(a.x + 1 + OFFSET, a.y     - OFFSET);
            }
            else {
                p1 = new Point2D.Double(a.x + 1 + OFFSET, a.y + 1 + OFFSET);
                p2 = new Point2D.Double(b.x + 1 + OFFSET, b.y + 1 + OFFSET);
                p3 = new Point2D.Double(b.x     - OFFSET, b.y     - OFFSET);
            }

            n = normalize(orthogonal(sub(p1, p2)));

            d1 = dot(n, p1);
            d2 = dot(n, p3);

            if (d1 > d2) {
                double d = d1;
                d1 = d2;
                d2 = d;
            }
        }

        public boolean check(int i, int j) {
            if (i < iMin || i > iMax || j < jMin || j > jMax) {
                return false;
            }
            double v = dot(n, i, j);
            return v >= d1 && v <= d2;
        }

        public void toWhereClause(StringBuilder sb, String iColumn, String jColumn) {
            sb.append('(')
              .append(iColumn).append(" >= ").append(iMin).append(" AND ")
              .append(iColumn).append(" <= ").append(iMax).append(" AND ")
              .append(jColumn).append(" >= ").append(jMin).append(" AND ")
              .append(jColumn).append(" <= ").append(jMax).append(" AND (")
              .append(n.x).append('*').append(iColumn).append(" + ")
              .append(n.y).append('*').append(jColumn)
              .append(") BETWEEN ").append(d1).append(" AND ").append(d2).append(')');
        }
    } // class Segment

    protected Segment head;

    protected String iColumn;
    protected String jColumn;

    public IndexBuffer(List<? extends Point> points) {
        this(points, I_COLUMN, J_COLUMN);
    }

    public IndexBuffer(List<? extends Point> points, String iColumn, String jColumn) {
        this.iColumn = iColumn;
        this.jColumn = jColumn;

        for (int i = 1, N = points.size(); i < N; ++i) {
            Point p1 = (Point)points.get(i-1);
            Point p2 = (Point)points.get(i);
            head = new Segment(p1, p2, head);
        }
    }

    public boolean check(int i, int j) {

        Segment current = head;
        while (current != null) {
            if (current.check(i, j)) {
                return true;
            }
            current = current.next;
        }
        return false;
    }

    public String toWhereClause() {

        StringBuilder sb = new StringBuilder();

        Segment current = head;

        while (current != null) {
            if (current != head) {
                sb.append(" OR ");
            }
            current.toWhereClause(sb, iColumn, jColumn);
            current = current.next;
        }

        return sb.toString();
    }

    public static Point2D.Double sub(Point2D.Double p1, Point2D.Double p2) {
        return new Point2D.Double(p1.x - p2.x, p1.y - p2.y);
    }

    public static final double dot(Point2D.Double p1, Point2D.Double p2) {
        return p1.x*p2.x + p1.y*p2.y;
    }

    public static final double dot(Point2D.Double p1, double x, double y) {
        return p1.x*x + p1.y*y;
    }

    public static final Point2D.Double scale(Point2D.Double p, double s) {
        return new Point2D.Double(s*p.x, s*p.y);
    }

    public static final Point2D.Double normalize(Point2D.Double p) {
        double len2 = Math.sqrt(dot(p, p));
        return len2 > EPSILON ? scale(p, 1d/len2) : p;
    }

    public static final Point2D.Double orthogonal(Point2D.Double p) {
        return new Point2D.Double(p.y, -p.x);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org