1
0
Fork 0

Merge branch 'cppTrav' of ssh://github.com/arangodb/arangodb into cppTrav

This commit is contained in:
Max Neunhoeffer 2015-04-30 23:10:24 -07:00
commit cb9fa2a342
11 changed files with 434 additions and 157 deletions

View File

@ -45,22 +45,75 @@ using namespace std;
using namespace triagens::basics; using namespace triagens::basics;
using namespace triagens::arango; using namespace triagens::arango;
struct WeightInfo { ////////////////////////////////////////////////////////////////////////////////
string keyWeight; /// @brief callback to weight an edge
double defaultWeight; ////////////////////////////////////////////////////////////////////////////////
bool usesWeight;
WeightInfo( typedef function<double(TRI_doc_mptr_copy_t& edge)> WeightCalculatorFunction;
////////////////////////////////////////////////////////////////////////////////
/// @brief Define edge weight by the number of hops.
/// Respectively 1 for any edge.
////////////////////////////////////////////////////////////////////////////////
class HopWeightCalculator {
public:
HopWeightCalculator() {};
////////////////////////////////////////////////////////////////////////////////
/// @brief Callable weight calculator for edge
////////////////////////////////////////////////////////////////////////////////
double operator() (TRI_doc_mptr_copy_t& edge) {
return 1;
};
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Define edge weight by ony special attribute.
/// Respectively 1 for any edge.
////////////////////////////////////////////////////////////////////////////////
class AttributeWeightCalculator {
TRI_shape_pid_t _shape_pid;
double _defaultWeight;
TRI_shaper_t* _shaper;
public:
AttributeWeightCalculator(
string keyWeight, string keyWeight,
double defaultWeight double defaultWeight,
) : TRI_shaper_t* shaper
keyWeight(keyWeight), defaultWeight(defaultWeight), usesWeight(true) ) : _defaultWeight(defaultWeight),
_shaper(shaper)
{ {
_shape_pid = _shaper->lookupAttributePathByName(_shaper, keyWeight.c_str());
}; };
WeightInfo() : usesWeight(false) { ////////////////////////////////////////////////////////////////////////////////
/// @brief Callable weight calculator for edge
////////////////////////////////////////////////////////////////////////////////
double operator() (TRI_doc_mptr_copy_t& edge) {
if (_shape_pid == 0) {
return _defaultWeight;
}
TRI_shape_sid_t sid;
TRI_EXTRACT_SHAPE_IDENTIFIER_MARKER(sid, edge.getDataPtr());
TRI_shape_access_t const* accessor = TRI_FindAccessorVocShaper(_shaper, sid, _shape_pid);
TRI_shaped_json_t shapedJson;
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, edge.getDataPtr());
TRI_shaped_json_t resultJson;
TRI_ExecuteShapeAccessor(accessor, &shapedJson, &resultJson);
if (resultJson._sid != TRI_SHAPE_NUMBER) {
return _defaultWeight;
}
TRI_json_t* json = TRI_JsonShapedJson(_shaper, &resultJson);
if (json == nullptr) {
return _defaultWeight;
}
double realResult = json->_value._number;
TRI_FreeJson(_shaper->_memoryZone, json);
return realResult ;
}; };
}; };
class SimpleEdgeExpander { class SimpleEdgeExpander {
@ -90,33 +143,20 @@ class SimpleEdgeExpander {
CollectionNameResolver* resolver; CollectionNameResolver* resolver;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief this is the information required to compute weight by a given /// @brief the weight calculation function
/// attribute. It contains an indicator if weight should be used.
/// Also it includes a default weight and the name of the weight
/// attribute.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
WeightInfo weightInfo; WeightCalculatorFunction weighter;
public: public:
SimpleEdgeExpander(TRI_edge_direction_e direction,
TRI_document_collection_t* edgeCollection,
string edgeCollectionName,
CollectionNameResolver* resolver)
: direction(direction), edgeCollection(edgeCollection),
resolver(resolver)
{
edgeIdPrefix = edgeCollectionName + "/";
};
SimpleEdgeExpander(TRI_edge_direction_e direction, SimpleEdgeExpander(TRI_edge_direction_e direction,
TRI_document_collection_t* edgeCollection, TRI_document_collection_t* edgeCollection,
string edgeCollectionName, string edgeCollectionName,
CollectionNameResolver* resolver, CollectionNameResolver* resolver,
WeightInfo weightInfo) WeightCalculatorFunction weighter)
: direction(direction), edgeCollection(edgeCollection), : direction(direction), edgeCollection(edgeCollection),
resolver(resolver), weightInfo(weightInfo) resolver(resolver), weighter(weighter)
{ {
edgeIdPrefix = edgeCollectionName + "/"; edgeIdPrefix = edgeCollectionName + "/";
}; };
@ -170,17 +210,16 @@ class SimpleEdgeExpander {
unordered_map<Traverser::VertexId, size_t> candidates; unordered_map<Traverser::VertexId, size_t> candidates;
Traverser::VertexId from; Traverser::VertexId from;
Traverser::VertexId to; Traverser::VertexId to;
if (weightInfo.usesWeight) {
for (size_t j = 0; j < edges.size(); ++j) { for (size_t j = 0; j < edges.size(); ++j) {
from = extractFromId(edges[j]); from = extractFromId(edges[j]);
to = extractToId(edges[j]); to = extractToId(edges[j]);
double currentWeight = weightInfo.defaultWeight; double currentWeight = weighter(edges[j]);
if (from != source) { auto inserter = [&](Traverser::VertexId s, Traverser::VertexId t) {
auto cand = candidates.find(from); auto cand = candidates.find(t);
if (cand == candidates.end()) { if (cand == candidates.end()) {
// Add weight // Add weight
result.emplace_back(to, from, currentWeight, extractEdgeId(edges[j])); result.emplace_back(t, s, currentWeight, extractEdgeId(edges[j]));
candidates.emplace(from, result.size() - 1); candidates.emplace(t, result.size() - 1);
} else { } else {
// Compare weight // Compare weight
auto oldWeight = result[cand->second].weight(); auto oldWeight = result[cand->second].weight();
@ -188,40 +227,12 @@ class SimpleEdgeExpander {
result[cand->second].setWeight(currentWeight); result[cand->second].setWeight(currentWeight);
} }
} }
} };
else if (to != source) {
auto cand = candidates.find(to);
if (cand == candidates.end()) {
// Add weight
result.emplace_back(to, from, currentWeight, extractEdgeId(edges[j]));
candidates.emplace(to, result.size() - 1);
} else {
auto oldWeight = result[cand->second].weight();
if (currentWeight < oldWeight) {
result[cand->second].setWeight(currentWeight);
}
}
}
}
}
else {
for (size_t j = 0; j < edges.size(); ++j) {
from = extractFromId(edges[j]);
to = extractToId(edges[j]);
if (from != source) { if (from != source) {
auto cand = candidates.find(from); inserter(to, from);
if (cand == candidates.end()) {
result.emplace_back(from, to, 1, extractEdgeId(edges[j]));
candidates.emplace(from, result.size()-1);
}
} }
else if (to != source) { else if (to != source) {
auto cand = candidates.find(to); inserter(from, to);
if (cand == candidates.end()) {
result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
candidates.emplace(to, result.size()-1);
}
}
} }
} }
} }
@ -283,7 +294,7 @@ void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
vector<string> writeCollections; vector<string> writeCollections;
double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL); double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL);
bool embed = false; bool embed = true;
bool waitForSync = false; bool waitForSync = false;
// get the vertex collection // get the vertex collection
@ -409,15 +420,16 @@ void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
unique_ptr<SimpleEdgeExpander> forwardExpander; unique_ptr<SimpleEdgeExpander> forwardExpander;
unique_ptr<SimpleEdgeExpander> backwardExpander; unique_ptr<SimpleEdgeExpander> backwardExpander;
WeightCalculatorFunction weighter;
if (useWeight) { if (useWeight) {
forwardExpander.reset(new SimpleEdgeExpander(forward, ecol, edgeCollectionName, weighter = AttributeWeightCalculator(
&resolver1, WeightInfo(weightAttribute, defaultWeight))); weightAttribute, defaultWeight, ecol->getShaper()
backwardExpander.reset(new SimpleEdgeExpander(backward, ecol, edgeCollectionName, );
&resolver2, WeightInfo(weightAttribute, defaultWeight)));
} else { } else {
forwardExpander.reset(new SimpleEdgeExpander(forward, ecol, edgeCollectionName, &resolver1)); weighter = HopWeightCalculator();
backwardExpander.reset(new SimpleEdgeExpander(backward, ecol, edgeCollectionName, &resolver2));
} }
forwardExpander.reset(new SimpleEdgeExpander(forward, ecol, edgeCollectionName, &resolver1, weighter));
backwardExpander.reset(new SimpleEdgeExpander(backward, ecol, edgeCollectionName, &resolver2, weighter));
Traverser traverser(*forwardExpander, *backwardExpander, bidirectional); Traverser traverser(*forwardExpander, *backwardExpander, bidirectional);

