[Git][debian-gis-team/mkgmap][upstream] New upstream version 0.0.0+svn4454

Bas Couwenberg gitlab at salsa.debian.org
Sun Mar 1 05:56:07 GMT 2020



Bas Couwenberg pushed to branch upstream at Debian GIS Project / mkgmap


Commits:
c030eea9 by Bas Couwenberg at 2020-03-01T06:42:36+01:00
New upstream version 0.0.0+svn4454
- - - - -


15 changed files:

- build.xml
- doc/index.txt
- doc/logging.txt
- doc/options.txt
- resources/help/en/options
- resources/mkgmap-version.properties
- src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
- src/uk/me/parabola/mkgmap/combiners/FileInfo.java
- src/uk/me/parabola/mkgmap/main/MapMaker.java
- src/uk/me/parabola/mkgmap/osmstyle/ConvertedWay.java
- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
- src/uk/me/parabola/mkgmap/osmstyle/WrongAngleFixer.java
- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
- src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
- + tools/buildoptions/OptionsBuilder.java


Changes:

=====================================
build.xml
=====================================
@@ -38,6 +38,7 @@
 
 	<property name="src" value="src"/>
 	<property name="test" value="test"/>
+	<property name="tools" value="tools"/>
 
 	<property name="doc" value="doc"/>
 	<property name="javadoc" value="${doc}/api"/>
@@ -370,6 +371,7 @@
 				<attribute name="Implementation-Version" value="${project.version}" />
 			</manifest>
 			<include name="**/*.class"/>
+			<exclude name="**/buildoptions/**"/>
 			<include name="*.csv"/>
 			<include name="known-hgt.bin"/>
 			<include name="*.xml"/>
@@ -422,6 +424,24 @@
 		</javadoc>
 	</target>
 
+	<!-- Compile the tools -->
+	<target name="compile-tools" depends="prepare" description="tool compilation">
+
+		<javac srcdir="${tools}" destdir="${build.classes}" encoding="utf-8" debug="true" includeantruntime="false">
+			<include name="**/*.java" />
+			<classpath refid="main"/>
+		</javac>
+	</target>
+
+	<!-- Generate help file options from doc file options.txt -->
+	<target name="gen-options-file" depends="compile-tools">
+		<exec executable="java" dir="${build.classes}" failonerror="true" failifexecutionfails="true" input="doc/options.txt">
+			<arg value="buildoptions.OptionsBuilder" />
+			<arg value="../../resources/help/en/options" />
+		</exec>
+	</target>
+	
+
 	<target name="macker" depends="build, resolve-macker">
 		<taskdef name="macker"
 						 classname="net.innig.macker.ant.MackerAntTask"


=====================================
doc/index.txt
=====================================
@@ -44,7 +44,7 @@ the OSM taged features are converted into the Garmin features.
 This documents the language that is accepted by the TYP compiler that
 is included within mkgmap.
 
-[/doc/options '''Logging''']
+[/doc/logging '''Logging''']
 Instructions on how to control messages that are logged and to where
 they are written.
 


=====================================
doc/logging.txt
=====================================
@@ -43,5 +43,5 @@ The above example enables certain informational messages and sends them to a
 log file, with warning and error messages being also sent to stdout.
 
 Further information can be found at
-https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html
+[https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html]
 


=====================================
doc/options.txt
=====================================
@@ -1,3 +1,5 @@
+=== Command line ===
+
 The command line is of the format:
 
 :	java.exe [java-options] -jar mkgmap.jar [mkgmap-options]
@@ -29,6 +31,7 @@ mkgmap code.
 disable specific logging messages. This is useful if you want to see
 certain types of message that are not logged by default or choose where
 the messages should be written.
+
 === Mkgmap options ===
 
 The order of the options is significant in that options only apply
@@ -49,7 +52,7 @@ general help information is displayed, the same as in help=help.
 
 === File options ===
 
-filename
+;filename
 ;--input-file=filename
 : 	Read input data from the given file.  This option (or just a
 filename) may be specified more than once. Make sure you set all 


=====================================
resources/help/en/options
=====================================
@@ -1,3 +1,5 @@
+=== Command line ===
+
 The command line is of the format:
 
     java.exe [java-options] -jar mkgmap.jar [mkgmap-options]
@@ -26,7 +28,9 @@ options you may need to use are:
     Specifies a logging configuration file that allows you to enable and
     disable specific logging messages. This is useful if you want to see
     certain types of message that are not logged by default or choose where the
-    messages should be written. === Mkgmap options ===
+    messages should be written.
+
+=== Mkgmap options ===
 
 The order of the options is significant in that options only apply to
 subsequent input files. If you are using splitter, you probably will need to


=====================================
resources/mkgmap-version.properties
=====================================
@@ -1,2 +1,2 @@
-svn.version: 4434
-build.timestamp: 2020-01-31T07:23:47+0000
+svn.version: 4454
+build.timestamp: 2020-02-20T09:16:25+0000


