view gnv-artifacts/src/main/java/de/intevation/gnv/utils/IndexBuffer.java @ 1051:8f836fb6f592

Introduced an epsilon (750ms) to be more tolerant while comparing two data objects (issue286). gnv-artifacts/trunk@1125 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 25 May 2010 17:46:28 +0000
parents 6cff63d0c434
children f953c9a559d8
line wrap: on
line source
package de.intevation.gnv.utils;

import java.awt.Point;

import java.awt.geom.Point2D;

import java.util.List;

/**
 * Create buffers around integer pairs (i_1..n), j_1..n).
 *
 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
 */
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