[gosmore] 10/20: Imported Upstream version 0.0.0.svn30327
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat May 7 12:24:59 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository gosmore.
commit 8ebc9e79378f03e31dd68ca3abbeca1452dd564d
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sat May 7 11:54:37 2016 +0200
Imported Upstream version 0.0.0.svn30327
---
AndroidManifest.xml | 60 +
Makefile.in | 61 +-
README | 31 +-
bboxSplit.cpp | 11 +-
bounds.osm.bz2 | Bin 127660 -> 114507 bytes
dailyUpdate.sh | 66 +
default.properties | 12 +
density.c | 2 +-
elemstyles.xml | 34 +-
gosmore.nsi | 5 +
jni/Android.mk | 15 +
jni/Application.mk | 4 +
ConvertUTF.c => jni/ConvertUTF.c | 0
ConvertUTF.h => jni/ConvertUTF.h | 0
ceglue.c => jni/ceglue.c | 0
ceglue.h => jni/ceglue.h | 0
gosmore.cpp => jni/gosmore.cpp | 1559 ++++++++++++--------
libgosm.cpp => jni/libgosm.cpp | 274 ++--
libgosm.h => jni/libgosm.h | 13 +-
jni/openglespolygon.cpp | 532 +++++++
jni/openglespolygon.h | 42 +
resource.h => jni/resource.h | 0
translations.c => jni/translations.c | 0
proguard.cfg | 48 +
res/drawable-hdpi/btn_square_overlay_normal.png | Bin 0 -> 929 bytes
res/drawable-hdpi/btn_zoom_down_disabled.png | Bin 0 -> 2376 bytes
.../btn_zoom_down_disabled_focused.png | Bin 0 -> 2697 bytes
res/drawable-hdpi/btn_zoom_down_normal.png | Bin 0 -> 2104 bytes
res/drawable-hdpi/btn_zoom_down_pressed.png | Bin 0 -> 4306 bytes
res/drawable-hdpi/btn_zoom_down_selected.png | Bin 0 -> 4348 bytes
res/drawable-hdpi/btn_zoom_up_disabled.png | Bin 0 -> 2531 bytes
res/drawable-hdpi/btn_zoom_up_disabled_focused.png | Bin 0 -> 2829 bytes
res/drawable-hdpi/btn_zoom_up_normal.png | Bin 0 -> 2065 bytes
res/drawable-hdpi/btn_zoom_up_pressed.png | Bin 0 -> 3806 bytes
res/drawable-hdpi/btn_zoom_up_selected.png | Bin 0 -> 3802 bytes
res/drawable-hdpi/ic_menu_play_clip.png | Bin 0 -> 2291 bytes
res/drawable-hdpi/icon.png | Bin 0 -> 3481 bytes
res/drawable-hdpi/stat_sys_upload_anim0.png | Bin 0 -> 927 bytes
res/drawable-ldpi/icon.png | Bin 0 -> 1518 bytes
res/drawable-mdpi/btn_square_overlay_normal.png | Bin 0 -> 1279 bytes
res/drawable-mdpi/btn_zoom_down_disabled.png | Bin 0 -> 1534 bytes
.../btn_zoom_down_disabled_focused.png | Bin 0 -> 1867 bytes
res/drawable-mdpi/btn_zoom_down_normal.png | Bin 0 -> 1305 bytes
res/drawable-mdpi/btn_zoom_down_pressed.png | Bin 0 -> 2370 bytes
res/drawable-mdpi/btn_zoom_down_selected.png | Bin 0 -> 2395 bytes
res/drawable-mdpi/btn_zoom_up_disabled.png | Bin 0 -> 1600 bytes
res/drawable-mdpi/btn_zoom_up_disabled_focused.png | Bin 0 -> 1911 bytes
res/drawable-mdpi/btn_zoom_up_normal.png | Bin 0 -> 1305 bytes
res/drawable-mdpi/btn_zoom_up_pressed.png | Bin 0 -> 2465 bytes
res/drawable-mdpi/btn_zoom_up_selected.png | Bin 0 -> 2463 bytes
res/drawable-mdpi/ic_menu_play_clip.png | Bin 0 -> 1194 bytes
res/drawable-mdpi/icon.png | Bin 0 -> 2383 bytes
res/drawable-mdpi/stat_sys_download_anim0.png | Bin 0 -> 588 bytes
res/drawable/mappaint.png | Bin 0 -> 792812 bytes
res/layout/download_progress.xml | 24 +
res/layout/map_help.xml | 107 ++
res/layout/map_view.xml | 67 +
res/layout/old_main.xml | 29 +
res/layout/search.xml | 29 +
res/layout/search_result.xml | 30 +
res/layout/update.xml | 31 +
res/menu/map.xml | 19 +
res/values/arrays.xml | 38 +
res/values/strings.xml | 58 +
src/org/osmu/gosmore/Gosmore.java | 83 ++
src/org/osmu/gosmore/MapActivity.java | 726 +++++++++
src/org/osmu/gosmore/Place.java | 10 +
src/org/osmu/gosmore/Preferences.java | 54 +
src/org/osmu/gosmore/Recent.java | 31 +
src/org/osmu/gosmore/Search.java | 131 ++
src/org/osmu/gosmore/Update.java | 243 +++
71 files changed, 3692 insertions(+), 787 deletions(-)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100755
index 0000000..a2a84c1
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.osmu.gosmore"
+ android:versionCode="1"
+ android:versionName="1.0">
+<!-- /ion/Program\ Files/Java/jdk1.6.0_23/bin/keytool.exe -genkey -keysize 2048 -keyalg RSA -validity 10000 -->
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <application android:name=".Gosmore" android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="false">
+ <activity android:name=".Menu">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Update"
+ android:label="Update">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Search"
+ android:label="Search">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Recent"
+ android:label="Recent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Preferences"
+ android:label="Preferences">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".MapActivity"
+ android:label="Gosmore"
+ android:configChanges="keyboardHidden|orientation">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="7"/>
+
+</manifest>
\ No newline at end of file
diff --git a/Makefile.in b/Makefile.in
index 3da1e07..6626f59 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -38,40 +38,33 @@ XMLFLAGS=`pkg-config --cflags libxml-2.0 || echo -I /usr/include/libxml2` \
`pkg-config --libs libxml-2.0 || echo -l xml2 -lm`
ARCH=arm-mingw32ce-
else
-# To compile with mingw, install MSYS and mingw, and then download
-# the "all-in-one bundle" from http://www.gtk.org/download-windows.html
-# and unzip it to C:\msys\1.0.
-EXTRAC=-mms-bitfields -mno-cygwin -mwindows \
+
+EXTRAC=-Ilibxml2-2.7.8/include \
`pkg-config --cflags gtk+-2.0 || echo -D NOGTK`
-EXTRAL=`pkg-config --libs gtk+-2.0`
+
+EXTRAL=`pkg-config --libs gtk+-2.0` \
+
EXE=.exe
-W32LIBS=-lwsock32 -lwinmm
+W32LIBS=-Llibxml2-2.7.8/.libs -lxml2 -lwsock32 -lwinmm -lgdi32
+
endif
all: gosmore$(EXE)
-# The planet is too big to fit into the address space of a single process on
-# a 32 bit CPUs. So we break it up into pieces (overlapping rectangles and
-# some lowzoom extracts) and then run one process for each piece. The parent
-# task then chooses the most
-# appropriate process and forwards the expose, search or routing request to
-# it. THE CODE IS NOT FINISHED. Linux version looks promising.
-gosmore: gosmore.cpp libgosm.cpp libgosm.h bboxes.c
- g++ -DCHILDREN=16 ${CFLAGS} ${WARNFLAGS} ${XMLFLAGS} \
- gosmore.cpp libgosm.cpp -o gosmore ${EXTRA}
-
-gosmore16: gosmore.cpp libgosm.cpp libgosm.h
- g++ -DGOSMZ=16 ${CFLAGS} ${WARNFLAGS} ${XMLFLAGS} \
- gosmore.cpp libgosm.cpp -o gosmore16 ${EXTRA}
-
-$(ARCH)gosmore.exe: gosmore.cpp libgosm.cpp gosmore.rsc resource.h \
- libgosm.h ceglue.h ceglue.c bboxes.c
- ${ARCH}g++ ${CFLAGS} ${EXTRAC} -c gosmore.cpp
- ${ARCH}g++ ${CFLAGS} ${EXTRAC} -c libgosm.cpp
- ${ARCH}gcc ${CFLAGS} ${EXTRAC} -c ConvertUTF.c
- ${ARCH}gcc ${CFLAGS} ${EXTRAC} -c ceglue.c
- ${ARCH}g++ -static ${CFLAGS} ${EXTRAC} -o $@ \
- gosmore.o libgosm.o ceglue.o ConvertUTF.o gosmore.rsc $(W32LIBS)
+gosmore: jni/gosmore.cpp jni/libgosm.cpp jni/libgosm.h jni/bboxes.c \
+ jni/openglespolygon.h jni/openglespolygon.cpp
+ g++ ${CFLAGS} ${WARNFLAGS} \
+ jni/gosmore.cpp jni/libgosm.cpp jni/openglespolygon.h \
+ jni/openglespolygon.cpp -o gosmore ${EXTRA} ${XMLFLAGS}
+
+$(ARCH)gosmore.exe: jni/gosmore.cpp jni/libgosm.cpp gosmore.rsc jni/resource.h \
+ jni/libgosm.h jni/ceglue.h jni/ceglue.c bboxes.c
+ ${ARCH}g++ ${CFLAGS} ${EXTRAC} -c jni/gosmore.cpp
+ ${ARCH}g++ ${CFLAGS} ${EXTRAC} -c jni/libgosm.cpp
+ ${ARCH}gcc ${CFLAGS} ${EXTRAC} -c jni/ConvertUTF.c
+ ${ARCH}gcc ${CFLAGS} ${EXTRAC} -c jni/ceglue.c
+ ${ARCH}g++ -static ${EXTRAL} \
+ gosmore.o libgosm.o ceglue.o ConvertUTF.o gosmore.rsc $(W32LIBS) -o $@
tagcmp.o: tagcmp.l
@@ -80,20 +73,20 @@ gosmore.rsc: gosmore.rc icons.bmp icons-mask.bmp gosmore.ico
WIKIPAGE=http://wiki.openstreetmap.org/index.php/Special:Export/Gosmore
translations.c: extract
- wget -O - ${WIKIPAGE}/Translations |./extract >translations.c
+ wget -O - ${WIKIPAGE}/Translations |./extract >jni/translations.c
extract: extract.c
${CC} ${CFLAGS} ${XMLFLAGS} extract.c -o extract
-bboxes.c: density.c density.txt
- gcc -lm density.c -o density
+jni/bboxes.c: density.c density.txt
+ gcc density.c -lm -o density
./density <density.txt >density.sh
# wget http://www.openstreetmap.org/api/0.6/changeset/1707270/download -O \
# countries.osm
-osmunda: osmunda.cpp libgosm.cpp libgosm.h
+osmunda: osmunda.cpp jni/libgosm.cpp jni/libgosm.h
g++ ${CFLAGS} ${WARNFLAGS} ${XMLFLAGS} \
- osmunda.cpp libgosm.cpp -o osmunda
+ osmunda.cpp jni/libgosm.cpp -o osmunda
voices:
echo '(voice_rab_diphone)' >/tmp/voice_rab_diphone
echo 'At the junction, turn left.' | festival_client \
@@ -178,7 +171,7 @@ routingTest: gosmore
dist:
mkdir gosmore-$(VERSION)
- cp gosmore.cpp Makefile elemstyles.xml icons.csv icons.xpm README \
+ cp jni/gosmore.cpp Makefile elemstyles.xml icons.csv icons.xpm README \
gosmore-$(VERSION)
tar zcf gosmore-$(VERSION).tar.gz gosmore-$(VERSION)
rm -rf gosmore-$(VERSION)
diff --git a/README b/README
index 0293175..cf54b0d 100644
--- a/README
+++ b/README
@@ -49,6 +49,31 @@ countries.osm comes from openstreetmap.org
The png files comes openclipart.org and other public domain sources.
-Everything else are placed by in the public domain by its authors.
-Written by Nic Roets with contribution(s) from Dave Hansen, David Dean and
-others.
+Everything else was written by Nic Roets with contributions from David Dean,
+Dave Hansen and others and is placed under the Simplified BSD License :
+
+Copyright 2010 Nic Roets. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ of conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY NIC ROETS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NIC ROETS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those of the
+authors and should not be interpreted as representing official policies, either expressed
+or implied, of Nic Roets.
diff --git a/bboxSplit.cpp b/bboxSplit.cpp
index f836db1..ca64de9 100755
--- a/bboxSplit.cpp
+++ b/bboxSplit.cpp
@@ -102,6 +102,9 @@ int main (int argc, char *argv[])
while (n < buf + cnt && isspace (*n)) n++;
if (isEnd && level == 2 && tipe[level - 1] == 'o') { // Note: n may be at buf + cnt
+ nwr[0].clear (); // Free some memory for in case one or more
+ nwr[1].clear (); // processes does heavy postprocessing.
+ nwr[2].clear ();
for (int j = 0; j < bcnt; j++) fprintf (f[j], "</osm>\n");
// By splitting these two steps we allow downstream XML converters
// like gosmore to do their post-XML processing in parallel.
@@ -173,10 +176,12 @@ int main (int argc, char *argv[])
olevel = level;
}
} // If it's /> or </..>
- else if (*ptr == '<') tipe[level++] = ptr[1];
+ else if (*ptr == '<') {
+ if (ptr[1] != '!') tipe[level++] = ptr[1];
+ }
// The tests for 'level' is not necessary for valid OSM-XML
else if (level == 3 && strncasecmp (ptr, "id=", 3) == 0) {
- id = atoi (ptr[3] == '\'' || ptr[3] == '\"' ? ptr + 4 : ptr + 3);
+ id = atoll (ptr[3] == '\'' || ptr[3] == '\"' ? ptr + 4 : ptr + 3);
}
else if (level == 3 && strncasecmp (ptr, "lat=", 4) == 0) {
lat = atof (ptr[4] == '\'' || ptr[4] == '\"' ? ptr + 5 : ptr + 4);
@@ -188,7 +193,7 @@ int main (int argc, char *argv[])
memberTipe = ptr[5] == '\'' || ptr[5] == '\"' ? ptr[6] : ptr[5];
}
else if (level == 4 && strncasecmp (ptr, "ref=", 4) == 0) {
- ref = atoi (ptr[4] == '\'' || ptr[4] == '\"' ? ptr + 5 : ptr + 4);
+ ref = atoll (ptr[4] == '\'' || ptr[4] == '\"' ? ptr + 5 : ptr + 4);
}
ptr = n;
} while (ptr + 1 < buf + cnt);
diff --git a/bounds.osm.bz2 b/bounds.osm.bz2
index 56206e7..6bba22b 100755
Binary files a/bounds.osm.bz2 and b/bounds.osm.bz2 differ
diff --git a/dailyUpdate.sh b/dailyUpdate.sh
new file mode 100755
index 0000000..e3602c7
--- /dev/null
+++ b/dailyUpdate.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# Copyright 2010 Nic Roets as detailed in the README file.
+# The Osm.org Routing demo daily update script
+# The script runs as a cron job.
+
+# make CFLAGS='-O2 -DRES_DIR=\"/usr/share/gosmore/\" -DHEADLESS -DONLY_ROUTING -DLD_CTRL'
+OSMOSIS=$HOME/osmosis-0.38/bin/osmosis
+FIRST_OSC=$(readlink $HOME/planet-latest.osm.bz2 |
+ sed 's/[^0-9]\|2$//g')
+# A crude way of getting the date of the planet e.g. 100716
+PLANET=$HOME/planet-$FIRST_OSC.osm.bz2
+# List of change files from youngest to oldest
+cd $HOME/daily
+# Get into working directory
+
+if [ g.o -nt lock ] ||
+ ! wget -c http://planet.openstreetmap.org/daily/$(date -d 'now - 1 day' +%Y%m%d)-$(date +%Y%m%d).osc.gz ||
+ ! gzip --test $(date -d 'now - 1 day' +%Y%m%d)-$(date +%Y%m%d).osc.gz
+then exit 0
+fi
+
+cd $HOME/gosmore
+OSC_LIST="ls -r $HOME/daily/*.gz "
+
+# I tried a number of different things (in comments) before I had success.
+# PARAM=$($OSC_LIST |grep -A 30 20${FIRST_OSC}- |
+# ( read first
+# echo --rxc $first
+# awk '{ print "--rxc ", $1, " --mc conflictResolutionMethod=version" }'))
+# CMD="$OSMOSIS $PARAM --rx /dev/stdin --ac --wx -"
+
+#----
+# nice -n 20 $OSMOSIS $PARAM --wxc week.osc
+# exit 0
+# CMD="$OSMOSIS --rxc week.osc --rx /dev/stdin --ac --wx -"
+
+#----
+# PARAM=$($OSC_LIST |grep -A 30 20${FIRST_OSC}- |
+# ( read first
+# echo --rxc $first --rx /dev/stdin --ac
+# awk '{ print "--rxc ", $1, " --ac" }'))
+# CMD="$OSMOSIS $PARAM --wx -"
+
+#----
+PARAM=$($OSC_LIST |grep -B 30 20${FIRST_OSC}- | awk '{ print "--rxc ", $1 }' )
+AC=$($OSC_LIST |grep -B 30 20${FIRST_OSC}- | awk '{ print "--ac " }')
+
+CMD="$OSMOSIS $PARAM --rx /dev/stdin $AC --wx -"
+
+echo $CMD
+# exit
+
+if nice -n 20 bzcat $PLANET | nice -n 20 $CMD |
+ (cd relations; nice -n 20 ../gosmore sortRelations) |
+ nice -n 20 ./bboxSplit -89 -179 89 -30 "./gosmore rebuild" g.o \
+ -89 -30 89 179 "cd e; ../gosmore rebuild" europe/g.o
+then mv america/gosmore.pak am.pak
+ mv europe/gosmore.pak eu.pak
+ mv gosmore.pak america/
+ mv e/gosmore.pak europe/
+ mv relations/relations.tbl .
+fi
+
+sleep 2
+touch lock
+./lockMmap $(date +'24*3600 - (%s - 18*3600) %% (24*3600)' |bc) america/gosmore.pak europe/gosmore.pak
diff --git a/default.properties b/default.properties
new file mode 100755
index 0000000..ad4ca32
--- /dev/null
+++ b/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-4
+proguard.config=proguard.cfg
diff --git a/density.c b/density.c
index 33423cb..9691704 100755
--- a/density.c
+++ b/density.c
@@ -24,7 +24,7 @@ char block[S * 2 + 1][98765], *bptr[S * 2 + 1];
int main (void)
{
char fname[30];
- FILE *html, *gosm = fopen ("bboxes.c", "w"), *sh = fopen ("bboxSplit.sh", "w");
+ FILE *html, *gosm = fopen ("jni/bboxes.c", "w"), *sh = fopen ("bboxSplit.sh", "w");
memset (cov, 0, sizeof (cov));
memset (mat, 0, sizeof (mat));
html= fopen ("density.html", "w");
diff --git a/elemstyles.xml b/elemstyles.xml
index 36ec52e..74088e0 100644
--- a/elemstyles.xml
+++ b/elemstyles.xml
@@ -923,6 +923,15 @@ The colours can only be in hex
</rule>
<rule>
+ <condition k="highway" v="tertiary_link"/>
+ <line width="3" realwidth="6" colour="#fdbf6f"/>
+ <!-- <icon annotate="true" src="misc/deprecated.png" /> -->
+ <scale_min>1</scale_min>
+ <scale_max>40000</scale_max>
+ <routing bicycle="12" foot="5" goods="50" hgv="50" motorcycle="50" motorcar="50" psv="50" moped="45" mofa="25"/>
+ </rule>
+
+ <rule>
<condition k="highway" v="unclassified"/>
<line width="2" realwidth="5" colour="#c0c0c0"/>
<!-- <icon annotate="true" src="misc/deprecated.png" /> -->
@@ -1042,7 +1051,7 @@ The colours can only be in hex
<!-- <icon annotate="true" src="misc/deprecated.png" /> -->
<scale_min>1</scale_min>
<scale_max>10000</scale_max>
- <routing bicycle="20" foot="5"/>
+ <routing foot="5"/>
</rule>
<rule>
@@ -1200,7 +1209,7 @@ The colours can only be in hex
<condition k="highway" v="bus_stop" />
<icon annotate="true" src="transport/bus_small.png" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
@@ -1434,7 +1443,7 @@ The colours can only be in hex
<icon annotate="true" src="nautical/weir.png" />
<line width="2" colour="#D8D8D8" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
@@ -1791,14 +1800,14 @@ The colours can only be in hex
<icon annotate="true" src="misc/landmark/power/tower.png" />
<area width="1" colour="#eeeeee" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
<condition k="power" v="pole"/>
<icon annotate="true" src="misc/landmark/power/pole.png"/>
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
@@ -1806,7 +1815,7 @@ The colours can only be in hex
<line width="1" colour="#eeeeee" />
<!-- <icon annotate="true" src="misc/deprecated.png" /> -->
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
@@ -1830,7 +1839,7 @@ The colours can only be in hex
<icon annotate="true" src="misc/landmark/power.png" />
<area width="1" colour="#eeeeee" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>10000</scale_max>
</rule>
<!--the power_source rules must be placed before the power=generator rule! -->
@@ -1839,7 +1848,7 @@ The colours can only be in hex
<icon annotate="true" src="misc/landmark/power/wind.png" />
<area width="1" colour="#eeeeee" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
@@ -1890,13 +1899,14 @@ The colours can only be in hex
<scale_max>50000</scale_max>
</rule>
+<!-- Rather render according to power_source icons
<rule>
- <condition k="power" v="generator" />
+ <condition k="power" v="generator" />
<icon annotate="true" src="misc/landmark/power.png" />
<area width="1" colour="#eeeeee" />
<scale_min>1</scale_min>
<scale_max>50000</scale_max>
- </rule>
+ </rule> -->
<!--man_made tags -->
<rule>
@@ -2057,7 +2067,7 @@ The colours can only be in hex
<icon annotate="true" src="leisure/water_park.png" />
<area colour="#c7f1a3" />
<scale_min>1</scale_min>
- <scale_max>50000</scale_max>
+ <scale_max>20000</scale_max>
</rule>
<rule>
@@ -3126,7 +3136,7 @@ The colours can only be in hex
<icon annotate="true" src="shop/toys.png" />
<area colour="#a0a0ff"/>
<scale_min>1</scale_min>
- <scale_max>65000</scale_max>
+ <scale_max>5000</scale_max>
</rule>
<rule>
diff --git a/gosmore.nsi b/gosmore.nsi
index 35e81fe..3b94765 100755
--- a/gosmore.nsi
+++ b/gosmore.nsi
@@ -15,6 +15,11 @@ UninstPage instfiles
Section "Gosmore"
SetOutPath $INSTDIR
File "gosmore.exe"
+ File "elemstyles.xml"
+ File "icons.csv"
+ File "libgcc_s_dw2-1.dll"
+ File "libstdc++-6.dll"
+ File "libxml2-2.dll"
File "default.pak"
File "gosmore.opt"
File "keepleft.wav"
diff --git a/jni/Android.mk b/jni/Android.mk
new file mode 100755
index 0000000..ef833db
--- /dev/null
+++ b/jni/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+CFLAGS := -g
+
+LOCAL_MODULE := gosmore
+
+LOCAL_CFLAGS := -DANDROID_NDK -DRES_DIR=\"/m8xp2az\"
+
+LOCAL_SRC_FILES := openglespolygon.cpp gosmore.cpp libgosm.cpp
+
+LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/jni/Application.mk b/jni/Application.mk
new file mode 100755
index 0000000..6ed8cf2
--- /dev/null
+++ b/jni/Application.mk
@@ -0,0 +1,4 @@
+APP_MODULES := gosmore
+APP_PROJECT_PATH := ..
+# APP_STL := gnustl_static
+APP_STL := stlport_static
diff --git a/ConvertUTF.c b/jni/ConvertUTF.c
similarity index 100%
rename from ConvertUTF.c
rename to jni/ConvertUTF.c
diff --git a/ConvertUTF.h b/jni/ConvertUTF.h
similarity index 100%
rename from ConvertUTF.h
rename to jni/ConvertUTF.h
diff --git a/ceglue.c b/jni/ceglue.c
similarity index 100%
rename from ceglue.c
rename to jni/ceglue.c
diff --git a/ceglue.h b/jni/ceglue.h
similarity index 100%
rename from ceglue.h
rename to jni/ceglue.h
diff --git a/gosmore.cpp b/jni/gosmore.cpp
similarity index 75%
rename from gosmore.cpp
rename to jni/gosmore.cpp
index 5473fcf..5fdfac6 100755
--- a/gosmore.cpp
+++ b/jni/gosmore.cpp
@@ -1,11 +1,11 @@
-/* This software is placed by in the public domain by its authors. */
+/* Copyright 2010 Nic Roets as detailed in the README file. */
/* Written by Nic Roets with contribution(s) from Dave Hansen, Ted Mielczarek
- David Dean, Pablo D'Angelo and Dmitry.
+ David Dean, Pablo D'Angelo, Dmitry and Adrian Batzill.
Thanks to
* Sven Geggus, Frederick Ramm, Johnny Rose Carlsen and Lambertus for hosting,
* Stephan Rossig, Simon Wood, David Dean, Lambertus and many others for testing,
* OSMF for partial funding. */
-
+// rm -f obj/local/armeabi/objs/gosmore/gosmore.o.d; ../../../../android/android-ndk-r5/ndk-build
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -18,6 +18,16 @@
#include <algorithm>
#include <queue>
#include <map>
+
+#define LG //__android_log_print (ANDROID_LOG_WARN, "Gosmore", "%d", __LINE__);
+#ifdef ANDROID_NDK
+#include <android/log.h>
+#include <jni.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#define NOGTK
+#define LOG //__android_log_print (ANDROID_LOG_WARN, "Gosmore", "%d", __LINE__);
+#endif
using namespace std;
#ifndef _WIN32
#include <sys/mman.h>
@@ -36,7 +46,7 @@ using namespace std;
#ifdef _WIN32_WCE
#define NOGTK
#endif
-#ifdef NOGTK
+#if defined(NOGTK) && defined (_WIN32)
#include <io.h>
#include <sys/stat.h>
#include <windowsx.h>
@@ -56,6 +66,9 @@ using namespace std;
#define OLDOLDOPTIONS \
o (ModelessDialog, 0, 2)
+
+HINSTANCE hInst;
+static HWND mWnd, dlgWnd = NULL, hwndEdit, button3D, buttons[3];
#else
#include <unistd.h>
#include <sys/stat.h>
@@ -63,6 +76,24 @@ using namespace std;
#define wchar_t char
#define wsprintf sprintf
#endif
+#if !defined (HEADLESS) && !defined (NOGTK)
+#ifdef USE_GNOMESOUND
+#include <libgnome/libgnome.h>
+#endif
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#endif
+#include "openglespolygon.h"
+#ifdef USE_GEOCLUE // Not used and never worked
+#include <geoclue/geoclue-position.h>
+#endif
+#ifdef USE_GPSD
+#include <gps.h>
+#endif
#define OPTIONS \
o (FollowGPSr, 0, 2) \
@@ -112,32 +143,13 @@ int Display3D = 0; // Not an option but a button for now.
o (cmduturn, 0, 0) o (cmdround1, 0, 0) o (cmdround2, 0, 0) \
o (cmdround3, 0, 0) o (cmdround4, 0, 0) o (cmdround5, 0, 0) \
o (cmdround6, 0, 0) o (cmdround7, 0, 0) o (cmdround8, 0, 0)
-
char docPrefix[80] = "";
int GpsIdle=999;
-#if !defined (HEADLESS) && !defined (NOGTK)
-#ifdef USE_GNOMESOUND
-#include <libgnome/libgnome.h>
-#endif
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
-#endif
-#ifdef USE_GEOCLUE // Not used and never worked
-#include <geoclue/geoclue-position.h>
-#endif
-#ifdef USE_GPSD
-#include <gps.h>
-#endif
// We emulate just enough of gtk to make it work
-#ifdef NOGTK
+#if defined(NOGTK)
#define gtk_widget_queue_clear(x) // After Click() returns we Invalidate
-HWND hwndList;
#define gtk_toggle_button_set_active(x,y) // followGPRr
struct GtkWidget {
struct {
@@ -160,10 +172,9 @@ enum { GDK_SCROLL_UP, GDK_SCROLL_DOWN };
#define VALIDATE_PEN 1
#define RESERVED_PENS 2 */
-HINSTANCE hInst;
-static HWND mWnd, dlgWnd = NULL, hwndEdit, button3D, buttons[3];
-
+#ifndef ANDROID_NDK
#define LOG logprintf ("%d\n", __LINE__);
+#endif
#else
#define LOG // Less debug info needed because we have gdb
#ifndef RES_DIR
@@ -189,6 +200,9 @@ const char *FindResource (const char *fname)
return strdup (fname);
}
#endif
+#ifndef HEADLESS
+GtkWidget *draw, *location, *display3D, *followGPSr;
+#endif
// used for showing logs to a file (with default)
// changed to more suitable value for WinCE in WinMain
@@ -270,19 +284,19 @@ int clon, clat, zoom, option = EnglishNum, gpsSockTag, setLocBusy = FALSE, gDisp
TCHAR currentBbox[80] = TEXT ("");
-void ChangePak (const TCHAR *pakfile, int mlon, int mlat)
-{
+int ChangePak (const TCHAR *pakfile, int mlon, int mlat)
+{ // Returns TRUE if pakfile or a bbox was loaded, false if default was loaded or failure
static int bboxList[][4] = {
#include "bboxes.c"
}, world[] = { -512, -512, 512, 512 }, *bbox = NULL;
-
+
if (bbox && bbox[0] <= (mlon >> 22) && bbox[1] <= ((-mlat) >> 22) &&
- bbox[2] > (mlon >> 22) && bbox[3] > ((-mlat) >> 22)) return;
- GosmFreeRoute ();
+ bbox[2] > (mlon >> 22) && bbox[3] > ((-mlat) >> 22)) return 0;
+ LG GosmFreeRoute ();
memset (gosmSstr, 0, sizeof (gosmSstr));
shortest = NULL;
- if (!pakfile) {
+ LG if (!pakfile) {
int best = 0;
for (size_t j = 0; j < sizeof (bboxList) / sizeof (bboxList[0]); j++) {
int worst = min (mlon / 8 - (bboxList[j][0] << 19),
@@ -335,13 +349,14 @@ void ChangePak (const TCHAR *pakfile, int mlon, int mlat)
CreateFileMapping(gmap, NULL, PAGE_READONLY, 0, 0, 0);
LOG map = fm == INVALID_HANDLE_VALUE ? NULL :
MapViewOfFile (fm, FILE_MAP_READ, 0, 0, 0);
+ int len = map ? GetFileSize (gmap, NULL) : 0;
LOG Exit = !map || !GosmInit (map, GetFileSize(gmap, NULL));
LOG if (Exit && gmap != INVALID_HANDLE_VALUE) {
MessageBox (NULL, TEXT ("mmap problem. Pak file too big ?"),
TEXT (""), MB_APPLMODAL|MB_OK);
}
- #if 0
+ #ifdef _WIN32
FILE *gmap = _wfopen (/*"./gosmore.pak"*/ , TEXT ("rb"));
if (!gmap) {
@@ -364,43 +379,62 @@ void ChangePak (const TCHAR *pakfile, int mlon, int mlat)
// printf ("%s %d %d\n", pakfile, (mlon >> 22) + 512, 512 - (mlat >> 22));
if (map != (void*) -1) munmap (map, len);
- FILE *gmap = fopen64 (pakfile, "r");
- if (!gmap && currentBbox == pakfile &&
- (gmap = fopen64 ("default.pak", "r")) == NULL) {
+ FILE *pakmap = fopen64 (pakfile, "r");
+ FILE *gmap = !pakmap && currentBbox == pakfile
+ ? fopen64 ("default.pak", "r") : pakmap;
+ if (!gmap && currentBbox == pakfile) {
gmap = fopen64 (RES_DIR "default.pak", "r");
}
- len = gmap && fseek (gmap, 0, SEEK_END) == 0 ? ftell (gmap) : 0;
+ LG len = gmap && fseek (gmap, 0, SEEK_END) == 0 ? ftell (gmap) : 0;
map = !len ? (void*)-1
: mmap (NULL, ftell (gmap), PROT_READ, MAP_SHARED, fileno (gmap), 0);
- Exit = map == (void *) -1 || !GosmInit (map, len);
- if (gmap) fclose (gmap);
+ LG Exit = map == (void *) -1 || !GosmInit (map, len);
+ LG if (gmap) fclose (gmap);
#endif
/* // Slightly more portable:
GMappedFile *gmap = g_mapped_file_new (pakfile, FALSE, NULL);
Exit = !gmap || !GosmInit (g_mapped_file_get_contents (gmap),
g_mapped_file_get_length (gmap));
*/
+// __android_log_print(ANDROID_LOG_WARN, "Gosmore", "re %p %d", bbox, Exit);
LOG if (Exit) bbox = NULL;
+ LG return pakmap != NULL;
+}
+#ifdef ANDROID_NDK
+extern "C" jint Java_org_osmu_gosmore_MapActivity_changePak (JNIEnv* env,
+ jobject thiz, jstring js, jint mlon, jint mlat)
+{
+ LG IconSet = 1;
+ DetailLevel = 3;
+ ButtonSize = 4;
+ Background = 1;
+ option= mapMode;
+ ShowCompass = 0;
+ const char *sdcard = env->GetStringUTFChars(js, NULL);
+ chdir (sdcard);
+ LG env->ReleaseStringUTFChars(js, sdcard);
+ if (ChangePak ("gosmore.pak", 0, 0)) return 2;
+ if (Exit && ChangePak (NULL, mlon, mlat)) return 2;
+ if (Exit) strcpy (currentBbox, "default");
+// __android_log_print(ANDROID_LOG_WARN, "Gosmore", "re %s", currentBbox);
+ return Exit ? 0 : 1;
+}
+
+extern "C" jstring Java_org_osmu_gosmore_Update_currentBbox
+ (JNIEnv* env, jobject thiz)
+{
+// __android_log_print(ANDROID_LOG_WARN, "Gosmore", "re %s", currentBbox);
+ currentBbox[16] = '\0'; // Strip the .pak off for Java
+ return env->NewStringUTF (currentBbox);
}
+#endif
+
#ifndef HEADLESS
-GtkWidget *draw, *location, *display3D, *followGPSr;
double cosAzimuth = 1.0, sinAzimuth = 0.0;
string highlight, searchStr ("Search");
-struct tsItem {
- string cmd;
- #ifndef NOGTK
- GdkPixbuf *pix;
- #else
- HICON pix;
- #endif
-// tsItem () {}
-};
-
-deque<tsItem> tsList;
-
inline void SetLocation (int nlon, int nlat)
{
clon = nlon;
@@ -409,6 +443,7 @@ inline void SetLocation (int nlon, int nlat)
char lstr[50];
int zl = 0;
while (zl < 32 && (zoom >> zl)) zl++;
+ setlocale (LC_NUMERIC, "C");
sprintf (lstr, "?lat=%.5lf&lon=%.5lf&zoom=%d", LatInverse (nlat),
LonInverse (nlon), 33 - zl);
setLocBusy = TRUE;
@@ -424,6 +459,7 @@ int ChangeLocation (void)
char *lstr = (char *) gtk_entry_get_text (GTK_ENTRY (location));
double lat, lon;
while (*lstr != '?' && *lstr != '\0') lstr++;
+ setlocale (LC_NUMERIC, "C");
if (sscanf (lstr, "?lat=%lf&lon=%lf&zoom=%d", &lat, &lon, &zoom) == 3) {
clat = Latitude (lat);
clon = Longitude (lon);
@@ -674,6 +710,8 @@ void CallRoute (int recalculate, int plon, int plat)
#endif
}
+
+#ifndef ANDROID_NDK
void DoFollowThing (gpsNewStruct *gps)
{
static int lastTime = -1;
@@ -711,18 +749,60 @@ void DoFollowThing (gpsNewStruct *gps)
}
if (!/*gps->fix.mode >= MODE_2D &&*/ FollowGPSr) return;
SetLocation (Longitude (gps->fix.longitude), Latitude (gps->fix.latitude));
-/* int plon = Longitude (gps->fix.longitude + gps->fix.speed * 3600.0 /
- 40000000.0 / cos (gps->fix.latitude * (M_PI / 180.0)) *
- sin (gps->fix.track * (M_PI / 180.0)));
- int plat = Latitude (gps->fix.latitude + gps->fix.speed * 3600.0 /
- 40000000.0 * cos (gps->fix.track * (M_PI / 180.0))); */
+ __int64 dlon = clon - flon, dlat = clat - flat;
+ flon = clon;
+ flat = clat;
+#else
+
+extern "C" void Java_org_osmu_gosmore_MapRenderer_startRoute (
+ JNIEnv* env, jobject thiz, jdouble lon, jdouble lat)
+{
+ flon = Longitude (lon);
+ flat = Latitude (lat);
+ GosmFreeRoute ();
+ shortest = NULL;
+}
+
+extern "C" void Java_org_osmu_gosmore_MapRenderer_endRoute (
+ JNIEnv* env, jobject thiz, jdouble lon, jdouble lat, jboolean fastest,
+ jint vehicle)
+{
+ tlon = Longitude (lon);
+ tlat = Latitude (lat);
+ Vehicle = vehicle;
+ FastestRoute = fastest;
+ Route (TRUE, 0, 0, Vehicle, FastestRoute);
+}
+
+extern "C" jint Java_org_osmu_gosmore_MapRenderer_doRoute (
+ JNIEnv* env, jobject thiz)
+{
+ if (!RouteLoop()) return routeSuccess ? 999 : -1;
+ // I suspect shortest is never NULL here, but I still guard against it.
+ return (jint)(!shortest ? 0 : ((Sqr (__int64 (shortest->nd->lon - tlon)) +
+ Sqr (__int64 (shortest->nd->lat - tlat))) * 100) /
+ (Sqr (__int64 (flon - tlon)) +
+ Sqr (__int64 (flat - tlat)) + (1<<15)));
+}
+
+extern "C" jstring Java_org_osmu_gosmore_MapRenderer_navigate (
+ JNIEnv* env, jobject thiz, jdouble lon, jdouble lat, jfloat speed,
+ jfloat bearing)
+{
+ const char *tts = "";
+ flon = Longitude (lon);
+ flat = Latitude (lat);
+ __int64 dlon = Longitude (lon + speed * 3600.0 /
+ 40000000.0 / cos (lat * (M_PI / 180.0)) *
+ sin (bearing * (M_PI / 180.0))) - flon;
+ __int64 dlat = Latitude (lat + speed * 3600.0 /
+ 40000000.0 * cos (bearing * (M_PI / 180.0))) - flat;
+ // Slightly faster would be dlon=speed*(...); dlat=speed*(...);
+#endif
// Predict the vector that will be traveled in the next 10seconds
// printf ("%5.1lf m/s Heading %3.0lf\n", gps->fix.speed, gps->fix.track);
// printf ("%lf %lf\n", gps->fix.latitude, gps->fix.longitude);
- __int64 dlon = clon - flon, dlat = clat - flat;
- flon = clon;
- flat = clat;
if (routeSuccess) CallRoute (FALSE, dlon, dlat);
static ndType *decide[3] = { NULL, NULL, NULL }, *oldDecide = NULL;
@@ -763,7 +843,7 @@ void DoFollowThing (gpsNewStruct *gps)
x->shortest->shortest ? x->shortest->shortest->nd->lon : tlon;
while (nd[-1].lon == nd->lon && nd[-1].lat == nd->lat) nd--;
int segCnt = 0; // Count number of segments at x->shortest
- int n2Left, fLeft = INT_MIN;
+ int n2Left = /* Keep compiler quiet*/ 0, fLeft = INT_MIN;
do {
// TODO : Only count segment traversable by 'Vehicle'
// Except for the case where a cyclist crosses a motorway_link.
@@ -819,7 +899,20 @@ void DoFollowThing (gpsNewStruct *gps)
oldCommand = command[0];
oldDecide = decide[0];
#define o(cmd,dummy1,dummy2) TEXT (#cmd),
-#ifdef _WIN32_WCE
+#ifdef ANDROID_NDK
+ static const char *cmds[] = {
+ "Turn left.", "Keep left.", "Turn right", "Keep right.",
+ "You have reached your destination.", "Make a U turn if possible.",
+ "At the roundabout, take the first exit.",
+ "At the roundabout, take the second exit.",
+ "At the roundabout, take the third exit.",
+ "At the roundabout, take the fourth exit.",
+ "At the roundabout, take the fifth exit.",
+ "At the roundabout, take the sixth exit.",
+ "At the roundabout, take the seventh exit.",
+ "At the roundabout, take the eighth exit." };
+ tts = cmds[command[0]-cmdturnleftNum];
+#elif defined(_WIN32_WCE)
static const wchar_t *cmdStr[] = { COMMANDS };
wchar_t argv0[80];
GetModuleFileName (NULL, argv0, sizeof (argv0) / sizeof (argv0[0]));
@@ -852,21 +945,66 @@ void DoFollowThing (gpsNewStruct *gps)
sinAzimuth = -dlon / dist;
}
gtk_widget_queue_clear (draw);
+ #ifdef ANDROID_NDK
+ return env->NewStringUTF( tts);
+ #endif
} // If following the GPSr and it has a fix.
+// Regrettably here are a few static variables with very generic names. They
+// are however unique in this file.
+static int cosa, sina, xadj, width = 320, height = 240;
+__int64 yadj;
+#define FAR3D 100000 // 3D view has a limit of roughly 5 km forwards
+#define WIDE3D 100000 // and roughly 5km between top left & top right corner
+#define CAMERA2C 20000 // How far the camera is behind the user (clat/lon)
+#define HEIGHT 12000 // Height of the camera
+#define PIX45 256 // Y value corresponding to 45 degrees down
+#define XFix PIX45
+
+#define myint int
+/* The 3D computations can all be done in signed 32 bits integers,
+ provided overflow bits are simply discarded. The C specification says
+ however that ints that overflow are undefined (as well as any
+ expression that touches them). So if the 3D display looks garbled
+ under a new compiler, try running with #define myint __int64
+*/
+
+#define MUL 64
+#define Depth(lon,lat) \
+ (int)(yadj + (lat) * (myint) cosa - (lon) * (myint) sina)
+#define X1(lon,lat) \
+ (int)(xadj + (lon) * (myint) cosa + (lat) * (myint) sina)
+#define AdjDepth(lon,lat) (Depth (lon, lat) < PIX45 * HEIGHT * MUL / 5000 \
+ && Depth (lon, lat) > -PIX45 * HEIGHT * MUL / 5000 ? \
+ PIX45 * HEIGHT * MUL / 5000 : Depth (lon, lat))
+#define Y(lon,lat) (Display3D ? PIX45 * HEIGHT * MUL / AdjDepth (lon, lat) \
+ : yadj + (int)(((lon) * (__int64) sina - (lat) * (__int64) cosa) >> 32))
+#define Y2(lon,lat) (Display3D ? PIX45 * HEIGHT * MUL * (__int64)65536 / AdjDepth (lon, lat) \
+ : (yadj<<16) + (int)(((lon) * (__int64) sina - (lat) * (__int64) cosa) >> 16))
+#define X(lon,lat) (Display3D ? width / 2 + \
+((AdjDepth (lon, lat) > 0 ? 1 : -1) * \
+ (X1 (lon, lat) / 32000 - AdjDepth (lon, lat) / XFix) > 0 ? 32000 : \
+(AdjDepth (lon, lat) > 0 ? 1 : -1) * \
+ (X1 (lon, lat) / 32000 + AdjDepth (lon, lat) / XFix) < 0 ? -32000 : \
+X1(lon,lat) / (AdjDepth (lon, lat) / XFix)) \
+: xadj + (int)(((lon) * (__int64) cosa + (lat) * (__int64) sina) >> 32))
+#define X2(lon,lat) (Display3D ? X(lon,lat)*65536 : \
+ (xadj<<16) + (int)(((lon) * (__int64) cosa + (lat) * (__int64) sina) >> 16))
+//X2 and Y2 are X and Y but 65536 times larger
+
#ifndef NOGTK
#ifdef ROUTE_TEST
gint RouteTest (GtkWidget * /*widget*/, GdkEventButton *event, void *)
{
static int ptime = 0;
ptime = time (NULL);
- int w = draw->allocation.width;
+ int w = width;
int perpixel = zoom / w;
clon += lrint ((event->x - w / 2) * perpixel);
- clat -= lrint ((event->y - draw->allocation.height / 2) * perpixel);
+ clat -= lrint ((event->y - height / 2) * perpixel);
/* int plon = clon + lrint ((event->x - w / 2) * perpixel);
int plat = clat -
- lrint ((event->y - draw->allocation.height / 2) * perpixel); */
+ lrint ((event->y - height / 2) * perpixel); */
FollowGPSr = TRUE;
gpsNewStruct gNew;
gNew.fix.latitude = LatInverse (clat);
@@ -927,7 +1065,7 @@ void GpsMove (gps_data_t *gps, char */*buf*/, size_t /*len*/
}*/
#endif // !ROUTE_TEST
-#else // else NOGTK
+#elif defined(_WIN32) // else NOGTK
#define NEWWAY_MAX_COORD 10
struct newWaysStruct {
int coord[NEWWAY_MAX_COORD][2], klas, cnt, oneway, bridge;
@@ -1011,6 +1149,7 @@ BOOL CALLBACK DlgSetTags2Proc (HWND hwnd, UINT Msg, WPARAM wParam,
#endif // NOGTK
+#ifndef ANDROID_NDK
int Scroll (GtkWidget * /*widget*/, GdkEventScroll *event, void * /*w_cur*/)
{
if (Display3D) {
@@ -1019,7 +1158,7 @@ int Scroll (GtkWidget * /*widget*/, GdkEventScroll *event, void * /*w_cur*/)
clat + lrint (cosAzimuth * k));
}
else {
- int w = draw->allocation.width, h = draw->allocation.height;
+ int w = width, h = height;
int perpixel = zoom / w;
if (event->direction == GDK_SCROLL_UP) zoom = zoom / 4 * 3;
if (event->direction == GDK_SCROLL_DOWN) zoom = zoom / 3 * 4;
@@ -1031,6 +1170,7 @@ int Scroll (GtkWidget * /*widget*/, GdkEventScroll *event, void * /*w_cur*/)
gtk_widget_queue_clear (draw);
return FALSE;
}
+#endif
int objectAddRow = -1;
#define ADD_HEIGHT 32
@@ -1039,7 +1179,7 @@ void HitButton (int b)
{
int returnToMap = b > 0 && option <= FastestRouteNum;
- #ifdef NOGTK
+ #ifdef _WIN32
if (AddWayOrNode && b == 0) {
AddWayOrNode = 0;
option = mapMode;
@@ -1063,7 +1203,7 @@ void HitButton (int b)
tlat = clat;
CallRoute (TRUE, 0, 0);
}
- #ifdef NOGTK
+ #ifdef _WIN32
else if (option == DisplayOffNum) {
if (CeEnableBacklight(FALSE)) {
gDisplayOff = TRUE;
@@ -1088,8 +1228,6 @@ void HitButton (int b)
if (returnToMap) option = mapMode;
}
-int firstDrag[2] = { -1, -1 }, lastDrag[2], pressTime;
-
#ifndef NOGTK
struct wayPointStruct {
int lat, lon;
@@ -1169,14 +1307,15 @@ int UpdateWayPoints (GtkWidget *, GdkEvent *, gpointer *)
return FALSE;
}
-gint Drag (GtkWidget * /*widget*/, GdkEventMotion *event, void * /*w_cur*/)
+//gint Drag (GtkWidget * /*widget*/, GdkEventMotion *event, void * /*w_cur*/)
+/*
{
if ((option == mapMode || option == optionMode) &&
(event->state & GDK_BUTTON1_MASK)) {
if (firstDrag[0] >= 0) gdk_draw_drawable (draw->window,
draw->style[0].fg_gc[0], draw->window,
0, 0, lrint (event->x) - lastDrag[0], lrint (event->y) - lastDrag[1],
- draw->allocation.width, draw->allocation.height);
+ width, height);
lastDrag[0] = lrint (event->x);
lastDrag[1] = lrint (event->y);
if (firstDrag[0] < 0) {
@@ -1185,7 +1324,7 @@ gint Drag (GtkWidget * /*widget*/, GdkEventMotion *event, void * /*w_cur*/)
}
}
return FALSE;
-}
+}*/
GtkWidget *bar;
int UpdateProcessFunction(void */*userData*/, double t, double d,
@@ -1200,7 +1339,6 @@ int UpdateProcessFunction(void */*userData*/, double t, double d,
void *UpdateMapThread (void *n)
{
CURL *curl;
- CURLcode res;
FILE *outfile;
curl = curl_easy_init();
@@ -1217,10 +1355,10 @@ void *UpdateMapThread (void *n)
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, UpdateProcessFunction);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ""); // Bar);
- res = curl_easy_perform(curl);
+ curl_easy_perform(curl);
fclose(outfile);
- system ("unzip tmp.zip"); //cmd.c_str ());
+ if (system ("unzip tmp.zip") == -1) fprintf (stderr, "Error:system()\n");
string dst ((string)(char*)n + ".pak");
rename ("gosmore.pak", dst.c_str ());
unlink ("tmp.zip");
@@ -1309,20 +1447,42 @@ DWORD WINAPI UpdateMapThread (LPVOID n)
}
#endif
-#define CompactOptions ((draw->allocation.width * draw->allocation.height < 400 * 400))
+/* These macros calling macros may result in very long bloated code and
+ inefficient machine code, depending on how well the compiler optimizes.
+*/
+
+#define CompactOptions ((width * height < 400 * 400))
int ListXY (int cnt, int isY)
{ // Returns either the x or the y for a certain list item
int max = mapMode; //option == optionMode ? mapNode :
int w = CompactOptions ? 70 : 105, h = CompactOptions ? 45 : 80;
- while ((draw->allocation.width/w) * (draw->allocation.height/h - 1) > max) {
+ while ((width/w) * (height/h - 1) > max) {
w++;
h++;
}
- return isY ? cnt / (draw->allocation.width / w) * h + h / 2 - listYOffset :
- (cnt % (draw->allocation.width / w)) * w + w / 2;
+ return isY ? cnt / (width / w) * h + h / 2 - listYOffset :
+ (cnt % (width / w)) * w + w / 2;
}
-#ifndef NOGTK
+#ifdef ANDROID_NDK // OPENGL
+typedef jint HDC;
+#define gdk_draw_drawable(win,dgc,sdc,x,y,dx,dy,w,h) \
+ do { int crop[] = { x, y + h, w, -h }; \
+ glEnable(GL_BLEND); \
+ glEnable(GL_TEXTURE_2D); \
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); \
+ glDrawTexiOES(dx, height - dy, 0, crop[2], h); \
+ glDisable(GL_TEXTURE_2D); \
+ glDisable(GL_BLEND);\
+ } while (0) // TODO Try to get a glMatrix that match OES coordinates
+#define gdk_draw_line(win,gc,sx,sy,dx,dy) \
+ do { GdkPoint l[2] = { sx, sy, dx, dy }; \
+ glVertexPointer (2, GL_SHORT, 0, l); \
+ glDrawArrays (GL_LINES, 0, 2); } while (0)
+
+static jmethodID drawTeks = 0;
+
+#elif !defined(NOGTK)
typedef GdkGC *HDC;
static GdkGC *maskGC = NULL, *fg_gc;
@@ -1355,13 +1515,13 @@ PangoLayout *pl;
void DrawString (int x, int y, const char *optStr)
{
- #if PANGO_VERSION
+ #ifdef PANGO_VERSION
PangoMatrix mat = PANGO_MATRIX_INIT;
pango_context_set_matrix (pc, &mat);
pango_layout_set_text (pl, optStr, -1);
gdk_draw_layout (GDK_DRAWABLE (draw->window),
fg_gc /*draw->style->fg_gc[0]*/, x, y, pl);
- #else
+ #elif defined (_WIN32)
SelectObject (mygc, sysFont);
const unsigned char *sStart = (const unsigned char*) optStr;
UTF16 wcTmp[70], *tStart = (UTF16 *) wcTmp;
@@ -1376,9 +1536,9 @@ void DrawString (int x, int y, const char *optStr)
void DrawPoI (int dstx, int dsty, int *icon)
{
if (icon[2] == 0 || dstx < -icon[2] || dsty < -icon[3] ||
- dstx > draw->allocation.width + icon[2] ||
+ dstx > width + icon[2] ||
// GDK need these tests for the Start&EndRoute markers
- dsty > draw->allocation.height + icon[3]) return;
+ dsty > height + icon[3]) return;
#ifndef NOGTK
// for gdk we first need to extract the portion of the mask
if (!maskicon) maskicon = gdk_pixmap_new(NULL, 100, 100, 1);
@@ -1411,7 +1571,94 @@ void GeoSearch (const char *key)
else GosmSearch (clon, clat, key);
}
-int HandleKeyboard (GdkEventButton *event)
+
+#if defined (ANDROID_NDK)
+/*extern "C" void Java_org_osmu_gosmore_MapView_setLocation (
+ JNIEnv* env, jobject thiz, jdouble lon, jdouble lat)
+{
+ LG clon = Longitude (lon);
+ clat = Latitude (lat);
+}*/
+
+#define DisplaySearchResults(); // Never in searchMode, no-op
+extern "C" void Java_org_osmu_gosmore_Search_search (
+ JNIEnv* env, jobject thiz, jstring jquery)
+{
+ static jmethodID meth = 0;
+ static int started = 0;
+ if (!started) {
+ started = 1;
+ jclass cls=env->GetObjectClass(thiz);
+ //cls =(jclass)( env->NewGlobalRef(jcls) );
+ //cls = env->FindClass(
+ // "org/osmu/gosmore/MyClb");
+
+ meth = env->GetMethodID(cls, "searchResult",
+ "(IIIIDIILjava/lang/String;DDI)V");
+// env->ExceptionClear();
+ /* if (method != 0)*/
+// env->ExceptionClear();
+ }
+ const char *query = env->GetStringUTFChars(jquery, NULL);
+ GeoSearch (query);
+ LG env->ReleaseStringUTFChars(jquery, query);
+
+#else
+void DisplaySearchResults (void)
+{
+#endif
+ for (int i = 0, y = SearchSpacing / 2; i < searchCnt && gosmSstr[i];
+ i++, y += SearchSpacing) {
+ double dist = sqrt (double (Sqr ((__int64) clon - gosmSway[i]->clon) +
+ Sqr ((__int64) clat - gosmSway[i]->clat))) * (20000 / 2147483648.0) *
+ cos (LatInverse (clat) * (M_PI / 180));
+
+ int x = SearchSpacing + 70;
+ __int64 lx = X (gosmSway[i]->clon, gosmSway[i]->clat) - width / 2;
+ __int64 ly = Y (gosmSway[i]->clon, gosmSway[i]->clat) - height / 2;
+ double norm = lx || ly ? sqrt (double(lx * lx + ly * ly)) / 64 : 1;
+ int u = lrint (lx / norm), v = lrint (ly / norm);
+ string s (gosmSstr[i], strcspn (gosmSstr[i], "\n"));
+ char *name = (char *)(gosmSway[i] + 1) + 1;
+ if (name != gosmSstr[i]) s += " (" +
+ string (name, strcspn (name, "\n")) + ")";
+ #ifdef ANDROID_NDK
+ jstring js = env->NewStringUTF (s.c_str ());
+ int *z = Style (gosmSway[i])->x + 4 * IconSet;
+ env->CallVoidMethod (thiz, meth, z[0], z[1], z[2], z[3],
+ dist, u, v, js,
+ LonInverse (gosmSway[i]->clon),
+ LatInverse (gosmSway[i]->clat),
+ gosmSway[i]->dlat + gosmSway[i]->dlon + (1 << 15));
+ #else
+ DrawPoI (SearchSpacing / 2, y, Style (gosmSway[i])->x + 4 * IconSet);
+
+ char distance[10]; // Formula inaccurate over long distances hence "Far"
+ sprintf (distance, dist > 998 ? "Far" : dist > 1 ? "%.0lf km" :
+ "%.0lf m", dist > 1 ? dist : dist * 1000);
+ DrawString (SearchSpacing + 33 - 11 * strcspn (distance, " "), y - 10,
+ distance); // Right adjustment is inaccurate
+ gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
+ x - u / 8, y - v / 8);
+ gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
+ x + u / 12 + v / 20, y - u / 20 + v / 12);
+ gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
+ x + u / 12 - v / 20, y + u / 20 + v / 12);
+
+ DrawString (SearchSpacing + x, y - 10, s.c_str ());
+
+ gdk_draw_line (draw->window, mygc, 0, y + SearchSpacing / 2,
+ width, y + SearchSpacing / 2);
+ #endif
+ }
+}
+
+
+#ifndef _WIN32_WCE
+int HandleKeyboard (int, int, int)
+{
+#else
+int HandleKeyboard (int event, int ex, int ey)
{ // Some WinCE devices, like the Mio Moov 200 does not have an input method
// and any call to activate it or set the text on an EDIT or STATIC (label)
// control will crash the application. So under WinCE we default to our
@@ -1420,13 +1667,12 @@ int HandleKeyboard (GdkEventButton *event)
// Draw our own keyboard (Expose Event) or handle the key (Click)
if (Keyboard) return FALSE; // Using the Windows keyboard
// DrawString (30, 5, searchStr.c_str ()); // For testing under GTK
- #ifdef _WIN32_WCE
if (!event) {
RECT r;
r.left = 0;
- r.top = draw->allocation.height - 32 * 3;
- r.right = draw->allocation.width;
- r.bottom = draw->allocation.height;
+ r.top = height - 32 * 3;
+ r.right = width;
+ r.bottom = height;
FillRect (mygc, &r, (HBRUSH) GetStockObject (WHITE_BRUSH)); //brush[KeyboardNum]);
SelectObject (mygc, GetStockObject (BLACK_PEN));
}
@@ -1434,9 +1680,9 @@ int HandleKeyboard (GdkEventButton *event)
const char *kbLayout[] = { "qwertyuiop", "asdfghjkl", " zxcvbnm,$" };
for (int i = 0; i < 3; i++) {
for (int j = 0; kbLayout[i][j] != '\0'; j++) {
- int hb = draw->allocation.width / strlen (kbLayout[0]) / 2, ys = 16;
- int x = (2 * j + (i & 1)) * hb, y = draw->allocation.height - (3 - i) * ys * 2;
- if (event && event->y >= y && event->y < y + ys + ys && event->x < x + hb + hb) {
+ int hb = width / strlen (kbLayout[0]) / 2, ys = 16;
+ int x = (2 * j + (i & 1)) * hb, y = height - (3 - i) * ys * 2;
+ if (event && ey >= y && ey < y + ys + ys && ex < x + hb + hb) {
if (kbLayout[i][j] != '$') searchStr += kbLayout[i][j];
else if (searchStr.length () > 0) searchStr.erase (searchStr.length () - 1, 1);
logprintf ("'%s'\n", searchStr.c_str());
@@ -1446,7 +1692,7 @@ int HandleKeyboard (GdkEventButton *event)
}
if (!event) {
if (j > 0) gdk_draw_line (draw->window, mygc, x, y, x, y + ys + ys);
- else gdk_draw_line (draw->window, mygc, 0, y, draw->allocation.width, y);
+ else gdk_draw_line (draw->window, mygc, 0, y, width, y);
string chr = string ("") + kbLayout[i][j];
if (kbLayout[i][j] == ' ') DrawString (x + hb - 5, y + ys / 2, "[ ]");
else if (kbLayout[i][j] != '$') DrawString (x + hb, y + ys / 2, chr.c_str ());
@@ -1462,29 +1708,56 @@ int HandleKeyboard (GdkEventButton *event)
return FALSE;
}
-int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
-{
- static int lastRelease = 0;
- int w = draw->allocation.width, h = draw->allocation.height;
+static int lastRelease = 0, oldx = -1, oldy, pressTime = -1;
+#if !defined (ANDROID_NDK)
+/*extern "C" int Java_org_osmu_gosmore_MapRenderer_mouseEv (
+ JNIEnv* env, jobject thiz, jint x, jint y, jint evTime,
+ jint button, jboolean click)*/
+int MouseEv (int x, int y, int evTime, int button, int click)
+{
// Anything that covers more than 3 pixels in either direction is a drag.
- int isDrag = DebounceDrag
- ? firstDrag[0] >= 0 && (lastRelease + 100 > (int) event->time ||
- pressTime + 100 < (int) event->time)
- : firstDrag[0] >= 0 && (abs((int)(firstDrag[0] - event->x)) > 3 ||
- abs((int)(firstDrag[1] - event->y)) > 3);
-
+ LG gtk_widget_queue_clear (draw);
+ int w = width, h = height;
+ int isDrag = //DebounceDrag ?
+ pressTime >= 0 && (lastRelease + 200 > evTime ||
+ pressTime + 200 < evTime);
+// : pressTime >= 0 && (abs((int)(firstDrag[0] - event->x)) > 3 ||
+// abs((int)(firstDrag[1] - event->y)) > 3;
// logprintf("Click (isDrag = %d): firstDrag = %d,%d; event = %d,%d\n",
// isDrag, firstDrag[0], firstDrag[1], event->x, event->y);
+ if (pressTime == -1) pressTime = evTime;
+ if (click) pressTime = -1;
+ if (click) lastRelease = evTime;
+ if (isDrag) {
+ if (option == optionMode) {
+ listYOffset = max (0, listYOffset + (int)lrint (oldy - y));
+ }
+ if (option == mapMode) {
+ int lon = clon + lrint (zoom / w *
+ (cosAzimuth * (Display3D ? 0 : oldx - x) - sinAzimuth * (y - oldy)));
+ int lat = clat + lrint (zoom / w *
+ (cosAzimuth * (y - oldy + sinAzimuth * (Display3D ? 0 : oldx - x))));
+ if (Display3D) {
+ double newa = atan2 (sinAzimuth, cosAzimuth) - (oldx-x) * M_PI / 580;
+ cosAzimuth = cos (newa);
+ sinAzimuth = sin (newa);
+ }
+ SetLocation (lon, lat);
+ }
+ }
+ oldx = x;
+ oldy = y;
+ if (!click || isDrag) return 0;
if (ButtonSize <= 0) ButtonSize = 4;
- int b = (draw->allocation.height - lrint (event->y)) / (ButtonSize * 20);
+ int b = (height - lrint (y)) / (ButtonSize * 20);
if (objectAddRow >= 0) {
int perRow = (w - ButtonSize * 20) / ADD_WIDTH;
- if (event->x < w - ButtonSize * 20) {
- #ifdef NOGTK
- newWays[newWayCnt].klas = objectAddRow + event->x / ADD_WIDTH +
- event->y / ADD_HEIGHT * perRow;
+ if (x < w - ButtonSize * 20) {
+ #ifdef _WIN32
+ newWays[newWayCnt].klas = objectAddRow + x / ADD_WIDTH +
+ y / ADD_HEIGHT * perRow;
SipShowIM (SIPF_ON);
if (DialogBox (hInst, MAKEINTRESOURCE (IDD_SETTAGS), NULL,
(DLGPROC) DlgSetTagsProc)) {} //DialogBox (hInst,
@@ -1493,20 +1766,17 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
#endif
objectAddRow = -1;
}
- else objectAddRow = int (event->y) * (restriction_no_right_turn / perRow
- + 2) / draw->allocation.height * perRow;
+ else objectAddRow = y * (restriction_no_right_turn / perRow + 2) /
+ height * perRow;
}
- else if (event->x > w - ButtonSize * 20 && b <
+ else if (x > w - ButtonSize * 20 && b <
(Layout >
(MenuKey == 0 || option != mapMode ? 0 : 1) ? 3 : 0)) HitButton (b);
else if (option == optionMode) {
- if (isDrag) {
- listYOffset = max (0, listYOffset + (int)lrint (firstDrag[1]-event->y));
- }
- else {
+ if (1) {
for (int best = 9999, i = 0; i < mapMode; i++) {
- int d = lrint (fabs (ListXY (i, FALSE) - event->x) +
- fabs (ListXY (i, TRUE) - event->y));
+ int d = lrint (fabs (double(ListXY (i, FALSE) - x)) +
+ fabs (double(ListXY (i, TRUE) - y)));
if (d < best) {
best = d;
option = i;
@@ -1517,6 +1787,7 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
char lstr[200];
int zl = 0;
while (zl < 32 && (zoom >> zl)) zl++;
+ setlocale (LC_NUMERIC, "C");
sprintf (lstr,
option == ViewOSMNum ? "%sopenstreetmap.org/?lat=%.5lf&lon=%.5lf&zoom=%d%s" :
option == EditInPotlatchNum ? "%sopenstreetmap.org/edit?lat=%.5lf&lon=%.5lf&zoom=%d%s" :
@@ -1563,7 +1834,7 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
option = mapMode;
}
#else
- #ifndef _WIN32_WCE
+ #if defined (_WIN32) && !defined (_WIN32_WCE)
else if (option == UpdateMapNum) {
struct stat s;
if (currentBbox[0] == '\0') {
@@ -1591,8 +1862,8 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
}
}
else if (option == searchMode) {
- int row = event->y / SearchSpacing;
- if (!HandleKeyboard (event) && row < searchCnt && gosmSstr[row]) {
+ int row = y / SearchSpacing;
+ if (!HandleKeyboard (TRUE, x, y) && row < searchCnt && gosmSstr[row]) {
SetLocation (gosmSway[row]->clon, gosmSway[row]->clat);
zoom = gosmSway[row]->dlat + gosmSway[row]->dlon + (1 << 15);
if (zoom <= (1 << 15)) zoom = Style (gosmSway[row])->scaleMax;
@@ -1609,16 +1880,12 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
return RouteTest (NULL /*widget*/, event, NULL /*para*/);
}
#endif
- int perpixel = zoom / w, dx = event->x - w / 2, dy = h / 2 - event->y;
- if (isDrag) {
- dx = firstDrag[0] - event->x;
- dy = event->y - firstDrag[1];
- }
+ int perpixel = zoom / w, dx = x - w / 2, dy = h / 2 - y;
int lon = clon + lrint (perpixel *
(cosAzimuth * (Display3D ? 0 : dx) - sinAzimuth * dy));
int lat = clat + lrint (perpixel *
(cosAzimuth * dy + sinAzimuth * (Display3D ? 0 : dx)));
- if (event->button == 1) {
+ if (button == 1) {
if (Display3D) {
double newa = atan2 (sinAzimuth, cosAzimuth) - dx * M_PI / 580;
cosAzimuth = cos (newa);
@@ -1626,7 +1893,7 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
}
SetLocation (lon, lat);
- #ifdef NOGTK
+ #ifdef _WIN32
if (AddWayOrNode && newWays[newWayCnt].cnt < NEWWAY_MAX_COORD) {
newWays[newWayCnt].coord[newWays[newWayCnt].cnt][0] = clon;
newWays[newWayCnt].coord[newWays[newWayCnt].cnt++][1] = clat;
@@ -1635,7 +1902,7 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (followGPSr), FALSE);
FollowGPSr = 0;
}
- else if (event->button == 2) {
+ else if (button == 2) {
flon = lon;
flat = lat;
GosmFreeRoute ();
@@ -1647,21 +1914,13 @@ int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
CallRoute (TRUE, 0, 0);
}
}
- firstDrag[0] = -1;
- lastRelease = event->time;
- gtk_widget_queue_clear (draw);
return FALSE;
}
-
-#if 0 //ifdef CHILDREN
-struct childStruct {
- int minlon, minlat, maxlon, maxlat, z;
- int pipe[2];
-} child[70];
#endif
+
#define STATEINFO OPTIONS o (clat, 0, 0) o (clon, 0, 0) \
o (sinAzimuth, 0, 0) o (cosAzimuth, 0, 0) o (zoom, 0, 0) o (option, 0, 0) \
- o (draw->allocation.width, 0, 0) o (draw->allocation.height, 0, 0)
+ o (width, 0, 0) o (height, 0, 0)
#define o(x,min,max) sizeof (x) +
static const size_t stateSize = STATEINFO 0;
#undef o
@@ -1693,12 +1952,12 @@ void Draw3DLine (int sx, int sy, int dx, int dy)
if (Display3D) {
if (sy < 0) {
if (dy < 0) return;
- sx = dx + (dx - sx) * (/*clip.height*/ 1024 - dy) / (dy - sy);
- sy = /*clip.height*/ 1024;
+ sx = dx + (dx - sx) * (/*height*/ 1024 - dy) / (dy - sy);
+ sy = /*height*/ 1024;
}
else if (dy < 0) {
- dx = sx + (sx - dx) * (/*clip.height*/ 1024 - sy) / (sy - dy);
- dy = /*clip.height*/ 1024;
+ dx = sx + (sx - dx) * (/*height*/ 1024 - sy) / (sy - dy);
+ dy = /*height*/ 1024;
}
}
gdk_draw_line (draw->window, mygc, sx, sy, dx, dy);
@@ -1721,13 +1980,13 @@ int TestOrSet (int *bits, int set, int x0, int y0, int ax, int ay,
bx = nx;
by = ny;
}
- if (y0 < 0 || y0 + ay + by > draw->allocation.height ||
- x0 + ax < 0 || x0 + bx > draw->allocation.width) return TRUE;
+ if (y0 < 0 || y0 + ay + by > height ||
+ x0 + ax < 0 || x0 + bx > width) return TRUE;
// Do not place anything offscreen.
const int shf = 9;
x0 <<= shf;
int x1 = x0, d0 = (ax << shf) / (ay + 1), d1 = (bx << shf) / (by + 1);
- int bpr = (draw->allocation.width + 31) / 32;
+ int bpr = (width + 31) / 32;
bits += bpr * y0;
for (int cnt = ay + by; cnt > 0; cnt--) {
x0 += d0;
@@ -1773,20 +2032,20 @@ void ConsiderText (queue<linePtType> *q, int finish, int len, int *best,
int dx = q->back ().x - q->front ().x, dy = q->back ().y - q->front ().y;
if (q->size () == 2) { // cumulative can't cope with clipping, so we
// only do it when we know detour will be 0
- for (int i = 0; i < 2; i++) {
- linePtType *f = !i ? &q->front () : &q->back ();
- if (f->x < 10 && dx != 0) clip[i] = max (clip[i], 256 * (10 - f->x) / (i ? -dx : dx));
+ LG for (int i = 0; i < 2; i++) {
+ LG linePtType *f = !i ? &q->front () : &q->back ();
+ LG if (f->x < 10 && dx != 0) clip[i] = max (clip[i], 256 * (10 - f->x) / (i ? -dx : dx));
if (f->y < 10 && dy != 0) clip[i] = max (clip[i], 256 * (10 - f->y) / (i ? -dy : dy));
- int r2x = f->x - draw->allocation.width + 10;
- if (r2x > 0 && dx != 0) clip[i] = max (clip[i], 256 * r2x / (i ? dx : -dx));
- int r2y = f->y - draw->allocation.height + 10;
+ int r2x = f->x - width + 10;
+ LG if (r2x > 0 && dx != 0) clip[i] = max (clip[i], 256 * r2x / (i ? dx : -dx));
+ int r2y = f->y - height + 10;
if (r2y > 0 && dy != 0) clip[i] = max (clip[i], 256 * r2y / (i ? dy : -dy));
}
}
int dst = isqrt (Sqr (dx) + Sqr (dy)) * (256 - clip[0] - clip[1]) / 256;
int detour = q->size () == 2 ? 0 : q->back ().cumulative - q->front ().cumulative - dst;
if (detour <= *best) {
- if (dst * DetailLevel > len * 14) {
+ LG if (dst * DetailLevel > len * 14) {
t->x = q->front ().x + dx * clip[0] / 256;
t->y = q->front ().y + dy * clip[0] / 256;
t->x2 = q->back ().x - dx * clip[1] / 256;
@@ -1806,14 +2065,168 @@ int WaySizeCmp (ndType **a, ndType **b)
Way (*b)->dlat * (__int64) Way (*b)->dlon ? 1 : -1;
}
-#ifdef NOGTK
+vector<short> casingCmds;
+#define CASING_MAX 20
+static short casing[10 + CASING_MAX * 2];
+static int casingx, casingy, casingPts = 0;
+void MoveTo (int x, int y)
+{
+#ifdef ANDROID_NDK // OPENGL
+ if (casingPts) {
+ casing[6] = casing[4];
+ casing[7] = casing[5];
+ int i, circ = min ((abs(casing[2] - casing[6]) + abs (casing[3] - casing[7])) / 3, CASING_MAX);
+ for (i = 1; i < circ; i++) {
+ casing[i + i + 6] = casing[6] +
+ (casing[2] - casing[6]) * (1 - cos (i * M_PI / circ))/2 -
+ (casing[3] - casing[7]) * sin (i * M_PI / circ)/2;
+ casing[i + i + 7] = casing[7] +
+ (casing[3] - casing[7]) * (1 - cos (i * M_PI / circ))/2 +
+ (casing[2] - casing[6]) * sin (i * M_PI / circ)/2;
+ }
+ casing[i + i + 6] = casing[2];
+ casing[i + i + 7] = casing[3];
+ glVertexPointer (2, GL_SHORT, 0, casing + 6);
+ casingCmds.push_back (i + 1);
+ casingCmds.push_back (0); // pad
+ casingCmds.insert (casingCmds.end(), casing + 6, casing + 8 + i + i);
+ //if (vol) glDrawArrays (GL_TRIANGLE_FAN, 0, i + 1);
+ glDrawArrays (GL_LINE_STRIP, 0, i + 1);
+ }
+#endif
+ casingx = x;
+ casingy = y;
+ casingPts = 0;
+}
+
+void LineTo (int x, int y, int width)
+{
+#ifdef ANDROID_NDK // OPENGL
+ int d = sqrt (double((x - casingx) * (x - casingx) +
+ (y - casingy) * (y - casingy))), i;
+ casing[0] = casingx + (Display3D ? (y - casingy) * casingy * width / PIX45
+ : (y - casingy) * width) / (d + d);
+ casing[1] = casingy + (Display3D ? (casingx - x) * casingy * width / PIX45
+ : (casingx - x) * width) / (d + d);
+ casing[6] = casing[0] - (Display3D ? (y - casingy) * casingy * width / PIX45
+ : (y - casingy) * width) / d;
+ casing[7] = casing[1] - (Display3D ? (casingx - x) * casingy * width / PIX45
+ : (casingx - x) * width) / d;
+ if (!casingPts++) {
+ int circ = min ((abs(casing[0] - casing[6]) + abs (casing[1] - casing[7])) / 3, CASING_MAX);
+ for (i = 1; i < circ; i++) {
+ casing[i + i + 6] = casing[6] +
+ (casing[0] - casing[6]) * (1 - cos (i * M_PI / circ))/2 +
+ (casing[1] - casing[7]) * sin (i * M_PI / circ)/2;
+ casing[i + i + 7] = casing[7] +
+ (casing[1] - casing[7]) * (1 - cos (i * M_PI / circ))/2 -
+ (casing[0] - casing[6]) * sin (i * M_PI / circ)/2;
+ }
+ }
+ else {
+ memcpy (casing + 8, (casing[2] - casingx) * (casingx - x) >
+ (casing[3] - casingy) * (y - casingy) ? casing + 2 : casing + 4, sizeof (casing[2]) * 2);
+ i = 2;
+ }
+
+ casing[2] = x + (Display3D ? (y - casingy) * y * width / PIX45
+ : (y - casingy) * width) / (d + d);
+ casing[3] = y + (Display3D ? (casingx - x) * y * width / PIX45
+ : (casingx - x) * width) / (d + d);
+ casing[4] = casing[2] - (Display3D ? (y - casingy) * y * width / PIX45
+ : (y - casingy) * width) / d;
+ casing[5] = casing[3] - (Display3D ? (casingx - x) * y * width / PIX45
+ : (casingx - x) * width) / d;
+ glVertexPointer (2, GL_SHORT, 0, casing);
+ casingCmds.push_back (i + 3);
+ casingCmds.push_back (0); // pad
+ casingCmds.insert (casingCmds.end(), casing, casing + i + i + 6);
+ //if (vol) glDrawArrays (GL_TRIANGLE_FAN, 0, i + 3);
+ glDrawArrays (GL_LINE_LOOP, 0, i + 3);
+#else
+ if (width) {} // Suppress warning from compiler
+ gdk_draw_line (GDK_DRAWABLE (draw->window), mygc, casingx, casingy, x, y);
+#endif
+ casingx = x;
+ casingy = y;
+}
+
+void FinishCasing ()
+{
+ #ifdef ANDROID_NDK // OPENGL
+ MoveTo (0, 0); // Draw round ending for last line
+ glVertexPointer (2, GL_SHORT, 0, &casingCmds[0] + 2);
+ for (int i = 0; i < casingCmds.size ();
+ i += casingCmds[i] < 0 ? 4 : casingCmds[i] + casingCmds[i] + 2) {
+ #ifdef ANDROID_NDK // OPENGL ES
+ if (casingCmds[i] < 0) glColor4x (casingCmds[i + 1] * 0x101,
+ casingCmds[i + 2] * 0x101, casingCmds[i + 3] * 0x101, 0x10000);
+ #else
+ if (casingCmds[i] < 0) glColor3f (casingCmds[i + 1] / 255.0,
+ casingCmds[i + 2] / 255.0, casingCmds[i + 3] / 255.0);
+ #endif
+ else {
+ glVertexPointer (2, GL_SHORT, 0, &casingCmds[i] + 2);
+ glDrawArrays (GL_TRIANGLE_FAN, 0, casingCmds[i]);
+ }
+ }
+ casingCmds.clear();
+ #endif
+}
+
+inline void SetCasingColor (short r, short g, short b)
+{
+ MoveTo (0, 0); // Complete previous line in previous colour
+ casingCmds.push_back (-1);
+ casingCmds.push_back (r); casingCmds.push_back (g); casingCmds.push_back (b);
+}
+
+#if defined (ANDROID_NDK)
+extern "C" void Java_org_osmu_gosmore_MapRenderer_render (
+ JNIEnv* env, jobject thiz, jdouble lon, jdouble lat,
+ jint dir, jint _zoom, jboolean threeD, jboolean follow,
+ jint _width, jint _height)
+{
+ static int started = 0, icons /* Not used */;
+ LG width = _width;
+ height = _height;
+ Display3D = threeD;
+ clon = Longitude (lon);
+ clat = Latitude (lat);
+ FollowGPSr = follow;
+ sinAzimuth = sin (dir * (M_PI / 180.0));
+ cosAzimuth = cos (dir * (M_PI / 180.0));
+ zoom = _zoom;
+ if (!started) {
+ started = 1;
+ jclass cls=env->GetObjectClass(thiz);
+ //cls =(jclass)( env->NewGlobalRef(jcls) );
+ //cls = env->FindClass(
+ // "org/osmu/gosmore/MyClb");
+
+ LG drawTeks = env->GetMethodID(cls, "drawTeks", "(Ljava/lang/String;IIFF)V");
+ // env->ExceptionClear();
+ /* if (drawTeksod != 0)*/
+ // env->ExceptionClear();
+ }
+ glDisable(GL_BLEND);
+ if (currentBbox[0] != '\0' && hashTable[bucketsMin1] < 500000 &&
+ zoom < 100000000) {
+ int nn = clat > -(1<<24) && clat < (1<<24) &&
+ clon > -(1<<24) && clon < (1<<24);
+ jstring js = env->NewStringUTF (nn ? "No location." : "No map.");
+ env->CallVoidMethod (thiz, drawTeks, js, width / 2, height/3*2,
+ (float)0, (float)1);
+ js = env->NewStringUTF (nn ? "Please search or enable the GPS" :
+ "Please update the map.");
+ env->CallVoidMethod (thiz, drawTeks, js, width / 2, height/3*2 + 30,
+ (float)0, (float)1);
+ }
+#elif defined(NOGTK)
int DrawExpose (HPEN *pen, HBRUSH *brush)
{
- struct {
- int width, height;
- } clip;
-/* clip.width = GetSystemMetrics(SM_CXSCREEN);
- clip.height = GetSystemMetrics(SM_CYSCREEN); */
+ width = draw->allocation.width;
+ height = draw->allocation.height;
WCHAR wcTmp[70];
iconsgc = mygc;
@@ -1824,18 +2237,18 @@ int DrawExpose (HPEN *pen, HBRUSH *brush)
SelectObject (mygc, sysFont);
//SetBkMode (mygc, TRANSPARENT);
SelectObject (mygc, GetStockObject (BLACK_PEN));
- for (int y = 0, i = objectAddRow; y < draw->allocation.height;
+ for (int y = 0, i = objectAddRow; y < height;
y += ADD_HEIGHT) {
- //gdk_draw_line (draw->window, mygc, 0, y, draw->allocation.width, y);
+ //gdk_draw_line (draw->window, mygc, 0, y, width, y);
gdk_draw_line (draw->window, mygc,
- draw->allocation.width - ButtonSize * 20,
- draw->allocation.height * i / restriction_no_right_turn,
- draw->allocation.width,
- draw->allocation.height * i / restriction_no_right_turn);
+ width - ButtonSize * 20,
+ height * i / restriction_no_right_turn,
+ width,
+ height * i / restriction_no_right_turn);
RECT klip;
klip.bottom = y + ADD_HEIGHT;
klip.top = y;
- for (int x = 0; x < draw->allocation.width - ButtonSize * 20 -
+ for (int x = 0; x < width - ButtonSize * 20 -
ADD_WIDTH && i < restriction_no_right_turn; x += ADD_WIDTH, i++) {
int *icon = style[i].x + 4 * IconSet;
gdk_draw_drawable (draw->window, mygc, icons, icon[0], icon[1],
@@ -1867,6 +2280,8 @@ gint DrawExpose (void)
{
static GdkColor styleColour[2 << STYLE_BITS][2];
static GdkColor /*routeColour, validateColour,*/ resultArrowColour;
+ height = draw->allocation.height;
+ width = draw->allocation.width;
if (!mygc || !iconsgc) {
mygc = gdk_gc_new (draw->window);
fg_gc = gdk_gc_new (draw->window);
@@ -1898,41 +2313,14 @@ gint DrawExpose (void)
firstElemStyle + Background - (Background > 8 ? 8 : 0)][0]);
oldBackground = Background;
}
- #if 0 //ifdef CHILDREN
- if (1) {
- vector<char> msg;
- msg.resize (4 + 3 * sizeof (XID), 0); // Zero the header
- *(XID*)&msg[4] = GDK_WINDOW_XID (draw->window);
- *(XID*)&msg[4 + sizeof (XID)] = GDK_PIXMAP_XID (icons);
- *(XID*)&msg[4 + sizeof (XID) * 2] = GDK_PIXMAP_XID (mask);
- #define o(x,min,max) msg.resize (msg.size () + sizeof (x)); \
- memcpy (&msg[msg.size () - sizeof (x)], &x, sizeof (x));
- STATEINFO
- #undef o
- write (child[0].pipe[1], &msg[0], msg.size ());
- // Avoid flicker here : gtk_widget_set_double_buffered
- //sleep (1);
- read (child[0].pipe[0], &msg[0], 4);
- /* Wait for finish to prevent queuing too many requests */
- return FALSE;
- }
- #endif
GdkRectangle r =
- { 0, 0, draw->allocation.width, draw->allocation.height };
+ { 0, 0, width, height };
gdk_window_begin_paint_rect (draw->window, &r);
-// gdk_gc_set_clip_rectangle (mygc, &clip);
// gdk_gc_set_foreground (mygc, &styleColour[0][0]);
// gdk_gc_set_line_attributes (mygc,
// 1, GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
-// clip.width = draw->allocation.width - ZOOM_PAD_SIZE;
-// gdk_gc_set_clip_rectangle (mygc, &clip);
-
- GdkRectangle clip;
- clip.x = 0;
- clip.y = 0;
-
PangoMatrix mat = PANGO_MATRIX_INIT;
pc = gdk_pango_context_get_for_screen (gdk_screen_get_default ());
pl = pango_layout_new (pc);
@@ -1950,73 +2338,35 @@ gint DrawExpose (void)
pango_layout_set_attributes (pl, list);
pango_attr_list_unref (list); */
#endif // GTK
- if (option == mapMode) ChangePak (NULL, clon, clat);
+ LG if (option == mapMode) ChangePak (NULL, clon, clat);
// This call can be almost anywhere, e.g. SetLocation(). Calling it in
// searchMode with GeoSearch may invalidate some of the results.
- clip.height = draw->allocation.height;
- clip.width = draw->allocation.width;
-
if (ButtonSize <= 0) ButtonSize = 4;
if (zoom < 0 || zoom > 1023456789) zoom = 1023456789;
- if (zoom / clip.width <= 1) zoom += 4000;
- int cosa = lrint (4294967296.0 * cosAzimuth * clip.width / zoom);
- int sina = lrint (4294967296.0 * sinAzimuth * clip.width / zoom);
- int xadj =
- clip.width / 2 - ((clon * (__int64) cosa + clat * (__int64) sina) >> 32);
- __int64 yadj =
- clip.height / 2 - ((clon * (__int64) sina - clat * (__int64) cosa) >> 32);
-
- #define FAR3D 100000 // 3D view has a limit of roughly 5 km forwards
- #define WIDE3D 100000 // and roughly 5km between top left & top right corner
- #define CAMERA2C 20000 // How far the camera is behind the user (clat/lon)
- #define HEIGHT 12000 // Height of the camera
- #define PIX45 256 // Y value corresponding to 45 degrees down
- #define XFix PIX45
-
- #define MUL 64
- if (Display3D) {
+ if (zoom / width <= 1) zoom += 4000;
+
+ LG cosa = lrint (4294967296.0 * cosAzimuth * width / zoom);
+ sina = lrint (4294967296.0 * sinAzimuth * width / zoom);
+ xadj =
+ width / 2 - ((clon * (__int64) cosa + clat * (__int64) sina) >> 32);
+ yadj =
+ height / 2 - ((clon * (__int64) sina - clat * (__int64) cosa) >> 32);
+
+ LG if (Display3D) {
cosa = lrint (cosAzimuth * MUL);
sina = lrint (sinAzimuth * MUL);
-
- #define myint int
- /* The 3D computations can all be done in signed 32 bits integers,
- provided overflow bits are simply discarded. The C specification says
- however that ints that overflow are undefined (as well as any
- expression that touches them). So if the 3D display looks garbled
- under a new compiler, try running with #define myint __int64
- */
-
+
yadj = (clon + (int)(sinAzimuth * CAMERA2C)) * (myint) sina -
(clat - (int)(cosAzimuth * CAMERA2C)) * (myint) cosa;
xadj = -(clon + (int)(sinAzimuth * CAMERA2C)) * (myint) cosa -
(clat - (int)(cosAzimuth * CAMERA2C)) * (myint) sina;
}
- #define Depth(lon,lat) \
- (int)(yadj + (lat) * (myint) cosa - (lon) * (myint) sina)
- #define X1(lon,lat) \
- (int)(xadj + (lon) * (myint) cosa + (lat) * (myint) sina)
- #define AdjDepth(lon,lat) (Depth (lon, lat) < PIX45 * HEIGHT * MUL / 5000 \
- && Depth (lon, lat) > -PIX45 * HEIGHT * MUL / 5000 ? \
- PIX45 * HEIGHT * MUL / 5000 : Depth (lon, lat))
- #define Y(lon,lat) (Display3D ? PIX45 * HEIGHT * MUL / AdjDepth (lon, lat) \
- : yadj + (int)(((lon) * (__int64) sina - (lat) * (__int64) cosa) >> 32))
- #define X(lon,lat) (Display3D ? clip.width / 2 + \
- ((AdjDepth (lon, lat) > 0 ? 1 : -1) * \
- (X1 (lon, lat) / 32000 - AdjDepth (lon, lat) / XFix) > 0 ? 32000 : \
- (AdjDepth (lon, lat) > 0 ? 1 : -1) * \
- (X1 (lon, lat) / 32000 + AdjDepth (lon, lat) / XFix) < 0 ? -32000 : \
- X1(lon,lat) / (AdjDepth (lon, lat) / XFix)) \
- : xadj + (int)(((lon) * (__int64) cosa + (lat) * (__int64) sina) >> 32))
-
- /* These macros calling macros may result in very long bloated code and
- inefficient machine code, depending on how well the compiler optimizes.
- */
if (option == mapMode) {
-// int perpixel = zoom / clip.width;
- int *block = (int*) calloc ((clip.width + 31) / 32 * 4, clip.height);
+// int perpixel = zoom / width;
+ int *block = (int*) calloc ((width + 31) / 32 * 4, height);
stack<text2Brendered> text2B;
text2B.push (text2Brendered ()); // Always have a spare one open
@@ -2028,11 +2378,11 @@ gint DrawExpose (void)
for (int i = 0; i < 2; i++) {
for (int m = -20; m <= 20; m += 40) {
text2B.top ().s = m < 0 ? (i ? "N" : "W") : i ? "S" : "E";
- text2B.top ().x = clip.width - 40 +
+ text2B.top ().x = width - 40 +
lrint ((i ? -sinAzimuth : cosAzimuth) * m) - 50;
text2B.top ().x2 = text2B.top ().x + 100;
text2B.top ().dst = 100;
- text2B.top ().y2 = text2B.top ().y = clip.height - 40 +
+ text2B.top ().y2 = text2B.top ().y = height - 40 +
lrint ((i ? cosAzimuth : sinAzimuth) * m);
text2B.push (text2Brendered ());
}
@@ -2050,7 +2400,7 @@ gint DrawExpose (void)
for (int wc = -1; wc <= 1; wc += 2) { // width and
for (int hc = -1; hc <= 1; hc += 2) { // height coefficients
int w = !Display3D ? zoom : hc > 0 ? WIDE3D : 0, h = !Display3D
- ? zoom / clip.width * clip.height : hc > 0 ? FAR3D : CAMERA2C;
+ ? zoom / width * height : hc > 0 ? FAR3D : CAMERA2C;
int lon = lrint (w * cosAzimuth * wc - h * sinAzimuth * hc);
int lat = lrint (h * cosAzimuth * hc + w * sinAzimuth * wc);
lonRadius[0] = min (lonRadius[0], lon);
@@ -2059,16 +2409,16 @@ gint DrawExpose (void)
latRadius[1] = max (latRadius[1], lat);
}
}
- OsmItr itr (clon + lonRadius[0] - 1000, clat + latRadius[0] - 1000,
+ LG OsmItr itr (clon + lonRadius[0] - 1000, clat + latRadius[0] - 1000,
clon + lonRadius[1] + 1000, clat + latRadius[1] + 1000);
// Widen this a bit so that we render nodes that are just a bit offscreen ?
while (Next (itr)) {
ndType *nd = itr.nd[0];
wayType *w = Way (nd);
- if (Style (w)->scaleMax < zoom / clip.width * 350 / (DetailLevel + 6)
- && !Display3D && w->dlat < zoom / clip.width * 20 &&
- w->dlon < zoom / clip.width * 20) continue;
+ if (Style (w)->scaleMax < zoom / width * 350 / (DetailLevel + 6)
+ && !Display3D && w->dlat < zoom / width * 20 &&
+ w->dlon < zoom / width * 20) continue;
// With 3D, the icons are filtered only much later when we know z.
if (nd->other[0] != 0) {
nd = itr.nd[0] + itr.nd[0]->other[0];
@@ -2078,45 +2428,52 @@ gint DrawExpose (void)
} // Only process this way when the Itr gives us the first node, or
// the first node that's inside the viewing area
if (nd->other[0] == 0 && nd->other[1] == 0) dlist[11].push (nd);
- else if (Style (w)->areaColour != -1) area.push_back (nd);
+ else if (Style (w)->areaColour != -1 ||
+ StyleNr(w) == natural_coastline) area.push_back (nd);
+ // I guess polygons that enter the bbox multiple times are drawn
+ // multiple times.
else dlist[Layer (w) + 5].push (nd);
}
- qsort (&area[0], area.size (), sizeof (area[0]),
+ LG qsort (&area[0], area.size (), sizeof (area[0]),
(int (*)(const void *a, const void *b))WaySizeCmp);
//for (; !dlist[0].empty (); dlist[0].pop ()) {
// ndType *nd = dlist[0].top ();
+ vector<PolygonEdge> coast;
+ vector<FixedPoint*> cpiece;
for (; !area.empty(); area.pop_back ()) {
ndType *nd = area.back ();
wayType *w = Way (nd);
- while (nd->other[0] != 0) nd += nd->other[0];
- #if defined (_WIN32_CE) || defined (NOGTK)
+ if (StyleNr(w) != natural_coastline) {
+ while (nd->other[0] != 0) nd += nd->other[0];
+ }
+ #if defined (_WIN32_CE) || defined (_WIN32)
#define GdkPoint POINT
#endif
- vector<GdkPoint> pt;
+ vector<FixedPoint> pt;
int oldx = 0, oldy = 0, x = 0 /* Shut up gcc*/, y = 0 /*Shut up gcc*/;
int firstx = INT_MIN, firsty = INT_MIN /* Shut up gcc */;
- for (; nd->other[1] != 0; nd += nd->other[1]) {
+ for (; ; nd += nd->other[1]) {
if (nd->lat != INT_MIN) {
- pt.push_back (GdkPoint ());
- pt.back ().x = x = X (nd->lon, nd->lat);
- pt.back ().y = y = Y (nd->lon, nd->lat);
+ pt.push_back (FixedPoint ());
+ pt.back ().x = x = X2 (nd->lon, nd->lat);
+ pt.back ().y = y = Y2 (nd->lon, nd->lat);
if (Display3D) {
if (firstx == INT_MIN) {
firstx = x;
firsty = y;
}
if (y > 0 && oldy < 0) {
- pt.back ().x = x + (x - oldx) * (1024 - y) / (y - oldy);
- pt.back ().y = 1024; // Insert modified instance of old point
- pt.push_back (GdkPoint ());
+ pt.back ().x = x + (x - oldx) * __int64((1<<26) - y) / (y - oldy);
+ pt.back ().y = 1<<26; // Insert modified instance of old point
+ pt.push_back (FixedPoint ());
pt.back ().x = x; // before current point.
pt.back ().y = y;
}
else if (y < 0) {
if (oldy < 0) pt.pop_back ();
else {
- pt.back ().x = oldx + (oldx - x) * (1024 - oldy) / (oldy - y);
- pt.back ().y = 1024;
+ pt.back ().x = oldx + (oldx - x) * __int64((1<<26) - oldy) / (oldy - y);
+ pt.back ().y = 1<<26;
}
}
oldx = x;
@@ -2125,67 +2482,119 @@ gint DrawExpose (void)
//pt[pts].x = X (nd->lon, nd->lat);
//pt[pts++].y = Y (nd->lon, nd->lat);
}
+ if (!nd->other[1]) break;
}
if (Display3D && y < 0 && firsty > 0) {
- pt.push_back (GdkPoint ());
- pt.back ().x = firstx + (firstx - x) * (1024 - firsty) / (firsty - y);
- pt.back ().y = 1024;
+ pt.push_back (FixedPoint ());
+ pt.back ().x = firstx + (firstx - x) * __int64((1<<26) - firsty) / (firsty - y);
+ pt.back ().y = 1<<26;
}
if (Display3D && firsty < 0 && y > 0) {
- pt.push_back (GdkPoint ());
- pt.back ().x = x + (x - firstx) * (1024 - y) / (y - firsty);
- pt.back ().y = 1024;
+ pt.push_back (FixedPoint ());
+ pt.back ().x = x + (x - firstx) * __int64((1<<26) - y) / (y - firsty);
+ pt.back ().y = 1<<26;
}
if (!pt.empty ()) {
- #ifdef NOGTK
- SelectObject (mygc, brush[StyleNr (w)]);
- SelectObject (mygc, pen[StyleNr (w)]);
- Polygon (mygc, &pt[0], pt.size ());
+ #if defined(ANDROID_NDK) || !defined(NOGTK)
+ if (StyleNr(w) == natural_coastline) {
+ cpiece.push_back ((FixedPoint*) malloc (pt.size() * sizeof (FixedPoint)));
+ memcpy (cpiece.back(), &pt[0], pt.size() * sizeof (FixedPoint));
+ AddClockwise (coast, cpiece.back(), pt.size());
+ }
+ else {
+ vector<PolygonEdge> pe;
+ AddPolygon (pe, &pt[0], pt.size ());
+ #ifdef ANDROID_NDK
+ #define glSColor(x) glColor4x ((x) >> 8, (x) & 0xffff, \
+ ((x) << 8)&0xffff, 0x10000)
+ glSColor (Style(w)->areaColour);
+ Fill (pe,FALSE);
+ #else
+ gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][0]);
+ Fill (pe, FALSE, draw->window, mygc);
+ #endif
+ /*if (pt.size () < 10) {
+ vector<PolygonEdge> pe2;
+ AddPolygon (pe2, &pt[0], pt.size ());
+ Fill (pe2,draw->window,mygc);
+ }*/
+ /*if (!Fill (pe)) {
+ __android_log_print (ANDROID_LOG_WARN, "Gosmore", "s %d", pt.size());
+ for (int m = 0; m < pt.size (); m++)
+ __android_log_print (ANDROID_LOG_WARN, "Gosmore", "%d %d", pt[m].x, pt[m].y);
+ }*/
+ // TODO: border
+ //glSColor ((Style(w)->areaColour >> 1) & 0xefefef);
+ //glLineWidth(1);
+ #elif defined(NOGTK)
+ if (StyleNr(w) != natural_coastline) {
+ SelectObject (mygc, brush[StyleNr (w)]);
+ SelectObject (mygc, pen[StyleNr (w)]);
+ Polygon (mygc, &pt[0], pt.size ());
#else
- gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][0]);
- gdk_draw_polygon (draw->window, mygc, TRUE, &pt[0], pt.size ());
- gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][1]);
- gdk_gc_set_line_attributes (mygc, Style (w)->lineWidth,
- Style (w)->dashed ? GDK_LINE_ON_OFF_DASH
- : GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
- gdk_draw_polygon (draw->window, mygc, FALSE, &pt[0], pt.size ());
+ if (StyleNr(w) != natural_coastline) {
+ gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][0]);
+ gdk_draw_polygon (draw->window, mygc, TRUE, &pt[0], pt.size ());
+ gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][1]);
+ gdk_gc_set_line_attributes (mygc, Style (w)->lineWidth,
+ Style (w)->dashed ? GDK_LINE_ON_OFF_DASH
+ : GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
+ gdk_draw_polygon (draw->window, mygc, FALSE, &pt[0], pt.size ());
#endif
- // Text placement: The basic idea is here : http://alienryderflex.com/polygon_fill/
- text2B.top ().dst = strcspn ((char*)(w + 1) + 1, "\n") * 9;
- text2B.top ().x = -1;
- for (unsigned i = 0; i < pt.size (); i++) {
- int iy = (pt[i].y + pt[i < pt.size () - 1 ? i + 1 : 0].y) / 2;
- // Look for a large horisontal space inside the poly at this y value
- vector<int> nx;
- for (unsigned j = 0, k = pt.size () - 1; j < pt.size (); j++) {
- if ((pt[j].y < iy && pt[k].y >= iy) || (pt[k].y < iy && pt[j].y >= iy)) {
- nx.push_back (pt[j].x + (pt[k].x - pt[j].x) * (iy - pt[j].y) /
- (pt[k].y - pt[j].y));
- }
- k = j;
+ // Text placement: The basic idea is here : http://alienryderflex.com/polygon_fill/
+ text2B.top ().dst = strcspn ((char*)(w + 1) + 1, "\n") * 9;
+ text2B.top ().x = -1;
+ for (unsigned i = 0; i < pt.size (); i++) {
+ pt[i].x >>= 16;
+ pt[i].y >>= 16;
}
- sort (nx.begin (), nx.end ());
- for (unsigned int j = 0; j < nx.size (); j += 2) {
- if (nx[j + 1] - nx[j] > text2B.top ().dst) {
- text2B.top ().x = nx[j];
- text2B.top ().x2 = nx[j + 1];
- text2B.top ().y = iy - 5;
- text2B.top ().dst = nx[j + 1] - nx[j];
+ for (unsigned i = 0; i < pt.size (); i++) {
+ int iy = (pt[i].y + pt[i < pt.size () - 1 ? i + 1 : 0].y) / 2;
+ // Look for a large horisontal space inside the poly at this y value
+ vector<int> nx;
+ for (unsigned j = 0, k = pt.size () - 1; j < pt.size (); j++) {
+ if ((pt[j].y < iy && pt[k].y >= iy) || (pt[k].y < iy && pt[j].y >= iy)) {
+ nx.push_back (pt[j].x + (pt[k].x - pt[j].x) * (iy - pt[j].y) /
+ (pt[k].y - pt[j].y));
+ }
+ k = j;
+ }
+ sort (nx.begin (), nx.end ());
+ for (unsigned int j = 0; j < nx.size (); j += 2) {
+ if (nx[j + 1] - nx[j] > text2B.top ().dst) {
+ text2B.top ().x = nx[j];
+ text2B.top ().x2 = nx[j + 1];
+ text2B.top ().y = iy - 5;
+ text2B.top ().dst = nx[j + 1] - nx[j];
+ }
}
}
- }
- if (text2B.top ().x >= 0) {
- text2B.top ().y2 = text2B.top ().y;
- text2B.top ().s = (char*)(w + 1) + 1;
- text2B.push (text2Brendered ());
- }
+ if (text2B.top ().x >= 0) {
+ text2B.top ().y2 = text2B.top ().y;
+ text2B.top ().s = (char*)(w + 1) + 1;
+ text2B.push (text2Brendered ());
+ }
+ } // If not a coastline
} // Polygon not empty
} // For each area
+ #ifdef ANDROID_NDK
+ glColor4x (0x8000, 0x8000, 0x10000, 0x10000);
+ LG Fill (coast, TRUE);
+ for (; cpiece.size () > 0; cpiece.pop_back()) free (cpiece.back());
+ glLineWidth (2);
+ #elif !defined (NOGTK)
+ gdk_gc_set_foreground (mygc, &styleColour[natural_coastline][1]);
+ Fill (coast, TRUE, draw->window,mygc);
+ for (; cpiece.size () > 0; cpiece.pop_back()) free (cpiece.back());
+ #endif
- queue<linePtType> q;
- for (int l = 0; l < 12; l++) {
- for (; !dlist[l].empty (); dlist[l].pop ()) {
+ LG queue<linePtType> q;
+ LG for (int l = 0; l < 12; l++) {
+ #ifdef ANDROID_NDK
+ glColor4x (0, 0, 0, 0x10000);
+ #endif
+ LG for (; !dlist[l].empty (); dlist[l].pop ()) {
ndType *nd = dlist[l].top ();
wayType *w = Way (nd);
@@ -2193,13 +2602,13 @@ gint DrawExpose (void)
int len = strcspn ((char *)(w + 1) + 1, "\n");
// single-point node
- if (nd->other[0] == 0 && nd->other[1] == 0) {
+ LG if (nd->other[0] == 0 && nd->other[1] == 0) {
int x = X (nd->lon, nd->lat), y = Y (nd->lon, nd->lat);
int *icon = Style (w)->x + 4 * IconSet, wd = icon[2], ht = icon[3];
if ((!Display3D || y > Style (w)->scaleMax / 400) && !TestOrSet (
block, FALSE, x - wd / 2, y - ht / 2, 0, ht, wd, 0)) {
TestOrSet (block, TRUE, x - wd / 2, y - ht / 2, 0, ht, wd, 0);
- DrawPoI (x, y, Style (w)->x + 4 * IconSet);
+ LG DrawPoI (x, y, Style (w)->x + 4 * IconSet);
#if 0 //def NOGTK
SelectObject (mygc, sysFont);
@@ -2219,7 +2628,7 @@ gint DrawExpose (void)
text2B.top ().y2 = text2B.top ().y = y +
Style (w)->x[IconSet * 4 + 3] / 2;
if (Sqr ((__int64) Style (w)->scaleMax / 2 /
- (zoom / clip.width)) * DetailLevel > len * len * 100 &&
+ (zoom / width)) * DetailLevel > len * len * 100 &&
len > 0) best = 0;
}
}
@@ -2227,7 +2636,7 @@ gint DrawExpose (void)
else if (nd->other[1] != 0) {
// perform validation (on non-areas)
bool valid;
- if (ValidateMode && Style(w)->areaColour == -1) {
+ LG if (ValidateMode && Style(w)->areaColour == -1) {
valid = len > 0 && StyleNr (w) != highway_road;
// most ways should have labels and they should not be
// highway=road
@@ -2250,10 +2659,13 @@ gint DrawExpose (void)
}
// two stages -> validate (if needed) then normal rendering
ndType *orig = nd;
- for (int stage = ( valid ? 1 : 0);stage<2;stage++) {
+ LG for (int stage = ( valid ? 1 : 0);stage<2;stage++) {
nd = orig;
if (stage==0) {
- #ifndef NOGTK
+ #ifdef ANDROID_NDK
+ glColor4x (0x10000, 0x999A, 0x999A, 0x1000);
+ glLineWidth(10);
+ #elif !defined(NOGTK)
gdk_gc_set_foreground (mygc,
&styleColour[firstElemStyle + ValidateModeNum][1]); //&validateColour);
gdk_gc_set_line_attributes (mygc, 10,
@@ -2264,7 +2676,12 @@ gint DrawExpose (void)
#endif
}
else if (stage == 1) {
- #ifndef NOGTK
+ #ifdef ANDROID_NDK
+ //glSColor (Style(w)->lineColour);
+ //glLineWidth(Style(w)->lineWidth);
+ SetCasingColor (Style(w)->lineColour >> 16,
+ (Style(w)->lineColour>>8)&0xff, Style(w)->lineColour & 0xff);
+ #elif !defined(NOGTK)
gdk_gc_set_foreground (mygc, &styleColour[Style (w) - style][1]);
gdk_gc_set_line_attributes (mygc, Style (w)->lineWidth,
Style (w)->dashed ? GDK_LINE_ON_OFF_DASH
@@ -2275,17 +2692,18 @@ gint DrawExpose (void)
}
int oldx = X (nd->lon, nd->lat), oldy = Y (nd->lon, nd->lat);
int cumulative = 0;
- q.push (linePtType (oldx, oldy, cumulative));
+ LG q.push (linePtType (oldx, oldy, cumulative));
+ MoveTo (oldx, oldy);
do {
ndType *next = nd + nd->other[1];
- if (next->lat == INT_MIN) break; // Node excluded from build
- int x = X (next->lon, next->lat), x2;
+ LG if (next->lat == INT_MIN) break; // Node excluded from build
+ LG int x = X (next->lon, next->lat), x2;
int y = Y (next->lon, next->lat), y2;
// printf ("%6.0lf %6.0lf - %6.0lf %6.0lf - %lf\n", x, y, oldx, oldy,
// AdjDepth (next->lon, next->lat));
- if ((x <= clip.width || oldx <= clip.width) &&
+ if ((x <= width || oldx <= width) &&
(x >= 0 || oldx >= 0) && (y >= 0 || oldy >= 0) &&
- (y <= clip.height || oldy <= clip.height)) {
+ (y <= height || oldy <= height)) {
// printf ("%4d %4d - %4d %4d\n", x,y,oldx,oldy);
/* If we're doing 3D and oldy is negative, it means the point
was behind the camera. Then we must draw an infinitely long
@@ -2301,9 +2719,10 @@ gint DrawExpose (void)
/* if (nx < 32760 && nx > -32760 &&
oldx < 32760 && oldx > -32760 &&
oldy < 32760 && oldy > -32760) */
- oldx = x + (x - oldx) * (clip.height + 10 - y) /
+ oldx = x + (x - oldx) * (height + 10 - y) /
(y - oldy);
- oldy = clip.height + 10;
+ oldy = height + 10;
+ MoveTo (oldx, oldy);
}
}
else /*if (oldy > 0 which is true)*/ {
@@ -2311,50 +2730,61 @@ gint DrawExpose (void)
oldx < 32760 && oldx > -32760 &&
oldy < 32760 && oldy > -32760) */
x2 = oldx +
- (oldx - x) * (clip.height + 10 - oldy) / (oldy - y);
- y2 = clip.height + 10;
+ (oldx - x) * (height + 10 - oldy) / (oldy - y);
+ y2 = height + 10;
}
- gdk_draw_line (draw->window, mygc, oldx, oldy, x2, y2);
+ #ifdef ANDROID_NDK
+ LineTo (x2, y2, Style(w)->lineWidth *
+ max (width * 1000 / zoom, 2));
+ #else
+ LG gdk_draw_line (draw->window, mygc, oldx, oldy, x2, y2);
+ #endif
// Draw3DLine
- if (oldx < 0 || oldx >= clip.width ||
- oldy < 0 || oldy >= clip.height) {
+ LG if (oldx < 0 || oldx >= width ||
+ oldy < 0 || oldy >= height) {
cumulative += 9999; // Insert a break in the queue
- q.push (linePtType (oldx, oldy, cumulative));
+ LG q.push (linePtType (oldx, oldy, cumulative));
// TODO: Interpolate the segment to get a point that is
// closer to the screen. The same applies to the other push
}
- cumulative += isqrt (Sqr (oldx - x2) + Sqr (oldy - y2));
- q.push (linePtType (x2, y2, cumulative));
- ConsiderText (&q, FALSE, len, &best, &text2B.top ());
+ LG cumulative += isqrt (Sqr (oldx - x2) + Sqr (oldy - y2));
+ LG q.push (linePtType (x2, y2, cumulative));
+ LG ConsiderText (&q, FALSE, len, &best, &text2B.top ());
}
- nd = next;
+ else MoveTo (x, y);
+ LG nd = next;
oldx = x;
oldy = y;
} while (itr.left <= nd->lon && nd->lon < itr.right &&
itr.top <= nd->lat && nd->lat < itr.bottom &&
nd->other[1] != 0);
- ConsiderText (&q, TRUE, len, &best, &text2B.top ());
+ LG ConsiderText (&q, TRUE, len, &best, &text2B.top ());
}
} /* If it has one or more segments */
- if (best < 30) {
+ LG if (best < 30) {
text2B.top ().s = (char *)(w + 1) + 1;
text2B.push (text2Brendered ());
}
} /* for each way / icon */
+ FinishCasing();
} // For each layer
// gdk_gc_set_foreground (draw->style->fg_gc[0], &highwayColour[rail]);
// gdk_gc_set_line_attributes (draw->style->fg_gc[0],
// 1, GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
// render route
- routeNodeType *rt;
+ LG routeNodeType *rt;
if (shortest && (rt = shortest->shortest)) {
double len;
int nodeCnt = 1, x = X (rt->nd->lon, rt->nd->lat);
int y = Y (rt->nd->lon, rt->nd->lat);
__int64 sumLat = rt->nd->lat;
- #ifndef NOGTK
+ #ifdef ANDROID_NDK
+ glSColor (style[firstElemStyle + StartRouteNum].lineColour);
+ glLineWidth (6);
+ #define CHARWIDTH 12
+ #elif !defined(NOGTK)
gdk_gc_set_foreground (mygc,
&styleColour[firstElemStyle + StartRouteNum][1]); //routeColour);
gdk_gc_set_line_attributes (mygc, 6,
@@ -2371,8 +2801,8 @@ gint DrawExpose (void)
for (; rt->shortest; rt = rt->shortest) {
int nx = X (rt->shortest->nd->lon, rt->shortest->nd->lat);
int ny = Y (rt->shortest->nd->lon, rt->shortest->nd->lat);
- if ((nx >= 0 || x >= 0) && (nx < clip.width || x < clip.width) &&
- (ny >= 0 || y >= 0) && (ny < clip.height || y < clip.height)) {
+ if ((nx >= 0 || x >= 0) && (nx < width || x < width) &&
+ (ny >= 0 || y >= 0) && (ny < height || y < height)) {
// Gdk looks only at the lower 16 bits ?
Draw3DLine (x, y, nx, ny);
}
@@ -2389,32 +2819,38 @@ gint DrawExpose (void)
char distStr[13];
sprintf (distStr, "%.3lf km", len * (20000 / 2147483648.0) *
cos (LatInverse (sumLat / nodeCnt) * (M_PI / 180)));
- DrawString (clip.width - CHARWIDTH * strlen (distStr), 10, distStr);
+ #ifdef ANDROID_NDK
+ jstring js = env->NewStringUTF (distStr);
+ env->CallVoidMethod (thiz, drawTeks, js, width -
+ CHARWIDTH/2 * strlen (distStr), 40, (float)0, (float)1);
+ #else
+ DrawString (width - CHARWIDTH * strlen (distStr), 10, distStr);
+ #endif
#if 0 //ndef NOGTK
gdk_draw_string (draw->window, f, fg_gc, //draw->style->fg_gc[0],
- clip.width - 7 * strlen (distStr), 10, distStr);
+ width - 7 * strlen (distStr), 10, distStr);
#else
#endif
}
- DrawPoI (X (flon, flat), Y (flon, flat), IconSet * 4 +
+ LG DrawPoI (X (flon, flat), Y (flon, flat), IconSet * 4 +
style[firstElemStyle + StartRouteNum].x);
- DrawPoI (X (tlon, tlat), Y (tlon, tlat), IconSet * 4 +
+ LG DrawPoI (X (tlon, tlat), Y (tlon, tlat), IconSet * 4 +
style[firstElemStyle + EndRouteNum].x);
#ifndef NOGTK
- for (deque<wayPointStruct>::iterator w = wayPoint.begin ();
+ LG for (deque<wayPointStruct>::iterator w = wayPoint.begin ();
w != wayPoint.end (); w++) {
DrawPoI (X (w->lon, w->lat), Y (w->lon, w->lat),
style[firstElemStyle + wayPointIconNum].x);
}
- for (int i = 1; shortest && ShowActiveRouteNodes && i < routeHeapSize; i++) {
+ LG for (int i = 1; shortest && ShowActiveRouteNodes && i < routeHeapSize; i++) {
gdk_draw_line (draw->window, mygc,
X (routeHeap[i].r->nd->lon, routeHeap[i].r->nd->lat) - 2,
Y (routeHeap[i].r->nd->lon, routeHeap[i].r->nd->lat),
X (routeHeap[i].r->nd->lon, routeHeap[i].r->nd->lat) + 2,
Y (routeHeap[i].r->nd->lon, routeHeap[i].r->nd->lat));
}
- #else
+ #elif defined (_WIN32)
for (int j = 0; j <= newWayCnt; j++) {
int x = X (newWays[j].coord[0][0], newWays[j].coord[0][1]);
int y = Y (newWays[j].coord[0][0], newWays[j].coord[0][1]);
@@ -2439,8 +2875,10 @@ gint DrawExpose (void)
}
}
#endif
- text2B.pop ();
- while (!text2B.empty ()) {
+ LG for (text2B.pop (); !text2B.empty (); text2B.pop ()) {
+ #ifndef ANDROID_NDK
+ if (pressTime != -1) continue; // Don't render text while dragging
+ #endif
text2Brendered *t = &text2B.top();
#ifdef PANGO_VERSION
PangoRectangle rect;
@@ -2449,7 +2887,7 @@ gint DrawExpose (void)
struct { double xx, xy, yy, yx; } mat;
#endif
int x0 = (t->x + t->x2) / 2, y0 = (t->y + t->y2) / 2;
- mat.yy = mat.xx = fabs (t->x - t->x2) / (double) t->dst;
+ mat.yy = mat.xx = fabs (double (t->x - t->x2)) / (double) t->dst;
mat.xy = (t->y - t->y2) / (double)(t->x > t->x2 ? -t->dst : t->dst);
mat.yx = -mat.xy;
@@ -2479,7 +2917,13 @@ gint DrawExpose (void)
lrint (mat.xy * (rect.height)), lrint (mat.xx * (rect.height)),
lrint (mat.xx * (rect.width + 10)),
lrint (mat.yx * (rect.width + 10)));
- #ifndef NOGTK
+ #ifdef ANDROID_NDK
+ jstring js = env->NewStringUTF (
+ string (txt, strcspn (txt, "\n")).c_str ());
+ env->CallVoidMethod (thiz, drawTeks, js, x0, y0,
+ (float)mat.xy, (float)mat.xx);
+
+ #elif !defined(NOGTK)
gdk_draw_layout (GDK_DRAWABLE (draw->window),
fg_gc /*draw->style->fg_gc[0]*/,
x0 - (rect.width * mat.xx + rect.height * fabs (mat.xy)) / 2,
@@ -2506,77 +2950,26 @@ gint DrawExpose (void)
SelectObject (mygc, oldf);
DeleteObject (customFont);
#endif
- if (zoom / clip.width > 20) break;
+ if (zoom / width > 20) break;
while (*txt != '\0' && *txt++ != '\n') {}
}
- text2B.pop ();
- }
- for (deque<tsItem>::iterator i = tsList.begin (); i != tsList.end (); i++) {
- int x, y, j;
- const char *p = i->cmd.c_str ();
- for (j = 0; j < 2; j++) {
- double coef = atof (p);
- p += strcspn (p, "whWH;");
- (j ? y : x) = lrint (*p == ';' ? coef : atoi (p + 1) +
- coef * (j ? draw->allocation.height : draw->allocation.width));
- while (*p != '\0' && *p++ != ';') {}
- //char *xs = i->cmd.c_str (), *ys = xs + strcspn (xs, ";");
- }
- #ifndef NOGTK
- gdk_draw_pixbuf (GDK_DRAWABLE (draw->window), fg_gc, i->pix, 0, 0, x, y,
- gdk_pixbuf_get_width (i->pix), gdk_pixbuf_get_height (i->pix), GDK_RGB_DITHER_NONE, 0, 0);
- #else
- #endif
}
free (block);
if (FollowGPSr && command[0] && command[0] == command[1] && command[0] == command[2]) {
- DrawPoI (draw->allocation.width / 2, draw->allocation.height / 6,
+ DrawPoI (width / 2, height / 6,
style[firstElemStyle + command[0]].x + 8); // Always square.big
}
} // Not in the menu
else if (option == searchMode) {
- for (int i = 0, y = SearchSpacing / 2; i < searchCnt && gosmSstr[i];
- i++, y += SearchSpacing) {
- DrawPoI (SearchSpacing / 2, y, Style (gosmSway[i])->x + 4 * IconSet);
-
- double dist = sqrt (Sqr ((__int64) clon - gosmSway[i]->clon) +
- Sqr ((__int64) clat - gosmSway[i]->clat)) * (20000 / 2147483648.0) *
- cos (LatInverse (clat) * (M_PI / 180));
- char distance[10]; // Formula inaccurate over long distances hence "Far"
- sprintf (distance, dist > 998 ? "Far" : dist > 1 ? "%.0lf km" :
- "%.0lf m", dist > 1 ? dist : dist * 1000);
- DrawString (SearchSpacing + 33 - 11 * strcspn (distance, " "), y - 10,
- distance); // Right adjustment is inaccurate
-
- #ifndef NOGTK
- gdk_gc_set_foreground (mygc, &resultArrowColour);
- gdk_gc_set_line_attributes (mygc, 1,
- GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
- #else
- SelectObject (mygc, GetStockObject (BLACK_PEN));
- #endif
- int x = SearchSpacing + 70;
- __int64 lx = X (gosmSway[i]->clon, gosmSway[i]->clat) - clip.width / 2;
- __int64 ly = Y (gosmSway[i]->clon, gosmSway[i]->clat) - clip.height / 2;
- double norm = lx || ly ? sqrt (lx * lx + ly * ly) / 64 : 1;
- int u = lrint (lx / norm), v = lrint (ly / norm);
- gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
- x - u / 8, y - v / 8);
- gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
- x + u / 12 + v / 20, y - u / 20 + v / 12);
- gdk_draw_line (draw->window, mygc, x + u / 8, y + v / 8,
- x + u / 12 - v / 20, y + u / 20 + v / 12);
-
- string s (gosmSstr[i], strcspn (gosmSstr[i], "\n"));
- char *name = (char *)(gosmSway[i] + 1) + 1;
- if (name != gosmSstr[i]) s += " (" +
- string (name, strcspn (name, "\n")) + ")";
- DrawString (SearchSpacing + x, y - 10, s.c_str ());
-
- gdk_draw_line (draw->window, mygc, 0, y + SearchSpacing / 2,
- clip.width, y + SearchSpacing / 2);
- }
- HandleKeyboard (NULL);
+ #ifndef NOGTK
+ gdk_gc_set_foreground (mygc, &resultArrowColour);
+ gdk_gc_set_line_attributes (mygc, 1,
+ GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
+ #elif defined (_WIN32)
+ SelectObject (mygc, GetStockObject (BLACK_PEN));
+ #endif
+ DisplaySearchResults ();
+ HandleKeyboard (FALSE, 0, 0);
}
else if (option == optionMode) {
for (int i = 0; i < wayPointIconNum; i++) {
@@ -2609,34 +3002,34 @@ gint DrawExpose (void)
OPTIONS
#undef o
0);
- DrawString (50, draw->allocation.height / 2, optStr);
+ DrawString (50, height / 2, optStr);
}
#ifndef NOGTK
/* Buttons now on the top row
gdk_draw_rectangle (draw->window, draw->style->bg_gc[0], TRUE,
- clip.width - ButtonSize * 20, clip.height - ButtonSize * 60,
- clip.width, clip.height);
+ width - ButtonSize * 20, height - ButtonSize * 60,
+ width, height);
for (int i = 0; i < 3; i++) {
gdk_draw_string (draw->window, f, draw->style->fg_gc[0],
- clip.width - ButtonSize * 10 - 5, clip.height + (f->ascent - f->descent)
+ width - ButtonSize * 10 - 5, height + (f->ascent - f->descent)
/ 2 - ButtonSize * (20 * i + 10), i == 0 ? "O" : i == 1 ? "-" : "+");
}
*/
gdk_window_end_paint (draw->window);
gdk_flush ();
#else
- #ifdef NOGTK
+ #ifdef WIN32
int i = (Layout > (MenuKey == 0 || option != mapMode ? 0 : 1) ? 3 : 0);
RECT r;
- r.left = clip.width - ButtonSize * 20;
- r.top = clip.height - ButtonSize * 20 * i;
- r.right = clip.width;
- r.bottom = clip.height;
+ r.left = width - ButtonSize * 20;
+ r.top = height - ButtonSize * 20 * i;
+ r.right = width;
+ r.bottom = height;
FillRect (mygc, &r, (HBRUSH) GetStockObject(LTGRAY_BRUSH));
SelectObject (mygc, sysFont);
//SetBkMode (mygc, TRANSPARENT);
while (--i >= 0) {
- ExtTextOut (mygc, clip.width - ButtonSize * 10 - 5, clip.height - 5 -
+ ExtTextOut (mygc, width - ButtonSize * 10 - 5, height - 5 -
ButtonSize * (20 * i + 10), 0, NULL, i == 0 ? TEXT ("O") :
i == 1 ? TEXT ("-") : TEXT ("+"), 1, NULL);
}
@@ -2645,11 +3038,12 @@ gint DrawExpose (void)
char coord[64];
if (ShowCoordinates == 1) {
if(GpsIdle==999)
- snprintf (coord, 63, "%9.5lf %10.5lf GPS OFF %s", LatInverse (clat), LonInverse (clon),routeSuccess?"Route":"No Route");
+ snprintf (coord, 63, "%9.5lf %10.5lf zoom=%d GPS OFF %s %sfollowing", LatInverse (clat), LonInverse (clon),zoom,routeSuccess?"Route":"No Route",FollowGPSr?"":"not ");
else
- snprintf (coord, 63, "%9.5lf %10.5lf GPS idle %ds %s", LatInverse (clat), LonInverse (clon),GpsIdle,routeSuccess?"Route":"No Route");
+ snprintf (coord, 63, "%9.5lf %10.5lf zoom=%d GPS idle %ds %s %sfollowing", LatInverse (clat), LonInverse (clon),zoom,GpsIdle,routeSuccess?"Route":"No Route",FollowGPSr?"":"not ");
DrawString (0, 5, coord);
}
+ #ifdef _WIN32
else if (ShowCoordinates == 2) {
MEMORYSTATUS memStat;
GlobalMemoryStatus (&memStat);
@@ -2658,19 +3052,31 @@ gint DrawExpose (void)
//ExtTextOut (mygc, 0, 10, 0, NULL, coord, 9, NULL);
}
#endif
+ #endif
#ifdef CAIRO_VERSION
// cairo_destroy (cai);
#endif
-/*
- clip.height = draw->allocation.height;
- gdk_gc_set_clip_rectangle (draw->style->fg_gc[0], &clip);
- gdk_draw_string (draw->window, f, draw->style->fg_gc[0],
- clip.width/2, clip.height - f->descent, "gosmore");
- */
+ #ifdef ANDROID_NDK
+ return;
+ #else
return FALSE;
+ #endif
}
#ifndef NOGTK
+gint Drag (GtkWidget * /*widget*/, GdkEventMotion *event, void * /*w_cur*/)
+{
+ if (event->state & GDK_BUTTON1_MASK) MouseEv
+ (event->x, event->y, event->time, 1, FALSE);
+ return TRUE;
+}
+
+int Click (GtkWidget * /*widget*/, GdkEventButton *event, void * /*para*/)
+{
+ MouseEv (event->x, event->y, event->time, event->button, TRUE);
+ return TRUE;
+}
+
GtkWidget *searchW;
int ToggleSearchResults (void)
@@ -2697,6 +3103,7 @@ void HitGtkButton (GtkWidget * /*w*/, void *data)
//------------------------------------------------------------------------
// Callbacks that are called with the user drops an icon and then binds it
+#if 0
static gboolean DropOnDraw (GtkWidget *w, GdkDragContext *c, gint /*x*/,
gint /* y */, guint time, gpointer)
{
@@ -2706,139 +3113,10 @@ static gboolean DropOnDraw (GtkWidget *w, GdkDragContext *c, gint /*x*/,
}
return c->targets ? TRUE : FALSE;
}
-
-static void ReadTsList (void)
-{
- FILE *fp = fopen ("main.ts", "r");
- gsize siz;
- for (; !tsList.empty (); tsList.pop_back()) g_object_unref (tsList.back().pix);
- while (fp && fread (&siz, sizeof (siz), 1, fp) == 1) {
- printf ("Reading %d\n", siz);
- void *buf = malloc (siz);
- fread (buf, siz, 1, fp);
- tsList.push_back (tsItem ());
- #ifndef NOGTK
- GInputStream *gis = g_memory_input_stream_new_from_data (buf, siz, NULL);
- GError *err = NULL;
- tsList.back ().pix = gdk_pixbuf_new_from_stream (gis, NULL, &err);
- #else
- tsList.back ().pix = CreateIconFromResource (buf, siz, TRUE, 0x30000);
- #endif
- int c;
- while ((c = fgetc (fp)) != '\0') tsList.back ().cmd += c;
- }
- if (fp) fclose (fp);
-}
-
-static void DropReceived (GtkWidget */*draw*/, GdkDragContext *c, gint x,
- gint y, GtkSelectionData *sdata, guint /*ttype*/, guint time, gpointer)
-{
- //FILE *fp;
- gchar **arr = sdata != NULL ? gtk_selection_data_get_uris (sdata) : NULL;
- gchar *f = arr ? g_filename_from_uri (arr[0], NULL, NULL) : NULL;
-// printf ("x%sx\n", f); //gtk_selection_data_get_text (sdata));
-// printf ("%p\n", gtk_selection_data_get_pixbuf (sdata));
-// if (sdata != NULL && sdata->length >= 7) printf ("%s\n----%s----\n", sdata->data,
-// string ((char*) sdata->data + 7, strcspn ((char*) sdata->data + 7, "\n\r")).c_str());
-
- GError *err = NULL;
- tsList.push_back (tsItem ());
- if ((f && (tsList.back ().pix = gdk_pixbuf_new_from_file (f, &err)))
- || (tsList.back ().pix = gtk_selection_data_get_pixbuf (sdata))) {
- //if (ttype == 0) printf ("Data=%s\n", sdata->data);
- printf ("C %p\n", tsList.back().pix);
- char a[40];
- if (draw->allocation.width <= x * 2) x -= draw->allocation.width;
- if (draw->allocation.height <= y * 2) y -= draw->allocation.height;
- sprintf (a, "%s %+d; %s %+d; ;", x < 0 ? "1.0 w" : "0.0 w", x,
- y < 0 ? "1.0 h" : "0.0 h", y);
- tsList.back ().cmd = string (a);
-
- GtkWidget *dialog, *dedit;
- dialog = gtk_dialog_new_with_buttons ("Set icon data", NULL, GTK_DIALOG_MODAL,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_DELETE, GTK_RESPONSE_NO,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- dedit = gtk_entry_new ();
- gtk_entry_set_text (GTK_ENTRY (dedit), tsList.back ().cmd.c_str ());
- gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dedit);
- gtk_widget_show_all (dialog);
- int result = gtk_dialog_run (GTK_DIALOG (dialog));
- if (result == GTK_RESPONSE_OK) {
- printf ("OK\n");
- tsList.back ().cmd = string (gtk_entry_get_text (GTK_ENTRY (dedit)));
- }
- else if (result == GTK_RESPONSE_NO) {
- printf ("Delete\n");
- tsList.pop_back ();
- }
- gtk_widget_destroy (dialog);
-
- FILE *fp = fopen ("main.ts", "w");
- for (deque<tsItem>::iterator i = tsList.begin (); i != tsList.end (); i++) {
- gsize siz;
- gchar *buf;
- printf ("%p %p\n", err, i->pix);
- gdk_pixbuf_save_to_buffer (i->pix, &buf, &siz, "ico", &err, NULL);
- printf ("Saving %u\n", siz);
- // gdk_pixbuf_new_from_buffer (
- fwrite (&siz, sizeof (siz), 1, fp);
- fwrite (buf, siz, 1, fp);
- fwrite (i->cmd.c_str (), i->cmd.length () + 1, 1, fp);
- }
- fclose (fp);
-
- #if 0
- //(fp = fopen (string ((char*) sdata->data + 7, strcspn ((char*) sdata->data + 7, "\n\r")).c_str(), "r"))) {
- png_structp pngp = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- printf ("%p\n", pngp);
- if (pngp) {
- png_infop infop = png_create_info_struct (pngp);
- printf ("i %p\n", infop);
- if (infop && !setjmp (png_jmpbuf (pngp))) {
- png_init_io (pngp, fp);
- png_read_png (pngp, infop, PNG_TRANSFORM_IDENTITY |
- PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |
- PNG_TRANSFORM_PACKSWAP /*| PNG_TRANSFORM_GRAY_TO_RGB Missing ?*/, NULL);
- png_bytep *row = png_get_rows(pngp, infop);
- printf ("%d %d %d\n", png_get_image_width (pngp, infop), png_get_image_height (pngp, infop),
- png_get_channels (pngp, infop));
- for (int i = 0; i < png_get_image_height (pngp, infop); i++) {
- for (int j = 0; j < png_get_image_width (pngp, infop); j++) {
- putchar (row[i][j * 4] & 128 ? '*' : ' ');
- }
- putchar ('\n');
- }
- }
- png_destroy_read_struct (&pngp, &infop, (png_infopp)NULL);
- }
- fclose (fp);
- #endif
- }
- else tsList.pop_back ();
- g_strfreev (arr);
- free (f);
- gtk_drag_finish (c, TRUE, FALSE, time);
-}
-
-void SeUpdate (GtkWidget *w, gpointer p)
-{
- GdkColor c;
- if (((intptr_t) p & 0xff) == 2) gtk_color_button_get_color (GTK_COLOR_BUTTON (w), &c);
- if (((intptr_t) p & 0xff) == 3) printf ("%s ", gtk_font_button_get_font_name (GTK_FONT_BUTTON (w)));
- if (((intptr_t) p & 0xff) == 4) printf ("%d ", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (w)));
- if (((intptr_t) p & 0xff) == 5) printf ("%d ", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
- printf ("%p | %4x %4x %4x\n", p, c.red, c.green, c.blue);
-}
-
-#endif // HEADLESS
-
-#if 0
-void SelectName (GtkWidget * /*w*/, int row, int /*column*/,
- GdkEventButton * /*ev*/, void * /*data*/)
-{
-}
#endif
+#endif // NOGTK
+
#endif // HEADLESS
inline void SerializeOptions (FILE *optFile, int r, const TCHAR *pakfile)
@@ -2923,7 +3201,7 @@ int UserInterface (int argc, char *argv[],
if (strcmp (pakfile, "nopak") == 0 && h) {
string ddir (string (h) + "/.gosmore");
mkdir (ddir.c_str (), 0755); // Usually already exists
- chdir (ddir.c_str ());
+ if (chdir (ddir.c_str ())) perror ("chdir(\".gosmore\")");
SerializeOptions (optFile, TRUE, NULL);
}
else SerializeOptions (optFile, TRUE, pakfile);
@@ -2994,7 +3272,8 @@ int UserInterface (int argc, char *argv[],
if (!f || (char*)-1L == (char*) (ld =
(ldCtrlType *) mmap (NULL, sizeof (*ld), PROT_READ | PROT_WRITE,
MAP_SHARED, fileno (f), 0))
- || lockf (F_LOCK, fileno (f), sizeof (*ld)) != 0) {
+ //|| lockf (F_LOCK, fileno (f), sizeof (*ld)) != 0) {
+ || lockf (fileno (f), F_LOCK, sizeof (*ld)) != 0) {
printf ("Content-Type: text/plain\n\r\n\rLd ctrl error%p %p %s\n\r",
f, ld, strerror (errno));
return 0;
@@ -3009,12 +3288,15 @@ int UserInterface (int argc, char *argv[],
gettimeofday (&ld->inst[myInst].start, &tz);
if (++ld->free >= MAX_INST) ld->free = 0;
UpdateLdCtrl (ld->free, calls, 0, 0, sysconf (_SC_NPROCESSORS_ONLN));
- lockf (F_ULOCK, fileno (f), sizeof (*ld));
+ //lockf (F_ULOCK, fileno (f), sizeof (*ld));
+ lockf (fileno (f), F_ULOCK, sizeof (*ld));
for (int i = 0; i < ld->inst[myInst].maks && RouteLoop (); i++) {}
- lockf (F_LOCK, fileno (f), sizeof (*ld));
+ //lockf (F_LOCK, fileno (f), sizeof (*ld));
+ lockf (fileno (f), F_LOCK, sizeof (*ld));
ld->inst[myInst].start.tv_sec = 0; // Mark that we're done.
UpdateLdCtrl (ld->free, calls, 0, 0, sysconf (_SC_NPROCESSORS_ONLN));
- lockf (F_ULOCK, fileno (f), sizeof (*ld));
+ //lockf (F_ULOCK, fileno (f), sizeof (*ld));
+ lockf (fileno (f), F_ULOCK, sizeof (*ld));
#else
while (RouteLoop ()) {}
/* It is reasonable to assume that there exists a short route in the actual
@@ -3038,29 +3320,57 @@ int UserInterface (int argc, char *argv[],
else {
if (!routeSuccess) printf ("Jump\n\r");
styleStruct *firstS = Style (Way (shortest->nd));
- double ups = lrint (3.6 / firstS->invSpeed[Vehicle]
- / firstS->aveSpeed[Vehicle] / (20000 / 2147483648.0) /
- cos (LatInverse (flat / 2 + tlat / 2) * (M_PI / 180)));
+ double ups = firstS->invSpeed[Vehicle] / 3.6
+ * firstS->aveSpeed[Vehicle] / 20000000 * 2147483648.0 /
+ cos (LatInverse (flat / 2 + tlat / 2) * (M_PI / 180));
// ups (Units per second) also works as an unsigned int.
-
+ double fSegLat = shortest->shortest ?
+ shortest->shortest->nd->lat - shortest->nd->lat : 1;
+ double fSegLon = shortest->shortest ?
+ shortest->shortest->nd->lon - shortest->nd->lon : 1;
+ double fpr = (fSegLat * (flat - shortest->nd->lat) +
+ fSegLon * (flon - shortest->nd->lon)) /
+ (Sqr (fSegLat) + Sqr (fSegLon));
+ fpr = fpr > 1 ? 1 : fpr < 0 ? 0 : fpr; // Clamp to [0,1]
for (; shortest; shortest = shortest->shortest) {
wayType *w = Way (shortest->nd);
char *name = (char*)(w + 1) + 1;
unsigned style= StyleNr(w);
- printf ("%lf,%lf,%c%s,%s,%.0lf,%.*s\n\r", LatInverse (shortest->nd->lat),
- LonInverse (shortest->nd->lon), JunctionType (shortest->nd),
+ printf ("%lf,%lf,%c%s,%s,%.0lf,%.*s\n\r",
+ LatInverse (shortest->nd->lat + fSegLat * fpr),
+ LonInverse (shortest->nd->lon + fSegLon * fpr), JunctionType (shortest->nd),
((1 << roundaboutR) & (Way (shortest->nd))->bits) ? "r" : "",
style < sizeof(klasTable)/sizeof(klasTable[0]) ? klasTable[style].desc :
"(unknown-style)", ((shortest->heapIdx < 0
? -shortest->heapIdx : routeHeap[shortest->heapIdx].best) -
shortest->remain) / ups,
(int) strcspn (name, "\n"), name);
+ fpr = 0;
+ if (!shortest->shortest) {
+ // I don't know why, but sometimes shortest->dir is wrong. But
+ // AFAIK it only happens at the first or last segment of the way,
+ // so inverting 'dir' solves the problem...
+ ndType *final = shortest->nd + shortest->nd->other[
+ (shortest->nd->other[shortest->dir] ? 0 : 1) ^ shortest->dir];
+ double pr = ((final->lat - shortest->nd->lat) * (double)
+ (tlat - shortest->nd->lat) + (final->lon - shortest->nd->lon) *
+ (double)(tlon - shortest->nd->lon)) /
+ (Sqr ((double)(final->lat - shortest->nd->lat)) +
+ Sqr ((double)(final->lon - shortest->nd->lon)) + 1);
+ pr = pr > 1 ? 1 : pr < 0 ? 0 : pr; // Clamp to [0,1]
+ printf("%lf,%lf,j,(unknown-style),0,fini\n\r",
+ LatInverse (shortest->nd->lat + pr * (final->lat - shortest->nd->lat)),
+ LonInverse (shortest->nd->lon + pr * (final->lon - shortest->nd->lon)));
+// shortest->dir, shortest->nd->other[shortest->dir]);
+// shortest->nd->other[1-shortest->dir]);
+ //final->lat - shortest->nd->lat, final->lon - shortest->nd->lon);
+ }
}
}
return 0;
}
- printf ("%s is in the public domain and comes without warranty\n",argv[0]);
+ printf ("%s is provided as is and any warranties are disclaimed. \n",argv[0]);
#ifndef HEADLESS
curl_global_init (CURL_GLOBAL_ALL);
@@ -3071,26 +3381,6 @@ int UserInterface (int argc, char *argv[],
#endif
draw = gtk_drawing_area_new ();
gtk_widget_set_double_buffered (draw, FALSE);
- #if 0 // ndef CHILDREN
- XID id[3];
- char sString[50];
- fread (sString, 4, 1, stdin);
- fread (id, sizeof (id), 1, stdin);
- draw->window = gdk_window_foreign_new (id[0]);
- icons = gdk_pixmap_foreign_new (id[1]);
- mask = gdk_pixmap_foreign_new (id[2]);
- for (;;) {
- #define o(x,min,max) if (fread (&x, sizeof (x), 1, stdin)) {};
- STATEINFO
- #undef o
- //fprintf (stderr, "%d %p | %p %p | %d %d -- %d %d\n", id[0], draw->window,
- // icons, mask, id[1], id[2], clon, clat);
- DrawExpose ();
- if (write (STDOUT_FILENO, sString, 4) != 4) exit (0);
- if (fread (sString, 4, 1, stdin) != 1) exit (0);
- fread (id, sizeof (id), 1, stdin); // Discard
- }
- #endif
gtk_signal_connect (GTK_OBJECT (draw), "expose_event",
(GtkSignalFunc) DrawExpose, NULL);
gtk_signal_connect (GTK_OBJECT (draw), "button-release-event",
@@ -3102,7 +3392,6 @@ int UserInterface (int argc, char *argv[],
gtk_signal_connect (GTK_OBJECT (draw), "scroll_event",
(GtkSignalFunc) Scroll, NULL);
-#if 0 // New UI editor code
static GtkTargetEntry drawDndTargets[] = {
{ (gchar*) "text/uri-list", 0, 0 },
{ (gchar*) "image/png", 0, 1 /* Will autodetect type on drop */ },
@@ -3111,10 +3400,9 @@ int UserInterface (int argc, char *argv[],
gtk_drag_dest_set (draw, GTK_DEST_DEFAULT_ALL /* GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT*/, drawDndTargets,
G_N_ELEMENTS (drawDndTargets), GDK_ACTION_COPY);
- g_signal_connect (draw, "drag-data-received", G_CALLBACK (DropReceived), NULL);
- g_signal_connect (draw, "drag-drop", G_CALLBACK (DropOnDraw), NULL);
- ReadTsList ();
-#endif
+// g_signal_connect (draw, "drag-data-received", G_CALLBACK (DropReceived), NULL);
+// g_signal_connect (draw, "drag-drop", G_CALLBACK (DropOnDraw), NULL);
+// ReadTsList ();
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "focus-in-event",
@@ -3269,30 +3557,13 @@ int UserInterface (int argc, char *argv[],
}
int main (int argc, char *argv[])
-{
- #if 0 // ifdef CHILDREN
- if (1) {
- int cmd[2], result[2];
- pipe (cmd);
- pipe (result);
- child[0].pipe[0] = result[0];
- child[0].pipe[1] = cmd[1];
- if (fork () == 0) {
- dup2 (cmd[0], STDIN_FILENO);
- dup2 (result[1], STDOUT_FILENO);
- execl ("./gosmore16", "./gosmore16", NULL);
- perror ("Starting slave process gosmore16");
- _exit (1);
- }
- }
- #endif
-
+{
int nextarg = 1;
bool rebuild = false;
const char* master = "";
int bbox[4] = { INT_MIN, INT_MIN, 0x7fffffff, 0x7fffffff };
- setlocale (LC_ALL, ""); /* Ensure decimal sign is "." for NMEA parsing. */
+ setlocale (LC_NUMERIC, "C"); /* Ensure decimal sign is "." for NMEA parsing. */
if (argc > 1 && stricmp (argv[1], "sortRelations") == 0) {
return SortRelations ();
@@ -3350,7 +3621,7 @@ int main (int argc, char *argv[])
// close the logfile if it has been opened. No. Rather let libc to it.
//if (logFP(false)) fclose(logFP(false));
}
-#else // NOGTK / WIN32 and WINCE Native;
+#elif _WIN32 // NOGTK / WIN32 and WINCE Native;
//-------------------------- WIN32 and WINCE Native ------------------
HANDLE port = INVALID_HANDLE_VALUE;
@@ -3570,7 +3841,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
} while (0);
break;
case WM_LBUTTONDOWN:
- pressTime = GetTickCount ();
+ //pressTime = GetTickCount ();
SetCapture (hWnd);
break;
case WM_LBUTTONUP:
@@ -3580,12 +3851,9 @@ LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
gDisplayOff = FALSE;
break;
}
- GdkEventButton ev;
- if ((ev.y = HIWORD (lParam) - topBar) > 0) {
- ev.x = LOWORD (lParam);
- ev.time = GetTickCount ();
- ev.button = 1;
- Click (NULL, &ev, NULL);
+ if (1) {
+ MouseEv ((short) LOWORD (lParam), (short) HIWORD (lParam) - topBar,
+ GetTickCount (), 1, TRUE);
if (option == LayoutNum) {
if (Keyboard) MoveWindow(hwndEdit, Layout > 1 ? 8 : 140,
Layout != 1 ? 5 : -25,
@@ -3602,11 +3870,15 @@ LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
else if (!Keyboard && LOWORD (lParam) > (Layout > 1 ? 8 : 140)) {
option = option == searchMode ? mapMode : searchMode;
}
- firstDrag[0] = -1;
- InvalidateRect (hWnd, NULL, FALSE);
+ InvalidateRect (hWnd, NULL, FALSE);
break;
case WM_MOUSEMOVE:
- if (wParam & MK_LBUTTON) {
+ if (wParam & MK_LBUTTON) {
+ MouseEv ((short) LOWORD (lParam), (short) HIWORD (lParam) - topBar,
+ GetTickCount (), 1, FALSE);
+ InvalidateRect (hWnd, NULL, FALSE);
+ }
+/* if (wParam & MK_LBUTTON) {
if (firstDrag[0] >= 0) {
HDC wdc = GetDC (hWnd);
int wadj = lastDrag[0] - LOWORD (lParam);
@@ -3620,7 +3892,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
lastDrag[0] = LOWORD (lParam);
lastDrag[1] = HIWORD (lParam) - topBar;
if (firstDrag[0] < 0) memcpy (firstDrag, lastDrag, sizeof (firstDrag));
- }
+ }*/
break;
case WM_MOUSEWHEEL:
do {
@@ -3856,7 +4128,7 @@ DWORD WINAPI NmeaReader (LPVOID lParam)
int now;
now=GetTickCount();
if(!lastgps) lastgps=now;
- GpsIdle=(lastgps-now)/1000;
+ GpsIdle=(now-lastgps)/1000;
lastgps=now;
PostMessage (mWnd, WM_USER + 1, 0, (int) /* intptr_t */ gpsNew);
}
@@ -3889,6 +4161,7 @@ void XmlOut (FILE *newWayFile, const char *k, const char *v)
}
}
+
extern "C" {
int WINAPI WinMain(
HINSTANCE hInstance, // handle of current instance
@@ -3911,6 +4184,20 @@ int WINAPI WinMain(
ConvertUTF16toUTF8 ((const UTF16 **) &sStart, sStart + wcslen (argv0),
&tStart, tStart + sizeof (docPrefix), lenientConversion);
*tStart = '\0';
+ #ifndef _WIN32_WCE
+ if (strncmp (lpszCmdLine, "rebuild", 7) == 0) {
+ int bbox[4] = { INT_MIN, INT_MIN, 0x7fffffff, 0x7fffffff };
+ _setmaxstdio (1024); // Try to prevent 'Too many open files'
+ RebuildPak("gosmore.pak", "elemstyles.xml", "icons.csv", "", bbox);
+ }
+ else if (lpszCmdLine[0] != '\0') {
+ chdir (docPrefix);
+ char cmdl[200];
+ sprintf (cmdl, "start cmd /C \"7z -so e %s | gosmore rebuild\"", lpszCmdLine);
+ system (cmdl);
+ return 0;
+ }
+ #endif
#if 0
GetModuleFileName (NULL, docPrefix, sizeof (docPrefix));
if (strrchr (docPrefix, '\\')) *strrchr (docPrefix, '\\') = '\0';
diff --git a/libgosm.cpp b/jni/libgosm.cpp
similarity index 90%
rename from libgosm.cpp
rename to jni/libgosm.cpp
index 0cfee84..00c6976 100755
--- a/libgosm.cpp
+++ b/jni/libgosm.cpp
@@ -15,6 +15,9 @@
#include <map>
#include <assert.h>
#include <float.h>
+#ifdef ANDROID_NDK
+#include <android/log.h>
+#endif
using namespace std;
#include "libgosm.h"
@@ -209,7 +212,7 @@ void GosmSearch (int clon, int clat, const char *key)
(unsigned) (clon + (clon & (1 << (bits + 16))) * 4 -
(2 << (bits + 16))) >> 16);
// Now we search through the 4 squares around (clat, clon)
- for (int mask = 0, maskI = 0; maskI < 4; mask += 0x55555555, maskI++) {
+ for (unsigned mask = 0; (mask & 7) != 4; mask += 0x55555555) {
int s = GosmIdxSearch (gosmData + idx[count + l],
(cz ^ (mask & swap)) & ~((4 << (bits << 1)) - 1)) - idx;
/* Print the square
@@ -363,8 +366,8 @@ routeNodeType *AddNd (ndType *nd, int dir, int cost, routeNodeType *newshort)
/* Will do later : routeHeap[routeHeapSize].r = n; */
n->heapIdx = routeHeapSize++;
n->dir = dir;
- n->remain = lrint (sqrt (Sqr ((__int64)(nd->lat - rlat)) +
- Sqr ((__int64)(nd->lon - rlon))));
+ n->remain = lrint (sqrt (double (Sqr ((__int64)(nd->lat - rlat)) +
+ Sqr ((__int64)(nd->lon - rlon)))));
if (!shortest || n->remain < shortest->remain) shortest = n;
ROUTE_SET_ADDND_COUNT (routeAddCnt + 1);
@@ -503,10 +506,23 @@ void Route (int recalculate, int plon, int plat, int _vehicle, int _fast)
// In particular, while gosmore is paused while a page is swapped in, the OS can
// zero some pages for us.
int dzero = open ("/dev/zero", O_RDWR);
+ #ifndef ANDROID_NDK
long long ds = sysconf (_SC_PAGESIZE) * (long long) sysconf (_SC_PHYS_PAGES) /
(sizeof (*routeHeap) + sizeof (*route) + 40);
+ #else
+ // sysconf(_SC_PHYS_PAGES) returned -3 on my Vodaphone 845
+ FILE *minfo = fopen ("/proc/meminfo", "r");
+ char meml[80];
+ while (fgets (meml, sizeof (meml)-1, minfo) && strncmp (meml,
+ "MemTotal:", 9)) {}
+ long long ds = (strncmp (meml, "MemTotal:", 9) ? 100000 :
+ atoi(meml + 9) - 28000) * (long long) 1000 /
+ (sizeof (*routeHeap) + sizeof (*route) + 40);
+ __android_log_print(ANDROID_LOG_DEBUG, "Gosmore", "re %d %d",
+ int(ds), sizeof (*routeHeap) + sizeof (*route) + 40);
+ #endif
dhashSize = ds > INT_MAX ? INT_MAX : ds;
- routeHeapMaxSize = lrint (sqrt (dhashSize)) * 3;
+ routeHeapMaxSize = lrint (sqrt ((double) dhashSize)) * 3;
routeHeap = (routeHeapType*) malloc (routeHeapMaxSize * sizeof (*routeHeap));
if (!routeHeap || dzero == -1 ||
(route = (routeNodeType*) mmap (NULL, dhashSize * sizeof (*route),
@@ -605,7 +621,7 @@ int RouteLoop (void)
int rootIsAdestination = Way (root->nd)->destination & (1 << Vehicle);
/* Now work through the segments connected to root. */
- unsigned layout[4] = { 0, 0, 0, 0 }, lmask = 1;
+ unsigned layout[4] = { 0, 0, 0, 0 }, lmask = 1, motorRoads = 0;
ndType *rtother = root->nd + root->nd->other[root->dir], *layoutNd[4];
// We categorize each segment leaving this junction according to the
// angle it form with the 'root' segment. The angles are 315 to 45,
@@ -622,6 +638,7 @@ int RouteLoop (void)
int azimuth = (dot > cross ? 0 : 3) ^ (dot + cross > 0 ? 0 : 1);
layout[azimuth] |= lmask << dir;
layoutNd[azimuth] = nd;
+ if ((Way (nd)->bits & (1 << motorcarR))) motorRoads++;
}
}
} while (++nd < ndBase + hashTable[bucketsMin1 + 1] &&
@@ -658,9 +675,9 @@ int RouteLoop (void)
wayType *w = Way (restrictItr);
if (StyleNr (w) >= restriction_no_right_turn &&
StyleNr (w) <= restriction_only_straight_on &&
- atoi ((char*)(w + 1) + 1) == nd->wayPtr &&
+ atol ((char*)(w + 1) + 1) == nd->wayPtr &&
(StyleNr (w) <= restriction_no_straight_on) ==
- (atoi (strchr ((char*)(w + 1) + 1, ' ')) == root->nd->wayPtr)) {
+ (atol (strchr ((char*)(w + 1) + 1, ' ')) == root->nd->wayPtr)) {
break;
}
}
@@ -708,19 +725,20 @@ int RouteLoop (void)
// you will probably have to wait for oncoming traffic.
}
- if (layout[1] && layout[3] && ((lmask << dir) & layout[0])) {
- // Straight over a T-junction
- if ((Way (layoutNd[1])->bits & (1 << motorcarR)) &&
- (Way (layoutNd[3])->bits & (1 << motorcarR)) && fast) {
- // And motorcars are allowed on both sides
- d += (Style (Way (layoutNd[1]))->invSpeed[motorcarR] <
- Style (w)->invSpeed[motorcarR] ? 10000 : 3000) *
- (fast ? Style (w)->invSpeed[Vehicle] : 1);
+ if (motorRoads > 2 && fast) d += 5000 * (motorRoads - 2) *
+ (fast ? Style (w)->invSpeed[Vehicle] : 1);
+ // T-junction 50m penalty. 4-way junction 100m penalty.
+
+ if (layout[1] && layout[3] && ((lmask << dir) & layout[0]) &&
+ Style (Way (layoutNd[1]))->invSpeed[bicycleR] > 1.4) {
+ // Straight over a 4 way junction and it is not preferred by
+ // cyclists. Then there is likely to be traffic that will delay us
+// d += (Style (Way (layoutNd[1]))->invSpeed[motorcarR] <
+// Style (w)->invSpeed[motorcarR] && ? 10000 : 3000) *
+// (fast ? Style (w)->invSpeed[Vehicle] : 1);
// Crossing a road that is faster that the road we are traveling
// on incurs a 100m penalty. If they are equal, the penality is
- // 30m. TODO: residential crossing residential should be less,
- // perhaps 20m.
- }
+ // 30m.
}
ndType *n2 = root->nd + root->nd->other[root->dir];
@@ -783,7 +801,7 @@ int GosmInit (void *d, long size)
{
if (!d) return FALSE;
gosmData = (char*) d;
- ndBase = (ndType *)(gosmData + ((int*)(gosmData + size))[-1]);
+ ndBase = (ndType *)(gosmData + ((unsigned*)(gosmData + size))[-1]);
bucketsMin1 = ((int *) (gosmData + size))[-2];
stylecount = ((int *) (gosmData + size))[-3];
style = (struct styleStruct *)
@@ -795,9 +813,7 @@ int GosmInit (void *d, long size)
return ndBase && hashTable && *(int*) gosmData == pakHead;
}
-// *** EVERYTHING AFTER THIS POINT IS NOT IN THE WINDOWS BUILDS ***
-
-#ifndef _WIN32
+#if !defined (_WIN32_WCE) && !defined (ANDROID_NDK)
void CalculateInvSpeeds (styleStruct *srec, int styleCnt)
{
@@ -845,17 +861,41 @@ void GosmLoadAltStyle(const char* elemstylefile, const char* iconscsvfile) {
/*--------------------------------- Rebuild code ---------------------------*/
// These defines are only used during rebuild
-#include <sys/mman.h>
#include <libxml/xmlreader.h>
+#ifndef _WIN32
+#include <sys/mman.h>
+#else
+#define PROT_READ 0x1 /* Page can be read. */
+#define PROT_WRITE 0x2 /* Page can be written. */
+#define MAP_SHARED 0x01 /* Share changes. */
+
+void *mmap (void *ptr, long size, long prot, long type, long handle, long offset)
+{
+ HANDLE file_h, map_h;
+
+ file_h = (HANDLE)_get_osfhandle(handle);
+ map_h = CreateFileMapping(file_h, 0, PAGE_READWRITE, 0, 0, 0);
+ if (!map_h) return (char *)(-1L);
+ ptr = (void *) MapViewOfFile(map_h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+ CloseHandle(map_h);
+ return ptr;
+}
+
+long munmap (void *ptr, long size)
+{
+ return UnmapViewOfFile (ptr) ? 0 : -1;
+}
+
+#endif
#define MAX_BUCKETS (1<<26)
#define IDXGROUPS 676
#define NGROUPS 60
-#define MAX_NODES 14000000 /* Max in a group */
#define S2GROUPS 129 // Last group is reserved for lowzoom halfSegs
-#define NGROUP(x) ((x) / MAX_NODES % NGROUPS + IDXGROUPS)
+#define NGROUP(x) ((x) / max_nodes % NGROUPS + IDXGROUPS)
#define S1GROUPS NGROUPS
-#define S1GROUP(x) ((x) / MAX_NODES % NGROUPS + IDXGROUPS + NGROUPS)
+#define S1GROUP(x) ((x) / max_nodes % NGROUPS + IDXGROUPS + NGROUPS)
#define S2GROUP(x) ((x) / (MAX_BUCKETS / (S2GROUPS - 1)) + IDXGROUPS + NGROUPS * 2)
#define PAIRS (16 * 1024 * 1024)
#define PAIRGROUPS 120
@@ -869,20 +909,29 @@ void GosmLoadAltStyle(const char* elemstylefile, const char* iconscsvfile) {
#define TO_HALFSEG -1 // Rebuild only
struct halfSegType { // Rebuild only
- int lon, lat, other, wayPtr;
+ int lon, lat, other;
+ unsigned wayPtr;
+};
+
+struct wayPartType { // Rebuild only
+ int other;
+ unsigned wayPtr;
+ long long id;
};
struct nodeType {
- int id, lon, lat;
+ long long id;
+ int lon, lat;
};
char *data;
+int max_nodes;
-inline nodeType *FindNode (nodeType *table, int id)
+inline nodeType *FindNode (nodeType *table, long long id)
{
unsigned hash = id;
for (;;) {
- nodeType *n = &table[hash % MAX_NODES];
+ nodeType *n = &table[hash % max_nodes];
if (n->id < 0 || n->id == id) return n;
hash = hash * (__int64) 1664525 + 1013904223;
}
@@ -948,7 +997,7 @@ int LoadElemstyles(/* in */ const char *elemstylesfname,
//------------------------- elemstyle.xml : --------------------------
int ruleCnt = 0, styleCnt = firstElemStyle;
// zero-out elemstyle-to-stylestruct mappings
- FILE *icons_csv = fopen (iconsfname, "r");
+ FILE *icons_csv = fopen (iconsfname, "rb");
xmlTextReaderPtr sXml = xmlNewTextReaderFilename (elemstylesfname);
if (!sXml || !icons_csv) {
fprintf (stderr, "Either icons.csv or elemstyles.xml not found\n");
@@ -1423,6 +1472,11 @@ deque<string> Osm2Gosmore (int /*id*/, k2vType &k2v, wayType &w,
s.aveSpeed[bicycleR] = 20;
// then we say cyclists will love it.
}
+ for (m = membership; m; m = Next (m)) {
+ if (Find (m, "route")) {
+ result.push_back (string (Find (m, "relation_id")) + '\n');
+ } // If it's a route add it's relation_id and index it.
+ }
if (isRelation && k2v["restriction"] && wayRole["from"] && wayRole["to"]) {
result.push_front (
@@ -1451,15 +1505,22 @@ deque<string> Osm2Gosmore (int /*id*/, k2vType &k2v, wayType &w,
}
}
// Now adjust for track type.
- if (k2v["tracktype"] && isdigit (k2v["tracktype"][5])) {
- s.aveSpeed[motorcarR] *= ('6' - k2v["tracktype"][5]) / 5.0;
- // Alternatively use ... (6 - atoi (k2v["tracktype"] + 5)) / 5.0;
- // TODO: Mooaar
+ if ((k2v["tracktype"] && isdigit (k2v["tracktype"][5])) ||
+ (k2v["highway"] && strcmp (k2v["highway"], "track") == 0)) {
+ // many tracks don't have a tracktype, assume them as rather slow
+ int tracktype = 2;
+ if (k2v["tracktype"] && isdigit (k2v["tracktype"][5]))
+ tracktype = atoi (k2v["tracktype"] + 5);
+ s.aveSpeed[motorcarR] *= (6 - tracktype) / 5.0;
+ if (tracktype >= 3) s.aveSpeed[bicycleR] *= (6 - tracktype) / 4.0;
+ if (tracktype == 5) s.aveSpeed[footR] *= 0.8;
}
if ((w.bits & (1 << onewayR)) && !(k2v["cycleway"] &&
(strcmp (k2v["cycleway"], "opposite_lane") == 0 ||
strcmp (k2v["cycleway"], "opposite_track") == 0 ||
- strcmp (k2v["cycleway"], "opposite") == 0))) {
+ strcmp (k2v["cycleway"], "opposite") == 0)) &&
+ !(k2v["oneway:bicycle"] && (strcmp (k2v["oneway:bicycle"], "0") == 0 ||
+ strcmp (k2v["oneway:bicycle"], "no") == 0))) {
// On oneway roads, cyclists are only allowed to go in the opposite
// direction, if the cycleway tag exist and starts with "opposite"
w.bits |= 1 << bicycleOneway;
@@ -1476,25 +1537,25 @@ deque<string> Osm2Gosmore (int /*id*/, k2vType &k2v, wayType &w,
ndType *LFollow (ndType *nd, ndType *ndItr, wayType *w, int forward)
{ // Helper function when a way is copied into lowzoom table.
if (forward) {
- nd += nd->other[1];
- if (nd->other[1]) return nd;
+ nd += nd->other[0];
+ if (nd->other[0]) return nd;
}
if (nd->lat == nd[1].lat && nd->lon == nd[1].lon) {
if ((nd->lat != nd[2].lat || nd->lon != nd[2].lon) &&
(nd->lat != nd[-1].lat || nd->lon != nd[-1].lon ||
// If there is a 3rd object there,
- (nd[-1].other[0] == 0 && nd[-1].other[0] == 0)) &&
+ (nd[-1].other[1] == 0 && nd[-1].other[1] == 0)) &&
// then it must be a node
- nd + 1 != ndItr && nd[1].other[!forward ? 1 : 0] == 0
+ nd + 1 != ndItr && nd[1].other[forward ? 1 : 0] == 0
// Must not loop back to start and must not be T juntion
&& StyleNr (w) == StyleNr ((wayType*)(data + nd[1].wayPtr))) nd++;
}
else if (nd->lat == nd[-1].lat && nd->lon == nd[-1].lon &&
(nd->lat != nd[-2].lat || nd->lon != nd[-2].lon ||
// If there is a 3rd object there,
- (nd[-2].other[0] == 0 && nd[-2].other[0] == 0)) &&
+ (nd[-2].other[1] == 0 && nd[-2].other[1] == 0)) &&
// then it must be a node
- nd - 1 != ndItr && nd[-1].other[!forward ? 1 : 0] == 0
+ nd - 1 != ndItr && nd[-1].other[forward ? 1 : 0] == 0
// Must not loop back to start and must not be T juntion
&& StyleNr (w) == StyleNr ((wayType*)(data + nd[-1].wayPtr))) nd--;
// If nd ends at a point where exactly two ways meet and they have the same
@@ -1510,10 +1571,10 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
int rebuildCnt = 0;
FILE *pak, *masterf;
- int ndStart;
+ unsigned ndStart;
wayType *master = NULL;
if (strcmp(masterpakfile,"")) {
- if (!(masterf = fopen64 (masterpakfile, "r")) ||
+ if (!(masterf = fopen64 (masterpakfile, "rb")) ||
fseek (masterf, -sizeof (ndStart), SEEK_END) != 0 ||
fread (&ndStart, sizeof (ndStart), 1, masterf) != 1 ||
(long)(master = (wayType *)mmap (NULL, ndStart, PROT_READ,
@@ -1524,31 +1585,33 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
}
}
- if (!(pak = fopen64 (pakfile, "w+"))) {
+ if (!(pak = fopen64 (pakfile, "w+b"))) {
fprintf (stderr, "Cannot create %s\n",pakfile);
return 2;
}
FWRITE (&pakHead, sizeof (pakHead), 1, pak);
//------------------------ elemstylesfile : -----------------------------
- styleStruct srec[2 << STYLE_BITS];
- elemstyleMapping eMap[2 << STYLE_BITS];
- memset (&srec, 0, sizeof (srec));
- memset (&eMap, 0, sizeof (eMap));
+ styleStruct *srec =
+ (styleStruct*) calloc ((2 << STYLE_BITS), sizeof (*srec));
+ elemstyleMapping *eMap =
+ (elemstyleMapping*) calloc ((2 << STYLE_BITS), sizeof (*eMap));
int elemCnt = LoadElemstyles(elemstylefile, iconscsvfile,
srec, eMap), styleCnt = elemCnt;
//------------------ OSM Data File (/dev/stdin) : ------------------------
+ max_nodes = ((time (NULL) - 1351071438) * (long long) 20 + 1980820697) /
+ NGROUPS; // Linear extrapolation from Oct 2012 at 20 nodes / second.
xmlTextReaderPtr xml = xmlReaderForFd (STDIN_FILENO, "", NULL, 0);
FILE *groupf[PAIRGROUP2 (0) + PAIRGROUPS2];
char groupName[PAIRGROUP2 (0) + PAIRGROUPS2][9];
for (int i = 0; i < PAIRGROUP2 (0) + PAIRGROUPS2; i++) {
sprintf (groupName[i], "%c%c%d.tmp", i / 26 % 26 + 'a', i % 26 + 'a',
i / 26 / 26);
- if (i < S2GROUP (0) && !(groupf[i] = fopen64 (groupName[i], "w+"))) {
- fprintf (stderr, "Cannot create temporary file.\n"
+ if (i < S2GROUP (0) && !(groupf[i] = fopen64 (groupName[i], "w+b"))) {
+ perror ("Cannot create temporary file.\n"
"Possibly too many open files, in which case you must run "
"ulimit -n or recompile\n");
return 9;
@@ -1567,15 +1630,15 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
#endif
nodeType nd;
- halfSegType s[2];
+ wayPartType wp[2];
int nOther = 0, lowzOther = FIRST_LOWZ_OTHER, isNode = 0;
int yesMask = 0, noMask = 0;
struct {
wayType *w; // Pointer to the first version in the master file.
int off;
} *wayFseek = NULL;
- int wStyle = elemCnt, ref = 0;
- int relationType = 0, onewayReverse = 0;
+ int wStyle = elemCnt, relationType = 0, onewayReverse = 0;
+ long long ref = 0;
vector<int> wayMember;
map<int,int> wayId;
wayType w;
@@ -1619,7 +1682,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
}
char *relationTable;
- FILE *relationTableFile = fopen ("relations.tbl", "r");
+ FILE *relationTableFile = fopen ("relations.tbl", "rb");
if (!relationTableFile || fseek (relationTableFile, 0, SEEK_END) != 0 ||
(relationTable = (char*) mmap (NULL, ftell (relationTableFile), PROT_READ,
MAP_SHARED, fileno (relationTableFile), 0)) == (char*)-1) {
@@ -1630,8 +1693,8 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
char *tag_k = NULL, *role = NULL; //, *tags = (char *) BAD_CAST xmlStrdup (BAD_CAST "");
//char *nameTag = NULL;
k2vType k2v, wayRole; // wayRole should be a vector< struct{char*,int} > ...
- deque<int> wayNd;
- map<int, deque<int> > outer;
+ deque<long long> wayNd;
+ map<int, deque<long long> > outer;
REBUILDWATCH (while (xmlTextReaderRead (xml) == 1)) {
char *name = (char *) BAD_CAST xmlTextReaderName (xml);
//xmlChar *value = xmlTextReaderValue (xml); // always empty
@@ -1642,10 +1705,10 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
char *aname = (char *) BAD_CAST xmlTextReaderName (xml);
char *avalue = (char *) BAD_CAST xmlTextReaderValue (xml);
// if (xmlStrcasecmp (name, "node") == 0)
- if (stricmp (aname, "id") == 0) nd.id = atoi (avalue);
+ if (stricmp (aname, "id") == 0) nd.id = atoll (avalue);
if (stricmp (aname, "lat") == 0) nd.lat = Latitude (atof (avalue));
if (stricmp (aname, "lon") == 0) nd.lon = Longitude (atof (avalue));
- if (stricmp (aname, "ref") == 0) ref = atoi (avalue);
+ if (stricmp (aname, "ref") == 0) ref = atoll (avalue);
if (stricmp (aname, "type") == 0) relationType = avalue[0];
#define K_IS(x) (stricmp (tag_k, x) == 0)
@@ -1734,7 +1797,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
while (!wayMember.empty ()) {
int idx;
for (idx = wayMember.size () - 1; !outer[wayMember[idx]].empty () ; idx--) {
- deque<int> *o = &outer[wayMember[idx]];
+ deque<long long> *o = &outer[wayMember[idx]];
if (wayNd.empty () || wayNd.back () == o->front () || idx == 0) {
if (!wayNd.empty () && wayNd.back () == o->front ()) wayNd.pop_back ();
wayNd.insert (wayNd.end (), o->begin (), o->end ());
@@ -1776,7 +1839,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
}
membershipType membership =
*relationTable == (isNode ? 'n' : nameIsRelation ? 'x' : 'w') &&
- atoi (relationTable + 1) == nd.id ? relationTable : NULL;
+ atoll (relationTable + 1) == nd.id ? relationTable : NULL;
for (membershipType m = membership; m; m = Next (m)) {
if (strcmp (Role (m), "inner") == 0 && wStyle == elemCnt) {
@@ -1788,7 +1851,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
}
}
else if (strcmp (Role (m), "outer") == 0) {
- outer[nd.id] = deque<int> ();
+ outer[nd.id] = deque<long long> ();
outer[nd.id].insert (outer[nd.id].end (), wayNd.begin (), wayNd.end ());
}
}
@@ -1805,31 +1868,33 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
if (wStyle == elemCnt /* 1 trick that did help enough to make files < 400MB
|| (!k2v["name"] && srec[wStyle].areaColour != -1)*/ ) wayNd.clear ();
else {
- s[0].other = -2;
+ wp[0].other = -2;
while (!wayNd.empty ()) {
- s[0].wayPtr = ftell (pak);
- s[1].wayPtr = TO_HALFSEG;
- s[1].other = s[0].other + 1;
- s[0].lat = onewayReverse ? wayNd.back () : wayNd.front ();
+ wp[0].wayPtr = ftell (pak);
+ wp[1].wayPtr = TO_HALFSEG;
+ wp[1].other = wp[0].other + 1;
+ wp[0].id = onewayReverse ? wayNd.back () : wayNd.front ();
/*if (lowzListCnt >=
int (sizeof (lowzList) / sizeof (lowzList[0]))) lowzListCnt--;
lowzList[lowzListCnt++] = s[0].lat; */
if (onewayReverse) wayNd.pop_back ();
else wayNd.pop_front ();
- s[0].other = wayNd.empty () ? -2 : nOther++ * 2;
- FWRITE (s, sizeof (s), 1, groupf[S1GROUP (s[0].lat)]);
+ wp[0].other = wayNd.empty () ? -2 : nOther++ * 2;
+ FWRITE (wp, sizeof (wp), 1, groupf[S1GROUP (wp[0].id)]);
}
if (nameIsNode && (!wayFseek || wayFseek->off)) {
- s[0].lat = nd.id; // Create 2 fake halfSegs
- s[0].wayPtr = ftell (pak);
- s[1].wayPtr = TO_HALFSEG;
- s[0].other = -2; // No next
- s[1].other = -1; // No prev
+ wp[0].id = nd.id; // Create 2 fake halfSegs
+ wp[0].wayPtr = ftell (pak);
+ wp[1].wayPtr = TO_HALFSEG;
+ wp[0].other = -2; // No next
+ wp[1].other = -1; // No prev
//lowzList[lowzListCnt++] = nd.id;
- FWRITE (s, sizeof (s), 1, groupf[S1GROUP (s[0].lat)]);
+ FWRITE (wp, sizeof (wp), 1, groupf[S1GROUP (wp[0].id)]);
}
- w.bits |= ~noMask & (yesMask | (eMap[wStyle].defaultRestrict &
+ w.bits |= ~noMask & ((yesMask & (1 << accessR))
+ ? yesMask | ((1 << onewayR) - (1 << (accessR + 1)))
+ : yesMask | (eMap[wStyle].defaultRestrict &
((noMask & (1 << accessR)) ? (1 << onewayR) : ~0)));
if (w.destination & (1 << accessR)) w.destination = ~0;
memcpy (&srec[styleCnt], &srec[wStyle], sizeof (srec[0]));
@@ -1946,6 +2011,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
xmlFree (name);
} // While reading xml
wayId.clear ();
+ fprintf (stderr, "nOther=%d FIRST_LOWZ_OTHER=%d\n", nOther, FIRST_LOWZ_OTHER);
assert (nOther * 2 < FIRST_LOWZ_OTHER);
bucketsMin1 = (nOther >> 5) | (nOther >> 4);
bucketsMin1 |= bucketsMin1 >> 2;
@@ -1956,27 +2022,32 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
for (int i = 0; i < IDXGROUPS; i++) fclose (groupf[i]);
for (int i = S2GROUP (0); i < PAIRGROUP2 (0) + PAIRGROUPS2; i++) {
- assert (groupf[i] = fopen64 (groupName[i], "w+"));
+ assert (groupf[i] = fopen64 (groupName[i], "w+b"));
} // Avoid exceeding ulimit
- nodeType *nodes = (nodeType *) malloc (sizeof (*nodes) * MAX_NODES);
+ nodeType *nodes = (nodeType *) malloc (sizeof (*nodes) * max_nodes);
if (!nodes) {
fprintf (stderr, "Out of memory. Reduce MAX_NODES and increase GRPs\n");
return 3;
}
+ halfSegType s[2];
for (int i = NGROUP (0); i < NGROUP (0) + NGROUPS; i++) {
rewind (groupf[i]);
- memset (nodes, -1, sizeof (*nodes) * MAX_NODES);
+ memset (nodes, -1, sizeof (*nodes) * max_nodes);
REBUILDWATCH (while (fread (&nd, sizeof (nd), 1, groupf[i]) == 1)) {
memcpy (FindNode (nodes, nd.id), &nd, sizeof (nd));
}
fclose (groupf[i]);
unlink (groupName[i]);
rewind (groupf[i + NGROUPS]);
- REBUILDWATCH (while (fread (s, sizeof (s), 1, groupf[i + NGROUPS])
+ REBUILDWATCH (while (fread (wp, sizeof (wp), 1, groupf[i + NGROUPS])
== 1)) {
- nodeType *n = FindNode (nodes, s[0].lat);
+ nodeType *n = FindNode (nodes, wp[0].id);
//if (n->id == -1) printf ("** Undefined node %d\n", s[0].lat);
+ s[0].other = wp[0].other;
+ s[1].other = wp[1].other;
+ s[0].wayPtr = wp[0].wayPtr;
+ s[1].wayPtr = wp[1].wayPtr;
s[0].lat = s[1].lat = n->id != -1 ? n->lat : INT_MIN;
s[0].lon = s[1].lon = n->id != -1 ? n->lon : INT_MIN;
FWRITE (s, sizeof (s), 1,
@@ -2028,6 +2099,8 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
ndWrite.other[0] = ndWrite.other[1] = 0;
FWRITE (&ndWrite, sizeof (ndWrite), 1, pak); // Insert 'stopper' record
+ assert (ftell (pak) < (1LL<<32));
+ // If this assert fails, wayPtr no longer fits in 32 bits
ndStart = ftell (pak);
int *pairing = (int *) malloc (sizeof (*pairing) * PAIRS);
@@ -2094,6 +2167,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
fseek (pak, ftell (pak), SEEK_SET);
vector<halfSegType> lseg;
ndBase = (ndType*)(data + ndStart);
+ #ifndef ONLY_ROUTING
REBUILDWATCH (for (ndType *ndItr = ndBase;
ndItr < ndBase + hashTable[bucketsMin1 + 1]; ndItr++)) {
//while (fread (&ndWrite, sizeof (ndWrite), 1, pak) == 1)) {
@@ -2124,12 +2198,12 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
// and the lats & lons have been dereferenced previously. So the pairing is
// simplified a lot.
ndType *prev = LFollow (ndItr, ndItr, way, 0);
- if (!ndItr->other[0] && prev->wayPtr >= ndItr->wayPtr) {
+ if (!ndItr->other[1] && prev->wayPtr >= ndItr->wayPtr) {
int length = 0;
ndType *end;
- for (end = ndItr; end->other[1]; end = LFollow (end, ndItr, way, 1)) {
- length += lrint (sqrt (Sqr ((double)(end->lat - end[end->other[1]].lat)) +
- Sqr ((double)(end->lon - end[end->other[1]].lon))));
+ for (end = ndItr; end->other[0]; end = LFollow (end, ndItr, way, 1)) {
+ length += lrint (sqrt (Sqr ((double)(end->lat - end[end->other[0]].lat)) +
+ Sqr ((double)(end->lon - end[end->other[0]].lon))));
if (prev != ndItr && end->wayPtr < ndItr->wayPtr) break;
// If it is circular and we didn't start at the way with the lowest
// wayPtr, then we abort
@@ -2180,6 +2254,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
} // If the way belongs in the lowzoom
} // If it was the start of a way
} // For each highzoom nd
+ #endif
REBUILDWATCH (qsort (&lseg[0], lseg.size () / 2, sizeof (lseg[0]) * 2,
(int (*)(const void *, const void *))HalfSegCmp));
int *lpair = new int[lowzOther - FIRST_LOWZ_OTHER];
@@ -2211,7 +2286,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
}
REBUILDWATCH (for (int i = 0; i < IDXGROUPS; i++)) {
- assert (groupf[i] = fopen64 (groupName[i], "r+"));
+ assert (groupf[i] = fopen64 (groupName[i], "r+b"));
fseek (groupf[i], 0, SEEK_END);
int fsize = ftell (groupf[i]);
if (fsize > 0) {
@@ -2236,7 +2311,7 @@ int RebuildPak(const char* pakfile, const char* elemstylefile,
bucketsMin1 + (bucketsMin1 >> 7) + 3, pak);
CalculateInvSpeeds (srec, styleCnt);
- FWRITE (&srec, sizeof (srec[0]), styleCnt, pak);
+ FWRITE (srec, sizeof (srec[0]), styleCnt, pak);
FWRITE (&styleCnt, sizeof(styleCnt), 1, pak); // File ends with these
FWRITE (&bucketsMin1, sizeof (bucketsMin1), 1, pak); // 3 variables
FWRITE (&ndStart, sizeof (ndStart), 1, pak); /* for ndBase */
@@ -2258,7 +2333,8 @@ int XmlTee (void * /*context*/, char *buf, int len)
int XmlClose (void */*context*/) { return 0; }
struct memberType {
- int ref, type;
+ int type;
+ long long ref;
const char *role, *tags;
};
@@ -2298,11 +2374,23 @@ int SortRelations (void)
#endif
rel = rel || stricmp (name, "relation") == 0;
- if (stricmp (name, "relation") == 0 && rStart < member.size ()) {
+ if (stricmp (name, "relation") == 0) { // && rStart < member.size ()) {
while (rStart < member.size ()) member[rStart++].tags = s->c_str ();
s = new string (); // It leaks memory, but it cannot be freed until
// moments before exit.
+ while (xmlTextReaderMoveToNextAttribute (xml)) {
+ char *aname = (char *) BAD_CAST xmlTextReaderName (xml);
+ if (stricmp (aname, "id") == 0) {
+ char *avalue = (char *) BAD_CAST xmlTextReaderValue (xml);
+ *s += "relation_id\nr";
+ *s += avalue;
+ *s += '\n';
+ xmlFree (avalue);
+ }
+ xmlFree (aname);
+ }
}
+
if (rel && (stricmp (name, "member") == 0 || stricmp (name, "tag") == 0)) {
if (name[0] == 'm') member.push_back (memberType ());
while (xmlTextReaderMoveToNextAttribute (xml)) {
@@ -2311,7 +2399,7 @@ int SortRelations (void)
if (stricmp (aname, "type") == 0) {
member.back ().type = avalue[0] == 'r' ? 'x' : avalue[0];
}
- else if (stricmp (aname, "ref") == 0) member.back ().ref = atoi (avalue);
+ else if (stricmp (aname, "ref") == 0) member.back ().ref = atoll (avalue);
else if (name[0] == 't' && stricmp (aname, "k") == 0) {
*s += avalue;
*s += '\n';
@@ -2331,7 +2419,7 @@ int SortRelations (void)
}
}
#ifdef MKDENSITY_CSV
- FILE *df = fopen ("density.csv", "w");
+ FILE *df = fopen ("density.csv", "wb");
for (lat = 1023; lat >= 0; lat--) {
for (lon = 0; lon < 1024; lon++) {
fprintf (df, "%d%c", cnt[lat * 1024 + lon], lon == 1023 ? '\n' : ' ');
@@ -2342,9 +2430,9 @@ int SortRelations (void)
while (rStart < member.size ()) member[rStart++].tags = s->c_str ();
qsort (&member[0], member.size (), sizeof (member[0]),
(int (*)(const void *, const void *)) MemberCmp);
- FILE *idx = fopen ("relations.tbl", "w");
+ FILE *idx = fopen ("relations.tbl", "wb");
for (unsigned i = 0; i < member.size (); i++) {
- fprintf (idx, "%c%d%c%s%c", member[i].type, member[i].ref, '\0', member[i].role, '\0');
+ fprintf (idx, "%c%lld%c%s%c", member[i].type, member[i].ref, '\0', member[i].role, '\0');
for (const char *ptr = member[i].tags; *ptr; ptr += strcspn (ptr, "\n") + 1) {
fprintf (idx, "%.*s%c", (int) strcspn (ptr, "\n"), ptr, '\0');
}
diff --git a/libgosm.h b/jni/libgosm.h
similarity index 98%
rename from libgosm.h
rename to jni/libgosm.h
index 07693e2..c467fd2 100755
--- a/libgosm.h
+++ b/jni/libgosm.h
@@ -17,7 +17,9 @@ typedef int intptr_t;
#endif
#ifndef _WIN32
+#ifndef ANDROID_NDK
#include <libxml/xmlreader.h>
+#endif
#include <inttypes.h>
#define stricmp strcasecmp
typedef long long __int64;
@@ -26,7 +28,7 @@ typedef long long __int64;
#define M_PI 3.14159265358979323846 // Not in math ??
#endif
-#if __FreeBSD__ || __APPLE__ // Thanks to Ted Mielczarek & Dmitry
+#if __FreeBSD__ || __APPLE__ || ANDROID_NDK
#define fopen64(x,y) fopen(x,y)
#endif
@@ -46,7 +48,7 @@ typedef long long __int64;
#endif
#define Sqr(x) ((x)*(x))
-inline int isqrt (int x) { return lrint (sqrt (x)); } // Optimize this ?
+inline int isqrt (int x) { return lrint (sqrt ((double)x)); } // Optimize this ?
#define TILEBITS (18)
#define TILESIZE (1<<TILEBITS)
@@ -270,7 +272,7 @@ enum {
s (landuse, retail, "retail area" , "") \
s (landuse, commercial, "commercial area" , "") \
s (landuse, construction, "construction area" , "") \
- s (landuse, reservoir, "reservoir" , "") \
+ s (natural, coastline, "coastline" , "") \
s (natural, water, "lake / dam" , "") \
s (landuse, basin, "basin" , "") \
s (landuse, landfill, "landfill" , "") \
@@ -322,7 +324,8 @@ struct styleStruct {
};
struct ndType {
- int wayPtr, lat, lon, other[2];
+ unsigned wayPtr;
+ int lat, lon, other[2];
};
/* This struct takes up a lot of space, but compressing is possible: If
other is encoded as byte offset from the current position, it should typically
@@ -476,7 +479,7 @@ int GosmInit (void *d, long size);
// *** EVERYTHING AFTER THIS POINT IS NOT IN THE WINDOWS BUILDS ***
-#ifndef _WIN32
+#ifndef _WIN32_WCE
void GosmLoadAltStyle(const char* elemstylefile, const char* iconscsvfile);
diff --git a/jni/openglespolygon.cpp b/jni/openglespolygon.cpp
new file mode 100755
index 0000000..53e7bb7
--- /dev/null
+++ b/jni/openglespolygon.cpp
@@ -0,0 +1,532 @@
+/* Copyright (C) 2011 Nic Roets as detailed in the README file. */
+#ifndef HEADLESS
+#include <assert.h>
+#include <string.h>
+#include <malloc.h>
+#ifdef ANDROID_NDK
+#include <jni.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <android/log.h>
+#else
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#endif
+#include "openglespolygon.h"
+#define LG //__android_log_print (ANDROID_LOG_WARN, "Gosmore", "%d", __LINE__);
+
+using namespace std;
+
+typedef long long calcType; // Used to prevent overflows when
+ // multiplying two GdkPoint fields
+
+int edgeCmp /*::operator()*/(const PolygonEdge *a, const PolygonEdge *b)
+{
+ const FixedPoint *ap = a->pt, *bp = b->pt,
+ *st = a->prev.y < b->prev.y ? &a->prev : &b->prev;
+ calcType cross;
+ if (a->pt == &a->prev) return a->prev.x < 0; // left and right borders
+ if (b->pt == &b->prev) return b->prev.x > 0;
+ while ((cross = (ap->x - st->x) * (calcType)(bp->y - st->y) -
+ (ap->y - st->y) * (calcType)(bp->x - st->x)) == 0) {
+ if (ap->y < bp->y) {
+ st = ap;
+ ap += a->delta;
+ if (ap - a->pt >= a->cnt || ap - a->pt + a->cnt <= 0) {
+ if (!a->continues) return !b->isLeft; // Edges are the same
+ a++;
+ ap = a->pt;
+ }
+ }
+ else {
+ st = bp;
+ bp += b->delta;
+ if (bp - b->pt >= b->cnt || bp - b->pt + b->cnt <= 0) {
+ if (!b->continues) return !b->isLeft; // Edges are the same
+ b++;
+ bp = b->pt;
+ }
+ }
+ }
+ return cross < 0;
+}
+
+//-------------------[ Start of AA tree code ]---------------------------
+#define AATREE_NOREBALANCE 1
+
+struct PolygonEdge *First (struct PolygonEdge *root)
+{
+ if (!root->left) return NULL;
+ while (root->left) root = root->left;
+ return root;
+}
+
+struct PolygonEdge *Next (struct PolygonEdge *n)
+{
+ if (n->right) {
+ n = n->right;
+ while (n->left) n = n->left;
+ }
+ else {
+ while (n->parent && n->parent->right == n) n = n->parent;
+ // Follow the parent link while it's pointing to the left.
+ n = n->parent; // Follow one parent link pointing to the right
+
+ if (!n->parent) return NULL;
+ // The last PolygonEdge is the root, because it has nothing to it's right
+ }
+ return n;
+}
+
+struct PolygonEdge *Prev (struct PolygonEdge *n)
+{
+ if (n->left) {
+ n = n->left;
+ while (n->right) n = n->right;
+ }
+ else {
+ while (n->parent && n->parent->left == n) n = n->parent;
+ // Follow the parent link while it's pointing to the left.
+ if (!n->parent) return NULL;
+ // The last PolygonEdge is the root, because it has nothing to it's right
+ n = n->parent; // Follow one parent link pointing to the right
+ }
+ return n;
+}
+
+void Skew (struct PolygonEdge *oldparent)
+{
+ struct PolygonEdge *newp = oldparent->left;
+
+ if (oldparent->parent->left == oldparent) oldparent->parent->left = newp;
+ else oldparent->parent->right = newp;
+ newp->parent = oldparent->parent;
+ oldparent->parent = newp;
+
+ oldparent->left = newp->right;
+ if (oldparent->left) oldparent->left->parent = oldparent;
+ newp->right = oldparent;
+
+ oldparent->level = oldparent->left ? oldparent->left->level + 1 : 1;
+}
+
+int Split (struct PolygonEdge *oldparent)
+{
+ struct PolygonEdge *newp = oldparent->right;
+
+ if (newp && newp->right && newp->right->level == oldparent->level) {
+ if (oldparent->parent->left == oldparent) oldparent->parent->left = newp;
+ else oldparent->parent->right = newp;
+ newp->parent = oldparent->parent;
+ oldparent->parent = newp;
+
+ oldparent->right = newp->left;
+ if (oldparent->right) oldparent->right->parent = oldparent;
+ newp->left = oldparent;
+ newp->level = oldparent->level + 1;
+ return 1;
+ }
+ return 0;
+}
+
+#if 0
+static struct PolygonEdge root;
+// A static variable to make things easy.
+
+void RebalanceAfterLeafAdd (struct PolygonEdge *n)
+{ // n is a PolygonEdge that has just been inserted and is now a leaf PolygonEdge.
+ n->level = 1;
+ n->left = NULL;
+ n->right = NULL;
+ for (n = n->parent; n != &root; n = n->parent) {
+ // At this point n->parent->level == n->level
+ if (n->level != (n->left ? n->left->level + 1 : 1)) {
+ // At this point the tree is correct, except (AA2) for n->parent
+ Skew (n);
+ // We handle it (a left add) by changing it into a right add using Skew
+ // If the original add was to the left side of a PolygonEdge that is on the
+ // right side of a horisontal link, n now points to the rights side
+ // of the second horisontal link, which is correct.
+
+ // However if the original add was to the left of PolygonEdge with a horisontal
+ // link, we must get to the right side of the second link.
+ if (!n->right || n->level != n->right->level) n = n->parent;
+ }
+ if (!Split (n->parent)) break;
+ }
+}
+#endif
+
+void Delete (struct PolygonEdge *n)
+{ // If n is not a leaf, we first swap it out with the leaf PolygonEdge that just
+ // precedes it.
+ struct PolygonEdge *leaf = n;
+
+ if (n->left) {
+ for (leaf = n->left; leaf->right; leaf = leaf->right) {}
+ // When we stop, left has no 'right' child so it cannot have a left one
+ #ifdef AATREE_NOREBALANCE
+ // Remove leaf:
+ if (leaf->parent->left == leaf) leaf->parent->left = leaf->left;
+ else leaf->parent->right = leaf->left;
+ if (leaf->left) leaf->left->parent = leaf->parent;
+ // Replace n with leaf:
+ leaf->parent = n->parent;
+ leaf->left = n->left;
+ leaf->right = n->right;
+ if (n->parent->left == n) n->parent->left = leaf;
+ else n->parent->right = leaf;
+ if (leaf->left) leaf->left->parent = leaf;
+ if (leaf->right) leaf->right->parent = leaf;
+ return;
+ #endif
+ }
+ #ifdef AATREE_NOREBALANCE
+ else {
+ if (n->parent->left == n) n->parent->left = n->right;
+ else n->parent->right = n->right;
+ if (n->right) n->right->parent = n->parent;
+ return;
+ }
+ #else
+ else if (n->right) leaf = n->right;
+ #endif
+
+ #ifndef AATREE_NOREBALANCE
+ struct PolygonEdge *tmp = leaf->parent == n ? leaf : leaf->parent;
+ #endif
+ if (leaf->parent->left == leaf) leaf->parent->left = NULL;
+ else leaf->parent->right = NULL;
+
+ if (n != leaf) {
+ if (n->parent->left == n) n->parent->left = leaf;
+ else n->parent->right = leaf;
+ leaf->parent = n->parent;
+ if (n->left) n->left->parent = leaf;
+ leaf->left = n->left;
+ if (n->right) n->right->parent = leaf;
+ leaf->right = n->right;
+ leaf->level = n->level;
+ }
+ #ifndef AATREE_NOREBALANCE
+ // free (n);
+ while (tmp != &root) {
+ // One of tmp's childern had it's level reduced
+ if (tmp->level > (tmp->left ? tmp->left->level + 1 : 1)) { // AA2 failed
+ tmp->level--;
+ if (Split (tmp)) {
+ if (Split (tmp)) Skew (tmp->parent->parent);
+ break;
+ }
+ tmp = tmp->parent;
+ }
+ else if (tmp->level <= (tmp->right ? tmp->right->level + 1 : 1)) break;
+ else { // AA3 failed
+ Skew (tmp);
+ //if (tmp->right) tmp->right->level = tmp->right->left ? tmp->right->left->level + 1 : 1;
+ if (tmp->level > tmp->parent->level) {
+ Skew (tmp);
+ Split (tmp->parent->parent);
+ break;
+ }
+ tmp = tmp->parent->parent;
+ }
+ }
+ #endif
+}
+
+void Check (struct PolygonEdge *n)
+{
+ assert (!n->left || n->left->parent == n);
+ assert (!n->right || n->right->parent == n);
+// assert (!Next (n) || n->data <= Next (n)->data);
+ assert (!n->parent || n->parent->level >= n->level);
+ assert (n->level == (n->left == NULL ? 1 : n->left->level + 1));
+ assert (n->level <= 1 || (n->right && n->level - n->right->level <= 1));
+ assert (!n->parent || !n->parent->parent ||
+ n->parent->parent->level > n->level);
+}
+
+void Add (struct PolygonEdge *n, struct PolygonEdge *root)
+{
+ struct PolygonEdge *s = root;
+ int lessThan = 1;
+ while (lessThan ? s->left : s->right) {
+ s = lessThan ? s->left : s->right;
+ lessThan = edgeCmp(n, s); //c.operator<(n, s);
+ }
+ if (lessThan) s->left = n;
+ else s->right = n;
+ n->parent = s;
+ #ifdef AATREE_NOREBALANCE
+ n->level = 1;
+ n->left = NULL;
+ n->right = NULL;
+ #else
+ RebalanceAfterLeafAdd (n);
+ #endif
+}
+//----------------------------[ End of AA tree ]----------------------------
+
+int ptSize = 0;
+void AddPolygon (vector<PolygonEdge> &d, FixedPoint *p, int cnt)
+{
+ int i, j, k, firstd = d.size();
+ ptSize = cnt;
+ for (j = cnt - 1; j > 0 && (p[j - 1].y == p[j].y || // p[j..cnt-1] becomes
+ (p[j - 1].y < p[j].y) == (p[j].y < p[0].y)); j--) {} // monotone
+ //if (j == 0) return; // Polygon has no height but it does not cause infinite loop
+ for (i = 0; i < j && (p[i].y == p[i + 1].y ||
+ (p[i].y < p[i + 1].y) == (p[j].y < p[0].y)); i++) {}
+ // Now p[cn-1],p[0..i] is the longest monotone sequence
+ d.resize (firstd + 2);
+ memset (&d[firstd], 0, sizeof (d[0]) * 2); // TODO: remove
+ d[firstd].delta = p[j].y < p[0].y ? 1 : -1;
+ d[firstd].continues = 1;
+ d[firstd + 1].delta = p[j].y < p[0].y ? 1 : -1;
+ d[firstd + 1].continues = 0;
+ d[firstd + !(p[j].y < p[0].y)].cnt = cnt - j;
+ d[firstd + (p[j].y < p[0].y)].cnt = i + 1;
+ d[firstd + !(p[j].y < p[0].y)].pt = p + (p[j].y < p[0].y ? j : cnt - 1);
+ d[firstd + (p[j].y < p[0].y)].pt = p + (p[j].y < p[0].y ? 0 : i);
+ //int lowest = j;
+ for (; i < j ; i = k) {
+ //if (p[lowest].y > p[i].y) lowest = i;
+ for (k = i + 1; k < j && (p[k].y == p[k + 1].y || // p[i..k] becomes
+ (p[k].y < p[k + 1].y) == (p[i].y < p[k].y)); k++) {} // monotone
+ d.push_back(PolygonEdge());
+ memset (&d.back(), 0, sizeof (d[0])); // TODO: remove
+ d[d.size() - 1].pt = p + (p[i].y < p[k].y ? i : k);
+ d[d.size() - 1].delta = p[i].y < p[k].y ? 1 : -1;
+ d[d.size() - 1].continues = 0;
+ d[d.size() - 1].cnt = k - i + 1;
+ }
+/* GdkPoint *ll = &p[lowest], *lr = &p[lowest];
+ do {
+ if (--ll < p) ll = p + cnt - 1;
+ } while (ll->y <= p[lowest].y);
+ do {
+ if (++lr >= p + cnt) lr = p;
+ } while (lr->y <= p[lowest].y);*/
+ calcType area = p[cnt-1].x * (calcType) p[0].y - p[0].x * (calcType) p[cnt-1].y;
+ for (i = 0; i < cnt - 1; i++) area += p[i].x*(calcType)p[i+1].y-
+ p[i+1].x * (calcType) p[i].y;
+ for (i = firstd; i < (int) d.size(); i++) {
+ // This ll/lr inequality is a cross product that is true if the polygon
+ // was clockwise. AddInnerPoly() will just negate isLeft.
+ d[i].isLeft = (area < 0) == (d[i].delta == 1);
+ }
+}
+
+void AddClockwise (vector<PolygonEdge> &d, FixedPoint *p, int cnt)
+{
+ int i, j;
+ #if 0
+ for (i = 0; i < cnt; i++) __android_log_print (ANDROID_LOG_WARN, "Gosmore",
+ "pt[ptCnt].x = %d; pt[ptCnt++].y=%d;", p[i].x, p[i].y);
+ __android_log_print (ANDROID_LOG_WARN, "Gosmore", "AddClockwise(d,pt,ptCnt); ptCnt = 0;");
+ #endif
+ for (i = 0; i < cnt - 1 && p[i].y == p[0].y; i++) {}
+ int up = p[i].y > p[0].y;
+ for (i = 0; i < cnt - 1; i = j) {
+ d.push_back(PolygonEdge());
+ memset (&d.back(), 0, sizeof (d[0])); //TODO: remove
+ for (j = i; j + 1 < cnt &&
+ (up ? p[j + 1].y >= p[j].y : p[j + 1].y <= p[j].y); j++) {}
+ d[d.size() - 1].pt = up ? p + i : p + j;
+ d[d.size() - 1].delta = up ? 1 : -1;
+ d[d.size() - 1].isLeft = up;
+ d[d.size() - 1].cnt = j - i + 1;
+ d[d.size() - 1].continues = 0;
+ up = !up;
+ }
+}
+
+#ifdef ANDROID_NDK
+void Fill (vector<PolygonEdge> &d,int isSea)
+#else
+void Fill (vector<PolygonEdge> &d,int isSea, GdkWindow *w, GdkGC *gc)
+#endif
+{
+ //PolygonEdge **heap = (PolygonEdge **) malloc ((d.size() + 1) * sizeof (*heap));
+ vector<PolygonEdge*> heap;
+ heap.resize (d.size() + 1);
+ memset (&heap[0], 0, sizeof (heap[0]) * (d.size()+1)); // TODO: remove
+ // leave heap[0] open to make indexing easier
+ int i, h = 1, j, sea = 0, start = 1;
+ PolygonEdge dummy, left, right, root;
+
+ root.left = NULL;
+ root.right = NULL;
+ root.level = 1000000;
+ root.parent = NULL;
+
+/* for (i = 0; i < d.size(); i++) {
+ for (j = 0; j + 1 < d[i].cnt; j++) assert (d[i].pt[j*d[i].delta].y <= d[i].pt[(j+1)*d[i].delta].y);
+ if (d[i].continues) assert (d[i].pt[j*d[i].delta].y <= d[i+1].pt->y);
+ } // Make sure AddPolygon() and variants are correct */
+ dummy.opp = &dummy;
+ for (i = 0; i < (int) d.size(); i++) {
+ for (j = h++; j > 1 && heap[j / 2]->pt->y > d[i].pt->y; j /= 2) {
+ heap[j] = heap[j/2];
+ }
+ heap[j] = &d[i];
+ d[i].opp = NULL;
+ memcpy (&d[i].prev, d[i].pt, sizeof (d[i].prev)); // This is only
+ // to make the compare work.
+ if (d[i].continues) ++i; // Don't add the second part to the heap
+ }
+ //for (i = 2; i < h; i++) assert (heap[i]->pt->y >= heap[i/2]->pt->y);
+ left.prev.x = -6000*65536;
+ left.prev.y = 0;
+ left.opp = &dummy;
+ //h < 3 || edgeCmp (heap[1],
+ // heap[h == 3 || heap[2]->pt->y < heap[3]->pt->y ? 2 : 3])
+ // != !heap[1]->isLeft ? &dummy : &right;
+ left.pt = &left.prev;
+ left.isLeft = 1;
+ Add (&left, &root);
+ right.prev.x = 6000*65536;
+ right.prev.y = 0;
+ right.opp = &dummy; //left.opp == &dummy ? &dummy : &left;
+ right.pt = &right.prev;
+ right.isLeft = 0;
+ Add (&right, &root);
+ while (h > 1) {
+ PolygonEdge *head = heap[1];
+ //printf ("%p %3d\n", head->opp, head->pt->y);
+ if (!head->opp) { // Insert it
+ Add (head, &root);
+ head->opp = head->isLeft ? Next (head) : Prev (head);
+ if (head->opp == NULL || head->opp->isLeft == head->isLeft) {
+ head->opp = &dummy;
+ }
+ }
+ PolygonEdge *o = head->opp;
+ /* Now we render the trapezium between head->opp and head->opp->opp up
+ to head->pt->y */
+ if (o != &dummy && o->opp != &dummy) {
+ GdkPoint q[6];
+ #define CLAMPX(x) (short)((x) >= (1<<29) ? 8191 : (x) < -(1<<29) ? -8191 : (x) >> 16)
+ q[2].x = CLAMPX (o->opp->prev.x);
+ q[2].y = CLAMPX (o->opp->prev.y);
+ q[3].x = CLAMPX (o->prev.x);
+ q[3].y = CLAMPX (o->prev.y);
+ o->prev.x = o->pt->y <= o->prev.y ? o->pt->x
+ : o->prev.x + (o->pt->x - o->prev.x) *
+ calcType (head->pt->y - o->prev.y) / (o->pt->y - o->prev.y);
+ q[0].x = CLAMPX(o->prev.x);
+ o->prev.y = head->pt->y;
+ q[0].y = CLAMPX(o->prev.y);
+ o->opp->prev.x = o->opp->pt->y <= o->opp->prev.y ? o->opp->pt->x
+ : o->opp->prev.x + (o->opp->pt->x - o->opp->prev.x) *
+ calcType (head->pt->y - o->opp->prev.y) / (o->opp->pt->y - o->opp->prev.y);
+ q[1].x = CLAMPX (o->opp->prev.x);
+ o->opp->prev.y = head->pt->y;
+ q[1].y = q[0].y;
+ //if (o->opp->prev.y != o->prev.y && o->opp->prev.x < 30000 &&
+ // o->opp->prev.x > -30000 && o->prev.x < 30000 && o->prev.x > -30000)
+ // __android_log_print (ANDROID_LOG_WARN, "Gosmore", "Prev dif");
+ if ((isSea || (o->pt != &o->prev && o->opp->pt != &o->opp->prev)) &&
+ q[o->pt == &o->prev ? 2 : 3].y < q[0].y) {
+ // Frequently it happens that one of the triangles has 0 area because
+ // two of the points are equal. TODO: Filter them out.
+ #ifdef ANDROID_NDK
+ memcpy (&q[4], &q[0], sizeof (q[4]));
+ memcpy (&q[5], &q[2], sizeof (q[5]));
+ glVertexPointer (2, GL_SHORT, 0, q);
+ glDrawArrays (GL_TRIANGLES, 0, 6);
+ #else
+ //memcpy (&q[2], &o->prev, sizeof (q[2]));
+ //memcpy (&q[3], &o->opp->prev, sizeof (q[3]));
+ gdk_draw_polygon (w, gc, TRUE, q, 4);
+ #endif
+ if (q[0].x > 100 && q[1].x <= 100) sea = o->opp == &left;
+ if (q[0].x <= 100 && q[1].x < 100) sea = o->opp == &right;
+ if (q[1].x > 100 && q[0].x <= 100) sea = o == &left;
+ if (q[1].x <= 100 && q[0].x < 100) sea = o == &right;
+
+ if (start) {
+ start = 0;
+ if (sea) {
+ q[2].x = -6000;
+ q[3].x = 6000;
+ q[4].x = 0;
+ q[4].y = -6000;
+ #ifdef ANDROID_NDK
+ glVertexPointer (2, GL_SHORT, 0, q + 2);
+ glDrawArrays (GL_TRIANGLES, 0, 3);
+ #else
+ //memcpy (&q[2], &o->prev, sizeof (q[2]));
+ //memcpy (&q[3], &o->opp->prev, sizeof (q[3]));
+ gdk_draw_polygon (w, gc, TRUE, q + 2, 3);
+ #endif
+ }
+ }
+ } // If the trapezium has a non-zero height
+ }
+ if (o != &dummy && o->opp != head) {
+ o->opp->opp = &dummy; // Complete the 'Add'
+ o->opp = head;
+ }
+
+ if (--head->cnt) head->pt += head->delta;
+ else if (head->continues) {
+ head->continues = head[1].continues;
+ head->cnt = head[1].cnt;
+ head->pt = head[1].pt;
+ }
+ else { // Remove it
+ head->opp->opp = &dummy;
+ PolygonEdge *n = head->isLeft ? Prev (head) : Next (head);
+ if (n && n->opp == &dummy) {
+ if (head->isLeft == n->isLeft &&
+ (head->opp->pt != &head->opp->prev || n->pt != &n->prev || sea)) {
+ n->opp = head->opp;
+ head->opp->opp = n;
+ n->prev.x += n->pt->y <= n->prev.y ? n->pt->x - n->prev.x :
+ (n->pt->x - n->prev.x) *
+ calcType(head->prev.y - n->prev.y) / (n->pt->y - n->prev.y);
+ n->prev.y = head->prev.y;
+ }
+ else {
+ // Either n is not a replacement for head because one of them is
+ // a left side and the other right side
+ // OR
+ // heap->opp is either left or right and n is either left or right.
+ // and we recently drew all the way to the left or right ("sea").
+ n->opp = &dummy;
+ head->opp->opp = &dummy;
+ }
+ }
+ Delete (head);
+ head = heap[--h];
+ }
+
+ for (j = 2; j < h; j *= 2) {
+ if (j + 1 < h && heap[j + 1]->pt->y < heap[j]->pt->y) j++;
+ if (heap[j]->pt->y >= head->pt->y) break;
+ heap[j / 2] = heap[j];
+ }
+ heap[j / 2] = head;
+ for (i = 2; i < h; i++) assert (heap[i]->pt->y >= heap[i/2]->pt->y);
+ } // While going through the edges
+ if (sea) { //left.opp == &right) {
+ GdkPoint end[3];
+ end[0].x = -6000;
+ end[0].y = max (left.prev.y, right.prev.y) >> 16;
+ end[1].x = 6000;
+ end[1].y = end[0].y;
+ end[2].x = 0;
+ end[2].y = 6000;
+ #ifdef ANDROID_NDK
+ glVertexPointer (2, GL_SHORT, 0, end);
+ glDrawArrays (GL_TRIANGLES, 0, 3);
+ #else
+ gdk_draw_polygon (w, gc, TRUE, end, 3);
+ #endif
+ }
+ //free (heap);
+}
+#endif
diff --git a/jni/openglespolygon.h b/jni/openglespolygon.h
new file mode 100755
index 0000000..9a5abf4
--- /dev/null
+++ b/jni/openglespolygon.h
@@ -0,0 +1,42 @@
+#if !defined(OPENGLESPOLYGON_H) && !defined(HEADLESS)
+#define OPENGLESPOLYGON_H
+#include <vector>
+#if !defined(ANDROID_NDK) && !defined(NOGTK)
+#include <gdk/gdk.h>
+#endif
+
+struct FixedPoint {
+ int x, y;
+};
+
+struct PolygonEdge {
+ int isLeft : 1;
+ int delta : 2; // Either -1 or 1
+ int continues : 1; // It's a polygon stored in an array and this edge wraps
+ // over. We should continue at this+1 when cnt runs out.
+ int cnt : 20;
+ FixedPoint *pt, prev;
+ PolygonEdge *opp;
+/* I tried to make PolygonEdge a node in a tree by using a set<>. It failed
+ and I'm not sure how to fix it (add an iterator here ?).
+ set<PolygonEdge *, edgeCmp>::iterator itr;
+
+ So instead I copied and pasted my own AA tree code here:
+*/
+ PolygonEdge *parent, *left, *right;
+ int level;
+};
+
+#if defined(ANDROID_NDK) || defined(NOGTK)
+struct GdkPoint {
+ short x, y;
+};
+
+void Fill (std::vector<PolygonEdge> &d,int hasSea);
+#else
+void Fill (std::vector<PolygonEdge> &d,int hasSea, GdkWindow *w, GdkGC *gc);
+#endif
+void AddPolygon (std::vector<PolygonEdge> &d, FixedPoint *p, int cnt);
+void AddClockwise (std::vector<PolygonEdge> &d, FixedPoint *p, int cnt);
+
+#endif
diff --git a/resource.h b/jni/resource.h
similarity index 100%
rename from resource.h
rename to jni/resource.h
diff --git a/translations.c b/jni/translations.c
similarity index 100%
rename from translations.c
rename to jni/translations.c
diff --git a/proguard.cfg b/proguard.cfg
new file mode 100755
index 0000000..bf4ea78
--- /dev/null
+++ b/proguard.cfg
@@ -0,0 +1,48 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-assumenosideeffects class android.util.Log {
+ public static *** d(...);
+ public static *** v(...);
+}
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keep class org.osmu.gosmore.MapRenderer {
+ void drawTeks(java.lang.String,int,int,float,float);
+}
+
+-keep class org.osmu.gosmore.Search {
+ void searchResult(int,int,int,int,double,int,int,
+ java.lang.String,double,double,int);
+}
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembernames class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/res/drawable-hdpi/btn_square_overlay_normal.png b/res/drawable-hdpi/btn_square_overlay_normal.png
new file mode 100755
index 0000000..419ad52
Binary files /dev/null and b/res/drawable-hdpi/btn_square_overlay_normal.png differ
diff --git a/res/drawable-hdpi/btn_zoom_down_disabled.png b/res/drawable-hdpi/btn_zoom_down_disabled.png
new file mode 100755
index 0000000..6fc8d50
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_down_disabled.png differ
diff --git a/res/drawable-hdpi/btn_zoom_down_disabled_focused.png b/res/drawable-hdpi/btn_zoom_down_disabled_focused.png
new file mode 100755
index 0000000..12d2244
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_down_disabled_focused.png differ
diff --git a/res/drawable-hdpi/btn_zoom_down_normal.png b/res/drawable-hdpi/btn_zoom_down_normal.png
new file mode 100755
index 0000000..4105dd3
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_down_normal.png differ
diff --git a/res/drawable-hdpi/btn_zoom_down_pressed.png b/res/drawable-hdpi/btn_zoom_down_pressed.png
new file mode 100755
index 0000000..d109a4d
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_down_pressed.png differ
diff --git a/res/drawable-hdpi/btn_zoom_down_selected.png b/res/drawable-hdpi/btn_zoom_down_selected.png
new file mode 100755
index 0000000..ed9b858
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_down_selected.png differ
diff --git a/res/drawable-hdpi/btn_zoom_up_disabled.png b/res/drawable-hdpi/btn_zoom_up_disabled.png
new file mode 100755
index 0000000..2d144b9
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_up_disabled.png differ
diff --git a/res/drawable-hdpi/btn_zoom_up_disabled_focused.png b/res/drawable-hdpi/btn_zoom_up_disabled_focused.png
new file mode 100755
index 0000000..d4757e0
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_up_disabled_focused.png differ
diff --git a/res/drawable-hdpi/btn_zoom_up_normal.png b/res/drawable-hdpi/btn_zoom_up_normal.png
new file mode 100755
index 0000000..9cddba8
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_up_normal.png differ
diff --git a/res/drawable-hdpi/btn_zoom_up_pressed.png b/res/drawable-hdpi/btn_zoom_up_pressed.png
new file mode 100755
index 0000000..614e78f
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_up_pressed.png differ
diff --git a/res/drawable-hdpi/btn_zoom_up_selected.png b/res/drawable-hdpi/btn_zoom_up_selected.png
new file mode 100755
index 0000000..86b8ca2
Binary files /dev/null and b/res/drawable-hdpi/btn_zoom_up_selected.png differ
diff --git a/res/drawable-hdpi/ic_menu_play_clip.png b/res/drawable-hdpi/ic_menu_play_clip.png
new file mode 100755
index 0000000..06b6531
Binary files /dev/null and b/res/drawable-hdpi/ic_menu_play_clip.png differ
diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png
new file mode 100755
index 0000000..0804f50
Binary files /dev/null and b/res/drawable-hdpi/icon.png differ
diff --git a/res/drawable-hdpi/stat_sys_upload_anim0.png b/res/drawable-hdpi/stat_sys_upload_anim0.png
new file mode 100755
index 0000000..96c333e
Binary files /dev/null and b/res/drawable-hdpi/stat_sys_upload_anim0.png differ
diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png
new file mode 100755
index 0000000..c868645
Binary files /dev/null and b/res/drawable-ldpi/icon.png differ
diff --git a/res/drawable-mdpi/btn_square_overlay_normal.png b/res/drawable-mdpi/btn_square_overlay_normal.png
new file mode 100755
index 0000000..4844802
Binary files /dev/null and b/res/drawable-mdpi/btn_square_overlay_normal.png differ
diff --git a/res/drawable-mdpi/btn_zoom_down_disabled.png b/res/drawable-mdpi/btn_zoom_down_disabled.png
new file mode 100755
index 0000000..4e27dea
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_down_disabled.png differ
diff --git a/res/drawable-mdpi/btn_zoom_down_disabled_focused.png b/res/drawable-mdpi/btn_zoom_down_disabled_focused.png
new file mode 100755
index 0000000..2d416e0
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_down_disabled_focused.png differ
diff --git a/res/drawable-mdpi/btn_zoom_down_normal.png b/res/drawable-mdpi/btn_zoom_down_normal.png
new file mode 100755
index 0000000..b362a84
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_down_normal.png differ
diff --git a/res/drawable-mdpi/btn_zoom_down_pressed.png b/res/drawable-mdpi/btn_zoom_down_pressed.png
new file mode 100755
index 0000000..b2a2344
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_down_pressed.png differ
diff --git a/res/drawable-mdpi/btn_zoom_down_selected.png b/res/drawable-mdpi/btn_zoom_down_selected.png
new file mode 100755
index 0000000..2f694ff
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_down_selected.png differ
diff --git a/res/drawable-mdpi/btn_zoom_up_disabled.png b/res/drawable-mdpi/btn_zoom_up_disabled.png
new file mode 100755
index 0000000..7f54672
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_up_disabled.png differ
diff --git a/res/drawable-mdpi/btn_zoom_up_disabled_focused.png b/res/drawable-mdpi/btn_zoom_up_disabled_focused.png
new file mode 100755
index 0000000..25b14f8
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_up_disabled_focused.png differ
diff --git a/res/drawable-mdpi/btn_zoom_up_normal.png b/res/drawable-mdpi/btn_zoom_up_normal.png
new file mode 100755
index 0000000..7af5e0d
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_up_normal.png differ
diff --git a/res/drawable-mdpi/btn_zoom_up_pressed.png b/res/drawable-mdpi/btn_zoom_up_pressed.png
new file mode 100755
index 0000000..8cec199
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_up_pressed.png differ
diff --git a/res/drawable-mdpi/btn_zoom_up_selected.png b/res/drawable-mdpi/btn_zoom_up_selected.png
new file mode 100755
index 0000000..0bf543e
Binary files /dev/null and b/res/drawable-mdpi/btn_zoom_up_selected.png differ
diff --git a/res/drawable-mdpi/ic_menu_play_clip.png b/res/drawable-mdpi/ic_menu_play_clip.png
new file mode 100755
index 0000000..a8151fc
Binary files /dev/null and b/res/drawable-mdpi/ic_menu_play_clip.png differ
diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png
new file mode 100755
index 0000000..4118dbb
Binary files /dev/null and b/res/drawable-mdpi/icon.png differ
diff --git a/res/drawable-mdpi/stat_sys_download_anim0.png b/res/drawable-mdpi/stat_sys_download_anim0.png
new file mode 100755
index 0000000..44576fd
Binary files /dev/null and b/res/drawable-mdpi/stat_sys_download_anim0.png differ
diff --git a/res/drawable/mappaint.png b/res/drawable/mappaint.png
new file mode 100755
index 0000000..d3d81e5
Binary files /dev/null and b/res/drawable/mappaint.png differ
diff --git a/res/layout/download_progress.xml b/res/layout/download_progress.xml
new file mode 100755
index 0000000..5587011
--- /dev/null
+++ b/res/layout/download_progress.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+android:layout_width="fill_parent" android:layout_height="fill_parent"
+android:padding="5dp">
+<ImageView android:id="@+id/status_icon"
+android:layout_width="wrap_content" android:layout_height="fill_parent"
+android:layout_alignParentLeft="true" />
+
+<RelativeLayout android:layout_width="fill_parent"
+android:layout_height="fill_parent" android:layout_toRightOf="@id/status_icon">
+
+<TextView android:id="@+id/status_text" android:layout_width="fill_parent"
+android:layout_height="wrap_content" android:layout_alignParentTop="true" />
+<ProgressBar android:id="@+id/status_progress"
+android:layout_width="fill_parent" android:layout_height="wrap_content"
+android:layout_below="@id/status_text"
+android:progressDrawable="@android:drawable/progress_horizontal"
+android:indeterminate="false" android:indeterminateOnly="false" />
+
+
+</RelativeLayout>
+
+</RelativeLayout>
+
diff --git a/res/layout/map_help.xml b/res/layout/map_help.xml
new file mode 100755
index 0000000..f677469
--- /dev/null
+++ b/res/layout/map_help.xml
@@ -0,0 +1,107 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="#ffffff"
+ android:gravity="center_vertical|left"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- Here is where we put the SurfaceView, in a frame so that we can
+ stack other views on top of it. -->
+<!-- <FrameLayout
+ android:layout_width="fill_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"> -->
+ <TextView android:layout_width="fill_parent"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:text="Icons used in Gosmore:"
+ android:layout_height="0dip" android:layout_weight="1"
+ android:gravity="center_horizontal|center_horizontal"/>
+ <LinearLayout android:orientation="horizontal"
+ android:gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip" android:layout_weight="1">
+
+ <ImageView android:id="@+id/map_search"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:src="@android:drawable/ic_menu_search"/>
+ <TextView android:layout_width="wrap_content"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:layout_height="fill_parent"
+ android:text="Search"
+ android:gravity="left|center_vertical"/>
+</LinearLayout>
+ <LinearLayout android:orientation="horizontal"
+ android:gravity="center"
+ android:layout_height="0dip" android:layout_weight="1"
+ android:layout_width="wrap_content">
+ <ImageView android:id="@+id/map_recent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:src="@android:drawable/ic_menu_recent_history"/>
+ <TextView android:layout_width="wrap_content"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:layout_height="fill_parent"
+ android:text="Recent Searches"
+ android:gravity="left|center_vertical"/>
+</LinearLayout>
+ <LinearLayout android:orientation="horizontal"
+ android:gravity="center"
+ android:layout_height="0dip" android:layout_weight="1"
+ android:layout_width="wrap_content">
+
+ <ImageView android:id="@+id/mylocation"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentBottom="true"
+ android:src="@android:drawable/ic_menu_mylocation"/>
+ <TextView android:layout_width="wrap_content"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:layout_height="fill_parent"
+ android:text="My Location / Enable GPS"
+ android:gravity="center_vertical"/>
+</LinearLayout>
+ <LinearLayout android:orientation="horizontal"
+ android:layout_height="0dip" android:layout_weight="1"
+ android:gravity="center"
+ android:layout_width="wrap_content">
+
+ <ImageView android:id="@+id/zoom_out"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:src="@drawable/btn_zoom_down_normal"/>
+ <!-- android:visibility="gone" -->
+
+ <ImageView android:id="@+id/zoom_in"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:src="@drawable/btn_zoom_up_normal"/>
+ <TextView android:layout_width="wrap_content"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:layout_height="fill_parent"
+ android:text="Zoom"
+ android:gravity="center"/>
+</LinearLayout>
+
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="0dip" android:layout_weight="1"
+ android:textSize="20sp"
+ android:textColor="#000000"
+ android:text="Now press 'Back'"
+ android:gravity="center_horizontal|center_horizontal"/>
+</LinearLayout>
diff --git a/res/layout/map_view.xml b/res/layout/map_view.xml
new file mode 100755
index 0000000..cd34dae
--- /dev/null
+++ b/res/layout/map_view.xml
@@ -0,0 +1,67 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- Here is where we put the SurfaceView, in a frame so that we can
+ stack other views on top of it. -->
+<!-- <FrameLayout
+ android:layout_width="fill_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"> -->
+<RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <org.osmu.gosmore.MapView android:id="@+id/mapview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+ <ImageView android:id="@+id/map_search"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:src="@android:drawable/ic_menu_search"/>
+
+ <ImageView android:id="@+id/map_recent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:src="@android:drawable/ic_menu_recent_history"/>
+
+ <ImageView android:id="@+id/mylocation"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentBottom="true"
+ android:src="@android:drawable/ic_menu_mylocation"/>
+ <LinearLayout android:id="@+id/hidecontainer"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentBottom="true">
+
+ <ImageView android:id="@+id/zoom_out"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:src="@drawable/btn_zoom_down_normal"/>
+ <!-- android:visibility="gone" -->
+
+ <ImageView android:id="@+id/zoom_in"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:src="@drawable/btn_zoom_up_normal"/>
+
+ </LinearLayout>
+
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout/old_main.xml b/res/layout/old_main.xml
new file mode 100755
index 0000000..329c046
--- /dev/null
+++ b/res/layout/old_main.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+
+ <Button android:id="@+id/button_search"
+ android:text="Search" android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent" />
+
+ <Button android:id="@+id/button_map"
+ android:text="Map" android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent" />
+
+ <Button android:id="@+id/button_configure"
+ android:text="Configure" android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent" />
+
+ <Button android:id="@+id/button_update"
+ android:text="Update" android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent" android:enabled="false"/>
+
+</LinearLayout>
diff --git a/res/layout/search.xml b/res/layout/search.xml
new file mode 100755
index 0000000..e10c8a3
--- /dev/null
+++ b/res/layout/search.xml
@@ -0,0 +1,29 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView android:id="@+id/spacer"
+ android:layout_width="37dip"
+ android:layout_height="48dip" />
+
+ <EditText android:id="@+id/search_query"
+ android:singleLine="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionDone"
+ android:autoText="false"
+ android:hint="Search"/>
+</LinearLayout>
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"/>
+
+
+</LinearLayout>
diff --git a/res/layout/search_result.xml b/res/layout/search_result.xml
new file mode 100755
index 0000000..f37e78e
--- /dev/null
+++ b/res/layout/search_result.xml
@@ -0,0 +1,30 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView android:id="@+id/result_icon"
+ android:layout_alignParentLeft="true"
+ android:scaleType="center"
+ android:layout_width="48dip"
+ android:layout_height="48dip" />
+
+<!-- android:layout_weight="1.0"
+ android:layout_width="0dip"
+ android:layout_gravity="left"
+-->
+
+ <TextView android:id="@+id/distance"
+ android:layout_alignParentRight="true"
+ android:gravity="center_vertical|right"
+ android:textSize="18sp"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent" />
+
+ <TextView android:id="@+id/result_text"
+ android:layout_toRightOf="@+id/result_icon"
+ android:gravity="center_vertical|left"
+ android:textSize="18sp"
+ android:layout_toLeftOf="@+id/distance"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+</RelativeLayout>
diff --git a/res/layout/update.xml b/res/layout/update.xml
new file mode 100755
index 0000000..5514fb0
--- /dev/null
+++ b/res/layout/update.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ProgressBar android:id="@+id/update_progress"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:max="100"
+ android:progress="0"
+ android:secondaryProgress="0" />
+
+ <!-- <TextView android:id="@+id/update_description"
+ android:layout_width="wrap_content"
+ android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:text="Downloading the default overview map"
+ android:layout_gravity="center_horizontal"/> -->
+ <TextView android:id="@+id/update_msg"
+ android:layout_width="wrap_content"
+ android:textSize="30sp"
+ android:layout_height="wrap_content"
+ android:text="" android:layout_gravity="center_horizontal"/>
+ <Button android:id="@+id/cancel_update"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="30sp"
+ android:text="Cancel" android:layout_gravity="center_horizontal"/>
+</LinearLayout>
diff --git a/res/menu/map.xml b/res/menu/map.xml
new file mode 100755
index 0000000..d36fe2a
--- /dev/null
+++ b/res/menu/map.xml
@@ -0,0 +1,19 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/start_route"
+ android:title="Start Route"
+ android:icon="@drawable/ic_menu_play_clip" />
+
+ <item android:id="@+id/end_route"
+ android:title="End Route"
+ android:icon="@drawable/btn_square_overlay_normal" />
+
+ <item android:id="@+id/preferences"
+ android:title="Settings"
+ android:icon="@android:drawable/ic_menu_preferences" />
+ <item android:id="@+id/update"
+ android:title="Update"
+ android:icon="@drawable/stat_sys_download_anim0" />
+ <item android:id="@+id/about"
+ android:title="About"
+ android:icon="@android:drawable/ic_dialog_info" />
+</menu>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100755
index 0000000..1ea8458
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,38 @@
+<resources>
+<string-array name="vehicle_entries">
+ <item>Motorcar</item>
+ <item>Bicycle</item>
+ <item>Pedestrian</item>
+ <item>Goods Vehicle</item>
+ <item>Heavy Goods Vehicle</item>
+ <item>Horse</item>
+ <item>Motorcycle</item>
+ <item>Bus</item>
+ <item>Moped</item>
+ <item>Mofa</item>
+ <item>Motorboat</item>
+ <item>Boat</item>
+ </string-array>
+ <string-array name="vehicle_values">
+ <item>12</item>
+ <item>13</item>
+ <item>14</item>
+ <item>15</item>
+ <item>16</item>
+ <item>17</item>
+ <item>18</item>
+ <item>19</item>
+ <item>20</item>
+ <item>21</item>
+ <item>22</item>
+ <item>23</item>
+ </string-array>
+ <string-array name="tts_entries">
+ <item>None / Disabled</item>
+ <item>English</item>
+ </string-array>
+ <string-array name="tts_values">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100755
index 0000000..e8c943c
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- <string name="hello">Hello World, Gosmore!</string> -->
+ <string name="app_name">Gosmore</string>
+ <string name="fastest">Fastest Route</string>
+ <string name="summary_fastest">Not the shortest</string>
+ <string name="north2d">Orient Northwards in 2D</string>
+ <string name="summary_north2d">Don\'t use the compass in 2D</string>
+ <string name="vehicle">Vehicle</string>
+ <string name="summary_vehicle">Vehicle / Transport mode</string>
+ <string name="tts">Voice Language</string>
+ <string name="summary_tts">Text to Speech instructions</string>
+ <string name="routing_progress">Calculating Route</string>
+ <string name="cancel">Cancel</string> <!-- Routing and no map dialogs -->
+ <string name="ok">OK</string> <!-- About and no map dialogs -->
+ <string name="about_title">About</string>
+ <string name="about_msg">
+ Copyright (C) 2011 Nic Roets and Gosmore contributors. All rights reserved.\n
+ THIS SOFTWARE IS PROVIDED BY NIC ROETS ``AS IS\'\' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NIC ROETS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n
+
+ Some of the icons are copyright (c) 2005-2008, The Android Open Source Project\n
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.\n
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.\n\n
+
+ Some of the data bundled with or downloaded by this application fall
+ under the following copyright. When the application interprets this data,
+ it does not affects it\'s copyright, only the copyright of the output.\n\n
+ Map data (C) OpenStreetMap contributors CC-BY-SA\n
+ http://creativecommons.org/licenses/by-sa/2.0/\n\n
+ Map styles and icons (C) JOSM and Gosmore contributors under the GNU
+ General Public License version 2 or later\n\n
+ City names and locations in default map (C)
+ Geonames.org contributors CC-BY 3.0\n\n
+ </string>
+ <string name="no_location_title">No location specified</string>
+ <string name="no_location_msg">
+ To find your location tap the location button.\n\n
+ To find a city, tap the search button and enter the first few letters.</string>
+ <string name="first_map_title">Location acquired</string>
+ <string name="first_map_msg">Download the map for your area ?</string>
+ <string name="no_sdcard_title">No SD Card</string>
+ <string name="no_sdcard_msg">The external storage is not mounted.</string>
+</resources>
diff --git a/src/org/osmu/gosmore/Gosmore.java b/src/org/osmu/gosmore/Gosmore.java
new file mode 100755
index 0000000..295ac3a
--- /dev/null
+++ b/src/org/osmu/gosmore/Gosmore.java
@@ -0,0 +1,83 @@
+package org.osmu.gosmore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import android.app.Application;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class Gosmore extends Application {
+ public Bitmap icons;
+ public class Settings implements Serializable {
+ static final long serialVersionUID = 6618718669L;
+ ArrayList<Place> recent;
+ String search;
+ Place searchResult; // This is where the app stores the current place
+ }
+ public Settings s;
+ public int updateProgress = -1;
+ public String updateMsg;
+ public boolean cancelUpdate = true;
+ public ProgressBar updateBar;
+ public TextView updateMsgView;
+ public Button updateCancel;
+ static {
+ System.loadLibrary("gosmore");
+ }
+ @Override
+ public void onCreate() {
+ File f = new File(Environment.getExternalStorageDirectory(), "/gosmore/icons.png");
+ InputStream is;
+ try {
+ is = new FileInputStream(f);
+ } catch (FileNotFoundException e) {
+ is = getApplicationContext().getResources().openRawResource(R.drawable.mappaint);
+ }
+ try {
+ icons = BitmapFactory.decodeStream(is);
+ } finally {
+ try {
+ is.close();
+ } catch(IOException e) {
+ Log.w ("Gosmore", "Cannot read icons.png");
+ // Ignore.
+ }
+ }
+ try {
+ FileInputStream fis = openFileInput ("settings");
+ ObjectInputStream in = new ObjectInputStream (fis);
+ try {
+ s = new Settings();
+ s.recent = (ArrayList<Place>) in.readObject();
+ s.search = (String) in.readObject();
+ s.searchResult = (Place) in.readObject();
+ }
+ catch (ClassNotFoundException ex) {Log.w("Gosmore", "Settings file is corrupt");}
+ in.close();
+ } catch (IOException ex) {}//Log.d("gosmore", "Settings file not found");}
+ finally {
+ if (s == null) {
+ s = new Settings();
+ s.searchResult = new Place();
+ s.searchResult.lat = 0; // Set up reasonable defaults
+ s.searchResult.lon = 0;
+ s.searchResult.zoom = 1000000;
+ s.searchResult.dir = 0;
+ s.recent = new ArrayList<Place> ();
+ }
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/src/org/osmu/gosmore/MapActivity.java b/src/org/osmu/gosmore/MapActivity.java
new file mode 100755
index 0000000..0f185db
--- /dev/null
+++ b/src/org/osmu/gosmore/MapActivity.java
@@ -0,0 +1,726 @@
+package org.osmu.gosmore;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.hardware.GeomagneticField;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.SystemClock;
+import android.preference.PreferenceManager;
+import android.speech.tts.TextToSpeech;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.widget.ImageView;
+
+public class MapActivity extends Activity implements TextToSpeech.OnInitListener {
+ private MapView mGLView;
+ private native int changePak (String sd, int lat, int lon);
+ public int pakType = 0; // This is really just a boolean
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ requestWindowFeature(Window.FEATURE_PROGRESS);
+ /*// Uncomment for full screen
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);*/
+ if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) &&
+ !Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState())) {
+ Log.d("Gosmore", "("+Environment.getExternalStorageState() + " " + Environment.MEDIA_MOUNTED+")"+
+ (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED));
+ showDialog (5);
+ }
+ else {
+ File sd = new File (Environment.getExternalStorageDirectory(), "gosmore");
+ sd.mkdir ();
+ if ((pakType = changePak (sd.getAbsolutePath(), 0, 0)) == 0) {
+ Intent intent = new Intent (MapActivity.this, Update.class);
+ startActivity(intent);
+ setContentView(R.layout.map_help);
+ //finish();
+ }
+ else if (false) { // Set this to see if things are faster with ImageViews
+ // Fixme and uncomment mGLView = new MapView(this);
+ setContentView(mGLView);
+ }
+ else {
+ setContentView(R.layout.map_view);
+ mGLView = (MapView) findViewById(R.id.mapview);
+ mGLView.activity = this; // So that the view can show a dialog
+ //final MapRenderer mr = mGLView.mRenderer;
+ ImageView.OnTouchListener otl = new ImageView.OnTouchListener() {
+ public boolean onTouch (View v, MotionEvent m) {
+ if (m.getAction() == MotionEvent.ACTION_DOWN) {
+ mGLView.requestRender ();
+ mGLView.mRenderer.zExp = v.getId() ==
+ R.id.zoom_out ? 0.001f : -0.001f;
+ mGLView.mRenderer.zTime = SystemClock.uptimeMillis()-50;
+ }
+ if (m.getAction() == MotionEvent.ACTION_UP) {
+ long now = SystemClock.uptimeMillis();
+ mGLView.mRenderer.p.zoom = (int)(mGLView.mRenderer.p.zoom * Math.exp (mGLView.mRenderer.zExp * (now - mGLView.mRenderer.zTime)));
+ mGLView.mRenderer.zTime = 0;
+ }
+ return false;
+ }
+ };
+ ImageView oImageView = (ImageView) findViewById (R.id.zoom_out);
+ oImageView.setOnTouchListener(otl);
+ ImageView iImageView = (ImageView) findViewById (R.id.zoom_in);
+ iImageView.setOnTouchListener(otl);
+ ImageView mImageView = (ImageView) findViewById (R.id.mylocation);
+ mImageView.setOnClickListener(new ImageView.OnClickListener() {
+ public void onClick (View v) {
+ mGLView.mRenderer.follow = true;
+ mGLView.lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10f, mGLView);
+ mGLView.mSensorManager.registerListener(mGLView.magListener,
+ mGLView.mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
+ SensorManager.SENSOR_DELAY_NORMAL);
+ mGLView.mSensorManager.registerListener(mGLView.accListener,
+ mGLView.mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_UI);
+ }
+ });
+ ImageView sImageView = (ImageView) findViewById (R.id.map_search);
+ sImageView.setOnClickListener(new ImageView.OnClickListener() {
+ public void onClick (View v) {
+ Intent sintent = new Intent (MapActivity.this, Search.class);
+ startActivity(sintent);
+ }
+ });
+ ImageView rImageView = (ImageView) findViewById (R.id.map_recent);
+ rImageView.setOnClickListener(new ImageView.OnClickListener() {
+ public void onClick (View v) {
+ Intent intent = new Intent (MapActivity.this, Recent.class);
+ startActivity(intent);
+ }
+ });
+ mGLView.mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mGLView.lm = (LocationManager) getSystemService(LOCATION_SERVICE);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (!prefs.getString ("vehicle", "0").equals("0")) {
+ mGLView.mRenderer.mTts = new TextToSpeech(this, this);
+ }
+ }
+ } // External storage is mounted
+ //mGLView.setDebugFlags (GLSurfaceView.DEBUG_CHECK_GL_ERROR );
+ }
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inf = getMenuInflater();
+ inf.inflate(R.menu.map, (Menu)menu);
+ return true;
+ }
+ @Override
+ public Dialog onCreateDialog(int id) {
+ if (id == 1) {
+ mGLView.mRenderer.rProgress = new ProgressDialog(this);
+ //mGLView.mRenderer.rProgress.setIcon(R.drawable.alert_dialog_icon);
+ mGLView.mRenderer.rProgress.setTitle(R.string.routing_progress);
+ mGLView.mRenderer.rProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ //mGLView.mRenderer.rProgress.setMax(MAX_PROGRESS);
+ mGLView.mRenderer.rProgress.setButton(getText(R.string.cancel), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ mGLView.mRenderer.route = false;
+ }
+ });
+ return mGLView.mRenderer.rProgress;
+ }
+ else if (id == 2) {
+ return new AlertDialog.Builder(this)
+ //.setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.about_title)
+ .setMessage(R.string.about_msg)
+ .setPositiveButton(R.string.ok, null)
+ .create ();
+ }
+ else if (id == 3) {
+ return new AlertDialog.Builder(this)
+ //.setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.no_location_title)
+ .setMessage(R.string.no_location_msg)
+ .setPositiveButton(R.string.ok, null)
+ .create ();
+ }
+ else if (id == 4) {
+ return new AlertDialog.Builder(this)
+ //.setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.first_map_title)
+ .setMessage(R.string.first_map_msg)
+ .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ Intent intent = new Intent (MapActivity.this, Update.class);
+ startActivity(intent);
+ }
+ })
+ .setNegativeButton(R.string.cancel, null)
+ .create ();
+ }
+ else if (id == 5) {
+ return new AlertDialog.Builder(this)
+ //.setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.no_sdcard_title)
+ .setMessage(R.string.no_sdcard_msg)
+ .setPositiveButton(R.string.ok, null)
+ .create ();
+ }
+ return null;
+ }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.start_route) {
+ mGLView.mRenderer.startR = true;
+ mGLView.requestRender ();
+ }
+ else if (item.getItemId() == R.id.end_route) {
+ showDialog(1);
+ mGLView.mRenderer.route = true;
+ mGLView.requestRender();
+ }
+ else if (item.getItemId() == R.id.preferences) {
+ Intent sintent = new Intent (MapActivity.this, Preferences.class);
+ startActivity(sintent);
+ }
+ else if (item.getItemId() == R.id.update) {
+ Intent sintent = new Intent (MapActivity.this, Update.class);
+ startActivity(sintent);
+ }
+ else if (item.getItemId() == R.id.about) {
+ showDialog(2);
+ }
+ else return false;
+ return true;
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ Intent sintent = new Intent (MapActivity.this, Search.class);
+ startActivity(sintent);
+ return false;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ Gosmore g = (Gosmore)getApplicationContext();
+ try {
+ FileOutputStream fos = openFileOutput ("settings", Context.MODE_PRIVATE);
+ ObjectOutputStream out = new ObjectOutputStream (fos);
+ out.writeObject(g.s.recent); // Can't serialize a Setting
+ out.writeObject(g.s.search); // for some unknown reason.
+ out.writeObject(g.s.searchResult);
+ out.close();
+ } catch (IOException ex) { Log.w ("Gosmore", "Cannot write settings");}
+ if (mGLView != null && mGLView.mRenderer.follow) {
+ mGLView.mRenderer.follow = false;
+ mGLView.lm.removeUpdates(mGLView);
+ mGLView.mSensorManager.unregisterListener (mGLView.magListener);
+ mGLView.mSensorManager.unregisterListener (mGLView.accListener);
+ }
+ }
+
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ // Don't resume tracking automatically.
+ }
+ @Override
+ protected void onDestroy()
+ {
+ if (mGLView != null && mGLView.mRenderer.mTts != null) {
+ mGLView.mRenderer.mTts.stop();
+ mGLView.mRenderer.mTts.shutdown();
+ }
+ super.onDestroy();
+ }
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int result = mGLView.mRenderer.mTts.setLanguage(Locale.US);
+ mGLView.mRenderer.tts = result != TextToSpeech.LANG_MISSING_DATA &&
+ result != TextToSpeech.LANG_NOT_SUPPORTED;
+ }
+ }
+}
+
+class MapView extends GLSurfaceView implements LocationListener {
+ public LocationManager lm;
+ public SensorManager mSensorManager;
+ public MapActivity activity;
+ // ---- Location Listener methods ----
+ public void onLocationChanged(Location location) {
+ mRenderer.lonSum += location.getLongitude();
+ mRenderer.latSum += location.getLatitude();
+ mRenderer.latLonCnt++;
+
+ mRenderer.p.lat = location.getLatitude();
+ mRenderer.declination =
+ (int)(new GeomagneticField((float)location.getLatitude(),
+ (float)location.getLongitude(),(float)location.getAltitude(),
+ /*time:*/1300000000000L)).getDeclination();
+ mRenderer.bearing = location.getBearing();
+ mRenderer.speed = location.getSpeed();
+ mRenderer.doNavigate = true;
+ if (Math.abs (mRenderer.p.lon - mRenderer.lonSum / mRenderer.latLonCnt) * 2 +
+ Math.abs (mRenderer.p.lat - mRenderer.latSum / mRenderer.latLonCnt)
+ > .000164 / mRenderer.latLonCnt + 0.00004) {
+ mRenderer.p.lon = mRenderer.lonSum / mRenderer.latLonCnt;
+ mRenderer.p.lat = mRenderer.latSum / mRenderer.latLonCnt;
+ mRenderer.latLonCnt = 0;
+ mRenderer.lonSum = 0;
+ mRenderer.latSum = 0;
+ requestRender ();
+ }
+ }
+ public void onProviderDisabled(String provider) {}
+ public void onProviderEnabled(String provider) {}
+ public void onStatusChanged(String provider, int status, Bundle extras) {}
+ // ---- Location Listener methods ----
+
+ //public native void setLocation (double lon, double lat);
+
+ public MapView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mRenderer = new MapRenderer(context);
+ mRenderer.mIcons = ((Gosmore)context.getApplicationContext()).icons;
+ mRenderer.p = ((Gosmore)context.getApplicationContext()).s.searchResult;
+ mRenderer.mapView = this;
+ setRenderer(mRenderer);
+ setRenderMode (RENDERMODE_WHEN_DIRTY);
+ }
+ private float mPreviousX, mPreviousY, prevX2, prevY2;
+
+ @Override public boolean onTrackballEvent(MotionEvent e) {
+ mRenderer.mPixelX += e.getX() * 5.0 / 320;
+ mRenderer.mPixelY += e.getY() * 5.0 / 320;
+ requestRender();
+ if (mRenderer.follow) {
+ mRenderer.follow = false;
+ lm.removeUpdates(this);
+ mSensorManager.unregisterListener (magListener);
+ mSensorManager.unregisterListener (accListener);
+ }
+ return true;
+ }
+ private static Method getPointerCount, getPointerId, getX, getY;
+ static {
+ try {
+ getPointerCount = MotionEvent.class.getMethod("getPointerCount",
+ new Class[] {});
+ getPointerId = MotionEvent.class.getMethod("getPointerId",
+ new Class[] { int.class });
+ getX = MotionEvent.class.getMethod("getX",
+ new Class[] { int.class });
+ getY = MotionEvent.class.getMethod("getY",
+ new Class[] { int.class });
+ } catch (NoSuchMethodException nsme) {}
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent e) {
+ if (true) {//getPointerCount == null) {
+ float x = e.getX();
+ float y = e.getY();
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ mRenderer.mPixelX += (int)(x - mPreviousX);
+ mRenderer.mPixelY += (int)(y - mPreviousY);
+ if (mRenderer.follow) {
+ mRenderer.follow = false;
+ lm.removeUpdates(this);
+ mSensorManager.unregisterListener (magListener);
+ mSensorManager.unregisterListener (accListener);
+ }
+ /*Log.d("Gosmore", "zoom = " + mRenderer.p.zoom);
+ if (mRenderer.p.zoom < 100000000 && activity.pakType < 2) {
+ activity.showDialog(Math.abs(mRenderer.p.lat) < 1 &&
+ Math.abs(mRenderer.p.lon) < 1 ? 3 : 4);
+ }*/
+ }
+ // pid = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
+ mPreviousX = x;
+ mPreviousY = y;
+ }
+ else {
+ try {
+ int pcnt = (Integer) getPointerCount.invoke (e);
+ float x = (Float) getPointerCount.invoke (e, 0);
+ //getAction & MotionEvent.ACTION_MASK
+ } catch (InvocationTargetException ite) {}
+ catch (IllegalAccessException ie) {}
+ }
+ requestRender();
+ return true;
+ }
+ private float[] lastAccels=new float[3];
+
+ public SensorEventListener accListener=new SensorEventListener() {
+ public void onSensorChanged(SensorEvent e) {
+ System.arraycopy(e.values, 0, lastAccels, 0, 3);
+ }
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+ };
+
+ public final SensorEventListener magListener = new SensorEventListener() {
+ public void onSensorChanged(SensorEvent e) {
+ double g = Math.sqrt(lastAccels[0]*lastAccels[0]+lastAccels[1]*lastAccels[1]+
+ lastAccels[2]*lastAccels[2]);
+ if (g > 5) {// If we are not in (momentary) free fall
+ float east[] = { e.values[1]*lastAccels[2]-e.values[2]*lastAccels[1],
+ e.values[2]*lastAccels[0]-e.values[0]*lastAccels[2],
+ e.values[0]*lastAccels[1]-e.values[1]*lastAccels[0]};
+ mRenderer.threeD = lastAccels[2]*2 < g;
+ int d = (int)(180/Math.PI*(lastAccels[2]*2 < g
+ ? Math.atan2(east[2],(east[0]*lastAccels[1]-east[1]*lastAccels[0])/g)
+ : -Math.atan2((east[1]*lastAccels[2]-east[2]*lastAccels[1])/g, east[0])))
+ - mRenderer.declination;
+ mRenderer.dirSum += mRenderer.dirSum < 90 * mRenderer.dirCnt ?
+ (d + 540) % 360 - 180 : mRenderer.dirSum > 270 * mRenderer.dirCnt
+ ? (d + 540) % 360 + 180 : (d + 720) % 360;
+ mRenderer.dirCnt++;
+ if (Math.abs(mRenderer.dirSum / mRenderer.dirCnt - mRenderer.p.dir) >
+ 30 / mRenderer.dirCnt + 10) {
+ //Log.d("Gosmore", "Azimuth = " + mRenderer.p.dir);
+ mRenderer.p.dir = mRenderer.dirSum / mRenderer.dirCnt;
+ mRenderer.dirSum = 0;
+ mRenderer.dirCnt = 0;
+ requestRender();
+ }
+ }
+ /*float gg = lastAccels[0]*lastAccels[0]+lastAccels[1]*lastAccels[1]+
+ lastAccels[2]*lastAccels[2];
+ if (gg > 5*5) { // If we are not in (momentary) free fall
+ float p = (e.values[0]*lastAccels[0]+e.values[1]*lastAccels[1]+
+ e.values[2]*lastAccels[2])/gg;
+ mRenderer.p.dir = (int) ((lastAccels[2]*lastAccels[2]*3 > gg ? Math.atan2(e.values[0]-p*lastAccels[0], e.values[1] - p*lastAccels[1]) :
+ lastAccels[1]*lastAccels[1]*3 > gg ? Math.PI - Math.atan2(e.values[0]-p*lastAccels[0], e.values[2] - p*lastAccels[2]) :
+ Math.atan2(e.values[2]-p*lastAccels[2], e.values[1] - p*lastAccels[1]))
+ *(180/Math.PI)) - mRenderer.declination;
+ mRenderer.threeD = lastAccels[1]*lastAccels[1]*3 > gg;
+ requestRender();
+ }*/
+ }
+ public void onAccuracyChanged(Sensor s, int accuracy) {}
+ };
+
+ public MapRenderer mRenderer;
+}
+
+class MapRenderer implements GLSurfaceView.Renderer {
+ private int width, height;
+ public int mPixelX = 0, mPixelY = 0; // These are only modified by the UI thread
+ public int oldPixelX = 0, oldPixelY = 0;
+ public int bitmapWidth, bitmapHeight;
+ public int dirSum = 0, dirCnt = 0, latLonCnt = 0;
+ public long zTime = 0;
+ public float zExp, speed, bearing;
+ public double latSum = 0, lonSum = 0;
+ public Bitmap mBitmap, mIcons;
+ public Paint mClearPaint;
+ public Place p; // = Gosmore.s.searchResult
+ public MapView mapView;
+ public int mTextureID, icons;
+ public boolean route = false, startR = false, doNavigate = false;
+ public ProgressDialog rProgress;
+ public TextToSpeech mTts;
+ public boolean tts = false, follow = false;
+ //public Context mContext;
+ /*public class Btn { int x, y, w, h, draw; }
+ public Btn btn[] = {
+
+ }*/
+
+/* public float mTexelWidth; // Convert texel to U
+ public float mTexelHeight; // Convert texel to V
+ public int mU;
+ public int mV;
+ public int mLineHeight;
+*/ //public ArrayList<Label> mLabels = new ArrayList<Label>();
+
+ public Canvas mCanvas;
+ public Paint mTextPaint;
+ public boolean fast = false, threeD = false;
+ public int declination = 0;
+ public void drawTeks(String s, int x, int y, float sin, float cos) {
+ if (!fast) {
+ Matrix m = mCanvas.getMatrix ();
+ m.setSinCos (-sin, cos, x, y);
+ mCanvas.setMatrix (m);
+ mCanvas.drawText(s, x, y, mTextPaint);
+ }
+ }
+ public long last = 0, fps = 0, frame = 0;
+ public native void render (double lon, double lat, int dir, int zoom,
+ boolean threeD, boolean follow, int width, int height);
+ public native String navigate (double lon, double lat, float speed,
+ float bearing);
+ public native void startRoute (double lon, double lat);
+ public native void endRoute (double lon, double lat, boolean fastest,
+ int vehicle);
+ public native int doRoute ();
+ public MapRenderer(Context context) {
+ //mContext = context;
+ }
+ public SharedPreferences prefs;
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(false);
+ mTextPaint.setTextSize(16);
+ mTextPaint.setColor(Color.BLACK);//0xFF000000);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ //mTextPaint.setPadding(3, 3, 3, 3);
+ gl.glDisable(GL10.GL_DITHER);
+ gl.glClearColor(1f,1f,1f, 1f);
+ prefs = PreferenceManager.getDefaultSharedPreferences(mapView.getContext());
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ width = w;
+ height = h;
+ gl.glViewport(0, 0, w, h);
+ //lm = new LabelMaker (false, 64,64);
+ bitmapWidth = w - 1;
+ bitmapWidth |= bitmapWidth >> 1;
+ bitmapWidth |= bitmapWidth >> 2;
+ bitmapWidth |= bitmapWidth >> 4;
+ bitmapWidth |= bitmapWidth >> 8;
+ bitmapWidth++;
+ bitmapHeight = h - 1;
+ bitmapHeight |= bitmapHeight >> 1;
+ bitmapHeight |= bitmapHeight >> 2;
+ bitmapHeight |= bitmapHeight >> 4;
+ bitmapHeight |= bitmapHeight >> 8;
+ bitmapHeight++;
+/* mTexelWidth = (float) (1.0 / bitmapWidth);
+ mTexelHeight = (float) (1.0 / bitmapHeight);*/
+ mClearPaint = new Paint();
+ mClearPaint.setARGB(0, 0, 0, 0);
+ mClearPaint.setStyle(Style.FILL);
+
+ //initialize(gl);
+ int[] textures = new int[2];
+ gl.glGenTextures(2, textures, 0);
+ mTextureID = textures[1];
+ icons = textures[0];
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+
+ // Use Nearest for performance.
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_NEAREST);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_CLAMP_TO_EDGE);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_CLAMP_TO_EDGE);
+
+ gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_REPLACE); // GL_MODULATE also works here.
+
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, icons);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_NEAREST);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_CLAMP_TO_EDGE);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_CLAMP_TO_EDGE);
+
+ gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_REPLACE); // GL_MODULATE also works here.
+ //int iw = mIcons.getWidth();
+ //int ih = mIcons.getHeight();
+ /*int[] pixels = new int[iw*ih];
+ mIcons.getPixels(pixels, 0, iw, 0, 0, iw, ih);
+ mBitmap = Bitmap.createBitmap(pixels, 0, iw, iw, ih,
+ Bitmap.Config.ARGB_8888);*/
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mIcons, 0);
+
+ mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, //Bitmap.Config.ARGB_4444);
+ Bitmap.Config.ALPHA_8);
+ mCanvas = new Canvas(mBitmap);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ if (startR) {
+ startRoute (p.lon, p.lat);
+ startR = false;
+ }
+ if (route) {
+ //Log.d ("Gosmore", "start route");
+ endRoute (p.lon, p.lat, prefs.getBoolean ("fastest", true),
+ Integer.parseInt(prefs.getString ("vehicle", "12")));
+ int p;
+ while ((p = doRoute()) < 999 && p >= 0 && route) rProgress.setProgress (p);
+ route = false;
+ //Log.d ("Gosmore", "p = " + p);
+ rProgress.dismiss();
+ }
+ if (doNavigate) {
+ doNavigate = false;
+ String msg = navigate (p.lon, p.lat, speed, bearing);
+ if (msg != "" && tts) mTts.speak(msg, TextToSpeech.QUEUE_FLUSH, null);
+ }
+
+ gl.glViewport(0,0,width,height);
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+
+ gl.glOrthof(0.0f,width,height,0.0f,-1.0f,1.0f);
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW); // Really necessary ?
+ gl.glLoadIdentity(); // Really necessary ?
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
+ gl.glDisable(GL10.GL_DEPTH_TEST);
+
+ if (!fast) mBitmap.eraseColor(0); // I don't think this can be done with drawRect,
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glDisable(GL10.GL_TEXTURE_2D);
+
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, icons);
+ gl.glShadeModel(GL10.GL_FLAT);
+// gl.glEnable(GL10.GL_BLEND);
+ //gl.glEnable(GL10.GL_LINE_SMOOTH); // If this is enabled on the LG OO,
+ // all lines will have width 1.
+
+ //gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+ // Not sure what this does.
+
+ //mouseEv (mPixelX, mPixelY, 0, 1, false);
+ if (zTime != 0) {
+ long now = SystemClock.uptimeMillis();
+ p.zoom = (int)(p.zoom * Math.exp (zExp * (now - zTime)));
+ zTime = now;
+ mapView.requestRender();
+ }
+ if (p.zoom < 999) p.zoom = 999;
+ else if (p.zoom > 500000000) p.zoom = 500000000;
+ double z = 360.0 / 4294967296.0 * (threeD ? 10000 : p.zoom) / width;
+ if (!threeD && prefs.getBoolean ("north2d", false)) p.dir = 0;
+ int diffY = threeD ? 0 : mPixelY-oldPixelY;
+ p.lat += z * (diffY * Math.cos(Math.PI/180*p.dir) +
+ (oldPixelX-mPixelX)*Math.sin(Math.PI/180*p.dir));
+ p.lon += z * ((oldPixelX-mPixelX)*Math.cos(Math.PI/180*p.dir) -
+ diffY*Math.sin(Math.PI/180*p.dir))
+ / Math.cos(Math.PI/180*p.lat);
+ if (threeD) p.dir += mPixelY - oldPixelY;
+ oldPixelX = mPixelX;
+ oldPixelY = mPixelY;
+ render(p.lon, p.lat, p.dir, threeD ? 50000 : p.zoom, threeD, follow, width, height);
+
+ /*long now = System.currentTimeMillis();
+ drawTeks (fps + "", 10, 250, 0, 1);
+ if (now - last > 1000) {
+ fps = frame;
+ frame = 0;
+ last = now;
+ }
+ else frame++;*/
+
+ if (!fast) {
+ gl.glEnable(GL10.GL_BLEND);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ //gl.glShadeModel(GL10.GL_FLAT);
+ gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+
+/* gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ gl.glOrthof(0.0f, width, 0.0f, height, 0.0f, 1.0f);
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ // Magic offsets to promote consistent rasterization.
+ gl.glTranslatef(0.375f, 0.375f, 0.0f);
+// beginDrawing(gl, width, height);
+ gl.glPushMatrix();*/
+ /*float snappedX = 10;
+ float snappedY = 10;
+ gl.glTranslatef(snappedX, snappedY, 0.0f);*/
+ //Label label = mLabels.get(id);
+ //Log.d("Gosmore", "w" + mBitmap.getWidth() + " h" + mBitmap.getHeight() + " x"+mBitmap.getRowBytes());
+ //Log.d("Gosmore", "w" + mIcons.getWidth() + " h" + mIcons.getHeight() + " x"+mIcons.getRowBytes());
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, icons);
+
+/* GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mIcons, 0);
+ //mBitmap2.recycle();
+
+ int[] crop2 = { 0, height - 1, width - 1, -height + 1 };
+ ((GL11)gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
+ GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop2, 0); //label.mCrop, 0);
+ gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+ ((GL11Ext)gl).glDrawTexiOES((int) 1, (int) 1, 0,
+ (int) width - 1, (int) height - 1);
+*/
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
+
+ int[] crop = { 0, height - 1, width - 1, -height + 1 };
+ ((GL11)gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
+ GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop, 0); //label.mCrop, 0);
+ gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+ ((GL11Ext)gl).glDrawTexiOES((int) 1, (int) 1, 0,
+ (int) width - 1, (int) height - 1);
+ ((GL11Ext)gl).glDrawTexiOES((int) -1, (int) -1, 0,
+ (int) width - 1, (int) height - 1);
+ gl.glColor4x(0,0,0,0x10000);//0x10000, 0x10000, 0x10000, 0x10000);
+ ((GL11Ext)gl).glDrawTexiOES((int) 0, (int) 0, 0,
+ (int) width - 1, (int) height - 1);
+ /*gl.glPopMatrix();
+
+ gl.glDisable(GL10.GL_BLEND);
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glPopMatrix();
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glPopMatrix();*/
+ }
+ /*
+ draw(gl, 10, 10, id);*/
+// endDrawing(gl);
+ }
+}
diff --git a/src/org/osmu/gosmore/Place.java b/src/org/osmu/gosmore/Place.java
new file mode 100755
index 0000000..cfccd3f
--- /dev/null
+++ b/src/org/osmu/gosmore/Place.java
@@ -0,0 +1,10 @@
+package org.osmu.gosmore;
+
+import java.io.Serializable;
+
+public class Place implements Serializable {
+ static final long serialVersionUID = 6618718668L;
+ double lat, lon;
+ int zoom, dir; // Currently dir is always 0
+ String name;
+}
diff --git a/src/org/osmu/gosmore/Preferences.java b/src/org/osmu/gosmore/Preferences.java
new file mode 100755
index 0000000..963215c
--- /dev/null
+++ b/src/org/osmu/gosmore/Preferences.java
@@ -0,0 +1,54 @@
+package org.osmu.gosmore;
+
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+
+public class Preferences extends PreferenceActivity {
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setPreferenceScreen(createPreferenceHierarchy());
+ }
+
+ private PreferenceScreen createPreferenceHierarchy() {
+ PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
+/* PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
+ inlinePrefCat.setTitle(R.string.inline_preferences);
+ root.addPreference(inlinePrefCat);*/
+
+ CheckBoxPreference fastest = new CheckBoxPreference(this);
+ fastest.setDefaultValue(true);
+ fastest.setKey("fastest");
+ fastest.setTitle(R.string.fastest);
+ fastest.setSummary(R.string.summary_fastest);
+ root.addPreference(fastest);
+
+ CheckBoxPreference north2d = new CheckBoxPreference(this);
+ north2d.setKey("north2d");
+ north2d.setTitle(R.string.north2d);
+ north2d.setSummary(R.string.summary_north2d);
+ root.addPreference(north2d);
+
+ ListPreference vehicle = new ListPreference(this);
+ vehicle.setEntries(R.array.vehicle_entries);
+ vehicle.setEntryValues(R.array.vehicle_values);
+ vehicle.setDialogTitle(R.string.vehicle);
+ vehicle.setKey("vehicle");
+ vehicle.setTitle(R.string.vehicle);
+ vehicle.setSummary(R.string.summary_vehicle);
+ /*dialogBasedPrefCat*/ root.addPreference(vehicle);
+
+ ListPreference ttsLocale = new ListPreference(this);
+ ttsLocale.setEntries(R.array.tts_entries);
+ ttsLocale.setEntryValues(R.array.tts_values);
+ ttsLocale.setDialogTitle(R.string.tts);
+ ttsLocale.setKey("tts");
+ ttsLocale.setTitle(R.string.tts);
+ ttsLocale.setSummary(R.string.summary_tts);
+ /*dialogBasedPrefCat*/ root.addPreference(ttsLocale);
+ return root;
+ }
+}
\ No newline at end of file
diff --git a/src/org/osmu/gosmore/Recent.java b/src/org/osmu/gosmore/Recent.java
new file mode 100755
index 0000000..05b3ee0
--- /dev/null
+++ b/src/org/osmu/gosmore/Recent.java
@@ -0,0 +1,31 @@
+package org.osmu.gosmore;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class Recent extends ListActivity {
+ protected void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Gosmore g = (Gosmore)getApplicationContext();
+ g.s.searchResult.lat = g.s.recent.get(g.s.recent.size()-1-position).lat;
+ g.s.searchResult.lon = g.s.recent.get(g.s.recent.size()-1-position).lon;
+ g.s.searchResult.dir = g.s.recent.get(g.s.recent.size()-1-position).dir;
+ g.s.searchResult.zoom = g.s.recent.get(g.s.recent.size()-1-position).zoom;
+ finish(); // Easier way to do a deep copy ?
+ }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ //setContentView(R.layout.search);
+ Gosmore g = ((Gosmore)getApplicationContext());
+ String names[] = new String[g.s.recent.size()];
+ for (int i = 0; i < g.s.recent.size(); i++) {
+ names[g.s.recent.size()-1-i] = g.s.recent.get(i).name;
+ }
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, names));
+ }
+}
diff --git a/src/org/osmu/gosmore/Search.java b/src/org/osmu/gosmore/Search.java
new file mode 100755
index 0000000..658fbb7
--- /dev/null
+++ b/src/org/osmu/gosmore/Search.java
@@ -0,0 +1,131 @@
+package org.osmu.gosmore;
+
+import java.util.ArrayList;
+
+import android.app.ListActivity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+public class Search extends ListActivity implements TextWatcher {
+ public Search ()
+ {
+ super();
+ adap = new EfficientAdapter ();
+ }
+ private EfficientAdapter adap;
+ private EditText et;
+
+ //---- It's also a TextWatcher for the EditText
+ public void afterTextChanged (Editable s){
+ adap.results.clear();
+ this.search (et.getText().toString());
+ setListAdapter(adap);
+ }
+ public void beforeTextChanged (CharSequence s, int start, int count, int after){}
+ public void onTextChanged (CharSequence s, int start, int before, int count){}
+ //---- End TextWatcher
+
+ protected void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Gosmore g = (Gosmore)getApplicationContext();
+ g.s.searchResult.lat = adap.results.get(position).lat;
+ g.s.searchResult.lon = adap.results.get(position).lon;
+ g.s.searchResult.zoom = adap.results.get(position).zoom;
+ g.s.searchResult.dir = 0;
+ g.s.searchResult.name = adap.results.get(position).s;
+ Place p = new Place();
+ p.lat = g.s.searchResult.lat;
+ p.lon = g.s.searchResult.lon;
+ p.zoom = g.s.searchResult.zoom;
+ p.dir = g.s.searchResult.dir;
+ p.name = g.s.searchResult.name;
+ g.s.recent.add(p);
+ if (g.s.recent.size() > 40) g.s.recent.remove(0);
+ g.s.search = et.getText().toString();
+ finish();
+ }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.search);
+ adap.icons = ((Gosmore)getApplicationContext()).icons;
+ adap.mInflater = getLayoutInflater();
+
+ et = (EditText) findViewById (R.id.search_query);
+ //et.setInputType(InputType.TYPE_CLASS_TEXT|0x00080000);
+ et.addTextChangedListener(this);
+ et.setText(((Gosmore)getApplicationContext()).s.search);
+ afterTextChanged (null);
+ et.requestFocus();//|0x00080000
+ }
+ //public int zoom;
+ //public native void setLocation (double lon, double lat);
+ public native void search (String s);
+ public void searchResult(int x, int y, int w, int h,
+ double dist, int u, int v, String s,
+ double lon, double lat, int _zoom) {
+ adap.results.add(new ResultData());
+ adap.results.get(adap.results.size()-1).x = x;
+ adap.results.get(adap.results.size()-1).y = y;
+ adap.results.get(adap.results.size()-1).w = w;
+ adap.results.get(adap.results.size()-1).h = h;
+ adap.results.get(adap.results.size()-1).dist = dist;
+ adap.results.get(adap.results.size()-1).s = s;
+ adap.results.get(adap.results.size()-1).v = v;
+ adap.results.get(adap.results.size()-1).u = u;
+ adap.results.get(adap.results.size()-1).lon = lon;
+ adap.results.get(adap.results.size()-1).lat = lat;
+ adap.results.get(adap.results.size()-1).zoom = _zoom;
+ }
+}
+
+class ResultData {
+ public ResultData () {}
+ public double dist, lon, lat;
+ public String s;
+ public int u, v, x, y, w, h, zoom;
+}
+
+class EfficientAdapter extends BaseAdapter {
+ public LayoutInflater mInflater;
+ public ArrayList<ResultData> results;
+ public Bitmap icons;
+ public EfficientAdapter() {
+ // Cache the LayoutInflate to avoid asking for a new one each time.
+ results = new ArrayList<ResultData>();
+ }
+ public int getCount() {
+ return results.size();
+ }
+ public Object getItem(int position) {
+ return position;
+ }
+ public long getItemId(int position) {
+ return position;
+ }
+ public View getView(int position, View convertView, ViewGroup parent) {
+ //if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.search_result, null);
+ TextView t = (TextView) convertView.findViewById(R.id.result_text);
+ t.setText(results.get(position).s);
+ TextView d = (TextView) convertView.findViewById(R.id.distance);
+ double dist = results.get(position).dist;
+ d.setText(dist >= 998 ? "Far " : dist > 1 ? (int) dist + " km " :
+ (int)(dist*1000) + " m ");
+ ImageView i = (ImageView) convertView.findViewById(R.id.result_icon);
+ if (results.get(position).w > 0) i.setImageBitmap(Bitmap.createBitmap(icons,results.get(position).x,
+ results.get(position).y, results.get(position).w, results.get(position).h));
+ return convertView;
+ }
+}
\ No newline at end of file
diff --git a/src/org/osmu/gosmore/Update.java b/src/org/osmu/gosmore/Update.java
new file mode 100755
index 0000000..cc9a1f1
--- /dev/null
+++ b/src/org/osmu/gosmore/Update.java
@@ -0,0 +1,243 @@
+package org.osmu.gosmore;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.StatFs;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+public class Update extends Activity implements LocationListener {
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_PROGRESS);
+ setContentView(R.layout.update);
+ setProgressBarVisibility(true);
+
+ String code = currentBbox ();
+
+ //if (!code.equals("default")) ((TextView) findViewById(R.id.update_description)).setText (code);
+ if (((Gosmore) getApplication()).updateProgress >= 0) {
+ ((TextView) findViewById(R.id.update_msg)).setText(
+ ((Gosmore) getApplication()).updateMsg);
+ }
+ else if (code.equals("")) {
+ ((Gosmore)getApplication()).updateMsg = "Cannot update a custom map";
+ }
+ else {
+ //else ((TextView) findViewById(R.id.update_description)).setText (R.string.default_update);
+ final UpdateTask dft;
+ dft = new UpdateTask ();
+ dft.gosmore = (Gosmore) getApplication();
+ dft.gosmore.updateProgress = 0;
+ dft.gosmore.cancelUpdate = false;
+ setProgress(0); // Redundant ?
+ if (dft.gosmore.s.searchResult.lon == 0 && dft.gosmore.s.searchResult.lat == 0) {
+ // New install. Center the view in anticipation of the initial download.
+ ((LocationManager) getSystemService(LOCATION_SERVICE)).requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 10f, this);
+ }
+
+ dft.notification = new Notification(R.drawable.icon, "Downloading Map", System.currentTimeMillis());
+ dft.notification.flags = dft.notification.flags | Notification.FLAG_ONGOING_EVENT;
+ dft.notification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_progress);
+ dft.notification.contentIntent = /*pendingIntent;*/ PendingIntent.getActivity(this, 0, new Intent(this, Update.class), 0);
+ //notification.contentView.setImageViewResource(R.id.status_icon, R.drawable.ic_menu_save);
+ dft.notification.contentView.setTextViewText(R.id.status_text, "Downloading map");
+ //notification.contentView.setProgressBar(R.id.status_progress, 100, progress, false);
+
+ //notification.setLatestEventInfo(getApplicationContext(), "Downloading", "Map", contentIntent);
+ dft.nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ dft.nm.notify (1, dft.notification);
+ dft.execute(code);
+ }
+ ((Button)findViewById(R.id.cancel_update)).setOnClickListener(new Button.OnClickListener() {
+ public void onClick (View v) {
+ ((Gosmore)getApplication()).cancelUpdate = true;
+ }
+ });
+ }
+ // ---- Location Listener methods ----
+ public void onLocationChanged(Location location) {
+ ((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
+ ((Gosmore) getApplication()).s.searchResult.lon = location.getLongitude();
+ ((Gosmore) getApplication()).s.searchResult.lat = location.getLatitude();
+ ((Gosmore) getApplication()).s.searchResult.zoom = 4000000;
+ }
+ public void onProviderDisabled(String provider) {}
+ public void onProviderEnabled(String provider) {}
+ public void onStatusChanged(String provider, int status, Bundle extras) {}
+ // ---- Location Listener methods ----
+
+ protected void onResume()
+ {
+ super.onResume();
+ ProgressBar pb = (ProgressBar) findViewById(R.id.update_progress);
+ pb.setProgress(((Gosmore)getApplication()).updateProgress);
+ ((Gosmore)getApplication()).updateBar = pb;
+ ((Gosmore)getApplication()).updateMsgView = ((TextView) findViewById(R.id.update_msg));
+ ((Gosmore)getApplication()).updateMsgView.setText(((Gosmore)getApplication()).updateMsg);
+ ((Gosmore)getApplication()).updateCancel = ((Button) findViewById(R.id.cancel_update));
+ if (((Gosmore)getApplication()).cancelUpdate) ((Gosmore)getApplication()).updateCancel.setEnabled(false);
+ }
+ protected void onDestroy ()
+ {
+ ((Gosmore)getApplication()).updateBar = null;
+ ((Gosmore)getApplication()).updateMsgView = null;
+ ((Gosmore)getApplication()).updateCancel = null;
+ super.onDestroy ();
+ }
+ private native String currentBbox ();
+}
+
+class UpdateTask extends AsyncTask<String, Integer, String> {
+ public Gosmore gosmore;
+ Notification notification;
+ NotificationManager nm;
+ protected String doInBackground(String... code) {
+ PipedInputStream in = new PipedInputStream();
+ File sd = Environment.getExternalStorageDirectory();
+ final long modifiedTm = (new File (sd, "/gosmore/" + code[0] + ".pak")).lastModified();
+ try {
+ final String myurl = "http://dev.openstreetmap.de/gosmore/" + code[0] + ".zip";
+ final PipedOutputStream out = new PipedOutputStream(in);
+ new Thread(
+ new Runnable(){
+ public void run(){
+ for (int downloaded = 0, l = 1, count; l > 0 && !gosmore.cancelUpdate;) {
+ try {
+ URL u = new URL(myurl);
+ URLConnection cx = u.openConnection();
+ cx.setRequestProperty("Range", "bytes=" + downloaded + "-");
+ cx.setReadTimeout(60000);
+ cx.setConnectTimeout(60000);
+ //cx.connect(); // getContentLen will do it for us.
+ if ((l = cx.getContentLength()) > 0) {
+ Log.d("Gosmore", "Start "+cx.getLastModified()+" len "+modifiedTm);
+ if (cx.getLastModified() < modifiedTm) {
+ l = 0;
+ break;
+ }
+ //Log.d("Gosmore", "Start "+downloaded+" len "+l + " "+ cx.getHeaderField("Accept-Ranges")+ " " + cx.getResponseCode());
+ InputStream is = cx.getInputStream();
+ byte[] buf = new byte[1500];
+ for (; (count=is.read(buf, 0, 1500)) != -1; l-=count) {
+ if(count > 0) out.write(buf,0,count);
+ downloaded += count;
+ }
+ }
+ else l = 1;
+ } catch (MalformedURLException mue) {
+ gosmore.updateMsg = "Bad URL. Retrying.";
+ } catch (IOException ioe) {
+ gosmore.updateMsg = "Network Error. Retrying.";
+ } catch (SecurityException se) {
+ gosmore.updateMsg = "Security error. Retrying.";
+ }
+ try {
+ if (l > 0) Thread.sleep (1);
+ } catch(InterruptedException e) {}
+ }
+ Log.d("Gosmore", "Leaving download thread "+gosmore.cancelUpdate);
+ try { out.close(); } catch (IOException ioe) {}
+ }
+ }
+ ).start();
+ } catch(IOException a) {Log.d ("Gosmore", "1st");}
+ Log.d ("Gosmore", "a");
+ try {
+ byte[] buffer = new byte[1024];
+ ZipInputStream dis = new ZipInputStream (in);
+ ZipEntry entry;
+
+ int length, done = 0;
+ Log.d ("Gosmore", "b");
+ if ((entry = dis.getNextEntry()) != null) {
+ Log.d ("Gosmore", "c");
+ StatFs stat = new StatFs (sd.getPath());
+ if (stat.getAvailableBlocks() * (long) stat.getBlockSize() <
+ entry.getSize()) {
+ gosmore.updateMsg = "Error: At least " +
+ (entry.getSize() / 1024/1024) + "MB storage space is needed";
+ publishProgress(-1);
+ }
+ else {
+ gosmore.updateMsg = "" + (int)(entry.getSize()/(2048*1024))+ " MB";
+ publishProgress(-1);
+ File f = new File(sd, "/gosmore/tmp.pak");
+ FileOutputStream fos = new FileOutputStream(f);
+ while (!gosmore.cancelUpdate && (length = dis.read(buffer)) != -1) {
+ fos.write(buffer, 0, length);
+ if ((done >> 20) < ((done + length) >> 20)) {
+ publishProgress(done / (int)(entry.getSize() / 100));
+ notification.contentView.setProgressBar(R.id.status_progress, 100, done / (int)(entry.getSize() / 100), false);
+ nm.notify(1, notification);
+ }
+ done += length;
+ }
+ fos.close();
+ //Log.d("Gosmore", "k" + done + " " + entry.getSize());
+ if (done == entry.getSize()) {
+ File to = new File (sd, "/gosmore/" + code[0] + ".pak");
+ f.renameTo(to);
+ gosmore.updateMsg = "Download successful.";
+ }
+ else gosmore.updateMsg = "Download incomplete. Aborting";
+ Log.d ("Gosmore", "a");
+ } // There was enough space with we started.
+ } // The zip looks valid
+ else gosmore.updateMsg = gosmore.cancelUpdate ? "Update cancelled" :
+ "No new map available."; // Empty file.
+ } catch (IOException ioe) {
+ gosmore.updateMsg = "File Error";
+ } catch (SecurityException se) {
+ gosmore.updateMsg = "Security error";
+ }
+ //publishProgress(100);
+ nm.cancel (1);
+ gosmore.updateProgress = -1; // Ready for a new update
+ return null;
+ }
+
+ protected void onProgressUpdate(Integer... progress) {
+ if (progress[0] >= 0) {
+ if (gosmore.updateBar != null) gosmore.updateBar.setProgress(progress[0]);
+ gosmore.updateProgress = progress[0];
+ }
+ else if (gosmore.updateMsgView != null) {
+ gosmore.updateMsgView.setText(gosmore.updateMsg);
+ }
+ }
+
+ protected void onPostExecute(String result) {
+ Log.d ("Gosmore", gosmore.updateMsg + (gosmore.updateMsgView != null ? " view" : " noview"));
+ if (gosmore.updateMsgView != null) gosmore.updateMsgView.setText(gosmore.updateMsg);
+ if (gosmore.updateCancel != null) gosmore.updateCancel.setEnabled(false);
+ gosmore.cancelUpdate = true;
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gosmore.git
More information about the Pkg-grass-devel
mailing list