No paths, main errors: [com.graphhopper.util.exceptions.PointNotFoundException: Cannot find point 0: 16.460901098063545,107.57018717529718, com.graphhopper.util.exceptions.PointNotFoundException: Cannot find point

Hello, I’m new of GrapHopper. Currently, I upgraded the version of the GrapHopper 0.9.0 to 7.0.0, so a lot of things changed. I was trying to build the profile for train. After several days, I still get the problem with drawing the railway shape.

My config.yml like that:

datareader.file: /Users/phamtai/sojo-project/graphhopper/vietosm/vietnam-latest.osm.pbf
graph.location: /Users/phamtai/sojo-project/graphhopper/traingdd
index.high_resolution: 300
index.max_region_search: 8
import.osm.ignored_highways:
graph.flag_encoders: train
graph.dataaccess: RAM_STORE
routing.instructions: true

TrainCommonParser

package com.axonvibe.vibe.transit.util.parsers;

import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.util.WayAccess;
import com.graphhopper.storage.IntsRef;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;

public class TrainCommonTagParser extends VibeTagParser {
    protected String[] railValues = {"rail", "narrow_gauge", "tram", "subway", "light_rail", "level_crossing"};
    protected String[] intendedValues = {"railway", "train"};

    public TrainCommonTagParser() {
    }

    public void handleWayTags(IntsRef var1, ReaderWay var2, IntsRef var3) {

    }

    public WayAccess getAccess(ReaderWay readerWay) {
        String railwayValue = readerWay.getTag("railway");

        if (StringUtils.isEmpty(railwayValue)) {
            if (readerWay.hasTag("route", intendedValues)) {
                return WayAccess.WAY;
            }
        } else {
            if (readerWay.hasTag("impassable", "yes") || readerWay.hasTag("status", "impassable")) {
                return WayAccess.CAN_SKIP;
            }

            if (Arrays.asList(railValues).contains(railwayValue)) {
                return WayAccess.WAY;
            }
        }

        return WayAccess.CAN_SKIP;
    }

}

TrainAccessParser

package com.axonvibe.vibe.transit.util.parsers.access;

import com.axonvibe.vibe.transit.util.parsers.TrainCommonTagParser;
import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.ev.BooleanEncodedValue;
import com.graphhopper.routing.ev.EncodedValueLookup;
import com.graphhopper.routing.ev.Roundabout;
import com.graphhopper.routing.ev.VehicleAccess;
import com.graphhopper.routing.util.WayAccess;
import com.graphhopper.storage.IntsRef;
import com.graphhopper.util.PMap;

public class TrainAccessParser extends TrainCommonTagParser {
    protected final BooleanEncodedValue roundaboutEnc;
    protected final BooleanEncodedValue accessEnc;

    public TrainAccessParser(EncodedValueLookup lookup, PMap properties) {
        this(
                lookup.getBooleanEncodedValue(VehicleAccess.key(properties.getString("name", "train"))),
                lookup.getBooleanEncodedValue(Roundabout.KEY)
        );
    }

    public TrainAccessParser(BooleanEncodedValue accessEnc, BooleanEncodedValue roundaboutEnc) {
        super();
        this.accessEnc = accessEnc;
        this.roundaboutEnc = roundaboutEnc;
    }

    @Override
    public void handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, IntsRef relationFlags) {
        this.handleWayTags(edgeFlags, readerWay);
    }

    public void handleWayTags(IntsRef edgeFlags, ReaderWay readerWay) {
        WayAccess wayAccess = getAccess(readerWay);

        if (!wayAccess.canSkip()) {
            accessEnc.setBool(false, edgeFlags, true);
            accessEnc.setBool(true, edgeFlags, true);
        }

    }
}

AverageSpeedParser

package com.axonvibe.vibe.transit.util.parsers.speed;

import com.axonvibe.vibe.transit.util.parsers.TrainCommonTagParser;
import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.ev.DecimalEncodedValue;
import com.graphhopper.routing.ev.EncodedValueLookup;
import com.graphhopper.routing.ev.VehicleSpeed;
import com.graphhopper.routing.util.WayAccess;
import com.graphhopper.storage.IntsRef;
import com.graphhopper.util.PMap;
import org.apache.commons.lang3.StringUtils;

