/**
* *****************************************************************************
* Copyright 2013 Johannes Mitlmeier
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
* ****************************************************************************
*/
package de.fub.agg2graph.roadgen;
import de.fub.agg2graph.agg.AggConnection;
import de.fub.agg2graph.agg.AggContainer;
import de.fub.agg2graph.agg.AggNode;
import de.fub.agg2graph.structs.IEdge;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
/**
* Methods for finding and processing intersections in the aggregated data in
* order to enable other classes to transform the data to a street graph.
*
* @author Johannes Mitlmeier
*
*/
public class DefaultIntersectionParser implements IIntersectionParser {
private static final Logger logger = Logger.getLogger("agg2graph.roadgen.intersectionparser");
private RoadNetwork roadNetwork;
private AggContainer agg;
@Override
public void makeNetwork(RoadNetwork roadNetwork, AggContainer agg) {
this.roadNetwork = roadNetwork;
this.agg = agg;
makeIntersections();
makeRoads();
}
/**
* An intersection candidate is an {@link AggNode} that is either already
* having a intersection structure itself or is at the end of a line.
*
* @param agg
* @return
*/
private Set<AggNode> getIntersectionCandidates(AggContainer agg) {
Set<AggNode> candidates = new HashSet<AggNode>();
Set<AggNode> nodes = agg.getCachingStrategy().getLoadedNodes();
for (AggNode node : nodes) {
if (node.isVisible()
&& (node.isAggIntersection() || node.isEndNode())) {
candidates.add(node);
}
}
return candidates;
}
private void makeIntersections() {
// get candidates
Set<AggNode> candidates = getIntersectionCandidates(agg);
for (AggNode candidate : candidates) {
Intersection intersection = new Intersection(candidate);
logger.info(MessageFormat.format("intersection found: {0}", intersection));
// intersection.out = candidate.getVisibleOut();
// intersection.in = candidate.getVisibleIn();
roadNetwork.getIntersections().add(intersection);
}
}
private void makeRoads() {
// parse roads
Iterator<Intersection> it = roadNetwork.getIntersections().iterator();
List<Intersection> intersections = new ArrayList<Intersection>(10);
while (it.hasNext()) {
Intersection startIntersection = it.next();
// every outgoing road
for (AggConnection c : startIntersection.baseNode.getVisibleOut()) {
Road road = new Road();
road.setFrom(startIntersection);
startIntersection.out.add(road);
AggConnection currentConn = c;
HashSet<AggConnection> set = new HashSet<AggConnection>();
// follow the road to the next intersection
while (currentConn.getTo().getIntersection() == null) {
// add current connection to road path
road.getPath().add(currentConn);
// determine current connection representation an intersection
if (currentConn.getTo().getVisibleOut() == null
|| currentConn.getTo().getVisibleOut().size() != 1) {
Intersection newIntersection = new Intersection(currentConn.getTo());
newIntersection.in.add(road);
intersections.add(newIntersection);
break;
} else if (set.contains(currentConn)) { // check whether whether a cycle occurred during traversal
IEdge<AggNode> node = null;
if (!road.getPath().isEmpty()) {
// we get the last node of the path
node = road.getPath().get(road.getPath().size() - 1);
} else {
// current node is the first node in the path
node = currentConn;
}
// create a intersection
Intersection newIntersection = new Intersection(node.getTo());
newIntersection.in.add(road);
intersections.add(newIntersection);
// because a cycle occurred, a possible intersection must be forcfully
// removed
currentConn.getTo().setIntersection(null);
break;
} else {
if (currentConn.getTo().getVisibleOut().size() != 1) {
// This case sould never occure.
// There is only one, otherwise it would have been an intersection itself
logger.severe("Error not exactly one element in set!");
}
set.add(currentConn);
// get next connection.
currentConn = currentConn.getTo().getVisibleOut().iterator().next();
}
}
set.clear();
/// add road to road network only when there is a valid end intersection
if (currentConn.getTo().getIntersection() != null) {
road.getPath().add(currentConn);
Intersection endIntersection = currentConn.getTo()
.getIntersection();
road.setTo(endIntersection);
endIntersection.in.add(road);
roadNetwork.getRoads().add(road);
}
}
}
roadNetwork.getIntersections().addAll(intersections);
}
}