View File

@ -2806,7 +2806,7 @@ void TRI_InitV8VocBridge (v8::Isolate* isolate,
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_SLEEP"), JS_QuerySleepAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_SLEEP"), JS_QuerySleepAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_IS_KILLED"), JS_QueryIsKilledAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_IS_KILLED"), JS_QueryIsKilledAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_SHORTEST_PATH"), JS_QueryShortestPath, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("CPP_SHORTEST_PATH"), JS_QueryShortestPath, true);

View File

@ -4328,8 +4328,8 @@ div.resizecontainer {
width: 2258px; } } width: 2258px; } }
div.centralRow { div.centralRow {
margin-top: 65px; margin-top: 40px;
margin-bottom: 65px; } margin-bottom: 40px; }
div.centralContent { div.centralContent {
background-color: rgba(0, 0, 0, 0.0675); background-color: rgba(0, 0, 0, 0.0675);

View File

@ -7,7 +7,8 @@
window.Airports = Backbone.Collection.extend({ window.Airports = Backbone.Collection.extend({
initialize: function() { initialize: function(options) {
this.collectionName = options.collectionName;
}, },
getAirports: function(callback) { getAirports: function(callback) {
@ -35,6 +36,50 @@
}); });
}, },
getShortestFlight: function(from, to, callback) {
$.ajax({
type: "POST",
url: "/_api/cursor",
data: JSON.stringify({
query: "RETURN SHORTEST_PATH(@@airports,@@flights,@start,@dest,'outbound',{})",
bindVars: {
"@flights": this.collectionName,
"@airports": "airports",
"start": "airports/" + from,
"dest": "airports/" + to
}
}),
contentType: "application/json",
processData: false,
success: function (data) {
callback(data.result[0]);
},
error: function (data) {
}
});
},
getFlightDistribution: function(callback) {
$.ajax({
type: "POST",
url: "/_api/cursor",
data: JSON.stringify({
query: "FOR f IN @@flights COLLECT dest = f._to " +
"WITH COUNT INTO n SORT n RETURN {Dest: SPLIT(dest, '/')[1], count: n}",
bindVars: {
"@flights": this.collectionName
}
}),
contentType: "application/json",
processData: false,
success: function (data) {
callback(data.result);
},
error: function (data) {
}
});
},
getFlightsForAirport: function(airport, callback) { getFlightsForAirport: function(airport, callback) {
var self = this; var self = this;
@ -42,9 +87,12 @@
type: "POST", type: "POST",
url: "/_api/cursor", url: "/_api/cursor",
data: JSON.stringify({ data: JSON.stringify({
query: "for f in flights12 filter f.Origin == @airport COLLECT dest = f.Dest " + query: "for f in @@flights filter f._from == @airport COLLECT dest = f._to " +
"WITH COUNT INTO n SORT n RETURN {Dest: dest, count: n}", "WITH COUNT INTO n SORT n RETURN {Dest: SPLIT(dest, '/')[1], count: n}",
bindVars: {"airport": airport} bindVars: {
"airport": "airports/" + airport,
"@flights": this.collectionName
}
}), }),
contentType: "application/json", contentType: "application/json",
processData: false, processData: false,

View File

@ -26,13 +26,18 @@
"userManagement": "userManagement", "userManagement": "userManagement",
"userProfile": "userProfile", "userProfile": "userProfile",
"logs": "logs", "logs": "logs",
"demo": "demo" "demo": "demo",
"demo/:collection": "demo"
}, },
demo: function () { demo: function (collection) {
if (!collection) {
collection = "flights";
}
if (!this.demoView) { if (!this.demoView) {
this.demoView = new window.DemoView({}); this.demoView = new window.DemoView({
collectionName: collection
});
} }
this.demoView.render(); this.demoView.render();

View File

@ -5,6 +5,7 @@
</div> </div>
<div class="search-field"> <div class="search-field">
<input type="text" id="demoSearchInput" class="search-input" placeholder="Search..."><img id="demoSearchSubmit" class="search-submit-icon"> <input type="text" id="demoSearchInput" class="search-input" placeholder="Search..."><img id="demoSearchSubmit" class="search-submit-icon">
<!--<div id="searchResults" class="demo-dropdown-menu"><ul></ul></div>-->
</div> </div>
<div class="styled-select"> <div class="styled-select">
<select id="flightQuerySelect" class="query-select" style="margin-top: 5px; height: 25px"> <select id="flightQuerySelect" class="query-select" style="margin-top: 5px; height: 25px">

View File

@ -35,22 +35,25 @@
*/ */
lineColors: [ lineColors: [
'rgb(255,255,229)', 'rgb(255,255,229)'
'rgb(255,247,188)', /*
'rgb(254,227,145)', - 'rgb(255,255,229)',
'rgb(254,196,79)', - 'rgb(255,247,188)',
'rgb(254,153,41)', - 'rgb(254,227,145)',
'rgb(236,112,20)', - 'rgb(254,196,79)',
'rgb(204,76,2)', - 'rgb(254,153,41)',
'rgb(153,52,4)', - 'rgb(236,112,20)',
'rgb(102,37,6)' - 'rgb(204,76,2)',
- 'rgb(153,52,4)',
- 'rgb(102,37,6)'
*/
], ],
airportColor: "#222222", airportColor: "#222222",
airportHighlightColor: "#FF4E4E", airportHighlightColor: "#FF4E4E",
airportHoverColor: "#ff8f35", airportHoverColor: "#ff8f35",
airportScale: 0.5, airportScale: 0.7,
airportHighligthScale: 0.95, airportHighligthScale: 0.95,
imageData: [], imageData: [],
@ -73,19 +76,32 @@
}, },
{ {
name: "All Flights from CWA" name: "All Flights from CWA"
},
{
name: "Flight distribution"
} }
], ],
el: '#content', el: '#content',
initialize: function () { initialize: function (options) {
this.airportCollection = new window.Airports(); var collectionName = options.collectionName;
window.HASS = this; // <--- BITTE ?!? ;) <-- zu viel Kontakt mit Jan this.airportCollection = new window.Airports({
collectionName: collectionName
});
}, },
events: { events: {
"change #flightQuerySelect" : "runSelectedQuery", "change #flightQuerySelect" : "runSelectedQuery",
"keyup #demoSearchInput" : "searchInput" "keyup #demoSearchInput" : "searchInput"
// "click #searchResults ul li": "selectAirport"
},
selectAirport: function (e) {
this.showAirportBalloon(e.currentTarget.id);
$("#searchResults").slideUp(function() {
$("#searchResults ul").html("");
});
}, },
template: templateEngine.createTemplate("demoView.ejs"), template: templateEngine.createTemplate("demoView.ejs"),
@ -152,7 +168,7 @@
var self = this, airports = this.index.search($(e.currentTarget).val()); var self = this, airports = this.index.search($(e.currentTarget).val());
self.resetDataHighlighting(); self.resetDataHighlighting();
self.removeFlightLines(false); self.removeFlightLines(true);
_.each(airports, function(airport) { _.each(airports, function(airport) {
self.setAirportColor(airport.ref, self.airportHighlightColor, false); self.setAirportColor(airport.ref, self.airportHighlightColor, false);
@ -164,16 +180,32 @@
//self.zoomToAirport(airports[0].ref); //self.zoomToAirport(airports[0].ref);
self.showAirportBalloon(airports[0].ref); // <-- only works with single map object, not multiple :( self.showAirportBalloon(airports[0].ref); // <-- only works with single map object, not multiple :(
} }
/*
//if (airports.length <= 10) { if (airports.length < 6 && airports.length > 1) {
//} self.insertAirportSelection(airports);
} else {
$("#searchResults").slideUp();
}
*/
self.map.validateData(); self.map.validateData();
},
insertAirportSelection: function (list) {
return;
/*
$("#searchResults ul").html("");
var i = 0;
for (i = 0; i < list.length; ++i) {
$("#searchResults ul").append("<li id='" + list[i].ref + "'>" + list[i].ref + "</li>");
}
$("#searchResults").slideDown();
*/
}, },
runSelectedQuery: function() { runSelectedQuery: function() {
this.resetDataHighlighting();
this.removeFlightLines(true);
var currentQueryPos = $( "#flightQuerySelect option:selected" ).attr('position'); var currentQueryPos = $( "#flightQuerySelect option:selected" ).attr('position');
if (currentQueryPos === "0") { if (currentQueryPos === "0") {
this.loadAirportData("SFO"); this.loadAirportData("SFO");
@ -190,6 +222,10 @@
if (currentQueryPos === "4") { if (currentQueryPos === "4") {
this.loadAirportData("CWA"); this.loadAirportData("CWA");
} }
if (currentQueryPos === "5") {
delete this.startPoint;
this.loadFlightDistData();
}
}, },
calculateAirportSize: function(airport, airports) { calculateAirportSize: function(airport, airports) {
@ -239,7 +275,70 @@
}, },
loadFlightDistData: function() {
var self = this;
var timer = new Date();
this.airportCollection.getFlightDistribution(function(list) {
var timeTaken = new Date() - timer;
self.removeFlightLines(false);
var allFlights = 0;
var i = 0;
self.resetDataHighlighting();
var least = list[0].count^3;
var best = list[list.length - 1].count^3;
var m = 2.625 /(best - least);
var distribute = function(x) {
return m * x - m * least;
};
for (i = 0; i < list.length; ++i) {
var to = list[i].Dest;
var count = list[i].count^3;
self.setAirportColor(to, self.airportHighlightColor);
var toSize = distribute(count);
toSize += 0.625;
self.setAirportSize(to, toSize);
if (i > list.length - 6) {
// Top 10 Color
self.setAirportColor(to,'rgb(153,52,4)');
}
}
if ($("#demo-mapdiv-info").length === 0) {
$("#demo-mapdiv").append("<div id='demo-mapdiv-info'></div>");
}
var tempHTML = "";
tempHTML = "<b>Aggregation</b> - Flight distribution<br>" +
"Query needed: <b>" + (timeTaken/1000).toFixed(3) + " sec" + "</b><br>" +
"Number destinations: <b>" + list.length + "</b><br>" +
"Number flights: <b>" + allFlights + "</b><br>" +
"Top 5:<br>";
for (i = (list.length - 1); i > Math.max(list.length - 6, 0); --i) {
var airportData = self.airportCollection.findWhere({_key: list[i].Dest});
tempHTML += airportData.get("Name") + " - " + airportData.get("_key") + ": <b>" + list[i].count + "</b>";
if (i > (list.length - 5)) {
tempHTML += "<br>";
}
}
$("#demo-mapdiv-info").html(tempHTML);
self.map.validateData();
});
},
loadAirportData: function(airport) { loadAirportData: function(airport) {
$("#flightQuerySelect :nth-child(1)").prop("selected", true);
var self = this; var self = this;
var timer = new Date(); var timer = new Date();
@ -256,13 +355,25 @@
self.resetDataHighlighting(); self.resetDataHighlighting();
var least = list[0].count^3;
var best = list[list.length - 1].count^3;
var m = 2.625 /(best - least);
var distribute = function(x) {
return m * x - m * least;
};
for (i = 0; i < list.length; ++i) { for (i = 0; i < list.length; ++i) {
var count = list[i].count^3;
var toSize = distribute(count);
toSize += 0.625;
self.addFlightLine( self.addFlightLine(
airport, airport,
list[i].Dest, list[i].Dest,
list[i].count, list[i].count,
self.calculateFlightColor(list.length, i), self.calculateFlightColor(list.length, i),
self.calculateFlightWidth(list.length, i) self.calculateFlightWidth(list.length, i),
toSize,
(i > list.length - 6)
); );
allFlights += list[i].count; allFlights += list[i].count;
} }
@ -272,15 +383,15 @@
} }
var tempHTML = ""; var tempHTML = "";
tempHTML = "<b>" + airportData.get("Name") + "</b> - " + airport + "<br>" + tempHTML = "<b>" + airportData.get("Name").substr(0,25) + "</b> - " + airport + "<br>" +
"Query needed: <b>" + (timeTaken/1000) + "sec" + "</b><br>" + "Query needed: <b>" + (timeTaken/1000).toFixed(3) + " sec" + "</b><br>" +
"Number destinations: <b>" + list.length + "</b><br>" + "Number destinations: <b>" + list.length + "</b><br>" +
"Number flights: <b>" + allFlights + "</b><br>" + "Number flights: <b>" + allFlights + "</b><br>" +
"Top 5:<br>"; "Top 5:<br>";
for (i = (list.length - 1); i > Math.max(list.length - 6, 0); --i) { for (i = (list.length - 1); i >= Math.max(list.length - 5, 0); --i) {
airportData = self.airportCollection.findWhere({_key: list[i].Dest}); airportData = self.airportCollection.findWhere({_key: list[i].Dest});
tempHTML += airportData.get("Name") + " - " + airportData.get("_key") + ": <b>" + list[i].count + "</b>"; tempHTML += airportData.get("Name").substr(0, 25) + " - " + airportData.get("_key") + ": <b>" + list[i].count + "</b>";
if (i > (list.length - 5)) { if (i > (list.length - 5)) {
tempHTML += "<br>"; tempHTML += "<br>";
} }
@ -296,12 +407,11 @@
//var intervallWidth = length/2; //var intervallWidth = length/2;
// return Math.floor(pos/intervallWidth) + 2; // return Math.floor(pos/intervallWidth) + 2;
//TODO: no custom width for lines wanted? //TODO: no custom width for lines wanted?
return 1.5; return 2;
}, },
calculateFlightColor: function(length, pos) { calculateFlightColor: function(length, pos) {
var intervallColor = length/this.lineColors.length; return this.lineColors[0];
return this.lineColors[Math.floor(pos/intervallColor)];
}, },
zoomToAirport: function (id) { zoomToAirport: function (id) {
@ -309,6 +419,7 @@
}, },
showAirportBalloon: function (id) { showAirportBalloon: function (id) {
this.map.allowMultipleDescriptionWindows = true;
var mapObject = this.map.getObjectById(id); var mapObject = this.map.getObjectById(id);
this.map.rollOverMapObject(mapObject); this.map.rollOverMapObject(mapObject);
}, },
@ -354,6 +465,7 @@
airport.color = self.airportColor; airport.color = self.airportColor;
airport.scale = self.airportScale; airport.scale = self.airportScale;
}); });
$("#demo-mapdiv-info").html("");
}, },
prepareData: function (data) { prepareData: function (data) {
@ -368,7 +480,7 @@
svgPath: self.MAPtarget, svgPath: self.MAPtarget,
color: self.airportColor, color: self.airportColor,
scale: self.airportScale, scale: self.airportScale,
selectedScale: 2.5, selectedScale: 1,
title: airport.City + " [" + airport._key + "]<br>" + airport.Name, title: airport.City + " [" + airport._key + "]<br>" + airport.Name,
rollOverColor: self.airportHoverColor, rollOverColor: self.airportHoverColor,
selectable: true selectable: true
@ -389,6 +501,8 @@
}, },
createFlightEntry: function(from, to, weight, lineColor, lineWidth) { createFlightEntry: function(from, to, weight, lineColor, lineWidth) {
if (this.keyToLongLat.hasOwnProperty(from)
&& this.keyToLongLat.hasOwnProperty(to)) {
return { return {
longitudes: [ longitudes: [
this.keyToLongLat[from].lon, this.keyToLongLat[from].lon,
@ -402,6 +516,44 @@
color: lineColor, color: lineColor,
thickness: lineWidth thickness: lineWidth
}; };
}
return undefined;
},
loadShortestPath: function(from, to) {
var self = this;
var timer = new Date();
this.airportCollection.getShortestFlight(from, to, function(list) {
var timeTaken = new Date() - timer;
if (!list.vertices) {
alert("Sorry there is no flight");
}
var vertices = list.vertices;
for (var i = 0; i < vertices.length - 1; ++i) {
var from = vertices[i].split("/")[1];
var to = vertices[i+1].split("/")[1];
self.addFlightLine(from, to, 1,
self.calculateFlightColor(vertices.length, i),
self.calculateFlightWidth(vertices.length, i),
2,
true,
false
);
}
var tempHTML = "";
tempHTML = "<b>Path</b> - Shortest Flight<br>" +
"Query needed: <b>" + (timeTaken/1000).toFixed(3) + " sec" + "</b><br>" +
"Number switches: <b>" + (vertices.length - 2) + "</b><br>" +
"Number flights: <b>" + list.edges.length + "</b><br>" +
"Airports:<br>";
for (i = 0; i < vertices.length; ++i) {
var airportData = self.airportCollection.findWhere({_key: vertices[i].split("/")[1]});
tempHTML += airportData.get("Name") + " - " + airportData.get("_key") + "<br>";
}
$("#demo-mapdiv-info").html(tempHTML);
self.map.validateData();
});
}, },
renderMap: function() { renderMap: function() {
@ -422,9 +574,17 @@
images: self.imageData, images: self.imageData,
getAreasFromMap: true getAreasFromMap: true
}, },
clickMapObject: function(mapObject) { clickMapObject: function(mapObject, event) {
//console.log(mapObject); if (mapObject.id !== undefined && mapObject.id.length === 3) {
if (event.shiftKey && self.hasOwnProperty("startPoint")) {
self.resetDataHighlighting();
self.removeFlightLines(true);
self.loadShortestPath(self.startPoint, mapObject.id);
} else {
self.startPoint = mapObject.id;
self.loadAirportData(mapObject.id); self.loadAirportData(mapObject.id);
}
}
}, },
balloon: { balloon: {
adjustBorderColor: true, adjustBorderColor: true,
@ -468,21 +628,19 @@
}); });
}, },
addFlightLine: function(from, to, count, lineColor, lineWidth, shouldRender) { addFlightLine: function(from, to, count, lineColor, lineWidth, toSize, highlight, shouldRender) {
//console.log("Adding", from, to, count, lineColor, lineWidth); var f = this.createFlightEntry(from, to, count, lineColor, lineWidth);
if (f !== undefined) {
this.lines.push(this.createFlightEntry(from, to, count, lineColor, lineWidth)); this.lines.push(f);
}
this.setAirportColor(from, "#FFFFFF"); this.setAirportColor(from, "#FFFFFF");
this.setAirportColor(to, this.airportHighlightColor); this.setAirportColor(to, this.airportHighlightColor);
this.setAirportSize(from, 1.5); this.setAirportSize(from, 1.5);
var toSize = count * 0.001;
if (toSize <= 0.25) {
toSize = 0.25;
}
this.setAirportSize(to, toSize); this.setAirportSize(to, toSize);
if (highlight) {
this.setAirportColor(to, 'rgb(153,52,4)');
}
} }
}); });

