1
0
forked from MTSR/mapserver

Fix Trainlines (#177) (#230)

* add global getMapDataWithAttributeLikeGlobalQuery

* add getMapDataWithAttributeLikeGlobalQuery for postgres

* perform global search when position missing (sqlite)

* perform global query when pos missing (postgres)

* TrainelineOverlay: query full information on visible lines before drawing

* hopefully fix errors, minor efficiency improvements

* stupid mistake

* you know it's probably late when mistakes like this happen

* same for postgres

* more optimizations
This commit is contained in:
Peter Nerlich 2022-01-17 08:53:45 +01:00 committed by GitHub
parent 1ee54f9032
commit 25e177fbb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 87 deletions

View File

@ -28,14 +28,23 @@ func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobject
)
} else {
//attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikePosQuery,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
q.AttributeLike.Key, q.AttributeLike.Value,
limit,
)
if (q.Pos1 == nil || q.Pos2 == nil) {
//global attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikeGlobalQuery,
q.AttributeLike.Key, q.AttributeLike.Value,
q.Type,
limit,
)
} else {
//attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikePosQuery,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
q.AttributeLike.Key, q.AttributeLike.Value,
limit,
)
}
}
if err != nil {

View File

@ -29,6 +29,20 @@ and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
order by o.id
limit $10
`
const getMapDataWithAttributeLikeGlobalQuery = `
select o.id, o.type, o.mtime,
o.x, o.y, o.z,
o.posx, o.posy, o.posz,
oa.key, oa.value
from objects o
left join object_attributes oa on o.id = oa.objectid
where o.id in (
select objectid from object_attributes where key = $2 and value ilike $3
)
and o.type = $1
order by o.id
limit $4
`
const removeMapDataQuery = `
delete from objects where posx = $1 and posy = $2 and posz = $3

View File

@ -28,14 +28,23 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
)
} else {
//attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikePosQuery,
q.AttributeLike.Key, q.AttributeLike.Value,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
limit,
)
if (q.Pos1 == nil || q.Pos2 == nil) {
//global attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikeGlobalQuery,
q.AttributeLike.Key, q.AttributeLike.Value,
q.Type,
limit,
)
} else {
//attribute like search
rows, err = db.db.Query(getMapDataWithAttributeLikePosQuery,
q.AttributeLike.Key, q.AttributeLike.Value,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
limit,
)
}
}
if err != nil {

View File

@ -31,6 +31,21 @@ order by o.id
limit ?
`
const getMapDataWithAttributeLikeGlobalQuery = `
select o.id, o.type, o.mtime,
o.x, o.y, o.z,
o.posx, o.posy, o.posz,
oa.key, oa.value
from objects o
left join object_attributes oa on o.id = oa.objectid
where o.id in (
select objectid from object_attributes where key = ? and value like ?
)
and o.type = ?
order by o.id
limit ?
`
const removeMapDataQuery = `
delete from objects where posx = ? and posy = ? and posz = ?
`

View File

@ -1,13 +1,16 @@
import AbstractGeoJsonOverlay from './AbstractGeoJsonOverlay.js';
import { getMapObjects } from '../../api.js';
export default AbstractGeoJsonOverlay.extend({
initialize: function() {
AbstractGeoJsonOverlay.prototype.initialize.call(this, "train");
},
createGeoJson: function(objects){
var geoJsonLayer = L.geoJSON([], {
this.cache = {
lines: {}, // { "A1":[] }
lineColors: {}, // { "A1": "red" }
lineFeat: []
};
this.pendingQueries = [];
this.lastLayer = L.geoJSON([], {
onEachFeature: function(feature, layer){
if (feature.properties && feature.properties.popupContent) {
layer.bindPopup(feature.properties.popupContent);
@ -29,86 +32,101 @@ export default AbstractGeoJsonOverlay.extend({
}
}
});
},
createGeoJson: function(objects){
var self = this;
var lines = {}; // { "A1":[] }
var lineColors = {}; // { "A1": "red" }
//Sort and add lines
// which unique lines do objects belong to?
var lines = [];
objects.forEach(function(obj){
if (!obj.attributes.line)
return;
var line = lines[obj.attributes.line];
if (!line){
line = [];
lines[obj.attributes.line] = line;
//default or new color
lineColors[obj.attributes.line] = "#ff7800";
if (obj.attributes.line && lines.indexOf(obj.attributes.line) == -1) {
lines.push(obj.attributes.line);
}
if (obj.attributes.color){
//new color
lineColors[obj.attributes.line] = obj.attributes.color;
}
line.push(obj);
});
//Order by index and display
Object.keys(lines).forEach(function(linename){
lines[linename].sort(function(a,b){
return parseInt(a.attributes.index) - parseInt(b.attributes.index);
});
// query for each line, add to cache
lines.forEach(function(linename){
if (!self.cache.lines[linename]){
// only request if not in cache.
// if someone changed the train lines, the user has to reload. sorry.
self.pendingQueries.push(linename);
getMapObjects({
type: self.type,
attributelike: {
key: "line",
value: linename
}
})
.then(function(objects){
objects.sort(function(a,b){
return parseInt(a.attributes.index) - parseInt(b.attributes.index);
});
var coords = [];
var stations = [];
self.cache.lines[linename] = objects;
// already sorted, determine color
self.cache.lineColors[linename] = "#ff7800";
for (var i = objects.length-1; i >= 0; i--) {
// find the last element specifying a color
// as was previous behaviour, but be more efficient
if (objects[i].attributes.color){
self.cache.lineColors[linename] = objects[i].attributes.color;
break;
}
}
//Add stations
lines[linename].forEach(function(entry){
coords.push([entry.x, entry.z]);
var feat = {
coords: [],
stations: [],
feature: null
};
//Add stations
objects.forEach(function(entry){
feat.coords.push([entry.x, entry.z]);
if (entry.attributes.station) {
stations.push({
"type": "Feature",
"properties": {
"name": entry.attributes.station,
"color": lineColors[linename],
"popupContent": "<b>Train-station (Line " + entry.attributes.line + ")</b><hr>" +
entry.attributes.station
},
"geometry": {
"type": "Point",
"coordinates": [entry.x, entry.z]
if (entry.attributes.station) {
feat.stations.push({
"type": "Feature",
"properties": {
"name": entry.attributes.station,
"color": self.cache.lineColors[linename],
"popupContent": "<b>Train-station (Line " + entry.attributes.line + ")</b><hr>" +
entry.attributes.station
},
"geometry": {
"type": "Point",
"coordinates": [entry.x, entry.z]
}
});
}
});
}
});
var feature = {
"type":"Feature",
"geometry": {
"type":"LineString",
"coordinates":coords
},
"properties":{
"name": linename,
"color": lineColors[linename],
"popupContent": "<b>Train-line (" + linename + ")</b>"
}
};
feat.feature = {
"type":"Feature",
"geometry": {
"type":"LineString",
"coordinates": feat.coords
},
"properties":{
"name": linename,
"color": self.cache.lineColors[linename],
"popupContent": "<b>Train-line (" + linename + ")</b>"
}
};
//line-points
geoJsonLayer.addData(feature);
//stations
stations.forEach(function(stationfeature){
geoJsonLayer.addData(stationfeature);
});
self.cache.lineFeat[linename] = feat;
//line-points
self.lastLayer.addData(feat.feature);
//stations
feat.stations.forEach(function(stationfeature){
self.lastLayer.addData(stationfeature);
});
});
}
});
return geoJsonLayer;
}
return self.lastLayer;
},
});