~ubuntu-branches/ubuntu/vivid/mkgmap/vivid

« back to all changes in this revision

Viewing changes to src/uk/me/parabola/mkgmap/reader/osm/SeaGenerator.java

  • Committer: Package Import Robot
  • Author(s): Andreas Tille
  • Date: 2014-08-13 22:13:41 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140813221341-i9dzzjuto2o7hfh6
Tags: 0.0.0+svn3333-1
* New upstream version
  Closes: #745097
* add debian/classpath (thanks for the patch to Manfred Stock
  <manfred.stock+debian@gmail.com>)
  Closes: #741596
* d/copyright: DEP5

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
import java.io.LineNumberReader;
23
23
import java.util.ArrayList;
24
24
import java.util.Collection;
25
 
import java.util.HashMap;
26
25
import java.util.HashSet;
 
26
import java.util.IdentityHashMap;
27
27
import java.util.Iterator;
28
28
import java.util.LinkedList;
29
29
import java.util.List;
30
30
import java.util.Map;
 
31
import java.util.Map.Entry;
31
32
import java.util.NavigableMap;
32
33
import java.util.NavigableSet;
33
34
import java.util.Set;
158
159
                                                        }
159
160
                                                } else if (precompSea.endsWith(".zip")){
160
161
                                                        zipFile = new ZipFile(precompSeaDir);
161
 
                                                        internalPath = "sea";
162
 
                                                        ZipEntry entry = zipFile.getEntry(internalPath);
163
 
                                                        if (entry == null)
 
162
                                                        internalPath = "sea/";
 
163
                                                        ZipEntry entry = zipFile.getEntry(internalPath + indexFileName);
 
164
                                                        if (entry == null){
 
165
                                                                indexFileName = "index.txt";
 
166
                                                                entry = zipFile.getEntry(internalPath + indexFileName);
 
167
                                                        }
 
168
                                                        if (entry == null){
164
169
                                                                internalPath = "";
165
 
                                                        else 
166
 
                                                                internalPath = internalPath + "/";
167
 
                                                        entry = zipFile.getEntry(internalPath + indexFileName);
168
 
                                                        if (entry == null){
169
 
                                                                indexFileName = "index.txt";
 
170
                                                                indexFileName = "index.txt.gz";
170
171
                                                                entry = zipFile.getEntry(internalPath + indexFileName);
171
172
                                                        }
172
173
                                                        if (entry != null){
173
174
                                                                indexStream = zipFile.getInputStream(entry);
174
 
                                                        }
 
175
                                                        } else 
 
176
                                                                log.error("Don't know how to read " + precompSeaDir);
175
177
                                                } else {
176
178
                                                        log.error("Don't know how to read " + precompSeaDir);
177
179
                                                }
412
414
                String natural = way.getTag("natural");
