I have modified the patch by the following things:
1. The relation style is now applied before the POIs are added
2. You must now set the add-pois-to-lines option to enable the POI
generation
3. Some basic help text
Running the relation style earlier is a bit contrary to the mkgmap
design but it seems to work (I don't know if processing of mp files is
affected by this?). Anyhow the relation style is a bit different from
the other style files as no garmin objects are created. So I think I can
live with it.
@Steve: What do you think? I think you have created big parts of the
style system and so you should be happy with that change.
I have also uploaded a compiled version of the patch:
http://files.mkgmap.org.uk/detail/40
Have fun!
WanMil
Hi,
I am very undecided if this option is reasonable or not.
But it's easy to implement so I decided to let you test and decide
yourself if it makes sense or not.
Attached patch does the trick. I haven't added an option yet so it works
if add-pois-to-areas is set. For each line all points plus the middle
point are added as POIs (tagged different with mkgmap:line2poitype).
For lines each POI is tagged additionally with the following tags:
mkgmap:line2poi=true
mkgmap:line2poitype=start|end|inner|mid
Have fun!
WanMil
Hi,
would an 'add-pois-to-lines' option (similar to the new
'add-pois-to-areas') make sense ?
I tried to create an maxspeed layer to show the maxspeeds using
the highway-shields, but this didn't work well (because garmin
shows the shields only for some roads).
With the suggested add-pois-to-lines it would be possible to
show little maxspeed icons (30) (50) etc. on the roads
or to show incline-icons on roads which have an incline=* tag.
Chris
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (revision 2064)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (working copy)
@@ -477,7 +477,7 @@
// Relations never resolve to a GType and so we ignore the return
// value.
- relationRules.resolveType(relation, TypeResult.NULL_RESULT);
+// relationRules.resolveType(relation, TypeResult.NULL_RESULT);
if(relation instanceof RestrictionRelation) {
RestrictionRelation rr = (RestrictionRelation)relation;
Index: src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java (revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java (revision 0)
@@ -0,0 +1,54 @@
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.io.FileNotFoundException;
+
+import uk.me.parabola.imgfmt.ExitException;
+import uk.me.parabola.mkgmap.osmstyle.StyleImpl;
+import uk.me.parabola.mkgmap.scan.SyntaxException;
+import uk.me.parabola.util.EnhancedProperties;
+
+public class RelationStyleHook extends OsmReadingHooksAdaptor {
+
+ private Style style;
+ private ElementSaver saver;
+
+ public RelationStyleHook() {
+ }
+
+ public boolean init(ElementSaver saver, EnhancedProperties props) {
+ this.saver = saver;
+
+ String loc = props.getProperty("style-file");
+ if (loc == null)
+ loc = props.getProperty("map-features");
+ String name = props.getProperty("style");
+
+ if (loc == null && name == null)
+ name = "default";
+
+ try {
+ this.style = new StyleImpl(loc, name);
+ this.style.applyOptionOverride(props);
+
+ } catch (SyntaxException e) {
+ System.err.println("Error in style: " + e.getMessage());
+ throw new ExitException("Could not open style " + name);
+ } catch (FileNotFoundException e) {
+ String name1 = (name != null)? name: loc;
+ throw new ExitException("Could not open style " + name1);
+ }
+
+ return super.init(saver, props);
+ }
+
+ public void end() {
+ Rule relationRules = style.getRelationRules();
+ for (Relation rel : saver.getRelations().values()) {
+ relationRules.resolveType(rel, TypeResult.NULL_RESULT);
+ }
+ super.end();
+ }
+
+
+
+}
Index: src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (revision 2064)
+++ src/uk/me/parabola/mkgmap/reader/osm/Areas2POIHook.java (working copy)
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2011.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 or
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-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;
-import uk.me.parabola.log.Logger;
-import uk.me.parabola.util.EnhancedProperties;
-
-/**
- * Adds a POI for each area and multipolygon with the same tags. Artificial areas created by
- * multipolygon relation processing are not used for POI creation. The location of the POI
- * is determined in different ways.<br/>
- * Element is of type {@link Way}:
- * <ul>
- * <li>the first node tagged with building=entrance</li>
- * <li>the center point of the area</li>
- * </ul>
- * Element is of type {@link MultiPolygonRelation}:
- * <ul>
- * <li>the node with role=label</li>
- * <li>the center point of the biggest area</li>
- * </ul>
- * Each node created by this hook is tagged with mkgmap:area2poi=true.
- * @author WanMil
- */
-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 */
- public static final String AREA2POI_TAG = "mkgmap:area2poi";
-
- 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.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");
- placementDefs = placementDefs.trim();
-
- if (placementDefs.length() == 0) {
- // the POIs should be placed in the center only
- // => return an empty list
- return tagList;
- }
-
- 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<String,String>(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();
- addPOIsToMPs();
- 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() {
- Map<Coord, Integer> labelCoords = new HashMap<Coord, Integer>();
-
- // save all coords with one of the placement tags to a map
- // so that ways use this coord as its labeling point
- 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);
- }
- }
- }
-
- 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) {
- 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()) {
- 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;
- poiOrder = cOrder;
- if (poiOrder == 0) {
- // there is no higher order
- 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/reader/osm/POIGeneratorHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/POIGeneratorHook.java (revision 2063)
+++ src/uk/me/parabola/mkgmap/reader/osm/POIGeneratorHook.java (working copy)
@@ -15,6 +15,7 @@
import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -27,7 +28,9 @@
import uk.me.parabola.util.EnhancedProperties;
/**
- * Adds a POI for each area and multipolygon with the same tags. Artificial areas created by
+ * Adds a POI for each area and multipolygon with the same tags in case the add-pois-to-areas option
+ * is set. Adds multipole POIs to each line if the add-pois-to-lines option is set.<br/>
+ * Artificial areas created by
* multipolygon relation processing are not used for POI creation. The location of the POI
* is determined in different ways.<br/>
* Element is of type {@link Way}:
@@ -43,19 +46,27 @@
* Each node created by this hook is tagged with mkgmap:area2poi=true.
* @author WanMil
*/
-public class Areas2POIHook extends OsmReadingHooksAdaptor {
- private static final Logger log = Logger.getLogger(Areas2POIHook.class);
+public class POIGeneratorHook extends OsmReadingHooksAdaptor {
+ private static final Logger log = Logger.getLogger(POIGeneratorHook.class);
private List<Entry<String,String>> poiPlacementTags;
private ElementSaver saver;
+ private boolean poisToAreas = false;
+ private boolean poisToLines = false;
+
/** 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 static final String LINE2POI_TAG = "mkgmap:line2poi";
+ public static final String LINE2POI_TYPE_TAG = "mkgmap:line2poitype";
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.");
+ poisToAreas = props.containsKey("add-pois-to-areas");
+ poisToLines = props.containsKey("add-pois-to-lines");
+
+ if ((poisToAreas || poisToLines) == false) {
+ log.info("Disable Areas2POIHook because add-pois-to-areas and add-pois-to-lines option is not set.");
return false;
}
@@ -72,6 +83,10 @@
* @return the parsed tag definition list
*/
private List<Entry<String,String>> getPoiPlacementTags(EnhancedProperties props) {
+ if (poisToAreas==false) {
+ return Collections.emptyList();
+ }
+
List<Entry<String,String>> tagList = new ArrayList<Entry<String,String>>();
String placementDefs = props.getProperty("pois-to-areas-placement", "entrance=main;entrance=yes;building=entrance");
@@ -152,7 +167,7 @@
// save all coords with one of the placement tags to a map
// so that ways use this coord as its labeling point
- if (poiPlacementTags.isEmpty() == false) {
+ if (poiPlacementTags.isEmpty() == false && poisToAreas) {
for (Node n : saver.getNodes().values()) {
int order = getPlacementOrder(n);
if (order >= 0) {
@@ -166,60 +181,142 @@
log.debug("Found", labelCoords.size(), "label coords");
int ways2POI = 0;
+ int lines2POI = 0;
for (Way w : saver.getWays().values()) {
- // check if it is an area
- if (w.isClosed() == false) {
- continue;
- }
-
+ // check if way has any tags
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) {
- 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()) {
- 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;
- poiOrder = cOrder;
- if (poiOrder == 0) {
- // there is no higher order
- break;
- }
+
+ // check if it is an area
+ if (w.isClosed()) {
+ if (poisToAreas) {
+ addPOItoPolygon(w, labelCoords);
+ ways2POI++;
+ }
+ } else {
+ if (poisToLines) {
+ lines2POI += addPOItoLine(w);
+ }
+ }
+ }
+
+ if (poisToAreas)
+ log.info(ways2POI, "POIs from single areas created");
+ if (poisToLines)
+ log.info(lines2POI, "POIs from lines created");
+ }
+
+ private void addPOItoPolygon(Way polygon, Map<Coord, Integer> labelCoords) {
+ if (poisToAreas == false) {
+ return;
+ }
+
+ // get the coord where the poi is placed
+ 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 : polygon.getPoints()) {
+ 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;
+ poiOrder = cOrder;
+ if (poiOrder == 0) {
+ // there is no higher order
+ break;
}
}
}
- if (poiCoord == null) {
- // did not find any label coord
- // use the common center point of the area
- poiCoord = w.getCofG();
+ }
+ if (poiCoord == null) {
+ // did not find any label coord
+ // use the common center point of the area
+ poiCoord = polygon.getCofG();
+ }
+
+ Node poi = createPOI(polygon, poiCoord, AREA2POI_TAG);
+ saver.addNode(poi);
+ }
+
+ private int addPOItoLine(Way line) {
+ Node startNode = createPOI(line, line.getPoints().get(0), LINE2POI_TAG);
+ startNode.addTag(LINE2POI_TYPE_TAG,"start");
+ saver.addNode(startNode);
+
+ Node endNode = createPOI(line, line.getPoints().get(line.getPoints().size()-1), LINE2POI_TAG);
+ endNode.addTag(LINE2POI_TYPE_TAG,"end");
+ saver.addNode(endNode);
+
+ int noPOIs = 2;
+
+ if (line.getPoints().size() > 2) {
+ for (Coord inPoint : line.getPoints().subList(1, line.getPoints().size()-1)) {
+ Node innerNode = createPOI(line, inPoint, LINE2POI_TAG);
+ innerNode.addTag(LINE2POI_TYPE_TAG,"inner");
+ saver.addNode(innerNode);
+ noPOIs++;
}
-
- 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");
+
+ // calculate the middle of the line
+ Coord prevC = null;
+ double sumDist = 0.0;
+ ArrayList<Double> dists = new ArrayList<Double>(line.getPoints().size()-1);
+ for (Coord c : line.getPoints()) {
+ if (prevC != null) {
+ double dist = prevC.distance(c);
+ dists.add(dist);
+ sumDist+=dist;
+ }
+ prevC = c;
+ }
+
+ Coord midPoint = null;
+ double remMidDist = sumDist/2;
+ for (int midPos =0; midPos < dists.size(); midPos++) {
+ double nextDist = dists.get(midPos);
+ if (remMidDist <= nextDist) {
+ double frac = remMidDist/nextDist;
+ midPoint = line.getPoints().get(midPos).makeBetweenPoint(line.getPoints().get(midPos+1), frac);
+ break;
+ }
+ remMidDist -= nextDist;
+ }
+ Node midNode = createPOI(line, midPoint, LINE2POI_TAG);
+ midNode.addTag(LINE2POI_TYPE_TAG,"mid");
+ saver.addNode(midNode);
+ noPOIs++;
+
+ return noPOIs;
+
+ }
+
+ private Node createPOI(Element source, Coord poiCoord, String poiTypeTag) {
+ Node poi = new Node(FakeIdGenerator.makeFakeId(), poiCoord);
+ poi.copyTags(source);
+ poi.deleteTag(MultiPolygonRelation.STYLE_FILTER_TAG);
+ poi.addTag(poiTypeTag, "true");
+ log.debug("Create POI",poi.toTagString(),"from",source.getId(),source.toTagString());
+ if (source.getTag("mkgmap:aname") != null) {
+ log.error(source.getId()
+ +" "+source.toTagString());
+ }
+ return poi;
+
}
private void addPOIsToMPs() {
@@ -236,16 +333,13 @@
continue;
}
- Node poi = new Node(FakeIdGenerator.makeFakeId(), point);
- poi.copyTags(r);
+ Node poi = createPOI(r, point, AREA2POI_TAG);
// 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");
+ log.info(mps2POI,"POIs from multipolygons created");
}
Property changes on: src\uk\me\parabola\mkgmap\reader\osm\POIGeneratorHook.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (revision 2064)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (working copy)
@@ -56,7 +56,8 @@
new RoutingHook(),
new HighwayHooks(),
new LocationHook(),
- new Areas2POIHook(),
+ new RelationStyleHook(),
+ new POIGeneratorHook(),
};
protected OsmConverter converter;
private final Set<String> usedTags = new HashSet<String>();
Index: resources/help/en/options
===================================================================
--- resources/help/en/options (revision 2064)
+++ resources/help/en/options (working copy)
@@ -375,9 +375,21 @@
0x2f15: a blue dot in the middle of the road, and if you select,
or 'hover' over it, the streetname appears.
+--add-pois-to-lines
+ Generate POIs for lines. For each line (must not be closed) POIs are
+ created at several points of the line. Each POI is tagged with the
+ same tags like the line and additional tags added by mkgmap:
+ mkgmap:line2poi=true and tag mkgmap:line2poitype having
+ the following values:
+ * start - The first point of the line
+ * end - The last point of the line
+ * inner - Each point of the line except the first and the last
+ * mid - The middle point
+
--add-pois-to-areas
Generate a POI for each polygon and multipolygon. The POIs are created
- before the style is applied. Each POI is tagged with the same tags of
+ after the relation style but before the other styles are applied. Each
+ POI is tagged with the same tags of
the area/multipolygon. Additionally the tag mkgmap:area2poi=true is
set so that it is possible to use that information in the points style
file. Artifical polygons created by multipolyon processing are not used.
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev