More work on OL3.

This commit is contained in:
Oliver Jowett 2016-07-02 14:44:14 +01:00
parent 5acecbaf6f
commit 8639ab3837
4 changed files with 152 additions and 154 deletions

View file

@ -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;
}

View file

@ -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
}
};

View file

@ -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);
}
}
};

View file

@ -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');
}