Restructure repository
This commit is contained in:
parent
a8e13aadbf
commit
3db27de275
620 changed files with 0 additions and 199096 deletions
|
@ -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>
|
5
DataExtractionOSM/.gitignore
vendored
5
DataExtractionOSM/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
|||
bin/
|
||||
build/
|
||||
build.zip
|
||||
cpd.xml
|
||||
/bin-tests
|
|
@ -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>
|
|
@ -1,3 +0,0 @@
|
|||
#Thu Apr 29 00:40:46 EEST 2010
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
|
@ -1,3 +0,0 @@
|
|||
#Mon Oct 10 15:40:12 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
line.separator=\n
|
|
@ -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.
|
@ -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
|
|
@ -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
|
|
@ -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="${build.version}";//"/>
|
||||
</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>
|
|
@ -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>
|
||||
|
||||
|
||||
|
1
DataExtractionOSM/icons/.gitignore
vendored
1
DataExtractionOSM/icons/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
resources
|
|
@ -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
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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=
|
|
@ -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.
|
@ -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
|
|
@ -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 $@
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
Binary file not shown.
|
@ -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);
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*----------------------------------------------------------------------------*/
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<mpl=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<mpl=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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
Loading…
Reference in a new issue