// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.graphview.core.graph;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.openstreetmap.josm.plugins.graphview.core.transition.Restriction;
import org.openstreetmap.josm.plugins.graphview.core.transition.Segment;
import org.openstreetmap.josm.plugins.graphview.core.transition.SegmentNode;
/**
* evaluation group that is based on segments and connects the node-based
* {@link JunctionEvaluationGroup}s.
*/
public class ConnectorEvaluationGroup extends EvaluationGroup {
private final Set<Segment> segments;
private final List<SegmentNode> borderNodes;
/**
* @param segments set of Segments, must not be modified
* after being used as constructor parameter; != null
* @param borderNodes nodes that are used as starting/target nodes for sequences; != null
*/
public ConnectorEvaluationGroup(Set<Segment> segments, Set<SegmentNode> borderNodes) {
assert segments != null && borderNodes != null;
this.segments = segments;
this.borderNodes = new ArrayList<>(borderNodes);
}
/**
* returns all nodes that can be used as start/target nodes
* @return border nodes; != null
*/
public Collection<SegmentNode> getBorderNodes() {
return borderNodes;
}
/**
* returns all segments in the group
* @return segment set; != null
*/
public Set<Segment> getSegments() {
return segments;
}
/**
* returns a segment sequence that runs from an inbound to an outbound
* segment or null if no connection is possible.
* {@link EvaluationGroup#evaluate(Collection)} needs be called before this method.
*
* @param startNode start of the potential sequence; must be border node; != null
* @param targetNode target of the potential sequence; must be border node; != null
* @return sequence of segments or null
*/
public List<Segment> getSegmentSequence(SegmentNode startNode, SegmentNode targetNode) {
assert startNode != null && borderNodes.contains(startNode);
assert targetNode != null && borderNodes.contains(targetNode);
if (!evaluated) {
throw new IllegalStateException(tr("Group not yet evaluated"));
}
int inboundIndex = borderNodes.indexOf(startNode);
int outboundIndex = borderNodes.indexOf(targetNode);
return segmentSequences[inboundIndex][outboundIndex];
}
@Override
protected void evaluateImpl(Collection<Restriction> restrictions) {
/* find segment sequences from inbound to outbound segments */
@SuppressWarnings("unchecked") //cannot create generic array without cast
List<Segment>[][] sequenceArray = new List[borderNodes.size()][borderNodes.size()];
for (int startIndex = 0; startIndex < borderNodes.size(); startIndex++) {
for (int targetIndex = 0; targetIndex < borderNodes.size(); targetIndex++) {
List<Segment> sequence =
findSegmentSequence(borderNodes.get(startIndex),
borderNodes.get(targetIndex), restrictions);
sequenceArray[startIndex][targetIndex] = sequence;
}
}
segmentSequences = sequenceArray;
}
@Override
protected boolean isUsableNode(SegmentNode node) {
return shareElement(segments, node.getInboundSegments())
|| shareElement(segments, node.getOutboundSegments());
}
@Override
protected boolean isUsableSegment(Segment segment) {
return segments.contains(segment);
}
@Override
public String toString() {
return "ConnectorEG " + segments;
}
}