TouchDevelop/lib/Location.ts

193 строки
7.3 KiB
TypeScript

///<reference path='refs.ts'/>
module TDev.RT {
//? A geo coordinate (latitude, longitude, ...)
//@ stem("loc") immutable ctx(general,indexkey,cloudfield,json) serializable
export class Location_
extends RTValue
{
public _latitude : number = undefined;
public _longitude : number = undefined;
public _altitude : number = undefined;
public _hor_accuracy : number = undefined;
public _vert_accuracy : number = undefined;
public _speed : number = undefined;
public _course : number = undefined;
constructor() {
super()
}
static mkShort(lat: number, lon: number): Location_
{
return Location_.mk(lat, lon, undefined, undefined, undefined, undefined, undefined);
}
static mk(lat : number, lon : number, alt : number, horacc : number, veracc : number, cou : number, spe : number) : Location_
{
var l = new Location_();
l._latitude = lat;
l._longitude = lon;
l._altitude = alt;
l._hor_accuracy = horacc;
l._vert_accuracy = veracc;
l._course = cou;
l._speed = spe;
return l;
}
static mkFromString(s: string):Location_ {
var pos = s.indexOf(",");
var l = new Location_();
l._latitude = Number(s.slice(0, pos));
l._longitude = Number(s.slice(pos + 1));
return l;
}
//? Converts to a string lat,long
public to_string() : string { return this._latitude + ',' + this._longitude; }
//ctx is ignored
public exportJson(ctx: JsonExportCtx): any {
return {
latitude: this._latitude,
longitude: this._longitude,
altitude: this._altitude,
hor_accuracy: this._hor_accuracy,
vert_accuracy: this._vert_accuracy,
course: this._course,
speed: this._speed
};
}
public importJson(ctx: JsonImportCtx, json: any): RT.RTValue {
Util.oops("should not call immutable instance for importing");
return undefined;
}
static mkFromJson(ctx: JsonImportCtx, json: any): RT.Location_ {
if (typeof json != "object")
return undefined;
var loc = new Location_();
loc._latitude = ctx.importNumber(json, "latitude");
loc._longitude = ctx.importNumber(json, "longitude");
loc._altitude = ctx.importNumber(json, "altitude");
loc._hor_accuracy = ctx.importNumber(json, "hor_accuracy");
loc._vert_accuracy = ctx.importNumber(json, "vert_accuracy");
loc._course = ctx.importNumber(json, "course");
loc._speed = ctx.importNumber(json, "speed");
return loc;
}
public isSerializable() { return true; }
public toJsonKey()
{
return [this._latitude, this._longitude, this._altitude,
this._hor_accuracy, this._vert_accuracy,
this._speed, this._course];
}
public keyCompareTo(o:any):number
{
var other:Location_ = o;
var diff = this._latitude - other._latitude;
if (diff) return diff;
diff = this._longitude - other._longitude;
if (diff) return diff;
diff = this._altitude - other._altitude;
if (diff) return diff;
diff = this._hor_accuracy - other._hor_accuracy;
if (diff) return diff;
diff = this._vert_accuracy - other._vert_accuracy;
if (diff) return diff;
diff = this._speed - other._speed;
if (diff) return diff;
diff = this._course - other._course;
return diff;
}
//? Gets the latitude of the coordinate
public latitude() : number { return this._latitude; }
//? Gets the longitude of the coordinate
public longitude() : number { return this._longitude; }
//? Gets the altitude of the coordinate
public altitude() : number { return this._altitude; }
//? Gets the horizontal accuracy of the coordinate
public hor_accuracy() : number { return this._hor_accuracy; }
//? Gets the vertical accuracy of the coordinate
public vert_accuracy() : number { return this._vert_accuracy; }
//? Gets the speed of the coordinate
public speed() : number { return this._speed; }
//? Gets the course of the coordinate
public course() : number { return this._course; }
public toString(): string {
return "(" + this._latitude + "," + this._longitude + ")";
}
//? Indicates if this instance is equal to the other
public equals(other:Location_) : boolean {
return (
this._latitude === other._latitude &&
this._longitude === other._longitude &&
this._altitude === other._altitude &&
this._hor_accuracy === other._hor_accuracy &&
this._vert_accuracy === other._vert_accuracy &&
this._speed === other._speed &&
this._course === other._course);
}
//? Shares the location (email, sms, social or '' to pick from a list)
//@ flow(SinkSharing) uiAsync
//@ [network].defl("social") [network].deflStrings("", "email", "sms", "social") [message].defl("Sent from TouchDevelop")
public share(network: string, message: string, r : ResumeCtx): void {
var lnk = Link.mk(Maps.mapUrl(this), LinkKind.hyperlink);
lnk.set_title(this.to_string());
lnk.set_description(message);
HTML.showProgressNotification(lf("sharing location..."));
ShareManager.shareLinkAsync(lnk, network).done(() => r.resume());
}
//? Calculates the distance in meters
public distance(other: Location_): number
{
return Location_.computeDistance(this.latitude(), this.longitude(), other.latitude(), other.longitude());
}
static computeDistance(lat1 : number, lng1 : number, lat2 : number, lng2 : number) : number
{
var radius = 6367.0; // earth radius in kilometers
return radius * 2 * Math.asin(
Math.min(
1,
Math.sqrt(
Math.pow(Math.sin(((Math_.deg_to_rad(lat2 - lat1))) / 2.0), 2.0)
+ Math.cos(Math_.deg_to_rad(lat1))
* Math.cos(Math_.deg_to_rad(lat2))
* Math.pow(Math.sin(((Math_.deg_to_rad(lng2 - lng1))) / 2.0), 2.0)
)
)
);
}
// Displays the location in a map using Bing.
public getViewCore(s: IStackFrame, b: BoxBase): HTMLElement
{
var map = Maps.create_map();
map.set_center(this);
map.add_text(this, this.latitude().toFixed(3) + ', ' + this.longitude().toFixed(3), Colors.background(s), Colors.foreground(s));
return map.getViewCore(s, b);
}
//? Displays the location in a map using Bing.
//@ cap(maps) flow(SinkSafe)
public post_to_wall(s:IStackFrame) : void { super.post_to_wall(s) }
}
}