/**
This file is created by Yu Dong (2023).
License : Apache 2.0
FileName : Point.cj
Author : Yu Dong
Version : 0.0.1
Date : 20230424
Note : First Commit
*/
/**
* @file
* Point
*/
package gistools.geometry
import std.math.*
import std.convert.*
import std.collection.*
import encoding.json.*
import encoding.json.stream.*
import serialization.serialization.*
import gistools.*
import gistools.base.*
/**
* Point
*
* @author Yu Dong
* @since 0.38.2
*/
public class Point <: Geometry & Serializable<Point>{
// the coordinate of the point
public var coordinate : Coordinate
/**
* The Property is to get the x coordinate
*
* @since 0.38.2
*/
public mut prop x : Float64 {
get() {coordinate.x}
set(v) {coordinate.x = v}
}
/**
* The Property is to get the y coordinate
*
* @since 0.38.2
*/
public mut prop y : Float64 {
get() {coordinate.y}
set(v) {coordinate.y = v}
}
/**
* The Function is init constructor
*
* @since 0.38.2
*/
public init() {
this.coordinate = Coordinate(Float64.NaN, Float64.NaN)
this.spatialReference = SpatialReference.unknown()
}
/**
* The Function is init constructor
*
* @param coordinate of Coordinate
*
* @since 0.38.2
*/
public init(coordinate : Coordinate) {
this.coordinate = coordinate
this.spatialReference = SpatialReference.unknown()
}
/**
* The Function is init constructor
*
* @param coordinate of Coordinate
* @param sr of SpatialReference
*
* @since 0.38.2
*/
public init(coordinate : Coordinate, sr : SpatialReference) {
this.coordinate = coordinate
this.spatialReference = sr
}
/**
* The Function is init constructor
*
* @param x of Float64
* @param y of Float64
*
* @since 0.38.2
*/
public init(x : Float64, y : Float64) {
this.coordinate = Coordinate(x, y)
this.spatialReference = SpatialReference.unknown()
}
/**
* The Function is init constructor
*
* @param x of Float64
* @param y of Float64
* @param sr of SpatialReference
*
* @since 0.38.2
*/
public init(x : Float64, y : Float64, sr : SpatialReference) {
this.coordinate = Coordinate(x, y)
this.spatialReference = sr
}
/**
* The Function is to create null point object
*
* @return Type of Point
* @since 0.38.2
*/
public static func NullPoint() : Point {
Point()
}
/**
* The Function is to determine whether the Point is Null
*
* @return Type of Bool
* @since 0.38.2
*/
public func isNull() : Bool {
x.isNaN() || y.isNaN()
}
/**
* The Function is to String
*
* @return Type of String
* @since 0.38.2
*/
public func toString() {
"Point(${x},${y}) sr:${spatialReference}"
}
/**
* The Function is to transfrom from data model to json value
* NaN (Not a number) is not acceptable
*
* @param jv of JsonValue
*
* @return Type of DataModel
* @since 0.38.2
*/
public static func fromJson(jv: JsonValue): DataModel {
try {
let geometry = jv.asObject().get("geometry").getOrThrow().asObject()
let geometry_type = geometry.get("type").getOrThrow().asString().getValue()
if (geometry_type != "Point") {
return DataModelNull()
}
let wkid = match(geometry.get("spatialReference")) {
case Some(v) => Int64.parse(v.toString())
case None => 0
}
let coordinates = (geometry.get("coordinates").getOrThrow() as JsonArray).getOrThrow()
let x = Float64.parse(coordinates[0].toString())
let y = Float64.parse(coordinates[1].toString())
let coordinates_dm = DataModelSeq(ArrayList<DataModel>([DataModelFloat(x), DataModelFloat(y)]))
var geometry_dm = DataModelStruct()
.add(field<String>("type", "Point"))
.add(Field("coordinates", coordinates_dm))
if (wkid != 0) {
geometry_dm = geometry_dm.add(field<Int64>("spatialReference", wkid))
}
DataModelStruct().add(Field("geometry", geometry_dm))
}catch (e : Exception) {
DataModelNull()
}
}
/**
* The Function is to JSON
*
* @return Type of JsonValue
* @since 0.38.2
*/
public func toJson(): JsonValue {
serialize().toJson()
}
/**
* The Function is to serialize the point object to data model
*
* @return Type of DataModel
* @since 0.38.2
*/
public func serialize(): DataModel {
let coordinates_dm = DataModelSeq(ArrayList<DataModel>([DataModelFloat(x), DataModelFloat(y)]))
var geometry_dm = DataModelStruct()
.add(field<String>("type", "Point"))
.add(Field("coordinates", coordinates_dm))
if (!spatialReference.isUnknown() && (spatialReference.wkid != 0)) {
geometry_dm = geometry_dm.add(field<Int64>("spatialReference", spatialReference.wkid))
}
DataModelStruct().add(Field("geometry", geometry_dm))
}
/**
* The Function is to deserialize data model to the point object
*
* @param dm of DataModel
*
* @return Type of DataModel
* @since 0.38.2
*/
static public func deserialize(dm: DataModel): Point {
try {
let geometry = ((dm as DataModelStruct).getOrThrow().get("geometry") as DataModelStruct).getOrThrow()
let geometry_type = String.deserialize(geometry.get("type"))
if (geometry_type != "Point") {
throw Exception()
}
let coordinates = (geometry.get("coordinates") as DataModelSeq).getOrThrow().getItems()
let x = Float64.deserialize(coordinates[0])
let y = Float64.deserialize(coordinates[1])
match(geometry.get("spatialReference") as DataModelInt) {
case Some(v) => Point(x, y, SpatialReference.fromWKID(v.getValue()) ?? SpatialReference.unknown())
case None => Point(x, y)
}
} catch (e : Exception) {
Point.NullPoint()
}
}
/**
* The Function is to compute the distance of 2 points
*
* @param point of Point
*
* @return Type of Float64
* @since 0.38.2
*/
public func distance(point : Point) : Float64{
CoordinateEngine.distance(this.coordinate, point.coordinate)
}
}
/**
* implemtentation of CoordinateTransformer<Point>
*
* @author Yu Dong
* @since 0.38.2
*/
extend Point <: CoordinateTransformer<Point> {
/**
* The Function is to transfrom point to GCJ-02
*
* @return Type of ?Point
* @since 0.38.2
*/
public func toGCJ02() : ?Point {
if (spatialReference.isWGS1984()) {
return Point(CoordinateEngine.WGS84ToGCJ02(coordinate), SpatialReference.gcj02())
}
if (spatialReference.isBD09()) {
return Point(CoordinateEngine.BD09ToGCJ02(coordinate), SpatialReference.gcj02())
}
None
}
/**
* The Function is to transfrom point to BD-09
*
* @return Type of ?Point
* @since 0.38.2
*/
public func toBD09() : ?Point {
if (spatialReference.isWGS1984()) {
return Point(CoordinateEngine.WGS84ToBD09(coordinate), SpatialReference.bd09())
}
if (spatialReference.isGCJ02()) {
return Point(CoordinateEngine.GCJ02ToBD09(coordinate), SpatialReference.bd09())
}
None
}
/**
* The Function is to transfrom point to WGS 1984
*
* @return Type of ?Point
* @since 0.38.2
*/
public func toWGS1984() : ?Point {
if (spatialReference.isBD09()) {
return Point(CoordinateEngine.BD09ToWGS84(coordinate), SpatialReference.bd09())
}
if (spatialReference.isGCJ02()) {
return Point(CoordinateEngine.GCJ02ToWGS84(coordinate), SpatialReference.bd09())
}
None
}
/**
* The Function is to project point to Mercator
*
* @return Type of ?Point
* @since 0.38.2
*/
public func projectToMercator() : ?Point {
if (this.spatialReference.isProjected()) {
return None
}
Point(CoordinateEngine.GeographicToMercator(coordinate),
ProjectedSpatialReference.WebMercator((this.spatialReference as GeographicSpatialReference) ?? GeographicSpatialReference.Unknown))
}
}