/*
* Copyright (C) 2008 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 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.
*
*
* Author: Steve Ratcliffe
* Create date: 04-Aug-2008
*/
package uk.me.parabola.mkgmap.reader.polish;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.imgfmt.app.CoordNode;
import uk.me.parabola.imgfmt.app.net.AccessTagsAndBits;
import uk.me.parabola.imgfmt.app.net.NumberStyle;
import uk.me.parabola.imgfmt.app.net.Numbers;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.mkgmap.general.MapRoad;
/**
* Used to remember all the road relevant parameters in a definition which
* can occur in any order. Also remembers routing nodes and makes sure
* the generated MapRoads all have the same RoutingNode objects.
*
* Use one instance of RoadHelper per file, and reset after reading
* each road.
*/
class RoadHelper
{
private static final Logger log =
Logger.
getLogger(RoadHelper.
class);
// routing node store, persistent over resets
private final Map<Long, CoordNode
> nodeCoords =
new HashMap<>();
private int roadId
;
private final List<NodeIndex
> nodes =
new ArrayList<>();
private int speed
;
private int roadClass
;
private boolean oneway
;
private boolean toll
;
private byte mkgmapAccess
;
private List<Numbers
> numbers
;
public RoadHelper
() {
clear
();
}
public void clear
() {
roadId =
0;
nodes.
clear();
speed =
0;
roadClass =
0;
oneway =
false;
toll =
false;
numbers =
null;
}
public void setRoadId
(int roadId
) {
this.
roadId = roadId
;
}
public void addNode
(String value
) {
String[] f = value.
split(",");
nodes.
add(new NodeIndex
(f
));
}
/**
* @param param cgpsmapper manual:
* RouteParam=speed,road_class,one_way,toll,
* denied_emergency,denied_delivery,denied_car,denied_bus,denied_taxi,denied_pedestrain,denied_bicycle,denied_truck
*/
public void setParam
(String param
) {
String[] f = param.
split(",");
speed =
Integer.
parseInt(f
[0]);
if (speed
< 0)
speed =
0;
if (speed
> 7)
speed =
7;
roadClass =
Integer.
parseInt(f
[1]);
if (roadClass
< 0)
roadClass =
0;
if (roadClass
> 4)
roadClass =
4;
oneway =
(f.
length > 2) ? Integer.
parseInt(f
[2]) > 0:
false;
toll =
(f.
length > 3) ? Integer.
parseInt(f
[3]) > 0:
false;
byte noAccess =
0;
for (int j =
0; j
< f.
length -
4; j++
){
if (Integer.
parseInt(f
[4+j
]) ==
0)
continue;
switch (j
){
case 0: noAccess |= AccessTagsAndBits.
EMERGENCY; break;
case 1: noAccess |= AccessTagsAndBits.
DELIVERY; break;
case 2: noAccess |= AccessTagsAndBits.
CAR; break;
case 3: noAccess |= AccessTagsAndBits.
BUS; break;
case 4: noAccess |= AccessTagsAndBits.
TAXI; break;
case 5: noAccess |= AccessTagsAndBits.
FOOT; break;
case 6: noAccess |= AccessTagsAndBits.
BIKE; break;
case 7: noAccess |= AccessTagsAndBits.
TRUCK; break;
}
}
mkgmapAccess =
(byte) ~noAccess
; // we store the allowed vehicles
}
public MapRoad makeRoad
(MapLine l
) {
assert roadId
!=
0;
if (log.
isDebugEnabled())
log.
debug("finishing road id " + roadId
);
MapRoad road =
new MapRoad
(roadId, roadId, l
);
// Set parameters.
road.
setRoadClass(roadClass
);
road.
setSpeed(speed
);
if (oneway
)
road.
setOneway();
if (toll
)
road.
setToll();
road.
setAccess(mkgmapAccess
);
if (numbers
!=
null && !numbers.
isEmpty()) {
convertNodesForHouseNumbers
(road
);
road.
setNumbers(numbers
);
}
List<Coord
> points = road.
getPoints();
for (NodeIndex ni : nodes
) {
int n = ni.
index;
if (log.
isDebugEnabled())
log.
debug("road has " + points.
size() +
" points");
Coord coord = points.
get(n
);
long id = coord.
getId();
if (id ==
0) {
CoordNode node = nodeCoords.
get((long) ni.
nodeId);
if (node ==
null) {
node =
new CoordNode
(coord, ni.
nodeId, ni.
boundary);
nodeCoords.
put((long) ni.
nodeId, node
);
}
points.
set(n, node
);
} else if (id
!= ni.
nodeId) {
log.
warn("Inconsistant node ids");
}
}
return road
;
}
/**
* Make sure that each node that is referenced by the house
* numbers is a number node. Some of them will later be changed
* to routing nodes.
* Only called if numbers is non-null and not empty.
*/
private void convertNodesForHouseNumbers
(MapRoad road
) {
int rNodNumber =
0;
for (Numbers n : numbers
) {
int node = n.
getNodeNumber();
n.
setIndex(rNodNumber++
);
road.
getPoints().
get(node
).
setNumberNode(true);
}
}
public boolean isRoad
() {
return roadId
!=
0;
}
public Map<Long, CoordNode
> getNodeCoords
() {
return nodeCoords
;
}
public void addNumbers
(String value
) {
if (numbers ==
null)
numbers =
new ArrayList<>();
Numbers num =
new Numbers
(value
);
if (num.
getLeftNumberStyle() != NumberStyle.
NONE || num.
getRightNumberStyle() != NumberStyle.
NONE)
numbers.
add(num
);
}
private static class NodeIndex
{
private final int index
;
private final int nodeId
;
private boolean boundary
;
private NodeIndex
(String[] f
) {
// f[0] is the index into the line
// f[1] is the node id
// f[2] is whether it's a boundary node
index =
Integer.
parseInt(f
[0]);
nodeId =
Integer.
parseInt(f
[1]);
if (f.
length > 2)
boundary =
Integer.
parseInt(f
[2]) > 0;
if (log.
isDebugEnabled())
log.
debug("ind=" + index +
"node=" + nodeId +
"bound=" + boundary
);
}
public String toString
() {
return String.
format("%d,%d,%b", index, nodeId, boundary
);
}
}
}