hkopendata
Version:
Access different Opendata API and data in Hong Kong
133 lines (124 loc) • 5.49 kB
JavaScript
const proj4 = require("proj4");
const BaseComponent = require("./BaseComponent");
const CoordinateValue = require("./CoordinateValue");
const PROJ4 = {
WGS84: " +ellps=WGS84 +datum=WGS84",
HK1980: " +ellps=intl +towgs84=-162.619,-276.959,-161.764,0.067753,-2.24365,-1.15883,-1.09425"
}
proj4.defs([
["EPSG:4326", "+title=WGS84 (long/lat) +proj=longlat" + PROJ4.WGS84 + " +no_defs"],
["EPSG:4611", "+title=HK80 (long/lat) +proj=longlat" + PROJ4.HK1980 + " +no_defs"],
["EPSG:2326", "+title=HK80 Grid +proj=tmerc +lat_0=22.312133333333335 +lon_0=114.17855555555556 +k=1 +x_0=836694.05 +y_0=819069.8" + PROJ4.HK1980 + " +units=m +no_defs"],
["EPSG:32649", "+title=WGS84 49N +proj=utm +zone=49" + PROJ4.WGS84 + " +units=m +no_defs"],
["EPSG:32650", "+title=WGS84 50N +proj=utm +zone=50" + PROJ4.WGS84 + " +units=m +no_defs"],
["HK8049", "+title=HK80 49N +proj=utm +zone=49" + PROJ4.HK1980 + " +units=m +no_defs"],
["HK8050", "+title=HK80 50N +proj=utm +zone=50" + PROJ4.HK1980 + " +units=m +no_defs"],
])
class Coordinate extends BaseComponent {
constructor(params) {
super();
this.assignClass(this, params);
this._raw = {...params};
this._type = this._type || "latlong";
this._system = this._system || "wgs84";
this.validateInput();
this._standard = this.getStandard();
}
validateInput() {
if (this._type == "latlong") {
if (this.latitude > 800000 && this.longitude > 800000) {
this._type = "tmerc";
this._system = "hk1980";
this.easting = this.longitude;
this.northing = this.latitude;
delete this.longitude;
delete this.latitude;
}
} else if (this._system == "hk1980" && this._type == "tmerc") {
if (Math.abs(this.easting) <= 180 && Math.abs(this.northing) <= 90) {
this._type = "latlong";
this._system = "wgs84";
this.longitude = this.easting;
this.latitude = this.northing;
delete this.easting;
delete this.northing;
}
}
}
distance(coor) {
if (typeof coor !== "object" || coor === null) return false;
if (Coordinate.prototype.isPrototypeOf(coor)) {
if (this._standard == coor._standard) return distance(this, coor)
return distance(this.toLatLong(), coor.toLatLong())
} else if ("latitude" in coor && "longitude" in coor) {
return distance(this.toLatLong(), coor)
} else if ("easting" in coor && "northing" in coor) {
return distance(this.toHK1980(), coor)
}
return false
}
toLatLongDms() {
let coor = this.toLatLong();
return {
latitude: new CoordinateValue(coor.latitude).toDms(),
longitude: new CoordinateValue(coor.longitude).toDms(),
}
}
toLatLong() {
if (this._system != "wgs84" || this._type != "latlong") {
let pt, res;
if (this._type == "latlong") {
pt = [parseFloat(this.longitude), parseFloat(this.latitude)];
} else if (this._type == "utm" || this._type == "tmerc") {
pt = [parseFloat(this.easting), parseFloat(this.northing)];
}
res = proj4(this._standard, "EPSG:4326", pt);
return {
latitude: res[1],
longitude: res[0],
}
}
return {
latitude: this.latitude,
longitude: this.longitude,
}
}
toHK1980() {
if (this._system != "hk1980" || this._type != "tmerc") {
let pt, res;
if (this._type == "latlong") {
pt = [parseFloat(this.longitude), parseFloat(this.latitude)];
} else if (this._type == "utm" || this._type == "tmerc") {
pt = [parseFloat(this.easting), parseFloat(this.northing)];
}
res = proj4(this._standard, "EPSG:2326", pt);
return {
northing: res[1],
easting: res[0],
}
}
return {
northing: this.northing,
easting: this.easting,
}
}
getStandard() {
if (this._system == "hk1980" && this._type == "utm") return "HK8050";
else if (this._system == "hk1980" && this._type == "latlong") return "EPSG:4611";
else if (this._system == "hk1980" && this._type == "tmerc") return "EPSG:2326";
else if (this._system == "wgs" && this._type == "utm") return "EPSG:32650";
return "EPSG:4326";
}
}
function distance(coor1, coor2) {
if ("latitude" in coor1 && "longitude" in coor1 && "latitude" in coor2 && "longitude" in coor2) {
let latDiff = Math.abs(parseFloat(coor1.latitude) - parseFloat(coor2.latitude));
let longDiff = Math.abs(parseFloat(coor1.longitude) - parseFloat(coor2.longitude));
return Math.sqrt(latDiff * latDiff + longDiff * longDiff) * 1.1132e2;
} else if ("easting" in coor1 && "northing" in coor1 && "easting" in coor2 && "northing" in coor2) {
let eDiff = Math.abs(parseFloat(coor1.easting) - parseFloat(coor2.easting));
let nDiff = Math.abs(parseFloat(coor1.northing) - parseFloat(coor2.northing));
return Math.sqrt(eDiff * eDiff + nDiff * nDiff) / 1000;
}
}
module.exports = Coordinate;