test search roads functionality

git-svn-id: https://osmand.googlecode.com/svn/trunk@850 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
vics001 2010-12-23 10:55:35 +00:00
parent 5a25fe2599
commit 6236cace53
8 changed files with 1889 additions and 51 deletions

View file

@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001, Eric D. Friedman All Rights Reserved.
// Copyright (c) 2009, Rob Eden All Rights Reserved.
// Copyright (c) 2009, Jeff Randall All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
///////////////////////////////////////////////////////////////////////////////
package gnu.trove.iterator;
//////////////////////////////////////////////////
// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! //
//////////////////////////////////////////////////
/**
* Iterator for maps of type long and Object.
* <p/>
* The iterator semantics for Trove's primitive maps is slightly different
* from those defined in <tt>java.util.Iterator</tt>, but still well within
* the scope of the pattern, as defined by Gamma, et al.
* <p/>
* This iterator does <b>not</b> implicitly advance to the next entry when
* the value at the current position is retrieved. Rather, you must explicitly
* ask the iterator to <tt>advance()</tt> and then retrieve either the <tt>key()</tt>,
* the <tt>value()</tt> or both. This is done so that you have the option, but not
* the obligation, to retrieve keys and/or values as your application requires, and
* without introducing wrapper objects that would carry both. As the iteration is
* stateful, access to the key/value parts of the current map entry happens in
* constant time.
* <p/>
* In practice, the iterator is akin to a "search finger" that you move from
* position to position. Read or write operations affect the current entry only and
* do not assume responsibility for moving the finger.
* <p/>
* Here are some sample scenarios for this class of iterator:
* <p/>
* <pre>
* // accessing keys/values through an iterator:
* for ( TLongObjectIterator it = map.iterator(); it.hasNext(); ) {
* it.advance();
* if ( satisfiesCondition( it.key() ) ) {
* doSomethingWithValue( it.value() );
* }
* }
* </pre>
* <p/>
* <pre>
* // modifying values in-place through iteration:
* for ( TLongObjectIterator it = map.iterator(); it.hasNext(); ) {
* it.advance();
* if ( satisfiesCondition( it.key() ) ) {
* it.setValue( newValueForKey( it.key() ) );
* }
* }
* </pre>
* <p/>
* <pre>
* // deleting entries during iteration:
* for ( TLongObjectIterator it = map.iterator(); it.hasNext(); ) {
* it.advance();
* if ( satisfiesCondition( it.key() ) ) {
* it.remove();
* }
* }
* </pre>
* <p/>
* <pre>
* // faster iteration by avoiding hasNext():
* TLongObjectIterator iterator = map.iterator();
* for ( int i = map.size(); i-- > 0; ) {
* iterator.advance();
* doSomethingWithKeyAndValue( iterator.key(), iterator.value() );
* }
* </pre>
*
* @author Eric D. Friedman
* @author Rob Eden
* @author Jeff Randall
* @version $Id: _E_ObjectIterator.template,v 1.1.2.1 2009/09/15 02:38:31 upholderoftruth Exp $
*/
public interface TLongObjectIterator<V> extends TAdvancingIterator {
/**
* Provides access to the key of the mapping at the iterator's position.
* Note that you must <tt>advance()</tt> the iterator at least once
* before invoking this method.
*
* @return the key of the entry at the iterator's current position.
*/
public long key();
/**
* Provides access to the value of the mapping at the iterator's position.
* Note that you must <tt>advance()</tt> the iterator at least once
* before invoking this method.
*
* @return the value of the entry at the iterator's current position.
*/
public V value();
/**
* Replace the value of the mapping at the iterator's position with the
* specified value. Note that you must <tt>advance()</tt> the iterator at
* least once before invoking this method.
*
* @param val the value to set in the current entry
* @return the old value of the entry.
*/
public V setValue( V val );
}

View file

