//
// Copyright (c) 2021 Clementine Computing LLC.
//
// This file is part of RideLogic.
//
// RideLogic is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RideLogic is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with RideLogic. If not, see .
//
var g_info = {
"geojson" : {},
"route" : {},
"route_path": {},
"active_route" : [],
"ol_route_layer" : {}
};
var Feature = ol.Feature;
var Map = ol.Map;
var Overlay = ol.Overlay;
var Point = ol.geom.Point;
var TileJSON = ol.source.TileJSON;
var VectorSource = ol.source.Vector;
var View = ol.View;
var Icon = ol.style.Icon;
var Style = ol.style.Style;
var TileLayer = ol.layer.Tile;
var VectorLayer = ol.layer.Vector;
var OSM = ol.source.OSM;
var fromLonLat = ol.proj.fromLonLat;
var Control = ol.control.Control;
var LineString = ol.geom.LineString;
//var defaultLonLat = [ -76.5019, 42.4440];
//var defaultLonLat = [ -76.1805, 42.6012 ];
var defaultLonLat = [ -76.2705, 42.5512 ];
var defaultWebMerc = fromLonLat(defaultLonLat);
function _rnd(a,b) {
a = ((typeof a == "undefined") ? 1.0 : a);
if (typeof b === "undefined") {
return Math.random()*a;
}
return Math.random()*(b-a) + a;
}
function example_change_pos() {
let w = 1/16.0;
let lonlat = [
defaultLonLat[0] + _rnd(-w,w),
defaultLonLat[1] + _rnd(-w,w)];
let merc = fromLonLat(lonlat);
_icon[0].feature.getGeometry().setCoordinates(merc);
busLayer.getSource().changed();
}
function example_change_opacity(p) {
p = ((typeof p === "undefined") ? 0.0 : p);
_icon[0].style.getImage().setOpacity(p);
busLayer.getSource().changed();
}
// icon can't change image src dynamically,
// so have to replace.
// See https://stackoverflow.com/questions/57341190/how-can-i-change-icon-source-dynamically
//
function example_change_image() {
let _nuimg = new Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'data/bus_gw_90.png',
});
_icon[0].style.setImage(_nuimg);
busLayer.getSource().changed();
}
//---
var vectorSource = new VectorSource();
var _icon = [];
for (let ii=0; ii<2; ii++) {
let w = 1/32.0;
let lonlat = [
defaultLonLat[0] + _rnd(-w,w),
defaultLonLat[1] + _rnd(-w,w)];
let merc = fromLonLat(lonlat);
let iconFeature = new Feature({
geometry: new Point([merc[0], merc[1]]),
name: 'bus'
});
let iconStyle = new Style({
image: new Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'data/icon.png',
}),
});
iconStyle.getImage().setOpacity(0.0);
_icon.push({ "style": iconStyle, "feature": iconFeature });
iconFeature.setStyle(iconStyle);
vectorSource.addFeature(iconFeature);
}
//---
const busLayer = new VectorLayer({
source: vectorSource,
zIndex: 2
});
//--
const rasterLayer = new TileLayer({
//source: ol.source.OSM()
source: new ol.source.OSM(),
});
//--
//-------------------
//-------------------
//-------------------
const g_map = new Map({
//layers: [rasterLayer, vectorLayer, routeLayer],
layers: [rasterLayer, busLayer ],
target: document.getElementById('map'),
controls:[],
view: new View({
center: defaultWebMerc,
zoom: 11,
}),
});
var g_side_toggle = true;
function toggle_sidebar(tf) {
g_side_toggle = (g_side_toggle ? false : true);
if (typeof tf !== "undefined") {
g_side_toggle = tf;
}
// my perpetual fight with CSS.
// I can't seem to get these values in when I put them in the
// CSS, so we do it here programatically.
//
// Create a scrollable bar only for the list and not
// for the map.
// Hide the scroll bar when collapsing.
// Hide the x scrollbar but dumping x values that overflow.
//
let ele = document.getElementById("sidebar-wrapper");
if (g_side_toggle) {
ele.style["overflow-y"] = "auto";
ele.style["overflow-x"] = "hidden";
ele.style["margin-left"] = 0;
ele.style["min-width"] = "15rem";
ele.style["max-height"] = "100vh";
}
else {
ele.style["overflow-y"] = "hidden";
ele.style["overflow-x"] = "hidden";
ele.style["margin-left"] = "-15rem";
ele.style["min-width"] = "0";
ele.style["max-height"] = "100vh";
}
}
class CustomToggle extends Control {
constructor(opt) {
opt = opt || {};
let ele = document.createElement("button");
ele.id = 'ui_route_toggle';
ele.innerHTML = "Route";
// class="btn" id="sidebarToggle" style='display:float;'
ele.classList.add("custom-button");
super({
element: ele,
target: opt.target
});
ele.addEventListener('click', this.fire.bind(this), false);
}
fire() {
toggle_sidebar();
// hacky, but functional
//
setTimeout(resize_map, 250);
}
}
// button to toggle side bar route list
//
g_map.addControl(new CustomToggle({ className: 'custom-button' }));
//-------------------
//-------------------
//-------------------
g_map.addControl(new ol.control.Zoom({
className: 'custom-zoom'
}));
const element = document.getElementById('popup');
const popup = new Overlay({
element: element,
positioning: 'bottom-center',
stopEvent: false,
});
g_map.addOverlay(popup);
// display popup on click
//
g_map.on('click', function (evt) {
// not working (wip)
//
/*
const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
return feature;
});
*/
});
// change mouse cursor when over marker
g_map.on('pointermove', function (e) {
const pixel = g_map.getEventPixel(e.originalEvent);
const hit = g_map.hasFeatureAtPixel(pixel);
g_map.getTarget().style.cursor = hit ? 'pointer' : '';
});
// Close the popup when the map is moved
//
g_map.on('movestart', function () {
//$(element).popover('dispose');
});
g_map.on("postrender", function(event) {
//console.log("bang...");
});
//-----
function update_buses(json_gtfs) {
let bearingIdxLookup = [ "0", "45", "90", "135", "180", "225", "270", "315" ];
for (let ii=0; ii 7) { iheading = 0; }
let _nuimg = new Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'data/bus_gw_' + bearingIdxLookup[iheading] + '.png',
});
_icon[ii].style.setImage(_nuimg);
_icon[ii].style.getImage().setOpacity(1.0);
//console.log(">>", id, lat, lon, bearing);
}
busLayer.getSource().changed();
}
function fetch_gtfs_vehicle_position() {
let xhr = new XMLHttpRequest();
xhr.onload = function() {
let ab = xhr.response;
let json_pb = pb2json.pb2json(ab);
//console.log(">>>", json_pb);
update_buses(json_pb)
};
xhr.responseType = "arraybuffer";
xhr.open("GET", "VehiclePosition.pb");
xhr.send();
}
//--
function ui_show_single_route(route_id) {
if (!(route_id in g_info.ol_route_layer)) {
console.log("route", route_id, "not found in g_info.ol_route_layer");
return;
}
for (let i=0; i