diff --git a/public_html/formatter.js b/public_html/formatter.js
index 11e151d..d73fd26 100644
--- a/public_html/formatter.js
+++ b/public_html/formatter.js
@@ -166,7 +166,7 @@ function format_distance_long(dist) {
return dist_text;
}
-// p as a LatLng
+// p is a [lon, lat] coordinate
function format_latlng(p) {
- return p.lat().toFixed(3) + DEGREES + "," + NBSP + p.lng().toFixed(3) + DEGREES;
+ return p[1].toFixed(3) + DEGREES + "," + NBSP + p[0].toFixed(3) + DEGREES;
}
diff --git a/public_html/markers.js b/public_html/markers.js
index bd4904f..2dae794 100755
--- a/public_html/markers.js
+++ b/public_html/markers.js
@@ -61,31 +61,31 @@ var _heavy_svg =
var MarkerIcons = {
generic : {
scale : 0.4,
- anchor : new google.maps.Point(32, 32),
+ anchor : [32, 32],
path : _generic_plane_svg
},
light : {
scale : 0.4,
- anchor : new google.maps.Point(32, 25),
+ anchor : [32, 25],
path : _beechcraft_svg
},
medium : {
scale : 0.4,
- anchor : new google.maps.Point(32, 32),
+ anchor : [32, 32],
path : _generic_plane_svg
},
heavy : {
scale : 0.6,
- anchor : new google.maps.Point(32, 32),
+ anchor : [32, 32],
path : _heavy_svg
},
rotorcraft : {
scale : 0.5,
- anchor : new google.maps.Point(22, 32),
+ anchor : [22, 32],
path : _rotorcraft_svg
}
};
diff --git a/public_html/planeObject.js b/public_html/planeObject.js
index bc717ee..e1ab6b5 100644
--- a/public_html/planeObject.js
+++ b/public_html/planeObject.js
@@ -13,6 +13,7 @@ function PlaneObject(icao) {
this.altitude = null;
this.speed = null;
this.track = null;
+ this.prev_position = null;
this.position = null;
this.position_from_mlat = false
this.sitedist = null;
@@ -59,67 +60,75 @@ function PlaneObject(icao) {
// Appends data to the running track so we can get a visual tail on the plane
// Only useful for a long running browser session.
PlaneObject.prototype.updateTrack = function(estimate_time) {
- var here = this.position;
- if (!here)
- return;
+ if (!this.position)
+ return false;
+ if (this.position == this.prev_position)
+ return false;
+
+ var projHere = ol.proj.fromLonLat(this.position);
+ var projPrev;
+ if (this.prev_position === null) {
+ projPrev = projHere;
+ } else {
+ projPrev = ol.proj.fromLonLat(this.prev_position);
+ }
+
+ this.prev_position = this.position;
if (this.track_linesegs.length == 0) {
// Brand new track
//console.log(this.icao + " new track");
- var newseg = { track : new google.maps.MVCArray([here,here]),
- line : null,
- head_update : this.last_position_time,
- tail_update : this.last_position_time,
- estimated : false,
- ground : (this.altitude === "ground")
+ var newseg = { fixed: new ol.geom.LineString([projHere]),
+ feature: null,
+ head_update: this.last_position_time,
+ tail_update: this.last_position_time,
+ estimated: false,
+ ground: (this.altitude === "ground")
};
this.track_linesegs.push(newseg);
- this.history_size += 2;
+ this.history_size ++;
return;
}
-
+
var lastseg = this.track_linesegs[this.track_linesegs.length - 1];
- var lastpos = lastseg.track.getAt(lastseg.track.getLength() - 1);
var elapsed = (this.last_position_time - lastseg.head_update);
- var new_data = (here !== lastpos);
var est_track = (elapsed > estimate_time);
var ground_track = (this.altitude === "ground");
- if (!new_data)
- return false;
-
if (est_track) {
+
if (!lastseg.estimated) {
// >5s gap in data, create a new estimated segment
//console.log(this.icao + " switching to estimated");
- this.track_linesegs.push({ track : new google.maps.MVCArray([lastpos, here]),
- line : null,
- head_update : this.last_position_time,
- estimated : true });
+ lastseg.fixed.appendCoordinate(projPrev);
+ this.track_linesegs.push({ fixed: new ol.geom.LineString([projPrev, projHere]),
+ feature: null,
+ head_update: this.last_position_time,
+ estimated: true });
this.history_size += 2;
- return true;
+ } else {
+ // Keep appending to the existing dashed line; keep every point
+ lastseg.fixed.appendCoordinate(projPrev);
+ lastseg.head_update = this.last_position_time;
+ this.history_size++;
}
-
- // Append to ongoing estimated line
- //console.log(this.icao + " extending estimated (" + lastseg.track.getLength() + ")");
- lastseg.track.push(here);
- lastseg.head_update = this.last_position_time;
- this.history_size++;
+
return true;
}
if (lastseg.estimated) {
- // We are back to good data.
- //console.log(this.icao + " switching to good track");
- this.track_linesegs.push({ track : new google.maps.MVCArray([lastpos, here]),
- line : null,
- head_update : this.last_position_time,
- tail_update : this.last_position_time,
- estimated : false,
- ground : (this.altitude === "ground") });
- this.history_size += 2;
- return true;
+ // We are back to good data (we got two points close in time), switch back to
+ // solid lines.
+ lastseg = { fixed: new ol.geom.LineString([projPrev]),
+ feature: null,
+ head_update: this.last_position_time,
+ tail_update: this.last_position_time,
+ estimated: false,
+ ground: (this.altitude === "ground") };
+ this.track_linesegs.push(lastseg);
+ this.history_size ++;
+ // continue
}
if ( (lastseg.ground && this.altitude !== "ground") ||
@@ -127,15 +136,17 @@ PlaneObject.prototype.updateTrack = function(estimate_time) {
//console.log(this.icao + " ground state changed");
// Create a new segment as the ground state changed.
// assume the state changed halfway between the two points
- var midpoint = google.maps.geometry.spherical.interpolate(lastpos,here,0.5);
- lastseg.track.push(midpoint);
- this.track_linesegs.push({ track : new google.maps.MVCArray([midpoint,here,here]),
- line : null,
- head_update : this.last_position_time,
- tail_update : this.last_position_time,
- estimated : false,
- ground : (this.altitude === "ground") });
- this.history_size += 4;
+ // FIXME needs reimplementing post-google
+
+ lastseg.fixed.appendCoordinate(projPrev);
+ this.track_linesegs.push({ fixed: new ol.geom.LineString([projPrev, projHere]),
+ latest: here,
+ feature: null,
+ head_update: this.last_position_time,
+ tail_update: this.last_position_time,
+ estimated: false,
+ ground: (this.altitude === "ground") });
+ this.history_size += 3;
return true;
}
@@ -145,24 +156,22 @@ PlaneObject.prototype.updateTrack = function(estimate_time) {
if (this.last_position_time - lastseg.tail_update >= 5) {
// enough time has elapsed; retain the last point and add a new one
//console.log(this.icao + " retain last point");
- lastseg.track.push(here);
+ lastseg.fixed.appendCoordinate(projHere);
lastseg.tail_update = lastseg.head_update;
this.history_size ++;
- } else {
- // replace the last point with the current position
- lastseg.track.setAt(lastseg.track.getLength()-1, here);
}
+
lastseg.head_update = this.last_position_time;
return true;
};
// This is to remove the line from the screen if we deselect the plane
PlaneObject.prototype.clearLines = function() {
- for (var i = 0; i < this.track_linesegs.length; ++i) {
+ for (var i = this.track_linesegs.length - 1; i >= 0 ; --i) {
var seg = this.track_linesegs[i];
- if (seg.line !== null) {
- seg.line.setMap(null);
- seg.line = null;
+ if (seg.feature !== null) {
+ PlaneTrailFeatures.remove(seg.feature);
+ seg.feature = null;
}
}
};
@@ -262,21 +271,19 @@ PlaneObject.prototype.updateIcon = function() {
var weight = this.selected ? 2 : 1;
var rotation = (this.track === null ? 0 : this.track);
- if (col === this.icon.fillColor && opacity == this.icon.fillOpacity && weight === this.icon.strokeWeight && outline == this.icon.strokeColor && rotation === this.icon.rotation && type == this.icon.type)
- return false; // no changes
-
- this.icon.fillColor = col;
- this.icon.fillOpacity = opacity;
- this.icon.strokeWeight = weight;
- this.icon.strokeColor = outline;
- this.icon.rotation = rotation;
- this.icon.type = type;
- this.icon.path = MarkerIcons[type].path;
- this.icon.anchor = MarkerIcons[type].anchor;
- this.icon.scale = MarkerIcons[type].scale;
- if (this.marker)
- this.marker.setIcon(this.icon);
+ /* TODO use the aircraft icon svgs */
+ this.markerStyle = new ol.style.Style({
+ image: new ol.style.Circle({
+ fill: new ol.style.Fill({ color: col }),
+ stroke: new ol.style.Stroke({ color: outline, width: weight }),
+ radius: 5,
+ })
+ });
+ if (this.marker !== null) {
+ this.marker.setStyle(this.markerStyle);
+ }
+
return true;
};
@@ -296,11 +303,12 @@ PlaneObject.prototype.updateData = function(receiver_timestamp, data) {
if (typeof data.track !== "undefined")
this.track = data.track;
if (typeof data.lat !== "undefined") {
- this.position = new google.maps.LatLng(data.lat, data.lon);
+ this.position = [data.lon, data.lat];
this.last_position_time = receiver_timestamp - data.seen_pos;
if (SitePosition !== null) {
- this.sitedist = google.maps.geometry.spherical.computeDistanceBetween (SitePosition, this.position);
+ var WGS84 = new ol.Sphere(6378137);
+ this.sitedist = WGS84.haversineDistance(SitePosition, this.position);
}
this.position_from_mlat = false;
@@ -352,8 +360,8 @@ PlaneObject.prototype.updateTick = function(receiver_timestamp, last_timestamp)
PlaneObject.prototype.clearMarker = function() {
if (this.marker) {
- this.marker.setMap(null);
- google.maps.event.clearListeners(this.marker, 'click');
+ PlaneIconFeatures.remove(this.marker);
+ /* FIXME google.maps.event.clearListeners(this.marker, 'click'); */
this.marker = null;
}
};
@@ -365,28 +373,30 @@ PlaneObject.prototype.updateMarker = function(moved) {
return;
}
- if (this.marker) {
- if (moved)
- this.marker.setPosition(this.position);
- this.updateIcon();
+ if (this.marker) {
+ if (moved) {
+ this.marker.setGeometry(new ol.geom.Point(ol.proj.fromLonLat(this.position)));
+ }
} else {
+ this.marker = new ol.Feature(new ol.geom.Point(ol.proj.fromLonLat(this.position)));
this.updateIcon();
- this.marker = new google.maps.Marker({
- position: this.position,
- map: GoogleMap,
- icon: this.icon,
- visible: true
- });
+ PlaneIconFeatures.push(this.marker);
+ /* FIXME
// Trap clicks for this marker.
google.maps.event.addListener(this.marker, 'click', selectPlaneByHex.bind(undefined,this.icao,false));
google.maps.event.addListener(this.marker, 'dblclick', selectPlaneByHex.bind(undefined,this.icao,true));
+ */
}
-
+
+ this.updateIcon();
+
+ /*
// Setting the marker title
var title = (this.flight === null || this.flight.length == 0) ? this.icao : (this.flight+' ('+this.icao+')');
if (title !== this.marker.title)
this.marker.setTitle(title);
+ */
};
// Update our planes tail line,
@@ -394,39 +404,55 @@ PlaneObject.prototype.updateLines = function() {
if (!this.selected)
return;
+ var estimateStyle = new ol.style.Style({
+ stroke: new ol.style.Stroke({
+ color: '#a08080',
+ width: 1.5,
+ lineDash: [3, 3]
+ })
+ });
+
+ var airStyle = new ol.style.Style({
+ stroke: new ol.style.Stroke({
+ color: '#000000',
+ width: 2
+ })
+ });
+
+ var groundStyle = new ol.style.Style({
+ stroke: new ol.style.Stroke({
+ color: '#408040',
+ width: 2
+ })
+ });
+
+ // create the new latest-position line
+ var lastseg = this.track_linesegs[this.track_linesegs.length - 1];
+ var lastfixed = lastseg.fixed.getCoordinateAt(1.0);
+ var geom = new ol.geom.LineString([lastfixed, ol.proj.fromLonLat(this.position)]);
+ var feature = new ol.Feature(geom);
+ feature.setStyle(this.altitude === 'ground' ? groundStyle : airStyle);
+
+ if (PlaneTrailFeatures.length == 0) {
+ PlaneTrailFeatures.push(feature);
+ } else {
+ PlaneTrailFeatures.setAt(0, feature);
+ }
+
+ // create any missing fixed line features
for (var i = 0; i < this.track_linesegs.length; ++i) {
var seg = this.track_linesegs[i];
- if (seg.line === null) {
- // console.log("create line for seg " + i + " with " + seg.track.getLength() + " points" + (seg.estimated ? " (estimated)" : ""));
- // for (var j = 0; j < seg.track.getLength(); j++) {
- // console.log(" point " + j + " at " + seg.track.getAt(j).lat() + "," + seg.track.getAt(j).lng());
- // }
-
+ if (seg.feature === null) {
+ seg.feature = new ol.Feature(seg.fixed);
if (seg.estimated) {
- var lineSymbol = {
- path: 'M 0,-1 0,1',
- strokeOpacity : 1,
- strokeColor : '#804040',
- strokeWeight : 2,
- scale: 2
- };
-
- seg.line = new google.maps.Polyline({
- path: seg.track,
- strokeOpacity: 0,
- icons: [{
- icon: lineSymbol,
- offset: '0',
- repeat: '10px' }],
- map : GoogleMap });
+ seg.feature.setStyle(estimateStyle);
+ } else if (seg.ground) {
+ seg.feature.setStyle(groundStyle);
} else {
- seg.line = new google.maps.Polyline({
- path: seg.track,
- strokeOpacity: 1.0,
- strokeColor: (seg.ground ? '#408040' : '#000000'),
- strokeWeight: 3,
- map: GoogleMap });
+ seg.feature.setStyle(airStyle);
}
+
+ PlaneTrailFeatures.push(seg.feature);
}
}
};
diff --git a/public_html/script.js b/public_html/script.js
index 761dbf7..a0950a2 100644
--- a/public_html/script.js
+++ b/public_html/script.js
@@ -18,7 +18,7 @@ var SpecialSquawks = {
};
// Get current map settings
-var CenterLat, CenterLon, ZoomLvl, MapType;
+var CenterLat, CenterLon, ZoomLvl;
var Dump1090Version = "unknown version";
var RefreshInterval = 1000;
@@ -319,7 +319,6 @@ function initialize_map() {
CenterLat = Number(localStorage['CenterLat']) || DefaultCenterLat;
CenterLon = Number(localStorage['CenterLon']) || DefaultCenterLon;
ZoomLvl = Number(localStorage['ZoomLvl']) || DefaultZoomLvl;
- //MapType = localStorage['MapType'] || google.maps.MapTypeId.ROADMAP;
// Set SitePosition, initialize sorting
if (SiteShow && (typeof SiteLat !== 'undefined') && (typeof SiteLon !== 'undefined')) {
@@ -635,7 +634,7 @@ function refreshSelected() {
$('#selected_follow').removeClass('hidden');
if (FollowSelected) {
$('#selected_follow').css('font-weight', 'bold');
- GoogleMap.panTo(selected.position);
+ OLMap.getView().setCenter(ol.proj.fromLonLat(selected.position));
} else {
$('#selected_follow').css('font-weight', 'normal');
}
@@ -810,8 +809,8 @@ function selectPlaneByHex(hex,autofollow) {
if (SelectedPlane !== null && autofollow) {
FollowSelected = true;
- if (GoogleMap.getZoom() < 8)
- GoogleMap.setZoom(8);
+ if (OLMap.getView().getZoom() < 8)
+ OLMap.getView().setZoom(8);
} else {
FollowSelected = false;
}
@@ -821,8 +820,8 @@ function selectPlaneByHex(hex,autofollow) {
function toggleFollowSelected() {
FollowSelected = !FollowSelected;
- if (FollowSelected && GoogleMap.getZoom() < 8)
- GoogleMap.setZoom(8);
+ if (FollowSelected && OLMap.getView().getZoom() < 8)
+ OLMap.getView().setZoom(8);
refreshSelected();
}
@@ -831,37 +830,10 @@ function resetMap() {
localStorage['CenterLat'] = CenterLat = DefaultCenterLat;
localStorage['CenterLon'] = CenterLon = DefaultCenterLon;
localStorage['ZoomLvl'] = ZoomLvl = DefaultZoomLvl;
- localStorage['MapType'] = MapType = google.maps.MapTypeId.ROADMAP;
// Set and refresh
- GoogleMap.setZoom(ZoomLvl);
- GoogleMap.setCenter(new google.maps.LatLng(CenterLat, CenterLon));
+ OLMap.getView().setZoom(ZoomLvl);
+ OLMap.getView().setCenter(ol.proj.fromLonLat([CenterLon, CenterLat]));
selectPlaneByHex(null,false);
}
-
-function drawCircle(marker, distance) {
- if (typeof distance === 'undefined') {
- return false;
- }
-
- distance = parseFloat(distance);
- if (isNaN(distance) || !isFinite(distance) || distance < 0) {
- return false;
- }
-
- distance *= 1000.0;
- if (!Metric) {
- distance *= 1.852;
- }
-
- // Add circle overlay and bind to marker
- var circle = new google.maps.Circle({
- map: GoogleMap,
- radius: distance, // In meters
- fillOpacity: 0.0,
- strokeWeight: 1,
- strokeOpacity: 0.3
- });
- circle.bindTo('center', marker, 'position');
-}