20
20
import com .graphhopper .config .CHProfile ;
21
21
import com .graphhopper .config .LMProfile ;
22
22
import com .graphhopper .config .Profile ;
23
- import com .graphhopper .reader .DataReader ;
24
23
import com .graphhopper .reader .dem .*;
24
+ import com .graphhopper .reader .osm .OSMReader ;
25
25
import com .graphhopper .reader .osm .conditional .DateRangeParser ;
26
26
import com .graphhopper .routing .DefaultWeightingFactory ;
27
27
import com .graphhopper .routing .Router ;
35
35
import com .graphhopper .routing .lm .LMConfig ;
36
36
import com .graphhopper .routing .lm .LMPreparationHandler ;
37
37
import com .graphhopper .routing .lm .LandmarkStorage ;
38
+ import com .graphhopper .routing .lm .PrepareLandmarks ;
38
39
import com .graphhopper .routing .subnetwork .PrepareRoutingSubnetworks ;
39
40
import com .graphhopper .routing .subnetwork .PrepareRoutingSubnetworks .PrepareJob ;
40
41
import com .graphhopper .routing .util .DefaultFlagEncoderFactory ;
43
44
import com .graphhopper .routing .util .FlagEncoderFactory ;
44
45
import com .graphhopper .routing .util .parsers .DefaultTagParserFactory ;
45
46
import com .graphhopper .routing .util .parsers .TagParserFactory ;
47
+ import com .graphhopper .routing .util .spatialrules .AbstractSpatialRule ;
48
+ import com .graphhopper .routing .util .spatialrules .SpatialRuleLookup ;
49
+ import com .graphhopper .routing .util .spatialrules .SpatialRuleLookupBuilder ;
46
50
import com .graphhopper .routing .weighting .DefaultTurnCostProvider ;
47
51
import com .graphhopper .routing .weighting .TurnCostProvider ;
48
52
import com .graphhopper .routing .weighting .Weighting ;
@@ -101,13 +105,15 @@ public class GraphHopper implements GraphHopperAPI {
101
105
private int maxRegionSearch = 4 ;
102
106
// for prepare
103
107
private int minNetworkSize = 200 ;
108
+ // for LM
109
+ private final JsonFeatureCollection landmarkSplittingFeatureCollection ;
104
110
105
111
// preparation handlers
106
112
private final LMPreparationHandler lmPreparationHandler = new LMPreparationHandler ();
107
113
private final CHPreparationHandler chPreparationHandler = new CHPreparationHandler ();
108
114
109
115
// for data reader
110
- private String dataReaderFile ;
116
+ private String osmFile ;
111
117
private double dataReaderWayPointMaxDistance = 1 ;
112
118
private int dataReaderWorkerThreads = 2 ;
113
119
private ElevationProvider eleProvider = ElevationProvider .NOOP ;
@@ -117,6 +123,11 @@ public class GraphHopper implements GraphHopperAPI {
117
123
private PathDetailsBuilderFactory pathBuilderFactory = new PathDetailsBuilderFactory ();
118
124
119
125
public GraphHopper () {
126
+ this (null );
127
+ }
128
+
129
+ public GraphHopper (JsonFeatureCollection landmarkSplittingFeatureCollection ) {
130
+ this .landmarkSplittingFeatureCollection = landmarkSplittingFeatureCollection ;
120
131
}
121
132
122
133
/**
@@ -322,19 +333,19 @@ public GraphHopper setGraphHopperLocation(String ghLocation) {
322
333
}
323
334
324
335
public String getDataReaderFile () {
325
- return dataReaderFile ;
336
+ return osmFile ;
326
337
}
327
338
328
339
/**
329
- * This file can be any file type supported by the DataReader. E.g. for the OSMReader it is the
330
- * OSM xml (.osm), a compressed xml (.osm.zip or .osm.gz) or a protobuf file (. pbf)
340
+ * This file can be an osm xml (.osm), a compressed xml (.osm.zip or .osm.gz) or a protobuf file
341
+ * (. pbf).
331
342
*/
332
- public GraphHopper setDataReaderFile (String dataReaderFileStr ) {
343
+ public GraphHopper setDataReaderFile (String osmFile ) {
333
344
ensureNotLoaded ();
334
- if (isEmpty (dataReaderFileStr ))
335
- throw new IllegalArgumentException ("Data reader file cannot be empty." );
345
+ if (isEmpty (osmFile ))
346
+ throw new IllegalArgumentException ("OSM file cannot be empty." );
336
347
337
- dataReaderFile = dataReaderFileStr ;
348
+ this . osmFile = osmFile ;
338
349
return this ;
339
350
}
340
351
@@ -430,14 +441,14 @@ public GraphHopper init(GraphHopperConfig ghConfig) {
430
441
431
442
String tmpOsmFile = ghConfig .getString ("datareader.file" , "" );
432
443
if (!isEmpty (tmpOsmFile ))
433
- dataReaderFile = tmpOsmFile ;
444
+ osmFile = tmpOsmFile ;
434
445
435
446
String graphHopperFolder = ghConfig .getString ("graph.location" , "" );
436
447
if (isEmpty (graphHopperFolder ) && isEmpty (ghLocation )) {
437
- if (isEmpty (dataReaderFile ))
448
+ if (isEmpty (osmFile ))
438
449
throw new IllegalArgumentException ("If no graph.location is provided you need to specify an OSM file." );
439
450
440
- graphHopperFolder = pruneFileEnd (dataReaderFile ) + "-gh" ;
451
+ graphHopperFolder = pruneFileEnd (osmFile ) + "-gh" ;
441
452
}
442
453
443
454
// graph
@@ -604,72 +615,59 @@ public void importAndClose() {
604
615
/**
605
616
* Creates the graph from OSM data.
606
617
*/
607
- private GraphHopper process (String graphHopperLocation , boolean closeEarly ) {
618
+ private void process (String graphHopperLocation , boolean closeEarly ) {
608
619
setGraphHopperLocation (graphHopperLocation );
609
620
GHLock lock = null ;
610
621
try {
622
+ if (ghStorage == null )
623
+ throw new IllegalStateException ("GraphHopperStorage must be initialized before starting the import" );
611
624
if (ghStorage .getDirectory ().getDefaultType ().isStoring ()) {
612
625
lockFactory .setLockDir (new File (graphHopperLocation ));
613
626
lock = lockFactory .create (fileLockName , true );
614
627
if (!lock .tryLock ())
615
628
throw new RuntimeException ("To avoid multiple writers we need to obtain a write lock but it failed. In " + graphHopperLocation , lock .getObtainFailedReason ());
616
629
}
617
-
618
- readData ();
630
+ ensureWriteAccess ();
631
+ importOSM ();
619
632
cleanUp ();
620
633
postProcessing (closeEarly );
621
634
flush ();
622
635
} finally {
623
636
if (lock != null )
624
637
lock .release ();
625
638
}
626
- return this ;
627
- }
628
-
629
- private void readData () {
630
- try {
631
- DataReader reader = importData ();
632
- DateFormat f = createFormatter ();
633
- ghStorage .getProperties ().put ("datareader.import.date" , f .format (new Date ()));
634
- if (reader .getDataDate () != null )
635
- ghStorage .getProperties ().put ("datareader.data.date" , f .format (reader .getDataDate ()));
636
- } catch (IOException ex ) {
637
- throw new RuntimeException ("Cannot read file " + getDataReaderFile (), ex );
638
- }
639
639
}
640
640
641
- protected DataReader importData () throws IOException {
642
- ensureWriteAccess ();
643
- if (ghStorage == null )
644
- throw new IllegalStateException ("Load graph before importing OSM data" );
645
-
646
- if (dataReaderFile == null )
641
+ protected void importOSM () {
642
+ if (osmFile == null )
647
643
throw new IllegalStateException ("Couldn't load from existing folder: " + ghLocation
648
644
+ " but also cannot use file for DataReader as it wasn't specified!" );
649
645
650
- DataReader reader = createReader (ghStorage );
651
- logger .info ("using " + ghStorage .toString () + ", memory:" + getMemInfo ());
652
- reader .readGraph ();
653
- return reader ;
654
- }
655
-
656
- protected DataReader createReader (GraphHopperStorage ghStorage ) {
657
- throw new UnsupportedOperationException ("Cannot create DataReader. Solutions: avoid import via calling load directly, "
658
- + "provide a DataReader or use e.g. GraphHopperOSM or a different subclass" );
659
- }
660
-
661
- protected DataReader initDataReader (DataReader reader ) {
662
- if (dataReaderFile == null )
663
- throw new IllegalArgumentException ("No file for DataReader specified" );
664
-
665
- logger .info ("start creating graph from " + dataReaderFile );
666
- return reader .setFile (new File (dataReaderFile )).
646
+ logger .info ("start creating graph from " + osmFile );
647
+ OSMReader reader = new OSMReader (ghStorage ).setFile (_getOSMFile ()).
667
648
setElevationProvider (eleProvider ).
668
649
setWorkerThreads (dataReaderWorkerThreads ).
669
650
setWayPointMaxDistance (dataReaderWayPointMaxDistance ).
670
651
setWayPointElevationMaxDistance (routerConfig .getElevationWayPointMaxDistance ()).
671
652
setSmoothElevation (smoothElevation ).
672
653
setLongEdgeSamplingDistance (longEdgeSamplingDistance );
654
+ logger .info ("using " + ghStorage .toString () + ", memory:" + getMemInfo ());
655
+ try {
656
+ reader .readGraph ();
657
+ } catch (IOException ex ) {
658
+ throw new RuntimeException ("Cannot read file " + getDataReaderFile (), ex );
659
+ }
660
+ DateFormat f = createFormatter ();
661
+ ghStorage .getProperties ().put ("datareader.import.date" , f .format (new Date ()));
662
+ if (reader .getDataDate () != null )
663
+ ghStorage .getProperties ().put ("datareader.data.date" , f .format (reader .getDataDate ()));
664
+ }
665
+
666
+ /**
667
+ * Currently we use this for a few tests where the dataReaderFile is loaded from the classpath
668
+ */
669
+ protected File _getOSMFile () {
670
+ return new File (osmFile );
673
671
}
674
672
675
673
/**
@@ -1045,23 +1043,41 @@ protected void prepareCH(boolean closeEarly) {
1045
1043
* For landmarks it is required to always call this method: either it creates the landmark data or it loads it.
1046
1044
*/
1047
1045
protected void loadOrPrepareLM (boolean closeEarly ) {
1048
- boolean tmpPrepare = lmPreparationHandler .isEnabled () && !lmPreparationHandler .getPreparations ().isEmpty ();
1049
- if (tmpPrepare ) {
1050
- for (LMProfile profile : lmPreparationHandler .getLMProfiles ()) {
1051
- if (!getProfileVersion (profile .getProfile ()).isEmpty ()
1052
- && !getProfileVersion (profile .getProfile ()).equals ("" + profilesByName .get (profile .getProfile ()).getVersion ()))
1053
- throw new IllegalArgumentException ("LM preparation of " + profile .getProfile () + " already exists in storage and doesn't match configuration" );
1054
- }
1055
- ensureWriteAccess ();
1056
- ghStorage .freeze ();
1057
- if (lmPreparationHandler .loadOrDoWork (ghStorage .getProperties (), closeEarly )) {
1058
- ghStorage .getProperties ().put (Landmark .PREPARE + "done" , true );
1059
- for (LMProfile profile : lmPreparationHandler .getLMProfiles ()) {
1060
- // potentially overwrite existing keys from CH
1061
- setProfileVersion (profile .getProfile (), profilesByName .get (profile .getProfile ()).getVersion ());
1046
+ if (!lmPreparationHandler .isEnabled () || lmPreparationHandler .getPreparations ().isEmpty ()) {
1047
+ return ;
1048
+ }
1049
+
1050
+ if (landmarkSplittingFeatureCollection != null && !landmarkSplittingFeatureCollection .getFeatures ().isEmpty ()) {
1051
+ SpatialRuleLookup ruleLookup = SpatialRuleLookupBuilder .buildIndex (
1052
+ Collections .singletonList (landmarkSplittingFeatureCollection ), "area" ,
1053
+ (id , polygons ) -> new AbstractSpatialRule (polygons ) {
1054
+ @ Override
1055
+ public String getId () {
1056
+ return id ;
1057
+ }
1058
+ });
1059
+ for (PrepareLandmarks prep : getLMPreparationHandler ().getPreparations ()) {
1060
+ // the ruleLookup splits certain areas from each other but avoids making this a permanent change so that other algorithms still can route through these regions.
1061
+ if (ruleLookup != null && !ruleLookup .getRules ().isEmpty ()) {
1062
+ prep .setSpatialRuleLookup (ruleLookup );
1062
1063
}
1063
1064
}
1064
1065
}
1066
+
1067
+ for (LMProfile profile : lmPreparationHandler .getLMProfiles ()) {
1068
+ if (!getProfileVersion (profile .getProfile ()).isEmpty ()
1069
+ && !getProfileVersion (profile .getProfile ()).equals ("" + profilesByName .get (profile .getProfile ()).getVersion ()))
1070
+ throw new IllegalArgumentException ("LM preparation of " + profile .getProfile () + " already exists in storage and doesn't match configuration" );
1071
+ }
1072
+ ensureWriteAccess ();
1073
+ ghStorage .freeze ();
1074
+ if (lmPreparationHandler .loadOrDoWork (ghStorage .getProperties (), closeEarly )) {
1075
+ ghStorage .getProperties ().put (Landmark .PREPARE + "done" , true );
1076
+ for (LMProfile profile : lmPreparationHandler .getLMProfiles ()) {
1077
+ // potentially overwrite existing keys from CH
1078
+ setProfileVersion (profile .getProfile (), profilesByName .get (profile .getProfile ()).getVersion ());
1079
+ }
1080
+ }
1065
1081
}
1066
1082
1067
1083
/**
0 commit comments