惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
P
Proofpoint News Feed
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
C
Check Point Blog
Microsoft Azure Blog
Microsoft Azure Blog
aimingoo的专栏
aimingoo的专栏
月光博客
月光博客
美团技术团队
D
Docker
博客园 - Franky
Y
Y Combinator Blog
大猫的无限游戏
大猫的无限游戏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

博客园 - Aimd

EPS图片转换 & 共享一个Excel宏,用于画Latex表格 Latex从零到开始使用 Eclipse下配置及使用Tomcat 6.0数据库连接池连接sqlserver2000 强制删除文件夹 SWT应用程序打包成jar过程 解决firefox频繁询问代理服务器用户名和密码问题 SQL server 2005 不能重新安装解决及ADO连接事例代码 SQL server 2005 远程连接问题及解决 家乡回长春路上拍的照片 blog的三种人 右键打不开磁盘又出新花样 用jni实现java使用dll 允许SWT Table的Tableitem多行显示 今天遇到一个geotools(GIS)和Eclipse合作的巨恶问题 慎用EMF Ecore文件的名字 数据压缩方法 BIRT插件的使用 RCP的布局得两个细节 RCP导出注意事项
实现模型间的多线连接
Aimd · 2006-06-07 · via 博客园 - Aimd

模型与模型间的连线多于一条时,这些线的布局就成了问题,否则线都会重叠到一起,本文简单介绍这个布局的环节。
类图如下(用于EMF):

1:ConnectionEditPart中:

    protected IFigure createFigure() {
        PolylineConnection conn 
= new PolylineConnection();
        conn.setLineStyle(SWT.LINE_DASH);
        conn.setTargetDecoration(
new PolygonDecoration());

        conn.add(lable, 
new MidpointLocator(conn, 0));
        
        
return conn;
    }


注意这里不能有setConnectionRouter方法出现,否则待会设置去除冲突的方法也就无效了。
2:DiagramEditPart中的RefreshVisuals中添加如下代码:

        ServiceRouter router = new ServiceRouter();
        router.setSeparation( 
30 );
        router.setNextRouter(
new BendpointConnectionRouter());
        cLayer.setConnectionRouter(router);


ServiceRouter类:

public class ServiceRouter extends AutomaticRouter {

    
private int separation = 10;

    
public int getSeparation() {
        
return separation;
    }


    
public void setSeparation(int value) {
        separation 
= value;
    }

    
    
/**
     * Modifies a given PointList that collides with some other PointList. The
     * given <i>index</i> indicates that this it the i<sup>th</sup> PointList
     * in a group of colliding points.
     * 
     * 
@param points
     *            the colliding points
     * 
@param index
     *            the index
     
*/

    
protected void handleCollision(PointList points, int index) {
        Point start 
= points.getFirstPoint();
        Point end 
= points.getLastPoint();

        
if (start.equals(end))
            
return;

        Point midPoint 
= new Point((end.x + start.x) / 2, (end.y + start.y) / 2);
        
int position = end.getPosition(start);
        Ray ray;
        
if (position == PositionConstants.SOUTH
                
|| position == PositionConstants.EAST)
            ray 
= new Ray(start, end);
        
else
            ray 
= new Ray(end, start);
        
double length = ray.length();

        
double xSeparation = separation * ray.x / length;
        
double ySeparation = separation * ray.y / length;

        Point bendPoint;

        
if (index % 2 == 0{
            bendPoint 
= new Point(
                    midPoint.x 
+ (index / 2* (-1 * ySeparation), 
                    midPoint.y 
+ (index / 2* xSeparation);
        }
 else {
            bendPoint 
= new Point(
                    midPoint.x 
+ (index / 2* ySeparation,
                    midPoint.y 
+ (index / 2* (-1 * xSeparation));
        }

        
if (!bendPoint.equals(midPoint))
            points.insertPoint(bendPoint, 
1);
    }

}

目前代码和FanRouter类的一样,我这样做的目的稍后解释,目前暂且当FanRouter一样看待就可以了。
3:定义自己的ConnectionAnchor。
       定义自己ConnectionAnchor的原因是,我的模型是用圆形表示的,按理说链接锚用EllipseAnchor就可以了,但是EllipseAnchor本身没有覆盖Equar和hashcode方法,导致使用Fantouter时不会出现逾期效果,因为Fanroute比较两条线是否重叠是通过比较锚点是否相同实现的,由于EllipseAnchor没有实现这个方法(可能是BUG),所以出现问题,但是ChopboxAnchor实现了,所以我扩展了ChopboxAnchor类,但是getLocation方法使用的是EllipseAnchor的代码,这里也可以自己写一个类似EllipseAnchor的链接锚,在这个自定义的类中实现比较两个对象是否相同的方法就可以了。

public class ServiceNodeConnectionAnchor extends ChopboxAnchor {
      
    
public ServiceNodeConnectionAnchor(IFigure figure) {
        
super(figure);
    }

    
    
public Point getLocation(Point reference) {
        Rectangle r 
= Rectangle.SINGLETON;
        r.setBounds(getOwner().getBounds());
        r.translate(
-1-1);
        r.resize(
11);
        getOwner().translateToAbsolute(r);
        
        Point ref 
= r.getCenter().negate().translate(reference);
        
        
if (ref.x == 0)
            
return new Point(reference.x, (ref.y > 0? r.bottom() : r.y);
        
if (ref.y == 0)
            
return new Point((ref.x > 0? r.right() : r.x, reference.y);
        
        
float dx = (ref.x > 0? 0.5f : -0.5f;
        
float dy = (ref.y > 0? 0.5f : -0.5f;
          
        
// ref.x, ref.y, r.width, r.height != 0 => safe to proceed
          
        
float k = (float)(ref.y * r.width) / (ref.x * r.height);
        k 
= k * k;
          
        
return r.getCenter().translate((int)(r.width * dx / Math.sqrt(1 + k)),
                                        (
int)(r.height * dy / Math.sqrt(1 + 1 / k)));
    }

}


这时的效果如下:

基本满足需求了,但是锚点现在都在一起,打算下一步解决。
打算用弧线来画的,所以我定义了ServiceRouter,而没有用FanRouter,打算在ServiceRouter的handleCollision里面做文章。