// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.JunctionChecker; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import javax.swing.Action; import javax.swing.Icon; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.Channel; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.ChannelDiGraph; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.OSMNode; import org.openstreetmap.josm.plugins.JunctionChecker.reader.ColorSchemeXMLReader; import org.openstreetmap.josm.tools.ImageProvider; /** * Diese Klasse enthält Teile der Klasse graphviewLayer des graphview Plugins * */ public class ChannelDiGraphLayer extends Layer { private ChannelDiGraph digraph; private static final int POINTSIZE = 5; //original 3 private static final float LINEWIDTH = 4; //original 2 private final ColorSchemeXMLReader cXMLReader; private static final Shape ARROW_HEAD; static { Polygon head = new Polygon(); head.addPoint(0, 0); head.addPoint(-15, +4); head.addPoint(-15, -4); ARROW_HEAD = head; } //die Farben für die zu zeichnenden Elemente private Color twoWayChannelColor; private Color oneWayChannelColor; private Color toNodeColor; private Color fromNodeColor; private Color nsccChannelColor; private Color selectedChannelColor; private Color partOfJunctionColor; public ChannelDiGraphLayer(ColorSchemeXMLReader cXMLReader) { super("ChannelDiGraphLayer"); this.cXMLReader = cXMLReader; initColors(); } public void initColors() { twoWayChannelColor = cXMLReader.getColor("TwoWayChannel"); oneWayChannelColor = cXMLReader.getColor("OneWayChannel"); toNodeColor = cXMLReader.getColor("ToNode"); fromNodeColor = cXMLReader.getColor("FromNode"); nsccChannelColor = cXMLReader.getColor("NotConnectedChannel"); selectedChannelColor = cXMLReader.getColor("selectedChannel"); partOfJunctionColor = cXMLReader.getColor("partOfJunction"); } @Override public Icon getIcon() { return ImageProvider.get("dialogs", "junctionchecker"); } @Override public Object getInfoComponent() { return null; } @Override public Action[] getMenuEntries() { Action[] action = new Action[0]; return action; } @Override public String getToolTipText() { return tr("Channel-Digraph created from the active OSM-Layer"); } @Override public boolean isMergable(Layer other) { return false; } @Override public void mergeFrom(Layer from) { } @Override public void paint(Graphics2D g, MapView mv, Bounds box) { if (digraph != null) { for (int i = 0; i < digraph.getChannels().size(); i++) { paintChannel(digraph.getChannelAtPosition(i), g, mv); } } } private void paintChannel(final Channel channel, final Graphics2D g, final MapView mv) { Point fromPoint = getCoord(channel.getFromNode(), mv); g.setColor(fromNodeColor); g.fillOval(fromPoint.x - POINTSIZE, fromPoint.y - POINTSIZE, 2 * POINTSIZE, 2 * POINTSIZE); Point toPoint = getCoord(channel.getToNode(), mv); g.setColor(toNodeColor); g.fillOval(toPoint.x - POINTSIZE, toPoint.y - POINTSIZE, 2 * POINTSIZE, 2 * POINTSIZE); Color c; if (channel.isPartOfJunction()) { c = partOfJunctionColor; } else if (channel.isSelected() == true) { c = selectedChannelColor; } else if (channel.isStrongConnected() == false) { c = nsccChannelColor; } else if (channel.getBackChannelID() != -100) { c = twoWayChannelColor; } else { c = oneWayChannelColor; } g.setColor(c); g.setStroke(new BasicStroke(LINEWIDTH)); g.draw(new Line2D.Float(fromPoint.x, fromPoint.y, toPoint.x, toPoint.y)); double angle = angleFromXAxis(fromPoint, toPoint); Shape head = ARROW_HEAD; head = AffineTransform.getRotateInstance(angle).createTransformedShape(head); head = AffineTransform.getTranslateInstance(toPoint.x, toPoint.y).createTransformedShape(head); g.fill(head); } private Point getCoord(OSMNode node, MapView mv) { return mv.getPoint(Main.getProjection().latlon2eastNorth(new LatLon(node.getLatitude(), node.getLongitude()))); } /** * calculates the angle between the x axis and a vector given by two points * @param p1 first point for vector; != null * @param p2 second point for vector; != null * @return angle in radians, in range [-Pi .. +Pi] */ private double angleFromXAxis(Point p1, Point p2) { assert p1 != null && p2 != null; final float vecX = p2.x - p1.x; final float vecY = p2.y - p1.y; final float vecLength = (float) Math.sqrt(vecX*vecX + vecY*vecY); final float dotProductVecAxis = vecX; float angle = (float) Math.acos(dotProductVecAxis / vecLength); if (p2.y < p1.y) { angle = -angle; } assert -Math.PI*0.5 < angle && angle <= Math.PI*0.5; return angle; } @Override public void visitBoundingBox(BoundingXYVisitor v) { } public void setDiGraph(ChannelDiGraph digraph) { this.digraph = digraph; } public ChannelDiGraph getDigraph() { return digraph; } public void setDigraph(ChannelDiGraph digraph) { this.digraph = digraph; } }