Package com.eugeneborshch.routecalculator.optimize

Source Code of com.eugeneborshch.routecalculator.optimize.WayStartNodeFinder

package com.eugeneborshch.routecalculator.optimize;

import com.eugeneborshch.routecalculator.OsmEntityAttributeKey;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.index.IndexHits;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
* Search for the start node of the way.
* <p/>
* The idea is to find the start nodes algorithmically rather then updating Neo4j graph with special marks.
* <p/>
* User: Eugene Borshch
*/
public class WayStartNodeFinder {


    private GraphDatabaseService db;

    public WayStartNodeFinder(GraphDatabaseService db) {
        this.db = db;
    }

    public Node getStartNode(Long wayId) {

        IndexHits<Relationship> ways = db.index().forRelationships("ways").get(OsmEntityAttributeKey.WAY_ID.name(), wayId);
        while (ways.hasNext()) {
            Relationship relationship = ways.next();
            Iterator<Relationship> incoming = relationship.getStartNode().getRelationships(Direction.INCOMING).iterator();

            boolean isStartNode = true;
            while (incoming.hasNext()) {
                Relationship incomingRel = incoming.next();
                Long incomingWayId = (Long) incomingRel.getProperty(OsmEntityAttributeKey.WAY_ID.name());
                if (wayId.equals(incomingWayId)) {
                    isStartNode = false;
                    break;
                }
            }

            if (isStartNode) {
                return relationship.getStartNode();
            }
        }
        //Try roundabout
        return getStartNodeForRoundabout(db, wayId);
    }


    /**
     * In case of roundabout -> first node with degree of 3 would be taken as start node.
     */
    private Node getStartNodeForRoundabout(GraphDatabaseService db, Long wayId) {

        Set<Long> startNodes = new HashSet<Long>();
        Set<Long> endNodes = new HashSet<Long>();
        Node startNodeCandidate = null;
        boolean isRoundabout = false;

        IndexHits<Relationship> ways = db.index().forRelationships("ways").get(OsmEntityAttributeKey.WAY_ID.name(), wayId);
        while (ways.hasNext()) {
            Relationship relationship = ways.next();

            Node startNode = relationship.getStartNode();
            Node endNode = relationship.getEndNode();

            Long startNodeId = (Long) startNode.getProperty(OsmEntityAttributeKey.NODE_ID.name());
            Long endNodeId = (Long) endNode.getProperty(OsmEntityAttributeKey.NODE_ID.name());

            //put start\end nodes in cache
            startNodes.add(startNodeId);
            endNodes.add(endNodeId);

            //take the first node with degree > 2 as candidate for the start
            if (startNodeCandidate == null && getDegreeOf(startNode) > 2) {
                startNodeCandidate = startNode;
            } else if (startNodeCandidate == null && getDegreeOf(endNode) > 2) {
                startNodeCandidate = endNode;
            }

        }
        //check if we have a roundabout
        if (startNodes.containsAll(endNodes)) {
            isRoundabout = true;
        }


        return isRoundabout ? startNodeCandidate : null;
    }

    private int getDegreeOf(Node node) {

        int degree = 0;
        Iterable<Relationship> relationships = node.getRelationships();
        for (Relationship rel : relationships) {
            degree++;
        }
        return degree;
    }

}
TOP

Related Classes of com.eugeneborshch.routecalculator.optimize.WayStartNodeFinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.