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

net.sf.eBusx.geo.Position Maven / Gradle / Ivy

//
// Copyright 2021 Charles W. Rapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package net.sf.eBusx.geo;

import java.math.BigDecimal;
import java.util.Objects;
import javax.annotation.Nullable;
import net.sf.eBus.messages.EField;
import net.sf.eBus.util.Validator;
import static net.sf.eBusx.geo.GeoObject.validateLatitude;
import static net.sf.eBusx.geo.GeoObject.validateLongitude;

/**
 * A position is the fundamental geometry construct. The
 * "coordinates" member of a Geometry object is composed of
 * either:
 * 
    *
  • * one position in the case of a Point geometry, *
  • *
  • * an array of positions in the case of a LineString or * MultiPoint geometry, *
  • *
  • * an array of LineString or linear ring coordinates in the * case of a Polygon or MultiLineString geometry, or *
  • *
  • * an array of Polygon coordinates in the case of a * MultiPolygon geometry. *
  • *
* A position is an array of numbers. There MUST be two or more * elements. The first two elements are longitude and latitude, * or easting and northing, precisely in that order and using * decimal numbers. Altitude or elevation may be * included as an optional third element. *

* Implementations should not extend positions * beyond three elements because the semantics of extra elements * are unspecified and ambiguous. Historically, some * implementations have used a fourth element to carry a linear * referencing measure (sometimes denoted as "M") or a numerical * timestamp, but in most situations a parser will not be able to * properly interpret these values. The interpretation and * meaning of additional elements is beyond the scope of this * specification, and additional elements may be ignored * by parsers. *

* * @author Charles W. Rapp */ public final class Position extends EField { //--------------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Constants. // /** * Serialization version identifier. */ private static final long serialVersionUID = 0x000100L; //----------------------------------------------------------- // Locals. // /** * Latitude coordinate in degrees (North of equator is * positive) using the standard WGS84 projection. Some * applications may not accept latitudes above/below ±85 * degrees for some projections. */ public final BigDecimal latitude; /** * Longitude coordinate in degrees (East of Greenwich is * positive) using the standard WGS84 projection. Note that * geographic poles will be exactly at latitude ±90 degrees * but in that case the longitude will be set to an arbitrary * value within this range. */ public final BigDecimal longitude; /** * Elevation is an optional third parameter and may be set to * {@code null}. */ @Nullable public final BigDecimal elevation; //--------------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Constructors. // /** * Creates a new GeoJSON position based on the builder * settings. * @param builder contains position latitude and longitude. */ private Position(final Builder builder) { super (builder); this.latitude = builder.mLatitude; this.longitude = builder.mLongitude; this.elevation = builder.mElevation; } // end of Position(Builder) // // end of Constructors. //----------------------------------------------------------- //----------------------------------------------------------- // Object Method Overrides. // /** * Returns {@code true} if either {@code o} is the same * {@code Position} instance as {@code this} or is a * non-{@code null Position} instance with the same latitude * and longitude as {@code this Position}. * @param o comparison object. * @return if {@code o} is a non-{@code null Position} * instance with the same latitude and longitude as * {@code this Position}. */ @Override public boolean equals(final Object o) { boolean retcode = (this == o); if (!retcode && o instanceof Position) { final Position pos = (Position) o; retcode = (latitude.equals(pos.latitude) && longitude.equals(pos.longitude) && Objects.equals(elevation, pos.elevation)); } return (retcode); } // end of equals(Object) /** * Returns a hash of the latitude and longitude. * @return hash of the GeoJSON position. */ @Override public int hashCode() { return (Objects.hash(latitude, longitude, elevation)); } // end of hashCode() /** * Returns human-readable text containing the position * latitude and longitude. * @return GeoJSON position as human-readable text. */ @Override public String toString() { final StringBuilder retval = new StringBuilder(); retval.append("[lat=").append(latitude.toPlainString()) .append(", long=").append(longitude.toPlainString()); if (elevation != null) { retval.append(", elev=") .append(elevation.toPlainString()); } retval.append("]"); return (retval.toString()); } // end of toString() // // end of Object Method Overrides. //----------------------------------------------------------- /** * Returns a new GeoJSON position builder instance. * @return new {@link Builder} instance. */ public static Builder builder() { return (new Builder()); } // end of builder() //--------------------------------------------------------------- // Inner classes. // /** * {@code Position} instances may be created only by using * a {@code Builder} instance. A {@code Builder} instance is * obtained by calling {@link #builder()} which returns a * newly instantiated builder instance. Once obtained, * call the setter methods for each field and * {@link #build()} to create a {@code Position} instance. */ public static final class Builder extends EField.Builder { //----------------------------------------------------------- // Member data. // //------------------------------------------------------- // Locals. // private BigDecimal mLatitude; private BigDecimal mLongitude; private BigDecimal mElevation; //----------------------------------------------------------- // Member methods. // //------------------------------------------------------- // Constructors. // private Builder() { super (Position.class); } // end of Builder() // // end of Constructors. //------------------------------------------------------- //------------------------------------------------------- // Builder Method Overrides. // /** * Checks if latitude and longitude are set. Elevation * may be null. * @param problems add each detected problem to this * validator. * @return {@code problems}. */ @Override protected Validator validate(final Validator problems) { return (super.validate(problems) .requireNotNull(mLatitude, "latitude") .requireNotNull(mLongitude, "longitude")); } // end of validate(Validator) /** * Returns a new position instance based on this * builder's settings. * @return new position instance. */ @Override protected Position buildImpl() { return (new Position(this)); } // end of buildImpl() // // end of Builder Method Overrides. //------------------------------------------------------- //------------------------------------------------------- // Set Methods. // /** * Sets position latitude. Returns * {@code this Builder} instance so that builder method * calls can be chained. * @param latitude position latitude. * @return {@code this Builder} instance. * @throws NullPointerException * if {@code position} is {@code null}. * @throws IllegalArgumentException * if {@code latitude} < * {@link GeoObject#MIN_LATITUDE} or > * {@link GeoObject#MAX_LATITUDE}. */ public Builder latitude(final BigDecimal latitude) { mLatitude = validateLatitude(latitude); return (this); } // end of latitude(BigDecimal) /** * Sets position longitude. Returns * {@code this Builder} instance so that builder method * calls can be chained. * @param longitude position longitude. * @return {@code this Builder} instance. * @throws NullPointerException * if {@code longitude} is {@code null}. * @throws IllegalArgumentException * if {@code longitude} < * {@link GeoObject#MIN_LONGITUDE} or > * {@link GeoObject#MAX_LONGITUDE}. */ public Builder longitude(final BigDecimal longitude) { mLongitude = validateLongitude(longitude); return (this); } // end of longitude(BigDecimal) /** * Sets position elevation. Returns * {@code this Builder} instance so that builder method * calls can be chained. May be set to {@code null}. All * values are accepted. * @param elevation position elevation. * @return {@code this Builder} instance. */ public Builder elevation(final BigDecimal elevation) { mElevation = elevation; return (this); } // end of elevation(BigDecimal) // // end of Set Methods. //------------------------------------------------------- } // end of class Builder } // end of class Position




© 2015 - 2024 Weber Informatics LLC | Privacy Policy