Rev 384 |
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 test.display.check.Log;
import uk.me.parabola.imgfmt.app.Coord;
import static test.util.ArcFlags.*;
/**
* An arc in the routing network.
*
* @author Steve Ratcliffe
*/
public class RouteArc
{
private int offset
; // Offset in the file section
private final RouteNode node
; // The associated start node.
private int alt6
;
private boolean longLink
;
private int link
;
private boolean bad
;
private int direction
;
private int index
;
private int distance
;
private boolean hasDirection
;
private boolean last
;
private int localNet
;
// This is the extra distance from the last arc
private int partialDistance
;
private int curveA
;
private int curveB
;
private RouteCenter.
TableA tableA
;
private RoadData road
;
private RouteNode targetNode
;
private boolean hasCurve
;
public RouteArc
(RouteNode node
) {
this.
node = node
;
}
public void setAlt6
(int alt6
) {
this.
alt6 = alt6
;
}
public boolean newNet
() {
return (alt6
& ARC_HASNET
) == 0x80
;
}
public boolean isSign
() {
return (alt6
& ARC_SIGN
) !=
0;
}
public boolean hasCurve
() {
return hasCurve
;
}
public int getAlt6Len
() {
return alt6
& ARC_LEN
;
}
public int getDestclass
() {
return alt6
& ARC_CLASSMASK
;
}
public String alt6String
() {
StringBuilder sb =
new StringBuilder();
if (newNet
())
sb.
append("new,");
else
sb.
append("cont,");
if (isSign
())
sb.
append("sign,");
if (hasCurve
())
sb.
append("curve,");
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 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 getDirection
() {
return direction
;
}
public void setDirection
(int direction
) {
hasDirection =
true;
this.
direction = direction
& 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 getInitialDegrees
() {
if (!hasDirection
())
return null;
return directionToDegrees
(direction
);
}
/**
* 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 setDistance
(int distance
) {
this.
distance = distance
;
}
/**
* @return The length in file units.
*/
public int getDistance
() {
return distance
;
}
public boolean hasDirection
() {
return hasDirection
;
}
public void setOffset
(long offset
) {
this.
offset =
(int) offset
;
}
public long getOffset
() {
return offset
;
}
public Double getActualInitialBearing
() {
Coord co1 = node.
getCoord();
CoordLocator loc = road.
locateNode(node
);
if (loc ==
null) return null;
loc = road.
nextCoord(loc, isSign
());
Coord co2 = loc.
getCoord();
if (co1.
distance(co2
) < Math.
min(10, co1.
distance(targetNode.
getCoord())/
50) +
11
&& targetNode.
getCoord().
distance(co2
) > 20) {
// We need the initial bearing of the road. However this may not be very
// well represented in the file.
//
// If the first segment is long, then the initial bearing will lie along that
// segment. If however it is a very short segment, then it may well not be. In
// this case we look at the next segment and use that as a perhaps better approximation.
// An even better approximation might be to work out the bearing at about 30-40m
// along the road.
//
// If the first coord is near the target already then use it.
loc = road.
nextCoord(loc, isSign
());
if (loc
!=
null)
co2 = loc.
getCoord();
}
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 setTableA
(RouteCenter.
TableA tableA
) {
this.
tableA = tableA
;
}
public Integer getNetOffset
() {
return tableA.
getNetOffset();
}
public int getRoadClass
() {
return tableA.
getRoadClass();
}
public int getSpeed
() {
return tableA.
getSpeed();
}
public int getAccess
() {
return tableA.
getAccess();
}
public boolean isOneway
() {
return tableA.
isOneway();
}
public void setPartialDistance
(int partialDistance
) {
this.
partialDistance = partialDistance
;
}
public int getPartialDistance
() {
return partialDistance
;
}
public void setCurveA
(int curveA
) {
this.
curveA = curveA
;
hasCurve =
true;
}
public int getCurveA
() {
return curveA
;
}
public void setCurveB
(int curveB
) {
this.
curveB = curveB
;
}
public int getCurveB
() {
return curveB
;
}
public int getCurveDirection
() {
if ((curveA
& 0xe0
) ==
0)
return curveB
;
else
return (curveA
& 0x1f
) << 3;
}
public void setRoad
(RoadData road
) {
this.
road = road
;
}
public RoadData getRoad
() {
return road
;
}
public void setTargetNode
(RouteNode targetNode
) {
this.
targetNode = targetNode
;
}
public RouteNode getTargetNode
() {
return targetNode
;
}
}