413
415
                if(natural != null) {
414
416
                        if("coastline".equals(natural)) {
415
 
                                way.deleteTag("natural");
416
 
                                if (coastlineFilenames == null && precompSeaDir == null)
417
 
                                        shoreline.add(way);
418
 
                                
419
 
                                if (precompSeaDir != null) {
420
 
                                        // add a copy of this way to be able to draw the coastline which is not possible with precompiled sea
421
 
                                        Way coastlineWay = new Way(FakeIdGenerator.makeFakeId(), way.getPoints());
422
 
                                        coastlineWay.addTag("natural", "coastline");
423
 
                                        // tag that this way is used as line only
424
 
                                        coastlineWay.addTag(MultiPolygonRelation.STYLE_FILTER_TAG, MultiPolygonRelation.STYLE_FILTER_LINE);
425
 
                                        saver.addWay(coastlineWay);
 
417
                                if (precompSeaDir != null)
 
418
                                        splitCoastLineToLineAndShape(way, natural);
 
419
                                else {
 
420
                                        if (coastlineFilenames == null){
 
421
                                                way.deleteTag("natural");
 
422
                                                shoreline.add(way);
 
423
                                        }
426
424
                                }
427
425
                        } else if (natural.contains(";")) {
428
426
                                // cope with compound tag value
438
436
                                }
439
437
 
440
438
                                if(foundCoastline) {
441
 
                                        way.deleteTag("natural");
442
 
                                        if(others != null)
443
 
                                                way.addTag("natural", others);
444
 
                                        if (coastlineFilenames == null && precompSeaDir == null)
445
 
                                                shoreline.add(way);
446
 
                                        
447
 
                                        if (precompSeaDir != null) {
448
 
                                                // add a copy of this way to be able to draw the coastline which is not possible with precompiled sea
449
 
                                                Way coastlineWay = new Way(FakeIdGenerator.makeFakeId(), way.getPoints());
450
 
                                                coastlineWay.addTag("natural", "coastline");
451
 
                                                // tag that this way is used as line only
452
 
                                                coastlineWay.addTag(MultiPolygonRelation.STYLE_FILTER_TAG, MultiPolygonRelation.STYLE_FILTER_LINE);
453
 
                                                saver.addWay(coastlineWay);
 
439
                                        if (precompSeaDir != null)
 
440
                                                splitCoastLineToLineAndShape(way, natural);
 
441
                                        else { 
 
442
                                                if (coastlineFilenames == null){
 
443
                                                        way.deleteTag("natural");
 
444
                                                        if(others != null)
 
445
                                                                way.addTag("natural", others);
 
446
                                                        shoreline.add(way);
 
447
                                                }
454
448
                                        }
455
449
                                }
456
450
                        }
458
452
        }
459
453
 
460
454
        /**
 
455
         * With precompiled sea, we don't want to process all natural=coastline
 
456
         * ways as shapes without additional processing.   
 
457
         * This should avoid duplicate shapes for islands that are also in the 
 
458
         * precompiled data. 
 
459
         * @param way the OSM way with tag key natural 
 
460
         * @param naturalVal the tag value
 
461
         */
 
462
        private void splitCoastLineToLineAndShape(Way way, String naturalVal){
 
463
                if (precompSeaDir == null)
 
464
                        return;
 
465
                if (way.hasIdenticalEndPoints()){
 
466
                        // add a copy of this way to be able to draw it as a shape
 
467
                        Way shapeWay = new Way(FakeIdGenerator.makeFakeId(), way.getPoints());
 
468
                        // change the tag so that only special rules looking for it are firing
 
469
                        shapeWay.deleteTag("natural"); 
 
470
                        shapeWay.addTag("mkgmap:removed_natural",naturalVal); 
 
471
                        // tag that this way so that it is used as shape only
 
472
                        shapeWay.addTag(MultiPolygonRelation.STYLE_FILTER_TAG, MultiPolygonRelation.STYLE_FILTER_POLYGON);
 
473
                        saver.addWay(shapeWay);         
 
474
                }
 
475
                // make sure that the original (unchanged) way is not processed as a shape
 
476
                way.addTag(MultiPolygonRelation.STYLE_FILTER_TAG, MultiPolygonRelation.STYLE_FILTER_LINE);
 
477
        }
 
478
        
 
479
        /**
461
480
         * Creates a reader for the given filename of the precomiled sea tile.
462
481
         * @param filename precompiled sea tile 
463
482
         * @return the reader for the tile
688
707
                        
689
708
                        Area bounds = saver.getBoundingBox();
690
709
                        // first add the complete bounding box as sea
691
 
                        Way sea = new Way(FakeIdGenerator.makeFakeId());
692
 
                        sea.addPoint(new Coord(bounds.getMinLat(), bounds.getMinLong()));
693
 
                        sea.addPoint(new Coord(bounds.getMinLat(), bounds.getMaxLong()));
694
 
                        sea.addPoint(new Coord(bounds.getMaxLat(), bounds.getMaxLong()));
695
 
                        sea.addPoint(new Coord(bounds.getMaxLat(), bounds.getMinLong()));
696
 
                        sea.addPoint(new Coord(bounds.getMinLat(), bounds.getMinLong()));
 
710
                        Way sea = new Way(FakeIdGenerator.makeFakeId(),bounds.toCoords());
697
711
                        sea.addTag("natural", "sea");
698
712
                        
699
713
                        for (Way w : landWays) {
767
781
         */
768
782
        public static ArrayList<Way> joinWays(Collection<Way> segments) {
769
783
                ArrayList<Way> joined = new ArrayList<Way>((int)Math.ceil(segments.size()*0.5));
770
 
                Map<Coord, Way> beginMap = new HashMap<Coord, Way>();
 
784
                Map<Coord, Way> beginMap = new IdentityHashMap<Coord, Way>();
771
785
 
772
786
                for (Way w : segments) {
773
 
                        if (w.isClosed()) {
 
787
                        if (w.hasIdenticalEndPoints()) {
774
788
                                joined.add(w);
775
789
                        } else if (w.getPoints() != null && w.getPoints().size() > 1){
776
790
                                List<Coord> points = w.getPoints();
785
799
                while (merged > 0) {
786
800
                        merged = 0;
787
801
                        for (Way w1 : beginMap.values()) {
788
 
                                if (w1.isClosed()) {
 
802
                                if (w1.hasIdenticalEndPoints()) {
789
803
                                        // this should not happen
790
804
                                        log.error("joinWays2: Way "+w1+" is closed but contained in the begin map");
791
805
                                        joined.add(w1);
812
826
                                        beginMap.remove(points2.get(0));
813
827
                                        merged++;
814
828
                                        
815
 
                                        if (wm.isClosed()) {
 
829
                                        if (wm.hasIdenticalEndPoints()) {
816
830
                                                joined.add(wm);
817
831
                                                beginMap.remove(wm.getPoints().get(0));
818
832
                                        }
836
850
                        return;
837
851
                }
838
852
 
839
 
                Area seaBounds = saver.getBoundingBox();
 
853
                final Area seaBounds = saver.getBoundingBox();
840
854
                if (coastlineFilenames == null) {
841
855
                        log.info("Shorelines before join", shoreline.size());
842
856
                        shoreline = joinWays(shoreline);
849
863
                int closedS = 0;
850
864
                int unclosedS = 0;
851
865
                for (Way w : shoreline) {
852
 
                        if (w.isClosed()) {
 
866
                        if (w.hasIdenticalEndPoints()) {
853
867
                                closedS++;
854
868
                        } else {
855
869
                                unclosedS++;
878
892
                        // match the land colour on the tiles that do contain
879
893
                        // some sea
880
894
                        long landId = FakeIdGenerator.makeFakeId();
881
 
                        Way land = new Way(landId);
882
 
                        land.addPoint(nw);
883
 
                        land.addPoint(sw);
884
 
                        land.addPoint(se);
885
 
                        land.addPoint(ne);
886
 
                        land.addPoint(nw);
 
895
                        Way land = new Way(landId, seaBounds.toCoords());
887
896
                        land.addTag(landTag[0], landTag[1]);
888
897
                        // no matter if the multipolygon option is used it is
889
898
                        // only necessary to create a land polygon
970
979
                                        se.getLongitude() + 1));
971
980
                        sea.addPoint(new Coord(ne.getLatitude() - 1,
972
981
                                        ne.getLongitude() + 1));
973
 
                        sea.addPoint(new Coord(nw.getLatitude() - 1,
974
 
                                        nw.getLongitude() - 1));
 
982
                        sea.addPoint(sea.getPoints().get(0)); // close shape
975
983
                        sea.addTag("natural", "sea");
976
984
 
977
985
                        log.info("sea: ", sea);
987
995
                        // background colour will match the land colour on the
988
996
                        // tiles that do contain some sea
989
997
                        long landId = FakeIdGenerator.makeFakeId();
990
 
                        Way land = new Way(landId);
991
 
                        land.addPoint(nw);
992
 
                        land.addPoint(sw);
993
 
                        land.addPoint(se);
994
 
                        land.addPoint(ne);
995
 
                        land.addPoint(nw);
 
998
                        Way land = new Way(landId, seaBounds.toCoords());
996
999
                        land.addTag(landTag[0], landTag[1]);
997
1000
                        saver.addWay(land);
998
1001
                        if (generateSeaUsingMP) {
1056
1059
                Iterator<Way> it = shoreline.iterator();
1057
1060
                while (it.hasNext()) {
1058
1061
                        Way w = it.next();
1059
 
                        if (w.isClosed()) {
 
1062
                        if (w.hasIdenticalEndPoints()) {
1060
1063
                                log.info("adding island", w);
1061
1064
                                islands.add(w);
1062
1065
                                it.remove();
1068
1071
                it = shoreline.iterator();
1069
1072
                while (it.hasNext()) {
1070
1073
                        Way w = it.next();
1071
 
                        if (w.isClosed()) {
 
1074
                        if (w.hasIdenticalEndPoints()) {
1072
1075
                                log.debug("island after concatenating");
1073
1076
                                islands.add(w);
1074
1077
                                it.remove();
1132
1135
                                hit = hNext;
1133
1136
                        } while (!hits.isEmpty() && !hit.equals(hFirst));
1134
1137
 
1135
 
                        if (!w.isClosed())
1136
 
                                w.getPoints().add(w.getPoints().get(0));
 
1138
                        if (!w.hasIdenticalEndPoints())
 
1139
                                w.addPoint(w.getPoints().get(0)); // close shape
1137
1140
                        log.info("adding non-island landmass, hits.size()=" + hits.size());
1138
1141
                        islands.add(w);
1139
1142
                        shorelineReachesBoundary = true;
1157
1160
                                Way w1 = new Way(FakeIdGenerator.makeFakeId());
1158
1161
                                w1.getPoints().addAll(w.getPoints());
1159
1162
                                // only copy the name tags
1160
 
                                for(String tag : w)
1161
 
                                        if(tag.equals("name") || tag.endsWith(":name"))
1162
 
                                                w1.addTag(tag, w.getTag(tag));
 
1163
                                for (Entry<String, String> tagEntry : w.getTagEntryIterator()){
 
1164
                                        if(tagEntry.getKey().equals("name") || tagEntry.getKey().contains("name"))
 
1165
                                                w1.addTag(tagEntry.getKey(), tagEntry.getValue());
 
1166
                                }
1163
1167
                                w = w1;
1164
1168
                        }
1165
1169
 
1235
1239
                                                Way w1 = new Way(FakeIdGenerator.makeFakeId());
1236
1240
                                                w1.getPoints().addAll(w.getPoints());
1237
1241
                                                // only copy the name tags
1238
 
                                                for(String tag : w)
1239
 
                                                        if(tag.equals("name") || tag.endsWith(":name"))
1240
 
                                                                w1.addTag(tag, w.getTag(tag));
 
1242
                                                for (Entry<String, String> tagEntry : w.getTagEntryIterator()){
 
1243
                                                        if(tagEntry.getKey().equals("name") || tagEntry.getKey().contains("name"))
 
1244
                                                                w1.addTag(tagEntry.getKey(), tagEntry.getValue());
 
1245
                                                }
1241
1246
                                                w = w1;
1242
1247
                                        }
1243
1248
                                        w.addTag(landTag[0], landTag[1]);
1275
1280
                                        // show the coastline even though we can't produce
1276
1281
                                        // a polygon for the land
1277
1282
                                        w.addTag("natural", "coastline");
 
1283
                                        if (w.hasIdenticalEndPoints() == false){
 
1284
                                                log.error("adding sea shape that is not really closed");
 
1285
                                        }
1278
1286
                                        saver.addWay(w);
1279
1287
                                }
1280
1288
                        } else {
1424
1432
                        while (changed) {
1425
1433
                                changed = false;
1426
1434
                                for (Way w1 : ways) {
1427
 
                                        if(w1.isClosed())
 
1435
                                        if(w1.hasIdenticalEndPoints())
1428
1436
                                                continue;
1429
1437
                                        List<Coord> points1 = w1.getPoints();
1430
1438
                                        Coord w1e = points1.get(points1.size() - 1);
1433
1441
                                        Way nearest = null;
1434
1442
                                        double smallestGap = Double.MAX_VALUE;
1435
1443
                                        for (Way w2 : ways) {
1436
 
                                                if(w1 == w2 || w2.isClosed())
 
1444
                                                if(w1 == w2 || w2.hasIdenticalEndPoints())
1437
1445
                                                        continue;
1438
1446
                                                List<Coord> points2 = w2.getPoints();
1439
1447
                                                Coord w2s = points2.get(0);