Subversion Repositories hibernate-spatial

Rev

Blame | Last modification | View Log | RSS feed

package org.hibernatespatial.jts.geom;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;

/**
 * A wrapper for <code>Coordinate</code>s that associates it with a measure value.
 *
 * @author Karel Maesen, Geovise BVBA
 *
 */
public class MeasuredCoordinate  {

    private double m = Coordinate.NULL_ORDINATE;
    private Coordinate coordinate;

    public MeasuredCoordinate(Coordinate c, double m) {
        this.coordinate = c;
        this.m = m;
    }

    public MeasuredCoordinate() {
        this.coordinate = new Coordinate();
        this.m = Double.NaN;
    }

    public Coordinate getCoordinate(){
        return this.coordinate;
    }

    public double getX() {
        return this.coordinate.x;
    }

    public double getY() {
        return this.coordinate.y;
    }

    public double getZ() {
        return this.coordinate.z;
    }

    public double getM() {
        return m;
    }

    /**
     * Returns the ordinate value specified in this Coordinate instance. The
     * index of the desired ordinates are specified in the CoordinateSequence
     * class; hence CoodinateSequence.X returns the x ordinate,
     * CoodinateSequence.Y the y ordinate, CoodinateSequence.Z the z ordinate,
     * and CoodinateSequence.M the m ordinate. Note that the dimension may not
     * imply the desired ordinate in the case where one is using a 2 dimensional
     * geometry with a measure value. Therefore, these constants are highly
     * recommended.
     *
     * @param ordinateIndex the desired ordinate index.
     * @return the value of stored in the ordinate index. Incorrect or unused
     *         indexes shall return Double.NaN
     */
    public double getOrdinate(int ordinateIndex) {
        switch (ordinateIndex) {
            case CoordinateSequence.X:
                return this.coordinate.x;
            case CoordinateSequence.Y:
                return this.coordinate.y;
            case CoordinateSequence.Z:
                return this.coordinate.z;
            case CoordinateSequence.M:
                return this.m;
        }
        return Double.NaN;
    }

    /**
     * the value for a given ordinate. This should be specified using the
     * CoordinateSequence ordinate index constants.
     *
     * @param ordinateIndex the desired ordinate index.
     * @param value         the new ordinate value
     * @throws IllegalArgumentException if the ordinateIndex value is incorrect
     * @see #getOrdinate(int)
     */
    public void setOrdinate(int ordinateIndex, double value) {
        switch (ordinateIndex) {
            case CoordinateSequence.X:
                this.coordinate.x = value;
                break;
            case CoordinateSequence.Y:
                this.coordinate.y = value;
                break;
            case CoordinateSequence.Z:
                this.coordinate.z = value;
                break;
            case CoordinateSequence.M:
                this.m = value;
                break;
            default:
                throw new IllegalArgumentException("invalid ordinateIndex");
        }
    }

    public boolean equals2DWithMeasure(MeasuredCoordinate other) {
        return this.coordinate.equals2D(other.coordinate) && (Double.compare(this.m, other.m) == 0) ;
    }

    public boolean equals3DWithMeasure(MeasuredCoordinate other) {
        return this.coordinate.equals3D(other.coordinate) &&
                (Double.compare(this.m, other.m) == 0);
    }

    public String toString() {
        return "(" + this.coordinate.x + "," + this.coordinate.y + "," + this.coordinate.z + "," + " m=" + this.m + ")";
    }

    public static MeasuredCoordinate from(Coordinate c) {
        return new MeasuredCoordinate(c, Double.NaN);
    }

    public static MeasuredCoordinate from(Coordinate c, double m){
        return new MeasuredCoordinate(c, m);
    }

    /**
     * A convenience method for creating a MeasuredCoordinate instance where there are
     * only 2 coordinates and an lrs measure value. The z value of the
     * coordinate shall be set to Double.NaN
     *
     * @param x the x coordinate value
     * @param y the y coordinate value
     * @param m the lrs measure value
     * @return The constructed MCoordinate value
     */
    public static MeasuredCoordinate to2DM(double x, double y, double m) {
        Coordinate c = new Coordinate(x,y);
        return new MeasuredCoordinate(c, m);
    }

    /**
     * A convenience method for creating a MCoordinate instance where there are
     * only 2 coordinates and an lrs measure value. The z and m value of the
     * coordinate shall be set to Double.NaN
     *
     * @param x the x coordinate value
     * @param y the y coordinate value
     * @return The constructed MCoordinate value
     */
    public static MeasuredCoordinate to2D(double x, double y) {
        Coordinate c = new Coordinate(x,y);
        return new MeasuredCoordinate(c, Double.NaN);
    }

    /**
     * A convenience method for creating a MCoordinate instance where there are
     * 3 coordinates and an lrs measure value.
     *
     * @param x the x coordinate value
     * @param y the y coordinate value
     * @param z the z coordinate value
     * @param m the lrs measure value
     * @return The constructed MCoordinate value
     */
    public static MeasuredCoordinate to3DM(double x, double y, double z,
                                                  double m) {
        Coordinate c = new Coordinate(x, y, z);
        return new MeasuredCoordinate(c, m);
    }

    /**
     * A convenience method for creating a MCoordinate instance where there are
     * 3 coordinates but no lrs measure value. The m value of the coordinate
     * shall be set to Double.NaN
     *
     * @param x the x coordinate value
     * @param y the y coordinate value
     * @param z the z coordinate value
     * @return The constructed MCoordinate value
     */
        public static MeasuredCoordinate to3D(double x, double y, double z) {
        Coordinate c = new Coordinate(x,y,z);
                return new MeasuredCoordinate(c, Double.NaN);
        }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MeasuredCoordinate that = (MeasuredCoordinate) o;

        if (Double.compare(that.m, m) != 0) return false;
        if (coordinate != null ? !coordinate.equals(that.coordinate) : that.coordinate != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = m != +0.0d ? Double.doubleToLongBits(m) : 0L;
        result = (int) (temp ^ (temp >>> 32));
        result = 31 * result + (coordinate != null ? coordinate.hashCode() : 0);
        return result;
    }
}