Subversion Repositories display

Rev

Rev 410 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2014 Steve Ratcliffe
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * version 2 as published by the Free Software Foundation.
 *
 * This program 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 General Public License for more details.
 */

package test.files;

import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;

import uk.me.parabola.imgfmt.app.Coord;

import static test.util.ArcFlags.ARC_CLASSMASK;

/**
 * A node from NOD 1 of the routing network.
 *
 * Each node is in a group we call the RouteCenter. A node has zero or more arcs that lead to
 * other nodes.
 *
 * @author Steve Ratcliffe
 */

public class RouteNode {
    private final int offset;
    private final RouteCenter center;
    private int flags;
    private Coord coord;
    private final List<RouteArc> arcs = new ArrayList<>();
        private final List<RoadData> roads = new ArrayList<>();
        private List<RouteCenter.Restriction> restrictions;
    private boolean bad;
    private boolean problem;
    private long nextStart;

        // NET1 points to one entry in NOD2, which points to one node. If this is such a node, then
        // save the road here.
    private RoadData linkedRoad;
        private int nodeClass;

        private int[] classes = new int[5];
        private int classSet; // a bit set

        public RouteNode(RouteCenter center, long offset) {
        this.center = center;
        this.offset = (int) offset;
    }

    public int getOffset() {
        return offset;
    }

    public void setFlags(int flags) {
        this.flags = flags;
    }

    public int getFlags() {
        return flags;
    }

    public boolean hasArcs() {
        return (flags & 0x40) != 0;
    }

    public boolean hasLargeCoordOffsets() {
        return (flags & 0x20) != 0;
    }

    public boolean hasRestrictions() {
        return (flags & 0x10) != 0;
    }

    public boolean isBoundary() {
        return (flags & 0x08) != 0;
    }

    public void setCoord(Coord coord) {
        this.coord = coord;
    }

    public Coord getCoord() {
        return coord;
    }

    public void addArc(RouteArc arc) {
        arcs.add(arc);
    }

    public List<RouteArc> getArcs() {
        return arcs;
    }

    public String flagString() {
        StringBuilder sb = new StringBuilder();
        if (hasArcs())
            sb.append(" arcs");
        if (hasLargeCoordOffsets())
            sb.append(" big");
        if (hasRestrictions())
            sb.append(" restrictions");
        if (isBoundary())
            sb.append(" boundary");
        return sb.toString();
    }

    public void setBad(boolean bad) {
        this.bad = bad;
    }

    public boolean isBad() {
        return bad;
    }

    public RouteCenter getCenter() {
        return center;
    }

    public void setProblem(boolean problem) {
        this.problem = problem;
    }

    public boolean isProblem() {
        return problem;
    }

    public void setNextStart(long nextStart) {
        this.nextStart = nextStart;
    }

    public long getNextStart() {
        return nextStart;
    }

        public int getDestclass() {
                return flags & ARC_CLASSMASK;
        }

    public void setLinkedRoad(RoadData linkedRoad) {
        this.linkedRoad = linkedRoad;
    }

        /**
         * A road points (via NET1->NOD2) to exactly one node. If this is such a node, then the
         * road is recorded here. It is not particularly interesting.
         */

    public RoadData getLinkedRoad() {
        return linkedRoad;
    }

        public void updateDestClass(int roadClass) {
                classes[roadClass]++;
                classSet |= 1<<roadClass;
        }

        public void addRoad(RoadData road) {
                roads.add(road);
        }

        public List<RoadData> getRoads() {
                return roads;
        }

        public int getMinDestclass() {
                return Integer.numberOfTrailingZeros(classSet);
        }

        public int getMaxDestclass() {
                return 31 - Integer.numberOfLeadingZeros(classSet);
        }

        public boolean connectsToClass(int roadClass) {
                return classes[roadClass] > 0;
        }

        public String getClasses() {
                Formatter fmt = new Formatter();
                fmt.format("[");
                for (int c = 0; c < 5; c++) {
                        int n = classes[c];
                        if (n > 0) {
                                fmt.format("%d", c);
                                if (n > 1)
                                        fmt.format("(%d)", n);
                                fmt.format(",");
                        }
                }
                fmt.format("]");
                return fmt.toString();
        }

        public int getNodeClass() {
                return nodeClass;
        }

        public void setNodeClass(int nodeClass) {
                this.nodeClass = nodeClass;
        }

        public int most(int roadClass) {
                int f = classes[roadClass];
                if (f == 1) {
                        int higher = 0;
                        for (int c = roadClass + 1; c < 5; c++) {
                                higher += classes[c];
                        }

                        if (higher == 0) {
                                for (int c = 0; c < roadClass; c++) {
                                        if (classes[c] > 0)
                                                return c;
                                }
                        }
                }
                return roadClass;
        }

        public int findFirstCross() {
                int high = 0;
                for (int c = 1; c < 5; c++) {
                        high += classes[c];
                }
                if (high > 1) {
                        for (int c = 1; c < 5; c++) {
                                if (classes[c] > 0)
                                        return c;
                        }
                }
                return 0;
        }

        public int connectionsAtClass(int roadClass) {
                return classes[roadClass];
        }

        public int higherConnectionsCount(int roadClass) {
                int count = 0;
                for (int c = roadClass+1; c < 5; c++)
                        count += classes[c];
                return count;
        }

        public int nClasses() {
                return Integer.bitCount(classSet);
        }

        public void addRestriction(RouteCenter.Restriction restr) {
                if (restrictions == null)
                        restrictions = new ArrayList<>();
                restrictions.add(restr);
        }

        public List<RouteCenter.Restriction> getRestrictions() {
                return restrictions;
        }
}