// 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; /** * group of nodes that will be evaluated independently from other groups */ public class JunctionEvaluationGroup extends EvaluationGroup { private final Set<SegmentNode> segmentNodes; protected List<Segment> inboundSegments; protected List<Segment> outboundSegments; /** * @param segmentNodes set of SegmentNodes, must not be modified * after being used as constructor parameter; != null */ public JunctionEvaluationGroup(Set<SegmentNode> segmentNodes) { assert segmentNodes != null; this.segmentNodes = segmentNodes; } /** * returns all segments that can be used to enter this group. * {@link #evaluate(Iterable)} needs be called before this method. * * @return segment collection; != null */ public Collection<Segment> getInboundSegments() { if (!evaluated) { throw new IllegalStateException(tr("Group not yet evaluated")); } return inboundSegments; } /** * returns all segments that can be used to leave this group. * {@link #evaluate(Iterable)} needs be called before this method. * * @return segment collection; != null */ public Collection<Segment> getOutboundSegments() { if (!evaluated) { throw new IllegalStateException(tr("Group not yet evaluated")); } return outboundSegments; } /** * 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 inboundSegment start of the potential sequence; * must be inbound segment; != null * @param outboundSegment target of the potential sequence; * must be outbound segment; != null * @return sequence of segments or null */ public List<Segment> getSegmentSequence(Segment inboundSegment, Segment outboundSegment) { assert inboundSegment != null && inboundSegments.contains(inboundSegment); assert outboundSegment != null && outboundSegments.contains(outboundSegment); if (!evaluated) { throw new IllegalStateException(tr("Group not yet evaluated")); } int inboundIndex = inboundSegments.indexOf(inboundSegment); int outboundIndex = outboundSegments.indexOf(outboundSegment); return segmentSequences[inboundIndex][outboundIndex]; } @Override protected void evaluateImpl(final Collection<Restriction> restrictions) { assert restrictions != null; /* find inbound and outbound segments. An inbound segment is a segment whose target * is in the set and whose start node isn't (analogous for outbound segments) */ inboundSegments = new ArrayList<>(); outboundSegments = new ArrayList<>(); for (SegmentNode segmentNode : segmentNodes) { for (Segment segment : segmentNode.getInboundSegments()) { if (!segmentNodes.contains(segment.getNode1())) { inboundSegments.add(segment); } } for (Segment segment : segmentNode.getOutboundSegments()) { if (!segmentNodes.contains(segment.getNode2())) { outboundSegments.add(segment); } } } /* find segment sequences from inbound to outbound segments */ @SuppressWarnings("unchecked") //cannot create generic array without cast List<Segment>[][] sequenceArray = new List[inboundSegments.size()][outboundSegments.size()]; for (int inboundIndex = 0; inboundIndex < inboundSegments.size(); inboundIndex++) { for (int outboundIndex = 0; outboundIndex < outboundSegments.size(); outboundIndex++) { List<Segment> sequence = findSegmentSequence(inboundSegments.get(inboundIndex), outboundSegments.get(outboundIndex), restrictions); sequenceArray[inboundIndex][outboundIndex] = sequence; } } segmentSequences = sequenceArray; } @Override protected boolean isUsableNode(SegmentNode node) { return segmentNodes.contains(node); } @Override protected boolean isUsableSegment(Segment segment) { return segmentNodes.contains(segment.getNode1()) && segmentNodes.contains(segment.getNode2()); } @Override public String toString() { return "JunctionEG " + segmentNodes; } }