The patch contains additionally:
* building=entrance nodes of a polygon are used as POI
* MPs preferably use a point with role=label as POI
I've uploaded the compiled patched mkgmap (now with the correctly named
osmprotobuf.jar :-) to http://files.mkgmap.org.uk/detail/36
WanMil
Index: src/uk/me/parabola/imgfmt/app/Coord.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/Coord.java (revision 2047)
+++ src/uk/me/parabola/imgfmt/app/Coord.java (working copy)
@@ -100,7 +100,7 @@
}
public int hashCode() {
- return latitude+longitude;
+ return 503*latitude + longitude;
}
public boolean equals(Object obj) {
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (working copy)
@@ -554,13 +554,6 @@
shape.setPoints(way.getPoints());
clipper.clipShape(shape, collector);
-
- nodeRules.resolveType(way, new TypeResult() {
- public void add(Element el, GType type) {
- if(type != null)
- shape.setPoiType(type.getType());
- }
- });
}
private void addPoint(Node node, GType gt) {
Index: src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/reader/osm/ElementSaver.java (working copy)
@@ -14,6 +14,7 @@
import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
@@ -550,6 +551,10 @@
return wayMap;
}
+ public Map<Long, Relation> getRelations() {
+ return relationMap;
+ }
+
/**
* Get the bounding box. This is either the one that was explicitly included in the input
* file, or if none was given, the calculated one.
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (working copy)
@@ -56,6 +56,7 @@
new RoutingHook(),
new HighwayHooks(),
new LocationHook(),
+ new Areas2POIHook(),
};
protected OsmConverter converter;
private final Set<String> usedTags = new HashSet<String>();
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java (working copy)
@@ -1,6 +1,7 @@
package uk.me.parabola.mkgmap.reader.osm;
-import java.awt.*;
+import java.awt.Polygon;
+import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.util.ArrayList;
@@ -15,9 +16,9 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
+import java.util.Map.Entry;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
@@ -40,6 +41,9 @@
public static final String STYLE_FILTER_LINE = "polyline";
public static final String STYLE_FILTER_POLYGON = "polygon";
+ /** A tag that is set with value true on each polygon that is created by the mp processing */
+ public static final String MP_CREATED_TAG = "mkgmap:mp_created";
+
private final Map<Long, Way> tileWayMap;
private final Map<Long, String> roleMap = new HashMap<Long, String>();
private Map<Long, Way> mpPolygons = new HashMap<Long, Way>();
@@ -49,12 +53,17 @@
protected ArrayList<JoinedWay> polygons;
protected Set<JoinedWay> intersectingPolygons;
+ protected double largestSize;
+ protected JoinedWay largestOuterPolygon;
+
protected Set<Way> outerWaysForLineTagging;
protected Map<String, String> outerTags;
private final uk.me.parabola.imgfmt.app.Area bbox;
protected Area bboxArea;
+ private Coord cOfG = null;
+
/**
* A point that has a lower or equal squared distance from
* a line is treated as if it lies one the line.<br/>
@@ -101,6 +110,19 @@
}
+ /**
+ * Retrieves the center point of this multipolygon. This is set in the
+ * {@link #processElements()} methods so it returns <code>null</code>
+ * before that. It can also return <code>null</code> in case the
+ * multipolygon could not be processed.<br/>
+ * The returned point may lie outside the multipolygon area. It is just
+ * the center point of it.
+ *
+ * @return the center point of this multipolygon (maybe <code>null</code>)
+ */
+ public Coord getCofG() {
+ return cOfG;
+ }
/**
* Retrieves the mp role of the given element.
@@ -893,6 +915,20 @@
outerWaysForLineTagging.addAll(currentPolygon.polygon.getOriginalWays());
}
+ // calculate the size of the polygon
+ double outerAreaSize = currentPolygon.polygon.getSizeOfArea();
+ if (outerAreaSize > largestSize) {
+ // subtract the holes
+ for (PolygonStatus hole : holes) {
+ outerAreaSize -= hole.polygon.getSizeOfArea();
+ }
+ // is it still larger than the largest known polygon?
+ if (outerAreaSize > largestSize) {
+ largestOuterPolygon = currentPolygon.polygon;
+ largestSize = outerAreaSize;
+ }
+ }
+
// check if the polygon is an outer polygon or
// if there are some holes
boolean processPolygon = currentPolygon.outer
@@ -955,7 +991,8 @@
// mark this polygons so that only polygon style rules are applied
mpWay.addTag(STYLE_FILTER_TAG, STYLE_FILTER_POLYGON);
-
+ mpWay.addTag(MP_CREATED_TAG, "true");
+
getMpPolygons().put(mpWay.getId(), mpWay);
}
}
@@ -996,6 +1033,14 @@
}
}
+ if (hasTags(this) == false) {
+ // add tags to the multipolygon that are taken from the outer ways
+ // they may be required by some hooks (e.g. Area2POIHook)
+ for (Entry<String, String> tags : outerTags.entrySet()) {
+ addTag(tags.getKey(), tags.getValue());
+ }
+ }
+
// Go through all original outer ways, create a copy, tag them
// with the mp tags and mark them only to be used for polyline processing
// This enables the style file to decide if the polygon information or
@@ -1004,6 +1049,7 @@
Way lineTagWay = new Way(FakeIdGenerator.makeFakeId(), orgOuterWay.getPoints());
lineTagWay.setName(orgOuterWay.getName());
lineTagWay.addTag(STYLE_FILTER_TAG, STYLE_FILTER_LINE);
+ lineTagWay.addTag(MP_CREATED_TAG, "true");
for (Entry<String,String> tag : outerTags.entrySet()) {
lineTagWay.addTag(tag.getKey(), tag.getValue());
@@ -1025,6 +1071,22 @@
protected void postProcessing() {
// copy all polygons created by the multipolygon algorithm to the global way map
tileWayMap.putAll(mpPolygons);
+
+ if (largestOuterPolygon != null) {
+ // check if the mp contains a node with role "label"
+ for (Map.Entry<String, Element> r_e : getElements()) {
+ if (r_e.getValue() instanceof Node && "label".equals(r_e.getKey())) {
+ // yes => use the label node as reference point
+ cOfG = ((Node)r_e.getValue()).getLocation();
+ break;
+ }
+ }
+
+ if (cOfG == null) {
+ // use the center of the largest polygon as reference point
+ cOfG = largestOuterPolygon.getCofG();
+ }
+ }
}
private void runIntersectionCheck(BitSet unfinishedPolys) {
@@ -1154,7 +1216,8 @@
taggedInnerPolygons = null;
outerPolygons = null;
taggedOuterPolygons = null;
-
+
+ largestOuterPolygon = null;
}
private CutPoint calcNextCutPoint(AreaCutData areaData) {
@@ -1949,6 +2012,7 @@
Way lineTagWay = new Way(FakeIdGenerator.makeFakeId(), orgOuterWay.getPoints());
lineTagWay.setName(orgOuterWay.getName());
lineTagWay.addTag(STYLE_FILTER_TAG, STYLE_FILTER_LINE);
+ lineTagWay.addTag(MP_CREATED_TAG, "true");
for (Entry<String,String> tag : tags.entrySet()) {
lineTagWay.addTag(tag.getKey(), tag.getValue());
@@ -2234,6 +2298,20 @@
public List<Way> getOriginalWays() {
return originalWays;
}
+
+ /**
+ * Retrieves a measurement of the area covered by this polygon. The
+ * returned value has no unit. It is just a rough comparable value
+ * because it uses a rectangular coordinate system without correction.
+ * @return size of the covered areas (0 if the way is not closed)
+ */
+ public double getSizeOfArea() {
+ if (isClosed()==false) {
+ return 0;
+ }
+
+ return SeaPolygonRelation.calcArea(getPoints());
+ }
public String toString() {
StringBuilder sb = new StringBuilder(200);
Index: src/uk/me/parabola/mkgmap/reader/osm/SeaPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/SeaPolygonRelation.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/reader/osm/SeaPolygonRelation.java (working copy)
@@ -180,7 +180,7 @@
seaCoords.clear();
}
- private double calcArea(List<Coord> polygon) {
+ public static double calcArea(List<Coord> polygon) {
Way w = new Way(0, polygon);
if (w.clockwise() == false) {
polygon = new ArrayList<Coord>(polygon);
Index: src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (revision 0)
@@ -0,0 +1,127 @@
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.util.EnhancedProperties;
+
+public class Areas2POIHook extends OsmReadingHooksAdaptor {
+ private static final Logger log = Logger.getLogger(Areas2POIHook.class);
+
+ private ElementSaver saver;
+
+ /** Name of the bool tag that is set to true if a POI is created from an area */
+ public static final String AREA2POI_TAG = "mkgmap:area2poi";
+
+ public Areas2POIHook() {
+ }
+
+ public boolean init(ElementSaver saver, EnhancedProperties props) {
+ if (props.containsKey("add-pois-to-areas") == false) {
+ log.info("Disable Areas2POIHook because add-pois-to-areas option is not set.");
+ return false;
+ }
+
+ this.saver = saver;
+
+ return true;
+ }
+
+ public void end() {
+ addPOIsToWays();
+ addPOIsToMPs();
+ }
+
+ private void addPOIsToWays() {
+ Set<Coord> labelCoords = new HashSet<Coord>();
+
+ // save all coords with building=entrance to a map
+ // so that ways use this coord as its labeling point
+ for (Node n : saver.getNodes().values()) {
+ if ("entrance".equals(n.getTag("building"))) {
+ labelCoords.add(n.getLocation());
+ }
+ }
+
+ log.debug("Found", labelCoords.size(), "label coords");
+
+ int ways2POI = 0;
+
+ for (Way w : saver.getWays().values()) {
+ // check if it is an area
+ if (w.isClosed() == false) {
+ continue;
+ }
+
+ if (w.getTagCount() == 0) {
+ continue;
+ }
+
+ // do not add POIs for polygons created by multipolygon processing
+ if (w.isBoolTag(MultiPolygonRelation.MP_CREATED_TAG)) {
+ log.debug("MP processed: Do not create POI for", w.toTagString());
+ continue;
+ }
+
+ // get the coord where the poi is placed
+ Coord poiCoord = null;
+ // do we have some labeling coords?
+ if (labelCoords.size() > 0) {
+ // go through all points of the way and check if one of the coords
+ // is a labeling coord
+ for (Coord c : w.getPoints()) {
+ if (labelCoords.contains(c)) {
+ // this coord is a labeling coord
+ // use it for the current way
+ poiCoord = c;
+ break;
+ }
+ }
+ }
+ if (poiCoord == null) {
+ // did not find any label coord
+ // use the common center point of the area
+ poiCoord = w.getCofG();
+ }
+
+ Node poi = new Node(FakeIdGenerator.makeFakeId(), poiCoord);
+ poi.copyTags(w);
+ poi.deleteTag(MultiPolygonRelation.STYLE_FILTER_TAG);
+ poi.addTag(AREA2POI_TAG, "true");
+ log.debug("Create POI",poi.toTagString(),"from",w.getId(),w.toTagString());
+ saver.addNode(poi);
+ ways2POI++;
+ }
+
+ log.info(ways2POI, "POIs from single areas created");
+ }
+
+ private void addPOIsToMPs() {
+ int mps2POI = 0;
+ for (Relation r : saver.getRelations().values()) {
+
+ // create POIs for multipolygon relations only
+ if (r instanceof MultiPolygonRelation == false) {
+ continue;
+ }
+
+ Coord point = ((MultiPolygonRelation)r).getCofG();
+ if (point == null) {
+ continue;
+ }
+
+ Node poi = new Node(FakeIdGenerator.makeFakeId(), point);
+ poi.copyTags(r);
+ // remove the type tag which makes only sense for relations
+ poi.deleteTag("type");
+ poi.addTag(AREA2POI_TAG, "true");
+ log.debug("Create POI",poi.toTagString(),"from mp",r.getId(),r.toTagString());
+ saver.addNode(poi);
+ mps2POI++;
+ }
+ log.info(mps2POI, "POIs from multipolygons created");
+ }
+
+}
Index: src/uk/me/parabola/mkgmap/general/MapShape.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapShape.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/general/MapShape.java (working copy)
@@ -28,8 +28,6 @@
*/
public class MapShape extends MapLine {// So top code can link objects from here
- private int poiType;
-
public MapShape() {
}
@@ -46,16 +44,6 @@
"can't set a direction on a polygon");
}
- public void setPoiType(int type)
- {
- this.poiType = type;
- }
-
- public int getPoiType()
- {
- return this.poiType;
- }
-
/**
* Checks if a point is contained within this shape. Points on the
* edge of the shape are considered inside.
Index: src/uk/me/parabola/mkgmap/main/MapMaker.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/MapMaker.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/main/MapMaker.java (working copy)
@@ -39,7 +39,6 @@
import uk.me.parabola.mkgmap.general.LoadableMapDataSource;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.mkgmap.general.MapPoint;
-import uk.me.parabola.mkgmap.general.MapPointFastFindMap;
import uk.me.parabola.mkgmap.general.MapRoad;
import uk.me.parabola.mkgmap.general.MapShape;
import uk.me.parabola.mkgmap.reader.plugin.MapReader;
@@ -58,8 +57,6 @@
LoadableMapDataSource src = loadFromFile(args, filename);
sort = args.getSort();
- log.info("Making Area POIs for", filename);
- makeAreaPOIs(args, src);
log.info("Making Road Name POIs for", filename);
makeRoadNamePOIS(args, src);
return makeMap(args, src);
@@ -150,80 +147,6 @@
return src;
}
- private void makeAreaPOIs(CommandArgs args, LoadableMapDataSource src) {
- String s = args.get("add-pois-to-areas", null);
- if (s != null) {
-
- MapPointFastFindMap poiMap = new MapPointFastFindMap();
-
- for (MapPoint point : src.getPoints())
- {
- if(!point.isRoadNamePOI()) // Don't put road pois in this list
- poiMap.put(null, point);
- }
-
- for (MapShape shape : src.getShapes()) {
- String shapeName = shape.getName();
-
- int pointType = shape.getPoiType();
-
- // only make a point if the shape has a name and we know what type of point to make
- if (pointType == 0)
- continue;
-
-
- // We don't want to add unnamed cities !!
- if(MapPoint.isCityType(pointType) && shapeName == null)
- continue;
-
- // check if there is not already a poi in that shape
-
- if(poiMap.findPointInShape(shape, pointType, shapeName) == null) {
- MapPoint newPoint = new MapPoint();
-
- newPoint.setName(shapeName);
- newPoint.setType(pointType);
-
- copyAddressInformation(shape, newPoint);
-
- newPoint.setLocation(shape.getLocation()); // TODO use centroid
-
- src.getPoints().add(newPoint);
-
- log.info("created POI ", shapeName, "from shape");
- }
- }
- }
-
- }
-
- /**
- * Copy the address information from a shape to a POI. Used when creating
- * POIs from areas.
- *
- * @param shape The shape which contains the address information.
- * @param newPoint The new point that will receive the address information.
- */
- private void copyAddressInformation(MapShape shape, MapPoint newPoint) {
- if (shape.getStreet() != null)
- newPoint.setStreet(shape.getStreet());
- if (shape.getCity() != null)
- newPoint.setCity(shape.getCity());
- if (shape.getZip() != null)
- newPoint.setZip(shape.getZip());
- if (shape.getCountry() != null)
- newPoint.setCountry(shape.getCountry());
- if (shape.getRegion() != null)
- newPoint.setRegion(shape.getRegion());
- if (shape.getPhone() != null)
- newPoint.setPhone(shape.getPhone());
- if (shape.getHouseNumber() != null)
- newPoint.setHouseNumber(shape.getHouseNumber());
- if (shape.getIsIn() != null)
- newPoint.setIsIn(shape.getIsIn());
- }
-
-
void makeRoadNamePOIS(CommandArgs args, LoadableMapDataSource src) {
String rnp = args.get("road-name-pois", null);
// are road name POIS wanted?
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev