Small data tile manager refactoring
This commit is contained in:
parent
5d1e5ea54d
commit
48fcb7d1dc
10 changed files with 222 additions and 207 deletions
|
@ -79,7 +79,9 @@ public class NativeLibrary {
|
||||||
|
|
||||||
public RouteDataObject[] getDataObjects(NativeRouteSearchResult rs, int x31, int y31) {
|
public RouteDataObject[] getDataObjects(NativeRouteSearchResult rs, int x31, int y31) {
|
||||||
if(rs.nativeHandler == 0) {
|
if(rs.nativeHandler == 0) {
|
||||||
throw new IllegalStateException("Native route handler is 0");
|
// do not throw exception because it is expected situation
|
||||||
|
return new RouteDataObject[0];
|
||||||
|
// throw new IllegalStateException("Native route handler is 0");
|
||||||
}
|
}
|
||||||
return getRouteDataObjects(rs.region.routeReg, rs.nativeHandler, x31, y31);
|
return getRouteDataObjects(rs.region.routeReg, rs.nativeHandler, x31, y31);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
package net.osmand.data;
|
package net.osmand.data;
|
||||||
|
|
||||||
|
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.osmand.osm.MapUtils;
|
import net.osmand.osm.MapUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param <T> - object to store in that manager
|
* @param <T> - object to store in that manager
|
||||||
*/
|
*/
|
||||||
public class DataTileManager<T> {
|
public class DataTileManager<T> {
|
||||||
|
|
||||||
private int zoom = 15;
|
private final int zoom;
|
||||||
|
|
||||||
/**
|
private TLongObjectHashMap<List<T>> objects = new TLongObjectHashMap<List<T>>();
|
||||||
* map for objects stores as 'xTile_yTile' -> List<T>
|
|
||||||
*/
|
|
||||||
private Map<String, List<T>> objects = new HashMap<String, List<T>>();
|
|
||||||
|
|
||||||
public DataTileManager(){
|
public DataTileManager(){
|
||||||
zoom = 15;
|
zoom = 15;
|
||||||
|
@ -34,29 +30,17 @@ public class DataTileManager<T> {
|
||||||
return zoom;
|
return zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setZoom(int zoom) {
|
|
||||||
// it is required to reindex all stored objects
|
|
||||||
if(!isEmpty()){
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
this.zoom = zoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
for(String s : objects.keySet()){
|
return getObjectsCount() == 0;
|
||||||
if(!objects.get(s).isEmpty()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
public int getObjectsCount(){
|
public int getObjectsCount(){
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for(String s : objects.keySet()){
|
for(List s : objects.values()){
|
||||||
x += objects.get(s).size();
|
x += s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +50,11 @@ public class DataTileManager<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public List<T> getAllObjects(){
|
public List<T> getAllObjects(){
|
||||||
List<T> l = new ArrayList<T>();
|
List<T> l = new ArrayList<T>();
|
||||||
for(String s : objects.keySet()){
|
for(List s : objects.values()){
|
||||||
l.addAll(objects.get(s));
|
l.addAll(s);
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -146,27 +131,29 @@ public class DataTileManager<T> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String evTile(int tileX, int tileY){
|
private long evTile(int tileX, int tileY){
|
||||||
return tileX +"_"+tileY; //$NON-NLS-1$
|
long tx = tileX;
|
||||||
|
long ty = tileY;
|
||||||
|
return ((tx) << zoom) + ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String evaluateTile(double latitude, double longitude){
|
public long evaluateTile(double latitude, double longitude){
|
||||||
int tileX = (int) MapUtils.getTileNumberX(zoom, longitude);
|
int tileX = (int) MapUtils.getTileNumberX(zoom, longitude);
|
||||||
int tileY = (int) MapUtils.getTileNumberY(zoom, latitude);
|
int tileY = (int) MapUtils.getTileNumberY(zoom, latitude);
|
||||||
return evTile(tileX, tileY);
|
return evTile(tileX, tileY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterObject(double latitude, double longitude, T object){
|
public void unregisterObject(double latitude, double longitude, T object){
|
||||||
String tile = evaluateTile(latitude, longitude);
|
long tile = evaluateTile(latitude, longitude);
|
||||||
if(objects.containsKey(tile)){
|
if(objects.containsKey(tile)){
|
||||||
objects.get(tile).remove(object);
|
objects.get(tile).remove(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String registerObject(double latitude, double longitude, T object){
|
public long registerObject(double latitude, double longitude, T object){
|
||||||
String tile = evaluateTile(latitude, longitude);
|
long tile = evaluateTile(latitude, longitude);
|
||||||
if(!objects.containsKey(tile)){
|
if(!objects.containsKey(tile)){
|
||||||
objects.put(tile, new ArrayList<T>());
|
objects.put(tile, new ArrayList<T>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,6 +167,7 @@ public class MapRoutingTypes {
|
||||||
if(value.startsWith("trunk") || value.startsWith("motorway")
|
if(value.startsWith("trunk") || value.startsWith("motorway")
|
||||||
|| value.startsWith("primary") || value.startsWith("secondary")
|
|| value.startsWith("primary") || value.startsWith("secondary")
|
||||||
|| value.startsWith("tertiary")
|
|| value.startsWith("tertiary")
|
||||||
|
|| value.startsWith("ferry")
|
||||||
) {
|
) {
|
||||||
init = true;
|
init = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -224,8 +224,7 @@ public class MinskTransReader {
|
||||||
OsmBaseStorage storage = new OsmBaseStorage();
|
OsmBaseStorage storage = new OsmBaseStorage();
|
||||||
|
|
||||||
final Map<String, Relation> definedRoutes = new HashMap<String, Relation>();
|
final Map<String, Relation> definedRoutes = new HashMap<String, Relation>();
|
||||||
final DataTileManager<Node> busStops = new DataTileManager<Node>();
|
final DataTileManager<Node> busStops = new DataTileManager<Node>(17);
|
||||||
busStops.setZoom(17);
|
|
||||||
storage.getFilters().add(new IOsmStorageFilter(){
|
storage.getFilters().add(new IOsmStorageFilter(){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
35
DataExtractionOSM/src/net/osmand/router/BaseRouteResult.java
Normal file
35
DataExtractionOSM/src/net/osmand/router/BaseRouteResult.java
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package net.osmand.router;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.osmand.data.DataTileManager;
|
||||||
|
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
|
||||||
|
|
||||||
|
public class BaseRouteResult {
|
||||||
|
|
||||||
|
private final List<RouteSegmentResult> baseResult;
|
||||||
|
private DataTileManager<RouteSegmentResult> indexedData = new DataTileManager<RouteSegmentResult>(15);
|
||||||
|
|
||||||
|
public BaseRouteResult(List<RouteSegmentResult> baseResult) {
|
||||||
|
this.baseResult = baseResult;
|
||||||
|
indexData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void indexData() {
|
||||||
|
for(RouteSegmentResult r : baseResult){
|
||||||
|
// r.getObject().getPoint31XTile(i);
|
||||||
|
|
||||||
|
// indexedData.evaluateTile(latitude, longitude)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public float getOrthogonalDistance(RouteSegment r){
|
||||||
|
float dist = 0;
|
||||||
|
int x = r.getRoad().getPoint31XTile(r.getSegmentStart());
|
||||||
|
int y = r.getRoad().getPoint31YTile(r.getSegmentStart());
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,6 +130,7 @@ public class BinaryRoutePlanner {
|
||||||
ctx.timeToLoad += local.timeToLoad;
|
ctx.timeToLoad += local.timeToLoad;
|
||||||
ctx.timeToLoadHeaders += local.timeToLoadHeaders;
|
ctx.timeToLoadHeaders += local.timeToLoadHeaders;
|
||||||
ctx.relaxedSegments += local.relaxedSegments;
|
ctx.relaxedSegments += local.relaxedSegments;
|
||||||
|
ctx.routingTime += local.routingTime;
|
||||||
|
|
||||||
local.unloadAllData(ctx);
|
local.unloadAllData(ctx);
|
||||||
if(restPartRecalculatedRoute != null) {
|
if(restPartRecalculatedRoute != null) {
|
||||||
|
@ -385,16 +386,16 @@ public class BinaryRoutePlanner {
|
||||||
RouteSegment s = iterator.next();
|
RouteSegment s = iterator.next();
|
||||||
// statStart.addNumber((float) s.distanceFromStart);
|
// statStart.addNumber((float) s.distanceFromStart);
|
||||||
// statEnd.addNumber((float) s.distanceToEnd);
|
// statEnd.addNumber((float) s.distanceToEnd);
|
||||||
if (s.distanceToEnd < mine) {
|
if (s.distanceFromStart > mine) {
|
||||||
mine = s.distanceToEnd;
|
mine = s.distanceFromStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double d = mine + 5000; // ctx.config.RELAX_NODES_IF_START_DIST_COEF;
|
double d = mine - 50000; // ctx.config.RELAX_NODES_IF_START_DIST_COEF;
|
||||||
if (d > 0) {
|
if (d > 0) {
|
||||||
iterator = graphSegments.iterator();
|
iterator = graphSegments.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
RouteSegment s = iterator.next();
|
RouteSegment s = iterator.next();
|
||||||
if (s.distanceToEnd > d) {
|
if (s.distanceFromStart < d) {
|
||||||
ctx.relaxedSegments++;
|
ctx.relaxedSegments++;
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class RoutingContext {
|
||||||
|
|
||||||
public Interruptable interruptable;
|
public Interruptable interruptable;
|
||||||
public List<RouteSegmentResult> previouslyCalculatedRoute;
|
public List<RouteSegmentResult> previouslyCalculatedRoute;
|
||||||
|
public BaseRouteResult baseRouteResult;
|
||||||
|
|
||||||
// 2. Routing memory cache (big objects)
|
// 2. Routing memory cache (big objects)
|
||||||
TLongObjectHashMap<List<RoutingSubregionTile>> indexedSubregions = new TLongObjectHashMap<List<RoutingSubregionTile>>();
|
TLongObjectHashMap<List<RoutingSubregionTile>> indexedSubregions = new TLongObjectHashMap<List<RoutingSubregionTile>>();
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<attribute name="zoomToLoadTiles" value="16" />
|
<attribute name="zoomToLoadTiles" value="16" />
|
||||||
<!-- by default it is 30. Value specified here overwrites all others
|
<!-- by default it is 30. Value specified here overwrites all others
|
||||||
(don't specify here ! it is device dependent) -->
|
(don't specify here ! it is device dependent) -->
|
||||||
<attribute name="memoryLimitInMB" value="" />
|
<attribute name="memoryLimitInMB" value="50" />
|
||||||
|
|
||||||
<!-- 1.2 Dynamic road prioritizing (heuristic) -->
|
<!-- 1.2 Dynamic road prioritizing (heuristic) -->
|
||||||
<attribute name="useDynamicRoadPrioritising" value="false" />
|
<attribute name="useDynamicRoadPrioritising" value="false" />
|
||||||
|
@ -57,49 +57,48 @@
|
||||||
<specialization input="avoid_motorway" speed="0"/>
|
<specialization input="avoid_motorway" speed="0"/>
|
||||||
</road>
|
</road>
|
||||||
|
|
||||||
<road tag="highway" value="trunk" speed="100" priority="1.2" dynamicPriority="1"/>
|
<road tag="highway" value="trunk" speed="100" priority="1.2" dynamicPriority="0.9"/>
|
||||||
<road tag="highway" value="trunk_link" speed="75" priority="1.2" dynamicPriority="1"/>
|
<road tag="highway" value="trunk_link" speed="75" priority="1.2" dynamicPriority="0.9"/>
|
||||||
|
|
||||||
<!-- generally linking larger towns. -->
|
<!-- generally linking larger towns. -->
|
||||||
<road tag="highway" value="primary" speed="65" priority="1.1" dynamicPriority="1"/>
|
<road tag="highway" value="primary" speed="65" priority="1.1" dynamicPriority="0.7"/>
|
||||||
<road tag="highway" value="primary_link" speed="50" priority="1.1" dynamicPriority="1"/>
|
<road tag="highway" value="primary_link" speed="50" priority="1.1" dynamicPriority="0.7"/>
|
||||||
|
|
||||||
<!-- generally linking smaller towns and villages -->
|
<!-- generally linking smaller towns and villages -->
|
||||||
<road tag="highway" value="secondary" speed="60" priority="1.05" dynamicPriority="1"/>
|
<road tag="highway" value="secondary" speed="60" priority="1.05" dynamicPriority="0.6"/>
|
||||||
<road tag="highway" value="secondary_link" speed="50" priority="1.05" dynamicPriority="1"/>
|
<road tag="highway" value="secondary_link" speed="50" priority="1.05" dynamicPriority="0.6"/>
|
||||||
|
|
||||||
<!-- important urban roads -->
|
<!-- important urban roads -->
|
||||||
<road tag="highway" value="tertiary" speed="45" priority="1" dynamicPriority="0.9"/>
|
<road tag="highway" value="tertiary" speed="45" priority="1" dynamicPriority="0.5"/>
|
||||||
<road tag="highway" value="tertiary_link" speed="40" priority="1" dynamicPriority="0.9"/>
|
<road tag="highway" value="tertiary_link" speed="40" priority="1" dynamicPriority="0.5"/>
|
||||||
<!-- lowest form of grid network, usually 90% of urban roads -->
|
<!-- lowest form of grid network, usually 90% of urban roads -->
|
||||||
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.7">
|
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.3">
|
||||||
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
||||||
</road>
|
</road>
|
||||||
<!-- road = no type, no review and may be not accurate -->
|
<!-- road = no type, no review and may be not accurate -->
|
||||||
<road tag="highway" value="road" speed="35" priority="0.7" dynamicPriority="0.7">
|
<road tag="highway" value="road" speed="35" priority="0.7" dynamicPriority="0.3">
|
||||||
<specialization input="short_way" priority="1" speed="45"/>
|
<specialization input="short_way" priority="1" speed="45"/>
|
||||||
</road>
|
</road>
|
||||||
<!-- primarily for access to properties, small roads with 1/2 intersections -->
|
<!-- primarily for access to properties, small roads with 1/2 intersections -->
|
||||||
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.7">
|
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.3">
|
||||||
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
||||||
</road>
|
</road>
|
||||||
<!-- parking + private roads -->
|
<!-- parking + private roads -->
|
||||||
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.5">
|
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.3">
|
||||||
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
|
||||||
</road>
|
</road>
|
||||||
<!-- very bad roads -->
|
<!-- very bad roads -->
|
||||||
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.5">
|
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.2">
|
||||||
<specialization input="short_way" priority="0.7" speed="45" dynamicPriority="0.7" />
|
<specialization input="short_way" priority="0.7" speed="45" dynamicPriority="0.7" />
|
||||||
<specialization input="avoid_unpaved" priority="0.1"/>
|
<specialization input="avoid_unpaved" priority="0.1"/>
|
||||||
</road>
|
</road>
|
||||||
|
|
||||||
<!-- too small for cars usually -->
|
<!-- too small for cars usually -->
|
||||||
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.5">
|
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.3">
|
||||||
<specialization input="short_way" priority="1" dynamicPriority="1" speed="35"/>
|
<specialization input="short_way" priority="1" dynamicPriority="1" speed="35"/>
|
||||||
</road>
|
</road>
|
||||||
<!-- car are able to enter in highway=pedestrian with restrictions -->
|
<!-- car are able to enter in highway=pedestrian with restrictions -->
|
||||||
<!-- Time actually is uknown. Currently unsupported -->
|
<!-- Time actually is uknown. Currently unsupported -->
|
||||||
<road tag="route" value="ferry" speed="15" priority="1.0" dynamicPriority="0.7">
|
<road tag="route" value="ferry" speed="15" priority="1.0" dynamicPriority="0.9">
|
||||||
<specialization input="avoid_ferries" speed="0"/>
|
<specialization input="avoid_ferries" speed="0"/>
|
||||||
</road>
|
</road>
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,11 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
public class MapClusterLayer implements MapPanelLayer {
|
public class MapClusterLayer implements MapPanelLayer {
|
||||||
|
|
||||||
private /*final */ static boolean ANIMATE_CLUSTERING = false;
|
|
||||||
private /*final */ static int SIZE_OF_ROUTES_TO_ANIMATE = 5;
|
private /*final */ static int SIZE_OF_ROUTES_TO_ANIMATE = 5;
|
||||||
private Log log = LogFactory.getLog(MapClusterLayer.class);
|
private Log log = LogFactory.getLog(MapClusterLayer.class);
|
||||||
|
|
||||||
|
|
||||||
private MapPanel map;
|
private MapPanel map;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyLayer() {
|
public void destroyLayer() {
|
||||||
|
|
||||||
|
@ -70,8 +67,26 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
|
|
||||||
};
|
};
|
||||||
menu.add(clustering);
|
menu.add(clustering);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClusteringContext {
|
||||||
|
// final
|
||||||
|
boolean ANIMATE_CLUSTERING = true;
|
||||||
|
boolean BASEMAP_CLUSTERING = true;
|
||||||
|
|
||||||
|
int ZOOM_LIMIT = BASEMAP_CLUSTERING ? 15 : 13;
|
||||||
|
int TILE_BOUNDARIES = BASEMAP_CLUSTERING? 1 : 10;
|
||||||
|
int LOCAL_TILE_BOUNDARIES = BASEMAP_CLUSTERING? 4 : 2;
|
||||||
|
int zm = 31 - ZOOM_LIMIT;
|
||||||
|
|
||||||
|
|
||||||
|
// variable
|
||||||
|
int outOfTile = 0;
|
||||||
|
int outOfDistance = 0;
|
||||||
|
int roadProcessed = 0;
|
||||||
|
int segmentsProcessed = 0;
|
||||||
|
float minRatio = 1f;
|
||||||
|
int roadMinProcessed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,14 +96,13 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
double fx = (popupMenuPoint.x - map.getCenterPointX()) / map.getTileSize();
|
double fx = (popupMenuPoint.x - map.getCenterPointX()) / map.getTileSize();
|
||||||
final double latitude = MapUtils.getLatitudeFromTile(map.getZoom(), map.getYTile() + fy);
|
final double latitude = MapUtils.getLatitudeFromTile(map.getZoom(), map.getYTile() + fy);
|
||||||
final double longitude = MapUtils.getLongitudeFromTile(map.getZoom(), map.getXTile() + fx);
|
final double longitude = MapUtils.getLongitudeFromTile(map.getZoom(), map.getXTile() + fx);
|
||||||
|
final ClusteringContext clusterCtx = new ClusteringContext();
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
List<RouteSegment> ways = clustering(latitude, longitude);
|
final DataTileManager<Way> points = new DataTileManager<Way>(11);
|
||||||
if (!ANIMATE_CLUSTERING) {
|
List<RouteSegment> ways = clustering(clusterCtx, latitude, longitude, points);
|
||||||
DataTileManager<Way> points = new DataTileManager<Way>();
|
|
||||||
points.setZoom(11);
|
|
||||||
for (RouteSegment s : ways) {
|
for (RouteSegment s : ways) {
|
||||||
Way w = new Way(-1);
|
Way w = new Way(-1);
|
||||||
for (int i = 0; i < s.getRoad().getPointsLength(); i++) {
|
for (int i = 0; i < s.getRoad().getPointsLength(); i++) {
|
||||||
|
@ -101,7 +115,6 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
}
|
}
|
||||||
map.setPoints(points);
|
map.setPoints(points);
|
||||||
map.repaint();
|
map.repaint();
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -111,7 +124,8 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RouteSegment> clustering(double lat, double lon) throws IOException{
|
private List<RouteSegment> clustering(final ClusteringContext clusterCtx, double lat, double lon,
|
||||||
|
final DataTileManager<Way> points ) throws IOException{
|
||||||
List<BinaryMapIndexReader> rs = new ArrayList<BinaryMapIndexReader>();
|
List<BinaryMapIndexReader> rs = new ArrayList<BinaryMapIndexReader>();
|
||||||
for (File f : new File(DataExtractionSettings.getSettings().getBinaryFilesDir()).listFiles()) {
|
for (File f : new File(DataExtractionSettings.getSettings().getBinaryFilesDir()).listFiles()) {
|
||||||
if (f.getName().endsWith(".obf")) {
|
if (f.getName().endsWith(".obf")) {
|
||||||
|
@ -123,7 +137,7 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
Builder builder = RoutingConfiguration.getDefault();
|
Builder builder = RoutingConfiguration.getDefault();
|
||||||
RoutingConfiguration config = builder.build("car", RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3);
|
RoutingConfiguration config = builder.build("car", RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3);
|
||||||
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(),
|
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(),
|
||||||
rs.toArray(new BinaryMapIndexReader[rs.size()]));
|
rs.toArray(new BinaryMapIndexReader[rs.size()]), clusterCtx.BASEMAP_CLUSTERING);
|
||||||
// find closest way
|
// find closest way
|
||||||
RouteSegment st = router.findRouteSegment(lat, lon, ctx);
|
RouteSegment st = router.findRouteSegment(lat, lon, ctx);
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
|
@ -132,8 +146,6 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
log.info("ROAD TO START " + highway + " " + //road.getName() + " "
|
log.info("ROAD TO START " + highway + " " + //road.getName() + " "
|
||||||
+ road.id);
|
+ road.id);
|
||||||
}
|
}
|
||||||
final DataTileManager<Way> points = new DataTileManager<Way>();
|
|
||||||
points.setZoom(11);
|
|
||||||
map.setPoints(points);
|
map.setPoints(points);
|
||||||
|
|
||||||
ctx.setVisitor(new RouteSegmentVisitor() {
|
ctx.setVisitor(new RouteSegmentVisitor() {
|
||||||
|
@ -141,7 +153,7 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
|
public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
|
||||||
if(!ANIMATE_CLUSTERING){
|
if(!clusterCtx.ANIMATE_CLUSTERING){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cache.add(s);
|
cache.add(s);
|
||||||
|
@ -150,11 +162,18 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
}
|
}
|
||||||
for (RouteSegment segment : cache) {
|
for (RouteSegment segment : cache) {
|
||||||
Way way = new Way(-1);
|
Way way = new Way(-1);
|
||||||
for (int i = 0; i < segment.getRoad().getPointsLength(); i++) {
|
boolean d = segment.getSegmentStart() <segment.getParentSegmentEnd() ;
|
||||||
|
for (int i = segment.getSegmentStart(); i != segment.getParentSegmentEnd(); ) {
|
||||||
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(segment.getRoad()
|
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(segment.getRoad()
|
||||||
.getPoint31YTile(i)), MapUtils.get31LongitudeX(segment.getRoad().getPoint31XTile(i)), -1);
|
.getPoint31YTile(i)), MapUtils.get31LongitudeX(segment.getRoad().getPoint31XTile(i)), -1);
|
||||||
way.addNode(n);
|
way.addNode(n);
|
||||||
|
if(d) {
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
i--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
way.putTag("color", "white");
|
||||||
LatLon n = way.getLatLon();
|
LatLon n = way.getLatLon();
|
||||||
points.registerObject(n.getLatitude(), n.getLongitude(), way);
|
points.registerObject(n.getLatitude(), n.getLongitude(), way);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +193,7 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
List<RouteSegment> results = searchCluster(ctx, st);
|
List<RouteSegment> results = searchCluster(clusterCtx, ctx, st);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,139 +201,111 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private long calculateId(RouteSegment r, int segment){
|
private long calculateId(RouteSegment r){
|
||||||
return (r.getRoad().getId() << 8) + segment;
|
return (r.getRoad().getId() /*<< 8*/) /*+ segment*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<RouteSegment> searchCluster(RoutingContext ctx, RouteSegment st) throws IOException {
|
private List<RouteSegment> searchCluster(ClusteringContext cCtx, RoutingContext ctx, RouteSegment st) throws IOException {
|
||||||
Queue<List<RouteSegment>> queue = new LinkedList<List<RouteSegment>>();
|
Queue<RouteSegment> queue = new LinkedList<RouteSegment>();
|
||||||
List<RouteSegment> result = new ArrayList<BinaryRoutePlanner.RouteSegment>();
|
List<RouteSegment> result = new ArrayList<BinaryRoutePlanner.RouteSegment>();
|
||||||
TLongHashSet visitedIds = new TLongHashSet();
|
TLongHashSet visitedIds = new TLongHashSet();
|
||||||
ArrayList<RouteSegment> start = new ArrayList<RouteSegment>();
|
queue.add(st);
|
||||||
start.add(st);
|
|
||||||
queue.add(start);
|
|
||||||
RouteDataObject startRoad = st.getRoad();
|
RouteDataObject startRoad = st.getRoad();
|
||||||
int ZOOM_LIMIT = 13;
|
|
||||||
int TILE_BOUNDARIES = 10;
|
int tileX = startRoad.getPoint31XTile(st.getSegmentStart()) >> cCtx.zm;
|
||||||
int LOCAL_TILE_BOUNDARIES = 2;
|
int tileY = startRoad.getPoint31YTile(st.getSegmentStart()) >> cCtx.zm;
|
||||||
int zm = 31 - ZOOM_LIMIT;
|
|
||||||
int tileX = startRoad.getPoint31XTile(st.getSegmentStart()) >> zm;
|
|
||||||
int tileY = startRoad.getPoint31YTile(st.getSegmentStart()) >> zm;
|
|
||||||
int outOfTile = 0;
|
|
||||||
int outOfDistance = 0;
|
|
||||||
int segmentsProcessed = 0;
|
|
||||||
float minRatio = 1f;
|
|
||||||
int segmentsMinProcessed = 0;
|
|
||||||
TLongHashSet onTheMap = new TLongHashSet();
|
|
||||||
while (!queue.isEmpty()) {
|
while (!queue.isEmpty()) {
|
||||||
List<RouteSegment> segments = queue.peek();
|
RouteSegment segment = queue.poll();
|
||||||
if(segments.size() == 0) {
|
if (visitedIds.contains(calculateId(segment))) {
|
||||||
queue.poll();
|
// System.out.println("contains " + segment.getRoad());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RouteSegment segment = segments.remove(segments.size() - 1);
|
// System.out.println(segment.getRoad());
|
||||||
RouteDataObject road = segment.getRoad();
|
visitedIds.add(calculateId(segment));
|
||||||
if(visitedIds.contains(calculateId(segment, segment.getSegmentStart()))){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
segmentsProcessed++;
|
|
||||||
if(segmentsProcessed > 50) {
|
|
||||||
float ratio = (float) (queue.size() + outOfTile + outOfDistance) / segmentsProcessed;
|
|
||||||
if(ratio < minRatio) {
|
|
||||||
minRatio = ratio;
|
|
||||||
segmentsMinProcessed = segmentsProcessed;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
visitedIds.add(calculateId(segment, segment.getSegmentStart()));
|
|
||||||
boolean minusAllowed = true;
|
|
||||||
boolean plusAllowed = true;
|
|
||||||
int d = 1;
|
|
||||||
while (minusAllowed || plusAllowed) {
|
|
||||||
int segmentEnd = segment.getSegmentStart() + d;
|
|
||||||
int currentD = d;
|
|
||||||
if (!minusAllowed && d > 0) {
|
|
||||||
d++;
|
|
||||||
} else if (!plusAllowed && d < 0) {
|
|
||||||
d--;
|
|
||||||
} else {
|
|
||||||
if (d <= 0) {
|
|
||||||
d = -d + 1;
|
|
||||||
} else {
|
|
||||||
d = -d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (segmentEnd < 0) {
|
|
||||||
minusAllowed = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (segmentEnd >= road.getPointsLength()) {
|
|
||||||
plusAllowed = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (visitedIds.contains(calculateId(segment, segmentEnd))) {
|
|
||||||
if (currentD > 0) {
|
|
||||||
plusAllowed = false;
|
|
||||||
} else {
|
|
||||||
minusAllowed = false;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
visitedIds.add(calculateId(segment, segmentEnd));
|
|
||||||
|
|
||||||
int x = road.getPoint31XTile(segmentEnd);
|
|
||||||
int y = road.getPoint31YTile(segmentEnd);
|
|
||||||
RouteSegment next = ctx.loadRouteSegment(x, y, 0);
|
|
||||||
RouteSegment toAdd = segment;
|
|
||||||
if (!onTheMap.contains(toAdd.getRoad().getId())) {
|
|
||||||
onTheMap.add(toAdd.getRoad().getId());
|
|
||||||
// Visualization of steps !
|
// Visualization of steps !
|
||||||
ctx.getVisitor().visitSegment(toAdd, -1, true);
|
if (ctx.getVisitor() != null) {
|
||||||
|
ctx.getVisitor().visitSegment(segment, -1, true);
|
||||||
}
|
}
|
||||||
List<RouteSegment> nextSegments = new ArrayList<BinaryRoutePlanner.RouteSegment>();
|
cCtx.roadProcessed++;
|
||||||
boolean out = false;
|
if (cCtx.roadProcessed > 50) {
|
||||||
boolean outDistance = false;
|
float ratio = (float) (queue.size() + cCtx.outOfTile + cCtx.outOfDistance) / cCtx.roadProcessed;
|
||||||
while (next != null) {
|
if (ratio < cCtx.minRatio) {
|
||||||
if (!visitedIds.contains(calculateId(next, next.getSegmentStart()))) {
|
cCtx.minRatio = ratio;
|
||||||
int tX = next.getRoad().getPoint31XTile(next.getSegmentStart()) >> zm;
|
cCtx.roadMinProcessed = cCtx.roadProcessed;
|
||||||
int tY = next.getRoad().getPoint31YTile(next.getSegmentStart()) >> zm;
|
|
||||||
String highway = next.getRoad().getHighway();
|
|
||||||
if(notClusterAtAll(next.getRoad())) {
|
|
||||||
out = true;
|
|
||||||
} else if(Math.abs(tX - tileX) < LOCAL_TILE_BOUNDARIES && Math.abs(tY - tileY) < LOCAL_TILE_BOUNDARIES) {
|
|
||||||
nextSegments.add(next);
|
|
||||||
} else {
|
|
||||||
if (!isMajorHighway(highway) && Math.abs(tX - tileX) < TILE_BOUNDARIES && Math.abs(tY - tileY) < TILE_BOUNDARIES) {
|
|
||||||
nextSegments.add(next);
|
|
||||||
} else {
|
|
||||||
outDistance = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
processSegment(cCtx, ctx, segment, queue, result, tileX, tileY, true);
|
||||||
|
processSegment(cCtx, ctx, segment, queue, result, tileX, tileY, false);
|
||||||
}
|
}
|
||||||
next = next.getNext();
|
log.info("Current ratio " + ((float) (queue.size() + cCtx.outOfTile + cCtx.outOfDistance) / cCtx.roadProcessed) + " min ratio " + cCtx.minRatio
|
||||||
}
|
+ " min segments procesed " + cCtx.roadMinProcessed );
|
||||||
if(out) {
|
String res = "Processed " + cCtx.roadProcessed + " / " + cCtx.segmentsProcessed+ " and borders are " + cCtx.outOfTile + " out because of distance " + cCtx.outOfDistance;
|
||||||
outOfTile++;
|
|
||||||
result.add(segment);
|
|
||||||
} else if(outDistance) {
|
|
||||||
outOfDistance++;
|
|
||||||
result.add(segment);
|
|
||||||
} else if(nextSegments.size() > 0) {
|
|
||||||
queue.add(nextSegments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("Current ratio " + ((float) (queue.size() + outOfTile + outOfDistance) / segmentsProcessed) + " min ratio " + minRatio
|
|
||||||
+ " min segments procesed " + segmentsMinProcessed );
|
|
||||||
String res = "Processed " + segmentsProcessed + " and borders are " + outOfTile + " out because of distance " + outOfDistance;
|
|
||||||
log.info(res);
|
log.info(res);
|
||||||
System.out.println(res);
|
System.out.println(res);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean notClusterAtAll(RouteDataObject obj) {
|
private void addSegmentResult(List<RouteSegment> result , RouteSegment sgm, int segmentSt, int segmentEnd) {
|
||||||
|
RouteSegment r = new RouteSegment(sgm.getRoad(), segmentSt);
|
||||||
|
r.setParentSegmentEnd(segmentEnd);
|
||||||
|
result.add(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSegment(ClusteringContext cCtx, RoutingContext ctx, RouteSegment segment, Queue<RouteSegment> queue, List<RouteSegment> result,
|
||||||
|
int tileX, int tileY, boolean direction ) {
|
||||||
|
|
||||||
|
int d = 1;
|
||||||
|
boolean directionAllowed = true;
|
||||||
|
int prev = segment.getSegmentStart();
|
||||||
|
while (directionAllowed) {
|
||||||
|
int segmentEnd = segment.getSegmentStart() + (direction?d : -d);
|
||||||
|
d++;
|
||||||
|
if (segmentEnd < 0 || segmentEnd >= segment.getRoad().getPointsLength()) {
|
||||||
|
directionAllowed = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = segment.getRoad().getPoint31XTile(segmentEnd);
|
||||||
|
int y = segment.getRoad().getPoint31YTile(segmentEnd);
|
||||||
|
int tX = x >> cCtx.zm;
|
||||||
|
int tY = y >> cCtx.zm;
|
||||||
|
cCtx.segmentsProcessed ++;
|
||||||
|
if(notClusterAtAll(cCtx, segment.getRoad())) {
|
||||||
|
cCtx.outOfTile++;
|
||||||
|
addSegmentResult(result, segment, prev, segmentEnd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isMajorHighway(cCtx, segment.getRoad().getHighway()) && (Math.abs(tX - tileX) > cCtx.TILE_BOUNDARIES || Math.abs(tY - tileY) <
|
||||||
|
cCtx.TILE_BOUNDARIES)) {
|
||||||
|
cCtx.outOfDistance++;
|
||||||
|
// System.out.println("Res Major " + segment.getRoad());
|
||||||
|
addSegmentResult(result, segment, prev, segmentEnd);
|
||||||
|
return;
|
||||||
|
} else if(Math.abs(tX - tileX) > cCtx.LOCAL_TILE_BOUNDARIES || Math.abs(tY - tileY) >
|
||||||
|
cCtx.LOCAL_TILE_BOUNDARIES) {
|
||||||
|
// System.out.println("Res " + segment.getRoad());
|
||||||
|
cCtx.outOfDistance++;
|
||||||
|
addSegmentResult(result, segment, prev, segmentEnd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RouteSegment next = ctx.loadRouteSegment(x, y, 0);
|
||||||
|
while (next != null) {
|
||||||
|
// System.out.println(" >> " + next.getRoad());
|
||||||
|
queue.add(next);
|
||||||
|
next = next.getNext();
|
||||||
|
|
||||||
|
}
|
||||||
|
prev = segmentEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean notClusterAtAll(ClusteringContext clusterCtx, RouteDataObject obj) {
|
||||||
|
if(clusterCtx.BASEMAP_CLUSTERING) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
String highway = obj.getHighway();
|
String highway = obj.getHighway();
|
||||||
if(highway != null) {
|
if(highway != null) {
|
||||||
return highway.equals("trunk") || highway.equals("motorway")
|
return highway.equals("trunk") || highway.equals("motorway")
|
||||||
|
@ -329,10 +320,13 @@ public class MapClusterLayer implements MapPanelLayer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMajorHighway(String h) {
|
public boolean isMajorHighway(ClusteringContext clusterCtx, String h) {
|
||||||
if(h == null) {
|
if(h == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(clusterCtx.BASEMAP_CLUSTERING) {
|
||||||
|
return h.equals("motorway") || h.equals("trunk");
|
||||||
|
}
|
||||||
return h.equals("primary")
|
return h.equals("primary")
|
||||||
|| h.equals("secondary");
|
|| h.equals("secondary");
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,8 +214,7 @@ public class MapRouterLayer implements MapPanelLayer {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
List<Way> ways = route_YOURS(startRoute, endRoute);
|
List<Way> ways = route_YOURS(startRoute, endRoute);
|
||||||
DataTileManager<Way> points = new DataTileManager<Way>();
|
DataTileManager<Way> points = new DataTileManager<Way>(11);
|
||||||
points.setZoom(11);
|
|
||||||
for(Way w : ways){
|
for(Way w : ways){
|
||||||
LatLon n = w.getLatLon();
|
LatLon n = w.getLatLon();
|
||||||
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
||||||
|
@ -235,8 +234,7 @@ public class MapRouterLayer implements MapPanelLayer {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
List<Way> ways = route_CloudMate(startRoute, endRoute);
|
List<Way> ways = route_CloudMate(startRoute, endRoute);
|
||||||
DataTileManager<Way> points = new DataTileManager<Way>();
|
DataTileManager<Way> points = new DataTileManager<Way>(11);
|
||||||
points.setZoom(11);
|
|
||||||
for (Way w : ways) {
|
for (Way w : ways) {
|
||||||
LatLon n = w.getLatLon();
|
LatLon n = w.getLatLon();
|
||||||
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
||||||
|
@ -295,8 +293,7 @@ public class MapRouterLayer implements MapPanelLayer {
|
||||||
public void run() {
|
public void run() {
|
||||||
List<Way> ways = selfRoute(startRoute, endRoute, intermediates, previousRoute, useBasemap);
|
List<Way> ways = selfRoute(startRoute, endRoute, intermediates, previousRoute, useBasemap);
|
||||||
if (ways != null) {
|
if (ways != null) {
|
||||||
DataTileManager<Way> points = new DataTileManager<Way>();
|
DataTileManager<Way> points = new DataTileManager<Way>(11);
|
||||||
points.setZoom(11);
|
|
||||||
for (Way w : ways) {
|
for (Way w : ways) {
|
||||||
LatLon n = w.getLatLon();
|
LatLon n = w.getLatLon();
|
||||||
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
||||||
|
@ -647,8 +644,7 @@ public class MapRouterLayer implements MapPanelLayer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final DataTileManager<Entity> points = new DataTileManager<Entity>();
|
final DataTileManager<Entity> points = new DataTileManager<Entity>(11);
|
||||||
points.setZoom(11);
|
|
||||||
map.setPoints(points);
|
map.setPoints(points);
|
||||||
ctx.setVisitor(new RouteSegmentVisitor() {
|
ctx.setVisitor(new RouteSegmentVisitor() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue