Home » Eclipse Projects » GEF » curved connections
curved connections [message #769560] |
Thu, 22 December 2011 05:30  |
Eclipse User |
|
|
|
Hallo,
I was looking for a way to connect two nodes with a cubic curve and I recognized, that I wasn't the fist looking for it.
I wanted the connections to look like the pipe-connection in Yahoo Pipes. I didn't anything. So I tried it myself with the following result. It's quite alright but it could be better. I would be glad if somebody had some hints for improvements, because im not good in graphic programming. the screenshot shows, how the connections look. The connection doesn't work well with the ShortestPathConnectionRouter (I think its because of obstacle avoidance). I used ConnectionRouter.NULL.
This is the Connection-Class:
import java.awt.LayoutManager;
import java.awt.geom.AffineTransform;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.AbstractPointListShape;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.ConnectionRouter;
import org.eclipse.draw2d.FigureListener;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.LayoutListener;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.RoutingListener;
import org.eclipse.draw2d.ShortestPathConnectionRouter;
import org.eclipse.draw2d.UpdateListener;
import org.eclipse.draw2d.UpdateManager;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
/**
*
* @author scheglov_ke
*/
public class PipeConnection extends PolylineConnection {
private static int OFFSET_X = 80;
private static int OFFSET_Y = 15;
private PointList connectionPoints = new PointList();
private int bend_X;
private int bend_Y;
@Override
protected void outlineShape(Graphics g) {
Point bendPointStart = null;
Point bendPointEnd = null;
int lineup = calculateLineup(getStart(), getEnd());
switch (lineup) {
case 1:
bendPointStart = new Point(getStart().x + bend_X, getStart().y - bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y + bend_Y);
break;
case 2:
bendPointStart = new Point(getStart().x + bend_X, getStart().y + bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y - bend_Y);
break;
case 3:
bendPointStart = new Point(getStart().x + bend_X, getStart().y - bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y + bend_Y);
break;
case 4:
bendPointStart = new Point(getStart().x + bend_X, getStart().y + bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y - bend_Y);
break;
default:
break;
}
CubicCurve2D curve = new CubicCurve2D.Float(getStart().x, getStart().y,
bendPointStart.x, bendPointStart.y, bendPointEnd.x,
bendPointEnd.y, getEnd().x, getEnd().y);
PathIterator pi = curve.getPathIterator(null, Float.MIN_VALUE);
PointList pl = new PointList();
pl.addPoint(getStart());
while (pi.isDone() == false) {
Point p = getCurrentPoint(pi);
if(pl.size()>0){
Point last = pl.getLastPoint();
if(p.x != last.x && p.y != last.y){
pl.addPoint(p);
}
}
pi.next();
}
connectionPoints.removeAllPoints();
connectionPoints.addAll(pl);
g.setInterpolation(SWT.HIGH);
pl.addPoint(getEnd());
Display display = Display.getCurrent();
g.setAntialias(SWT.ON);
g.setForegroundColor(display.getSystemColor(SWT.COLOR_DARK_BLUE));
g.setLineWidth(3);
g.setAlpha(180);
g.drawPolyline(connectionPoints);
g.setForegroundColor(display.getSystemColor(SWT.COLOR_WHITE));
g.setLineWidth(1);
g.drawPolyline(connectionPoints);
}
@Override
public void paint(Graphics graphics) {
// TODO Auto-generated method stub
super.paint(graphics);
}
private Point getCurrentPoint(PathIterator pi) {
double[] coordinates = new double[6];
Point p = new Point();
int type = pi.currentSegment(coordinates);
if(type == PathIterator.SEG_LINETO || type == PathIterator.SEG_MOVETO){
Double d = new Double(coordinates[0]);
long x = Math.round(coordinates[0]);
long y = Math.round(coordinates[1]);
p.setX(new Long(x).intValue());
p.setY(new Long(y).intValue());
}
return p;
}
@Override
public Rectangle getBounds() {
// TODO Auto-generated method stub
Rectangle bounds = super.getBounds();
Rectangle newBounds = new Rectangle();
newBounds.width = bounds.width + 40;
newBounds.height = bounds.height + 40;
newBounds.x = bounds.x - 20;
newBounds.y = bounds.y - 20;
bounds.union(newBounds);
return bounds;
}
private int calculateLineup(Point startPoint, Point endPoint) {
if (startPoint.x <= endPoint.x && startPoint.y <= endPoint.y) {
this.bend_X = OFFSET_X;
this.bend_Y = OFFSET_Y;
return 1;
}
if (startPoint.x <= endPoint.x && startPoint.y >= endPoint.y) {
this.bend_X = OFFSET_X;
this.bend_Y = OFFSET_Y;
return 2;
}
if (startPoint.x >= endPoint.x && startPoint.y >= endPoint.y) {
int reference = (startPoint.x - endPoint.x);
if(reference>100)reference = 100;
this.bend_X = OFFSET_X+reference;
this.bend_Y = OFFSET_Y+30;
return 3;
}
if (startPoint.x >= endPoint.x && startPoint.y <= endPoint.y) {
int reference = (startPoint.x - endPoint.x)/2;
if(reference>130)reference = 130;
this.bend_X = OFFSET_X+reference;
this.bend_Y = OFFSET_Y+30;
return 4;
}
return 0;
}
public PointList getConnectionPoints() {
return connectionPoints;
}
public void setConnectionPoints(PointList connectionPoints) {
this.connectionPoints = connectionPoints;
}
}
|
|
| | | |
Re: curved connections [message #892028 is a reply to message #872608] |
Tue, 26 June 2012 17:48  |
Eclipse User |
|
|
|
Hallo,
because the curves were a little bit nasty, I tried to improve it a little.
here is the connection class:
package org.ssprenger.spectrecockpit.figures;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.widgets.Display;
/**
*
* @author scheglov_ke
*/
public class PipeConnection extends PolylineConnection {
private static int OFFSET_X = 80;
private static int OFFSET_Y = 15;
private List<PrecisionPoint> connectionPoints = new ArrayList<PrecisionPoint>();
private int bend_X;
private int bend_Y;
private int queueEntries = 0;
@Override
protected void outlineShape(Graphics g) {
connectionPoints.clear();
Point bendPointStart = null;
Point bendPointEnd = null;
int lineup = calculateLineup(getStart(), getEnd());
switch (lineup) {
case 1:
bendPointStart = new Point(getStart().x + bend_X, getStart().y
- bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y + bend_Y);
break;
case 2:
bendPointStart = new Point(getStart().x + bend_X, getStart().y
+ bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y - bend_Y);
break;
case 3:
bendPointStart = new Point(getStart().x + bend_X, getStart().y
- bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y + bend_Y);
break;
case 4:
bendPointStart = new Point(getStart().x + bend_X, getStart().y
+ bend_Y);
bendPointEnd = new Point(getEnd().x - bend_X, getEnd().y - bend_Y);
break;
default:
break;
}
CubicCurve2D curve = new CubicCurve2D.Float(getStart().x, getStart().y,
bendPointStart.x, bendPointStart.y, bendPointEnd.x,
bendPointEnd.y, getEnd().x, getEnd().y);
PathIterator pi = curve.getPathIterator(null, Float.MIN_VALUE);
while (pi.isDone() == false) {
PrecisionPoint p = getCurrentPoint(pi);
connectionPoints.add(p);
pi.next();
}
Path p = new Path(Display.getCurrent());
p.moveTo(getStart().x, getStart().y);
for (PrecisionPoint po : connectionPoints) {
p.lineTo((float) po.preciseX(), (float) po.preciseY());
}
p.lineTo(getEnd().x, getEnd().y);
g.setInterpolation(SWT.HIGH);
Display display = Display.getCurrent();
g.setAntialias(SWT.ON);
g.setForegroundColor(display.getSystemColor(SWT.COLOR_DARK_BLUE));
g.setLineWidth(4);
g.setAlpha(180);
g.drawPath(p);
g.setForegroundColor(display.getSystemColor(SWT.COLOR_WHITE));
g.setLineWidth(2);
g.drawPath(p);
g.setForegroundColor(display.getSystemColor(SWT.COLOR_RED));
g.setLineWidth(4);
int counter = queueEntries;
Path path = new Path(Display.getCurrent());
PrecisionPoint last = connectionPoints.get(connectionPoints.size() - 1);
path.moveTo((float) last.preciseX(), (float) last.preciseY());
int size = connectionPoints.size() - 1;
for (int i = 0; i < counter * 35; i++) {
PrecisionPoint nextPoint = connectionPoints.get(size - i);
path.lineTo((float) nextPoint.preciseX(),
(float) nextPoint.preciseY());
}
if (counter > 1) {
g.drawPath(path);
}
}
@Override
public void paint(Graphics graphics) {
// TODO Auto-generated method stub
super.paint(graphics);
}
private PrecisionPoint getCurrentPoint(PathIterator pi) {
double[] coordinates = new double[6];
PrecisionPoint p = new PrecisionPoint();
int type = pi.currentSegment(coordinates);
if (type == PathIterator.SEG_LINETO || type == PathIterator.SEG_MOVETO) {
double x = coordinates[0];
double y = coordinates[1];
p.setPreciseX(x);
p.setPreciseY(y);
}
return p;
}
@Override
public Rectangle getBounds() {
// TODO Auto-generated method stub
Rectangle bounds = super.getBounds();
Rectangle newBounds = new Rectangle();
newBounds.width = bounds.width + 40;
newBounds.height = bounds.height + 40;
newBounds.x = bounds.x - 20;
newBounds.y = bounds.y - 20;
bounds.union(newBounds);
return bounds;
}
private int calculateLineup(Point startPoint, Point endPoint) {
if (startPoint.x <= endPoint.x && startPoint.y <= endPoint.y) {
this.bend_X = OFFSET_X;
this.bend_Y = OFFSET_Y;
return 1;
}
if (startPoint.x <= endPoint.x && startPoint.y >= endPoint.y) {
this.bend_X = OFFSET_X;
this.bend_Y = OFFSET_Y;
return 2;
}
if (startPoint.x >= endPoint.x && startPoint.y >= endPoint.y) {
int reference = (startPoint.x - endPoint.x);
if (reference > 100)
reference = 100;
this.bend_X = OFFSET_X + reference;
this.bend_Y = OFFSET_Y + 30;
return 3;
}
if (startPoint.x >= endPoint.x && startPoint.y <= endPoint.y) {
int reference = (startPoint.x - endPoint.x) / 2;
if (reference > 130)
reference = 130;
this.bend_X = OFFSET_X + reference;
this.bend_Y = OFFSET_Y + 30;
return 4;
}
return 0;
}
public List<PrecisionPoint> getConnectionPoints() {
return connectionPoints;
}
public void setConnectionPoints(List<PrecisionPoint> connectionPoints) {
this.connectionPoints = connectionPoints;
}
public void setEntry(int count) {
this.queueEntries = count;
}
}
in the attachment is screenshot that shows the connections
|
|
|
Goto Forum:
Current Time: Wed Jul 02 16:04:45 EDT 2025
Powered by FUDForum. Page generated in 0.04186 seconds
|