Merge branch 'master' into text_scale

This commit is contained in:
vshcherb 2020-06-19 12:47:02 +02:00 committed by GitHub
commit 3580b5be29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
335 changed files with 12304 additions and 104471 deletions

View file

@ -43,6 +43,7 @@ task collectTestResources(type: Copy) {
into "src/test/resources/"
from("../../resources/test-resources") {
include "*"
include "/search/*"
}
from("../../resources/poi") {
include "poi_types.xml"

View file

@ -33,8 +33,9 @@ public class CollatorStringMatcher implements StringMatcher {
public CollatorStringMatcher(String part, StringMatcherMode mode) {
this.collator = OsmAndCollator.primaryCollator();
this.part = part.toLowerCase(Locale.getDefault());
this.part = simplifyStringAndAlignChars(part);
this.mode = mode;
}
public Collator getCollator() {
@ -123,14 +124,15 @@ public class CollatorStringMatcher implements StringMatcher {
* @param theStart
* @return true if searchIn starts with token
*/
public static boolean cstartsWith(Collator collator, String fullText, String theStart,
public static boolean cstartsWith(Collator collator, String fullTextP, String theStart,
boolean checkBeginning, boolean checkSpaces, boolean equals) {
String searchIn = fullText.toLowerCase(Locale.getDefault());
String searchIn = simplifyStringAndAlignChars(fullTextP);
int searchInLength = searchIn.length();
int startLength = theStart.length();
if (startLength == 0) {
return true;
}
// this is not correct because of Auhofstrasse != Auhofstraße
if (startLength > searchInLength) {
return false;
}
@ -152,7 +154,8 @@ public class CollatorStringMatcher implements StringMatcher {
if (isSpace(searchIn.charAt(i - 1)) && !isSpace(searchIn.charAt(i))) {
if (collator.equals(searchIn.substring(i, i + startLength), theStart)) {
if(equals) {
if(i + startLength == searchInLength || isSpace(searchIn.charAt(i + startLength))) {
if(i + startLength == searchInLength ||
isSpace(searchIn.charAt(i + startLength))) {
return true;
}
} else {
@ -168,7 +171,17 @@ public class CollatorStringMatcher implements StringMatcher {
return false;
}
private static String simplifyStringAndAlignChars(String fullText) {
int i;
fullText = fullText.toLowerCase(Locale.getDefault());
while( (i = fullText.indexOf('ß') ) != -1 ) {
fullText = fullText.substring(0, i) + "ss" + fullText.substring(i+1);
}
return fullText;
}
private static boolean isSpace(char c){
return !Character.isLetter(c) && !Character.isDigit(c);
}
}

View file

@ -957,6 +957,24 @@ public class GPXUtilities {
return ls;
}
public static QuadRect calculateBounds(List<WptPt> pts) {
QuadRect trackBounds = new QuadRect(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
updateBounds(trackBounds, pts, 0);
return trackBounds;
}
public static void updateBounds(QuadRect trackBounds, List<WptPt> pts, int startIndex) {
for (int i = startIndex; i < pts.size(); i++) {
WptPt pt = pts.get(i);
trackBounds.right = Math.max(trackBounds.right, pt.lon);
trackBounds.left = Math.min(trackBounds.left, pt.lon);
trackBounds.top = Math.max(trackBounds.top, pt.lat);
trackBounds.bottom = Math.min(trackBounds.bottom, pt.lat);
}
}
public static class GPXFile extends GPXExtensions {
public String author;
public Metadata metadata;

View file

@ -354,6 +354,7 @@ public class NativeLibrary {
FileInputStream fis = new FileInputStream(f);
Algorithms.streamCopy(fis, ous);
fis.close();
System.out.println("FONT " + name);
initFontType(ous.toByteArray(), name.substring(0, name.length() - 4), name.toLowerCase().contains("bold"),
name.toLowerCase().contains("italic"));
} catch (IOException e) {

View file

@ -38,4 +38,5 @@ public class OsmAndCollator {
}
};
}
}

View file

@ -1,6 +1,7 @@
package net.osmand;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import org.apache.commons.logging.Log;
@ -19,61 +20,67 @@ public class Reshaper {
return "";
}
}
public static String reshape(String s) {
// if(true) {
// return s;
// }
try {
ArabicShaping as = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK);
ArabicShaping as = new ArabicShaping(ArabicShaping.LETTERS_SHAPE |
ArabicShaping.LENGTH_GROW_SHRINK);
//printSplit("B", s);
try {
s = as.shape(s);
} catch (ArabicShapingException e) {
LOG.error(e.getMessage(), e);
}
//printSplit("A", s);
Bidi line = new Bidi(s.length(), s.length());
line.setPara(s, Bidi.LEVEL_DEFAULT_LTR, null);
line.setPara(s, Bidi.LEVEL_DEFAULT_LTR, null);
// line.setPara(s, Bidi.LEVEL_DEFAULT_LTR, null);
// s = line.writeReordered(Bidi.DO_MIRRORING);
// s = reordered;
byte direction = line.getDirection();
if (direction != Bidi.MIXED) {
// unidirectional
if(line.isLeftToRight()) {
return s;
} else {
if (line.isLeftToRight()) {
return s;
} else {
char[] chs = new char[s.length()];
for(int i = 0; i< chs.length ; i++) {
chs[i] = s.charAt(chs.length - i - 1);
// chs[i] = s.charAt(chs.length - i - 1);
chs[i] = mirror(s.charAt(chs.length - i - 1));
}
return new String(chs);
}
} else {
// // mixed-directional
// mixed-directional
// System.out.println(s);
// printSplit("Split", s);
int count = line.countRuns();
// if (styleRunCount <= 1) {
// int style = styleRuns[0].style;
// // iterate over directional runs
// for (i = 0; i < count; ++i) {
// run = line.getVisualRun(i);
// renderRun(text, run.getStart(), run.getLimit(),
// run.getDirection(), style);
// }
// }
StringBuilder res = new StringBuilder();
// iterate over both directional and style runs
for (int i = 0; i < count; ++i) {
StringBuilder runs = new StringBuilder();
BidiRun run = line.getVisualRun(i);
int st = run.getStart();
int e = run.getLimit();
int j = run.getDirection() == Bidi.LTR ? st : e - 1;
int l = run.getDirection() == Bidi.LTR ? e : st - 1;
boolean plus = run.getDirection() == Bidi.LTR;
while (j != l) {
res.append(s.charAt(j));
if (plus) {
j++;
} else {
j--;
boolean ltr = run.getDirection() == Bidi.LTR;
int start = run.getStart();
int limit = run.getLimit();
int begin = ltr ? start : limit - 1;
int end = ltr ? limit : start - 1;
int ind = begin;
while (ind != end) {
char ch = s.charAt(ind);
if (!ltr) {
ch = mirror(ch);
}
res.append(ch);
runs.append(ch);
if (ltr) {
ind++;
} else {
ind--;
}
}
printSplit(run.getDirection() + " " + run.getEmbeddingLevel(), runs.toString());
}
return res.toString();
}
@ -83,24 +90,77 @@ public class Reshaper {
}
}
public static void main(String[] args) {
// char[] c = new char[] {'א', 'ד','ם', ' ', '1', '2'} ;
// String reshape = "אדם";
char[] c = new char[] {'א', 'ד','ם'} ;
String reshape = reshape(new String(c));
for(int i=0; i < reshape.length(); i++) {
System.out.println(reshape.charAt(i));
private static char mirror(char ch) {
switch (ch) {
case '(': ch = ')'; break;
case ')': ch = '('; break;
case '[': ch = ']'; break;
case ']': ch = '['; break;
}
return ch;
}
public static void main(String[] args) {
test2();
test3();
test4();
test5();
}
private static void test2() {
public static void test3() {
String s = "מרכז מסחרי/השלום (40050)";
String reshape = reshape(s);
String expected = "(40050) םולשה/ירחסמ זכרמ";
check(s, reshape, expected);
}
public static void test5() {
String s = "מרכז מסחרי/השלום (מרז)";
String reshape = reshape(s);
String expected = "(זרמ) םולשה/ירחסמ זכרמ";
check(s, reshape, expected);
}
public static void check(String source, String reshape, String expected) {
printSplit("Source ", source);
printSplit("Expected", expected);
printSplit("Reshaped", reshape);
System.out.println(reshape);
if (!reshape.equals(expected)) {
throw new IllegalArgumentException(String.format("Bug: expected '%s', reshaped '%s'", expected, reshape));
}
}
static void printSplit(String p, String source) {
printSplit(p, source, true);
printSplit(p, source, false);
}
static void printSplit(String p, String source, boolean f) {
System.out.print(p);
System.out.print(": \u2066");
for (int i = 0; i < source.length(); i++) {
if (f) {
System.out.print(source.charAt(i));
System.out.print(" \u200e");
} else {
System.out.print(String.format("%04x ", (int) source.charAt(i)));
}
}
// System.out.println(Arrays.toString(source.toCharArray()));
System.out.println();
System.out.flush();
}
public static void test2() {
String s = "گچ پژ نمکی باللغة العربي";
String reshape = reshape(s);
String expected1 = "ﻲﺑﺮﻌﻟﺍ ﺔﻐﻠﻟﺎﺑ ﯽﮑﻤﻧ ﮋﭘ ﭻﮔ";
String expected2 = "ﻲﺑﺮﻌﻟﺍ ﺔﻐﻠﻟﺎﺑ یکﻤﻧ ژپ چگ";
check(s, reshape, expected1);
}
if (!reshape.equals("ﻲﺑﺮﻌﻟﺍ ﺔﻐﻠﻟﺎﺑ ﯽﮑﻤﻧ ﮋﭘ ﭻﮔ")) {
throw new IllegalArgumentException("BUG!!!");
}
public static void test4() {
String s = "Abc (123)";
check(s, reshape(s), s);
}
}

View file

@ -221,7 +221,7 @@ public class BinaryMapAddressReaderAdapter {
int fp = codedIS.getTotalBytesRead();
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
City c = readCityHeader(new DefaultCityMatcher(matcher), fp, additionalTagsTable);
City c = readCityHeader(resultMatcher, new DefaultCityMatcher(matcher), fp, additionalTagsTable);
if (c != null) {
if (resultMatcher == null || resultMatcher.publish(c)) {
cities.add(c);
@ -256,6 +256,7 @@ public class BinaryMapAddressReaderAdapter {
int oldLimit = codedIS.pushLimit(length);
readStreet(s, null, false, x >> 7, y >> 7, city.isPostcode() ? city.getName() : null,
attributeTagsTable);
publishRawData(resultMatcher, s);
if (resultMatcher == null || resultMatcher.publish(s)) {
city.registerStreet(s);
}
@ -303,7 +304,7 @@ public class BinaryMapAddressReaderAdapter {
}
}
protected City readCityHeader(CityMatcher matcher, int filePointer, List<String> additionalTagsTable) throws IOException {
protected City readCityHeader(SearchRequest<? super City> resultMatcher, CityMatcher matcher, int filePointer, List<String> additionalTagsTable) throws IOException {
int x = 0;
int y = 0;
City c = null;
@ -313,6 +314,7 @@ public class BinaryMapAddressReaderAdapter {
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
publishRawData(resultMatcher, c);
return (matcher == null || matcher.matches(c)) ? c : null;
case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER:
int type = codedIS.readUInt32();
@ -445,6 +447,7 @@ public class BinaryMapAddressReaderAdapter {
if (loadBuildingsAndIntersected) {
int oldLimit = codedIS.pushLimit(length);
Building b = readBuilding(offset, x, y, additionalTagsTable);
publishRawData(buildingsMatcher, b);
if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) {
if (buildingsMatcher == null || buildingsMatcher.publish(b)) {
s.addBuilding(b);
@ -688,7 +691,7 @@ public class BinaryMapAddressReaderAdapter {
codedIS.seek(contOffset);
int len = codedIS.readRawVarint32();
int old = codedIS.pushLimit(len);
obj = readCityHeader(null, contOffset, reg.attributeTagsTable);
obj = readCityHeader(req, null, contOffset, reg.attributeTagsTable);
codedIS.popLimit(old);
}
if (obj != null) {
@ -701,6 +704,7 @@ public class BinaryMapAddressReaderAdapter {
readStreet(s, null, false, MapUtils.get31TileNumberX(l.getLongitude()) >> 7,
MapUtils.get31TileNumberY(l.getLatitude()) >> 7, obj.isPostcode() ? obj.getName() : null,
reg.attributeTagsTable);
publishRawData(req, s);
boolean matches = stringMatcher.matches(s.getName());
if (!matches) {
for (String n : s.getAllNames()) {
@ -727,7 +731,8 @@ public class BinaryMapAddressReaderAdapter {
codedIS.seek(offset);
int len = codedIS.readRawVarint32();
int old = codedIS.pushLimit(len);
City obj = readCityHeader(cityPostcodeMatcher, list.get(j), reg.attributeTagsTable);
City obj = readCityHeader(req, cityPostcodeMatcher, list.get(j), reg.attributeTagsTable);
publishRawData(req, obj);
if (obj != null && !published.contains(offset)) {
req.publish(obj);
published.add(offset);
@ -805,4 +810,9 @@ public class BinaryMapAddressReaderAdapter {
}
}
private <T> void publishRawData(SearchRequest<T> resultMatcher, T obj) {
if (resultMatcher != null && obj != null) {
resultMatcher.collectRawData(obj);
}
}
}

View file

@ -496,7 +496,7 @@ public class BinaryMapIndexReader {
}
}
Iterator<Entry<TransportIndex, TIntArrayList>> it = groupPoints.entrySet().iterator();
if (it.hasNext()) {
while (it.hasNext()) {
Entry<TransportIndex, TIntArrayList> e = it.next();
TransportIndex ind = e.getKey();
TIntArrayList pointers = e.getValue();
@ -1457,8 +1457,14 @@ public class BinaryMapIndexReader {
public static <T> SearchRequest<T> buildAddressByNameRequest(ResultMatcher<T> resultMatcher, String nameRequest,
StringMatcherMode matcherMode) {
return buildAddressByNameRequest(resultMatcher, null, nameRequest, matcherMode);
}
public static <T> SearchRequest<T> buildAddressByNameRequest(ResultMatcher<T> resultMatcher, ResultMatcher<T> rawDataCollector, String nameRequest,
StringMatcherMode matcherMode) {
SearchRequest<T> request = new SearchRequest<T>();
request.resultMatcher = resultMatcher;
request.rawDataCollector = rawDataCollector;
request.nameQuery = nameRequest.trim();
request.matcherMode = matcherMode;
return request;
@ -1542,6 +1548,10 @@ public class BinaryMapIndexReader {
public static SearchRequest<Amenity> buildSearchPoiRequest(int x, int y, String nameFilter, int sleft, int sright, int stop, int sbottom, ResultMatcher<Amenity> resultMatcher) {
return buildSearchPoiRequest(x, y, nameFilter, sleft, sright, stop, sbottom, resultMatcher, null);
}
public static SearchRequest<Amenity> buildSearchPoiRequest(int x, int y, String nameFilter, int sleft, int sright, int stop, int sbottom, ResultMatcher<Amenity> resultMatcher, ResultMatcher<Amenity> rawDataCollector) {
SearchRequest<Amenity> request = new SearchRequest<Amenity>();
request.x = x;
request.y = y;
@ -1550,6 +1560,7 @@ public class BinaryMapIndexReader {
request.top = stop;
request.bottom = sbottom;
request.resultMatcher = resultMatcher;
request.rawDataCollector = rawDataCollector;
request.nameQuery = nameFilter.trim();
return request;
}
@ -1634,6 +1645,7 @@ public class BinaryMapIndexReader {
private boolean ocean = false;
private ResultMatcher<T> resultMatcher;
private ResultMatcher<T> rawDataCollector;
// 31 zoom tiles
// common variables
@ -1711,6 +1723,12 @@ public class BinaryMapIndexReader {
return false;
}
public void collectRawData(T obj) {
if (rawDataCollector != null) {
rawDataCollector.publish(obj);
}
}
protected void publishOceanTile(boolean ocean) {
if (ocean) {
this.ocean = true;

View file

@ -26,7 +26,6 @@ import net.osmand.data.Amenity.AmenityRoutePoint;
import net.osmand.data.LatLon;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
@ -591,6 +590,7 @@ public class BinaryMapPoiReaderAdapter {
}
}
if (matches) {
req.collectRawData(am);
req.publish(am);
}
}
@ -637,6 +637,7 @@ public class BinaryMapPoiReaderAdapter {
int yp = (int) MapUtils.getTileNumberY(zSkip, am.getLocation().getLatitude());
long valSkip = (((long) xp) << zSkip) | yp;
if (!toSkip.contains(valSkip)) {
req.collectRawData(am);
boolean publish = req.publish(am);
if (publish) {
read = true;
@ -647,6 +648,7 @@ public class BinaryMapPoiReaderAdapter {
return read;
}
} else {
req.collectRawData(am);
if (req.publish(am)) {
read = true;
}

View file

@ -93,33 +93,6 @@ public class Amenity extends MapObject {
return str;
}
public String unzipContent(String str) {
if (str != null) {
if (str.startsWith(" gz ")) {
try {
int ind = 4;
byte[] bytes = new byte[str.length() - ind];
for (int i = ind; i < str.length(); i++) {
char ch = str.charAt(i);
bytes[i - ind] = (byte) ((int) ch - 128 - 32);
}
GZIPInputStream gzn = new GZIPInputStream(new ByteArrayInputStream(bytes));
BufferedReader br = new BufferedReader(new InputStreamReader(gzn, "UTF-8"));
StringBuilder bld = new StringBuilder();
String s;
while ((s = br.readLine()) != null) {
bld.append(s);
}
br.close();
str = bld.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return str;
}
public Map<String, String> getAdditionalInfo() {
if (additionalInfo == null) {

View file

@ -8,6 +8,10 @@ import net.osmand.util.TransliterationHelper;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -18,6 +22,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;
public abstract class MapObject implements Comparable<MapObject> {
@ -55,7 +60,7 @@ public abstract class MapObject implements Comparable<MapObject> {
public String getName() {
if (name != null) {
return name;
return unzipContent(name);
}
return ""; //$NON-NLS-1$
}
@ -73,7 +78,7 @@ public abstract class MapObject implements Comparable<MapObject> {
if (names == null) {
names = new HashMap<String, String>();
}
names.put(lang, name);
names.put(lang, unzipContent(name));
}
}
@ -95,19 +100,25 @@ public abstract class MapObject implements Comparable<MapObject> {
}
Map<String, String> mp = new HashMap<String, String>();
if (names != null) {
mp.putAll(names);
Iterator<Entry<String, String>> it = mp.entrySet().iterator();
while(it.hasNext()) {
Entry<String, String> e = it.next();
mp.put(e.getKey(), unzipContent(e.getValue()));
}
}
mp.put("en", enName);
mp.put("en", unzipContent(enName));
return mp;
}
public List<String> getAllNames() {
List<String> l = new ArrayList<String>();
if (!Algorithms.isEmpty(enName)) {
l.add(enName);
l.add(unzipContent(enName));
}
if (names != null) {
l.addAll(names.values());
for(String nm : names.values()) {
l.add(unzipContent(nm));
}
}
return l;
}
@ -179,7 +190,7 @@ public abstract class MapObject implements Comparable<MapObject> {
if (names != null) {
String nm = names.get(lang);
if (!Algorithms.isEmpty(nm)) {
return nm;
return unzipContent(nm);
}
if (transliterate) {
return TransliterationHelper.transliterate(getName());
@ -192,7 +203,7 @@ public abstract class MapObject implements Comparable<MapObject> {
public String getEnName(boolean transliterate) {
if (!Algorithms.isEmpty(enName)) {
return this.enName;
return unzipContent(this.enName);
} else if (!Algorithms.isEmpty(getName()) && transliterate) {
return TransliterationHelper.transliterate(getName());
}
@ -322,12 +333,12 @@ public abstract class MapObject implements Comparable<MapObject> {
public JSONObject toJSON() {
JSONObject json = new JSONObject();
json.put("name", name);
json.put("enName", enName);
json.put("name", unzipContent(name));
json.put("enName", unzipContent(enName));
if (names != null && names.size() > 0) {
JSONObject namesObj = new JSONObject();
for (Entry<String, String> e : names.entrySet()) {
namesObj.put(e.getKey(), e.getValue());
namesObj.put(e.getKey(), unzipContent(e.getValue()));
}
json.put("names", namesObj);
}
@ -340,6 +351,31 @@ public abstract class MapObject implements Comparable<MapObject> {
return json;
}
public String unzipContent(String str) {
if (str != null && str.startsWith(" gz ")) {
try {
int ind = 4;
byte[] bytes = new byte[str.length() - ind];
for (int i = ind; i < str.length(); i++) {
char ch = str.charAt(i);
bytes[i - ind] = (byte) ((int) ch - 128 - 32);
}
GZIPInputStream gzn = new GZIPInputStream(new ByteArrayInputStream(bytes));
BufferedReader br = new BufferedReader(new InputStreamReader(gzn, "UTF-8"));
StringBuilder bld = new StringBuilder();
String s;
while ((s = br.readLine()) != null) {
bld.append(s);
}
br.close();
str = bld.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
return str;
}
protected static void parseJSON(JSONObject json, MapObject o) {
if (json.has("name")) {
o.name = json.getString("name");

View file

@ -301,8 +301,11 @@ public abstract class Entity implements Serializable {
String values = getTag(OSMTagKey.IS_IN);
if (values == null) {
String city = getTag(OSMTagKey.ADDR_CITY);
String place = getTag(OSMTagKey.ADDR_PLACE);
if(!Algorithms.isEmpty(city)) {
return Collections.singleton(city.trim());
} else if(!Algorithms.isEmpty(place)) {
return Collections.singleton(place.trim());
}
return Collections.emptySet();
}

View file

@ -34,9 +34,11 @@ public class OSMSettings {
// address
PLACE("place"), //$NON-NLS-1$
ADDR_HOUSE_NUMBER("addr:housenumber"), //$NON-NLS-1$
ADDR2_HOUSE_NUMBER("addr2:housenumber"), //$NON-NLS-1$
ADDR_HOUSE_NAME("addr:housename"), //$NON-NLS-1$
ADDR_STREET("addr:street"), //$NON-NLS-1$
ADDR_STREET2("addr:street2"), //$NON-NLS-1$
ADDR2_STREET("addr2:street"), //$NON-NLS-1$
ADDR_CITY("addr:city"), //$NON-NLS-1$
ADDR_PLACE("addr:place"), //$NON-NLS-1$
ADDR_POSTCODE("addr:postcode"), //$NON-NLS-1$

View file

@ -8,6 +8,9 @@ import java.util.Map;
public class RenderingRuleStorageProperties {
public static final String UI_CATEGORY_HIDDEN = "ui_hidden";
public static final String UI_CATEGORY_DETAILS = "details";
public static final String UI_CATEGORY_HIDE = "hide";
public static final String UI_CATEGORY_ROUTES = "routes";
public static final String A_ENGINE_V1 = "engine_v1";
public static final String A_APP_MODE= "appMode";
public static final String A_BASE_APP_MODE = "baseAppMode";

View file

@ -11,6 +11,7 @@ import java.util.PriorityQueue;
import net.osmand.PlatformUtil;
import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.util.MapUtils;
@ -138,7 +139,7 @@ public class BinaryRoutePlanner {
checkIfGraphIsEmpty(ctx, ctx.getPlanRoadDirection() >= 0, graphDirectSegments, start, visitedDirectSegments,
"Route is not found from selected start point.");
if (ctx.planRouteIn2Directions()) {
forwardSearch = (nonHeuristicSegmentsComparator.compare(graphDirectSegments.peek(), graphReverseSegments.peek()) < 0);
forwardSearch = nonHeuristicSegmentsComparator.compare(graphDirectSegments.peek(), graphReverseSegments.peek()) <= 0;
// if (graphDirectSegments.size() * 2 > graphReverseSegments.size()) {
// forwardSearch = false;
// } else if (graphDirectSegments.size() < 2 * graphReverseSegments.size()) {
@ -798,41 +799,40 @@ public class BinaryRoutePlanner {
" distToEnd=" + distanceToEnd +
" segmentPoint=" + segmentPoint + " -- ", next, true);
}
if (!visitedSegments.containsKey(calculateRoutePointId(next, next.isPositive()))) {
if (next.getParentRoute() == null
|| ctx.roadPriorityComparator(next.distanceFromStart, next.distanceToEnd,
distFromStart, distanceToEnd) > 0) {
next.distanceFromStart = distFromStart;
next.distanceToEnd = distanceToEnd;
if (TRACE_ROUTING) {
printRoad(" "+segmentPoint+">>" , next, null);
}
// put additional information to recover whole route after
next.setParentRoute(segment);
next.setParentSegmentEnd(segmentPoint);
graphSegments.add(next);
}
} else {
RouteSegment visIt = visitedSegments.get(calculateRoutePointId(next, next.isPositive()));
boolean toAdd = true;
if (visIt != null) {
// the segment was already visited! We need to follow better route if it exists
// that is very exceptional situation and almost exception, it can happen
// 1. when we underestimate distnceToEnd - wrong h()
// 2. because we process not small segments but the whole road, it could be that
// deviation from the road is faster than following the whole road itself!
if (distFromStart < next.distanceFromStart) {
if (TRACE_ROUTING) {
printRoad(">?", visitedSegments.get(calculateRoutePointId(next, next.isPositive())),
next.isPositive());
}
if (distFromStart < visIt.distanceFromStart && next.getParentRoute() == null) {
toAdd = true;
if (ctx.config.heuristicCoefficient <= 1) {
System.err.println("! Alert distance from start " + distFromStart + " < "
+ next.distanceFromStart + " id=" + next.road.id);
}
// A: we can't change parent route just here, because we need to update visitedSegments
// presumably we can do visitedSegments.put(calculateRoutePointId(next), next);
// next.distanceFromStart = distFromStart;
// next.setParentRoute(segment);
// next.setParentSegmentEnd(segmentPoint);
if (ctx.visitor != null) {
// ctx.visitor.visitSegment(next, false);
+ visIt.distanceFromStart + " id=" + next.road.id);
}
} else {
toAdd = false;
}
}
if (toAdd && (next.getParentRoute() == null || ctx.roadPriorityComparator(next.distanceFromStart,
next.distanceToEnd, distFromStart, distanceToEnd) > 0)) {
next.distanceFromStart = distFromStart;
next.distanceToEnd = distanceToEnd;
if (TRACE_ROUTING) {
printRoad(" " + segmentPoint + ">>", next, null);
}
// put additional information to recover whole route after
next.setParentRoute(segment);
next.setParentSegmentEnd(segmentPoint);
graphSegments.add(next);
}
}
}
@ -860,6 +860,12 @@ public class BinaryRoutePlanner {
public int preciseX;
public int preciseY;
public List<RouteSegmentPoint> others;
public LatLon getPreciseLatLon() {
return new LatLon(MapUtils.get31LatitudeY(preciseY), MapUtils.get31LongitudeX(preciseX));
}
}
public static class RouteSegment {

View file

@ -91,7 +91,7 @@ public class RoutePlannerFrontEnd {
}
if (road != null) {
if(!transportStop) {
float prio = ctx.getRouter().defineSpeedPriority(road.road);
float prio = Math.max(ctx.getRouter().defineSpeedPriority(road.road), 0.3f);
if (prio > 0) {
road.distSquare = (road.distSquare + GPS_POSSIBLE_ERROR * GPS_POSSIBLE_ERROR)
/ (prio * prio);
@ -234,6 +234,7 @@ public class RoutePlannerFrontEnd {
if (intermediates != null) {
for (LatLon l : intermediates) {
if (!addSegment(l, ctx, indexNotFound++, points, false)) {
System.out.println(points.get(points.size() - 1).getRoad().toString());
return null;
}
}
@ -242,9 +243,7 @@ public class RoutePlannerFrontEnd {
return null;
}
ctx.calculationProgress.nextIteration();
List<RouteSegmentResult> res = searchRoute(ctx, points, routeDirection);
// make start and end more precise
makeStartEndPointsPrecise(res, start, end, intermediates);
List<RouteSegmentResult> res = searchRouteImpl(ctx, points, routeDirection);
if (res != null) {
new RouteResultPreparation().printResults(ctx, start, end, res);
}
@ -255,33 +254,6 @@ public class RoutePlannerFrontEnd {
if (res.size() > 0) {
updateResult(res.get(0), start, true);
updateResult(res.get(res.size() - 1), end, false);
if (intermediates != null) {
int k = 1;
for (int i = 0; i < intermediates.size(); i++) {
LatLon ll = intermediates.get(i);
int px = MapUtils.get31TileNumberX(ll.getLongitude());
int py = MapUtils.get31TileNumberY(ll.getLatitude());
for (; k < res.size(); k++) {
double currentsDist = projectDistance(res, k, px, py);
if (currentsDist < 500 * 500) {
for (int k1 = k + 1; k1 < res.size(); k1++) {
double c2 = projectDistance(res, k1, px, py);
if (c2 < currentsDist) {
k = k1;
currentsDist = c2;
} else if (k1 - k > 15) {
break;
}
}
updateResult(res.get(k), ll, false);
if (k < res.size() - 1) {
updateResult(res.get(k + 1), ll, true);
}
break;
}
}
}
}
}
}
@ -300,7 +272,8 @@ public class RoutePlannerFrontEnd {
int py = MapUtils.get31TileNumberY(point.getLatitude());
int pind = st ? routeSegmentResult.getStartPointIndex() : routeSegmentResult.getEndPointIndex();
RouteDataObject r = routeSegmentResult.getObject();
RouteDataObject r = new RouteDataObject(routeSegmentResult.getObject());
routeSegmentResult.setObject(r);
QuadPoint before = null;
QuadPoint after = null;
if (pind > 0) {
@ -364,7 +337,7 @@ public class RoutePlannerFrontEnd {
ctx.calculationProgress.segmentNotFound = indexNotFound;
return false;
} else {
log.info("Route segment found " + f.getRoad().id + " " + f.getRoad().getName());
log.info("Route segment found " + f.road);
res.add(f);
return true;
}
@ -383,6 +356,10 @@ public class RoutePlannerFrontEnd {
ctx.precalculatedRouteDirection = routeDirection.adopt(ctx);
}
if (ctx.nativeLib != null) {
ctx.startX = start.preciseX;
ctx.startY = start.preciseY;
ctx.targetX = end.preciseX;
ctx.targetY = end.preciseY;
return runNativeRouting(ctx, recalculationEnd);
} else {
refreshProgressDistance(ctx);
@ -468,13 +445,18 @@ public class RoutePlannerFrontEnd {
}
private List<RouteSegmentResult> searchRoute(final RoutingContext ctx, List<RouteSegmentPoint> points, PrecalculatedRouteDirection routeDirection)
private List<RouteSegmentResult> searchRouteImpl(final RoutingContext ctx, List<RouteSegmentPoint> points, PrecalculatedRouteDirection routeDirection)
throws IOException, InterruptedException {
if (points.size() <= 2) {
// simple case 2 points only
if (!useSmartRouteRecalculation) {
ctx.previouslyCalculatedRoute = null;
}
return searchRoute(ctx, points.get(0), points.get(1), routeDirection);
pringGC(ctx, true);
List<RouteSegmentResult> res = searchRouteInternalPrepare(ctx, points.get(0), points.get(1), routeDirection);
pringGC(ctx, false);
makeStartEndPointsPrecise(res, points.get(0).getPreciseLatLon(), points.get(1).getPreciseLatLon(), null);
return res;
}
ArrayList<RouteSegmentResult> firstPartRecalculatedRoute = null;
@ -516,7 +498,7 @@ public class RoutePlannerFrontEnd {
local.visitor = ctx.visitor;
local.calculationProgress = ctx.calculationProgress;
List<RouteSegmentResult> res = searchRouteInternalPrepare(local, points.get(i), points.get(i + 1), routeDirection);
makeStartEndPointsPrecise(res, points.get(i).getPreciseLatLon(), points.get(i + 1).getPreciseLatLon(), null);
results.addAll(res);
ctx.distinctLoadedTiles += local.distinctLoadedTiles;
ctx.loadedTiles += local.loadedTiles;
@ -539,27 +521,22 @@ public class RoutePlannerFrontEnd {
}
@SuppressWarnings("static-access")
private List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegmentPoint start, RouteSegmentPoint end,
PrecalculatedRouteDirection routeDirection) throws IOException, InterruptedException {
if (ctx.SHOW_GC_SIZE) {
long h1 = ctx.runGCUsedMemory();
private void pringGC(final RoutingContext ctx, boolean before) {
if (RoutingContext.SHOW_GC_SIZE && before) {
long h1 = RoutingContext.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Used before routing " + h1 / mb + " actual");
}
List<RouteSegmentResult> result = searchRouteInternalPrepare(ctx, start, end, routeDirection);
if (RoutingContext.SHOW_GC_SIZE) {
} else if (RoutingContext.SHOW_GC_SIZE && !before) {
int sz = ctx.global.size;
log.warn("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.indexedSubregions.size());
ctx.runGCUsedMemory();
long h1 = ctx.runGCUsedMemory();
RoutingContext.runGCUsedMemory();
long h1 = RoutingContext.runGCUsedMemory();
ctx.unloadAllData();
ctx.runGCUsedMemory();
long h2 = ctx.runGCUsedMemory();
RoutingContext.runGCUsedMemory();
long h2 = RoutingContext.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual");
}
return result;
}

View file

@ -1,5 +1,26 @@
package net.osmand.router;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.hash.TIntHashSet;
import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
@ -18,26 +39,6 @@ import net.osmand.util.Algorithms;
import net.osmand.util.MapAlgorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.hash.TIntHashSet;
public class RouteResultPreparation {
public static boolean PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = false;
@ -395,7 +396,6 @@ public class RouteResultPreparation {
}
// reverse it just to attach good direction roads
Collections.reverse(result);
segment = finalSegment.reverseWaySearch ? finalSegment.opposite.getParentRoute() : finalSegment;
int parentSegmentEnd = finalSegment.reverseWaySearch ? finalSegment.opposite.getParentSegmentEnd() : finalSegment.opposite.getSegmentStart();
parentRoutingTime = -1;
@ -622,7 +622,7 @@ public class RouteResultPreparation {
// calculateStatistics(result);
}
private void calculateStatistics(List<RouteSegmentResult> result) {
protected void calculateStatistics(List<RouteSegmentResult> result) {
InputStream is = RenderingRulesStorage.class.getResourceAsStream("default.render.xml");
final Map<String, String> renderingConstants = new LinkedHashMap<String, String>();
try {
@ -799,13 +799,22 @@ public class RouteResultPreparation {
}
if (dist < mergeDistance) {
mergeTurnLanes(leftside, currentSegment, nextSegment);
inferCommonActiveLane(currentSegment.getTurnType(), nextSegment.getTurnType());
TurnType turnType = currentSegment.getTurnType();
Integer[] possibleTurn = getPossibleTurnsFromActiveLanes(turnType.getLanes(), true);
if (possibleTurn.length == 1) {
TurnType tt = TurnType.valueOf(possibleTurn[0], currentSegment.getTurnType().isLeftSide());
tt.setLanes(turnType.getLanes());
tt.setSkipToSpeak(turnType.isSkipToSpeak());
currentSegment.setTurnType(tt);
turnType = tt;
}
inferCommonActiveLane(turnType, nextSegment.getTurnType());
merged = true;
}
}
if (!merged) {
TurnType tt = currentSegment.getTurnType();
inferActiveTurnLanesFromTurn(tt, TurnType.C);
inferActiveTurnLanesFromTurn(tt, tt.getValue());
}
nextSegment = currentSegment;
dist = 0;
@ -983,11 +992,9 @@ public class RouteResultPreparation {
if(turnSet.size() == 1) {
singleTurn = turnSet.iterator().next();
} else if(currentTurn.goAhead() && turnSet.contains(nextTurn.getValue())) {
if(currentTurn.isPossibleLeftTurn() &&
TurnType.isLeftTurn(nextTurn.getValue())) {
if (currentTurn.isPossibleLeftTurn() && TurnType.isLeftTurn(nextTurn.getValue())) {
singleTurn = nextTurn.getValue();
} else if(currentTurn.isPossibleLeftTurn() &&
TurnType.isLeftTurn(nextTurn.getActiveCommonLaneTurn())) {
} else if (currentTurn.isPossibleLeftTurn() && TurnType.isLeftTurn(nextTurn.getActiveCommonLaneTurn())) {
singleTurn = nextTurn.getActiveCommonLaneTurn();
} else if(currentTurn.isPossibleRightTurn() &&
TurnType.isRightTurn(nextTurn.getValue())) {
@ -1053,7 +1060,7 @@ public class RouteResultPreparation {
// add description about turn
double mpi = MapUtils.degreesDiff(prev.getBearingEnd(), rr.getBearingBegin());
if(noAttachedRoads){
// TODO VICTOR : look at the comment inside direction route
// VICTOR : look at the comment inside direction route
// ? avoid small zigzags is covered at (search for "zigzags")
// double begin = rr.getObject().directionRoute(rr.getStartPointIndex(), rr.getStartPointIndex() <
// rr.getEndPointIndex(), 25);
@ -1262,23 +1269,12 @@ public class RouteResultPreparation {
}
}
t.setPossibleLeftTurn(possiblyLeftTurn);
t.setPossibleRightTurn(possiblyRightTurn);
if (rs.keepLeft || rs.keepRight) {
String[] splitLaneOptions = turnLanes.split("\\|", -1);
int activeBeginIndex = findActiveIndex(rawLanes, splitLaneOptions, rs.leftLanes, true,
rs.leftLanesInfo, rs.roadsOnLeft, rs.addRoadsOnLeft);
if(!rs.keepLeft && activeBeginIndex != -1 &&
splitLaneOptions.length > 0 && !splitLaneOptions[splitLaneOptions.length - 1].contains(";")) {
activeBeginIndex = Math.max(activeBeginIndex, 1);
}
int activeEndIndex = findActiveIndex(rawLanes, splitLaneOptions, rs.rightLanes, false,
rs.rightLanesInfo, rs.roadsOnRight, rs.addRoadsOnRight);
if(!rs.keepRight && activeEndIndex != -1 &&
splitLaneOptions.length > 0 && !splitLaneOptions[0].contains(";") ) {
activeEndIndex = Math.min(activeEndIndex, rawLanes.length - 1);
}
if (activeBeginIndex == -1 || activeEndIndex == -1 || activeBeginIndex > activeEndIndex) {
// something went wrong
return createSimpleKeepLeftRightTurn(leftSide, prevSegm, currentSegm, rs);
@ -1288,36 +1284,65 @@ public class RouteResultPreparation {
rawLanes[k] |= 1;
}
}
int tp = inferSlightTurnFromLanes(rawLanes, rs);
int tp = inferSlightTurnFromActiveLanes(rawLanes, rs.keepLeft, rs.keepRight);
// Checking to see that there is only one unique turn
if (tp != 0) {
// add extra lanes with same turn
for(int i = 0; i < rawLanes.length; i++) {
if(TurnType.getSecondaryTurn(rawLanes[i]) == tp) {
TurnType.setSecondaryToPrimary(rawLanes, i);
rawLanes[i] |= 1;
} else if(TurnType.getPrimaryTurn(rawLanes[i]) == tp) {
rawLanes[i] |= 1;
}
}
}
if (tp != t.getValue() && tp != 0) {
t = TurnType.valueOf(tp, leftSide);
} else {
if (rs.keepRight && TurnType.getSecondaryTurn(rawLanes[activeEndIndex]) == 0) {
t = TurnType.valueOf(TurnType.getPrimaryTurn(rawLanes[activeEndIndex]), leftSide);
} else if (rs.keepLeft && TurnType.getSecondaryTurn(rawLanes[activeBeginIndex]) == 0) {
t = TurnType.valueOf(TurnType.getPrimaryTurn(rawLanes[activeBeginIndex]), leftSide);
}
}
} else {
// case for go straight and identify correct turn:lane to go straight
Integer[] possibleTurns = getPossibleTurns(rawLanes, false, false);
int tp = TurnType.C;
if (possibleTurns.length == 1) {
tp = possibleTurns[0];
} else if (possibleTurns.length == 3) {
if ((!possiblyLeftTurn || !possiblyRightTurn) && TurnType.isSlightTurn(possibleTurns[1])) {
tp = possibleTurns[1];
t = TurnType.valueOf(tp, leftSide);
}
}
for (int k = 0; k < rawLanes.length; k++) {
int turn = TurnType.getPrimaryTurn(rawLanes[k]);
int sturn = TurnType.getSecondaryTurn(rawLanes[k]);
int tturn = TurnType.getTertiaryTurn(rawLanes[k]);
boolean active = false;
// some turns go through many segments (to turn right or left)
// so on one first segment the lane could be available and may be only 1 possible
// all undesired lanes will be disabled through the 2nd pass
if((TurnType.isRightTurn(sturn) && possiblyRightTurn) ||
(TurnType.isLeftTurn(sturn) && possiblyLeftTurn)) {
if ((TurnType.isRightTurn(sturn) && possiblyRightTurn)
|| (TurnType.isLeftTurn(sturn) && possiblyLeftTurn)) {
// we can't predict here whether it will be a left turn or straight on,
// it could be done during 2nd pass
TurnType.setPrimaryTurn(rawLanes, k, sturn);
TurnType.setSecondaryTurn(rawLanes, k, turn);
TurnType.setSecondaryToPrimary(rawLanes, k);
active = true;
} else if((TurnType.isRightTurn(tturn) && possiblyRightTurn) ||
(TurnType.isLeftTurn(tturn) && possiblyLeftTurn)) {
TurnType.setPrimaryTurn(rawLanes, k, tturn);
TurnType.setTertiaryTurn(rawLanes, k, turn);
} else if ((TurnType.isRightTurn(tturn) && possiblyRightTurn)
|| (TurnType.isLeftTurn(tturn) && possiblyLeftTurn)) {
TurnType.setTertiaryToPrimary(rawLanes, k);
active = true;
} else if((TurnType.isRightTurn(turn) && possiblyRightTurn) ||
(TurnType.isLeftTurn(turn) && possiblyLeftTurn)) {
} else if ((TurnType.isRightTurn(turn) && possiblyRightTurn)
|| (TurnType.isLeftTurn(turn) && possiblyLeftTurn)) {
active = true;
} else if (turn == TurnType.C) {
// } else if (turn == TurnType.C) {
} else if (turn == tp) {
active = true;
}
if (active) {
@ -1327,6 +1352,8 @@ public class RouteResultPreparation {
}
t.setSkipToSpeak(!rs.speak);
t.setLanes(rawLanes);
t.setPossibleLeftTurn(possiblyLeftTurn);
t.setPossibleRightTurn(possiblyRightTurn);
return t;
}
@ -1569,10 +1596,8 @@ public class RouteResultPreparation {
int[] lanes = new int[splitLaneOptions.length];
for (int i = 0; i < splitLaneOptions.length; i++) {
String[] laneOptions = splitLaneOptions[i].split(";");
boolean isTertiaryTurn = false;
for (int j = 0; j < laneOptions.length; j++) {
int turn = TurnType.convertType(laneOptions[j]);
final int primary = TurnType.getPrimaryTurn(lanes[i]);
if (primary == 0) {
TurnType.setPrimaryTurnAndReset(lanes, i, turn);
@ -1582,12 +1607,12 @@ public class RouteResultPreparation {
(TurnType.isLeftTurn(calcTurnType) && TurnType.isLeftTurn(turn))
) {
TurnType.setPrimaryTurnShiftOthers(lanes, i, turn);
} else if (!isTertiaryTurn) {
TurnType.setSecondaryTurnShiftOthers(lanes, i, turn);
isTertiaryTurn = true;
} else {
} else if (TurnType.getSecondaryTurn(lanes[i]) == 0) {
TurnType.setSecondaryTurn(lanes, i, turn);
} else if (TurnType.getTertiaryTurn(lanes[i]) == 0) {
TurnType.setTertiaryTurn(lanes, i, turn);
break;
} else {
// ignore
}
}
}
@ -1595,96 +1620,90 @@ public class RouteResultPreparation {
return lanes;
}
private int inferSlightTurnFromLanes(int[] oLanes, RoadSplitStructure rs) {
TIntHashSet possibleTurns = new TIntHashSet();
for (int i = 0; i < oLanes.length; i++) {
if ((oLanes[i] & 1) == 0) {
continue;
}
if (possibleTurns.isEmpty()) {
// Nothing is in the list to compare to, so add the first elements
possibleTurns.add(TurnType.getPrimaryTurn(oLanes[i]));
if (TurnType.getSecondaryTurn(oLanes[i]) != 0) {
possibleTurns.add(TurnType.getSecondaryTurn(oLanes[i]));
}
if (TurnType.getTertiaryTurn(oLanes[i]) != 0) {
possibleTurns.add(TurnType.getTertiaryTurn(oLanes[i]));
}
} else {
TIntArrayList laneTurns = new TIntArrayList();
laneTurns.add(TurnType.getPrimaryTurn(oLanes[i]));
if (TurnType.getSecondaryTurn(oLanes[i]) != 0) {
laneTurns.add(TurnType.getSecondaryTurn(oLanes[i]));
}
if (TurnType.getTertiaryTurn(oLanes[i]) != 0) {
laneTurns.add(TurnType.getTertiaryTurn(oLanes[i]));
}
possibleTurns.retainAll(laneTurns);
if (possibleTurns.isEmpty()) {
// No common turns, so can't determine anything.
return 0;
}
}
}
// Remove all turns from lanes not selected...because those aren't it
private int inferSlightTurnFromActiveLanes(int[] oLanes, boolean mostLeft, boolean mostRight) {
Integer[] possibleTurns = getPossibleTurns(oLanes, false, true);
if (possibleTurns.length == 0) {
// No common turns, so can't determine anything.
return 0;
}
int infer = 0;
if (possibleTurns.length == 1) {
infer = possibleTurns[0];
} else {
if (mostLeft && !mostRight) {
infer = possibleTurns[0];
} else if(mostRight && !mostLeft) {
infer = possibleTurns[possibleTurns.length - 1];
} else {
infer = possibleTurns[1];
// infer = TurnType.C;
}
}
return infer;
}
private Integer[] getPossibleTurnsFromActiveLanes(int[] oLanes, boolean onlyPrimary) {
return getPossibleTurns(oLanes, onlyPrimary, true);
}
private Integer[] getPossibleTurns(int[] oLanes, boolean onlyPrimary, boolean uniqueFromActive) {
Set<Integer> possibleTurns = new LinkedHashSet<>();
Set<Integer> upossibleTurns = new LinkedHashSet<>();
for (int i = 0; i < oLanes.length; i++) {
if ((oLanes[i] & 1) == 0 && !possibleTurns.isEmpty()) {
possibleTurns.remove((Integer) TurnType.getPrimaryTurn(oLanes[i]));
if (TurnType.getSecondaryTurn(oLanes[i]) != 0) {
possibleTurns.remove((Integer) TurnType.getSecondaryTurn(oLanes[i]));
}
if (TurnType.getTertiaryTurn(oLanes[i]) != 0) {
possibleTurns.remove((Integer) TurnType.getTertiaryTurn(oLanes[i]));
// Nothing is in the list to compare to, so add the first elements
upossibleTurns.clear();
upossibleTurns.add(TurnType.getPrimaryTurn(oLanes[i]));
if (!onlyPrimary && TurnType.getSecondaryTurn(oLanes[i]) != 0) {
upossibleTurns.add(TurnType.getSecondaryTurn(oLanes[i]));
}
if (!onlyPrimary && TurnType.getTertiaryTurn(oLanes[i]) != 0) {
upossibleTurns.add(TurnType.getTertiaryTurn(oLanes[i]));
}
if (!uniqueFromActive) {
possibleTurns.addAll(upossibleTurns);
// if (!possibleTurns.isEmpty()) {
// possibleTurns.retainAll(upossibleTurns);
// if(possibleTurns.isEmpty()) {
// break;
// }
// } else {
// possibleTurns.addAll(upossibleTurns);
// }
} else if ((oLanes[i] & 1) == 1) {
if (!possibleTurns.isEmpty()) {
possibleTurns.retainAll(upossibleTurns);
if(possibleTurns.isEmpty()) {
break;
}
} else {
possibleTurns.addAll(upossibleTurns);
}
}
}
// remove all non-slight turns // TEST don't pass
// if(possibleTurns.size() > 1) {
// TIntIterator it = possibleTurns.iterator();
// while(it.hasNext()) {
// int nxt = it.next();
// if(!TurnType.isSlightTurn(nxt)) {
// it.remove();
// }
// }
// }
int infer = 0;
if (possibleTurns.size() == 1) {
infer = possibleTurns.iterator().next();
} else if (possibleTurns.size() > 1) {
if (rs.keepLeft && rs.keepRight && possibleTurns.contains(TurnType.C)) {
infer = TurnType.C;
} else if (rs.keepLeft || rs.keepRight) {
TIntIterator it = possibleTurns.iterator();
infer = it.next();
while(it.hasNext()) {
int next = it.next();
int orderInfer = TurnType.orderFromLeftToRight(infer);
int orderNext = TurnType.orderFromLeftToRight(next) ;
if(rs.keepLeft && orderNext < orderInfer) {
infer = next;
} else if(rs.keepRight && orderNext > orderInfer) {
infer = next;
// Remove all turns from lanes not selected...because those aren't it
if (uniqueFromActive) {
for (int i = 0; i < oLanes.length; i++) {
if ((oLanes[i] & 1) == 0) {
possibleTurns.remove((Integer) TurnType.getPrimaryTurn(oLanes[i]));
if (TurnType.getSecondaryTurn(oLanes[i]) != 0) {
possibleTurns.remove((Integer) TurnType.getSecondaryTurn(oLanes[i]));
}
if (TurnType.getTertiaryTurn(oLanes[i]) != 0) {
possibleTurns.remove((Integer) TurnType.getTertiaryTurn(oLanes[i]));
}
}
}
}
Integer[] array = possibleTurns.toArray(new Integer[possibleTurns.size()]);
Arrays.sort(array, new Comparator<Integer>() {
// Checking to see that there is only one unique turn
if (infer != 0) {
for(int i = 0; i < oLanes.length; i++) {
if(TurnType.getSecondaryTurn(oLanes[i]) == infer) {
int pt = TurnType.getPrimaryTurn(oLanes[i]);
int en = oLanes[i] & 1;
TurnType.setPrimaryTurnAndReset(oLanes, i, infer);
oLanes[i] |= en;
TurnType.setSecondaryTurn(oLanes, i, pt);
}
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(TurnType.orderFromLeftToRight(o1), TurnType.orderFromLeftToRight(o2));
}
}
return infer;
});
return array;
}
private boolean isMotorway(RouteSegmentResult s){
@ -1721,7 +1740,7 @@ public class RouteResultPreparation {
}
}
Iterator<RouteSegment> it;
if(rr.getPreAttachedRoutes(pointInd) != null) {
if (rr.getPreAttachedRoutes(pointInd) != null) {
final RouteSegmentResult[] list = rr.getPreAttachedRoutes(pointInd);
it = new Iterator<BinaryRoutePlanner.RouteSegment>() {
int i = 0;
@ -1740,7 +1759,7 @@ public class RouteResultPreparation {
public void remove() {
}
};
} else if (recalculation) {
} else if (recalculation || ctx.nativeLib == null) {
RouteSegment rt = ctx.loadRouteSegment(road.getPoint31XTile(pointInd), road.getPoint31YTile(pointInd), ctx.config.memoryLimitation);
it = rt == null ? null : rt.getIterator();
} else {
@ -1753,7 +1772,7 @@ public class RouteResultPreparation {
if (routeSegment.road.getId() != road.getId() && routeSegment.road.getId() != previousRoadId) {
RouteDataObject addRoad = routeSegment.road;
checkAndInitRouteRegion(ctx, addRoad);
// TODO restrictions can be considered as well
// Future: restrictions can be considered as well
int oneWay = ctx.getRouter().isOneWay(addRoad);
if (oneWay >= 0 && routeSegment.getSegmentStart() < addRoad.getPointsLength() - 1) {
long pointL = getPoint(addRoad, routeSegment.getSegmentStart() + 1);

View file

@ -21,7 +21,9 @@ import gnu.trove.map.hash.TIntObjectHashMap;
public class RouteSegmentResult implements StringExternalizable<RouteDataBundle> {
private final RouteDataObject object;
// this should be bigger (50-80m) but tests need to be fixed first
private static final float DIST_BEARING_DETECT = 5;
private RouteDataObject object;
private int startPointIndex;
private int endPointIndex;
private List<RouteSegmentResult>[] attachedRoutes;
@ -403,7 +405,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
}
public void copyPreattachedRoutes(RouteSegmentResult toCopy, int shift) {
if(toCopy.preAttachedRoutes != null) {
if (toCopy.preAttachedRoutes != null) {
int l = toCopy.preAttachedRoutes.length - shift;
preAttachedRoutes = new RouteSegmentResult[l][];
System.arraycopy(toCopy.preAttachedRoutes, shift, preAttachedRoutes, 0, l);
@ -412,7 +414,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
public RouteSegmentResult[] getPreAttachedRoutes(int routeInd) {
int st = Math.abs(routeInd - startPointIndex);
if(preAttachedRoutes != null && st < preAttachedRoutes.length) {
if (preAttachedRoutes != null && st < preAttachedRoutes.length) {
return preAttachedRoutes[st];
}
return null;
@ -421,7 +423,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
public List<RouteSegmentResult> getAttachedRoutes(int routeInd) {
int st = Math.abs(routeInd - startPointIndex);
List<RouteSegmentResult> list = attachedRoutes[st];
if(list == null) {
if (list == null) {
return Collections.emptyList();
}
return list;
@ -444,11 +446,11 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
}
public float getBearingBegin() {
return (float) (object.directionRoute(startPointIndex, startPointIndex < endPointIndex) / Math.PI * 180);
return (float) (object.directionRoute(startPointIndex, startPointIndex < endPointIndex, DIST_BEARING_DETECT) / Math.PI * 180);
}
public float getBearing(int point, boolean plus) {
return (float) (object.directionRoute(point, plus) / Math.PI * 180);
return (float) (object.directionRoute(point, plus, DIST_BEARING_DETECT) / Math.PI * 180);
}
public float getDistance(int point, boolean plus) {
@ -456,7 +458,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
}
public float getBearingEnd() {
return (float) (MapUtils.alignAngleDifference(object.directionRoute(endPointIndex, startPointIndex > endPointIndex) - Math.PI) / Math.PI * 180);
return (float) (MapUtils.alignAngleDifference(object.directionRoute(endPointIndex, startPointIndex > endPointIndex, DIST_BEARING_DETECT) - Math.PI) / Math.PI * 180);
}
public void setSegmentTime(float segmentTime) {
@ -534,9 +536,15 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
this.description = description;
}
public void setObject(RouteDataObject r) {
this.object = r;
}
@Override
public String toString() {
return object.toString() + ": " + startPointIndex + "-" + endPointIndex;
}
}

View file

@ -36,7 +36,7 @@ import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
public class RoutingContext {
public static final boolean SHOW_GC_SIZE = false;
public static boolean SHOW_GC_SIZE = false;
private final static Log log = PlatformUtil.getLog(RoutingContext.class);
@ -436,7 +436,7 @@ public class RoutingContext {
}
TLongIterator it = ts.iterator();
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
while(it.hasNext()){
while (it.hasNext()) {
getAllObjects(it.next(), toFillIn, excludeDuplications);
}
timeToFindInitialSegments += (System.nanoTime() - now);
@ -467,15 +467,14 @@ public class RoutingContext {
long h2 = runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload tiles : estimated " + (sz1 - sz2) / mb + " ?= " + (h1 - h2) / mb + " actual");
log.warn("Used after " + h2 / mb + " of " + Runtime.getRuntime().totalMemory() / mb + " max "
+ maxMemory() / mb);
log.warn("Used after " + h2 / mb + " of " + Runtime.getRuntime().totalMemory() / mb );
} else {
float mb = (1 << 20);
int sz2 = getCurrentEstimatedSize();
log.warn("Unload tiles : occupied before " + sz1 / mb + " Mb - now " + sz2 / mb + "MB "
+ memoryLimit / mb + " limit MB " + config.memoryLimitation / mb);
long us2 = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
log.warn("Used memory before " + us1 / mb + "after " + us1 / mb + " of max " + maxMemory() / mb);
log.warn("Used memory before " + us1 / mb + "after " + us1 / mb );
}
}
if (!indexedSubregions.containsKey(tileId)) {
@ -507,12 +506,6 @@ public class RoutingContext {
return tileId;
}
private long maxMemory() {
// AVIAN FIXME
// return Runtime.getRuntime().maxMemory();
return 0;
}
public boolean checkIfMemoryLimitCritical(long memoryLimit) {

View file

@ -23,7 +23,7 @@ import net.osmand.osm.edit.Way;
import net.osmand.util.MapUtils;
public class TransportStopsRouteReader {
public static final int MISSING_STOP_SEARCH_RADIUS = 15000;
public static final int MISSING_STOP_SEARCH_RADIUS = 50000;
TLongObjectHashMap<TransportRoute> combinedRoutesCache = new TLongObjectHashMap<TransportRoute>();
Map<BinaryMapIndexReader, TIntObjectHashMap<TransportRoute>> routesFilesCache = new LinkedHashMap<BinaryMapIndexReader,
TIntObjectHashMap<TransportRoute>>();
@ -128,6 +128,7 @@ public class TransportStopsRouteReader {
}
}
}
return routesToLoad;
}

View file

@ -210,16 +210,25 @@ public class TurnType {
public static void setPrimaryTurnShiftOthers(int[] lanes, int lane, int turnType) {
int pt = getPrimaryTurn(lanes[lane]);
int st = getSecondaryTurn(lanes[lane]);
//int tt = getTertiaryTurn(lanes[lane]);
//int tt = getTertiaryTurn(lanes[lane]); is lost here
setPrimaryTurnAndReset(lanes, lane, turnType);
setSecondaryTurn(lanes, lane, pt);
setTertiaryTurn(lanes, lane, st);
}
public static void setSecondaryTurnShiftOthers(int[] lanes, int lane, int turnType) {
public static void setSecondaryToPrimary(int[] lanes, int lane) {
int st = getSecondaryTurn(lanes[lane]);
//int tt = getTertiaryTurn(lanes[lane]);
setSecondaryTurn(lanes, lane, turnType);
int pt = getPrimaryTurn(lanes[lane]);
setPrimaryTurn(lanes, lane, st);
setSecondaryTurn(lanes, lane, pt);
}
public static void setTertiaryToPrimary(int[] lanes, int lane) {
int st = getSecondaryTurn(lanes[lane]);
int pt = getPrimaryTurn(lanes[lane]);
int tt = getTertiaryTurn(lanes[lane]);
setPrimaryTurn(lanes, lane, tt);
setSecondaryTurn(lanes, lane, pt);
setTertiaryTurn(lanes, lane, st);
}

View file

@ -516,7 +516,7 @@ public class SearchUICore {
}
currentSearchResult = collection;
if (phrase.getSettings().isExportObjects()) {
//rm.createTestJSON(collection);
rm.createTestJSON(collection);
}
rm.searchFinished(phrase);
if (onResultsComplete != null) {

View file

@ -35,6 +35,7 @@ import net.osmand.util.MapUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@ -140,10 +141,16 @@ public class SearchCoreFactory {
protected void subSearchApiOrPublish(SearchPhrase phrase, SearchResultMatcher resultMatcher, SearchResult res, SearchBaseAPI api)
throws IOException {
subSearchApiOrPublish(phrase, resultMatcher, res, api, true);
}
protected void subSearchApiOrPublish(SearchPhrase phrase, SearchResultMatcher resultMatcher, SearchResult res, SearchBaseAPI api,
boolean publish)
throws IOException {
phrase.countUnknownWordsMatchMainResult(res);
boolean firstUnknownWordMatches = res.firstUnknownWordMatches;
List<String> leftUnknownSearchWords = new ArrayList<String>(phrase.getUnknownSearchWords());
if(res.otherWordsMatch != null) {
if (res.otherWordsMatch != null) {
leftUnknownSearchWords.removeAll(res.otherWordsMatch);
}
SearchResult newParentSearchResult = null;
@ -187,19 +194,25 @@ public class SearchCoreFactory {
leftUnknownSearchWords.add(0, phrase.getFirstUnknownSearchWord());
}
// publish result to set parentSearchResult before search
if(newParentSearchResult != null) {
SearchResult prev = resultMatcher.setParentSearchResult(newParentSearchResult);
resultMatcher.publish(res);
resultMatcher.setParentSearchResult(prev);
} else {
resultMatcher.publish(res);
if (publish) {
if (newParentSearchResult != null) {
SearchResult prev = resultMatcher.setParentSearchResult(newParentSearchResult);
resultMatcher.publish(res);
resultMatcher.setParentSearchResult(prev);
} else {
resultMatcher.publish(res);
}
}
if (!leftUnknownSearchWords.isEmpty() && api != null && api.isSearchAvailable(phrase)) {
SearchPhrase nphrase = phrase.selectWord(res, leftUnknownSearchWords, phrase.isLastUnknownSearchWordComplete());
SearchResult prev = resultMatcher.setParentSearchResult(res);
SearchPhrase nphrase = phrase.selectWord(res, leftUnknownSearchWords,
phrase.isLastUnknownSearchWordComplete() ||
!leftUnknownSearchWords.contains(phrase.getLastUnknownSearchWord()));
SearchResult prev = resultMatcher.setParentSearchResult(publish ? res :
resultMatcher.getParentSearchResult());
api.search(nphrase, resultMatcher);
resultMatcher.setParentSearchResult(prev);
}
}
@Override
@ -387,9 +400,6 @@ public class SearchCoreFactory {
int limit = 0;
@Override
public boolean publish(MapObject object) {
if (phrase.getSettings().isExportObjects()) {
resultMatcher.exportObject(phrase, object);
}
if (isCancelled()) {
return false;
}
@ -414,7 +424,8 @@ public class SearchCoreFactory {
if (object.getName().startsWith("<")) {
return false;
}
if (!phrase.getFirstUnknownNameStringMatcher().matches(stripBraces(sr.localeName))) {
if (!phrase.getUnknownWordToSearchBuildingNameMatcher().matches(stripBraces(sr.localeName))) {
sr.priorityDistance = 5;
}
sr.objectType = ObjectType.STREET;
@ -481,6 +492,23 @@ public class SearchCoreFactory {
resultMatcher.isCancelled();
}
};
ResultMatcher<MapObject> rawDataCollector = null;
if (phrase.getSettings().isExportObjects()) {
rawDataCollector = new ResultMatcher<MapObject>() {
@Override
public boolean publish(MapObject object) {
resultMatcher.exportObject(phrase, object);
return true;
}
@Override
public boolean isCancelled() {
return false;
}
};
}
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getRadiusOfflineIndexes(DEFAULT_ADDRESS_BBOX_RADIUS * 5,
SearchPhraseDataType.ADDRESS);
String wordToSearch = phrase.getUnknownWordToSearch();
@ -488,7 +516,7 @@ public class SearchCoreFactory {
BinaryMapIndexReader r = offlineIterator.next();
currentFile[0] = r;
immediateResults.clear();
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, wordToSearch.toLowerCase(),
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, rawDataCollector, wordToSearch.toLowerCase(),
phrase.isMainUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE
: StringMatcherMode.CHECK_STARTS_FROM_SPACE);
if (locSpecified) {
@ -538,6 +566,22 @@ public class SearchCoreFactory {
final NameStringMatcher nm = phrase.getMainUnknownNameStringMatcher();
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
final Set<String> ids = new HashSet<String>();
ResultMatcher<Amenity> rawDataCollector = null;
if (phrase.getSettings().isExportObjects()) {
rawDataCollector = new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity object) {
resultMatcher.exportObject(phrase, object);
return true;
}
@Override
public boolean isCancelled() {
return false;
}
};
}
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest((int) bbox.centerX(),
(int) bbox.centerY(), searchWord, (int) bbox.left, (int) bbox.right, (int) bbox.top,
(int) bbox.bottom, new ResultMatcher<Amenity>() {
@ -545,9 +589,6 @@ public class SearchCoreFactory {
@Override
public boolean publish(Amenity object) {
if (phrase.getSettings().isExportObjects()) {
resultMatcher.exportObject(phrase, object);
}
if (limit++ > LIMIT) {
return false;
}
@ -587,7 +628,7 @@ public class SearchCoreFactory {
public boolean isCancelled() {
return resultMatcher.isCancelled() && (limit < LIMIT);
}
});
}, rawDataCollector);
while (offlineIterator.hasNext()) {
BinaryMapIndexReader r = offlineIterator.next();
@ -630,6 +671,11 @@ public class SearchCoreFactory {
}
}
protected static class PoiTypeResult {
public AbstractPoiType pt;
public Set<String> foundWords = new LinkedHashSet<String>();
}
public static class SearchAmenityTypesAPI extends SearchBaseAPI {
public final static String STD_POI_FILTER_PREFIX = "std_";
@ -664,68 +710,102 @@ public class SearchCoreFactory {
}
}
public Map<AbstractPoiType, List<String>> getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) {
Map<AbstractPoiType, List<String>> results = new LinkedHashMap<>();
public Map<String, PoiTypeResult> getPoiTypeResults(NameStringMatcher nm, NameStringMatcher nmAdditional) {
Map<String, PoiTypeResult> results = new LinkedHashMap<>();
for (AbstractPoiType pf : topVisibleFilters) {
checkPoiType(nm, pf, results);
PoiTypeResult res = checkPoiType(nm, pf);
if(res != null) {
results.put(res.pt.getKeyName(), res);
}
}
if (nmAdditional != null) {
addAditonals(nmAdditional, results, types.getOtherMapCategory());
}
for (PoiCategory c : categories) {
checkPoiType(nm, c, results);
PoiTypeResult res = checkPoiType(nm, c);
if(res != null) {
results.put(res.pt.getKeyName(), res);
}
if (nmAdditional != null) {
addAditonals(nmAdditional, results, c);
}
}
Iterator<Entry<String, PoiType>> it = translatedNames.entrySet().iterator();
while (it.hasNext()) {
Entry<String, PoiType> e = it.next();
PoiType pt = e.getValue();
if (pt.getCategory() != types.getOtherMapCategory()) {
checkPoiType(nm, pt, results);
List<PoiType> additionals = pt.getPoiAdditionals();
if (additionals != null && includeAdditionals) {
for (PoiType a : additionals) {
if (!results.containsKey(a)) {
String enTranslation = a.getEnTranslation().toLowerCase();
if (!"yes".equals(enTranslation) && !"no".equals(enTranslation)) {
checkPoiType(nm, a, results);
}
}
}
if (pt.getCategory() != types.getOtherMapCategory() && !pt.isReference()) {
PoiTypeResult res = checkPoiType(nm, pt);
if(res != null) {
results.put(res.pt.getKeyName(), res);
}
if (nmAdditional != null) {
addAditonals(nmAdditional, results, pt);
}
}
}
return results;
}
private void checkPoiType(NameStringMatcher nm, AbstractPoiType pf, Map<AbstractPoiType, List<String>> results) {
List<String> lst = results.get(pf);
boolean nl = lst == null;
private void addAditonals(NameStringMatcher nm, Map<String, PoiTypeResult> results, AbstractPoiType pt) {
List<PoiType> additionals = pt.getPoiAdditionals();
if (additionals != null) {
for (PoiType a : additionals) {
PoiTypeResult existingResult = results.get(a.getKeyName());
if (existingResult != null) {
PoiAdditionalCustomFilter f ;
if (existingResult.pt instanceof PoiAdditionalCustomFilter) {
f = (PoiAdditionalCustomFilter) existingResult.pt;
} else {
f = new PoiAdditionalCustomFilter(types, (PoiType) existingResult.pt);
}
f.additionalPoiTypes.add(a);
existingResult.pt = f;
} else {
String enTranslation = a.getEnTranslation().toLowerCase();
if (!"no".equals(enTranslation) // && !"yes".equals(enTranslation)
) {
PoiTypeResult ptr = checkPoiType(nm, a);
if (ptr != null) {
results.put(a.getKeyName(), ptr);
}
}
}
}
}
}
private PoiTypeResult checkPoiType(NameStringMatcher nm, AbstractPoiType pf) {
PoiTypeResult res = null;
if (nm.matches(pf.getTranslation())) {
lst = addToList(pf.getTranslation(), lst);
res = addIfMatch(nm, pf.getTranslation(), pf, res);
}
if (nm.matches(pf.getEnTranslation())) {
lst = addToList(pf.getEnTranslation(), lst);
res = addIfMatch(nm, pf.getEnTranslation(), pf, res);
}
if (nm.matches(pf.getKeyName())) {
lst = addToList(pf.getKeyName().replace('_', ' '), lst);
res = addIfMatch(nm, pf.getKeyName().replace('_', ' '), pf, res);
}
if (nm.matches(pf.getSynonyms())) {
String[] synonyms = pf.getSynonyms().split(";");
for (String synonym : synonyms) {
if (nm.matches(synonym)) {
lst = addToList(synonym, lst);
}
res = addIfMatch(nm, synonym, pf, res);
}
}
if(lst != null && nl) {
results.put(pf, lst);
}
return res;
}
private List<String> addToList(String s, List<String> lst) {
if(lst == null) {
lst = new ArrayList<>();
private PoiTypeResult addIfMatch(NameStringMatcher nm, String s, AbstractPoiType pf, PoiTypeResult res) {
if (nm.matches(s)) {
if (res == null) {
res = new PoiTypeResult();
res.pt = pf;
}
res.foundWords.add(s);
}
lst.add(s);
return lst;
return res;
}
private void initPoiTypes() {
@ -741,6 +821,7 @@ public class SearchCoreFactory {
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
boolean showTopFiltersOnly = !phrase.isUnknownSearchWordPresent();
NameStringMatcher nm = phrase.getFirstUnknownNameStringMatcher();
initPoiTypes();
if (showTopFiltersOnly) {
for (AbstractPoiType pt : topVisibleFilters) {
@ -752,11 +833,13 @@ public class SearchCoreFactory {
} else {
boolean includeAdditional = !phrase.hasMoreThanOneUnknownSearchWord();
Map<AbstractPoiType, List<String>> poiTypes = getPoiTypeResults(nm, includeAdditional);
for (Entry<AbstractPoiType, List<String>> pt : poiTypes.entrySet()) {
NameStringMatcher nmAdditional = includeAdditional ?
new NameStringMatcher(phrase.getFirstUnknownSearchWord(), StringMatcherMode.CHECK_EQUALS_FROM_SPACE) : null;
Map<String, PoiTypeResult> poiTypes = getPoiTypeResults(nm, nmAdditional);
for (PoiTypeResult ptr : poiTypes.values()) {
boolean match = !phrase.isFirstUnknownSearchWordComplete();
if (!match) {
for (String foundName : pt.getValue()) {
for (String foundName : ptr.foundWords) {
CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
match = csm.matches(phrase.getUnknownSearchPhrase());
if (match) {
@ -766,9 +849,9 @@ public class SearchCoreFactory {
}
if (match) {
SearchResult res = new SearchResult(phrase);
res.localeName = pt.getKey().getTranslation();
res.object = pt.getKey();
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(pt.getKey()),
res.localeName = ptr.pt.getTranslation();
res.object = ptr.pt;
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(ptr.pt),
res);
}
}
@ -786,7 +869,7 @@ public class SearchCoreFactory {
}
private void addPoiTypeResult(SearchPhrase phrase, SearchResultMatcher resultMatcher, boolean showTopFiltersOnly,
String stdFilterId , SearchResult res) {
String stdFilterId, SearchResult res) {
res.priorityDistance = 0;
res.objectType = ObjectType.POI_TYPE;
res.firstUnknownWordMatches = true;
@ -879,7 +962,7 @@ public class SearchCoreFactory {
SearchPoiTypeFilter poiTypeFilter = null;
String nameFilter = null;
int countExtraWords = 0;
Map<String, PoiType> poiAdditionals = new LinkedHashMap<String, PoiType>();
Set<String> poiAdditionals = new LinkedHashSet<>();
if (phrase.isLastWord(ObjectType.POI_TYPE)) {
Object obj = phrase.getLastSelectedWord().getResult().object;
if (obj instanceof AbstractPoiType) {
@ -892,11 +975,13 @@ public class SearchCoreFactory {
nameFilter = phrase.getUnknownSearchPhrase();
} else if (searchAmenityTypesAPI != null && phrase.isFirstUnknownSearchWordComplete()) {
NameStringMatcher nm = phrase.getFirstUnknownNameStringMatcher();
NameStringMatcher nmAdditional = new NameStringMatcher(phrase.getFirstUnknownSearchWord(),
StringMatcherMode.CHECK_EQUALS_FROM_SPACE) ;
searchAmenityTypesAPI.initPoiTypes();
Map<AbstractPoiType, List<String>> poiTypeResults = searchAmenityTypesAPI.getPoiTypeResults(nm, true);
Map<String, PoiTypeResult> poiTypeResults = searchAmenityTypesAPI.getPoiTypeResults(nm, nmAdditional);
// find first full match only
for (Entry<AbstractPoiType, List<String>> poiType : poiTypeResults.entrySet()) {
for (String foundName : poiType.getValue()) {
for (PoiTypeResult poiTypeResult : poiTypeResults.values()) {
for (String foundName : poiTypeResult.foundWords) {
CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
// matches only completely
int mwords = phrase.countWords(foundName) ;
@ -913,8 +998,8 @@ public class SearchCoreFactory {
nameFilter += otherSearchWords.get(k);
}
}
poiTypeFilter = getPoiTypeFilter(poiType.getKey(), poiAdditionals);
unselectedPoiType = poiType.getKey();
poiTypeFilter = getPoiTypeFilter(poiTypeResult.pt, poiAdditionals);
unselectedPoiType = poiTypeResult.pt;
}
}
}
@ -943,7 +1028,7 @@ public class SearchCoreFactory {
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchPoiTypeFilter poiTypeFilter,
final SearchResultMatcher resultMatcher, final String nameFilter,
final BinaryMapIndexReader selected, final Set<String> searchedPois,
final Map<String, PoiType> poiAdditionals, final int countExtraWords) {
final Collection<String> poiAdditionals, final int countExtraWords) {
final NameStringMatcher ns = nameFilter == null ? null : new NameStringMatcher(nameFilter, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
@ -964,7 +1049,7 @@ public class SearchCoreFactory {
}
if (!poiAdditionals.isEmpty()) {
boolean found = false;
for (String add : poiAdditionals.keySet()) {
for (String add : poiAdditionals) {
if(object.getAdditionalInfo().containsKey(add)) {
found = true;
break;
@ -996,6 +1081,8 @@ public class SearchCoreFactory {
res.localeName += " " + ref;
}
}
} else {
phrase.countUnknownWordsMatch(res, "", null, countExtraWords);
}
res.object = object;
@ -1016,13 +1103,13 @@ public class SearchCoreFactory {
};
}
private SearchPoiTypeFilter getPoiTypeFilter(AbstractPoiType pt, Map<String, PoiType> poiAdditionals ) {
private SearchPoiTypeFilter getPoiTypeFilter(AbstractPoiType pt, Set<String> poiAdditionals ) {
final Map<PoiCategory, LinkedHashSet<String>> acceptedTypes = new LinkedHashMap<PoiCategory,
LinkedHashSet<String>>();
pt.putTypes(acceptedTypes);
poiAdditionals.clear();
if (pt instanceof PoiType && ((PoiType) pt).isAdditional() && ((PoiType) pt).getParentType() != null) {
poiAdditionals.put(pt.getKeyName(), (PoiType) pt);
if (pt.isAdditional()) {
poiAdditionals.add(pt.getKeyName());
}
return new SearchPoiTypeFilter() {
@ -1102,11 +1189,11 @@ public class SearchCoreFactory {
res.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
res.otherNames = object.getAllNames(true);
boolean pub = true;
if (object.getName().startsWith("<")) {
// streets related to city
continue;
}
if (phrase.isUnknownSearchWordPresent()
pub = false;
} else if (phrase.isUnknownSearchWordPresent()
&& !(nm.matches(res.localeName) || nm.matches(res.otherNames))) {
continue;
}
@ -1118,7 +1205,7 @@ public class SearchCoreFactory {
res.priority = SEARCH_STREET_BY_CITY_PRIORITY;
//res.priorityDistance = 1;
res.objectType = ObjectType.STREET;
subSearchApiOrPublish(phrase, resultMatcher, res, streetsAPI);
subSearchApiOrPublish(phrase, resultMatcher, res, streetsAPI, pub);
if (limit++ > LIMIT) {
break;
}
@ -1226,8 +1313,8 @@ public class SearchCoreFactory {
res.file = file;
res.priority = priority;
res.priorityDistance = 0;
// TOOO phrase.countUnknownWordsMatchMainResult(res);
res.firstUnknownWordMatches = startMatch.matches(res.localeName);
// phrase.countUnknownWordsMatchMainResult(res); // same as above
res.relatedObject = s;
res.localeRelatedObjectName = s.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
res.objectType = ObjectType.HOUSE;
@ -1238,6 +1325,7 @@ public class SearchCoreFactory {
res.location = b.getLocation();
}
res.preferredZoom = 17;
resultMatcher.publish(res);
}
String streetIntersection = phrase.getUnknownWordToSearch();
@ -1251,7 +1339,6 @@ public class SearchCoreFactory {
|| !phrase.isSearchTypeAllowed(ObjectType.STREET_INTERSECTION)) {
continue;
}
// TOOO phrase.countUnknownWordsMatchMainResult(res);
res.otherNames = street.getAllNames(true);
res.localeName = street.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
res.object = street;
@ -1263,6 +1350,7 @@ public class SearchCoreFactory {
res.objectType = ObjectType.STREET_INTERSECTION;
res.location = street.getLocation();
res.preferredZoom = 16;
phrase.countUnknownWordsMatchMainResult(res);
resultMatcher.publish(res);
}
}
@ -1282,6 +1370,36 @@ public class SearchCoreFactory {
}
}
protected static class PoiAdditionalCustomFilter extends AbstractPoiType {
protected List<PoiType> additionalPoiTypes = new ArrayList<PoiType>();
public PoiAdditionalCustomFilter(MapPoiTypes registry, PoiType pt) {
super(pt.getKeyName(), registry);
additionalPoiTypes.add(pt);
}
@Override
public boolean isAdditional() {
return true;
}
public Map<PoiCategory, LinkedHashSet<String>> putTypes(Map<PoiCategory, LinkedHashSet<String>> acceptedTypes) {
for (PoiType p : additionalPoiTypes) {
if (p.getParentType() == registry.getOtherMapCategory()) {
for (PoiCategory c : registry.getCategories(false)) {
c.putTypes(acceptedTypes);
}
} else {
p.getParentType().putTypes(acceptedTypes);
}
}
return acceptedTypes;
}
}
public static class SearchLocationAndUrlAPI extends SearchBaseAPI {
private static final int OLC_RECALC_DISTANCE_THRESHOLD = 100000; // 100 km

View file

@ -526,7 +526,7 @@ public class SearchPhrase {
public NameStringMatcher getFirstUnknownNameStringMatcher() {
if (firstUnknownNameStringMatcher == null) {
firstUnknownNameStringMatcher = getNameStringMatcher(firstUnknownSearchWord, lastUnknownSearchWordComplete);
firstUnknownNameStringMatcher = getNameStringMatcher(firstUnknownSearchWord, isFirstUnknownSearchWordComplete());
}
return firstUnknownNameStringMatcher;
}
@ -793,6 +793,13 @@ public class SearchPhrase {
return r;
}
public String getLastUnknownSearchWord() {
if(otherUnknownWords.size() > 0) {
return otherUnknownWords.get(otherUnknownWords.size() - 1);
}
return firstUnknownSearchWord;
}
public int getRadiusSearch(int meters, int radiusLevel) {
int res = meters;
@ -877,4 +884,6 @@ public class SearchPhrase {
}

View file

@ -23,8 +23,7 @@ public class SearchSettings {
private ObjectType[] searchTypes;
private boolean emptyQueryAllowed;
private boolean sortByName;
private SearchExportSettings exportSettings;
//private SearchExportSettings exportSettings = new SearchExportSettings(false, false, -1);
private SearchExportSettings exportSettings; // = new SearchExportSettings(true, true, -1);
public SearchSettings(SearchSettings s) {
if(s != null) {

View file

@ -0,0 +1,56 @@
package net.osmand;
import java.text.Normalizer;
import org.junit.Test;
import com.ibm.icu.text.ArabicShaping;
import com.ibm.icu.text.ArabicShapingException;
import com.ibm.icu.text.Bidi;
import net.osmand.Reshaper;
public class ReShaperTest {
//
// Source : ه ە ی ب ە
// Expected: ه ە ی ب ە
// Reshaped: ە ە
@Test
public void testArabName() throws ArabicShapingException {
// https://www.compart.com/en/unicode/U+FCD8
// String source = "\uFEEB\u06d5";
// System.out.println(new ArabicShaping(0).shape(s));
// System.out.println("\uFEEB\u06d5");
String source = "هەیبە";
String expected = "ەﺐﯾەﻩ";
String res = Reshaper.reshape(source);
Reshaper.check(source, res, expected);
}
@Test
public void test2() throws ArabicShapingException {
Reshaper.test2();
}
@Test
public void test3() throws ArabicShapingException {
Reshaper.test3();
}
@Test
public void test4() throws ArabicShapingException {
Reshaper.test4();
}
@Test
public void test5() throws ArabicShapingException {
Reshaper.test5();
}
}

View file

@ -38,15 +38,13 @@ public class RouteResultPreparationTest {
private static RoutePlannerFrontEnd fe;
private static RoutingContext ctx;
private String testName;
private LatLon startPoint;
private LatLon endPoint;
private Map<Long, String> expectedResults;
private Log log = PlatformUtil.getLog(RouteResultPreparationTest.class);
protected Log log = PlatformUtil.getLog(RouteResultPreparationTest.class);
public RouteResultPreparationTest(String testName, LatLon startPoint, LatLon endPoint, Map<Long, String> expectedResults) {
this.testName = testName;
this.startPoint = startPoint;
this.endPoint = endPoint;
this.expectedResults = expectedResults;

View file

@ -1,13 +1,16 @@
package net.osmand.search;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.search.SearchUICore.SearchResultCollection;
import net.osmand.search.SearchUICore.SearchResultMatcher;
import net.osmand.search.core.SearchPhrase;
import net.osmand.search.core.SearchResult;
import net.osmand.search.core.SearchSettings;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.json.JSONArray;
import org.json.JSONException;
@ -19,23 +22,18 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.xmlpull.v1.XmlPullParserException;
import net.osmand.OsmAndCollator;
import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.Amenity;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.Street;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.search.SearchUICore.SearchResultCollection;
import net.osmand.search.SearchUICore.SearchResultMatcher;
import net.osmand.search.core.SearchPhrase;
import net.osmand.search.core.SearchResult;
import net.osmand.search.core.SearchSettings;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
@RunWith(Parameterized.class)
public class SearchUICoreTest {
@ -94,11 +92,12 @@ public class SearchUICoreTest {
@Test
public void testSearch() throws IOException, JSONException {
File jsonFile = testFile;
File obfFile = new File(testFile.getParentFile(), testFile.getName().replace(".json", ".obf"));
File obfZipFile = new File(testFile.getParentFile(), testFile.getName().replace(".json", ".obf.gz"));
String sourceJsonText = Algorithms.getFileAsString(jsonFile);
Assert.assertNotNull(sourceJsonText);
Assert.assertTrue(sourceJsonText.length() > 0);
BinaryMapIndexReaderTest reader = new BinaryMapIndexReaderTest();
JSONObject sourceJson = new JSONObject(sourceJsonText);
JSONArray phrasesJson = sourceJson.optJSONArray("phrases");
String singlePhrase = sourceJson.optString("phrase", null);
@ -115,39 +114,23 @@ public class SearchUICoreTest {
}
}
JSONObject settingsJson = sourceJson.getJSONObject("settings");
if (sourceJson.has("amenities")) {
JSONArray amenitiesArr = sourceJson.getJSONArray("amenities");
List<Amenity> amenities = new ArrayList<>();
for (int i = 0; i < amenitiesArr.length(); i++) {
JSONObject amenityObj = amenitiesArr.getJSONObject(i);
amenities.add(Amenity.parseJSON(amenityObj));
BinaryMapIndexReader reader = null;
boolean useData = settingsJson.optBoolean("useData", true);
if (useData) {
boolean obfZipFileExists = obfZipFile.exists();
if (!obfZipFileExists) {
System.out.println(String.format("Could not find obf file: %s", obfZipFile.getPath()));
return;
}
reader.amenities = amenities;
}
if (sourceJson.has("cities")) {
JSONArray citiesArr = sourceJson.getJSONArray("cities");
List<City> cities = new ArrayList<>();
List<City> initCities = new ArrayList<>();
List<City> matchedCities = new ArrayList<>();
List<City> streetCities = new ArrayList<>();
for (int i = 0; i < citiesArr.length(); i++) {
JSONObject cityObj = citiesArr.getJSONObject(i);
final City city = City.parseJSON(cityObj);
cities.add(city);
if (cityObj.has("init")) {
initCities.add(city);
}
if (cityObj.has("matchCity")) {
matchedCities.add(city);
}
if (cityObj.has("matchStreet")) {
streetCities.add(city);
}
}
reader.cities = cities;
reader.initCities = initCities;
reader.matchedCities = matchedCities;
reader.streetCities = streetCities;
//Assert.assertTrue(obfZipFileExists);
GZIPInputStream gzin = new GZIPInputStream(new FileInputStream(obfZipFile));
FileOutputStream fous = new FileOutputStream(obfFile);
Algorithms.streamCopy(gzin, fous);
fous.close();
gzin.close();
reader = new BinaryMapIndexReader(new RandomAccessFile(obfFile.getPath(), "r"), obfFile);
}
List<List<String>> results = new ArrayList<>();
for (int i = 0; i < phrases.size(); i++) {
@ -166,7 +149,9 @@ public class SearchUICoreTest {
}
SearchSettings s = SearchSettings.parseJSON(settingsJson);
s.setOfflineIndexes(Collections.singletonList(reader));
if (reader != null) {
s.setOfflineIndexes(Collections.singletonList(reader));
}
final SearchUICore core = new SearchUICore(MapPoiTypes.getDefault(), "en", false);
core.init();
@ -216,6 +201,8 @@ public class SearchUICoreTest {
}
}
}
obfFile.delete();
}
private void parseResults(JSONObject sourceJson, String tag, List<List<String>> results) {
@ -329,116 +316,4 @@ public class SearchUICoreTest {
return val;
}
};
private static class BinaryMapIndexReaderTest extends BinaryMapIndexReader {
List<Amenity> amenities = Collections.emptyList();
List<City> cities = Collections.emptyList();
List<City> initCities = Collections.emptyList();
List<City> matchedCities = Collections.emptyList();
List<City> streetCities = Collections.emptyList();
BinaryMapIndexReaderTest() throws IOException {
super(null, null, false);
}
@Override
public List<Amenity> searchPoiByName(SearchRequest<Amenity> req) throws IOException {
for (Amenity amenity : amenities) {
req.publish(amenity);
}
return req.getSearchResults();
}
@Override
public List<Amenity> searchPoi(SearchRequest<Amenity> req) throws IOException {
for (Amenity amenity : amenities) {
req.publish(amenity);
}
return req.getSearchResults();
}
@Override
public List<City> getCities(SearchRequest<City> resultMatcher, int cityType) throws IOException {
for (City city : initCities) {
if (resultMatcher != null) {
resultMatcher.publish(city);
}
}
return initCities;
}
@Override
public int preloadStreets(City c, SearchRequest<Street> resultMatcher) throws IOException {
return 0;
}
@Override
public void preloadBuildings(Street s, SearchRequest<Building> resultMatcher) throws IOException {
// cities must be filled with streets and buildings
}
@Override
public List<MapObject> searchAddressDataByName(SearchRequest<MapObject> req) throws IOException {
for (City city : streetCities) {
for (Street street : city.getStreets()) {
req.publish(street);
}
}
for (City city : matchedCities) {
req.publish(city);
}
return req.getSearchResults();
}
@Override
public String getRegionName() {
return "Test region";
}
@Override
public boolean containsPoiData(int left31x, int top31y, int right31x, int bottom31y) {
return true;
}
@Override
public boolean containsMapData() {
return true;
}
@Override
public boolean containsPoiData() {
return true;
}
@Override
public boolean containsRouteData() {
return true;
}
@Override
public boolean containsRouteData(int left31x, int top31y, int right31x, int bottom31y, int zoom) {
return true;
}
@Override
public boolean containsAddressData(int left31x, int top31y, int right31x, int bottom31y) {
return true;
}
@Override
public boolean containsMapData(int tile31x, int tile31y, int zoom) {
return true;
}
@Override
public boolean containsMapData(int left31x, int top31y, int right31x, int bottom31y, int zoom) {
return true;
}
@Override
public boolean containsAddressData() {
return true;
}
}
}

View file

@ -1,5 +1,6 @@
/*.json
/osm_live/*.json
/search/*
*.obf
*.osm
phrases.xml

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,736 +0,0 @@
{
"settings": {
"lat": "55.28666",
"lon": "52.00556",
"radiusLevel": 1,
"totalLimit": -1,
"lang": "",
"transliterateIfMissing": false,
"emptyQueryAllowed": false,
"sortByName": false
},
"phrase": "parking ",
"results": [
"Parking (Personal transport) [[1, POI_TYPE, 1.000, 0.00 km]]",
"для посетителей [[0, POI, 2.000, 0.03 km]]",
"Parking [[0, POI, 2.000, 0.05 km]]",
"Parking [[0, POI, 2.000, 0.11 km]]",
"Parking [[0, POI, 2.000, 0.16 km]]",
"Parking [[0, POI, 2.000, 0.17 km]]",
"Parking [[0, POI, 2.000, 0.23 km]]",
"Parking [[0, POI, 2.000, 0.35 km]]",
"Parking [[0, POI, 2.000, 0.40 km]]",
"Parking [[0, POI, 2.000, 0.48 km]]",
"Parking [[0, POI, 2.000, 0.49 km]]",
"Parking [[0, POI, 2.000, 0.55 km]]",
"Автостоянка №1 [[0, POI, 2.000, 0.56 km]]",
"Parking [[0, POI, 2.000, 0.58 km]]",
"Parking [[0, POI, 2.000, 0.61 km]]",
"Parking [[0, POI, 2.000, 0.72 km]]",
"Parking [[0, POI, 2.000, 0.81 km]]",
"Parking [[0, POI, 2.000, 0.81 km]]",
"Parking [[0, POI, 2.000, 0.85 km]]",
"для клиентов [[0, POI, 2.000, 0.89 km]]",
"Parking [[0, POI, 2.000, 0.93 km]]",
"Parking [[0, POI, 2.000, 0.94 km]]",
"Заинская ГРЭС [[0, POI, 2.000, 1.01 km]]",
"Parking [[0, POI, 2.000, 1.02 km]]",
"Южная [[0, POI, 2.000, 1.03 km]]",
"Parking [[0, POI, 2.000, 1.06 km]]",
"Parking [[0, POI, 2.000, 1.09 km]]",
"Parking [[0, POI, 2.000, 1.10 km]]",
"Служебная [[0, POI, 2.000, 1.14 km]]",
"Parking [[0, POI, 2.000, 1.20 km]]",
"Parking [[0, POI, 2.000, 1.21 km]]",
"Parking [[0, POI, 2.000, 1.36 km]]",
"Parking [[0, POI, 2.000, 1.44 km]]",
"Три тополя [[0, POI, 2.000, 1.47 km]]",
"Parking [[0, POI, 2.000, 1.53 km]]",
"Parking [[0, POI, 2.000, 1.56 km]]",
"Parking [[0, POI, 2.000, 1.62 km]]",
"Parking [[0, POI, 2.000, 1.85 km]]",
"Штрафстоянка (Эвакуатор) [[0, POI, 2.000, 2.03 km]]",
"Parking [[0, POI, 2.000, 2.05 km]]",
"для регистрации в ГИБДД [[0, POI, 2.000, 2.06 km]]",
"Parking [[0, POI, 2.000, 2.06 km]]",
"Parking [[0, POI, 2.000, 2.07 km]]",
"для техосмотра [[0, POI, 2.000, 2.09 km]]",
"Parking [[0, POI, 2.000, 2.18 km]]",
"Parking [[0, POI, 2.000, 2.55 km]]",
"Parking [[0, POI, 2.000, 3.40 km]]",
"Parking [[0, POI, 2.000, 3.41 km]]",
"Parking [[0, POI, 2.000, 3.41 km]]",
"Parking [[0, POI, 2.000, 3.45 km]]",
"Parking [[0, POI, 2.000, 4.29 km]]",
"Parking [[0, POI, 2.000, 6.71 km]]"
],
"amenities": [
{
"lat": "55.29801",
"lon": "51.99100",
"id": 881010149,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.29481",
"lon": "51.98964",
"id": 803545283,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"parking_surface": "surface"
}
},
{
"name": "Заинская ГРЭС",
"lat": "55.28492",
"lon": "52.02125",
"id": 481494555,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_yes": "yes",
"parking_surface": "surface"
}
},
{
"lat": "55.29105",
"lon": "51.99531",
"id": 540237721,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28683",
"lon": "52.01479",
"id": 888343263,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_unpaved": "unpaved",
"access_permissive": "permissive",
"supervised_yes": "yes"
}
},
{
"lat": "55.30317",
"lon": "52.00192",
"id": 1161722765,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"parking_surface": "surface",
"operator": "cахарный завод"
}
},
{
"name": "для техосмотра",
"lat": "55.30439",
"lon": "52.01634",
"id": 484385195,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28615",
"lon": "52.00702",
"id": 1040771455,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28582",
"lon": "52.00758",
"id": 535925577,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.30950",
"lon": "51.96954",
"id": 1228158833,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"parking_surface": "surface"
}
},
{
"lat": "55.29345",
"lon": "51.99385",
"id": 535897911,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.30957",
"lon": "52.00374",
"id": 897019441,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28602",
"lon": "52.00908",
"id": 268235957,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28777",
"lon": "51.99608",
"id": 4410403520512,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_unpaved": "unpaved",
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes",
"capacity": "70"
}
},
{
"lat": "55.34092",
"lon": "52.05172",
"id": 2136388576,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no"
}
},
{
"lat": "55.28271",
"lon": "52.00248",
"id": 536030271,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28391",
"lon": "52.00273",
"id": 536035007,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"name": "Служебная",
"lat": "55.28615",
"lon": "52.02350",
"id": 481491939,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_asphalt": "asphalt",
"fee_no": "no",
"access_permissive": "permissive",
"supervised_yes": "yes",
"parking_surface": "surface"
}
},
{
"lat": "55.30969",
"lon": "51.96917",
"id": 1228158821,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.31022",
"lon": "51.97104",
"id": 1228158819,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"parking_surface": "surface"
}
},
{
"lat": "55.29275",
"lon": "51.99355",
"id": 892959215,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"name": "для посетителей",
"lat": "55.28688",
"lon": "52.00578",
"id": 11390213698,
"subType": "parking",
"type": "transportation"
},
{
"lat": "55.30838",
"lon": "51.96767",
"id": 1164434353,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"parking_surface": "surface"
}
},
{
"name": "Южная",
"lat": "55.27739",
"lon": "52.00544",
"id": 641567205,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_unpaved": "unpaved",
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes"
}
},
{
"lat": "55.28045",
"lon": "51.99550",
"id": 478137507,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes"
}
},
{
"name": "Автостоянка №1",
"lat": "55.29028",
"lon": "51.99934",
"id": 502948005,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_gravel": "gravel",
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes"
}
},
{
"lat": "55.27839",
"lon": "52.00301",
"id": 1168315587,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"parking_surface": "surface",
"operator": "Заинская ЦРБ"
}
},
{
"lat": "55.30468",
"lon": "52.01335",
"id": 897014805,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.32509",
"lon": "51.99930",
"id": 1172111487,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"name": "Штрафстоянка (Эвакуатор)",
"lat": "55.30439",
"lon": "52.01346",
"id": 5153530824,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes",
"phone": "+7 (85558) 7-77-01"
}
},
{
"name": "Три тополя",
"lat": "55.29666",
"lon": "51.99048",
"id": 642175341,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_unpaved": "unpaved",
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes"
}
},
{
"lat": "55.29077",
"lon": "52.00812",
"id": 1168356553,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_asphalt": "asphalt",
"supervised_yes": "yes",
"parking_surface": "surface",
"fee_yes": "yes"
}
},
{
"lat": "55.29429",
"lon": "51.99190",
"id": 893048919,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.29959",
"lon": "52.00516",
"id": 1022216961,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28355",
"lon": "51.99881",
"id": 943827057,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"parking_surface": "surface"
}
},
{
"lat": "55.28651",
"lon": "52.00479",
"id": 905757839,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28928",
"lon": "52.00977",
"id": 190467181,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_gravel": "gravel",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28674",
"lon": "52.00282",
"id": 1168411743,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"name": "для клиентов",
"lat": "55.29116",
"lon": "51.99394",
"id": 821840897,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"surface_asphalt": "asphalt",
"parking_surface": "surface",
"access_customers": "customers"
}
},
{
"lat": "55.29068",
"lon": "51.99490",
"id": 540238031,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.28982",
"lon": "51.98911",
"id": 190489189,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.29341",
"lon": "51.99072",
"id": 806562897,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no"
}
},
{
"lat": "55.28042",
"lon": "52.00155",
"id": 1159734951,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.30493",
"lon": "52.01007",
"id": 1172110357,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.30500",
"lon": "52.01108",
"id": 1172110359,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface",
"capacity": "13"
}
},
{
"lat": "55.29816",
"lon": "51.99222",
"id": 1160388645,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.29015",
"lon": "51.99366",
"id": 503278061,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.30624",
"lon": "52.00475",
"id": 691494051,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface",
"operator": "ЗЗМК - Тимер"
}
},
{
"name": "для регистрации в ГИБДД",
"lat": "55.30438",
"lon": "52.01483",
"id": 484385289,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
},
{
"lat": "55.29258",
"lon": "51.99188",
"id": 892959265,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no"
}
},
{
"lat": "55.28050",
"lon": "52.00200",
"id": 1159662915,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface",
"capacity": "10"
}
},
{
"lat": "55.29845",
"lon": "51.99057",
"id": 881010015,
"subType": "parking",
"type": "transportation",
"additionalInfo": {
"fee_no": "no",
"surface_asphalt": "asphalt",
"supervised_no": "no",
"parking_surface": "surface"
}
}
]
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,17 +0,0 @@
{
"settings": {
"lat": "55.75138",
"lon": "37.62940",
"radiusLevel": 1,
"totalLimit": -1,
"lang": "",
"transliterateIfMissing": false,
"emptyQueryAllowed": false,
"sortByName": false
},
"phrase": "QHW6+CQ",
"results": [
"55.796062, 37.56194 [[1, LOCATION, 1.000, 6.52 km]]"
],
"cities": []
}

View file

@ -1,710 +0,0 @@
{
"settings": {
"lat": "51.04933",
"lon": "13.73815",
"radiusLevel": 1,
"totalLimit": -1,
"lang": "",
"transliterateIfMissing": false,
"emptyQueryAllowed": false,
"sortByName": false
},
"phrase": "Biergarten ",
"results": [
"Biergarten (Food) [[1, POI_TYPE, 1.000, 0.00 km]]",
"Biergarten Italienisches Dörfchen [[1, POI, 2.000, 0.55 km]]",
"Biergarten Narrenhäus'l [[1, POI, 2.000, 0.84 km]]",
"Biergarten Elbsegler [[1, POI, 2.000, 0.89 km]]",
"Biergarten Elbsegler [[1, POI, 2.000, 0.90 km]]",
"Körnergarten [[1, POI, 2.000, 5.18 km]]",
"Biergarten Goldener Anker [[1, POI, 2.000, 9.78 km]]",
"Palais Bistro [[0, POI, 2.000, 0.29 km]]",
"Augustus Garten am Narrenhäusl [[0, POI, 2.000, 0.88 km]]",
"Zum Schießhaus [[0, POI, 2.000, 0.96 km]]",
"Biergarten [[0, POI, 2.000, 1.24 km]]",
"Wachstube [[0, POI, 2.000, 1.24 km]]",
"Torwirtschaft [[0, POI, 2.000, 1.27 km]]",
"Altes Wettbüro [[0, POI, 2.000, 1.77 km]]",
"Bottoms Up [[0, POI, 2.000, 2.16 km]]",
"Louisengarten [[0, POI, 2.000, 2.20 km]]",
"Biergarten [[0, POI, 2.000, 2.28 km]]",
"Fährgarten Johannstadt [[0, POI, 2.000, 2.42 km]]",
"Carolaschlösschen [[0, POI, 2.000, 2.53 km]]",
"Alt-Dresden [[0, POI, 2.000, 2.75 km]]",
"Biergarten [[0, POI, 2.000, 2.90 km]]",
"Café & Restaurant Saite [[0, POI, 2.000, 3.09 km]]",
"Brauhaus am Waldschlößchen [[0, POI, 2.000, 3.45 km]]",
"Brauhaus Watzke [[0, POI, 2.000, 3.51 km]]",
"el Horst [[0, POI, 2.000, 3.67 km]]",
"Biergarten [[0, POI, 2.000, 3.74 km]]",
"Spitzwegerich [[0, POI, 2.000, 3.81 km]]",
"Biergarten [[0, POI, 2.000, 3.88 km]]",
"Biergarten [[0, POI, 2.000, 4.46 km]]",
"Trobischhof [[0, POI, 2.000, 4.48 km]]",
"Biergarten [[0, POI, 2.000, 4.80 km]]",
"Biergarten [[0, POI, 2.000, 4.91 km]]",
"Schillergarten [[0, POI, 2.000, 4.97 km]]",
"Biergarten [[0, POI, 2.000, 5.11 km]]",
"Biergarten [[0, POI, 2.000, 5.13 km]]",
"Demnitz Elbegarten [[0, POI, 2.000, 5.16 km]]",
"Körnergarten [[0, POI, 2.000, 5.18 km]]",
"Biergarten [[0, POI, 2.000, 5.31 km]]",
"Trachauer Sommergarten [[0, POI, 2.000, 5.31 km]]",
"Biergarten [[0, POI, 2.000, 5.91 km]]",
"Biergarten [[0, POI, 2.000, 6.12 km]]",
"Biergarten [[0, POI, 2.000, 6.26 km]]",
"Biergarten [[0, POI, 2.000, 6.42 km]]",
"Biergarten [[0, POI, 2.000, 6.88 km]]",
"Biergarten [[0, POI, 2.000, 7.11 km]]",
"Straußenwirtschaft Weingut Pesterwitz [[0, POI, 2.000, 7.14 km]]",
"Klotzscher Sommerwirtschaft [[0, POI, 2.000, 7.16 km]]",
"Biergarten [[0, POI, 2.000, 7.17 km]]",
"Zacke [[0, POI, 2.000, 8.20 km]]",
"Weingut Seifert [[0, POI, 2.000, 8.50 km]]",
"Biergarten [[0, POI, 2.000, 8.82 km]]",
"Biergarten [[0, POI, 2.000, 9.11 km]]",
"Biergarten [[0, POI, 2.000, 9.23 km]]",
"Landgut Hofewiese [[0, POI, 2.000, 9.40 km]]",
"Biergarten Goldener Anker [[0, POI, 2.000, 9.78 km]]",
"Biergarten [[0, POI, 2.000, 10.00 km]]",
"Biergarten [[0, POI, 2.000, 10.22 km]]",
"Besenwirtschaft Steinrücken [[0, POI, 2.000, 10.85 km]]"
],
"amenities": [
{
"lat": "51.02489",
"lon": "13.69860",
"id": 244538865,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"surface_fine_gravel": "fine_gravel"
}
},
{
"lat": "51.09478",
"lon": "13.84153",
"id": 865332598,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Einkehr"
}
},
{
"lat": "51.01123",
"lon": "13.67918",
"id": 9712288200,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"website": "http://www.zur-linde-freital.de/",
"operator": "Zur Linde",
"image": "http://commons.wikimedia.org/wiki/File:Hotel_und_Gasthaus_Zur_Linde_Freital-Birkigt.jpg"
}
},
{
"name": "Altes Wettbüro",
"lat": "51.06472",
"lon": "13.74467",
"id": 11451975032,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Tu-Sa 17:00-22:00",
"additionalInfo": {
"wheelchair_limited": "limited",
"outdoor_seating_yes": "yes",
"outdoor_seating_filter_yes": "yes",
"opening_hours": "Tu-Sa 17:00-22:00",
"website": "http://www.altes-wettbuero.de",
"phone": "+49 351 6588983",
"operator": "Falk Gruß"
}
},
{
"name": "Carolaschlösschen",
"lat": "51.03341",
"lon": "13.76392",
"id": 3704353318,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su 11:00-24:00",
"additionalInfo": {
"wheelchair_limited": "limited",
"opening_hours": "Mo-Su 11:00-24:00",
"facebook": "https://www.facebook.com/carolaschloesschen/"
}
},
{
"lat": "51.01251",
"lon": "13.69407",
"id": 562115695,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Torwirtschaft",
"lat": "51.04156",
"lon": "13.75139",
"id": 517007905,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes",
"website": "http://www.torwirtschaft-dresden.de",
"facebook": "https://www.facebook.com/Torwirtschaft-der-Biergarten-f%C3%BCr-alle-Dynamofans-168677023169963/"
}
},
{
"name": "Biergarten Italienisches Dörfchen",
"lat": "51.05429",
"lon": "13.73759",
"id": 486232011,
"subType": "biergarten",
"type": "sustenance"
},
{
"lat": "51.04261",
"lon": "13.75229",
"id": 98518191,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes"
}
},
{
"name": "Körnergarten",
"names": {
"prefix": "Biergarten"
},
"lat": "51.05316",
"lon": "13.81192",
"id": 3704353594,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su 11:00-24:00",
"additionalInfo": {
"wheelchair_limited": "limited",
"opening_hours": "Mo-Su 11:00-24:00",
"website": "http://www.koernergarten.de/"
}
},
{
"lat": "51.06397",
"lon": "13.79748",
"id": 670742479,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Weingut Seifert",
"lat": "51.11134",
"lon": "13.66701",
"id": 789740008,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"note": "not really a 'biergarten' :)"
}
},
{
"lat": "50.98710",
"lon": "13.65086",
"id": 9037536542,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Zum Gründl"
}
},
{
"lat": "51.10538",
"lon": "13.62622",
"id": 9289210778,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Zum Bürgergarten"
}
},
{
"lat": "51.09459",
"lon": "13.84170",
"id": 5598697742,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Einkehr"
}
},
{
"name": "Trobischhof",
"lat": "51.08649",
"lon": "13.71338",
"id": 409847251,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_limited": "limited"
}
},
{
"name": "Demnitz Elbegarten",
"lat": "51.05328",
"lon": "13.81175",
"id": 771102016,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_no": "no",
"cuisine_german": "german",
"website": "http://www.elbegarten.de"
}
},
{
"name": "Augustus Garten am Narrenhäusl",
"lat": "51.05697",
"lon": "13.74166",
"id": 465538291,
"subType": "biergarten",
"type": "sustenance"
},
{
"lat": "51.01529",
"lon": "13.65107",
"id": 7482890514,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Burgwartschänke"
}
},
{
"name": "el Horst",
"lat": "51.04361",
"lon": "13.78979",
"id": 559979958,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Oct-Apr: Mo-Fr 17:00-18:00+, Oct-Apr: Sa,PH 11:30-18:00+, May-Sep: Mo-Fr 15:00-18:00+, May-Sep: Sa,PH 11:30-18:00+",
"additionalInfo": {
"opening_hours": "Oct-Apr: Mo-Fr 17:00-18:00+, Oct-Apr: Sa,PH 11:30-18:00+, May-Sep: Mo-Fr 15:00-18:00+, May-Sep: Sa,PH 11:30-18:00+"
}
},
{
"lat": "51.07376",
"lon": "13.70135",
"id": 553613482,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Wirtshaus Lindenschänke"
}
},
{
"name": "Wachstube",
"lat": "51.04254",
"lon": "13.75222",
"id": 46060263,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "11:00+",
"additionalInfo": {
"wheelchair_no": "no",
"opening_hours": "11:00+",
"website": "https://www.torwirtschaft-dresden.de/wachstube/restaurant.php",
"phone": "+49 351 4466975",
"image": "https://commons.wikimedia.org/wiki/File:Torhaus_N_Grosser_Garten_Dresden-2.jpg",
"wheelchair_description:de": "Zugang ins Gebäude nur über Stufen",
"height": "5.7",
"facebook": "https://www.facebook.com/Wachstube-im-Gro%C3%9Fen-Garten-Dresden-144180698984577/",
"email": "info@wachstube-dresden.de"
}
},
{
"lat": "51.09050",
"lon": "13.70555",
"id": 6300849046,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Bäckerei Werner"
}
},
{
"name": "Biergarten Elbsegler",
"lat": "51.05731",
"lon": "13.73973",
"id": 465318113,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_limited": "limited"
}
},
{
"name": "Straußenwirtschaft Weingut Pesterwitz",
"lat": "51.02883",
"lon": "13.64144",
"id": 478369183,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"website": "https://www.gut-pesterwitz.de/"
}
},
{
"name": "Schillergarten",
"lat": "51.05228",
"lon": "13.80908",
"id": 493702544,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su 11:00-01:00",
"additionalInfo": {
"wheelchair_yes": "yes",
"opening_hours": "Mo-Su 11:00-01:00"
}
},
{
"lat": "51.04111",
"lon": "13.80554",
"id": 5837244174,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Astloch"
}
},
{
"name": "Spitzwegerich",
"lat": "51.07767",
"lon": "13.70757",
"id": 412610355,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes",
"toilets_wheelchair_no": "no"
}
},
{
"name": "Biergarten Goldener Anker",
"lat": "51.10399",
"lon": "13.62850",
"id": 143015201,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Tu-Su,PH 11:00-21:00",
"additionalInfo": {
"wheelchair_yes": "yes",
"opening_hours": "Tu-Su,PH 11:00-21:00"
}
},
{
"name": "Bottoms Up",
"lat": "51.06516",
"lon": "13.75615",
"id": 1394136626,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Biergarten Narrenhäus'l",
"lat": "51.05666",
"lon": "13.74130",
"id": 466763007,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Zum Schießhaus",
"lat": "51.05464",
"lon": "13.72727",
"id": 326416539,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su,PH 11:00-23:00",
"additionalInfo": {
"wheelchair_yes": "yes",
"toilets_wheelchair_no": "no",
"opening_hours": "Mo-Su,PH 11:00-23:00"
}
},
{
"name": "Palais Bistro",
"lat": "51.05182",
"lon": "13.73682",
"id": 501015667,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Apr-Oct: Mo-Su 11:00-24:00, Nov-Mar: Mo-Th 12:00-14:30,17:30-24:00, Nov-Mar: Fr-Su 12:00-24:00",
"additionalInfo": {
"wheelchair_yes": "yes",
"opening_hours": "Apr-Oct: Mo-Su 11:00-24:00, Nov-Mar: Mo-Th 12:00-14:30,17:30-24:00, Nov-Mar: Fr-Su 12:00-24:00"
}
},
{
"name": "Brauhaus am Waldschlößchen",
"lat": "51.06778",
"lon": "13.77786",
"id": 594989978,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su 11:00-01:00",
"additionalInfo": {
"wheelchair_limited": "limited",
"opening_hours": "Mo-Su 11:00-01:00"
}
},
{
"lat": "51.00222",
"lon": "13.68504",
"id": 2469999180,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Biergarten Elbsegler",
"lat": "51.05738",
"lon": "13.73913",
"id": 466539133,
"subType": "biergarten",
"type": "sustenance"
},
{
"lat": "51.01010",
"lon": "13.66208",
"id": 7987508388,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes",
"operator": "Zum goldenen Löwen"
}
},
{
"lat": "50.99476",
"lon": "13.72701",
"id": 6765029580,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Eutschützer Mühle"
}
},
{
"lat": "50.99295",
"lon": "13.64362",
"id": 6065174964,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Alte Schmiede"
}
},
{
"name": "Louisengarten",
"lat": "51.06681",
"lon": "13.75278",
"id": 68516655,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Apr-Sep Su-Th 16:00+; Apr-Sep Fr,Sa 15:00+ || off \"Bei unfreundlichem Wetter\"",
"additionalInfo": {
"wheelchair_no": "no",
"opening_hours": "Apr-Sep Su-Th 16:00+; Apr-Sep Fr,Sa 15:00+ || off \"Bei unfreundlichem Wetter\"",
"website": "http://www.biergarten-dresden.de",
"note": "Neustädter Winter Hüttn von Oktober-Dezember",
"alt_name": "Neustädter Winter Hüttn"
}
},
{
"lat": "51.00871",
"lon": "13.65959",
"id": 9237211698,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes",
"operator": "Akropolis"
}
},
{
"lat": "51.03435",
"lon": "13.76042",
"id": 595971770,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Apr-Oct: Mo-Fr 11:00-19:00; Sa-Su 10:00-19:00; PH 10:00-19:00",
"additionalInfo": {
"wheelchair_yes": "yes",
"opening_hours": "Apr-Oct: Mo-Fr 11:00-19:00; Sa-Su 10:00-19:00; PH 10:00-19:00",
"website": "https://www.grosser-garten-dresden.de/de/gaesteservice/gastronomie-shop/",
"phone": "+49 152 37 00 67 53"
}
},
{
"name": "Landgut Hofewiese",
"lat": "51.10989",
"lon": "13.83207",
"id": 8455509378,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes"
}
},
{
"name": "Café & Restaurant Saite",
"lat": "51.07636",
"lon": "13.74825",
"id": 577481323,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Fr 18:00-24:00, Su 10:00-15:00",
"additionalInfo": {
"wheelchair_limited": "limited",
"opening_hours": "Mo-Fr 18:00-24:00, Su 10:00-15:00"
}
},
{
"name": "Alt-Dresden",
"lat": "51.04977",
"lon": "13.69881",
"id": 970594717,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_limited": "limited",
"phone": "0351 4135133"
}
},
{
"lat": "51.08677",
"lon": "13.70081",
"id": 413620001,
"subType": "biergarten",
"type": "sustenance"
},
{
"lat": "50.98618",
"lon": "13.63208",
"id": 10355747978,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "Hirschbergschenke"
}
},
{
"name": "Fährgarten Johannstadt",
"lat": "51.06151",
"lon": "13.76679",
"id": 4415013507072,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_yes": "yes",
"outdoor_seating_yes": "yes",
"outdoor_seating_filter_yes": "yes",
"website": "http://www.faehrgarten.de/",
"phone": "+49 351 4596262",
"brewery_additional": "Radeberger",
"email": "info@faehrgarten.de"
}
},
{
"lat": "51.02343",
"lon": "13.73347",
"id": 4563637454,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Besenwirtschaft Steinrücken",
"lat": "51.11590",
"lon": "13.62457",
"id": 7474665554,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"website": "http://www.besenwirtschaft-steinruecken.de/index.html"
}
},
{
"lat": "51.05181",
"lon": "13.81396",
"id": 9819148822,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"operator": "WSV \"Am Blauen Wunder\""
}
},
{
"name": "Zacke",
"lat": "51.01300",
"lon": "13.63618",
"id": 7498805230,
"subType": "biergarten",
"type": "sustenance"
},
{
"name": "Klotzscher Sommerwirtschaft",
"lat": "51.11072",
"lon": "13.76879",
"id": 717794449,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Fr 17:00-23:00; Sa-Su 11:00-23:00; Nov-Mar off",
"additionalInfo": {
"opening_hours": "Mo-Fr 17:00-23:00; Sa-Su 11:00-23:00; Nov-Mar off",
"website": "http://klotzschersommerwirtschaft.de",
"phone": "+49 351 8804570",
"fax": "+49 351 8902050",
"email": "Kontakt@klotzscher-sommerwirtschaft.de",
"capacity": "20"
}
},
{
"name": "Brauhaus Watzke",
"lat": "51.07744",
"lon": "13.71540",
"id": 397976739,
"subType": "biergarten",
"type": "sustenance",
"additionalInfo": {
"wheelchair_limited": "limited",
"toilets_wheelchair_no": "no"
}
},
{
"name": "Trachauer Sommergarten",
"lat": "51.09166",
"lon": "13.70289",
"id": 1822089672,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "Mo-Su 17:00-21:00",
"additionalInfo": {
"opening_hours": "Mo-Su 17:00-21:00",
"note": "Auch im Winter geöffnet"
}
},
{
"lat": "51.06520",
"lon": "13.82406",
"id": 11565282314,
"subType": "biergarten",
"type": "sustenance",
"openingHours": "seasonal",
"additionalInfo": {
"outdoor_seating_yes": "yes",
"outdoor_seating_filter_yes": "yes",
"opening_hours": "seasonal"
}
}
]
}

View file

@ -1,25 +0,0 @@
{
"settings": {
"lat": "51.04933",
"lon": "13.73815",
"radiusLevel": 1,
"totalLimit": -1,
"lang": "",
"transliterateIfMissing": false,
"emptyQueryAllowed": false,
"sortByName": false
},
"phrase": ["Fuel", "Fuel "],
"results": [[
"Aircraft fuel station (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]",
"Gas station (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]",
"Gas station for boats (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]"
],
[
"Aircraft fuel station (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]",
"Gas station (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]",
"Gas station for boats (Filling station) [[1, POI_TYPE, 1.000, 0.00 km]]"
]],
"amenities": [],
"cities": []
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@
<string name="not_found_yet">Яшчэ не знойдзена</string>
<string name="re_send_location">Пераадправіць звесткі аб месцазнаходжанні</string>
<string name="last_available_location">Апошняе даступнае месца</string>
<string name="sharing_status">"Статус абмену "</string>
<string name="sharing_status">Статус абмену</string>
<string name="location_sharing_status">Абмен: %1$s</string>
<string name="shared_string_enabled">Уключана</string>
<string name="shared_string_status">Статус</string>
@ -75,7 +75,7 @@
<string name="send_my_location_desc">Вызначыць мінімальны інтэрвал для абмену інфармацыяй аб месцазнаходжанні.</string>
<string name="send_my_location">Адправіць маё месцазнаходжанне</string>
<string name="gps_and_location">Пазіцыя</string>
<string name="sharing_time">"Час абмену "</string>
<string name="sharing_time">Час абмену</string>
<string name="expire_at">Сыходзіць</string>
<string name="stop_sharing_all">Абмен уключаны (выключыць)</string>
<string name="turn_off_location_sharing">Выключыць абмен</string>
@ -168,9 +168,7 @@
<string name="shared_string_hour_short">г</string>
<string name="shared_string_minute_short">хвіл</string>
<string name="shared_string_second_short">сек</string>
<string name="welcome_descr">
<b>Назіральнік OsmAnd</b> Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.<br/>
<br/> Дадатак выкарыстоўвае Telegram API, таму вам неабходны акаўнт Тэлеграм.</string>
<string name="welcome_descr"><b>Назіральнік OsmAnd</b> Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.<br/> <br/> Дадатак выкарыстоўвае Telegram API, таму вам неабходны акаўнт Тэлеграм.</string>
<string name="my_location">Маё месцазнаходжанне</string>
<string name="live_now">Зараз дзейнічае</string>
<string name="send_location_as">Адправіць месцазнаходжанне як</string>
@ -246,10 +244,10 @@
<string name="timeline_no_data_descr">Даныя для абранага дня адсутнічаюць</string>
<string name="timeline_no_data">Няма даных</string>
<string name="shared_string_end">Канец</string>
<string name="shared_string_start">Пачатак</string>
<string name="shared_string_start">Запусціць назіральнік</string>
<string name="shared_string_apply">Ужыць</string>
<string name="set_time_timeline_descr">Абраць час для паказу</string>
<string name="start_end_date">Пачатак - дата завяршэння</string>
<string name="start_end_date">Дата пачатку - дата завяршэння</string>
<string name="saved_messages">Захаваныя паведамленні</string>
<string name="time_zone_descr">Абярыце часавы пояс, каб паказваць ваш час у паведамленнях.</string>
<string name="time_zone">Часавы пояс</string>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="shared_string_suggested">Kinniget</string>
<string name="back_to_osmand">Distreiñ da OsmAnd</string>
<string name="duration_ago">%1$e \'zo</string>
<string name="shared_string_error_short">FAZI</string>
</resources>

View file

@ -18,7 +18,7 @@
<string name="share_location_as">Standort teilen als</string>
<string name="live_now_description">Kontakte und Gruppen, die ihren Standort mit Ihnen teilen.</string>
<string name="logout_from_osmand_telegram">Aus OsmAnd Tracker abmelden\?</string>
<string name="shared_string_name">"Name "</string>
<string name="shared_string_name">Name</string>
<string name="by_distance">Nach Entfernung</string>
<string name="by_name">Nach Namen</string>
<string name="by_group">Nach Gruppe</string>
@ -44,7 +44,7 @@
<string name="send_my_location">Meinen Standort senden</string>
<string name="gps_and_location">Position</string>
<string name="open_osmand">OsmAnd öffnen</string>
<string name="shared_string_live">"Live "</string>
<string name="shared_string_live">Live</string>
<string name="get_telegram_title">Registrierung in Telegram</string>
<string name="get_telegram_account_first">Sie benötigen ein Telegram-Konto, um die Standortfreigabe nutzen zu können.</string>
<string name="get_telegram_description_continue">Bitte installieren Sie Telegram und richten Sie ein Konto ein.</string>
@ -151,9 +151,7 @@
<string name="start_location_sharing">Standort freigeben</string>
<string name="location_service_no_gps_available">Wählen Sie einen der Standortanbieter aus, um Ihren Standort freizugeben.</string>
<string name="sharing_location">Standort teilen</string>
<string name="welcome_descr">
<b>OsmAnd Tracker</b> ermöglicht es Ihnen, Ihren Standort zu teilen und den anderer in OsmAnd zu sehen.<br/>
<br/>Die App verwendet die API von Telegram, also benötigen Sie ein Telegram-Konto.</string>
<string name="welcome_descr"><b>OsmAnd Tracker</b> ermöglicht es Ihnen, Ihren Standort zu teilen und den anderer in OsmAnd zu sehen.<br/> <br/>Die App verwendet die API von Telegram, also benötigen Sie ein Telegram-Konto.</string>
<string name="enter_another_device_name">Wählen Sie einen Namen, den Sie noch nicht benutzt haben</string>
<string name="device_added_successfully">%1$s hinzugefügt.</string>
<string name="shared_string_add">Hinzufügen</string>

View file

@ -77,7 +77,7 @@
<string name="shared_string_back">Atzera</string>
<string name="start_location_sharing">Partekatu kokapena</string>
<string name="show_on_map">Erakutsi mapan</string>
<string name="app_name">OsmAnd Online GPS Tracker</string>
<string name="app_name">OsmAnd lineako GPS aztarnaria</string>
<string name="phone_number_title">Telefono zenbakia</string>
<string name="phone_number_descr">Telefono zenbakia formatu internazionalean</string>
<string name="shared_string_password">Pasahitza</string>
@ -100,7 +100,7 @@
<string name="shared_string_distance">Distantzia</string>
<string name="share_location">Partekatu kokapena</string>
<string name="sharing_location">Partekatzen kokapena</string>
<string name="process_service">OsmAnd Tracker zebitzua</string>
<string name="process_service">OsmAnd aztarnaria zerbitzua</string>
<string name="osmand_logo">OsmAnd logoa</string>
<string name="install_osmand_dialog_message">OsmAnd doako edo ordainpeko bertsioa instalatu behar duzu lehenik</string>
<string name="install_osmand">Instalatu OsmAnd</string>
@ -199,15 +199,15 @@
<string name="buffer_time_descr">Bufferraren puntuak gordetzeko gehieneko denbora</string>
<string name="buffer_time">Bufferraren iraungitze-denbora</string>
<string name="shared_string_suggested">Iradokita</string>
<string name="status_widget_title">OsmAnd Tracker-en egoera</string>
<string name="status_widget_title">OsmAnd aztarnariaren egoera</string>
<string name="back_to_osmand">Atzera OsmAnd-era</string>
<string name="last_response_date">Azken erantzuna: %1$s</string>
<string name="last_update_from_telegram_duration">Telegram-en azken eguneraketa duela %1$s</string>
<string name="last_response_duration">Azken erantzuna duela %1$s</string>
<string name="duration_ago">duela %1$s</string>
<string name="welcome_descr"><b>OsmAnd Tracker</b>-ri esker, kokapena partekatu dezakezu eta besteena OsmAnd-en ikus. <br/> <br/> Aplikazioak Telegram APIa erabiltzen du eta, beraz, Telegram kontua behar duzu.</string>
<string name="welcome_descr"><b>OsmAnd aztarnaria</b>-ri esker, kokapena partekatu dezakezu eta besteena OsmAnd-en ikus. <br/> <br/> Aplikazioak Telegram APIa erabiltzen du eta, beraz, Telegram kontua behar duzu.</string>
<string name="shared_string_authorization_descr">Sartu zure Telegram-eko telefono zenbakia nazioarteko formatuan</string>
<string name="osmand_service_descr">OsmAnd Tracker atzeko planoan exekutatzen da pantaila itzalita dagoenean.</string>
<string name="osmand_service_descr">OsmAnd aztarnaria atzeko planoan exekutatzen da pantaila itzalita dagoenean.</string>
<string name="location_service_no_gps_available">Hautatu kokapen-hornitzaileetako bat zure kokapena partekatzeko.</string>
<string name="no_location_permission">Aplikazioak ez du kokapena atzitzeko baimenik.</string>
<string name="authentication_code_descr">"Telegramek kode bat bidali dizu OsmAnd-ek zure kontuan saioa hasteko."</string>
@ -234,11 +234,11 @@
<string name="stale_location_desc">Kontaktu bat mugitu zen azken aldia.</string>
<string name="location_history_desc">Ezkutatu denbora jakin batean mugitu ez diren kontaktuak</string>
<string name="osmand_connect">OsmAnd konexioa</string>
<string name="osmand_connect_desc">Aukeratu OsmAnd Tracker-ek posizioak bistaratzeko erabiliko duen OsmAnd bertsioa.</string>
<string name="osmand_connect_desc">Aukeratu OsmAnd aztarnariak posizioak bistaratzeko erabiliko duen OsmAnd bertsioa.</string>
<string name="in_time">%1$s-n</string>
<string name="logout_help_desc">Nola itzali OsmAnd Tracker Telegram-etik</string>
<string name="disconnect_from_telegram">Nola itzali OsmAnd Tracker Telegram-etik</string>
<string name="disconnect_from_telegram_desc">Kokapena partekatzeko sarbidea baliogabetzeko. Ireki Telegram, joan Ezarpenak → Pribatutasuna eta segurtasuna → Saioak eta amaitu OsmAnd Tracker saioa atalera.</string>
<string name="logout_help_desc">Nola itzali OsmAnd aztarnaria Telegram-etik</string>
<string name="disconnect_from_telegram">Nola itzali OsmAnd aztarnaria Telegram-etik</string>
<string name="disconnect_from_telegram_desc">Kokapena partekatzeko sarbidea baliogabetzeko. Ireki Telegram, joan Ezarpenak → Pribatutasuna eta segurtasuna → Saioak eta amaitu OsmAnd aztarnariaren saioa atalera.</string>
<string name="logout_no_internet_msg">"Konektatu Internetera Telegram saioa behar bezala amaiatzeko."</string>
<string name="last_response">Azken erantzuna</string>
<string name="disable_all_sharing_desc">Kokapena partekatzea itzaltzen du hautatutako txat guztietan (%1$d).</string>
@ -246,8 +246,8 @@
<string name="by_group">Taldearen arabera</string>
<string name="by_name">Izenaren arabera</string>
<string name="by_distance">Distantziaren arabera</string>
<string name="logout_from_osmand_telegram">Amaitu OsmAnd Tracker saioa\?</string>
<string name="logout_from_osmand_telegram_descr">Ziur zaude OsmAnd Tracker saioa amaitu nahi duzula\? Ezingo duzu kokapena partekatu edo besteen kokapena ikusi</string>
<string name="logout_from_osmand_telegram">Amaitu OsmAnd aztarnariaren saioa\?</string>
<string name="logout_from_osmand_telegram_descr">Ziur zaude OsmAnd aztarnariaren saioa amaitu nahi duzula\? Ezingo duzu kokapena partekatu edo besteen kokapena ikusi</string>
<string name="live_now_description">Zurekin kokapena partekatzen duten kontaktuak eta taldeak.</string>
<string name="location_sharing_status">Partekatzen:% 1 $ s</string>
<string name="sharing_status">Partekatze egoera</string>
@ -255,7 +255,7 @@
<string name="not_found_yet">Oraindik ez da aurkitu</string>
<string name="not_sent_yet">Oraindik ez da bidali</string>
<string name="sharing_in_background">Atzeko planoan partekatzea</string>
<string name="battery_optimization_description">Itzali bateriaren optimizazioa OsmAnd Trackerrentzat, bat-batean itzali ez dadin bigarren planoan dagoela.</string>
<string name="battery_optimization_description">Itzali bateriaren optimizazioa OsmAnd aztarnariarentzat, bat-batean itzali ez dadin bigarren planoan dagoela.</string>
<string name="background_work">Bigarren planoko lana</string>
<string name="background_work_description">Aldatu bateriaren optimizazio ezarpenak kokapena partekatzea egonkortzeko.</string>
<string name="waiting_for_response_from_telegram">Telegram-en erantzunaren zain</string>
@ -265,6 +265,6 @@
<string name="share_location_as_description">Hainbat gailu Telegram kontu bakarrera konektatu nahi badituzu, gailu desberdinak erabili behar dituzu kokapena partekatzeko.</string>
<string name="share_location_as_description_second_line">Telegrama bezeroan gailuaren IDa sortu eta ikusi dezakezu %1$s txat bota erabiliz. % 2 $ s</string>
<string name="privacy_policy_agree">\"Jarraitu\" sakatuz, Telegram eta OsmAnd pribatutasun-politiken baldintzak onartzen dituzu.</string>
<string name="privacy_policy_telegram_client">OsmAnd tracker-ek Telegram plataforma irekia erabiltzen duten bezeroetako bat da. Zure kontaktuek Telegram-eko beste edozein bezero erabil dezakete.</string>
<string name="privacy_policy_telegram_client">OsmAnd aztarnariak Telegram plataforma irekia erabiltzen duten bezeroetako bat da. Zure kontaktuek Telegram-eko beste edozein bezero erabil dezakete.</string>
<string name="last_update_from_telegram_date">Telegram-eko azken eguneratzea: %1$s</string>
</resources>

View file

@ -90,12 +90,12 @@
<string name="initializing">Estase a iniciar</string>
<string name="searching_for_gps">Estase a ubicar…</string>
<string name="connecting_to_the_internet">Estase a conectar á Internet</string>
<string name="battery_optimization_description">Desactiva-la optimización da batería para o OsmAnd Tracker de xeito que non se desconecte de xeito súbito cando esté no segundo plano.</string>
<string name="battery_optimization_description">Desactivar a optimización da batería para o OsmAnd Tracker de xeito que non se desconecte de xeito súbito cando estea no segundo plano.</string>
<string name="logout_no_internet_msg">Conéctate á Internet para pecha-la sesión no Telegram de xeito correcto.</string>
<string name="disconnect_from_telegram_desc">Para revoga-lo acceso á ubicación compartillada. Abre o Telegram, vai cara ós «Axustes → Privacidade e Seguranza → Sesións» e pecha a sesión do OsmAnd Tracker.</string>
<string name="disconnect_from_telegram">De que xeito desactivar o rastrexador do OsmAnd (OsmAnd Tracker) dende o Telegram</string>
<string name="logout_help_desc">De que xeito desactivar o rastrexador do OsmAnd (OsmAnd Tracker) dende o Telegram</string>
<string name="osmand_connect_desc">Escolle a versión do OsmAnd na cal o rastrexador do OsmAnd (OsmAnd Tracker) empregará para amosa-las ubicacións.</string>
<string name="osmand_connect_desc">Escolle a versión do OsmAnd na cal o OsmAnd Tracker empregará para amosar as posicións.</string>
<string name="osmand_connect">Conectar ó OsmAnd</string>
<string name="location_history_desc">Agocha-los contactos que non se moveron nun tempo determinado.</string>
<string name="stale_location_desc">A última vez que un contacto se moveu.</string>
@ -195,7 +195,7 @@
<string name="shared_string_telegram">Telegram</string>
<string name="privacy_policy_use_telegram">O Telegram (a aplicación de mensaxaría) emprégase para conectar e comunicar ás persoas.</string>
<string name="privacy_policy_telegram_client">O rastrexador do OsmAnd (OsmAnd tracker) é un dos clientes que emprega a plataforma aberta do Telegram. Os teus contactos poden empregar calquera outro cliente do Telegram.</string>
<string name="privacy_policy_agree">Ó premer en continuar, aceptas as Políticas de Privacidade do Telegram e do OsmAnd.</string>
<string name="privacy_policy_agree">Ó premer en \"Continuar\", aceptas as condicións do Telegram e as políticas de privacidade do OsmAnd.</string>
<string name="shared_string_accept">Aceptar</string>
<string name="telegram_privacy_policy">Política de privacidade do Telegram</string>
<string name="osmand_privacy_policy">Política de privacidade do OsmAnd</string>
@ -216,4 +216,56 @@
<string name="search_contacts_descr">Procura en tódolos teus grupos e contactos.</string>
<string name="type_contact_or_group_name">Escribe o nome do contacto ou do grupo</string>
<string name="shared_string_search">Procurar</string>
<string name="status_widget_title">Estado do Rastrexador do OsmAnd</string>
<string name="shared_string_suggested">Suxerido</string>
<string name="back_to_osmand">Voltar ó OsmAnd</string>
<string name="duration_ago">hai %1$s</string>
<string name="last_response_duration">Última resposta: hai %1$s</string>
<string name="last_update_from_telegram_duration">Última actualización dende o Telegram: hai %1$s</string>
<string name="last_response_date">Última resposta: %1$s</string>
<string name="last_update_from_telegram_date">Última actualización dende o Telegram: %1$s</string>
<string name="shared_string_error_short">ERR</string>
<string name="bearing">Traxectoria</string>
<string name="altitude">Altitude</string>
<string name="precision">Precisión</string>
<string name="direction">Enderezo</string>
<string name="privacy">Privacidade</string>
<string name="proxy">Proxy</string>
<string name="proxy_settings">Axustes do proxy</string>
<string name="proxy_disconnected">Desconectado</string>
<string name="proxy_connected">Conectado</string>
<string name="proxy_type">Tipo de proxy</string>
<string name="shared_string_enable">Activar</string>
<string name="shared_string_connection">Conexión</string>
<string name="proxy_server">Servidor</string>
<string name="proxy_port">Porto</string>
<string name="proxy_credentials">Credenciais</string>
<string name="proxy_username">Nome de usuario</string>
<string name="proxy_password">Contrasinal</string>
<string name="proxy_key">Chave</string>
<string name="gpx_settings">Axustes de GPX</string>
<string name="min_logging_speed_descr">Filtro: sen rexistro por embaixo da velocidade escollida</string>
<string name="min_logging_speed">Velocidade mínima de rexistro</string>
<string name="min_logging_accuracy_descr">Filtro: sen registro a menos que se acade a precisión</string>
<string name="min_logging_accuracy">Precisión mínima de rexistro</string>
<string name="min_logging_distance_descr">Filtro: distancia mínima para rexistrar un novo punto</string>
<string name="min_logging_distance">Distancia mínima de rexistro</string>
<string name="shared_string_select">Escoller</string>
<string name="timeline_no_data">Sen datos</string>
<string name="timeline_no_data_descr">Non temos datos recollidos para o día escollido</string>
<string name="start_end_date">Data de comezo — Fin</string>
<string name="set_time_timeline_descr">Escoller a hora para a visualización</string>
<string name="shared_string_apply">Aplicar</string>
<string name="shared_string_start">Comezo</string>
<string name="shared_string_end">Fin</string>
<string name="saved_messages">Mensaxes gardadas</string>
<string name="unit_of_speed_system">Unidade de velocidade</string>
<string name="unit_of_speed_system_descr">Definir unidade de velocidade.</string>
<string name="unit_of_length">Unidades de lonxitude</string>
<string name="unit_of_length_descr">Mudar as unidades de lonxitude.</string>
<string name="units_and_formats">Unidades e formatos</string>
<string name="time_zone">Fuso horario</string>
<string name="time_zone_descr">Escolle a zona horaria que desexas amosar nas mensaxes de localización.</string>
<string name="buffer_time">Tempo de caducidade do búfer</string>
<string name="buffer_time_descr">Tempo máximo para almacenar puntos no búfer</string>
</resources>

View file

@ -26,7 +26,7 @@
<string name="searching_for_gps">Posicionando…</string>
<string name="connecting_to_the_internet">Conectando-se à Internet</string>
<string name="background_work_description">Altere as configurações de otimização da bateria para estabilizar o compartilhamento de local.</string>
<string name="background_work">"Funcionamento em segundo plano "</string>
<string name="background_work">Funcionamento em segundo plano</string>
<string name="battery_optimization_description">Desative a otimização da bateria do OsmAnd Tracker para que ele não seja desligado repentinamente quando estiver em segundo plano.</string>
<string name="sharing_in_background">Compartilhando em segundo plano</string>
<string name="go_to_settings">Vá para as configurações</string>
@ -72,7 +72,7 @@
<string name="shared_string_account">Conta</string>
<string name="in_time">no %1$s</string>
<string name="osmand_connect_desc">Escolha a versão OsmAnd que OsmAnd Tracker usa para exibir posições.</string>
<string name="osmand_connect">"Conectar OsmAnd "</string>
<string name="osmand_connect">Conectar OsmAnd</string>
<string name="location_history_desc">Ocultar contatos que não foram movidos em um determinado momento.</string>
<string name="location_history">Histórico de localização</string>
<string name="stale_location_desc">A última vez que um contato foi movido.</string>
@ -173,9 +173,7 @@
<string name="shared_string_hour_short">h</string>
<string name="shared_string_minute_short">min</string>
<string name="shared_string_second_short">seg</string>
<string name="welcome_descr">
<b>OsmAnd Tracker</b> permite que você compartilhe sua localização e veja a dos outros no OsmAnd.<br/>
<br/>O aplicativo usa a API Telegram e você precisa de uma conta Telegram.</string>
<string name="welcome_descr"><b>OsmAnd Tracker</b> permite que você compartilhe sua localização e veja a dos outros no OsmAnd.<br/> <br/>O aplicativo usa a API Telegram e você precisa de uma conta Telegram.</string>
<string name="my_location">Minha localização</string>
<string name="live_now">Ao vivo agora</string>
<string name="monitoring_is_enabled">Monitoramento está ativado</string>
@ -186,13 +184,13 @@
<string name="open_in_osmand">Mostrar no OsmAnd</string>
<string name="end_date">Data final</string>
<string name="start_date">Data de início</string>
<string name="timeline">"Linha do tempo "</string>
<string name="timeline">Linha do tempo</string>
<string name="gps_points_in_buffer">enviado (%1$d em buffer)</string>
<string name="points_size">"%1$d pontos "</string>
<string name="points_size">%1$d pontos</string>
<string name="shared_string_date">Data</string>
<string name="shared_string_collected">Coletado</string>
<string name="gps_points">Pontos de GPS</string>
<string name="shared_string_sent">"Enviar "</string>
<string name="shared_string_sent">Enviar</string>
<string name="please_update_osmand">Por favor, atualize o OsmAnd para ver os dados no mapa</string>
<string name="shared_string_update">Atualizar</string>
<string name="shared_string_telegram">Telegram</string>
@ -201,7 +199,7 @@
<string name="privacy_policy_agree">Ao clicar em \"Continuar\", você concorda com as condições da política de privacidade do Telegram- e OsmAnd.</string>
<string name="shared_string_accept">Aceitar</string>
<string name="telegram_privacy_policy">Política de privacidade do Telegram</string>
<string name="osmand_privacy_policy">"Política de privacidade do OsmAnd "</string>
<string name="osmand_privacy_policy">Política de privacidade do OsmAnd</string>
<string name="how_it_works">Como funciona</string>
<string name="received_gps_points">Pontos GPX recebidos: %1$s</string>
<string name="shared_string_appearance">Aparência</string>

View file

@ -137,7 +137,7 @@
<string name="last_available_location">Последнее местоположение</string>
<string name="sharing_status">Статус отправки</string>
<string name="location_sharing_status">Трансляция: %1$s</string>
<string name="shared_string_enabled">Включён</string>
<string name="shared_string_enabled">Включено</string>
<string name="shared_string_status">Статус</string>
<string name="no_gps_connection">Отсутствует GPS</string>
<string name="no_internet_connection">Отсутствует интернет</string>

View file

@ -53,4 +53,5 @@
<string name="units_and_formats">Мерне јединице &amp; форматирања</string>
<string name="unit_of_length_descr">Промени јединице за дужину.</string>
<string name="unit_of_length">Јединице дужине</string>
<string name="shared_string_appearance">Изглед</string>
</resources>

View file

@ -60,11 +60,11 @@
<string name="start_end_date">Başlangıç — Bitiş tarihi</string>
<string name="timeline_no_data_descr">Seçilen gün için toplanan veri yok</string>
<string name="timeline_no_data">Veri yok</string>
<string name="min_logging_distance">Minimum kayıt mesafesi</string>
<string name="min_logging_distance_descr">Filtre: yeni bir nokta kaydetmek için minimum mesafe</string>
<string name="min_logging_accuracy">Minimum kayıt hassasiyeti</string>
<string name="min_logging_accuracy_descr">Filtre: hassasiyete ulaşılmadığı sürece kaydetme yok</string>
<string name="min_logging_speed">Minimum kayıt hızı</string>
<string name="min_logging_distance">Asgari kayıt mesafesi</string>
<string name="min_logging_distance_descr">Filtre: yeni bir nokta kaydetmek için asgari mesafe</string>
<string name="min_logging_accuracy">Asgari kayıt doğruluğu</string>
<string name="min_logging_accuracy_descr">Filtre: bu doğruluğa ulaşılmadıkça kaydetme yok</string>
<string name="min_logging_speed">Asgari kayıt hızı</string>
<string name="min_logging_speed_descr">Filtre: seçili hızın altında kaydetme yok</string>
<string name="gpx_settings">GPX ayarları</string>
<string name="proxy_key">Anahtar</string>
@ -81,7 +81,7 @@
<string name="proxy">Proxy</string>
<string name="privacy">Gizlilik</string>
<string name="direction">Yön</string>
<string name="precision">Hassaslık</string>
<string name="precision">Hassasiyet</string>
<string name="search_contacts">Kişileri ara</string>
<string name="search_contacts_descr">Tüm gruplarınızda ve kişilerinizde arayın.</string>
<string name="type_contact_or_group_name">Kişi veya grup adı yazın</string>
@ -182,7 +182,7 @@
<string name="location_history">Konum geçmişi</string>
<string name="stale_location_desc">Bir kişinin en son hareket ettiği zaman.</string>
<string name="stale_location">Hareket etmiyor</string>
<string name="send_my_location_desc">Konum paylaşımı için minimum aralığı ayarlayın.</string>
<string name="send_my_location_desc">Konum paylaşımı için en küçük aralığı ayarlayın.</string>
<string name="send_my_location">Konumumu gönder</string>
<string name="gps_and_location">Konum</string>
<string name="sharing_time">Paylaşım zamanı</string>
@ -256,7 +256,7 @@
<string name="unit_of_length">Uzunluk birimleri</string>
<string name="unit_of_speed_system_descr">Hız birimini tanımlayın.</string>
<string name="unit_of_speed_system">Hız birimi</string>
<string name="buffer_time_descr">Noktaların arabellekte saklanacağı maksimum süre</string>
<string name="buffer_time_descr">Noktaların arabellekte saklanacağı azami süre</string>
<string name="buffer_time">Arabellek zaman aşım süresi</string>
<string name="shared_string_suggested">Önerilen</string>
<string name="status_widget_title">OsmAnd Tracker durumu</string>

View file

@ -524,7 +524,7 @@ dependencies {
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'com.google.android.material:material:1.2.0-beta01'
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.preference:preference:1.1.0'
implementation fileTree(include: ['gnu-trove-osmand.jar', 'icu4j-49_1_patched.jar'], dir: 'libs')

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 971 B

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 939 B

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1,012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 529 B

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 955 B

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show more