All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.postgis.Point Maven / Gradle / Ivy

Go to download

PostGIS adds support for geographic objects to the PostgreSQL object-relational database.

There is a newer version: 2023.1.0
Show newest version
/*
 * Point.java
 * 
 * PostGIS extension for PostgreSQL JDBC driver - geometry model
 * 
 * (C) 2004 Paul Ramsey, [email protected]
 * 
 * (C) 2005 Markus Schaber, [email protected]
 *
 * (C) 2015 Phillip Ross, [email protected]
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */

package org.postgis;

import java.sql.SQLException;
import java.util.List;

public class Point extends Geometry {
    /* JDK 1.5 Serialization */
    private static final long serialVersionUID = 0x100;

    public static final boolean CUTINTS = true;

    public int hashCode() {
        return super.hashCode() ^ hashCode(x) ^ hashCode(y) ^ hashCode(z) ^ hashCode(m);
    }

    public static int hashCode(double value) {
        long v = Double.doubleToLongBits(value);
        return (int) (v ^ (v >>> 32));
    }

    protected boolean equalsintern(Geometry otherg) {
        Point other = (Point) otherg;
        return equals(other);
    }

	public static boolean double_equals(double a, double b) {
		if ( Double.isNaN(a) && Double.isNaN(b) ) {
			return true;
		}
		else {
			return (a == b);
		}
	}

    public final boolean equals(Point other) {
        boolean xequals = double_equals(x, other.x);
        boolean yequals = double_equals(y, other.y);
        boolean zequals = ((dimension == 2) || double_equals(z, other.z));
        boolean mequals = ((haveMeasure == false) || double_equals(m,other.m));
        boolean result = xequals && yequals && zequals && mequals;
        return result;
    }

    public Point getPoint(int index) {
        if (index == 0) {
            return this;
        } else {
            throw new ArrayIndexOutOfBoundsException("Point only has a single Point! " + index);
        }
    }

    /** Optimized versions for this special case */
    public Point getFirstPoint() {
        return this;
    }

    /** Optimized versions for this special case */
    public Point getLastPoint() {
        return this;
    }

    public int numPoints() {
        return 1;
    }

    /**
     * The X coordinate of the point.
     * In most long/lat systems, this is the longitude.
     */
    public double x;

    /**
     * The Y coordinate of the point.
     * In most long/lat systems, this is the latitude.
     */
    public double y;

    /**
     * The Z coordinate of the point.
     * In most long/lat systems, this is a radius from the 
     * center of the earth, or the height / elevation over
     * the ground.
     */
    public double z;

    /**
     * The measure of the point.
     */
    public double m = 0.0;

    public Point() {
        super(POINT);
    }

    /** Constructs a new Point
     * @param x the longitude / x ordinate
     * @param y the latitude / y ordinate
     * @param z the radius / height / elevation / z ordinate
     */
    public Point(double x, double y, double z) {
        this();
        this.x = x;
        this.y = y;
        this.z = z;
        dimension = 3;
    }

    /** Constructs a new Point
     * @param x the longitude / x ordinate
     * @param y the latitude / y ordinate
     */
    public Point(double x, double y) {
        this();
        this.x = x;
        this.y = y;
        this.z = 0.0;
        dimension = 2;
    }

    /**
     * Construct a Point from EWKT.
     * 
     * (3D and measures are legal, but SRID is not allowed).
     *
     * @param value String representation of the geometry.
     * @throws SQLException when a SQLException occurs
     */
    public Point(String value) throws SQLException {
        this(value, false);
    }

    /**
     * Construct a Point
     * 
     * @param value The text representation of this point
     * @param haveM Hint whether we have a measure. This is used by other
     *            geometries parsing inner points where we only get "1 2 3 4"
     *            like strings without the "POINT(" and ")" stuff. If there
     *            acutally is a POINTM prefix, this overrides the given value.
     *            However, POINT does not set it to false, as they can be
     *            contained in measured collections, as in
     *            "GEOMETRYCOLLECTIONM(POINT(0 0 0))".
     * @throws SQLException when a SQLException occurs
     */
    protected Point(String value, boolean haveM) throws SQLException {
        this();
        value = initSRID(value);

        if (value.indexOf("POINTM") == 0) {
            haveM = true;
            value = value.substring(6).trim();
        } else if (value.indexOf("POINT") == 0) {
            value = value.substring(5).trim();
        }
        String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value, "(", ")");
        List tokens = GeometryTokenizer.tokenize(valueNoParans, ' ');
        try {
            x = Double.valueOf(tokens.get(0)).doubleValue();
            y = Double.valueOf(tokens.get(1)).doubleValue();
            haveM |= tokens.size() == 4;
            if ((tokens.size() == 3 && !haveM) || (tokens.size() == 4)) {
                z = Double.valueOf(tokens.get(2)).doubleValue();
                dimension = 3;
            } else {
                dimension = 2;
            }
            if (haveM) {
                m = Double.valueOf(tokens.get(dimension)).doubleValue();
            }
        } catch (NumberFormatException e) {
            throw new SQLException("Error parsing Point: " + e.toString());
        }
        haveMeasure = haveM;
    }

    public void innerWKT(StringBuffer sb) {
        sb.append(x);
        if (CUTINTS)
            cutint(sb);
        sb.append(' ');
        sb.append(y);
        if (CUTINTS)
            cutint(sb);
        if (dimension == 3) {
            sb.append(' ');
            sb.append(z);
            if (CUTINTS)
                cutint(sb);
        }
        if (haveMeasure) {
            sb.append(' ');
            sb.append(m);
            if (CUTINTS)
                cutint(sb);
        }
    }

    private static void cutint(StringBuffer sb) {
        int l = sb.length() - 2;
        if ((sb.charAt(l + 1) == '0') && (sb.charAt(l) == '.')) {
            sb.setLength(l);
        }
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public double getZ() {
        return z;
    }

    public double getM() {
        return m;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }

    public void setZ(double z) {
        this.z = z;
    }

    public void setM(double m) {
        haveMeasure = true;
        this.m = m;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setZ(int z) {
        this.z = z;
    }

    public double distance(Point other) {
        double tx, ty, tz;
        if (this.dimension != other.dimension) {
            throw new IllegalArgumentException("Points have different dimensions!");
        }
        tx = this.x - other.x;
        switch (this.dimension) {
        case 1 :
            return Math.sqrt(tx * tx);
        case 2 :
            ty = this.y - other.y;
            return Math.sqrt(tx * tx + ty * ty);
        case 3 :
            ty = this.y - other.y;
            tz = this.z - other.z;
            return Math.sqrt(tx * tx + ty * ty + tz * tz);
        default :
            throw new IllegalArgumentException("Illegal dimension of Point" + this.dimension);
        }
    }

    public boolean checkConsistency() {
        return super.checkConsistency() && (this.dimension == 3 || this.z == 0.0)
                && (this.haveMeasure || this.m == 0.0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy