class QueryGraph implements Graph {

    public boolean enforceHeading(int nodeId, double favoredHeading, boolean incoming) {
        if (Double.isNaN(favoredHeading))
            return false;

        if (!isVirtualNode(nodeId))
            return false;

        int virtNodeIDintern = nodeId - mainNodes;
        favoredHeading = AC.convertAzimuth2xaxisAngle(favoredHeading);

        // either penalize incoming or outgoing edges
        int[] edgePositions = incoming ? new int[]{VE_BASE, VE_ADJ_REV} : new int[]{VE_BASE_REV, VE_ADJ};
        boolean enforcementOccurred = false;
        for (int edgePos : edgePositions) {
            VirtualEdgeIteratorState edge = getVirtualEdge(virtNodeIDintern * 4 + edgePos);

            PointList wayGeo = edge.fetchWayGeometry(3);
            double edgeOrientation;
            if (incoming) {
                int numWayPoints = wayGeo.getSize();
                edgeOrientation = AC.calcOrientation(wayGeo.getLat(numWayPoints - 2), wayGeo.getLon(numWayPoints - 2),
                        wayGeo.getLat(numWayPoints - 1), wayGeo.getLon(numWayPoints - 1));
            } else {
                edgeOrientation = AC.calcOrientation(wayGeo.getLat(0), wayGeo.getLon(0),
                        wayGeo.getLat(1), wayGeo.getLon(1));
            }

            edgeOrientation = AC.alignOrientation(favoredHeading, edgeOrientation);
            double delta = (edgeOrientation - favoredHeading);

            if (Math.abs(delta) > 1.74) // penalize if a turn of more than 100°
            {
                edge.setUnfavored(true);
                unfavoredEdges.add(edge);
                //also apply to opposite edge for reverse routing
                VirtualEdgeIteratorState reverseEdge = getVirtualEdge(virtNodeIDintern * 4 + getPosOfReverseEdge(edgePos));
                reverseEdge.setUnfavored(true);
                unfavoredEdges.add(reverseEdge);
                enforcementOccurred = true;
            }

        }
        return enforcementOccurred;
    }

    private  QueryGraph(Graph graph, List<QueryResult> queryResults);
    private  QueryGraph(Graph graph, QueryGraph superQueryGraph);

}