diff --git a/DataExtractionOSM/src/net/osmand/ToDoConstants.java b/DataExtractionOSM/src/net/osmand/ToDoConstants.java index c13dd04321..c26461e126 100644 --- a/DataExtractionOSM/src/net/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/net/osmand/ToDoConstants.java @@ -8,49 +8,40 @@ package net.osmand; public class ToDoConstants { - // TODO max 94 + // TODO max 96 // FOR 0.4 beta RELEASE + // ! 89. Transport redesign UI (enable run from context menu, switch go to goal/not) ! + // ! 95. Show progress while map rendered and loaded + // 90. Use Junidecode library on the client for english translation (for map rendering and other save disk space) + // + // !_25. Add all attributes needed for routing (highway attributes, turn_restrictions) + // !_22. Verify all POI has a point_type (in order to search them) + // !_1 . VELCOM + // !_18. Fix loading map data in rotated mode (check properly boundaries) +/- + + // not required // ! 81. Add some objects to POI category (1) to add them into OSM 2) to help navigation) // highway (?), traffic_calming (?), barrier(?), military(?-), landuse (?), office(?), man_made(?), power(?), // railway( station, subway?) - issue 17 // ! 87. Use network availability for defining loading tiles from internet. - // ! 89. Transport redesign UI (enable run from context menu, switch go to goal/not) ! - // ! 95. Show progress while map rendered and loaded - // 90. Use Junidecode library on the client for english translation (for map rendering and other save disk space) - // outside base 0.4 release + // _19. colors for road trunk and motorway + // _12. Fix : find proper location for streets ! centralize them (when create index)? + // _28. Fix freeze while map downloading (?) + + // Outside base 0.4 release // 86. Allow to add/edit custom tags to POI objects. // 91. Invent binary format (minimize disk space, maximize speed) // 92. Replace poi index with standard map index and unify POI categories - // 93. Implement multitype vector objects (?) - building with fence, road & tram ... (binary format) - // 94. Revise index to decrease their size (especially address) - replace to float lat/lon + // 94. Revise index to decrease their size (especially address) - replace to float lat/lon and remove for POI + // eng_name, possibly remove en part for adress - - // TODO small improvements for release : - // 19. colors for road trunk and motorway - // 12. Fix : find proper location for streets ! centralize them (when create index)? - // 24. +! define clockwise/anticlockwise on android for closed path to understand area outised or inside - // fix Rendering for incompleted rings, - // fix Index Creator : 1) determine clockwise area (inverse if needed)+ 2) index low level multipolygon pass param + - // 3) pass inverse to low level indexes+ 4) coastline / add area + - // 5) identify case when there is only inner boundary (!!!!) + - // 26. Move leisure below forest and grass layer (footway/cycleway below unspecified) - // 25. Add all attributes needed for routing (highway attributes, turn_restrictions) - // 27. Fix bug with some buildings in AMS (WTC) that have fence(?) - // 28. Fix freeze while map downloading - - // TODO Improvements : - // 1! VELCOM - // +17. Implement multipolygons to polygons (!?) + coastline - (todo indexCreator) - // +23! Remove one bit from type! - //+-18. Fix loading map data in rotated mode (check properly boundaries) - // 22. Verify all POI has a point_type (in order to search them) - + ///////////////////////////// UNKNOWN STATE //////////////////// // Unscheduled (complex) // 65. Intermediate points - for better control routing, to avoid traffic jams ...(?) - // 63. Support simple offline routing(require new index file) (?) + // 63. Support simple offline routing(require index file with turn restrictions etc) (?) // Not clear if it is really needed // 69. Add phone information to POI @@ -59,6 +50,7 @@ public class ToDoConstants { // 83. Add monitoring service to send locations to internet (?) // DONE ANDROID : + // 93. Implement multitype vector objects - building with fence, road & tram ... // DONE SWING // 12. Reinvent UI of swing app (remove Region object and clear other MapObject) diff --git a/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java b/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java index b257dbcea0..110c050c68 100644 --- a/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java +++ b/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java @@ -1710,11 +1710,11 @@ public class IndexCreator { // creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/belarus_nodes.tmp.odb")); // creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/belarus_2010_09_03.osm.bz2"), new ConsoleProgressImplementation(3), null); -// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/ams.tmp.odb")); -// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/ams_part_map.osm"), new ConsoleProgressImplementation(3), null); + creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/ams.tmp.odb")); + creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/ams_part_map.osm"), new ConsoleProgressImplementation(3), null); - creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/den_haag.tmp.odb")); - creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/den_haag.osm"), new ConsoleProgressImplementation(3), null); +// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/den_haag.tmp.odb")); +// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/den_haag.osm"), new ConsoleProgressImplementation(3), null); // creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/one.tmp.odb")); // creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/one_multipolygon.osm"), new ConsoleProgressImplementation(3), null); diff --git a/DataExtractionOSM/src/net/osmand/osm/MapRenderObject.java b/DataExtractionOSM/src/net/osmand/osm/MapRenderObject.java index 972dc32428..f0d9149604 100644 --- a/DataExtractionOSM/src/net/osmand/osm/MapRenderObject.java +++ b/DataExtractionOSM/src/net/osmand/osm/MapRenderObject.java @@ -93,23 +93,47 @@ public class MapRenderObject { public float getMapOrder(){ if (order == -1) { - int oType = MapRenderingTypes.getMainObjectType(type >> 1); - int sType = MapRenderingTypes.getObjectSubType(type >> 1); - if (isMultiPolygon() || isPolygon()) { - // 1 - 9 - if (oType == MapRenderingTypes.MAN_MADE && sType == MapRenderingTypes.SUBTYPE_BUILDING) { - // draw over lines + order = getOrder(getMainType()); + } + return order; + } + + public static float getOrder(int wholeType) { + float order = 0; + int t = wholeType & 3; + int oType = MapRenderingTypes.getMainObjectType(wholeType); + int sType = MapRenderingTypes.getObjectSubType(wholeType); + int layer = MapRenderingTypes.getWayLayer(wholeType); + if (t == MapRenderingTypes.MULTY_POLYGON_TYPE || t == MapRenderingTypes.POLYGON_TYPE) { + // 1 - 9 + if (oType == MapRenderingTypes.MAN_MADE && sType == MapRenderingTypes.SUBTYPE_BUILDING) { + // draw over lines + if(layer != 1){ + order = 64; + } else { + order = 2; + } + } else { + if(layer == 1){ + order = 0.5f; + } else if(layer == 2){ + // over lines order = 64; } else if (oType == MapRenderingTypes.LANDUSE) { switch (sType) { - case 5: case 6: case 15: case 18: case 20: case 23: + case 5: + case 6: + case 15: + case 18: + case 20: + case 23: order = 1; break; case 22: order = 5; break; default: - order = 1.5f; + order = 1f; break; } } else if (oType == MapRenderingTypes.LEISURE) { @@ -117,66 +141,66 @@ public class MapRenderObject { case 3: case 10: case 13: - order = 4; + order = 2; break; + case 6: + order = 4; default: - order = 1; + order = 2; break; } } else if (oType == MapRenderingTypes.POWER) { order = 4; - } else if (oType == MapRenderingTypes.WATERWAY || oType == MapRenderingTypes.NATURAL) { + } else if (oType == MapRenderingTypes.NATURAL) { + if (order == 5) { + // coastline + order = 0.5f; + } else if (order == 21) { + // water + order = 5; + } else { + order = 1; + } + } else if (oType == MapRenderingTypes.WATERWAY) { // water 5 order = 5; } else { order = 1; } - } else if (isPolyLine()) { - // 10 - 68 - int layer = MapRenderingTypes.getWayLayer(type >> 1); - if(layer == 1 && oType != MapRenderingTypes.RAILWAY){ - // not subway especially - order = 10; - } else if(layer == 2) { - order = 67; // over buildings - } else if (oType == MapRenderingTypes.HIGHWAY) { - order = 32 - sType + 24; - if(sType == MapRenderingTypes.PL_HW_MOTORWAY){ - // TODO ? that was done only to have good overlay - // but really it should be motorway_link have -= 10 - order -= 2; - } - } else if (oType == MapRenderingTypes.RAILWAY) { - order = 58; - } else if (oType == MapRenderingTypes.AERIALWAY) { - order = 68; // over buildings - } else if (oType == MapRenderingTypes.POWER) { - order = 68; // over buildings - } else if (oType == MapRenderingTypes.ADMINISTRATIVE) { - order = 62; - } else if (oType == MapRenderingTypes.WATERWAY) { - order = 18; - } else { - order = 10; - } - } else { - order = 128; } + } else if (t == MapRenderingTypes.POLYLINE_TYPE) { + // 10 - 68 + if(layer == 1 && oType != MapRenderingTypes.RAILWAY){ + // not subway especially + order = 10; + } else if(layer == 2) { + order = 67; // over buildings + } else if (oType == MapRenderingTypes.HIGHWAY) { + order = 32 - sType + 24; + if(sType == MapRenderingTypes.PL_HW_MOTORWAY){ + // TODO ? that was done only to have good overlay + // but really it should be motorway_link have -= 10 + order -= 2; + } + } else if (oType == MapRenderingTypes.RAILWAY) { + order = 58; + } else if (oType == MapRenderingTypes.AERIALWAY) { + order = 68; // over buildings + } else if (oType == MapRenderingTypes.POWER) { + order = 68; // over buildings + } else if (oType == MapRenderingTypes.ADMINISTRATIVE) { + order = 62; + } else if (oType == MapRenderingTypes.WATERWAY) { + order = 18; + } else { + order = 10; + } + } else { + order = 128; } return order; } - private boolean isMultiPolygon(){ - return ((type >> 1) & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE; - } - - private boolean isPolygon(){ - return ((type >> 1) & 3) == MapRenderingTypes.POLYGON_TYPE; - } - - private boolean isPolyLine(){ - return ((type >> 1) & 3) == MapRenderingTypes.POLYLINE_TYPE; - } } diff --git a/DataExtractionOSM/src/net/osmand/osm/MapRenderingTypes.java b/DataExtractionOSM/src/net/osmand/osm/MapRenderingTypes.java index d8c409321c..00ffd7ee02 100644 --- a/DataExtractionOSM/src/net/osmand/osm/MapRenderingTypes.java +++ b/DataExtractionOSM/src/net/osmand/osm/MapRenderingTypes.java @@ -17,16 +17,16 @@ import net.osmand.osm.OSMSettings.OSMTagKey; */ public class MapRenderingTypes { - + // TODO Internet access bits for point, polygon /** standard schema : - Last bit describe whether types additional exist - polygon : aaaaa ttttt 11 : 26 bits + 6 bits for special info - t - object type, a - area subtype, p - point object type, s - point object subtype - multi : - polyline : ppppp ttttt 10 : 13 bits + 19 bits for special info - t - object type, p - polyline object type, - point : ssssssss ttttt 10 : 16 bits + 16 bits for special info - t - object type, a - subtype + Last bit describe whether types additional exist (it is needed only for main type, other consists only from 15 bits) + polygon : aaaaa ttttt 11 _ : 15 bits + multi : aaaaa ttttt 00 _ : 15 bits + t - object type, a - area subtype,l - layer + polyline : ll ppppp ttttt 10 _ : 15 bits + 2 bits for special info (+16) + t - object type, p - polyline object type, l - layer + point : ssssssss ttttt 10 _ : 16 bits + t - object type, a - subtype */ public final static int MULTY_POLYGON_TYPE = 0; @@ -53,7 +53,6 @@ public class MapRenderingTypes { public final static char REF_CHAR = ((char)0x0019); - // TODO Internet access bits for point public final static int HIGHWAY = 1; public final static int BARRIER = 2; public final static int WATERWAY = 3; @@ -128,26 +127,6 @@ public class MapRenderingTypes { } } - /*public static int getPolygonSubType(int type) { - - } - - public static int getPolygonPointType(int type) { - return (type >> (TYPE_MASK_LEN + OBJ_TYPE_MASK_LEN + PG_SUBTYPE_MASK_LEN)) & OBJ_TYPE_MASK; - } - - public static int getPolygonPointSubType(int type) { - return (type >> (TYPE_MASK_LEN + OBJ_TYPE_MASK_LEN + PG_SUBTYPE_MASK_LEN + OBJ_TYPE_MASK_LEN)) & PO_SUBTYPE_MASK; - } - - public static int getPolylineSubType(int type) { - return (type >> (TYPE_MASK_LEN + OBJ_TYPE_MASK_LEN)) & PL_SUBTYPE_MASK; - } - - public static int getPointSubType(int type) { - return (type >> (TYPE_MASK_LEN + OBJ_TYPE_MASK_LEN)) & PO_SUBTYPE_MASK; - } - */ // stored information to convert from osm tags to int type private static Map types = null; @@ -300,7 +279,8 @@ public class MapRenderingTypes { } } else if (polygon && (pr == POLYGON_WITH_CENTER_TYPE || pr == POLYGON_TYPE)) { boolean prevPoint = (polylineType == 0 && polygonType == 0); - polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (typeVal & MASK_12); + int attr = getLayerAttributes(e) << 12; + polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (typeVal & MASK_12) | attr; if (prevPoint){ addTypes.add(0, polygonType); } else { @@ -351,7 +331,7 @@ public class MapRenderingTypes { } public static boolean isOneWayWay(int type){ - return ((1 << 14) & type) > 0; + return ((1 << 15) & type) > 0; } // 0 - normal, 1 - under, 2 - bridge,over @@ -591,6 +571,7 @@ public class MapRenderingTypes { register("barrier", "hedge", BARRIER, 1, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ register("natural", "hedge", BARRIER, 1, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ register("barrier", "fence", BARRIER, 2, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ + register("fenced", "yes", BARRIER, 2, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ register("barrier", "wall", BARRIER, 3, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ register("barrier", "ditch", BARRIER, 1, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ register("barrier", "retaining_wall", BARRIER, 4, POLYLINE_TYPE); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/OsmAnd/src/net/osmand/render/OsmandRenderer.java b/OsmAnd/src/net/osmand/render/OsmandRenderer.java index 8698a0b4e4..b9adb2796f 100644 --- a/OsmAnd/src/net/osmand/render/OsmandRenderer.java +++ b/OsmAnd/src/net/osmand/render/OsmandRenderer.java @@ -7,6 +7,7 @@ import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import net.osmand.LogUtil; import net.osmand.R; @@ -38,7 +39,7 @@ import android.graphics.Shader.TileMode; import android.text.TextPaint; import android.util.FloatMath; -public class OsmandRenderer implements Comparator { +public class OsmandRenderer { private static final Log log = LogUtil.getLog(OsmandRenderer.class); private TextPaint paintText; @@ -244,20 +245,36 @@ public class OsmandRenderer implements Comparator { return shaders.get(resId); } - @Override - public int compare(MapRenderObject object1, MapRenderObject object2) { - float o1 = object1.getMapOrder(); - float o2 = object2.getMapOrder(); - return o1 < o2 ? -1 : (o1 == o2 ? 0 : 1); + private void put(Map> map, K k, T v, int init){ + if(!map.containsKey(k)){ + map.put(k, new ArrayList(init)); + } + map.get(k).add(v); } - public Bitmap generateNewBitmap(int width, int height, float leftTileX, float topTileY, List objects, int zoom, float rotate) { long now = System.currentTimeMillis(); + // put in order map + int sz = objects.size(); + int init = sz / 4; + TreeMap> orderMap = new TreeMap>(); + for (int i = 0; i < sz; i++) { + MapRenderObject o = objects.get(i); + int mt = o.getMainType(); + int sh = i << 8; + put(orderMap, MapRenderObject.getOrder(mt), sh + 1, init); + int s = o.getSecondType(); + if (s != 0) { + put(orderMap, MapRenderObject.getOrder(s), sh + 2, init); + } + byte multiTypes = o.getMultiTypes(); + for (int j = 0; j < multiTypes; j++) { + put(orderMap, MapRenderObject.getOrder(o.getAdditionalType(j)), sh + (j + 3), init); + } + } - Collections.sort(objects, this); Bitmap bmp = null; if (objects != null && !objects.isEmpty() && width > 0 && height > 0) { // init rendering context @@ -275,8 +292,20 @@ public class OsmandRenderer implements Comparator { Canvas cv = new Canvas(bmp); cv.drawRect(0, 0, bmp.getWidth(), bmp.getHeight(), paintFillEmpty); - for (MapRenderObject o : objects) { - draw(o, cv, rc); + for (List list : orderMap.values()) { + for (Integer i : list) { + int ind = i >> 8; + int l = i & 0xff; + MapRenderObject obj = objects.get(ind); + if (l == 1) { + // show text only for main type + drawObj(obj, cv, rc, obj.getMainType(), true); + } else if (l == 2) { + drawObj(obj, cv, rc, obj.getSecondType(), false); + } else { + drawObj(obj, cv, rc, obj.getAdditionalType(l - 3), false); + } + } } for(IconDrawInfo icon : rc.iconsToDraw){ if(icon.resId != 0){ @@ -451,22 +480,19 @@ public class OsmandRenderer implements Comparator { } - protected PointF drawObj(MapRenderObject obj, Canvas canvas, RenderingContext rc, int mainType, boolean renderText, PointF center) { - if(mainType == 0){ - return center; - } + protected void drawObj(MapRenderObject obj, Canvas canvas, RenderingContext rc, int mainType, boolean renderText) { int t = mainType & 3; int type = MapRenderingTypes.getMainObjectType(mainType); int subtype = MapRenderingTypes.getObjectSubType(mainType); if(t == MapRenderingTypes.POINT_TYPE){ - drawPoint(obj, canvas, rc, null, type, subtype, renderText); + drawPoint(obj, canvas, rc, type, subtype, renderText); } else if(t == MapRenderingTypes.POLYLINE_TYPE){ drawPolyline(obj, canvas, rc, type, subtype, mainType); } else { if(t == MapRenderingTypes.MULTY_POLYGON_TYPE && !(obj instanceof MultyPolygon)){ - return center; + return; } - center = drawPolygon(obj, canvas, rc, type, subtype, t == MapRenderingTypes.MULTY_POLYGON_TYPE); + PointF center = drawPolygon(obj, canvas, rc, type, subtype, t == MapRenderingTypes.MULTY_POLYGON_TYPE); String name = obj.getName(); if(name != null && center != null){ rc.clearText(); @@ -479,31 +505,8 @@ public class OsmandRenderer implements Comparator { } } - return center; - } - protected void draw(MapRenderObject obj, Canvas canvas, RenderingContext rc) { - int mainType = obj.getMainType(); - int t = mainType & 3; - int sz = rc.textToDraw.size(); - PointF center = null; - center = drawObj(obj, canvas, rc, mainType, sz == rc.textToDraw.size(), center); - if (t != MapRenderingTypes.POINT_TYPE) { - int second = obj.getSecondType(); - if (second != 0) { - center = drawObj(obj, canvas, rc, second, sz == rc.textToDraw.size(), center); - } - if (obj.isMultitype()) { - byte ts = obj.getMultiTypes(); - for (int k = 0; k < ts; k++) { - center = drawObj(obj, canvas, rc, obj.getAdditionalType(k), sz == rc.textToDraw.size(), center); - } - } - } - } - - private PointF calcPoint(MapRenderObject o, int ind, RenderingContext rc){ rc.pointCount ++; @@ -613,16 +616,24 @@ public class OsmandRenderer implements Comparator { shaders.clear(); } - private void drawPoint(MapRenderObject obj, Canvas canvas, RenderingContext rc, PointF p, int type, int subtype, boolean renderText) { - if (p == null) { - p = calcPoint(obj, 0, rc); + private void drawPoint(MapRenderObject obj, Canvas canvas, RenderingContext rc, int type, int subtype, boolean renderText) { + int len = obj.getPointsLength(); + PointF ps = new PointF(0, 0); + for (int i = 0; i < len; i++) { + PointF p = calcPoint(obj, i, rc); + ps.x += p.x; + ps.y += p.y; + } + if(len > 1){ + ps.x /= len; + ps.y /= len; } int zoom = rc.zoom; int resId = PointRenderer.getPointBitmap(zoom, type, subtype); if(resId != 0){ IconDrawInfo ico = new IconDrawInfo(); - ico.x = p.x; - ico.y = p.y; + ico.x = ps.x; + ico.y = ps.y; ico.resId = resId; rc.iconsToDraw.add(ico); } @@ -633,7 +644,7 @@ public class OsmandRenderer implements Comparator { n = renderObjectText(n, subtype, type, zoom, true, rc); if (rc.textSize > 0 && n != null) { TextDrawInfo info = new TextDrawInfo(n); - info.fillProperties(rc, p.x, p.y); + info.fillProperties(rc, ps.x, ps.y); rc.textToDraw.add(info); } }