More work on OL3.
This commit is contained in:
parent
5acecbaf6f
commit
8639ab3837
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,20 +271,18 @@ 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
|
||||
/* 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,
|
||||
})
|
||||
});
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue