CorePreparationHandler.java

/*  This file is part of Openrouteservice.
 *
 *  Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.

 *  This library 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 Lesser General Public License for more details.

 *  You should have received a copy of the GNU Lesser General Public License along with this library;
 *  if not, see <https://www.gnu.org/licenses/>.
 */
package org.heigit.ors.routing.graphhopper.extensions.core;

import com.graphhopper.routing.ch.CHPreparationHandler;
import com.graphhopper.routing.ch.PrepareContractionHierarchies;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.storage.CHConfig;
import com.graphhopper.storage.GraphHopperStorage;
import org.heigit.ors.routing.RoutingProfileCategory;
import org.heigit.ors.routing.graphhopper.extensions.GraphProcessContext;
import org.heigit.ors.routing.graphhopper.extensions.ORSGraphHopperConfig;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.EdgeFilterSequence;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.core.*;
import org.heigit.ors.routing.graphhopper.extensions.flagencoders.FlagEncoderNames;
import org.heigit.ors.routing.graphhopper.extensions.util.ORSParameters.Core;

/**
 * This class implements the Core Algo decorator and provides several helper methods related to core
 * preparation and its vehicle profiles.
 * <p>
 * This code is based on that from GraphHopper GmbH.
 *
 * @author Peter Karich
 * @author Hendrik Leuschner
 * @author Andrzej Oles
 */
public class CorePreparationHandler extends CHPreparationHandler {

    private GraphProcessContext processContext;

    public CorePreparationHandler() {
        super();
        PREPARE = Core.PREPARE;
        DISABLE = Core.DISABLE;
    }

    public void init(ORSGraphHopperConfig ghConfig) {
        setPreparationThreads(ghConfig.getInt(PREPARE + "threads", getPreparationThreads()));
        setCHProfiles(ghConfig.getCoreProfiles());
        pMap = ghConfig.asPMap();
    }

    @Override
    public void createPreparations(GraphHopperStorage ghStorage) {
        if (processContext == null)
            throw new IllegalStateException("Set processContext first!");
        super.createPreparations(ghStorage);
    }

    @Override
    protected PrepareContractionHierarchies createCHPreparation(GraphHopperStorage ghStorage, CHConfig chConfig) {
        EdgeFilter restrictionFilter = createCoreEdgeFilter(chConfig, ghStorage, processContext);
        PrepareContractionHierarchies pch = new PrepareCore(ghStorage, chConfig, restrictionFilter);
        pch.setParams(pMap);
        return pch;
    }

    public CorePreparationHandler setProcessContext(GraphProcessContext processContext) {
        this.processContext = processContext;
        return this;
    }

    private EdgeFilter createCoreEdgeFilter(CHConfig chProfile, GraphHopperStorage gs, GraphProcessContext processContext) {
        EncodingManager encodingManager = gs.getEncodingManager();

        int routingProfileCategory = RoutingProfileCategory.getFromEncoder(encodingManager);

        /* Initialize edge filter sequence */
        EdgeFilterSequence edgeFilterSequence = new EdgeFilterSequence();

        /* Heavy vehicle filter */
        if (encodingManager.hasEncoder(FlagEncoderNames.HEAVYVEHICLE)) {
            edgeFilterSequence.add(new HeavyVehicleCoreEdgeFilter(gs));
        }

        /* Avoid features */
        if ((routingProfileCategory & (RoutingProfileCategory.DRIVING | RoutingProfileCategory.CYCLING | RoutingProfileCategory.WALKING | RoutingProfileCategory.WHEELCHAIR)) != 0) {
            edgeFilterSequence.add(new AvoidFeaturesCoreEdgeFilter(gs, routingProfileCategory));
        }

        /* Avoid borders */
        if ((routingProfileCategory & (RoutingProfileCategory.DRIVING | RoutingProfileCategory.CYCLING)) != 0) {
            edgeFilterSequence.add(new AvoidBordersCoreEdgeFilter(gs));
        }

        if (routingProfileCategory == RoutingProfileCategory.WHEELCHAIR) {
            edgeFilterSequence.add(new WheelchairCoreEdgeFilter(gs));
        }

        /* Maximum speed & turn restrictions */
        if ((routingProfileCategory & RoutingProfileCategory.DRIVING) != 0) {
            String[] encoders = {FlagEncoderNames.CAR_ORS, FlagEncoderNames.HEAVYVEHICLE};
            for (String encoderName : encoders) {
                if (encodingManager.hasEncoder(encoderName)) {
                    FlagEncoder flagEncoder = encodingManager.getEncoder(encoderName);
                    edgeFilterSequence.add(new MaximumSpeedCoreEdgeFilter(flagEncoder, processContext.getMaximumSpeedLowerBound()));
                    if (chProfile.isEdgeBased() && flagEncoder.supportsTurnCosts())
                        edgeFilterSequence.add(new TurnRestrictionsCoreEdgeFilter(flagEncoder, gs));
                    break;
                }
            }
        }

        /* Conditional edges */
        if (TimeDependentCoreEdgeFilter.hasConditionals(encodingManager)) {
            edgeFilterSequence.add(new TimeDependentCoreEdgeFilter(gs));
        }

        if (TrafficSpeedCoreEdgeFilter.hasTrafficGraphStorage(gs)) {
            edgeFilterSequence.add(new TrafficSpeedCoreEdgeFilter(gs));
        }

        return edgeFilterSequence;
    }

}