Codebase list mkgmap / c04f388
Update upstream source from tag 'upstream/0.0.0+svn4620' Update to upstream version '0.0.0+svn4620' with Debian dir 95288c4383a44a709bd36eb738898f3b18003127 Bas Couwenberg 3 years ago
24 changed file(s) with 119 addition(s) and 86 deletion(s). Raw diff Collapse all Expand all
0 svn.version: 4604
1 build.timestamp: 2021-02-28T07:50:49+0000
0 svn.version: 4620
1 build.timestamp: 2021-03-28T10:11:16+0100
1111 */
1212 package uk.me.parabola.imgfmt;
1313
14 import uk.me.parabola.log.Logger;
15
1614 /**
1715 * Used for cases where the current map has failed to compile, but the error
1816 * is expected to be specific to the map (eg it is too big etc). When this
2523 * @author Steve Ratcliffe
2624 */
2725 public class MapFailedException extends RuntimeException {
28 private static final Logger log = Logger.getLogger(MapFailedException.class);
2926
3027 /**
31 * Constructs a new runtime exception with the specified detail message.
28 * Constructs a new runtime exception with the calling method name
29 * appended to the detail message.
3230 * The cause is not initialized, and may subsequently be initialized by a
3331 * call to {@link #initCause}.
3432 *
3634 * later retrieval by the {@link #getMessage()} method.
3735 */
3836 public MapFailedException(String message) {
39 super(message);
40 log(message);
37 super(buildMessage(message));
4138 }
4239
4340 /**
44 * Constructs a new runtime exception with the specified detail message and
45 * cause. <p>Note that the detail message associated with
41 * Constructs a new runtime exception with the calling method name
42 * appended to the detail message and includes the cause.
43 * <p>Note that the detail message associated with
4644 * <code>cause</code> is <i>not</i> automatically incorporated in
4745 * this runtime exception's detail message.
4846 *
5250 * {@link #getCause()} method). (A <tt>null</tt> value is
5351 * permitted, and indicates that the cause is nonexistent or
5452 * unknown.)
55 * @since 1.4
5653 */
5754 public MapFailedException(String message, Throwable cause) {
58 super(message, cause);
59 log(message);
55 super(buildMessage(message), cause);
6056 }
6157
62 private static void log(String message){
58 /**
59 * Constructs a new runtime exception without appending the calling method
60 * name to the detail message. The calling method can be appended by the
61 * derived class if required.
62 */
63 protected MapFailedException(String message, boolean ignored) {
64 super(message);
65 }
66
67 /**
68 * Appends the calling method name to the supplied message.
69 */
70 protected static String buildMessage(String message) {
6371 String thrownBy = "";
6472 try{
6573 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
6674 int callerPosInStack = 3;
6775 String[] caller = stackTraceElements[callerPosInStack].getClassName().split("\\.");
68 thrownBy = "(thrown in " + caller[caller.length-1]+ "." +stackTraceElements[callerPosInStack].getMethodName() + "()) ";
76 thrownBy = " (thrown in " + caller[caller.length-1]+ "." +stackTraceElements[callerPosInStack].getMethodName() + "())";
6977 } catch(Exception e){
70 log.info(e);
7178 }
72 log.error(thrownBy + message);
79 return message + thrownBy;
7380 }
7481 }
0 package uk.me.parabola.imgfmt;
1
2 public class MapTooBigException extends MapFailedException {
3 protected final long maxAllowedSize;
4
5 public MapTooBigException(long maxSize, String message, String suggestion) {
6 super(message + " The maximum size is " + maxSize + " bytes. " + suggestion, false);
7 maxAllowedSize = maxSize;
8 }
9
10 public long getMaxAllowedSize() {
11 return maxAllowedSize;
12 }
13 }
1919 import java.nio.ByteBuffer;
2020 import java.nio.ByteOrder;
2121
22 import uk.me.parabola.imgfmt.MapFailedException;
22 import uk.me.parabola.imgfmt.MapTooBigException;
2323 import uk.me.parabola.imgfmt.Sized;
2424 import uk.me.parabola.imgfmt.fs.ImgChannel;
2525 import uk.me.parabola.imgfmt.sys.FileLink;
4040 private static final int GUARD_SIZE = KBYTE;
4141
4242 private final ImgChannel chan;
43 private final String subfile;
4344
4445 private ByteBuffer buf = ByteBuffer.allocate(INIT_SIZE);
4546 private int bufferSize = INIT_SIZE;
5455 // The maximum allowed file size.
5556 private long maxAllowedSize = 0xffffff;
5657
57 public BufferedImgFileWriter(ImgChannel chan) {
58 public BufferedImgFileWriter(ImgChannel chan, String subfile) {
5859 this.chan = chan;
60 this.subfile = subfile;
5961 buf.order(ByteOrder.LITTLE_ENDIAN);
6062 if (chan instanceof FileLink) {
6163 ((FileLink) chan).link(this, this);
269271 while(needed > (bufferSize - GUARD_SIZE))
270272 bufferSize += GROW_SIZE;
271273 if (bufferSize > maxAllowedSize) {
272 // Previous message was confusing people, although it is difficult to come
273 // up with something that is strictly true in all situations.
274 throw new MapFailedException(
275 "There is not enough room in a single garmin map for all the input data." +
276 " The .osm file should be split into smaller pieces first.");
274 throw new MapTooBigException(maxAllowedSize,
275 "The " + subfile + " section of the map or tile is too big.",
276 "Try splitting the map into smaller tiles or reducing the amount of information included in the map.");
277277 }
278278 ByteBuffer newb = ByteBuffer.allocate(bufferSize);
279279 newb.order(ByteOrder.LITTLE_ENDIAN);
1414
1515 import java.util.List;
1616
17 import uk.me.parabola.imgfmt.ExitException;
1718 import uk.me.parabola.imgfmt.Utils;
1819 import uk.me.parabola.imgfmt.app.Area;
1920 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
4546 setHeader(demHeader);
4647
4748 if (write) {
48 setWriter(new BufferedImgFileWriter(chan));
49 setWriter(new BufferedImgFileWriter(chan, "DEM"));
4950 position(DEMHeader.HEADER_LEN);
5051 } else {
5152 setReader(new BufferedImgFileReader(chan));
9798 }
9899 // last 4 bits of distance should be 0
99100 distance = ((distance + 8) / 16) * 16;
101 if (distance == 0)
102 throw new ExitException("DEM distance is zero");
100103
101104 int xTop = top;
102105 int xLeft = left;
6565 lblHeader.setOffsetMultiplier(OFFSET_MULTIPLIER);
6666 setHeader(lblHeader);
6767
68 setWriter(new BufferedImgFileWriter(chan));
68 setWriter(new BufferedImgFileWriter(chan, "LBL"));
6969
7070 position((long) LBLHeader.HEADER_LEN + lblHeader.getSortDescriptionLength());
7171
2424 */
2525 public class Mdr1MapIndex {
2626 private final Mdr1SubHeader subHeader = new Mdr1SubHeader();
27 private final BufferedImgFileWriter subWriter = new BufferedImgFileWriter(null);
27 private final BufferedImgFileWriter subWriter = new BufferedImgFileWriter(null, "MDR");
2828
2929 private int pointerSize;
3030
5050
5151 public NETFile(ImgChannel chan) {
5252 setHeader(netHeader);
53 setWriter(new BufferedImgFileWriter(chan));
53 setWriter(new BufferedImgFileWriter(chan, "NET"));
5454 position(NETHeader.HEADER_LEN);
5555 }
5656
5858 public NODFile(ImgChannel chan, boolean write) {
5959 setHeader(nodHeader);
6060 if (write) {
61 setWriter(new BufferedImgFileWriter(chan));
61 setWriter(new BufferedImgFileWriter(chan, "NOD"));
6262 position(NODHeader.HEADER_LEN);
6363 } else {
6464 setReader(new BufferedImgFileReader(chan));
3939 private final List<Integer> srt8Starts = new ArrayList<>();
4040
4141 public SRTFile(ImgChannel chan) {
42 BufferedImgFileWriter fileWriter = new BufferedImgFileWriter(chan);
42 BufferedImgFileWriter fileWriter = new BufferedImgFileWriter(chan, "SRT");
4343 fileWriter.setMaxSize(Long.MAX_VALUE);
4444 setWriter(fileWriter);
4545 }
5656 public RGNFile(ImgChannel chan) {
5757 setHeader(header);
5858
59 setWriter(new BufferedImgFileWriter(chan));
59 setWriter(new BufferedImgFileWriter(chan, "RGN"));
6060
6161 // Position at the start of the writable area.
6262 position(HEADER_LEN);
6363
6464 public TREFile(ImgChannel chan) {
6565 setHeader(header);
66 setWriter(new BufferedImgFileWriter(chan));
66 setWriter(new BufferedImgFileWriter(chan, "TRE"));
6767
6868 // Position at the start of the writable area.
6969 position(header.getHeaderLength());
5454
5555 public TYPFile(ImgChannel chan) {
5656 setHeader(header);
57 setWriter(new BufferedImgFileWriter(chan));
57 setWriter(new BufferedImgFileWriter(chan, "TYP"));
5858 position(TYPHeader.HEADER_LEN);
5959 }
6060
4545
4646 public MpsFile(ImgChannel chan) {
4747 assert chan instanceof FileNode;
48 writer = new BufferedImgFileWriter(chan);
48 writer = new BufferedImgFileWriter(chan, "MPS");
4949 }
5050
5151 public void sync() throws IOException {
240240 });
241241 try {
242242 opts.readOptionFile(filename);
243 } catch (IOException e) {
244 throw new ExitException("Failed to read option file", e);
243 } catch (Exception e) {
244 throw new ExitException("Failed to read option file.", e);
245245 }
246246 }
247247
3535 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
3636 import uk.me.parabola.imgfmt.ExitException;
3737 import uk.me.parabola.imgfmt.MapFailedException;
38 import uk.me.parabola.imgfmt.MapTooBigException;
3839 import uk.me.parabola.imgfmt.Utils;
3940 import uk.me.parabola.imgfmt.app.Area;
4041 import uk.me.parabola.imgfmt.app.Coord;
373374 long t2 = System.currentTimeMillis();
374375 log.info("DEM file calculation for", map.getFilename(), "took", (t2 - t1), "ms");
375376 demFile.write();
377 } catch (MapTooBigException e) {
378 throw new MapTooBigException(e.getMaxAllowedSize(), "The DEM section of the map or tile is too big.", "Try increasing the DEM distance.");
376379 } catch (MapFailedException e) {
377 log.error("exception while creating DEM file", e.getMessage());
378 throw new MapFailedException("DEM");
380 throw new MapFailedException("Error creating DEM File. " + e.getMessage());
379381 }
380382 }
381383
500502 }
501503
502504 }
503
505
504506 private void processRoads(Map map, MapDataSource src) {
505507 LBLFile lbl = map.getLblFile();
506508 MapPoint searchPoint = new MapPoint();
2121 import uk.me.parabola.imgfmt.FileNotWritableException;
2222 import uk.me.parabola.imgfmt.FileSystemParam;
2323 import uk.me.parabola.imgfmt.MapFailedException;
24 import uk.me.parabola.imgfmt.MapTooBigException;
2425 import uk.me.parabola.imgfmt.Utils;
2526 import uk.me.parabola.imgfmt.app.Area;
2627 import uk.me.parabola.imgfmt.app.Coord;
194195 throw new ExitException("Could not create overview map", e);
195196 } catch (FileNotWritableException e) {
196197 throw new ExitException("Could not write to overview map", e);
198 } catch (MapTooBigException e) {
199 throw new MapTooBigException(e.getMaxAllowedSize(),
200 "The overview map is too big.",
201 "Try reducing the highest overview resolution or reducing the amount of information included in the overview.");
197202 }
198203 }
199204
2929 public class RemoveObsoletePointsFilter implements MapFilter {
3030 private static final Logger log = Logger.getLogger(RemoveObsoletePointsFilter.class);
3131
32 final Coord[] areaTest = new Coord[3];
33
3432 private boolean checkPreserved;
3533
3634 @Override
4745 MapLine line = (MapLine) element;
4846 List<Coord> points = line.getPoints();
4947 int numPoints = points.size();
50 if (numPoints <= 1){
51 return;
48 if (numPoints <= 1) {
49 return;
5250 }
5351 int requiredPoints = (line instanceof MapShape ) ? 4:2;
5452 List<Coord> newPoints = new ArrayList<>(numPoints);
6664 if (lastP.equals(newP)){
6765 // only add the new point if it has different
6866 // coordinates to the last point or is preserved
69 if (checkPreserved && line.isRoad()){
67 if (checkPreserved && line.isRoad()) {
7068 if (!newP.preserved()) {
7169 continue;
72 } else if (!lastP.preserved()){
70 } else if (!lastP.preserved()) {
7371 newPoints.set(last, newP); // replace last
74 }
75 } else {
72 continue;
73 }
74 } else {
7675 continue;
7776 }
7877 }
115114 int nPoints = newPoints.size();
116115 switch(Utils.isStraight(newPoints.get(newPoints.size()-2), newPoints.get(0), newPoints.get(1))){
117116 case Utils.STRAIGHT_SPIKE:
117 log.debug("removing closing spike");
118118 newPoints.remove(0);
119119 newPoints.set(newPoints.size()-1, newPoints.get(0));
120120 if (newPoints.get(newPoints.size()-2).equals(newPoints.get(newPoints.size()-1)))
121121 newPoints.remove(newPoints.size()-1);
122122 break;
123123 case Utils.STRICTLY_STRAIGHT:
124 log.debug("removing straight line across closing");
124125 newPoints.remove(newPoints.size()-1);
125126 newPoints.set(0, newPoints.get(newPoints.size()-1));
126127 break;
3030 @Override
3131 public void init(FilterConfig config) {
3232 shift = config.getShift();
33 keepNodes = config.getLevel() == 0 && config.hasNet();
3433 level = config.getLevel();
34 keepNodes = level == 0 && config.hasNet();
3535 }
3636
3737 /**
4040 */
4141 @Override
4242 public void doFilter(MapElement element, MapFilterChain next) {
43 MapLine line = (MapLine) element;
44 if(shift == 0) {
43 if (shift == 0) {
4544 // do nothing
46 next.doFilter(line);
47 }
48 else {
45 next.doFilter(element);
46 } else {
47 MapLine line = (MapLine) element;
4948 int half = 1 << (shift - 1); // 0.5 shifted
5049 int mask = ~((1 << shift) - 1); // to remove fraction bits
5150
6362 int lon = (p.getLongitude() + half) & mask;
6463 Coord newP;
6564
66 if(p instanceof CoordNode && keepNodes)
65 if (p instanceof CoordNode && keepNodes) {
6766 newP = new CoordNode(lat, lon, p.getId(), p.getOnBoundary(), p.getOnCountryBorder());
68 else {
67 } else {
6968 newP = new Coord(lat, lon);
7069 newP.preserved(p.preserved());
7170 newP.setNumberNode(hasNumbers && p.isNumberNode());
7473 // only add the new point if it has different
7574 // coordinates to the last point or if it's a
7675 // special node
77 if (lastP == null || !lastP.equals(newP) || newP.getId() > 0|| (hasNumbers && newP.isNumberNode())) {
76 if (lastP == null || !lastP.equals(newP) || newP.getId() > 0 || (hasNumbers && newP.isNumberNode())) {
7877 newPoints.add(newP);
7978 lastP = newP;
8079 } else if (newP.preserved()) {
8685 lastP.preserved(true);
8786 }
8887 }
89 if(newPoints.size() > 1) {
88 if (newPoints.size() > 1) {
9089 MapLine newLine = line.copy();
9190 newLine.setPoints(newPoints);
9291 next.doFilter(newLine);
148148 System.err.println("Try using the mkgmap --max-jobs option with a value less than " + mm.maxJobs + " to reduce the memory requirement, or use the Java -Xmx option to increase the available heap memory.");
149149 else
150150 System.err.println("Try using the Java -Xmx option to increase the available heap memory.");
151 } catch (MapFailedException e) {
151 } catch (MapFailedException | ExitException e) {
152152 // one of the combiners failed
153 e.printStackTrace();
154 ++numExitExceptions;
155 } catch (ExitException e) {
156153 ++numExitExceptions;
157154 String message = e.getMessage();
158155 Throwable cause = e.getCause();
564561 } catch (MapFailedException mfe) {
565562 numMapFailedExceptions++;
566563 setProgramRC(-1);
567 } catch (Throwable t) {
568 t.printStackTrace();
569564 if (!args.getProperties().getProperty("keep-going", false)) {
570565 throw new ExitException("Exiting - if you want to carry on regardless, use the --keep-going option");
571566 }
567 } catch (Exception e) {
568 e.printStackTrace();
569 throw new ExitException("Exiting due to unexpected error");
572570 }
573571 }
574572 }
119119 map.close();
120120 return outName;
121121 } catch (FileExistsException e) {
122 log.error("File exists already");
122123 throw new MapFailedException("File exists already", e);
123124 } catch (FileNotWritableException e) {
125 log.error("Could not create or write to file");
124126 throw new MapFailedException("Could not create or write to file", e);
127 }
128 catch (MapFailedException e) {
129 log.error(e.getMessage()); // make sure the filename is logged
130 throw e;
125131 }
126132 }
127133
890890 MapRoad[] uncheckedRoads = new MapRoad[houses.length];
891891 for (int i = 0 ; i < houses.length; i++)
892892 uncheckedRoads[i] = houses[i].getRoad();
893 isOK = info.checkRoads();
893 info.checkRoads();
894894 // check if houses are assigned to different roads now
895895 houses = info.getHouseNodes();
896896 for (int i = 0 ; i < houses.length; i++) {
897897 if (houses[i].getRoad() != uncheckedRoads[i]) {
898898 initialHousesForRoads.removeMapping(uncheckedRoads[i], houses[i]);
899 if (!houses[i].isIgnored())
899 if (!houses[i].isIgnored()) {
900900 initialHousesForRoads.add(houses[i].getRoad(), houses[i]);
901 else {
902 if (!isOK)
903 log.info("housenumber is assigned to different road after checking addr:interpolation way which turned out to be invalid",houses[i],info );
904901 }
905902 }
906903 }
11561153 if (dupCount > 0) {
11571154 log.warn("addr:interpolation way",streetName,hivl,"is ignored, it produces",dupCount,"duplicate number(s) too far from existing nodes");
11581155 badIvls.add(hivl);
1159 }
1160 else {
1156 } else {
11611157 housesToAdd.put(hivl, interpolatedHouses);
11621158 for (HousenumberMatch hnm : interpolatedHouses)
11631159 interpolatedNumbers.put(hnm.getHousenumber(), hnm);
1616 import java.util.Collections;
1717 import java.util.List;
1818 import java.util.Map;
19
1920 import uk.me.parabola.imgfmt.Utils;
2021 import uk.me.parabola.imgfmt.app.Coord;
2122 import uk.me.parabola.log.Logger;
199200 HousenumberGenerator.findClosestRoadSegment(test[i], r);
200201 test[i].calcRoadSide();
201202 }
202 if (test[i].getRoad() == null || test[i].getDistance() > MAX_INTERPOLATION_DISTANCE_TO_ROAD ){
203 if (test[i].getRoad() == null || test[i].getDistance() > MAX_INTERPOLATION_DISTANCE_TO_ROAD) {
203204 foundSingleRoad = false;
204205 break;
205206 }
256257 }
257258 }
258259 }
259 if (!foundSingleRoad && bestRoad != null){
260 if (!foundSingleRoad && bestRoad != null) {
260261 // not matching road name in original OSM data, use the closest
261262 foundSingleRoad = true;
262263 test[0] = closest[0];
270271 hasMultipleRoads = true;
271272 return true;
272273 }
273 // we found the road that should be used for interpolation
274 for (int i = 0; i < 2; i++) {
275 if (test[i].getSegmentFrac() < 0 || test[i].getSegmentFrac() > 1) {
276 // might still be one road that bends but that will not cause trouble
277 hasMultipleRoads = true;
278 return true;
279 }
280 }
281
282 // we found a single road instance that should be used for all interpolated numbers
274283 roadForInterpolatedHouses = test[0].getRoad();
275284
276285 // we found a single plausible road, make sure that both nodes are using it
277 for (int i = 0; i < 2; i++){
278 if (knownHouses[i].getRoad() != test[i].getRoad() || knownHouses[i].getSegment() != test[i].getSegment()){
286 for (int i = 0; i < 2; i++) {
287 if (knownHouses[i].getRoad() != test[i].getRoad() || knownHouses[i].getSegment() != test[i].getSegment()) {
279288 copyRoadData(test[i], knownHouses[i]);
280289 knownHouses[i].forgetAlternativeRoads();
281290 }
282 if (knownHouses[i].getSegmentFrac() < 0 || knownHouses[i].getSegmentFrac() > 1){
283 hasMultipleRoads = true;
284 }
285 }
286 if (knownHouses[0].isLeft() != knownHouses[1].isLeft()){
287 log.warn("addr:interpolation way crosses road",streetName,this);
291 }
292 if (knownHouses[0].isLeft() != knownHouses[1].isLeft()) {
293 log.warn("addr:interpolation way crosses road", streetName, this);
288294 return false;
289295 }
290296 return true;
478484 return false;
479485 }
480486
481 public boolean foundCluster() {
482 return foundCluster;
483 }
484
485487 public void setEqualEnds() {
486488 this.equalEnds = true;
487489
13001300 String tagName = tagEntry.getKey();
13011301 // all tags are style relevant
13021302 // except: type (for relations), mkgmap:*
1303 boolean isStyleRelevant = !(element instanceof Relation && "typ".equals(tagName))
1303 boolean isStyleRelevant = !(element instanceof Relation && "type".equals(tagName))
13041304 && !tagName.startsWith("mkgmap:");
13051305 if (isStyleRelevant) {
13061306 return true;