public class TrainAverageSpeedParser extends TrainCommonTagParser {
    public static final double TRAIN_MAX_SPEED = 120.0;
    private final DecimalEncodedValue avgSpeedEnc;
    private final double maxPossibleSpeed;

    public TrainAverageSpeedParser(EncodedValueLookup lookup, PMap properties) {
        this(lookup.getDecimalEncodedValue(VehicleSpeed.key(properties.getString("name", "train"))));
    }

    public TrainAverageSpeedParser(DecimalEncodedValue avgSpeedEnc) {
        super();
        this.avgSpeedEnc = avgSpeedEnc;
        this.maxPossibleSpeed = this.avgSpeedEnc.getNextStorableValue(TRAIN_MAX_SPEED);
    }

    public void handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationFlags) {
        WayAccess wayAccess = getAccess(way);
        double speed = 1.0;

        if (WayAccess.WAY.equals(wayAccess)) {
            String maxSpeed = way.getTag("maxspeed");
            String railwayValue = way.getTag("railway");

            if (railwayValue != null) {
                switch (railwayValue) {
                    case "rail":
                        speed = 50.0D;
                        break;
                    case "tram":
                        speed = 20.0D;
                        break;
                    case "narrow_gauge":
                        speed = 30.0D;
                        break;
                    case "subway":
                        speed = 20.0D;
                        break;
                }
            }

            if (!StringUtils.isEmpty(maxSpeed)) {
                try {
                    speed = Double.parseDouble(maxSpeed);
                } catch (NumberFormatException nfe) {
                    speed = 10.0; //everything else failed, so we just pick 35kph
                }
            }
        }

        if (!wayAccess.canSkip()) {
            this.avgSpeedEnc.setDecimal(false, edgeFlags, speed);
            this.avgSpeedEnc.setDecimal(true, edgeFlags, speed);
        }


    }
}

PriorityParser

package com.axonvibe.vibe.transit.util.parsers.priority;

import com.axonvibe.vibe.transit.util.parsers.TrainCommonTagParser;
import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.ev.DecimalEncodedValue;
import com.graphhopper.routing.ev.EncodedValueLookup;
import com.graphhopper.routing.ev.VehiclePriority;
import com.graphhopper.routing.util.PriorityCode;
import com.graphhopper.routing.util.WayAccess;
import com.graphhopper.storage.IntsRef;
import com.graphhopper.util.PMap;

public class TrainPriorityParser extends TrainCommonTagParser {
    protected final DecimalEncodedValue priorityEnc;

    public TrainPriorityParser(EncodedValueLookup lookup, PMap properties) {
        this(lookup.getDecimalEncodedValue(VehiclePriority.key(properties.getString("name", "train"))));
    }

    public TrainPriorityParser(DecimalEncodedValue priorityEnc) {
        super();
        this.priorityEnc = priorityEnc;
    }

    @Override
    public void handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationFlags) {
        Integer priorityFromRelation;
        WayAccess wayAccess = getAccess(way);

        switch (wayAccess) {
            case WAY -> {
                priorityFromRelation = PriorityCode.BEST.getValue();
            }
            case OTHER -> {
                priorityFromRelation = PriorityCode.SLIGHT_PREFER.getValue();
            }
            default -> {
                priorityFromRelation = PriorityCode.REACH_DESTINATION.getValue();
            }
        }

        if (!wayAccess.canSkip()) {
            priorityEnc.setDecimal(false, edgeFlags, priorityFromRelation);
            priorityEnc.setDecimal(true, edgeFlags, priorityFromRelation);
        }
    }

}

VehicleEncodedValues

public static VehicleEncodedValues train(PMap properties) {
        String name = properties.getString("name", "train");
        int speedBits = properties.getInt("speed_bits", 7);
        double speedFactor = properties.getDouble("speed_factor", 1.0);
        int maxTurnCosts = properties.getInt("max_turn_costs", 1);
        BooleanEncodedValue accessEnc = VehicleAccess.create(name);
        DecimalEncodedValue speedEnc = VehicleSpeed.create(name, speedBits, speedFactor, true);
        DecimalEncodedValue priorityEnc = VehiclePriority.create(name, 7, speedFactor, true);
        DecimalEncodedValue turnCostEnc = TurnCost.create(name, maxTurnCosts);

        return new VehicleEncodedValues(name, accessEnc, speedEnc, priorityEnc, turnCostEnc);
    }

