Restructure repository

This commit is contained in:
Victor Shcherb 2012-12-12 02:10:00 +01:00
parent a8e13aadbf
commit 3db27de275
620 changed files with 0 additions and 199096 deletions

View file

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="icons"/>
<classpathentry kind="src" path="src-tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>
<classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/json-20090211.jar"/>
<classpathentry kind="lib" path="lib/h2-latest.jar"/>
<classpathentry kind="lib" path="lib/bsh-core-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/junidecode-0.1.jar"/>
<classpathentry kind="lib" path="lib/jleveldb-v01.jar"/>
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar"/>
<classpathentry kind="lib" path="lib/jsch-20120101.jar"/>
<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.18-bin.jar"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<classpathentry kind="lib" path="lib/icu4j-49_1.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/OsmAnd-java"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -1,5 +0,0 @@
bin/
build/
build.zip
cpd.xml
/bin-tests

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DataExtractionOSM</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
</projectDescription>

View file

@ -1,3 +0,0 @@
#Thu Apr 29 00:40:46 EEST 2010
eclipse.preferences.version=1
encoding/<project>=UTF-8

View file

@ -1,3 +0,0 @@
#Mon Oct 10 15:40:12 CEST 2011
eclipse.preferences.version=1
line.separator=\n

View file

@ -1,80 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

View file

@ -1,4 +0,0 @@
REM the JVM. With the below settings the heap size (Available memory for the application)
REM will range from 64 megabyte up to 720 megabyte.
start javaw.exe -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx720M -cp "./OsmAndMapCreator.jar;./lib/*.jar" net.osmand.swing.OsmExtractionUI

View file

@ -1,7 +0,0 @@
#!/bin/sh
# This file will start the Osm Extraction UI with custom memory settings for
# the JVM. With the below settings the heap size (Available memory for the application)
# will range from 64 megabyte up to 720 megabyte.
java -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx720M -cp "./OsmAndMapCreator.jar:./lib/*.jar" net.osmand.swing.OsmExtractionUI

View file

@ -1,171 +0,0 @@
<!-- build JAR libraty -->
<project name="DataExtractionOSM" default="build" basedir=".">
<property file="local.properties" />
<property name="file.to.upload" value="OsmAndMapCreator-nightbuild.zip"/>
<property name="src.dir" value="src"/>
<property name="osmand-core.dir" location="../OsmAnd-java/"/>
<property name="osmand-core.jar" value="OsmAnd-core.jar"/>
<property name="src.absolute.dir" location="${src.dir}" />
<property name="icons.dir" value="icons/resources"/>
<property name="icons.absolute.dir" location="${icons.dir}" />
<property name="bin.dir" value="bin"/>
<property name="bintests.dir" value="bin-tests"/>
<property name="bin.absolute.dir" location="${bin.dir}" />
<property name="lib.dir" value="lib"/>
<property name="lib.absolute.dir" location="${lib.dir}" />
<property name="java.encoding" value="UTF-8" />
<property name="srctests.dir" value="src-tests"/>
<property name="reports.tests" value="${basedir}/test-results" />
<path id="build.path">
<fileset dir="${osmand-core.dir}">
<include name="${osmand-core.jar}"/>
</fileset>
<fileset dir="${lib.absolute.dir}">
<include name="*.jar"/>
</fileset>
</path>
<target name="-dirs">
<mkdir dir="${bin.absolute.dir}"/>
<mkdir dir="${bintests.dir}"/>
</target>
<target name="-copy-resources">
<mkdir dir="${icons.absolute.dir}"/>
<copy todir="${icons.absolute.dir}">
<fileset dir="../OsmAnd/res/drawable-mdpi/">
<include name="h_*.png"/>
<include name="g_*.png"/>
</fileset>
</copy>
<ant antfile="${osmand-core.dir}/build.xml" target="jar" >
</ant>
</target>
<target name="-version" if="build.version">
<replace file="src/net/osmand/MapCreatorVersion.java" token="String APP_DESCRIPTION" value="String APP_DESCRIPTION=&quot;${build.version}&quot;;//"/>
</target>
<target name="clean">
<delete dir="${bin.absolute.dir}"/>
</target>
<target name="compile" depends="-copy-resources,-dirs,-version">
<copy todir="${bin.absolute.dir}">
<fileset dir="${src.absolute.dir}">
<exclude name="**/*.java" />
</fileset>
</copy>
<javac srcdir="${src.absolute.dir}"
destdir="${bin.absolute.dir}"
encoding="${java.encoding}"
classpathref="build.path"
debug="on"
source="1.6"
/>
<javac srcdir="${srctests.dir}"
destdir="${bintests.dir}"
encoding="${java.encoding}"
classpathref="test.classpath"
debug="on"
source="1.6"
/>
</target>
<path id="test.classpath">
<pathelement location="${bin.absolute.dir}" />
<pathelement location="${bintests.dir}" />
<pathelement location="${srctests.dir}" />
<fileset dir="${osmand-core.dir}">
<include name="${osmand-core.jar}"/>
</fileset>
<fileset dir="${lib.absolute.dir}">
<include name="*.jar" />
</fileset>
</path>
<target name="junits" depends="compile">
<junit fork="false">
<sysproperty key="basedir" value="${basedir}"/>
<!-- <sysproperty key="OBF_DIR" value="${obfdir}"/> -->
<classpath refid="test.classpath"/>
<formatter type="xml" />
<!-- test name="net.osmand.router.test.JUnitRouteTest" todir="${basedir}/test-results" /-->
<batchtest fork="false" todir="${reports.tests}" >
<fileset dir="${srctests.dir}" >
<include name="**/*Test*.java" />
<exclude name="**/AllTests.java" />
<exclude name="**/*Suite*.java" />
</fileset>
</batchtest>
</junit>
</target>
<target name="jar" depends="-copy-resources, -dirs, compile">
<manifestclasspath property="lib.list" jarfile="OsmAndMapCreator.jar">
<classpath refid="build.path"/>
</manifestclasspath>
<echo>list is ${lib.list}</echo>
<delete file="OsmAndMapCreator.jar" />
<delete file="MANIFEST.MF" />
<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}" />
<attribute name="Main-Class" value="net.osmand.swing.OsmExtractionUI" />
<attribute name="Class-Path" value="${lib.list}"/>
</manifest>
<jar destfile="OsmAndMapCreator.jar" manifest="MANIFEST.MF">
<fileset dir="${bin.absolute.dir}">
<include name="**/*" />
</fileset>
<fileset dir="${icons.absolute.dir}/..">
<include name="**/*" />
</fileset>
<fileset dir="${src.absolute.dir}">
<include name="**/*.java" />
</fileset>
</jar>
<delete file="MANIFEST.MF" />
</target>
<target name="build" depends="jar, junits">
<delete dir="build"/>
<copy todir="build">
<fileset dir=".">
<include name="OsmAndMapCreator.jar"/>
<include name="lib/**"/>
<include name="logging.properties"/>
<include name="*.bat"/>
<include name="*.sh"/>
<exclude name="lib/h2*"/>
</fileset>
<fileset dir="src/net/osmand/osm/">
<include name="rendering_types.xml"/>
</fileset>
<fileset dir=".">
<include name="../build-scripts/regions/indexes.xml" />
</fileset>
<fileset dir="src/net/osmand/data/index">
<include name="batch.xml" />
</fileset>
</copy>
<copy todir="build/lib">
<fileset dir="${osmand-core.dir}">
<include name="${osmand-core.jar}" />
</fileset>
</copy>
<zip destfile="build.zip">
<fileset dir="build">
</fileset>
</zip>
<delete file="OsmAndMapCreator.jar" />
</target>
</project>

View file

@ -1,20 +0,0 @@
<!-- build JAR libraty -->
<project name="DataExtractionOsm" default="all" basedir=".">
<target name="build">
<exec dir="." executable="protoc">
<arg value="src/osmand_odb.proto" />
<arg value="--java_out=./src/" />
</exec>
</target>
<target name="all" depends="build,cpp"/>
<target name="cpp">
<exec dir="." executable="protoc">
<arg value="src/osmand_odb.proto" />
<arg value="--cpp_out=../Osmand-kernel/osmand/src/proto" />
</exec>
</target>
</project>

View file

@ -1 +0,0 @@
resources

View file

@ -1 +0,0 @@
java.exe -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx512M -cp "./OsmAndMapCreator.jar;./lib/*.jar" net.osmand.binary.BinaryInspector %1 %2 %3 %4 %5 %6 %7 %8 %9

View file

@ -1,7 +0,0 @@
#!/bin/sh
# This file will start the Osm Extraction UI with custom memory settings for
# the JVM. With the below settings the heap size (Available memory for the application)
# will range from 64 megabyte up to 512 megabyte.
java -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx512M -cp "./OsmAndMapCreator.jar:./lib/*.jar" net.osmand.binary.BinaryInspector $@

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked in Version Control Systems,
# as it contains information specific to your local configuration.
# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
ftp.user=osmand
ftp.password=

View file

@ -1,14 +0,0 @@
.level = SEVERE
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
# Set the default logging level for the logger named com.mycompany
net.osmand.level = ALL
# configured in java code (In working dir) by default %h/Osmand/osmand.log
# java.util.logging.FileHandler.pattern=%h/Application Data/Osmand/osmand.log
#java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
#java.util.logging.FileHandler.append = true
#java.util.logging.FileHandler.limit = 5000000
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

Binary file not shown.

View file

@ -1,2 +0,0 @@
% Pass full paths to route_tests.xml files. All routing.xml configuration should be configured by OsmAndMapCreator
java.exe -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx512M -cp "./OsmAndMapCreator.jar;./lib/*.jar" net.osmand.router.test.RouterTestsSuite %1 %2 %3 %4 %5 %6 %7 %8 %9

View file

@ -1,8 +0,0 @@
#!/bin/sh
# This file will start the Osm Extraction UI with custom memory settings for
# the JVM. With the below settings the heap size (Available memory for the application)
# will range from 64 megabyte up to 512 megabyte.
# Pass full paths to route_tests.xml files. All routing.xml configuration should be configured by OsmAndMapCreator
java -Djava.util.logging.config.file=logging.properties -Xms64M -Xmx512M -cp "./OsmAndMapCreator.jar:./lib/*.jar" net.osmand.router.test.RouterTestsSuite $@

View file

@ -1,28 +0,0 @@
package net.osmand.data;
import com.ibm.icu.text.ArabicShaping;
import com.ibm.icu.text.ArabicShapingException;
import com.ibm.icu.text.Bidi;
public class ArabicShaper {
public static void main(String[] args) throws ArabicShapingException {
ArabicShaping as = new ArabicShaping(ArabicShaping.LETTERS_SHAPE |
ArabicShaping.LENGTH_GROW_SHRINK);
String s = "אנשים 12";
// for (int i = 0; i < s.length(); i++) {
// System.out.println(s.charAt(i));
// }
Bidi bd = new Bidi(s.length(), s.length());
bd.setPara(s, Bidi.LEVEL_DEFAULT_LTR, null);
System.out.println(bd.baseIsLeftToRight());
String r = as.shape(s);
// for (int i = 0; i < r.length(); i++) {
// System.out.println(r.charAt(i));
// }
System.out.println(r);
}
}

View file

@ -1,229 +0,0 @@
package net.osmand.data;
import static org.junit.Assert.*;
import net.osmand.osm.LatLon;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import org.junit.Before;
import org.junit.Test;
public class MultipolygonTest {
private Multipolygon testee;
private Way poly1_1_of_2;
private Way poly1_2_of_2;
private int wayid;
private Way poly2;
private Way openedBaseCircle;
private Way closedBaseCircle;
@Before
public void setUp()
{
testee = new Multipolygon();
poly1_1_of_2 = polygon(n(0,0),n(1,0),n(1,1),n(1,2));
poly1_2_of_2 = polygon(n(1,2),n(0,2),n(-1,2),n(0,0));
poly2 = polygon(n(4,4), n(4,5), n(3,5), n(4,4));
openedBaseCircle = polygon(n(1,-1), n(1,1), n(-1,1), n(-1,-1));
closedBaseCircle = polygon(n(1,-1), n(1,1), n(-1,1), n(-1,-1), n(1,-1));
}
public Way polygon(Node... n) {
Way way = new Way(wayid++);
for (Node nn : n) {
way.addNode(nn);
}
return way;
}
public Way scale(int i, Way w) {
Way way = new Way(wayid++);
for (Node nn : w.getNodes()) {
way.addNode(n(i*(int)nn.getLatitude(),i*(int)nn.getLongitude()));
}
return way;
}
public Way move(int i, int j, Way w) {
Way way = new Way(wayid++);
for (Node nn : w.getNodes()) {
way.addNode(n(i+(int)nn.getLatitude(),j+(int)nn.getLongitude()));
}
return way;
}
public Node n(int i, int j) {
return new Node(i, j, i*i + j*j + i*j + i + j); //Node has ID derived from i,j
}
@Test
public void test_twoWayPolygon() {
testee.addOuterWay(poly1_1_of_2);
testee.addOuterWay(poly1_2_of_2);
assertEquals(1, testee.countOuterPolygons());
assertFalse(testee.hasOpenedPolygons());
}
@Test
public void test_ringArea(){
Way w = new Way(0L);
w.addNode(new Node(0.0, 0.0, 1));
w.addNode(new Node(1.0, 0.0, 2));
w.addNode(new Node(1.0, 0.5, 3));
w.addNode(new Node(1.5, 0.5, 4));
w.addNode(new Node(1.0, 1.0, 5));
Multipolygon m = new Multipolygon();
m.addOuterWay(w);
Ring r = m.getOuterRings().get(0);
// calculated with JOSM measurement tool
double expected = 7716818755.73;
// allow 1% deviation because of rounding errors and alternative projections
assertTrue(expected/r.getArea() > 0.99);
assertTrue(expected/r.getArea() < 1.01);
}
@Test
public void test_oneWayPolygon() {
testee.addOuterWay(poly2);
assertEquals(1, testee.countOuterPolygons());
assertFalse(testee.hasOpenedPolygons());
}
@Test
public void test_containsPoint()
{
testee.addOuterWay(scale(4,poly2));
LatLon center = testee.getCenterPoint();
assertTrue(testee.containsPoint(center));
}
@Test
public void test_containsPointOpenedCircle()
{
testee.addOuterWay(scale(4,openedBaseCircle));
LatLon center = testee.getCenterPoint();
assertTrue(testee.containsPoint(center));
}
@Test
public void test_containsPointClosedCircle()
{
testee.addOuterWay(scale(4,openedBaseCircle));
LatLon center = testee.getCenterPoint();
assertTrue(testee.containsPoint(center));
}
@Test
public void test_oneInnerRingOneOuterRingOpenedCircle()
{
test_oneInnerRingOneOuterRing(openedBaseCircle);
}
@Test
public void test_oneInnerRingOneOuterRingClosedCircle()
{
test_oneInnerRingOneOuterRing(closedBaseCircle);
}
public void test_oneInnerRingOneOuterRing(Way polygon)
{
testee.addOuterWay(scale(4,polygon));
LatLon center = testee.getCenterPoint();
assertTrue(testee.containsPoint(center));
Multipolygon mpoly2 = new Multipolygon();
mpoly2.addOuterWay(polygon);
assertTrue(testee.containsPoint(mpoly2.getCenterPoint()));
testee.addInnerWay(polygon);
assertFalse(testee.containsPoint(mpoly2.getCenterPoint()));
}
@Test
public void test_twoInnerRingsOneOuterRingOpenedCircle()
{
test_twoInnerRingsOneOuterRing(openedBaseCircle);
}
@Test
public void test_twoInnerRingsOneOuterRingClosedCircle()
{
test_twoInnerRingsOneOuterRing(closedBaseCircle);
}
public void test_twoInnerRingsOneOuterRing(Way polygon)
{
testee.addOuterWay(scale(40,polygon));
LatLon center = testee.getCenterPoint();
assertTrue(testee.containsPoint(center));
Multipolygon mpoly2 = new Multipolygon();
mpoly2.addOuterWay(polygon);
Multipolygon movepoly2 = new Multipolygon();
movepoly2.addOuterWay(move(10,10,polygon));
assertTrue(testee.containsPoint(mpoly2.getCenterPoint()));
assertTrue(testee.containsPoint(movepoly2.getCenterPoint()));
testee.addInnerWay(polygon);
testee.addInnerWay(move(10,10,polygon));
assertFalse(testee.containsPoint(mpoly2.getCenterPoint()));
assertFalse(testee.containsPoint(movepoly2.getCenterPoint()));
}
@Test
public void test_multipolygon1twoWay2oneWay()
{
testee.addOuterWay(poly1_1_of_2);
testee.addOuterWay(poly1_2_of_2);
testee.addOuterWay(poly2);
assertEquals(2, testee.countOuterPolygons());
assertFalse(testee.hasOpenedPolygons());
}
@Test
public void test_firstEmptyWayThanOpenedWay()
{
testee.addOuterWay(new Way(111));
testee.addOuterWay(poly1_1_of_2);
assertEquals(1, testee.countOuterPolygons());
assertTrue(testee.hasOpenedPolygons());
}
@Test
public void test_mergingExistingPolygons()
{
Way part1 = polygon(n(1,1),n(1,2),n(1,3));
Way part2 = polygon(n(1,3),n(1,4),n(1,5));
Way part3 = polygon(n(1,5),n(1,6),n(1,2));
testee.addOuterWay(part1);
testee.addOuterWay(part3);
testee.addOuterWay(part2);
assertEquals(1, testee.countOuterPolygons());
assertTrue(testee.hasOpenedPolygons());
}
@Test
public void test_mergingExistingPolygonsReversed()
{
Way part1 = polygon(n(1,3),n(1,2),n(1,1));
Way part2 = polygon(n(1,3),n(1,4),n(1,5));
Way part3 = polygon(n(1,5),n(1,6),n(1,2));
testee.addOuterWay(part1);
testee.addOuterWay(part3);
testee.addOuterWay(part2);
assertEquals(1, testee.countOuterPolygons());
assertTrue(testee.hasOpenedPolygons());
}
}

View file

@ -1,80 +0,0 @@
package net.osmand.router;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import net.osmand.Algoritms;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.router.RoutingConfiguration;
import net.osmand.swing.DataExtractionSettings;
import net.osmand.swing.NativeSwingRendering;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@Ignore
public class JUnitRouteTest {
static BinaryMapIndexReader[] rs;
static NativeSwingRendering lib;
@Before
public void setupFiles() throws IOException {
if(rs != null){
return;
}
// test without native because it is not present on the server
// lib = NativeSwingRendering.getDefaultFromSettings();
RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true;
String obfdir = System.getenv("OBF_DIR");
if(Algoritms.isEmpty(obfdir)){
obfdir = DataExtractionSettings.getSettings().getBinaryFilesDir();
}
List<File> files = new ArrayList<File>();
for (File f : new File(obfdir).listFiles()) {
if (f.getName().endsWith(".obf")) {
files.add(f);
}
}
rs = new BinaryMapIndexReader[files.size()];
int it = 0;
for (File f : files) {
RandomAccessFile raf = new RandomAccessFile(f, "r"); //$NON-NLS-1$ //$NON-NLS-2$
rs[it++] = new BinaryMapIndexReader(raf);
}
}
@Test
public void runCZ() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("cz.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNL() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNL2() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl2.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNLLeid() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl_leid.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runBLR() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("blr.test.xml"), rs, RoutingConfiguration.getDefault());
}
}

View file

@ -1,280 +0,0 @@
package net.osmand.router;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import net.osmand.NativeLibrary;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingConfiguration.Builder;
import net.osmand.router.RoutingContext;
import net.osmand.swing.DataExtractionSettings;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class RouterTestsSuite {
public static int MEMORY_TEST_LIMIT = 800;
public static boolean TEST_WO_HEURISTIC = true;
public static boolean TEST_BOTH_DIRECTION = true;
private static class Parameters {
public File obfDir;
public List<File> tests = new ArrayList<File>();
public RoutingConfiguration.Builder configBuilder;
public static Parameters init(String[] args) throws SAXException, IOException {
Parameters p = new Parameters();
String routingXmlFile = null;
String obfDirectory = null;
RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = false;
for (String a : args) {
if (a.startsWith("-routingXmlPath=")) {
routingXmlFile = a.substring("-routingXmlPath=".length());
} else if (a.startsWith("-verbose")) {
RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true;
} else if (a.startsWith("-obfDir=")) {
obfDirectory = a.substring("-obfDir=".length());
} else if (a.startsWith("-testDir=")) {
String testDirectory = a.substring("-testDir=".length());
for(File f : new File(testDirectory).listFiles()) {
if(f.getName().endsWith(".test.xml")){
p.tests.add(f);
}
}
} else if(!a.startsWith("-")){
p.tests.add(new File(a));
}
}
if (obfDirectory == null) {
obfDirectory = DataExtractionSettings.getSettings().getBinaryFilesDir();
}
if (obfDirectory != null && obfDirectory.length() > 0) {
p.obfDir = new File(obfDirectory);
}
if (routingXmlFile == null) {
routingXmlFile = DataExtractionSettings.getSettings().getRoutingXmlPath();
}
if (routingXmlFile.equals("routing.xml")) {
p.configBuilder = RoutingConfiguration.getDefault();
} else {
p.configBuilder = RoutingConfiguration.parseFromInputStream(new FileInputStream(routingXmlFile));
}
return p;
}
}
public static void main(String[] args) throws Exception {
Parameters params = Parameters.init(args);
if(params.tests.isEmpty() || params.obfDir == null) {
println("Run router tests is console utility to test route calculation for osmand.");
println("\nUsage for run tests : runTestsSuite [-routingXmlPath=PATH] [-verbose] [-obfDir=PATH] [-testDir=PATH] {individualTestPath}");
return;
}
List<File> files = new ArrayList<File>();
for (File f : params.obfDir.listFiles()) {
if (f.getName().endsWith(".obf")) {
files.add(f);
}
}
BinaryMapIndexReader[] rs = new BinaryMapIndexReader[files.size()];
int it = 0;
for (File f : files) {
RandomAccessFile raf = new RandomAccessFile(f, "r"); //$NON-NLS-1$ //$NON-NLS-2$
rs[it++] = new BinaryMapIndexReader(raf);
}
boolean allSuccess = true;
for(File f : params.tests) {
allSuccess &= test(null, new FileInputStream(f), rs, params.configBuilder);
}
if (allSuccess) {
System.out.println("All is successfull");
}
}
private static void println(String string) {
System.out.println(string);
}
public static boolean test(NativeLibrary lib, InputStream resource, BinaryMapIndexReader[] rs, RoutingConfiguration.Builder config) throws Exception {
Document testSuite = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(resource));
NodeList tests = testSuite.getElementsByTagName("test");
for (int i = 0; i < tests.getLength(); i++) {
Element e = (Element) tests.item(i);
testRoute(e, config, lib, rs);
}
return true;
}
private static float parseFloat(Element e, String attr) {
if(e.getAttribute(attr) == null || e.getAttribute(attr).length() == 0){
return 0;
}
return Float.parseFloat(e.getAttribute(attr));
}
private static boolean isInOrLess(float expected, float value, float percent){
if(equalPercent(expected, value, percent)){
return true;
}
if(value < expected) {
System.err.println("Test could be adjusted value " + value + " is much less then expected " + expected);
return true;
}
return false;
}
private static boolean equalPercent(float expected, float value, float percent){
if(Math.abs(value/expected - 1) < percent / 100){
return true;
}
return false;
}
private static void testRoute(Element testCase, Builder config, NativeLibrary lib, BinaryMapIndexReader[] rs) throws IOException, SAXException, InterruptedException {
String vehicle = testCase.getAttribute("vehicle");
int loadedTiles = (int) parseFloat(testCase, "loadedTiles");
int visitedSegments = (int) parseFloat(testCase, "visitedSegments");
int complete_time = (int) parseFloat(testCase, "complete_time");
int routing_time = (int) parseFloat(testCase, "routing_time");
int complete_distance = (int) parseFloat(testCase, "complete_distance");
float percent = parseFloat(testCase, "best_percent");
String testDescription = testCase.getAttribute("description");
if(percent == 0){
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because 'best_percent' attribute is not specified \n\n" );
return;
}
RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT);
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(false);
RoutingContext ctx = new RoutingContext(rconfig,
lib, rs);
String skip = testCase.getAttribute("skip_comment");
if (skip != null && skip.length() > 0) {
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because '" + skip + "'\n\n" );
return;
}
System.out.println("Run test " + testDescription);
double startLat = Double.parseDouble(testCase.getAttribute("start_lat"));
double startLon = Double.parseDouble(testCase.getAttribute("start_lon"));
RouteSegment startSegment = router.findRouteSegment(startLat, startLon, ctx);
double endLat = Double.parseDouble(testCase.getAttribute("target_lat"));
double endLon = Double.parseDouble(testCase.getAttribute("target_lon"));
RouteSegment endSegment = router.findRouteSegment(endLat, endLon, ctx);
if(startSegment == null){
throw new IllegalArgumentException("Start segment is not found for test : " + testDescription);
}
if(endSegment == null){
throw new IllegalArgumentException("End segment is not found for test : " + testDescription);
}
List<RouteSegmentResult> route = router.searchRoute(ctx, startSegment, endSegment, false);
final float calcRoutingTime = ctx.routingTime;
float completeTime = 0;
float completeDistance = 0;
for (int i = 0; i < route.size(); i++) {
completeTime += route.get(i).getSegmentTime();
completeDistance += route.get(i).getDistance();
}
if(complete_time > 0 && !isInOrLess(complete_time, completeTime, percent)) {
throw new IllegalArgumentException(String.format("Complete time (expected) %s != %s (original) : %s", complete_time, completeTime, testDescription));
}
if(complete_distance > 0 && !isInOrLess(complete_distance, completeDistance, percent)) {
throw new IllegalArgumentException(String.format("Complete distance (expected) %s != %s (original) : %s", complete_distance, completeDistance, testDescription));
}
if(routing_time > 0 && !isInOrLess(routing_time, calcRoutingTime, percent)) {
throw new IllegalArgumentException(String.format("Complete routing time (expected) %s != %s (original) : %s", routing_time, calcRoutingTime, testDescription));
}
if (visitedSegments > 0 && !isInOrLess(visitedSegments, ctx.visitedSegments, percent)) {
throw new IllegalArgumentException(String.format("Visited segments (expected) %s != %s (original) : %s", visitedSegments,
ctx.visitedSegments, testDescription));
}
if (loadedTiles > 0 && !isInOrLess(loadedTiles, ctx.loadedTiles, percent)) {
throw new IllegalArgumentException(String.format("Loaded tiles (expected) %s != %s (original) : %s", loadedTiles,
ctx.loadedTiles, testDescription));
}
if(TEST_BOTH_DIRECTION){
rconfig.planRoadDirection = -1;
runTestSpecialTest(lib, rs, rconfig, router, startSegment, endSegment, calcRoutingTime, "Calculated routing time in both direction %s != %s time in -1 direction");
rconfig.planRoadDirection = 1;
runTestSpecialTest(lib, rs, rconfig, router, startSegment, endSegment, calcRoutingTime, "Calculated routing time in both direction %s != %s time in 1 direction");
}
if(TEST_WO_HEURISTIC) {
rconfig.planRoadDirection = 0;
rconfig.heuristicCoefficient = 0.5f;
runTestSpecialTest(lib, rs, rconfig, router, startSegment, endSegment, calcRoutingTime,
"Calculated routing time with heuristic 1 %s != %s with heuristic 0.5");
}
}
private static void runTestSpecialTest(NativeLibrary lib, BinaryMapIndexReader[] rs, RoutingConfiguration rconfig, RoutePlannerFrontEnd router,
RouteSegment startSegment, RouteSegment endSegment, final float calcRoutingTime, String msg) throws IOException, InterruptedException {
RoutingContext ctx;
ctx = new RoutingContext(rconfig, lib, rs);
router.searchRoute(ctx, startSegment, endSegment, false);
FinalRouteSegment frs = ctx.finalRouteSegment;
if(frs == null || !equalPercent(calcRoutingTime, frs.distanceFromStart, 0.5f)){
throw new IllegalArgumentException(String.format(msg, calcRoutingTime+"",frs == null?"0":frs.distanceFromStart+""));
}
}
protected static NodeList compareBySegment(Element testCase, String testDescription, List<RouteSegmentResult> route) {
NodeList segments = testCase.getElementsByTagName("segment");
int i = 0;
while (i < segments.getLength() && i < route.size()) {
Element segment = (Element) segments.item(i);
long expectedId = Long.parseLong(segment.getAttribute("id"));
int expectedStart = Integer.parseInt(segment.getAttribute("start"));
int expectedEnd = Integer.parseInt(segment.getAttribute("end"));
RouteSegmentResult segmentResult = route.get(i);
if (expectedId != segmentResult.getObject().getId() >> 1) {
throw new IllegalArgumentException("Test : '" + testDescription + "' on segment " + (i + 1) + " : " + "\n"
+ "(expected route id) " + expectedId + " != " + (segmentResult.getObject().getId() >> 1) + " (actual route id)");
}
if (expectedStart != segmentResult.getStartPointIndex()) {
throw new IllegalArgumentException("Test : '" + testDescription + "' on segment " + (i + 1) + " : " + "\n"
+ "(expected start index) " + expectedStart + " != " + segmentResult.getStartPointIndex() + " (actual start index)");
}
if (expectedEnd != segmentResult.getEndPointIndex()) {
throw new IllegalArgumentException("Test : '" + testDescription + "' on segment " + (i + 1) + " : " + "\n"
+ "(expected end index) " + expectedEnd + " != " + segmentResult.getEndPointIndex() + " (actual end index)");
}
i++;
}
return segments;
}
}

View file

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="" description="Belarus" best_percent="5" vehicle="car"
start_lat="53.91102495838691" start_lon="27.579245567321777" target_lat="53.908383230651346" target_lon="27.48626947402954" complete_time="1093.2324" complete_distance = "9285.089" >
<segment id="40885459" start="3" end="2" time = "10.731602" name = "" distance = "89.43001" turn = "Go ahead" start_bearing = "30.2094" end_bearing = "30.2094" description = "Go ahead and go 89.43 meters" />
<segment id="40885456" start="1" end="0" time = "0.7542267" name = "" distance = "6.2852225" turn = "Turn left" start_bearing = "-57.804268" end_bearing = "-57.804268" description = "Turn left and go 47.32 meters" />
<segment id="40885457" start="1" end="0" time = "1.6372955" name = "" distance = "13.64413" start_bearing = "-57.47511" end_bearing = "-57.47511" description = "" />
<segment id="31691782" start="2" end="0" time = "3.287282" name = "" distance = "27.394016" start_bearing = "-59.641884" end_bearing = "-59.858616" description = "" />
<segment id="33911443" start="1" end="6" time = "22.942951" name = "просп. Независимости" distance = "414.24774" turn = "Turn right" start_bearing = "30.876814" end_bearing = "42.998978" description = "Turn right and go 635.18 meters" />
<segment id="33911472" start="0" end="2" time = "12.236243" name = "просп. Независимости" distance = "220.93216" start_bearing = "41.969524" end_bearing = "41.436733" description = "" />
<segment id="25228007" start="0" end="1" time = "36.176476" name = "" distance = "11.437971" turn = "Turn left" start_bearing = "-46.27303" end_bearing = "-46.27303" description = "Turn left and go 11.44 meters" />
<segment id="33911476" start="0" end="1" time = "54.669903" name = "просп. Независимости" distance = "355.151" turn = "Turn left" start_bearing = "-137.84839" end_bearing = "-137.84839" description = "Turn left and go 804.58 meters" />
<segment id="33911471" start="0" end="5" time = "24.89128" name = "просп. Независимости" distance = "449.42587" start_bearing = "-143.58362" end_bearing = "-149.44403" description = "" />
<segment id="33911401" start="0" end="8" time = "19.800528" name = "просп. Машерова" distance = "357.50955" turn = "Turn right" start_bearing = "-53.686356" end_bearing = "-22.9321" description = "Turn right and go 4360.46 meters" />
<segment id="29200977" start="0" end="1" time = "35.731197" name = "просп. Машерова" distance = "13.202153" start_bearing = "-22.988716" end_bearing = "-22.988716" description = "" />
<segment id="38571376" start="0" end="7" time = "55.68208" name = "просп. Машерова" distance = "373.42645" start_bearing = "-25.277721" end_bearing = "-61.99082" description = "" />
<segment id="37808103" start="0" end="2" time = "46.7727" name = "просп. Машерова" distance = "212.56265" start_bearing = "-74.52867" end_bearing = "-81.035515" description = "" />
<segment id="25228815" start="0" end="5" time = "51.711323" name = "просп. Машерова" distance = "301.73218" start_bearing = "-81.045204" end_bearing = "-80.848755" description = "" />
<segment id="30858073" start="0" end="6" time = "61.830868" name = "просп. Машерова" distance = "484.44623" start_bearing = "-80.458824" end_bearing = "-79.11447" description = "" />
<segment id="36988094" start="0" end="4" time = "48.48783" name = "просп. Машерова" distance = "243.53029" start_bearing = "-80.28675" end_bearing = "-85.36454" description = "" />
<segment id="36988096" start="0" end="5" time = "49.378212" name = "просп. Машерова" distance = "279.5764" start_bearing = "-90.96286" end_bearing = "-97.44326" description = "" />
<segment id="25379391" start="0" end="1" time = "5.269285" name = "просп. Машерова" distance = "102.45833" start_bearing = "-99.41367" end_bearing = "-99.41367" description = "" />
<segment id="25924616" start="0" end="7" time = "32.054688" name = "просп. Машерова" distance = "623.2856" start_bearing = "-100.11034" end_bearing = "-128.10757" description = "" />
<segment id="33911070" start="0" end="1" time = "1.2957808" name = "" distance = "17.996956" start_bearing = "-129.32698" end_bearing = "-129.32698" description = "" />
<segment id="33911069" start="0" end="8" time = "21.719967" name = "просп. Машерова" distance = "392.16608" start_bearing = "-128.97601" end_bearing = "-114.03429" description = "" />
<segment id="28382666" start="0" end="7" time = "22.299809" name = "просп. Машерова" distance = "402.63544" start_bearing = "-110.353226" end_bearing = "-104.80087" description = "" />
<segment id="25449141" start="0" end="2" time = "6.281684" name = "просп. Машерова" distance = "113.41929" start_bearing = "-111.887634" end_bearing = "-117.06471" description = "" />
<segment id="30813627" start="0" end="8" time = "47.840637" name = "просп. Машерова" distance = "231.84482" start_bearing = "-122.00539" end_bearing = "-150.3215" description = "" />
<segment id="25309517" start="0" end="4" time = "7.218898" name = "просп. Машерова" distance = "130.34122" start_bearing = "-155.16142" end_bearing = "-170.82646" description = "" />
<segment id="70219519" start="0" end="2" time = "4.4489284" name = "просп. Машерова" distance = "80.32787" start_bearing = "-174.47246" end_bearing = "-179.02898" description = "" />
<segment id="25924583" start="0" end="6" time = "8.19895" name = "просп. Машерова" distance = "148.03659" turn = "Keep right" start_bearing = "-162.0875" end_bearing = "-97.71833" description = "Keep right and go 2146.40 meters (*)" />
<segment id="25425696" start="0" end="1" time = "0.4735253" name = "Кальварийская ул." distance = "8.549762" start_bearing = "-79.38035" end_bearing = "-79.38035" description = "" />
<segment id="145696273" start="0" end="8" time = "23.085945" name = "Кальварийская ул." distance = "416.82956" start_bearing = "-80.37184" end_bearing = "-80.13419" description = "" />
<segment id="76769621" start="0" end="10" time = "70.60633" name = "Кальварийская ул." distance = "642.8921" start_bearing = "-77.541756" end_bearing = "-63.78502" description = "" />
<segment id="23625153" start="0" end="7" time = "24.953074" name = "ул. Притыцкого" distance = "450.54163" start_bearing = "-74.01036" end_bearing = "-96.74558" description = "" />
<segment id="61939976" start="0" end="1" time = "48.15234" name = "ул. Притыцкого" distance = "237.4728" start_bearing = "-96.055466" end_bearing = "-96.055466" description = "" />
<segment id="32883063" start="0" end="1" time = "1.8827579" name = "ул. Притыцкого" distance = "33.99424" start_bearing = "-97.457054" end_bearing = "-97.457054" description = "" />
<segment id="48470333" start="0" end="1" time = "1.0960325" name = "ул. Притыцкого" distance = "19.789476" start_bearing = "-96.28249" end_bearing = "-96.28249" description = "" />
<segment id="48470334" start="0" end="1" time = "1.9557701" name = "ул. Притыцкого" distance = "35.312515" start_bearing = "-95.710594" end_bearing = "-95.710594" description = "" />
<segment id="30821121" start="0" end="2" time = "8.472641" name = "ул. Притыцкого" distance = "152.97824" start_bearing = "-97.1709" end_bearing = "-96.88172" description = "" />
<segment id="30821121" start="2" end="8" time = "93.19126" name = "ул. Притыцкого" distance = "418.73114" turn = "Keep left" lanes = "[1, 1, 1, 1, 0]" start_bearing = "-96.74975" end_bearing = "-96.74693" description = "Keep left[1, 1, 1, 1, 0] and go 418.73 meters (*)" />
<segment id="30821121" start="8" end="10" time = "19.437342" name = "ул. Притыцкого" distance = "350.952" turn = "Keep left" lanes = "[1, 1, 1, 1, 0]" start_bearing = "-96.4875" end_bearing = "-97.1382" description = "Keep left[1, 1, 1, 1, 0] and go 350.95 meters (*)" />
<segment id="25231295" start="0" end="1" time = "36.09955" name = "ул. Бельского" distance = "18.32582" turn = "Turn left" start_bearing = "175.64302" end_bearing = "175.64302" description = "Turn left and go 18.33 meters" />
<segment id="30813591" start="0" end="1" time = "45.96917" name = "ул. Притыцкого" distance = "198.05447" turn = "Turn left" start_bearing = "83.51464" end_bearing = "83.51464" description = "Turn left and go 198.05 meters" />
<segment id="37761053" start="0" end="2" time = "7.0919204" name = "" distance = "59.099335" turn = "Keep right" lanes = "[0, 0, 0, 0, 1]" start_bearing = "116.16157" end_bearing = "115.28797" description = "Keep right[0, 0, 0, 0, 1] and go 73.57 meters" />
<segment id="37761055" start="0" end="1" time = "1.7364992" name = "" distance = "14.470827" start_bearing = "116.86981" end_bearing = "116.86981" description = "" />
<segment id="37761056" start="0" end="5" time = "11.629894" name = "" distance = "96.91579" turn = "Take 4 exit" start_bearing = "117.78681" end_bearing = "85.515396" description = "Take 4 exit and go 130.65 meters" />
<segment id="37761059" start="0" end="1" time = "4.0479445" name = "" distance = "33.732872" start_bearing = "-1.7305776" end_bearing = "-1.7305776" description = "" />
</test>
</router_tests>

View file

@ -1,253 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="" description="Czech" best_percent="10" vehicle="car"
start_lat="50.07577452522076" start_lon="14.45427417755127" target_lat="49.120547036367746" target_lon="16.335017681121826" complete_time="7241.0713" routing_time="7662" complete_distance = "204110.28" >
<segment id="148483636" start="1" end="3" time = "7.144318" name = "" distance = "69.45865" turn = "Go ahead" turn_angle = "0.0" start_bearing = "-13.969152" end_bearing = "-15.124007" description = "Go ahead and go 184.99 meters" />
<segment id="38611055" start="0" end="3" time = "11.883394" name = "Perunova" distance = "115.533" start_bearing = "-13.348727" end_bearing = "-14.32272" description = "" />
<segment id="128493079" start="0" end="10" time = "27.32003" name = "Vinohradská" distance = "341.5004" turn = "Turn right" turn_angle = "99.87288" start_bearing = "85.550156" end_bearing = "84.289406" description = "Turn right and go 341.50 meters" />
<segment id="7654037" start="0" end="6" time = "49.618195" name = "Boleslavská" distance = "245.22742" turn = "Turn right" turn_angle = "80.586586" start_bearing = "164.87599" end_bearing = "165.96376" description = "Turn right and go 291.67 meters" />
<segment id="40843659" start="0" end="4" time = "18.715546" name = "Benešovská" distance = "46.44432" start_bearing = "168.2317" end_bearing = "159.53773" description = "" />
<segment id="40843659" start="4" end="14" time = "49.094654" name = "Benešovská" distance = "613.68317" turn = "Keep left" turn_angle = "-21.298035" start_bearing = "138.2397" end_bearing = "97.792076" description = "Keep left and go 794.66 meters" />
<segment id="4083665" start="0" end="2" time = "23.651302" name = "Benešovská (243) " distance = "144.18837" start_bearing = "121.27156" end_bearing = "119.560356" description = "" />
<segment id="4647199" start="0" end="1" time = "17.207037" name = "Ruská (243) " distance = "36.78396" start_bearing = "87.6264" end_bearing = "87.6264" description = "" />
<segment id="4646742" start="0" end="3" time = "21.745153" name = "Bělocerkevská (243) " distance = "93.68268" turn = "Turn right" turn_angle = "76.97804" start_bearing = "164.60445" end_bearing = "165.65067" description = "Turn right and go 673.54 meters" />
<segment id="79271207" start="0" end="4" time = "4.2129865" name = "Bělocerkevská (243) " distance = "70.21644" start_bearing = "165.52971" end_bearing = "165.96376" description = "" />
<segment id="36897267" start="0" end="4" time = "20.532732" name = "Bělocerkevská (243) " distance = "92.21221" start_bearing = "174.41275" end_bearing = "-151.1013" description = "" />
<segment id="79271204" start="0" end="4" time = "7.927393" name = "Bělocerkevská (243) " distance = "132.12321" start_bearing = "-145.79654" end_bearing = "-144.8299" description = "" />
<segment id="79271201" start="0" end="6" time = "8.0121155" name = "Bělocerkevská (243) " distance = "133.53526" start_bearing = "-144.30777" end_bearing = "160.01689" description = "" />
<segment id="4882816" start="0" end="6" time = "39.105984" name = "U Slavie (243) " distance = "151.76642" start_bearing = "161.1139" end_bearing = "167.90524" description = "" />
<segment id="4882816" start="6" end="9" time = "6.3298717" name = "U Slavie (243) " distance = "105.497856" turn = "Keep left" turn_angle = "1.6431274" start_bearing = "169.54837" end_bearing = "-175.79465" description = "Keep left and go 105.50 meters (*)" />
<segment id="4882816" start="9" end="11" time = "3.7265334" name = "U Slavie (243) " distance = "62.10889" turn = "Keep right" turn_angle = "0.1197052" start_bearing = "-175.67494" end_bearing = "-179.43553" description = "Keep right and go 1246.39 meters (*)" />
<segment id="8927051" start="1" end="0" time = "4.6551995" name = " (243) " distance = "77.586655" start_bearing = "-175.1894" end_bearing = "-175.1894" description = "" />
<segment id="128564782" start="1" end="0" time = "1.9319879" name = "U Vršovického hřbitova (243) " distance = "32.1998" start_bearing = "-176.96953" end_bearing = "-176.96953" description = "" />
<segment id="141873944" start="4" end="0" time = "17.393198" name = "U Vršovického hřbitova (243) " distance = "289.88663" start_bearing = "-177.17604" end_bearing = "177.01137" description = "" />
<segment id="4083664" start="1" end="0" time = "9.197536" name = "U Vršovického hřbitova (243) " distance = "153.29228" start_bearing = "177.42021" end_bearing = "177.42021" description = "" />
<segment id="8134281" start="0" end="10" time = "45.90269" name = "Bohdalecká (243) " distance = "515.0448" start_bearing = "-166.53479" end_bearing = "166.373" description = "" />
<segment id="17169152" start="0" end="2" time = "21.97615" name = "Chodovská (243) " distance = "116.26917" start_bearing = "160.22392" end_bearing = "162.48567" description = "" />
<segment id="17169152" start="2" end="3" time = "4.66618" name = "Chodovská (243) " distance = "77.76967" turn = "Keep left" turn_angle = "-0.3382721" lanes = "[1, 1, 0]" start_bearing = "162.1474" end_bearing = "162.1474" description = "Keep left[1, 1, 0] and go 696.89 meters (*)" />
<segment id="141867960" start="0" end="9" time = "28.635384" name = "Chodovská (243) " distance = "477.25638" start_bearing = "164.32048" end_bearing = "129.69489" description = "" />
<segment id="31794292" start="0" end="1" time = "3.6192472" name = "Chodovská (243) " distance = "60.320786" start_bearing = "129.80557" end_bearing = "129.80557" description = "" />
<segment id="31794293" start="0" end="2" time = "2.4550827" name = "Chodovská (243) " distance = "40.918045" start_bearing = "128.88449" end_bearing = "129.28941" description = "" />
<segment id="27609116" start="0" end="1" time = "2.9252183" name = "Spořilovská (243) " distance = "40.628033" start_bearing = "134.61546" end_bearing = "134.61546" description = "" />
<segment id="27609116" start="1" end="3" time = "2.0349395" name = "Spořilovská (243) " distance = "28.26305" turn = "Keep left" turn_angle = "7.9083557" lanes = "[1, 1, 0]" start_bearing = "142.52382" end_bearing = "146.72511" description = "Keep left[1, 1, 0] and go 154.11 meters (*)" />
<segment id="160662431" start="0" end="1" time = "18.566303" name = "Spořilovská (243) " distance = "49.531994" start_bearing = "149.11325" end_bearing = "149.11325" description = "" />
<segment id="17169157" start="0" end="2" time = "5.4946117" name = "Spořilovská (243) " distance = "76.31405" start_bearing = "147.08226" end_bearing = "137.1211" description = "" />
<segment id="17169157" start="2" end="4" time = "5.962459" name = "Spořilovská (243) " distance = "82.811935" turn = "Keep right" turn_angle = "-9.974403" lanes = "[0, 1, 1]" start_bearing = "127.14669" end_bearing = "116.22536" description = "Keep right[0, 1, 1] and go 82.81 meters" />
<segment id="151406530" start="0" end="2" time = "2.025483" name = "Spořilovská (243) " distance = "56.263416" turn = "Keep left" turn_angle = "1.6290894" lanes = "[1, 1, 0]" start_bearing = "117.85445" end_bearing = "120.20324" description = "Keep left[1, 1, 0] and go 1249.94 meters" />
<segment id="27609112" start="0" end="22" time = "53.126442" name = "Spořilovská (243) " distance = "1180.5875" start_bearing = "121.429565" end_bearing = "-157.27696" description = "" />
<segment id="12201623" start="0" end="1" time = "0.5891617" name = "Spořilovská" distance = "13.092482" start_bearing = "-158.66315" end_bearing = "-158.66315" description = "" />
<segment id="12201623" start="1" end="2" time = "2.3254316" name = "Spořilovská" distance = "51.676254" turn = "Keep left" turn_angle = "-5.449692" lanes = "[1, 1, 0]" start_bearing = "-164.11284" end_bearing = "-164.11284" description = "Keep left[1, 1, 0] and go 358.48 meters (*)" />
<segment id="30334627" start="0" end="3" time = "7.9866686" name = "Spořilovská" distance = "177.4815" start_bearing = "-168.38327" end_bearing = "178.9013" description = "" />
<segment id="9043583" start="0" end="2" time = "5.819285" name = "" distance = "129.31743" start_bearing = "170.64513" end_bearing = "162.17514" description = "" />
<segment id="9043583" start="2" end="11" time = "17.769726" name = "" distance = "394.88278" turn = "Keep right" turn_angle = "-5.5872498" lanes = "[0, 1, 1]" start_bearing = "156.58789" end_bearing = "156.58789" description = "Keep right[0, 1, 1] and go 650.41 meters (*)" />
<segment id="27620514" start="0" end="1" time = "4.5381336" name = "" distance = "100.84741" start_bearing = "162.62029" end_bearing = "162.62029" description = "" />
<segment id="27462071" start="0" end="1" time = "2.023968" name = "" distance = "44.977066" start_bearing = "166.74529" end_bearing = "166.74529" description = "" />
<segment id="27462062" start="0" end="2" time = "4.9368167" name = "" distance = "109.70703" start_bearing = "165.64699" end_bearing = "164.08997" description = "" />
<segment id="27462062" start="2" end="8" time = "21.322693" name = "" distance = "473.8376" turn = "Keep left" turn_angle = "0.46609497" start_bearing = "164.55606" end_bearing = "128.57652" description = "Keep left and go 1763.69 meters" />
<segment id="32489712" start="0" end="8" time = "46.434803" name = " (D1) " distance = "1289.8557" start_bearing = "146.01804" end_bearing = "122.4919" description = "" />
<segment id="32489712" start="8" end="9" time = "17.079693" name = " (D1) " distance = "474.4359" turn = "Keep left" turn_angle = "-1.0206909" lanes = "[1, 1, 1, 0]" start_bearing = "121.47121" end_bearing = "121.47121" description = "Keep left[1, 1, 1, 0] and go 2580.44 meters (*)" />
<segment id="100515393" start="0" end="5" time = "58.319992" name = " (D1) " distance = "2105.9998" start_bearing = "121.15706" end_bearing = "114.30778" description = "" />
<segment id="100515393" start="5" end="11" time = "24.33348" name = " (D1) " distance = "878.70905" turn = "Keep left" turn_angle = "-1.6493225" lanes = "[1, 1, 1, 0]" start_bearing = "112.658455" end_bearing = "104.03625" description = "Keep left[1, 1, 1, 0] and go 1570.91 meters (*)" />
<segment id="51551835" start="0" end="1" time = "1.0894294" name = " (D1) " distance = "33.28812" start_bearing = "104.76045" end_bearing = "104.76045" description = "" />
<segment id="51551832" start="0" end="3" time = "18.246792" name = " (D1) " distance = "658.9119" start_bearing = "104.977905" end_bearing = "110.52511" description = "" />
<segment id="51551832" start="3" end="12" time = "63.484108" name = " (D1) " distance = "2292.4817" turn = "Keep left" turn_angle = "-0.121536255" lanes = "[1, 1, 1, 0]" start_bearing = "110.40357" end_bearing = "131.747" description = "Keep left[1, 1, 1, 0] and go 2292.48 meters (*)" />
<segment id="51551832" start="12" end="19" time = "54.802387" name = " (D1) " distance = "1978.9751" turn = "Keep left" turn_angle = "0.25242615" lanes = "[1, 1, 1, 0]" start_bearing = "131.99942" end_bearing = "142.31366" description = "Keep left[1, 1, 1, 0] and go 7177.71 meters (*)" />
<segment id="45054929" start="0" end="1" time = "2.1604805" name = " (D1) " distance = "66.01468" start_bearing = "141.62706" end_bearing = "141.62706" description = "" />
<segment id="45054930" start="0" end="8" time = "102.976585" name = " (D1) " distance = "3718.5989" start_bearing = "141.38727" end_bearing = "145.03313" description = "" />
<segment id="119766572" start="0" end="10" time = "35.606503" name = " (D1) " distance = "1285.7904" start_bearing = "142.07788" end_bearing = "114.616394" description = "" />
<segment id="51518005" start="0" end="1" time = "1.6190716" name = " (D1) " distance = "58.466473" start_bearing = "113.09938" end_bearing = "113.09938" description = "" />
<segment id="51518002" start="0" end="1" time = "1.9346191" name = " (D1) " distance = "69.861244" start_bearing = "112.704315" end_bearing = "112.704315" description = "" />
<segment id="51518002" start="1" end="2" time = "5.5831866" name = " (D1) " distance = "201.61508" turn = "Keep left" turn_angle = "0.07909393" lanes = "[1, 1, 1, 1, 0]" start_bearing = "112.78341" end_bearing = "112.78341" description = "Keep left[1, 1, 1, 1, 0] and go 5159.90 meters (*)" />
<segment id="119766569" start="0" end="15" time = "137.30647" name = " (D1) " distance = "4958.2896" start_bearing = "112.061325" end_bearing = "151.84012" description = "" />
<segment id="32065252" start="0" end="7" time = "15.569629" name = " (D1) " distance = "562.2366" turn = "Keep left" turn_angle = "-2.0514374" lanes = "[1, 1, 0]" start_bearing = "149.78868" end_bearing = "131.24828" description = "Keep left[1, 1, 0] and go 5835.55 meters (*)" />
<segment id="51519381" start="0" end="1" time = "1.2693012" name = " (D1) " distance = "45.835876" start_bearing = "129.71306" end_bearing = "129.71306" description = "" />
<segment id="51519375" start="0" end="13" time = "30.020567" name = " (D1) " distance = "1084.076" start_bearing = "129.92526" end_bearing = "115.989235" description = "" />
<segment id="64250368" start="0" end="3" time = "5.630075" name = " (D1) " distance = "203.30826" start_bearing = "118.05846" end_bearing = "123.7742" description = "" />
<segment id="64250377" start="0" end="4" time = "7.90974" name = " (D1) " distance = "285.6295" start_bearing = "126.28254" end_bearing = "132.84163" description = "" />
<segment id="64250345" start="0" end="1" time = "0.43655643" name = " (D1) " distance = "15.764537" start_bearing = "135.98776" end_bearing = "135.98776" description = "" />
<segment id="64250347" start="0" end="5" time = "24.710007" name = " (D1) " distance = "892.3057" start_bearing = "135.63307" end_bearing = "145.65291" description = "" />
<segment id="26474366" start="0" end="1" time = "6.775518" name = " (D1) " distance = "244.67148" start_bearing = "145.72327" end_bearing = "145.72327" description = "" />
<segment id="4608306" start="0" end="19" time = "69.27838" name = " (D1) " distance = "2501.7192" start_bearing = "145.59088" end_bearing = "166.91277" description = "" />
<segment id="4608306" start="19" end="28" time = "19.794218" name = " (D1) " distance = "714.79114" turn = "Keep left" turn_angle = "-2.2573853" lanes = "[1, 1, 0]" start_bearing = "164.65538" end_bearing = "136.15733" description = "Keep left[1, 1, 0] and go 2529.61 meters (*)" />
<segment id="12840264" start="0" end="5" time = "14.022935" name = " (D1) " distance = "506.38373" start_bearing = "132.01266" end_bearing = "120.3516" description = "" />
<segment id="12839852" start="0" end="10" time = "36.23363" name = " (D1) " distance = "1308.4366" start_bearing = "116.18181" end_bearing = "142.30576" description = "" />
<segment id="12839852" start="10" end="31" time = "94.88607" name = " (D1) " distance = "3426.4414" turn = "Keep left" turn_angle = "0.5669861" lanes = "[1, 1, 0]" start_bearing = "142.87274" end_bearing = "105.39645" description = "Keep left[1, 1, 0] and go 3788.02 meters (*)" />
<segment id="31401909" start="0" end="1" time = "0.8794719" name = " (D1) " distance = "26.872753" start_bearing = "102.09476" end_bearing = "102.09476" description = "" />
<segment id="31401912" start="0" end="1" time = "10.953911" name = " (D1) " distance = "334.70282" start_bearing = "98.758675" end_bearing = "98.758675" description = "" />
<segment id="31401912" start="1" end="6" time = "38.207638" name = " (D1) " distance = "1167.4556" turn = "Keep left" turn_angle = "-0.78782654" lanes = "[1, 1, 0]" start_bearing = "97.97085" end_bearing = "106.14815" description = "Keep left[1, 1, 0] and go 1167.46 meters (*)" />
<segment id="31401912" start="6" end="25" time = "222.07196" name = " (D1) " distance = "6785.532" turn = "Keep left" turn_angle = "2.2298203" lanes = "[1, 1, 0]" start_bearing = "108.37797" end_bearing = "121.32201" description = "Keep left[1, 1, 0] and go 6785.53 meters (*)" />
<segment id="31401912" start="25" end="39" time = "113.403465" name = " (D1) " distance = "3465.106" turn = "Keep left" turn_angle = "-1.0894394" lanes = "[1, 1, 0]" start_bearing = "120.23257" end_bearing = "154.44446" description = "Keep left[1, 1, 0] and go 3512.67 meters (*)" />
<segment id="39815323" start="0" end="1" time = "1.5565345" name = " (D1) " distance = "47.560776" start_bearing = "154.88516" end_bearing = "154.88516" description = "" />
<segment id="39815322" start="0" end="2" time = "8.118108" name = " (D1) " distance = "248.05328" turn = "Keep left" turn_angle = "-1.1968842" lanes = "[1, 1, 0]" start_bearing = "153.68828" end_bearing = "154.41148" description = "Keep left[1, 1, 0] and go 4689.85 meters (*)" />
<segment id="39815331" start="0" end="1" time = "6.5625153" name = " (D1) " distance = "200.52129" start_bearing = "154.17421" end_bearing = "154.17421" description = "" />
<segment id="39815329" start="0" end="35" time = "138.80536" name = " (D1) " distance = "4241.275" start_bearing = "154.23067" end_bearing = "122.28814" description = "" />
<segment id="119763495" start="0" end="19" time = "95.9254" name = " (D1) " distance = "2931.054" turn = "Keep left" turn_angle = "-2.177597" lanes = "[1, 1, 1, 0]" start_bearing = "120.11054" end_bearing = "81.25384" description = "Keep left[1, 1, 1, 0] and go 2997.46 meters (*)" />
<segment id="26784182" start="0" end="2" time = "2.173136" name = " (D1) " distance = "66.401375" start_bearing = "86.077286" end_bearing = "87.96668" description = "" />
<segment id="26784183" start="0" end="21" time = "66.32422" name = " (D1) " distance = "2026.5734" turn = "Keep left" turn_angle = "2.3035812" lanes = "[1, 1, 0]" start_bearing = "90.27026" end_bearing = "135.38976" description = "Keep left[1, 1, 0] and go 4088.49 meters (*)" />
<segment id="119763491" start="0" end="8" time = "67.48084" name = " (D1) " distance = "2061.9146" start_bearing = "141.82753" end_bearing = "158.84573" description = "" />
<segment id="119763493" start="0" end="13" time = "59.394455" name = " (D1) " distance = "1814.8306" turn = "Keep left" turn_angle = "-0.3955536" lanes = "[1, 1, 0]" start_bearing = "158.45018" end_bearing = "110.95136" description = "Keep left[1, 1, 0] and go 9380.92 meters (*)" />
<segment id="5931788" start="0" end="10" time = "55.8795" name = " (D1) " distance = "1707.4292" start_bearing = "110.77359" end_bearing = "130.07109" description = "" />
<segment id="26786278" start="0" end="1" time = "1.1448889" name = " (D1) " distance = "34.982716" start_bearing = "130.3999" end_bearing = "130.3999" description = "" />
<segment id="26786279" start="0" end="27" time = "76.12142" name = " (D1) " distance = "2325.9324" start_bearing = "133.21516" end_bearing = "117.557846" description = "" />
<segment id="93542367" start="0" end="1" time = "7.3202024" name = " (D1) " distance = "223.67285" start_bearing = "117.11595" end_bearing = "117.11595" description = "" />
<segment id="93542373" start="0" end="16" time = "61.635036" name = " (D1) " distance = "1883.2928" start_bearing = "117.0923" end_bearing = "169.34862" description = "" />
<segment id="26786265" start="0" end="1" time = "0.41669723" name = " (D1) " distance = "12.732416" start_bearing = "169.69516" end_bearing = "169.69516" description = "" />
<segment id="26786266" start="0" end="2" time = "45.09975" name = " (D1) " distance = "1378.048" start_bearing = "169.28906" end_bearing = "169.34047" description = "" />
<segment id="26786266" start="2" end="4" time = "14.0724325" name = " (D1) " distance = "429.991" turn = "Keep left" turn_angle = "0.032577515" lanes = "[1, 1, 0]" start_bearing = "169.37305" end_bearing = "169.1228" description = "Keep left[1, 1, 0] and go 4460.16 meters (*)" />
<segment id="22868199" start="0" end="1" time = "1.1800733" name = " (D1) " distance = "36.057796" start_bearing = "169.23001" end_bearing = "169.23001" description = "" />
<segment id="22868200" start="0" end="1" time = "3.3324301" name = " (D1) " distance = "101.82426" start_bearing = "170.46594" end_bearing = "170.46594" description = "" />
<segment id="119759944" start="0" end="5" time = "61.84606" name = " (D1) " distance = "1889.7407" start_bearing = "169.22552" end_bearing = "168.5975" description = "" />
<segment id="119759946" start="0" end="9" time = "65.53793" name = " (D1) " distance = "2002.5481" start_bearing = "169.40523" end_bearing = "162.7139" description = "" />
<segment id="119759946" start="9" end="34" time = "149.54803" name = " (D1) " distance = "4569.5234" turn = "Keep left" turn_angle = "-0.0068359375" lanes = "[1, 1, 0]" start_bearing = "162.70706" end_bearing = "118.76765" description = "Keep left[1, 1, 0] and go 4569.52 meters (*)" />
<segment id="119759946" start="34" end="54" time = "61.090347" name = " (D1) " distance = "1866.6494" turn = "Keep left" turn_angle = "-0.4402008" lanes = "[1, 1, 0]" start_bearing = "118.327446" end_bearing = "97.7313" description = "Keep left[1, 1, 0] and go 8694.02 meters (*)" />
<segment id="6109867" start="0" end="5" time = "8.474227" name = " (D1) " distance = "258.9347" start_bearing = "94.64046" end_bearing = "82.21298" description = "" />
<segment id="4608309" start="0" end="5" time = "14.30948" name = " (D1) " distance = "437.2341" start_bearing = "79.704796" end_bearing = "61.529053" description = "" />
<segment id="119746296" start="0" end="20" time = "63.845406" name = " (D1) " distance = "1950.8319" start_bearing = "58.6646" end_bearing = "130.58223" description = "" />
<segment id="119746297" start="0" end="2" time = "3.980696" name = " (D1) " distance = "121.63238" start_bearing = "131.1705" end_bearing = "131.90991" description = "" />
<segment id="119745461" start="0" end="1" time = "0.6482078" name = " (D1) " distance = "19.806349" start_bearing = "129.32698" end_bearing = "129.32698" description = "" />
<segment id="119745460" start="0" end="13" time = "62.601353" name = " (D1) " distance = "1912.8191" start_bearing = "131.19409" end_bearing = "142.87805" description = "" />
<segment id="119745459" start="0" end="1" time = "6.3625135" name = " (D1) " distance = "194.41013" start_bearing = "144.91429" end_bearing = "144.91429" description = "" />
<segment id="119745465" start="0" end="6" time = "33.972603" name = " (D1) " distance = "1038.0518" start_bearing = "144.94089" end_bearing = "137.67075" description = "" />
<segment id="119745464" start="0" end="8" time = "29.24661" name = " (D1) " distance = "893.6464" start_bearing = "134.6502" end_bearing = "116.85887" description = "" />
<segment id="119745464" start="8" end="28" time = "74.51884" name = " (D1) " distance = "2276.9646" turn = "Keep left" turn_angle = "2.0963593" lanes = "[1, 1, 1, 0]" start_bearing = "118.95523" end_bearing = "103.44121" description = "Keep left[1, 1, 1, 0] and go 5336.39 meters (*)" />
<segment id="119745443" start="0" end="28" time = "100.12664" name = " (D1) " distance = "3059.425" start_bearing = "106.68452" end_bearing = "168.93823" description = "" />
<segment id="119745443" start="28" end="56" time = "65.54259" name = " (D1) " distance = "2002.6901" turn = "Keep left" turn_angle = "-1.9328461" lanes = "[1, 1, 0]" start_bearing = "167.00539" end_bearing = "109.822464" description = "Keep left[1, 1, 0] and go 2002.69 meters (*)" />
<segment id="119745443" start="56" end="57" time = "2.2691507" name = " (D1) " distance = "69.33516" turn = "Keep left" turn_angle = "0.63980865" lanes = "[1, 1, 0]" start_bearing = "110.46227" end_bearing = "110.46227" description = "Keep left[1, 1, 0] and go 4906.00 meters (*)" />
<segment id="51685606" start="0" end="1" time = "1.8112754" name = " (D1) " distance = "55.344524" start_bearing = "107.341896" end_bearing = "107.341896" description = "" />
<segment id="51685605" start="0" end="15" time = "61.345135" name = " (D1) " distance = "1874.4346" start_bearing = "107.700424" end_bearing = "102.59657" description = "" />
<segment id="53155778" start="0" end="1" time = "0.98972464" name = " (D1) " distance = "30.241587" start_bearing = "102.75753" end_bearing = "102.75753" description = "" />
<segment id="53155779" start="0" end="25" time = "83.74765" name = " (D1) " distance = "2558.956" start_bearing = "104.65438" end_bearing = "99.16754" description = "" />
<segment id="53092521" start="0" end="1" time = "0.8711285" name = " (D1) " distance = "26.617815" start_bearing = "98.187805" end_bearing = "98.187805" description = "" />
<segment id="53092517" start="0" end="3" time = "9.526083" name = " (D1) " distance = "291.07477" start_bearing = "97.587395" end_bearing = "93.39134" description = "" />
<segment id="53092517" start="3" end="38" time = "96.63228" name = " (D1) " distance = "2952.653" turn = "Keep left" turn_angle = "-2.9738922" lanes = "[1, 1, 0]" start_bearing = "90.41745" end_bearing = "111.903175" description = "Keep left[1, 1, 0] and go 7964.06 meters (*)" />
<segment id="115609324" start="0" end="2" time = "2.2820845" name = " (D1) " distance = "69.730354" start_bearing = "112.988716" end_bearing = "115.69919" description = "" />
<segment id="115609329" start="0" end="18" time = "47.90957" name = " (D1) " distance = "1463.9036" start_bearing = "117.42335" end_bearing = "138.84245" description = "" />
<segment id="121296542" start="0" end="10" time = "26.613022" name = " (D1) " distance = "813.17566" start_bearing = "136.16052" end_bearing = "143.61565" description = "" />
<segment id="115609347" start="0" end="1" time = "1.1968368" name = " (D1) " distance = "36.570015" start_bearing = "143.86072" end_bearing = "143.86072" description = "" />
<segment id="115609355" start="0" end="23" time = "86.00804" name = " (D1) " distance = "2628.0234" start_bearing = "142.76517" end_bearing = "108.72269" description = "" />
<segment id="115609355" start="23" end="25" time = "13.843906" name = " (D1) " distance = "423.00824" turn = "Keep left" turn_angle = "0.19644165" lanes = "[1, 1, 1, 0]" start_bearing = "108.91913" end_bearing = "109.74683" description = "Keep left[1, 1, 1, 0] and go 7271.72 meters (*)" />
<segment id="121296541" start="0" end="9" time = "49.00695" name = " (D1) " distance = "1497.4346" start_bearing = "109.8733" end_bearing = "113.64562" description = "" />
<segment id="4608310" start="0" end="7" time = "26.32358" name = " (D1) " distance = "804.3316" start_bearing = "111.71127" end_bearing = "104.43373" description = "" />
<segment id="45556207" start="0" end="1" time = "1.5573034" name = " (D1) " distance = "47.58427" start_bearing = "102.629456" end_bearing = "102.629456" description = "" />
<segment id="45556208" start="0" end="25" time = "80.1859" name = " (D1) " distance = "2450.1245" start_bearing = "103.15371" end_bearing = "149.30556" description = "" />
<segment id="45556168" start="0" end="1" time = "1.1189631" name = " (D1) " distance = "34.19054" start_bearing = "145.42581" end_bearing = "145.42581" description = "" />
<segment id="45556169" start="0" end="21" time = "65.94713" name = " (D1) " distance = "2015.051" start_bearing = "142.61322" end_bearing = "132.91322" description = "" />
<segment id="45556169" start="21" end="33" time = "38.258057" name = " (D1) " distance = "1168.9962" turn = "Keep left" turn_angle = "-3.2228546" lanes = "[1, 1, 0]" start_bearing = "129.69037" end_bearing = "97.69853" description = "Keep left[1, 1, 0] and go 1224.07 meters (*)" />
<segment id="26328888" start="0" end="1" time = "1.3394171" name = " (D1) " distance = "40.926636" start_bearing = "100.03925" end_bearing = "100.03925" description = "" />
<segment id="26328915" start="0" end="1" time = "0.46315435" name = " (D1) " distance = "14.151938" start_bearing = "100.45991" end_bearing = "100.45991" description = "" />
<segment id="4610857" start="0" end="11" time = "17.429176" name = " (D1) " distance = "629.38696" turn = "Keep left" turn_angle = "1.7146835" lanes = "[1, 1, 0, 0]" start_bearing = "102.17459" end_bearing = "120.56976" description = "Keep left[1, 1, 0, 0] and go 7172.71 meters (*)" />
<segment id="26329128" start="0" end="1" time = "1.5027716" name = " (D1) " distance = "54.26675" start_bearing = "121.3516" end_bearing = "121.3516" description = "" />
<segment id="26329085" start="0" end="1" time = "12.653235" name = " (D1) " distance = "456.9224" start_bearing = "124.47341" end_bearing = "124.47341" description = "" />
<segment id="37095713" start="0" end="1" time = "3.4557798" name = " (D1) " distance = "124.792046" start_bearing = "124.9483" end_bearing = "124.9483" description = "" />
<segment id="37095638" start="0" end="1" time = "28.528063" name = " (D1) " distance = "1030.18" start_bearing = "124.701294" end_bearing = "124.701294" description = "" />
<segment id="10869983" start="0" end="17" time = "157.54277" name = " (D1) " distance = "4813.807" start_bearing = "124.97004" end_bearing = "100.53515" description = "" />
<segment id="43790205" start="0" end="1" time = "1.9126884" name = " (D1) " distance = "58.443256" start_bearing = "100.49148" end_bearing = "100.49148" description = "" />
<segment id="43790206" start="0" end="1" time = "0.16062258" name = " (D1) " distance = "4.9079123" start_bearing = "101.30993" end_bearing = "101.30993" description = "" />
<segment id="43790206" start="1" end="4" time = "8.614767" name = " (D1) " distance = "263.229" turn = "Keep left" turn_angle = "1.0897369" lanes = "[1, 1, 0]" start_bearing = "102.399666" end_bearing = "105.298164" description = "Keep left[1, 1, 0] and go 2507.03 meters (*)" />
<segment id="4078523" start="0" end="17" time = "73.43346" name = " (D1) " distance = "2243.8" start_bearing = "107.23182" end_bearing = "105.58795" description = "" />
<segment id="4078523" start="17" end="28" time = "86.885765" name = " (D1) " distance = "2654.8428" turn = "Keep left" turn_angle = "-1.3506699" lanes = "[1, 1, 0]" start_bearing = "104.23728" end_bearing = "90.830315" description = "Keep left[1, 1, 0] and go 12163.09 meters (*)" />
<segment id="22747195" start="0" end="2" time = "3.6082203" name = " (D1) " distance = "110.251175" start_bearing = "90.83637" end_bearing = "91.74156" description = "" />
<segment id="22747196" start="0" end="22" time = "116.52651" name = " (D1) " distance = "3560.5325" start_bearing = "88.64552" end_bearing = "94.87245" description = "" />
<segment id="53659367" start="0" end="1" time = "1.6861058" name = " (D1) " distance = "51.5199" start_bearing = "95.86154" end_bearing = "95.86154" description = "" />
<segment id="53659285" start="0" end="22" time = "92.728546" name = " (D1) " distance = "2833.3723" start_bearing = "95.85601" end_bearing = "105.48417" description = "" />
<segment id="22747165" start="0" end="1" time = "2.9886184" name = " (D1) " distance = "91.31889" start_bearing = "104.69341" end_bearing = "104.69341" description = "" />
<segment id="22747166" start="0" end="1" time = "20.34724" name = " (D1) " distance = "621.72125" start_bearing = "105.36635" end_bearing = "105.36635" description = "" />
<segment id="42225566" start="0" end="1" time = "0.7333077" name = " (D1) " distance = "22.406626" start_bearing = "105.388466" end_bearing = "105.388466" description = "" />
<segment id="42225567" start="0" end="2" time = "29.359941" name = " (D1) " distance = "897.1093" start_bearing = "105.43434" end_bearing = "104.98443" description = "" />
<segment id="53761535" start="0" end="1" time = "0.99840534" name = " (D1) " distance = "30.50683" start_bearing = "104.97684" end_bearing = "104.97684" description = "" />
<segment id="53761534" start="0" end="8" time = "38.201786" name = " (D1) " distance = "1167.2769" start_bearing = "104.99508" end_bearing = "100.99812" description = "" />
<segment id="53761542" start="0" end="1" time = "2.9462337" name = " (D1) " distance = "90.0238" start_bearing = "105.04133" end_bearing = "105.04133" description = "" />
<segment id="53761543" start="0" end="1" time = "1.0541312" name = " (D1) " distance = "32.209564" start_bearing = "105.13308" end_bearing = "105.13308" description = "" />
<segment id="4610859" start="0" end="7" time = "26.798027" name = " (D1) " distance = "967.70654" turn = "Keep left" turn_angle = "4.1018677" lanes = "[1, 1, 0]" start_bearing = "109.23495" end_bearing = "118.264465" description = "Keep left[1, 1, 0] and go 4849.35 meters (*)" />
<segment id="22747168" start="0" end="1" time = "2.8082016" name = " (D1) " distance = "101.40728" start_bearing = "118.04651" end_bearing = "118.04651" description = "" />
<segment id="22747171" start="0" end="8" time = "36.098972" name = " (D1) " distance = "1103.0242" start_bearing = "116.11976" end_bearing = "106.01956" description = "" />
<segment id="75070506" start="0" end="2" time = "3.4172683" name = " (D1) " distance = "104.41653" start_bearing = "106.249146" end_bearing = "109.32318" description = "" />
<segment id="75070473" start="0" end="5" time = "53.928986" name = " (D1) " distance = "1647.8301" start_bearing = "110.4635" end_bearing = "116.41485" description = "" />
<segment id="25096900" start="0" end="1" time = "2.284889" name = " (D1) " distance = "69.816055" start_bearing = "116.49492" end_bearing = "116.49492" description = "" />
<segment id="25096901" start="0" end="1" time = "27.986803" name = " (D1) " distance = "855.1523" start_bearing = "116.471855" end_bearing = "116.471855" description = "" />
<segment id="25096901" start="1" end="3" time = "17.10907" name = " (D1) " distance = "522.77716" turn = "Keep left" turn_angle = "-0.10053253" lanes = "[1, 1, 0]" start_bearing = "116.37132" end_bearing = "116.72736" description = "Keep left[1, 1, 0] and go 1826.53 meters (*)" />
<segment id="22747143" start="0" end="1" time = "2.0877662" name = " (D1) " distance = "75.391556" start_bearing = "117.67682" end_bearing = "117.67682" description = "" />
<segment id="22747142" start="0" end="1" time = "19.479925" name = " (D1) " distance = "703.4417" start_bearing = "116.536766" end_bearing = "116.536766" description = "" />
<segment id="22747140" start="0" end="1" time = "2.1645055" name = " (D1) " distance = "78.16269" start_bearing = "116.888756" end_bearing = "116.888756" description = "" />
<segment id="22747139" start="0" end="1" time = "12.371632" name = " (D1) " distance = "446.7534" start_bearing = "116.73209" end_bearing = "116.73209" description = "" />
<segment id="22747139" start="1" end="2" time = "9.7767725" name = " (D1) " distance = "353.0501" turn = "Keep left" turn_angle = "0.9297943" start_bearing = "117.66189" end_bearing = "117.66189" description = "Keep left and go 3971.72 meters (*)" />
<segment id="22747096" start="0" end="1" time = "1.6933564" name = " (D1) " distance = "61.14898" start_bearing = "117.3777" end_bearing = "117.3777" description = "" />
<segment id="22747095" start="0" end="2" time = "12.118266" name = " (D1) " distance = "437.60406" start_bearing = "118.32294" end_bearing = "118.1621" description = "" />
<segment id="12876555" start="0" end="3" time = "17.813232" name = " (D1) " distance = "643.2556" start_bearing = "117.67757" end_bearing = "114.62721" description = "" />
<segment id="48204429" start="0" end="1" time = "1.2147677" name = " (D1) " distance = "43.86661" start_bearing = "112.9321" end_bearing = "112.9321" description = "" />
<segment id="48204412" start="0" end="16" time = "51.554684" name = " (D1) " distance = "1861.6968" start_bearing = "111.622574" end_bearing = "111.616714" description = "" />
<segment id="22747985" start="0" end="6" time = "11.767733" name = "Most Vysočina (D1) " distance = "424.9459" start_bearing = "111.17347" end_bearing = "123.4293" description = "" />
<segment id="22747984" start="0" end="1" time = "4.0472884" name = " (D1) " distance = "146.15207" start_bearing = "125.07904" end_bearing = "125.07904" description = "" />
<segment id="12876552" start="0" end="19" time = "68.4392" name = " (D1) " distance = "2091.198" turn = "Keep left" turn_angle = "-1.5127182" start_bearing = "123.56632" end_bearing = "136.06006" description = "Keep left and go 2307.70 meters (*)" />
<segment id="38891873" start="0" end="1" time = "0.90000695" name = " (D1) " distance = "27.500212" start_bearing = "131.0741" end_bearing = "131.0741" description = "" />
<segment id="38891874" start="0" end="1" time = "6.1855593" name = " (D1) " distance = "189.0032" start_bearing = "131.0304" end_bearing = "131.0304" description = "" />
<segment id="38891874" start="1" end="4" time = "31.951897" name = " (D1) " distance = "976.3079" turn = "Keep left" turn_angle = "-1.8799286" start_bearing = "129.15047" end_bearing = "131.45427" description = "Keep left and go 6695.29 meters (*)" />
<segment id="12876541" start="0" end="3" time = "35.008175" name = " (D1) " distance = "1264.1841" start_bearing = "133.79936" end_bearing = "124.68058" description = "" />
<segment id="22747979" start="0" end="1" time = "3.9542692" name = " (D1) " distance = "142.79305" start_bearing = "125.22133" end_bearing = "125.22133" description = "" />
<segment id="22747980" start="0" end="10" time = "64.399284" name = " (D1) " distance = "2325.5298" start_bearing = "125.10681" end_bearing = "115.68128" description = "" />
<segment id="38892034" start="0" end="1" time = "1.1556858" name = " (D1) " distance = "41.733097" start_bearing = "115.621994" end_bearing = "115.621994" description = "" />
<segment id="38892035" start="0" end="5" time = "50.329838" name = " (D1) " distance = "1817.4663" start_bearing = "115.70074" end_bearing = "124.54682" description = "" />
<segment id="4078526" start="0" end="1" time = "3.5245652" name = " (D1) " distance = "127.27596" start_bearing = "123.98289" end_bearing = "123.98289" description = "" />
<segment id="4078526" start="1" end="15" time = "160.77141" name = " (D1) " distance = "5805.634" turn = "Keep left" turn_angle = "-3.836914" start_bearing = "120.14597" end_bearing = "131.46771" description = "Keep left and go 6419.31 meters (*)" />
<segment id="51179620" start="0" end="1" time = "1.2204846" name = " (D1) " distance = "44.073055" start_bearing = "131.40123" end_bearing = "131.40123" description = "" />
<segment id="51179614" start="0" end="2" time = "15.773702" name = " (D1) " distance = "569.6059" start_bearing = "131.47899" end_bearing = "129.83476" description = "" />
<segment id="51179614" start="2" end="6" time = "29.88488" name = " (D1) " distance = "1079.1763" turn = "Keep left" turn_angle = "-3.3793259" start_bearing = "126.45544" end_bearing = "113.421906" description = "Keep left and go 2263.93 meters (*)" />
<segment id="51179619" start="0" end="1" time = "1.6894739" name = " (D1) " distance = "61.008778" start_bearing = "113.34401" end_bearing = "113.34401" description = "" />
<segment id="51179613" start="0" end="5" time = "31.11908" name = " (D1) " distance = "1123.7445" start_bearing = "111.062355" end_bearing = "106.41528" description = "" />
<segment id="51179613" start="5" end="7" time = "8.596398" name = " (D1) " distance = "310.42548" turn = "Keep left" turn_angle = "1.8207245" start_bearing = "108.23601" end_bearing = "111.097946" description = "Keep left and go 3988.02 meters (*)" />
<segment id="34780548" start="0" end="1" time = "0.688714" name = " (D1) " distance = "24.870228" start_bearing = "110.71417" end_bearing = "110.71417" description = "" />
<segment id="34780549" start="0" end="1" time = "6.8291125" name = " (D1) " distance = "246.60684" start_bearing = "110.83636" end_bearing = "110.83636" description = "" />
<segment id="4610862" start="0" end="1" time = "11.824662" name = " (D1) " distance = "427.0017" start_bearing = "111.10313" end_bearing = "111.10313" description = "" />
<segment id="22747632" start="0" end="1" time = "1.9018472" name = " (D1) " distance = "68.67782" start_bearing = "107.67105" end_bearing = "107.67105" description = "" />
<segment id="22747633" start="0" end="6" time = "80.59664" name = " (D1) " distance = "2910.434" start_bearing = "106.81263" end_bearing = "95.988754" description = "" />
<segment id="22747633" start="6" end="12" time = "51.008945" name = " (D1) " distance = "1841.9896" turn = "Keep left" turn_angle = "1.4799881" lanes = "[1, 1, 0]" start_bearing = "97.46874" end_bearing = "121.72555" description = "Keep left[1, 1, 0] and go 1841.99 meters (*)" />
<segment id="22747633" start="12" end="49" time = "279.2498" name = " (D1) " distance = "10084.02" turn = "Keep left" turn_angle = "0.24525452" lanes = "[1, 1, 0]" start_bearing = "121.9708" end_bearing = "133.86182" description = "Keep left[1, 1, 0] and go 10228.45 meters (*)" />
<segment id="22731678" start="0" end="1" time = "2.6552923" name = " (D1) " distance = "95.88555" start_bearing = "134.50323" end_bearing = "134.50323" description = "" />
<segment id="22731679" start="0" end="1" time = "1.3442168" name = " (D1) " distance = "48.54116" start_bearing = "137.74165" end_bearing = "137.74165" description = "" />
<segment id="22731679" start="1" end="17" time = "99.423744" name = " (D1) " distance = "3590.3018" turn = "Keep left" turn_angle = "2.443924" lanes = "[1, 1, 0]" start_bearing = "140.18558" end_bearing = "119.83446" description = "Keep left[1, 1, 0] and go 3793.93 meters (*)" />
<segment id="4742968" start="0" end="1" time = "5.6390696" name = " (D1) " distance = "203.63306" start_bearing = "116.61421" end_bearing = "116.61421" description = "" />
<segment id="4019266" start="0" end="12" time = "16.798882" name = "" distance = "373.30847" turn = "Keep right" turn_angle = "1.0724487" lanes = "[0, 0, 1]" start_bearing = "117.68666" end_bearing = "57.847706" description = "Keep right[0, 0, 1] and go 748.04 meters" />
<segment id="129822710" start="0" end="1" time = "2.898033" name = " (23) " distance = "80.500916" start_bearing = "68.63497" end_bearing = "68.63497" description = "" />
<segment id="4043629" start="0" end="3" time = "8.883274" name = " (602) " distance = "148.05458" start_bearing = "75.198006" end_bearing = "102.388466" description = "" />
<segment id="12841635" start="0" end="2" time = "4.271525" name = " (602) " distance = "71.192085" start_bearing = "91.97494" end_bearing = "76.39027" description = "" />
<segment id="12841636" start="0" end="1" time = "4.4987855" name = " (602) " distance = "74.97976" start_bearing = "72.8863" end_bearing = "72.8863" description = "" />
<segment id="12841636" start="1" end="3" time = "6.8179064" name = " (602) " distance = "113.631775" turn = "Keep right" turn_angle = "0.093177795" start_bearing = "72.97948" end_bearing = "81.41638" description = "Keep right and go 113.63 meters (*)" />
<segment id="5375491" start="0" end="2" time = "13.396884" name = " (602) " distance = "223.2814" turn = "Make uturn" turn_angle = "-167.24919" start_bearing = "-85.83281" end_bearing = "-90.86659" description = "Make uturn and go 223.28 meters" />
<segment id="5375491" start="2" end="4" time = "8.294335" name = " (602) " distance = "138.23892" turn = "Keep left" turn_angle = "-6.180916" start_bearing = "-97.04751" end_bearing = "-104.44903" description = "Keep left and go 1672.84 meters (*)" />
<segment id="39812443" start="0" end="1" time = "2.781806" name = " (602) " distance = "46.36343" start_bearing = "-109.653824" end_bearing = "-109.653824" description = "" />
<segment id="5587921" start="0" end="1" time = "2.950296" name = " (23) " distance = "81.95266" start_bearing = "-110.99872" end_bearing = "-110.99872" description = "" />
<segment id="129822709" start="0" end="10" time = "37.794914" name = " (23) " distance = "1049.8588" start_bearing = "-107.19449" end_bearing = "-75.04991" description = "" />
<segment id="40480847" start="0" end="6" time = "16.039394" name = " (23) " distance = "356.431" start_bearing = "-79.401566" end_bearing = "-111.087685" description = "" />
<segment id="48852859" start="0" end="1" time = "2.184517" name = " (23) " distance = "48.54482" turn = "Keep left" turn_angle = "-8.319504" start_bearing = "-119.40719" end_bearing = "-119.40719" description = "Keep left and go 1105.95 meters (*)" />
<segment id="40480846" start="0" end="5" time = "38.06651" name = " (23) " distance = "1057.4031" start_bearing = "-122.6034" end_bearing = "-126.13275" description = "" />
<segment id="6905687" start="0" end="22" time = "82.17584" name = " (394) " distance = "1369.5973" turn = "Turn left" turn_angle = "-72.02673" start_bearing = "161.84052" end_bearing = "-134.11859" description = "Turn left and go 1369.60 meters" />
<segment id="6905687" start="22" end="23" time = "2.6222274" name = " (394) " distance = "43.703793" turn = "Turn slightly left" turn_angle = "-47.95456" start_bearing = "177.92685" end_bearing = "177.92685" description = "Turn slightly left and go 562.21 meters" />
<segment id="48151948" start="0" end="1" time = "0.66179377" name = " (394) " distance = "11.029897" start_bearing = "175.156" end_bearing = "175.156" description = "" />
<segment id="28908949" start="0" end="1" time = "1.874181" name = " (394) " distance = "31.236351" start_bearing = "175.26656" end_bearing = "175.26656" description = "" />
<segment id="28908950" start="0" end="1" time = "1.479829" name = "Nádražní (394) " distance = "24.663815" start_bearing = "-160.70996" end_bearing = "-160.70996" description = "" />
<segment id="115619534" start="0" end="4" time = "11.534336" name = "Nádražní (394) " distance = "192.23892" start_bearing = "-160.55997" end_bearing = "-156.58263" description = "" />
<segment id="38127607" start="0" end="2" time = "25.71455" name = " (394) " distance = "11.9091625" start_bearing = "-156.8014" end_bearing = "-157.89055" description = "" />
<segment id="8025800" start="0" end="3" time = "53.640903" name = "Na Brněnce (394) " distance = "60.681717" start_bearing = "-158.1986" end_bearing = "-163.0245" description = "" />
<segment id="38127604" start="0" end="4" time = "11.204794" name = "Palackého (394) " distance = "186.74657" start_bearing = "-157.6403" end_bearing = "-117.99715" description = "" />
<segment id="38127604" start="4" end="7" time = "6.2677417" name = "Palackého (394) " distance = "104.46236" turn = "Keep right" turn_angle = "24.183075" start_bearing = "-93.81407" end_bearing = "-102.05078" description = "Keep right and go 104.46 meters (*)" />
<segment id="38127604" start="7" end="8" time = "0.83324337" name = "Palackého (394) " distance = "13.88739" turn = "Keep left" turn_angle = "-24.819115" start_bearing = "-126.869896" end_bearing = "-126.869896" description = "Keep left and go 13.89 meters" />
<segment id="38127604" start="8" end="11" time = "23.940708" name = "Palackého (394) " distance = "399.0118" turn = "Keep left" turn_angle = "-22.71305" start_bearing = "-149.58295" end_bearing = "-151.2651" description = "Keep left and go 3703.53 meters" />
<segment id="98748263" start="0" end="1" time = "1.0517589" name = "Palackého (394) " distance = "17.529314" start_bearing = "-147.52881" end_bearing = "-147.52881" description = "" />
<segment id="98748259" start="0" end="3" time = "24.772429" name = "Palackého (394) " distance = "412.8738" start_bearing = "-143.0224" end_bearing = "-119.21358" description = "" />
<segment id="98748248" start="0" end="13" time = "127.26957" name = " (394) " distance = "2121.1594" start_bearing = "-119.14063" end_bearing = "-164.20407" description = "" />
<segment id="45101822" start="0" end="2" time = "17.58294" name = " (394) " distance = "244.20749" start_bearing = "-173.19868" end_bearing = "-168.30322" description = "" />
<segment id="51738023" start="0" end="7" time = "36.629616" name = " (394) " distance = "508.74466" start_bearing = "-157.40166" end_bearing = "142.65915" description = "" />
<segment id="51738024" start="0" end="2" time = "4.0385013" name = " (394) " distance = "56.090298" turn = "Turn slightly right" turn_angle = "58.440933" start_bearing = "-158.89992" end_bearing = "-144.10733" description = "Turn slightly right and go 56.09 meters" />
<segment id="150980321" start="0" end="5" time = "31.654377" name = " (394) " distance = "439.64413" turn = "Keep left" turn_angle = "-22.322235" start_bearing = "-166.42957" end_bearing = "-166.70993" description = "Keep left and go 590.18 meters" />
<segment id="45101820" start="0" end="3" time = "9.032092" name = " (394) " distance = "150.53487" start_bearing = "-172.27136" end_bearing = "179.11859" description = "" />
<segment id="45101820" start="3" end="5" time = "1.8757632" name = " (394) " distance = "31.26272" turn = "Keep right" turn_angle = "23.55275" start_bearing = "-157.32866" end_bearing = "-137.77916" description = "Keep right and go 31.26 meters (*)" />
<segment id="26134637" start="0" end="46" time = "340.66763" name = " (39410) " distance = "4258.3457" turn = "Turn right" turn_angle = "70.503265" start_bearing = "-67.275894" end_bearing = "158.44292" description = "Turn right and go 4258.35 meters" />
<segment id="26134637" start="46" end="57" time = "29.622349" name = " (39410) " distance = "370.27936" turn = "Turn slightly right" turn_angle = "48.81241" start_bearing = "-152.74467" end_bearing = "-129.4495" description = "Turn slightly right and go 757.76 meters" />
<segment id="38087319" start="1" end="0" time = "1.0348622" name = "Oslavanská (393) " distance = "17.247704" start_bearing = "-95.97433" end_bearing = "-95.97433" description = "" />
<segment id="38087318" start="1" end="0" time = "2.1630492" name = "Oslavanská (393) " distance = "36.05082" start_bearing = "-95.927505" end_bearing = "-95.927505" description = "" />
<segment id="25211357" start="3" end="0" time = "7.1650267" name = "Oslavanská (393) " distance = "119.417114" start_bearing = "-96.08853" end_bearing = "-96.16545" description = "" />
<segment id="25211061" start="0" end="2" time = "4.8646584" name = " (393) " distance = "81.07764" start_bearing = "-91.98252" end_bearing = "-65.071526" description = "" />
<segment id="48151944" start="0" end="2" time = "8.020991" name = " (393) " distance = "133.6832" start_bearing = "-48.08765" end_bearing = "-32.82854" description = "" />
<segment id="38087313" start="0" end="4" time = "19.534384" name = "" distance = "189.91763" turn = "Turn left" turn_angle = "-82.94078" start_bearing = "-115.769325" end_bearing = "173.47635" description = "Turn left and go 189.92 meters" />
</test>
</router_tests>

View file

@ -1,403 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="" description="Long route to Maastricht" best_percent="5" vehicle="car"
start_lat="52.290868841722975" start_lon="4.831130504608154" target_lat="50.85492897352447" target_lon="5.701689720153809" complete_time="7043.331" complete_distance = "208488.69" routing_time = "8800" >
<segment id="7366509" start="9" end="11" time = "9.088743" name = "" distance = "75.739525" turn = "Go ahead" turn_angle = "0.0" start_bearing = "115.31378" end_bearing = "115.46335" description = "Go ahead and go 75.74 meters" />
<segment id="47633918" start="2" end="1" time = "2.140907" name = "Noorddammerweg" distance = "26.761337" turn = "Turn right" turn_angle = "89.33931" start_bearing = "-155.19734" end_bearing = "-155.19734" description = "Turn right and go 26.76 meters" />
<segment id="7367247" start="2" end="0" time = "20.482542" name = "Zetterij" distance = "256.03177" turn = "Turn left" turn_angle = "-90.48619" start_bearing = "114.31647" end_bearing = "106.46359" description = "Turn left and go 761.63 meters" />
<segment id="7364788" start="4" end="0" time = "23.708342" name = "Zetterij" distance = "296.35428" start_bearing = "108.9465" end_bearing = "115.2737" description = "" />
<segment id="7364764" start="1" end="0" time = "1.6481074" name = "Zetterij" distance = "20.601343" start_bearing = "111.709885" end_bearing = "111.709885" description = "" />
<segment id="7364763" start="1" end="0" time = "6.9382887" name = "Zetterij" distance = "86.728615" start_bearing = "112.44515" end_bearing = "112.44515" description = "" />
<segment id="7364766" start="1" end="0" time = "1.1748635" name = "Zetterij" distance = "14.685793" start_bearing = "119.27525" end_bearing = "119.27525" description = "" />
<segment id="7364508" start="0" end="2" time = "6.2802095" name = "Zetterij" distance = "87.225136" start_bearing = "110.00669" end_bearing = "94.62415" description = "" />
<segment id="7365070" start="0" end="1" time = "1.0716465" name = "Bovenkerkerweg (N521) " distance = "14.883979" turn = "Turn right" turn_angle = "94.95008" start_bearing = "-170.42577" end_bearing = "-170.42577" description = "Turn right and go 58.89 meters" />
<segment id="7365086" start="0" end="1" time = "3.1682494" name = "Bovenkerkerweg (N521) " distance = "44.003468" start_bearing = "-172.57889" end_bearing = "-172.57889" description = "" />
<segment id="7365086" start="1" end="3" time = "30.227621" name = "Bovenkerkerweg (N521) " distance = "72.60584" turn = "Keep right" turn_angle = "1.9589691" start_bearing = "-170.61992" end_bearing = "-173.29016" description = "Keep right and go 110.76 meters" />
<segment id="7365099" start="0" end="3" time = "2.747028" name = "Bovenkerkerweg (N521) " distance = "38.15317" start_bearing = "-173.21103" end_bearing = "-177.61406" description = "" />
<segment id="7365062" start="6" end="7" time = "0.84723866" name = "Beneluxbaan" distance = "11.767203" turn = "Make uturn" turn_angle = "0.0" start_bearing = "97.0165" end_bearing = "97.0165" description = "Make uturn and go 1105.87 meters" />
<segment id="7365101" start="0" end="3" time = "2.8561046" name = "Bovenkerkerweg (N521) " distance = "39.66812" start_bearing = "10.885527" end_bearing = "11.458753" description = "" />
<segment id="7365085" start="0" end="1" time = "8.459829" name = "Bovenkerkerweg (N521) " distance = "117.49763" start_bearing = "6.4971123" end_bearing = "6.4971123" description = "" />
<segment id="7365069" start="0" end="1" time = "0.57796" name = "Bovenkerkerweg (N521) " distance = "8.027223" start_bearing = "5.3145456" end_bearing = "5.3145456" description = "" />
<segment id="7364510" start="0" end="1" time = "1.1475279" name = "Bovenkerkerweg (N521) " distance = "15.937888" start_bearing = "12.60016" end_bearing = "12.60016" description = "" />
<segment id="7364786" start="0" end="2" time = "9.050575" name = "Bovenkerkerweg (N521) " distance = "125.70244" start_bearing = "7.8605475" end_bearing = "-2.726311" description = "" />
<segment id="7364769" start="0" end="2" time = "16.702217" name = "Bovenkerkerweg (N521) " distance = "278.3703" start_bearing = "10.541818" end_bearing = "8.130102" description = "" />
<segment id="7364781" start="0" end="6" time = "64.496864" name = "Handweg" distance = "548.56757" start_bearing = "8.130102" end_bearing = "9.901572" description = "" />
<segment id="7364782" start="1" end="0" time = "26.062386" name = "Keizer Karelweg" distance = "14.755359" turn = "Turn right" turn_angle = "89.328316" start_bearing = "99.22989" end_bearing = "99.22989" description = "Turn right and go 917.26 meters" />
<segment id="7364779" start="0" end="5" time = "13.558414" name = "Keizer Karelweg" distance = "188.31131" start_bearing = "96.254036" end_bearing = "66.169136" description = "" />
<segment id="7364775" start="1" end="0" time = "4.9813266" name = "Keizer Karelweg" distance = "69.18509" start_bearing = "62.372807" end_bearing = "62.372807" description = "" />
<segment id="7364776" start="0" end="1" time = "4.9812937" name = "Keizer Karelweg" distance = "69.18464" start_bearing = "62.334564" end_bearing = "62.334564" description = "" />
<segment id="7364778" start="0" end="1" time = "3.806921" name = "Keizer Karelweg" distance = "52.873905" start_bearing = "62.48443" end_bearing = "62.48443" description = "" />
<segment id="7364787" start="0" end="1" time = "0.5657692" name = "Keizer Karelweg" distance = "7.8579054" start_bearing = "65.897766" end_bearing = "65.897766" description = "" />
<segment id="7364771" start="0" end="1" time = "1.5512005" name = "Keizer Karelweg" distance = "21.544453" start_bearing = "61.50436" end_bearing = "61.50436" description = "" />
<segment id="58661684" start="0" end="1" time = "0.6126022" name = "Keizer Karelweg" distance = "8.508364" start_bearing = "61.189205" end_bearing = "61.189205" description = "" />
<segment id="7364071" start="0" end="1" time = "4.6289053" name = "Keizer Karelweg" distance = "64.29035" start_bearing = "62.34026" end_bearing = "62.34026" description = "" />
<segment id="7364489" start="0" end="1" time = "3.0778131" name = "Keizer Karelweg" distance = "42.747406" start_bearing = "62.333244" end_bearing = "62.333244" description = "" />
<segment id="7364488" start="0" end="1" time = "0.8222186" name = "Keizer Karelweg" distance = "11.4197035" start_bearing = "62.19854" end_bearing = "62.19854" description = "" />
<segment id="7364487" start="0" end="1" time = "3.6412437" name = "Keizer Karelweg" distance = "50.57283" start_bearing = "63.893307" end_bearing = "63.893307" description = "" />
<segment id="7364482" start="0" end="1" time = "2.4905744" name = "Keizer Karelweg" distance = "34.59131" start_bearing = "61.38954" end_bearing = "61.38954" description = "" />
<segment id="7364483" start="0" end="1" time = "2.506028" name = "Keizer Karelweg" distance = "34.805946" start_bearing = "57.228592" end_bearing = "57.228592" description = "" />
<segment id="48147997" start="0" end="2" time = "2.944532" name = "Keizer Karelweg" distance = "40.89628" start_bearing = "57.707115" end_bearing = "51.679886" description = "" />
<segment id="7364498" start="0" end="2" time = "3.2543092" name = "Keizer Karelweg" distance = "45.198742" start_bearing = "52.460567" end_bearing = "70.857735" description = "" />
<segment id="7364496" start="0" end="1" time = "1.0199182" name = "Keizer Karelweg" distance = "14.165531" start_bearing = "53.746162" end_bearing = "53.746162" description = "" />
<segment id="58384522" start="0" end="4" time = "30.041615" name = "Keizer Karelweg" distance = "70.02242" start_bearing = "9.050722" end_bearing = "19.798876" description = "" />
<segment id="7364485" start="0" end="2" time = "5.4958763" name = "Keizer Karelweg" distance = "76.33162" start_bearing = "28.694904" end_bearing = "18.610165" description = "" />
<segment id="7364485" start="2" end="3" time = "2.772" name = "Keizer Karelweg" distance = "38.500004" turn = "Keep right" turn_angle = "7.832197" start_bearing = "26.442362" end_bearing = "26.442362" description = "Keep right and go 38.50 meters" />
<segment id="49900222" start="0" end="1" time = "26.05053" name = " (5) " distance = "29.181383" turn = "Keep right" turn_angle = "26.471804" start_bearing = "52.914165" end_bearing = "52.914165" description = "Keep right and go 29.18 meters" />
<segment id="7364501" start="1" end="14" time = "15.055797" name = " (5) " distance = "418.21658" turn = "Turn right" turn_angle = "72.713745" start_bearing = "125.62791" end_bearing = "101.61149" description = "Turn right and go 860.22 meters" />
<segment id="7363599" start="0" end="2" time = "15.912092" name = "Burgemeester van Sonweg (A9) " distance = "442.0026" start_bearing = "110.03965" end_bearing = "111.34803" description = "" />
<segment id="73841697" start="0" end="1" time = "3.0741942" name = "Burgemeester van Sonweg (A9) " distance = "85.39429" turn = "Keep left" turn_angle = "-1.123169" lanes = "[1, 1, 1, 0]" start_bearing = "110.22486" end_bearing = "110.22486" description = "Keep left[1, 1, 1, 0] and go 5031.67 meters (*)" />
<segment id="73841702" start="0" end="6" time = "23.457874" name = "Burgemeester van Sonweg (A9) " distance = "651.60767" start_bearing = "110.73096" end_bearing = "102.372154" description = "" />
<segment id="7363585" start="0" end="1" time = "3.1736984" name = "Burgemeester van Sonweg (A9) " distance = "88.158295" start_bearing = "102.43956" end_bearing = "102.43956" description = "" />
<segment id="7363584" start="0" end="2" time = "11.333597" name = "Burgemeester van Sonweg (A9) " distance = "314.82217" start_bearing = "101.97764" end_bearing = "102.30124" description = "" />
<segment id="7361538" start="0" end="3" time = "14.295719" name = "Burgemeester van Sonweg (A9) " distance = "397.1033" start_bearing = "104.50872" end_bearing = "108.59298" description = "" />
<segment id="142320420" start="0" end="2" time = "5.5521536" name = "Burgemeester van Sonweg (A9) " distance = "154.22649" start_bearing = "110.93831" end_bearing = "113.5104" description = "" />
<segment id="7361528" start="0" end="2" time = "17.812927" name = "Burgemeester van Sonweg (A9) " distance = "494.80356" start_bearing = "116.33478" end_bearing = "118.19917" description = "" />
<segment id="7361526" start="0" end="1" time = "1.9970839" name = "Burgemeester van Sonweg (A9) " distance = "55.474556" start_bearing = "116.99262" end_bearing = "116.99262" description = "" />
<segment id="7052161" start="0" end="5" time = "41.986267" name = "Burgemeester van Sonweg (A9) " distance = "1166.2852" start_bearing = "115.737404" end_bearing = "107.69727" description = "" />
<segment id="73841596" start="0" end="1" time = "4.142789" name = "Burgemeester van Sonweg (A9) " distance = "115.07747" start_bearing = "105.54368" end_bearing = "105.54368" description = "" />
<segment id="73841593" start="0" end="7" time = "45.15565" name = "Burgemeester van Sonweg (A9) " distance = "1254.3236" start_bearing = "104.22892" end_bearing = "94.48044" description = "" />
<segment id="7052166" start="0" end="1" time = "2.1076596" name = "Burgemeester van Sonweg (A9) " distance = "58.546097" start_bearing = "94.316025" end_bearing = "94.316025" description = "" />
<segment id="7052167" start="0" end="1" time = "7.050495" name = "Burgemeester van Sonweg (A9) " distance = "195.84709" start_bearing = "92.99034" end_bearing = "92.99034" description = "" />
<segment id="7050550" start="0" end="14" time = "45.65967" name = " (A2) " distance = "1268.3242" turn = "Keep right" turn_angle = "3.1677475" lanes = "[0, 0, 1, 1]" start_bearing = "96.15809" end_bearing = "155.08707" description = "Keep right[0, 0, 1, 1] and go 2825.55 meters" />
<segment id="7050539" start="0" end="1" time = "5.4304996" name = " (A2) " distance = "150.84721" start_bearing = "154.9497" end_bearing = "154.9497" description = "" />
<segment id="7050532" start="0" end="1" time = "4.303684" name = " (A2) " distance = "119.54679" start_bearing = "154.99895" end_bearing = "154.99895" description = "" />
<segment id="7052391" start="0" end="5" time = "46.325794" name = " (A2) " distance = "1286.8276" start_bearing = "154.56238" end_bearing = "163.39973" description = "" />
<segment id="79276793" start="0" end="4" time = "21.940208" name = " (A2) " distance = "609.45026" turn = "Keep left" turn_angle = "-2.96138" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "160.43835" end_bearing = "160.22612" description = "Keep left[1, 1, 1, 1, 1, 0] and go 4179.89 meters (*)" />
<segment id="7052394" start="0" end="1" time = "3.6575377" name = " (A2) " distance = "101.598274" start_bearing = "161.66277" end_bearing = "161.66277" description = "" />
<segment id="7052396" start="0" end="1" time = "2.5187688" name = " (A2) " distance = "69.965805" start_bearing = "161.65929" end_bearing = "161.65929" description = "" />
<segment id="7048564" start="0" end="2" time = "10.061515" name = " (A2) " distance = "279.4865" start_bearing = "165.30898" end_bearing = "166.53188" description = "" />
<segment id="179467573" start="0" end="6" time = "77.62425" name = " (A2) " distance = "2156.2292" start_bearing = "166.56369" end_bearing = "161.2148" description = "" />
<segment id="7048569" start="0" end="1" time = "1.9461962" name = " (A2) " distance = "54.06101" start_bearing = "161.44237" end_bearing = "161.44237" description = "" />
<segment id="7048574" start="0" end="2" time = "23.552534" name = " (A2) " distance = "654.2371" start_bearing = "161.33673" end_bearing = "159.06078" description = "" />
<segment id="179467574" start="0" end="2" time = "9.175154" name = " (A2) " distance = "254.86539" start_bearing = "159.10223" end_bearing = "157.23166" description = "" />
<segment id="127580800" start="0" end="5" time = "31.653484" name = " (A2) " distance = "879.2635" turn = "Keep left" turn_angle = "-5.7964783" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "151.43518" end_bearing = "160.15231" description = "Keep left[1, 1, 1, 1, 1, 0] and go 6003.83 meters (*)" />
<segment id="156689123" start="0" end="1" time = "1.2813264" name = " (A2) " distance = "35.5924" start_bearing = "162.03085" end_bearing = "162.03085" description = "" />
<segment id="7071327" start="0" end="2" time = "4.237085" name = " (A2) " distance = "117.69681" start_bearing = "165.54758" end_bearing = "165.56084" description = "" />
<segment id="7071344" start="0" end="1" time = "3.895726" name = " (A2) " distance = "108.214615" start_bearing = "167.9524" end_bearing = "167.9524" description = "" />
<segment id="156689148" start="0" end="12" time = "175.07043" name = " (A2) " distance = "4863.068" start_bearing = "171.80692" end_bearing = "177.47583" description = "" />
<segment id="7071319" start="0" end="2" time = "23.41219" name = " (A2) " distance = "650.3386" turn = "Keep left" turn_angle = "1.7103577" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "179.18619" end_bearing = "177.08644" description = "Keep left[1, 1, 1, 1, 1, 0] and go 3519.18 meters (*)" />
<segment id="7071324" start="0" end="1" time = "1.5838847" name = " (A2) " distance = "43.9968" start_bearing = "176.88657" end_bearing = "176.88657" description = "" />
<segment id="7070772" start="0" end="1" time = "7.2220364" name = " (A2) " distance = "200.61214" start_bearing = "177.91554" end_bearing = "177.91554" description = "" />
<segment id="127580788" start="0" end="1" time = "1.3697265" name = " (A2) " distance = "38.047962" start_bearing = "179.16159" end_bearing = "179.16159" description = "" />
<segment id="127580809" start="0" end="8" time = "36.29545" name = " (A2) " distance = "1008.207" start_bearing = "178.4745" end_bearing = "156.75131" description = "" />
<segment id="7070784" start="0" end="1" time = "1.6745965" name = " (A2) " distance = "46.51657" start_bearing = "156.89088" end_bearing = "156.89088" description = "" />
<segment id="127580802" start="0" end="3" time = "55.132523" name = " (A2) " distance = "1531.459" start_bearing = "155.18443" end_bearing = "157.22044" description = "" />
<segment id="127580802" start="3" end="5" time = "23.851204" name = " (A2) " distance = "662.53345" turn = "Keep left" turn_angle = "-0.8713379" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "156.3491" end_bearing = "157.03491" description = "Keep left[1, 1, 1, 1, 1, 0] and go 3086.16 meters (*)" />
<segment id="76140687" start="0" end="1" time = "1.273901" name = " (A2) " distance = "35.38614" start_bearing = "157.15196" end_bearing = "157.15196" description = "" />
<segment id="76140684" start="0" end="12" time = "85.97655" name = " (A2) " distance = "2388.2375" start_bearing = "158.17053" end_bearing = "133.95096" description = "" />
<segment id="79262900" start="0" end="8" time = "33.028996" name = " (A2) " distance = "917.4721" turn = "Keep left" turn_angle = "-1.6629486" lanes = "[1, 1, 1, 1, 0, 0]" start_bearing = "132.28801" end_bearing = "124.28688" description = "Keep left[1, 1, 1, 1, 0, 0] and go 6977.00 meters" />
<segment id="79262901" start="0" end="11" time = "83.45524" name = " (A2) " distance = "2318.2012" start_bearing = "123.34157" end_bearing = "138.1617" description = "" />
<segment id="7061299" start="0" end="4" time = "12.982101" name = " (A2) " distance = "360.61395" start_bearing = "137.78456" end_bearing = "139.08562" description = "" />
<segment id="151258641" start="0" end="6" time = "22.246897" name = " (A2) " distance = "617.96936" start_bearing = "143.19708" end_bearing = "150.50703" description = "" />
<segment id="80761370" start="0" end="9" time = "58.68163" name = "Leidsche Rijntunnel (A2) " distance = "1630.0453" start_bearing = "153.77612" end_bearing = "172.87498" description = "" />
<segment id="80761383" start="0" end="2" time = "11.184597" name = " (A2) " distance = "310.68326" start_bearing = "174.99852" end_bearing = "179.38173" description = "" />
<segment id="80761369" start="0" end="1" time = "1.9537628" name = " (A2) " distance = "54.27119" start_bearing = "-178.45705" end_bearing = "-178.45705" description = "" />
<segment id="152126643" start="0" end="8" time = "27.638739" name = " (A2) " distance = "767.7428" start_bearing = "-176.12459" end_bearing = "-165.6754" description = "" />
<segment id="93810171" start="0" end="1" time = "8.644352" name = " (A2) " distance = "240.1209" turn = "Keep left" turn_angle = "-1.1266632" lanes = "[1, 1, 0, 0]" start_bearing = "-166.80206" end_bearing = "-166.80206" description = "Keep left[1, 1, 0, 0] and go 4539.38 meters" />
<segment id="7054468" start="0" end="2" time = "29.638718" name = " (A2) " distance = "823.2977" start_bearing = "-167.47635" end_bearing = "-165.95709" description = "" />
<segment id="7054457" start="0" end="1" time = "3.6500416" name = " (A2) " distance = "101.390045" start_bearing = "-166.36688" end_bearing = "-166.36688" description = "" />
<segment id="7054352" start="0" end="3" time = "24.02921" name = " (A2) " distance = "667.478" start_bearing = "-165.3489" end_bearing = "-165.1765" description = "" />
<segment id="78380419" start="0" end="1" time = "1.7932974" name = " (A2) " distance = "49.81382" start_bearing = "-165.75967" end_bearing = "-165.75967" description = "" />
<segment id="78380416" start="0" end="1" time = "6.098158" name = " (A2) " distance = "169.39328" start_bearing = "-164.95683" end_bearing = "-164.95683" description = "" />
<segment id="7064773" start="0" end="10" time = "66.43809" name = " (A2) " distance = "1845.5026" start_bearing = "-165.6186" end_bearing = "-178.60915" description = "" />
<segment id="48836778" start="0" end="1" time = "1.2691222" name = " (A2) " distance = "35.2534" start_bearing = "-177.61406" end_bearing = "-177.61406" description = "" />
<segment id="48836779" start="0" end="3" time = "21.856815" name = " (A2) " distance = "607.1338" start_bearing = "-179.3338" end_bearing = "-178.12825" description = "" />
<segment id="178647034" start="0" end="2" time = "9.700615" name = " (A2) " distance = "269.46155" turn = "Keep left" turn_angle = "-0.6485443" lanes = "[1, 1, 1, 1, 0]" start_bearing = "-178.7768" end_bearing = "-178.34505" description = "Keep left[1, 1, 1, 1, 0] and go 3330.81 meters (*)" />
<segment id="7064794" start="0" end="10" time = "42.247013" name = " (A2) " distance = "1173.5282" start_bearing = "-179.2284" end_bearing = "165.80145" description = "" />
<segment id="7064545" start="0" end="1" time = "12.333144" name = " (A2) " distance = "342.58737" start_bearing = "163.14783" end_bearing = "163.14783" description = "" />
<segment id="178069079" start="0" end="1" time = "0.93667734" name = " (A2) " distance = "26.018816" start_bearing = "163.0725" end_bearing = "163.0725" description = "" />
<segment id="178069080" start="0" end="1" time = "0.5939401" name = " (A2) " distance = "16.498337" start_bearing = "162.84758" end_bearing = "162.84758" description = "" />
<segment id="7104689" start="0" end="1" time = "2.6430216" name = " (A2) " distance = "73.41727" start_bearing = "163.73979" end_bearing = "163.73979" description = "" />
<segment id="7103427" start="0" end="6" time = "43.938156" name = " (A2) " distance = "1220.5044" start_bearing = "163.17859" end_bearing = "160.65762" description = "" />
<segment id="7103414" start="0" end="1" time = "1.6054673" name = " (A2) " distance = "44.596317" start_bearing = "162.22868" end_bearing = "162.22868" description = "" />
<segment id="7103412" start="0" end="1" time = "5.9111137" name = " (A2) " distance = "164.1976" start_bearing = "162.19199" end_bearing = "162.19199" description = "" />
<segment id="7103443" start="0" end="2" time = "17.572462" name = " (A2) " distance = "488.124" turn = "Keep left" turn_angle = "2.604477" lanes = "[1, 1, 1, 0]" start_bearing = "164.79646" end_bearing = "166.83194" description = "Keep left[1, 1, 1, 0] and go 1533.52 meters (*)" />
<segment id="7103439" start="0" end="2" time = "9.107542" name = " (A2) " distance = "252.98729" start_bearing = "163.19218" end_bearing = "162.343" description = "" />
<segment id="7103434" start="0" end="3" time = "19.30155" name = " (A2) " distance = "536.1542" start_bearing = "161.72829" end_bearing = "160.20113" description = "" />
<segment id="7102720" start="0" end="1" time = "9.225261" name = " (A2) " distance = "256.25723" start_bearing = "160.61691" end_bearing = "160.61691" description = "" />
<segment id="7104154" start="0" end="2" time = "16.467108" name = " (A2) " distance = "457.41968" turn = "Keep left" turn_angle = "-2.2422028" lanes = "[1, 1, 1, 0]" start_bearing = "158.37471" end_bearing = "157.46214" description = "Keep left[1, 1, 1, 0] and go 1699.12 meters (*)" />
<segment id="7104177" start="0" end="1" time = "2.1778877" name = " (A2) " distance = "60.496883" start_bearing = "155.77225" end_bearing = "155.77225" description = "" />
<segment id="7104172" start="0" end="5" time = "14.296287" name = " (A2) " distance = "397.11908" start_bearing = "152.75946" end_bearing = "136.88458" description = "" />
<segment id="7104142" start="0" end="1" time = "2.0603602" name = " (A2) " distance = "57.23223" start_bearing = "131.77003" end_bearing = "131.77003" description = "" />
<segment id="7104152" start="0" end="1" time = "1.4631333" name = " (A2) " distance = "40.642593" start_bearing = "130.43335" end_bearing = "130.43335" description = "" />
<segment id="7104164" start="0" end="1" time = "10.391346" name = " (A2) " distance = "288.6485" start_bearing = "130.75597" end_bearing = "130.75597" description = "" />
<segment id="86072810" start="0" end="1" time = "7.987593" name = " (A2) " distance = "221.8776" start_bearing = "131.00754" end_bearing = "131.00754" description = "" />
<segment id="7104146" start="0" end="1" time = "3.7763226" name = " (A2) " distance = "104.89785" start_bearing = "129.2824" end_bearing = "129.2824" description = "" />
<segment id="87090708" start="0" end="1" time = "2.5482104" name = " (A2) " distance = "70.78362" start_bearing = "131.8435" end_bearing = "131.8435" description = "" />
<segment id="7102170" start="0" end="1" time = "3.3917997" name = " (A2) " distance = "94.21666" turn = "Keep left" turn_angle = "-0.17274475" lanes = "[1, 1, 1, 0, 0]" start_bearing = "131.67076" end_bearing = "131.67076" description = "Keep left[1, 1, 1, 0, 0] and go 5522.52 meters (*)" />
<segment id="7102178" start="0" end="1" time = "0.71769714" name = " (A2) " distance = "23.923237" start_bearing = "133.43494" end_bearing = "133.43494" description = "" />
<segment id="7102130" start="0" end="10" time = "43.528393" name = " (A2) " distance = "1450.9464" start_bearing = "135.60858" end_bearing = "148.08437" description = "" />
<segment id="7097184" start="0" end="11" time = "109.479805" name = " (A2) " distance = "3953.4375" start_bearing = "148.05557" end_bearing = "133.73483" description = "" />
<segment id="7097194" start="0" end="8" time = "43.497807" name = " (A2) " distance = "1570.754" turn = "Keep left" turn_angle = "0.06976318" lanes = "[1, 1, 1, 1, 0]" start_bearing = "133.8046" end_bearing = "150.01294" description = "Keep left[1, 1, 1, 1, 0] and go 1570.75 meters (*)" />
<segment id="7097194" start="8" end="12" time = "16.804197" name = " (A2) " distance = "606.81824" turn = "Keep left" turn_angle = "-1.9629059" lanes = "[1, 1, 1, 1, 0]" start_bearing = "148.05003" end_bearing = "148.71149" description = "Keep left[1, 1, 1, 1, 0] and go 2206.27 meters (*)" />
<segment id="7097169" start="0" end="1" time = "0.3284921" name = " (A2) " distance = "11.862215" start_bearing = "148.17255" end_bearing = "148.17255" description = "" />
<segment id="7096870" start="0" end="8" time = "43.963947" name = " (A2) " distance = "1587.5869" start_bearing = "147.72594" end_bearing = "155.28047" description = "" />
<segment id="7096870" start="8" end="9" time = "5.4189553" name = " (A2) " distance = "195.6845" turn = "Keep left" turn_angle = "0.73513794" lanes = "[1, 1, 1, 1, 0]" start_bearing = "156.01561" end_bearing = "156.01561" description = "Keep left[1, 1, 1, 1, 0] and go 1907.79 meters (*)" />
<segment id="7098059" start="0" end="1" time = "1.1506269" name = " (A2) " distance = "41.55042" start_bearing = "155.2425" end_bearing = "155.2425" description = "" />
<segment id="7098100" start="0" end="6" time = "46.261436" name = " (A2) " distance = "1670.5518" start_bearing = "155.3205" end_bearing = "149.64128" description = "" />
<segment id="7098100" start="6" end="7" time = "1.5732108" name = " (A2) " distance = "56.810394" turn = "Keep left" turn_angle = "-0.95614624" lanes = "[1, 1, 1, 1, 0]" start_bearing = "148.68513" end_bearing = "148.68513" description = "Keep left[1, 1, 1, 1, 0] and go 2654.42 meters (*)" />
<segment id="7098114" start="0" end="1" time = "2.9690444" name = " (A2) " distance = "107.21549" start_bearing = "147.26477" end_bearing = "147.26477" description = "" />
<segment id="7098118" start="0" end="4" time = "35.539787" name = " (A2) " distance = "1283.3812" start_bearing = "146.94855" end_bearing = "151.58258" description = "" />
<segment id="7098127" start="0" end="1" time = "3.466326" name = " (A2) " distance = "125.17288" start_bearing = "152.30426" end_bearing = "152.30426" description = "" />
<segment id="7092550" start="0" end="4" time = "29.9587" name = " (A2) " distance = "1081.8419" start_bearing = "151.51157" end_bearing = "154.65134" description = "" />
<segment id="7092550" start="4" end="15" time = "44.069485" name = " (A2) " distance = "1591.398" turn = "Keep left" turn_angle = "-2.8650055" lanes = "[1, 1, 1, 1, 0]" start_bearing = "151.78633" end_bearing = "152.6247" description = "Keep left[1, 1, 1, 1, 0] and go 1814.80 meters (*)" />
<segment id="112900344" start="0" end="1" time = "6.701931" name = " (A2) " distance = "223.39769" start_bearing = "152.31825" end_bearing = "152.31825" description = "" />
<segment id="78378519" start="0" end="9" time = "112.09753" name = " (A2) " distance = "3736.5842" turn = "Keep left" turn_angle = "-0.14260864" lanes = "[1, 1, 1, 0, 0]" start_bearing = "152.17564" end_bearing = "149.908" description = "Keep left[1, 1, 1, 0, 0] and go 3736.58 meters (*)" />
<segment id="78378519" start="9" end="11" time = "23.144165" name = " (A2) " distance = "771.47217" turn = "Keep left" turn_angle = "1.1197357" lanes = "[1, 1, 1, 0]" start_bearing = "151.02774" end_bearing = "151.37378" description = "Keep left[1, 1, 1, 0] and go 4246.51 meters (*)" />
<segment id="7092540" start="0" end="1" time = "1.3856925" name = " (A2) " distance = "46.189747" start_bearing = "151.09972" end_bearing = "151.09972" description = "" />
<segment id="7092538" start="0" end="5" time = "18.39537" name = " (A2) " distance = "613.17896" start_bearing = "150.65927" end_bearing = "159.40591" description = "" />
<segment id="87195853" start="0" end="1" time = "1.1823686" name = " (A2) " distance = "39.41229" start_bearing = "161.98946" end_bearing = "161.98946" description = "" />
<segment id="87195831" start="0" end="4" time = "15.733271" name = " (A2) " distance = "524.4423" start_bearing = "165.02228" end_bearing = "173.97273" description = "" />
<segment id="7092534" start="0" end="1" time = "8.92977" name = "Martinus Nijhoffbrug (A2) " distance = "297.65903" start_bearing = "173.48323" end_bearing = "173.48323" description = "" />
<segment id="7092532" start="0" end="4" time = "7.656289" name = " (A2) " distance = "255.20963" start_bearing = "174.74905" end_bearing = "178.70978" description = "" />
<segment id="7092530" start="0" end="1" time = "1.2177086" name = " (A2) " distance = "40.590286" start_bearing = "-179.47676" end_bearing = "-179.47676" description = "" />
<segment id="7083242" start="0" end="8" time = "23.373617" name = " (A2) " distance = "779.12054" start_bearing = "-177.66797" end_bearing = "-177.48619" description = "" />
<segment id="7083262" start="0" end="1" time = "1.0658783" name = " (A2) " distance = "35.529278" start_bearing = "-176.44215" end_bearing = "-176.44215" description = "" />
<segment id="60928833" start="0" end="1" time = "25.311256" name = " (A2) " distance = "843.7085" start_bearing = "-177.94655" end_bearing = "-177.94655" description = "" />
<segment id="7082839" start="0" end="10" time = "58.871197" name = " (A2) " distance = "1962.3732" turn = "Keep left" turn_angle = "0.121292114" lanes = "[1, 1, 1, 0]" start_bearing = "-177.82526" end_bearing = "176.08842" description = "Keep left[1, 1, 1, 0] and go 4778.54 meters (*)" />
<segment id="87195824" start="0" end="1" time = "3.1519196" name = " (A2) " distance = "105.06398" start_bearing = "175.76361" end_bearing = "175.76361" description = "" />
<segment id="87195824" start="1" end="9" time = "24.882273" name = " (A2) " distance = "829.40906" start_bearing = "175.87665" end_bearing = "158.7495" description = "" />
<segment id="87195830" start="0" end="7" time = "19.536932" name = " (A2) " distance = "651.231" start_bearing = "157.98872" end_bearing = "135.32278" description = "" />
<segment id="7082846" start="0" end="1" time = "1.332016" name = " (A2) " distance = "44.40053" start_bearing = "132.66948" end_bearing = "132.66948" description = "" />
<segment id="7082849" start="0" end="3" time = "12.256795" name = " (A2) " distance = "408.5598" start_bearing = "129.9005" end_bearing = "123.859245" description = "" />
<segment id="7082851" start="0" end="1" time = "1.7693062" name = " (A2) " distance = "58.976868" start_bearing = "124.133446" end_bearing = "124.133446" description = "" />
<segment id="7081833" start="0" end="9" time = "21.555794" name = " (A2) " distance = "718.5264" start_bearing = "125.44192" end_bearing = "141.00053" description = "" />
<segment id="7081833" start="9" end="11" time = "18.920055" name = " (A2) " distance = "630.6685" turn = "Keep left" turn_angle = "1.3838348" lanes = "[1, 1, 1, 0]" start_bearing = "142.38437" end_bearing = "143.98479" description = "Keep left[1, 1, 1, 0] and go 4214.98 meters (*)" />
<segment id="7081844" start="0" end="1" time = "0.74438155" name = " (A2) " distance = "24.812717" start_bearing = "144.41263" end_bearing = "144.41263" description = "" />
<segment id="7081846" start="0" end="2" time = "31.507397" name = " (A2) " distance = "1050.2466" start_bearing = "144.40886" end_bearing = "145.51918" description = "" />
<segment id="7081846" start="2" end="3" time = "0.46107167" name = " (A2) " distance = "15.369055" start_bearing = "145.561" end_bearing = "145.561" description = "" />
<segment id="7081825" start="0" end="1" time = "1.5179313" name = " (A2) " distance = "50.59771" start_bearing = "145.9634" end_bearing = "145.9634" description = "" />
<segment id="7081704" start="0" end="3" time = "36.545654" name = " (A2) " distance = "1218.1884" start_bearing = "145.98322" end_bearing = "145.91476" description = "" />
<segment id="7081701" start="0" end="1" time = "3.0920525" name = " (A2) " distance = "103.068405" start_bearing = "146.47978" end_bearing = "146.47978" description = "" />
<segment id="7081703" start="0" end="1" time = "4.506509" name = " (A2) " distance = "150.21695" start_bearing = "145.66266" end_bearing = "145.66266" description = "" />
<segment id="7081386" start="0" end="1" time = "6.63905" name = " (A2) " distance = "221.30167" start_bearing = "145.88553" end_bearing = "145.88553" description = "" />
<segment id="7081384" start="0" end="1" time = "1.1803325" name = " (A2) " distance = "39.344418" start_bearing = "145.42284" end_bearing = "145.42284" description = "" />
<segment id="7081015" start="0" end="3" time = "21.335112" name = " (A2) " distance = "711.17035" start_bearing = "145.26582" end_bearing = "140.59818" description = "" />
<segment id="54318418" start="0" end="27" time = "123.92231" name = " (A2) " distance = "4130.7437" turn = "Keep left" turn_angle = "-2.0806732" lanes = "[1, 1, 0, 0]" start_bearing = "138.5175" end_bearing = "164.93518" description = "Keep left[1, 1, 0, 0] and go 7595.80 meters" />
<segment id="6950203" start="0" end="1" time = "1.0974485" name = " (A2) " distance = "36.581615" start_bearing = "166.4589" end_bearing = "166.4589" description = "" />
<segment id="35286295" start="0" end="4" time = "8.819818" name = " (A2) " distance = "293.9939" start_bearing = "167.24911" end_bearing = "172.56018" description = "" />
<segment id="35266566" start="0" end="2" time = "3.0470872" name = " (A2) " distance = "101.56957" start_bearing = "174.98376" end_bearing = "177.47758" description = "" />
<segment id="141801782" start="0" end="1" time = "0.99822295" name = " (A2) " distance = "33.274097" start_bearing = "178.1014" end_bearing = "178.1014" description = "" />
<segment id="141801796" start="0" end="1" time = "1.309543" name = " (A2) " distance = "43.651432" start_bearing = "179.51239" end_bearing = "179.51239" description = "" />
<segment id="48863173" start="0" end="5" time = "12.422368" name = " (A2) " distance = "414.07892" start_bearing = "-176.99934" end_bearing = "-167.01416" description = "" />
<segment id="6950193" start="0" end="1" time = "2.033889" name = " (A2) " distance = "67.796295" start_bearing = "-165.77403" end_bearing = "-165.77403" description = "" />
<segment id="6949530" start="0" end="5" time = "29.506603" name = " (A2) " distance = "983.55334" start_bearing = "-166.04355" end_bearing = "-169.1576" description = "" />
<segment id="50322663" start="0" end="1" time = "3.6776545" name = " (A2) " distance = "122.58848" start_bearing = "-169.60266" end_bearing = "-169.60266" description = "" />
<segment id="50322643" start="0" end="1" time = "3.8385742" name = " (A2) " distance = "127.95247" start_bearing = "-169.6655" end_bearing = "-169.6655" description = "" />
<segment id="50322655" start="0" end="8" time = "13.800583" name = " (A2) " distance = "383.34952" start_bearing = "-168.90211" end_bearing = "-147.63907" description = "" />
<segment id="6951107" start="0" end="12" time = "30.839975" name = " (A2) " distance = "856.666" start_bearing = "-142.57951" end_bearing = "-103.60809" description = "" />
<segment id="6951107" start="12" end="26" time = "44.36613" name = " (A2) " distance = "1232.3926" turn = "Keep left" turn_angle = "-2.497841" lanes = "[1, 1, 1, 0]" start_bearing = "-106.105934" end_bearing = "-112.256386" description = "Keep left[1, 1, 1, 0] and go 1232.39 meters (*)" />
<segment id="78371513" start="0" end="10" time = "23.557737" name = " (A2) " distance = "654.38165" turn = "Keep left" turn_angle = "2.691574" lanes = "[1, 1, 0, 0]" start_bearing = "-109.56481" end_bearing = "-114.50123" description = "Keep left[1, 1, 0, 0] and go 2395.60 meters" />
<segment id="7076123" start="0" end="2" time = "4.4418974" name = " (A2) " distance = "123.38604" start_bearing = "-119.0546" end_bearing = "-121.2777" description = "" />
<segment id="7076135" start="0" end="7" time = "10.14244" name = " (A2) " distance = "281.73447" start_bearing = "-126.351395" end_bearing = "-140.2677" description = "" />
<segment id="7076154" start="0" end="2" time = "3.9266477" name = " (A2) " distance = "109.07355" start_bearing = "-143.08163" end_bearing = "-146.80579" description = "" />
<segment id="7076164" start="0" end="8" time = "8.537001" name = " (A2) " distance = "237.13892" start_bearing = "-149.19855" end_bearing = "-160.99402" description = "" />
<segment id="7076127" start="0" end="1" time = "1.21495" name = " (A2) " distance = "33.74861" start_bearing = "-165.51024" end_bearing = "-165.51024" description = "" />
<segment id="7074364" start="0" end="17" time = "38.245663" name = " (A2) " distance = "956.14154" start_bearing = "-166.86598" end_bearing = "167.3092" description = "" />
<segment id="7074364" start="17" end="36" time = "81.58548" name = " (A2) " distance = "2039.6371" turn = "Keep left" turn_angle = "-2.0724487" lanes = "[1, 1, 0]" start_bearing = "165.23676" end_bearing = "175.20016" description = "Keep left[1, 1, 0] and go 4359.56 meters (*)" />
<segment id="54214845" start="0" end="3" time = "11.566906" name = " (A2) " distance = "385.5635" start_bearing = "174.44444" end_bearing = "170.36424" description = "" />
<segment id="7074103" start="0" end="1" time = "1.6293857" name = " (A2) " distance = "54.312855" start_bearing = "169.3442" end_bearing = "169.3442" description = "" />
<segment id="7074107" start="0" end="2" time = "56.401367" name = " (A2) " distance = "1880.0455" start_bearing = "168.9801" end_bearing = "167.95552" description = "" />
<segment id="7074107" start="2" end="22" time = "60.01322" name = " (A2) " distance = "2000.4406" turn = "Keep left" turn_angle = "-0.6495209" lanes = "[1, 1, 0]" start_bearing = "167.306" end_bearing = "140.546" description = "Keep left[1, 1, 0] and go 5054.83 meters (*)" />
<segment id="7174664" start="0" end="1" time = "1.093775" name = " (A2) " distance = "36.459167" start_bearing = "142.20137" end_bearing = "142.20137" description = "" />
<segment id="7174662" start="0" end="17" time = "73.75601" name = " (A2) " distance = "2458.5334" start_bearing = "142.77292" end_bearing = "160.42688" description = "" />
<segment id="7173998" start="0" end="1" time = "0.9634669" name = " (A2) " distance = "32.115562" start_bearing = "162.60667" end_bearing = "162.60667" description = "" />
<segment id="7173912" start="0" end="8" time = "12.146003" name = " (A2) " distance = "404.86673" start_bearing = "164.6402" end_bearing = "175.66768" description = "" />
<segment id="7173915" start="0" end="1" time = "1.8925273" name = " (A2) " distance = "63.084244" start_bearing = "177.30571" end_bearing = "177.30571" description = "" />
<segment id="7173917" start="0" end="1" time = "1.7798107" name = " (A2) " distance = "59.32702" start_bearing = "178.19316" end_bearing = "178.19316" description = "" />
<segment id="7173917" start="1" end="2" time = "4.5603037" name = " (A2) " distance = "152.01012" turn = "Keep left" turn_angle = "0.6930847" lanes = "[1, 1, 0]" start_bearing = "178.88625" end_bearing = "178.88625" description = "Keep left[1, 1, 0] and go 6521.90 meters (*)" />
<segment id="7173905" start="0" end="1" time = "1.4901867" name = " (A2) " distance = "49.67289" start_bearing = "-180.0" end_bearing = "180.0" description = "" />
<segment id="7173935" start="0" end="5" time = "47.21756" name = " (A2) " distance = "1573.9186" start_bearing = "178.95203" end_bearing = "176.12459" description = "" />
<segment id="7173935" start="5" end="21" time = "142.38881" name = " (A2) " distance = "4746.2935" start_bearing = "174.63979" end_bearing = "145.51537" description = "" />
<segment id="7173935" start="21" end="29" time = "67.018425" name = " (A2) " distance = "2233.9475" turn = "Keep left" turn_angle = "-0.6148071" lanes = "[1, 1, 0]" start_bearing = "144.90056" end_bearing = "141.10718" description = "Keep left[1, 1, 0] and go 2233.95 meters (*)" />
<segment id="7173935" start="29" end="32" time = "14.9291725" name = " (A2) " distance = "497.63907" turn = "Keep left" turn_angle = "-1.8707886" lanes = "[1, 1, 0]" start_bearing = "139.23639" end_bearing = "138.31236" description = "Keep left[1, 1, 0] and go 1980.99 meters (*)" />
<segment id="7179075" start="0" end="1" time = "1.5465801" name = " (A2) " distance = "51.55267" start_bearing = "138.19594" end_bearing = "138.19594" description = "" />
<segment id="7179071" start="0" end="5" time = "15.394137" name = " (A2) " distance = "513.1379" start_bearing = "138.33195" end_bearing = "143.4089" description = "" />
<segment id="78351468" start="0" end="1" time = "2.646936" name = " (A2) " distance = "88.23119" start_bearing = "143.44254" end_bearing = "143.44254" description = "" />
<segment id="7179066" start="0" end="1" time = "2.9943397" name = " (A2) " distance = "99.81132" start_bearing = "144.1382" end_bearing = "144.1382" description = "" />
<segment id="7164288" start="0" end="5" time = "21.91868" name = " (A2) " distance = "730.6226" start_bearing = "143.65816" end_bearing = "143.59764" description = "" />
<segment id="61417466" start="0" end="18" time = "22.64163" name = " (A2) " distance = "754.721" turn = "Keep right" turn_angle = "14.600952" lanes = "[0, 0, 1, 1]" start_bearing = "158.1986" end_bearing = "-132.08916" description = "Keep right[0, 0, 1, 1] and go 1161.12 meters" />
<segment id="7163552" start="0" end="1" time = "2.2204328" name = " (A2) " distance = "74.01442" start_bearing = "-128.75014" end_bearing = "-128.75014" description = "" />
<segment id="41723227" start="0" end="1" time = "9.971562" name = " (A2) " distance = "332.3854" start_bearing = "-126.04385" end_bearing = "-126.04385" description = "" />
<segment id="41723227" start="1" end="10" time = "23.28754" name = " (A2) " distance = "776.2513" turn = "Keep left" turn_angle = "1.016571" lanes = "[1, 1, 0]" start_bearing = "-125.02728" end_bearing = "-107.847595" description = "Keep left[1, 1, 0] and go 10249.63 meters" />
<segment id="45514016" start="0" end="1" time = "2.1432974" name = " (A2) " distance = "71.443245" start_bearing = "-107.525566" end_bearing = "-107.525566" description = "" />
<segment id="45032716" start="0" end="14" time = "21.68405" name = " (A2) " distance = "722.80164" start_bearing = "-104.424995" end_bearing = "-152.94595" description = "" />
<segment id="126096711" start="0" end="2" time = "2.4006703" name = " (A2) " distance = "80.02234" start_bearing = "-158.31093" end_bearing = "-164.1846" description = "" />
<segment id="126096712" start="0" end="5" time = "6.3677316" name = " (A2) " distance = "212.2577" start_bearing = "-166.42957" end_bearing = "173.82007" description = "" />
<segment id="46115604" start="0" end="7" time = "18.722918" name = " (A2) " distance = "624.0972" start_bearing = "171.88927" end_bearing = "174.1485" description = "" />
<segment id="79143009" start="0" end="6" time = "15.6428795" name = " (A2) " distance = "521.42926" start_bearing = "173.60341" end_bearing = "172.44615" description = "" />
<segment id="45122596" start="0" end="1" time = "1.5765182" name = " (A2) " distance = "52.550602" start_bearing = "171.61038" end_bearing = "171.61038" description = "" />
<segment id="46269145" start="0" end="6" time = "20.522358" name = " (A2) " distance = "684.0786" start_bearing = "169.17699" end_bearing = "159.41142" description = "" />
<segment id="56993702" start="0" end="44" time = "81.80696" name = " (A2) " distance = "2726.8987" start_bearing = "157.74411" end_bearing = "-172.24141" description = "" />
<segment id="42556558" start="0" end="1" time = "1.9370726" name = " (A2) " distance = "64.569084" start_bearing = "-173.26143" end_bearing = "-173.26143" description = "" />
<segment id="42556556" start="0" end="1" time = "4.959161" name = " (A2) " distance = "165.30536" start_bearing = "-173.27509" end_bearing = "-173.27509" description = "" />
<segment id="45122592" start="0" end="1" time = "1.9371598" name = " (A2) " distance = "64.57199" start_bearing = "-173.03903" end_bearing = "-173.03903" description = "" />
<segment id="45122595" start="0" end="2" time = "9.068394" name = " (A2) " distance = "302.2798" start_bearing = "-173.04163" end_bearing = "-176.38266" description = "" />
<segment id="43680916" start="0" end="2" time = "2.0981252" name = " (A2) " distance = "69.93751" start_bearing = "-179.37384" end_bearing = "177.9011" description = "" />
<segment id="43680915" start="0" end="6" time = "20.195648" name = " (A2) " distance = "673.18823" start_bearing = "176.71075" end_bearing = "173.5205" description = "" />
<segment id="43992358" start="0" end="1" time = "1.905056" name = " (A2) " distance = "63.501865" start_bearing = "174.27267" end_bearing = "174.27267" description = "" />
<segment id="43992359" start="0" end="5" time = "24.733604" name = " (A2) " distance = "824.4534" start_bearing = "174.79437" end_bearing = "175.7536" description = "" />
<segment id="43992356" start="0" end="1" time = "1.323533" name = " (A2) " distance = "44.117767" start_bearing = "175.65675" end_bearing = "175.65675" description = "" />
<segment id="43992357" start="0" end="1" time = "15.758663" name = " (A2) " distance = "525.28876" start_bearing = "175.59352" end_bearing = "175.59352" description = "" />
<segment id="43584255" start="0" end="1" time = "1.8351485" name = " (A2) " distance = "61.17161" start_bearing = "175.61473" end_bearing = "175.61473" description = "" />
<segment id="43584256" start="0" end="6" time = "17.022135" name = " (A2) " distance = "567.4045" start_bearing = "174.2616" end_bearing = "172.39104" description = "" />
<segment id="43584251" start="0" end="1" time = "1.0576898" name = " (A2) " distance = "35.256325" start_bearing = "171.82724" end_bearing = "171.82724" description = "" />
<segment id="43584252" start="0" end="4" time = "9.502739" name = " (A2) " distance = "316.75797" start_bearing = "173.51292" end_bearing = "178.03929" description = "" />
<segment id="54323149" start="0" end="1" time = "1.4189636" name = " (A2) " distance = "47.298782" turn = "Keep left" turn_angle = "-9.881363" lanes = "[1, 1, 0]" start_bearing = "168.15793" end_bearing = "168.15793" description = "Keep left[1, 1, 0] and go 4387.81 meters" />
<segment id="61421404" start="0" end="6" time = "4.7477856" name = " (A2) " distance = "158.25952" start_bearing = "166.82013" end_bearing = "150.94539" description = "" />
<segment id="41875183" start="0" end="2" time = "3.0844235" name = " (A2) " distance = "102.81412" start_bearing = "144.79985" end_bearing = "140.40833" description = "" />
<segment id="7168852" start="0" end="6" time = "6.4909453" name = " (A2) " distance = "216.36484" start_bearing = "134.16968" end_bearing = "112.0679" description = "" />
<segment id="7183053" start="0" end="3" time = "3.210082" name = " (A2) " distance = "107.00273" start_bearing = "107.71201" end_bearing = "97.125015" description = "" />
<segment id="7168147" start="0" end="5" time = "5.2099776" name = " (A2) " distance = "173.66592" start_bearing = "94.338264" end_bearing = "80.7974" description = "" />
<segment id="34601778" start="0" end="13" time = "47.981785" name = " (A2;A67) " distance = "1599.3927" start_bearing = "82.30395" end_bearing = "88.43239" description = "" />
<segment id="34601802" start="0" end="1" time = "1.7866222" name = " (A2;A67) " distance = "59.55407" start_bearing = "88.58993" end_bearing = "88.58993" description = "" />
<segment id="34601800" start="0" end="3" time = "21.627018" name = " (A2;A67) " distance = "720.9005" start_bearing = "87.86634" end_bearing = "92.97983" description = "" />
<segment id="34601796" start="0" end="1" time = "0.80496925" name = " (A2;A67) " distance = "26.832308" start_bearing = "93.70463" end_bearing = "93.70463" description = "" />
<segment id="34601794" start="0" end="3" time = "5.901169" name = " (A2;A67) " distance = "196.70563" start_bearing = "92.57915" end_bearing = "92.804085" description = "" />
<segment id="44354762" start="0" end="1" time = "1.0291723" name = " (A2;A67) " distance = "34.30574" start_bearing = "93.14496" end_bearing = "93.14496" description = "" />
<segment id="44360916" start="0" end="1" time = "7.328647" name = " (A2;A67) " distance = "244.28822" start_bearing = "92.400475" end_bearing = "92.400475" description = "" />
<segment id="34601786" start="0" end="1" time = "2.101605" name = " (A2;A67) " distance = "70.05349" start_bearing = "92.71913" end_bearing = "92.71913" description = "" />
<segment id="34601788" start="0" end="2" time = "17.838524" name = " (A2;A67) " distance = "594.61743" start_bearing = "92.92696" end_bearing = "92.76961" description = "" />
<segment id="129359000" start="0" end="1" time = "0.8941588" name = " (A2;A67) " distance = "29.80529" start_bearing = "92.80981" end_bearing = "92.80981" description = "" />
<segment id="129359001" start="0" end="1" time = "0.17860866" name = " (A2;A67) " distance = "5.953622" start_bearing = "91.7357" end_bearing = "91.7357" description = "" />
<segment id="41960113" start="0" end="9" time = "12.305996" name = " (A2) " distance = "410.19983" turn = "Keep left" turn_angle = "0.41725922" lanes = "[1, 1, 0, 0]" start_bearing = "92.15296" end_bearing = "107.69364" description = "Keep left[1, 1, 0, 0] and go 6969.30 meters" />
<segment id="46177355" start="0" end="3" time = "2.9886634" name = " (A2) " distance = "99.62211" start_bearing = "107.61258" end_bearing = "111.48204" description = "" />
<segment id="7181608" start="0" end="13" time = "14.447598" name = " (A2) " distance = "481.5866" start_bearing = "112.94894" end_bearing = "141.93434" description = "" />
<segment id="129358985" start="0" end="2" time = "2.1925447" name = " (A2) " distance = "73.08482" start_bearing = "146.47247" end_bearing = "146.47247" description = "" />
<segment id="129358986" start="0" end="10" time = "15.391882" name = " (A2) " distance = "513.0627" start_bearing = "148.48593" end_bearing = "174.4588" description = "" />
<segment id="57124219" start="0" end="1" time = "3.6961312" name = " (A2) " distance = "123.20437" start_bearing = "163.70851" end_bearing = "163.70851" description = "" />
<segment id="7138181" start="0" end="11" time = "158.05623" name = " (A2) " distance = "5268.541" start_bearing = "164.86745" end_bearing = "150.9332" description = "" />
<segment id="7138582" start="0" end="1" time = "12.939249" name = " (A2) " distance = "431.3083" turn = "Keep left" turn_angle = "1.0292664" lanes = "[1, 1, 0]" start_bearing = "151.96246" end_bearing = "151.96246" description = "Keep left[1, 1, 0] and go 6302.33 meters (*)" />
<segment id="7138584" start="0" end="1" time = "1.9605826" name = " (A2) " distance = "65.35275" start_bearing = "151.7652" end_bearing = "151.7652" description = "" />
<segment id="7138593" start="0" end="8" time = "22.77318" name = " (A2) " distance = "759.106" start_bearing = "149.63991" end_bearing = "122.376434" description = "" />
<segment id="7138594" start="0" end="1" time = "1.104279" name = " (A2) " distance = "36.809303" start_bearing = "122.19573" end_bearing = "122.19573" description = "" />
<segment id="7138598" start="0" end="1" time = "10.109423" name = " (A2) " distance = "336.98074" start_bearing = "122.33052" end_bearing = "122.33052" description = "" />
<segment id="7138602" start="0" end="1" time = "0.42181835" name = " (A2) " distance = "14.060611" start_bearing = "122.24247" end_bearing = "122.24247" description = "" />
<segment id="7138604" start="0" end="1" time = "7.019979" name = " (A2) " distance = "233.9993" start_bearing = "122.72699" end_bearing = "122.72699" description = "" />
<segment id="7138608" start="0" end="1" time = "0.5713057" name = " (A2) " distance = "19.043524" start_bearing = "121.53479" end_bearing = "121.53479" description = "" />
<segment id="7138570" start="0" end="4" time = "30.841974" name = " (A2) " distance = "1028.0658" start_bearing = "122.167595" end_bearing = "120.012825" description = "" />
<segment id="7137120" start="0" end="9" time = "60.733063" name = " (A2) " distance = "2024.4354" start_bearing = "119.456055" end_bearing = "142.62645" description = "" />
<segment id="7137120" start="9" end="12" time = "19.791756" name = " (A2) " distance = "659.72516" start_bearing = "141.7927" end_bearing = "142.10811" description = "" />
<segment id="7137076" start="0" end="1" time = "1.9422636" name = " (A2) " distance = "64.74212" start_bearing = "142.06673" end_bearing = "142.06673" description = "" />
<segment id="7137093" start="0" end="2" time = "18.860876" name = " (A2) " distance = "628.6958" start_bearing = "143.43219" end_bearing = "148.48138" description = "" />
<segment id="7137085" start="0" end="2" time = "8.986393" name = " (A2) " distance = "299.54642" turn = "Keep left" turn_angle = "-1.9695587" lanes = "[1, 1, 0]" start_bearing = "146.51183" end_bearing = "144.0556" description = "Keep left[1, 1, 0] and go 2280.14 meters (*)" />
<segment id="7137084" start="0" end="1" time = "1.7814373" name = " (A2) " distance = "59.38124" start_bearing = "144.39911" end_bearing = "144.39911" description = "" />
<segment id="7137099" start="0" end="3" time = "9.2395115" name = " (A2) " distance = "307.9837" start_bearing = "145.8525" end_bearing = "147.90741" description = "" />
<segment id="7137060" start="0" end="1" time = "0.6640553" name = " (A2) " distance = "22.135176" start_bearing = "147.89374" end_bearing = "147.89374" description = "" />
<segment id="7134766" start="0" end="6" time = "47.732796" name = " (A2) " distance = "1591.0931" start_bearing = "147.97134" end_bearing = "128.12758" description = "" />
<segment id="7134766" start="6" end="8" time = "41.02873" name = " (A2) " distance = "1367.6243" turn = "Keep left" turn_angle = "-0.15433502" lanes = "[1, 1, 0]" start_bearing = "127.97324" end_bearing = "127.87689" description = "Keep left[1, 1, 0] and go 1783.04 meters (*)" />
<segment id="7134748" start="0" end="1" time = "1.8177253" name = " (A2) " distance = "60.590843" start_bearing = "128.16707" end_bearing = "128.16707" description = "" />
<segment id="7134752" start="0" end="1" time = "3.6708686" name = " (A2) " distance = "122.36228" start_bearing = "127.67535" end_bearing = "127.67535" description = "" />
<segment id="7134760" start="0" end="1" time = "0.73418015" name = " (A2) " distance = "24.47267" start_bearing = "126.95711" end_bearing = "126.95711" description = "" />
<segment id="7134786" start="0" end="4" time = "6.239682" name = " (A2) " distance = "207.9894" start_bearing = "132.66269" end_bearing = "143.909" description = "" />
<segment id="7134786" start="4" end="18" time = "46.656086" name = " (A2) " distance = "1555.2029" turn = "Keep left" turn_angle = "3.9660034" lanes = "[1, 1, 0]" start_bearing = "147.875" end_bearing = "129.92787" description = "Keep left[1, 1, 0] and go 1555.20 meters (*)" />
<segment id="7133368" start="0" end="45" time = "161.42354" name = " (A2) " distance = "5380.784" turn = "Keep left" turn_angle = "-7.772148" lanes = "[1, 1, 0]" start_bearing = "122.15572" end_bearing = "127.22508" description = "Keep left[1, 1, 0] and go 5380.78 meters (*)" />
<segment id="6735354" start="0" end="1" time = "3.023609" name = " (A2) " distance = "100.78696" turn = "Keep left" turn_angle = "7.550812" lanes = "[1, 1, 0]" start_bearing = "134.7759" end_bearing = "134.7759" description = "Keep left[1, 1, 0] and go 6298.18 meters (*)" />
<segment id="57123265" start="0" end="4" time = "11.997399" name = " (A2) " distance = "399.9133" start_bearing = "139.2456" end_bearing = "150.65193" description = "" />
<segment id="6735330" start="0" end="1" time = "1.8624623" name = " (A2) " distance = "62.082073" start_bearing = "152.81473" end_bearing = "152.81473" description = "" />
<segment id="6735347" start="0" end="3" time = "19.002733" name = " (A2) " distance = "633.4244" start_bearing = "153.98177" end_bearing = "158.04019" description = "" />
<segment id="6735335" start="0" end="1" time = "2.4163463" name = " (A2) " distance = "80.54487" start_bearing = "159.67686" end_bearing = "159.67686" description = "" />
<segment id="6733875" start="0" end="12" time = "67.998856" name = " (A2) " distance = "2266.6284" start_bearing = "158.63722" end_bearing = "121.59014" description = "" />
<segment id="6733875" start="12" end="30" time = "82.64402" name = " (A2) " distance = "2754.8008" start_bearing = "121.56035" end_bearing = "146.53694" description = "" />
<segment id="6733875" start="30" end="31" time = "5.352952" name = " (A2) " distance = "178.43173" turn = "Keep left" turn_angle = "-1.6221619" lanes = "[1, 1, 0]" start_bearing = "144.91478" end_bearing = "144.91478" description = "Keep left[1, 1, 0] and go 7194.36 meters (*)" />
<segment id="6733858" start="0" end="1" time = "1.2741007" name = " (A2) " distance = "42.47002" start_bearing = "144.78241" end_bearing = "144.78241" description = "" />
<segment id="6761009" start="0" end="8" time = "57.463886" name = " (A2) " distance = "2075.0847" start_bearing = "142.9811" end_bearing = "149.37885" description = "" />
<segment id="6761009" start="8" end="19" time = "135.64726" name = " (A2) " distance = "4898.3735" start_bearing = "149.62903" end_bearing = "157.77496" description = "" />
<segment id="6761009" start="19" end="27" time = "26.163582" name = " (A2) " distance = "944.796" turn = "Keep left" turn_angle = "1.53656" lanes = "[1, 1, 0]" start_bearing = "159.31152" end_bearing = "138.09918" description = "Keep left[1, 1, 0] and go 4997.55 meters (*)" />
<segment id="6760794" start="0" end="11" time = "44.944664" name = " (A2) " distance = "1623.0017" start_bearing = "137.40173" end_bearing = "113.73268" description = "" />
<segment id="37874907" start="0" end="1" time = "1.0011903" name = " (A2) " distance = "36.154095" start_bearing = "114.14554" end_bearing = "114.14554" description = "" />
<segment id="6760588" start="0" end="6" time = "26.170221" name = " (A2) " distance = "945.03577" start_bearing = "113.55517" end_bearing = "126.09393" description = "" />
<segment id="65652957" start="0" end="1" time = "1.1647427" name = " (A2) " distance = "42.060154" start_bearing = "128.50066" end_bearing = "128.50066" description = "" />
<segment id="6760590" start="0" end="1" time = "0.6923826" name = " (A2) " distance = "25.002703" start_bearing = "129.5309" end_bearing = "129.5309" description = "" />
<segment id="6760592" start="0" end="5" time = "10.907824" name = " (A2) " distance = "393.89362" start_bearing = "131.45523" end_bearing = "141.5198" description = "" />
<segment id="6760593" start="0" end="1" time = "0.5635869" name = " (A2) " distance = "20.35175" start_bearing = "143.63713" end_bearing = "143.63713" description = "" />
<segment id="6760276" start="0" end="1" time = "3.973777" name = " (A2) " distance = "143.49751" start_bearing = "140.29984" end_bearing = "140.29984" description = "" />
<segment id="6760273" start="0" end="1" time = "4.2607803" name = " (A2) " distance = "153.86151" start_bearing = "139.64078" end_bearing = "139.64078" description = "" />
<segment id="6760274" start="0" end="1" time = "4.038248" name = " (A2) " distance = "145.82564" start_bearing = "140.87056" end_bearing = "140.87056" description = "" />
<segment id="6759456" start="0" end="6" time = "14.512677" name = " (A2) " distance = "524.06885" start_bearing = "140.52519" end_bearing = "153.18086" description = "" />
<segment id="65652935" start="0" end="13" time = "23.336346" name = " (A2) " distance = "842.7014" turn = "Keep left" turn_angle = "2.7785187" lanes = "[1, 1, 0]" start_bearing = "155.95938" end_bearing = "-178.55046" description = "Keep left[1, 1, 0] and go 1800.26 meters (*)" />
<segment id="6759453" start="0" end="1" time = "0.6217311" name = " (A2) " distance = "22.4514" start_bearing = "-178.57973" end_bearing = "-178.57973" description = "" />
<segment id="6759445" start="0" end="2" time = "8.417113" name = " (A2) " distance = "303.9513" start_bearing = "-178.8857" end_bearing = "-178.61964" description = "" />
<segment id="6759435" start="0" end="1" time = "0.518142" name = " (A2) " distance = "18.710684" start_bearing = "-178.86559" end_bearing = "-178.86559" description = "" />
<segment id="6762479" start="0" end="3" time = "16.959984" name = " (A2) " distance = "612.44385" start_bearing = "-178.35559" end_bearing = "-178.64574" description = "" />
<segment id="6762479" start="3" end="33" time = "75.5849" name = " (A2) " distance = "2729.4548" turn = "Keep left" turn_angle = "0.39468384" lanes = "[1, 1, 0]" start_bearing = "-178.25105" end_bearing = "-126.719765" description = "Keep left[1, 1, 0] and go 4632.34 meters (*)" />
<segment id="78584109" start="0" end="4" time = "21.346128" name = " (A2) " distance = "711.53754" start_bearing = "-128.93886" end_bearing = "-131.01477" description = "" />
<segment id="78584112" start="0" end="7" time = "35.740578" name = " (A2) " distance = "1191.3525" start_bearing = "-133.77788" end_bearing = "-132.98265" description = "" />
<segment id="78584112" start="7" end="8" time = "10.193341" name = " (A2) " distance = "339.778" turn = "Keep left" turn_angle = "1.8592834" lanes = "[1, 1, 0]" start_bearing = "-131.12337" end_bearing = "-131.12337" description = "Keep left[1, 1, 0] and go 4660.08 meters (*)" />
<segment id="6762481" start="0" end="1" time = "0.81427324" name = " (A2) " distance = "27.14244" start_bearing = "-129.0194" end_bearing = "-129.0194" description = "" />
<segment id="6756968" start="0" end="12" time = "51.92214" name = " (A2) " distance = "1730.7379" start_bearing = "-131.39786" end_bearing = "-151.28493" description = "" />
<segment id="6756967" start="0" end="1" time = "0.86474246" name = " (A2) " distance = "28.824747" start_bearing = "-151.12456" end_bearing = "-151.12456" description = "" />
<segment id="6764626" start="0" end="13" time = "76.00803" name = " (A2) " distance = "2533.601" start_bearing = "-151.3797" end_bearing = "-170.0643" description = "" />
<segment id="6764626" start="13" end="22" time = "39.152573" name = " (A2) " distance = "1305.0857" turn = "Keep left" turn_angle = "-3.17984" lanes = "[1, 1, 0]" start_bearing = "-173.24414" end_bearing = "171.15948" description = "Keep left[1, 1, 0] and go 3249.24 meters (*)" />
<segment id="6764626" start="22" end="28" time = "34.96675" name = " (A2) " distance = "1165.5583" start_bearing = "171.74103" end_bearing = "-178.93416" description = "" />
<segment id="6764627" start="0" end="1" time = "1.2607403" name = " (A2) " distance = "42.024677" start_bearing = "-176.93352" end_bearing = "-176.93352" description = "" />
<segment id="6764640" start="0" end="2" time = "6.8866363" name = " (A2) " distance = "229.55453" start_bearing = "-177.31622" end_bearing = "-173.53018" description = "" />
<segment id="6764637" start="0" end="1" time = "1.7470565" name = " (A2) " distance = "58.235214" start_bearing = "-173.29016" end_bearing = "-173.29016" description = "" />
<segment id="6763783" start="0" end="1" time = "13.463537" name = " (A2) " distance = "448.78455" start_bearing = "-173.04414" end_bearing = "-173.04414" description = "" />
<segment id="6763783" start="1" end="14" time = "59.323814" name = " (A2) " distance = "1977.4604" turn = "Keep left" turn_angle = "-0.20355225" lanes = "[1, 1, 0]" start_bearing = "-173.2477" end_bearing = "-143.40068" description = "Keep left[1, 1, 0] and go 6223.03 meters (*)" />
<segment id="6763785" start="0" end="1" time = "0.72068155" name = " (A2) " distance = "24.022718" start_bearing = "-142.94347" end_bearing = "-142.94347" description = "" />
<segment id="6763423" start="0" end="2" time = "38.506706" name = " (A2) " distance = "1283.5568" start_bearing = "-143.46468" end_bearing = "-143.62914" description = "" />
<segment id="6764162" start="0" end="1" time = "0.5496586" name = " (A2) " distance = "18.321953" start_bearing = "-143.59123" end_bearing = "-143.59123" description = "" />
<segment id="6764112" start="0" end="15" time = "87.5901" name = " (A2) " distance = "2919.67" start_bearing = "-143.59123" end_bearing = "-162.96223" description = "" />
<segment id="6764112" start="15" end="16" time = "12.817549" name = " (A2) " distance = "427.2516" turn = "Keep left" turn_angle = "0.30574036" lanes = "[1, 1, 0]" start_bearing = "-162.6565" end_bearing = "-162.6565" description = "Keep left[1, 1, 0] and go 2001.79 meters (*)" />
<segment id="6776791" start="0" end="1" time = "1.3554204" name = " (A2) " distance = "45.18068" start_bearing = "-163.52957" end_bearing = "-163.52957" description = "" />
<segment id="6776798" start="0" end="3" time = "13.345422" name = " (A2) " distance = "444.84735" start_bearing = "-162.94937" end_bearing = "-167.86557" description = "" />
<segment id="6776788" start="0" end="1" time = "1.4594101" name = " (A2) " distance = "48.647003" start_bearing = "-170.60916" end_bearing = "-170.60916" description = "" />
<segment id="6774982" start="0" end="11" time = "31.075895" name = " (A2) " distance = "1035.8632" start_bearing = "-174.4368" end_bearing = "155.75833" description = "" />
<segment id="6774982" start="11" end="16" time = "8.318511" name = " (A2) " distance = "277.2837" turn = "Keep left" turn_angle = "1.7171173" lanes = "[1, 1, 0, 0]" start_bearing = "157.47545" end_bearing = "165.72327" description = "Keep left[1, 1, 0, 0] and go 625.35 meters" />
<segment id="6774986" start="0" end="1" time = "1.193324" name = " (A2) " distance = "39.777462" start_bearing = "167.14766" end_bearing = "167.14766" description = "" />
<segment id="6774822" start="0" end="4" time = "9.248604" name = " (A2) " distance = "308.28677" start_bearing = "168.73532" end_bearing = "177.14854" description = "" />
<segment id="6774822" start="4" end="9" time = "12.855928" name = " (A2) " distance = "428.53094" turn = "Keep left" turn_angle = "0.15716553" lanes = "[1, 1, 0]" start_bearing = "177.30571" end_bearing = "-175.156" description = "Keep left[1, 1, 0] and go 1859.37 meters (*)" />
<segment id="6775285" start="0" end="1" time = "2.0140622" name = " (A2) " distance = "67.1354" start_bearing = "-175.16959" end_bearing = "-175.16959" description = "" />
<segment id="6775316" start="0" end="3" time = "31.417942" name = " (A2) " distance = "1047.2646" start_bearing = "-175.58209" end_bearing = "-177.13759" description = "" />
<segment id="6775293" start="0" end="3" time = "8.217698" name = " (A2) " distance = "273.92325" start_bearing = "178.83086" end_bearing = "173.03853" description = "" />
<segment id="80503748" start="0" end="1" time = "1.2753391" name = " (A2) " distance = "42.511303" start_bearing = "172.01514" end_bearing = "172.01514" description = "" />
<segment id="80503746" start="0" end="5" time = "20.195436" name = " (A2) " distance = "673.1812" turn = "Keep left" turn_angle = "-3.4476776" lanes = "[1, 1, 0]" start_bearing = "168.56746" end_bearing = "174.3032" description = "Keep left[1, 1, 0] and go 2945.10 meters (*)" />
<segment id="6775303" start="0" end="1" time = "2.5965672" name = " (A2) " distance = "86.55224" start_bearing = "177.13136" end_bearing = "177.13136" description = "" />
<segment id="6773089" start="0" end="5" time = "14.480419" name = " (A2) " distance = "482.68063" start_bearing = "177.7094" end_bearing = "-171.79578" description = "" />
<segment id="6773086" start="0" end="1" time = "0.97906727" name = " (A2) " distance = "32.635574" start_bearing = "-170.75389" end_bearing = "-170.75389" description = "" />
<segment id="6777666" start="0" end="7" time = "18.026918" name = " (A2) " distance = "600.8972" start_bearing = "-169.69516" end_bearing = "-160.51387" description = "" />
<segment id="6777666" start="7" end="8" time = "2.2491179" name = " (A2) " distance = "74.9706" start_bearing = "-158.54279" end_bearing = "-158.54279" description = "" />
<segment id="163556624" start="0" end="1" time = "0.64583343" name = " (A2) " distance = "21.527779" start_bearing = "-157.61986" end_bearing = "-157.61986" description = "" />
<segment id="163556988" start="0" end="5" time = "18.745827" name = " (A2) " distance = "624.86084" start_bearing = "-155.4445" end_bearing = "-149.23146" description = "" />
<segment id="6777681" start="0" end="1" time = "1.31523" name = " (A2) " distance = "43.841" start_bearing = "-148.86969" end_bearing = "-148.86969" description = "" />
<segment id="6777683" start="0" end="1" time = "9.118502" name = " (A2) " distance = "303.95004" start_bearing = "-149.59557" end_bearing = "-149.59557" description = "" />
<segment id="6777689" start="0" end="5" time = "14.656341" name = " (A2) " distance = "488.54468" turn = "Keep left" turn_angle = "-0.0695343" lanes = "[1, 1, 0]" start_bearing = "-149.6651" end_bearing = "-158.8012" description = "Keep left[1, 1, 0] and go 4597.78 meters (*)" />
<segment id="6777658" start="0" end="1" time = "1.4205163" name = " (A2) " distance = "47.35054" start_bearing = "-159.04422" end_bearing = "-159.04422" description = "" />
<segment id="6777640" start="0" end="10" time = "40.372505" name = " (A2) " distance = "1345.7501" start_bearing = "-158.54814" end_bearing = "-142.79338" description = "" />
<segment id="6777642" start="0" end="1" time = "0.9938683" name = " (A2) " distance = "33.128944" start_bearing = "-141.5463" end_bearing = "-141.5463" description = "" />
<segment id="6777645" start="0" end="17" time = "48.536095" name = " (A2) " distance = "1617.8698" start_bearing = "-143.87587" end_bearing = "-152.49356" description = "" />
<segment id="6777677" start="0" end="16" time = "31.954033" name = " (A2) " distance = "1065.1344" start_bearing = "-149.36028" end_bearing = "-140.67715" description = "" />
<segment id="6777005" start="0" end="5" time = "15.218739" name = " (A2) " distance = "507.29126" turn = "Keep left" turn_angle = "-0.707016" lanes = "[1, 1, 0]" start_bearing = "-141.38417" end_bearing = "-157.75098" description = "Keep left[1, 1, 0] and go 4750.28 meters (*)" />
<segment id="6779737" start="0" end="1" time = "1.9872186" name = " (A2) " distance = "66.240616" start_bearing = "-158.79979" end_bearing = "-158.79979" description = "" />
<segment id="27195291" start="0" end="3" time = "22.922112" name = " (A2) " distance = "764.0704" start_bearing = "-159.72656" end_bearing = "-159.64677" description = "" />
<segment id="6779757" start="0" end="1" time = "1.279087" name = " (A2) " distance = "42.63623" start_bearing = "-159.50266" end_bearing = "-159.50266" description = "" />
<segment id="6779755" start="0" end="2" time = "14.648318" name = " (A2) " distance = "488.27725" start_bearing = "-163.73431" end_bearing = "-165.3161" description = "" />
<segment id="6779751" start="0" end="1" time = "1.9059914" name = " (A2) " distance = "63.533043" start_bearing = "-166.29305" end_bearing = "-166.29305" description = "" />
<segment id="6779107" start="0" end="3" time = "8.923741" name = " (A2) " distance = "297.45804" start_bearing = "-166.03221" end_bearing = "-159.17911" description = "" />
<segment id="132365568" start="0" end="1" time = "1.6167188" name = " (A2) " distance = "53.89062" start_bearing = "-155.85446" end_bearing = "-155.85446" description = "" />
<segment id="132365574" start="0" end="7" time = "22.951693" name = " (A2) " distance = "765.0564" start_bearing = "-153.64464" end_bearing = "-148.3777" description = "" />
<segment id="72400805" start="0" end="4" time = "16.450336" name = " (A2) " distance = "411.2584" start_bearing = "-145.36246" end_bearing = "-135.27545" description = "" />
<segment id="132365572" start="0" end="5" time = "27.85979" name = " (A2) " distance = "696.4948" start_bearing = "-133.04579" end_bearing = "-139.87816" description = "" />
<segment id="7125104" start="0" end="1" time = "0.87968373" name = " (A2) " distance = "21.992092" start_bearing = "-140.5722" end_bearing = "-140.5722" description = "" />
<segment id="132365571" start="0" end="5" time = "26.710241" name = " (A2) " distance = "519.3658" start_bearing = "-141.59787" end_bearing = "-145.58632" description = "" />
<segment id="7125108" start="0" end="1" time = "3.795417" name = " (A2) " distance = "52.714127" start_bearing = "-143.29416" end_bearing = "-143.29416" description = "" />
<segment id="74176013" start="0" end="5" time = "68.20989" name = "Viaductweg" distance = "252.9152" turn = "Turn right" turn_angle = "82.28676" start_bearing = "-61.007404" end_bearing = "-68.404686" description = "Turn right and go 724.83 meters" />
<segment id="7125080" start="0" end="3" time = "32.31564" name = "Viaductweg" distance = "132.08797" start_bearing = "-69.443954" end_bearing = "-67.22757" description = "" />
<segment id="7126430" start="0" end="1" time = "1.6430479" name = "Viaductweg" distance = "29.666143" start_bearing = "-65.46227" end_bearing = "-65.46227" description = "" />
<segment id="7126427" start="0" end="6" time = "10.318509" name = "Viaductweg" distance = "143.31262" start_bearing = "-65.64201" end_bearing = "-83.198685" description = "" />
<segment id="7126427" start="6" end="13" time = "12.012888" name = "Viaductweg" distance = "166.84567" start_bearing = "-84.289406" end_bearing = "-97.0165" description = "" />
<segment id="7126424" start="0" end="1" time = "26.031185" name = "" distance = "12.889814" turn = "Turn left" turn_angle = "-91.472435" start_bearing = "171.51106" end_bearing = "171.51106" description = "Turn left and go 872.82 meters" />
<segment id="102699301" start="0" end="5" time = "28.381628" name = "Franciscus Romanusweg" distance = "46.967056" start_bearing = "171.8699" end_bearing = "-159.22775" description = "" />
<segment id="144552858" start="10" end="0" time = "14.33854" name = "Franciscus Romanusweg" distance = "199.1464" start_bearing = "-123.69007" end_bearing = "-95.59934" description = "" />
<segment id="32102945" start="7" end="0" time = "32.39706" name = "Franciscus Romanusweg" distance = "102.73698" start_bearing = "-94.76364" end_bearing = "-134.44374" description = "" />
<segment id="7126419" start="18" end="4" time = "14.372538" name = "Franciscus Romanusweg" distance = "199.61858" start_bearing = "-135.0" end_bearing = "171.8699" description = "" />
<segment id="7126419" start="4" end="0" time = "14.157407" name = "Franciscus Romanusweg" distance = "196.63066" start_bearing = "171.79913" end_bearing = "171.17232" description = "" />
<segment id="7126414" start="1" end="0" time = "1.3585912" name = "Franciscus Romanusweg" distance = "22.643187" start_bearing = "175.156" end_bearing = "175.156" description = "" />
<segment id="7126200" start="0" end="4" time = "6.637338" name = "Franciscus Romanusweg" distance = "92.18526" start_bearing = "178.2643" end_bearing = "-169.38034" description = "" />
<segment id="7126312" start="0" end="4" time = "11.829202" name = "Karel de Vogelstraat" distance = "115.00613" turn = "Turn left" turn_angle = "-90.10545" start_bearing = "100.514206" end_bearing = "35.387886" description = "Turn left and go 115.01 meters" />
<segment id="7126313" start="1" end="0" time = "4.8251657" name = "Valentijn Clotsstraat" distance = "46.91133" turn = "Turn right" turn_angle = "97.50303" start_bearing = "132.89091" end_bearing = "132.89091" description = "Turn right and go 46.91 meters" />
<segment id="7126355" start="4" end="0" time = "5.2888374" name = "Gebroeders Hermansstraat" distance = "51.419254" turn = "Turn left" turn_angle = "-81.665085" start_bearing = "51.22583" end_bearing = "136.49434" description = "Turn left and go 51.42 meters" />
<segment id="7126356" start="3" end="2" time = "0.0" name = "" distance = "0.0" turn = "Turn right" turn_angle = "81.091034" start_bearing = "-142.41463" end_bearing = "-140.19443" description = "Turn right and go 0.00 meters" />
</test>
</router_tests>

View file

@ -1,310 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="" description="Route to Antwerpen" best_percent="10" vehicle="car"
start_lat="52.29344776082418" start_lon="4.834756851196289" target_lat="51.21717320613008" target_lon="4.402492046356201" complete_time="5953.306" complete_distance = "159654.98" routing_time = "6900.458" >
<segment id="7367192" start="1" end="0" time = "1.9570006" name = "" distance = "24.462507" turn = "Go ahead" turn_angle = "0.0" start_bearing = "108.39158" end_bearing = "108.39158" description = "Go ahead and go 24.46 meters" />
<segment id="7366497" start="4" end="0" time = "8.245201" name = "Noorddammerweg" distance = "103.06502" turn = "Turn right" turn_angle = "96.414085" start_bearing = "-155.19434" end_bearing = "-129.80557" description = "Turn right and go 127.54 meters" />
<segment id="7366502" start="1" end="0" time = "2.9368546" name = "Urbanusparkstraat" distance = "24.473787" start_bearing = "-116.56505" end_bearing = "-116.56505" description = "" />
<segment id="7366495" start="1" end="0" time = "4.3885183" name = "Urbanusparkstraat" distance = "36.570984" start_bearing = "-150.29" end_bearing = "-150.29" description = "" />
<segment id="7366522" start="1" end="0" time = "8.302308" name = "Noorddammerweg" distance = "103.77885" start_bearing = "-154.70195" end_bearing = "-154.70195" description = "" />
<segment id="7366534" start="1" end="0" time = "4.5096536" name = "Sint Urbanuspark" distance = "56.37067" start_bearing = "-158.61427" end_bearing = "-158.61427" description = "" />
<segment id="7366606" start="1" end="0" time = "4.542828" name = "Sint Urbanuspark" distance = "56.785347" start_bearing = "-153.1908" end_bearing = "-153.1908" description = "" />
<segment id="47633918" start="2" end="1" time = "2.140907" name = "Noorddammerweg" distance = "26.761337" start_bearing = "-155.19734" end_bearing = "-155.19734" description = "" />
<segment id="7367247" start="2" end="0" time = "20.482542" name = "Zetterij" distance = "256.03177" turn = "Turn left" turn_angle = "-90.48619" start_bearing = "114.31647" end_bearing = "106.46359" description = "Turn left and go 761.63 meters" />
<segment id="7364788" start="4" end="0" time = "23.70847" name = "Zetterij" distance = "296.35587" start_bearing = "108.9465" end_bearing = "115.43968" description = "" />
<segment id="7364764" start="1" end="0" time = "1.6481074" name = "Zetterij" distance = "20.601343" start_bearing = "111.709885" end_bearing = "111.709885" description = "" />
<segment id="7364763" start="1" end="0" time = "6.9382887" name = "Zetterij" distance = "86.728615" start_bearing = "112.44515" end_bearing = "112.44515" description = "" />
<segment id="7364766" start="1" end="0" time = "1.1748635" name = "Zetterij" distance = "14.685793" start_bearing = "119.27525" end_bearing = "119.27525" description = "" />
<segment id="7364508" start="0" end="2" time = "6.2802095" name = "Zetterij" distance = "87.225136" start_bearing = "110.00669" end_bearing = "94.62415" description = "" />
<segment id="7365070" start="0" end="1" time = "1.0716465" name = "Bovenkerkerweg (N521) " distance = "14.883979" turn = "Turn right" turn_angle = "94.95008" start_bearing = "-170.42577" end_bearing = "-170.42577" description = "Turn right and go 58.89 meters" />
<segment id="7365086" start="0" end="1" time = "3.1682494" name = "Bovenkerkerweg (N521) " distance = "44.003468" start_bearing = "-172.57889" end_bearing = "-172.57889" description = "" />
<segment id="27797366" start="0" end="4" time = "31.34122" name = "Bovenkerkerweg" distance = "88.0725" turn = "Keep left" turn_angle = "-1.6711273" start_bearing = "-174.25002" end_bearing = "176.74805" description = "Keep left and go 88.07 meters" />
<segment id="98511727" start="1" end="2" time = "1.38718" name = "Bovenkerkerweg" distance = "19.266388" turn = "Make uturn" turn_angle = "-139.98875" start_bearing = "36.75929" end_bearing = "36.75929" description = "Make uturn and go 1113.37 meters" />
<segment id="7365085" start="0" end="1" time = "8.459829" name = "Bovenkerkerweg (N521) " distance = "117.49763" start_bearing = "6.4971123" end_bearing = "6.4971123" description = "" />
<segment id="7365069" start="0" end="1" time = "0.57796" name = "Bovenkerkerweg (N521) " distance = "8.027223" start_bearing = "5.3145456" end_bearing = "5.3145456" description = "" />
<segment id="7364510" start="0" end="1" time = "1.1475279" name = "Bovenkerkerweg (N521) " distance = "15.937888" start_bearing = "12.60016" end_bearing = "12.60016" description = "" />
<segment id="7364786" start="0" end="2" time = "9.050575" name = "Bovenkerkerweg (N521) " distance = "125.70244" start_bearing = "7.8605475" end_bearing = "-2.726311" description = "" />
<segment id="7364769" start="0" end="2" time = "16.702217" name = "Bovenkerkerweg (N521) " distance = "278.3703" start_bearing = "10.541818" end_bearing = "8.130102" description = "" />
<segment id="7364781" start="0" end="6" time = "64.496864" name = "Handweg" distance = "548.56757" start_bearing = "8.130102" end_bearing = "9.901572" description = "" />
<segment id="7364782" start="1" end="0" time = "26.062386" name = "Keizer Karelweg" distance = "14.755359" turn = "Turn right" turn_angle = "89.328316" start_bearing = "99.22989" end_bearing = "99.22989" description = "Turn right and go 917.26 meters" />
<segment id="7364779" start="0" end="5" time = "13.558414" name = "Keizer Karelweg" distance = "188.31131" start_bearing = "96.254036" end_bearing = "66.169136" description = "" />
<segment id="7364775" start="1" end="0" time = "4.9813266" name = "Keizer Karelweg" distance = "69.18509" start_bearing = "62.372807" end_bearing = "62.372807" description = "" />
<segment id="7364776" start="0" end="1" time = "4.9812937" name = "Keizer Karelweg" distance = "69.18464" start_bearing = "62.334564" end_bearing = "62.334564" description = "" />
<segment id="7364778" start="0" end="1" time = "3.806921" name = "Keizer Karelweg" distance = "52.873905" start_bearing = "62.48443" end_bearing = "62.48443" description = "" />
<segment id="7364787" start="0" end="1" time = "0.5657692" name = "Keizer Karelweg" distance = "7.8579054" start_bearing = "65.897766" end_bearing = "65.897766" description = "" />
<segment id="7364771" start="0" end="1" time = "1.5512005" name = "Keizer Karelweg" distance = "21.544453" start_bearing = "61.50436" end_bearing = "61.50436" description = "" />
<segment id="58661684" start="0" end="1" time = "0.6126022" name = "Keizer Karelweg" distance = "8.508364" start_bearing = "61.189205" end_bearing = "61.189205" description = "" />
<segment id="7364071" start="0" end="1" time = "4.6289053" name = "Keizer Karelweg" distance = "64.29035" start_bearing = "62.34026" end_bearing = "62.34026" description = "" />
<segment id="7364489" start="0" end="1" time = "3.0778131" name = "Keizer Karelweg" distance = "42.747406" start_bearing = "62.333244" end_bearing = "62.333244" description = "" />
<segment id="7364488" start="0" end="1" time = "0.8222186" name = "Keizer Karelweg" distance = "11.4197035" start_bearing = "62.19854" end_bearing = "62.19854" description = "" />
<segment id="7364487" start="0" end="1" time = "3.6412437" name = "Keizer Karelweg" distance = "50.57283" start_bearing = "63.893307" end_bearing = "63.893307" description = "" />
<segment id="7364482" start="0" end="1" time = "2.4905744" name = "Keizer Karelweg" distance = "34.59131" start_bearing = "61.38954" end_bearing = "61.38954" description = "" />
<segment id="7364483" start="0" end="1" time = "2.506028" name = "Keizer Karelweg" distance = "34.805946" start_bearing = "57.228592" end_bearing = "57.228592" description = "" />
<segment id="48147997" start="0" end="2" time = "2.944532" name = "Keizer Karelweg" distance = "40.89628" start_bearing = "57.707115" end_bearing = "51.679886" description = "" />
<segment id="7364498" start="0" end="2" time = "3.2543092" name = "Keizer Karelweg" distance = "45.198742" start_bearing = "52.460567" end_bearing = "70.857735" description = "" />
<segment id="7364496" start="0" end="1" time = "1.0199182" name = "Keizer Karelweg" distance = "14.165531" start_bearing = "53.746162" end_bearing = "53.746162" description = "" />
<segment id="58384522" start="0" end="4" time = "30.041615" name = "Keizer Karelweg" distance = "70.02242" start_bearing = "9.050722" end_bearing = "19.798876" description = "" />
<segment id="7364485" start="0" end="2" time = "5.4958763" name = "Keizer Karelweg" distance = "76.33162" start_bearing = "28.694904" end_bearing = "18.610165" description = "" />
<segment id="7364485" start="2" end="3" time = "2.772" name = "Keizer Karelweg" distance = "38.500004" turn = "Keep right" turn_angle = "7.832197" start_bearing = "26.442362" end_bearing = "26.442362" description = "Keep right and go 38.50 meters" />
<segment id="49900222" start="0" end="1" time = "26.05053" name = " (5) " distance = "29.181383" turn = "Keep right" turn_angle = "26.471804" start_bearing = "52.914165" end_bearing = "52.914165" description = "Keep right and go 29.18 meters" />
<segment id="7364501" start="1" end="14" time = "15.055797" name = " (5) " distance = "418.21658" turn = "Turn right" turn_angle = "72.713745" start_bearing = "125.62791" end_bearing = "101.61149" description = "Turn right and go 860.22 meters" />
<segment id="7363599" start="0" end="2" time = "15.912092" name = "Burgemeester van Sonweg (A9) " distance = "442.0026" start_bearing = "110.03965" end_bearing = "111.34803" description = "" />
<segment id="73841697" start="0" end="1" time = "3.0741942" name = "Burgemeester van Sonweg (A9) " distance = "85.39429" turn = "Keep left" turn_angle = "-1.123169" lanes = "[1, 1, 1, 0]" start_bearing = "110.22486" end_bearing = "110.22486" description = "Keep left[1, 1, 1, 0] and go 5031.67 meters (*)" />
<segment id="73841702" start="0" end="6" time = "23.457874" name = "Burgemeester van Sonweg (A9) " distance = "651.60767" start_bearing = "110.73096" end_bearing = "102.372154" description = "" />
<segment id="7363585" start="0" end="1" time = "3.1736984" name = "Burgemeester van Sonweg (A9) " distance = "88.158295" start_bearing = "102.43956" end_bearing = "102.43956" description = "" />
<segment id="7363584" start="0" end="2" time = "11.333597" name = "Burgemeester van Sonweg (A9) " distance = "314.82217" start_bearing = "101.97764" end_bearing = "102.30124" description = "" />
<segment id="7361538" start="0" end="3" time = "14.295719" name = "Burgemeester van Sonweg (A9) " distance = "397.1033" start_bearing = "104.50872" end_bearing = "108.59298" description = "" />
<segment id="142320420" start="0" end="2" time = "5.5521536" name = "Burgemeester van Sonweg (A9) " distance = "154.22649" start_bearing = "110.93831" end_bearing = "113.5104" description = "" />
<segment id="7361528" start="0" end="2" time = "17.812927" name = "Burgemeester van Sonweg (A9) " distance = "494.80356" start_bearing = "116.33478" end_bearing = "118.19917" description = "" />
<segment id="7361526" start="0" end="1" time = "1.9970839" name = "Burgemeester van Sonweg (A9) " distance = "55.474556" start_bearing = "116.99262" end_bearing = "116.99262" description = "" />
<segment id="7052161" start="0" end="5" time = "41.986267" name = "Burgemeester van Sonweg (A9) " distance = "1166.2852" start_bearing = "115.737404" end_bearing = "107.69727" description = "" />
<segment id="73841596" start="0" end="1" time = "4.142789" name = "Burgemeester van Sonweg (A9) " distance = "115.07747" start_bearing = "105.54368" end_bearing = "105.54368" description = "" />
<segment id="73841593" start="0" end="7" time = "45.15565" name = "Burgemeester van Sonweg (A9) " distance = "1254.3236" start_bearing = "104.22892" end_bearing = "94.48044" description = "" />
<segment id="7052166" start="0" end="1" time = "2.1076596" name = "Burgemeester van Sonweg (A9) " distance = "58.546097" start_bearing = "94.316025" end_bearing = "94.316025" description = "" />
<segment id="7052167" start="0" end="1" time = "7.050495" name = "Burgemeester van Sonweg (A9) " distance = "195.84709" start_bearing = "92.99034" end_bearing = "92.99034" description = "" />
<segment id="7050550" start="0" end="14" time = "45.65967" name = " (A2) " distance = "1268.3242" turn = "Keep right" turn_angle = "3.1677475" lanes = "[0, 0, 1, 1]" start_bearing = "96.15809" end_bearing = "155.08707" description = "Keep right[0, 0, 1, 1] and go 2825.55 meters" />
<segment id="7050539" start="0" end="1" time = "5.4304996" name = " (A2) " distance = "150.84721" start_bearing = "154.9497" end_bearing = "154.9497" description = "" />
<segment id="7050532" start="0" end="1" time = "4.303684" name = " (A2) " distance = "119.54679" start_bearing = "154.99895" end_bearing = "154.99895" description = "" />
<segment id="7052391" start="0" end="5" time = "46.325794" name = " (A2) " distance = "1286.8276" start_bearing = "154.56238" end_bearing = "163.39973" description = "" />
<segment id="79276793" start="0" end="4" time = "21.940208" name = " (A2) " distance = "609.45026" turn = "Keep left" turn_angle = "-2.96138" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "160.43835" end_bearing = "160.22612" description = "Keep left[1, 1, 1, 1, 1, 0] and go 4179.89 meters (*)" />
<segment id="7052394" start="0" end="1" time = "3.6575377" name = " (A2) " distance = "101.598274" start_bearing = "161.66277" end_bearing = "161.66277" description = "" />
<segment id="7052396" start="0" end="1" time = "2.5187688" name = " (A2) " distance = "69.965805" start_bearing = "161.65929" end_bearing = "161.65929" description = "" />
<segment id="7048564" start="0" end="2" time = "10.061515" name = " (A2) " distance = "279.4865" start_bearing = "165.30898" end_bearing = "166.53188" description = "" />
<segment id="179467573" start="0" end="6" time = "77.62425" name = " (A2) " distance = "2156.2292" start_bearing = "166.56369" end_bearing = "161.2148" description = "" />
<segment id="7048569" start="0" end="1" time = "1.9461962" name = " (A2) " distance = "54.06101" start_bearing = "161.44237" end_bearing = "161.44237" description = "" />
<segment id="7048574" start="0" end="2" time = "23.552534" name = " (A2) " distance = "654.2371" start_bearing = "161.33673" end_bearing = "159.06078" description = "" />
<segment id="179467574" start="0" end="2" time = "9.175154" name = " (A2) " distance = "254.86539" start_bearing = "159.10223" end_bearing = "157.23166" description = "" />
<segment id="127580800" start="0" end="5" time = "31.653484" name = " (A2) " distance = "879.2635" turn = "Keep left" turn_angle = "-5.7964783" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "151.43518" end_bearing = "160.15231" description = "Keep left[1, 1, 1, 1, 1, 0] and go 6003.83 meters (*)" />
<segment id="156689123" start="0" end="1" time = "1.2813264" name = " (A2) " distance = "35.5924" start_bearing = "162.03085" end_bearing = "162.03085" description = "" />
<segment id="7071327" start="0" end="2" time = "4.237085" name = " (A2) " distance = "117.69681" start_bearing = "165.54758" end_bearing = "165.56084" description = "" />
<segment id="7071344" start="0" end="1" time = "3.895726" name = " (A2) " distance = "108.214615" start_bearing = "167.9524" end_bearing = "167.9524" description = "" />
<segment id="156689148" start="0" end="12" time = "175.07043" name = " (A2) " distance = "4863.068" start_bearing = "171.80692" end_bearing = "177.47583" description = "" />
<segment id="7071319" start="0" end="2" time = "23.41219" name = " (A2) " distance = "650.3386" turn = "Keep left" turn_angle = "1.7103577" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "179.18619" end_bearing = "177.08644" description = "Keep left[1, 1, 1, 1, 1, 0] and go 3519.18 meters (*)" />
<segment id="7071324" start="0" end="1" time = "1.5838847" name = " (A2) " distance = "43.9968" start_bearing = "176.88657" end_bearing = "176.88657" description = "" />
<segment id="7070772" start="0" end="1" time = "7.2220364" name = " (A2) " distance = "200.61214" start_bearing = "177.91554" end_bearing = "177.91554" description = "" />
<segment id="127580788" start="0" end="1" time = "1.3697265" name = " (A2) " distance = "38.047962" start_bearing = "179.16159" end_bearing = "179.16159" description = "" />
<segment id="127580809" start="0" end="8" time = "36.29545" name = " (A2) " distance = "1008.207" start_bearing = "178.4745" end_bearing = "156.75131" description = "" />
<segment id="7070784" start="0" end="1" time = "1.6745965" name = " (A2) " distance = "46.51657" start_bearing = "156.89088" end_bearing = "156.89088" description = "" />
<segment id="127580802" start="0" end="3" time = "55.132523" name = " (A2) " distance = "1531.459" start_bearing = "155.18443" end_bearing = "157.22044" description = "" />
<segment id="127580802" start="3" end="5" time = "23.851204" name = " (A2) " distance = "662.53345" turn = "Keep left" turn_angle = "-0.8713379" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "156.3491" end_bearing = "157.03491" description = "Keep left[1, 1, 1, 1, 1, 0] and go 3086.16 meters (*)" />
<segment id="76140687" start="0" end="1" time = "1.273901" name = " (A2) " distance = "35.38614" start_bearing = "157.15196" end_bearing = "157.15196" description = "" />
<segment id="76140684" start="0" end="12" time = "85.97655" name = " (A2) " distance = "2388.2375" start_bearing = "158.17053" end_bearing = "133.95096" description = "" />
<segment id="7063640" start="0" end="4" time = "22.955816" name = " (A2) " distance = "637.66156" turn = "Keep right" turn_angle = "5.8865967" lanes = "[0, 0, 0, 0, 1, 1]" start_bearing = "139.83755" end_bearing = "133.75592" description = "Keep right[0, 0, 0, 0, 1, 1] and go 637.66 meters" />
<segment id="80749050" start="0" end="8" time = "29.595013" name = " (A2) " distance = "822.08374" turn = "Keep left" turn_angle = "-6.2392197" lanes = "[1, 0, 0]" start_bearing = "127.5167" end_bearing = "124.00188" description = "Keep left[1, 0, 0] and go 1675.15 meters" />
<segment id="80749051" start="0" end="1" time = "5.690788" name = " (A2) " distance = "158.07745" start_bearing = "123.72714" end_bearing = "123.72714" description = "" />
<segment id="114712634" start="0" end="5" time = "25.019554" name = " (A2) " distance = "694.9876" start_bearing = "123.795296" end_bearing = "122.66091" description = "" />
<segment id="80749052" start="0" end="7" time = "27.790503" name = " (A2) " distance = "771.95844" turn = "Keep left" turn_angle = "1.7918243" start_bearing = "124.452736" end_bearing = "135.1993" description = "Keep left and go 3777.28 meters (*)" />
<segment id="99998240" start="0" end="10" time = "39.82047" name = " (A2) " distance = "1106.1241" start_bearing = "137.54857" end_bearing = "150.25511" description = "" />
<segment id="32512734" start="0" end="9" time = "59.071857" name = "Leidsche Rijntunnel (A2) " distance = "1640.885" start_bearing = "153.49524" end_bearing = "174.09386" description = "" />
<segment id="51795374" start="0" end="2" time = "9.2991705" name = " (A2) " distance = "258.3103" start_bearing = "176.55423" end_bearing = "179.28766" description = "" />
<segment id="51795374" start="2" end="3" time = "1.7690709" name = " (A2) " distance = "49.14086" turn = "Keep left" turn_angle = "-0.5798187" lanes = "[1, 1, 0, 0]" start_bearing = "178.70784" end_bearing = "178.70784" description = "Keep left[1, 1, 0, 0] and go 1041.26 meters" />
<segment id="51763743" start="0" end="1" time = "1.9273798" name = " (A2) " distance = "53.53833" start_bearing = "-178.62674" end_bearing = "-178.62674" description = "" />
<segment id="51764573" start="0" end="6" time = "12.954628" name = " (A2) " distance = "359.8508" start_bearing = "-175.96658" end_bearing = "-171.84186" description = "" />
<segment id="114712628" start="0" end="2" time = "7.6056266" name = " (A2) " distance = "211.26741" start_bearing = "-170.33298" end_bearing = "-165.04005" description = "" />
<segment id="45356321" start="0" end="1" time = "13.2288" name = " (A2) " distance = "367.46667" start_bearing = "-164.98569" end_bearing = "-164.98569" description = "" />
<segment id="93810170" start="0" end="18" time = "32.24873" name = " (A2) " distance = "895.7981" turn = "Keep right" turn_angle = "1.6514435" lanes = "[0, 0, 1]" start_bearing = "-163.33424" end_bearing = "-165.01373" description = "Keep right[0, 0, 1] and go 4389.06 meters" />
<segment id="7054459" start="0" end="1" time = "0.5385003" name = " (A2) " distance = "14.958343" start_bearing = "-165.11374" end_bearing = "-165.11374" description = "" />
<segment id="7054436" start="0" end="1" time = "3.7654755" name = " (A2) " distance = "104.59655" start_bearing = "-165.37912" end_bearing = "-165.37912" description = "" />
<segment id="7065542" start="0" end="2" time = "16.98387" name = " (A2) " distance = "471.77417" start_bearing = "-166.1587" end_bearing = "-165.21095" description = "" />
<segment id="7065536" start="0" end="1" time = "7.173017" name = " (A2) " distance = "199.25047" start_bearing = "-166.11705" end_bearing = "-166.11705" description = "" />
<segment id="78380417" start="0" end="1" time = "1.6784111" name = " (A2) " distance = "46.62253" start_bearing = "-167.54431" end_bearing = "-167.54431" description = "" />
<segment id="78380413" start="0" end="1" time = "6.054087" name = " (A2) " distance = "168.1691" start_bearing = "-168.89789" end_bearing = "-168.89789" description = "" />
<segment id="7064773" start="0" end="10" time = "66.43809" name = " (A2) " distance = "1845.5026" start_bearing = "-165.6186" end_bearing = "-178.60915" description = "" />
<segment id="48836778" start="0" end="1" time = "1.2691222" name = " (A2) " distance = "35.2534" start_bearing = "-177.61406" end_bearing = "-177.61406" description = "" />
<segment id="48836779" start="0" end="3" time = "21.856815" name = " (A2) " distance = "607.1338" start_bearing = "-179.3338" end_bearing = "-178.12825" description = "" />
<segment id="178647034" start="0" end="2" time = "9.700615" name = " (A2) " distance = "269.46155" turn = "Keep left" turn_angle = "-0.6485443" lanes = "[1, 1, 1, 1, 0]" start_bearing = "-178.7768" end_bearing = "-178.34505" description = "Keep left[1, 1, 1, 1, 0] and go 3330.81 meters (*)" />
<segment id="7064794" start="0" end="10" time = "42.247013" name = " (A2) " distance = "1173.5282" start_bearing = "-179.2284" end_bearing = "165.80145" description = "" />
<segment id="7064545" start="0" end="1" time = "12.333144" name = " (A2) " distance = "342.58737" start_bearing = "163.14783" end_bearing = "163.14783" description = "" />
<segment id="178069079" start="0" end="1" time = "0.93667734" name = " (A2) " distance = "26.018816" start_bearing = "163.0725" end_bearing = "163.0725" description = "" />
<segment id="178069080" start="0" end="1" time = "0.5939401" name = " (A2) " distance = "16.498337" start_bearing = "162.84758" end_bearing = "162.84758" description = "" />
<segment id="7104689" start="0" end="1" time = "2.6430216" name = " (A2) " distance = "73.41727" start_bearing = "163.73979" end_bearing = "163.73979" description = "" />
<segment id="7103427" start="0" end="6" time = "43.938156" name = " (A2) " distance = "1220.5044" start_bearing = "163.17859" end_bearing = "160.65762" description = "" />
<segment id="7103414" start="0" end="1" time = "1.6054673" name = " (A2) " distance = "44.596317" start_bearing = "162.22868" end_bearing = "162.22868" description = "" />
<segment id="7103412" start="0" end="1" time = "5.9111137" name = " (A2) " distance = "164.1976" start_bearing = "162.19199" end_bearing = "162.19199" description = "" />
<segment id="7103443" start="0" end="2" time = "17.572462" name = " (A2) " distance = "488.124" turn = "Keep left" turn_angle = "2.604477" lanes = "[1, 1, 1, 0]" start_bearing = "164.79646" end_bearing = "166.83194" description = "Keep left[1, 1, 1, 0] and go 1533.52 meters (*)" />
<segment id="7103439" start="0" end="2" time = "9.107542" name = " (A2) " distance = "252.98729" start_bearing = "163.19218" end_bearing = "162.343" description = "" />
<segment id="7103434" start="0" end="3" time = "19.30155" name = " (A2) " distance = "536.1542" start_bearing = "161.72829" end_bearing = "160.20113" description = "" />
<segment id="7102720" start="0" end="1" time = "9.225261" name = " (A2) " distance = "256.25723" start_bearing = "160.61691" end_bearing = "160.61691" description = "" />
<segment id="7104154" start="0" end="2" time = "16.467108" name = " (A2) " distance = "457.41968" turn = "Keep left" turn_angle = "-2.2422028" lanes = "[1, 1, 1, 0]" start_bearing = "158.37471" end_bearing = "157.46214" description = "Keep left[1, 1, 1, 0] and go 1699.12 meters (*)" />
<segment id="7104177" start="0" end="1" time = "2.1778877" name = " (A2) " distance = "60.496883" start_bearing = "155.77225" end_bearing = "155.77225" description = "" />
<segment id="7104172" start="0" end="5" time = "14.296287" name = " (A2) " distance = "397.11908" start_bearing = "152.75946" end_bearing = "136.88458" description = "" />
<segment id="7104142" start="0" end="1" time = "2.0603602" name = " (A2) " distance = "57.23223" start_bearing = "131.77003" end_bearing = "131.77003" description = "" />
<segment id="7104152" start="0" end="1" time = "1.4631333" name = " (A2) " distance = "40.642593" start_bearing = "130.43335" end_bearing = "130.43335" description = "" />
<segment id="7104164" start="0" end="1" time = "10.391346" name = " (A2) " distance = "288.6485" start_bearing = "130.75597" end_bearing = "130.75597" description = "" />
<segment id="86072810" start="0" end="1" time = "7.987593" name = " (A2) " distance = "221.8776" start_bearing = "131.00754" end_bearing = "131.00754" description = "" />
<segment id="7104146" start="0" end="1" time = "3.7763226" name = " (A2) " distance = "104.89785" start_bearing = "129.2824" end_bearing = "129.2824" description = "" />
<segment id="87090708" start="0" end="1" time = "2.5482104" name = " (A2) " distance = "70.78362" start_bearing = "131.8435" end_bearing = "131.8435" description = "" />
<segment id="42426226" start="0" end="2" time = "3.3978639" name = " (A27) " distance = "94.38511" turn = "Keep right" turn_angle = "9.727051" lanes = "[0, 0, 0, 1, 1]" start_bearing = "141.57056" end_bearing = "134.831" description = "Keep right[0, 0, 0, 1, 1] and go 6073.34 meters" />
<segment id="7102177" start="0" end="1" time = "0.78649557" name = " (A27) " distance = "21.8471" start_bearing = "134.66495" end_bearing = "134.66495" description = "" />
<segment id="7102180" start="0" end="23" time = "49.669712" name = " (A27) " distance = "1379.7142" start_bearing = "139.31602" end_bearing = "-150.96867" description = "" />
<segment id="7102145" start="0" end="1" time = "0.8997185" name = " (A27) " distance = "29.990616" start_bearing = "-143.61565" end_bearing = "-143.61565" description = "" />
<segment id="7101785" start="0" end="19" time = "85.955215" name = " (A27) " distance = "2865.1738" start_bearing = "-141.91351" end_bearing = "-90.85163" description = "" />
<segment id="85090362" start="0" end="1" time = "10.984186" name = " (A27) " distance = "366.13953" start_bearing = "-89.682976" end_bearing = "-89.682976" description = "" />
<segment id="7105534" start="0" end="1" time = "3.1761682" name = " (A27) " distance = "105.87227" start_bearing = "-89.60349" end_bearing = "-89.60349" description = "" />
<segment id="7105527" start="0" end="2" time = "32.15839" name = " (A27) " distance = "1071.9463" start_bearing = "-89.62215" end_bearing = "-89.76733" description = "" />
<segment id="7105526" start="0" end="1" time = "1.8532431" name = " (A27) " distance = "61.77477" start_bearing = "-90.873344" end_bearing = "-90.873344" description = "" />
<segment id="7105529" start="0" end="1" time = "2.2947965" name = " (A27) " distance = "76.49321" start_bearing = "-91.89562" end_bearing = "-91.89562" description = "" />
<segment id="7105529" start="1" end="7" time = "13.594052" name = " (A27) " distance = "453.13507" turn = "Keep left" turn_angle = "-0.26545715" lanes = "[1, 1, 0]" start_bearing = "-92.16108" end_bearing = "-97.71189" description = "Keep left[1, 1, 0] and go 7680.72 meters (*)" />
<segment id="7105512" start="0" end="1" time = "2.8290696" name = " (A27) " distance = "94.302315" start_bearing = "-100.784294" end_bearing = "-100.784294" description = "" />
<segment id="9549841" start="0" end="18" time = "66.241486" name = " (A27) " distance = "2208.0496" start_bearing = "-102.7533" end_bearing = "-148.43011" description = "" />
<segment id="85090376" start="0" end="1" time = "0.59406275" name = " (A27) " distance = "19.802092" start_bearing = "-147.65256" end_bearing = "-147.65256" description = "" />
<segment id="85090355" start="0" end="1" time = "21.082352" name = " (A27) " distance = "702.74506" start_bearing = "-148.32182" end_bearing = "-148.32182" description = "" />
<segment id="7105844" start="0" end="1" time = "0.71602994" name = " (A27) " distance = "23.867664" start_bearing = "-148.2764" end_bearing = "-148.2764" description = "" />
<segment id="10197738" start="0" end="1" time = "2.694568" name = " (A27) " distance = "89.818924" start_bearing = "-148.04465" end_bearing = "-148.04465" description = "" />
<segment id="7105833" start="0" end="1" time = "0.97316283" name = " (A27) " distance = "32.43876" start_bearing = "-148.20108" end_bearing = "-148.20108" description = "" />
<segment id="7105838" start="0" end="4" time = "12.845104" name = " (A27) " distance = "428.17014" start_bearing = "-147.84592" end_bearing = "-151.59348" description = "" />
<segment id="7105835" start="0" end="1" time = "1.1449802" name = " (A27) " distance = "38.166004" start_bearing = "-152.30673" end_bearing = "-152.30673" description = "" />
<segment id="7105842" start="0" end="11" time = "107.7067" name = " (A27) " distance = "3590.2234" start_bearing = "-155.1287" end_bearing = "-166.30568" description = "" />
<segment id="7109387" start="0" end="1" time = "9.073263" name = " (A27) " distance = "302.44208" turn = "Keep left" turn_angle = "0.164505" lanes = "[1, 1, 0]" start_bearing = "-166.14117" end_bearing = "-166.14117" description = "Keep left[1, 1, 0] and go 5594.20 meters (*)" />
<segment id="7109392" start="0" end="1" time = "2.1320362" name = " (A27) " distance = "71.06787" start_bearing = "-166.68306" end_bearing = "-166.68306" description = "" />
<segment id="7109396" start="0" end="1" time = "9.105985" name = " (A27) " distance = "303.5328" start_bearing = "-166.04816" end_bearing = "-166.04816" description = "" />
<segment id="7109400" start="0" end="6" time = "30.953196" name = " (A27) " distance = "1031.7732" start_bearing = "-167.03697" end_bearing = "-158.87846" description = "" />
<segment id="7109402" start="0" end="1" time = "2.1459546" name = " (A27) " distance = "71.53182" start_bearing = "-159.66669" end_bearing = "-159.66669" description = "" />
<segment id="7109403" start="0" end="2" time = "39.75041" name = " (A27) " distance = "1325.0135" start_bearing = "-158.95221" end_bearing = "-159.1193" description = "" />
<segment id="7109403" start="2" end="7" time = "69.964554" name = " (A27) " distance = "2332.1519" start_bearing = "-159.25357" end_bearing = "-163.85815" description = "" />
<segment id="28196316" start="0" end="1" time = "5.6407747" name = " (A27) " distance = "156.6882" start_bearing = "-163.61809" end_bearing = "-163.61809" description = "" />
<segment id="10196765" start="0" end="1" time = "22.247164" name = " (A27) " distance = "617.9768" turn = "Keep left" turn_angle = "-0.49978638" lanes = "[1, 1, 0, 0]" start_bearing = "-164.11787" end_bearing = "-164.11787" description = "Keep left[1, 1, 0, 0] and go 2155.25 meters" />
<segment id="43545572" start="0" end="1" time = "1.1079632" name = " (A27) " distance = "30.776758" start_bearing = "-163.86441" end_bearing = "-163.86441" description = "" />
<segment id="43545571" start="0" end="1" time = "6.129849" name = " (A27) " distance = "170.27359" start_bearing = "-164.27641" end_bearing = "-164.27641" description = "" />
<segment id="7111062" start="0" end="1" time = "3.681373" name = " (A27) " distance = "102.26036" start_bearing = "-164.53667" end_bearing = "-164.53667" description = "" />
<segment id="7111009" start="0" end="1" time = "23.47949" name = " (A27) " distance = "652.20807" start_bearing = "-163.89453" end_bearing = "-163.89453" description = "" />
<segment id="7110610" start="0" end="1" time = "2.548688" name = " (A27) " distance = "70.79689" start_bearing = "-165.24127" end_bearing = "-165.24127" description = "" />
<segment id="7110615" start="0" end="1" time = "1.7539996" name = " (A27) " distance = "48.722214" start_bearing = "-162.86545" end_bearing = "-162.86545" description = "" />
<segment id="7110632" start="0" end="1" time = "5.6535645" name = " (A27) " distance = "157.04346" start_bearing = "-164.22066" end_bearing = "-164.22066" description = "" />
<segment id="7110642" start="0" end="1" time = "10.986813" name = " (A27) " distance = "305.18927" start_bearing = "-163.92134" end_bearing = "-163.92134" description = "" />
<segment id="7110613" start="0" end="1" time = "3.5661037" name = " (A27) " distance = "99.05844" turn = "Keep left" turn_angle = "-1.1884766" lanes = "[1, 1, 0]" start_bearing = "-165.10982" end_bearing = "-165.10982" description = "Keep left[1, 1, 0] and go 3741.93 meters (*)" />
<segment id="80477496" start="0" end="1" time = "5.6386447" name = " (A27) " distance = "156.62901" start_bearing = "-166.12709" end_bearing = "-166.12709" description = "" />
<segment id="7110624" start="0" end="1" time = "6.5408063" name = " (A27) " distance = "181.68907" start_bearing = "-166.83951" end_bearing = "-166.83951" description = "" />
<segment id="7110618" start="0" end="1" time = "27.419453" name = "Merwedebrug (A27) " distance = "761.6515" start_bearing = "-167.36594" end_bearing = "-167.36594" description = "" />
<segment id="7111245" start="0" end="2" time = "29.739605" name = " (A27) " distance = "826.10016" start_bearing = "-167.46669" end_bearing = "-166.04471" description = "" />
<segment id="61509732" start="0" end="4" time = "47.798935" name = " (A27) " distance = "1593.2977" start_bearing = "-164.21489" end_bearing = "-164.06125" description = "" />
<segment id="7118608" start="0" end="1" time = "2.0945265" name = " (A27) " distance = "69.81755" start_bearing = "-164.24136" end_bearing = "-164.24136" description = "" />
<segment id="85076242" start="0" end="1" time = "1.6107373" name = " (A27) " distance = "53.691242" start_bearing = "-167.06454" end_bearing = "-167.06454" description = "" />
<segment id="7118606" start="0" end="2" time = "5.283568" name = " (A27) " distance = "176.11893" turn = "Keep left" turn_angle = "-2.2571716" lanes = "[1, 1, 0]" start_bearing = "-169.32172" end_bearing = "-170.65683" description = "Keep left[1, 1, 0] and go 2906.18 meters (*)" />
<segment id="7118631" start="0" end="6" time = "81.90192" name = " (A27) " distance = "2730.0637" start_bearing = "-173.17369" end_bearing = "178.0464" description = "" />
<segment id="7118631" start="6" end="18" time = "67.97151" name = " (A27) " distance = "2265.7168" turn = "Keep left" turn_angle = "-0.51820374" lanes = "[1, 1, 0]" start_bearing = "177.5282" end_bearing = "-163.64418" description = "Keep left[1, 1, 0] and go 4487.76 meters (*)" />
<segment id="7118867" start="0" end="1" time = "3.947046" name = " (A27) " distance = "131.5682" start_bearing = "-163.6786" end_bearing = "-163.6786" description = "" />
<segment id="7118635" start="0" end="8" time = "34.481792" name = " (A27) " distance = "1149.3931" start_bearing = "-163.27983" end_bearing = "-152.46683" description = "" />
<segment id="7118635" start="8" end="14" time = "28.23234" name = " (A27) " distance = "941.07794" start_bearing = "-150.59381" end_bearing = "-143.1301" description = "" />
<segment id="7269367" start="0" end="5" time = "11.039033" name = " (A27) " distance = "367.96774" turn = "Keep left" turn_angle = "1.8817291" lanes = "[1, 1, 0]" start_bearing = "-141.24837" end_bearing = "-134.22127" description = "Keep left[1, 1, 0] and go 3099.88 meters (*)" />
<segment id="7269370" start="0" end="1" time = "1.28553" name = " (A27) " distance = "42.850998" start_bearing = "-132.92996" end_bearing = "-132.92996" description = "" />
<segment id="7269381" start="0" end="1" time = "13.34158" name = " (A27) " distance = "444.71933" start_bearing = "-132.06519" end_bearing = "-132.06519" description = "" />
<segment id="7269376" start="0" end="4" time = "16.699413" name = " (A27) " distance = "556.6471" start_bearing = "-132.34679" end_bearing = "-140.2308" description = "" />
<segment id="76035316" start="0" end="1" time = "0.81749547" name = " (A27) " distance = "27.249847" start_bearing = "-141.03769" end_bearing = "-141.03769" description = "" />
<segment id="76035355" start="0" end="11" time = "30.309141" name = " (A27) " distance = "1010.3046" start_bearing = "-143.57907" end_bearing = "-165.56119" description = "" />
<segment id="7269359" start="0" end="1" time = "8.896009" name = "Keizersveerbrug (A27) " distance = "296.53363" start_bearing = "-167.02675" end_bearing = "-167.02675" description = "" />
<segment id="7269356" start="0" end="4" time = "9.760793" name = " (A27) " distance = "325.35974" start_bearing = "-167.15846" end_bearing = "-172.55174" description = "" />
<segment id="7269351" start="0" end="1" time = "0.8472775" name = " (A27) " distance = "28.242582" start_bearing = "-174.36406" end_bearing = "-174.36406" description = "" />
<segment id="7269346" start="0" end="11" time = "77.342514" name = " (A27) " distance = "2578.0835" turn = "Keep left" turn_angle = "-1.3995514" lanes = "[1, 1, 0]" start_bearing = "-175.76361" end_bearing = "-168.92665" description = "Keep left[1, 1, 0] and go 2671.22 meters (*)" />
<segment id="7264065" start="0" end="1" time = "0.7659678" name = " (A27) " distance = "25.532259" start_bearing = "-168.60786" end_bearing = "-168.60786" description = "" />
<segment id="142392444" start="0" end="1" time = "2.0280354" name = " (A27) " distance = "67.60118" start_bearing = "-170.66713" end_bearing = "-170.66713" description = "" />
<segment id="142392444" start="1" end="3" time = "12.945285" name = " (A27) " distance = "431.5095" turn = "Keep left" turn_angle = "1.4390106" lanes = "[1, 1, 0]" start_bearing = "-169.22812" end_bearing = "-169.06316" description = "Keep left[1, 1, 0] and go 4370.98 meters (*)" />
<segment id="7264089" start="0" end="1" time = "1.8755107" name = " (A27) " distance = "62.51702" start_bearing = "-169.3182" end_bearing = "-169.3182" description = "" />
<segment id="7263795" start="0" end="3" time = "10.26141" name = " (A27) " distance = "342.047" start_bearing = "-169.05159" end_bearing = "-169.09497" description = "" />
<segment id="7265108" start="0" end="2" time = "1.876499" name = " (A27) " distance = "62.549965" start_bearing = "-168.89616" end_bearing = "-168.64088" description = "" />
<segment id="142044475" start="0" end="1" time = "1.8756815" name = " (A27) " distance = "62.522717" start_bearing = "-169.42203" end_bearing = "-169.42203" description = "" />
<segment id="7262378" start="0" end="14" time = "102.295135" name = " (A27) " distance = "3409.8376" start_bearing = "-169.13594" end_bearing = "175.74397" description = "" />
<segment id="7262161" start="0" end="3" time = "18.2269" name = " (A27) " distance = "607.56335" turn = "Keep left" turn_angle = "1.6749115" lanes = "[1, 1, 0]" start_bearing = "177.41888" end_bearing = "177.81676" description = "Keep left[1, 1, 0] and go 2207.02 meters (*)" />
<segment id="7262167" start="0" end="13" time = "47.983597" name = " (A27) " distance = "1599.4531" start_bearing = "177.29585" end_bearing = "-145.17426" description = "" />
<segment id="7263539" start="0" end="1" time = "13.529672" name = " (A27) " distance = "450.989" turn = "Keep left" turn_angle = "0.5317688" lanes = "[1, 1, 0]" start_bearing = "-144.64249" end_bearing = "-144.64249" description = "Keep left[1, 1, 0] and go 573.67 meters (*)" />
<segment id="7263540" start="0" end="1" time = "2.1952474" name = " (A27) " distance = "73.17491" start_bearing = "-144.76836" end_bearing = "-144.76836" description = "" />
<segment id="7263534" start="0" end="1" time = "1.48518" name = " (A27) " distance = "49.505997" start_bearing = "-145.16777" end_bearing = "-145.16777" description = "" />
<segment id="7263551" start="0" end="1" time = "8.081274" name = " (A27) " distance = "269.3758" turn = "Keep left" turn_angle = "0.65522766" lanes = "[1, 1, 0]" start_bearing = "-144.51254" end_bearing = "-144.51254" description = "Keep left[1, 1, 0] and go 4618.85 meters (*)" />
<segment id="7263543" start="0" end="1" time = "1.4930464" name = " (A27) " distance = "49.76821" start_bearing = "-144.33705" end_bearing = "-144.33705" description = "" />
<segment id="7263541" start="0" end="2" time = "11.839014" name = " (A27) " distance = "394.6338" start_bearing = "-145.24902" end_bearing = "-145.88075" description = "" />
<segment id="7263262" start="0" end="11" time = "81.95613" name = " (A27) " distance = "2731.8708" start_bearing = "-147.21733" end_bearing = "-132.22498" description = "" />
<segment id="7263262" start="11" end="18" time = "29.815554" name = " (A27) " distance = "993.85175" start_bearing = "-131.86111" end_bearing = "-143.02669" description = "" />
<segment id="7219085" start="0" end="1" time = "2.0454745" name = " (A27) " distance = "68.18248" start_bearing = "-143.31764" end_bearing = "-143.31764" description = "" />
<segment id="7219039" start="0" end="1" time = "3.334863" name = " (A27) " distance = "111.162094" start_bearing = "-142.7682" end_bearing = "-142.7682" description = "" />
<segment id="7219034" start="0" end="2" time = "12.746751" name = " (A27) " distance = "424.89166" turn = "Keep left" turn_angle = "-0.589859" lanes = "[1, 1, 0]" start_bearing = "-143.35806" end_bearing = "-145.30484" description = "Keep left[1, 1, 0] and go 1365.41 meters (*)" />
<segment id="7219027" start="0" end="1" time = "1.6405184" name = " (A27) " distance = "54.683945" start_bearing = "-147.00862" end_bearing = "-147.00862" description = "" />
<segment id="7219025" start="0" end="6" time = "15.782211" name = " (A27) " distance = "526.0737" start_bearing = "-149.25807" end_bearing = "-158.61047" description = "" />
<segment id="7218894" start="0" end="4" time = "10.792704" name = " (A27) " distance = "359.75677" start_bearing = "-161.12717" end_bearing = "-168.77754" description = "" />
<segment id="7220566" start="0" end="29" time = "102.40725" name = " (A27) " distance = "3413.5747" turn = "Keep left" turn_angle = "-1.792633" lanes = "[1, 1, 0]" start_bearing = "-170.57018" end_bearing = "157.38014" description = "Keep left[1, 1, 0] and go 3413.57 meters (*)" />
<segment id="7220794" start="0" end="10" time = "16.72306" name = " (A58) " distance = "557.4353" turn = "Keep right" turn_angle = "-2.1552887" lanes = "[0, 0, 1]" start_bearing = "155.22485" end_bearing = "174.5309" description = "Keep right[0, 0, 1] and go 2815.65 meters" />
<segment id="7220801" start="0" end="1" time = "1.6023617" name = " (A58) " distance = "53.412052" start_bearing = "-179.21518" end_bearing = "-179.21518" description = "" />
<segment id="7220803" start="0" end="11" time = "14.813116" name = " (A58) " distance = "493.7705" start_bearing = "-177.337" end_bearing = "-127.07811" description = "" />
<segment id="7220805" start="1" end="6" time = "51.330936" name = " (A58) " distance = "1711.0311" start_bearing = "-124.491516" end_bearing = "-124.81439" description = "" />
<segment id="7220805" start="6" end="10" time = "51.539986" name = " (A58) " distance = "1717.9994" turn = "Keep left" turn_angle = "2.5764084" lanes = "[1, 1, 0]" start_bearing = "-122.23798" end_bearing = "-117.04074" description = "Keep left[1, 1, 0] and go 3497.83 meters (*)" />
<segment id="7221420" start="0" end="1" time = "1.9121938" name = " (A58) " distance = "63.73979" start_bearing = "-117.30431" end_bearing = "-117.30431" description = "" />
<segment id="7221419" start="0" end="19" time = "51.48283" name = " (A58) " distance = "1716.0944" start_bearing = "-115.9752" end_bearing = "-88.17446" description = "" />
<segment id="56501888" start="0" end="1" time = "3.3406813" name = " (A16) " distance = "111.35604" turn = "Keep left" turn_angle = "-0.870697" lanes = "[1, 0, 0]" start_bearing = "-89.04516" end_bearing = "-89.04516" description = "Keep left[1, 0, 0] and go 4532.32 meters" />
<segment id="7230700" start="0" end="2" time = "15.107924" name = " (A16) " distance = "503.59747" start_bearing = "-87.86395" end_bearing = "-87.70623" description = "" />
<segment id="7230677" start="0" end="1" time = "1.2922341" name = " (A16) " distance = "43.074467" start_bearing = "-87.55295" end_bearing = "-87.55295" description = "" />
<segment id="7230685" start="0" end="1" time = "1.2477278" name = " (A16) " distance = "41.590923" start_bearing = "-87.97268" end_bearing = "-87.97268" description = "" />
<segment id="92292394" start="0" end="1" time = "0.7128807" name = " (A16) " distance = "23.762688" start_bearing = "-88.13738" end_bearing = "-88.13738" description = "" />
<segment id="92292396" start="0" end="17" time = "10.317441" name = " (A16) " distance = "343.9147" start_bearing = "-86.82017" end_bearing = "105.4885" description = "" />
<segment id="92292395" start="0" end="2" time = "0.8898133" name = " (A16) " distance = "29.660442" start_bearing = "119.577835" end_bearing = "123.27489" description = "" />
<segment id="92292384" start="0" end="4" time = "3.73704" name = " (A16) " distance = "124.568" start_bearing = "138.65222" end_bearing = "158.76529" description = "" />
<segment id="7230924" start="1" end="10" time = "72.10512" name = " (A16) " distance = "2403.504" start_bearing = "169.56697" end_bearing = "-174.40125" description = "" />
<segment id="7230924" start="10" end="14" time = "27.218878" name = " (A16) " distance = "907.2959" start_bearing = "-174.17928" end_bearing = "-166.34499" description = "" />
<segment id="7230924" start="14" end="19" time = "40.624348" name = " (A16) " distance = "1354.1449" turn = "Keep left" turn_angle = "2.1087189" lanes = "[1, 1, 0]" start_bearing = "-164.23627" end_bearing = "-160.95901" description = "Keep left[1, 1, 0] and go 4952.99 meters (*)" />
<segment id="5094229" start="0" end="10" time = "107.96547" name = " (E19) " distance = "3598.8489" start_bearing = "-160.84958" end_bearing = "-166.38635" description = "" />
<segment id="5094229" start="10" end="18" time = "95.98541" name = " (E19) " distance = "3199.5134" turn = "Keep left" turn_angle = "-0.7148895" lanes = "[1, 1, 0]" start_bearing = "-167.10124" end_bearing = "-163.62823" description = "Keep left[1, 1, 0] and go 3199.51 meters (*)" />
<segment id="5094229" start="18" end="50" time = "102.16231" name = " (E19) " distance = "3405.4102" turn = "Keep left" turn_angle = "-0.37800598" lanes = "[1, 1, 0]" start_bearing = "-164.00624" end_bearing = "-138.6669" description = "Keep left[1, 1, 0] and go 3405.41 meters (*)" />
<segment id="5094229" start="50" end="70" time = "246.07271" name = " (E19) " distance = "8202.423" turn = "Keep left" turn_angle = "-1.3254089" lanes = "[1, 1, 0]" start_bearing = "-139.99231" end_bearing = "-143.49081" description = "Keep left[1, 1, 0] and go 13267.43 meters (*)" />
<segment id="51547436" start="0" end="1" time = "2.411135" name = " (E19) " distance = "73.67357" start_bearing = "-141.06812" end_bearing = "-141.06812" description = "" />
<segment id="51547362" start="0" end="6" time = "96.860985" name = " (E19) " distance = "3228.6995" start_bearing = "-140.88599" end_bearing = "-127.73496" description = "" />
<segment id="4410110" start="0" end="5" time = "52.879166" name = " (E19) " distance = "1762.6388" start_bearing = "-127.923325" end_bearing = "-127.55282" description = "" />
<segment id="4410110" start="5" end="13" time = "54.734066" name = " (E19) " distance = "1824.4689" turn = "Keep left" turn_angle = "0.80013275" start_bearing = "-126.752686" end_bearing = "-125.00896" description = "Keep left and go 9051.38 meters (*)" />
<segment id="4409927" start="0" end="1" time = "7.6439724" name = " (E19) " distance = "254.79907" start_bearing = "-126.668625" end_bearing = "-126.668625" description = "" />
<segment id="30836136" start="0" end="46" time = "201.309" name = " (E19) " distance = "6710.3" start_bearing = "-129.35175" end_bearing = "-90.59066" description = "" />
<segment id="25555295" start="0" end="1" time = "2.913197" name = " (E19) " distance = "97.10657" start_bearing = "-92.32602" end_bearing = "-92.32602" description = "" />
<segment id="25555303" start="0" end="1" time = "3.3679214" name = " (E19) " distance = "112.26404" start_bearing = "-94.26789" end_bearing = "-94.26789" description = "" />
<segment id="25555304" start="0" end="1" time = "1.5732371" name = " (E19) " distance = "52.44123" start_bearing = "-94.916565" end_bearing = "-94.916565" description = "" />
<segment id="25555293" start="0" end="1" time = "0.62859356" name = " (E19) " distance = "20.95312" turn = "Keep left" turn_angle = "0.40258026" start_bearing = "-94.513985" end_bearing = "-94.513985" description = "Keep left and go 1375.95 meters (*)" />
<segment id="146511986" start="0" end="12" time = "40.64995" name = " (E19) " distance = "1354.9982" start_bearing = "-96.938385" end_bearing = "-115.788925" description = "" />
<segment id="146511986" start="12" end="66" time = "42.2464" name = " (E19) " distance = "1408.2133" turn = "Keep left" turn_angle = "-0.77612305" start_bearing = "-116.56505" end_bearing = "-146.92932" description = "Keep left and go 2377.37 meters (*)" />
<segment id="4322956" start="0" end="10" time = "29.07467" name = " (R1) " distance = "969.15564" start_bearing = "-158.4047" end_bearing = "-179.59422" description = "" />
<segment id="48525690" start="0" end="2" time = "11.406443" name = " (R1) " distance = "380.21475" turn = "Keep left" turn_angle = "-1.7390594" start_bearing = "178.66672" end_bearing = "178.84267" description = "Keep left and go 3762.28 meters (*)" />
<segment id="4322890" start="0" end="1" time = "3.0917888" name = " (R1) " distance = "103.05962" start_bearing = "-180.0" end_bearing = "180.0" description = "" />
<segment id="4322864" start="0" end="3" time = "15.195565" name = " (R1) " distance = "506.5188" start_bearing = "179.7205" end_bearing = "176.42366" description = "" />
<segment id="4322584" start="0" end="18" time = "62.07714" name = " (R1) " distance = "1724.3651" start_bearing = "173.4802" end_bearing = "137.81555" description = "" />
<segment id="4322569" start="0" end="11" time = "37.73253" name = " (R1) " distance = "1048.1259" start_bearing = "136.1935" end_bearing = "167.69199" description = "" />
<segment id="4322548" start="0" end="9" time = "37.797874" name = " (R1) " distance = "1049.941" turn = "Keep left" turn_angle = "4.876602" start_bearing = "172.56859" end_bearing = "-148.27234" description = "Keep left and go 1049.94 meters (*)" />
<segment id="4312411" start="0" end="4" time = "12.700957" name = "" distance = "282.2435" turn = "Keep right" turn_angle = "8.655991" start_bearing = "-139.61635" end_bearing = "-135.0" description = "Keep right and go 466.72 meters" />
<segment id="4312416" start="0" end="1" time = "3.1672919" name = "" distance = "70.38426" start_bearing = "-131.5834" end_bearing = "-131.5834" description = "" />
<segment id="4312424" start="0" end="2" time = "5.134262" name = "" distance = "114.09471" start_bearing = "-135.54565" end_bearing = "-142.83553" description = "" />
<segment id="4312429" start="0" end="2" time = "3.6745079" name = "" distance = "81.65573" turn = "Keep right" turn_angle = "2.3079834" start_bearing = "-140.52754" end_bearing = "-132.18445" description = "Keep right and go 81.66 meters" />
<segment id="146171826" start="0" end="2" time = "3.7306597" name = "Luitenant Lippenslaan (N184) " distance = "62.17766" turn = "Turn slightly right" turn_angle = "51.157074" start_bearing = "-81.027374" end_bearing = "-80.01059" description = "Turn slightly right and go 1112.29 meters" />
<segment id="4395067" start="0" end="1" time = "26.002739" name = " (N184) " distance = "16.712315" start_bearing = "-79.69515" end_bearing = "-79.69515" description = "" />
<segment id="4453106" start="0" end="6" time = "42.581" name = "Plantin en Moretuslei (N184) " distance = "293.01666" start_bearing = "-84.33272" end_bearing = "-84.770546" description = "" />
<segment id="35006131" start="0" end="4" time = "16.293785" name = "Plantin en Moretuslei (N184) " distance = "271.56308" start_bearing = "-81.809135" end_bearing = "-79.597755" description = "" />
<segment id="29218710" start="0" end="8" time = "28.1292" name = "Plantin en Moretuslei (N184) " distance = "468.82" start_bearing = "-75.28796" end_bearing = "-101.04094" description = "" />
<segment id="34785645" start="0" end="2" time = "34.048256" name = "Plantin en Moretuslei (N184) " distance = "150.80424" turn = "Keep right" turn_angle = "30.52707" start_bearing = "-70.51387" end_bearing = "-84.97339" description = "Keep right and go 530.38 meters" />
<segment id="50897387" start="0" end="1" time = "1.1658815" name = "Plantin en Moretuslei (N184) " distance = "19.43136" start_bearing = "-90.0" end_bearing = "-90.0" description = "" />
<segment id="34785644" start="0" end="4" time = "6.049807" name = "Plantin en Moretuslei (N184) " distance = "100.830124" start_bearing = "-91.39718" end_bearing = "-96.340195" description = "" />
<segment id="43287076" start="1" end="0" time = "26.194777" name = "Plantin en Moretuslei" distance = "16.594124" start_bearing = "-96.1155" end_bearing = "-96.1155" description = "" />
<segment id="50897385" start="0" end="1" time = "38.910587" name = "Plantin en Moretuslei (N184) " distance = "231.8431" start_bearing = "-96.993225" end_bearing = "-96.993225" description = "" />
<segment id="21080483" start="0" end="1" time = "0.7834903" name = "Plantin en Moretuslei (N184) " distance = "10.881809" start_bearing = "-74.42746" end_bearing = "-74.42746" description = "" />
<segment id="29239262" start="0" end="1" time = "1.9438865" name = "Plantin en Moretuslei (N184) " distance = "26.998425" turn = "Keep left" turn_angle = "-20.766968" start_bearing = "-95.19443" end_bearing = "-95.19443" description = "Keep left and go 1284.40 meters" />
<segment id="4394995" start="0" end="1" time = "25.981947" name = "Plantin en Moretuslei (N184) " distance = "13.63815" start_bearing = "-98.130104" end_bearing = "-98.130104" description = "" />
<segment id="4394994" start="0" end="1" time = "26.742825" name = "Van Eycklei (N184) " distance = "24.205906" start_bearing = "-99.6052" end_bearing = "-99.6052" description = "" />
<segment id="34855821" start="0" end="1" time = "2.282983" name = "Van Eycklei (N184) " distance = "31.7081" start_bearing = "-97.16724" end_bearing = "-97.16724" description = "" />
<segment id="34855824" start="0" end="8" time = "32.686893" name = "Van Eycklei (N184) " distance = "453.98465" start_bearing = "-84.99417" end_bearing = "-56.309933" description = "" />
<segment id="4394980" start="0" end="1" time = "25.729961" name = "Maria-Henriëttalei (N184) " distance = "12.16601" start_bearing = "-46.301952" end_bearing = "-46.301952" description = "" />
<segment id="4430256" start="0" end="2" time = "31.529934" name = "Maria-Henriëttalei (N184) " distance = "108.83224" start_bearing = "-50.833004" end_bearing = "-47.683777" description = "" />
<segment id="133434343" start="0" end="1" time = "0.48502362" name = "Maria-Henriëttalei (N184) " distance = "8.083727" start_bearing = "-31.429565" end_bearing = "-31.429565" description = "" />
<segment id="8052374" start="0" end="3" time = "27.157873" name = "Frankrijklei" distance = "35.96455" start_bearing = "-35.90972" end_bearing = "-44.464542" description = "" />
<segment id="4446690" start="0" end="5" time = "32.255695" name = "Bourlastraat" distance = "90.6962" start_bearing = "-48.576336" end_bearing = "-71.87814" description = "" />
<segment id="4446716" start="0" end="7" time = "3.168966" name = "Leopoldplaats" distance = "39.612076" start_bearing = "-59.743565" end_bearing = "-8.972627" description = "" />
<segment id="7940942" start="0" end="10" time = "28.6721" name = "Leopoldstraat" distance = "358.40125" start_bearing = "4.969741" end_bearing = "-23.498566" description = "" />
<segment id="7940955" start="0" end="2" time = "6.4086165" name = "Komedieplaats" distance = "80.107704" start_bearing = "-46.684685" end_bearing = "-51.608463" description = "" />
<segment id="4446795" start="0" end="2" time = "1.3632743" name = "Komedieplaats" distance = "17.04093" turn = "Keep right" turn_angle = "11.372105" start_bearing = "-40.23636" end_bearing = "-27.645975" description = "Keep right and go 226.12 meters" />
<segment id="4446775" start="0" end="16" time = "15.203991" name = "Huidevettersstraat" distance = "190.0499" start_bearing = "-8.746162" end_bearing = "-1.1457628" description = "" />
<segment id="4446826" start="0" end="3" time = "1.5223826" name = "Meir" distance = "19.029783" start_bearing = "-7.6960516" end_bearing = "-30.963757" description = "" />
<segment id="25150191" start="0" end="5" time = "27.61911" name = "Meir" distance = "32.738888" turn = "Keep left" turn_angle = "-32.47119" start_bearing = "-63.434948" end_bearing = "-69.14554" description = "Keep left and go 439.14 meters" />
<segment id="19752616" start="0" end="1" time = "27.84184" name = "Meirbrug" distance = "35.52302" start_bearing = "-75.08797" end_bearing = "-75.08797" description = "" />
<segment id="33682293" start="0" end="1" time = "0.71734244" name = "Meirbrug" distance = "8.966781" start_bearing = "-86.00909" end_bearing = "-86.00909" description = "" />
<segment id="7940939" start="0" end="6" time = "5.6946187" name = "Schoenmarkt" distance = "71.18273" start_bearing = "-103.392494" end_bearing = "-96.94099" description = "" />
<segment id="76441128" start="0" end="5" time = "5.179564" name = "Schoenmarkt" distance = "64.74455" start_bearing = "-94.159645" end_bearing = "-80.37184" description = "" />
<segment id="76441130" start="0" end="3" time = "27.35271" name = "Schoenmarkt" distance = "29.40888" start_bearing = "-82.874985" end_bearing = "-69.04422" description = "" />
<segment id="19752819" start="0" end="5" time = "5.676056" name = "Groenplaats" distance = "70.9507" start_bearing = "-73.73979" end_bearing = "-68.06462" description = "" />
<segment id="19882382" start="0" end="3" time = "1.5475764" name = "" distance = "19.344706" start_bearing = "-90.0" end_bearing = "-147.65256" description = "" />
<segment id="7940936" start="15" end="14" time = "37.753136" name = "Nationalestraat" distance = "106.27612" start_bearing = "-154.78815" end_bearing = "-154.78815" description = "" />
<segment id="22092951" start="0" end="3" time = "39.686947" name = "Lombardenvest" distance = "142.78978" turn = "Turn sharply left" turn_angle = "-122.33687" start_bearing = "82.874985" end_bearing = "101.13282" description = "Turn sharply left and go 187.15 meters" />
<segment id="174336129" start="0" end="1" time = "0.76859903" name = "Lombardenvest" distance = "7.4724903" start_bearing = "131.7603" end_bearing = "131.7603" description = "" />
<segment id="22093399" start="0" end="1" time = "3.7942796" name = "" distance = "36.88883" start_bearing = "173.29337" end_bearing = "173.29337" description = "" />
</test>
</router_tests>

View file

@ -1,140 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="" description="Amstelveen-Leiden" best_percent="5" vehicle="car"
start_lat="52.291026337270445" start_lon="4.848833084106445" target_lat="52.16400849542039" target_lon="4.478881359100342" complete_time="1810.644" complete_distance = "41994.66" >
<segment id="48102635" start="9" end="17" time = "26.337616" name = "" distance = "365.80023" turn = "Go ahead" turn_angle = "0.0" start_bearing = "-80.22256" end_bearing = "-79.69515" description = "Go ahead and go 365.80 meters" />
<segment id="7364781" start="0" end="6" time = "64.496864" name = "Handweg" distance = "548.56757" turn = "Turn right" turn_angle = "87.82526" start_bearing = "8.130102" end_bearing = "9.901572" description = "Turn right and go 548.57 meters" />
<segment id="7364782" start="1" end="0" time = "26.062386" name = "Keizer Karelweg" distance = "14.755359" turn = "Turn right" turn_angle = "89.328316" start_bearing = "99.22989" end_bearing = "99.22989" description = "Turn right and go 917.26 meters" />
<segment id="7364779" start="0" end="5" time = "13.558414" name = "Keizer Karelweg" distance = "188.31131" start_bearing = "96.254036" end_bearing = "66.169136" description = "" />
<segment id="7364775" start="1" end="0" time = "4.9813266" name = "Keizer Karelweg" distance = "69.18509" start_bearing = "62.372807" end_bearing = "62.372807" description = "" />
<segment id="7364776" start="0" end="1" time = "4.9812937" name = "Keizer Karelweg" distance = "69.18464" start_bearing = "62.334564" end_bearing = "62.334564" description = "" />
<segment id="7364778" start="0" end="1" time = "3.806921" name = "Keizer Karelweg" distance = "52.873905" start_bearing = "62.48443" end_bearing = "62.48443" description = "" />
<segment id="7364787" start="0" end="1" time = "0.5657692" name = "Keizer Karelweg" distance = "7.8579054" start_bearing = "65.897766" end_bearing = "65.897766" description = "" />
<segment id="7364771" start="0" end="1" time = "1.5512005" name = "Keizer Karelweg" distance = "21.544453" start_bearing = "61.50436" end_bearing = "61.50436" description = "" />
<segment id="58661684" start="0" end="1" time = "0.6126022" name = "Keizer Karelweg" distance = "8.508364" start_bearing = "61.189205" end_bearing = "61.189205" description = "" />
<segment id="7364071" start="0" end="1" time = "4.6289053" name = "Keizer Karelweg" distance = "64.29035" start_bearing = "62.34026" end_bearing = "62.34026" description = "" />
<segment id="7364489" start="0" end="1" time = "3.0778131" name = "Keizer Karelweg" distance = "42.747406" start_bearing = "62.333244" end_bearing = "62.333244" description = "" />
<segment id="7364488" start="0" end="1" time = "0.8222186" name = "Keizer Karelweg" distance = "11.4197035" start_bearing = "62.19854" end_bearing = "62.19854" description = "" />
<segment id="7364487" start="0" end="1" time = "3.6412437" name = "Keizer Karelweg" distance = "50.57283" start_bearing = "63.893307" end_bearing = "63.893307" description = "" />
<segment id="7364482" start="0" end="1" time = "2.4905744" name = "Keizer Karelweg" distance = "34.59131" start_bearing = "61.38954" end_bearing = "61.38954" description = "" />
<segment id="7364483" start="0" end="1" time = "2.506028" name = "Keizer Karelweg" distance = "34.805946" start_bearing = "57.228592" end_bearing = "57.228592" description = "" />
<segment id="48147997" start="0" end="2" time = "2.944532" name = "Keizer Karelweg" distance = "40.89628" start_bearing = "57.707115" end_bearing = "51.679886" description = "" />
<segment id="7364498" start="0" end="2" time = "3.2543092" name = "Keizer Karelweg" distance = "45.198742" start_bearing = "52.460567" end_bearing = "70.857735" description = "" />
<segment id="7364496" start="0" end="1" time = "1.0199182" name = "Keizer Karelweg" distance = "14.165531" start_bearing = "53.746162" end_bearing = "53.746162" description = "" />
<segment id="58384522" start="0" end="4" time = "30.041615" name = "Keizer Karelweg" distance = "70.02242" start_bearing = "9.050722" end_bearing = "19.798876" description = "" />
<segment id="7364485" start="0" end="2" time = "5.4958763" name = "Keizer Karelweg" distance = "76.33162" start_bearing = "28.694904" end_bearing = "18.610165" description = "" />
<segment id="7365615" start="0" end="3" time = "7.2419686" name = "Keizer Karelweg" distance = "100.5829" turn = "Keep left" turn_angle = "-2.6131277" start_bearing = "15.997037" end_bearing = "11.788183" description = "Keep left and go 165.64 meters" />
<segment id="46899722" start="0" end="1" time = "3.2722278" name = "Keizer Karelweg" distance = "45.44761" start_bearing = "19.010767" end_bearing = "19.010767" description = "" />
<segment id="46907124" start="0" end="2" time = "26.411913" name = "Keizer Karelweg" distance = "19.609913" start_bearing = "16.039944" end_bearing = "-5.194429" description = "" />
<segment id="46936678" start="0" end="1" time = "0.58887875" name = "Keizer Karelweg" distance = "9.814647" turn = "Keep right" turn_angle = "-35.04193" start_bearing = "-40.23636" end_bearing = "-40.23636" description = "Keep right and go 1255.32 meters" />
<segment id="7653699" start="0" end="6" time = "10.217556" name = " (5) " distance = "283.821" start_bearing = "-60.642246" end_bearing = "-67.54718" description = "" />
<segment id="47459626" start="0" end="5" time = "14.381371" name = "Burgemeester van Sonweg (A9) " distance = "399.48254" start_bearing = "-59.004417" end_bearing = "-72.72188" description = "" />
<segment id="7366229" start="0" end="4" time = "16.7413" name = "Burgemeester van Sonweg (A9) " distance = "465.03613" start_bearing = "-75.815704" end_bearing = "-77.17866" description = "" />
<segment id="7366219" start="0" end="1" time = "2.0451295" name = "Burgemeester van Sonweg (A9) " distance = "56.809155" start_bearing = "-78.007576" end_bearing = "-78.007576" description = "" />
<segment id="7366222" start="0" end="1" time = "1.4526641" name = "Burgemeester van Sonweg (A9) " distance = "40.35178" start_bearing = "-76.4736" end_bearing = "-76.4736" description = "" />
<segment id="7366222" start="1" end="4" time = "18.41388" name = "Burgemeester van Sonweg (A9) " distance = "511.49667" turn = "Keep left" turn_angle = "1.5671005" lanes = "[1, 1, 1, 0]" start_bearing = "-74.9065" end_bearing = "-69.903076" description = "Keep left[1, 1, 1, 0] and go 2050.72 meters (*)" />
<segment id="7366408" start="0" end="1" time = "1.2294494" name = "Burgemeester van Sonweg (A9) " distance = "34.151375" start_bearing = "-69.40767" end_bearing = "-69.40767" description = "" />
<segment id="7366412" start="0" end="4" time = "23.745186" name = "Burgemeester van Sonweg (A9) " distance = "659.5885" start_bearing = "-68.06238" end_bearing = "-58.380173" description = "" />
<segment id="7366400" start="0" end="1" time = "2.6364217" name = "Burgemeester (A9) " distance = "73.23394" start_bearing = "-56.97613" end_bearing = "-56.97613" description = "" />
<segment id="7366389" start="0" end="3" time = "13.477453" name = "Burgemeester van Sonweg (A9) " distance = "374.37372" start_bearing = "-54.02313" end_bearing = "-48.993145" description = "" />
<segment id="7366392" start="0" end="1" time = "7.055489" name = " (A9) " distance = "195.98581" start_bearing = "-44.32153" end_bearing = "-44.32153" description = "" />
<segment id="7366394" start="0" end="1" time = "2.1986048" name = " (A9) " distance = "61.07236" start_bearing = "-40.266563" end_bearing = "-40.266563" description = "" />
<segment id="7366395" start="0" end="1" time = "5.0694094" name = " (A9) " distance = "140.81693" start_bearing = "-39.672035" end_bearing = "-39.672035" description = "" />
<segment id="7366399" start="0" end="3" time = "17.410093" name = " (A9) " distance = "483.6137" turn = "Keep left" turn_angle = "4.4496155" lanes = "[1, 1, 1, 0]" start_bearing = "-35.22242" end_bearing = "-27.70203" description = "Keep left[1, 1, 1, 0] and go 1270.54 meters (*)" />
<segment id="7391827" start="0" end="3" time = "16.218348" name = " (A9) " distance = "450.50967" start_bearing = "-27.27588" end_bearing = "-30.757805" description = "" />
<segment id="7391845" start="0" end="2" time = "12.111105" name = " (A9) " distance = "336.4196" start_bearing = "-36.934338" end_bearing = "-39.16816" description = "" />
<segment id="138581970" start="0" end="3" time = "9.409037" name = " (A4) " distance = "261.36215" turn = "Keep right" turn_angle = "0.7019577" lanes = "[0, 0, 1, 1]" start_bearing = "-38.4662" end_bearing = "-44.173107" description = "Keep right[0, 0, 1, 1] and go 261.36 meters" />
<segment id="138581978" start="0" end="1" time = "14.312377" name = " (A9) " distance = "397.56604" turn = "Keep left" turn_angle = "-3.9159317" lanes = "[1, 1, 0]" start_bearing = "-48.08904" end_bearing = "-48.08904" description = "Keep left[1, 1, 0] and go 586.41 meters" />
<segment id="47633922" start="0" end="1" time = "6.79849" name = " (A9) " distance = "188.84695" start_bearing = "-49.776634" end_bearing = "-49.776634" description = "" />
<segment id="138581965" start="0" end="16" time = "14.470292" name = " (A4) " distance = "401.95258" turn = "Keep right" turn_angle = "6.5390244" lanes = "[0, 0, 1]" start_bearing = "-43.23761" end_bearing = "-139.97626" description = "Keep right[0, 0, 1] and go 570.67 meters" />
<segment id="138581972" start="2" end="3" time = "0.8736524" name = " (A4) " distance = "24.268124" start_bearing = "-122.18263" end_bearing = "-122.18263" description = "" />
<segment id="23482007" start="0" end="1" time = "3.3637545" name = " (A4) " distance = "93.43763" start_bearing = "-122.26571" end_bearing = "-122.26571" description = "" />
<segment id="23482008" start="0" end="1" time = "1.8365201" name = " (A4) " distance = "51.01445" start_bearing = "-121.594124" end_bearing = "-121.594124" description = "" />
<segment id="23482008" start="1" end="5" time = "17.970161" name = " (A4) " distance = "499.17117" turn = "Keep left" turn_angle = "4.0060425" lanes = "[1, 1, 0]" start_bearing = "-117.58808" end_bearing = "-105.72703" description = "Keep left[1, 1, 0] and go 2123.37 meters" />
<segment id="7387527" start="0" end="2" time = "17.785975" name = " (A4) " distance = "494.05487" start_bearing = "-107.873505" end_bearing = "-106.7262" description = "" />
<segment id="7391842" start="0" end="8" time = "40.685017" name = " (A4) " distance = "1130.1394" start_bearing = "-104.69241" end_bearing = "-114.18361" description = "" />
<segment id="7391177" start="0" end="8" time = "28.468485" name = " (A4) " distance = "790.79126" turn = "Keep left" turn_angle = "-6.119072" lanes = "[1, 1, 1, 1, 0, 0]" start_bearing = "-120.30268" end_bearing = "-142.94156" description = "Keep left[1, 1, 1, 1, 0, 0] and go 3659.78 meters (*)" />
<segment id="7392518" start="0" end="4" time = "21.6246" name = "Schipholtunnel (A4) " distance = "600.68335" start_bearing = "-147.5052" end_bearing = "-158.58344" description = "" />
<segment id="7392519" start="0" end="6" time = "33.880722" name = " (A4) " distance = "941.1312" start_bearing = "-158.51917" end_bearing = "-158.88887" description = "" />
<segment id="48928930" start="0" end="4" time = "18.968428" name = " (A4) " distance = "632.28094" start_bearing = "-158.87662" end_bearing = "-157.43513" description = "" />
<segment id="7392566" start="0" end="6" time = "22.742098" name = " (A4) " distance = "694.89746" start_bearing = "-153.9124" end_bearing = "-137.86241" description = "" />
<segment id="7392555" start="0" end="1" time = "31.326166" name = " (A4) " distance = "1044.2054" turn = "Keep left" turn_angle = "-0.6644745" lanes = "[1, 1, 1, 1, 0]" start_bearing = "-138.52689" end_bearing = "-138.52689" description = "Keep left[1, 1, 1, 1, 0] and go 4688.94 meters (*)" />
<segment id="76256823" start="0" end="1" time = "1.5981343" name = " (A4) " distance = "53.27114" start_bearing = "-139.16467" end_bearing = "-139.16467" description = "" />
<segment id="73834410" start="0" end="1" time = "2.2036479" name = " (A4) " distance = "73.454926" start_bearing = "-138.84094" end_bearing = "-138.84094" description = "" />
<segment id="134438595" start="0" end="1" time = "17.09856" name = " (A4) " distance = "569.95197" start_bearing = "-138.81062" end_bearing = "-138.81062" description = "" />
<segment id="79290805" start="0" end="2" time = "12.83234" name = " (A4) " distance = "427.74466" start_bearing = "-139.27637" end_bearing = "-138.68178" description = "" />
<segment id="134438614" start="0" end="1" time = "3.8931432" name = " (A4) " distance = "129.77144" start_bearing = "-138.1139" end_bearing = "-138.1139" description = "" />
<segment id="134438620" start="0" end="4" time = "71.71622" name = " (A4) " distance = "2390.5405" start_bearing = "-138.7688" end_bearing = "-139.07118" description = "" />
<segment id="134438608" start="0" end="1" time = "26.764736" name = " (A4) " distance = "892.15784" turn = "Keep left" turn_angle = "0.18760681" lanes = "[1, 1, 1, 1, 1, 0]" start_bearing = "-138.88358" end_bearing = "-138.88358" description = "Keep left[1, 1, 1, 1, 1, 0] and go 2172.36 meters (*)" />
<segment id="134438607" start="0" end="1" time = "38.406105" name = " (A4) " distance = "1280.2035" start_bearing = "-138.61885" end_bearing = "-138.61885" description = "" />
<segment id="73833494" start="0" end="1" time = "44.74289" name = " (A4) " distance = "1491.4296" turn = "Keep left" turn_angle = "-0.23878479" lanes = "[1, 1, 1, 1, 0, 0]" start_bearing = "-138.85764" end_bearing = "-138.85764" description = "Keep left[1, 1, 1, 1, 0, 0] and go 1491.43 meters (*)" />
<segment id="127572846" start="0" end="10" time = "31.107876" name = " (A44) " distance = "1036.9292" turn = "Keep right" turn_angle = "1.402359" lanes = "[0, 0, 1, 1]" start_bearing = "-137.45528" end_bearing = "-112.77435" description = "Keep right[0, 0, 1, 1] and go 1778.32 meters" />
<segment id="127572943" start="0" end="7" time = "15.031159" name = " (A44) " distance = "501.03864" start_bearing = "-109.87218" end_bearing = "-97.94562" description = "" />
<segment id="127572922" start="0" end="1" time = "7.2106943" name = " (A44) " distance = "240.35648" start_bearing = "-97.5889" end_bearing = "-97.5889" description = "" />
<segment id="127572922" start="1" end="2" time = "10.849909" name = " (A44) " distance = "361.6636" turn = "Keep left" turn_angle = "-0.5248642" lanes = "[1, 1, 0]" start_bearing = "-98.11376" end_bearing = "-98.11376" description = "Keep left[1, 1, 0] and go 3573.27 meters (*)" />
<segment id="127572881" start="0" end="1" time = "1.5470482" name = " (A44) " distance = "51.56827" start_bearing = "-97.35238" end_bearing = "-97.35238" description = "" />
<segment id="127572873" start="0" end="1" time = "11.498509" name = " (A44) " distance = "383.28363" start_bearing = "-97.52791" end_bearing = "-97.52791" description = "" />
<segment id="127572844" start="0" end="9" time = "33.256123" name = " (A44) " distance = "1108.5374" start_bearing = "-97.775215" end_bearing = "-93.01279" description = "" />
<segment id="127572925" start="0" end="3" time = "6.357968" name = " (A44) " distance = "211.93225" start_bearing = "-93.91316" end_bearing = "-98.29076" description = "" />
<segment id="127572848" start="0" end="12" time = "43.68857" name = " (A44) " distance = "1456.2855" start_bearing = "-101.377106" end_bearing = "-93.971985" description = "" />
<segment id="127572863" start="0" end="1" time = "11.523968" name = " (A44) " distance = "384.13223" turn = "Keep left" turn_angle = "-0.6149826" lanes = "[1, 1, 0]" start_bearing = "-94.58697" end_bearing = "-94.58697" description = "Keep left[1, 1, 0] and go 2455.20 meters (*)" />
<segment id="127572853" start="0" end="1" time = "3.6939206" name = " (A44) " distance = "123.13068" start_bearing = "-94.25524" end_bearing = "-94.25524" description = "" />
<segment id="127572861" start="0" end="1" time = "9.576368" name = " (A44) " distance = "319.21225" start_bearing = "-93.54158" end_bearing = "-93.54158" description = "" />
<segment id="127572938" start="0" end="7" time = "22.92751" name = " (A44) " distance = "764.25024" start_bearing = "-94.00912" end_bearing = "-115.84439" description = "" />
<segment id="127572857" start="0" end="1" time = "0.8048988" name = " (A44) " distance = "26.82996" start_bearing = "-117.93714" end_bearing = "-117.93714" description = "" />
<segment id="127572918" start="0" end="2" time = "12.34009" name = " (A44) " distance = "411.3363" start_bearing = "-119.62935" end_bearing = "-119.52635" description = "" />
<segment id="127572897" start="0" end="1" time = "4.046369" name = " (A44) " distance = "134.87897" start_bearing = "-119.696655" end_bearing = "-119.696655" description = "" />
<segment id="127572914" start="0" end="2" time = "8.742952" name = " (A44) " distance = "291.43173" start_bearing = "-119.66132" end_bearing = "-117.302055" description = "" />
<segment id="37685756" start="0" end="3" time = "8.791759" name = " (A44) " distance = "293.0586" turn = "Keep left" turn_angle = "5.0677414" lanes = "[1, 1, 0]" start_bearing = "-112.234314" end_bearing = "-107.311646" description = "Keep left[1, 1, 0] and go 2654.12 meters (*)" />
<segment id="37685757" start="0" end="1" time = "2.7248127" name = " (A44) " distance = "90.82709" start_bearing = "-108.10587" end_bearing = "-108.10587" description = "" />
<segment id="127572870" start="0" end="1" time = "2.6695774" name = " (A44) " distance = "88.98591" start_bearing = "-107.50791" end_bearing = "-107.50791" description = "" />
<segment id="127572934" start="0" end="4" time = "26.49488" name = " (A44) " distance = "883.16266" start_bearing = "-108.23557" end_bearing = "-107.8305" description = "" />
<segment id="127572900" start="0" end="1" time = "1.0124283" name = " (A44) " distance = "33.747604" start_bearing = "-107.54133" end_bearing = "-107.54133" description = "" />
<segment id="127572929" start="0" end="4" time = "18.008535" name = " (A44) " distance = "600.2845" start_bearing = "-107.91201" end_bearing = "-107.83552" description = "" />
<segment id="127572878" start="0" end="1" time = "0.96405894" name = " (A44) " distance = "32.135296" start_bearing = "-107.053314" end_bearing = "-107.053314" description = "" />
<segment id="127572927" start="0" end="4" time = "10.684452" name = " (A44) " distance = "356.1484" start_bearing = "-109.17901" end_bearing = "-121.84905" description = "" />
<segment id="127572852" start="0" end="1" time = "0.88802284" name = " (A44) " distance = "29.60076" start_bearing = "-123.293564" end_bearing = "-123.293564" description = "" />
<segment id="127572889" start="0" end="1" time = "7.384954" name = " (A44) " distance = "246.16513" start_bearing = "-122.4777" end_bearing = "-122.4777" description = "" />
<segment id="127572937" start="0" end="6" time = "33.83987" name = " (A44) " distance = "1127.9957" turn = "Keep left" turn_angle = "0.13690186" lanes = "[1, 1, 0]" start_bearing = "-122.3408" end_bearing = "-122.45586" description = "Keep left[1, 1, 0] and go 1837.03 meters (*)" />
<segment id="127572902" start="0" end="1" time = "0.8881579" name = " (A44) " distance = "29.605263" start_bearing = "-122.11802" end_bearing = "-122.11802" description = "" />
<segment id="127572876" start="0" end="1" time = "4.624057" name = " (A44) " distance = "154.13521" start_bearing = "-122.52323" end_bearing = "-122.52323" description = "" />
<segment id="127572858" start="0" end="1" time = "0.77881515" name = " (A44) " distance = "25.960505" start_bearing = "-122.90524" end_bearing = "-122.90524" description = "" />
<segment id="127572893" start="0" end="1" time = "7.1423736" name = " (A44) " distance = "238.0791" start_bearing = "-122.72464" end_bearing = "-122.72464" description = "" />
<segment id="127572864" start="0" end="1" time = "1.2652649" name = " (A44) " distance = "42.175495" start_bearing = "-122.868675" end_bearing = "-122.868675" description = "" />
<segment id="127572907" start="0" end="1" time = "1.9110428" name = " (A44) " distance = "63.701424" start_bearing = "-122.040405" end_bearing = "-122.040405" description = "" />
<segment id="127572860" start="0" end="1" time = "4.6614137" name = " (A44) " distance = "155.38045" start_bearing = "-122.25471" end_bearing = "-122.25471" description = "" />
<segment id="127572912" start="0" end="2" time = "9.992768" name = " (A44) " distance = "333.0923" turn = "Keep left" turn_angle = "-0.090156555" lanes = "[1, 1, 0]" start_bearing = "-122.344864" end_bearing = "-121.91887" description = "Keep left[1, 1, 0] and go 3297.52 meters (*)" />
<segment id="127572854" start="0" end="1" time = "1.3020737" name = " (A44) " distance = "43.402454" start_bearing = "-122.307335" end_bearing = "-122.307335" description = "" />
<segment id="127572909" start="0" end="1" time = "2.6900423" name = " (A44) " distance = "89.66807" start_bearing = "-122.06739" end_bearing = "-122.06739" description = "" />
<segment id="7455971" start="0" end="1" time = "1.3996769" name = " (A44) " distance = "46.655895" start_bearing = "-122.93869" end_bearing = "-122.93869" description = "" />
<segment id="7455847" start="0" end="2" time = "7.6089964" name = " (A44) " distance = "253.63321" start_bearing = "-122.839775" end_bearing = "-121.33176" description = "" />
<segment id="7455984" start="0" end="13" time = "41.96604" name = " (A44) " distance = "1398.868" start_bearing = "-122.41506" end_bearing = "-161.4873" description = "" />
<segment id="10074876" start="0" end="1" time = "2.6363664" name = " (A44) " distance = "87.878876" start_bearing = "-162.09555" end_bearing = "-162.09555" description = "" />
<segment id="7456947" start="0" end="5" time = "31.329775" name = " (A44) " distance = "1044.3258" start_bearing = "-161.84627" end_bearing = "-163.69829" description = "" />
<segment id="47805660" start="0" end="3" time = "14.836821" name = " (A44) " distance = "494.56067" turn = "Keep left" turn_angle = "-3.7022247" lanes = "[1, 1, 0]" start_bearing = "-167.40051" end_bearing = "-168.2376" description = "Keep left[1, 1, 0] and go 1449.69 meters (*)" />
<segment id="127572879" start="0" end="1" time = "1.3521364" name = " (A44) " distance = "45.071213" start_bearing = "-168.27919" end_bearing = "-168.27919" description = "" />
<segment id="127572920" start="0" end="2" time = "13.026337" name = " (A44) " distance = "434.2112" start_bearing = "-167.84041" end_bearing = "-167.59436" description = "" />
<segment id="7452303" start="0" end="2" time = "14.275366" name = " (A44) " distance = "475.84552" start_bearing = "-167.61009" end_bearing = "-167.90056" description = "" />
<segment id="7462489" start="0" end="1" time = "1.5106231" name = " (8) " distance = "33.5694" turn = "Keep right" turn_angle = "6.73201" lanes = "[0, 0, 1]" start_bearing = "-161.16855" end_bearing = "-161.16855" description = "Keep right[0, 0, 1] and go 608.90 meters" />
<segment id="75006434" start="0" end="11" time = "50.889664" name = " (8) " distance = "575.32587" start_bearing = "-166.7236" end_bearing = "-162.3777" description = "" />
<segment id="50094707" start="0" end="2" time = "54.242847" name = "Ingenieur G.Tjalmaweg (N206) " distance = "58.928417" turn = "Turn left" turn_angle = "-80.147865" start_bearing = "117.474434" end_bearing = "117.249435" description = "Turn left and go 492.87 meters" />
<segment id="7462456" start="0" end="1" time = "5.5570893" name = "Ingenieur G.Tjalmaweg (N206) " distance = "77.1818" start_bearing = "111.17347" end_bearing = "111.17347" description = "" />
<segment id="54145941" start="0" end="2" time = "6.716044" name = "Plesmanlaan (N206) " distance = "93.2784" start_bearing = "110.18287" end_bearing = "109.04123" description = "" />
<segment id="59374279" start="0" end="1" time = "1.0861655" name = "Plesmanlaan (N206) " distance = "15.085632" start_bearing = "105.751175" end_bearing = "105.751175" description = "" />
<segment id="7452565" start="0" end="2" time = "42.884644" name = "Plesmanlaan (N206) " distance = "248.39784" start_bearing = "101.6278" end_bearing = "99.095955" description = "" />
<segment id="7452565" start="2" end="5" time = "9.551005" name = "Plesmanlaan (N206) " distance = "132.65285" turn = "Keep left" turn_angle = "-9.095955" start_bearing = "90.0" end_bearing = "98.775055" description = "Keep left and go 229.90 meters" />
<segment id="84277998" start="0" end="1" time = "25.961454" name = "Plesmanlaan (N206) " distance = "13.353545" start_bearing = "98.343895" end_bearing = "98.343895" description = "" />
<segment id="7452550" start="0" end="1" time = "0.74511296" name = "Plesmanlaan" distance = "10.348791" start_bearing = "98.74616" end_bearing = "98.74616" description = "" />
<segment id="84506292" start="0" end="2" time = "5.2950974" name = "Plesmanlaan" distance = "73.54302" start_bearing = "96.75357" end_bearing = "95.39911" description = "" />
<segment id="111682884" start="0" end="8" time = "44.947136" name = "Plesmanlaan" distance = "277.04355" turn = "Keep left" turn_angle = "1.1487961" start_bearing = "96.547905" end_bearing = "130.60129" description = "Keep left and go 826.44 meters (*)" />
<segment id="7452292" start="0" end="12" time = "39.55688" name = "Plesmanlaan" distance = "549.4011" start_bearing = "126.05462" end_bearing = "90.61606" description = "" />
<segment id="7452292" start="12" end="13" time = "7.903302" name = "Plesmanlaan" distance = "109.76809" turn = "Keep left" turn_angle = "-0.42378998" start_bearing = "90.19227" end_bearing = "90.19227" description = "Keep left and go 558.88 meters (*)" />
<segment id="7452300" start="0" end="2" time = "1.3699057" name = "Plesmanlaan" distance = "19.026468" start_bearing = "91.21887" end_bearing = "88.12212" description = "" />
<segment id="97634915" start="0" end="1" time = "3.0848742" name = "Plesmanlaan" distance = "42.845478" start_bearing = "82.25726" end_bearing = "82.25726" description = "" />
<segment id="7452298" start="0" end="1" time = "0.5373205" name = "Plesmanlaan" distance = "7.462785" start_bearing = "79.9194" end_bearing = "79.9194" description = "" />
<segment id="144375594" start="0" end="10" time = "26.690458" name = "Plesmanlaan" distance = "370.70084" start_bearing = "77.686935" end_bearing = "118.15619" description = "" />
<segment id="7450989" start="0" end="2" time = "25.502869" name = "Schipholweg" distance = "9.079578" start_bearing = "80.21759" end_bearing = "73.73979" description = "" />
<segment id="149555300" start="6" end="9" time = "26.771402" name = "Morsweg" distance = "22.142519" turn = "Make uturn" turn_angle = "-135.12933" start_bearing = "-61.38954" end_bearing = "-38.884495" description = "Make uturn and go 104.33 meters" />
<segment id="7452288" start="0" end="2" time = "5.917617" name = "" distance = "82.189125" start_bearing = "-62.281498" end_bearing = "-69.78357" description = "" />
</test>
</router_tests>

View file

@ -1,122 +0,0 @@
package crosby.binary;
import java.util.Date;
import java.util.List;
import com.google.protobuf.InvalidProtocolBufferException;
import crosby.binary.Osmformat;
import crosby.binary.file.BlockReaderAdapter;
import crosby.binary.file.FileBlock;
import crosby.binary.file.FileBlockPosition;
public abstract class BinaryParser implements BlockReaderAdapter {
protected int granularity;
private long lat_offset;
private long lon_offset;
protected int date_granularity;
private String strings[];
/** Take a Info protocol buffer containing a date and convert it into a java Date object */
protected Date getDate(Osmformat.Info info) {
if (info.hasTimestamp()) {
return new Date(date_granularity * (long) info.getTimestamp());
} else
return NODATE;
}
public static final Date NODATE = new Date();
/** Get a string based on the index used.
*
* Index 0 is reserved to use as a delimiter, therefore, index 1 corresponds to the first string in the table
* @param id
* @return
*/
protected String getStringById(int id) {
return strings[id];
}
@Override
public void handleBlock(FileBlock message) {
// TODO Auto-generated method stub
try {
if (message.getType().equals("OSMHeader")) {
Osmformat.HeaderBlock headerblock = Osmformat.HeaderBlock
.parseFrom(message.getData());
parse(headerblock);
} else if (message.getType().equals("OSMData")) {
Osmformat.PrimitiveBlock primblock = Osmformat.PrimitiveBlock
.parseFrom(message.getData());
parse(primblock);
}
} catch (InvalidProtocolBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new Error("ParseError"); // TODO
}
}
@Override
public boolean skipBlock(FileBlockPosition block) {
// System.out.println("Seeing block of type: "+block.getType());
if (block.getType().equals("OSMData"))
return false;
if (block.getType().equals("OSMHeader"))
return false;
System.out.println("Skipped block of type: " + block.getType());
return true;
}
/** Convert a latitude value stored in a protobuf into a double, compensating for granularity and latitude offset */
public double parseLat(long degree) {
// Support non-zero offsets. (We don't currently generate them)
return (granularity * degree + lat_offset) * .000000001;
}
/** Convert a longitude value stored in a protobuf into a double, compensating for granularity and longitude offset */
public double parseLon(long degree) {
// Support non-zero offsets. (We don't currently generate them)
return (granularity * degree + lon_offset) * .000000001;
}
/** Parse a Primitive block (containing a string table, other paramaters, and PrimitiveGroups */
public void parse(Osmformat.PrimitiveBlock block) {
Osmformat.StringTable stablemessage = block.getStringtable();
strings = new String[stablemessage.getSCount()];
for (int i = 0; i < strings.length; i++) {
strings[i] = stablemessage.getS(i).toStringUtf8();
}
granularity = block.getGranularity();
lat_offset = block.getLatOffset();
lon_offset = block.getLonOffset();
date_granularity = block.getDateGranularity();
for (Osmformat.PrimitiveGroup groupmessage : block
.getPrimitivegroupList()) {
// Exactly one of these should trigger on each loop.
parseNodes(groupmessage.getNodesList());
parseWays(groupmessage.getWaysList());
parseRelations(groupmessage.getRelationsList());
if (groupmessage.hasDense())
parseDense(groupmessage.getDense());
}
}
/** Parse a list of Relation protocol buffers and send the resulting relations to a sink. */
protected abstract void parseRelations(List<Osmformat.Relation> rels);
/** Parse a DenseNode protocol buffer and send the resulting nodes to a sink. */
protected abstract void parseDense(Osmformat.DenseNodes nodes);
/** Parse a list of Node protocol buffers and send the resulting nodes to a sink. */
protected abstract void parseNodes(List<Osmformat.Node> nodes);
/** Parse a list of Way protocol buffers and send the resulting ways to a sink. */
protected abstract void parseWays(List<Osmformat.Way> ways);
/** Parse a header message. */
protected abstract void parse(Osmformat.HeaderBlock header);
}

View file

@ -1,148 +0,0 @@
package crosby.binary;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import crosby.binary.Osmformat.PrimitiveGroup;
import crosby.binary.file.BlockOutputStream;
import crosby.binary.file.FileBlock;
/**
* Generic serializer common code
*
* Serialize a set of blobs and process them. Subclasses implement handlers for
* different API's (osmosis, mkgmap, splitter, etc.)
*
* All data is converted into PrimGroupWriterInterface objects, which are then
* ordered to process their data at the appropriate time.
* */
public class BinarySerializer {
/**
* Interface used to write a group of primitives. One of these for each
* group type (Node, Way, Relation, DenseNode, Changeset)
*/
protected interface PrimGroupWriterInterface {
/** This callback is invoked on each group that is going into the fileblock in order to give it a chance to
* add to the stringtable pool of strings. */
public void addStringsToStringtable();
/**
* This callback is invoked to request that the primgroup serialize itself into the given protocol buffer object.
*/
public Osmformat.PrimitiveGroup serialize();
}
/** Set the granularity (precision of lat/lon, measured in unites of nanodegrees. */
public void configGranularity(int granularity) {
this.granularity = granularity;
}
/** Set whether metadata is to be omitted */
public void configOmit(boolean omit_metadata) {
this.omit_metadata = omit_metadata;
}
/** Configure the maximum number of entities in a batch */
public void configBatchLimit(int batch_limit) {
this.batch_limit = batch_limit;
}
// Paramaters affecting the output size.
protected final int MIN_DENSE = 10;
protected int batch_limit = 4000;
// Parmaters affecting the output.
protected int granularity = 100;
protected int date_granularity = 1000;
protected boolean omit_metadata = false;
/** How many primitives have been seen in this batch */
protected int batch_size = 0;
protected int total_entities = 0;
private StringTable stringtable = new StringTable();
protected List<PrimGroupWriterInterface> groups = new ArrayList<PrimGroupWriterInterface>();
protected BlockOutputStream output;
public BinarySerializer(BlockOutputStream output) {
this.output = output;
}
public StringTable getStringTable() {
return stringtable;
}
public void flush() throws IOException {
processBatch();
output.flush();
}
public void close() throws IOException {
flush();
output.close();
}
long debug_bytes = 0;
public void processBatch() {
// System.out.format("Batch of %d groups: ",groups.size());
if (groups.size() == 0)
return;
Osmformat.PrimitiveBlock.Builder primblock = Osmformat.PrimitiveBlock
.newBuilder();
stringtable.clear();
// Preprocessing: Figure out the stringtable.
for (PrimGroupWriterInterface i : groups)
i.addStringsToStringtable();
stringtable.finish();
// Now, start serializing.
for (PrimGroupWriterInterface i : groups) {
PrimitiveGroup group = i.serialize();
if (group != null)
primblock.addPrimitivegroup(group);
}
primblock.setStringtable(stringtable.serialize());
primblock.setGranularity(this.granularity);
primblock.setDateGranularity(this.date_granularity);
// Only generate data with offset (0,0)
//
Osmformat.PrimitiveBlock message = primblock.build();
// System.out.println(message);
debug_bytes += message.getSerializedSize();
if (false) // TODO: Prettyprinted output.
System.out.format(" =======> %.2f / %.2f (%dk)\n", message
.getSerializedSize() / 1024.0, debug_bytes / 1024 / 1024.0,
total_entities / 1000);
// if (message.getSerializedSize() > 1000000)
// System.out.println(message);
try {
output.write(FileBlock.newInstance("OSMData", message
.toByteString(), null));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new Error(e);
} finally {
batch_size = 0;
groups.clear();
}
// System.out.format("\n");
}
/** Convert from a degrees represented as a double into the serialized offset in nanodegrees.. */
public long mapRawDegrees(double degrees) {
return (long) ((degrees / .000000001));
}
/** Convert from a degrees represented as a double into the serialized offset. */
public int mapDegrees(double degrees) {
return (int) ((degrees / .0000001) / (granularity / 100));
}
}

View file

@ -1,926 +0,0 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: fileformat.proto
package crosby.binary;
public final class Fileformat {
private Fileformat() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
}
public static final class Blob extends
com.google.protobuf.GeneratedMessage {
// Use Blob.newBuilder() to construct.
private Blob() {
initFields();
}
private Blob(boolean noInit) {}
private static final Blob defaultInstance;
public static Blob getDefaultInstance() {
return defaultInstance;
}
@Override
public Blob getDefaultInstanceForType() {
return defaultInstance;
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return crosby.binary.Fileformat.internal_static_Blob_descriptor;
}
@Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return crosby.binary.Fileformat.internal_static_Blob_fieldAccessorTable;
}
// optional bytes raw = 1;
public static final int RAW_FIELD_NUMBER = 1;
private boolean hasRaw;
private com.google.protobuf.ByteString raw_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasRaw() { return hasRaw; }
public com.google.protobuf.ByteString getRaw() { return raw_; }
// optional int32 raw_size = 2;
public static final int RAW_SIZE_FIELD_NUMBER = 2;
private boolean hasRawSize;
private int rawSize_ = 0;
public boolean hasRawSize() { return hasRawSize; }
public int getRawSize() { return rawSize_; }
// optional bytes zlib_data = 3;
public static final int ZLIB_DATA_FIELD_NUMBER = 3;
private boolean hasZlibData;
private com.google.protobuf.ByteString zlibData_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasZlibData() { return hasZlibData; }
public com.google.protobuf.ByteString getZlibData() { return zlibData_; }
// optional bytes lzma_data = 4;
public static final int LZMA_DATA_FIELD_NUMBER = 4;
private boolean hasLzmaData;
private com.google.protobuf.ByteString lzmaData_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasLzmaData() { return hasLzmaData; }
public com.google.protobuf.ByteString getLzmaData() { return lzmaData_; }
// optional bytes bzip2_data = 5;
public static final int BZIP2_DATA_FIELD_NUMBER = 5;
private boolean hasBzip2Data;
private com.google.protobuf.ByteString bzip2Data_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasBzip2Data() { return hasBzip2Data; }
public com.google.protobuf.ByteString getBzip2Data() { return bzip2Data_; }
private void initFields() {
}
@Override
public final boolean isInitialized() {
return true;
}
@Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasRaw()) {
output.writeBytes(1, getRaw());
}
if (hasRawSize()) {
output.writeInt32(2, getRawSize());
}
if (hasZlibData()) {
output.writeBytes(3, getZlibData());
}
if (hasLzmaData()) {
output.writeBytes(4, getLzmaData());
}
if (hasBzip2Data()) {
output.writeBytes(5, getBzip2Data());
}
getUnknownFields().writeTo(output);
}
private int memoizedSerializedSize = -1;
@Override
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasRaw()) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getRaw());
}
if (hasRawSize()) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, getRawSize());
}
if (hasZlibData()) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(3, getZlibData());
}
if (hasLzmaData()) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(4, getLzmaData());
}
if (hasBzip2Data()) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(5, getBzip2Data());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
public static crosby.binary.Fileformat.Blob parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.Blob parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static crosby.binary.Fileformat.Blob parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static crosby.binary.Fileformat.Blob parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static crosby.binary.Fileformat.Blob parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
@Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(crosby.binary.Fileformat.Blob prototype) {
return newBuilder().mergeFrom(prototype);
}
@Override
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> {
private crosby.binary.Fileformat.Blob result;
// Construct using crosby.binary.Fileformat.Blob.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new crosby.binary.Fileformat.Blob();
return builder;
}
@Override
protected crosby.binary.Fileformat.Blob internalGetResult() {
return result;
}
@Override
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new crosby.binary.Fileformat.Blob();
return this;
}
@Override
public Builder clone() {
return create().mergeFrom(result);
}
@Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return crosby.binary.Fileformat.Blob.getDescriptor();
}
@Override
public crosby.binary.Fileformat.Blob getDefaultInstanceForType() {
return crosby.binary.Fileformat.Blob.getDefaultInstance();
}
@Override
public boolean isInitialized() {
return result.isInitialized();
}
@Override
public crosby.binary.Fileformat.Blob build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private crosby.binary.Fileformat.Blob buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
@Override
public crosby.binary.Fileformat.Blob buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
crosby.binary.Fileformat.Blob returnMe = result;
result = null;
return returnMe;
}
@Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof crosby.binary.Fileformat.Blob) {
return mergeFrom((crosby.binary.Fileformat.Blob)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(crosby.binary.Fileformat.Blob other) {
if (other == crosby.binary.Fileformat.Blob.getDefaultInstance()) return this;
if (other.hasRaw()) {
setRaw(other.getRaw());
}
if (other.hasRawSize()) {
setRawSize(other.getRawSize());
}
if (other.hasZlibData()) {
setZlibData(other.getZlibData());
}
if (other.hasLzmaData()) {
setLzmaData(other.getLzmaData());
}
if (other.hasBzip2Data()) {
setBzip2Data(other.getBzip2Data());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder(
this.getUnknownFields());
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
this.setUnknownFields(unknownFields.build());
return this;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
this.setUnknownFields(unknownFields.build());
return this;
}
break;
}
case 10: {
setRaw(input.readBytes());
break;
}
case 16: {
setRawSize(input.readInt32());
break;
}
case 26: {
setZlibData(input.readBytes());
break;
}
case 34: {
setLzmaData(input.readBytes());
break;
}
case 42: {
setBzip2Data(input.readBytes());
break;
}
}
}
}
// optional bytes raw = 1;
public boolean hasRaw() {
return result.hasRaw();
}
public com.google.protobuf.ByteString getRaw() {
return result.getRaw();
}
public Builder setRaw(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
result.hasRaw = true;
result.raw_ = value;
return this;
}
public Builder clearRaw() {
result.hasRaw = false;
result.raw_ = getDefaultInstance().getRaw();
return this;
}
// optional int32 raw_size = 2;
public boolean hasRawSize() {
return result.hasRawSize();
}
public int getRawSize() {
return result.getRawSize();
}
public Builder setRawSize(int value) {
result.hasRawSize = true;
result.rawSize_ = value;
return this;
}
public Builder clearRawSize() {
result.hasRawSize = false;
result.rawSize_ = 0;
return this;
}
// optional bytes zlib_data = 3;
public boolean hasZlibData() {
return result.hasZlibData();
}
public com.google.protobuf.ByteString getZlibData() {
return result.getZlibData();
}
public Builder setZlibData(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
result.hasZlibData = true;
result.zlibData_ = value;
return this;
}
public Builder clearZlibData() {
result.hasZlibData = false;
result.zlibData_ = getDefaultInstance().getZlibData();
return this;
}
// optional bytes lzma_data = 4;
public boolean hasLzmaData() {
return result.hasLzmaData();
}
public com.google.protobuf.ByteString getLzmaData() {
return result.getLzmaData();
}
public Builder setLzmaData(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
result.hasLzmaData = true;
result.lzmaData_ = value;
return this;
}
public Builder clearLzmaData() {
result.hasLzmaData = false;
result.lzmaData_ = getDefaultInstance().getLzmaData();
return this;
}
// optional bytes bzip2_data = 5;
public boolean hasBzip2Data() {
return result.hasBzip2Data();
}
public com.google.protobuf.ByteString getBzip2Data() {
return result.getBzip2Data();
}
public Builder setBzip2Data(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
result.hasBzip2Data = true;
result.bzip2Data_ = value;
return this;
}
public Builder clearBzip2Data() {
result.hasBzip2Data = false;
result.bzip2Data_ = getDefaultInstance().getBzip2Data();
return this;
}
// @@protoc_insertion_point(builder_scope:Blob)
}
static {
defaultInstance = new Blob(true);
crosby.binary.Fileformat.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:Blob)
}
public static final class BlockHeader extends
com.google.protobuf.GeneratedMessage {
// Use BlockHeader.newBuilder() to construct.
private BlockHeader() {
initFields();
}
private BlockHeader(boolean noInit) {}
private static final BlockHeader defaultInstance;
public static BlockHeader getDefaultInstance() {
return defaultInstance;
}
@Override
public BlockHeader getDefaultInstanceForType() {
return defaultInstance;
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return crosby.binary.Fileformat.internal_static_BlockHeader_descriptor;
}
@Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return crosby.binary.Fileformat.internal_static_BlockHeader_fieldAccessorTable;
}
// required string type = 1;
public static final int TYPE_FIELD_NUMBER = 1;
private boolean hasType;
private java.lang.String type_ = "";
public boolean hasType() { return hasType; }
public java.lang.String getType() { return type_; }
// optional bytes indexdata = 2;
public static final int INDEXDATA_FIELD_NUMBER = 2;
private boolean hasIndexdata;
private com.google.protobuf.ByteString indexdata_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasIndexdata() { return hasIndexdata; }
public com.google.protobuf.ByteString getIndexdata() { return indexdata_; }
// required int32 datasize = 3;
public static final int DATASIZE_FIELD_NUMBER = 3;
private boolean hasDatasize;
private int datasize_ = 0;
public boolean hasDatasize() { return hasDatasize; }
public int getDatasize() { return datasize_; }
private void initFields() {
}
@Override
public final boolean isInitialized() {
if (!hasType) return false;
if (!hasDatasize) return false;
return true;
}
@Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasType()) {
output.writeString(1, getType());
}
if (hasIndexdata()) {
output.writeBytes(2, getIndexdata());
}
if (hasDatasize()) {
output.writeInt32(3, getDatasize());
}
getUnknownFields().writeTo(output);
}
private int memoizedSerializedSize = -1;
@Override
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasType()) {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(1, getType());
}
if (hasIndexdata()) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(2, getIndexdata());
}
if (hasDatasize()) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, getDatasize());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static crosby.binary.Fileformat.BlockHeader parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static crosby.binary.Fileformat.BlockHeader parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
@Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(crosby.binary.Fileformat.BlockHeader prototype) {
return newBuilder().mergeFrom(prototype);
}
@Override
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> {
private crosby.binary.Fileformat.BlockHeader result;
// Construct using crosby.binary.Fileformat.BlockHeader.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new crosby.binary.Fileformat.BlockHeader();
return builder;
}
@Override
protected crosby.binary.Fileformat.BlockHeader internalGetResult() {
return result;
}
@Override
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new crosby.binary.Fileformat.BlockHeader();
return this;
}
@Override
public Builder clone() {
return create().mergeFrom(result);
}
@Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return crosby.binary.Fileformat.BlockHeader.getDescriptor();
}
@Override
public crosby.binary.Fileformat.BlockHeader getDefaultInstanceForType() {
return crosby.binary.Fileformat.BlockHeader.getDefaultInstance();
}
@Override
public boolean isInitialized() {
return result.isInitialized();
}
@Override
public crosby.binary.Fileformat.BlockHeader build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private crosby.binary.Fileformat.BlockHeader buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
@Override
public crosby.binary.Fileformat.BlockHeader buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
crosby.binary.Fileformat.BlockHeader returnMe = result;
result = null;
return returnMe;
}
@Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof crosby.binary.Fileformat.BlockHeader) {
return mergeFrom((crosby.binary.Fileformat.BlockHeader)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(crosby.binary.Fileformat.BlockHeader other) {
if (other == crosby.binary.Fileformat.BlockHeader.getDefaultInstance()) return this;
if (other.hasType()) {
setType(other.getType());
}
if (other.hasIndexdata()) {
setIndexdata(other.getIndexdata());
}
if (other.hasDatasize()) {
setDatasize(other.getDatasize());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder(
this.getUnknownFields());
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
this.setUnknownFields(unknownFields.build());
return this;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
this.setUnknownFields(unknownFields.build());
return this;
}
break;
}
case 10: {
setType(input.readString());
break;
}
case 18: {
setIndexdata(input.readBytes());
break;
}
case 24: {
setDatasize(input.readInt32());
break;
}
}
}
}
// required string type = 1;
public boolean hasType() {
return result.hasType();
}
public java.lang.String getType() {
return result.getType();
}
public Builder setType(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
result.hasType = true;
result.type_ = value;
return this;
}
public Builder clearType() {
result.hasType = false;
result.type_ = getDefaultInstance().getType();
return this;
}
// optional bytes indexdata = 2;
public boolean hasIndexdata() {
return result.hasIndexdata();
}
public com.google.protobuf.ByteString getIndexdata() {
return result.getIndexdata();
}
public Builder setIndexdata(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
result.hasIndexdata = true;
result.indexdata_ = value;
return this;
}
public Builder clearIndexdata() {
result.hasIndexdata = false;
result.indexdata_ = getDefaultInstance().getIndexdata();
return this;
}
// required int32 datasize = 3;
public boolean hasDatasize() {
return result.hasDatasize();
}
public int getDatasize() {
return result.getDatasize();
}
public Builder setDatasize(int value) {
result.hasDatasize = true;
result.datasize_ = value;
return this;
}
public Builder clearDatasize() {
result.hasDatasize = false;
result.datasize_ = 0;
return this;
}
// @@protoc_insertion_point(builder_scope:BlockHeader)
}
static {
defaultInstance = new BlockHeader(true);
crosby.binary.Fileformat.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:BlockHeader)
}
private static com.google.protobuf.Descriptors.Descriptor
internal_static_Blob_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_Blob_fieldAccessorTable;
private static com.google.protobuf.Descriptors.Descriptor
internal_static_BlockHeader_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_BlockHeader_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\020fileformat.proto\"_\n\004Blob\022\013\n\003raw\030\001 \001(\014\022" +
"\020\n\010raw_size\030\002 \001(\005\022\021\n\tzlib_data\030\003 \001(\014\022\021\n\t" +
"lzma_data\030\004 \001(\014\022\022\n\nbzip2_data\030\005 \001(\014\"@\n\013B" +
"lockHeader\022\014\n\004type\030\001 \002(\t\022\021\n\tindexdata\030\002 " +
"\001(\014\022\020\n\010datasize\030\003 \002(\005B\017\n\rcrosby.binary"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@Override
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
internal_static_Blob_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_Blob_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_Blob_descriptor,
new java.lang.String[] { "Raw", "RawSize", "ZlibData", "LzmaData", "Bzip2Data", },
crosby.binary.Fileformat.Blob.class,
crosby.binary.Fileformat.Blob.Builder.class);
internal_static_BlockHeader_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_BlockHeader_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_BlockHeader_descriptor,
new java.lang.String[] { "Type", "Indexdata", "Datasize", },
crosby.binary.Fileformat.BlockHeader.class,
crosby.binary.Fileformat.BlockHeader.Builder.class);
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
}
public static void internalForceInit() {}
// @@protoc_insertion_point(outer_class_scope)
}

File diff suppressed because it is too large Load diff

View file

@ -1,86 +0,0 @@
package crosby.binary;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import com.google.protobuf.ByteString;
/**
* Class for mapping a set of strings to integers, giving frequently occuring
* strings small integers.
*/
public class StringTable {
public StringTable() {
clear();
}
private HashMap<String, Integer> counts;
private HashMap<String, Integer> stringmap;
private String set[];
public void incr(String s) {
if (counts.containsKey(s)) {
counts.put(s, new Integer(counts.get(s).intValue() + 1));
} else {
counts.put(s, new Integer(1));
}
}
/** After the stringtable has been built, return the offset of a string in it.
*
* Note, value '0' is reserved for use as a delimiter and will not be returned.
* @param s
* @return
*/
public int getIndex(String s) {
return stringmap.get(s).intValue();
}
public void finish() {
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(final String s1, String s2) {
int diff = counts.get(s2) - counts.get(s1);
return diff;
}
};
set = counts.keySet().toArray(new String[0]);
if (set.length > 0) {
// Sort based on the frequency.
Arrays.sort(set, comparator);
// Each group of keys that serializes to the same number of bytes is
// sorted lexiconographically.
// to maximize deflate compression.
// Don't sort the first array. There's not likely to be much benefit, and we want frequent values to be small.
//Arrays.sort(set, Math.min(0, set.length-1), Math.min(1 << 7, set.length-1));
Arrays.sort(set, Math.min(1 << 7, set.length-1), Math.min(1 << 14,
set.length-1));
Arrays.sort(set, Math.min(1 << 14, set.length-1), Math.min(1 << 21,
set.length-1), comparator);
}
stringmap = new HashMap<String, Integer>(2 * set.length);
for (int i = 0; i < set.length; i++) {
stringmap.put(set[i], new Integer(i+1)); // Index 0 is reserved for use as a delimiter.
}
counts = null;
}
public void clear() {
counts = new HashMap<String, Integer>(100);
stringmap = null;
set = null;
}
public Osmformat.StringTable.Builder serialize() {
Osmformat.StringTable.Builder builder = Osmformat.StringTable
.newBuilder();
builder.addS(ByteString.copyFromUtf8("")); // Add a unused string at offset 0 which is used as a delimiter.
for (int i = 0; i < set.length; i++)
builder.addS(ByteString.copyFromUtf8(set[i]));
return builder;
}
}

View file

@ -1,26 +0,0 @@
package crosby.binary.file;
import java.io.IOException;
import java.io.InputStream;
public class BlockInputStream {
// TODO: Should be seekable input stream!
public BlockInputStream(InputStream input, BlockReaderAdapter adaptor) {
this.input = input;
this.adaptor = adaptor;
}
public void process() throws IOException {
while (input.available() > 0) {
FileBlock.process(input, adaptor);
}
adaptor.complete();
}
public void close() throws IOException {
input.close();
}
InputStream input;
BlockReaderAdapter adaptor;
}

View file

@ -1,58 +0,0 @@
package crosby.binary.file;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class BlockOutputStream {
public enum CompressFlags {
NONE, DEFLATE
}
public BlockOutputStream(OutputStream output) {
this.outwrite = new DataOutputStream(output);
this.compression = CompressFlags.DEFLATE;
}
public void setCompress(CompressFlags flag) {
compression = flag;
}
public void setCompress(String s) {
if (s.equals("none"))
compression = CompressFlags.NONE;
else if (s.equals("deflate"))
compression = CompressFlags.DEFLATE;
else
throw new Error("Unknown compression type: " + s);
}
/** Write a block with the stream's default compression flag */
public void write(FileBlock block) throws IOException {
this.write(block, compression);
}
/** Write a specific block with a specific compression flags */
public void write(FileBlock block, CompressFlags compression)
throws IOException {
FileBlockPosition ref = block.writeTo(outwrite, compression);
writtenblocks.add(ref);
}
public void flush() throws IOException {
outwrite.flush();
}
public void close() throws IOException {
outwrite.flush();
outwrite.close();
}
OutputStream outwrite;
List<FileBlockPosition> writtenblocks = new ArrayList<FileBlockPosition>();
CompressFlags compression;
}

View file

@ -1,23 +0,0 @@
package crosby.binary.file;
/** An adaptor that receives blocks from an input stream */
public interface BlockReaderAdapter {
/**
* Does the reader understand this block? Does it want the data in it?
*
* A reference contains the metadata about a block and can saved --- or
* stored ---- for future random access. However, during a strea read of the
* file, does the user want this block?
*
* handleBlock will be called on all blocks that are not skipped, in file
* order.
*
* */
boolean skipBlock(FileBlockPosition message);
/** Called with the data in the block. */
void handleBlock(FileBlock message);
/** Called when the file is fully read. */
void complete();
}

View file

@ -1,127 +0,0 @@
package crosby.binary.file;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.Deflater;
import com.google.protobuf.ByteString;
import crosby.binary.Fileformat;
import crosby.binary.Fileformat.BlockHeader;
import crosby.binary.file.BlockOutputStream.CompressFlags;
/** A full fileblock object contains both the metadata and data of a fileblock */
public class FileBlock extends FileBlockBase {
/** Contains the contents of a block for use or further processing */
ByteString data; // serialized Format.Blob
/** Don't be noisy unless the warning occurs somewhat often */
static int warncount = 0;
private FileBlock(String type, ByteString blob, ByteString indexdata) {
super(type, indexdata);
this.data = blob;
}
public static FileBlock newInstance(String type, ByteString blob,
ByteString indexdata) {
if (blob != null && blob.size() > MAX_BODY_SIZE/2) {
System.err.println("Warning: Fileblock has body size too large and may be considered corrupt");
if (blob != null && blob.size() > MAX_BODY_SIZE-1024*1024) {
throw new Error("This file has too many entities in a block. Parsers will reject it.");
}
}
if (indexdata != null && indexdata.size() > MAX_HEADER_SIZE/2) {
System.err.println("Warning: Fileblock has indexdata too large and may be considered corrupt");
if (indexdata != null && indexdata.size() > MAX_HEADER_SIZE-512) {
throw new Error("This file header is too large. Parsers will reject it.");
}
}
return new FileBlock(type, blob, indexdata);
}
protected void deflateInto(crosby.binary.Fileformat.Blob.Builder blobbuilder) {
int size = data.size();
Deflater deflater = new Deflater();
deflater.setInput(data.toByteArray());
deflater.finish();
byte out[] = new byte[size];
deflater.deflate(out);
if (!deflater.finished()) {
// Buffer wasn't long enough. Be noisy.
++warncount;
if (warncount > 10 && warncount%100 == 0)
System.out.println("Compressed buffers are too short, causing extra copy");
int newLength = size + size / 64 + 16;
byte[] copy = new byte[newLength];
System.arraycopy(out, 0, copy, 0, Math.min(out.length, newLength));
out = copy;
deflater.deflate(out, deflater.getTotalOut(), out.length - deflater.getTotalOut());
if (!deflater.finished()) {
throw new Error("Internal error in compressor");
}
}
ByteString compressed = ByteString.copyFrom(out, 0, deflater
.getTotalOut());
blobbuilder.setZlibData(compressed);
deflater.end();
}
public FileBlockPosition writeTo(OutputStream outwrite, CompressFlags flags)
throws IOException {
BlockHeader.Builder builder = Fileformat.BlockHeader
.newBuilder();
if (indexdata != null)
builder.setIndexdata(indexdata);
builder.setType(type);
Fileformat.Blob.Builder blobbuilder = Fileformat.Blob.newBuilder();
if (flags == CompressFlags.NONE) {
blobbuilder.setRaw(data);
} else {
blobbuilder.setRawSize(data.size());
if (flags == CompressFlags.DEFLATE)
deflateInto(blobbuilder);
else
throw new Error("Compression flag not understood");
}
Fileformat.Blob blob = blobbuilder.build();
builder.setDatasize(blob.getSerializedSize());
Fileformat.BlockHeader message = builder.build();
int size = message.getSerializedSize();
// System.out.format("Outputed header size %d bytes, header of %d bytes, and blob of %d bytes\n",
// size,message.getSerializedSize(),blob.getSerializedSize());
(new DataOutputStream(outwrite)).writeInt(size);
message.writeTo(outwrite);
long offset = -1;
if (outwrite instanceof FileOutputStream)
offset = ((FileOutputStream) outwrite).getChannel().position();
blob.writeTo(outwrite);
return FileBlockPosition.newInstance(this, offset, size);
}
/** Reads or skips a fileblock. */
static void process(InputStream input, BlockReaderAdapter callback)
throws IOException {
FileBlockHead fileblock = FileBlockHead.readHead(input);
if (callback.skipBlock(fileblock)) {
// System.out.format("Attempt to skip %d bytes\n",header.getDatasize());
fileblock.skipContents(input);
} else {
callback.handleBlock(fileblock.readContents(input));
}
}
public ByteString getData() {
return data;
}
}

View file

@ -1,41 +0,0 @@
package crosby.binary.file;
import com.google.protobuf.ByteString;
/**
* Base class that contains the metadata about a fileblock.
*
* Subclasses of this include additional fields, such as byte offsets that let a
* fileblock be read in a random-access fashion, or the data itself.
*
* @author crosby
*
*/
public class FileBlockBase {
/** If a block header is bigger than this, fail. We use excessively large header size as an indication of corrupt files */
static final int MAX_HEADER_SIZE = 64*1024;
/** If a block's size is bigger than this, fail. We use excessively large block sizes as an indication of corrupt files */
static final int MAX_BODY_SIZE = 32*1024*1024;
protected FileBlockBase(String type, ByteString indexdata) {
this.type = type;
this.indexdata = indexdata;
}
/** Identifies the type of the data within a block */
protected final String type;
/**
* Block metadata, stored in the index block and as a prefix for every
* block.
*/
protected final ByteString indexdata;
public String getType() {
return type;
}
public ByteString getIndexData() {
return indexdata;
}
}

View file

@ -1,80 +0,0 @@
package crosby.binary.file;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import com.google.protobuf.ByteString;
import crosby.binary.Fileformat;
/**
* Intermediate representation of the header of a fileblock when a set of
* fileblocks is read as in a stream. The data in the fileblock must be either
* skipped (where the returned value is a reference to the fileblock) or parsed.
*
* @author crosby
*
*/
public class FileBlockHead extends FileBlockReference {
protected FileBlockHead(String type, ByteString indexdata) {
super(type, indexdata);
}
/**
* Read the header. After reading the header, either the contents must be
* skipped or read
*/
static FileBlockHead readHead(InputStream input) throws IOException {
DataInputStream datinput = new DataInputStream(input);
int headersize = datinput.readInt();
// System.out.format("Header size %d %x\n",headersize,headersize);
if (headersize > MAX_HEADER_SIZE) {
throw new FileFormatException("Unexpectedly long header "+MAX_HEADER_SIZE+ " bytes. Possibly corrupt file.");
}
byte buf[] = new byte[headersize];
datinput.readFully(buf);
// System.out.format("Read buffer for header of %d bytes\n",buf.length);
Fileformat.BlockHeader header = Fileformat.BlockHeader
.parseFrom(buf);
FileBlockHead fileblock = new FileBlockHead(header.getType(), header
.getIndexdata());
fileblock.datasize = header.getDatasize();
if (header.getDatasize() > MAX_BODY_SIZE) {
throw new FileFormatException("Unexpectedly long body "+MAX_BODY_SIZE+ " bytes. Possibly corrupt file.");
}
fileblock.input = input;
if (input instanceof FileInputStream)
fileblock.data_offset = ((FileInputStream) input).getChannel()
.position();
return fileblock;
}
/**
* Assumes the stream is positioned over at the start of the data, skip over
* it.
*
* @throws IOException
*/
void skipContents(InputStream input) throws IOException {
if (input.skip(getDatasize()) != getDatasize())
assert false : "SHORT READ";
}
/**
* Assumes the stream is positioned over at the start of the data, read it
* and return the complete FileBlock
*
* @throws IOException
*/
FileBlock readContents(InputStream input) throws IOException {
DataInputStream datinput = new DataInputStream(input);
byte buf[] = new byte[getDatasize()];
datinput.readFully(buf);
return parseData(buf);
}
}

View file

@ -1,95 +0,0 @@
package crosby.binary.file;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import crosby.binary.Fileformat;
/**
* Stores the position in the stream of a fileblock so that it can be easily
* read in a random-access fashion.
*
* We can turn this into a 'real' block by appropriately seeking into the file
* and doing a 'read'.
*
* */
public class FileBlockPosition extends FileBlockBase {
protected FileBlockPosition(String type, ByteString indexdata) {
super(type, indexdata);
}
/** Parse out and decompress the data part of a fileblock helper function. */
FileBlock parseData(byte buf[]) throws InvalidProtocolBufferException {
FileBlock out = FileBlock.newInstance(type, null, indexdata);
Fileformat.Blob blob = Fileformat.Blob.parseFrom(buf);
if (blob.hasRaw()) {
out.data = blob.getRaw();
} else if (blob.hasZlibData()) {
byte buf2[] = new byte[blob.getRawSize()];
Inflater decompresser = new Inflater();
decompresser.setInput(blob.getZlibData().toByteArray());
// decompresser.getRemaining();
try {
decompresser.inflate(buf2);
} catch (DataFormatException e) {
e.printStackTrace();
throw new Error(e);
}
assert (decompresser.finished());
decompresser.end();
out.data = ByteString.copyFrom(buf2);
}
return out;
}
public int getDatasize() {
return datasize;
}
/*
* Given any form of fileblock and an offset/length value, return a
* reference that can be used to dereference and read the contents.
*/
static FileBlockPosition newInstance(FileBlockBase base, long offset,
int length) {
FileBlockPosition out = new FileBlockPosition(base.type, base.indexdata);
out.datasize = length;
out.data_offset = offset;
return out;
}
public FileBlock read(InputStream input) throws IOException {
if (input instanceof FileInputStream) {
((FileInputStream) input).getChannel().position(data_offset);
byte buf[] = new byte[getDatasize()];
(new DataInputStream(input)).readFully(buf);
return parseData(buf);
} else {
throw new Error("Random access binary reads require seekability");
}
}
/**
* TODO: Convert this reference into a serialized representation that can be
* stored.
*/
public ByteString serialize() {
throw new Error("TODO");
}
/** TODO: Parse a serialized representation of this block reference */
static FileBlockPosition parseFrom(ByteString b) {
throw new Error("TODO");
}
protected int datasize;
/** Offset into the file of the data part of the block */
long data_offset;
}

View file

@ -1,37 +0,0 @@
package crosby.binary.file;
import java.io.IOException;
import java.io.InputStream;
import com.google.protobuf.ByteString;
/**
* A FileBlockPosition that remembers what file this is so that it can simply be
* dereferenced
*/
public class FileBlockReference extends FileBlockPosition {
/**
* Convenience cache for storing the input this reference is contained
* within so that it can be cached
*/
protected InputStream input;
protected FileBlockReference(String type, ByteString indexdata) {
super(type, indexdata);
}
public FileBlock read() throws IOException {
return read(input);
}
static FileBlockPosition newInstance(FileBlockBase base, InputStream input,
long offset, int length) {
FileBlockReference out = new FileBlockReference(base.type,
base.indexdata);
out.datasize = length;
out.data_offset = offset;
out.input = input;
return out;
}
}

View file

@ -1,16 +0,0 @@
package crosby.binary.file;
import java.io.IOException;
public class FileFormatException extends IOException {
public FileFormatException(String string) {
super(string);
}
/**
*
*/
private static final long serialVersionUID = -8128010128748910923L;
}

View file

@ -1,28 +0,0 @@
option java_package = "crosby.binary";
//protoc --java_out=../.. fileformat.proto
//
// STORAGE LAYER: Storing primitives.
//
message Blob {
optional bytes raw = 1; // No compression
optional int32 raw_size = 2; // When compressed, the uncompressed size
// Possible compressed versions of the data.
optional bytes zlib_data = 3;
optional bytes lzma_data = 4;
optional bytes bzip2_data = 5;
}
/* A file contains an sequence of fileblock headers, each prefixed by
their length, followed by a data block containing the actual data.
types staring with a "_" are reserved.
*/
message BlockHeader {
required string type = 1;
optional bytes indexdata = 2;
required int32 datasize = 3;
}

View file

@ -1,22 +0,0 @@
package net.osmand;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class MapCreatorVersion {
public static String APP_VERSION = "1.1.0"; //$NON-NLS-1$
public static final String APP_DESCRIPTION = "alpha"; //$NON-NLS-1$
public static final String APP_MAP_CREATOR_NAME = "OsmAndMapCreator"; //$NON-NLS-1$
public static final String APP_MAP_CREATOR_VERSION = APP_MAP_CREATOR_NAME + " " + APP_VERSION; //$NON-NLS-1$
public static final String APP_MAP_CREATOR_FULL_NAME = APP_MAP_CREATOR_NAME + " " + APP_VERSION + " " +APP_DESCRIPTION; //$NON-NLS-1$ //$NON-NLS-2$
public static String getVersionAsURLParam() {
try {
return "osmandver=" + URLEncoder.encode(APP_VERSION + " " + APP_DESCRIPTION, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
}
}

View file

@ -1,827 +0,0 @@
package net.osmand;
/******************************************************************************
*
* SunriseSunset.java
*
*******************************************************************************
*
* Java Class: SunriseSunset
*
* This Java class is part of a collection of classes developed for the
* reading and processing of oceanographic and meterological data collected
* since 1970 by environmental buoys and stations. This dataset is
* maintained by the National Oceanographic Data Center and is publicly
* available. These Java classes were written for the US Environmental
* Protection Agency's National Exposure Research Laboratory under Contract
* No. GS-10F-0073K with Neptune and Company of Los Alamos, New Mexico.
*
* Purpose:
*
* This Java class performs calculations to determine the time of
* sunrise and sunset given lat, long, and date.
*
* Inputs:
*
* Latitude, longitude, date/time, and time zone.
*
* Outputs:
*
* Local time of sunrise and sunset as calculated by the
* program.
* If no sunrise or no sunset occurs, or if the sun is up all day
* or down all day, appropriate boolean values are set.
* A boolean is provided to identify if the time provided is during the day.
*
* The above values are accessed by the following methods:
*
* Date getSunrise() returns date/time of sunrise
* Date getSunset() returns date/time of sunset
* boolean isSunrise() returns true if there was a sunrise, else false
* boolean isSunset() returns true if there was a sunset, else false
* boolean isSunUp() returns true if sun is up all day, else false
* boolean isSunDown() returns true if sun is down all day, else false
* boolean isDaytime() returns true if sun is up at the time
* specified, else false
*
* Required classes from the Java library:
*
* java.util.Date
* java.text.SimpleDateFormat
* java.text.ParseException;
* java.math.BigDecimal;
*
* Package of which this class is a member:
*
* default
*
* Known limitations:
*
* It is assumed that the data provided are within value ranges
* (i.e. latitude between -90 and +90, longitude between 0 and 360,
* a valid date, and time zone between -14 and +14.
*
* Compatibility:
*
* Java 1.1.8
*
* References:
*
* The mathematical algorithms used in this program are patterned
* after those debveloped by Roger Sinnott in his BASIC program,
* SUNUP.BAS, published in Sky & Telescope magazine:
* Sinnott, Roger W. "Sunrise and Sunset: A Challenge"
* Sky & Telescope, August, 1994 p.84-85
*
* The following is a cross-index of variables used in SUNUP.BAS.
* A single definition from multiple reuse of variable names in
* SUNUP.BAS was clarified with various definitions in this program.
*
* SUNUP.BAS this class
*
* A dfA
* A(2) dfAA1, dfAA2
* A0 dfA0
* A2 dfA2
* A5 dfA5
* AZ Not used
* C dfCosLat
* C0 dfC0
* D iDay
* D(2) dfDD1, dfDD2
* D0 dfD0
* D1 dfD1
* D2 dfD2
* D5 dfD5
* D7 Not used
* DA dfDA
* DD dfDD
* G bGregorian, dfGG
* H dfTimeZone
* H0 dfH0
* H1 dfH1
* H2 dfH2
* H3 dfHourRise, dfHourSet
* H7 Not used
* J dfJ
* J3 dfJ3
* K1 dfK1
* L dfLL
* L0 dfL0
* L2 dfL2
* L5 dfLon
* M iMonth
* M3 dfMinRise, dfMinSet
* N7 Not used
* P dfP
* S iSign, dfSinLat, dfSS
* T dfT
* T0 dfT0
* T3 not used
* TT dfTT
* U dfUU
* V dfVV
* V0 dfV0
* V1 dfV1
* V2 dfV2
* W dfWW
* Y iYear
* Z dfZenith
* Z0 dfTimeZone
*
*
* Author/Company:
*
* JDT: John Tauxe, Neptune and Company
* JMG: Jo Marie Green
*
* Change log:
*
* date ver by description of change
* _________ _____ ___ ______________________________________________
* 5 Jan 01 0.006 JDT Excised from ssapp.java v. 0.005.
* 11 Jan 01 0.007 JDT Minor modifications to comments based on
* material from Sinnott, 1994.
* 7 Feb 01 0.008 JDT Fixed backwards time zone. The standard is that
* local time zone is specified in hours EAST of
* Greenwich, so that EST would be -5, for example.
* For some reason, SUNUP.BAS does this backwards
* (probably an americocentric perspective) and
* SunriseSunset adopted that convention. Oops.
* So the sign in the math is changed.
* 7 Feb 01 0.009 JDT Well, that threw off the azimuth calculation...
* Removed the azimuth calculations.
* 14 Feb 01 0.010 JDT Added ability to accept a time (HH:mm) in
* dateInput, and decide if that time is daytime
* or nighttime.
* 27 Feb 01 0.011 JDT Added accessor methods in place of having public
* variables to get results.
* 28 Feb 01 0.012 JDT Cleaned up list of imported classes.
* 28 Mar 01 1.10 JDT Final version accompanying deliverable 1b.
* 4 Apr 01 1.11 JDT Moved logic supporting .isDaytime into method.
* Moved calculations out of constructor.
* 01 May 01 1.12 JMG Added 'GMT' designation and testing lines.
* 16 May 01 1.13 JDT Added setLenient( false ) and setTimeZone( tz )
* to dfmtDay, dfmtMonth, and dfmtYear in
* doCalculations.
* 27 Jun 01 1.14 JDT Removed reliance on StationConstants (GMT).
* 13 Aug 01 1.20 JDT Final version accompanying deliverable 1c.
* 6 Sep 01 1.21 JDT Thorough code and comment review.
* 21 Sep 01 1.30 JDT Final version accompanying deliverable 2.
* 17 Dec 01 1.40 JDT Version accompanying final deliverable.
*
*----------------------------------------------------------------------------*/
// Import required classes and packages
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.TimeZone;
/******************************************************************************
* class: SunriseSunset class
*******************************************************************************
*
* This Java class performs calculations to determine the time of
* sunrise and sunset given lat, long, and date.
*
* It is assumed that the data provided are within value ranges
* (i.e. latitude between -90 and +90, longitude between 0 and 360,
* a valid date, and time zone between -14 and +14.
*
*----------------------------------------------------------------------------*/
public class SunriseSunset
{
// Declare and initialize variables
private double dfLat; // latitude from user
private double dfLon; // latitude from user
private Date dateInput; // date/time from user
private double dfTimeZone; // time zone from user
private Date dateSunrise; // date and time of sunrise
private Date dateSunset; // date and time of sunset
private boolean bSunriseToday = false; // flag for sunrise on this date
private boolean bSunsetToday = false; // flag for sunset on this date
private boolean bSunUpAllDay = false; // flag for sun up all day
private boolean bSunDownAllDay = false; // flag for sun down all day
private boolean bDaytime = false; // flag for daytime, given
// hour and min in dateInput
private boolean bSunrise = false; // sunrise during hour checked
private boolean bSunset = false; // sunset during hour checked
private boolean bGregorian = false; // flag for Gregorian calendar
private int iJulian; // Julian day
private int iYear; // year of date of interest
private int iMonth; // month of date of interest
private int iDay; // day of date of interest
private int iCount; // a simple counter
private int iSign; // SUNUP.BAS: S
private double dfHourRise, dfHourSet; // hour of event: SUNUP.BAS H3
private double dfMinRise, dfMinSet; // minute of event: SUNUP.BAS M3
private double dfSinLat, dfCosLat; // sin and cos of latitude
private double dfZenith; // SUNUP.BAS Z: Zenith
// private SimpleDateFormat dfmtDate; // formatting for date alone
private SimpleDateFormat dfmtDateTime; // formatting for date and time
private SimpleDateFormat dfmtYear; // formatting for year
private SimpleDateFormat dfmtMonth; // formatting for month
private SimpleDateFormat dfmtDay; // formatting for day
// Many variables in SUNUP.BAS have undocumented meanings,
// and so are translated rather directly to avoid confusion:
private double dfAA1 = 0, dfAA2 = 0; // SUNUP.BAS A(2)
private double dfDD1 = 0, dfDD2 = 0; // SUNUP.BAS D(2)
private double dfC0; // SUNUP.BAS C0
private double dfK1; // SUNUP.BAS K1
private double dfP; // SUNUP.BAS P
private double dfJ; // SUNUP.BAS J
private double dfJ3; // SUNUP.BAS J3
private double dfA; // SUNUP.BAS A
private double dfA0, dfA2, dfA5; // SUNUP.BAS A0, A2, A5
private double dfD0, dfD1, dfD2, dfD5; // SUNUP.BAS D0, D1, D2, D5
private double dfDA, dfDD; // SUNUP.BAS DA, DD
private double dfH0, dfH1, dfH2; // SUNUP.BAS H0, H1, H2
private double dfL0, dfL2; // SUNUP.BAS L0, L2
private double dfT, dfT0, dfTT; // SUNUP.BAS T, T0, TT
private double dfV0, dfV1, dfV2; // SUNUP.BAS V0, V1, V2
private TimeZone tz = TimeZone.getTimeZone( "GMT" );
private double origTimeZone;
/******************************************************************************
* method: SunriseSunset
*******************************************************************************
*
* Constructor for SunriseSunset class.
*
*----------------------------------------------------------------------------*/
public SunriseSunset(
double dfLatIn, // latitude
double dfLonIn, // longitude
Date dateInputIn, // date
TimeZone tzIn // time zone
)
{
// Calculate internal representation of timezone offset as fraction of hours from GMT
// Our calculations consider offsets to the West as positive, so we must invert
// the signal of the values provided by the standard library
double dfTimeZoneIn = 1.0 * tzIn.getOffset(dateInputIn.getTime()) / 3600000;
// Copy values supplied as agruments to local variables.
dfLat = dfLatIn;
dfLon = dfLonIn;
dateInput = dateInputIn;
dfTimeZone = dfTimeZoneIn;
origTimeZone= dfTimeZoneIn;
// Call the method to do the calculations.
doCalculations();
} // end of class constructor
/******************************************************************************
* method: doCalculations
*******************************************************************************
*
* Method for performing the calculations done in SUNUP.BAS.
*
*----------------------------------------------------------------------------*/
private void doCalculations()
{
try
{
// Break out day, month, and year from date provided.
// (This is necesary for the math algorithms.)
dfmtYear = new SimpleDateFormat( "yyyy" );
dfmtYear.setLenient( false );
dfmtYear.setTimeZone( tz );
dfmtMonth = new SimpleDateFormat( "M" );
dfmtMonth.setLenient( false );
dfmtMonth.setTimeZone( tz );
dfmtDay = new SimpleDateFormat( "d" );
dfmtDay.setLenient( false );
dfmtDay.setTimeZone( tz );
iYear = Integer.parseInt( dfmtYear.format( dateInput ) );
iMonth = Integer.parseInt( dfmtMonth.format( dateInput ) );
iDay = Integer.parseInt( dfmtDay.format( dateInput ) );
// Convert time zone hours to decimal days (SUNUP.BAS line 50)
dfTimeZone = dfTimeZone / 24.0;
// NOTE: (7 Feb 2001) Here is a non-standard part of SUNUP.BAS:
// It (and this algorithm) assumes that the time zone is
// positive west, instead of the standard negative west.
// Classes calling SunriseSunset will be assuming that
// times zones are specified in negative west, so here the
// sign is changed so that the SUNUP algorithm works:
dfTimeZone = -dfTimeZone;
// Convert longitude to fraction (SUNUP.BAS line 50)
dfLon = dfLon / 360.0;
// Convert calendar date to Julian date:
// Check to see if it's later than 1583: Gregorian calendar
// When declared, bGregorian is initialized to false.
// ** Consider making a separate class of this function. **
if( iYear >= 1583 ) bGregorian = true;
// SUNUP.BAS 1210
dfJ = -Math.floor( 7.0 // SUNUP used INT, not floor
* ( Math.floor(
( iMonth + 9.0 )
/ 12.0
) + iYear
) / 4.0
)
// add SUNUP.BAS 1240 and 1250 for G = 0
+ Math.floor( iMonth * 275.0 / 9.0 )
+ iDay
+ 1721027.0
+ iYear * 367.0;
if ( bGregorian )
{
// SUNUP.BAS 1230
if ( ( iMonth - 9.0 ) < 0.0 ) iSign = -1;
else iSign = 1;
dfA = Math.abs( iMonth - 9.0 );
// SUNUP.BAS 1240 and 1250
dfJ3 = -Math.floor(
(
Math.floor(
Math.floor( iYear
+ (double)iSign
* Math.floor( dfA / 7.0 )
)
/ 100.0
) + 1.0
) * 0.75
);
// correct dfJ as in SUNUP.BAS 1240 and 1250 for G = 1
dfJ = dfJ + dfJ3 + 2.0;
}
// SUNUP.BAS 1290
iJulian = (int)dfJ - 1;
// SUNUP.BAS 60 and 70 (see also line 1290)
dfT = (double)iJulian - 2451545.0 + 0.5;
dfTT = dfT / 36525.0 + 1.0; // centuries since 1900
// Calculate local sidereal time at 0h in zone time
// SUNUP.BAS 410 through 460
dfT0 = ( dfT * 8640184.813 / 36525.0
+ 24110.5
+ dfTimeZone * 86636.6
+ dfLon * 86400.0
)
/ 86400.0;
dfT0 = dfT0 - Math.floor( dfT0 ); // NOTE: SUNUP.BAS uses INT()
dfT0 = dfT0 * 2.0 * Math.PI;
// SUNUP.BAS 90
dfT = dfT + dfTimeZone;
// SUNUP.BAS 110: Get Sun's position
for( iCount=0; iCount<=1; iCount++ ) // Loop thru only twice
{
// Calculate Sun's right ascension and declination
// at the start and end of each day.
// SUNUP.BAS 910 - 1160: Fundamental arguments
// from van Flandern and Pulkkinen, 1979
// declare local temporary doubles for calculations
double dfGG; // SUNUP.BAS G
double dfLL; // SUNUP.BAS L
double dfSS; // SUNUP.BAS S
double dfUU; // SUNUP.BAS U
double dfVV; // SUNUP.BAS V
double dfWW; // SUNUP.BAS W
dfLL = 0.779072 + 0.00273790931 * dfT;
dfLL = dfLL - Math.floor( dfLL );
dfLL = dfLL * 2.0 * Math.PI;
dfGG = 0.993126 + 0.0027377785 * dfT;
dfGG = dfGG - Math.floor( dfGG );
dfGG = dfGG * 2.0 * Math.PI;
dfVV = 0.39785 * Math.sin( dfLL )
- 0.01000 * Math.sin( dfLL - dfGG )
+ 0.00333 * Math.sin( dfLL + dfGG )
- 0.00021 * Math.sin( dfLL ) * dfTT;
dfUU = 1
- 0.03349 * Math.cos( dfGG )
- 0.00014 * Math.cos( dfLL * 2.0 )
+ 0.00008 * Math.cos( dfLL );
dfWW = - 0.00010
- 0.04129 * Math.sin( dfLL * 2.0 )
+ 0.03211 * Math.sin( dfGG )
- 0.00104 * Math.sin( 2.0 * dfLL - dfGG )
- 0.00035 * Math.sin( 2.0 * dfLL + dfGG )
- 0.00008 * Math.sin( dfGG ) * dfTT;
// Compute Sun's RA and Dec; SUNUP.BAS 1120 - 1140
dfSS = dfWW / Math.sqrt( dfUU - dfVV * dfVV );
dfA5 = dfLL
+ Math.atan( dfSS / Math.sqrt( 1.0 - dfSS * dfSS ));
dfSS = dfVV / Math.sqrt( dfUU );
dfD5 = Math.atan( dfSS / Math.sqrt( 1 - dfSS * dfSS ));
// Set values and increment t
if ( iCount == 0 ) // SUNUP.BAS 125
{
dfAA1 = dfA5;
dfDD1 = dfD5;
}
else // SUNUP.BAS 145
{
dfAA2 = dfA5;
dfDD2 = dfD5;
}
dfT = dfT + 1.0; // SUNUP.BAS 130
} // end of Get Sun's Position for loop
if ( dfAA2 < dfAA1 ) dfAA2 = dfAA2 + 2.0 * Math.PI;
// SUNUP.BAS 150
dfZenith = Math.PI * 90.833 / 180.0; // SUNUP.BAS 160
dfSinLat = Math.sin( dfLat * Math.PI / 180.0 ); // SUNUP.BAS 170
dfCosLat = Math.cos( dfLat * Math.PI / 180.0 ); // SUNUP.BAS 170
dfA0 = dfAA1; // SUNUP.BAS 190
dfD0 = dfDD1; // SUNUP.BAS 190
dfDA = dfAA2 - dfAA1; // SUNUP.BAS 200
dfDD = dfDD2 - dfDD1; // SUNUP.BAS 200
dfK1 = 15.0 * 1.0027379 * Math.PI / 180.0; // SUNUP.BAS 330
// Initialize sunrise and sunset times, and other variables
// hr and min are set to impossible times to make errors obvious
dfHourRise = 99.0;
dfMinRise = 99.0;
dfHourSet = 99.0;
dfMinSet = 99.0;
dfV0 = 0.0; // initialization implied by absence in SUNUP.BAS
dfV2 = 0.0; // initialization implied by absence in SUNUP.BAS
// Test each hour to see if the Sun crosses the horizon
// and which way it is heading.
for( iCount=0; iCount<24; iCount++ ) // SUNUP.BAS 210
{
double tempA; // SUNUP.BAS A
double tempB; // SUNUP.BAS B
double tempD; // SUNUP.BAS D
double tempE; // SUNUP.BAS E
dfC0 = (double)iCount;
dfP = ( dfC0 + 1.0 ) / 24.0; // SUNUP.BAS 220
dfA2 = dfAA1 + dfP * dfDA; // SUNUP.BAS 230
dfD2 = dfDD1 + dfP * dfDD; // SUNUP.BAS 230
dfL0 = dfT0 + dfC0 * dfK1; // SUNUP.BAS 500
dfL2 = dfL0 + dfK1; // SUNUP.BAS 500
dfH0 = dfL0 - dfA0; // SUNUP.BAS 510
dfH2 = dfL2 - dfA2; // SUNUP.BAS 510
// hour angle at half hour
dfH1 = ( dfH2 + dfH0 ) / 2.0; // SUNUP.BAS 520
// declination at half hour
dfD1 = ( dfD2 + dfD0 ) / 2.0; // SUNUP.BAS 530
// Set value of dfV0 only if this is the first hour,
// otherwise, it will get set to the last dfV2 (SUNUP.BAS 250)
if ( iCount == 0 ) // SUNUP.BAS 550
{
dfV0 = dfSinLat * Math.sin( dfD0 )
+ dfCosLat * Math.cos( dfD0 ) * Math.cos( dfH0 )
- Math.cos( dfZenith ); // SUNUP.BAS 560
}
else
dfV0 = dfV2; // That is, dfV2 from the previous hour.
dfV2 = dfSinLat * Math.sin( dfD2 )
+ dfCosLat * Math.cos( dfD2 ) * Math.cos( dfH2 )
- Math.cos( dfZenith ); // SUNUP.BAS 570
// if dfV0 and dfV2 have the same sign, then proceed to next hr
if (
( dfV0 >= 0.0 && dfV2 >= 0.0 ) // both are positive
|| // or
( dfV0 < 0.0 && dfV2 < 0.0 ) // both are negative
)
{
// Break iteration and proceed to test next hour
dfA0 = dfA2; // SUNUP.BAS 250
dfD0 = dfD2; // SUNUP.BAS 250
continue; // SUNUP.BAS 610
}
dfV1 = dfSinLat * Math.sin( dfD1 )
+ dfCosLat * Math.cos( dfD1 ) * Math.cos( dfH1 )
- Math.cos( dfZenith ); // SUNUP.BAS 590
tempA = 2.0 * dfV2 - 4.0 * dfV1 + 2.0 * dfV0;
// SUNUP.BAS 600
tempB = 4.0 * dfV1 - 3.0 * dfV0 - dfV2; // SUNUP.BAS 600
tempD = tempB * tempB - 4.0 * tempA * dfV0; // SUNUP.BAS 610
if ( tempD < 0.0 )
{
// Break iteration and proceed to test next hour
dfA0 = dfA2; // SUNUP.BAS 250
dfD0 = dfD2; // SUNUP.BAS 250
continue; // SUNUP.BAS 610
}
tempD = Math.sqrt( tempD ); // SUNUP.BAS 620
// Determine occurence of sunrise or sunset.
// Flags to identify occurrence during this day are
// bSunriseToday and bSunsetToday, and are initialized false.
// These are set true only if sunrise or sunset occurs
// at any point in the hourly loop. Never set to false.
// Flags to identify occurrence during this hour:
bSunrise = false; // reset before test
bSunset = false; // reset before test
if ( dfV0 < 0.0 && dfV2 > 0.0 ) // sunrise occurs this hour
{
bSunrise = true; // SUNUP.BAS 640
bSunriseToday = true; // sunrise occurred today
}
if ( dfV0 > 0.0 && dfV2 < 0.0 ) // sunset occurs this hour
{
bSunset = true; // SUNUP.BAS 660
bSunsetToday = true; // sunset occurred today
}
tempE = ( tempD - tempB ) / ( 2.0 * tempA );
if ( tempE > 1.0 || tempE < 0.0 ) // SUNUP.BAS 670, 680
tempE = ( -tempD - tempB ) / ( 2.0 * tempA );
// Set values of hour and minute of sunset or sunrise
// only if sunrise/set occurred this hour.
if ( bSunrise )
{
dfHourRise = Math.floor( dfC0 + tempE + 1.0/120.0 );
dfMinRise = Math.floor(
( dfC0 + tempE + 1.0/120.0
- dfHourRise
)
* 60.0
);
}
if ( bSunset )
{
dfHourSet = Math.floor( dfC0 + tempE + 1.0/120.0 );
dfMinSet = Math.floor(
( dfC0 + tempE + 1.0/120.0
- dfHourSet
)
* 60.0
);
}
// Change settings of variables for next loop
dfA0 = dfA2; // SUNUP.BAS 250
dfD0 = dfD2; // SUNUP.BAS 250
} // end of loop testing each hour for an event
// After having checked all hours, set flags if no rise or set
// bSunUpAllDay and bSundownAllDay are initialized as false
if ( !bSunriseToday && !bSunsetToday )
{
if ( dfV2 < 0.0 )
bSunDownAllDay = true;
else
bSunUpAllDay = true;
}
// Load dateSunrise with data
dfmtDateTime = new SimpleDateFormat( "d M yyyy HH:mm z" );
// Timezone signal is reversed in SunriseSunset class
String tz_signal = origTimeZone <= 0?"-":"+";
double abs_tz = Math.abs(origTimeZone);
NumberFormat formatter = new DecimalFormat("00");
String tz_offset_hours = formatter.format((int)abs_tz);
String tz_offset_minutes = formatter.format((int)(60 * (abs_tz - (int)abs_tz)));
if( bSunriseToday )
{
dateSunrise = dfmtDateTime.parse( iDay
+ " " + iMonth
+ " " + iYear
+ " " + (int)dfHourRise
+ ":" + (int)dfMinRise
+ " GMT"
+ tz_signal + tz_offset_hours
+":" + tz_offset_minutes );
}
// Load dateSunset with data
if( bSunsetToday )
{
dateSunset = dfmtDateTime.parse( iDay
+ " " + iMonth
+ " " + iYear
+ " " + (int)dfHourSet
+ ":" + (int)dfMinSet
+ " GMT"
+ tz_signal + tz_offset_hours
+":" + tz_offset_minutes );
}
} // end of try
// Catch errors
catch( ParseException e )
{
e.printStackTrace();
} // end of catch
}
/******************************************************************************
* method: getSunrise()
*******************************************************************************
*
* Gets the date and time of sunrise. If there is no sunrise, returns null.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public Date getSunrise()
{
if ( bSunriseToday )
return( dateSunrise );
else
return( null );
}
/******************************************************************************
* method: getSunset()
*******************************************************************************
*
* Gets the date and time of sunset. If there is no sunset, returns null.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public Date getSunset()
{
if ( bSunsetToday )
return( dateSunset );
else
return( null );
}
/******************************************************************************
* method: isSunrise()
*******************************************************************************
*
* Returns a boolean identifying if there was a sunrise.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public boolean isSunrise()
{
return( bSunriseToday );
}
/******************************************************************************
* method: isSunset()
*******************************************************************************
*
* Returns a boolean identifying if there was a sunset.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public boolean isSunset()
{
return( bSunsetToday );
}
/******************************************************************************
* method: isSunUp()
*******************************************************************************
*
* Returns a boolean identifying if the sun is up all day.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public boolean isSunUp()
{
return( bSunUpAllDay );
}
/******************************************************************************
* method: isSunDown()
*******************************************************************************
*
* Returns a boolean identifying if the sun is down all day.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public boolean isSunDown()
{
return( bSunDownAllDay );
}
/******************************************************************************
* method: isDaytime()
*******************************************************************************
*
* Returns a boolean identifying if it is daytime at the hour contained in
* the Date object passed to SunriseSunset on construction.
*
* Member of SunriseSunset class
*
* -------------------------------------------------------------------------- */
public boolean isDaytime()
{
// Determine if it is daytime (at sunrise or later)
// or nighttime (at sunset or later) at the location of interest
// but expressed in the time zone requested.
if ( bSunriseToday && bSunsetToday ) // sunrise and sunset
{
if ( dateSunrise.before( dateSunset ) ) // sunrise < sunset
{
if (
(
dateInput.after( dateSunrise )
||
dateInput.equals( dateSunrise )
)
&&
dateInput.before( dateSunset )
)
bDaytime = true;
else
bDaytime = false;
}
else // sunrise comes after sunset (in opposite time zones)
{
if (
(
dateInput.after( dateSunrise )
||
dateInput.equals( dateSunrise )
)
|| // use OR rather than AND
dateInput.before( dateSunset )
)
bDaytime = true;
else
bDaytime = false;
}
}
else if ( bSunUpAllDay ) // sun is up all day
bDaytime = true;
else if ( bSunDownAllDay ) // sun is down all day
bDaytime = false;
else if ( bSunriseToday ) // sunrise but no sunset
{
if ( dateInput.before( dateSunrise ) )
bDaytime = false;
else
bDaytime = true;
}
else if ( bSunsetToday ) // sunset but no sunrise
{
if ( dateInput.before( dateSunset ) )
bDaytime = true;
else
bDaytime = false;
}
else bDaytime = false; // this should never execute
return( bDaytime );
}
} // end of class
/*-----------------------------------------------------------------------------
* end of class
*----------------------------------------------------------------------------*/

View file

@ -1,62 +0,0 @@
package net.osmand;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class TestSunriseSunset {
public static final String MARCH = "05.03.2012";
public static final String AUGUST = "05.08.2012";
public static final String OCTOBER = "05.10.2012";
public static final String DECEMBER = "05.12.2012";
public static final String FEBRUARY = "05.02.2012";
public static final String MAY = "05.05.2012";
public static final String[] DATES = new String[] {MARCH, AUGUST, OCTOBER, DECEMBER, FEBRUARY, MAY};
public static void printSunriseSunset(String date, float lat, float lon, TimeZone tz) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
SimpleDateFormat prt = new SimpleDateFormat("dd.MM.yyyy HH:mm");
prt.setTimeZone(TimeZone.getTimeZone("GMT"));
Date time = sdf.parse(date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
SunriseSunset ss = new SunriseSunset(lat, lon, time, TimeZone.getTimeZone("GMT"));
// Location location = new Location(lat, lon);
// SunriseSunsetCalculator calc = new SunriseSunsetCalculator(location, TimeZone.getTimeZone("GMT"));
System.out.println("Sunrise : " + prt.format(ss.getSunrise()) + " GMT");
// System.out.println("Sunrise : " + prt.format(calc.getOfficialSunriseCalendarForDate(calendar).getTime()));
// System.out.println("Sunset : " + prt.format( calc.getOfficialSunsetCalendarForDate(calendar).getTime()));
System.out.println("Sunset : " + prt.format(ss.getSunset()) + " GMT");
}
public static void testPCT() throws ParseException{
System.out.println("California");
for (String d : DATES) {
printSunriseSunset(d, 34.08f, -118f, TimeZone.getTimeZone("PST"));
}
}
public static void testCET() throws ParseException{
System.out.println("Amsterdam");
for (String d : DATES) {
printSunriseSunset(d, 52.88f, 4.86f, TimeZone.getTimeZone("CET"));
}
}
public static void testEDT() throws ParseException{
System.out.println("New york");
for (String d : DATES) {
printSunriseSunset(d, 40.88f, -73.86f, TimeZone.getTimeZone("America/New_York"));
}
}
public static void main(String[] args) throws ParseException {
testPCT();
testCET();
testEDT();
}
}

View file

@ -1,26 +0,0 @@
package net.osmand;
/**
* This class is designed to put all to do's and link them with code.
*/
public class ToDoConstants {
// Map QuadTree index (skip small areas!!!)
// Polish UI with new building address search ...(Better completely new address search)
// Search for city in all indexes
// Test GeoIndexActivity
// Images in the map index ?
// Prepare C++ version of routing algorithm
}

View file

@ -1,55 +0,0 @@
package net.osmand.data;
public class Boundary
extends Multipolygon
{
private long boundaryId;
private String name;
private int adminLevel;
private long adminCenterId;
public Boundary() {
}
public long getBoundaryId() {
return boundaryId;
}
public void setBoundaryId(long boundaryId) {
this.boundaryId = boundaryId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAdminLevel() {
return adminLevel;
}
public void setAdminLevel(int adminLevel) {
this.adminLevel = adminLevel;
}
@Override
public String toString() {
return getName() + " alevel:" + getAdminLevel() + " type: has opened polygons:" + hasOpenedPolygons() + " no. of outer polygons:" + countOuterPolygons();
}
public void setAdminCenterId(long l) {
this.adminCenterId = l;
}
public long getAdminCenterId() {
return adminCenterId;
}
}

View file

@ -1,405 +0,0 @@
package net.osmand.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import org.apache.commons.logging.Log;
/**
* The idea of multipolygon:
* - we treat each outer way as closed polygon
* - multipolygon is always closed!
* - each way we try to assign to existing way and form
* so a more complex polygon
* - number of outer ways, is number of polygons
*
* @author Pavol Zibrita
*/
public class Multipolygon {
/**
* cache with the ways grouped per Ring
*/
private List<Ring> innerRings, outerRings;
private Map<Ring, Set<Ring>> cacheContainedInnerInOuter = new LinkedHashMap<Ring, Set<Ring>>();
/**
* ways added by the user
*/
private List<Way> outerWays, innerWays;
// Cache for fast contains calculation
private float maxLat = -90;
private float minLat = 90;
private float maxLon = -180;
private float minLon = 180;
/**
* an optional id of the multipolygon
*/
private long id;
/**
* Create a multipolygon with initialized outer and inner ways
* @param outers a list of outer ways
* @param inners a list of inner ways
*/
public Multipolygon(List<Way> outers, List<Way> inners) {
this();
outerWays.addAll(outers);
innerWays.addAll(inners);
}
/**
* create a new empty multipolygon
*/
public Multipolygon(){
outerWays = new ArrayList<Way> ();
innerWays = new ArrayList<Way> ();
id = 0L;
}
/**
* create a new empty multipolygon with specified id
* @param id the id to set
*/
public Multipolygon(long id){
this();
setId(id);
}
/**
* set the id of the multipolygon
* @param newId id to set
*/
public void setId(long newId) {
id = newId;
}
/**
* get the id of the multipolygon
* @return id
*/
public long getId() {
return id;
}
/**
* check if this multipolygon contains a point
* @param point point to check
* @return true if this multipolygon is correct and contains the point
*/
public boolean containsPoint(LatLon point) {
return containsPoint(point.getLatitude(), point.getLongitude());
}
/**
* check if this multipolygon contains a point
* @param latitude lat to check
* @param longitude lon to check
* @return true if this multipolygon is correct and contains the point
*/
public boolean containsPoint(double latitude, double longitude) {
// fast check
updateCacheOfRings();
if(maxLat + 0.3 < latitude || minLat - 0.3 > latitude ||
maxLon + 0.3 < longitude || minLon - 0.3 > longitude) {
return false;
}
Ring containedInOuter = null;
// use a sortedset to get the smallest outer containing the point
for (Ring outer : outerRings) {
if (outer.containsPoint(latitude, longitude)) {
containedInOuter = outer;
break;
}
}
if (containedInOuter == null) {
return false;
}
//use a sortedSet to get the smallest inner Ring
Ring containedInInner = null;
for (Ring inner : innerRings) {
if (inner.containsPoint(latitude, longitude)) {
containedInInner = inner;
break;
}
}
if (containedInInner == null) return true;
if (outerRings.size() == 1) {
// return immediately false
return false;
}
// if it is both, in an inner and in an outer, check if the inner is indeed the smallest one
Set<Ring> s = cacheContainedInnerInOuter.get(containedInInner);
if(s == null) {
throw new IllegalStateException();
}
return !s.contains(containedInOuter);
}
/**
* get the Inner Rings
* @return the inner rings
*/
public List<Ring> getInnerRings() {
updateCacheOfRings();
return innerRings;
}
/**
* get the outer rings
* @return outer rings
*/
public List<Ring> getOuterRings() {
updateCacheOfRings();
return outerRings;
}
/**
* get the outer ways
* @return outerWays or empty list if null
*/
private List<Way> getOuterWays() {
if (outerWays == null) {
outerWays = new ArrayList<Way>(1);
}
return outerWays;
}
/**
* get the inner ways
* @return innerWays or empty list if null
*/
private List<Way> getInnerWays() {
if (innerWays == null) {
innerWays = new ArrayList<Way>(1);
}
return innerWays;
}
/**
* get the number of outer Rings
* @return
*/
public int countOuterPolygons() {
updateCacheOfRings();
return zeroSizeIfNull(getOuterRings());
}
/**
* Check if this multiPolygon has uncomplete rings
* @return true it has uncomplete rings
*/
public boolean hasOpenedPolygons() {
return !areRingsComplete();
}
/**
* chekc if all rings are closed
* @return true if all rings are closed by nature, false otherwise
*/
public boolean areRingsComplete() {
List<Ring> set = getOuterRings();
for (Ring r : set) {
if (!r.isClosed()) {
return false;
}
}
set = getInnerRings();
for (Ring r : set) {
if (!r.isClosed()) {
return false;
}
}
return true;
}
/**
* return 0 if the list is null
* @param l the list to check
* @return the size of the list, or 0 if the list is null
*/
private int zeroSizeIfNull(Collection<?> l) {
return l != null ? l.size() : 0;
}
/**
* Add an inner way to the multiPolygon
* @param w the way to add
*/
public void addInnerWay(Way w) {
getInnerWays().add(w);
innerRings = null;
}
/**
* Add an outer way to the multiPolygon
* @param w the way to add
*/
public void addOuterWay(Way w) {
getOuterWays().add(w);
outerRings = null;
}
/**
* Add everything from multipolygon to this
* @param multipolygon the MultiPolygon to copy
*/
public void copyPolygonsFrom(Multipolygon multipolygon) {
for (Way inner : multipolygon.getInnerWays()) {
addInnerWay(inner);
}
for (Way outer : multipolygon.getOuterWays()) {
addOuterWay(outer);
}
// reset cache
outerRings = null;
innerRings = null;
}
/**
* Add outer ways to the outer Ring
* @param ways the ways to add
*/
public void addOuterWays(List<Way> ways) {
for (Way outer : ways) {
addOuterWay(outer);
}
}
/**
* Get the weighted center of all nodes in this multiPolygon <br />
* This only works when the ways have initialized nodes
* @return the weighted center
*/
public LatLon getCenterPoint() {
List<Node> points = new ArrayList<Node>();
for (Way w : getOuterWays()) {
points.addAll(w.getNodes());
}
for (Way w : getInnerWays()) {
points.addAll(w.getNodes());
}
return MapUtils.getWeightCenterForNodes(points);
}
/**
* Create the cache <br />
* The cache has to be null before it will be created
*/
private void updateCacheOfRings() {
if (outerRings == null) {
outerRings = Ring.combineToRings(getOuterWays());
maxLat = -90;
minLat = 90;
maxLon = -180;
minLon = 180;
for(Ring r : outerRings) {
for(Node n : r.getBorder()){
maxLat = (float) Math.max(maxLat, n.getLatitude());
minLat = (float) Math.min(minLat, n.getLatitude());
maxLon = (float) Math.max(maxLon, n.getLongitude());
minLon = (float) Math.min(minLon, n.getLongitude());
}
}
// keep sorted
Collections.sort(outerRings);
}
if (innerRings == null) {
innerRings = Ring.combineToRings(getInnerWays());
for(Ring inner : innerRings) {
HashSet<Ring> outContainingRings = new HashSet<Ring>();
for(Ring out : outerRings) {
if(inner.isIn(out)) {
outContainingRings.add(out);
}
}
cacheContainedInnerInOuter.put(inner, outContainingRings);
}
// keep sorted
Collections.sort(innerRings);
}
}
/**
* Split this multipolygon in several separate multipolygons with one outer ring each
* @param log the stream to log problems to, if log = null, nothing will be logged
* @return a list with multipolygons which have exactly one outer ring
*/
public List<Multipolygon> splitPerOuterRing(Log log) {
//make a clone of the inners set
// this set will be changed through execution of the method
ArrayList<Ring> inners = new ArrayList<Ring>(getInnerRings());
// get the set of outer rings in a variable. This set will not be changed
// sort it to start with the smallest
SortedSet<Ring> outers = new TreeSet<Ring>(getOuterRings());
ArrayList<Multipolygon> multipolygons = new ArrayList<Multipolygon>();
// loop; start with the smallest outer ring
for (Ring outer : outers) {
// create a new multipolygon with this outer and a list of inners
Multipolygon m = new Multipolygon();
m.addOuterWays(outer.getWays());
// Search the inners inside this outer ring
ArrayList<Ring> innersInsideOuter = new ArrayList<Ring>();
for (Ring inner : inners) {
if (inner.isIn(outer)) {
innersInsideOuter.add(inner);
for (Way w : inner.getWays()) {
m.addInnerWay(w);
}
}
}
// the inners should belong to this outer, so remove them from the list to check
inners.removeAll(innersInsideOuter);
multipolygons.add(m);
}
if (inners.size() != 0 && log != null)
log.warn("Multipolygon "+getId() + " has a mismatch in outer and inner rings");
return multipolygons;
}
/**
* This method only works when the multipolygon has exactly one outer Ring
* @return the list of nodes in the outer ring
*/
public List<Node> getOuterNodes() {
return getOuterRings().get(0).getBorder();
}
}

View file

@ -1,541 +0,0 @@
package net.osmand.data;
import java.util.ArrayList;
import java.util.List;
import net.osmand.osm.LatLon;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
/**
* A ring is a list of ways that form a simple boundary or an area. <p />
*
* @author sander
*
*/
public class Ring implements Comparable<Ring> {
/**
* This is a list of the ways added by the user
* The order can be changed with methods from this class
*/
private final ArrayList<Way> ways;
/**
* a concatenation of the ways to form the border
* this is NOT necessarily a CLOSED way
* The id is random, so this may never leave the Ring object
*/
private Way border;
/**
* area can be asked a lot of times when comparing rings, chace it
*/
private double area = -1;
/**
* Construct a Ring with a list of ways
* @param ways the ways that make up the Ring
*/
private Ring(List<Way> ways) {
this.ways = new ArrayList<Way>(ways);
}
/**
* Get the ways added to the Ring.
* This is not closed
* The order is not fixed
* @return the ways added to the Ring
*/
public List<Way> getWays() {
return new ArrayList<Way>(ways);
}
/**
* check if this ring is closed by nature
* @return true if this ring is closed, false otherwise
*/
public boolean isClosed() {
mergeWays();
return border.getFirstNodeId() == border.getLastNodeId();
}
/**
* get a single closed way that represents the border
* this method is CPU intensive
* @return a list of Nodes that represents the border
* if the border can't be created, an empty list will be returned
*/
public List<Node> getBorder() {
mergeWays();
List<Node> l = border.getNodes();
if (border.getNodes().size() != 0 && !isClosed()) {
l.add(border.getNodes().get(0));
}
return l;
}
/**
* Merge all ways from the into a single border way
* If the original ways are initialized with nodes, the border will be so too
* If the original ways aren't initialized with nodes, the border won't be either
* If only some original ways are initialized with nodes, the border will only have the nodes of the initialized ways
*/
private void mergeWays() {
if (border != null) return;
//make a copy of the ways
List<Way> ways = new ArrayList<Way>(getWays());
// do we have to include ways with uninitialized nodes?
// Only if all ways have uninitialized nodes
boolean unInitializedNodes = true;
for (Way w : ways) {
if (w.getNodes() != null && w.getNodes().size() != 0) {
unInitializedNodes = false;
break;
}
}
List<Way> borderWays = new ArrayList<Way>();
for (Way w : ways) {
// if the way has no nodes initialized, and we should initialize them, continue
if ((w.getNodes() == null || w.getNodes().size() == 0) &&
!unInitializedNodes) continue;
// merge the Way w with the first borderway suitable, repeat until nothing can be merged
Way wayToMerge = w;
Way newWay;
do {
newWay = null;
for (Way borderWay : borderWays) {
newWay = combineTwoWaysIfHasPoints(wayToMerge, borderWay);
if(newWay != null) {
wayToMerge = newWay;
borderWays.remove(borderWay);
break;
}
}
} while (newWay != null);
//no suitable borderWay has been found, add this way as one of the boundaries
borderWays.add(wayToMerge);
}
if (borderWays.size() != 1) {
border = new Way(nextRandId());
return;
}
border = borderWays.get(0);
return;
}
/**
* check if this Ring contains the node
* @param n the Node to check
* @return yes if the node is inside the ring
*/
public boolean containsNode(Node n) {
return containsPoint(n.getLatitude(), n.getLongitude());
}
/**
* check if this Ring contains the point
* @param latitude lat of the point
* @param longitude lon of the point
* @return yes if the point is inside the ring
*/
public boolean containsPoint(double latitude, double longitude){
return countIntersections(latitude, longitude) % 2 == 1;
}
/**
* count the intersections when going from lat, lon to outside the ring
* @param latitude the lat to start
* @param longitude the lon to start
* @param intersections the number of intersections to start with
* @return the number of intersections
*/
private int countIntersections(double latitude, double longitude) {
int intersections = 0;
List<Node> polyNodes = getBorder();
if (polyNodes.size() == 0) return 0;
for (int i = 0; i < polyNodes.size() - 1; i++) {
if (MapAlgorithms.ray_intersect_lon(polyNodes.get(i),
polyNodes.get(i + 1), latitude, longitude) != -360d) {
intersections++;
}
}
// special handling, also count first and last, might not be closed, but
// we want this!
if (MapAlgorithms.ray_intersect_lon(polyNodes.get(0),
polyNodes.get(polyNodes.size() - 1), latitude, longitude) != -360d) {
intersections++;
}
return intersections;
}
/**
* Check if this is in Ring r
* @param r the ring to check
* @return true if this Ring is inside Ring r
*/
public boolean isIn(Ring r) {
/*
* bi-directional check is needed because some concave rings can intersect
* and would only fail on one of the checks
*/
List<Node> points = this.getBorder();
// r should contain all nodes of this
for(Node n : points) {
if (!r.containsNode(n)) {
return false;
}
}
points = r.getBorder();
// this should not contain a node from r
for(Node n : points) {
if (this.containsNode(n)) {
return false;
}
}
return true;
}
/**
* If this Ring is not complete
* (some ways are not initialized
* because they are not included in the OSM file) <p />
*
* We are trying to close this Ring by using the other Ring.<p />
*
* The other Ring must be complete, and the part of this Ring
* inside the other Ring must also be complete.
* @param other the other Ring (which is complete) used to close this one
*/
public void closeWithOtherRing(Ring other) {
List<Node> thisBorder = getBorder();
List<Integer> thisSwitchPoints = new ArrayList<Integer>();
boolean insideOther = other.containsNode(thisBorder.get(0));
// Search the node pairs for which the ring goes inside or out the other
for (int i = 0; i<thisBorder.size(); i++) {
Node n = thisBorder.get(i);
if (other.containsNode(n) != insideOther) {
// we are getting out or in the boundary now.
// toggle switch
insideOther = !insideOther;
thisSwitchPoints.add(i);
}
}
List<Integer> otherSwitchPoints = new ArrayList<Integer>();
// Search the according node pairs in the other ring
for (int i : thisSwitchPoints) {
LatLon a = thisBorder.get(i-1).getLatLon();
LatLon b = thisBorder.get(i).getLatLon();
otherSwitchPoints.add(crossRingBorder(a, b));
}
/*
* TODO:
*
* * Split the other Ring into ways from splitPoint to splitPoint
*
* * Split this ring into ways from splitPoint to splitPoint
*
* * Filter out the parts of way from this that are inside the other Ring
* Use the insideOther var and the switchPoints list for this.
*
* * For each two parts of way from this, search a part of way connecting the two.
* If there are two, take the shortest.
*/
}
/**
* Get the segment of the Ring that intersects a segment
* going from point a to point b
*
* @param a the begin point of the segment
* @param b the end point of the segment
* @return an integer i which is the index so that the segment
* from getBorder().get(i-1) to getBorder().get(i) intersects with
* the segment from parameters a to b. <p />
*
* 0 if the segment from a to b doesn't intersect with the Ring.
*/
public int crossRingBorder(LatLon a, LatLon b) {
List<Node> border = getBorder();
for (int i = 1; i<border.size(); i++) {
LatLon c = border.get(i-1).getLatLon();
LatLon d = border.get(i).getLatLon();
if (MapAlgorithms.linesIntersect(
a.getLatitude(), a.getLongitude(),
b.getLatitude(), b.getLongitude(),
c.getLatitude(), c.getLongitude(),
d.getLatitude(), d.getLongitude())) {
return i;
}
}
return 0;
}
public double getArea() {
if (area == -1) {
//cache the area
area = MapAlgorithms.getArea(getBorder());
}
return area;
}
/**
* Use area size as comparable metric
*/
@Override
public int compareTo(Ring r) {
return Double.compare(getArea(), r.getArea());
}
/**
* Join the ways in connected strings for further processing
* @return A list with list of connected ways
*/
private static ArrayList<ArrayList<Way>> createMultiLines(List<Way> ways){
// make a list of multiLines (connecter pieces of way)
// One ArrayList<Way> is one multiLine
ArrayList<ArrayList<Way>> multiLines = new ArrayList<ArrayList<Way>>();
for (Way toAdd : ways) {
/*
* Check if the way has at least 2 nodes
*
* TO LOG OR NOT TO LOG?
*
* logging this creates a whole bunch of log lines for all ways
* part of a multipolygon but not in the map
*/
if (toAdd.getNodeIds().size() < 2) {
continue;
}
long toAddBeginPt = toAdd.getFirstNodeId();
long toAddEndPt = toAdd.getLastNodeId();
// the way has been added to this number of multiLines
int addedTo = 0;
// save the first and second changed multiLine
ArrayList<Way> firstMultiLine = new ArrayList<Way> ();
ArrayList<Way> secondMultiLine = new ArrayList<Way> ();
// iterate over the multiLines, and add the way to the correct one
for( ArrayList<Way> multiLine : multiLines) {
// to check if this multiLine has been changed at the end of the loop
int previousAddedTo = addedTo;
// get the first and last way of a multiLine
Way firstWay = multiLine.get(0);
Way lastWay = multiLine.get(multiLine.size() - 1);
// add the way to the correct multiLines (maybe two)
if (toAddBeginPt == firstWay.getFirstNodeId() ||
toAddBeginPt == firstWay.getLastNodeId() ||
toAddEndPt == firstWay.getFirstNodeId() ||
toAddEndPt == firstWay.getLastNodeId() ) {
// add the way to the begining to respect order
multiLine.add(0, toAdd);
addedTo++;
} else if (toAddBeginPt == lastWay.getFirstNodeId() ||
toAddBeginPt == lastWay.getLastNodeId() ||
toAddEndPt == lastWay.getFirstNodeId() ||
toAddEndPt == lastWay.getLastNodeId()) {
// add the way to the end
multiLine.add(toAdd);
addedTo++;
}
// save this multiLines if it has been changed
if (previousAddedTo != addedTo) {
if (addedTo == 1) {
firstMultiLine = multiLine;
}
if (addedTo == 2) {
secondMultiLine = multiLine;
}
// a Ring may never contain a fork
// if there is a third multiline, don't process
// hope there is a fourth one, sot these two will be processed later on
}
}
// If the way is added to nothing, make a new multiLine
if (addedTo == 0 ) {
ArrayList<Way> multiLine = new ArrayList<Way>();
multiLine.add(toAdd);
multiLines.add(multiLine);
continue;
}
//everything OK
if (addedTo == 1) continue;
// only the case addedTo == 2 remains
// two multiLines have to be merged
if (firstMultiLine.get(firstMultiLine.size() - 1) == secondMultiLine.get(0)) {
// add the second to the first
secondMultiLine.remove(0) ;
for (Way w : secondMultiLine) {
firstMultiLine.add(w);
}
multiLines.remove(secondMultiLine);
} else if (secondMultiLine.get(secondMultiLine.size() - 1) == firstMultiLine.get(0)) {
// just add the first to the second
firstMultiLine.remove(0) ;
for (Way w : firstMultiLine) {
secondMultiLine.add(w);
}
multiLines.remove(firstMultiLine);
} else if (firstMultiLine.get(0) == secondMultiLine.get(0)) {
// add the first in reversed to the beginning of the second
firstMultiLine.remove(toAdd);
for (Way w : firstMultiLine) {
secondMultiLine.add(0,w);
}
multiLines.remove(firstMultiLine);
} else {
// add the first in reversed to the end of the second
firstMultiLine.remove(toAdd);
int index = secondMultiLine.size();
for (Way w : firstMultiLine) {
secondMultiLine.add(index ,w);
}
multiLines.remove(firstMultiLine);
}
}
return multiLines;
}
/**
* Combine a list of ways into a list of rings
*
* The ways must not have initialized nodes for this
*
* @param ways the ways to group
* @return a list of Rings
*/
public static ArrayList<Ring> combineToRings(List<Way> ways){
ArrayList<ArrayList<Way>> multiLines = createMultiLines(ways);
ArrayList<Ring> result = new ArrayList<Ring> ();
for (ArrayList<Way> multiLine : multiLines) {
Ring r = new Ring(multiLine);
result.add(r);
}
return result;
}
private static long initialValue = -1000;
private final static long randomInterval = 5000;
/**
* get a random long number
* @return
*/
private static long nextRandId() {
// exclude duplicates in one session (!) and be quazirandom every run
long val = initialValue - Math.round(Math.random()*randomInterval);
initialValue = val;
return val;
}
/**
* make a new Way with the nodes from two other ways
* @param w1 the first way
* @param w2 the second way
* @return null if it is not possible
*/
private static Way combineTwoWaysIfHasPoints(Way w1, Way w2) {
boolean combine = true;
boolean firstReverse = false;
boolean secondReverse = false;
if(w1.getFirstNodeId() == w2.getFirstNodeId()) {
firstReverse = true;
secondReverse = false;
} else if(w1.getLastNodeId() == w2.getFirstNodeId()) {
firstReverse = false;
secondReverse = false;
} else if(w1.getLastNodeId() == w2.getLastNodeId()) {
firstReverse = false;
secondReverse = true;
} else if(w1.getFirstNodeId() == w2.getLastNodeId()) {
firstReverse = true;
secondReverse = true;
} else {
combine = false;
}
if (combine) {
Way newWay = new Way(nextRandId());
boolean nodePresent = w1.getNodes() != null || w1.getNodes().size() != 0;
int w1size = nodePresent ? w1.getNodes().size() : w1.getNodeIds().size();
for (int i = 0; i < w1size; i++) {
int ind = firstReverse ? (w1size - 1 - i) : i;
if (nodePresent) {
newWay.addNode(w1.getNodes().get(ind));
} else {
newWay.addNode(w1.getNodeIds().get(ind));
}
}
int w2size = nodePresent ? w2.getNodes().size() : w2.getNodeIds().size();
for (int i = 1; i < w2size; i++) {
int ind = secondReverse ? (w2size - 1 - i) : i;
if (nodePresent) {
newWay.addNode(w2.getNodes().get(ind));
} else {
newWay.addNode(w2.getNodeIds().get(ind));
}
}
return newWay;
}
return null;
}
}

View file

@ -1,13 +0,0 @@
package net.osmand.data;
public class WayBoundary extends Boundary {
public WayBoundary() {
super();
}
@Override
public String toString() {
return getName() + " alevel:" + getAdminLevel() + " type: way closed:" + !hasOpenedPolygons();
}
}

View file

@ -1,177 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import net.osmand.LogUtil;
import net.osmand.data.index.ExtractGooglecodeAuthorization.GooglecodeUploadTokens;
import org.apache.commons.logging.Log;
public class DownloaderIndexFromGoogleCode {
private final static Log log = LogUtil.getLog(DownloaderIndexFromGoogleCode.class);
public static void main(String[] args) {
System.out.println(DownloaderIndexFromGoogleCode.getIndexFiles(new LinkedHashMap<String, String>()));
}
private static Map<String, String> getContent(Map<String, String> files,
String... ext) {
BufferedReader reader = null;
int num = 400;
int start = 0;
boolean downloadNext = true;
while (downloadNext) {
downloadNext = false;
try {
URL url = new URL(
"http://code.google.com/p/osmand/downloads/list?num=" + num + "&start=" + start); //$NON-NLS-1$ //$NON-NLS-2$
reader = new BufferedReader(new InputStreamReader(url
.openStream()));
String s = null;
String prevFile = null;
while ((s = reader.readLine()) != null) {
boolean hrefDownload = s.indexOf("files") != -1; //$NON-NLS-1$
if (hrefDownload || s.indexOf("{") != -1) { //$NON-NLS-1$
downloadNext |= hrefDownload;
for (String extension : ext) {
prevFile = getIndexFiles(files, s, prevFile, extension);
}
}
}
start += num + 1;
} catch (MalformedURLException e) {
log.error("Unexpected exception", e); //$NON-NLS-1$
} catch (IOException e) {
log.error("Input/Output exception", e); //$NON-NLS-1$
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error("Error closing stream to url.", e); //$NON-NLS-1$
}
}
}
}
log.info("Loaded indexes:" + files.size()); //$NON-NLS-1$
return files;
}
private static String getIndexFiles(Map<String, String> files, String content, String prevFile, String ext){
int i = content.indexOf(ext, 0);
if (i != -1) {
int j = i - 1;
while (content.charAt(j) == '_' || Character.isLetterOrDigit(content.charAt(j)) || content.charAt(j) == '-' || content.charAt(j) == '.') {
j--;
}
prevFile = content.substring(j + 1, i) + ext;
}
if (prevFile != null && ((i = content.indexOf('{')) != -1)) {
int j = content.indexOf('}');
if (j != -1 && j - i < 40) {
// String description = content.substring(i, j + 1);
files.put(prevFile, content);
prevFile = null;
}
}
return prevFile;
}
public static Map<String, String> getIndexFiles(Map<String, String> files){
return getContent(files, ".obf", ".zip", ".zip-1", ".zip-2", ".zip-3", ".zip-4");
}
public static URL getInputStreamToLoadIndex(String indexName) throws IOException{
URL url = new URL("http://osmand.googlecode.com/files/"+indexName); //$NON-NLS-1$
return url;
}
public static String deleteFileFromGoogleDownloads(String fileName, GooglecodeUploadTokens ggtokens) throws IOException {
// prepare data
Map<String, String> cookies = new HashMap<String, String>();
cookies.put("HSID", ggtokens.getHsid()); //$NON-NLS-1$
cookies.put("SID", ggtokens.getSid()); //$NON-NLS-1$
StringBuilder cookieString = new StringBuilder();
int size = cookies.size();
for (String c : cookies.keySet()) {
size--;
cookieString.append(c).append("=").append(cookies.get(c)); //$NON-NLS-1$
if (size > 0) {
cookieString.append("; "); //$NON-NLS-1$
}
}
String urlText = "http://code.google.com/p/osmand/downloads/delete.do?name="+fileName; //$NON-NLS-1$
log.info("Url to delete :" + urlText);
StringBuilder requestBody = new StringBuilder();
requestBody.
append("token=").append(ggtokens.getToken()). //$NON-NLS-1$
append("&pagegen=").append(ggtokens.getPagegen()). //$NON-NLS-1$
append("&filename=").append(fileName). //$NON-NLS-1$
append("&delete=Delete+download"); //$NON-NLS-1$
log.info("Request body : " + requestBody);
// getting url
URL url = new URL(urlText);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Cookie", cookieString.toString()); //$NON-NLS-1$
connection.setConnectTimeout(15000);
connection.setRequestMethod("POST"); //$NON-NLS-1$
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //$NON-NLS-1$//$NON-NLS-2$
connection.setRequestProperty("Content-Length", requestBody.length()+""); //$NON-NLS-1$ //$NON-NLS-2$
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
OutputStream out = connection.getOutputStream();
if (requestBody != null) {
BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 1024); //$NON-NLS-1$
bwr.write(requestBody.toString());
bwr.flush();
bwr.close();
}
log.info("Response : " + connection.getResponseMessage()); //$NON-NLS-1$
// populate return fields.
StringBuilder responseBody = new StringBuilder();
InputStream i = connection.getInputStream();
if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256); //$NON-NLS-1$
String s;
boolean f = true;
while ((s = in.readLine()) != null) {
if(!f){
responseBody.append("\n"); //$NON-NLS-1$
} else {
f = false;
}
responseBody.append(s);
}
}
return responseBody.toString();
}
}

View file

@ -1,226 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.CookieHandler;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExtractGooglecodeAuthorization {
public static class GooglecodeUploadTokens {
private final String sid, hsid, token, pagegen;
public GooglecodeUploadTokens(String sid, String hsid, String token,
String pagegen) {
this.sid = sid;
this.hsid = hsid;
this.token = token;
this.pagegen = pagegen;
}
public String getHsid() {
return hsid;
}
public String getSid() {
return sid;
}
public String getToken() {
return token;
}
public String getPagegen() {
return pagegen;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Token:").append(token)//
.append("\nPagegen:").append(pagegen)//
.append("\nSID:").append(sid)//
.append("\nHSID:").append(hsid);
return builder.toString();
}
}
boolean debug = false;
public ExtractGooglecodeAuthorization() {
this(false);
}
public ExtractGooglecodeAuthorization(boolean debug) {
this.debug = debug;
}
public GooglecodeUploadTokens getGooglecodeTokensForUpload(String user, String password) throws IOException {
final MyCookieStore cookies = new MyCookieStore(
new java.net.CookieManager().getCookieStore());
CookieHandler.setDefault(new java.net.CookieManager(cookies, null));
//first try to delete file
HttpURLConnection conn = connectTo("http://code.google.com/p/osmand/downloads/delete?name=en-tts_0.voice.zip");
StringBuilder responseBody = readAnswer(conn.getInputStream());
//then we are redirect to login page
conn = connectTo("https://www.google.com/accounts/ServiceLogin?service=code&ltmpl=phosting&continue=http%3A%2F%2Fcode.google.com%2Fp%2Fosmand%2Fdownloads%2Fdelete%3Fname%3Den-tts_0.voice.zip");
responseBody = readAnswer(conn.getInputStream());
String dsh = matchResponseBody(".*id=\"dsh\"[^\"]*value=\"([^\"]*)\".*", responseBody);
String galx = matchResponseBody(".*name=\"GALX\"[^\"]*value=\"([^\"]*)\".*", responseBody);
if (dsh == null || galx == null) {
throw new IOException("Failed to retrieve dsh or galx from login page!");
}
StringBuilder data = buildPostData(user, password, dsh, galx);
// try authentification Request: https://www.google.com/accounts/ServiceLoginAuth");
URL url = new URL("https://accounts.google.com/ServiceLoginAuth");
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
conn.setRequestProperty("Accept-Charset", "ISO-8859-2,utf-8;q=0.7,*;q=0.7");
conn.setRequestProperty("Accept-Language", "sk,cs;q=0.8,en-us;q=0.5,en;q=0.3");
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty(
"Referer",
"https://www.google.com/accounts/ServiceLogin?service=code&ltmpl=phosting&continue=http%3A%2F%2Fcode.google.com%2Fp%2Fosmand%2Fdownloads%2Fdelete%3Fname%3Den-tts_0.voice.zip");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //$NON-NLS-1$ //$NON-NLS-
conn.setRequestProperty("Content-Length", data.length() + "");
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
// write parameters
writer.write(data.toString());
writer.flush();
conn.connect();
if (debug) {
System.out.println("Connected to:" + url.toString());
System.out.println("-- Data sent:\n" + data.toString());
System.out.println("--");
}
// Get the response
responseBody = readAnswer(conn.getInputStream());
writer.close();
//try again the delete page, we should be now connected
conn = connectTo("http://code.google.com/p/osmand/downloads/delete?name=en-tts_0.voice.zip");
responseBody = readAnswer(conn.getInputStream());
String token = matchResponseBody(".*name=\"token\"[^\"]*value=\"([^\"]*)\".*", responseBody);
String pagegen = matchResponseBody(".*name=\"pagegen\"[^\"]*value=\"([^\"]*)\".*", responseBody);
if (token == null || pagegen == null) {
throw new IOException("Faild to retrieve token or pagegen from delete page!");
}
return new GooglecodeUploadTokens(cookies.getCookie("SID"), cookies.getCookie("HSID"), token, pagegen);
}
private String matchResponseBody(String matchString, StringBuilder responseBody) {
String dsh = null;
Matcher matcher = Pattern.compile(matchString, Pattern.DOTALL | Pattern.MULTILINE).matcher(responseBody.toString());
if (matcher.matches()) {
dsh = matcher.group(1);
}
return dsh;
}
private StringBuilder buildPostData(String user, String password,
String dsh, String galx) throws UnsupportedEncodingException {
// Build parameter string
Map<String, String> values = new LinkedHashMap<String, String>();
values.put("asts", null);
values.put("continue","https://code.google.com/p/osmand/downloads/delete?name=en-tts_0.voice.zip");
// values.put("dnConn","https://accounts.youtube.com");
values.put("dsh", dsh);
values.put("Email", user);
values.put("GALX", galx);
values.put("ltmpl", "phosting");
values.put("Passwd", password);
values.put("pstMsg", "1");
values.put("rmShow", "1");
values.put("secTok", null);
values.put("service", "code");
values.put("signIn", "Sign in");
values.put("timeStmp", null);
StringBuilder data = new StringBuilder();
for (String key : values.keySet()) {
data.append(URLEncoder.encode(key, "UTF-8")).append("=");
if (values.get(key) != null) {
data.append(URLEncoder.encode(values.get(key), "UTF-8"));
}
data.append("&");
}
data.deleteCharAt(data.length() - 1);
return data;
}
private HttpURLConnection connectTo(String urlString) throws MalformedURLException,
IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
conn.setRequestProperty("Accept-Charset", "ISO-8859-2,utf-8;q=0.7,*;q=0.7");
conn.setRequestProperty("Accept-Language", "sk,cs;q=0.8,en-us;q=0.5,en;q=0.3");
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0");
conn.connect();
if (debug) {
System.out.println("Connecting to:" + urlString);
}
return conn;
}
private StringBuilder readAnswer(InputStream input)
throws IOException, UnsupportedEncodingException {
StringBuilder responseBody = new StringBuilder();
InputStream i = input;
if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i,
"UTF-8"), 256); //$NON-NLS-1$
String s;
boolean f = true;
while ((s = in.readLine()) != null) {
if (!f) {
responseBody.append("\n"); //$NON-NLS-1$
} else {
f = false;
}
responseBody.append(s);
}
i.close();
}
if (debug) {
System.out.println("Aswer from server:\n" + responseBody.toString());
}
return responseBody;
}
public static void main(String[] args) throws IOException
{
if (args.length < 2) {
System.out.println("Use: ExtractGooglecodeAuthorization gmailname gmailpassword");
return;
} else {
System.out.println(new ExtractGooglecodeAuthorization(true).getGooglecodeTokensForUpload(args[0], args[1]).toString());
}
}
}

View file

@ -1,183 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* This class is used to upload a file to a FTP server.
*
* @author Muthu
*/
public class FTPFileUpload
{
/**
* Upload a file to a FTP server. A FTP URL is generated with the
* following syntax:
* ftp://user:password@host:port/filePath;type=i.
*
* @param ftpServer , FTP server address (optional port ':portNumber').
* @param user , Optional user name to login.
* @param password , Optional password for user.
* @param fileName , Destination file name on FTP server (with optional
* preceding relative path, e.g. "myDir/myFile.txt").
* @param source , Source file to upload.
* @throws MalformedURLException, IOException on error.
*/
public void upload( String ftpServer, String user, String password,
String fileName, File source, int bufferSize ) throws MalformedURLException,
IOException
{
if (ftpServer != null && fileName != null && source != null)
{
StringBuffer sb = new StringBuffer( "ftp://" );
// check for authentication else assume its anonymous access.
if (user != null && password != null)
{
sb.append( user );
sb.append( ':' );
sb.append( password );
sb.append( '@' );
}
sb.append( ftpServer );
sb.append( '/' );
sb.append( fileName );
/*
* type ==> a=ASCII mode, i=image (binary) mode, d= file directory
* listing
*/
sb.append( ";type=i" );
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try
{
URL url = new URL( sb.toString() );
URLConnection urlc = url.openConnection();
bos = new BufferedOutputStream( urlc.getOutputStream(), bufferSize);
bis = new BufferedInputStream( new FileInputStream( source ), bufferSize);
int i;
// read byte by byte until end of stream
while ((i = bis.read()) != -1)
{
bos.write( i );
}
}
finally
{
if (bis != null)
try
{
bis.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
if (bos != null)
try
{
bos.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
else
{
System.out.println( "Input not available." );
}
}
/**
* Download a file from a FTP server. A FTP URL is generated with the
* following syntax:
* ftp://user:password@host:port/filePath;type=i.
*
* @param ftpServer , FTP server address (optional port ':portNumber').
* @param user , Optional user name to login.
* @param password , Optional password for user.
* @param fileName , Name of file to download (with optional preceeding
* relative path, e.g. one/two/three.txt).
* @param destination , Destination file to save.
* @throws MalformedURLException, IOException on error.
*/
public void download( String ftpServer, String user, String password,
String fileName, File destination ) throws MalformedURLException,
IOException
{
if (ftpServer != null && fileName != null && destination != null)
{
StringBuffer sb = new StringBuffer( "ftp://" );
// check for authentication else assume its anonymous access.
if (user != null && password != null)
{
sb.append( user );
sb.append( ':' );
sb.append( password );
sb.append( '@' );
}
sb.append( ftpServer );
sb.append( '/' );
sb.append( fileName );
/*
* type ==> a=ASCII mode, i=image (binary) mode, d= file directory
* listing
*/
sb.append( ";type=i" );
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try
{
URL url = new URL( sb.toString() );
URLConnection urlc = url.openConnection();
bis = new BufferedInputStream( urlc.getInputStream() );
bos = new BufferedOutputStream( new FileOutputStream(
destination.getName() ) );
int i;
while ((i = bis.read()) != -1)
{
bos.write( i );
}
}
finally
{
if (bis != null)
try
{
bis.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
if (bos != null)
try
{
bos.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
else
{
System.out.println( "Input not available" );
}
}
}

View file

@ -1,294 +0,0 @@
/*
* Created on May 24, 2007
*
* This code belongs to Jonathan Fuerth
*/
package net.osmand.data.index;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import net.osmand.Base64;
import net.osmand.LogUtil;
import org.apache.commons.logging.Log;
/**
* Initially was taken from GoogleCodeUploadTask
*/
public class GoogleCodeUploadIndex {
private final static Log log = LogUtil.getLog(GoogleCodeUploadIndex.class);
/**
* Google user name to authenticate as (this is just the username part;
* don't include the @gmail.com part).
*/
private String userName;
/**
* Coogle Code password (not the same as the gmail password) !!!!
*/
private String password;
/**
* Google Code project name to upload to.
*/
private String projectName;
/**
* The local path of the file to upload.
*/
private String fileName;
/**
* The file name that this file will be given on Google Code.
*/
private String targetFileName;
/**
* Summary of the upload.
*/
private String summary;
/**
* Description of the upload.
*/
private String description;
/**
* The labels that the download should have, separated by commas. Extra
* whitespace before and after each label name will not be considered part
* of the label name.
*/
private String labels;
private void log(String e){
log.info(e);
}
/**
* Uploads the contents of the file {@link #fileName} to the project's
* Google Code upload url. Performs the basic http authentication required
* by Google Code.
*/
public void upload() throws IOException {
System.clearProperty("javax.net.ssl.trustStoreProvider"); // fixes open-jdk-issue //$NON-NLS-1$
System.clearProperty("javax.net.ssl.trustStoreType"); //$NON-NLS-1$
final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$
URL url = createUploadURL();
log("The upload URL is " + url); //$NON-NLS-1$
InputStream in = new BufferedInputStream(new FileInputStream(fileName));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Authorization", "Basic " + createAuthToken(userName, password)); //$NON-NLS-1$ //$NON-NLS-2$
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$
conn.setRequestProperty("User-Agent", "Google Code Upload Ant Task 0.1"); //$NON-NLS-1$ //$NON-NLS-2$
log("Attempting to connect (username is " + userName + ")..."); //$NON-NLS-1$ //$NON-NLS-2$
conn.connect();
//log("Sending request parameters..."); //$NON-NLS-1$
OutputStream out = conn.getOutputStream();
sendLine(out, "--" + BOUNDARY); //$NON-NLS-1$
sendLine(out, "content-disposition: form-data; name=\"summary\""); //$NON-NLS-1$
sendLine(out, ""); //$NON-NLS-1$
sendLine(out, summary);
if (labels != null) {
String[] labelArray = labels.split("\\,"); //$NON-NLS-1$
if (labelArray != null && labelArray.length > 0) {
// log("Setting "+labelArray.length+" label(s)"); //$NON-NLS-1$ //$NON-NLS-2$
for (int n = 0, i = labelArray.length; n < i; n++) {
sendLine(out, "--" + BOUNDARY); //$NON-NLS-1$
sendLine(out, "content-disposition: form-data; name=\"label\""); //$NON-NLS-1$
sendLine(out, ""); //$NON-NLS-1$
sendLine(out, labelArray[n].trim());
}
}
}
log("Sending file... "+targetFileName); //$NON-NLS-1$
sendLine(out, "--" + BOUNDARY); //$NON-NLS-1$
sendLine(out, "content-disposition: form-data; name=\"filename\"; filename=\"" + targetFileName + "\""); //$NON-NLS-1$ //$NON-NLS-2$
sendLine(out, "Content-Type: application/octet-stream"); //$NON-NLS-1$
sendLine(out, ""); //$NON-NLS-1$
int count;
byte[] buf = new byte[8192];
while ( (count = in.read(buf)) >= 0 ) {
out.write(buf, 0, count);
}
in.close();
sendLine(out, ""); //$NON-NLS-1$
sendLine(out, "--" + BOUNDARY + "--"); //$NON-NLS-1$ //$NON-NLS-2$
out.flush();
out.close();
log("Response code " + conn.getResponseCode());
in = conn.getErrorStream();
if (in != null) {
StringBuilder errorBody = new StringBuilder();
while ((count = in.read(buf)) >= 0) {
errorBody.append(new String(buf, 0, count, "utf-8")); //$NON-NLS-1$
}
if (errorBody.length() > 0) {
log("ERROR " + errorBody.toString());
}
in.close();
}
// For whatever reason, you have to read from the input stream before
// the url connection will start sending
in = conn.getInputStream();
StringBuilder responseBody = new StringBuilder();
while ( (count = in.read(buf)) >= 0 ) {
responseBody.append(new String(buf, 0, count, "ascii")); //$NON-NLS-1$
}
log("Upload finished response " + responseBody.toString());
in.close();
conn.disconnect();
}
/**
* Just sends an ASCII version of the given string, followed by a CRLF line terminator,
* to the given output stream.
*/
private void sendLine(OutputStream out, String string) throws IOException {
out.write(string.getBytes("ascii")); //$NON-NLS-1$
out.write("\r\n".getBytes("ascii")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Creates a (base64-encoded) HTTP basic authentication token for the
* given user name and password.
*/
public static String createAuthToken(String userName, String password) {
String string = (userName + ":" + password); //$NON-NLS-1$
try {
return Base64.encode(string.getBytes("UTF-8")); //$NON-NLS-1$
}
catch (java.io.UnsupportedEncodingException notreached){
throw new InternalError(notreached.toString());
}
}
/**
* Creates the correct URL for uploading to the named google code project.
* If uploadUrl is not set (this is the standard case), the correct URL will
* be generated based on the {@link #projectName}. Otherwise, if uploadUrl
* is set, it will be used and the project name setting will be ignored.
*/
private URL createUploadURL() throws MalformedURLException {
if (projectName == null) {
throw new NullPointerException("projectName must be set"); //$NON-NLS-1$
}
return new URL("https", projectName + ".googlecode.com", "/files"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
}
// ============ Getters and Setters ==============
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTargetFileName() {
return targetFileName;
}
public void setTargetFileName(String targetFileName) {
this.targetFileName = targetFileName;
}
public String getLabels() {
return labels;
}
public void setLabels(String labels) {
this.labels = labels;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static void main(String[] args) throws IOException {
GoogleCodeUploadIndex uploadIndex = new GoogleCodeUploadIndex();
// uploadIndex.setLabels("");
// uploadIndex.setProjectName("osmand");
// uploadIndex.setFileName(_);
// uploadIndex.setTargetFileName(_);
// uploadIndex.setUserName(_);
// uploadIndex.setSummary(_);
// uploadIndex.setPassword(_);
uploadIndex.upload();
}
}

View file

@ -1,539 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.SimpleFormatter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.Algoritms;
import net.osmand.LogUtil;
import net.osmand.MapCreatorVersion;
import net.osmand.data.IndexConstants;
import net.osmand.data.preparation.DBDialect;
import net.osmand.data.preparation.IndexCreator;
import net.osmand.data.preparation.MapZooms;
import net.osmand.impl.ConsoleProgressImplementation;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.swing.OsmExtractionUI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.Jdk14Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import rtree.RTree;
public class IndexBatchCreator {
private static final int INMEM_LIMIT = 600;
protected static final Log log = LogUtil.getLog(IndexBatchCreator.class);
public static final String GEN_LOG_EXT = ".gen.log";
public static class RegionCountries {
String namePrefix = ""; // for states of the country
String nameSuffix = "";
Map<String, RegionSpecificData> regionNames = new LinkedHashMap<String, RegionSpecificData>();
String siteToDownload = "";
}
private static class RegionSpecificData {
public String cityAdminLevel;
}
// process atributtes
File skipExistingIndexes;
MapZooms mapZooms = null;
Integer zoomWaySmoothness = null;
MapRenderingTypes types = MapRenderingTypes.getDefault();
File osmDirFiles;
File indexDirFiles;
File workDir;
boolean indexPOI = false;
boolean indexTransport = false;
boolean indexAddress = false;
boolean indexMap = false;
boolean indexRouting = false;
private String wget;
private DBDialect osmDbDialect;
private DBDialect mapDBDialect;
public static void main(String[] args) {
IndexBatchCreator creator = new IndexBatchCreator();
OsmExtractionUI.configLogFile();
if(args == null || args.length == 0){
System.out.println("Please specify -local parameter or path to batch.xml configuration file as 1 argument.");
throw new IllegalArgumentException("Please specify -local parameter or path to batch.xml configuration file as 1 argument.");
}
String name = args[0];
InputStream stream;
InputStream regionsStream = null;
if(name.equals("-local")){
stream = IndexBatchCreator.class.getResourceAsStream("batch.xml");
regionsStream = IndexBatchCreator.class.getResourceAsStream("regions.xml");
log.info("Using local settings");
} else {
try {
stream = new FileInputStream(name);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("XML configuration file not found : " + name, e);
}
if (args.length > 1) {
try {
File regionsFile = new File(args[1]);
regionsStream = new FileInputStream(regionsFile);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("Please specify xml-file with regions to download", e); //$NON-NLS-1$
}
}
}
try {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
Document regions = null;
if(regionsStream != null) {
name = args[1];
regions = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(regionsStream);
}
creator.runBatch(doc, regions);
} catch (Exception e) {
System.out.println("XML configuration file could not be read from " + name);
e.printStackTrace();
log.error("XML configuration file could not be read from " + name, e);
} finally {
safeClose(stream, "Error closing stream for " + name);
}
}
public void runBatch(Document doc, Document regions) throws SAXException, IOException, ParserConfigurationException{
NodeList list = doc.getElementsByTagName("process");
if(list.getLength() != 1){
throw new IllegalArgumentException("You should specify exactly 1 process element!");
}
Element process = (Element) list.item(0);
IndexCreator.REMOVE_POI_DB = true;
String file = process.getAttribute("skipExistingIndexesAt");
if (file != null && new File(file).exists()) {
skipExistingIndexes = new File(file);
}
wget = process.getAttribute("wget");
indexPOI = Boolean.parseBoolean(process.getAttribute("indexPOI"));
indexMap = Boolean.parseBoolean(process.getAttribute("indexMap"));
indexRouting = process.getAttribute("indexRouting") == null ||
process.getAttribute("indexRouting").equalsIgnoreCase("true");
indexTransport = Boolean.parseBoolean(process.getAttribute("indexTransport"));
indexAddress = Boolean.parseBoolean(process.getAttribute("indexAddress"));
parseProcessAttributes(process);
list = doc.getElementsByTagName("process_attributes");
if(list.getLength() == 1){
parseProcessAttributes((Element) list.item(0));
}
String dir = process.getAttribute("directory_for_osm_files");
if(dir == null || !new File(dir).exists()) {
throw new IllegalArgumentException("Please specify directory with .osm or .osm.bz2 files as directory_for_osm_files (attribute)" + dir); //$NON-NLS-1$
}
osmDirFiles = new File(dir);
dir = process.getAttribute("directory_for_index_files");
if(dir == null || !new File(dir).exists()) {
throw new IllegalArgumentException("Please specify directory with generated index files as directory_for_index_files (attribute)"); //$NON-NLS-1$
}
indexDirFiles = new File(dir);
workDir = indexDirFiles;
dir = process.getAttribute("directory_for_generation");
if(dir != null && new File(dir).exists()) {
workDir = new File(dir);
}
List<RegionCountries> countriesToDownload = new ArrayList<RegionCountries>();
parseCountriesToDownload(doc, countriesToDownload);
if (regions != null) {
parseCountriesToDownload(regions, countriesToDownload);
}
runBatch(countriesToDownload);
}
private void parseCountriesToDownload(Document doc, List<RegionCountries> countriesToDownload) {
NodeList regions = doc.getElementsByTagName("regions");
for(int i=0; i< regions.getLength(); i++){
Element el = (Element) regions.item(i);
if(!Boolean.parseBoolean(el.getAttribute("skip"))){
RegionCountries countries = new RegionCountries();
countries.siteToDownload = el.getAttribute("siteToDownload");
if(countries.siteToDownload == null){
continue;
}
countries.namePrefix = el.getAttribute("region_prefix");
if(countries.namePrefix == null){
countries.namePrefix = "";
}
countries.nameSuffix = el.getAttribute("region_suffix");
if(countries.nameSuffix == null){
countries.nameSuffix = "";
}
NodeList ncountries = el.getElementsByTagName("region");
log.info("Region to download " +countries.siteToDownload);
for(int j=0; j< ncountries.getLength(); j++){
Element ncountry = (Element) ncountries.item(j);
String name = ncountry.getAttribute("name");
RegionSpecificData data = new RegionSpecificData();
data.cityAdminLevel = ncountry.getAttribute("cityAdminLevel");
if(name != null && !Boolean.parseBoolean(ncountry.getAttribute("skip"))){
countries.regionNames.put(name, data);
}
}
countriesToDownload.add(countries);
}
}
}
private void parseProcessAttributes(Element process) {
String zooms = process.getAttribute("mapZooms");
if(zooms == null || zooms.length() == 0){
mapZooms = MapZooms.getDefault();
} else {
mapZooms = MapZooms.parseZooms(zooms);
}
String szoomWaySmoothness = process.getAttribute("zoomWaySmoothness");
if(szoomWaySmoothness != null && !szoomWaySmoothness.equals("")){
zoomWaySmoothness = Integer.parseInt(szoomWaySmoothness);
}
String f = process.getAttribute("renderingTypesFile");
if(f == null || f.length() == 0){
types = MapRenderingTypes.getDefault();
} else {
types = new MapRenderingTypes(f);
}
String osmDbDialect = process.getAttribute("osmDbDialect");
if(osmDbDialect != null && osmDbDialect.length() > 0){
try {
this.osmDbDialect = DBDialect.valueOf(osmDbDialect.toUpperCase());
} catch (RuntimeException e) {
}
}
String mapDbDialect = process.getAttribute("mapDbDialect");
if (mapDbDialect != null && mapDbDialect.length() > 0) {
try {
this.mapDBDialect = DBDialect.valueOf(mapDbDialect.toUpperCase());
} catch (RuntimeException e) {
}
}
}
public void runBatch(List<RegionCountries> countriesToDownload ){
Set<String> alreadyGeneratedFiles = new LinkedHashSet<String>();
if(!countriesToDownload.isEmpty()){
downloadFilesAndGenerateIndex(countriesToDownload, alreadyGeneratedFiles);
}
generatedIndexes(alreadyGeneratedFiles);
}
protected void downloadFilesAndGenerateIndex(List<RegionCountries> countriesToDownload, Set<String> alreadyGeneratedFiles){
// clean before downloading
// for(File f : osmDirFiles.listFiles()){
// log.info("Delete old file " + f.getName()); //$NON-NLS-1$
// f.delete();
// }
for(RegionCountries regionCountries : countriesToDownload){
String prefix = regionCountries.namePrefix;
String site = regionCountries.siteToDownload;
String suffix = regionCountries.nameSuffix;
for(String name : regionCountries.regionNames.keySet()){
name = name.toLowerCase();
RegionSpecificData regionSpecificData = regionCountries.regionNames.get(name);
String url = MessageFormat.format(site, name);
String regionName = prefix + name;
String fileName = Algoritms.capitalizeFirstLetterAndLowercase(prefix + name + suffix);
if (skipExistingIndexes != null) {
File bmif = new File(skipExistingIndexes, fileName + "_" + IndexConstants.BINARY_MAP_VERSION
+ IndexConstants.BINARY_MAP_INDEX_EXT);
File bmifz = new File(skipExistingIndexes, bmif.getName() + ".zip");
if (bmif.exists() || bmifz.exists()) {
continue;
}
}
File toSave = downloadFile(url, fileName);
if (toSave != null) {
generateIndex(toSave, regionName, regionSpecificData, alreadyGeneratedFiles);
}
}
}
}
protected File downloadFile(String url, String regionName) {
String ext = ".osm";
if(url.endsWith(".osm.bz2")){
ext = ".osm.bz2";
} else if(url.endsWith(".pbf")){
ext = ".osm.pbf";
}
File toIndex = null;
File saveTo = new File(osmDirFiles, regionName + ext);
if (wget == null || wget.trim().length() == 0) {
toIndex = internalDownload(url, saveTo);
} else {
toIndex = wgetDownload(url, saveTo);
}
if(toIndex == null) {
saveTo.delete();
}
return toIndex;
}
private File wgetDownload(String url, File toSave)
{
BufferedReader wgetOutput = null;
OutputStream wgetInput = null;
Process wgetProc = null;
try {
log.info("Executing " + wget + " " + url + " -O "+ toSave.getCanonicalPath()); //$NON-NLS-1$//$NON-NLS-2$ $NON-NLS-3$
ProcessBuilder exec = new ProcessBuilder(wget, "--read-timeout=5", "--progress=dot:binary", url, "-O", //$NON-NLS-1$//$NON-NLS-2$ $NON-NLS-3$
toSave.getCanonicalPath());
exec.redirectErrorStream(true);
wgetProc = exec.start();
wgetOutput = new BufferedReader(new InputStreamReader(wgetProc.getInputStream()));
String line;
while ((line = wgetOutput.readLine()) != null) {
log.info("wget output:" + line); //$NON-NLS-1$
}
int exitValue = wgetProc.waitFor();
wgetProc = null;
if (exitValue != 0) {
log.error("Wget exited with error code: " + exitValue); //$NON-NLS-1$
} else {
return toSave;
}
} catch (IOException e) {
log.error("Input/output exception " + toSave.getName() + " downloading from " + url + "using wget: " + wget, e); //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-3$
} catch (InterruptedException e) {
log.error("Interrupted exception " + toSave.getName() + " downloading from " + url + "using wget: " + wget, e); //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-3$
} finally {
safeClose(wgetOutput, ""); //$NON-NLS-1$
safeClose(wgetInput, ""); //$NON-NLS-1$
if (wgetProc != null) {
wgetProc.destroy();
}
}
return null;
}
private final static int DOWNLOAD_DEBUG = 1 << 20;
private final static int BUFFER_SIZE = 1 << 15;
private File internalDownload(String url, File toSave) {
int count = 0;
int downloaded = 0;
int mbDownloaded = 0;
byte[] buffer = new byte[BUFFER_SIZE];
OutputStream ostream = null;
InputStream stream = null;
try {
ostream = new FileOutputStream(toSave);
stream = new URL(url).openStream();
log.info("Downloading country " + toSave.getName() + " from " + url); //$NON-NLS-1$//$NON-NLS-2$
while ((count = stream.read(buffer)) != -1) {
ostream.write(buffer, 0, count);
downloaded += count;
if(downloaded > DOWNLOAD_DEBUG){
downloaded -= DOWNLOAD_DEBUG;
mbDownloaded += (DOWNLOAD_DEBUG>>20);
log.info(mbDownloaded +" megabytes downloaded of " + toSave.getName());
}
}
return toSave;
} catch (IOException e) {
log.error("Input/output exception " + toSave.getName() + " downloading from " + url, e); //$NON-NLS-1$ //$NON-NLS-2$
} finally {
safeClose(ostream, "Input/output exception " + toSave.getName() + " to close stream "); //$NON-NLS-1$ //$NON-NLS-2$
safeClose(stream, "Input/output exception " + url + " to close stream "); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
private static void safeClose(Closeable ostream, String message) {
if (ostream != null) {
try {
ostream.close();
} catch (Exception e) {
log.error(message, e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
protected void generatedIndexes(Set<String> alreadyGeneratedFiles) {
for (File f : getSortedFiles(osmDirFiles)) {
if (alreadyGeneratedFiles.contains(f.getName())) {
continue;
}
if (f.getName().endsWith(".osm.bz2") || f.getName().endsWith(".osm") || f.getName().endsWith(".osm.pbf")) {
if (skipExistingIndexes != null) {
int i = f.getName().indexOf(".osm");
String name = Algoritms.capitalizeFirstLetterAndLowercase(f.getName().substring(0, i));
File bmif = new File(skipExistingIndexes, name + "_" + IndexConstants.BINARY_MAP_VERSION
+ IndexConstants.BINARY_MAP_INDEX_EXT_ZIP);
log.info("Check if " + bmif.getAbsolutePath() + " exists");
if (bmif.exists()) {
continue;
}
}
generateIndex(f, null, null, alreadyGeneratedFiles);
}
}
log.info("GENERATING INDEXES FINISHED ");
}
protected void generateIndex(File f, String rName, RegionSpecificData regionSpecificData, Set<String> alreadyGeneratedFiles) {
try {
// be independent of previous results
RTree.clearCache();
String regionName = f.getName();
log.warn("-------------------------------------------");
log.warn("----------- Generate " + f.getName() + "\n\n\n");
int i = f.getName().indexOf('.');
if (i > -1) {
regionName = Algoritms.capitalizeFirstLetterAndLowercase(f.getName().substring(0, i));
}
if(Algoritms.isEmpty(rName)){
rName = regionName;
} else {
rName = Algoritms.capitalizeFirstLetterAndLowercase(rName);
}
DBDialect osmDb = this.osmDbDialect;
if(f.length() / 1024 / 1024 > INMEM_LIMIT && osmDb == DBDialect.SQLITE_IN_MEMORY) {
log.warn("Switching SQLITE in memory dialect to SQLITE");
osmDb = DBDialect.SQLITE;
}
IndexCreator indexCreator = new IndexCreator(workDir);
indexCreator.setDialects(osmDb, this.mapDBDialect);
indexCreator.setIndexAddress(indexAddress);
indexCreator.setIndexPOI(indexPOI);
indexCreator.setIndexTransport(indexTransport);
indexCreator.setIndexMap(indexMap);
indexCreator.setIndexRouting(indexRouting);
indexCreator.setLastModifiedDate(f.lastModified());
indexCreator.setNormalizeStreets(true);
indexCreator.setRegionName(rName);
if (regionSpecificData != null && regionSpecificData.cityAdminLevel != null) {
indexCreator.setCityAdminLevel(regionSpecificData.cityAdminLevel);
}
if(zoomWaySmoothness != null){
indexCreator.setZoomWaySmothness(zoomWaySmoothness);
}
String mapFileName = regionName + "_" + IndexConstants.BINARY_MAP_VERSION + IndexConstants.BINARY_MAP_INDEX_EXT;
indexCreator.setMapFileName(mapFileName);
try {
alreadyGeneratedFiles.add(f.getName());
Log warningsAboutMapData = null;
File logFileName = new File(workDir, mapFileName + GEN_LOG_EXT);
FileHandler fh = null;
// configure log path
try {
FileOutputStream fout = new FileOutputStream(logFileName);
fout.write((new Date() + "\n").getBytes());
fout.write((MapCreatorVersion.APP_MAP_CREATOR_FULL_NAME + "\n").getBytes());
fout.close();
fh = new FileHandler(logFileName.getAbsolutePath(), 5000000, 1, true);
fh.setFormatter(new SimpleFormatter());
fh.setLevel(Level.ALL);
Jdk14Logger jdk14Logger = new Jdk14Logger("tempLogger");
jdk14Logger.getLogger().setLevel(Level.ALL);
jdk14Logger.getLogger().setUseParentHandlers(false);
jdk14Logger.getLogger().addHandler(fh);
warningsAboutMapData = jdk14Logger;
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
if (fh != null) {
LogManager.getLogManager().getLogger("").addHandler(fh);
}
try {
indexCreator.generateIndexes(f, new ConsoleProgressImplementation(1), null, mapZooms, types, warningsAboutMapData);
} finally {
if (fh != null) {
fh.close();
LogManager.getLogManager().getLogger("").removeHandler(fh);
}
}
File generated = new File(workDir, mapFileName);
generated.renameTo(new File(indexDirFiles, generated.getName()));
File copyLog = new File(indexDirFiles, logFileName.getName());
FileOutputStream fout = new FileOutputStream(copyLog);
FileInputStream fin = new FileInputStream(logFileName);
Algoritms.streamCopy(fin, fout);
fin.close();
fout.close();
// logFileName.renameTo(new File(indexDirFiles, logFileName.getName()));
} catch (Exception e) {
log.error("Exception generating indexes for " + f.getName(), e); //$NON-NLS-1$
}
} catch (OutOfMemoryError e) {
System.gc();
log.error("OutOfMemory", e);
}
System.gc();
}
protected File[] getSortedFiles(File dir){
File[] listFiles = dir.listFiles();
Arrays.sort(listFiles, new Comparator<File>(){
@Override
public int compare(File o1, File o2) {
return o1.getName().compareTo(o2.getName());
}
});
return listFiles;
}
}

View file

@ -1,896 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import net.osmand.Algoritms;
import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.IndexConstants;
import net.osmand.data.index.ExtractGooglecodeAuthorization.GooglecodeUploadTokens;
import org.apache.commons.logging.Log;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
/**
* This helper will find obf and zip files, create description for them, and zip them, or update the description.
* This helper also can upload files through ssh,ftp or to googlecode.
*
* IndexUploader dir targetDir [--ff=file] [--fp=ptns] [--ep=ptns] [--dp=ptns] [-ssh|-ftp|-google] [--password=|--user=|--url=|--path=|--gpassword=|--privKey=|--knownHosts=]
* --ff file with names of files to be uploaded from the dir, supporting regexp
* --fp comma separated names of files to be uploaded from the dir, supporting regexp
* --ep comma separated names of files to be excluded from upload, supporting regexp
* --dp comma separated names of files to be delete on remote system, supporting regexp
* One of:
* -ssh to upload to ssh site
* -fpt to upload to ftp site
* -google to upload to googlecode of osmand
* Additional params:
* --user user to use for ftp,ssh,google
* --password password to use for ftp,ssh,google (gmail password to retrieve tokens for deleting files)
* --url url to use for ssh,ftp
* --path path in url to use for ssh,ftp
* --gpassword googlecode password to use for google
* --privKey priv key for ssh
* --knownHosts known hosts for ssh
*
* @author Pavol Zibrita <pavol.zibrita@gmail.com>
*/
public class IndexUploader {
protected static final Log log = LogUtil.getLog(IndexUploader.class);
private final static double MIN_SIZE_TO_UPLOAD = 0.001d;
private final static double MAX_SIZE_TO_NOT_SPLIT = 190d;
private final static double MAX_UPLOAD_SIZE = 195d;
private final static int BUFFER_SIZE = 1 << 15;
private final static int MB = 1 << 20;
/**
* Something bad have happend
*/
public static class IndexUploadException extends Exception {
private static final long serialVersionUID = 2343219168909577070L;
public IndexUploadException(String message) {
super(message);
}
public IndexUploadException(String message, Throwable e) {
super(message, e);
}
}
/**
* Processing of one file failed, but other files could continue
*/
public static class OneFileException extends Exception {
private static final long serialVersionUID = 6463200194419498979L;
public OneFileException(String message) {
super(message);
}
}
private File directory;
private File targetDirectory;
private UploadCredentials uploadCredentials = new DummyCredentials();
private FileFilter fileFilter = new FileFilter();
private FileFilter deleteFileFilter = null;
private boolean roadProcess;
public IndexUploader(String path, String targetPath) throws IndexUploadException {
directory = new File(path);
if (!directory.isDirectory()) {
throw new IndexUploadException("Not a directory:" + path);
}
targetDirectory = new File(targetPath);
if (!targetDirectory.isDirectory()) {
throw new IndexUploadException("Not a directory:" + targetPath);
}
}
public static void main(String[] args) {
try {
String srcPath = extractDirectory(args, 0);
String targetPath = srcPath;
if (args.length > 1) {
targetPath = extractDirectory(args, 1);
}
IndexUploader indexUploader = new IndexUploader(srcPath, targetPath);
if(args.length > 2) {
indexUploader.parseParameters(args, 2);
}
indexUploader.run();
} catch (IndexUploadException e) {
log.error(e.getMessage());
}
}
private void parseParameters(String[] args, int start) throws IndexUploadException {
int idx = parseFilter(args, start);
if (args.length > idx) {
parseUploadCredentials(args, idx);
}
}
private int parseFilter(String[] args, int start) throws IndexUploadException {
FileFilter fileFilter = null;
int p;
do {
p = start;
if (args[start].startsWith("--ff=")) {
try {
if (fileFilter == null) {
fileFilter = new FileFilter();
}
fileFilter.parseFile(args[start].substring("--ff=".length()));
} catch (IOException e) {
throw new IndexUploadException(e.getMessage());
}
start++;
} else if (args[start].startsWith("--fp=")) {
if (fileFilter == null) {
fileFilter = new FileFilter();
}
fileFilter.parseCSV(args[start].substring("--fp=".length()));
start++;
} else if (args[start].startsWith("--ep=")) {
if (fileFilter == null) {
throw new NullPointerException();
}
fileFilter.parseExcludeCSV(args[start].substring("--ep=".length()));
start++;
} else if (args[start].startsWith("--dp=")) {
deleteFileFilter = new FileFilter();
deleteFileFilter.parseCSV(args[start].substring("--dp=".length()));
start++;
} else if (args[start].startsWith("--roads")) {
roadProcess = true;
start++;
}
} while(p != start);
if(fileFilter != null) {
this.fileFilter = fileFilter;
}
return start;
}
protected void parseUploadCredentials(String[] args, int start) throws IndexUploadException {
if ("-ssh".equals(args[start])) {
uploadCredentials = new UploadSSHCredentials();
} else if ("-ftp".equals(args[start])) {
uploadCredentials = new UploadFTPCredentials();
} else if ("-google".equals(args[start])){
uploadCredentials = new UploadToGoogleCodeCredentials();
} else {
return;
}
for (int i = start + 1; i < args.length; i++) {
uploadCredentials.parseParameter(args[i]);
}
}
public void setUploadCredentials(UploadCredentials uploadCredentials) {
this.uploadCredentials = uploadCredentials;
}
protected static class FileFilter {
private List<Pattern> matchers = null;
private List<Pattern> exculdeMatchers = null;
public void parseCSV(String patterns){
String[] s = patterns.split(",");
if(matchers == null) {
matchers = new ArrayList<Pattern>();
}
for(String p : s) {
matchers.add(Pattern.compile(p.trim()));
}
}
public void parseExcludeCSV(String patterns){
String[] s = patterns.split(",");
if(exculdeMatchers == null) {
exculdeMatchers = new ArrayList<Pattern>();
}
for(String p : s) {
exculdeMatchers.add(Pattern.compile(p.trim()));
}
}
public void parseFile(String file) throws IOException{
File f = new File(file);
if (f.exists()) {
readPatterns(f);
}
}
private void readPatterns(File f) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(f));
try {
String line;
if(matchers == null) {
matchers = new ArrayList<Pattern>();
}
while ((line = reader.readLine()) != null) {
matchers.add(Pattern.compile(line));
}
} finally {
Algoritms.closeStream(reader);
}
}
public boolean patternMatches(String name){
return internalPatternMatches(name, matchers);
}
public boolean internalPatternMatches(String name, List<Pattern> matchers ){
if(matchers == null) {
return true;
}
for (Pattern p : matchers) {
if (p.matcher(name).matches()) {
return true;
}
}
return false;
}
protected boolean fileCanBeUploaded(File f) {
if (!f.isFile() || f.getName().endsWith(IndexBatchCreator.GEN_LOG_EXT)) {
return false;
}
boolean matches = internalPatternMatches(f.getName(), matchers);
if(matches && exculdeMatchers != null && internalPatternMatches(f.getName(), exculdeMatchers)) {
return false;
}
return matches;
}
}
public void run() throws IndexUploadException {
// take files before whole upload process
try {
uploadCredentials.connect();
File[] listFiles = directory.listFiles();
for (File f : listFiles) {
try {
if (!fileFilter.fileCanBeUploaded(f)) {
continue;
}
long timestampCreated = f.lastModified();
if(!uploadCredentials.checkIfUploadNeededByTimestamp(f.getName(), timestampCreated)) {
log.info("File skipped because timestamp was not changed " + f.getName() );
continue;
}
log.info("Process file " + f.getName());
File unzipped = unzip(f);
boolean skip = false;
File logFile = new File(f.getParentFile(), unzipped.getName() + IndexBatchCreator.GEN_LOG_EXT);
try {
String description = checkfileAndGetDescription(unzipped);
if(description == null) {
log.info("Skip file " + f.getName());
skip = true;
} else {
List<File> files = new ArrayList<File>();
files.add(unzipped);
if (logFile.exists()) {
files.add(logFile);
}
File zFile = new File(f.getParentFile(), unzipped.getName() + ".zip");
zip(files, zFile, description, timestampCreated);
uploadIndex(f, zFile, description, uploadCredentials);
}
} finally {
if (!skip) {
if (!f.getName().equals(unzipped.getName()) || (targetDirectory != null && !targetDirectory.equals(directory))) {
unzipped.delete(); // delete the unzipped file
}
if (logFile.exists()) {
logFile.delete();
}
}
}
} catch (OneFileException e) {
log.error(f.getName() + ": " + e.getMessage(), e);
} catch (RuntimeException e) {
log.error(f.getName() + ": " + e.getMessage(), e);
}
}
if(deleteFileFilter != null) {
if(uploadCredentials instanceof UploadToGoogleCodeCredentials) {
log.info("About to delete files from googlecode");
Map<String, String> files = DownloaderIndexFromGoogleCode.getIndexFiles(new LinkedHashMap<String, String>());
for (String f : files.keySet()) {
if (deleteFileFilter.patternMatches(f)) {
log.info("About to delete " + f);
try {
DownloaderIndexFromGoogleCode.deleteFileFromGoogleDownloads(f, ((UploadToGoogleCodeCredentials)uploadCredentials).ggtokens);
} catch (IOException e) {
throw new IndexUploadException("Delete " + f + " was failed", e);
}
}
}
} else {
log.error("Delete file filter is not supported with this credentions (method) " + uploadCredentials);
}
}
} finally {
uploadCredentials.disconnect();
}
}
public static File zip(List<File> fs, File zFile, String description, long lastModifiedTime) throws OneFileException {
try {
ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zFile));
zout.setLevel(9);
for (File f : fs) {
log.info("Zipping to file: " + zFile.getName() + " file:" + f.getName() + " with desc:" + description);
ZipEntry zEntry = new ZipEntry(f.getName());
zEntry.setSize(f.length());
zEntry.setComment(description);
zout.putNextEntry(zEntry);
FileInputStream is = new FileInputStream(f);
Algoritms.streamCopy(is, zout);
Algoritms.closeStream(is);
}
Algoritms.closeStream(zout);
zFile.setLastModified(lastModifiedTime);
} catch (IOException e) {
throw new OneFileException("cannot zip file:" + e.getMessage());
}
return zFile;
}
private String checkfileAndGetDescription(File f) throws OneFileException {
String fileName = f.getName();
if (fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT) || fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(f, "r");
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
if(reader.getVersion() != IndexConstants.BINARY_MAP_VERSION) {
throw new OneFileException("Uploader version is not compatible " + reader.getVersion() + " to current " + IndexConstants.BINARY_MAP_VERSION);
}
boolean roadFile = reader.containsRouteData() && !reader.containsMapData();
if(roadFile != this.roadProcess) {
return null;
}
String summary = getDescription(reader, fileName);
reader.close();
return summary;
} catch (IOException e) {
if (raf != null) {
try {
raf.close();
} catch (IOException e1) {
}
}
throw new OneFileException("Reader could not read the index: " + e.getMessage());
}
} else {
throw new OneFileException("Not supported file format " + fileName);
}
}
private String getDescription(BinaryMapIndexReader reader, String fileName) {
String summary;
summary = " index for ";
boolean fir = true;
if (reader.containsAddressData()) {
summary = "Address" + (fir ? "" : ", ") + summary;
fir = false;
}
if (reader.hasTransportData()) {
summary = "Transport" + (fir ? "" : ", ") + summary;
fir = false;
}
if (reader.containsPoiData()) {
summary = "POI" + (fir ? "" : ", ") + summary;
fir = false;
}
if (reader.containsRouteData()) {
summary = "Roads" + (fir ? "" : ", ") + summary;
fir = false;
}
if (reader.containsMapData()) {
summary = "Map" + (fir ? "" : ", ") + summary;
fir = false;
}
int last = fileName.lastIndexOf('_', fileName.indexOf('.'));
if (last == -1) {
last = fileName.indexOf('.');
}
String regionName = fileName.substring(0, last);
summary += regionName;
summary = summary.replace('_', ' ');
return summary;
}
private File unzip(File f) throws OneFileException {
try {
if (!Algoritms.isZipFile(f)) {
return f;
}
log.info("Unzipping file: " + f.getName());
ZipFile zipFile;
zipFile = new ZipFile(f);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
File mainFile = null;
long slastModified = f.lastModified();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
long lastModified = slastModified;
if(entry.getTime() < lastModified) {
lastModified = entry.getTime();
}
File tempFile = new File(f.getParentFile(), entry.getName());
InputStream zin = zipFile.getInputStream(entry);
FileOutputStream out = new FileOutputStream(tempFile);
Algoritms.streamCopy(zin, out);
Algoritms.closeStream(zin);
Algoritms.closeStream(out);
if (!tempFile.getName().endsWith(IndexConstants.GEN_LOG_EXT)) {
mainFile = tempFile;
}
tempFile.setLastModified(lastModified);
}
return mainFile;
} catch (ZipException e) {
throw new OneFileException("cannot unzip:" + e.getMessage());
} catch (IOException e) {
throw new OneFileException("cannot unzip:" + e.getMessage());
}
}
private List<File> splitFiles(File f) throws IOException {
double mbLengh = (double) f.length() / MB;
if (mbLengh < MAX_SIZE_TO_NOT_SPLIT) {
return Collections.singletonList(f);
} else {
ArrayList<File> arrayList = new ArrayList<File>();
FileInputStream in = new FileInputStream(f);
byte[] buffer = new byte[BUFFER_SIZE];
int i = 1;
int read = 0;
while (read != -1) {
File fout = new File(f.getParent(), f.getName() + "-" + i);
arrayList.add(fout);
FileOutputStream fo = new FileOutputStream(fout);
int limit = (int) (MAX_SIZE_TO_NOT_SPLIT * MB);
while (limit > 0 && ((read = in.read(buffer)) != -1)) {
fo.write(buffer, 0, read);
limit -= read;
}
fo.flush();
fo.close();
i++;
}
in.close();
return arrayList;
}
}
private void uploadIndex(File srcFile, File zipFile, String summary, UploadCredentials uc) {
double mbLengh = (double) zipFile.length() / MB;
String fileName = zipFile.getName();
if (mbLengh < MIN_SIZE_TO_UPLOAD) {
log.info("Skip uploading index due to size " + fileName);
// do not upload small files
}
try {
log.info("Upload index " + fileName);
File toUpload = zipFile;
boolean uploaded = uploadFileToServer(toUpload, summary, uc);
// remove source file if file was splitted
if (uploaded && targetDirectory != null && !targetDirectory.equals(directory)) {
File toBackup = new File(targetDirectory, toUpload.getName());
if (toBackup.exists()) {
toBackup.delete();
}
toUpload.renameTo(toBackup);
if(srcFile.equals(zipFile)){
srcFile.delete();
}
}
} catch (IOException e) {
log.error("Input/output exception uploading " + fileName, e);
}
}
private static String extractDirectory(String[] args, int ind) throws IndexUploadException {
if (args.length > ind) {
if ("-h".equals(args[0])) {
throw new IndexUploadException("Usage: IndexZipper [directory] (if not specified, the current one will be taken)");
} else {
return args[ind];
}
}
return ".";
}
public abstract static class UploadCredentials {
String password;
String user;
String url;
String path;
protected void parseParameter(String param) throws IndexUploadException {
if (param.startsWith("--url=")) {
url = param.substring("--url=".length());
} else if (param.startsWith("--password=")) {
password = param.substring("--password=".length());
} else if (param.startsWith("--user=")) {
user = param.substring("--user=".length());
} else if (param.startsWith("--path=")) {
path = param.substring("--path=".length());
}
}
public boolean checkIfUploadNeededByTimestamp(String filename, long time) {
return true;
}
public void disconnect() {
//if the uploading needs to close a session
}
public void connect() throws IndexUploadException {
//if the uploading needs to open a session
}
public abstract void upload(IndexUploader uploader, File toUpload, String summary, String size, String date) throws IOException, JSchException;
}
public static class DummyCredentials extends UploadCredentials {
@Override
public void upload(IndexUploader uploader, File toUpload,
String summary, String size, String date) throws IOException,
JSchException {
//do nothing
}
}
public static class UploadFTPCredentials extends UploadCredentials {
@Override
public void upload(IndexUploader uploader, File toUpload,
String summary, String size, String date) throws IOException,
JSchException {
uploader.uploadToFTP(toUpload, summary, size, date, this);
}
}
public static class UploadSSHCredentials extends UploadCredentials {
String privateKey;
String knownHosts;
@Override
protected void parseParameter(String param) throws IndexUploadException {
super.parseParameter(param);
if (param.startsWith("--privKey=")) {
privateKey = param.substring("--privKey=".length());
} else if (param.startsWith("--knownHosts=")) {
knownHosts = param.substring("--knownHosts=".length());
}
}
@Override
public void upload(IndexUploader uploader, File toUpload,
String summary, String size, String date) throws IOException, JSchException {
uploader.uploadToSSH(toUpload, summary, size, date, this);
}
}
public static class UploadToGoogleCodeCredentials extends UploadCredentials {
GooglecodeUploadTokens ggtokens;
String gpassword;
private Map<String, String> uploaded = new HashMap<String, String>();
@Override
protected void parseParameter(String param) throws IndexUploadException {
super.parseParameter(param);
if (param.startsWith("--gpassword=")) {
gpassword = param.substring("--gpassword=".length());
}
if (gpassword != null && user != null && ggtokens == null) {
ExtractGooglecodeAuthorization tool = new ExtractGooglecodeAuthorization();
try {
ggtokens = tool.getGooglecodeTokensForUpload(user, gpassword);
} catch (IOException e) {
throw new IndexUploadException(e.getMessage());
}
}
}
@Override
public void connect() throws IndexUploadException {
if (ggtokens == null || user == null || password == null) {
throw new IndexUploadException("Not enought googlecode credentials entered!");
}
Map<String, String> uploadedDes = DownloaderIndexFromGoogleCode.getIndexFiles(new HashMap<String, String>());
for(String fileName : uploadedDes.keySet()) {
String description = uploadedDes.get(fileName);
int o = description.indexOf('{');
if(o != -1 && description.length() > o + 11) {
uploaded.put(fileName, description.substring(o+1, o+11));
}
}
}
@Override
public boolean checkIfUploadNeededByTimestamp(String filename, long time) {
String date = new MessageFormat("{0,date,dd.MM.yyyy}", Locale.US).format(new Object[]{new Date(time)});
if (uploaded.containsKey(filename) && date.equals(uploaded.get(filename))) {
return false;
}
filename += "-1";
if (uploaded.containsKey(filename) && date.equals(uploaded.get(filename))) {
return false;
}
return true;
}
@Override
public void upload(IndexUploader uploader, File toUpload,
String summary, String size, String date) throws IOException,
JSchException {
if (uploaded.containsKey(toUpload.getName()) && date.equals(uploaded.get(toUpload.getName()))) {
return;
}
String descriptionFile = "{" + date + " : " + size + " MB}";
summary += " " + descriptionFile;
List<File> splittedFiles = Collections.emptyList();
try {
splittedFiles = uploader.splitFiles(toUpload);
for (File fs : splittedFiles) {
if (uploaded.containsKey(fs.getName()) && date.equals(uploaded.get(fs.getName()))) {
return;
}
uploader.uploadToGoogleCode(fs, summary, this);
}
} finally {
// remove all splitted files
for (File fs : splittedFiles) {
if (!fs.equals(toUpload)) {
fs.delete();
}
}
}
}
}
public void uploadToGoogleCode(File f, String summary, UploadToGoogleCodeCredentials gc) throws IOException {
if (f.length() / MB > MAX_UPLOAD_SIZE) {
System.err.println("ERROR : file " + f.getName() + " exceeded 200 mb!!! Could not be uploaded.");
throw new IOException("ERROR : file " + f.getName() + " exceeded 200 mb!!! Could not be uploaded.");
// restriction for google code
}
try {
DownloaderIndexFromGoogleCode.deleteFileFromGoogleDownloads(f.getName(), gc.ggtokens);
if (f.getName().endsWith("obf.zip") && f.length() / MB < 5) {
// try to delete without .zip part
DownloaderIndexFromGoogleCode.deleteFileFromGoogleDownloads(f.getName().substring(0, f.getName().length() - 4), gc.ggtokens);
} else if (f.getName().endsWith("poi.zip") && f.length() / MB < 5) {
// try to delete without .zip part
DownloaderIndexFromGoogleCode.deleteFileFromGoogleDownloads(f.getName().substring(0, f.getName().length() - 3) + "odb", gc.ggtokens);
} else if (f.getName().endsWith(".zip-1")) {
DownloaderIndexFromGoogleCode.deleteFileFromGoogleDownloads(f.getName().substring(0, f.getName().length() - 2), gc.ggtokens);
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// wait 5 seconds
}
} catch (IOException e) {
log.warn("Deleting file from downloads" + f.getName() + " " + e.getMessage());
}
GoogleCodeUploadIndex uploader = new GoogleCodeUploadIndex();
uploader.setFileName(f.getAbsolutePath());
uploader.setTargetFileName(f.getName());
uploader.setProjectName("osmand");
uploader.setUserName(gc.user);
uploader.setPassword(gc.password);
uploader.setLabels("Type-Archive, Testdata");
uploader.setSummary(summary);
uploader.setDescription(summary);
uploader.upload();
}
public boolean uploadFileToServer(File toUpload, String summary, UploadCredentials credentials) throws IOException {
double originalLength = (double) toUpload.length() / MB;
MessageFormat dateFormat = new MessageFormat("{0,date,dd.MM.yyyy}", Locale.US);
MessageFormat numberFormat = new MessageFormat("{0,number,##.#}", Locale.US);
String size = numberFormat.format(new Object[] { originalLength });
String date = dateFormat.format(new Object[] { new Date(toUpload.lastModified()) });
try {
credentials.upload(this,toUpload,summary,size,date);
} catch (IOException e) {
log.error("Input/output exception uploading " + toUpload.getName(), e);
return false;
} catch (JSchException e) {
log.error("Input/output exception uploading " + toUpload.getName(), e);
return false;
}
return true;
}
public void uploadToFTP(File f, String description, String size, String date, UploadCredentials credentials)
throws IOException {
log.info("Uploading file " + f.getName() + " " + size + " MB " + date + " of " + description);
// Upload to ftp
FTPFileUpload upload = new FTPFileUpload();
String serverName = credentials.url;
if(serverName.startsWith("ftp://")){
serverName = serverName.substring("ftp://".length());
}
upload.upload(serverName, credentials.password, credentials.password, credentials.path + "" + f.getName(), f, 1 << 15);
log.info("Finish uploading file index");
}
public void uploadToSSH(File f, String description, String size, String date, UploadSSHCredentials cred) throws IOException,
JSchException {
log.info("Uploading file " + f.getName() + " " + size + " MB " + date + " of " + description);
// Upload to ftp
JSch jSch = new JSch();
boolean knownHosts = false;
if (cred.knownHosts != null) {
jSch.setKnownHosts(cred.knownHosts);
knownHosts = true;
}
if (cred.privateKey != null) {
jSch.addIdentity(cred.privateKey);
}
String serverName = cred.url;
if (serverName.startsWith("ssh://")) {
serverName = serverName.substring("ssh://".length());
}
Session session = jSch.getSession(cred.user, serverName);
if (cred.password != null) {
session.setPassword(cred.password);
}
if(!knownHosts) {
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
}
String rfile = cred.path + "/"+ f.getName();
String lfile = f.getAbsolutePath();
session.connect();
// exec 'scp -t rfile' remotely
String command = "scp -p -t " + rfile;
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream();
channel.connect();
if (checkAck(in) != 0) {
channel.disconnect();
session.disconnect();
return;
}
// send "C0644 filesize filename", where filename should not include '/'
long filesize = (new File(lfile)).length();
command = "C0644 " + filesize + " ";
if (lfile.lastIndexOf('/') > 0) {
command += lfile.substring(lfile.lastIndexOf('/') + 1);
} else {
command += lfile;
}
command += "\n";
out.write(command.getBytes());
out.flush();
if (checkAck(in) != 0) {
channel.disconnect();
session.disconnect();
return;
}
// send a content of lfile
FileInputStream fis = new FileInputStream(lfile);
byte[] buf = new byte[1024];
try {
int len;
while ((len = fis.read(buf, 0, buf.length)) > 0) {
out.write(buf, 0, len); // out.flush();
}
} finally {
fis.close();
}
fis = null;
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (checkAck(in) != 0) {
channel.disconnect();
session.disconnect();
return;
}
out.close();
channel.disconnect();
session.disconnect();
log.info("Finish uploading file index");
}
static int checkAck(InputStream in) throws IOException {
int b = in.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if (b == 0)
return b;
if (b == -1)
return b;
if (b == 1 || b == 2) {
StringBuffer sb = new StringBuffer();
int c;
do {
c = in.read();
sb.append((char) c);
} while (c != '\n');
if (b == 1) { // error
System.out.print(sb.toString());
}
if (b == 2) { // fatal error
System.out.print(sb.toString());
}
}
return b;
}
}

View file

@ -1,54 +0,0 @@
package net.osmand.data.index;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;
public class MyCookieStore implements CookieStore {
private final CookieStore cookieStore;
public MyCookieStore(CookieStore cookieStore) {
this.cookieStore = cookieStore;
}
@Override
public void add(URI uri, HttpCookie cookie) {
cookieStore.add(uri, cookie);
}
@Override
public List<HttpCookie> get(URI uri) {
return cookieStore.get(uri);
}
@Override
public List<HttpCookie> getCookies() {
return cookieStore.getCookies();
}
@Override
public List<URI> getURIs() {
return cookieStore.getURIs();
}
@Override
public boolean remove(URI uri, HttpCookie cookie) {
return cookieStore.remove(uri, cookie);
}
@Override
public boolean removeAll() {
return cookieStore.removeAll();
}
public String getCookie(String key) {
for (HttpCookie c : cookieStore.getCookies()) {
if (c.getName().equals(key)) {
return c.getValue();
}
}
return null;
}
}

View file

@ -1,702 +0,0 @@
package net.osmand.data.index;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.logging.Log;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import net.osmand.Algoritms;
import net.osmand.LogUtil;
import net.osmand.MapCreatorVersion;
import net.osmand.data.IndexConstants;
import net.osmand.data.preparation.IndexCreator;
import net.osmand.impl.ConsoleProgressImplementation;
// http://toolserver.org/~dispenser/dumps/coord_commonswiki.sql.gz
// select * from coord_commonswiki limit 10;
public class WikiIndexer {
private static final Log log = LogUtil.getLog(WikiIndexer.class);
private final File srcPath;
private final File workPath;
private final File targetPath;
private final String userName = "jenkins";
private final String password = "jenkins";
private final String url = "jdbc:mysql://localhost/wiki";
private final File srcDone;
public static class WikiIndexerException extends Exception {
private static final long serialVersionUID = 1L;
public WikiIndexerException(String name) {
super(name);
}
public WikiIndexerException(String string, Exception e) {
super(string, e);
}
}
public WikiIndexer(File srcPath, File targetPath, File workPath, File srcDone) {
this.srcPath = srcPath;
this.targetPath = targetPath;
this.workPath = workPath;
this.srcDone = srcDone;
}
public static void main(String[] args) {
try {
File srcPath = extractDirectory(args, 0);
File targetPath = extractDirectory(args, 1);
File workPath = extractDirectory(args, 2);
File srcDone = srcPath;
for (int i = 3; i < args.length; i++) {
if(args[i].startsWith("--source-done=")){
srcDone = new File(srcPath, args[i].substring("--source-done=".length()));
// } else if(args[i].startsWith("--description=")){
}
}
WikiIndexer wikiIndexer = new WikiIndexer(srcPath, targetPath, workPath, srcDone);
wikiIndexer.run();
} catch (WikiIndexerException e) {
log.error(e.getMessage());
}
}
private static File extractDirectory(String[] args, int ind) throws WikiIndexerException {
if (args.length <= ind) {
throw new WikiIndexerException(
"Usage: WikiIndexer src_directory target_directory work_directory [--description={full|normal|minimum}]" + " missing "
+ (ind + 1));
} else {
File fs = new File(args[ind]);
fs.mkdir();
if (!fs.exists() || !fs.isDirectory()) {
throw new WikiIndexerException("Specified directory doesn't exist : " + args[ind]);
}
return fs;
}
}
public void run() throws WikiIndexerException {
log.info("Obtain database connection");
Connection conn;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url, userName, password);
log.info("Database connection established");
} catch (InstantiationException e1) {
throw new WikiIndexerException("Could not establish connection to " + url + " with " + userName, e1);
} catch (IllegalAccessException e1) {
throw new WikiIndexerException("Could not establish connection to " + url + " with " + userName, e1);
} catch (ClassNotFoundException e1) {
throw new WikiIndexerException("Could not establish connection to " + url + " with " + userName, e1);
} catch (SQLException e1) {
throw new WikiIndexerException("Could not establish connection to " + url + " with " + userName, e1);
}
File[] listFiles = srcPath.listFiles();
for (File f : listFiles) {
try {
if (f.isFile() && (f.getName().endsWith(".xml") || f.getName().endsWith(".xml.bz2"))) {
log.info("About to process " + f.getName());
File outFile = process(f, conn);
if (outFile != null) {
f.renameTo(new File(srcDone, f.getName()));
IndexCreator ic = new IndexCreator(workPath);
ic.setIndexPOI(true);
ic.setIndexMap(false);
ic.setIndexRouting(false);
ic.setIndexTransport(false);
ic.setIndexAddress(false);
ic.generateIndexes(outFile, new ConsoleProgressImplementation(3), null, null, null, log);
// final step
String targetMapFileName = ic.getMapFileName();
targetMapFileName =
targetMapFileName.substring(0, targetMapFileName.length() - IndexConstants.BINARY_MAP_INDEX_EXT.length()) +
"_" + IndexConstants.BINARY_MAP_VERSION + IndexConstants.BINARY_MAP_INDEX_EXT;
new File(workPath, ic.getMapFileName()).renameTo(new File(targetPath, targetMapFileName));
}
}
} catch (WikiIndexerException e) {
log.error("Error processing " + f.getName(), e);
} catch (RuntimeException e) {
log.error("Error processing " + f.getName(), e);
} catch (IOException e) {
log.error("Error processing " + f.getName(), e);
} catch (SAXException e) {
log.error("Error processing " + f.getName(), e);
} catch (SQLException e) {
log.error("Error processing " + f.getName(), e);
} catch (InterruptedException e) {
log.error("Error processing " + f.getName(), e);
}
}
}
protected File process(File f, Connection dbConnection) throws WikiIndexerException {
InputStream fi = null;
BufferedWriter out = null;
try {
int in = f.getName().indexOf('.');
int in2 = f.getName().indexOf('.', in + 1);
if (in2 == -1) {
log.error("File was not processed " + f.getName() + " please use name <Index-name>.<2Letters-Locale>.xml.bz2");
return null;
}
String wikiLocale = f.getName().substring(in + 1, in2);
log.info("Locale for file " + wikiLocale);
PreparedStatement locSearch = dbConnection.prepareStatement("SELECT gc_lat, gc_lon, gc_type FROM coord_"+wikiLocale+"wiki WHERE gc_from=?");
PreparedStatement enSearch = null;
try {
enSearch = dbConnection.prepareStatement("SELECT gc_lat, gc_lon, gc_type FROM coord_enwiki WHERE gc_name=?");
} catch (SQLException e) {
log.warn("EN coord not initialized " , e);
}
File osmOut = new File(workPath, f.getName().substring(0, in) + ".osm");
fi = new BufferedInputStream(new FileInputStream(f));
InputStream progressStream = fi;
if (f.getName().endsWith(".bz2")) {
if (fi.read() != 'B' || fi.read() != 'Z') {
throw new RuntimeException("The source stream must start with the characters BZ if it is to be read as a BZip2 stream."); //$NON-NLS-1$
} else {
fi = new CBZip2InputStream(fi);
}
}
ConsoleProgressImplementation progress = new ConsoleProgressImplementation();
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(osmOut), "UTF-8"));
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
WikiOsmHandler wikiOsmHandler = new WikiOsmHandler(saxParser, out, progress, progressStream, locSearch, enSearch, wikiLocale);
saxParser.parse(fi, wikiOsmHandler);
locSearch.close();
enSearch.close();
if (wikiOsmHandler.getCount() < 1) {
return null;
}
return osmOut;
} catch (ParserConfigurationException e) {
throw new WikiIndexerException("Parse exception", e);
} catch (SAXException e) {
throw new WikiIndexerException("Parse exception", e);
} catch (IOException e) {
throw new WikiIndexerException("Parse exception", e);
} catch (XMLStreamException e) {
throw new WikiIndexerException("Parse exception", e);
} catch (SQLException e) {
throw new WikiIndexerException("Database exception or locale configuration problem", e);
} finally {
Algoritms.closeStream(out);
Algoritms.closeStream(fi);
}
}
public class WikiOsmHandler extends DefaultHandler {
private final static boolean RECOGNIZE_ENGLISH = true;
long id = 1;
private final SAXParser saxParser;
private boolean page = false;
private boolean revision = false;
private StringBuilder ctext = null;
private StringBuilder title = new StringBuilder();
private StringBuilder text = new StringBuilder();
private StringBuilder pageId = new StringBuilder();
private float clat = 0;
private float clon = 0;
private long cid;
private String subcategory = null;
private boolean parseText = false;
private final ConsoleProgressImplementation progress;
private final InputStream progIS;
private XMLStreamWriter streamWriter;
private final PreparedStatement locSearch;
private final PreparedStatement enSearch;
private final String locale;
WikiOsmHandler(SAXParser saxParser, BufferedWriter outOsm, ConsoleProgressImplementation progress, InputStream progIS,
PreparedStatement dbStat, PreparedStatement enSearch, String wikiLocale)
throws IOException, XMLStreamException {
this.saxParser = saxParser;
this.progress = progress;
this.progIS = progIS;
this.locSearch = dbStat;
this.enSearch = enSearch;
this.locale = wikiLocale;
XMLOutputFactory xof = XMLOutputFactory.newInstance();
streamWriter = xof.createXMLStreamWriter(outOsm);
streamWriter.writeStartDocument();
streamWriter.writeCharacters("\n");
streamWriter.writeStartElement("osm");
streamWriter.writeAttribute("version", "0.6");
streamWriter.writeAttribute("generator", MapCreatorVersion.APP_MAP_CREATOR_VERSION);
progress.startTask("Parse wiki xml", progIS.available());
}
public int getCount() {
return (int) (id - 1);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
String name = saxParser.isNamespaceAware() ? localName : qName;
if (!page) {
page = name.equals("page");
} else {
if (name.equals("title")) {
title.setLength(0);
ctext = title;
} else if (name.equals("text")) {
if(parseText || RECOGNIZE_ENGLISH) {
text.setLength(0);
ctext = text;
}
} else if (name.equals("revision")) {
revision = true;
} else if (name.equals("id") && !revision) {
pageId.setLength(0);
ctext = pageId;
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (page) {
if (ctext != null) {
ctext.append(ch, start, length);
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
String name = saxParser.isNamespaceAware() ? localName : qName;
try {
if (page) {
if (name.equals("page")) {
page = false;
parseText = false;
progress.remaining(progIS.available());
} else if (name.equals("title")) {
ctext = null;
} else if (name.equals("revision")) {
revision = false;
} else if (name.equals("id") && !revision) {
ctext = null;
cid = Long.parseLong(pageId.toString());
locSearch.setLong(1, cid);
ResultSet rs = locSearch.executeQuery();
parseText = false;
if(rs.next()) {
parseText = true;
clat = rs.getFloat(1);
clon = rs.getFloat(2);
subcategory = rs.getString(3);
if(subcategory == null){
subcategory = "";
}
subcategory = subcategory.toLowerCase();
}
} else if (name.equals("text")) {
if(!parseText && RECOGNIZE_ENGLISH) {
tryToMatchEnglish();
}
if (parseText) {
if(id % 500 == 0) {
log.debug("Article accepted " + cid + " " + title.toString());
}
analyzeTextForGeoInfoNew();
}
ctext = null;
}
}
} catch (IOException e) {
throw new SAXException(e);
} catch (XMLStreamException e) {
throw new SAXException(e);
} catch (SQLException e) {
throw new SAXException(e);
}
}
public void tryToMatchEnglish() throws SQLException {
int i = text.lastIndexOf("[[en:");
if(i != -1){
int ei = text.indexOf("]]",i);
if(ei != -1) {
String englishName = text.substring("[[en:".length() + i, ei).trim();
enSearch.setString(1, englishName);
ResultSet rs = enSearch.executeQuery();
if (rs.next()) {
clat = rs.getFloat(1);
clon = rs.getFloat(2);
subcategory = rs.getString(3);
parseText = true;
if (subcategory == null) {
subcategory = "";
}
subcategory = subcategory.toLowerCase();
}
}
}
}
private String readProperty(String prop, int s, int e) {
int res = -1;
for (int i = s; i < e - prop.length(); i++) {
if (prop.charAt(0) == text.charAt(i)) {
boolean neq = false;
for (int j = 0; j < prop.length(); j++) {
if (prop.charAt(j) != text.charAt(i + j)) {
neq = true;
break;
}
}
if (!neq) {
res = i + prop.length();
break;
}
}
}
if (res == -1) {
return null;
}
int sr = -1;
int se = e;
for (int i = res; i < e; i++) {
if (text.charAt(i) == '|') {
se = i;
break;
}
if (text.charAt(i) == '=') {
sr = i + 1;
}
}
if (sr != -1) {
String result = text.substring(sr, se);
int commSt = result.indexOf("<!--");
if (commSt != -1) {
int commEnd = result.indexOf("-->");
if (commEnd == -1) {
commEnd = result.length();
} else {
commEnd += "-->".length();
}
return (result.substring(0, commSt) + result.substring(commEnd)).trim();
}
return result.trim();
}
return null;
}
private float zeroParseFloat(String s) {
return s == null || s.length() == 0 ? 0 : Float.parseFloat(s);
}
private int findOpenBrackets(int i) {
int h = text.indexOf("{{", i);
boolean check = true;
while (check) {
int startComment = text.indexOf("<!--", i);
check = false;
if (startComment != -1 && startComment < h) {
i = text.indexOf("-->", startComment);
h = text.indexOf("{{", i);
check = true;
}
}
return h;
}
private int findClosedBrackets(int i) {
if (i == -1) {
return -1;
}
int stack = 1;
int h = text.indexOf("{{", i + 2);
int e = text.indexOf("}}", i + 2);
while (stack != 0 && e != -1) {
if (h != -1 && h < e) {
i = h;
stack++;
} else {
i = e;
stack--;
}
if (stack != 0) {
h = text.indexOf("{{", i + 2);
e = text.indexOf("}}", i + 2);
}
}
if (stack == 0) {
return e;
}
return -1;
}
@Deprecated
private void analyzeTextForGeoInfo() throws XMLStreamException {
// fast precheck
if (title.toString().endsWith("/doc") || title.toString().startsWith("Шаблон:") || title.toString().startsWith("Template:")) {
// Looks as template article no information in it
return;
}
int ls = text.indexOf("lat_dir");
if (ls != -1 && text.charAt(ls + 1 + "lat_dir".length()) != '|') {
float lat = 0;
float lon = 0;
String subcategory = "";
StringBuilder description = new StringBuilder();
int h = findOpenBrackets(0);
int e = findClosedBrackets(h);
// 1. Find main header section {{ ... lat, lon }}
while (h != -1 && e != -1) {
String lat_dir = readProperty("lat_dir", h, e);
// continue if nothing was found
if (lat_dir != null) {
break;
}
h = findOpenBrackets(e);
e = findClosedBrackets(h);
}
if (h == -1 || e == -1) {
return;
}
// 2. Parse lat lon
try {
String lat_dir = readProperty("lat_dir", h, e);
String lon_dir = readProperty("lon_dir", h, e);
String lat_dg = readProperty("lat_deg", h, e);
String lon_dg = readProperty("lon_deg", h, e);
if (lon_dg == null || lat_dg == null || lat_dg.length() == 0 || lon_dg.length() == 0) {
return;
}
float lat_deg = Float.parseFloat(lat_dg);
float lon_deg = Float.parseFloat(lon_dg);
float lat_min = zeroParseFloat(readProperty("lat_min", h, e));
float lon_min = zeroParseFloat(readProperty("lon_min", h, e));
float lat_sec = zeroParseFloat(readProperty("lat_sec", h, e));
float lon_sec = zeroParseFloat(readProperty("lon_sec", h, e));
lat = (("S".equals(lat_dir)) ? -1 : 1) * (lat_deg + (lat_min + lat_sec / 60) / 60);
lon = (("W".equals(lon_dir)) ? -1 : 1) * (lon_deg + (lon_min + lon_sec / 60) / 60);
} catch (RuntimeException es) {
log.error("Article " + title, es);
return;
}
// 3. Parse main subcategory name
for (int j = h + 2; j < e; j++) {
if (Character.isWhitespace(text.charAt(j)) || text.charAt(j) == '|') {
subcategory = text.substring(h + 2, j).trim();
break;
}
}
// Special case
// 4. Parse main subcategory name
processDescription(description, e + 3);
if (description.length() > 0) {
writeNode(lat, lon, subcategory, description);
}
}
}
private void analyzeTextForGeoInfoNew() throws XMLStreamException {
StringBuilder description = new StringBuilder();
try {
int beg = 0;
int h = findOpenBrackets(beg);
// 1. Find main header section {{ ... lat, lon }}
while (h != -1 && text.substring(beg, h).trim().length() == 0 ) {
beg = findClosedBrackets(h);
if(beg == -1){
return;
}
beg += 2;
h = findOpenBrackets(beg);
}
// 3. Parse main subcategory name
// String subcategory ;
// for (int j = h + 2; j < e; j++) {
// if (Character.isWhitespace(text.charAt(j)) || text.charAt(j) == '|') {
// subcategory = text.substring(h + 2, j).trim();
// break;
// }
// }
// Special case
// 4. Parse main subcategory name
processDescription(description, beg);
} catch (RuntimeException e) {
description.setLength(0);
log.error(e.getMessage(), e);
}
if (description.length() > 0) {
writeNode(clat, clon, subcategory, description);
}
}
private int checkAndParse(int i, String start, String end, StringBuilder d, boolean add) {
if (text.charAt(i) != start.charAt(0)) {
return -1;
}
for (int j = 1; j < start.length() && i + j < text.length(); j++) {
if (text.charAt(i + j) != start.charAt(j)) {
return -1;
}
}
int st = i + start.length();
int en = text.length();
boolean colon = false;
for (int j = i + start.length(); j < text.length(); j++) {
if (text.charAt(j) == '|') {
st = j + 1;
if (colon) {
// Special case to prevent adding
// [[File:av.png|thumb|220|220]]
add = false;
}
} else if (j + end.length() <= text.length()) {
boolean eq = true;
if (text.charAt(j) == ':') {
colon = true;
}
for (int k = 0; k < end.length(); k++) {
if (text.charAt(j + k) != end.charAt(k)) {
eq = false;
break;
}
}
if (eq) {
en = j;
break;
}
}
}
if (add) {
d.append(text, st, en);
}
return en + end.length();
}
private void processDescription(StringBuilder description, int start) {
for (int j = start; j < text.length();) {
if (text.charAt(j) == '=' && text.charAt(j + 1) == '=' && j - start > 2048) {
break;
} else if (text.charAt(j) == '\n' && j - start > 2048) {
break;
} else {
int r = -1;
if (r == -1) {
r = checkAndParse(j, "<ref", "</ref>", description, false);
}
if (r == -1) {
r = checkAndParse(j, "[[", "]]", description, true);
}
if (r == -1) {
r = checkAndParse(j, "{{", "}}", description, true);
}
if (r == -1) {
r = checkAndParse(j, "''", "''", description, true);
}
if (r == -1) {
description.append(text.charAt(j));
j++;
} else {
j = r;
}
}
}
}
private void writeNode(double lat, double lon, String subcategory, StringBuilder description) throws XMLStreamException {
streamWriter.writeCharacters("\n");
streamWriter.writeStartElement("node");
id++;
streamWriter.writeAttribute("id", "-" + cid);
streamWriter.writeAttribute("lat", lat + "");
streamWriter.writeAttribute("lon", lon + "");
streamWriter.writeCharacters("\n ");
streamWriter.writeStartElement("tag");
streamWriter.writeAttribute("k", "name");
streamWriter.writeAttribute("v", title.toString());
streamWriter.writeEndElement();
streamWriter.writeCharacters("\n ");
streamWriter.writeStartElement("tag");
streamWriter.writeAttribute("k", "wikipedia");
streamWriter.writeAttribute("v", locale + ":"+title.toString());
streamWriter.writeEndElement();
streamWriter.writeCharacters("\n ");
streamWriter.writeStartElement("tag");
streamWriter.writeAttribute("k", "osmwiki");
streamWriter.writeAttribute("v", subcategory);
streamWriter.writeEndElement();
streamWriter.writeCharacters("\n ");
streamWriter.writeStartElement("tag");
streamWriter.writeAttribute("k", "description");
streamWriter.writeAttribute("v", description.toString().trim());
streamWriter.writeEndElement();
streamWriter.writeEndElement();
streamWriter.writeCharacters("\n");
}
@Override
public void endDocument() throws SAXException {
try {
streamWriter.writeEndElement();
streamWriter.writeCharacters("\n");
streamWriter.writeEndDocument();
} catch (XMLStreamException e) {
throw new SAXException(e);
}
}
}
}

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<batch_process>
<process_attributes mapZooms="" renderingTypesFile="" zoomWaySmoothness=""
osmDbDialect="sqlite" mapDbDialect="sqlite"/>
<!-- There are 3 subprocess :
1. Download fresh osm files from servers to 'directory_for_osm_files' (override existings).
2. Generate index files from all files in 'directory_for_osm_files' and put all indexes into 'directory_for_index_files'
3. Upload index files from 'directory_for_index_files' to googlecode.
If directory directory_for_uploaded_files is specified all uploaded files will be moved to it
All these subprocess could be ran independently ! So you can create some files check them and after that try to upload on googlecode,
or you can upload any file you have to googlecode (just put into 'directory_for_index_files')
-->
<!-- zoomWaySmoothness - 1-4, typical mapZooms - 8-10;11-12;13-14;15 -->
<process directory_for_osm_files="/home/..." directory_for_index_files="/home/..." directory_for_generation="/home/..."
skipExistingIndexesAt="/home/..." indexPOI="true" indexRouting="true" indexMap="true" indexTransport="true" indexAddress="true">
<!-- Add wget="C:/Program Files/GNUWin32/bin/wget.exe" to process, to use wget for download.
On linux systems if wget is in your path it can be wget="wget" or you can make own script with wget command:
wget="/path/to/script/wget.sh"
Defaultly enabled parameter of wget is: &-&-read-timeout=5 that prevents hanging of download from cloudmade/geofabrik server
-->
</process>
</batch_process>

View file

@ -1,121 +0,0 @@
package net.osmand.data.preparation;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import rtree.Element;
import rtree.Pack;
import rtree.RTree;
import rtree.RTreeException;
public class AbstractIndexPartCreator {
private final static Log log = LogFactory.getLog(AbstractIndexPartCreator.class);
protected int BATCH_SIZE = 1000;
protected Map<PreparedStatement, Integer> pStatements = new LinkedHashMap<PreparedStatement, Integer>();
public PreparedStatement createPrepareStatement(Connection mapConnection,
String string) throws SQLException {
PreparedStatement prepareStatement = mapConnection.prepareStatement(string);
pStatements.put(prepareStatement, 0);
return prepareStatement;
}
protected void closePreparedStatements(PreparedStatement... preparedStatements) throws SQLException {
for (PreparedStatement p : preparedStatements) {
if (p != null) {
p.executeBatch();
p.close();
pStatements.remove(p);
}
}
}
protected void closeAllPreparedStatements() throws SQLException {
for (PreparedStatement p : pStatements.keySet()) {
if (pStatements.get(p) > 0) {
p.executeBatch();
}
p.close();
}
}
protected boolean executePendingPreparedStatements() throws SQLException {
boolean exec = false;
for (PreparedStatement p : pStatements.keySet()) {
if (pStatements.get(p) > 0) {
p.executeBatch();
pStatements.put(p, 0);
exec = true;
}
}
return exec;
}
protected void addBatch(PreparedStatement p) throws SQLException {
addBatch(p, BATCH_SIZE, true);
}
protected void addBatch(PreparedStatement p, boolean commit) throws SQLException{
addBatch(p, BATCH_SIZE, commit);
}
protected void addBatch(PreparedStatement p, int batchSize, boolean commit) throws SQLException{
p.addBatch();
if(pStatements.get(p) >= batchSize){
p.executeBatch();
if(commit){
p.getConnection().commit();
}
pStatements.put(p, 0);
} else {
pStatements.put(p, pStatements.get(p) + 1);
}
}
protected boolean nodeIsLastSubTree(RTree tree, long ptr) throws RTreeException {
rtree.Node parent = tree.getReadNode(ptr);
Element[] e = parent.getAllElements();
for (int i = 0; i < parent.getTotalElements(); i++) {
if (e[i].getElementType() != rtree.Node.LEAF_NODE) {
return false;
}
}
return true;
}
protected RTree packRtreeFile(RTree tree, String nonPackFileName, String packFileName) throws IOException {
try {
assert rtree.Node.MAX < 50 : "It is better for search performance"; //$NON-NLS-1$
tree.flush();
File file = new File(packFileName);
if (file.exists()) {
file.delete();
}
long rootIndex = tree.getFileHdr().getRootIndex();
if (!nodeIsLastSubTree(tree, rootIndex)) {
// there is a bug for small files in packing method
new Pack().packTree(tree, packFileName);
tree.getFileHdr().getFile().close();
file = new File(nonPackFileName);
file.delete();
return new RTree(packFileName);
}
} catch (RTreeException e) {
log.error("Error flushing", e); //$NON-NLS-1$
throw new IOException(e);
}
return tree;
}
}

View file

@ -1,532 +0,0 @@
package net.osmand.data.preparation;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TLongObjectHashMap;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.osmand.Algoritms;
import net.osmand.binary.OsmandOdb.MapData;
import net.osmand.binary.OsmandOdb.MapDataBlock;
import net.osmand.data.MapAlgorithms;
import net.osmand.data.preparation.MapZooms.MapZoomPair;
import net.osmand.osm.Entity;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import net.osmand.osm.WayChain;
import net.osmand.osm.MapRenderingTypes.MapRulType;
import org.apache.commons.logging.Log;
import org.apache.tools.bzip2.CBZip2InputStream;
public class BasemapProcessor {
TLongObjectHashMap<WayChain> coastlinesEndPoint = new TLongObjectHashMap<WayChain>();
TLongObjectHashMap<WayChain> coastlinesStartPoint = new TLongObjectHashMap<WayChain>();
private static final byte SEA = 0x2;
private static final byte LAND = 0x1;
/**
* The zoom level for which the tile info is valid.
*/
public static final byte TILE_ZOOMLEVEL = 12;
private static final byte BITMASK = 0x3;
private static final int BITS_COUNT = (1 << TILE_ZOOMLEVEL) * (1 << TILE_ZOOMLEVEL);
private BitSet seaTileInfo = new BitSet(BITS_COUNT);
private BitSet landTileInfo = new BitSet(BITS_COUNT);
private TIntArrayList typeUse = new TIntArrayList();
List<MapRulType> tempNameUse = new ArrayList<MapRenderingTypes.MapRulType>();
TIntArrayList addtypeUse = new TIntArrayList(8);
Map<MapRulType, String> namesUse = new LinkedHashMap<MapRenderingTypes.MapRulType, String>();
private final int zoomWaySmothness;
private final MapRenderingTypes renderingTypes;
private final MapZooms mapZooms;
private final Log logMapDataWarn;
private SimplisticQuadTree[] quadTrees;
private static class SimplisticQuadTree {
int zoom;
int x;
int y;
boolean ocean;
boolean land;
public SimplisticQuadTree(int x, int y, int zoom) {
this.x = x;
this.y = y;
this.zoom = zoom;
}
SimplisticQuadTree[] children = null;
Map<MapZoomPair,List<SimplisticBinaryData>> dataObjects = null;
public SimplisticQuadTree[] getAllChildren(){
initChildren();
return children;
}
public boolean areChildrenDefined(){
return children != null;
}
public void addQuadData(MapZoomPair p, SimplisticBinaryData w){
if(dataObjects == null) {
dataObjects = new LinkedHashMap<MapZooms.MapZoomPair, List<SimplisticBinaryData>>();
}
if(!dataObjects.containsKey(p)){
dataObjects.put(p, new ArrayList<SimplisticBinaryData>());
}
dataObjects.get(p).add(w);
}
public boolean dataIsDefined(MapZoomPair p){
return dataObjects != null && dataObjects.get(p) != null;
}
public List<SimplisticBinaryData> getData(MapZoomPair p) {
return dataObjects.get(p);
}
public SimplisticQuadTree getOrCreateSubTree(int x, int y, int zm) {
if (zm <= zoom) {
return this;
} else {
initChildren();
int nx = (x >> (zm - zoom - 1)) - (this.x << 1);
int ny = (y >> (zm - zoom - 1)) - (this.y << 1);
if (nx > 1 || nx < 0 || ny > 1 || ny < 0) {
return null;
}
return children[nx * 2 + ny].getOrCreateSubTree(x, y, zm);
}
}
private void initChildren() {
if (children == null) {
children = new SimplisticQuadTree[4];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
children[i * 2 + j] = new SimplisticQuadTree(((this.x << 1) + i), ((this.y << 1) + j), zoom + 1);
}
}
}
}
}
private static class SimplisticBinaryData {
// consequent 31 coordinates
public byte[] coordinates;
public int[] types;
public int[] addTypes;
public long id = -500;
public Map<MapRulType, String> names;
}
public BasemapProcessor(Log logMapDataWarn, MapZooms mapZooms, MapRenderingTypes renderingTypes, int zoomWaySmothness) {
this.logMapDataWarn = logMapDataWarn;
this.mapZooms = mapZooms;
this.renderingTypes = renderingTypes;
this.zoomWaySmothness = zoomWaySmothness;
constructBitSetInfo();
quadTrees = new SimplisticQuadTree[mapZooms.getLevels().size()];
for (int i = 0; i < mapZooms.getLevels().size(); i++) {
MapZoomPair p = mapZooms.getLevels().get(i);
quadTrees[i] = constructTilesQuadTree(Math.min(p.getMaxZoom() - 1, 12));
}
}
private void constructBitSetInfo() {
try {
InputStream stream = BasemapProcessor.class.getResourceAsStream("oceantiles_12.dat.bz2");
if (stream.read() != 'B' || stream.read() != 'Z') {
throw new RuntimeException("The source stream must start with the characters BZ if it is to be read as a BZip2 stream."); //$NON-NLS-1$
}
InputStream dis = new CBZip2InputStream(stream);
int currentByte;
for (int i = 0; i < BITS_COUNT / 4; i++) {
currentByte = dis.read();
if (((currentByte >> 6) & BITMASK) == SEA) {
seaTileInfo.set(i * 4);
} else if (((currentByte >> 6) & BITMASK) == LAND) {
landTileInfo.set(i * 4);
}
if (((currentByte >> 4) & BITMASK) == SEA) {
seaTileInfo.set(i * 4 + 1);
} else if (((currentByte >> 4) & BITMASK) == LAND) {
landTileInfo.set(i * 4 + 1);
}
if (((currentByte >> 2) & BITMASK) == SEA) {
seaTileInfo.set(i * 4 + 2);
} else if (((currentByte >> 2) & BITMASK) == LAND) {
landTileInfo.set(i * 4 + 2);
}
if ((currentByte & BITMASK) == SEA) {
seaTileInfo.set(i * 4 + 3);
} else if (((currentByte >> 0) & BITMASK) == LAND) {
landTileInfo.set(i * 4 + 3);
}
}
} catch (IOException e) {
throw new RuntimeException("File with coastline tiles was not found ");
}
}
public int getTileZoomLevel(){
return TILE_ZOOMLEVEL;
}
public boolean isWaterTile(int x, int y, int zoom) {
if (zoom >= TILE_ZOOMLEVEL) {
int x1 = x >> (zoom - TILE_ZOOMLEVEL);
int y1 = y >> (zoom - TILE_ZOOMLEVEL);
if (!seaTileInfo.get(y1 * 4096 + x1)) {
return false;
}
return true;
} else {
int x1 = x << (TILE_ZOOMLEVEL - zoom);
int y1 = y << (TILE_ZOOMLEVEL - zoom);
int max = 1 << TILE_ZOOMLEVEL - zoom;
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
if (!seaTileInfo.get((y1 + j) * 4096 + (x1 + i))) {
return false;
}
}
}
return true;
}
}
public boolean isLandTile(int x, int y, int zoom) {
if (zoom >= TILE_ZOOMLEVEL) {
int x1 = x >> (zoom - TILE_ZOOMLEVEL);
int y1 = y >> (zoom - TILE_ZOOMLEVEL);
if (!landTileInfo.get(y1 * 4096 + x1)) {
return false;
}
return true;
} else {
int x1 = x << (TILE_ZOOMLEVEL - zoom);
int y1 = y << (TILE_ZOOMLEVEL - zoom);
int max = 1 << (TILE_ZOOMLEVEL - zoom);
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
if (!landTileInfo.get((y1 + i) * 4096 + (x1 + j))) {
return false;
}
}
}
return true;
}
}
public SimplisticQuadTree constructTilesQuadTree(int maxZoom){
SimplisticQuadTree rootTree = new SimplisticQuadTree(0, 0, 0);
int baseZoom = 4;
int tiles = 1 << baseZoom;
ArrayList<SimplisticQuadTree> toVisit = new ArrayList<SimplisticQuadTree>();
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) {
toVisit.add(rootTree.getOrCreateSubTree(x, y, baseZoom));
}
}
initializeQuadTree(rootTree, baseZoom, maxZoom, toVisit);
return rootTree;
}
protected ArrayList<SimplisticQuadTree> initializeQuadTree(SimplisticQuadTree rootTree, int baseZoom, int maxZoom,
ArrayList<SimplisticQuadTree> toVisit) {
for (int zoom = baseZoom; zoom <= maxZoom && !toVisit.isEmpty(); zoom++) {
ArrayList<SimplisticQuadTree> newToVisit = new ArrayList<SimplisticQuadTree>();
for (SimplisticQuadTree subtree : toVisit) {
int x = subtree.x;
int y = subtree.y;
if (isWaterTile(x, y, zoom)) {
rootTree.getOrCreateSubTree(x, y, zoom).ocean = true;
} else if (isLandTile(x, y, zoom)) {
rootTree.getOrCreateSubTree(x, y, zoom).land = true;
} else if(zoom < TILE_ZOOMLEVEL){
SimplisticQuadTree[] vis = rootTree.getOrCreateSubTree(x, y, zoom).getOrCreateSubTree(x, y, zoom)
.getAllChildren();
for (SimplisticQuadTree t : vis) {
newToVisit.add(t);
}
}
}
toVisit = newToVisit;
}
return toVisit;
}
public void writeBasemapFile(BinaryMapIndexWriter writer, String regionName) throws IOException {
writer.startWriteMapIndex(regionName);
// write map encoding rules
writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes());
int i = 0;
for (MapZoomPair p : mapZooms.getLevels()) {
// write map levels and map index
writer.startWriteMapLevelIndex(p.getMinZoom(), p.getMaxZoom(), 0, (1 << 31) - 1, 0, (1 << 31) - 1);
Map<SimplisticQuadTree, BinaryFileReference> refs = new LinkedHashMap<BasemapProcessor.SimplisticQuadTree, BinaryFileReference>();
writeBinaryMapTree(quadTrees[i], writer, refs, p);
// without data blocks
writeBinaryMapBlock(quadTrees[i], writer, refs, p);
writer.endWriteMapLevelIndex();
i++;
}
writer.endWriteMapIndex();
writer.flush();
}
private void writeBinaryMapBlock(SimplisticQuadTree simplisticQuadTree, BinaryMapIndexWriter writer,
Map<SimplisticQuadTree, BinaryFileReference> refs, MapZoomPair level) throws IOException {
Iterator<Entry<SimplisticQuadTree, BinaryFileReference>> it = refs.entrySet().iterator();
while(it.hasNext()) {
Entry<SimplisticQuadTree, BinaryFileReference> e = it.next();
MapDataBlock.Builder dataBlock = MapDataBlock.newBuilder();
SimplisticQuadTree quad = e.getKey();
Map<String, Integer> stringTable = new LinkedHashMap<String, Integer> ();
for (SimplisticBinaryData w : quad.getData(level)) {
dataBlock.setBaseId(w.id);
int[] wts = null;
int[] wats = null;
if(w.types != null ){
wts = new int[w.types.length];
for (int j = 0; j < w.types.length; j ++) {
wts[j] = renderingTypes.getTypeByInternalId(w.types[j]).getTargetId();
}
}
if(w.addTypes != null){
wats = new int[w.addTypes.length];
for (int j = 0; j < w.addTypes.length; j ++) {
wats[j] = renderingTypes.getTypeByInternalId(w.addTypes[j]).getTargetId();
}
}
MapData mapData = writer.writeMapData(0,
quad.x << (31 - quad.zoom), quad.y << (31 - quad.zoom), false,
w.coordinates, null, wts, wats, w.names, stringTable, dataBlock, level.getMaxZoom() > 15);
if (mapData != null) {
dataBlock.addDataObjects(mapData);
}
}
writer.writeMapDataBlock(dataBlock, stringTable, e.getValue());
}
}
private void writeBinaryMapTree(SimplisticQuadTree quadTree, BinaryMapIndexWriter writer,
Map<SimplisticQuadTree, BinaryFileReference> refs, MapZoomPair p) throws IOException {
int xL = (quadTree.x) << (31 - quadTree.zoom);
int xR = ((quadTree.x + 1) << (31 - quadTree.zoom)) - 1;
int yT = (quadTree.y) << (31 - quadTree.zoom);
int yB = ((quadTree.y + 1) << (31 - quadTree.zoom)) - 1;
boolean defined = quadTree.dataIsDefined(p);
boolean ocean = false;
boolean land = false;
if (!defined) {
ocean = quadTree.ocean || isWaterTile(quadTree.x, quadTree.y, quadTree.zoom);
land = quadTree.land || isLandTile(quadTree.x, quadTree.y, quadTree.zoom);
}
BinaryFileReference ref = writer.startMapTreeElement(xL, xR, yT, yB, defined, ocean, land);
if (ref != null) {
refs.put(quadTree, ref);
}
if (quadTree.areChildrenDefined()) {
SimplisticQuadTree[] allChildren = quadTree.getAllChildren();
for (SimplisticQuadTree ch : allChildren) {
writeBinaryMapTree(ch, writer, refs, p);
}
}
writer.endWriteMapTreeElement();
}
public void processEntity(Entity e) {
if (e instanceof Way || e instanceof Node) {
for (int level = 0; level < mapZooms.getLevels().size(); level++) {
renderingTypes.encodeEntityWithType(e, mapZooms.getLevel(level).getMaxZoom(), typeUse, addtypeUse, namesUse, tempNameUse);
if (typeUse.isEmpty()) {
continue;
}
MapZoomPair zoomPair = mapZooms.getLevel(level);
if (e instanceof Way) {
if(((Way) e).getNodes().size() < 2){
continue;
}
if ("coastline".equals(e.getTag("natural")) || !Algoritms.isEmpty(e.getTag("admin_level"))) {
splitContinuousWay(((Way) e).getNodes(), typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null,
zoomPair, quadTrees[level]);
} else {
List<Node> ns = ((Way) e).getNodes();
int z = getViewZoom(zoomPair);
int tilex = 0;
int tiley = 0;
boolean sameTile = false;
while (!sameTile) {
tilex = (int) MapUtils.getTileNumberX(z, ns.get(0).getLongitude());
tiley = (int) MapUtils.getTileNumberY(z, ns.get(0).getLatitude());
sameTile = true;
for (int i = 1; i < ns.size(); i++) {
int tx = (int) MapUtils.getTileNumberX(z, ns.get(i).getLongitude());
int ty = (int) MapUtils.getTileNumberY(z, ns.get(i).getLatitude());
if (tx != tilex || ty != tiley) {
sameTile = false;
break;
}
}
if (!sameTile) {
z--;
}
}
List<Node> res = new ArrayList<Node>();
MapAlgorithms.simplifyDouglasPeucker(ns, zoomPair.getMaxZoom() - 1 + 8 + zoomWaySmothness, 3, res);
addSimplisticData(res, typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair,
quadTrees[level], z, tilex, tiley, namesUse.isEmpty() ? null : new LinkedHashMap<MapRenderingTypes.MapRulType, String>(namesUse));
}
} else {
int z = getViewZoom(zoomPair);
int tilex = (int) MapUtils.getTileNumberX(z, ((Node) e).getLongitude());
int tiley = (int) MapUtils.getTileNumberY(z, ((Node) e).getLatitude());
addSimplisticData(Collections.singletonList((Node)e), typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair,
quadTrees[level], z, tilex, tiley, namesUse.isEmpty() ? null : new LinkedHashMap<MapRenderingTypes.MapRulType, String>(namesUse));
}
}
}
}
public void splitContinuousWay(List<Node> ns, int[] types, int[] addTypes, MapZoomPair zoomPair, SimplisticQuadTree quadTree) {
int z = getViewZoom(zoomPair);
int i = 1;
Node prevNode = ns.get(0);
int px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
int py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
while (i < ns.size()) {
List<Node> w = new ArrayList<Node>();
w.add(prevNode);
int tilex = px31 >> (31 - z);
int tiley = py31 >> (31 - z);
boolean sameTile = true;
wayConstruct: while (sameTile && i < ns.size()) {
Node next = ns.get(i);
int ntilex = (int) MapUtils.getTileNumberX(z, next.getLongitude());
int ntiley = (int) MapUtils.getTileNumberY(z, next.getLatitude());
if (ntilex == tilex && tiley == ntiley) {
sameTile = true;
w.add(next);
prevNode = next;
px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
i++;
} else {
int nx31 = MapUtils.get31TileNumberX(next.getLongitude());
int ny31 = MapUtils.get31TileNumberY(next.getLatitude());
// increase boundaries to drop into another tile
int leftX = (tilex << (31 - z)) - 1;
int rightX = (tilex + 1) << (31 - z);
if (rightX < 0) {
rightX = Integer.MAX_VALUE;
}
int topY = (tiley << (31 - z)) - 1;
int bottomY = (tiley + 1) << (31 - z);
if (bottomY < 0) {
bottomY = Integer.MAX_VALUE;
}
long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY);
int cy31 = (int) inter;
int cx31 = (int) (inter >> 32l);
if (inter == -1) {
cx31 = nx31;
cy31 = ny31;
i++;
logMapDataWarn.warn("Can't find intersection for " + MapUtils.get31LongitudeX(px31) + ","
+ MapUtils.get31LatitudeY(py31) + " - " + MapUtils.get31LongitudeX(nx31) + ","
+ MapUtils.get31LatitudeY(ny31));
}
prevNode = new Node(MapUtils.get31LatitudeY(cy31), MapUtils.get31LongitudeX(cx31), -1000);
px31 = cx31;
py31 = cy31;
w.add(prevNode);
break wayConstruct;
}
}
List<Node> res = new ArrayList<Node>();
MapAlgorithms.simplifyDouglasPeucker(w, zoomPair.getMaxZoom() - 1 + 8 + zoomWaySmothness, 3, res);
addSimplisticData(res, types, addTypes, zoomPair, quadTree, z, tilex, tiley, null);
}
}
private void addSimplisticData(List<Node> res, int[] types, int[] addTypes, MapZoomPair zoomPair, SimplisticQuadTree quadTree, int z, int tilex,
int tiley, Map<MapRulType, String> names) {
SimplisticQuadTree quad = quadTree.getOrCreateSubTree(tilex, tiley, z);
if (quad == null) {
if (logMapDataWarn != null) {
logMapDataWarn.error("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
} else {
System.err.println("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
}
}
ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream();
for (Node n : res) {
if (n != null) {
int y = MapUtils.get31TileNumberY(n.getLatitude());
int x = MapUtils.get31TileNumberX(n.getLongitude());
try {
Algoritms.writeInt(bcoordinates, x);
Algoritms.writeInt(bcoordinates, y);
} catch (IOException e1) {
throw new IllegalStateException(e1);
}
}
}
SimplisticBinaryData data = new SimplisticBinaryData();
// not needed
// data.id = w.getId();
data.coordinates = bcoordinates.toByteArray();
data.types = types;
data.addTypes = addTypes;
data.names = names;
quad.addQuadData(zoomPair, data);
}
private int getViewZoom(MapZoomPair zoomPair) {
return Math.min((zoomPair.getMinZoom() + zoomPair.getMaxZoom()) / 2 - 1, zoomPair.getMinZoom() + 1);
}
}

View file

@ -1,45 +0,0 @@
package net.osmand.data.preparation;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Utility to keep references between binary blocks
* while generating binary file
*/
public class BinaryFileReference {
private long pointerToWrite;
private long pointerToCalculateShiftFrom;
private long pointerToCalculateShiftTo;
public BinaryFileReference(long pointerToWrite, long pointerToCalculateShiftFrom) {
this.pointerToWrite = pointerToWrite;
this.pointerToCalculateShiftFrom = pointerToCalculateShiftFrom;
}
public long getStartPointer() {
return pointerToCalculateShiftFrom;
}
public int writeReference(RandomAccessFile raf, long pointerToCalculateShifTo) throws IOException {
this.pointerToCalculateShiftTo = pointerToCalculateShifTo;
long currentPosition = raf.getFilePointer();
raf.seek(pointerToWrite);
int val = (int) (pointerToCalculateShiftTo - pointerToCalculateShiftFrom);
raf.writeInt(val);
raf.seek(currentPosition);
return val;
}
public static BinaryFileReference createSizeReference(long pointerToWrite){
return new BinaryFileReference(pointerToWrite, pointerToWrite + 4);
}
public static BinaryFileReference createShiftReference(long pointerToWrite, long pointerShiftFrom){
return new BinaryFileReference(pointerToWrite, pointerShiftFrom);
}
}

View file

@ -1,135 +0,0 @@
package net.osmand.data.preparation;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import net.osmand.Algoritms;
import org.apache.commons.logging.Log;
import org.sqlite.SQLiteJDBCLoader;
import com.anvisics.jleveldb.LevelDBAccess;
import com.anvisics.jleveldb.ext.DBAccessor;
import com.anvisics.jleveldb.ext.Options;
import com.anvisics.jleveldb.ext.Status;
public enum DBDialect {
DERBY,
H2,
NOSQL,
SQLITE,
SQLITE_IN_MEMORY;
public void deleteTableIfExists(String table, Statement stat) throws SQLException {
if(this == DERBY){
try {
stat.executeUpdate("drop table " + table); //$NON-NLS-1$
} catch (SQLException e) {
// ignore it
}
} else {
stat.executeUpdate("drop table if exists " + table); //$NON-NLS-1$
}
}
public boolean databaseFileExists(File dbFile) {
if (DBDialect.H2 == this) {
return new File(dbFile.getAbsolutePath() + ".h2.db").exists(); //$NON-NLS-1$
} else {
return dbFile.exists();
}
}
public void removeDatabase(File file) {
if (DBDialect.H2 == this) {
File[] list = file.getParentFile().listFiles();
for (File f : list) {
if (f.getName().startsWith(file.getName())) {
Algoritms.removeAllFiles(f);
}
}
} else {
Algoritms.removeAllFiles(file);
}
}
public void commitDatabase(Object connection) throws SQLException {
if(DBDialect.NOSQL != this){
if (!((Connection) connection).getAutoCommit()) {
((Connection) connection).commit();
}
} else {
}
}
public void closeDatabase(Object dbConn) throws SQLException {
if(DBDialect.NOSQL != this){
if (DBDialect.H2 == this) {
((Connection) dbConn).createStatement().execute("SHUTDOWN COMPACT"); //$NON-NLS-1$
}
((Connection) dbConn).close();
} else {
// ((DBAccessor) dbConn).close();
}
}
protected Object getDatabaseConnection(String fileName, Log log) throws SQLException {
if (DBDialect.NOSQL == this) {
DBAccessor dbAccessor = LevelDBAccess.getDBAcessor();
Options opts = new Options();
opts.setCreateIfMissing(true);
Status status = dbAccessor.open(opts, fileName);
if(!status.ok()){
throw new SQLException(status.ToString());
}
return dbAccessor;
} else if (DBDialect.SQLITE == this || DBDialect.SQLITE_IN_MEMORY == this) {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
log.error("Illegal configuration", e);
throw new IllegalStateException(e);
}
Connection connection = DriverManager.getConnection("jdbc:sqlite:" + (DBDialect.SQLITE_IN_MEMORY == this? ":memory:":
fileName));
Statement statement = connection.createStatement();
statement.executeUpdate("PRAGMA synchronous = 0");
//no journaling, saves some I/O access, but database can go corrupt
statement.executeQuery("PRAGMA journal_mode = OFF");
//we are exclusive, some speed increase ( no need to get and release logs
statement.executeQuery("PRAGMA locking_mode = EXCLUSIVE");
//increased cache_size, by default it is 2000 and we have quite huge files...
//statement.executeUpdate("PRAGMA cache_size = 10000"); cache size could be probably contraproductive on slower disks?
statement.close();
log.info(String.format("SQLITE running in %s mode", SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java"));
return connection;
} else if (DBDialect.DERBY == this) {
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
} catch (ClassNotFoundException e) {
log.error("Illegal configuration", e);
throw new IllegalStateException(e);
}
Connection conn = DriverManager.getConnection("jdbc:derby:" + fileName + ";create=true");
conn.setAutoCommit(false);
return conn;
} else if (DBDialect.H2 == this) {
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
log.error("Illegal configuration", e);
throw new IllegalStateException(e);
}
return DriverManager.getConnection("jdbc:h2:file:" + fileName);
} else {
throw new UnsupportedOperationException();
}
}
}

View file

@ -1,801 +0,0 @@
package net.osmand.data.preparation;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import net.osmand.Algoritms;
import net.osmand.IProgress;
import net.osmand.data.IndexConstants;
import net.osmand.data.preparation.OsmDbAccessor.OsmDbVisitor;
import net.osmand.data.preparation.address.IndexAddressCreator;
import net.osmand.impl.ConsoleProgressImplementation;
import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.Relation;
import net.osmand.osm.io.IOsmStorageFilter;
import net.osmand.osm.io.OsmBaseStorage;
import net.osmand.osm.io.OsmBaseStoragePbf;
import net.osmand.swing.DataExtractionSettings;
import net.osmand.swing.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.xml.sax.SAXException;
import rtree.RTreeException;
/**
* http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing#Is_inside.2Foutside
* http://wiki.openstreetmap.org/wiki/Relations/Proposed/Postal_Addresses
* http://wiki.openstreetmap.org/wiki/Proposed_features/House_numbers/Karlsruhe_Schema#Tags (node, way)
*
* That data extraction has aim, save runtime memory and generate indexes on the fly. It will be longer than load in memory (needed part)
* and save into index.
*/
public class IndexCreator {
private static final Log log = LogFactory.getLog(IndexCreator.class);
// ONLY derby.jar needed for derby dialect
// (NOSQL is the fastest but is supported only on linux 32)
// Sqlite better to use only for 32-bit machines
private DBDialect osmDBdialect = DBDialect.SQLITE;
private DBDialect mapIndexDBDialect = DBDialect.SQLITE;
public static boolean REMOVE_POI_DB = true;
public static final int BATCH_SIZE = 5000;
public static final int BATCH_SIZE_OSM = 10000;
public static final String TEMP_NODES_DB = "nodes.tmp.odb";
public static final int STEP_MAIN = 4;
private File workingDir = null;
private boolean indexMap;
private boolean indexPOI;
private boolean indexTransport;
private boolean indexAddress;
private boolean indexRouting = true;
private boolean normalizeStreets = true; // true by default
private int zoomWaySmothness = 2;
private String regionName;
private String mapFileName = null;
private Long lastModifiedDate = null;
private IndexTransportCreator indexTransportCreator;
private IndexPoiCreator indexPoiCreator;
private IndexAddressCreator indexAddressCreator;
private IndexVectorMapCreator indexMapCreator;
private IndexRouteCreator indexRouteCreator;
private OsmDbAccessor accessor;
// constants to start process from the middle and save temporary results
private boolean recreateOnlyBinaryFile = false; // false;
private boolean deleteOsmDB = true;
private boolean deleteDatabaseIndexes = true;
private Object dbConn;
private File dbFile;
private File mapFile;
private RandomAccessFile mapRAFile;
private Connection mapConnection;
public static final int DEFAULT_CITY_ADMIN_LEVEL = 8;
private String cityAdminLevel = "" + DEFAULT_CITY_ADMIN_LEVEL;
public IndexCreator(File workingDir) {
this.workingDir = workingDir;
}
public void setIndexAddress(boolean indexAddress) {
this.indexAddress = indexAddress;
}
public void setIndexRouting(boolean indexRouting) {
this.indexRouting = indexRouting;
}
public void setIndexMap(boolean indexMap) {
this.indexMap = indexMap;
}
public void setIndexPOI(boolean indexPOI) {
this.indexPOI = indexPOI;
}
public void setIndexTransport(boolean indexTransport) {
this.indexTransport = indexTransport;
}
public void setNormalizeStreets(boolean normalizeStreets) {
this.normalizeStreets = normalizeStreets;
}
public void setZoomWaySmothness(int zoomWaySmothness) {
this.zoomWaySmothness = zoomWaySmothness;
}
public String getRegionName() {
if (regionName == null) {
return "Region"; //$NON-NLS-1$
}
return regionName;
}
public void setRegionName(String regionName) {
this.regionName = regionName;
}
private Object getDatabaseConnection(String fileName, DBDialect dialect) throws SQLException {
return dialect.getDatabaseConnection(fileName, log);
}
public void setNodesDBFile(File file) {
dbFile = file;
}
public void setMapFileName(String mapFileName) {
this.mapFileName = mapFileName;
}
public String getMapFileName() {
if (mapFileName == null) {
return getRegionName() + IndexConstants.BINARY_MAP_INDEX_EXT;
}
return mapFileName;
}
public String getTempMapDBFileName() {
return getMapFileName() + ".tmp"; //$NON-NLS-1$
}
public void setDialects(DBDialect osmDBdialect, DBDialect mapIndexDBDialect) {
if(osmDBdialect != null) {
this.osmDBdialect = osmDBdialect;
}
if(mapIndexDBDialect != null) {
this.mapIndexDBDialect = mapIndexDBDialect;
}
}
public Long getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Long lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public String getPoiFileName() {
return getRegionName() + IndexConstants.POI_INDEX_EXT;
}
public String getCityAdminLevel() {
return cityAdminLevel;
}
public void setCityAdminLevel(String cityAdminLevel) {
this.cityAdminLevel = cityAdminLevel;
}
public String getRTreeMapIndexNonPackFileName() {
return mapFile.getAbsolutePath() + ".rtree"; //$NON-NLS-1$
}
public String getRTreeRouteIndexNonPackFileName() {
return mapFile.getAbsolutePath() + ".rte"; //$NON-NLS-1$
}
public String getRTreeRouteIndexPackFileName() {
return mapFile.getAbsolutePath() + ".prte"; //$NON-NLS-1$
}
public String getRTreeTransportStopsFileName() {
return mapFile.getAbsolutePath() + ".trans"; //$NON-NLS-1$
}
public String getRTreeTransportStopsPackFileName() {
return mapFile.getAbsolutePath() + ".ptrans"; //$NON-NLS-1$
}
public String getRTreeMapIndexPackFileName() {
return mapFile.getAbsolutePath() + ".prtree"; //$NON-NLS-1$
}
/* ***** END OF GETTERS/SETTERS ***** */
private void iterateMainEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (indexPOI) {
indexPoiCreator.iterateEntity(e, ctx);
}
if (indexTransport) {
indexTransportCreator.visitEntityMainStep(e, ctx);
}
if (indexMap) {
indexMapCreator.iterateMainEntity(e, ctx);
}
if (indexAddress) {
indexAddressCreator.iterateMainEntity(e, ctx);
}
if (indexRouting) {
indexRouteCreator.iterateMainEntity(e, ctx);
}
}
private OsmDbCreator extractOsmToNodesDB(File readFile, IProgress progress, IOsmStorageFilter addFilter) throws FileNotFoundException,
IOException, SQLException, SAXException {
boolean pbfFile = false;
InputStream stream = new BufferedInputStream(new FileInputStream(readFile), 8192 * 4);
InputStream streamFile = stream;
long st = System.currentTimeMillis();
if (readFile.getName().endsWith(".bz2")) { //$NON-NLS-1$
if (stream.read() != 'B' || stream.read() != 'Z') {
// throw new RuntimeException("The source stream must start with the characters BZ if it is to be read as a BZip2 stream."); //$NON-NLS-1$
} else {
stream = new CBZip2InputStream(stream);
}
} else if (readFile.getName().endsWith(".pbf")) { //$NON-NLS-1$
pbfFile = true;
}
OsmBaseStorage storage = pbfFile? new OsmBaseStoragePbf() : new OsmBaseStorage();
storage.setSupressWarnings(DataExtractionSettings.getSettings().isSupressWarningsForDuplicatedId());
if (addFilter != null) {
storage.getFilters().add(addFilter);
}
storage.getFilters().add(new IOsmStorageFilter() {
@Override
public boolean acceptEntityToLoad(OsmBaseStorage storage, EntityId entityId, Entity entity) {
if(indexAddressCreator != null) {
indexAddressCreator.registerCityIfNeeded(entity);
}
// accept to allow db creator parse it
return true;
}
});
// 1. Loading osm file
OsmDbCreator dbCreator = new OsmDbCreator(this);
try {
progress.setGeneralProgress("[15 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.LOADING_FILE") + readFile.getAbsolutePath(), -1); //$NON-NLS-1$
// 1 init database to store temporary data
dbCreator.initDatabase(osmDBdialect, dbConn);
storage.getFilters().add(dbCreator);
if (pbfFile) {
((OsmBaseStoragePbf) storage).parseOSMPbf(stream, progress, false);
} else {
storage.parseOSM(stream, progress, streamFile, false);
}
dbCreator.finishLoading();
osmDBdialect.commitDatabase(dbConn);
if (log.isInfoEnabled()) {
log.info("File parsed : " + (System.currentTimeMillis() - st)); //$NON-NLS-1$
}
progress.finishTask();
return dbCreator;
} finally {
if (log.isInfoEnabled()) {
log.info("File indexed : " + (System.currentTimeMillis() - st)); //$NON-NLS-1$
}
}
}
private boolean createPlainOsmDb(IProgress progress, File readFile, IOsmStorageFilter addFilter, boolean deletePrevious) throws SQLException, FileNotFoundException, IOException, SAXException{
// dbFile = new File(workingDir, TEMP_NODES_DB);
// initialize db file
boolean loadFromExistingFile = dbFile != null && osmDBdialect.databaseFileExists(dbFile) && !deletePrevious;
if (dbFile == null || deletePrevious) {
dbFile = new File(workingDir, TEMP_NODES_DB);
// to save space
if (osmDBdialect.databaseFileExists(dbFile)) {
osmDBdialect.removeDatabase(dbFile);
}
}
dbConn = getDatabaseConnection(dbFile.getAbsolutePath(), osmDBdialect);
int allRelations = 100000;
int allWays = 1000000;
int allNodes = 10000000;
if (!loadFromExistingFile) {
OsmDbCreator dbCreator = extractOsmToNodesDB(readFile, progress, addFilter);
if (dbCreator != null) {
allNodes = dbCreator.getAllNodes();
allWays = dbCreator.getAllWays();
allRelations = dbCreator.getAllRelations();
}
} else {
if (DBDialect.NOSQL != osmDBdialect) {
Connection dbc = (Connection) dbConn;
final Statement stmt = dbc.createStatement();
accessor.computeRealCounts(stmt);
allRelations = accessor.getAllRelations();
allNodes = accessor.getAllNodes();
allWays = accessor.getAllWays();
stmt.close();
}
}
accessor.initDatabase(dbConn, osmDBdialect, allNodes, allWays, allRelations);
return loadFromExistingFile;
}
private void createDatabaseIndexesStructure() throws SQLException, IOException {
// 2.1 create temporary sqlite database to put temporary results to it
mapFile = new File(workingDir, getMapFileName());
// to save space
mapFile.getParentFile().mkdirs();
File tempDBMapFile = new File(workingDir, getTempMapDBFileName());
mapIndexDBDialect.removeDatabase(tempDBMapFile);
mapConnection = (Connection) getDatabaseConnection(tempDBMapFile.getAbsolutePath(), mapIndexDBDialect);
mapConnection.setAutoCommit(false);
// 2.2 create rtree map
if (indexMap) {
indexMapCreator.createDatabaseStructure(mapConnection, mapIndexDBDialect, getRTreeMapIndexNonPackFileName());
}
if (indexRouting) {
indexRouteCreator.createDatabaseStructure(mapConnection, mapIndexDBDialect, getRTreeRouteIndexNonPackFileName());
}
if (indexAddress) {
indexAddressCreator.createDatabaseStructure(mapConnection, mapIndexDBDialect);
}
if (indexPOI) {
indexPoiCreator.createDatabaseStructure(new File(workingDir, getPoiFileName()));
}
if (indexTransport) {
indexTransportCreator.createDatabaseStructure(mapConnection, mapIndexDBDialect, getRTreeTransportStopsFileName());
}
}
public void generateBasemapIndex(IProgress progress, IOsmStorageFilter addFilter, MapZooms mapZooms,
MapRenderingTypes renderingTypes, Log logMapDataWarn, String regionName, File... readFiles) throws IOException, SAXException, SQLException, InterruptedException {
if (logMapDataWarn == null) {
logMapDataWarn = log;
}
if (logMapDataWarn == null) {
logMapDataWarn = log;
}
if (renderingTypes == null) {
renderingTypes = MapRenderingTypes.getDefault();
}
if (mapZooms == null) {
mapZooms = MapZooms.getDefault();
}
// clear previous results and setting variables
try {
final BasemapProcessor processor = new BasemapProcessor(logMapDataWarn, mapZooms, renderingTypes, zoomWaySmothness);
for (File readFile : readFiles) {
this.accessor = new OsmDbAccessor();
createPlainOsmDb(progress, readFile, addFilter, true);
// 2. Create index connections and index structure
progress.setGeneralProgress("[50 / 100]");
progress.startTask(Messages.getString("IndexCreator.PROCESS_OSM_NODES"), accessor.getAllNodes());
accessor.iterateOverEntities(progress, EntityType.NODE, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
processor.processEntity(e);
}
});
progress.setGeneralProgress("[70 / 100]");
progress.startTask(Messages.getString("IndexCreator.PROCESS_OSM_WAYS"), accessor.getAllWays());
accessor.iterateOverEntities(progress, EntityType.WAY, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
processor.processEntity(e);
}
});
accessor.closeReadingConnection();
}
mapFile = new File(workingDir, getMapFileName());
// to save space
mapFile.getParentFile().mkdirs();
if (mapFile.exists()) {
mapFile.delete();
}
mapRAFile = new RandomAccessFile(mapFile, "rw");
BinaryMapIndexWriter writer = new BinaryMapIndexWriter(mapRAFile);
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing map index to binary file...", -1);
processor.writeBasemapFile(writer, regionName);
progress.finishTask();
writer.close();
mapRAFile.close();
log.info("Finish writing binary file"); //$NON-NLS-1$
} catch (RuntimeException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (SQLException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (IOException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (SAXException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
}
}
public void generateIndexes(File readFile, IProgress progress, IOsmStorageFilter addFilter, MapZooms mapZooms,
MapRenderingTypes renderingTypes, Log logMapDataWarn) throws IOException, SAXException, SQLException, InterruptedException {
// if(LevelDBAccess.load()){
// dialect = DBDialect.NOSQL;
// }
if(logMapDataWarn == null) {
logMapDataWarn = log ;
}
if (renderingTypes == null) {
renderingTypes = MapRenderingTypes.getDefault();
}
if (mapZooms == null) {
mapZooms = MapZooms.getDefault();
}
// clear previous results and setting variables
if (readFile != null && regionName == null) {
int i = readFile.getName().indexOf('.');
if (i > -1) {
regionName = Algoritms.capitalizeFirstLetterAndLowercase(readFile.getName().substring(0, i));
}
}
this.indexTransportCreator = new IndexTransportCreator();
this.indexPoiCreator = new IndexPoiCreator(renderingTypes);
this.indexAddressCreator = new IndexAddressCreator(logMapDataWarn);
this.indexMapCreator = new IndexVectorMapCreator(logMapDataWarn, mapZooms, renderingTypes, zoomWaySmothness);
this.indexRouteCreator = new IndexRouteCreator(logMapDataWarn);
this.accessor = new OsmDbAccessor();
// init address
String[] normalizeDefaultSuffixes = null;
String[] normalizeSuffixes = null;
if (normalizeStreets) {
normalizeDefaultSuffixes = DataExtractionSettings.getSettings().getDefaultSuffixesToNormalizeStreets();
normalizeSuffixes = DataExtractionSettings.getSettings().getSuffixesToNormalizeStreets();
}
indexAddressCreator.initSettings(normalizeStreets, normalizeDefaultSuffixes, normalizeSuffixes, cityAdminLevel);
// Main generation method
try {
// ////////////////////////////////////////////////////////////////////////
// 1. creating nodes db to fast access for all nodes and simply import all relations, ways, nodes to it
boolean loadFromExistingFile = createPlainOsmDb(progress, readFile, addFilter, false);
// do not create temp map file and rtree files
if (recreateOnlyBinaryFile) {
mapFile = new File(workingDir, getMapFileName());
File tempDBMapFile = new File(workingDir, getTempMapDBFileName());
mapConnection = (Connection) getDatabaseConnection(tempDBMapFile.getAbsolutePath(), mapIndexDBDialect);
mapConnection.setAutoCommit(false);
try {
if (indexMap) {
indexMapCreator.createRTreeFiles(getRTreeMapIndexPackFileName());
}
if (indexRouting) {
indexRouteCreator.createRTreeFiles(getRTreeRouteIndexPackFileName());
}
if (indexTransport) {
indexTransportCreator.createRTreeFile(getRTreeTransportStopsPackFileName());
}
} catch (RTreeException e) {
log.error("Error flushing", e); //$NON-NLS-1$
throw new IOException(e);
}
} else {
// 2. Create index connections and index structure
createDatabaseIndexesStructure();
// 3. Processing all entries
// 3.1 write all cities
if (indexAddress) {
progress.setGeneralProgress("[20 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.INDEX_CITIES"), accessor.getAllNodes()); //$NON-NLS-1$
if (loadFromExistingFile) {
// load cities names
accessor.iterateOverEntities(progress, EntityType.NODE, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) {
indexAddressCreator.registerCityIfNeeded(e);
}
});
}
indexAddressCreator.writeCitiesIntoDb();
}
// 3.2 index address relations
if (indexAddress || indexMap || indexRouting) {
progress.setGeneralProgress("[30 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PREINDEX_BOUNDARIES_RELATIONS"), accessor.getAllRelations()); //$NON-NLS-1$
accessor.iterateOverEntities(progress, EntityType.RELATION, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (indexAddress) {
//indexAddressCreator.indexAddressRelation((Relation) e, ctx); streets needs loaded boundaries !!!
indexAddressCreator.indexBoundariesRelation((Relation) e, ctx);
}
if (indexMap) {
indexMapCreator.indexMapRelationsAndMultiPolygons(e, ctx);
}
if (indexRouting) {
indexRouteCreator.indexRelations(e, ctx);
}
if (indexTransport) {
indexTransportCreator.indexRelations(e, ctx);
}
}
});
if (indexAddress) {
progress.setGeneralProgress("[40 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PREINDEX_BOUNDARIES_WAYS"), accessor.getAllWays()); //$NON-NLS-1$
accessor.iterateOverEntities(progress, EntityType.WAY_BOUNDARY, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
indexAddressCreator.indexBoundariesRelation(e, ctx);
}
});
progress.setGeneralProgress("[42 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.BIND_CITIES_AND_BOUNDARIES"), 100); //$NON-NLS-1$
//finish up the boundaries and cities
indexAddressCreator.bindCitiesWithBoundaries(progress);
progress.setGeneralProgress("[45 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PREINDEX_ADRESS_MAP"), accessor.getAllRelations()); //$NON-NLS-1$
accessor.iterateOverEntities(progress, EntityType.RELATION, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
indexAddressCreator.indexAddressRelation((Relation) e, ctx);
}
});
indexAddressCreator.commitToPutAllCities();
}
}
// 3.3 MAIN iterate over all entities
progress.setGeneralProgress("[50 / 100]");
progress.startTask(Messages.getString("IndexCreator.PROCESS_OSM_NODES"), accessor.getAllNodes());
accessor.iterateOverEntities(progress, EntityType.NODE, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
iterateMainEntity(e, ctx);
}
});
progress.setGeneralProgress("[70 / 100]");
progress.startTask(Messages.getString("IndexCreator.PROCESS_OSM_WAYS"), accessor.getAllWays());
accessor.iterateOverEntities(progress, EntityType.WAY, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
iterateMainEntity(e, ctx);
}
});
progress.setGeneralProgress("[85 / 100]");
progress.startTask(Messages.getString("IndexCreator.PROCESS_OSM_REL"), accessor.getAllRelations());
accessor.iterateOverEntities(progress, EntityType.RELATION, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
iterateMainEntity(e, ctx);
}
});
// 3.4 combine all low level ways and simplify them
if (indexMap || indexRouting) {
progress.setGeneralProgress("[90 / 100]");
if(indexMap) {
progress.startTask(Messages.getString("IndexCreator.INDEX_LO_LEVEL_WAYS"), indexMapCreator.getLowLevelWays());
indexMapCreator.processingLowLevelWays(progress);
}
if(indexRouting) {
progress.startTask(Messages.getString("IndexCreator.INDEX_LO_LEVEL_WAYS"), -1);
indexRouteCreator.processingLowLevelWays(progress);
}
}
// 3.5 update all postal codes from relations
if (indexAddress) {
progress.setGeneralProgress("[90 / 100]");
progress.startTask(Messages.getString("IndexCreator.REGISTER_PCODES"), -1);
indexAddressCreator.processingPostcodes();
}
// 4. packing map rtree indexes
if (indexMap) {
progress.setGeneralProgress("[90 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PACK_RTREE_MAP"), -1); //$NON-NLS-1$
indexMapCreator.packRtreeFiles(getRTreeMapIndexNonPackFileName(), getRTreeMapIndexPackFileName());
}
if(indexRouting) {
indexRouteCreator.packRtreeFiles(getRTreeRouteIndexNonPackFileName(), getRTreeRouteIndexPackFileName());
}
if (indexTransport) {
progress.setGeneralProgress("[90 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PACK_RTREE_TRANSP"), -1); //$NON-NLS-1$
indexTransportCreator.packRTree(getRTreeTransportStopsFileName(), getRTreeTransportStopsPackFileName());
}
}
// 5. Writing binary file
if (indexMap || indexAddress || indexTransport || indexPOI || indexRouting) {
if (mapFile.exists()) {
mapFile.delete();
}
mapRAFile = new RandomAccessFile(mapFile, "rw");
BinaryMapIndexWriter writer = new BinaryMapIndexWriter(mapRAFile);
if (indexMap) {
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing map index to binary file...", -1);
indexMapCreator.writeBinaryMapIndex(writer, regionName);
}
if (indexRouting) {
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing route index to binary file...", -1);
indexRouteCreator.writeBinaryRouteIndex(writer, regionName);
}
if (indexAddress) {
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing address index to binary file...", -1);
indexAddressCreator.writeBinaryAddressIndex(writer, regionName, progress);
}
if (indexPOI) {
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing poi index to binary file...", -1);
indexPoiCreator.writeBinaryPoiIndex(writer, regionName, progress);
}
if (indexTransport) {
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing transport index to binary file...", -1);
indexTransportCreator.writeBinaryTransportIndex(writer, regionName, mapConnection);
}
progress.finishTask();
writer.close();
mapRAFile.close();
log.info("Finish writing binary file"); //$NON-NLS-1$
}
} catch (RuntimeException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (SQLException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (IOException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} catch (SAXException e) {
log.error("Log exception", e); //$NON-NLS-1$
throw e;
} finally {
try {
accessor.closeReadingConnection();
indexPoiCreator.commitAndClosePoiFile(lastModifiedDate);
if(REMOVE_POI_DB) {
indexPoiCreator.removePoiFile();
}
indexAddressCreator.closeAllPreparedStatements();
indexTransportCreator.commitAndCloseFiles(getRTreeTransportStopsFileName(), getRTreeTransportStopsPackFileName(),
deleteDatabaseIndexes);
indexMapCreator.commitAndCloseFiles(getRTreeMapIndexNonPackFileName(), getRTreeMapIndexPackFileName(),
deleteDatabaseIndexes);
indexRouteCreator.commitAndCloseFiles(getRTreeRouteIndexNonPackFileName(), getRTreeRouteIndexPackFileName(),
deleteDatabaseIndexes);
if (mapConnection != null) {
mapConnection.commit();
mapConnection.close();
mapConnection = null;
File tempDBFile = new File(workingDir, getTempMapDBFileName());
if (mapIndexDBDialect.databaseFileExists(tempDBFile) && deleteDatabaseIndexes) {
// do not delete it for now
mapIndexDBDialect.removeDatabase(tempDBFile);
}
}
// do not delete first db connection
if (dbConn != null) {
osmDBdialect.commitDatabase(dbConn);
osmDBdialect.closeDatabase(dbConn);
dbConn = null;
}
if (deleteOsmDB) {
if (DBDialect.DERBY == osmDBdialect) {
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true"); //$NON-NLS-1$
} catch (SQLException e) {
// ignore exception
}
}
osmDBdialect.removeDatabase(dbFile);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException, SAXException, SQLException, InterruptedException {
long time = System.currentTimeMillis();
IndexCreator creator = new IndexCreator(new File("/home/victor/projects/OsmAnd/data/osm-gen/")); //$NON-NLS-1$
creator.setIndexMap(true);
creator.setIndexAddress(true);
creator.setIndexPOI(true);
creator.setIndexTransport(true);
creator.setIndexRouting(true);
// creator.deleteDatabaseIndexes = false;
// creator.recreateOnlyBinaryFile = true;
// creator.deleteOsmDB = false;
creator.setZoomWaySmothness(2);
MapRenderingTypes rt = MapRenderingTypes.getDefault();
MapZooms zooms = MapZooms.getDefault(); // MapZooms.parseZooms("15-");
String file = "/home/victor/projects/OsmAnd/temp/map.osm";
// String file = "/home/victor/projects/OsmAnd/temp/belgium.osm.pbf";
int st = file.lastIndexOf('/');
int e = file.indexOf('.', st);
creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/"+file.substring(st, e) + ".tmp.odb"));
creator.generateIndexes(new File(file),
new ConsoleProgressImplementation(1), null, zooms, rt, log);
// BASEMAP generation
// zooms = MapZooms.parseZooms("1-2;3;4-5;6-7;8-9;10-");
// creator.setMapFileName("World_basemap_2.obf");
// File basemapParent = new File("/home/victor/projects/OsmAnd/data/basemap/ready/");
// creator.generateBasemapIndex(new ConsoleProgressImplementation(1), null, zooms, rt, log, "basemap",
// new File(basemapParent, "10m_coastline_out.osm"),
// new File(basemapParent, "10m_admin_level.osm"),
// new File(basemapParent, "10m_rivers.osm"),
// new File(basemapParent, "10m_lakes.osm"),
// new File(basemapParent, "10m_populated_places.osm")
// );
log.info("WHOLE GENERATION TIME : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
log.info("COORDINATES_SIZE " + BinaryMapIndexWriter.COORDINATES_SIZE + " count " + BinaryMapIndexWriter.COORDINATES_COUNT); //$NON-NLS-1$ //$NON-NLS-2$
log.info("TYPES_SIZE " + BinaryMapIndexWriter.TYPES_SIZE); //$NON-NLS-1$
log.info("ID_SIZE " + BinaryMapIndexWriter.ID_SIZE); //$NON-NLS-1$
log.info("- COORD_TYPES_ID SIZE " + (BinaryMapIndexWriter.COORDINATES_SIZE + BinaryMapIndexWriter.TYPES_SIZE + BinaryMapIndexWriter.ID_SIZE)); //$NON-NLS-1$
log.info("- MAP_DATA_SIZE " + BinaryMapIndexWriter.MAP_DATA_SIZE); //$NON-NLS-1$
log.info("- STRING_TABLE_SIZE " + BinaryMapIndexWriter.STRING_TABLE_SIZE); //$NON-NLS-1$
log.info("-- MAP_DATA_AND_STRINGS SIZE " + (BinaryMapIndexWriter.MAP_DATA_SIZE + BinaryMapIndexWriter.STRING_TABLE_SIZE)); //$NON-NLS-1$
}
}

View file

@ -1,567 +0,0 @@
package net.osmand.data.preparation;
import gnu.trove.list.array.TIntArrayList;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
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 java.util.TreeMap;
import net.osmand.Algoritms;
import net.osmand.IProgress;
import net.osmand.binary.BinaryMapPoiReaderAdapter;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.data.IndexConstants;
import net.osmand.impl.ConsoleProgressImplementation;
import net.osmand.osm.Entity;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.sf.junidecode.Junidecode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class IndexPoiCreator extends AbstractIndexPartCreator {
private static final Log log = LogFactory.getLog(IndexPoiCreator.class);
private Connection poiConnection;
private File poiIndexFile;
private PreparedStatement poiPreparedStatement;
private static final int ZOOM_TO_SAVE_END = 16;
private static final int ZOOM_TO_SAVE_START = 6;
private static final int ZOOM_TO_WRITE_CATEGORIES_START = 12;
private static final int ZOOM_TO_WRITE_CATEGORIES_END = 16;
private static final int CHARACTERS_TO_BUILD = 4;
private boolean useInMemoryCreator = true;
private List<Amenity> tempAmenityList = new ArrayList<Amenity>();
private final MapRenderingTypes renderingTypes;
public IndexPoiCreator(MapRenderingTypes renderingTypes) {
this.renderingTypes = renderingTypes;
}
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
tempAmenityList.clear();
tempAmenityList = Amenity.parseAmenities(renderingTypes, e, tempAmenityList);
if (!tempAmenityList.isEmpty() && poiPreparedStatement != null) {
for (Amenity a : tempAmenityList) {
// do not add that check because it is too much printing for batch creation
// by statistic < 1% creates maps manually
// checkEntity(e);
a.setEntity(e);
if (a.getLocation() != null) {
// do not convert english name
// convertEnglishName(a);
insertAmenityIntoPoi(a);
}
}
}
}
public void commitAndClosePoiFile(Long lastModifiedDate) throws SQLException {
closeAllPreparedStatements();
if (poiConnection != null) {
poiConnection.commit();
poiConnection.close();
poiConnection = null;
if (lastModifiedDate != null) {
poiIndexFile.setLastModified(lastModifiedDate);
}
}
}
public void removePoiFile(){
Algoritms.removeAllFiles(poiIndexFile);
}
public void checkEntity(Entity e) {
String name = e.getTag(OSMTagKey.NAME);
if (name == null) {
String msg = "";
Collection<String> keys = e.getTagKeySet();
int cnt = 0;
for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
String key = iter.next();
if (key.startsWith("name:") && key.length() <= 8) {
// ignore specialties like name:botanical
if (cnt == 0)
msg += "Entity misses default name tag, but it has localized name tag(s):\n";
msg += key + "=" + e.getTag(key) + "\n";
cnt++;
}
}
if (cnt > 0) {
msg += "Consider adding the name tag at " + e.getOsmUrl();
log.warn(msg);
}
}
}
private void insertAmenityIntoPoi(Amenity amenity) throws SQLException {
assert IndexConstants.POI_TABLE != null : "use constants here to show table usage "; //$NON-NLS-1$
poiPreparedStatement.setLong(1, amenity.getId());
poiPreparedStatement.setInt(2, MapUtils.get31TileNumberX(amenity.getLocation().getLongitude()));
poiPreparedStatement.setInt(3, MapUtils.get31TileNumberY(amenity.getLocation().getLatitude()));
poiPreparedStatement.setString(4, amenity.getEnName());
poiPreparedStatement.setString(5, amenity.getName());
poiPreparedStatement.setString(6, AmenityType.valueToString(amenity.getType()));
poiPreparedStatement.setString(7, amenity.getSubType());
poiPreparedStatement.setString(8, amenity.getOpeningHours());
poiPreparedStatement.setString(9, amenity.getSite());
poiPreparedStatement.setString(10, amenity.getPhone());
poiPreparedStatement.setString(11, amenity.getDescription());
addBatch(poiPreparedStatement);
}
public void createDatabaseStructure(File poiIndexFile) throws SQLException {
this.poiIndexFile = poiIndexFile;
// delete previous file to save space
if (poiIndexFile.exists()) {
Algoritms.removeAllFiles(poiIndexFile);
}
poiIndexFile.getParentFile().mkdirs();
// creating connection
poiConnection = (Connection) DBDialect.SQLITE.getDatabaseConnection(poiIndexFile.getAbsolutePath(), log);
// create database structure
Statement stat = poiConnection.createStatement();
stat.executeUpdate("create table " + IndexConstants.POI_TABLE + //$NON-NLS-1$
" (id bigint, x int, y int, name_en varchar(1024), name varchar(1024), "
+ "type varchar(1024), subtype varchar(1024), opening_hours varchar(1024), phone varchar(1024), site varchar(1024), description varchar(4096), "
+ "primary key(id, type, subtype))");
stat.executeUpdate("create index poi_loc on poi (x, y, type, subtype)");
stat.executeUpdate("create index poi_id on poi (id, type, subtype)");
stat.execute("PRAGMA user_version = " + IndexConstants.POI_TABLE_VERSION); //$NON-NLS-1$
stat.close();
// create prepared statment
poiPreparedStatement = poiConnection
.prepareStatement("INSERT INTO " + IndexConstants.POI_TABLE + "(id, x, y, name_en, name, type, subtype, opening_hours, site, phone, description) " + //$NON-NLS-1$//$NON-NLS-2$
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
pStatements.put(poiPreparedStatement, 0);
poiConnection.setAutoCommit(false);
}
private void buildTypeIds(String category, String subcategory, Map<String, Map<String, Integer>> categories,
Map<String, Integer> catIndexes, TIntArrayList types) {
Map<String, Integer> map = categories.get(category);
if (map == null) {
throw new IllegalArgumentException("Unknown category " + category);
}
int catInd = catIndexes.get(category);
if (subcategory.contains(";") || subcategory.contains(",")) {
String[] split = subcategory.split(",|;");
for (String sub : split) {
sub = sub.trim();
Integer subcatInd = map.get(sub);
if (subcatInd == null) {
throw new IllegalArgumentException("Unknown subcategory " + sub + " category " + category);
}
types.add((subcatInd << BinaryMapPoiReaderAdapter.SHIFT_BITS_CATEGORY) | catInd);
}
} else {
subcategory = subcategory.trim();
Integer subcatInd = map.get(subcategory);
if (subcatInd == null) {
throw new IllegalArgumentException("Unknown subcategory " + subcategory + " category " + category);
}
types.add((subcatInd << BinaryMapPoiReaderAdapter.SHIFT_BITS_CATEGORY) | catInd);
}
}
public void writeBinaryPoiIndex(BinaryMapIndexWriter writer, String regionName, IProgress progress) throws SQLException, IOException {
if (poiPreparedStatement != null) {
closePreparedStatements(poiPreparedStatement);
}
poiConnection.commit();
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
Map<String, Set<PoiTileBox>> namesIndex = new TreeMap<String, Set<PoiTileBox>>();
// 0. process all entities
ResultSet rs;
if(useInMemoryCreator) {
rs = poiConnection.createStatement().executeQuery("SELECT x,y,name,name_en,type,subtype,id,opening_hours,site, phone, description from poi");
} else {
rs = poiConnection.createStatement().executeQuery("SELECT x,y,name,name_en,type,subtype from poi");
}
int zoomToStart = ZOOM_TO_SAVE_START;
Tree<PoiTileBox> rootZoomsTree = new Tree<PoiTileBox>();
rootZoomsTree.setNode(new PoiTileBox());
int minX = Integer.MAX_VALUE;
int maxX = 0;
int minY = Integer.MAX_VALUE;
int maxY = 0;
int count = 0;
ConsoleProgressImplementation console = new ConsoleProgressImplementation();
console.startWork(1000000);
while (rs.next()) {
int x = rs.getInt(1);
int y = rs.getInt(2);
minX = Math.min(x, minX);
maxX = Math.max(x, maxX);
minY = Math.min(y, minY);
maxY = Math.max(y, maxY);
if(count++ > 10000){
count = 0;
console.progress(10000);
}
String name = rs.getString(3);
String nameEn = rs.getString(4);
String type = rs.getString(5);
String subtype = rs.getString(6);
Tree<PoiTileBox> prevTree = rootZoomsTree;
rootZoomsTree.getNode().addCategory(type, subtype);
for (int i = zoomToStart; i <= ZOOM_TO_SAVE_END; i++) {
int xs = x >> (31 - i);
int ys = y >> (31 - i);
Tree<PoiTileBox> subtree = null;
for (Tree<PoiTileBox> sub : prevTree.getSubtrees()) {
if (sub.getNode().x == xs && sub.getNode().y == ys && sub.getNode().zoom == i) {
subtree = sub;
break;
}
}
if (subtree == null) {
subtree = new Tree<PoiTileBox>();
PoiTileBox poiBox = new PoiTileBox();
subtree.setNode(poiBox);
poiBox.x = xs;
poiBox.y = ys;
poiBox.zoom = i;
prevTree.addSubTree(subtree);
}
subtree.getNode().addCategory(type, subtype);
prevTree = subtree;
}
addNamePrefix(name, nameEn, prevTree.getNode(), namesIndex);
if (useInMemoryCreator) {
if (prevTree.getNode().poiData == null) {
prevTree.getNode().poiData = new ArrayList<PoiData>();
}
PoiData poiData = new PoiData();
poiData.x = x;
poiData.y = y;
poiData.name = name;
poiData.nameEn = nameEn;
poiData.type = type;
poiData.subtype = subtype;
poiData.id = rs.getLong(7);
poiData.openingHours = rs.getString(8);
poiData.site = rs.getString(9);
poiData.phone = rs.getString(10);
poiData.description = rs.getString(11);
prevTree.getNode().poiData.add(poiData);
}
}
log.info("Poi processing finishied");
// Finish process all entities
// 1. write header
int right31 = maxX;
int left31 = minX;
int bottom31 = maxY;
int top31 = minY;
long startFpPoiIndex = writer.startWritePoiIndex(regionName, left31, right31, bottom31, top31);
// 2. write categories table
Map<String, Map<String, Integer>> categories = rootZoomsTree.node.categories;
Map<String, Integer> catIndexes = writer.writePoiCategoriesTable(categories);
// 2.5 write names table
Map<PoiTileBox, List<BinaryFileReference>> fpToWriteSeeks = writer.writePoiNameIndex(namesIndex, startFpPoiIndex);
// 3. write boxes
log.info("Poi box processing finishied");
int level = 0;
for (; level < (ZOOM_TO_SAVE_END - zoomToStart); level++) {
int subtrees = rootZoomsTree.getSubTreesOnLevel(level);
if (subtrees > 8) {
level--;
break;
}
}
if (level > 0) {
rootZoomsTree.extractChildrenFromLevel(level);
zoomToStart = zoomToStart + level;
}
// 3.2 write tree using stack
for (Tree<PoiTileBox> subs : rootZoomsTree.getSubtrees()) {
writePoiBoxes(writer, subs, startFpPoiIndex, fpToWriteSeeks, categories, catIndexes);
}
// 4. write poi data
// not so effictive probably better to load in memory one time
PreparedStatement prepareStatement = poiConnection
.prepareStatement("SELECT id, x, y, name_en, name, type, subtype, opening_hours, site, phone from poi "
+ "where x >= ? AND x < ? AND y >= ? AND y < ?");
TIntArrayList types = new TIntArrayList();
for (Map.Entry<PoiTileBox, List<BinaryFileReference>> entry : fpToWriteSeeks.entrySet()) {
int z = entry.getKey().zoom;
int x = entry.getKey().x;
int y = entry.getKey().y;
writer.startWritePoiData(z, x, y, entry.getValue());
if(useInMemoryCreator){
List<PoiData> poiData = entry.getKey().poiData;
for(PoiData poi : poiData){
int x31 = poi.x;
int y31 = poi.y;
String type = poi.type;
String subtype = poi.subtype;
types.clear();
buildTypeIds(type, subtype, categories, catIndexes, types);
int x24shift = (x31 >> 7) - (x << (24 - z));
int y24shift = (y31 >> 7) - (y << (24 - z));
writer.writePoiDataAtom(poi.id, x24shift, y24shift, poi.nameEn, poi.name, types, poi.openingHours, poi.site, poi.phone, poi.description);
}
} else {
prepareStatement.setInt(1, x << (31 - z));
prepareStatement.setInt(2, (x + 1) << (31 - z));
prepareStatement.setInt(3, y << (31 - z));
prepareStatement.setInt(4, (y + 1) << (31 - z));
ResultSet rset = prepareStatement.executeQuery();
while (rset.next()) {
long id = rset.getLong(1);
int x31 = rset.getInt(2);
int y31 = rset.getInt(3);
int x24shift = (x31 >> 7) - (x << (24 - z));
int y24shift = (y31 >> 7) - (y << (24 - z));
String nameEn = rset.getString(4);
String name = rset.getString(5);
String type = rset.getString(6);
String subtype = rset.getString(7);
types.clear();
buildTypeIds(type, subtype, categories, catIndexes, types);
String openingHours = rset.getString(8);
String site = rset.getString(9);
String phone = rset.getString(10);
String description = rset.getString(11);
writer.writePoiDataAtom(id, x24shift, y24shift, nameEn, name, types, openingHours, site, phone, description);
}
rset.close();
}
writer.endWritePoiData();
}
prepareStatement.close();
writer.endWritePoiIndex();
}
public void addNamePrefix(String name, String nameEn, PoiTileBox data, Map<String, Set<PoiTileBox>> poiData) {
if(Algoritms.isEmpty(nameEn)){
nameEn = Junidecode.unidecode(name);
}
parsePrefix(name, data, poiData);
parsePrefix(nameEn, data, poiData);
}
private void parsePrefix(String name, PoiTileBox data, Map<String, Set<PoiTileBox>> poiData) {
int prev = -1;
for (int i = 0; i <= name.length(); i++) {
if (i == name.length() || (!Character.isLetter(name.charAt(i)) && !Character.isDigit(name.charAt(i)) && name.charAt(i) != '\'')) {
if (prev != -1) {
String substr = name.substring(prev, i);
if (substr.length() > CHARACTERS_TO_BUILD) {
substr = substr.substring(0, CHARACTERS_TO_BUILD);
}
String val = substr.toLowerCase();
if(!poiData.containsKey(val)){
poiData.put(val, new LinkedHashSet<PoiTileBox>());
}
poiData.get(val).add(data);
prev = -1;
}
} else {
if(prev == -1){
prev = i;
}
}
}
}
private void writePoiBoxes(BinaryMapIndexWriter writer, Tree<PoiTileBox> tree,
long startFpPoiIndex, Map<PoiTileBox, List<BinaryFileReference>> fpToWriteSeeks,
Map<String, Map<String, Integer>> categories, Map<String, Integer> catIndexes) throws IOException, SQLException {
int x = tree.getNode().x;
int y = tree.getNode().y;
int zoom = tree.getNode().zoom;
boolean end = zoom == ZOOM_TO_SAVE_END;
BinaryFileReference fileRef = writer.startWritePoiBox(zoom, x, y, startFpPoiIndex, end);
if(fileRef != null){
if(!fpToWriteSeeks.containsKey(tree.getNode())) {
fpToWriteSeeks.put(tree.getNode(), new ArrayList<BinaryFileReference>());
}
fpToWriteSeeks.get(tree.getNode()).add(fileRef);
}
if(zoom >= ZOOM_TO_WRITE_CATEGORIES_START && zoom <= ZOOM_TO_WRITE_CATEGORIES_END){
TIntArrayList types = new TIntArrayList();
for(Map.Entry<String, Map<String, Integer>> cats : tree.getNode().categories.entrySet()) {
for(String subcat : cats.getValue().keySet()){
String cat = cats.getKey();
buildTypeIds(cat, subcat, categories, catIndexes, types);
}
}
writer.writePoiCategories(types);
}
if (!end) {
for (Tree<PoiTileBox> subTree : tree.getSubtrees()) {
writePoiBoxes(writer, subTree, startFpPoiIndex, fpToWriteSeeks, categories, catIndexes);
}
}
writer.endWritePoiBox();
}
private static class PoiData {
int x;
int y;
String name;
String nameEn;
String type;
String subtype;
long id;
String openingHours;
String phone;
String site;
String description;
}
public static class PoiTileBox {
int x;
int y;
int zoom;
Map<String, Map<String, Integer>> categories = new LinkedHashMap<String, Map<String, Integer>>();
List<PoiData> poiData = null;
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZoom() {
return zoom;
}
private void addCategory(String cat, String subCat){
if(!categories.containsKey(cat)){
categories.put(cat, new TreeMap<String, Integer>());
}
if (subCat.contains(";") || subCat.contains(",")) {
String[] split = subCat.split(",|;");
for (String sub : split) {
categories.get(cat).put(sub.trim(), 0);
}
} else {
categories.get(cat).put(subCat.trim(), 0);
}
categories.get(cat).put(subCat, 0);
}
}
private static class Tree<T> {
private T node;
private List<Tree<T>> subtrees = null;
public List<Tree<T>> getSubtrees() {
if (subtrees == null) {
subtrees = new ArrayList<Tree<T>>();
}
return subtrees;
}
public void addSubTree(Tree<T> t) {
getSubtrees().add(t);
}
public T getNode() {
return node;
}
public void setNode(T node) {
this.node = node;
}
public void extractChildrenFromLevel(int level) {
List<Tree<T>> list = new ArrayList<Tree<T>>();
collectChildrenFromLevel(list, level);
subtrees = list;
}
public void collectChildrenFromLevel(List<Tree<T>> list, int level) {
if (level == 0) {
if (subtrees != null) {
list.addAll(subtrees);
}
} else if (subtrees != null) {
for (Tree<T> sub : subtrees) {
sub.collectChildrenFromLevel(list, level - 1);
}
}
}
public int getSubTreesOnLevel(int level) {
if (level == 0) {
if (subtrees == null) {
return 0;
} else {
return subtrees.size();
}
} else {
int sum = 0;
if (subtrees != null) {
for (Tree<T> t : subtrees) {
sum += t.getSubTreesOnLevel(level - 1);
}
}
return sum;
}
}
}
}

View file

@ -1,508 +0,0 @@
package net.osmand.data.preparation;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import net.osmand.data.TransportRoute;
import net.osmand.data.TransportStop;
import net.osmand.osm.Entity;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.sf.junidecode.Junidecode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import rtree.Element;
import rtree.IllegalValueException;
import rtree.LeafElement;
import rtree.NonLeafElement;
import rtree.RTree;
import rtree.RTreeException;
import rtree.RTreeInsertException;
import rtree.Rect;
public class IndexTransportCreator extends AbstractIndexPartCreator {
private static final Log log = LogFactory.getLog(IndexTransportCreator.class);
private Set<Long> visitedStops = new HashSet<Long>();
private PreparedStatement transRouteStat;
private PreparedStatement transRouteStopsStat;
private PreparedStatement transStopsStat;
private RTree transportStopsTree;
private Map<Long, Relation> masterRoutes = new HashMap<Long, Relation>();
private static Set<String> acceptedRoutes = new HashSet<String>();
static {
acceptedRoutes.add("bus"); //$NON-NLS-1$
acceptedRoutes.add("trolleybus"); //$NON-NLS-1$
acceptedRoutes.add("share_taxi"); //$NON-NLS-1$
acceptedRoutes.add("subway"); //$NON-NLS-1$
acceptedRoutes.add("train"); //$NON-NLS-1$
acceptedRoutes.add("tram"); //$NON-NLS-1$
acceptedRoutes.add("ferry"); //$NON-NLS-1$
}
public IndexTransportCreator(){
}
public void createRTreeFile(String rtreeTransportStopFile) throws RTreeException{
transportStopsTree = new RTree(rtreeTransportStopFile);
}
public void writeBinaryTransportTree(rtree.Node parent, RTree r, BinaryMapIndexWriter writer,
PreparedStatement selectTransportStop, PreparedStatement selectTransportRouteStop,
Map<Long, Long> transportRoutes, Map<String, Integer> stringTable) throws IOException, RTreeException, SQLException {
Element[] e = parent.getAllElements();
List<Long> routes = null;
for (int i = 0; i < parent.getTotalElements(); i++) {
Rect re = e[i].getRect();
if (e[i].getElementType() == rtree.Node.LEAF_NODE) {
long id = ((LeafElement) e[i]).getPtr();
selectTransportStop.setLong(1, id);
selectTransportRouteStop.setLong(1, id);
ResultSet rs = selectTransportStop.executeQuery();
if (rs.next()) {
int x24 = (int) MapUtils.getTileNumberX(24, rs.getDouble(3));
int y24 = (int) MapUtils.getTileNumberY(24, rs.getDouble(2));
String name = rs.getString(4);
String nameEn = rs.getString(5);
if (nameEn != null && nameEn.equals(Junidecode.unidecode(name))) {
nameEn = null;
}
ResultSet rset = selectTransportRouteStop.executeQuery();
if (routes == null) {
routes = new ArrayList<Long>();
} else {
routes.clear();
}
while (rset.next()) {
Long route = transportRoutes.get(rset.getLong(1));
if (route == null) {
log.error("Something goes wrong with transport route id = " + rset.getLong(1)); //$NON-NLS-1$
} else {
routes.add(route);
}
}
rset.close();
writer.writeTransportStop(id, x24, y24, name, nameEn, stringTable, routes);
} else {
log.error("Something goes wrong with transport id = " + id); //$NON-NLS-1$
}
} else {
long ptr = ((NonLeafElement) e[i]).getPtr();
rtree.Node ns = r.getReadNode(ptr);
writer.startTransportTreeElement(re.getMinX(), re.getMaxX(), re.getMinY(), re.getMaxY());
writeBinaryTransportTree(ns, r, writer, selectTransportStop, selectTransportRouteStop, transportRoutes, stringTable);
writer.endWriteTransportTreeElement();
}
}
}
public void packRTree(String rtreeTransportStopsFileName, String rtreeTransportStopsPackFileName) throws IOException {
transportStopsTree = packRtreeFile(transportStopsTree, rtreeTransportStopsFileName, rtreeTransportStopsPackFileName);
}
public void indexRelations(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Relation && e.getTag(OSMTagKey.ROUTE_MASTER) != null) {
ctx.loadEntityRelation((Relation) e);
for (Entry<Entity, String> child : ((Relation) e).getMemberEntities().entrySet()) {
Entity entity = child.getKey();
masterRoutes.put(entity.getId(), (Relation) e);
}
}
}
public void visitEntityMainStep(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Relation && e.getTag(OSMTagKey.ROUTE) != null) {
ctx.loadEntityRelation((Relation) e);
TransportRoute route = indexTransportRoute((Relation) e);
if (route != null) {
insertTransportIntoIndex(route);
}
}
}
public void createDatabaseStructure(Connection conn, DBDialect dialect, String rtreeStopsFileName) throws SQLException, IOException{
Statement stat = conn.createStatement();
stat.executeUpdate("create table transport_route (id bigint primary key, type varchar(1024), operator varchar(1024)," +
"ref varchar(1024), name varchar(1024), name_en varchar(1024), dist int)");
stat.executeUpdate("create index transport_route_id on transport_route (id)");
stat.executeUpdate("create table transport_route_stop (stop bigint, route bigint, ord int, direction smallint, primary key (route, ord, direction))");
stat.executeUpdate("create index transport_route_stop_stop on transport_route_stop (stop)");
stat.executeUpdate("create index transport_route_stop_route on transport_route_stop (route)");
stat.executeUpdate("create table transport_stop (id bigint primary key, latitude double, longitude double, name varchar(1024), name_en varchar(1024))");
stat.executeUpdate("create index transport_stop_id on transport_stop (id)");
stat.executeUpdate("create index transport_stop_location on transport_stop (latitude, longitude)");
// if(dialect == DBDialect.SQLITE){
// stat.execute("PRAGMA user_version = " + IndexConstants.TRANSPORT_TABLE_VERSION); //$NON-NLS-1$
// }
stat.close();
try {
File file = new File(rtreeStopsFileName);
if (file.exists()) {
file.delete();
}
transportStopsTree = new RTree(file.getAbsolutePath());
} catch (RTreeException e) {
throw new IOException(e);
}
transRouteStat = createStatementTransportRouteInsert(conn);
transRouteStopsStat = createStatementTransportRouteStopInsert(conn);
transStopsStat = createStatementTransportStopInsert(conn);
pStatements.put(transRouteStat, 0);
pStatements.put(transRouteStopsStat, 0);
pStatements.put(transStopsStat, 0);
}
private void insertTransportIntoIndex(TransportRoute route) throws SQLException {
transRouteStat.setLong(1, route.getId());
transRouteStat.setString(2, route.getType());
transRouteStat.setString(3, route.getOperator());
transRouteStat.setString(4, route.getRef());
transRouteStat.setString(5, route.getName());
transRouteStat.setString(6, route.getEnName());
transRouteStat.setInt(7, route.getAvgBothDistance());
addBatch(transRouteStat);
writeRouteStops(route, route.getForwardStops(), true);
writeRouteStops(route, route.getBackwardStops(), false);
}
private PreparedStatement createStatementTransportStopInsert(Connection conn) throws SQLException{
return conn.prepareStatement("insert into transport_stop(id, latitude, longitude, name, name_en) values(?, ?, ?, ?, ?)");
}
private PreparedStatement createStatementTransportRouteStopInsert(Connection conn) throws SQLException{
return conn.prepareStatement("insert into transport_route_stop(route, stop, direction, ord) values(?, ?, ?, ?)");
}
private void writeRouteStops(TransportRoute r, List<TransportStop> stops, boolean direction) throws SQLException {
int i = 0;
for(TransportStop s : stops){
if (!visitedStops.contains(s.getId())) {
transStopsStat.setLong(1, s.getId());
transStopsStat.setDouble(2, s.getLocation().getLatitude());
transStopsStat.setDouble(3, s.getLocation().getLongitude());
transStopsStat.setString(4, s.getName());
transStopsStat.setString(5, s.getEnName());
int x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude());
int y = (int) MapUtils.getTileNumberY(24, s.getLocation().getLatitude());
addBatch(transStopsStat);
try {
transportStopsTree.insert(new LeafElement(new Rect(x, y, x, y), s.getId()));
} catch (RTreeInsertException e) {
throw new IllegalArgumentException(e);
} catch (IllegalValueException e) {
throw new IllegalArgumentException(e);
}
visitedStops.add(s.getId());
}
transRouteStopsStat.setLong(1, r.getId());
transRouteStopsStat.setLong(2, s.getId());
transRouteStopsStat.setInt(3, direction ? 1 : 0);
transRouteStopsStat.setInt(4, i++);
addBatch(transRouteStopsStat);
}
}
private PreparedStatement createStatementTransportRouteInsert(Connection conn) throws SQLException{
return conn.prepareStatement("insert into transport_route(id, type, operator, ref, name, name_en, dist) values(?, ?, ?, ?, ?, ?, ?)");
}
public void writeBinaryTransportIndex(BinaryMapIndexWriter writer, String regionName,
Connection mapConnection) throws IOException, SQLException {
try {
closePreparedStatements(transRouteStat, transRouteStopsStat, transStopsStat);
mapConnection.commit();
transportStopsTree.flush();
visitedStops = null; // allow gc to collect it
PreparedStatement selectTransportRouteData = mapConnection.prepareStatement(
"SELECT id, dist, name, name_en, ref, operator, type FROM transport_route"); //$NON-NLS-1$
PreparedStatement selectTransportData = mapConnection.prepareStatement("SELECT S.stop, S.direction," + //$NON-NLS-1$
" A.latitude, A.longitude, A.name, A.name_en " + //$NON-NLS-1$
"FROM transport_route_stop S INNER JOIN transport_stop A ON A.id = S.stop WHERE S.route = ? ORDER BY S.ord asc"); //$NON-NLS-1$
writer.startWriteTransportIndex(regionName);
writer.startWriteTransportRoutes();
// expect that memory would be enough
Map<String, Integer> stringTable = createStringTableForTransport();
Map<Long, Long> transportRoutes = new LinkedHashMap<Long, Long>();
ResultSet rs = selectTransportRouteData.executeQuery();
List<TransportStop> directStops = new ArrayList<TransportStop>();
List<TransportStop> reverseStops = new ArrayList<TransportStop>();
while (rs.next()) {
long idRoute = rs.getLong(1);
int dist = rs.getInt(2);
String routeName = rs.getString(3);
String routeEnName = rs.getString(4);
if (routeEnName != null && routeEnName.equals(Junidecode.unidecode(routeName))) {
routeEnName = null;
}
String ref = rs.getString(5);
String operator = rs.getString(6);
String type = rs.getString(7);
selectTransportData.setLong(1, idRoute);
ResultSet rset = selectTransportData.executeQuery();
reverseStops.clear();
directStops.clear();
while (rset.next()) {
boolean dir = rset.getInt(2) != 0;
long idStop = rset.getInt(1);
String stopName = rset.getString(5);
String stopEnName = rset.getString(6);
if (stopEnName != null && stopEnName.equals(Junidecode.unidecode(stopName))) {
stopEnName = null;
}
TransportStop st = new TransportStop();
st.setId(idStop);
st.setName(stopName);
st.setLocation(rset.getDouble(3), rset.getDouble(4));
if (stopEnName != null) {
st.setEnName(stopEnName);
}
if (dir) {
directStops.add(st);
} else {
reverseStops.add(st);
}
}
writer.writeTransportRoute(idRoute, routeName, routeEnName, ref, operator, type, dist, directStops, reverseStops,
stringTable, transportRoutes);
}
rs.close();
selectTransportRouteData.close();
selectTransportData.close();
writer.endWriteTransportRoutes();
PreparedStatement selectTransportStop = mapConnection.prepareStatement(
"SELECT A.id, A.latitude, A.longitude, A.name, A.name_en FROM transport_stop A where A.id = ?"); //$NON-NLS-1$
PreparedStatement selectTransportRouteStop = mapConnection.prepareStatement(
"SELECT DISTINCT S.route FROM transport_route_stop S WHERE S.stop = ? "); //$NON-NLS-1$
long rootIndex = transportStopsTree.getFileHdr().getRootIndex();
rtree.Node root = transportStopsTree.getReadNode(rootIndex);
Rect rootBounds = calcBounds(root);
if (rootBounds != null) {
writer.startTransportTreeElement(rootBounds.getMinX(), rootBounds.getMaxX(), rootBounds.getMinY(), rootBounds.getMaxY());
writeBinaryTransportTree(root, transportStopsTree, writer, selectTransportStop, selectTransportRouteStop,
transportRoutes, stringTable);
writer.endWriteTransportTreeElement();
}
selectTransportStop.close();
selectTransportRouteStop.close();
writer.writeTransportStringTable(stringTable);
writer.endWriteTransportIndex();
writer.flush();
} catch (RTreeException e) {
throw new IllegalStateException(e);
}
}
private Rect calcBounds(rtree.Node n) {
Rect r = null;
Element[] e = n.getAllElements();
for (int i = 0; i < n.getTotalElements(); i++) {
Rect re = e[i].getRect();
if (r == null) {
try {
r = new Rect(re.getMinX(), re.getMinY(), re.getMaxX(), re.getMaxY());
} catch (IllegalValueException ex) {
}
} else {
r.expandToInclude(re);
}
}
return r;
}
private int registerString(Map<String, Integer> stringTable, String s) {
if (stringTable.containsKey(s)) {
return stringTable.get(s);
}
int size = stringTable.size();
stringTable.put(s, size);
return size;
}
private Map<String, Integer> createStringTableForTransport() {
Map<String, Integer> stringTable = new LinkedHashMap<String, Integer>();
registerString(stringTable, "bus"); //$NON-NLS-1$
registerString(stringTable, "trolleybus"); //$NON-NLS-1$
registerString(stringTable, "subway"); //$NON-NLS-1$
registerString(stringTable, "tram"); //$NON-NLS-1$
registerString(stringTable, "share_taxi"); //$NON-NLS-1$
registerString(stringTable, "taxi"); //$NON-NLS-1$
registerString(stringTable, "train"); //$NON-NLS-1$
registerString(stringTable, "ferry"); //$NON-NLS-1$
return stringTable;
}
public void commitAndCloseFiles(String rtreeStopsFileName, String rtreeStopsPackFileName, boolean deleteDatabaseIndexes) throws IOException, SQLException {
// delete transport rtree files
if (transportStopsTree != null) {
transportStopsTree.getFileHdr().getFile().close();
File f = new File(rtreeStopsFileName);
if (f.exists() && deleteDatabaseIndexes) {
f.delete();
}
f = new File(rtreeStopsPackFileName);
if (f.exists() && deleteDatabaseIndexes) {
f.delete();
}
}
closeAllPreparedStatements();
}
private TransportRoute indexTransportRoute(Relation rel) {
String ref = rel.getTag(OSMTagKey.REF);
String route = rel.getTag(OSMTagKey.ROUTE);
String operator = rel.getTag(OSMTagKey.OPERATOR);
Relation master = masterRoutes.get(rel.getId());
if (master != null) {
if (ref == null)
ref = master.getTag(OSMTagKey.REF);
if (route == null)
route = master.getTag(OSMTagKey.ROUTE);
if (operator == null)
operator = master.getTag(OSMTagKey.OPERATOR);
}
if (route == null || ref == null) {
return null;
}
if (!acceptedRoutes.contains(route)) {
return null;
}
TransportRoute r = new TransportRoute(rel, ref);
r.setOperator(operator);
r.setType(route);
if (operator != null) {
route = operator + " : " + route; //$NON-NLS-1$
}
final Map<TransportStop, Integer> forwardStops = new LinkedHashMap<TransportStop, Integer>();
final Map<TransportStop, Integer> backwardStops = new LinkedHashMap<TransportStop, Integer>();
int currentStop = 0;
int forwardStop = 0;
int backwardStop = 0;
for (Entry<Entity, String> e : rel.getMemberEntities().entrySet()) {
if (e.getValue().contains("stop")) { //$NON-NLS-1$
if (e.getKey() instanceof Node) {
TransportStop stop = new TransportStop(e.getKey());
boolean forward = e.getValue().contains("forward"); //$NON-NLS-1$
boolean backward = e.getValue().contains("backward"); //$NON-NLS-1$
currentStop++;
if (forward || !backward) {
forwardStop++;
}
if (backward) {
backwardStop++;
}
boolean common = !forward && !backward;
int index = -1;
int i = e.getValue().length() - 1;
int accum = 1;
while (i >= 0 && Character.isDigit(e.getValue().charAt(i))) {
if (index < 0) {
index = 0;
}
index = accum * Character.getNumericValue(e.getValue().charAt(i)) + index;
accum *= 10;
i--;
}
if (index < 0) {
index = forward ? forwardStop : (backward ? backwardStop : currentStop);
}
if (forward || common) {
forwardStops.put(stop, index);
r.getForwardStops().add(stop);
}
if (backward || common) {
if (common) {
// put with negative index
backwardStops.put(stop, -index);
} else {
backwardStops.put(stop, index);
}
r.getBackwardStops().add(stop);
}
}
} else if (e.getKey() instanceof Way) {
r.addWay((Way) e.getKey());
}
}
if (forwardStops.isEmpty() && backwardStops.isEmpty()) {
return null;
}
Collections.sort(r.getForwardStops(), new Comparator<TransportStop>() {
@Override
public int compare(TransportStop o1, TransportStop o2) {
return forwardStops.get(o1) - forwardStops.get(o2);
}
});
// all common stops are with negative index (reeval them)
for (TransportStop s : new ArrayList<TransportStop>(backwardStops.keySet())) {
if (backwardStops.get(s) < 0) {
backwardStops.put(s, backwardStops.size() + backwardStops.get(s) - 1);
}
}
Collections.sort(r.getBackwardStops(), new Comparator<TransportStop>() {
@Override
public int compare(TransportStop o1, TransportStop o2) {
return backwardStops.get(o1) - backwardStops.get(o2);
}
});
return r;
}
}

View file

@ -1,880 +0,0 @@
package net.osmand.data.preparation;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.hash.TLongHashSet;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.osmand.Algoritms;
import net.osmand.IProgress;
import net.osmand.binary.OsmandOdb.MapData;
import net.osmand.binary.OsmandOdb.MapDataBlock;
import net.osmand.data.MapAlgorithms;
import net.osmand.data.Multipolygon;
import net.osmand.data.Ring;
import net.osmand.data.preparation.MapZooms.MapZoomPair;
import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapRenderingTypes.MapRulType;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import org.apache.commons.logging.Log;
import rtree.Element;
import rtree.IllegalValueException;
import rtree.LeafElement;
import rtree.NonLeafElement;
import rtree.RTree;
import rtree.RTreeException;
import rtree.RTreeInsertException;
import rtree.Rect;
public class IndexVectorMapCreator extends AbstractIndexPartCreator {
// map zoom levels <= 2^MAP_LEVELS
private static final int MAP_LEVELS_POWER = 3;
private static final int MAP_LEVELS_MAX = 1 << MAP_LEVELS_POWER;
private MapRenderingTypes renderingTypes;
private MapZooms mapZooms;
Map<Long, TIntArrayList> multiPolygonsWays = new LinkedHashMap<Long, TIntArrayList>();
// local purpose to speed up processing cache allocation
TIntArrayList typeUse = new TIntArrayList(8);
List<MapRulType> tempNameUse = new ArrayList<MapRenderingTypes.MapRulType>();
Map<MapRulType, String> namesUse = new LinkedHashMap<MapRenderingTypes.MapRulType, String>();
Map<EntityId, Map<String, String>> propogatedTags = new LinkedHashMap<Entity.EntityId, Map<String, String>>();
TIntArrayList addtypeUse = new TIntArrayList(8);
private PreparedStatement mapBinaryStat;
private PreparedStatement mapLowLevelBinaryStat;
private int lowLevelWays = -1;
private RTree[] mapTree = null;
private Connection mapConnection;
private int zoomWaySmothness = 0;
private final Log logMapDataWarn;
private static long notUsedId = - 1 << 40; // million million
public IndexVectorMapCreator(Log logMapDataWarn, MapZooms mapZooms, MapRenderingTypes renderingTypes, int zoomWaySmothness) {
this.logMapDataWarn = logMapDataWarn;
this.mapZooms = mapZooms;
this.zoomWaySmothness = zoomWaySmothness;
this.renderingTypes = renderingTypes;
lowLevelWays = -1;
}
public void indexMapRelationsAndMultiPolygons(Entity e, OsmDbAccessorContext ctx) throws SQLException {
indexMultiPolygon(e, ctx);
if(e instanceof Relation) {
Map<String, String> ts = ((Relation) e).getTags();
Map<String, String> propogated = null;
Iterator<Entry<String, String>> its = ts.entrySet().iterator();
while(its.hasNext()) {
Entry<String, String> ev = its.next();
if(renderingTypes.isRelationalTagValuePropogated(ev.getKey(), ev.getValue())) {
if(propogated == null) {
propogated = new LinkedHashMap<String, String>();
}
propogated.put(ev.getKey(), ev.getValue());
}
}
if(propogated != null) {
ctx.loadEntityRelation((Relation) e);
for(EntityId id : ((Relation) e).getMembersMap().keySet()) {
if(!propogatedTags.containsKey(id)) {
propogatedTags.put(id, new LinkedHashMap<String, String>());
}
propogatedTags.get(id).putAll(propogated);
}
}
}
}
/**
* index a multipolygon into the database
* only multipolygons without admin_level and with type=multipolygon are indexed
* broken multipolygons are also indexed, inner ways are sometimes left out, broken rings are split and closed
* broken multipolygons will normally be logged
* @param e the entity to index
* @param ctx the database context
* @throws SQLException
*/
private void indexMultiPolygon(Entity e, OsmDbAccessorContext ctx) throws SQLException {
// Don't handle things that aren't multipolygon, and nothing administrative
if (! (e instanceof Relation) ||
! "multipolygon".equals(e.getTag(OSMTagKey.TYPE)) ||
e.getTag(OSMTagKey.ADMIN_LEVEL) != null ) return;
ctx.loadEntityRelation((Relation) e);
Map<Entity, String> entities = ((Relation) e).getMemberEntities();
// create a multipolygon object for this
Multipolygon original = new Multipolygon(e.getId());
// fill the multipolygon with all ways from the Relation
for (Entity es : entities.keySet()) {
if (es instanceof Way) {
boolean inner = "inner".equals(entities.get(es)); //$NON-NLS-1$
if (inner) {
original.addInnerWay((Way) es);
} else {
original.addOuterWay((Way) es);
}
}
}
renderingTypes.encodeEntityWithType(e, mapZooms.getLevel(0).getMaxZoom(), typeUse, addtypeUse, namesUse, tempNameUse);
//Don't add multipolygons with an unknown type
if (typeUse.size() == 0) return;
// Log the fact that Rings aren't complete, but continue with the relation, try to close it as well as possible
if (!original.areRingsComplete()) {
logMapDataWarn.warn("In multipolygon " + e.getId() + " there are incompleted ways");
}
// Rings with different types (inner or outer) in one ring will be logged in the previous case
// The Rings are only composed by type, so if one way gets in a different Ring, the rings will be incomplete
List<Multipolygon> multipolygons = original.splitPerOuterRing(logMapDataWarn);
for (Multipolygon m : multipolygons) {
if(m.getOuterNodes().size() == 0) {
logMapDataWarn.warn("Multipolygon has an outer ring that can't be formed: "+e.getId());
// don't index this
continue;
}
// innerWays are new closed ways
List<List<Node>> innerWays = new ArrayList<List<Node>>();
for (Ring r : m.getInnerRings()) {
innerWays.add(r.getBorder());
}
// don't use the relation ids. Create new ones
long baseId = notUsedId --;
nextZoom: for (int level = 0; level < mapZooms.size(); level++) {
renderingTypes.encodeEntityWithType(e, mapZooms.getLevel(level).getMaxZoom(), typeUse, addtypeUse, namesUse,
tempNameUse);
if (typeUse.isEmpty()) {
continue;
}
long id = convertBaseIdToGeneratedId(baseId, level);
// simplify route
List<Node> outerWay = m.getOuterNodes();
int zoomToSimplify = mapZooms.getLevel(level).getMaxZoom() - 1;
if (zoomToSimplify < 15) {
outerWay = simplifyCycleWay(outerWay, zoomToSimplify, zoomWaySmothness);
if (outerWay == null) {
continue nextZoom;
}
List<List<Node>> newinnerWays = new ArrayList<List<Node>>();
for (List<Node> ls : innerWays) {
ls = simplifyCycleWay(ls, zoomToSimplify, zoomWaySmothness);
if (ls != null) {
newinnerWays.add(ls);
}
}
innerWays = newinnerWays;
}
insertBinaryMapRenderObjectIndex(mapTree[level], outerWay, innerWays, namesUse, id, true, typeUse, addtypeUse, true);
}
}
}
public static List<Node> simplifyCycleWay(List<Node> ns, int zoom, int zoomWaySmothness) throws SQLException {
if (checkForSmallAreas(ns, zoom + Math.min(zoomWaySmothness / 2, 3), 2, 4)) {
return null;
}
List<Node> res = new ArrayList<Node>();
// simplification
MapAlgorithms.simplifyDouglasPeucker(ns, zoom + 8 + zoomWaySmothness, 3, res);
if (res.size() < 2) {
return null;
}
return res;
}
public int getLowLevelWays() {
return lowLevelWays;
}
private void loadNodes(byte[] nodes, List<Float> toPut) {
toPut.clear();
for (int i = 0; i < nodes.length;) {
int lat = Algoritms.parseIntFromBytes(nodes, i);
i += 4;
int lon = Algoritms.parseIntFromBytes(nodes, i);
i += 4;
toPut.add(Float.intBitsToFloat(lat));
toPut.add(Float.intBitsToFloat(lon));
}
}
private void parseAndSort(TIntArrayList ts, byte[] bs) {
ts.clear();
if (bs != null && bs.length > 0) {
for (int j = 0; j < bs.length; j += 2) {
ts.add(Algoritms.parseSmallIntFromBytes(bs, j));
}
}
ts.sort();
}
public void processingLowLevelWays(IProgress progress) throws SQLException {
mapLowLevelBinaryStat.executeBatch();
mapLowLevelBinaryStat.close();
pStatements.remove(mapLowLevelBinaryStat);
mapLowLevelBinaryStat = null;
mapConnection.commit();
PreparedStatement startStat = mapConnection.prepareStatement("SELECT id, start_node, end_node, nodes, name, type, addType FROM low_level_map_objects"
+ " WHERE start_node = ? AND level = ?");
PreparedStatement endStat = mapConnection.prepareStatement("SELECT id, start_node, end_node, nodes, name, type, addType FROM low_level_map_objects"
+ " WHERE end_node = ? AND level = ?");
Statement selectStatement = mapConnection.createStatement();
ResultSet rs = selectStatement.executeQuery("SELECT id, start_node, end_node, nodes, name, type, addType, level FROM low_level_map_objects");
TLongHashSet visitedWays = new TLongHashSet();
ArrayList<Float> list = new ArrayList<Float>(100);
TIntArrayList temp = new TIntArrayList();
TIntArrayList tempAdd = new TIntArrayList();
while (rs.next()) {
if (lowLevelWays != -1) {
progress.progress(1);
}
long id = rs.getLong(1);
if (visitedWays.contains(id)) {
continue;
}
visitedWays.add(id);
int level = rs.getInt(8);
int zoom = mapZooms.getLevel(level).getMaxZoom();
long startNode = rs.getLong(2);
long endNode = rs.getLong(3);
String name = rs.getString(5);
parseAndSort(typeUse, rs.getBytes(6));
parseAndSort(addtypeUse, rs.getBytes(7));
loadNodes(rs.getBytes(4), list);
ArrayList<Float> wayNodes = new ArrayList<Float>(list);
// combine startPoint with EndPoint
boolean combined = true;
while (combined) {
combined = false;
endStat.setLong(1, startNode);
endStat.setShort(2, (short) level);
ResultSet fs = endStat.executeQuery();
// search by exact name
while (fs.next() && !combined) {
if (!visitedWays.contains(fs.getLong(1))) {
parseAndSort(temp, fs.getBytes(6));
parseAndSort(tempAdd, fs.getBytes(7));
if(temp.equals(typeUse) && tempAdd.equals(addtypeUse)){
combined = true;
long lid = fs.getLong(1);
startNode = fs.getLong(2);
visitedWays.add(lid);
loadNodes(fs.getBytes(4), list);
if(!Algoritms.objectEquals(fs.getString(5), name)){
name = null;
}
ArrayList<Float> li = new ArrayList<Float>(list);
// remove first lat/lon point
wayNodes.remove(0);
wayNodes.remove(0);
li.addAll(wayNodes);
wayNodes = li;
}
}
}
fs.close();
}
// combined end point
combined = true;
while (combined) {
combined = false;
startStat.setLong(1, endNode);
startStat.setShort(2, (short) level);
ResultSet fs = startStat.executeQuery();
while (fs.next() && !combined) {
if (!visitedWays.contains(fs.getLong(1))) {
parseAndSort(temp, fs.getBytes(6));
parseAndSort(tempAdd, fs.getBytes(7));
if(temp.equals(typeUse) && tempAdd.equals(addtypeUse)){
combined = true;
long lid = fs.getLong(1);
if (!Algoritms.objectEquals(fs.getString(5), name)) {
name = null;
}
endNode = fs.getLong(3);
visitedWays.add(lid);
loadNodes(fs.getBytes(4), list);
for (int i = 2; i < list.size(); i++) {
wayNodes.add(list.get(i));
}
}
}
}
fs.close();
}
List<Node> wNodes = new ArrayList<Node>();
int wNsize = wayNodes.size();
for (int i = 0; i < wNsize; i += 2) {
wNodes.add(new Node(wayNodes.get(i), wayNodes.get(i + 1), i == 0 ? startNode : endNode));
}
boolean skip = false;
boolean cycle = startNode == endNode;
if (cycle) {
skip = checkForSmallAreas(wNodes, zoom + Math.min(zoomWaySmothness / 2, 3), 3, 4);
} else {
// coastline
if(!typeUse.contains(renderingTypes.getCoastlineRuleType().getInternalId())) {
skip = checkForSmallAreas(wNodes, zoom + Math.min(zoomWaySmothness / 2, 3), 2, 8);
}
}
if (!skip) {
List<Node> res = new ArrayList<Node>();
MapAlgorithms.simplifyDouglasPeucker(wNodes, zoom - 1 + 8 + zoomWaySmothness, 3, res);
if (res.size() > 0) {
namesUse.clear();
if (name != null && name.length() > 0) {
namesUse.put(renderingTypes.getNameRuleType(), name);
}
insertBinaryMapRenderObjectIndex(mapTree[level], res, null, namesUse, id, false, typeUse, addtypeUse, false);
}
}
// end cycle
}
}
public static boolean checkForSmallAreas(List<Node> nodes, int zoom, int minz, int maxz) {
int minX = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE;
int maxY = Integer.MIN_VALUE;
int c = 0;
int nsize = nodes.size();
for (int i = 0; i < nsize; i++) {
if (nodes.get(i) != null) {
c++;
int x = (int) (MapUtils.getTileNumberX(zoom, nodes.get(i).getLongitude()) * 256d);
int y = (int) (MapUtils.getTileNumberY(zoom, nodes.get(i).getLatitude()) * 256d);
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
}
if (c < 2) {
return true;
}
return ((maxX - minX) <= minz && (maxY - minY) <= maxz) || ((maxX - minX) <= maxz && (maxY - minY) <= minz);
}
public void iterateMainEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Way || e instanceof Node) {
EntityId eid = EntityId.valueOf(e);
Map<String, String> tags = propogatedTags.get(eid);
if (tags != null) {
Iterator<Entry<String, String>> iterator = tags.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, String> ts = iterator.next();
if (e.getTag(ts.getKey()) == null) {
e.putTag(ts.getKey(), ts.getValue());
}
}
}
// manipulate what kind of way to load
for (int level = 0; level < mapZooms.size(); level++) {
boolean area = renderingTypes.encodeEntityWithType(e, mapZooms.getLevel(level).getMaxZoom(), typeUse, addtypeUse, namesUse,
tempNameUse);
if (typeUse.isEmpty()) {
continue;
}
boolean hasMulti = e instanceof Way && multiPolygonsWays.containsKey(e.getId());
if (hasMulti) {
TIntArrayList set = multiPolygonsWays.get(e.getId());
typeUse.removeAll(set);
}
if (typeUse.isEmpty()) {
continue;
}
long id = convertBaseIdToGeneratedId(e.getId(), level);
List<Node> res = null;
if (e instanceof Node) {
res = Collections.singletonList((Node) e);
} else {
id |= 1;
// simplify route
int zoomToSimplify = mapZooms.getLevel(level).getMaxZoom() - 1;
if (zoomToSimplify < 15) {
boolean cycle = ((Way) e).getFirstNodeId() == ((Way) e).getLastNodeId();
if (cycle) {
res = simplifyCycleWay(((Way) e).getNodes(), zoomToSimplify, zoomWaySmothness);
} else {
String ename = namesUse.get(renderingTypes.getNameRuleType());
insertLowLevelMapBinaryObject(level, zoomToSimplify, typeUse, addtypeUse, id, ((Way) e).getNodes(), ename);
}
} else {
res = ((Way) e).getNodes();
}
}
if (res != null) {
insertBinaryMapRenderObjectIndex(mapTree[level], res, null, namesUse, id, area, typeUse, addtypeUse, true);
}
}
}
}
public void writeBinaryMapIndex(BinaryMapIndexWriter writer, String regionName) throws IOException, SQLException {
closePreparedStatements(mapBinaryStat, mapLowLevelBinaryStat);
mapConnection.commit();
try {
writer.startWriteMapIndex(regionName);
// write map encoding rules
writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes());
PreparedStatement selectData = mapConnection
.prepareStatement("SELECT area, coordinates, innerPolygons, types, additionalTypes, name FROM binary_map_objects WHERE id = ?");
// write map levels and map index
TLongObjectHashMap<BinaryFileReference> treeHeader = new TLongObjectHashMap<BinaryFileReference>();
for (int i = 0; i < mapZooms.size(); i++) {
RTree rtree = mapTree[i];
long rootIndex = rtree.getFileHdr().getRootIndex();
rtree.Node root = rtree.getReadNode(rootIndex);
Rect rootBounds = calcBounds(root);
if (rootBounds != null) {
writer.startWriteMapLevelIndex(mapZooms.getLevel(i).getMinZoom(), mapZooms.getLevel(i).getMaxZoom(),
rootBounds.getMinX(), rootBounds.getMaxX(), rootBounds.getMinY(), rootBounds.getMaxY());
writeBinaryMapTree(root, rootBounds, rtree, writer, treeHeader);
writeBinaryMapBlock(root, rootBounds, rtree, writer, selectData, treeHeader, new LinkedHashMap<String, Integer>(),
new LinkedHashMap<MapRenderingTypes.MapRulType, String>(), mapZooms.getLevel(i));
writer.endWriteMapLevelIndex();
}
}
selectData.close();
writer.endWriteMapIndex();
writer.flush();
} catch (RTreeException e) {
throw new IllegalStateException(e);
}
}
private long convertBaseIdToGeneratedId(long baseId, int level) {
if (level >= MAP_LEVELS_MAX) {
throw new IllegalArgumentException("Number of zoom levels " + level + " exceeds allowed maximum : " + MAP_LEVELS_MAX);
}
return ((baseId << MAP_LEVELS_POWER) | level) << 1;
}
public long convertGeneratedIdToObfWrite(long id) {
return (id >> (MAP_LEVELS_POWER)) + (id & 1);
}
private static final char SPECIAL_CHAR = ((char) 0x60000);
private String encodeNames(Map<MapRulType, String> tempNames) {
StringBuilder b = new StringBuilder();
for (Map.Entry<MapRulType, String> e : tempNames.entrySet()) {
if (e.getValue() != null) {
b.append(SPECIAL_CHAR).append((char)e.getKey().getInternalId()).append(e.getValue());
}
}
return b.toString();
}
private void decodeNames(String name, Map<MapRulType, String> tempNames) {
int i = name.indexOf(SPECIAL_CHAR);
while (i != -1) {
int n = name.indexOf(SPECIAL_CHAR, i + 2);
int ch = (short) name.charAt(i + 1);
MapRulType rt = renderingTypes.getTypeByInternalId(ch);
if (n == -1) {
tempNames.put(rt, name.substring(i + 2));
} else {
tempNames.put(rt, name.substring(i + 2, n));
}
i = n;
}
}
public void writeBinaryMapBlock(rtree.Node parent, Rect parentBounds, RTree r, BinaryMapIndexWriter writer, PreparedStatement selectData,
TLongObjectHashMap<BinaryFileReference> bounds, Map<String, Integer> tempStringTable, Map<MapRulType, String> tempNames, MapZoomPair level)
throws IOException, RTreeException, SQLException {
Element[] e = parent.getAllElements();
MapDataBlock.Builder dataBlock = null;
BinaryFileReference ref = bounds.get(parent.getNodeIndex());
long baseId = 0;
for (int i = 0; i < parent.getTotalElements(); i++) {
if (e[i].getElementType() == rtree.Node.LEAF_NODE) {
long id = ((LeafElement) e[i]).getPtr();
selectData.setLong(1, id);
// selectData = mapConnection.prepareStatement("SELECT area, coordinates, innerPolygons, types, additionalTypes, name FROM binary_map_objects WHERE id = ?");
ResultSet rs = selectData.executeQuery();
if (rs.next()) {
long cid = convertGeneratedIdToObfWrite(id);
if (dataBlock == null) {
baseId = cid;
dataBlock = writer.createWriteMapDataBlock(baseId);
tempStringTable.clear();
}
tempNames.clear();
decodeNames(rs.getString(6), tempNames);
byte[] types = rs.getBytes(4);
int[] typeUse = new int[types.length / 2];
for (int j = 0; j < types.length; j += 2) {
int ids = Algoritms.parseSmallIntFromBytes(types, j);
typeUse[j / 2] = renderingTypes.getTypeByInternalId(ids).getTargetId();
}
byte[] addTypes = rs.getBytes(5);
int[] addtypeUse = null ;
if (addTypes != null) {
addtypeUse = new int[addTypes.length / 2];
for (int j = 0; j < addTypes.length; j += 2) {
int ids = Algoritms.parseSmallIntFromBytes(addTypes, j);
addtypeUse[j / 2] = renderingTypes.getTypeByInternalId(ids).getTargetId();
}
}
MapData mapData = writer.writeMapData(cid - baseId, parentBounds.getMinX(), parentBounds.getMinY(), rs.getBoolean(1), rs.getBytes(2), rs.getBytes(3),
typeUse, addtypeUse, tempNames, tempStringTable, dataBlock, level.getMaxZoom() > 15);
if(mapData != null) {
dataBlock.addDataObjects(mapData);
}
} else {
logMapDataWarn.error("Something goes wrong with id = " + id); //$NON-NLS-1$
}
}
}
if (dataBlock != null) {
writer.writeMapDataBlock(dataBlock, tempStringTable, ref);
}
for (int i = 0; i < parent.getTotalElements(); i++) {
if (e[i].getElementType() != rtree.Node.LEAF_NODE) {
long ptr = ((NonLeafElement) e[i]).getPtr();
rtree.Node ns = r.getReadNode(ptr);
writeBinaryMapBlock(ns, e[i].getRect(), r, writer, selectData, bounds, tempStringTable, tempNames,level);
}
}
}
public void writeBinaryMapTree(rtree.Node parent, Rect re, RTree r, BinaryMapIndexWriter writer, TLongObjectHashMap<BinaryFileReference> bounds)
throws IOException, RTreeException {
Element[] e = parent.getAllElements();
boolean containsLeaf = false;
for (int i = 0; i < parent.getTotalElements(); i++) {
if (e[i].getElementType() == rtree.Node.LEAF_NODE) {
containsLeaf = true;
}
}
BinaryFileReference ref = writer.startMapTreeElement(re.getMinX(), re.getMaxX(), re.getMinY(), re.getMaxY(), containsLeaf);
if (ref != null) {
bounds.put(parent.getNodeIndex(), ref);
}
for (int i = 0; i < parent.getTotalElements(); i++) {
if (e[i].getElementType() != rtree.Node.LEAF_NODE) {
rtree.Node chNode = r.getReadNode(((NonLeafElement) e[i]).getPtr());
writeBinaryMapTree(chNode, e[i].getRect(), r, writer, bounds);
}
}
writer.endWriteMapTreeElement();
}
public Rect calcBounds(rtree.Node n) {
Rect r = null;
Element[] e = n.getAllElements();
for (int i = 0; i < n.getTotalElements(); i++) {
Rect re = e[i].getRect();
if (r == null) {
try {
r = new Rect(re.getMinX(), re.getMinY(), re.getMaxX(), re.getMaxY());
} catch (IllegalValueException ex) {
}
} else {
r.expandToInclude(re);
}
}
return r;
}
public void createDatabaseStructure(Connection mapConnection, DBDialect dialect, String rtreeMapIndexNonPackFileName)
throws SQLException, IOException {
createMapIndexStructure(mapConnection);
this.mapConnection = mapConnection;
mapBinaryStat = createStatementMapBinaryInsert(mapConnection);
mapLowLevelBinaryStat = createStatementLowLevelMapBinaryInsert(mapConnection);
try {
mapTree = new RTree[mapZooms.size()];
for (int i = 0; i < mapZooms.size(); i++) {
File file = new File(rtreeMapIndexNonPackFileName + i);
if (file.exists()) {
file.delete();
}
mapTree[i] = new RTree(rtreeMapIndexNonPackFileName + i);
// very slow
// mapTree[i].getFileHdr().setBufferPolicy(true);
}
} catch (RTreeException e) {
throw new IOException(e);
}
pStatements.put(mapBinaryStat, 0);
pStatements.put(mapLowLevelBinaryStat, 0);
}
private void createMapIndexStructure(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
stat.executeUpdate("create table binary_map_objects (id bigint primary key, name varchar(4096), "
+ "area smallint, types binary, additionalTypes binary, coordinates binary, innerPolygons binary)");
stat.executeUpdate("create index binary_map_objects_ind on binary_map_objects (id)");
stat.executeUpdate("create table low_level_map_objects (id bigint primary key, start_node bigint, "
+ "end_node bigint, name varchar(1024), nodes binary, type binary, addType binary, level smallint)");
stat.executeUpdate("create index low_level_map_objects_ind on low_level_map_objects (id)");
stat.executeUpdate("create index low_level_map_objects_ind_st on low_level_map_objects (start_node, type)");
stat.executeUpdate("create index low_level_map_objects_ind_end on low_level_map_objects (end_node, type)");
stat.close();
}
private PreparedStatement createStatementMapBinaryInsert(Connection conn) throws SQLException {
return conn
.prepareStatement("insert into binary_map_objects(id, area, coordinates, innerPolygons, types, additionalTypes, name) values(?, ?, ?, ?, ?, ?, ?)");
}
private PreparedStatement createStatementLowLevelMapBinaryInsert(Connection conn) throws SQLException {
return conn
.prepareStatement("insert into low_level_map_objects(id, start_node, end_node, name, nodes, type, addType, level) values(?, ?, ?, ?, ?, ?, ?, ?)");
}
private void insertLowLevelMapBinaryObject(int level, int zoom, TIntArrayList types, TIntArrayList addTypes, long id, List<Node> in, String name)
throws SQLException {
lowLevelWays++;
List<Node> nodes = new ArrayList<Node>();
MapAlgorithms.simplifyDouglasPeucker(in, zoom + 8 + zoomWaySmothness, 3, nodes);
boolean first = true;
long firstId = -1;
long lastId = -1;
ByteArrayOutputStream bNodes = new ByteArrayOutputStream();
ByteArrayOutputStream bTypes = new ByteArrayOutputStream();
ByteArrayOutputStream bAddtTypes = new ByteArrayOutputStream();
try {
for (Node n : nodes) {
if (n != null) {
if (first) {
firstId = n.getId();
first = false;
}
lastId = n.getId();
Algoritms.writeInt(bNodes, Float.floatToRawIntBits((float) n.getLatitude()));
Algoritms.writeInt(bNodes, Float.floatToRawIntBits((float) n.getLongitude()));
}
}
} catch (IOException e) {
throw new IllegalStateException(e);
}
if (firstId == -1) {
return;
}
for (int j = 0; j < types.size(); j++) {
try {
Algoritms.writeSmallInt(bTypes, types.get(j));
} catch (IOException e) {
}
}
for (int j = 0; j < addTypes.size(); j++) {
try {
Algoritms.writeSmallInt(bAddtTypes, addTypes.get(j));
} catch (IOException e) {
}
}
mapLowLevelBinaryStat.setLong(1, id);
mapLowLevelBinaryStat.setLong(2, firstId);
mapLowLevelBinaryStat.setLong(3, lastId);
mapLowLevelBinaryStat.setString(4, name);
mapLowLevelBinaryStat.setBytes(5, bNodes.toByteArray());
mapLowLevelBinaryStat.setBytes(6, bTypes.toByteArray());
mapLowLevelBinaryStat.setBytes(7, bAddtTypes.toByteArray());
mapLowLevelBinaryStat.setShort(8, (short) level);
addBatch(mapLowLevelBinaryStat);
}
private void insertBinaryMapRenderObjectIndex(RTree mapTree, Collection<Node> nodes, List<List<Node>> innerWays,
Map<MapRulType, String> names, long id, boolean area, TIntArrayList types, TIntArrayList addTypes, boolean commit)
throws SQLException {
boolean init = false;
int minX = Integer.MAX_VALUE;
int maxX = 0;
int minY = Integer.MAX_VALUE;
int maxY = 0;
ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream();
ByteArrayOutputStream binnercoord = new ByteArrayOutputStream();
ByteArrayOutputStream btypes = new ByteArrayOutputStream();
ByteArrayOutputStream badditionalTypes = new ByteArrayOutputStream();
try {
for (int j = 0; j < types.size(); j++) {
Algoritms.writeSmallInt(btypes, types.get(j));
}
for (int j = 0; j < addTypes.size(); j++) {
Algoritms.writeSmallInt(badditionalTypes, addTypes.get(j));
}
for (Node n : nodes) {
if (n != null) {
int y = MapUtils.get31TileNumberY(n.getLatitude());
int x = MapUtils.get31TileNumberX(n.getLongitude());
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
init = true;
Algoritms.writeInt(bcoordinates, x);
Algoritms.writeInt(bcoordinates, y);
}
}
if (innerWays != null) {
for (List<Node> ws : innerWays) {
boolean exist = false;
if (ws != null) {
for (Node n : ws) {
if (n != null) {
exist = true;
int y = MapUtils.get31TileNumberY(n.getLatitude());
int x = MapUtils.get31TileNumberX(n.getLongitude());
Algoritms.writeInt(binnercoord, x);
Algoritms.writeInt(binnercoord, y);
}
}
}
if (exist) {
Algoritms.writeInt(binnercoord, 0);
Algoritms.writeInt(binnercoord, 0);
}
}
}
} catch (IOException es) {
throw new IllegalStateException(es);
}
if (init) {
// conn.prepareStatement("insert into binary_map_objects(id, area, coordinates, innerPolygons, types, additionalTypes, name) values(?, ?, ?, ?, ?, ?, ?)");
mapBinaryStat.setLong(1, id);
mapBinaryStat.setBoolean(2, area);
mapBinaryStat.setBytes(3, bcoordinates.toByteArray());
mapBinaryStat.setBytes(4, binnercoord.toByteArray());
mapBinaryStat.setBytes(5, btypes.toByteArray());
mapBinaryStat.setBytes(6, badditionalTypes.toByteArray());
mapBinaryStat.setString(7, encodeNames(names));
addBatch(mapBinaryStat, commit);
try {
mapTree.insert(new LeafElement(new Rect(minX, minY, maxX, maxY), id));
} catch (RTreeInsertException e1) {
throw new IllegalArgumentException(e1);
} catch (IllegalValueException e1) {
throw new IllegalArgumentException(e1);
}
}
}
public void createRTreeFiles(String rTreeMapIndexPackFileName) throws RTreeException {
mapTree = new RTree[mapZooms.size()];
for (int i = 0; i < mapZooms.size(); i++) {
mapTree[i] = new RTree(rTreeMapIndexPackFileName + i);
}
}
public void packRtreeFiles(String rTreeMapIndexNonPackFileName, String rTreeMapIndexPackFileName) throws IOException {
for (int i = 0; i < mapZooms.size(); i++) {
mapTree[i] = packRtreeFile(mapTree[i], rTreeMapIndexNonPackFileName + i, rTreeMapIndexPackFileName + i);
}
}
public void commitAndCloseFiles(String rTreeMapIndexNonPackFileName, String rTreeMapIndexPackFileName, boolean deleteDatabaseIndexes)
throws IOException, SQLException {
// delete map rtree files
if (mapTree != null) {
for (int i = 0; i < mapTree.length; i++) {
if (mapTree[i] != null) {
RandomAccessFile file = mapTree[i].getFileHdr().getFile();
file.close();
}
}
for (int i = 0; i < mapTree.length; i++) {
File f = new File(rTreeMapIndexNonPackFileName + i);
if (f.exists() && deleteDatabaseIndexes) {
f.delete();
}
f = new File(rTreeMapIndexPackFileName + i);
if (f.exists() && deleteDatabaseIndexes) {
f.delete();
}
}
}
closeAllPreparedStatements();
}
public void setZoomWaySmothness(int zoomWaySmothness) {
this.zoomWaySmothness = zoomWaySmothness;
}
public int getZoomWaySmothness() {
return zoomWaySmothness;
}
}

View file

@ -1,97 +0,0 @@
package net.osmand.data.preparation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MapZooms {
public static class MapZoomPair {
public static int MAX_ALLOWED_ZOOM = 22;
private int minZoom;
private int maxZoom;
public MapZoomPair(int minZoom, int maxZoom) {
this.maxZoom = maxZoom;
this.minZoom = minZoom;
}
public int getMinZoom() {
return minZoom;
}
public int getMaxZoom() {
return maxZoom;
}
@Override
public String toString() {
return "MapZoomPair : " + minZoom + " - "+ maxZoom;
}
}
private List<MapZoomPair> levels = new ArrayList<MapZoomPair>();
public List<MapZoomPair> getLevels() {
return levels;
}
public void setLevels(List<MapZoomPair> levels) {
this.levels = levels;
Collections.sort(levels, new Comparator<MapZoomPair>() {
@Override
public int compare(MapZoomPair o1, MapZoomPair o2) {
return -new Integer(o1.getMaxZoom()).compareTo(o2.getMaxZoom());
}
});
}
/**
* @param zooms - could be 5-8;7-10;11-14;15-
*/
public static MapZooms parseZooms(String zooms) throws IllegalArgumentException {
String[] split = zooms.split(";");
int zeroLevel = 15;
List<MapZoomPair> list = new ArrayList<MapZoomPair>();
for(String s : split){
s = s.trim();
int i = s.indexOf('-');
if (i == -1) {
zeroLevel = Integer.parseInt(s);
list.add(0, new MapZoomPair(zeroLevel, zeroLevel));
} else if(s.endsWith("-")){
list.add(0, new MapZoomPair(Integer.parseInt(s.substring(0, i)), MapZoomPair.MAX_ALLOWED_ZOOM));
} else {
list.add(0, new MapZoomPair(Integer.parseInt(s.substring(0, i)), Integer.parseInt(s.substring(i + 1))));
}
}
if(list.size() < 1 || list.size() > 8){
throw new IllegalArgumentException("Map zooms should have at least 1 level and less than 8 levels");
}
MapZooms mapZooms = new MapZooms();
mapZooms.setLevels(list);
return mapZooms;
}
public int size(){
return levels.size();
}
public MapZoomPair getLevel(int level){
return levels.get(level);
}
private static MapZooms DEFAULT = null;
public static String MAP_ZOOMS_DEFAULT = "7;8;9;10;11;12;13-14;15-";
public static MapZooms getDefault(){
if(DEFAULT == null){
DEFAULT = parseZooms(MAP_ZOOMS_DEFAULT);
}
return DEFAULT;
}
}

View file

@ -1,376 +0,0 @@
package net.osmand.data.preparation;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import net.osmand.IProgress;
import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.Node;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
public class OsmDbAccessor implements OsmDbAccessorContext {
//private static final Log log = LogFactory.getLog(OsmDbAccessor.class);
private PreparedStatement pselectNode;
private PreparedStatement pselectWay;
private PreparedStatement pselectRelation;
private int allRelations;
private int allWays;
private int allNodes;
private int allBoundaries;
private boolean realCounts = false;
private Connection dbConn;
private DBDialect dialect;
private PreparedStatement iterateNodes;
private PreparedStatement iterateWays;
private PreparedStatement iterateRelations;
private PreparedStatement iterateWayBoundaries;
public interface OsmDbVisitor {
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException;
}
public OsmDbAccessor(){
}
public void initDatabase(Object dbConnection, DBDialect dialect, int allNodes, int allWays, int allRelations) throws SQLException {
this.dialect = dialect;
this.allNodes = allNodes;
this.allWays = allWays;
this.allRelations = allRelations;
if(this.dialect == DBDialect.NOSQL){
throw new UnsupportedOperationException();
} else {
this.dbConn = (Connection) dbConnection;
pselectNode = dbConn.prepareStatement("select n.latitude, n.longitude, n.tags from node n where n.id = ?"); //$NON-NLS-1$
pselectWay = dbConn.prepareStatement("select w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id where w.id = ? order by w.ord"); //$NON-NLS-1$
pselectRelation = dbConn.prepareStatement("select r.member, r.type, r.role, r.ord, r.tags " + //$NON-NLS-1$
"from relations r where r.id = ? order by r.ord"); //$NON-NLS-1$
iterateNodes = dbConn.prepareStatement("select n.id, n.latitude, n.longitude, n.tags from node n where length(n.tags) > 0"); //$NON-NLS-1$
iterateWays = dbConn.prepareStatement("select w.id, w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id order by w.id, w.ord"); //$NON-NLS-1$
iterateWayBoundaries = dbConn.prepareStatement("select w.id, w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id where w.boundary > 0 order by w.id, w.ord"); //$NON-NLS-1$
iterateRelations = dbConn.prepareStatement("select r.id, r.tags from relations r where length(r.tags) > 0"); //$NON-NLS-1$
}
}
public int getAllNodes() {
return allNodes;
}
public int getAllRelations() {
return allRelations;
}
public int getAllWays() {
return allWays;
}
@Override
public void loadEntityWay(Way e) throws SQLException {
if (e.getEntityIds().isEmpty()) {
pselectWay.setLong(1, e.getId());
if (pselectWay.execute()) {
ResultSet rs = pselectWay.getResultSet();
while (rs.next()) {
int ord = rs.getInt(2);
if (ord == 0) {
readTags(e, rs.getBytes(3));
}
if (rs.getObject(5) != null) {
Node n = new Node(rs.getDouble(4), rs.getDouble(5), rs.getLong(1));
((Way) e).addNode(n);
readTags(n, rs.getBytes(6));
} else {
((Way) e).addNode(rs.getLong(1));
}
}
rs.close();
}
}
}
@Override
public void loadEntityRelation(Relation e) throws SQLException {
loadEntityRelation(e, 1);
}
public void loadEntityRelation(Relation e, int level) throws SQLException {
if (e.isDataLoaded()) { //data was already loaded, nothing to do
return;
}
Map<EntityId, Entity> map = new LinkedHashMap<EntityId, Entity>();
if (e.getMemberIds().isEmpty()) {
pselectRelation.setLong(1, e.getId());
if (pselectRelation.execute()) {
ResultSet rs = pselectRelation.getResultSet();
while (rs.next()) {
int ord = rs.getInt(4);
if (ord == 0 ) {
readTags(e, rs.getBytes(5));
}
e.addMember(rs.getLong(1), EntityType.values()[rs.getInt(2)], rs.getString(3));
}
rs.close();
}
}
Collection<EntityId> ids = e.getMemberIds() ;
if (level > 0) {
for (EntityId i : ids) {
if (i.getType() == EntityType.NODE) {
pselectNode.setLong(1, i.getId());
if (pselectNode.execute()) {
ResultSet rs = pselectNode.getResultSet();
Node n = null;
while (rs.next()) {
if (n == null) {
n = new Node(rs.getDouble(1), rs.getDouble(2), i.getId());
readTags(n, rs.getBytes(3));
}
}
map.put(i, n);
rs.close();
}
} else if (i.getType() == EntityType.WAY) {
Way way = new Way(i.getId());
loadEntityWay(way);
map.put(i, way);
} else if (i.getType() == EntityType.RELATION) {
Relation rel = new Relation(i.getId());
loadEntityRelation(rel, level - 1);
map.put(i, rel);
}
}
e.initializeLinks(map);
e.entityDataLoaded();
}
}
public void readTags(Entity e, byte[] tags){
if (tags != null) {
try {
int prev = 0;
List<String> vs = new ArrayList<String>();
for (int i = 0; i < tags.length; i++) {
if (tags[i] == 0) {
vs.add(new String(tags, prev, i - prev, "UTF-8"));
prev = i + 1;
}
}
for(int i=0; i<vs.size(); i+=2) {
e.putTag(vs.get(i), vs.get(i+1));
}
} catch (UnsupportedEncodingException e1) {
throw new RuntimeException(e1);
}
}
}
public int iterateOverEntities(IProgress progress, EntityType type, OsmDbVisitor visitor) throws SQLException, InterruptedException {
Statement statement = dbConn.createStatement();
PreparedStatement select;
int count = 0;
computeRealCounts(statement);
statement.close();
BlockingQueue<Entity> toProcess = new ArrayBlockingQueue<Entity>(100000);
AbstractProducer entityProducer = null;
if (type == EntityType.NODE) {
// filter out all nodes without tags
select = iterateNodes;
count = allNodes;
} else if (type == EntityType.WAY) {
select = iterateWays;
count = allWays;
} else if (type == EntityType.WAY_BOUNDARY) {
select = iterateWayBoundaries;
count = allBoundaries;
} else {
select = iterateRelations;
count = allRelations;
}
entityProducer = new EntityProducer(toProcess, type, select);
progress.startWork(count);
//produce
entityProducer.start();
try {
// wait a little before starting taking entities from queue
Thread.sleep(150);
} catch (InterruptedException e) {
}
Entity entityToProcess = null;
Entity endEntity = entityProducer.getEndingEntity();
while ((entityToProcess = toProcess.take()) != endEntity) {
if (progress != null) {
progress.progress(1);
}
visitor.iterateEntity(entityToProcess, this);
}
return count;
}
public void computeRealCounts(Statement statement) throws SQLException {
if (!realCounts) {
realCounts = true;
// filter out all nodes without tags
allNodes = statement.executeQuery("select count(distinct n.id) from node n where length(n.tags) > 0").getInt(1); //$NON-NLS-1$
allWays = statement.executeQuery("select count(*) from ways w where w.ord = 0").getInt(1); //$NON-NLS-1$
allRelations = statement.executeQuery("select count(distinct r.id) from relations r").getInt(1); //$NON-NLS-1$
allBoundaries = statement.executeQuery("select count(*) from ways w where w.ord = 0 and w.boundary > 0").getInt(1); //$NON-NLS-1$
}
}
public void closeReadingConnection() throws SQLException {
if (dialect != DBDialect.NOSQL) {
if (pselectNode != null) {
pselectNode.close();
}
if (pselectWay != null) {
pselectWay.close();
}
if (pselectRelation != null) {
pselectRelation.close();
}
if (iterateNodes != null) {
iterateNodes.close();
}
if (iterateRelations != null) {
iterateRelations.close();
}
if (iterateWays != null) {
iterateWays.close();
}
if (iterateWayBoundaries != null) {
iterateWayBoundaries.close();
}
}
}
public class AbstractProducer extends Thread {
private final Entity endingEntity = new Node(0,0,0);
public Entity getEndingEntity() {
return endingEntity;
}
}
public class EntityProducer extends AbstractProducer {
private final BlockingQueue<Entity> toProcess;
private final PreparedStatement select;
private final EntityType type;
private final boolean putEndingEntity;
public EntityProducer(BlockingQueue<Entity> toProcess, EntityType type, PreparedStatement select) {
this(toProcess,type,select,true);
}
public EntityProducer(BlockingQueue<Entity> toProcess, EntityType type, PreparedStatement select, boolean putEndingEntity) {
this.toProcess = toProcess;
this.type = type;
this.select = select;
this.putEndingEntity = putEndingEntity;
setDaemon(true);
setName("EntityProducer");
}
@Override
public void run() {
ResultSet rs;
try {
select.execute();
rs = select.getResultSet();
// rs.setFetchSize(1000); !! not working for SQLite would case troubles probably
Entity prevEntity = null;
long prevId = Long.MIN_VALUE;
while (rs.next()) {
long curId = rs.getLong(1);
boolean newEntity = curId != prevId;
Entity e = prevEntity;
if (type == EntityType.NODE) {
e = new Node(rs.getDouble(2), rs.getDouble(3), curId);
readTags(e, rs.getBytes(4));
} else if (type == EntityType.WAY || type == EntityType.WAY_BOUNDARY) {
if (newEntity) {
e = new Way(curId);
}
int ord = rs.getInt(3);
if (ord == 0) {
readTags(e, rs.getBytes(4));
}
if (rs.getObject(6) == null) {
((Way) e).addNode(rs.getLong(2));
} else {
Node n = new Node(rs.getDouble(5), rs.getDouble(6), rs.getLong(2));
readTags(n, rs.getBytes(7));
((Way) e).addNode(n);
}
} else {
e = new Relation(curId);
readTags(e, rs.getBytes(2));
}
if (newEntity) {
if (prevEntity != null) {
toProcess.put(prevEntity);
}
prevEntity = e;
}
prevId = curId;
}
if (prevEntity != null) {
toProcess.put(prevEntity);
}
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (putEndingEntity) {
try {
toProcess.put(getEndingEntity());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}

View file

@ -1,20 +0,0 @@
package net.osmand.data.preparation;
import java.sql.SQLException;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
public interface OsmDbAccessorContext {
/**
* Load way with points (with tags) and tags
*/
public void loadEntityWay(Way e) throws SQLException;
/**
* Load one level relation members :
* ways - loaded with tags and points, nodes with tags, relations with members and tags
*/
public void loadEntityRelation(Relation e) throws SQLException;
}

View file

@ -1,281 +0,0 @@
package net.osmand.data.preparation;
import gnu.trove.list.array.TLongArrayList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Map.Entry;
import net.osmand.osm.Entity;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.io.IOsmStorageFilter;
import net.osmand.osm.io.OsmBaseStorage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.anvisics.jleveldb.ArraySerializer;
import com.anvisics.jleveldb.ext.DBAccessor;
import com.anvisics.jleveldb.ext.DBWriteBatch;
import com.anvisics.jleveldb.ext.WriteOptions;
public class OsmDbCreator implements IOsmStorageFilter {
private static final Log log = LogFactory.getLog(OsmDbCreator.class);
public static final int BATCH_SIZE_OSM = 100000;
// do not store these tags in the database, just ignore them
final String[] tagsToIgnore= {"created_by","source","converted_by"};
DBDialect dialect;
int currentCountNode = 0;
private PreparedStatement prepNode;
int allNodes = 0;
int currentRelationsCount = 0;
private PreparedStatement prepRelations;
int allRelations = 0;
int currentWaysCount = 0;
private PreparedStatement prepWays;
int allWays = 0;
private Connection dbConn;
protected final IndexCreator indexCreator;
private DBAccessor database;
private DBWriteBatch batch;
private WriteOptions options;
public OsmDbCreator(IndexCreator indexCreator) {
this.indexCreator = indexCreator;
}
public void initDatabase(DBDialect dialect, Object databaseConn) throws SQLException {
this.dialect = dialect;
if(dialect == DBDialect.NOSQL){
database = (DBAccessor) databaseConn;
batch = new DBWriteBatch();
options = new WriteOptions();
} else {
this.dbConn = (Connection) databaseConn;
// prepare tables
Statement stat = dbConn.createStatement();
dialect.deleteTableIfExists("node", stat);
stat.executeUpdate("create table node (id bigint primary key, latitude double, longitude double, tags blob)"); //$NON-NLS-1$
stat.executeUpdate("create index IdIndex ON node (id)"); //$NON-NLS-1$
dialect.deleteTableIfExists("ways", stat);
stat.executeUpdate("create table ways (id bigint, node bigint, ord smallint, tags blob, boundary smallint, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create index IdWIndex ON ways (id)"); //$NON-NLS-1$
dialect.deleteTableIfExists("relations", stat);
stat.executeUpdate("create table relations (id bigint, member bigint, type smallint, role varchar(1024), ord smallint, tags blob, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create index IdRIndex ON relations (id)"); //$NON-NLS-1$
stat.close();
prepNode = dbConn.prepareStatement("insert into node values (?, ?, ?, ?)"); //$NON-NLS-1$
prepWays = dbConn.prepareStatement("insert into ways values (?, ?, ?, ?, ?)"); //$NON-NLS-1$
prepRelations = dbConn.prepareStatement("insert into relations values (?, ?, ?, ?, ?, ?)"); //$NON-NLS-1$
dbConn.setAutoCommit(false);
}
}
public void finishLoading() throws SQLException {
if (dialect != DBDialect.NOSQL) {
if (currentCountNode > 0) {
prepNode.executeBatch();
}
prepNode.close();
if (currentWaysCount > 0) {
prepWays.executeBatch();
}
prepWays.close();
if (currentRelationsCount > 0) {
prepRelations.executeBatch();
}
prepRelations.close();
} else {
database.write(options, batch);
}
}
public static String serializeEntityWOId(Entity e){
StringBuilder builder = new StringBuilder();
ArraySerializer.startArray(builder, true);
if(!e.getTags().isEmpty()){
ArraySerializer.startArray(builder, true);
boolean f = true;
for(Map.Entry<String, String> es : e.getTags().entrySet()){
ArraySerializer.value(builder, es.getKey(), f);
f = false;
ArraySerializer.value(builder, es.getValue(), f);
}
ArraySerializer.endArray(builder);
}
if (e instanceof Node) {
ArraySerializer.value(builder, ((float) ((Node) e).getLatitude()) + "", false);
ArraySerializer.value(builder, ((float) ((Node) e).getLongitude()) + "", false);
} else if (e instanceof Way) {
ArraySerializer.startArray(builder, false);
boolean f = true;
TLongArrayList nodeIds = ((Way) e).getNodeIds();
for (int j = 0; j < nodeIds.size(); j++) {
ArraySerializer.value(builder, nodeIds.get(j) + "", f);
f = false;
}
ArraySerializer.endArray(builder);
} else {
ArraySerializer.startArray(builder, false);
boolean f = true;
for(Entry<EntityId, String> l : ((Relation) e).getMembersMap().entrySet()) {
String k = l.getKey().getType() == EntityType.NODE ? "0" : (l.getKey().getType() == EntityType.WAY ? "1" : "2");
ArraySerializer.value(builder, k +""+l.getKey().getId(), f);
f = false;
ArraySerializer.value(builder, l.getValue(), f);
}
ArraySerializer.endArray(builder);
}
ArraySerializer.endArray(builder);
return builder.toString();
}
@Override
public boolean acceptEntityToLoad(OsmBaseStorage storage, EntityId entityId, Entity e) {
// put all nodes into temporary db to get only required nodes after loading all data
if (dialect == DBDialect.NOSQL) {
String key;
currentCountNode++;
if (e instanceof Node) {
if (!e.getTags().isEmpty()) {
allNodes++;
}
key = "0" + e.getId();
} else if (e instanceof Way) {
allWays++;
key = "1" + e.getId();
} else {
allRelations++;
key = "2" + e.getId();
}
batch.Put(key, serializeEntityWOId(e));
if (currentCountNode > BATCH_SIZE_OSM) {
database.write(options, batch);
batch = new DBWriteBatch();
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
log.info("" + Runtime.getRuntime().totalMemory() / (1024 * 1024) + " MB Total " + (usedMemory / (1024 * 1024))
+ " MB used memory");
currentCountNode = 0;
}
} else {
try {
e.removeTags(tagsToIgnore);
ByteArrayOutputStream tags = new ByteArrayOutputStream();
try {
for (Entry<String, String> i : e.getTags().entrySet()) {
// UTF-8 default
tags.write(i.getKey().getBytes("UTF-8"));
tags.write(0);
tags.write(i.getValue().getBytes("UTF-8"));
tags.write(0);
}
} catch (IOException es) {
throw new RuntimeException(es);
}
if (e instanceof Node) {
currentCountNode++;
if (!e.getTags().isEmpty()) {
allNodes++;
}
prepNode.setLong(1, e.getId());
prepNode.setDouble(2, ((Node) e).getLatitude());
prepNode.setDouble(3, ((Node) e).getLongitude());
prepNode.setBytes(4, tags.toByteArray());
prepNode.addBatch();
if (currentCountNode >= BATCH_SIZE_OSM) {
prepNode.executeBatch();
dbConn.commit(); // clear memory
currentCountNode = 0;
}
} else if (e instanceof Way) {
allWays++;
short ord = 0;
TLongArrayList nodeIds = ((Way) e).getNodeIds();
int boundary = ((Way)e).getTag(OSMTagKey.BOUNDARY) != null ? 1 : 0;
for (int j = 0; j < nodeIds.size(); j++) {
currentWaysCount++;
if (ord == 0) {
prepWays.setBytes(4, tags.toByteArray());
}
prepWays.setLong(1, e.getId());
prepWays.setLong(2, nodeIds.get(j));
prepWays.setLong(3, ord++);
prepWays.setInt(5, boundary);
prepWays.addBatch();
}
if (currentWaysCount >= BATCH_SIZE_OSM) {
prepWays.executeBatch();
dbConn.commit(); // clear memory
currentWaysCount = 0;
}
} else {
allRelations++;
short ord = 0;
for (Entry<EntityId, String> i : ((Relation) e).getMembersMap().entrySet()) {
currentRelationsCount++;
if (ord == 0) {
prepRelations.setBytes(6, tags.toByteArray());
}
prepRelations.setLong(1, e.getId());
prepRelations.setLong(2, i.getKey().getId());
prepRelations.setLong(3, i.getKey().getType().ordinal());
prepRelations.setString(4, i.getValue());
prepRelations.setLong(5, ord++);
prepRelations.addBatch();
}
if (currentRelationsCount >= BATCH_SIZE_OSM) {
prepRelations.executeBatch();
dbConn.commit(); // clear memory
currentRelationsCount = 0;
}
}
} catch (SQLException ex) {
log.error("Could not save in db", ex); //$NON-NLS-1$
}
}
// do not add to storage
return false;
}
public int getAllNodes() {
return allNodes;
}
public int getAllRelations() {
return allRelations;
}
public int getAllWays() {
return allWays;
}
}

View file

@ -1,89 +0,0 @@
package net.osmand.data.preparation.address;
import gnu.trove.set.hash.TLongHashSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.osm.Entity;
import net.osmand.osm.LatLon;
import net.osmand.osm.Way;
public class CachedDBStreetDAO extends DBStreetDAO
{
private Map<String, SimpleStreet> addressStreetLocalMap = new HashMap<String, SimpleStreet>();
private TLongHashSet addressBuildingLocalSet = new TLongHashSet();
private TLongHashSet addressStreetNodeLocalSet = new TLongHashSet();
@Override
public SimpleStreet findStreet(String name, City city, String cityPart) {
return addressStreetLocalMap.get(createStreetUniqueName(name, city, cityPart)); //$NON-NLS-1$
}
@Override
public SimpleStreet findStreet(String name, City city) {
return addressStreetLocalMap.get(createStreetUniqueName(name, city)); //$NON-NLS-1$
}
private String createStreetUniqueName(String name, City city, String cityPart) {
return new StringBuilder().append(name).append('_').append(city.getId()).append('_').append(cityPart).toString();
}
private String createStreetUniqueName(String name, City city) {
return new StringBuilder().append(name).append('_').append(city.getId()).toString();
}
@Override
protected void writeStreetWayNodes(Set<Long> streetId, Way way)
throws SQLException {
super.writeStreetWayNodes(streetId, way);
addressStreetNodeLocalSet.add(way.getId());
}
@Override
protected void writeBuilding(Set<Long> streetId, Building building)
throws SQLException {
super.writeBuilding(streetId, building);
addressBuildingLocalSet.add(building.getId());
}
@Override
public long insertStreet(String name, String nameEn, LatLon location, City city, String cityPart) throws SQLException {
//batch the insert
long streetId = fillInsertStreetStatement(name, nameEn, location, city, cityPart);
addBatch(addressStreetStat);
SimpleStreet ss = new SimpleStreet(streetId,name,cityPart,location);
addressStreetLocalMap.put(createStreetUniqueName(name, city, cityPart), ss);
addressStreetLocalMap.put(createStreetUniqueName(name, city), ss);
return streetId;
}
@Override
public SimpleStreet updateStreetCityPart(SimpleStreet street, City city, String cityPart) throws SQLException {
commit(); //we are doing batch updates, so we must commit before this update
super.updateStreetCityPart(street, city, cityPart);
SimpleStreet updatedSS = new SimpleStreet(street.getId(),street.getName(),cityPart,street.getLocation());
addressStreetLocalMap.put(createStreetUniqueName(street.getName(), city), updatedSS);
addressStreetLocalMap.put(createStreetUniqueName(street.getName(), city, cityPart), updatedSS);
return updatedSS;
}
@Override
public boolean findBuilding(Entity e) {
return addressBuildingLocalSet.contains(e.getId());
}
@Override
public boolean removeBuilding(Entity e) throws SQLException {
addressBuildingLocalSet.remove(e.getId());
return super.removeBuilding(e);
}
@Override
public boolean findStreetNode(Entity e) {
return addressStreetNodeLocalSet.contains(e.getId());
}
}

View file

@ -1,232 +0,0 @@
package net.osmand.data.preparation.address;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.preparation.AbstractIndexPartCreator;
import net.osmand.data.preparation.DBDialect;
import net.osmand.osm.Entity;
import net.osmand.osm.LatLon;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
public class DBStreetDAO extends AbstractIndexPartCreator
{
public static class SimpleStreet {
private final long id;
private final String name;
private final String cityPart;
private LatLon location;
public SimpleStreet(long id, String name, String cityPart, double latitude, double longitude) {
this(id,name,cityPart, new LatLon(latitude,longitude));
}
public SimpleStreet(long id, String name, String cityPart,
LatLon location) {
this.id = id;
this.name = name;
this.cityPart = cityPart;
this.location = location;
}
public String getCityPart() {
return cityPart;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public LatLon getLocation() {
return location;
}
}
protected PreparedStatement addressStreetStat;
private PreparedStatement addressStreetNodeStat;
private PreparedStatement addressBuildingStat;
private PreparedStatement addressSearchStreetStat;
private PreparedStatement addressSearchBuildingStat;
private PreparedStatement addressRemoveBuildingStat;
private PreparedStatement addressSearchStreetNodeStat;
private PreparedStatement addressSearchStreetStatWithoutCityPart;
private Connection mapConnection;
private PreparedStatement addressStreetUpdateCityPart;
public void createDatabaseStructure(Connection mapConnection, DBDialect dialect) throws SQLException {
this.mapConnection = mapConnection;
Statement stat = mapConnection.createStatement();
stat.executeUpdate("create table street (id bigint primary key, latitude double, longitude double, " +
"name varchar(1024), name_en varchar(1024), city bigint, citypart varchar(1024))");
stat.executeUpdate("create index street_cnp on street (city,citypart,name,id)");
stat.executeUpdate("create index street_city on street (city)");
stat.executeUpdate("create index street_id on street (id)");
// create index on name ?
stat.executeUpdate("create table building (id bigint, latitude double, longitude double, " +
"name2 varchar(1024), name_en2 varchar(1024), lat2 double, lon2 double, interval int, interpolateType varchar(50), " +
"name varchar(1024), name_en varchar(1024), street bigint, postcode varchar(1024), primary key(street, id))");
stat.executeUpdate("create index building_postcode on building (postcode)");
stat.executeUpdate("create index building_street on building (street)");
stat.executeUpdate("create index building_id on building (id)");
stat.executeUpdate("create table street_node (id bigint, latitude double, longitude double, " +
"street bigint, way bigint)");
stat.executeUpdate("create index street_node_street on street_node (street)");
stat.executeUpdate("create index street_node_way on street_node (way)");
stat.close();
addressStreetStat = createPrepareStatement(mapConnection,"insert into street (id, latitude, longitude, name, name_en, city, citypart) values (?, ?, ?, ?, ?, ?, ?)");
addressStreetNodeStat = createPrepareStatement(mapConnection,"insert into street_node (id, latitude, longitude, street, way) values (?, ?, ?, ?, ?)");
addressBuildingStat = createPrepareStatement(mapConnection,"insert into building (id, latitude, longitude, name, name_en, street, postcode, name2, name_en2, lat2, lon2, interval, interpolateType) values (?, ?, ?, ?, ?, ?, ?, ?, ? ,? ,? ,? ,?)");
addressSearchStreetStat = createPrepareStatement(mapConnection,"SELECT id,latitude,longitude FROM street WHERE ? = city AND ? = citypart AND ? = name");
addressSearchStreetStatWithoutCityPart = createPrepareStatement(mapConnection,"SELECT id,name,citypart,latitude,longitude FROM street WHERE ? = city AND ? = name");
addressStreetUpdateCityPart = createPrepareStatement(mapConnection,"UPDATE street SET citypart = ? WHERE id = ?");
addressSearchBuildingStat = createPrepareStatement(mapConnection,"SELECT id FROM building where ? = id");
addressRemoveBuildingStat = createPrepareStatement(mapConnection,"DELETE FROM building where ? = id");
addressSearchStreetNodeStat = createPrepareStatement(mapConnection,"SELECT way FROM street_node WHERE ? = way");
}
protected void writeStreetWayNodes(Set<Long> streetIds, Way way) throws SQLException {
for (Long streetId : streetIds) {
for (Node n : way.getNodes()) {
if (n == null) {
continue;
}
addressStreetNodeStat.setLong(1, n.getId());
addressStreetNodeStat.setDouble(2, n.getLatitude());
addressStreetNodeStat.setDouble(3, n.getLongitude());
addressStreetNodeStat.setLong(5, way.getId());
addressStreetNodeStat.setLong(4, streetId);
addBatch(addressStreetNodeStat);
}
}
}
protected void writeBuilding(Set<Long> streetIds, Building building) throws SQLException {
for (Long streetId : streetIds) {
addressBuildingStat.setLong(1, building.getId());
addressBuildingStat.setDouble(2, building.getLocation().getLatitude());
addressBuildingStat.setDouble(3, building.getLocation().getLongitude());
addressBuildingStat.setString(4, building.getName());
addressBuildingStat.setString(5, building.getEnName());
addressBuildingStat.setLong(6, streetId);
addressBuildingStat.setString(7, building.getPostcode() == null ? null : building.getPostcode().toUpperCase());
addressBuildingStat.setString(8, building.getName2());
addressBuildingStat.setString(9, building.getName2());
LatLon l = building.getLatLon2() ;
addressBuildingStat.setDouble(10, l == null? 0 : l.getLatitude());
addressBuildingStat.setDouble(11, l == null? 0 : l.getLongitude());
addressBuildingStat.setInt(12, building.getInterpolationInterval());
if(building.getInterpolationType() == null) {
addressBuildingStat.setString(13, null);
} else {
addressBuildingStat.setString(13, building.getInterpolationType().toString());
}
addBatch(addressBuildingStat);
}
}
public DBStreetDAO.SimpleStreet findStreet(String name, City city) throws SQLException {
addressSearchStreetStatWithoutCityPart.setLong(1, city.getId());
addressSearchStreetStatWithoutCityPart.setString(2, name);
ResultSet rs = addressSearchStreetStatWithoutCityPart.executeQuery();
DBStreetDAO.SimpleStreet foundId = null;
if (rs.next()) {
foundId = new SimpleStreet(rs.getLong(1),rs.getString(2),rs.getString(3),rs.getDouble(4),rs.getDouble(5));
}
rs.close();
return foundId;
}
public DBStreetDAO.SimpleStreet findStreet(String name, City city, String cityPart) throws SQLException {
addressSearchStreetStat.setLong(1, city.getId());
addressSearchStreetStat.setString(2, cityPart);
addressSearchStreetStat.setString(3, name);
ResultSet rs = addressSearchStreetStat.executeQuery();
DBStreetDAO.SimpleStreet foundId = null;
if (rs.next()) {
foundId = new SimpleStreet(rs.getLong(1),name,cityPart,rs.getDouble(2),rs.getDouble(3));
}
rs.close();
return foundId;
}
private long streetIdSequence = 0;
public long insertStreet(String name, String nameEn, LatLon location,
City city, String cityPart) throws SQLException {
long streetId = fillInsertStreetStatement(name, nameEn, location, city, cityPart);
// execute the insert statement
addressStreetStat.execute();
// commit immediately to search after
mapConnection.commit();
return streetId;
}
protected long fillInsertStreetStatement(String name, String nameEn,
LatLon location, City city, String cityPart)
throws SQLException {
long streetId = streetIdSequence++;
addressStreetStat.setLong(1, streetId);
addressStreetStat.setString(4, name);
addressStreetStat.setString(5, nameEn);
addressStreetStat.setDouble(2, location.getLatitude());
addressStreetStat.setDouble(3, location.getLongitude());
addressStreetStat.setLong(6, city.getId());
addressStreetStat.setString(7, cityPart);
return streetId;
}
public boolean findBuilding(Entity e) throws SQLException {
commit(); //we are doing batch adds, to search, we must commit
addressSearchBuildingStat.setLong(1, e.getId());
ResultSet rs = addressSearchBuildingStat.executeQuery();
boolean exist = rs.next();
rs.close();
return exist;
}
public boolean removeBuilding(Entity e) throws SQLException {
executePendingPreparedStatements(); //ala flush
addressRemoveBuildingStat.setLong(1, e.getId());
boolean res = addressRemoveBuildingStat.execute();
commit();
return res;
}
public boolean findStreetNode(Entity e) throws SQLException {
commit(); //we are doing batch adds, to search, we must commit
addressSearchStreetNodeStat.setLong(1, e.getId());
ResultSet rs = addressSearchStreetNodeStat.executeQuery();
boolean exist = rs.next();
rs.close();
return exist;
}
public void commit() throws SQLException {
if (executePendingPreparedStatements()) {
mapConnection.commit();
}
}
public void close() throws SQLException {
closePreparedStatements(addressStreetStat, addressStreetNodeStat, addressBuildingStat);
}
public DBStreetDAO.SimpleStreet updateStreetCityPart(DBStreetDAO.SimpleStreet street, City city, String cityPart) throws SQLException {
addressStreetUpdateCityPart.setString(1, cityPart);
addressStreetUpdateCityPart.setLong(2, street.getId());
addressStreetUpdateCityPart.executeUpdate();
mapConnection.commit();
return new SimpleStreet(street.getId(),street.getName(),cityPart,street.getLocation());
}
}

View file

@ -1,113 +0,0 @@
package net.osmand.impl;
import java.text.MessageFormat;
import net.osmand.Algoritms;
import net.osmand.IProgress;
import net.osmand.LogUtil;
import org.apache.commons.logging.Log;
public class ConsoleProgressImplementation implements IProgress {
public static double deltaPercentsToPrint = 3.5;
public static long deltaTimeToPrint = 1000;
private static Log log = LogUtil.getLog(ConsoleProgressImplementation.class);
String currentTask;
int work;
int currentDone;
double delta;
long deltaTime = deltaTimeToPrint;
private long previousTaskStarted = 0;
private long lastTimePrinted = 0;
double lastPercentPrint = 0;
public ConsoleProgressImplementation(){
delta = deltaPercentsToPrint;
}
public ConsoleProgressImplementation(double deltaToPrint){
delta = deltaToPrint;
}
public ConsoleProgressImplementation(double deltaToPrint, int deltaTime){
delta = deltaToPrint;
deltaToPrint = deltaTime;
}
@Override
public void finishTask() {
log.info("Task " + currentTask + " is finished "); //$NON-NLS-1$ //$NON-NLS-2$
this.currentTask = null;
}
@Override
public boolean isIndeterminate() {
return work == -1;
}
@Override
public void progress(int deltaWork) {
this.currentDone += deltaWork;
printIfNeeded();
}
private void printIfNeeded() {
if(getCurrentPercent() - lastPercentPrint >= delta){
this.lastPercentPrint = getCurrentPercent();
long now = System.currentTimeMillis();
if(now - lastTimePrinted >= deltaTimeToPrint || deltaTime < 0){
log.info(MessageFormat.format("Done {0} %.", getCurrentPercent())); //$NON-NLS-1$
lastTimePrinted = now;
}
}
}
public double getCurrentPercent(){
return (double) currentDone * 100d / work;
}
@Override
public void remaining(int remainingWork) {
this.currentDone = work - remainingWork;
printIfNeeded();
}
@Override
public void startTask(String taskName, int work) {
if(!Algoritms.objectEquals(currentTask, taskName)){
this.currentTask = taskName;
log.debug("Memory before task exec: " + Runtime.getRuntime().totalMemory() + " free : " + Runtime.getRuntime().freeMemory()); //$NON-NLS-1$ //$NON-NLS-2$
if (previousTaskStarted == 0) {
log.info(taskName + " started - " + work); //$NON-NLS-1$
} else {
log.info(taskName + " started after " + (System.currentTimeMillis() - previousTaskStarted) + " ms" + " - " + work); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
previousTaskStarted = System.currentTimeMillis();
}
startWork(work);
}
@Override
public void startWork(int work) {
if(this.work != work){
this.work = work;
log.info("Task " + currentTask + ": work total has changed to " + work); //$NON-NLS-1$
}
this.currentDone = 0;
this.lastPercentPrint = 0;
}
@Override
public boolean isInterrupted() {
return false;
}
@Override
public void setGeneralProgress(String genProgress) {
}
}

View file

@ -1,125 +0,0 @@
package net.osmand.map;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo;
import net.osmand.map.OsmandRegionInfo.OsmAndRegions;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class RegionsRegistryConverter {
public static List<RegionCountry> parseRegions() throws IllegalStateException {
InputStream is = RegionsRegistryConverter.class.getResourceAsStream("countries.xml");
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
RegionsHandler h = new RegionsHandler(parser);
parser.parse(new InputSource(is), h);
return h.getCountries();
} catch (SAXException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
} catch (ParserConfigurationException e) {
throw new IllegalStateException(e);
}
}
private static class RegionsHandler extends DefaultHandler {
private SAXParser parser;
private String continentName;
private RegionCountry current;
private RegionCountry currentRegion;
private List<RegionCountry> countries = new ArrayList<RegionCountry>();
private StringBuilder txt = new StringBuilder();
public RegionsHandler(SAXParser parser) {
this.parser = parser;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
String tagName = parser.isNamespaceAware() ? localName : qName;
if(tagName.equals("continent")) {
continentName = attributes.getValue("name");
} else if(tagName.equals("country")) {
RegionCountry c = new RegionCountry();
c.continentName = continentName;
c.name = attributes.getValue("name");
current = c;
countries.add(c);
} else if(tagName.equals("tiles")) {
txt.setLength(0);
} else if(tagName.equals("region")) {
RegionCountry c = new RegionCountry();
c.name = attributes.getValue("name");
currentRegion = c;
current.addSubregion(c);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
txt.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
String tagName = parser.isNamespaceAware() ? localName : qName;
if(tagName.equals("region")) {
currentRegion = null;
} else if(tagName.equals("tiles")) {
String[] s = txt.toString().split("( |;)");
RegionCountry a = currentRegion == null ? current : currentRegion;
for(int i =0; i < s.length; i+=2) {
a.add(Integer.parseInt(s[i]), Integer.parseInt(s[i+1]));
}
}
}
public List<RegionCountry> getCountries() {
return countries;
}
}
public static void main(String[] args) throws IOException {
List<RegionCountry> countries = parseRegions();
OsmAndRegions.Builder regions= OsmAndRegions.newBuilder();
for(RegionCountry c : countries){
regions.addRegions(c.convert());
}
String filePath = "../OsmAnd-java/src/net/osmand/map/"+RegionRegistry.fileName;
long t = -System.currentTimeMillis();
FileOutputStream out = new FileOutputStream(filePath);
OsmAndRegionInfo.newBuilder().setRegionInfo(regions)
.build().writeTo(out);
out.close();
InputStream in = RegionRegistry.class.getResourceAsStream(RegionRegistry.fileName);
OsmAndRegionInfo regInfo = OsmAndRegionInfo.newBuilder().mergeFrom(in).build();
t += System.currentTimeMillis();
for(int j = 0; j < regInfo.getRegionInfo().getRegionsCount(); j++) {
RegionCountry.construct(regInfo.getRegionInfo().getRegions(j));
}
System.out.println("Read countries " + regInfo.getRegionInfo().getRegionsCount() + " " + countries.size() );
System.out.println("Timing " + t);
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,66 +0,0 @@
package net.osmand.osm;
import java.util.ArrayList;
import java.util.List;
public class WayChain {
private List<Way> ways = new ArrayList<Way>(1);
private List<Node> chainNodes;
public WayChain(Way w) {
ways.add(w);
}
public List<Way> getWays() {
return ways;
}
public void append(Way w) {
ways.add(w);
}
public void append(WayChain w) {
ways.addAll(w.ways);
}
public void prepend(Way w) {
ways.add(0, w);
}
public long getFistNode(){
return ways.get(0).getFirstNodeId();
}
public long getLastNode() {
return ways.get(ways.size() - 1).getLastNodeId();
}
public boolean isIncomplete() {
for (int j = 0; j < ways.size(); j++) {
if(ways.get(j).getNodes().size() != ways.get(j).getNodeIds().size()) {
return true;
}
}
return false;
}
public List<Node> getChainNodes(){
if(chainNodes == null) {
chainNodes = new ArrayList<Node>();
for(int j = 0; j< ways.size(); j++) {
List<Node> ns = ways.get(j).getNodes();
if(j == 0 && ns.get(0) != null) {
chainNodes.add(ns.get(0));
}
for(int i=1; i<ns.size(); i++){
if(ns.get(i) != null) {
chainNodes.add(ns.get(i));
}
}
}
}
return chainNodes;
}
}

View file

@ -1,221 +0,0 @@
package net.osmand.osm.io;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import net.osmand.IProgress;
import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.Node;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import crosby.binary.BinaryParser;
import crosby.binary.Osmformat.DenseNodes;
import crosby.binary.Osmformat.HeaderBlock;
import crosby.binary.Osmformat.Info;
import crosby.binary.Osmformat.Relation.MemberType;
import crosby.binary.file.BlockInputStream;
public class OsmBaseStoragePbf extends OsmBaseStorage {
public synchronized void parseOSMPbf(final InputStream stream, final IProgress progress, final boolean entityInfo) throws IOException {
BinaryParser parser = new BinaryParser() {
public void updateProgress(int count) {
progressEntity += count;
if (progress != null && progressEntity > moduleProgress && !progress.isIndeterminate()) {
try {
progressEntity = 0;
progress.remaining(stream.available());
} catch (IOException e) {
progress.startWork(-1);
}
}
}
public void registerEntity(EntityType type, Entity e, EntityInfo info) {
EntityId entityId = new EntityId(type, e.getId());
if (acceptEntityToLoad(entityId, e)) {
Entity oldEntity = entities.put(entityId, e);
if (info != null) {
OsmBaseStoragePbf.this.entityInfo.put(entityId, info);
}
if (!supressWarnings && oldEntity != null) {
throw new UnsupportedOperationException("Entity with id=" + oldEntity.getId() + " is duplicated in osm map"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
@Override
protected void parse(HeaderBlock header) {
}
private DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); //$NON-NLS-1$
@Override
protected void parseDense(DenseNodes n) {
EntityInfo info = null;
long changeset = 0;
long timestamp = 0;
int uid = 0;
int user = 0;
long id = 0;
long lat = 0;
long lon = 0;
int keyInd = 0;
boolean tagsEmpty = n.getKeysValsCount() == 0;
for (int i = 0; i < n.getIdCount(); i++) {
id += n.getId(i);
lat += n.getLat(i);
lon += n.getLon(i);
Node node = new Node(parseLat(lat), parseLon(lon), id);
if (entityInfo && n.getDenseinfo() != null) {
info = new EntityInfo();
changeset += n.getDenseinfo().getChangeset(i);
timestamp += n.getDenseinfo().getTimestamp(i);
uid += n.getDenseinfo().getUid(i);
user += n.getDenseinfo().getUserSid(i);
info.setChangeset((changeset) + ""); //$NON-NLS-1$
info.setTimestamp(format.format(new Date(date_granularity * (timestamp))));
info.setUser(getStringById(user));
info.setUid(uid + ""); //$NON-NLS-1$
info.setVersion(n.getDenseinfo().getVersion(i) + ""); //$NON-NLS-1$
info.setVisible("true"); //$NON-NLS-1$
}
if (!tagsEmpty) {
while (n.getKeysVals(keyInd) != 0) {
String key = getStringById(n.getKeysVals(keyInd));
String val = getStringById(n.getKeysVals(keyInd + 1));
node.putTag(key, val);
keyInd += 2;
}
keyInd++;
}
registerEntity(EntityType.NODE, node, info);
}
updateProgress(n.getIdCount());
}
protected EntityInfo parseEntityInfo(Info i) {
EntityInfo info = new EntityInfo();
info.setChangeset(i.getChangeset() + ""); //$NON-NLS-1$
info.setTimestamp(format.format(getDate(i)));
info.setUser(getStringById(i.getUserSid()));
info.setUid(i.getUid() + ""); //$NON-NLS-1$
info.setVersion(i.getVersion() + ""); //$NON-NLS-1$
info.setVisible("true"); //$NON-NLS-1$
return info;
}
@Override
protected void parseNodes(List<crosby.binary.Osmformat.Node> n) {
EntityInfo info = null;
int nsize = n.size();
for (int i = 0; i < nsize; i++) {
crosby.binary.Osmformat.Node nod = n.get(i);
Node e = new Node(parseLat(nod.getLat()), parseLon(nod.getLon()), nod.getId());
for (int j = 0; j < nod.getKeysCount(); j++) {
String key = getStringById(nod.getKeys(j));
String val = getStringById(nod.getVals(j));
e.putTag(key, val);
}
if (entityInfo) {
info = parseEntityInfo(nod.getInfo());
}
registerEntity(EntityType.NODE, e, info);
}
updateProgress(nsize);
}
@Override
protected void parseRelations(List<crosby.binary.Osmformat.Relation> r) {
EntityInfo info = null;
int rsize = r.size();
for (int i = 0; i < rsize; i++) {
crosby.binary.Osmformat.Relation rel = r.get(i);
Relation e = new Relation(rel.getId());
long id = 0;
for (int j = 0; j < rel.getMemidsCount(); j++) {
id += rel.getMemids(j);
String role = getStringById(rel.getRolesSid(j));
MemberType t = rel.getTypes(j);
EntityType ts = EntityType.NODE;
switch (t) {
case NODE:
ts = EntityType.NODE;
break;
case WAY:
ts = EntityType.WAY;
break;
case RELATION:
ts = EntityType.RELATION;
break;
}
e.addMember(id, ts, role);
}
for (int j = 0; j < rel.getKeysCount(); j++) {
String key = getStringById(rel.getKeys(j));
String val = getStringById(rel.getVals(j));
e.putTag(key, val);
}
if (entityInfo) {
info = parseEntityInfo(rel.getInfo());
}
registerEntity(EntityType.RELATION, e, info);
}
updateProgress(rsize);
}
@Override
protected void parseWays(List<crosby.binary.Osmformat.Way> w) {
EntityInfo info = null;
int wsize = w.size();
for (int i = 0; i < wsize; i++) {
crosby.binary.Osmformat.Way way = w.get(i);
Way e = new Way(way.getId());
long id = 0;
for (int j = 0; j < way.getRefsCount(); j++) {
id += way.getRefs(j);
e.addNode(id);
}
for (int j = 0; j < way.getKeysCount(); j++) {
String key = getStringById(way.getKeys(j));
String val = getStringById(way.getVals(j));
e.putTag(key, val);
}
if (entityInfo) {
info = parseEntityInfo(way.getInfo());
}
registerEntity(EntityType.WAY, e, info);
}
updateProgress(wsize);
}
@Override
public void complete() {
}
};
this.progressEntity = 0;
this.entities.clear();
this.entityInfo.clear();
if(progress != null){
progress.startWork(stream.available());
}
BlockInputStream bis = new BlockInputStream(stream, parser);
bis.process();
if(progress != null){
progress.finishTask();
}
completeReading();
}
}

View file

@ -1,36 +0,0 @@
package net.osmand.osm.io;
import net.osmand.osm.Entity;
import net.osmand.osm.Node;
import net.osmand.osm.Entity.EntityId;
public class OsmBoundsFilter implements IOsmStorageFilter {
private final double lonEnd;
private final double latDown;
private final double latUp;
private final double lonStart;
public OsmBoundsFilter(double latStart, double lonStart, double latEnd, double lonEnd){
this.latUp = latStart;
this.lonStart = lonStart;
this.latDown = latEnd;
this.lonEnd = lonEnd;
}
@Override
public boolean acceptEntityToLoad(OsmBaseStorage storage, EntityId entityId, Entity entity) {
if(entity instanceof Node){
double lon = ((Node) entity).getLongitude();
double lat = ((Node) entity).getLatitude();
if (latDown <= lat && lat <= latUp && lonStart <= lon && lon <= lonEnd) {
return true;
}
return false;
}
// unknown for other locations
return true;
}
}

View file

@ -1,204 +0,0 @@
package net.osmand.osm.io;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_CHANGESET;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_ID;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_K;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_LAT;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_LON;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_REF;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_ROLE;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_TIMESTAMP;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_TYPE;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_UID;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_USER;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_V;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_VERSION;
import static net.osmand.osm.io.OsmBaseStorage.ATTR_VISIBLE;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_MEMBER;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_ND;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_NODE;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_OSM;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_RELATION;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_TAG;
import static net.osmand.osm.io.OsmBaseStorage.ELEM_WAY;
import gnu.trove.list.array.TLongArrayList;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.Map.Entry;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.XMLOutputFactory;
import net.osmand.Algoritms;
import net.osmand.data.MapObject;
import net.osmand.osm.Entity;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.Node;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import net.osmand.osm.Entity.EntityId;
public class OsmStorageWriter {
private final String INDENT = " ";
private final String INDENT2 = INDENT + INDENT;
public OsmStorageWriter(){
}
public void saveStorage(OutputStream output, OsmBaseStorage storage, Collection<EntityId> interestedObjects, boolean includeLinks) throws XMLStreamException, IOException {
Map<EntityId, Entity> entities = storage.getRegisteredEntities();
Map<EntityId, EntityInfo> entityInfo = storage.getRegisteredEntityInfo();
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// String indent = "{http://xml.apache.org/xslt}indent-amount";
// transformer.setOutputProperty(indent, "4");
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter streamWriter = xof.createXMLStreamWriter(new OutputStreamWriter(output));
List<Node> nodes = new ArrayList<Node>();
List<Way> ways = new ArrayList<Way>();
List<Relation> relations = new ArrayList<Relation>();
if(interestedObjects == null){
interestedObjects = entities.keySet();
}
Stack<EntityId> toResolve = new Stack<EntityId>();
toResolve.addAll(interestedObjects);
while(!toResolve.isEmpty()){
EntityId l = toResolve.pop();
if(entities.get(l) instanceof Node){
nodes.add((Node) entities.get(l));
} else if(entities.get(l) instanceof Way){
ways.add((Way) entities.get(l));
if(includeLinks){
toResolve.addAll(((Way)entities.get(l)).getEntityIds());
}
} else if(entities.get(l) instanceof Relation){
relations.add((Relation) entities.get(l));
if(includeLinks){
toResolve.addAll(((Relation)entities.get(l)).getMemberIds());
}
}
}
streamWriter.writeStartDocument();
writeStartElement(streamWriter, ELEM_OSM, "");
streamWriter.writeAttribute(ATTR_VERSION, "0.6");
for(Node n : nodes){
writeStartElement(streamWriter, ELEM_NODE, INDENT);
streamWriter.writeAttribute(ATTR_LAT, n.getLatitude()+"");
streamWriter.writeAttribute(ATTR_LON, n.getLongitude()+"");
streamWriter.writeAttribute(ATTR_ID, n.getId()+"");
writeEntityAttributes(streamWriter, n, entityInfo.get(EntityId.valueOf(n)));
writeTags(streamWriter, n);
writeEndElement(streamWriter, INDENT);
}
for(Way w : ways){
writeStartElement(streamWriter, ELEM_WAY, INDENT);
streamWriter.writeAttribute(ATTR_ID, w.getId()+"");
writeEntityAttributes(streamWriter, w, entityInfo.get(EntityId.valueOf(w)));
TLongArrayList ids = w.getNodeIds();
for(int i=0; i< ids.size(); i++){
writeStartElement(streamWriter, ELEM_ND, INDENT2);
streamWriter.writeAttribute(ATTR_REF, ids.get(i)+"");
writeEndElement(streamWriter, INDENT2);
}
writeTags(streamWriter, w);
writeEndElement(streamWriter, INDENT);
}
for(Relation r : relations){
writeStartElement(streamWriter, ELEM_RELATION, INDENT);
streamWriter.writeAttribute(ATTR_ID, r.getId()+"");
writeEntityAttributes(streamWriter, r, entityInfo.get(EntityId.valueOf(r)));
for(Entry<EntityId, String> e : r.getMembersMap().entrySet()){
writeStartElement(streamWriter, ELEM_MEMBER, INDENT2);
streamWriter.writeAttribute(ATTR_REF, e.getKey().getId()+"");
String s = e.getValue();
if(s == null){
s = "";
}
streamWriter.writeAttribute(ATTR_ROLE, s);
streamWriter.writeAttribute(ATTR_TYPE, e.getKey().getType().toString().toLowerCase());
writeEndElement(streamWriter, INDENT2);
}
writeTags(streamWriter, r);
writeEndElement(streamWriter, INDENT);
}
writeEndElement(streamWriter, ""); // osm
streamWriter.writeEndDocument();
streamWriter.flush();
}
private void writeEntityAttributes(XMLStreamWriter writer, Entity i, EntityInfo info) throws XMLStreamException{
if(i.getId() < 0 && (info == null || info.getAction() == null)){
writer.writeAttribute("action", "modify");
}
if(info != null){
// for josm editor
if(info.getAction() != null){
writer.writeAttribute("action", info.getAction());
}
if(info.getChangeset() != null){
writer.writeAttribute(ATTR_CHANGESET, info.getChangeset());
}
if(info.getTimestamp() != null){
writer.writeAttribute(ATTR_TIMESTAMP, info.getTimestamp());
}
if(info.getUid() != null){
writer.writeAttribute(ATTR_UID, info.getUid());
}
if(info.getUser() != null){
writer.writeAttribute(ATTR_USER, info.getUser());
}
if(info.getVisible() != null){
writer.writeAttribute(ATTR_VISIBLE, info.getVisible());
}
if(info.getVersion() != null){
writer.writeAttribute(ATTR_VERSION, info.getVersion());
}
}
}
public boolean couldBeWrited(MapObject e){
if(!Algoritms.isEmpty(e.getName()) && e.getLocation() != null){
return true;
}
return false;
}
private void writeStartElement(XMLStreamWriter writer, String name, String indent) throws XMLStreamException{
writer.writeCharacters("\n"+indent);
writer.writeStartElement(name);
}
private void writeEndElement(XMLStreamWriter writer, String indent) throws XMLStreamException{
writer.writeCharacters("\n"+indent);
writer.writeEndElement();
}
private void writeTags(XMLStreamWriter writer, Entity e) throws XMLStreamException{
for(Entry<String, String> en : e.getTags().entrySet()){
writeStartElement(writer, ELEM_TAG, INDENT2);
writer.writeAttribute(ATTR_K, en.getKey());
writer.writeAttribute(ATTR_V, en.getValue());
writer.writeEndElement();
}
}
}

View file

@ -1,728 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<osmand_types>
<!-- currently name tags are indexed with name and additional in nameTags separated by comma-->
<!-- additional -->
<type tag="oneway" value="yes" minzoom="15" additional="true"/>
<type tag="oneway" value="true" target_value="yes" minzoom="15" additional="true"/>
<type tag="oneway" value="no" minzoom="15" additional="true"/>
<type tag="oneway" value="false" target_value="no" minzoom="15" additional="true"/>
<type tag="oneway" value="-1" minzoom="15" additional="true"/>
<type tag="oneway" value="reverse" target_value="-1" minzoom="15" additional="true"/>
<type tag="access" value="no" minzoom="15" additional="true"/>
<type tag="access" value="false" target_value="no" minzoom="15" additional="true"/>
<type tag="access" value="private" minzoom="15" additional="true"/>
<type tag="access" value="yes" minzoom="15" additional="true"/>
<type tag="access" value="true" target_value="yes" minzoom="15" additional="true"/>
<type tag="layer" value="0" minzoom="10" additional="true"/>
<type tag="layer" value="1" minzoom="10" additional="true"/>
<type tag="layer" value="-1" minzoom="10" additional="true"/>
<type tag="layer" value="+1" target_value="1" minzoom="10" additional="true"/>
<type tag="layer" value="2" target_value="1" minzoom="10" additional="true"/>
<type tag="layer" value="+2" target_value="1" minzoom="10" additional="true"/>
<type tag="layer" value="-2" target_value="-1" minzoom="10" additional="true"/>
<type tag="layer" value="3" target_value="1" minzoom="10" additional="true"/>
<type tag="layer" value="+3" target_value="1" minzoom="10" additional="true"/>
<type tag="layer" value="-3" target_value="-1" minzoom="10" additional="true"/>
<type tag="bridge" value="yes" minzoom="10" additional="true"/>
<type tag="tunnel" value="yes" minzoom="10" additional="true"/>
<category name="highway">
<type tag="highway" value="motorway" minzoom="5" nameTags="ref"/>
<type tag="highway" value="motorway_link" minzoom="10" nameTags="ref"/>
<type tag="highway" value="trunk" minzoom="5" nameTags="ref"/>
<type tag="highway" value="trunk_link" minzoom="10" nameTags="ref"/>
<type tag="highway" value="primary" minzoom="7" nameTags="ref"/>
<type tag="highway" value="primary_link" minzoom="10" nameTags="ref"/>
<type tag="highway" value="secondary" minzoom="9" nameTags="ref"/>
<type tag="highway" value="secondary_link" minzoom="10" nameTags="ref"/>
<type tag="highway" value="tertiary" minzoom="10" nameTags="ref"/>
<type tag="highway" value="tertiary_link" minzoom="11" nameTags="ref"/>
<type tag="highway" value="residential" minzoom="12" nameTags="ref"/>
<type tag="highway" value="service" minzoom="12" nameTags="ref"/>
<type tag="highway" value="unclassified" minzoom="12" nameTags="ref"/>
<type tag="highway" value="road" minzoom="12" nameTags="ref"/>
<type tag="highway" value="track" minzoom="12" nameTags="ref"/>
<type tag="highway" value="path" minzoom="12" nameTags="ref"/>
<type tag="highway" value="living_street" minzoom="12" nameTags="ref"/>
<type tag="highway" value="pedestrian" minzoom="12" nameTags="ref"/>
<type tag="highway" value="cycleway" minzoom="12" nameTags="ref"/>
<type tag="highway" value="byway" minzoom="12" nameTags="ref"/>
<type tag="highway" value="footway" minzoom="12" nameTags="ref"/>
<type tag="highway" value="steps" minzoom="14" nameTags="ref"/>
<type tag="highway" value="bridleway" minzoom="12" nameTags="ref"/>
<type tag="highway" value="services" minzoom="12" nameTags="ref"/>
<!-- <type id="" tag="highway" value="bus_guideway" minzoom="15" /> -->
<type tag="highway" value="ford" minzoom="14" />
<type tag="highway" value="construction" minzoom="14" nameTags="ref"/>
<type tag="highway" value="proposed" minzoom="14" nameTags="ref"/>
<!-- POINT typeS -->
<type tag="highway" value="mini_roundabout" minzoom="16" />
<type tag="highway" value="stop" minzoom="16" />
<type tag="highway" value="give_way" minzoom="16" />
<type tag="highway" value="traffic_signals" minzoom="16" />
<type tag="highway" value="motorway_junction" minzoom="13" />
<type tag="highway" value="bus_stop" minzoom="15" poi_category="transportation"/>
<type tag="highway" value="platform" minzoom="15" poi_category="transportation"/>
<type tag="highway" value="turning_circle" minzoom="16" poi_category="transportation"/>
<type tag="highway" value="emergency_access_point" minzoom="16" poi_category="emergency"/>
<type tag="highway" value="speed_camera" minzoom="16" poi_category="transportation"/>
<type tag="highway" value="street_lamp" minzoom="16" />
</category>
<category name="routes">
<type tag="route" value="ferry" minzoom="8" relation="true"/>
<type tag="route" value="hiking" minzoom="8" relation="true"/>
</category>
<category name="tracktype">
<type tag="tracktype" value="grade1" minzoom="12" additional="true"/>
<type tag="tracktype" value="grade2" minzoom="12" additional="true"/>
<type tag="tracktype" value="grade3" minzoom="12" additional="true"/>
<type tag="tracktype" value="grade4" minzoom="12" additional="true"/>
<type tag="tracktype" value="grade5" minzoom="12" additional="true"/>
</category>
<category name="smoothness">
<type tag="smoothness" value="excelent" minzoom="12" additional="true"/>
<type tag="smoothness" value="good" minzoom="12" additional="true"/>
<type tag="smoothness" value="intermediate" minzoom="12" additional="true"/>
<type tag="smoothness" value="bad" minzoom="12" additional="true"/>
<type tag="smoothness" value="very_bad" minzoom="12" additional="true"/>
<type tag="smoothness" value="horrible" minzoom="12" additional="true"/>
<type tag="smoothness" value="very_horrible" minzoom="12" additional="true"/>
<type tag="smoothness" value="impassable" minzoom="12" additional="true"/>
</category>
<category name="sac_scale">
<type tag="sac_scale" value="hiking" minzoom="12" additional="true"/>
<type tag="sac_scale" value="mountain_hiking" minzoom="12" additional="true"/>
<type tag="sac_scale" value="demanding_mountain_hiking" minzoom="12" additional="true"/>
<type tag="sac_scale" value="alpine_hiking" minzoom="12" additional="true"/>
<type tag="sac_scale" value="demanding_alpine_hiking" minzoom="12" additional="true"/>
<type tag="sac_scale" value="difficult_alpine_hiking" minzoom="12" additional="true"/>
</category>
<category name="cycleway">
<type tag="cycleway" value="lane" minzoom="12"/>
<type tag="cycleway" value="opposite_lane" minzoom="12"/>
<type tag="cycleway" value="track" minzoom="12"/>
<type tag="cycleway:left" target_tag="cycleway" value="lane" minzoom="12"/>
<type tag="cycleway:right" target_tag="cycleway" value="lane" minzoom="12"/>
</category>
<category name="traffic_calming" poi_tag="traffic_calming" poi_category="barrier" poi_prefix="traffic_calming_">
<type tag="traffic_calming" value="yes" minzoom="16" />
<type tag="traffic_calming" value="bump" minzoom="16" />
<type tag="traffic_calming" value="chicane" minzoom="16" />
<type tag="traffic_calming" value="cushion" minzoom="16" />
<type tag="traffic_calming" value="hump" minzoom="16" />
<type tag="traffic_calming" value="rumble_strip" minzoom="16" />
<type tag="traffic_calming" value="table" minzoom="16" />
<type tag="traffic_calming" value="choker" minzoom="16" />
</category>
<category name="barrier" poi_tag="barrier" poi_category="barrier">
<type tag="barrier" value="hedge" minzoom="15" />
<type tag="natural" value="hedge" minzoom="15" />
<type tag="barrier" value="fence" minzoom="15" />
<type tag="fenced" value="yes" minzoom="15" target_tag="barrier" target_value="fence" poi_category="barrier"/>
<type tag="barrier" value="wall" minzoom="15" />
<type tag="barrier" value="ditch" minzoom="15" />
<type tag="barrier" value="retaining_wall" minzoom="15" />
<type tag="barrier" value="city_wall" minzoom="13" />
<type tag="historic" value="city_walls" minzoom="13" target_tag="barrier" target_value="city_wall" poi_category="barrier"/>
<type tag="barrier" value="bollard" minzoom="15" />
<type tag="barrier" value="cycle_barrier" minzoom="15" />
<type tag="barrier" value="block" minzoom="15" />
<type tag="barrier" value="cattle_grid" minzoom="15" />
<type tag="barrier" value="toll_booth" minzoom="14" />
<type tag="barrier" value="entrance" minzoom="15" />
<type tag="barrier" value="gate" minzoom="15" />
<type tag="highway" value="gate" minzoom="15" poi_category="barrier"/>
<type tag="barrier" value="lift_gate" minzoom="15" />
<type tag="barrier" value="stile" minzoom="15" />
<type tag="barrier" value="horse_stile" minzoom="15" />
<type tag="barrier" value="kissing_gate" minzoom="15" />
<type tag="barrier" value="sally_port" minzoom="15" />
<type tag="barrier" value="turnstile" minzoom="15" />
<type tag="barrier" value="kent_carriage_gap" minzoom="15" />
</category>
<category name="waterway" poi_tag="waterway" poi_category="man_made">
<type tag="waterway" value="stream" minzoom="13" poi_category="natural"/>
<type tag="waterway" value="riverbank" minzoom="8" poi_category="natural"/>
<type tag="waterway" value="river" minzoom="5" poi_category="natural"/> <!-- Example of user defined category poi_category="user_defined" -->
<type tag="waterway" value="canal" minzoom="10" poi_category="natural"/>
<type tag="waterway" value="ditch" minzoom="13" poi_category="natural"/>
<type tag="waterway" value="drain" minzoom="13" poi_category="natural"/>
<type tag="waterway" value="dock" minzoom="10" poi_prefix="water_"/>
<type tag="waterway" value="lock_gate" minzoom="15" poi_prefix="water_"/>
<type tag="waterway" value="lock" minzoom="15" poi_prefix="water_"/>
<type tag="waterway" value="turning_point" minzoom="15" poi_prefix="water_"/>
<type tag="waterway" value="boatyard" minzoom="15" />
<type tag="waterway" value="weir" minzoom="15" poi_prefix="water_"/>
<type tag="waterway" value="dam" minzoom="13" />
<type tag="waterway" value="mill_pond" minzoom="13" poi_prefix="water_"/>
</category>
<category name="railway" poi_tag="railway" poi_category="transportation" poi_prefix="railway_">
<type tag="railway" value="rail" minzoom="7" poi_prefix=""/>
<type tag="railway" value="tram" minzoom="13" poi_prefix=""/>
<type tag="railway" value="light_rail" minzoom="13" poi_prefix=""/>
<type tag="railway" value="abandoned" minzoom="15" />
<type tag="railway" value="disused" minzoom="15" />
<type tag="railway" value="subway" minzoom="13" poi_prefix=""/>
<type tag="railway" value="preserved" minzoom="13" />
<type tag="railway" value="narrow_gauge" minzoom="15" />
<type tag="railway" value="construction" minzoom="15" />
<type tag="railway" value="monorail" minzoom="15" />
<type tag="railway" value="funicular" minzoom="15" />
<type tag="railway" value="platform" minzoom="15" />
<type tag="railway" value="station" minzoom="12" />
<type tag="railway" value="turntable" minzoom="15" />
<type tag="railway" value="halt" minzoom="15" poi_prefix=""/>
<type tag="railway" value="tram_stop" minzoom="15" poi_prefix=""/>
<type tag="railway" value="crossing" minzoom="15" />
<type tag="railway" value="level_crossing" minzoom="15" />
<type tag="railway" value="subway_entrance" minzoom="15" poi_prefix=""/>
<type tag="railway" value="buffer_stop" minzoom="15" />
</category>
<category name="public_transport" poi_tag="public_transport" poi_category="transportation" poi_prefix="public_transport_">
<type tag="public_transport" value="platform" minzoom="15" />
<type tag="public_transport" value="station" minzoom="15" />
<type tag="public_transport" value="stop_position" minzoom="15" poi_prefix=""/>
</category>
<category name="aeroway" poi_tag="aeroway" poi_category="transportation">
<type tag="aeroway" value="aerodrome" minzoom="12" />
<type tag="aeroway" value="terminal" minzoom="15" />
<type tag="aeroway" value="helipad" minzoom="12" />
<type tag="aeroway" value="runway" minzoom="11" poi_prefix="aeroway_"/>
<type tag="aeroway" value="taxiway" minzoom="12" poi_prefix="aeroway_"/>
<type tag="aeroway" value="apron" minzoom="12" poi_prefix="aeroway_"/>
<type tag="aeroway" value="airport" minzoom="11" />
<type tag="aeroway" value="gate" minzoom="15" nameTags="ref" />
<type tag="aeroway" value="windsock" minzoom="15" />
</category>
<category name="aerialway" poi_tag="aerialway" poi_category="transportation" poi_prefix="aerialway_">
<type tag="aerialway" value="cable_car" minzoom="13" />
<type tag="aerialway" value="gondola" minzoom="13" />
<type tag="aerialway" value="chair_lift" minzoom="13" />
<type tag="aerialway" value="mixed_lift" minzoom="13" />
<type tag="aerialway" value="drag_lift" minzoom="13" />
<type tag="aerialway" value="goods" minzoom="15" />
<type tag="aerialway" value="station" minzoom="15" />
<type tag="aerialway" value="pylon" minzoom="15" poi_category=""/>
</category>
<category name="power">
<type tag="power" value="tower" minzoom="13" />
<type tag="power" value="pole" minzoom="15" />
<type tag="power" value="line" minzoom="13" />
<type tag="power" value="minor_line" minzoom="15" />
<type tag="power" value="station" minzoom="13" poi_category="man_made" poi_prefix="power_"/>
<type tag="power" value="sub_station" minzoom="13" poi_category="man_made" poi_prefix="power_"/>
<type tag="power" value="generator" minzoom="15" poi_category="man_made" poi_prefix="power_"/>
<type tag="power" value="cable_distribution_cabinet" minzoom="15" poi_category="man_made" poi_prefix="power_"/>
</category>
<category name="man_made" poi_tag="man_made" poi_category="man_made">
<type tag="building" minzoom="16" poi_category="" nameTags="addr:housenumber"/>
<type tag="addr:housenumber" minzoom="16" poi_category="" nameTags="addr:housenumber"/>
<type tag="man_made" value="wastewater_plant" minzoom="15" />
<type tag="man_made" value="water_works" minzoom="15" />
<type tag="man_made" value="works" minzoom="15" />
<type tag="man_made" value="cutline" minzoom="15" />
<type tag="man_made" value="groyne" minzoom="13" />
<type tag="man_made" value="breakwater" minzoom="13" />
<type tag="man_made" value="pier" minzoom="13" />
<type tag="man_made" value="pipeline" minzoom="15" />
<type tag="man_made" value="reservoir_covered" minzoom="15" />
<type tag="man_made" value="embankment" minzoom="15" />
<type tag="man_made" value="beacon" minzoom="15" />
<type tag="man_made" value="crane" minzoom="15" />
<type tag="man_made" value="lighthouse" minzoom="15" />
<type tag="man_made" value="mineshaft" minzoom="15" />
<type tag="man_made" value="adit" minzoom="15" />
<type tag="man_made" value="petroleum_well" minzoom="15" />
<type tag="man_made" value="surveillance" minzoom="15" />
<type tag="man_made" value="survey_point" minzoom="15" />
<type tag="man_made" value="tower" minzoom="15" />
<type tag="man_made" value="watermill" minzoom="15" />
<type tag="man_made" value="water_tower" minzoom="15" />
<type tag="man_made" value="water_well" minzoom="15" />
<type tag="man_made" value="windmill" minzoom="15" />
</category>
<category name="leisure" poi_tag="leisure" poi_category="leisure">
<type tag="leisure" value="dog_park" minzoom="15" />
<type tag="leisure" value="sports_centre" minzoom="13" />
<type tag="leisure" value="golf_course" minzoom="12" />
<type tag="leisure" value="stadium" minzoom="13" />
<type tag="leisure" value="track" minzoom="12" />
<type tag="leisure" value="pitch" minzoom="12" />
<type tag="leisure" value="water_park" minzoom="13" />
<type tag="leisure" value="marina" minzoom="13" />
<type tag="leisure" value="slipway" minzoom="15" />
<type tag="leisure" value="fishing" minzoom="15" />
<type tag="leisure" value="nature_reserve" minzoom="10" />
<type tag="natural" value="park" minzoom="12" poi_category="leisure"/>
<type tag="leisure" value="park" minzoom="12" />
<type tag="leisure" value="recreation_ground" minzoom="12" />
<type tag="leisure" value="playground" minzoom="15" />
<type tag="leisure" value="garden" minzoom="12" />
<type tag="leisure" value="common" minzoom="12" />
<type tag="leisure" value="ice_rink" minzoom="15" />
<type tag="leisure" value="miniature_golf" minzoom="15" />
<type tag="leisure" value="dance" minzoom="15" />
<type tag="leisure" value="bird_hide" minzoom="15" />
</category>
<category name="office" poi_tag="office" poi_category="office" >
<type tag="office" value="accountant" minzoom="15" />
<type tag="office" value="architect" minzoom="15" />
<type tag="office" value="company" minzoom="15" />
<type tag="office" value="employment_agency" minzoom="15" />
<type tag="office" value="estate_agent" minzoom="15" />
<type tag="office" value="government" minzoom="15" />
<type tag="office" value="insurance" minzoom="15" />
<type tag="office" value="it" minzoom="15" />
<type tag="office" value="lawyer" minzoom="15" />
<type tag="office" value="ngo" minzoom="15" />
<type tag="office" value="quango" minzoom="15" />
<type tag="office" value="research" minzoom="15" />
<type tag="office" value="telecommunication" minzoom="15" />
<type tag="office" value="travel_agent" minzoom="15" />
<type tag="amenity" value="architect_office" minzoom="15" target_tag="office" target_value="architect" poi_category="office"/>
</category>
<category name="shop" poi_tag="shop" poi_category="shop" >
<type tag="shop" value="alcohol" minzoom="15" />
<type tag="shop" value="bakery" minzoom="15" />
<type tag="shop" value="beauty" minzoom="15" />
<type tag="shop" value="beverages" minzoom="15" />
<type tag="shop" value="bicycle" minzoom="15" />
<type tag="shop" value="books" minzoom="15" />
<type tag="shop" value="boutique" minzoom="15" />
<type tag="shop" value="butcher" minzoom="15" />
<type tag="shop" value="car" minzoom="15" />
<type tag="shop" value="car_parts" minzoom="15" />
<type tag="shop" value="car_repair" minzoom="15" />
<type tag="shop" value="charity" minzoom="15" />
<type tag="shop" value="chemist" minzoom="15" />
<type tag="shop" value="clothes" minzoom="15" />
<type tag="shop" value="fashion" minzoom="15" />
<type tag="shop" value="computer" minzoom="15" />
<type tag="shop" value="confectionery" minzoom="15" />
<type tag="shop" value="convenience" minzoom="15" />
<type tag="shop" value="department_store" minzoom="15" />
<type tag="shop" value="dry_cleaning" minzoom="15" />
<type tag="shop" value="doityourself" minzoom="15" />
<type tag="shop" value="electronics" minzoom="15" />
<type tag="shop" value="fabrics" minzoom="15" />
<type tag="shop" value="farm" minzoom="15" />
<type tag="shop" value="florist" minzoom="15" />
<type tag="shop" value="funeral_directors" minzoom="15" />
<type tag="shop" value="furniture" minzoom="15" />
<type tag="shop" value="garden_centre" minzoom="15" />
<type tag="shop" value="general" minzoom="15" />
<type tag="shop" value="gift" minzoom="15" />
<type tag="shop" value="glaziery" minzoom="15" />
<type tag="shop" value="greengrocer" minzoom="15" />
<type tag="shop" value="hairdresser" minzoom="15" />
<type tag="shop" value="hardware" minzoom="15" />
<type tag="shop" value="hearing_aids" minzoom="15" />
<type tag="shop" value="hifi" minzoom="15" />
<type tag="shop" value="ice_cream" minzoom="15" />
<type tag="shop" value="jewelry" minzoom="15" />
<type tag="shop" value="kiosk" minzoom="15" />
<type tag="shop" value="laundry" minzoom="15" />
<type tag="shop" value="mall" minzoom="15" />
<type tag="shop" value="massage" minzoom="15" />
<type tag="shop" value="money_lender" minzoom="15" />
<type tag="shop" value="motorcycle" minzoom="15" />
<type tag="shop" value="newsagent" minzoom="15" />
<type tag="shop" value="optician" minzoom="15" />
<type tag="shop" value="organic" minzoom="15" />
<type tag="shop" value="outdoor" minzoom="15" />
<type tag="shop" value="pawnbroker" minzoom="15" />
<type tag="shop" value="second_hand" minzoom="15" />
<type tag="shop" value="sports" minzoom="15" />
<type tag="shop" value="stationery" minzoom="15" />
<type tag="shop" value="supermarket" minzoom="15" />
<type tag="shop" value="shoes" minzoom="15" />
<type tag="shop" value="tattoo" minzoom="15" />
<type tag="shop" value="toys" minzoom="15" />
<type tag="shop" value="travel_agency" minzoom="15" />
<type tag="shop" value="variety_store" minzoom="15" />
<type tag="shop" value="video" minzoom="15" />
</category>
<category name="emergency" poi_tag="emergency" poi_category="emergency">
<type tag="emergency" value="ambulance_station" minzoom="15" />
<type tag="emergency" value="ses_station" minzoom="15" />
<type tag="emergency" value="fire_extinguisher" minzoom="15" />
<type tag="emergency" value="fire_flapper" minzoom="15" />
<type tag="emergency" value="fire_hose" minzoom="15" />
<type tag="emergency" value="fire_hydrant" minzoom="15" />
<type tag="emergency" value="phone" minzoom="15" />
<type tag="emergency" value="access_point" minzoom="15" />
<type tag="amenity" value="emergency_phone" target_tag="emergency" target_value="phone" minzoom="15" />
<type tag="emergency" value="siren" minzoom="15" />
<type tag="amenity" value="fire_station" minzoom="15" poi_category="emergency"/>
</category>
<category name="tourism" poi_tag="tourism" poi_category="tourism" >
<type tag="tourism" value="attraction" minzoom="13" />
<type tag="tourism" value="artwork" minzoom="15" />
<type tag="tourism" value="camp_site" minzoom="13" />
<type tag="tourism" value="caravan_site" minzoom="13" />
<type tag="tourism" value="picnic_site" minzoom="13" />
<type tag="tourism" value="theme_park" minzoom="12" />
<type tag="tourism" value="zoo" minzoom="12" />
<type tag="tourism" value="alpine_hut" minzoom="14" />
<type tag="tourism" value="chalet" minzoom="15" />
<type tag="tourism" value="guest_house" minzoom="15" />
<type tag="tourism" value="hostel" minzoom="15" />
<type tag="tourism" value="hotel" minzoom="15" />
<type tag="tourism" value="motel" minzoom="15" />
<type tag="tourism" value="museum" minzoom="15" />
<type tag="tourism" value="information" minzoom="15" />
<type tag="tourism" value="viewpoint" minzoom="15" />
</category>
<category name="historic" poi_tag="historic" poi_category="historic">
<type tag="historic" value="archaeological_site" minzoom="15" />
<type tag="historic" value="battlefield" minzoom="15" />
<type tag="historic" value="castle" minzoom="15" />
<type tag="historic" value="fort" minzoom="15" />
<type tag="historic" value="ruins" minzoom="15" />
<type tag="historic" value="monument" minzoom="15" />
<type tag="historic" value="boundary_stone" minzoom="15" />
<type tag="historic" value="memorial" minzoom="15" />
<type tag="historic" value="wayside_cross" minzoom="15" />
<type tag="historic" value="wayside_shrine" minzoom="15" />
<type tag="historic" value="wreck" minzoom="15" />
</category>
<category name="landuse">
<type tag="landuse" value="allotments" minzoom="10" />
<type tag="landuse" value="basin" minzoom="10" poi_category="landuse"/>
<type tag="landuse" value="brownfield" minzoom="12" />
<type tag="landuse" value="cemetery" minzoom="11" poi_category="landuse"/>
<!-- landuse=grave_yard should be wrong tagging: type tag="landuse" value="grave_yard" minzoom="15" poi_category="landuse"/ -->
<type tag="landuse" value="commercial" minzoom="10" />
<type tag="landuse" value="construction" minzoom="12" />
<type tag="landuse" value="farm" minzoom="12" />
<type tag="landuse" value="farmland" minzoom="12" />
<type tag="landuse" value="farmyard" minzoom="12" />
<type tag="landuse" value="forest" minzoom="8" poi_category="landuse"/>
<type tag="landuse" value="garages" minzoom="12" />
<type tag="landuse" value="grass" minzoom="12" />
<type tag="landuse" value="greenfield" minzoom="12" />
<type tag="landuse" value="greenhouse_horticulture" minzoom="12" />
<type tag="landuse" value="industrial" minzoom="10" />
<type tag="landuse" value="landfill" minzoom="12" />
<type tag="landuse" value="meadow" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="military" minzoom="10" poi_category="landuse"/>
<type tag="landuse" value="orchard" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="railway" minzoom="12" />
<type tag="landuse" value="recreation_ground" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="conservation" minzoom="10" poi_category="landuse"/>
<type tag="landuse" value="village_green" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="reservoir" minzoom="7" poi_category="landuse"/>
<type tag="landuse" value="water" minzoom="7" poi_category="landuse"/>
<type tag="landuse" value="residential" minzoom="10" />
<type tag="landuse" value="retail" minzoom="12" />
<type tag="landuse" value="salt_pond" minzoom="10" poi_category="landuse"/>
<type tag="landuse" value="quarry" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="vineyard" minzoom="12" poi_category="landuse"/>
<type tag="landuse" value="field" minzoom="12" />
<type tag="natural" value="field" minzoom="12" target_tag="landuse" target_value="field" poi_category="" />
</category>
<category name="military" poi_category="military" poi_tag="military">
<type tag="military" value="airfield" minzoom="12" />
<type tag="military" value="bunker" minzoom="15" />
<type tag="military" value="barracks" minzoom="13" />
<type tag="military" value="danger_area" minzoom="10" />
<type tag="military" value="range" minzoom="10" />
<type tag="military" value="naval_base" minzoom="12" />
</category>
<category name="natural" poi_category="natural" poi_tag="natural">
<!-- coastline is polyline !!! -->
<type tag="natural" value="coastline" minzoom="1" />
<type tag="natural" value="bay" minzoom="5" />
<type tag="natural" value="beach" minzoom="11" />
<type tag="natural" value="cave_entrance" minzoom="13" />
<type tag="natural" value="cliff" minzoom="13" />
<type tag="natural" value="fell" minzoom="13" />
<type tag="natural" value="glacier" minzoom="7" />
<type tag="natural" value="heath" minzoom="11" />
<type tag="natural" value="land" minzoom="10" poi_category="" />
<type tag="natural" value="marsh" minzoom="11" />
<type tag="natural" value="mud" minzoom="11" />
<type tag="natural" value="peak" minzoom="11" nameTags="ele" />
<type tag="natural" value="sand" minzoom="11" />
<type tag="natural" value="scree" minzoom="11" />
<type tag="natural" value="scrub" minzoom="11" />
<type tag="natural" value="spring" minzoom="14" />
<type tag="natural" value="stone" minzoom="15" />
<type tag="natural" value="tree" minzoom="15" poi_category="" />
<type tag="natural" value="volcano" minzoom="11" />
<type tag="natural" value="water" minzoom="4" />
<type tag="natural" value="lake" minzoom="4" />
<type tag="natural" value="wetland" minzoom="10" />
<type tag="natural" value="wood" minzoom="8" />
<type tag="landuse" value="wood" minzoom="8"
target_tag="natural" target_value="wood" poi_category="natural" />
<type tag="contour" value="elevation" minzoom="11" />
</category>
<category name="contourtype">
<type tag="contourtype" value="10m" minzoom="11" additional="true"/>
<type tag="contourtype" value="20m" minzoom="11" additional="true"/>
<type tag="contourtype" value="50m" minzoom="11" additional="true"/>
<type tag="contourtype" value="100m" minzoom="11" additional="true"/>
</category>
<category name="geocache" poi_tag="geocache" poi_category="geocache">
<type tag="geocache" value="found" minzoom="15" />
<type tag="geocache" value="not found" minzoom="15" />
</category>
<!-- Amenities -->
<category name="sustenance" poi_category="sustenance">
<type tag="amenity" value="restaurant" minzoom="15" />
<type tag="amenity" value="cafe" minzoom="15" />
<type tag="amenity" value="food_court" minzoom="15" />
<type tag="amenity" value="fast_food" minzoom="15" />
<type tag="amenity" value="pub" minzoom="15" />
<type tag="amenity" value="bar" minzoom="15" />
<type tag="amenity" value="biergarten" minzoom="15" />
<type tag="amenity" value="drinking_water" minzoom="15" />
<type tag="amenity" value="bbq" minzoom="15" />
</category>
<category name="education" poi_category="education">
<type tag="amenity" value="kindergarten" minzoom="15" />
<type tag="amenity" value="school" minzoom="15" />
<type tag="amenity" value="college" minzoom="15" />
<type tag="amenity" value="library" minzoom="15" />
<type tag="amenity" value="university" minzoom="15" />
</category>
<category name="transportation" poi_category="transportation">
<type tag="amenity" value="parking" minzoom="15" />
<type tag="amenity" value="bicycle_parking" minzoom="15" />
<type tag="amenity" value="ferry_terminal" minzoom="12" />
<type tag="amenity" value="fuel" minzoom="13" />
<type tag="amenity" value="taxi" minzoom="15" />
<type tag="amenity" value="bicycle_rental" minzoom="15" />
<type tag="amenity" value="bus_station" minzoom="13" />
<type tag="amenity" value="car_rental" minzoom="15" />
<type tag="amenity" value="car_sharing" minzoom="15" />
<type tag="amenity" value="car_wash" minzoom="15" />
<type tag="amenity" value="grit_bin" minzoom="15" />
<type tag="rwn_ref" value="" minzoom="14" nameTags="rwn_ref" poi_prefix="walking_node_"/>
<type tag="rcn_ref" value="" minzoom="14" nameTags="rcn_ref" poi_prefix="cycle_node_"/>
</category>
<category name="finance" poi_category="finance">
<type tag="amenity" value="atm" minzoom="15" />
<type tag="amenity" value="bank" minzoom="15" />
<type tag="amenity" value="bureau_de_change" minzoom="15" />
</category>
<category name="healthcare" poi_category="healthcare">
<type tag="amenity" value="pharmacy" minzoom="15" />
<type tag="amenity" value="hospital" minzoom="15" />
<type tag="amenity" value="baby_hatch" minzoom="15" />
<type tag="amenity" value="dentist" minzoom="15" />
<type tag="amenity" value="doctors" minzoom="15" />
<type tag="amenity" value="veterinary" minzoom="15" />
<type tag="amenity" value="first_aid" minzoom="15" />
</category>
<category name="entertainment" poi_category="entertainment">
<type tag="amenity" value="arts_centre" minzoom="15" />
<type tag="amenity" value="cinema" minzoom="15" />
<type tag="amenity" value="community_centre" minzoom="15" />
<type tag="amenity" value="social_centre" minzoom="15" />
<type tag="amenity" value="nightclub" minzoom="15" />
<type tag="amenity" value="stripclub" minzoom="15" />
<type tag="amenity" value="studio" minzoom="15" />
<type tag="amenity" value="theatre" minzoom="15" />
<type tag="amenity" value="sauna" minzoom="15" />
<type tag="amenity" value="brothel" minzoom="15" />
</category>
<category name="amenity_other" poi_tag="amenity" poi_category="other">
<type tag="amenity" value="marketplace" minzoom="15" />
<type tag="amenity" value="courthouse" minzoom="15" />
<type tag="amenity" value="crematorium" minzoom="15" />
<type tag="amenity" value="embassy" minzoom="15" />
<type tag="amenity" value="grave_yard" minzoom="15" />
<type tag="amenity" value="hunting_stand" minzoom="15" />
<type tag="amenity" value="police" minzoom="15" />
<type tag="amenity" value="post_box" minzoom="15" />
<type tag="amenity" value="post_office" minzoom="15" />
<type tag="amenity" value="prison" minzoom="15" />
<type tag="amenity" value="public_building" minzoom="15" />
<type tag="amenity" value="recycling" minzoom="15" />
<type tag="amenity" value="shelter" minzoom="15" />
<type tag="amenity" value="telephone" minzoom="15" />
<type tag="amenity" value="toilets" minzoom="15" />
<type tag="amenity" value="townhall" minzoom="15" />
<type tag="amenity" value="vending_machine" minzoom="15" />
<type tag="amenity" value="waste_basket" minzoom="15" />
<type tag="amenity" value="waste_disposal" minzoom="15" />
<type tag="amenity" value="fountain" minzoom="15" />
<type tag="amenity" value="bench" minzoom="15" />
<type tag="amenity" value="clock" minzoom="15" />
<type tag="amenity" value="place_of_worship" minzoom="15" />
</category>
<category name="internet_access" poi_tag="internet_access" poi_prefix="internet_access_" poi_category="other">
<type tag="internet_access" value="wifi" minzoom="15" />
<type tag="internet_access" value="wlan" minzoom="15" />
<type tag="internet_access" value="terminal" minzoom="15" />
<type tag="internet_access" value="wired" minzoom="15" />
<type tag="internet_access" value="public" minzoom="15" />
<type tag="internet_access" value="service" minzoom="15" />
</category>
<!-- administrative place-->
<category name="administrative" poi_tag="place" poi_category="administrative" >
<type tag="place" value="continent" minzoom="1" />
<type tag="place" value="country" minzoom="2" />
<type tag="place" value="state" minzoom="3" />
<type tag="place" value="region" minzoom="4" />
<type tag="place" value="county" minzoom="4" />
<type tag="place" value="city" minzoom="4" />
<type tag="place" value="town" minzoom="6" />
<type tag="place" value="village" minzoom="10" />
<type tag="place" value="hamlet" minzoom="10" />
<type tag="place" value="suburb" minzoom="10" />
<type tag="place" value="locality" minzoom="10" />
<type tag="place" value="island" minzoom="10" />
</category>
<!-- administrative boundaries -->
<category>
<!-- register(st, "boundary", "administrative", ADMINISTRATIVE, 15, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ -->
<type tag="admin_level" value="1" minzoom="2" />
<type tag="admin_level" value="0" minzoom="2" />
<type tag="admin_level" value="2" minzoom="3" />
<type tag="admin_level" value="3" minzoom="5" />
<type tag="admin_level" value="4" minzoom="5" />
<type tag="admin_level" value="5" minzoom="6" />
<type tag="admin_level" value="6" minzoom="6" />
<type tag="admin_level" value="7" minzoom="6" />
<type tag="admin_level" value="8" minzoom="10" />
<type tag="admin_level" value="9" minzoom="11" />
<type tag="admin_level" value="10" minzoom="12" />
<type tag="boundary" value="civil" minzoom="7" />
<type tag="boundary" value="political" minzoom="7" />
<type tag="boundary" value="maritime" minzoom="7" />
<type tag="boundary" value="national_park" minzoom="7" />
<type tag="boundary" value="protected_area" minzoom="7" />
</category>
<!-- sport -->
<category name="sport" poi_tag="sport" poi_category="sport">
<type tag="sport" value="9pin" minzoom="15" />
<type tag="sport" value="10pin" minzoom="15" />
<type tag="sport" value="archery" minzoom="15" />
<type tag="sport" value="athletics" minzoom="15" />
<type tag="sport" value="australian_football" minzoom="15" />
<type tag="sport" value="baseball" minzoom="15" />
<type tag="sport" value="basketball" minzoom="15" />
<type tag="sport" value="beachvolleyball" minzoom="15" />
<type tag="sport" value="boules" minzoom="15" />
<type tag="sport" value="bowls" minzoom="15" />
<type tag="sport" value="canoe" minzoom="15" />
<type tag="sport" value="chess" minzoom="15" />
<type tag="sport" value="climbing" minzoom="15" />
<type tag="sport" value="cricket" minzoom="15" />
<type tag="sport" value="cricket_nets" minzoom="15" />
<type tag="sport" value="croquet" minzoom="15" />
<type tag="sport" value="cycling" minzoom="15" />
<type tag="sport" value="diving" minzoom="15" />
<type tag="sport" value="scuba_diving" minzoom="15" />
<type tag="sport" value="dog_racing" minzoom="15" />
<type tag="sport" value="equestrian" minzoom="15" />
<type tag="sport" value="football" minzoom="15" />
<type tag="sport" value="golf" minzoom="15" />
<type tag="sport" value="gymnastics" minzoom="15" />
<type tag="sport" value="hockey" minzoom="15" />
<type tag="sport" value="horse_racing" minzoom="15" />
<type tag="sport" value="ice_stock" minzoom="15" />
<type tag="sport" value="korfball" minzoom="15" />
<type tag="sport" value="motor" minzoom="15" />
<type tag="sport" value="multi" minzoom="15" />
<type tag="sport" value="orienteering" minzoom="15" />
<type tag="sport" value="paddle_tennis" minzoom="15" />
<type tag="sport" value="paragliding" minzoom="15" />
<type tag="sport" value="pelota" minzoom="15" />
<type tag="sport" value="racquet" minzoom="15" />
<type tag="sport" value="rowing" minzoom="15" />
<type tag="sport" value="rugby" minzoom="15" />
<type tag="sport" value="shooting" minzoom="15" />
<type tag="sport" value="skating" minzoom="15" />
<type tag="sport" value="skateboard" minzoom="15" />
<type tag="sport" value="skiing" minzoom="15" />
<type tag="sport" value="soccer" minzoom="15" />
<type tag="sport" value="swimming" minzoom="15" />
<type tag="sport" value="table_tennis" minzoom="15" />
<type tag="sport" value="team_handball" minzoom="15" />
<type tag="sport" value="tennis" minzoom="15" />
<type tag="sport" value="toboggan" minzoom="15" />
<type tag="sport" value="volleyball" minzoom="15" />
</category>
<category name="osmwiki" poi_tag="osmwiki" poi_category="osmwiki"/>
<category name="tiles">
</category>
<category name="user_defined" poi_tag="user_defined" poi_category="user_defined">
<!-- Here user defined categories could be added -->
<!-- <type tag="user_defined" value="wsl" minzoom="10" /> -->
</category>
</osmand_types>

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