With this version of the patch, the intersection of the bounding box and
the landmass does not have to be simply connected as in version 3 of the
patch.
There are still some "flooded island" in ireland, but I'm pretty sure
this is a problem in the multipolygon code this patch relies on (it just
add one sea polygon and constructs a multipolygon with all land
components as inner ways).
Best wishes
Christian
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java (Arbeitskopie)
@@ -1,12 +1,13 @@
package uk.me.parabola.mkgmap.reader.osm;
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import uk.me.parabola.imgfmt.Utils;
import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.mkgmap.general.MapShape;
+import uk.me.parabola.mkgmap.general.MultiShapeMerger;
/**
* Representation of an OSM Multipolygon Relation.
@@ -16,15 +17,19 @@
*/
public class MultiPolygonRelation extends Relation {
private Way outer;
- private final Collection<Way> inners = new ArrayList<Way>();
+ private List<Way> outers = new ArrayList<Way>();
+ private List<Way> inners = new ArrayList<Way>();
+ private Map<Long, Way> myWayMap;
/**
* Create an instance based on an exsiting relation. We need to do
* this because the type of the relation is not known until after all
* its tags are read in.
* @param other The relation to base this one on.
+ * @param wayMap Map of all ways.
*/
- public MultiPolygonRelation(Relation other) {
+ public MultiPolygonRelation(Relation other, Map<Long, Way> wayMap) {
+ myWayMap = wayMap;
setId(other.getId());
for (Map.Entry<Element, String> pairs: other.getRoles().entrySet()){
addElement(pairs.getValue(), pairs.getKey());
@@ -33,10 +38,12 @@
if (value != null && pairs.getKey() instanceof Way) {
Way way = (Way) pairs.getKey();
- if (value.equals("outer"))
- outer = way;
- else if (value.equals("inner"))
+ if (value.equals("outer")){
+ outers.add(way);
+ }
+ else if (value.equals("inner")){
inners.add(way);
+ }
}
}
@@ -45,18 +52,120 @@
}
/** Process the ways in this relation.
+ * Joins way with the role "outer"
* Adds ways with the role "inner" to the way with the role "outer"
*/
+ public void processElementsNew() {
+ if (outers != null)
+ {
+ // copy first outer way
+ Iterator<Way> it = outers.iterator();
+ if (it.hasNext()){
+ // duplicate outer way and remove tags for cascaded multipolygons
+ Way tempWay = it.next();
+ outer = new Way(-tempWay.getId());
+ outer.copyTags(tempWay);
+ for(Coord point: tempWay.getPoints()){
+ outer.addPoint(point);
+ }
+ myWayMap.put(outer.getId(), outer);
+ if (tempWay.getTags() != null){
+ tempWay.getTags().removeAll();
+ }
+ it.remove();
+ }
+
+ // if we have more than one outer way, we join them if they are parts of a long way
+ it = outers.iterator();
+ while (it.hasNext()){
+ Way tempWay = it.next();
+ if (tempWay.getPoints().get(0) == outer.getPoints().get(outer.getPoints().size()-1)){
+ for(Coord point: tempWay.getPoints()){
+ outer.addPoint(point);
+ }
+ if (tempWay.getTags() != null){
+ tempWay.getTags().removeAll();
+ }
+ it.remove();
+ it = outers.iterator();
+ }
+ }
+ }
+
+ if (outer != null)
+ {
+ MapShape outer_s = new MapShape();
+ outer_s.setPoints(outer.getPoints());
+ MultiShapeMerger merger = new MultiShapeMerger(outer_s);
+
+ for (Way w: inners) {
+ if (w != null) {
+ MapShape inner_s = new MapShape();
+ inner_s.setPoints(w.getPoints());
+ merger.addInner(inner_s);
+ }
+ }
+
+ merger.processElements();
+ }
+ }
+
+
public void processElements() {
- if (outer != null)
- {
+
+ if (outers != null)
+ {
+ // copy first outer way
+ Iterator<Way> it = outers.iterator();
+ if (it.hasNext()){
+ // duplicate outer way and remove tags for cascaded multipolygons
+ Way tempWay = it.next();
+ outer = new Way(-tempWay.getId());
+ outer.copyTags(tempWay);
+ for(Coord point: tempWay.getPoints()){
+ outer.addPoint(point);
+ }
+ myWayMap.put(outer.getId(), outer);
+ if (tempWay.getTags() != null){
+ tempWay.getTags().removeAll();
+ }
+ it.remove();
+ }
+
+ // if we have more than one outer way, we join them if they are parts of a long way
+ it = outers.iterator();
+ while (it.hasNext()){
+ Way tempWay = it.next();
+ if (tempWay.getPoints().get(0) == outer.getPoints().get(outer.getPoints().size()-1)){
+ for(Coord point: tempWay.getPoints()){
+ outer.addPoint(point);
+ }
+ if (tempWay.getTags() != null){
+ tempWay.getTags().removeAll();
+ }
+ it.remove();
+ it = outers.iterator();
+ }
+ }
+
for (Way w: inners) {
- if (w != null) {
- List<Coord> pts = w.getPoints();
- int[] insert = findCpa(outer.getPoints(), pts);
- if (insert[0] > 0)
- insertPoints(pts, insert[0], insert[1]);
- pts.clear();
+ if (w != null && outer!= null) {
+ int[] insert = findCpa(outer.getPoints(), w.getPoints());
+ if (insert[0] >= 0)
+ insertPoints(w, insert[0], insert[1]);
+
+ // remove tags from inner way that are available in the outer way
+ if (outer.getTags() != null){
+ for (Map.Entry<String, String> mapTags: outer.getTags().getKeyValues().entrySet()){
+ String key = mapTags.getKey();
+ String value = mapTags.getValue();
+ if (w.getTag(key) != null){
+ if (w.getTag(key).equals(value)){
+ w.deleteTag(key);
+ }
+ }
+ }
+ }
}
}
}
@@ -64,22 +173,43 @@
/**
* Insert Coordinates into the outer way.
- * @param inList List of Coordinates to be inserted
+ * @param way Way to be inserted
* @param out Coordinates will be inserted after this point in the outer way.
* @param in Points will be inserted starting at this index,
* then from element 0 to (including) this element;
*/
- private void insertPoints(List<Coord> inList, int out, int in){
+ private void insertPoints(Way way, int out, int in){
List<Coord> outList = outer.getPoints();
+ List<Coord> inList = way.getPoints();
int index = out+1;
- for (int i = in; i < inList.size(); i++)
+ for (int i = in; i < inList.size(); i++){
outList.add(index++, inList.get(i));
- for (int i = 0; i <= in; i++)
+ }
+ for (int i = 0; i < in; i++){
outList.add(index++, inList.get(i));
-
- //with this line commented we get triangles, when uncommented some areas disappear
- // at least in mapsource, on device itself looks OK.
- outList.add(index,outList.get(out));
+ }
+
+ if (outer.getPoints().size() < 32){
+ outList.add(index++, inList.get(in));
+ outList.add(index, outList.get(out));
+ }
+ else{
+ // we shift the nodes to avoid duplicate nodes (large areas only)
+ int oLat = outList.get(out).getLatitude();
+ int oLon = outList.get(out).getLongitude();
+ int iLat = inList.get(in).getLatitude();
+ int iLon = inList.get(in).getLongitude();
+ if (Math.abs(oLat - iLat) > Math.abs(oLon - iLon)){
+ int delta = (oLon > iLon)? -1 : 1;
+ outList.add(index++, new Coord(iLat + delta, iLon));
+ outList.add(index, new Coord(oLat + delta, oLon));
+ }
+ else{
+ int delta = (oLat > iLat)? 1 : -1;
+ outList.add(index++, new Coord(iLat, iLon + delta));
+ outList.add(index, new Coord(oLat, oLon + delta));
+ }
+ }
}
/**
Index: src/uk/me/parabola/mkgmap/reader/osm/Way.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Way.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/reader/osm/Way.java (Arbeitskopie)
@@ -76,6 +76,10 @@
}
}
+ public boolean isClosed() {
+ return points.size() > 0 && points.get(0).equals(points.get(points.size()-1));
+ }
+
/**
* A simple representation of this way.
* @return A string with the name and start point
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java (Arbeitskopie)
@@ -19,9 +19,13 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.NavigableSet;
import uk.me.parabola.imgfmt.app.Area;
import uk.me.parabola.imgfmt.app.Coord;
@@ -65,6 +69,7 @@
private final Map<String, Long> fakeIdMap = new HashMap<String, Long>();
private final List<Node> exits = new ArrayList<Node>();
private final List<Way> motorways = new ArrayList<Way>();
+ private final List<Way> shoreline = new ArrayList<Way>();
private static final int MODE_NODE = 1;
private static final int MODE_WAY = 2;
@@ -92,6 +97,7 @@
private final boolean ignoreTurnRestrictions;
private final boolean linkPOIsToWays;
private final boolean routing;
+ private final boolean generateSea;
private final Double minimumArcLength;
private final String frigRoundabouts;
@@ -105,6 +111,7 @@
}
linkPOIsToWays = props.getProperty("link-pois-to-ways", false);
ignoreBounds = props.getProperty("ignore-osm-bounds", false);
+ generateSea = props.getProperty("generate-sea", false);
routing = props.containsKey("route");
String rsa = props.getProperty("remove-short-arcs", null);
if(rsa != null)
@@ -370,6 +377,8 @@
if("motorway".equals(highway) ||
"trunk".equals(highway))
motorways.add(currentWay);
+ if(generateSea && "coastline".equals(currentWay.getTag("natural")))
+ shoreline.add(currentWay);
currentWay = null;
// ways are processed at the end of the document,
// may be changed by a Relation class
@@ -399,7 +408,7 @@
String type = currentRelation.getTag("type");
if (type != null) {
if ("multipolygon".equals(type))
- currentRelation = new MultiPolygonRelation(currentRelation);
+ currentRelation = new MultiPolygonRelation(currentRelation, wayMap);
else if("restriction".equals(type)) {
if(ignoreTurnRestrictions)
@@ -446,6 +455,10 @@
}
coordMap = null;
+
+ if (generateSea)
+ generateSeaPolygon(shoreline);
+
for (Relation r : relationMap.values())
converter.convertRelation(r);
@@ -707,7 +720,7 @@
}
currentWay.addPoint(co);
co.incHighwayCount(); // nodes (way joins) will have highwayCount > 1
- if(minimumArcLength != null)
+ if (minimumArcLength != null || generateSea)
nodeIdMap.put(co, id);
}
}
@@ -746,4 +759,294 @@
return fakeIdVal;
}
}
+
+ private void generateSeaPolygon(List<Way> shoreline) {
+
+ Area seaBounds;
+ if (bbox != null)
+ seaBounds = bbox;
+ else
+ seaBounds = mapper.getBounds();
+
+ log.info("generating sea, seaBounds=", seaBounds);
+ int minLat = seaBounds.getMinLat();
+ int maxLat = seaBounds.getMaxLat();
+ int minLong = seaBounds.getMinLong();
+ int maxLong = seaBounds.getMaxLong();
+ Coord nw = new Coord(minLat, minLong);
+ Coord ne = new Coord(minLat, maxLong);
+ Coord sw = new Coord(maxLat, minLong);
+ Coord se = new Coord(maxLat, maxLong);
+
+ long seaId = (1L << 62) + nextFakeId++;
+ Way sea = new Way(seaId);
+ sea.addPoint(nw);
+ sea.addPoint(sw);
+ sea.addPoint(se);
+ sea.addPoint(ne);
+ sea.addPoint(nw);
+ sea.addTag("natural", "sea");
+ log.info("sea: ", sea);
+ wayMap.put(seaId, sea);
+
+ long multiId = (1L << 62) + nextFakeId++;
+ Relation seaRelation = new GeneralRelation(multiId);
+ seaRelation.addTag("type", "multipolygon");
+ seaRelation.addElement("outer", sea);
+
+ List<Way> islands = new ArrayList();
+
+ // handle islands (closes shoreline components) first (they're easy)
+ Iterator<Way> it = shoreline.iterator();
+ while (it.hasNext()) {
+ Way w = it.next();
+ if (w.isClosed()) {
+ islands.add(w);
+ it.remove();
+ }
+ }
+ concatenateWays(shoreline);
+ // there may be more islands now
+ it = shoreline.iterator();
+ while (it.hasNext()) {
+ Way w = it.next();
+ if (w.isClosed()) {
+ log.debug("island after concatenating\n");
+ islands.add(w);
+ it.remove();
+ }
+ }
+
+ // create a "inner" way for each island
+ for (Way w : islands) {
+ log.info("adding island " + w);
+ seaRelation.addElement("inner", w);
+ }
+
+ // the remaining shoreline segments should intersect the boundary
+ // find the intersection points and store them in a SortedMap
+ SortedMap<EdgeHit, Way> hitMap = new TreeMap<EdgeHit, Way>();
+ for (Way w : shoreline) {
+ List<Coord> points = w.getPoints();
+ Coord pStart = points.get(0);
+ Coord pEnd = points.get(points.size()-1);
+
+ EdgeHit hStart = getEdgeHit(seaBounds, pStart);
+ EdgeHit hEnd = getEdgeHit(seaBounds, pEnd);
+ if (hStart == null || hEnd == null) {
+ String msg = String.format("Non-closed coastline segment does not hit bounding box - expect strange results: %d (%s) %d (%s) %s\n",
+ nodeIdMap.get(pStart), pStart.toDegreeString(),
+ nodeIdMap.get(pEnd), pEnd.toDegreeString(),
+ pStart.toOSMURL());
+ log.error(msg);
+ seaRelation.addElement("inner", w);
+ }
+ else {
+ log.debug("hits: ", hStart, hEnd);
+ hitMap.put(hStart, w);
+ hitMap.put(hEnd, null);
+ }
+ }
+
+
+ // now construct inner ways from these segments
+ NavigableSet<EdgeHit> hits = (NavigableSet<EdgeHit>) hitMap.keySet();
+ while (hits.size() > 0) {
+ long id = (1L << 62) + nextFakeId++;
+ Way w = new Way(id);
+ wayMap.put(id, w);
+
+ EdgeHit hit = hits.first();
+ EdgeHit hFirst = hit;
+ EdgeHit hNext;
+ do {
+ Way segment = hitMap.get(hit);
+ log.info("current hit: " + hit);
+ if (segment != null) {
+ // add the segment and get the "ending hit"
+ log.info("adding: ", segment);
+ w.getPoints().addAll(segment.getPoints());
+ hNext = getEdgeHit(seaBounds, segment.getPoints().get(segment.getPoints().size()-1));
+ }
+ else {
+ w.addPoint(hit.getPoint(seaBounds));
+ hNext = hits.higher(hit);
+ if (hNext == null)
+ hNext = hFirst;
+
+ Coord p = hit.getPoint(seaBounds);
+ if (hit.edge < hNext.edge) {
+ log.info("joining: ", hit, hNext);
+ for (int i=hit.edge; i<hNext.edge; i++) {
+ EdgeHit corner = new EdgeHit(i, 1.0);
+ p = corner.getPoint(seaBounds);
+ log.debug("way: ", corner, p);
+ w.addPoint(p);
+ }
+ }
+ else if (hit.edge > hNext.edge) {
+ log.info("joining: ", hit, hNext);
+ for (int i=hit.edge; i<4; i++) {
+ EdgeHit corner = new EdgeHit(i, 1.0);
+ p = corner.getPoint(seaBounds);
+ log.debug("way: ", corner, p);
+ w.addPoint(p);
+ }
+ for (int i=0; i<hNext.edge; i++) {
+ EdgeHit corner = new EdgeHit(i, 1.0);
+ p = corner.getPoint(seaBounds);
+ log.debug("way: ", corner, p);
+ w.addPoint(p);
+ }
+ }
+ w.addPoint(hNext.getPoint(seaBounds));
+ }
+ hits.remove(hit);
+ hit = hNext;
+ } while (hits.size() > 0 && !hit.equals(hFirst));
+
+ if (!w.isClosed())
+ w.getPoints().add(w.getPoints().get(0));
+ w.addTag("highway", "primary");
+ log.info("adding non-island landmass, hits.size()=" + hits.size());
+ seaRelation.addElement("inner", w);
+ }
+
+ seaRelation = new MultiPolygonRelation(seaRelation, wayMap);
+ relationMap.put(multiId, seaRelation);
+ seaRelation.processElements();
+ }
+
+ /**
+ * Specifies where an edge of the bounding box is hit.
+ */
+ private static class EdgeHit implements Comparable<EdgeHit>
+ {
+ int edge;
+ double t;
+
+ EdgeHit(int edge, double t) {
+ this.edge = edge;
+ this.t = t;
+ }
+
+ public int compareTo(EdgeHit o) {
+ if (edge < o.edge)
+ return -1;
+ else if (edge > o.edge)
+ return +1;
+ else if (t > o.t)
+ return +1;
+ else if (t < o.t)
+ return -1;
+ else
+ return 0;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o instanceof EdgeHit) {
+ EdgeHit h = (EdgeHit) o;
+ return (h.edge == edge && Double.compare(h.t, t) == 0);
+ }
+ else
+ return false;
+ }
+
+ Coord getPoint(Area a) {
+ log.info("getPoint: ", this, a);
+ switch (edge) {
+ case 0:
+ return new Coord(a.getMinLat(), (int) (a.getMinLong() + t * (a.getMaxLong()-a.getMinLong())));
+
+ case 1:
+ return new Coord((int)(a.getMinLat() + t * (a.getMaxLat()-a.getMinLat())), a.getMaxLong());
+
+ case 2:
+ return new Coord(a.getMaxLat(), (int)(a.getMaxLong() - t * (a.getMaxLong()-a.getMinLong())));
+
+ case 3:
+ return new Coord((int)(a.getMaxLat() - t * (a.getMaxLat()-a.getMinLat())), a.getMinLong());
+
+ default:
+ throw new RuntimeException("illegal state");
+ }
+ }
+
+ public String toString() {
+ return "EdgeHit " + edge + "@" + t;
+ }
+ }
+
+ private EdgeHit getEdgeHit(Area a, Coord p)
+ {
+ return getEdgeHit(a, p, 10);
+ }
+
+ private EdgeHit getEdgeHit(Area a, Coord p, int tolerance)
+ {
+ int lat = p.getLatitude();
+ int lon = p.getLongitude();
+ int minLat = a.getMinLat();
+ int maxLat = a.getMaxLat();
+ int minLong = a.getMinLong();
+ int maxLong = a.getMaxLong();
+
+ log.info(String.format("getEdgeHit: (%d %d) (%d %d %d %d)", lat, lon, minLat, minLong, maxLat, maxLong));
+ if (lat <= minLat+tolerance) {
+ return new EdgeHit(0, ((double)(lon - minLong))/(maxLong-minLong));
+ }
+ else if (lon >= maxLong-tolerance) {
+ return new EdgeHit(1, ((double)(lat - minLat))/(maxLat-minLat));
+ }
+ else if (lat >= maxLat-tolerance) {
+ return new EdgeHit(2, ((double)(maxLong - lon))/(maxLong-minLong));
+ }
+ else if (lon <= minLong+tolerance) {
+ return new EdgeHit(3, ((double)(maxLat - lat))/(maxLat-minLat));
+ }
+ else
+ return null;
+ }
+
+ private void concatenateWays(List<Way> ways) {
+ Map<Coord, Way> beginMap = new HashMap();
+
+ for (Way w : ways) {
+ if (!w.isClosed()) {
+ List<Coord> points = w.getPoints();
+ beginMap.put(points.get(0), w);
+ }
+ }
+
+ int merged = 1;
+ while (merged > 0) {
+ merged = 0;
+ for (Way w1 : ways) {
+ if (w1.isClosed()) continue;
+
+ List<Coord> points1 = w1.getPoints();
+ Way w2 = beginMap.get(points1.get(points1.size()-1));
+ if (w2 != null) {
+ log.info("merging: ", ways.size(), w1.getId(), w2.getId());
+ List<Coord> points2 = w2.getPoints();
+ Way wm;
+ if (w1.getId() < (1L << 62)) {
+ wm = new Way((1L << 62) + nextFakeId++);
+ ways.remove(w1);
+ ways.add(wm);
+ wm.getPoints().addAll(points1);
+ beginMap.put(points1.get(0), wm);
+ }
+ else {
+ wm = w1;
+ }
+ wm.getPoints().addAll(points2);
+ ways.remove(w2);
+ beginMap.remove(points2.get(0));
+ merged++;
+ break;
+ }
+ }
+ }
+ }
}
Index: src/uk/me/parabola/mkgmap/reader/osm/Element.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Element.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/reader/osm/Element.java (Arbeitskopie)
@@ -86,6 +86,7 @@
* element.
*/
public void copyTags(Element other) {
+ if (other.tags != null)
tags = other.tags.copy();
}
@@ -97,4 +98,8 @@
if (this.name == null)
this.name = name;
}
+
+ public Tags getTags() {
+ return tags;
+ }
}
Index: src/uk/me/parabola/mkgmap/reader/osm/Tags.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Tags.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/reader/osm/Tags.java (Arbeitskopie)
@@ -16,7 +16,9 @@
*/
package uk.me.parabola.mkgmap.reader.osm;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
/**
* Store the tags that belong to an Element.
@@ -120,7 +122,7 @@
}
return null;
}
-
+
/**
* Make a deep copy of this object.
* @return A copy of this object.
@@ -271,4 +273,22 @@
put(e.key, e.value);
}
}
-}
+
+ public void removeAll() {
+ for (int i = 0; i < capacity; i++){
+ keys[i] = null;
+ values[i] = null;
+ }
+ size = 0;
+ }
+
+ public Map<String, String> getKeyValues() {
+ Map<String, String> tagMap = new HashMap<String, String>();
+ for (int i = 0; i < capacity; i++)
+ if (keys[i] != null && values[i] != null)
+ tagMap.put(keys[i], values[i]);
+ return tagMap;
+ }
+
+
+}
\ No newline at end of file
Index: src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java (Arbeitskopie)
@@ -30,14 +30,19 @@
*/
public class PolygonSplitterBase extends BaseFilter {
protected static final int MAX_SIZE = 0x7fff/2;
-
+ protected boolean dontSplit = false;
+
/**
* Split the given shape and place the resulting shapes in the outputs list.
* @param shape The original shape (that is too big).
* @param outputs The output list.
*/
protected void split(MapShape shape, List<MapShape> outputs) {
-
+ if (dontSplit) {
+ outputs.add(shape);
+ return;
+ }
+ else {
// Convert to a awt polygon
Polygon polygon = new Polygon();
for (Coord co : shape.getPoints()) {
@@ -73,6 +78,7 @@
areaToShapes(shape, a1, outputs);
areaToShapes(shape, a2, outputs);
+ }
}
/**
@@ -93,7 +99,7 @@
while (!pit.isDone()) {
int type = pit.currentSegment(res);
- //System.out.println("T" + type + " " + res[0] + "," + res[1] + " " + res[2] + "," + res[3] + " " + res[4] + "," + res[5]);
+ //System.out.println("T" + type + " " + res[0] + "," + res[1] + " " + res[2] + "," + res[3] + " " + res[4] + "," + res[5] + ": " + pit.getWindingRule());
Coord co = new Coord(Math.round(res[1]), Math.round(res[0]));
if (type == PathIterator.SEG_MOVETO) {
Index: src/uk/me/parabola/mkgmap/general/MapShape.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapShape.java (Revision 1135)
+++ src/uk/me/parabola/mkgmap/general/MapShape.java (Arbeitskopie)
@@ -67,6 +67,19 @@
return contains(this.getPoints(), co, true);
}
+ /**
+ * Checks if a point is contained within this shape. An additional
+ * option allows to control, whether points on the edge of the shape
+ * are considered inside.
+ *
+ * @param co point to check
+ * @param onLineIsInside controls, whether points on the edge are considered inside
+ * @return true if point is in shape, false otherwise
+ */
+ public boolean contains(Coord co, boolean onLineIsInside) {
+ return contains(this.getPoints(), co, onLineIsInside);
+ }
+
/*
* Checks if a point is contained within a shape.
*
Index: resources/styles/default/polygons
===================================================================
--- resources/styles/default/polygons (Revision 1135)
+++ resources/styles/default/polygons (Arbeitskopie)
@@ -54,6 +54,7 @@
natural=mud [0x51 resolution 20]
natural=scrub [0x4f resolution 20]
natural=water [0x3c resolution 20]
+natural=sea [0x32 resolution 10]
natural=wood [0x50 resolution 18]
place=village [0x03 resolution 18]