My initing GrapHopper code

ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        ResourceLoader resourceLoader = new DefaultResourceLoader();

        GraphHopperConfig graphHopperConfig = objectMapper.readValue(resourceLoader.getResource("classpath:config.yml").getInputStream(), GraphHopperConfig.class);
        List<Profile> profiles = buildProfiles();

        graphHopperConfig.setProfiles(profiles);
        graphHopperConfig.setCHProfiles(buildCHProfiles(profiles));

        graphHopper = new GraphHopper().init(graphHopperConfig);
        graphHopper.setMinNetworkSize(0);
        graphHopper.setEncodedValuesString("road_class,surface,road_environment,max_speed,max_width,max_height");
        graphHopper.setVehicleTagParserFactory(new VibeVehicleTagParsersFactory());
        graphHopper.setVehicleEncodedValuesFactory(new VibeVehicleEncodedValuesFactory());
        graphHopper.importOrLoad();

Can any experts take care it? Thanks so much! :pray:

What is the problem you are running into?

I got the problem Do you want live notifications when people reply to your posts? Enable Notifications​

[No paths, main errors: com.graphhopper.util.exceptions.PointNotFoundException: Cannot find point 0: 16.460901098063545,107.57018717529718, com.graphhopper.util.exceptions.PointNotFoundException: Cannot find point When I want to draw trhe train shape between 16.460901098063545,107.57018717529718 to another point. Do you have the standard model for it?

Try this:

      hopper.importOrLoad();
      Snap snap = hopper.getLocationIndex().findClosest(16.460901098063545, 107.57018717529718, EdgeFilter.ALL_EDGES);
      System.out.println(snap.toString());
      System.out.println(snap.isValid());
      System.out.println(snap.getQueryPoint());
      System.out.println(snap.getSnappedPosition());
      System.out.println(snap.getSnappedPoint());
      System.out.println(snap.getQueryDistance());
      System.out.println(snap.getClosestEdge());
      System.out.println(snap.getClosestNode());

What happens? Also use a debugger to step through the findClosest call to find out what happens. You can also use the maps client and enable the routing graph layer to see if there are any edges near your point.

1 Like

I know why we couldn’t draw the shape for railway. In OSMParsers of GrapHopper 7.0 contains logic to filter out the way which have no highway tag, and only accepts platform railway value. I don’t know why they put this logic into OSMParsers. It is so weird. acceptWay(Readerway way).

Yes, that is correct. railways are filtered out at an early stage, because so far GraphHopper is mostly geared towards routing on the road network. OSMParsers and OSMReader can be seen as specific for road networks. WaySegmentParser offers a lower level API, though. Take a look here: Extract WaySegmentParser from OSMReader by easbar · Pull Request #2448 · graphhopper/graphhopper · GitHub where we also mentioned a low-level implementation for a water way router.

Quite possibly the acceptWay method (which is specific for road networks) could be moved from OSMParsers to OSMReader, though. Feel free to open a pull request on Github if you have a good idea how to make the code better suitable for railway routing.

Yeah, I’m trying to create the pull request to update the OSMParser. My idea:

  • Allowing customizing the acceptedRailways by adding this value into config.yml. Not hard code like the current. Now, we only accept the “platform”.
  • Still keep the platform as the default value of the accepted railway list. This step is used to avoid error of new version.

But, I’m newbie of GrapHopper. Could you give me the permission of contributor to create new pull request? My email: phamphutaitrainer@gmail.com . Thanks!

I’m not sure if this justifies a new entry in the config file, because for railway routing changes in Java are necessary anyway. I’d be more looking for changes in the Java code that make it easier to adjust.

You don’t need extra permission to open a pull request. You can just fork the repository and open a PR upstream: Creating a pull request from a fork - GitHub Docs

I actually do think that adding accepted railway values by configuration is more flexible. It is so quickly if we just change Java code. Ha ha :smiley:

Here is my pull request: Extend railway OSM Parsers by kanephamphu · Pull Request #2797 · graphhopper/graphhopper · GitHub

Pls help me look over!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.