View File

@ -0,0 +1,42 @@
div.demo-dropdown-menu {
@extend %clickable;
@include border-radius(0 0 5px 5px);
background-color: $c-bar-bg;
margin-bottom: 5px;
margin-left: 5px;
position: absolute;
top: 32px;
width: 222px;
z-index: 100;
}
#flightQuerySelect.query-select {
height: 25px;
margin-top: 6px;
font-size: 13px;
line-height: 1.1em;
}
#demo-mapdiv {
position: relative;
}
#demo-mapdiv-info {
position: absolute;
right: 20px;
width: 225px;
height: 150px;
bottom: 20px;
border: 1.5px solid #222;
border-radius: 4px;
background-color: rgba(255,255,255, 0.75);
padding: 6px 6px 3px 6px;
font-size: 11px;
line-height: 1.3em;
}
.amcharts-balloon-div {
line-height: 1.1em;
}

View File

@ -504,8 +504,8 @@ div.resizecontainer {
div.centralRow { div.centralRow {
margin: { margin: {
top: 65px; top: 40px;
bottom: 65px; bottom: 40px;
} }
} }

View File

@ -87,4 +87,4 @@
@import 'uploadfile'; @import 'uploadfile';
// Demo // Demo
//@import 'demo'; @import 'demo';

View File

@ -5598,6 +5598,17 @@ function AQL_SHORTEST_PATH (vertexCollection,
params) { params) {
'use strict'; 'use strict';
if (typeof startVertex === "string" && typeof endVertex === "string") {
var opts = {
direction: direction
};
if (params.hasOwnProperty("distance") && params.hasOwnProperty("defaultDistance")) {
opts.distance = params.distance;
opts.defaultDistance = params.defaultDistance;
}
return CPP_SHORTEST_PATH(vertexCollection, edgeCollection, startVertex, endVertex, opts);
}
params = SHORTEST_PATH_PARAMS(params); params = SHORTEST_PATH_PARAMS(params);
return TRAVERSAL_FUNC("SHORTEST_PATH", return TRAVERSAL_FUNC("SHORTEST_PATH",