Subversion Repositories display

Rev

Rev 324 | 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 uk.me.parabola.imgfmt.app.Coord;

import test.elements.Line;

import static test.util.ArcFlags.ARC_CLASSMASK;
import static test.util.ArcFlags.ARC_CURVE;
import static test.util.ArcFlags.ARC_HASNET;
import static test.util.ArcFlags.ARC_LEN;
import static test.util.ArcFlags.ARC_SIGN;
import static test.util.ArcFlags.ARC_UNK;

/**
 * An arc in the routing network.
 *
 * @author Steve Ratcliffe
 */

public class RouteArc {
    private final RouteNode node;
    private int alt6;

    private boolean longLink;
    private int link;
    private RouteNode linkNode;
    private Integer netOffset;
    private int roadClass;
    private boolean bad;
    private int rawDirection;
    private int index;
    private int rawDistance;
    private boolean hasDirection;
    private long offset;
    private Line line;
    private int linePos;
    private boolean last;
    private int localNet;
    private int speed;

    public RouteArc(RouteNode node) {
        this.node = node;
    }

    public void setAlt6(int alt6) {
        this.alt6 = alt6;
    }

    public boolean hasNet() {
        return (alt6 & ARC_HASNET) == 0x80;
    }

    public boolean isSign() {
        return (alt6 & ARC_SIGN) != 0;
    }
    public boolean isCurve() {
        return (alt6 & ARC_CURVE) != 0;
    }
    public int getAlt6Len() {
        return alt6 & ARC_LEN;
    }
    public boolean isAlt6Unk() {
        return (alt6 & ARC_UNK) != 0;
    }
    public int getDestclass() {
        return alt6 & ARC_CLASSMASK;
    }

    public String alt6String() {
        StringBuilder sb = new StringBuilder();
        if (hasNet())
            sb.append("net,");
        if (isSign())
            sb.append("sign,");
        if (isAlt6Unk())
            sb.append("unk,");
        sb.append(String.format("l%x,", getAlt6Len()));
        sb.append("dst");
        sb.append(getDestclass());
        return sb.toString();
    }

    public void setLongLink(boolean longLink) {
        this.longLink = longLink;
    }

    public boolean isLongLink() {
        return longLink;
    }

    public void setLink(int link) {
        this.link = link;
    }

    public int getLink() {
        return link;
    }

    public void setNetOffset(int netOffset) {
        this.netOffset = netOffset;
    }

    public Integer getNetOffset() {
        return netOffset;
    }

    public void setRoadClass(int thisClass) {
        this.roadClass = thisClass;
    }

    public int getRoadClass() {
        return roadClass;
    }

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

    public boolean isBad() {
        return bad;
    }

        /**
         * The initial bearing in file format.
         * @return An byte sized representation of the bearing. 256 is 360 degrees.
         */

    public int getRawDirection() {
        return rawDirection;
    }

    public void setRawDirection(int rawDirection) {
        hasDirection = true;
        this.rawDirection = rawDirection & 0xff;
    }

        /**
         * @return The initial bearing converted to degrees.
         * Can return null if there was no direction or it wasn't found. I don't think that this
         * can happen any more, since we should always read one now even if it is wrong.
         */

    public Double getDirection() {
        if (!hasDirection())
            return null;

        return directionToDegrees(rawDirection);
    }

        /**
         * Convert from the integer based direction to value in degrees.
         *
         * Note that if the bearing is stored as a 4-bit number then this is shifted up to the
         * top bits so that they are easily comparable with the 8-bit bearings.
         *
         * @param raw The value from the file.
         * @return Bearing in degrees.
         */

        public static double directionToDegrees(int raw) {
                double dir = (raw * 360) / 256;
                if (dir > 180)
                        dir -= 360;
                return dir;
        }

        public static int directionFromDegrees(double dir) {
                return (int) Math.round(dir * 256.0 / 360) & 0xff;
        }

        public RouteNode getNode() {
        return node;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }

    public void setRawDistance(int rawDistance) {
        this.rawDistance = rawDistance;
    }

    /**
     * @return The length in the form found in the file.
     */

    public int getRawDistance() {
        return rawDistance;
    }

    /**
     * @return Length of arc in meters.
     */

    public int getDistance() {
        return toMeters(rawDistance);
    }

    /**
     * Get a lower bound to the distance.
     * @return The distance in meters for the next lower raw distance value.
     */

    public int getDistanceLow() {
        return toMeters(rawDistance - 1);
    }

    /**
     * Get an upper bound to the real distance.
     * @return The arc length in meters for the next higher distance value.
     */

    public int getDistanceHigh() {
        return toMeters(rawDistance + 1);
    }

    /**
     * Convert from the internal representation to meters.
     * @param raw The internal length value.  Represents 16 feet.
     * @return Length of the arc in meters.
     */

    public static int toMeters(int raw) {
        return (int) (raw * 16 / 3.25);
    }

    public boolean hasDirection() {

        return hasDirection;
    }

    public void setOffset(long offset) {
        this.offset = offset;
    }

    public long getOffset() {
        return offset;
    }

    public void setLine(Line line) {
        this.line = line;
    }

    public Line getLine() {
        return line;
    }

    public void setLinePos(int linePos) {
        this.linePos = linePos;
    }

    public Double getActualInitialBearing() {
        if (line == null)
            return null;
        Coord co1 = line.getCoords().get(linePos);
        Coord co2 = line.getCoords().get(linePos + (isSign() ? 1 : -1));
        return co1.bearingTo(co2);
    }

    public void setLast(boolean last) {
        this.last = last;
    }

    public boolean isLast() {
        return last;
    }

    public void setLocalNet(int localNet) {
        this.localNet = localNet;
    }

    public int getLocalNet() {
        return localNet;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getSpeed() {
        return speed;
    }
}