Small data tile manager refactoring

This commit is contained in:
Victor Shcherb 2012-10-15 22:05:41 +02:00
parent 5d1e5ea54d
commit 48fcb7d1dc
10 changed files with 222 additions and 207 deletions

View file

@ -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);
} }

View file

@ -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;
@ -33,30 +29,18 @@ public class DataTileManager<T> {
public int getZoom() { public int getZoom() {
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>());
} }

View file

@ -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;

View file

@ -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

View 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;
}
}

View file

@ -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();
} }

View file

@ -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>>();

View file

@ -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>

View file

@ -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,27 +96,25 @@ 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>(); for (RouteSegment s : ways) {
points.setZoom(11); Way w = new Way(-1);
for (RouteSegment s : ways) { for (int i = 0; i < s.getRoad().getPointsLength(); i++) {
Way w = new Way(-1); double lat = MapUtils.get31LatitudeY(s.getRoad().getPoint31YTile(i));
for (int i = 0; i < s.getRoad().getPointsLength(); i++) { double lon = MapUtils.get31LongitudeX(s.getRoad().getPoint31XTile(i));
double lat = MapUtils.get31LatitudeY(s.getRoad().getPoint31YTile(i)); w.addNode(new Node(lat, lon, -1));
double lon = MapUtils.get31LongitudeX(s.getRoad().getPoint31XTile(i));
w.addNode(new Node(lat, lon, -1));
}
LatLon n = w.getLatLon();
points.registerObject(n.getLatitude(), n.getLongitude(), w);
} }
map.setPoints(points); LatLon n = w.getLatLon();
map.repaint(); points.registerObject(n.getLatitude(), n.getLongitude(), w);
} }
map.setPoints(points);
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; while (!queue.isEmpty()) {
int tileY = startRoad.getPoint31YTile(st.getSegmentStart()) >> zm; RouteSegment segment = queue.poll();
int outOfTile = 0; if (visitedIds.contains(calculateId(segment))) {
int outOfDistance = 0; // System.out.println("contains " + segment.getRoad());
int segmentsProcessed = 0;
float minRatio = 1f;
int segmentsMinProcessed = 0;
TLongHashSet onTheMap = new TLongHashSet();
while(!queue.isEmpty()){
List<RouteSegment> segments = queue.peek();
if(segments.size() == 0) {
queue.poll();
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()))){ // Visualization of steps !
continue; if (ctx.getVisitor() != null) {
ctx.getVisitor().visitSegment(segment, -1, true);
} }
segmentsProcessed++; cCtx.roadProcessed++;
if(segmentsProcessed > 50) { if (cCtx.roadProcessed > 50) {
float ratio = (float) (queue.size() + outOfTile + outOfDistance) / segmentsProcessed; float ratio = (float) (queue.size() + cCtx.outOfTile + cCtx.outOfDistance) / cCtx.roadProcessed;
if(ratio < minRatio) { if (ratio < cCtx.minRatio) {
minRatio = ratio; cCtx.minRatio = ratio;
segmentsMinProcessed = segmentsProcessed; cCtx.roadMinProcessed = cCtx.roadProcessed;
}
}
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 !
ctx.getVisitor().visitSegment(toAdd, -1, true);
}
List<RouteSegment> nextSegments = new ArrayList<BinaryRoutePlanner.RouteSegment>();
boolean out = false;
boolean outDistance = false;
while (next != null) {
if (!visitedIds.contains(calculateId(next, next.getSegmentStart()))) {
int tX = next.getRoad().getPoint31XTile(next.getSegmentStart()) >> zm;
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;
}
}
}
next = next.getNext();
}
if(out) {
outOfTile++;
result.add(segment);
} else if(outDistance) {
outOfDistance++;
result.add(segment);
} else if(nextSegments.size() > 0) {
queue.add(nextSegments);
} }
} }
processSegment(cCtx, ctx, segment, queue, result, tileX, tileY, true);
processSegment(cCtx, ctx, segment, queue, result, tileX, tileY, false);
} }
log.info("Current ratio " + ((float) (queue.size() + outOfTile + outOfDistance) / segmentsProcessed) + " min ratio " + minRatio log.info("Current ratio " + ((float) (queue.size() + cCtx.outOfTile + cCtx.outOfDistance) / cCtx.roadProcessed) + " min ratio " + cCtx.minRatio
+ " min segments procesed " + segmentsMinProcessed ); + " min segments procesed " + cCtx.roadMinProcessed );
String res = "Processed " + segmentsProcessed + " and borders are " + outOfTile + " out because of distance " + outOfDistance; String res = "Processed " + cCtx.roadProcessed + " / " + cCtx.segmentsProcessed+ " and borders are " + cCtx.outOfTile + " out because of distance " + cCtx.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");
} }

View file

@ -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() {