// 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; } }