Browse Source

Edge renderer work

master
Máté Kukri 2 years ago
parent
commit
527ab01961
  1. 15
      src/main/java/xyz/mkukri/SwingGraph/Pair.java
  2. 39
      src/main/java/xyz/mkukri/SwingGraph/SwingGraph.java
  3. 50
      src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererOrthogonal.java
  4. 47
      src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererStraight.java
  5. 25
      src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererUtil.java
  6. 2
      src/main/java/xyz/mkukri/SwingGraph/geometry/Line.java
  7. 24
      src/main/java/xyz/mkukri/SwingGraph/geometry/Rectangle.java

15
src/main/java/xyz/mkukri/SwingGraph/Pair.java

@ -0,0 +1,15 @@
package xyz.mkukri.SwingGraph;
/**
* Pair of two object
* @param <T> type of objects in this pair
*/
public class Pair<T> {
public T obj1;
public T obj2;
public Pair(T obj1, T obj2) {
this.obj1 = obj1;
this.obj2 = obj2;
}
}

39
src/main/java/xyz/mkukri/SwingGraph/SwingGraph.java

@ -1,26 +1,22 @@
package xyz.mkukri.SwingGraph;
import xyz.mkukri.SwingGraph.edge.EdgeRenderer;
import xyz.mkukri.SwingGraph.edge.EdgeRendererMid;
import xyz.mkukri.SwingGraph.geometry.Line;
import xyz.mkukri.SwingGraph.edge.EdgeRendererOrthogonal;
import xyz.mkukri.SwingGraph.edge.EdgeRendererStraight;
import xyz.mkukri.SwingGraph.geometry.Point;
import xyz.mkukri.SwingGraph.geometry.Rectangle;
import javax.swing.JPanel;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -67,10 +63,10 @@ public class SwingGraph extends JPanel {
/**
* Edges in the current graph
*/
private Set<Edge> edges = new HashSet<>();
private Set<Pair<Component>> edges = new HashSet<>();
public SwingGraph() {
this(new EdgeRendererMid());
this(new EdgeRendererStraight());
}
public SwingGraph(EdgeRenderer edgeRenderer) {
@ -187,8 +183,8 @@ public class SwingGraph extends JPanel {
Stroke oldStroke = g2D.getStroke();
Color oldColor = g2D.getColor();
for (Edge e : edges) {
edgeRenderer.renderEdge(g2D, getBorderRect(e.v1), getBorderRect(e.v2));
for (Pair<Component> e : edges) {
edgeRenderer.renderEdge(g2D, getBorderRect(e.obj1), getBorderRect(e.obj2));
}
// Draw vertex borders
@ -269,27 +265,6 @@ public class SwingGraph extends JPanel {
* @param v2 AWT or Swing component of the v2
*/
public void addEdge(Component v1, Component v2) {
edges.add(new Edge(v1, v2));
}
/**
* Represents an edge in a graph
*/
private static class Edge {
private Component v1;
private Component v2;
public Edge(Component v1, Component v2) {
this.v1 = v1;
this.v2 = v2;
}
public Component getV1() {
return v1;
}
public Component getV2() {
return v2;
}
edges.add(new Pair<>(v1, v2));
}
}

50
src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererOrthogonal.java

@ -0,0 +1,50 @@
package xyz.mkukri.SwingGraph.edge;
import xyz.mkukri.SwingGraph.geometry.Line;
import xyz.mkukri.SwingGraph.geometry.Point;
import xyz.mkukri.SwingGraph.geometry.Rectangle;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* Find the sides facing each other of two rectangles and
* draw orthogonally staggered edges between their midpoints
*/
public class EdgeRendererOrthogonal implements EdgeRenderer {
private List<Line> getHorizontalEdge(Line l) {
List<Line> lines = new ArrayList<>();
Point m1 = new Point(l.x1, l.y1);
Point m2 = new Point(l.x2, l.y2);
double halfDistance = (m2.y - m1.y) / 2.0;
Point h1 = new Point(m1.x, (int) (m1.y + halfDistance));
Point h2 = new Point(m2.x, (int) (m2.y - halfDistance));
lines.add(new Line(m1, h1));
lines.add(new Line(m2, h2));
lines.add(new Line(h1, h2));
return lines;
}
private List<Line> getVerticalEdge(Line l) {
List<Line> lines = new ArrayList<>();
Point m1 = new Point(l.x1, l.y1);
Point m2 = new Point(l.x2, l.y2);
double halfDistance = (m2.x - m1.x) / 2.0;
Point h1 = new Point((int) (m1.x + halfDistance), m1.y);
Point h2 = new Point((int) (m2.x - halfDistance), m2.y);
lines.add(new Line(m1, h1));
lines.add(new Line(m2, h2));
lines.add(new Line(h1, h2));
return lines;
}
@Override
public void renderEdge(Graphics2D graphics2D, Rectangle v1, Rectangle v2) {
Line h = EdgeRendererUtil.connectClosestMidpoints(v1.getHorizontalSides(), v2.getHorizontalSides());
Line v = EdgeRendererUtil.connectClosestMidpoints(v1.getVerticalSides(), v2.getVerticalSides());
for (Line l : h.getLength() < v.getLength() ? getHorizontalEdge(h) : getVerticalEdge(v)) {
graphics2D.drawLine(l.x1, l.y1, l.x2, l.y2);
}
}
}

47
src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererMid.java → src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererStraight.java

@ -4,24 +4,29 @@ import xyz.mkukri.SwingGraph.geometry.Point;
import xyz.mkukri.SwingGraph.geometry.Rectangle;
import xyz.mkukri.SwingGraph.geometry.Line;
import java.awt.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.util.List;
/**
* Draws straight edges between the midpoint of the closest side of two vertices
* Find the sides facing each other of two rectangles and
* draw straight edges between their midpoints
*/
public class EdgeRendererMid implements EdgeRenderer {
public class EdgeRendererStraight implements EdgeRenderer {
private final Color edgeColor;
private final int edgeWidth;
private final int arrowHeadSize;
private final Polygon arrowHead;
public EdgeRendererMid() {
public EdgeRendererStraight() {
this(Color.black, 1, 5);
}
public EdgeRendererMid(Color edgeColor, int edgeWidth, int arrowHeadSize) {
public EdgeRendererStraight(Color edgeColor, int edgeWidth, int arrowHeadSize) {
this.edgeColor = edgeColor;
this.edgeWidth = edgeWidth;
this.arrowHeadSize = arrowHeadSize;
@ -33,30 +38,10 @@ public class EdgeRendererMid implements EdgeRenderer {
arrowHead.addPoint(arrowHeadSize, -arrowHeadSize);
}
/**
* Calculate the midpoint line between the closest sides of two rectangles
* @param r1 rectangle 1
* @param r2 rectangle 2
* @return line
*/
private Line midpointLine(Rectangle r1, Rectangle r2) {
java.util.List<Line> sides1 = r1.getSides();
List<Line> sides2 = r2.getSides();
Line shortestLine = null;
for (Line s1 : sides1) {
xyz.mkukri.SwingGraph.geometry.Point m1 = s1.getMidpoint();
for (Line s2 : sides2) {
xyz.mkukri.SwingGraph.geometry.Point m2 = s2.getMidpoint();
Line curLine = new Line(m1, m2);
if (shortestLine == null || curLine.getLength() < shortestLine.getLength()) {
shortestLine = curLine;
}
}
}
return shortestLine;
private Line getEdge(Rectangle r1, Rectangle r2) {
Line h = EdgeRendererUtil.connectClosestMidpoints(r1.getHorizontalSides(), r2.getHorizontalSides());
Line v = EdgeRendererUtil.connectClosestMidpoints(r1.getVerticalSides(), r2.getVerticalSides());
return h.getLength() < v.getLength() ? h : v;
}
@Override
@ -70,7 +55,7 @@ public class EdgeRendererMid implements EdgeRenderer {
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Render line
Line line = midpointLine(v1, v2);
Line line = getEdge(v1, v2);
graphics2D.drawLine(line.x1, line.y1, line.x2, line.y2);
// Render arrow head

25
src/main/java/xyz/mkukri/SwingGraph/edge/EdgeRendererUtil.java

@ -0,0 +1,25 @@
package xyz.mkukri.SwingGraph.edge;
import xyz.mkukri.SwingGraph.Pair;
import xyz.mkukri.SwingGraph.geometry.Line;
import xyz.mkukri.SwingGraph.geometry.Point;
import xyz.mkukri.SwingGraph.geometry.Rectangle;
import java.util.List;
public class EdgeRendererUtil {
public static Line connectClosestMidpoints(List<Line> lines1, List<Line> lines2) {
Line closestLine = null;
for (Line line1 : lines1) {
Point mid1 = line1.getMidpoint();
for (Line line2 : lines2) {
Point mid2 = line2.getMidpoint();
Line currentLine = new Line(mid1, mid2);
if (closestLine == null || currentLine.getLength() < closestLine.getLength()) {
closestLine = currentLine;
}
}
}
return closestLine;
}
}

2
src/main/java/xyz/mkukri/SwingGraph/geometry/Line.java

@ -1,5 +1,7 @@
package xyz.mkukri.SwingGraph.geometry;
import xyz.mkukri.SwingGraph.Pair;
public class Line {
public int x1;
public int y1;

24
src/main/java/xyz/mkukri/SwingGraph/geometry/Rectangle.java

@ -33,28 +33,24 @@ public class Rectangle {
}
/**
* Convert a rectangle to a list of vertices
* @return list of vertices
* Get the horizontal sides of the rectangle
* @return horizontal sides
*/
public List<Point> getVertices() {
List<Point> vertices = new ArrayList<>();
vertices.add(new Point(x, y));
vertices.add(new Point(x + width, y));
vertices.add(new Point(x, y + height));
vertices.add(new Point(x + width, y + height));
return vertices;
public List<Line> getHorizontalSides() {
List<Line> sides = new ArrayList<>();
sides.add(new Line(x, y, x + width, y));
sides.add(new Line(x, y + height, x + width, y + height));
return sides;
}
/**
* Convert a rectangle to a list of sides
* @return list of sides
* Get the vertical sides of this rectangle
* @return vertical sides
*/
public List<Line> getSides() {
public List<Line> getVerticalSides() {
List<Line> sides = new ArrayList<>();
sides.add(new Line(x, y, x + width, y));
sides.add(new Line(x, y, x, y + height));
sides.add(new Line(x + width, y, x + width, y + height));
sides.add(new Line(x, y + height, x + width, y + height));
return sides;
}
}
Loading…
Cancel
Save