=====================================
src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
=====================================
@@ -51,7 +51,8 @@ public class LinePreparer {
 	private final boolean ignoreNumberOnlyNodes;
 
 	LinePreparer(Polyline line) {
-		extraBit = line.isRoad() && line.getSubdiv().getZoom().getLevel() == 0 && line.hasInternalNodes();
+		extraBit = line.isRoad() && line.getSubdiv().getZoom().getLevel() == 0
+				&& (line.hasInternalNodes() || !line.isLastSegment());
 		ignoreNumberOnlyNodes = !line.hasHouseNumbers();
 		extTypeLine = line.hasExtendedType();
 


=====================================
src/uk/me/parabola/mkgmap/combiners/FileInfo.java
=====================================
@@ -144,9 +144,12 @@ public class FileInfo {
 	 * @throws FileNotFoundException If the file doesn't actually exist.
 	 */
 	public static FileInfo getFileInfo(String inputName) throws FileNotFoundException {
-
 		int end = inputName.length();
-		String ext = inputName.substring(end - 3).toUpperCase(Locale.ENGLISH);
+		File f = new File(inputName);
+		if (f.isDirectory() || end < 3)
+			return new FileInfo(inputName, UNKNOWN_KIND);
+		
+		String ext = end < 3 ? "" : inputName.substring(end - 3).toUpperCase(Locale.ENGLISH);
 		FileInfo info;
 
 		if (Objects.equals(ext, "IMG")) {


=====================================
src/uk/me/parabola/mkgmap/main/MapMaker.java
=====================================
@@ -50,6 +50,10 @@ public class MapMaker implements MapProcessor {
 	}
 
 	public String makeMap(CommandArgs args, String filename) {
+		if (new File(filename).isDirectory()) {
+			System.err.println("Need a single file, not a directory: " + filename);
+			return filename;
+		}
 		try {
 			LoadableMapDataSource src = loadFromFile(args, filename);
 			sort = args.getSort();


=====================================
src/uk/me/parabola/mkgmap/osmstyle/ConvertedWay.java
=====================================
@@ -36,12 +36,12 @@ public class ConvertedWay {
 	private final int index;
 	private final Way way;				// with tags after Style processing
 	private final GType gt;
+	private final boolean isRoad;
 
 	private byte roadClass;			// 0-4
 	private byte roadSpeed;			// 0-7
 	private byte mkgmapAccess; 		// bit mask, see ACCESS_TAGS 
 	private final byte routeFlags;	// bit mask, see ROUTING_TAGS
-	private boolean isRoad;
 	private boolean reversed;		// points were reversed
 	private boolean overlay;		// this is a non-routable overlay line that for a road 
 	
@@ -73,10 +73,12 @@ public class ConvertedWay {
 		// copy all other attributes
 		this.index = other.index;
 		this.gt = other.gt;
+		this.isRoad	 = other.isRoad;
 		this.roadClass = other.roadClass;
 		this.roadSpeed = other.roadSpeed;
 		this.mkgmapAccess = other.mkgmapAccess;
 		this.routeFlags = other.routeFlags;
+		this.overlay = other.overlay;
 	}
 	
 	public int getIndex(){


=====================================
src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
=====================================
@@ -28,8 +28,8 @@ import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.logging.Level;
 
 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
@@ -118,7 +118,7 @@ public class StyledConverter implements OsmConverter {
 	private IdentityHashMap<Coord, CoordNode> nodeIdMap = new IdentityHashMap<>();
 
 	public static final String WAY_POI_NODE_IDS = "mkgmap:way-poi-node-ids";
-	private final HashMap<Integer, Map<String,MapPoint>> pointMap;
+	private final HashMap<Integer, Map<String, MapPoint>> pointMap;
 	
 	/** boundary ways with admin_level=2 */
 	private final Set<Way> borders = new LinkedHashSet<>();
@@ -128,8 +128,7 @@ public class StyledConverter implements OsmConverter {
 	
 	private List<ConvertedWay> roads = new ArrayList<>();
 	private List<ConvertedWay> lines = new ArrayList<>();
-	private HashMap<Long, ConvertedWay> modifiedRoads = new HashMap<>();
-	private HashSet<Long> deletedRoads = new HashSet<>();
+	private List<MapPoint> renderedCoordPOI = new ArrayList<>();
 
 	private int nextRoadId = 1;
 	
@@ -588,6 +587,9 @@ public class StyledConverter implements OsmConverter {
 				return;
 			}
 
+			if (node.getLocation() instanceof CoordPOI) {
+				renderedCoordPOI.add(mp);
+			}
 			collector.addPoint(mp);
 		}
 
@@ -883,12 +885,15 @@ public class StyledConverter implements OsmConverter {
 		borders.clear();
 		
 		setHighwayCounts();
+		HashMap<Long, ConvertedWay> modifiedRoads = new HashMap<>();
 		findUnconnectedRoads();
-		rotateClosedWaysToFirstNode();
+		rotateClosedWaysToFirstNode(modifiedRoads);
 		filterCoordPOI();
-		WrongAngleFixer wrongAngleFixer = new WrongAngleFixer(bbox);
-		wrongAngleFixer.optimizeWays(roads, lines, modifiedRoads, deletedRoads, restrictions);
 
+		HashSet<Long> deletedRoads = new HashSet<>();
+		WrongAngleFixer wrongAngleFixer = new WrongAngleFixer(bbox);
+		wrongAngleFixer.optimizeWays(roads, lines, modifiedRoads, deletedRoads, restrictions, renderedCoordPOI);
+		
 		// make sure that copies of modified roads have equal points 
 		for (ConvertedWay line : lines){
 			if (!line.isValid())
@@ -915,8 +920,8 @@ public class StyledConverter implements OsmConverter {
 				log.warn("Way that is used in valid restriction relation was removed, id:",wayId);
 			}
 		}
-		deletedRoads = null;
-		modifiedRoads = null;
+		deletedRoads.clear();
+		modifiedRoads.clear(); 
 		mergeRoads();
 		
 		resetHighwayCounts();
@@ -998,9 +1003,10 @@ public class StyledConverter implements OsmConverter {
 	 * Try to make sure that closed ways start with a point that is 
 	 * also part of another road. This reduces the number of nodes
 	 * a little bit.
+	 * @param modifiedRoads Will contain roads modified by this routine  
 	 * 
 	 */
-	private void rotateClosedWaysToFirstNode() {
+	private void rotateClosedWaysToFirstNode(HashMap<Long, ConvertedWay> modifiedRoads ) {
 		for (ConvertedWay cw: roads){
 			if (!cw.isValid())
 				continue;
@@ -1945,7 +1951,6 @@ public class StyledConverter implements OsmConverter {
 		return trailingWay;
 	}
 
-
 	/**
 	 * Increment the highway counter for each coord of each road.
 	 * As a result, all road junctions have a count > 1. 


=====================================
src/uk/me/parabola/mkgmap/osmstyle/WrongAngleFixer.java
=====================================
@@ -29,6 +29,7 @@ import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.filters.DouglasPeuckerFilter;
+import uk.me.parabola.mkgmap.general.MapPoint;
 import uk.me.parabola.mkgmap.reader.osm.CoordPOI;
 import uk.me.parabola.mkgmap.reader.osm.FakeIdGenerator;
 import uk.me.parabola.mkgmap.reader.osm.Node;
@@ -60,12 +61,17 @@ public class WrongAngleFixer {
 	
 	private final Area bbox;
 	private static final String DEBUG_PATH = null;
-	static final int MODE_ROADS = 0;
-	static final int MODE_LINES = 1;
-	private int mode = MODE_ROADS;
 	private int pass;
 	private boolean extraPass;
-	
+
+	private ArrayList<ConvertedWay> convertedWays;
+
+	/**
+	 * Construct new WrongAngleFixer
+	 * @param bbox the bounding box, ignored if null, else might be used for debugging
+	 * @param allCoordPOI all {@code MapPoint} instances which refer to {@code CoordP} instances. There location might be changed
+	 * in this class.
+	 */
 	public WrongAngleFixer(Area bbox) {
 		this.bbox = bbox;
 		if (DEBUG_PATH != null && bbox != null && (long) bbox.getWidth() * bbox.getHeight() < 100000) {
@@ -87,28 +93,45 @@ public class WrongAngleFixer {
 	 * @param lines list of non-routable ways  
 	 * @param modifiedRoads Will be enlarged by all roads modified in this method 
 	 * @param deletedRoads Will be enlarged by all roads in roads that were set to null by this method 
-	 * @param restrictions Map with restriction relations 
+	 * @param restrictions Map with restriction relations
+	 * @param renderedPOI all MapPoint instances for {@code CoordPOI} instances 
 	 */
 	public void optimizeWays(List<ConvertedWay> roads, List<ConvertedWay> lines, Map<Long, ConvertedWay> modifiedRoads,
-			Set<Long> deletedRoads, List<RestrictionRelation> restrictions) {
+			Set<Long> deletedRoads, List<RestrictionRelation> restrictions, List<MapPoint> renderedPOI) {
 		printBadAngles("bad_angles_start", roads);
 		writeOSM("roads_orig", roads);
 		writeOSM("lines_orig", lines);
-		Long2ObjectOpenHashMap<Coord> coordMap = new Long2ObjectOpenHashMap<>();
-		replaceDuplicateBoundaryNodes(roads, coordMap);
-		replaceDuplicateBoundaryNodes(lines, coordMap);
-		coordMap.clear();
-		removeWrongAngles(roads, lines, modifiedRoads, deletedRoads, restrictions);
+		
+		convertedWays = new ArrayList<>();
+		convertedWays.addAll(roads);
+		convertedWays.addAll(lines);
+		convertedWays.removeIf(ConvertedWay::isOverlay);
+		convertedWays.sort((o1,o2) -> Long.compare(o1.getWay().getId(), o2.getWay().getId()));
+		replaceDuplicateBoundaryNodes(convertedWays);
+		Map<Coord, Coord> replacements = removeWrongAngles(modifiedRoads, deletedRoads);
 		writeOSM("roads_post_rem_wrong_angles", roads);
-		removeObsoletePoints(roads, modifiedRoads);
+		removeObsoletePoints(modifiedRoads);
 		writeOSM("roads_post_rem_obsolete_points", roads);
 		printBadAngles("bad_angles_finish", roads);
-		this.mode = MODE_LINES;
-		writeOSM("lines_after_roads", lines);
-		removeWrongAngles(null, lines, modifiedRoads, null, restrictions);
 		writeOSM("lines_post_rem_wrong_angles", lines);
-		removeObsoletePoints(lines, modifiedRoads);
-		writeOSM("lines_final", lines);
+		convertedWays = null;
+		
+		for (RestrictionRelation rr : restrictions) {
+			for (Coord p : rr.getViaCoords()) {
+				Coord replacement = getReplacement(p, null, replacements);
+				if (p != replacement) {
+					rr.replaceViaCoord(p, replacement);
+				}
+			}
+		}
+
+		// update positions of the POIs which were already created. 
+		for (MapPoint mp : renderedPOI) {
+			Coord replacement = getReplacement(mp.getLocation(), null, replacements);
+			if (mp.getLocation() != replacement) {
+				mp.setLocation(replacement);
+			}
+		}
 	}	
 	
 	/**
@@ -116,10 +139,10 @@ public class WrongAngleFixer {
 	 * @param convertedWays
 	 * @param coordMap
 	 */
-	private static void replaceDuplicateBoundaryNodes(List<ConvertedWay> convertedWays,
-			Long2ObjectOpenHashMap<Coord> coordMap) {
+	private static void replaceDuplicateBoundaryNodes(List<ConvertedWay> convertedWays) {
+		Long2ObjectOpenHashMap<Coord> coordMap = new Long2ObjectOpenHashMap<>();
 		for (ConvertedWay cw : convertedWays) {
-			if (!cw.isValid() || cw.isOverlay())
+			if (!cw.isValid())
 				continue;
 			Way way = cw.getWay();
 			List<Coord> points = way.getPoints();
@@ -195,14 +218,11 @@ public class WrongAngleFixer {
 	/**
 	 * Find wrong angles caused by rounding to map units. Try to fix them by
 	 * moving, removing or merging points.
-	 * @param roads list with routable ways or null, if lines should be optimized
-	 * @param lines list with non-routable ways
 	 * @param modifiedRoads map of modified routable ways (modified by this routine)
 	 * @param deletedRoads set of ids of deleted routable ways (modified by this routine)
-	 * @param restrictions Map with restriction relations. The restriction relations may be modified by this routine 
+	 * @return 
 	 */
-	private void removeWrongAngles(List<ConvertedWay> roads, List<ConvertedWay> lines,
-			Map<Long, ConvertedWay> modifiedRoads, Set<Long> deletedRoads, List<RestrictionRelation> restrictions) {
+	private Map<Coord, Coord> removeWrongAngles(Map<Long, ConvertedWay> modifiedRoads, Set<Long> deletedRoads) {
 		// replacements maps those nodes that have been replaced to
 		// the node that replaces them
 		Map<Coord, Coord> replacements = new IdentityHashMap<>();
@@ -212,10 +232,8 @@ public class WrongAngleFixer {
 		HashSet<Way> waysWithBearingErrors = new HashSet<>();
 		HashSet<Long> waysThatMapToOnePoint = new HashSet<>();
 		
-		List<ConvertedWay> convertedWays = (roads != null) ? roads: lines;
-
 		// filter with Douglas Peucker algo
-		prepWithDouglasPeucker(convertedWays, modifiedRoads);
+		prepWithDouglasPeucker(modifiedRoads);
 
 		Way lastWay = null;
 		boolean anotherPassRequired = true;
@@ -225,12 +243,12 @@ public class WrongAngleFixer {
 				break;
 			anotherPassRequired = false;
 			log.info("Removing wrong angles - PASS", pass);
-			writeOSM(((mode == MODE_LINES) ? "lines" : "roads") + "_pass_" + pass, convertedWays);
+			writeOSM("pass_" + pass, convertedWays);
 			
 			// Step 1: detect points which are parts of line segments with wrong bearings
 			lastWay = null;
 			for (ConvertedWay cw : convertedWays) {
-				if (!cw.isValid() || cw.isOverlay())
+				if (!cw.isValid())
 					continue;
 				Way way = cw.getWay();
 				if (way.equals(lastWay))
@@ -251,7 +269,7 @@ public class WrongAngleFixer {
 					if (pass == 1)
 						p.setRemove(false);
 					p = getReplacement(p, way, replacements);
-					if (i == 0 || i == points.size() - 1) {
+					if (!cw.isRoad() && (i == 0 || i == points.size() - 1)) {
 						p.setEndOfWay(true);
 					}
 
@@ -279,7 +297,7 @@ public class WrongAngleFixer {
 
 			lastWay = null;
 			for (ConvertedWay cw : convertedWays) {
-				if (!cw.isValid() || cw.isOverlay() || cw.getWay().equals(lastWay))
+				if (!cw.isValid() || cw.getWay().equals(lastWay))
 					continue;
 				Way way = cw.getWay();
 				if (pass != 1 && !waysWithBearingErrors.contains(way))
@@ -299,8 +317,9 @@ public class WrongAngleFixer {
 						if (p == prev) {
 							points.remove(i);
 							--i;
-							if (mode == MODE_ROADS)
+							if (cw.isRoad()) {
 								modifiedRoads.put(way.getId(), cw);
+							}
 							continue;
 						}
 						if (p.isPartOfBadAngle() || prev.isPartOfBadAngle()) {
@@ -308,15 +327,15 @@ public class WrongAngleFixer {
 							// save both points with their neighbour
 							Coord p1 = prev;
 							Coord p2 = p;
-							CenterOfAngle coa1 = getOrCreateCenter(p, way, centerMap, centers, overlaps);
-							CenterOfAngle coa2 = getOrCreateCenter(prev, way, centerMap, centers, overlaps);
+							CenterOfAngle coa1 = getOrCreateCenter(p, cw, centerMap, centers, overlaps);
+							CenterOfAngle coa2 = getOrCreateCenter(prev, cw, centerMap, centers, overlaps);
 							coa1.addNeighbour(coa2);
 							coa2.addNeighbour(coa1);
 							if (points.size() == 2) {
 								// way has only two points, don't merge them
 								coa1.addBadMergeCandidate(coa2);
 							}
-							if (mode == MODE_ROADS && p1.getHighwayCount() >= 2 && p2.getHighwayCount() >= 2
+							if (cw.isRoad() && p1.getHighwayCount() >= 2 && p2.getHighwayCount() >= 2
 									&& cw.isRoundabout()) {
 								// avoid to merge exits of roundabouts
 								coa1.addBadMergeCandidate(coa2);
@@ -333,7 +352,7 @@ public class WrongAngleFixer {
 			// Step 3: Update list of ways with bearing errors or points next to them 
 			lastWay = null;
 			for (ConvertedWay cw : convertedWays) {
-				if (!cw.isValid() || cw.isOverlay() || cw.getWay().equals(lastWay))
+				if (!cw.isValid() || cw.getWay().equals(lastWay))
 					continue;
 				Way way = cw.getWay();
 				lastWay = way;
@@ -381,7 +400,7 @@ public class WrongAngleFixer {
 			boolean lastWayModified = false;
 			ConvertedWay lastConvertedWay = null;
 			for (ConvertedWay cw : convertedWays) {
-				if (!cw.isValid() || cw.isOverlay() || !waysWithBearingErrors.contains(cw.getWay()))
+				if (!cw.isValid() || !waysWithBearingErrors.contains(cw.getWay()))
 					continue;
 				Way way = cw.getWay();
 				List<Coord> points = way.getPoints();
@@ -442,7 +461,7 @@ public class WrongAngleFixer {
 						anotherPassRequired = true;
 					}
 				}
-				if (lastWayModified && mode == MODE_ROADS) {
+				if (lastWayModified && cw.isRoad()) {
 					modifiedRoads.put(way.getId(), cw);
 				}
 			}
@@ -470,19 +489,17 @@ public class WrongAngleFixer {
 		boolean lastWayModified = false;
 		ConvertedWay lastConvertedWay = null;
 		for (ConvertedWay cw : convertedWays) {
-			if (cw.isOverlay())
-				continue;
 			Way way = cw.getWay();
 			
 			List<Coord> points = way.getPoints();
 			if (points.size() < 2) {
 				if (log.isInfoEnabled())
 					log.info("  Way " + way.getTag("name") + " (" + way.toBrowseURL() + ") has less than 2 points - deleting it");
-				if (mode == MODE_LINES && !waysThatMapToOnePoint.contains(way.getId())) {
+				if (!cw.isRoad() && !waysThatMapToOnePoint.contains(way.getId())) {
 					log.warn("non-routable way ", way.getId(), "was removed");
 				}
 				
-				if (mode == MODE_ROADS)
+				if (cw.isRoad())
 					deletedRoads.add(way.getId());
 				++numWaysDeleted;
 				continue;
@@ -511,41 +528,30 @@ public class WrongAngleFixer {
 				prev = p;
 			}
 		}
-		if (mode == MODE_ROADS) {
-			// treat special case: non-routable ways may be connected to moved
-			// points in roads
-			for (ConvertedWay cw : lines) {
-				if (!cw.isValid() || cw.isOverlay())
-					continue;
-				Way way = cw.getWay();
-				List<Coord> points = way.getPoints();
-				int n = points.size();
-				boolean hasReplacedPoints = false;
-				for (int i = 0; i < n; i++) {
-					Coord p = points.get(i);
-					if (p.isReplaced()) {
-						hasReplacedPoints = true;
-						points.set(i, getReplacement(p, null, replacements));
-					}
-				}
-				if (hasReplacedPoints && DEBUG_PATH != null) {
-					GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, way.getId() + "_mod_non_routable"), points);
+		// treat special case: non-routable ways may be connected to moved
+		// points in roads
+		for (ConvertedWay cw : convertedWays) {
+			if (!cw.isValid() || cw.isRoad())
+				continue;
+			Way way = cw.getWay();
+			List<Coord> points = way.getPoints();
+			int n = points.size();
+			boolean hasReplacedPoints = false;
+			for (int i = 0; i < n; i++) {
+				Coord p = points.get(i);
+				if (p.isReplaced()) {
+					hasReplacedPoints = true;
+					points.set(i, getReplacement(p, null, replacements));
 				}
 			}
-		
-			for (RestrictionRelation rr : restrictions) {
-				for (Coord p : rr.getViaCoords()) {
-					Coord replacement = getReplacement(p, null, replacements);
-					if (p != replacement) {
-						rr.replaceViaCoord(p, replacement);
-					}
-				}
+			if (hasReplacedPoints && DEBUG_PATH != null) {
+				GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, way.getId() + "_mod_non_routable"), points);
 			}
 		}
-		
+
 		if (DEBUG_PATH != null) {
 			GpxCreator.createGpx(
-					Utils.joinPath(DEBUG_PATH, (mode == MODE_ROADS ? "roads_" : "lines_") + "solved_badAngles"),
+					Utils.joinPath(DEBUG_PATH, "solved_badAngles"),
 					bbox.toCoords(), new ArrayList<>(changedPlaces));
 		}
 		if (anotherPassRequired) {
@@ -554,17 +560,18 @@ public class WrongAngleFixer {
 			log.info("Removing wrong angles - finished in", pass, "passes (", numNodesMerged, "nodes merged,",
 					numWaysDeleted, "ways deleted)");
 		}
+		return replacements;
 	}
 
-	private CenterOfAngle getOrCreateCenter(Coord p, Way way, IdentityHashMap<Coord, CenterOfAngle> centerMap,
+	private CenterOfAngle getOrCreateCenter(Coord p, ConvertedWay cw, IdentityHashMap<Coord, CenterOfAngle> centerMap,
 			List<CenterOfAngle> centers, Map<Coord, Set<Way>> overlaps) {
 		CenterOfAngle coa = centerMap.get(p);
 		if (coa == null) {
 			coa = new CenterOfAngle(p, centerMap.size() + 1);
 			centerMap.put(p, coa);
 			centers.add(coa);
-			if (mode == MODE_ROADS && pass > 1) {
-				overlaps.computeIfAbsent(p, k -> new HashSet<>()).add(way);
+			if (cw.isRoad() && pass > 1) { 
+				overlaps.computeIfAbsent(p, k -> new HashSet<>()).add(cw.getWay());
 			}
 		}
 		return coa;
@@ -590,19 +597,18 @@ public class WrongAngleFixer {
 	 * very close to 180 degrees angles in the real line or wrong points. 
 	 * Wrong points are those that produce wrong angles, so that  
 	 * removing them reduces the error.
-	 * @param convertedWays 
 	 * @param modifiedRoads 
 	 */
-	private void removeObsoletePoints(List<ConvertedWay> convertedWays, Map<Long, ConvertedWay> modifiedRoads) {
+	private void removeObsoletePoints(Map<Long, ConvertedWay> modifiedRoads) {
 		ConvertedWay lastConvertedWay = null;
 		int numPointsRemoved = 0;
 		boolean lastWasModified = false;
 		List<Coord> removedInWay = new ArrayList<>();
 		List<Coord> obsoletePoints = new ArrayList<>();
 		List<Coord> modifiedPoints = new ArrayList<>();
-		
+		markEndPoints(convertedWays, true); // don't allow to remove end points of ways
 		for (ConvertedWay cw : convertedWays) {
-			if (!cw.isValid() || cw.isOverlay())
+			if (!cw.isValid())
 				continue;
 			Way way = cw.getWay();
 			if (lastConvertedWay != null && way.equals(lastConvertedWay.getWay())) {
@@ -667,7 +673,7 @@ public class WrongAngleFixer {
 						keepThis = false;
 					} else if (c1.equals(c2)) {
 						// spike / overlap
-						log.debug("pass", pass, "roads=" + (mode == MODE_ROADS),
+						log.debug("pass", pass, "roads=" + (cw.isRoad()),
 								"extra remove to remove spike or overlap near", cm.toDegreeString());
 						keepThis = false;
 
@@ -693,7 +699,7 @@ public class WrongAngleFixer {
 				modifiedPoints.add(points.get(points.size() - 1));
 				points.clear();
 				points.addAll(modifiedPoints);
-				if (mode == MODE_ROADS)
+				if (cw.isRoad())
 					modifiedRoads.put(way.getId(), cw);
 				if (DEBUG_PATH != null && (draw || cw.isRoundabout())) {
 					GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, way.getId() + "_dpmod"), points, removedInWay);
@@ -701,10 +707,10 @@ public class WrongAngleFixer {
 			}
 		}
 		if (DEBUG_PATH != null) {
-			GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, (mode == MODE_ROADS ? "roads" : "lines") + "_obsolete"),
+			GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, "_obsolete"),
 					bbox.toCoords(), new ArrayList<>(obsoletePoints));
 		}
-		log.info("Removed", numPointsRemoved, "obsolete points in lines"); 
+		log.info("Removed", numPointsRemoved, "obsolete points from lines"); 
 	}
 	
 	/** 
@@ -768,23 +774,21 @@ public class WrongAngleFixer {
 			if (hasBadAngles)
 				badWays.add(cw);
 		}
-		GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, (mode==MODE_ROADS ? "roads_" : "lines_")+name), bbox.toCoords(), new ArrayList<>(badAngles));
+		GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, name), bbox.toCoords(), new ArrayList<>(badAngles));
 		writeOSM(name, badWays);
 	}
 	
 	/**
-	 * Check if the point can safely be removed from a road. 
+	 * Check if the point can safely be removed. 
 	 * @param p
 	 * @return true if remove is okay
 	 */
-	private boolean allowedToRemove(Coord p){
-		if (p.getOnBoundary() || p.getOnCountryBorder())
+	private static boolean allowedToRemove(Coord p) {
+		if (p.getOnBoundary() || p.getOnCountryBorder() || p.isEndOfWay())
 			return false;
-		if (mode == MODE_LINES && p.isEndOfWay())
+		if (p instanceof CoordPOI && ((CoordPOI) p).isUsed())
 			return false;
-		if (p instanceof CoordPOI && ((CoordPOI) p).isUsed()){
-				return false;
-		}
+		
 		return p.getHighwayCount() < 2 && !p.isViaNodeOfRestriction();
 	}
 	
@@ -892,7 +896,7 @@ public class WrongAngleFixer {
 			toRepl.setReplaced(true);
 			if (toRepl instanceof CoordPOI) {
 				CoordPOI cp = (CoordPOI) toRepl;
-				if (cp.isUsed()) {
+				if (cp.isUsed() ) {
 					replacement = new CoordPOI(replacement);
 					((CoordPOI) replacement).setNode(cp.getNode());
 					((CoordPOI) replacement).setUsed(true);
@@ -975,7 +979,7 @@ public class WrongAngleFixer {
 					List<Coord> altPositions = currentCenter.getAlternativePositions();
 					for (Coord altCenter : altPositions) {
 						if (dupCheck.contains(altCenter)) {
-							log.debug("pass", pass, "roads=" + (mode == MODE_ROADS),
+							log.debug("pass", pass, 
 									"extra move to remove spike or overlap near", currentCenter.toDegreeString());
 							replaceCoord(currentCenter, altCenter, replacements);
 							return true;
@@ -1291,7 +1295,7 @@ public class WrongAngleFixer {
 
 		@SuppressWarnings("unused")
 		private void createGPX(String gpxName, Map<Coord, Coord> replacements) {
-			if (gpxName == null || DEBUG_PATH == null)
+			if (DEBUG_PATH == null || gpxName == null)
 				return;
 			if (gpxName.isEmpty())
 				gpxName = Utils.joinPath(DEBUG_PATH, id + "_no_info");
@@ -1405,13 +1409,13 @@ public class WrongAngleFixer {
 	 * @param convertedWays list of ways to filter
 	 * @param modifiedRoads if ways are routable we add the modified ways to this map 
 	 */
-	private void prepWithDouglasPeucker(List<ConvertedWay> convertedWays, Map<Long, ConvertedWay> modifiedRoads) {
+	private void prepWithDouglasPeucker(Map<Long, ConvertedWay> modifiedRoads) {
 		// we don't want to remove end points of ways
-		markEndPoints(convertedWays);
+		markEndPoints(convertedWays, true);
 		double maxErrorDistance = 0.05;
 		Way lastWay = null;
 		for (ConvertedWay cw : convertedWays) {
-			if (!cw.isValid() || cw.isOverlay() || cw.getWay().equals(lastWay))
+			if (!cw.isValid() || cw.getWay().equals(lastWay))
 				continue;
 			Way way = cw.getWay();
 			lastWay = way;
@@ -1433,24 +1437,25 @@ public class WrongAngleFixer {
 			// Simplify the rest
 			DouglasPeuckerFilter.douglasPeucker(coords, 0, endIndex, maxErrorDistance);
 			if (coords.size() != points.size()) {
-				if (mode == MODE_ROADS) {
+				if (cw.isRoad()) {
 					modifiedRoads.put(way.getId(), cw);
 				}
 				points.clear();
 				points.addAll(coords);
 			}
 		}
+		markEndPoints(convertedWays, false);
 	}
 
-	private static void markEndPoints(List<ConvertedWay> convertedWays) {
+	private static void markEndPoints(List<ConvertedWay> convertedWays, boolean b) {
 		Way lastWay = null;
 		for (ConvertedWay cw : convertedWays) {
-			if (!cw.isValid() || cw.isOverlay() || cw.getWay().equals(lastWay))
+			if (!cw.isValid() || cw.getWay().equals(lastWay))
 				continue;
 			Way way = cw.getWay();
 			lastWay = way;
-			way.getFirstPoint().setEndOfWay(true);
-			way.getLastPoint().setEndOfWay(true);
+			way.getFirstPoint().setEndOfWay(b);
+			way.getLastPoint().setEndOfWay(b);
 		}
 	}
 


=====================================
src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
=====================================
@@ -148,6 +148,8 @@ public class OsmMapDataSource extends MapperBasedMapDataSource implements Loadab
 	public void load(String name, boolean addBackground) throws FileNotFoundException {
 		try (InputStream is = Utils.openFile(name)) {
 			parse(is, name);
+		} catch (FileNotFoundException e) {
+			throw e;
 		} catch (IOException e) {
 			// exception thrown from implicit call to close() on resource variable 'is'
 		}


=====================================
src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
=====================================
@@ -56,6 +56,7 @@ import uk.me.parabola.mkgmap.general.MapShape;
 import uk.me.parabola.mkgmap.general.ZipCodeInfo;
 import uk.me.parabola.mkgmap.reader.MapperBasedMapDataSource;
 import uk.me.parabola.mkgmap.reader.osm.FakeIdGenerator;
+import uk.me.parabola.mkgmap.reader.osm.FeatureKind;
 import uk.me.parabola.mkgmap.reader.osm.GType;
 import uk.me.parabola.mkgmap.reader.osm.GeneralRelation;
 import uk.me.parabola.mkgmap.reader.osm.MultiPolygonRelation;
@@ -419,10 +420,12 @@ public class PolishMapDataSource extends MapperBasedMapDataSource implements Loa
 			if (type <= 0xff)
 				type <<= 8;
 			point.setType(type);
+			checkType(FeatureKind.POINT, point.getType());
 		} else if (name.equals("SubType")) {
 			int subtype = Integer.decode(value);
 			int type = point.getType();
 			point.setType(type | subtype);
+			checkType(FeatureKind.POINT, point.getType());
 		} else if (name.startsWith("Data") || name.startsWith("Origin")) {
 			Coord co = makeCoord(value);
 			setResolution(point, name);
@@ -447,6 +450,7 @@ public class PolishMapDataSource extends MapperBasedMapDataSource implements Loa
 	private void line(String name, String value) {
 		if (name.equals("Type")) {
 			polyline.setType(Integer.decode(value));
+			checkType(FeatureKind.POLYLINE, polyline.getType());
 		} else if (name.startsWith("Data")) {
 			extractResolution(name);
 			addLineString(value, false);
@@ -585,6 +589,7 @@ public class PolishMapDataSource extends MapperBasedMapDataSource implements Loa
 			if (type == 0x4a00)
 				type = 0x4a;
 			shape.setType(type);
+			checkType(FeatureKind.POLYGON, type);
 			if(type == 0x4b)
 				havePolygon4B = true;
 		} else if (name.startsWith("Data")) {
@@ -1023,4 +1028,11 @@ public class PolishMapDataSource extends MapperBasedMapDataSource implements Loa
 	public String getDefaultRegion() {
 		return defaultRegion;
 	}
+	
+	private void checkType(FeatureKind kind, int type) {
+		if (!GType.checkType(kind, type)) {
+			throw new MapFailedException("invalid type " + GType.formatType(type) + " for " + kind + ", line " + lineNo);
+		}
+	}
+
 }


=====================================
tools/buildoptions/OptionsBuilder.java
=====================================
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019.
+ *
+ * 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 buildoptions;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Convert options.txt to format needed in help file options. 
+ * Saves some manual edits to keep both files in sync.
+ * Used with ant gen-options-file  
+ * @author Mike Baggaley
+ *
+ */
+public class OptionsBuilder {
+
+	public static void main(String[] args) {
+		final int indentSize = 4;
+		boolean hasNonAscii = false;
+		int lineNumber = 0;
+		File outputFile = new File(args[0]);
+		System.setProperty("line.separator", "\n");
+		try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+				BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile))) {
+			String line;
+			String previousLine = "";
+			int indent = 0;
+			boolean preformatted = false;
+			while((line = br.readLine()) != null) {
+				++lineNumber;
+				if (!line.matches("\\p{ASCII}*")) {
+					System.err.println("Line " + lineNumber + " contains one or more non-ASCII characters.\r\n" + line);
+					hasNonAscii = true;
+				}
+				if (preformatted) {
+					if (line.trim().compareToIgnoreCase("</pre>") == 0)
+						preformatted = false;
+					else {
+					    bw.write(line);
+					    bw.newLine();
+					}
+				} else {
+					line = line.replaceAll("\\s+", " ");
+					if (line.length() > 0) {
+						if (line.startsWith(";")) {
+							line = line.substring(1);
+							indent = 0;
+							if (!previousLine.isEmpty()) {
+							    bw.write(previousLine);
+							    bw.newLine();
+							    previousLine = "";
+							}
+						}
+						else if (line.charAt(0) == ':') {
+							if (!previousLine.isEmpty()) {
+							    bw.write(previousLine);
+							    bw.newLine();
+							    previousLine = "";
+							}
+							indent = 1;
+							line = line.substring(1);
+							while (line.charAt(0) == ':') {
+								indent++;
+								line = line.substring(1);
+							}
+							if (line.charAt(0) == ';')
+								line = line.substring(1);
+						}
+						else if (line.trim().compareToIgnoreCase("<p>") == 0) {
+							if (!previousLine.isEmpty()) {
+							    bw.write(previousLine);
+							    bw.newLine();
+							    previousLine = "";
+							}
+							line = "";
+						    bw.newLine();
+						}
+						else if (line.trim().compareToIgnoreCase("<pre>") == 0) {
+							if (!previousLine.isEmpty()) {
+							    bw.write(previousLine);
+							    bw.newLine();
+							    previousLine = "";
+							}
+							line = "";
+						    preformatted = true;
+						}
+						line = line.trim();
+						if (!previousLine.isEmpty()) {
+							if (!line.isEmpty()) {
+								previousLine += " " + line;
+							}
+						} else {
+							previousLine = line;
+							for (int i = 0; i < indent; i++) {
+								for (int j = 0; j < indentSize; j++)
+									previousLine = " " + previousLine;
+							}
+						}
+						while (previousLine.length() > 79) {
+							line = previousLine.substring(0, 80);
+							int lastSpaceIndex = line.lastIndexOf(' ');
+							int firstNonSpaceIndex = 0;
+							while (firstNonSpaceIndex < 79) {
+								if (line.charAt(firstNonSpaceIndex) != ' ')
+									break;
+								firstNonSpaceIndex++;
+							}
+							if (lastSpaceIndex > firstNonSpaceIndex) {
+								line = line.substring(0, lastSpaceIndex);
+								previousLine = previousLine.substring(lastSpaceIndex + 1);
+								for (int i = 0; i < indent; i++) {
+									for (int j = 0; j < indentSize; j++)
+										previousLine = " " + previousLine;
+								}
+							    bw.write(line);
+							    bw.newLine();
+							}
+							else {
+							    bw.write(previousLine);
+							    bw.newLine();
+							    previousLine = "";
+							}
+						}
+					}
+					else {
+						indent = 0;
+						if (!previousLine.isEmpty()) {
+						    bw.write(previousLine);
+						    bw.newLine();
+						    previousLine = "";
+						}
+						bw.newLine();
+					}
+				}
+			}
+			if (!previousLine.isEmpty()) {
+			    bw.write(previousLine);
+			    bw.newLine();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			System.exit(-1);
+		}
+		if (hasNonAscii) {
+			System.exit(-1);
+		}
+	}
+
+}



View it on GitLab: https://salsa.debian.org/debian-gis-team/mkgmap/-/commit/c030eea9b51dba4cb40a6a11f1e7612458941388

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/mkgmap/-/commit/c030eea9b51dba4cb40a6a11f1e7612458941388
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20200301/bf70eda9/attachment-0001.html>


More information about the Pkg-grass-devel mailing list