Skip to content

Commit

Permalink
Merge pull request #44 from DavidLevinsky/master
Browse files Browse the repository at this point in the history
Better search
  • Loading branch information
davidmtech authored May 19, 2017
2 parents e2b9d72 + d964437 commit 471cfdb
Show file tree
Hide file tree
Showing 14 changed files with 398 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vts-browser-js",
"version": "2.3.0",
"version": "2.4.0",
"description": "JavaScript WebGL 3D maps rendering engine",
"main": "src/browser/index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/browser/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ Browser.prototype.onMapLoaded = function(event) {

Browser.prototype.getLinkWithCurrentPos = function() {
var map = this.getMap();
if (map == null) {
if (!map) {
return '';
}

Expand Down
6 changes: 3 additions & 3 deletions src/browser/control-mode/map-observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ ControlModeMapObserver.prototype.getAzimuthAndDistance = function(dx, dy) {

ControlModeMapObserver.prototype.tick = function() {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand Down Expand Up @@ -432,7 +432,7 @@ function constrainMapPosition(browser, pos) {

var distance = (pos.getViewExtent()*0.5) / Math.tan(math.radians(pos.getFov()*0.5));

//reduce tilt whe you are far off the planet
//reduce tilt when you are far off the planet
if (pos.getViewMode() == 'obj') {
var rf = map.getReferenceFrame();
var srs = map.getSrsInfo(rf['navigationSrs']);
Expand All @@ -453,7 +453,7 @@ function constrainMapPosition(browser, pos) {
o[1] = minTilt;
}

pos = pos.setOrientation(o);
pos.setOrientation(o);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/browser/control-mode/pano.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ControlModePano.prototype.up = function(event) {

ControlModePano.prototype.wheel = function(event) {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand Down Expand Up @@ -93,7 +93,7 @@ ControlModePano.prototype.tick = function() {
}

var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand Down
16 changes: 13 additions & 3 deletions src/browser/ui/control/compass.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var UIControlCompass = function(ui, visible) {

UIControlCompass.prototype.update = function() {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand All @@ -58,10 +58,15 @@ UIControlCompass.prototype.update = function() {

UIControlCompass.prototype.onDrag = function(event) {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

if (this.browser.autopilot) { //stop autorotation
this.browser.autopilot.setAutorotate(0);
this.browser.autopilot.setAutopan(0,0);
}

var delta = event.getDragDelta();
var sensitivity = 0.4;

Expand All @@ -76,10 +81,15 @@ UIControlCompass.prototype.onDrag = function(event) {

UIControlCompass.prototype.onDoubleClick = function(event) {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

if (this.browser.autopilot) { //stop autorotation
this.browser.autopilot.setAutorotate(0);
this.browser.autopilot.setAutopan(0,0);
}

var pos = map.getPosition();
var orientation = pos.getOrientation();
orientation[0] = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/browser/ui/control/credits.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ UIControlCredits.prototype.getCreditsString = function(array, separator, full) {

UIControlCredits.prototype.update = function() {
var map = this.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/browser/ui/control/loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ UIControlLoading.prototype.update = function() {
}

var map = this.ui.browser.getMap();
if (map == null) {
if (!map) {
return;
}

Expand Down
242 changes: 242 additions & 0 deletions src/browser/ui/control/search-filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@

import {math as math_} from '../../../core/utils/math';

//get rid of compiler mess
var math = math_;

// Deduplication of hits, that have the same display_name
// and are subsequent in a result set.
function dedupe(hits) {
var hit, result = [], dupes = [];

// Helper function, that takes set of duplicities
// and returns just one hit.
//
// we return first populated place - if exist
// or if not exist we return just first one
var filterHits = (function(dupes){
for (var j = 0; j < dupes.length; j++) {
switch (dupes[j].type) {
case 'hamlet':
case 'village':
case 'town':
case 'city':
return dupes[j];
}
}

return dupes[0];
});

// We go through all hits and separate results
// and duplicities
for (var i = 0; i < hits.length - 1; i++) {
hit = hits[i];

if (hit.display_name === hits[ i + 1 ].display_name) {
dupes.push(hit);
} else {
if (dupes.length > 0) {
dupes.push(hit);
result.push(filterHits(dupes));
dupes.length = 0;
} else {
result.push(hit);
}
}
}

// Make sure filterHits is called
if (dupes.length) {
result.push(filterHits(dupes));
}

return result;
}

function getDistance(lon1, lat1, lon2, lat2) {
var r = 6371e3; // metres
var l1 = math.radians(lat1);
var l2 = math.radians(lat2);
var dlat = math.radians(lat2-lat1);
var dlon = math.radians(lon2-lon1);

var a = Math.sin(dlat/2) * Math.sin(dlat/2) +
Math.cos(l1) * Math.cos(l2) *
Math.sin(dlon/2) * Math.sin(dlon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

return r * c;
}

// Stupid unprecise comparsion of two points, if
// they lay close to each other (less than 10km)
function layClose(A, B) {
//return ruler.distance([ A.lon, A.lat ], [ B.lon, B.lat ] ) < 10
var diff = 0.1;

return ( +B.lat > +A.lat - diff ) && ( +B.lat < +A.lat + diff )
&& ( +B.lon > +A.lon - diff ) && ( +B.lon < +A.lon + diff );
}

// Hits with low importance can be reshaked by its distance
function reshakeHits(hits) {
var maxDiff = 0.06;
var maxRank = 0.4;
var temp, done;

do {
done = true;

for (var i = 0; i < hits.length - 1; i++ ) {
var h1 = hits[i];
var h2 = hits[i + 1];

if (( h1.rank < maxRank && h2.rank < maxRank ) // both hits have lowRank
&& ( Math.abs( h1.rank - h2.rank ) < maxDiff ) // ...and diff in their rank is small
&& ( h1.distance > h2.distance ) // ...and h1 has bigger distance
) {

// Switch both hits
h1.note = 'reshaked-down'
h2.note = 'reshaked-up'

temp = h1;
hits[i] = h2;
hits[i + 1] = temp;
done = false;
}
}
} while (!done);
}


// Return Promise, that resolves nice deduplicated results from
// Nominatim (on particular keyword)
function filterSearch(data, lon, lat) {
var rtrn = [];
var hasLocation = lat && lon;
var hits = data;

/*
// Should we search ZIP code?
var querySubString = ( /^\d{3,5}$/.test( query ) ) ?
`postalcode=${ query }` : `q=${ encodeURIComponent( query ) }`
var url = `${ searchServer }search.php?format=json&limit=20&addressdetails=1&${ querySubString }&accept-language=${lang}`;
if( program.dev ) log.info(url);
*/

var rtrnHit, hit, adr, region, county, display, bounds;

// Deduplication number 1: Deduplicate consequent
// results with same name
if( hits.length > 1) {
hits = dedupe( hits );
}

//Cycle each hit and reduce uts size
for (var i = 0; i < hits.length; i++) {

// Shortcuts
hit = hits[i];

bounds = hit.boundingbox;

adr = hit.address;

display = hit.display_name.replace(/,.*/,'');

region = adr.state && adr.state
|| ( adr.state_district && adr.state_district ||
( adr.county && adr.county || '' ) );

county = adr.county && adr.county
|| ( adr.state_district && adr.state_district || region );

// If county is same as title, find
// something better
if (county === display) {
county = adr.state_district && adr.state_district || region;
}

// Deduplication number 2: Simple process of throwing away hits
// that have lower importance, and lay in vicinity
// of previous hit
if (rtrnHit && layClose(rtrnHit, hit)) continue;

// Filter out results with low, low low importance
// but only if there is more results
if (hit.importance < 0.01 && i > 5) continue;

// Rewrite these types of regions
// "Graubünden - Grigioni - Grischun" --> "Graubunder"
if (new RegExp(/ - /).test( region )) {
region = region.replace(/ -.*/,'');
}

// Should we display bounds instead of dot in a map?
if (hit.type === 'archipelago' ||
( hit.type === 'administrative' &&
(display === adr.country || display === region ))) {

// Repair undefined lon values in bounds
if( bounds[2] === '-180' ) {
bounds[2] = bounds[3] = hit.lon;
}

} else {
bounds = null;
}

// Changes display name in adress querries like "Kopeckeho 27"
if (display === adr.house_number && adr.road ) {
display = adr.road;
}

rtrnHit = {
lat: +hit.lat,
lon: +hit.lon,
title: display,

rank: hit.importance,

// for US we use State as country
country: adr.country_code === 'us' ? region : ( adr.country && adr.country.replace(/,.*/,'') ),

region: county || '',
state: region || '',
cc: adr.country_code,
type: hit.type,
bounds: bounds,
polygon : hit.polygonpoints || [],
bbox : hit.boundingbox
}

// Calculate distance
if (hasLocation) {
rtrnHit.distance = getDistance(lon, lat, rtrnHit.lon, rtrnHit.lat);
}


rtrn.push(rtrnHit)
}

// Reshake hits by distance
if (hasLocation) {
reshakeHits(rtrn);
}

return rtrn;
}

// return query on reverse search
/*
function geoSearch = ( { lat,lon,zoom,lang } ) => {
var url = `${ searchServer }reverse.php?format=json&lat=${ lat }&lon=${ lon }&zoom=${ zoom }&addressdetails=1&accept-language=${ lang }`
return rp.get(url,{ timeout: 3000, json: true })
}
*/

export {filterSearch};
Loading

0 comments on commit 471cfdb

Please sign in to comment.