@ -0,0 +1,425 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001, Eric D. Friedman All Rights Reserved.
// Copyright (c) 2009, Rob Eden All Rights Reserved.
// Copyright (c) 2009, Jeff Randall All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
///////////////////////////////////////////////////////////////////////////////
package gnu.trove.map;
import gnu.trove.iterator.TLongObjectIterator;
import gnu.trove.procedure.TLongProcedure;
import gnu.trove.procedure.TObjectProcedure;
import gnu.trove.procedure.TLongObjectProcedure;
import gnu.trove.function.TObjectFunction;
import gnu.trove.set.TLongSet;
import java.util.Collection;
import java.util.Map;
//////////////////////////////////////////////////
// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! //
//////////////////////////////////////////////////
/**
* Interface for a primitive map of long keys and Object values.
*/
public interface TLongObjectMap<V> {
// Query Operations
/**
* Returns the value that represents null in the {@link #keySet()}.
* The default value is generally zero, but can be changed during
* construction of the collection.
*
* @return the value that represents a null value in this collection.
*/
long getNoEntryKey();
/**
* Returns the number of key-value mappings in this map. If the
* map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* @return the number of key-value mappings in this map
*/
int size();
/**
* Returns <tt>true</tt> if this map contains no key-value mappings.
*
* @return <tt>true</tt> if this map contains no key-value mappings
*/
boolean isEmpty();
/**
* Returns <tt>true</tt> if this map contains a mapping for the specified
* key. More formally, returns <tt>true</tt> if and only if
* this map contains a mapping for a key <tt>k</tt> such that
* <tt>key.equals(k)</tt>. (There can be at most one such mapping.)
*
* @param key key whose presence in this map is to be tested
* @return <tt>true</tt> if this map contains a mapping for the specified
* key
* @throws ClassCastException if the key is of an inappropriate type for
* this map (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys (optional)
*/
boolean containsKey( long key );
/**
* Returns <tt>true</tt> if this map maps one or more keys to the
* specified value. More formally, returns <tt>true</tt> if and only if
* this map contains at least one mapping to a value <tt>v</tt> such that
* <tt>(value==null ? v==null : value.equals(v))</tt>. This operation
* will probably require time linear in the map size for most
* implementations of the <tt>Map</tt> interface.
*
* @param value value whose presence in this map is to be tested
* @return <tt>true</tt> if this map maps one or more keys to the
* specified value
* @throws ClassCastException if the value is of an inappropriate type for
* this map (optional)
* @throws NullPointerException if the specified value is null and this
* map does not permit null values (optional)
*/
boolean containsValue( Object value );
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>If this map permits null values, then a return value of
* {@code null} does not <i>necessarily</i> indicate that the map
* contains no mapping for the key; it's also possible that the map
* explicitly maps the key to {@code null}. The {@link #containsKey
* containsKey} operation may be used to distinguish these two cases.
*
* @param key the key whose associated value is to be returned
* @return the <tt>long</tt> value to which the specified key is mapped, or
* {@code null} if this map contains no mapping for the key
* @throws ClassCastException if the key is of an inappropriate type for
* this map (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys (optional)
*/
V get( long key );
// Modification Operations
/**
* Associates the specified value with the specified key in this map
* (optional operation). If the map previously contained a mapping for
* the key, the old value is replaced by the specified value. (A map
* <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
* if {@link #containsKey(long) m.containsKey(k)} would return
* <tt>true</tt>.)
*
* @param key key with which the specified value is to be associated
* @param value an <tt>long</tt> value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>no_entry_value</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>no_entry_value</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>,
* if the implementation supports <tt>null</tt> values.)
* @throws UnsupportedOperationException if the <tt>put</tt> operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
* @throws NullPointerException if the specified key or value is null
* and this map does not permit null keys or values
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
* @see #getNoEntryKey()
*/
V put( long key, V value);
/**
* Inserts a key/value pair into the map if the specified key is not already
* associated with a value.
*
* @param key key with which the specified value is to be associated
* @param value an <tt>long</tt> value to be associated with the specified key
*
* @return the previous value associated with <tt>key</tt>, or null
* if none was found.
*/
V putIfAbsent( long key, V value );
/**
* Removes the mapping for a key from this map if it is present
* (optional operation). More formally, if this map contains a mapping
* from key <tt>k</tt> to value <tt>v</tt> such that
* <code>key.equals(k)</code>, that mapping
* is removed. (The map can contain at most one such mapping.)
*
* <p>Returns the value to which this map previously associated the key,
* or <tt>null</tt> if the map contained no mapping for the key.
*
* <p>If this map permits null values, then a return value of
* <tt>null</tt> does not <i>necessarily</i> indicate that the map
* contained no mapping for the key; it's also possible that the map
* explicitly mapped the key to <tt>null</tt>.
*
* <p>The map will not contain a mapping for the specified key once the
* call returns.
*
* @param key key whose mapping is to be removed from the map
* @return the previous <tt>long</tt> value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this map
* @throws ClassCastException if the key is of an inappropriate type for
* this map (optional)
* @throws NullPointerException if the specified key is null and this
* map does not permit null keys (optional)
*/
V remove( long key );
// Bulk Operations
/**
* Copies all of the mappings from the specified map to this map
* (optional operation). The effect of this call is equivalent to that
* of calling {@link #put(long,Object) put(k, v)} on this map once
* for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
* specified map. The behavior of this operation is undefined if the
* specified map is modified while the operation is in progress.
*
* @param m mappings to be stored in this map
* @throws UnsupportedOperationException if the <tt>putAll</tt> operation
* is not supported by this map
* @throws ClassCastException if the class of a key or value in the
* specified map prevents it from being stored in this map
* @throws NullPointerException if the specified map is null, or if
* this map does not permit null keys or values, and the
* specified map contains null keys or values
* @throws IllegalArgumentException if some property of a key or value in
* the specified map prevents it from being stored in this map
*/
void putAll( Map<? extends Long, ? extends V> m);
/**
* Put all the entries from the given map into this map.
*
* @param map The map from which entries will be obtained to put into this map.
*/
void putAll( TLongObjectMap<V> map );
/**
* Removes all of the mappings from this map (optional operation).
* The map will be empty after this call returns.
*
* @throws UnsupportedOperationException if the <tt>clear</tt> operation
* is not supported by this map
*/
void clear();
// Views
/**
* Returns a {@link TLongSet} view of the keys contained in this map.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own <tt>remove</tt> operation), the results of
* the iteration are undefined. The set supports element removal,
* which removes the corresponding mapping from the map, via the
* <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
* operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
* operations.
*
* @return a set view of the keys contained in this map
*/
TLongSet keySet();
/**
* Returns a copy of the keys of the map as an array.
* Changes to the array of keys will not be reflected in the map
* nor vice-versa.
*
* @return a copy of the keys of the map as an array.
*/
long[] keys();
/**
* Returns a copy of the keys of the map as an array.
* Changes to the array of keys will not be reflected in the map
* nor vice-versa.
*
* @param array the array into which the elements of the list are to be stored,
* if it is big enough; otherwise, a new array of the same type is
* allocated for this purpose.
* @return the keys of the map as an array.
*/
long[] keys( long[] array );
/**
* Returns a {@link Collection} view of the values contained in this map.
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. If the map is
* modified while an iteration over the collection is in progress
* (except through the iterator's own <tt>remove</tt> operation),
* the results of the iteration are undefined. The collection
* supports element removal, which removes the corresponding
* mapping from the map, via the <tt>Iterator.remove</tt>,
* <tt>Collection.remove</tt>, <tt>removeAll</tt>,
* <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
* support the <tt>add</tt> or <tt>addAll</tt> operations.
*
* @return a collection view of the values contained in this map
*/
Collection<V> valueCollection();
/**
* Returns the values of the map as an array of <tt>long</tt> values.
* Changes to the array of values will not be reflected in the map
* nor vice-versa.
*
* @return the values of the map as an array of <tt>long</tt> values.
*/
V[] values();
/**
* Returns the values of the map using an existing array.
* Changes to the array of values will not be reflected in the map
* nor vice-versa.
*
* @param array the array into which the elements of the list are to be stored,
* if it is big enough; otherwise, a new array of the same type is
* allocated for this purpose.
* @return the values of the map as an array of <tt>long</tt> values.
*/
<T> T[] values( T[] array );
/**
* Returns a <tt>TLongObjectIterator</tt> with access to this map's keys and values.
*
* @return a <tt>TLongObjectIterator</tt> with access to this map's keys and values.
*/
public TLongObjectIterator<V> iterator();
/**
* Executes <tt>procedure</tt> for each key in the map.
*
* @param procedure a <code>TObjectProcedure</code> value
* @return false if the loop over the keys terminated because
* the procedure returned false for some key.
*/
public boolean forEachKey( TLongProcedure procedure );
/**
* Executes <tt>procedure</tt> for each value in the map.
*
* @param procedure a <code>TObjectProcedure</code> value
* @return false if the loop over the values terminated because
* the procedure returned false for some value.
*/
public boolean forEachValue( TObjectProcedure<V> procedure );
/**
* Executes <tt>procedure</tt> for each key/value entry in the
* map.
*
* @param procedure a <code>TLongObjectProcedure</code> value
* @return false if the loop over the entries terminated because
* the procedure returned false for some entry.
*/
public boolean forEachEntry( TLongObjectProcedure<V> procedure );
/**
* Transform the values in this map using <tt>function</tt>.
*
* @param function a <code>TObjectFunction</code> value
*/
public void transformValues( TObjectFunction<V,V> function );
/**
* Retains only those entries in the map for which the procedure
* returns a true value.
*
* @param procedure determines which entries to keep
* @return true if the map was modified.
*/
public boolean retainEntries( TLongObjectProcedure<V> procedure );
// Comparison and hashing
/**
* Compares the specified object with this map for equality. Returns
* <tt>true</tt> if the given object is also a map and the two maps
* represent the same mappings. More formally, two maps <tt>m1</tt> and
* <tt>m2</tt> represent the same mappings if
* <tt>m1.entrySet().equals(m2.entrySet())</tt>. This ensures that the
* <tt>equals</tt> method works properly across different implementations
* of the <tt>Map</tt> interface.
*
* @param o object to be compared for equality with this map
* @return <tt>true</tt> if the specified object is equal to this map
*/
boolean equals( Object o );
/**
* Returns the hash code value for this map. The hash code of a map is
* defined to be the sum of the hash codes of each entry in the map's
* <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt>
* implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
* <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
* {@link Object#hashCode}.
*
* @return the hash code value for this map
* @see Object#equals(Object)
* @see #equals(Object)
*/
int hashCode();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001, Eric D. Friedman All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
///////////////////////////////////////////////////////////////////////////////
package gnu.trove.procedure;
//////////////////////////////////////////////////
// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! //
//////////////////////////////////////////////////
/**
* Interface for procedures that take two parameters of type long and Object.
*/
public interface TLongObjectProcedure<T> {
/**
* Executes this procedure. A false return value indicates that
* the application executing this procedure should not invoke this
* procedure again.
*
* @param a a <code>long</code> value
* @param b an <code>Object</code> value
* @return true if additional invocations of the procedure are
* allowed.
*/
public boolean execute( long a, T b );
}

View file

@ -9,8 +9,8 @@ public class ToDoConstants {
// TODO max 115
// !!! ROUTING
// ! New UI (+)
// !!63. Support simple offline routing(require index file with turn restrictions etc) (Issue)
// For 0.5 release
// 104. Add activity to show current loaded indexes and information about them
@ -23,21 +23,19 @@ public class ToDoConstants {
// possibly introduce settings to limit usage of functionality or put poi index into binary index
// Outside base 0.5 release
// 109. Update download index activity (introduce select/deselect all, update existing)
// and make green text for already loaded indexes.
// 113. Calculate speed cameras/bumps on the road (announce about them)
// 110. Use android voice for pronounce command (could be used in future to pronounce street)
// 111. Investigate showing street name while driving
// 110. Use android voice for pronounce command (could be used in future to pronounce street) (Issue)
// 111. Investigate showing street name while driving (Issue)
// 86. Allow to add/edit custom tags to POI objects (Issue)
// 96. Introduce settings for MPH, imperial units (Issue)
// 114. Index streets according to city bounds
// 114. Index streets according to city bounds (Issue)
// _19. colors for road trunk and motorway
///////////////////////////// UNKNOWN STATE ////////////////////
// Unscheduled (complex)
// 65. Intermediate points - for better control routing, to avoid traffic jams ...(?)
// 63. Support simple offline routing(require index file with turn restrictions etc) (?)
// Not clear if it is really needed
// 66. Transport routing (show next stop, total distance, show stop get out, voice) (needed ?).
@ -48,6 +46,8 @@ public class ToDoConstants {
// DONE ANDROID :
// 106. Download region from android device (select minzoom/maxzoom)
// 105. Route mode fast/short (Issue)
// 109. Update download index activity (introduce select/deselect all, update existing)
// and make green text for already loaded indexes.
// DONE SWING

View file

@ -1,6 +1,7 @@
package net.osmand.binary;
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
public class BinaryMapDataObject {
protected int[] coordinates = null;
@ -45,6 +46,13 @@ public class BinaryMapDataObject {
return types;
}
public TagValuePair getTagValue(int indType){
if(mapIndex == null){
return null;
}
return mapIndex.decodeType(types[indType]);
}
public long getId() {
return id;
}

View file

@ -1,19 +1,25 @@
package net.osmand.binary;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
import gnu.trove.set.hash.TLongHashSet;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
@ -23,7 +29,7 @@ public class BinaryRouteDataReader {
private CodedInputStreamRAF codedIS;
private final BinaryMapIndexReader map;
protected BinaryRouteDataReader(BinaryMapIndexReader map){
public BinaryRouteDataReader(BinaryMapIndexReader map){
this.codedIS = map.codedIS;
this.map = map;
}
@ -36,8 +42,7 @@ public class BinaryRouteDataReader {
return map.readInt();
}
private class CarRouter {
private static class CarRouter {
// no distinguish for speed in city/outside city (for now)
private Map<String, Double> autoValues = new LinkedHashMap<String, Double>();
{
@ -80,34 +85,59 @@ public class BinaryRouteDataReader {
}
private static class RoutingContext {
// TODO replace with lightweight collection
Map<Long, BinaryMapDataObject> map = new LinkedHashMap<Long, BinaryMapDataObject>();
public static class RoutingContext {
TLongObjectMap<BinaryMapDataObject> idObjects = new TLongObjectHashMap<BinaryMapDataObject>();
TLongObjectMap<RouteSegment> routes = new TLongObjectHashMap<RouteSegment>();
CarRouter router = new CarRouter();
TIntSet loadedTiles = new TIntHashSet();
public Collection<BinaryMapDataObject> values(){
return map.values();
return idObjects.valueCollection();
}
}
private final static int ZOOM_LOAD_TILES = 15;
public void searchRoutes(RoutingContext ctx, int tileX, int tileY) throws IOException {
public static class RouteSegment {
int segmentStart = 0;
int segmentEnd = 0;
BinaryMapDataObject road;
// needed to store intersection of routes
RouteSegment next = null;
// search context (needed for searching route)
int parentRoute = 0;
int parentSegmentEnd = 0;
public BinaryMapDataObject getRoad() {
return road;
}
}
public static class RouteSegmentResult {
public LatLon startPoint;
public LatLon endPoint;
public BinaryMapDataObject object;
public int startPointIndex;
public int endPointIndex;
}
private static double dist(int x1, int y1, int x2, int y2) {
return Math.sqrt(((double)x1 - x2) * ((double)x1 - x2) + ((double)y1 - y2) * ((double)y1 - y2));
}
public void loadRoutes(final RoutingContext ctx, int tileX, int tileY) throws IOException {
int tileC = tileX << ZOOM_LOAD_TILES + tileY;
if(ctx.loadedTiles.contains(tileC)){
return;
}
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
request.left = tileX << (31 - ZOOM_LOAD_TILES);
request.right = (tileX + 1) << (31 - ZOOM_LOAD_TILES);
request.top = tileY << (31 - ZOOM_LOAD_TILES);
request.bottom = (tileY + 1) << (31 - ZOOM_LOAD_TILES);
request.zoom = 15;
final CarRouter router = new CarRouter();
request.setSearchFilter(new BinaryMapIndexReader.SearchFilter(){
@Override
public boolean accept(TIntArrayList types, MapIndex index) {
@ -117,11 +147,11 @@ public class BinaryRouteDataReader {
if (pair != null) {
int t = wholeType & 3;
if(t == MapRenderingTypes.POINT_TYPE){
if(router.acceptPoint(pair)){
if(ctx.router.acceptPoint(pair)){
return true;
}
} else if(t == MapRenderingTypes.POLYLINE_TYPE){
if(router.acceptLine(pair)){
if(ctx.router.acceptLine(pair)){
return true;
}
}
@ -131,25 +161,31 @@ public class BinaryRouteDataReader {
}
});
map.searchMapIndex(request);
for(BinaryMapDataObject o : request.searchResults){
ctx.map.put(o.getId(), o);
for (BinaryMapDataObject o : request.searchResults) {
if(ctx.idObjects.containsKey(o.getId())){
continue;
}
ctx.idObjects.put(o.getId(), o);
for (int j = 0; j < o.getPointsLength(); j++) {
long l = (((long) o.getPoint31XTile(j)) << 31) + (long) o.getPoint31YTile(j);
RouteSegment segment = new RouteSegment();
segment.road = o;
segment.segmentEnd = segment.segmentStart = j;
if (ctx.routes.get(l) != null) {
segment.next = ctx.routes.get(l);
}
ctx.routes.put(l, segment);
}
}
ctx.loadedTiles.add(tileC);
}
private static class RouteSegment {
int segment = 0;
BinaryMapDataObject road;
}
private static double dist(int x1, int y1, int x2, int y2) {
return Math.sqrt(((double)x1 - x2) * ((double)x1 - x2) + ((double)y1 - y2) * ((double)y1 - y2));
}
public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException {
double tileX = MapUtils.getTileNumberX(ZOOM_LOAD_TILES, lon);
double tileY = MapUtils.getTileNumberY(ZOOM_LOAD_TILES, lat);
searchRoutes(ctx, (int) tileX , (int) tileY);
loadRoutes(ctx, (int) tileX , (int) tileY);
RouteSegment road = null;
double dist = 0;
@ -164,7 +200,8 @@ public class BinaryRouteDataReader {
if (road == null || prevDist + cDist - mDist < dist) {
road = new RouteSegment();
road.road = r;
road.segment = j;
road.segmentStart = j - 1;
road.segmentEnd = j;
dist = prevDist + cDist - mDist;
}
prevDist = cDist;
@ -174,48 +211,139 @@ public class BinaryRouteDataReader {
return road;
}
public List<RouteSegmentResult> searchRoute(RoutingContext ctx, RouteSegment start, RouteSegment end) throws IOException {
List<RouteSegmentResult> result = new ArrayList<RouteSegmentResult>();
List<RouteSegment> searchList = new ArrayList<RouteSegment>();
TLongHashSet visitedPoints = new TLongHashSet();
searchList.add(start);
int stIndex = 0;
int endIndex = -1;
while(stIndex < searchList.size() && endIndex == -1){
RouteSegment segment = searchList.get(stIndex);
BinaryMapDataObject road = segment.road;
// try to find all ways
// TODO check for one way (?) and start from segment end
for (int j = 0; j < road.getPointsLength() && endIndex == -1; j++) {
long l = (((long) road.getPoint31XTile(j)) << 31) + (long) road.getPoint31YTile(j);
if(visitedPoints.contains(l)){
continue;
}
// TODO efficient (?)
loadRoutes(ctx, (road.getPoint31XTile(j) >> (31 - ZOOM_LOAD_TILES)), (road.getPoint31YTile(j) >> (31 - ZOOM_LOAD_TILES)));
RouteSegment next = ctx.routes.get(l);
if(next != null){
visitedPoints.add(l);
}
while(next != null){
if(next.road.id != road.id){
next.parentRoute = stIndex;
next.parentSegmentEnd = j;
searchList.add(next);
// TODO check that there is way to that point !!!
if(end.road.id == next.road.id){
endIndex = searchList.size() - 1;
break;
}
}
next = next.next;
}
}
stIndex++;
}
stIndex = endIndex;
start.parentRoute = -1;
int parentSegmentEnd = end.segmentEnd;
while(stIndex != -1){
RouteSegment segment = searchList.get(stIndex);
RouteSegmentResult res = new RouteSegmentResult();
res.object = segment.road;
res.endPointIndex = parentSegmentEnd;
res.startPointIndex = segment.segmentStart;
res.startPoint = convertPoint(res.object, res.startPointIndex);
res.endPoint = convertPoint(res.object, res.endPointIndex);
if(res.startPointIndex != res.endPointIndex) {
// skip duplicates
result.add(0, res);
}
parentSegmentEnd = segment.parentSegmentEnd;
stIndex = segment.parentRoute;
}
return result;
}
private LatLon convertPoint(BinaryMapDataObject o, int ind){
return new LatLon(MapUtils.get31LatitudeY(o.getPoint31YTile(ind)), MapUtils.get31LongitudeX(o.getPoint31XTile(ind)));
}
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("d:\\android\\data\\Belarus.obf"), "r"); //$NON-NLS-1$ //$NON-NLS-2$
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
BinaryRouteDataReader router = new BinaryRouteDataReader(reader);
// int sleft = MapUtils.get31TileNumberX(27.596);
// int sright = MapUtils.get31TileNumberX(27.599);
// int stop = MapUtils.get31TileNumberY(53.921);
// int sbottom = MapUtils.get31TileNumberY(53.919);
//double lon = 27.5967;
//double lat = 53.9204;
// akad
// double lon = 27.5993;
// double lat = 53.9186;
double lon = 27.6024;
double lat = 53.9141;
double lon = 27.5976;
double lat = 53.9199;
double elon = 27.6018;
double elat = 53.9223;
RoutingContext ctx = new RoutingContext();
long ms = System.currentTimeMillis();
// find closest way
RouteSegment routeSegment = router.findRouteSegment(lat, lon, ctx);
if (routeSegment != null) {
BinaryMapDataObject road = routeSegment.road;
RouteSegment start = router.findRouteSegment(lat, lon, ctx);
if (start != null) {
BinaryMapDataObject road = start.road;
TagValuePair pair = road.mapIndex.decodeType(road.getTypes()[0]);
System.out.println("ROAD TO START " + pair.tag + " " + pair.value + " " + road.name + " " + routeSegment.segment + " "
System.out.println("ROAD TO START " + pair.tag + " " + pair.value + " " + road.name + " " + start.segmentStart + " "
+ (road.id >> 3));
}
RouteSegment end = router.findRouteSegment(elat, elon, ctx);
if (end != null) {
BinaryMapDataObject road = end.road;
TagValuePair pair = road.mapIndex.decodeType(road.getTypes()[0]);
System.out.println("ROAD TO END " + pair.tag + " " + pair.value + " " + road.name + " " + end.segmentStart + " "
+ (road.id >> 3));
}
double tileX = Math.round(MapUtils.getTileNumberX(ZOOM_LOAD_TILES, lon));
double tileY = Math.round(MapUtils.getTileNumberY(ZOOM_LOAD_TILES, lat));
// preload neighboors
router.searchRoutes(ctx, (int) tileX, (int) tileY);
router.searchRoutes(ctx, (int) tileX - 1, (int) tileY);
router.searchRoutes(ctx, (int) tileX, (int) tileY - 1);
router.searchRoutes(ctx, (int) tileX - 1, (int) tileY - 1);
// router.loadRoutes(ctx, (int) tileX, (int) tileY);
// router.loadRoutes(ctx, (int) tileX - 1, (int) tileY);
// router.loadRoutes(ctx, (int) tileX, (int) tileY - 1);
// router.loadRoutes(ctx, (int) tileX - 1, (int) tileY - 1);
for(RouteSegmentResult s : router.searchRoute(ctx, start, end)){
double dist = MapUtils.getDistance(s.startPoint, s.endPoint);
System.out.println("Street " + s.object.name + " distance " + dist);
}
Collection<BinaryMapDataObject> res = ctx.values();
System.out.println(res.size() + " objects for " + (System.currentTimeMillis() - ms) + " ms");
for(BinaryMapDataObject r : res){
TagValuePair pair = r.mapIndex.decodeType(r.getTypes()[0]);
// for(BinaryMapDataObject r : res){
// TagValuePair pair = r.mapIndex.decodeType(r.getTypes()[0]);
// if(r.name != null){
// System.out.println(pair.tag + " " + pair.value + " " + r.name );
// } else {
// System.out.println(pair.tag + " " + pair.value + " " + (r.id >> 3));
// }
}
// }
}

View file

@ -5,12 +5,15 @@ import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractAction;
@ -21,6 +24,13 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.ExceptionHandler;
import net.osmand.binary.BinaryMapDataObject;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryRouteDataReader;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
import net.osmand.binary.BinaryRouteDataReader.RouteSegment;
import net.osmand.binary.BinaryRouteDataReader.RouteSegmentResult;
import net.osmand.binary.BinaryRouteDataReader.RoutingContext;
import net.osmand.data.DataTileManager;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
@ -109,6 +119,22 @@ public class MapRouterLayer implements MapPanelLayer {
}
};
menu.add(altroute);
Action selfRoute = new AbstractAction("Calculate self route") {
private static final long serialVersionUID = 507156107455281238L;
public void actionPerformed(ActionEvent e) {
List<Way> ways = selfRoute(startRoute, endRoute);
DataTileManager<Way> points = new DataTileManager<Way>();
points.setZoom(11);
for(Way w : ways){
LatLon n = w.getLatLon();
points.registerObject(n.getLatitude(), n.getLongitude(), w);
}
map.setPoints(points);
}
};
menu.add(selfRoute);
}
@ -274,6 +300,65 @@ public class MapRouterLayer implements MapPanelLayer {
return res;
}
public List<Way> selfRoute(LatLon start, LatLon end) {
List<Way> res = new ArrayList<Way>();
long time = System.currentTimeMillis();
System.out.println("Self made route from " + start + " to " + end);
if (start != null && end != null) {
try {
RandomAccessFile raf = new RandomAccessFile(new File("d:\\android\\data\\Belarus.obf"), "r"); //$NON-NLS-1$ //$NON-NLS-2$
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
BinaryRouteDataReader router = new BinaryRouteDataReader(reader);
RoutingContext ctx = new RoutingContext();
// find closest way
RouteSegment st = router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);
if (st != null) {
BinaryMapDataObject road = st.getRoad();
TagValuePair pair = road.getTagValue(0);
System.out.println("ROAD TO START " + pair.tag + " " + pair.value + " " + road.getName() + " "
+ (road.getId() >> 3));
}
RouteSegment e = router.findRouteSegment(end.getLatitude(), end.getLongitude(), ctx);
if ( e != null) {
BinaryMapDataObject road = e.getRoad();
TagValuePair pair = road.getTagValue(0);
System.out.println("ROAD TO END " + pair.tag + " " + pair.value + " " + road.getName()+ " " +
+ (road.getId() >> 3));
}
for(RouteSegmentResult s : router.searchRoute(ctx, st, e)){
// double dist = MapUtils.getDistance(s.startPoint, s.endPoint);
Way way = new Way(-1);
boolean plus = s.startPointIndex < s.endPointIndex;
int i=s.startPointIndex;
while (true) {
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(s.object.getPoint31YTile(i)), MapUtils
.get31LongitudeX(s.object.getPoint31XTile(i)), -1);
way.addNode(n);
if (i == s.endPointIndex) {
break;
}
if (plus) {
i++;
} else {
i--;
}
}
res.add(way);
}
} catch (IOException e) {
ExceptionHandler.handle(e);
}
System.out.println("Finding self routes " + res.size() + " " + (System.currentTimeMillis() - time) + " ms");
}
return res;
}
@Override
public void prepareToDraw() {
}