Because I know lots of you want to configure the placement behaviour of
the add-pois-to-areas option I have implemented a small patch for it.
The patch adds a new option "pois-to-areas-placement". This option
defines on which node the POI generated from a polygon is placed
preferrably.
Example:
pois-to-areas-placement=entrance=main;entrance=yes;building=entrance
means:
The POI node is placed to the first node with entrance=main or if it
does not exists at the first node with entrance=yes or if that does not
exist at the first node with building=entrance. If no rule matches the
POI is generated at the center of the polygon.
It's also possible to use wildcards like:
pois-to-areas-placement=entrance=*;building=entrance
Maybe someone can read my awful help text in the options file and can
improve that? It would be good to have a better text to commit :-)
Have fun!
WanMil
Index: src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (revision 2049)
+++ src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (working copy)
@@ -13,7 +13,13 @@
package uk.me.parabola.mkgmap.reader.osm;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import uk.me.parabola.imgfmt.app.Coord;
@@ -40,6 +46,8 @@
public class Areas2POIHook extends OsmReadingHooksAdaptor {
private static final Logger log = Logger.getLogger(Areas2POIHook.class);
+ private List<Entry<String,String>> poiPlacementTags;
+
private ElementSaver saver;
/** Name of the bool tag that is set to true if a POI is created from an area */
@@ -51,11 +59,65 @@
return false;
}
+ this.poiPlacementTags = getPoiPlacementTags(props);
+
this.saver = saver;
return true;
}
+ /**
+ * Reads the tag definitions of the option poi2area-placement-tags from the given properties.
+ * @param props mkgmap options
+ * @return the parsed tag definition list
+ */
+ private List<Entry<String,String>> getPoiPlacementTags(EnhancedProperties props) {
+ List<Entry<String,String>> tagList = new ArrayList<Entry<String,String>>();
+
+ String placementDefs = props.getProperty("pois-to-areas-placement", "entrance=main;entrance=yes;building=entrance");
+ String[] placementDefsParts = placementDefs.split(";");
+ for (String placementDef : placementDefsParts) {
+ int ind = placementDef.indexOf('=');
+ String tagName = null;
+ String tagValue = null;
+ if (ind < 0) {
+ // only the tag is defined => interpret it as tag=*
+ tagName = placementDef;
+ tagValue = null;
+ } else if (ind > 0) {
+ tagName = placementDef.substring(0,ind);
+ tagValue = placementDef.substring(ind+1);
+ } else {
+ log.error("Option pois-to-areas-placement contains a tag that starts with '='. This is not allowed. Ignoring it.");
+ continue;
+ }
+ tagName = tagName.trim();
+ if (tagName.length() == 0) {
+ log.error("Option pois-to-areas-placement contains a whitespace tag '='. This is not allowed. Ignoring it.");
+ continue;
+ }
+ if (tagValue != null) {
+ tagValue = tagValue.trim();
+ if (tagValue.length() == 0 || "*".equals(tagValue)) {
+ tagValue = null;
+ }
+ }
+ Entry<String,String> tag = new AbstractMap.SimpleImmutableEntry(tagName, tagValue);
+ tagList.add(tag);
+ }
+ return tagList;
+ }
+
+
+ public Set<String> getUsedTags() {
+ // return all tags defined in the poiPlacementTags
+ Set<String> tags = new HashSet<String>();
+ for (Entry<String,String> poiTag : poiPlacementTags) {
+ tags.add(poiTag.getValue());
+ }
+ return tags;
+ }
+
public void end() {
log.info("Areas2POIHook started");
addPOIsToWays();
@@ -63,14 +125,33 @@
log.info("Areas2POIHook finished");
}
+ private int getPlacementOrder(Element elem) {
+ for (int order = 0; order < poiPlacementTags.size(); order++) {
+ Entry<String,String> poiTagDef = poiPlacementTags.get(order);
+ String tagValue = elem.getTag(poiTagDef.getKey());
+ if (tagValue != null) {
+ if (poiTagDef.getValue() == null || poiTagDef.getValue().equals(tagValue)) {
+ return order;
+ }
+ }
+ }
+ // no poi tag match
+ return -1;
+ }
+
private void addPOIsToWays() {
- Set<Coord> labelCoords = new HashSet<Coord>();
+ Map<Coord, Integer> labelCoords = new HashMap<Coord, Integer>();
- // save all coords with building=entrance to a map
+ // save all coords with one of the placement tags 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());
+ if (poiPlacementTags.isEmpty() == false) {
+ for (Node n : saver.getNodes().values()) {
+ int order = getPlacementOrder(n);
+ if (order >= 0) {
+ Integer prevOrder = labelCoords.get(n.getLocation());
+ if (prevOrder == null || order < prevOrder.intValue())
+ labelCoords.put(n.getLocation(), order);
+ }
}
}
@@ -98,14 +179,20 @@
Coord poiCoord = null;
// do we have some labeling coords?
if (labelCoords.size() > 0) {
+ int poiOrder = Integer.MAX_VALUE;
// 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)) {
+ Integer cOrder = labelCoords.get(c);
+ if (cOrder != null && cOrder.intValue() < poiOrder) {
// this coord is a labeling coord
// use it for the current way
poiCoord = c;
- break;
+ poiOrder = cOrder;
+ if (poiOrder == 0) {
+ // there is no higher order
+ break;
+ }
}
}
}
@@ -153,4 +240,5 @@
log.info(mps2POI, "POIs from multipolygons created");
}
+
}
Index: resources/help/en/options
===================================================================
--- resources/help/en/options (revision 2049)
+++ resources/help/en/options (working copy)
@@ -383,12 +383,18 @@
file. Artifical polygons created by multipolyon processing are not used.
The POIs are created at the following positions (first rule that applies):
polygons:
- * the first node tagged with building=entrance
+ * the first node tagged with a tag defined by the pois-to-areas-placement
+ option
* the center point
multipolygons:
* the node with role=label
* the center point of the biggest area
+--pois-to-areas-placement[=taglist]
+ A list of tag=value definitions that defines tags where a POI is placed
+ preferrably. It is possible to define wildcards for tag values like entrance=*.
+ Default: entrance=main;entrance=yes;building=entrance
+
--generate-sea[=ValueList]
Generate sea polygons. ValueList is an optional comma
separated list of values:
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev