说明:

  1、未实现障碍物自动避让功能;

  2、未实现添加图元到连线之间,连线自动避开新增图元功能;

后续再完善...

 version 1:

package com.sunsheen.jfids.studio.uml.modulediagram.anchorAndRouter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.runtime.Assert;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Vector; import com.sunsheen.jfids.studio.monitor.HKMoniter;
import com.sunsheen.jfids.studio.monitor.HKMoniterFactory;
import com.sunsheen.jfids.studio.uml.UMLPlugin;
import com.sunsheen.jfids.studio.uml.activitydiagram.editpart.FlowEditPart; /**
* uml连接线路由算法
* 1、一旦用户对某条连线的路由方式进行了调整,就不再为其提供智能路由布线的功能。
* 2、用户是否对连线的路径进行了调整的信息是需要持久存储的。
* 3、用户在建模时,只有当发生了连线和模型的布局冲突时,才对存在布局冲突的连线进行路由调整,对其他连线不做更改。
*
* @author WangSong
*/
public class AIUmlConnectionRouter extends BendpointConnectionRouter { private IFigure content;// 当前操作的图元
private final static int DEFAULT_SPACE = 10;// 默认点间距
private PointList points;// 连线上位置点集合
private int space; /* 离障碍物的间隙 */
private Vector endDirection;// 结束方向
private Point endPoint;// 结束位置 // 连线是否跟图元起点边平行
private boolean parallelStartSide;
// 连线是否跟图元终点边平行
private boolean parallelEndSide;
// 连线跟连接点平行的边(源图元)
private String parallelSideSource; // 上下左右
// 连线跟连接点平行的边(目标图元)
private String parallelSideTarget; // 上下左右
private int rectangleAffirm = 0;// 初始化当前图元选择 // 冲突图元、拐点、关联关系
Map<Rectangle,List<Point[]>> rectangleLinesRelationMap = new HashMap<Rectangle,List<Point[]>>();//关联关系
private List<Rectangle> conflictRectangleList = new ArrayList<Rectangle>(); //有冲突的图元
private List<Point[]> conflictPointArrayList = new ArrayList<Point[]>();//存放一对一对冲突的拐点 private boolean sourceAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(原图原)
private boolean targetAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(目标图元)
private Rectangle sourceRect;// 初始化矩形图元
private Rectangle targetRect;//初始化目標圖元
//源点位于源图元的边
private String sourceSide;
//源点位于目标图元的边
private String targetSide; // 初始化上下左右方向(从原点看)
private final Vector
DOWN = new Vector(0, -1),//下
UP = new Vector(0, 1), //上
LEFT = new Vector(-1, 0),//左
RIGHT = new Vector(1, 0),//右 LEFT_UP = new Vector(-1,1),//左上
RIGHT_UP = new Vector(1,1),//右上
LEFT_DOWN = new Vector(-1,-1),//左下
RIGHT_DOWN = new Vector(1,-1);//右下 //直线方向数组
private Vector[] straightLineArr = {DOWN,UP,LEFT,RIGHT};
//折线集合
private Vector[] brokenLineArr = {LEFT_UP,RIGHT_UP,LEFT_DOWN,RIGHT_DOWN}; public AIUmlConnectionRouter(IFigure content) {
this(content, DEFAULT_SPACE);
} public AIUmlConnectionRouter(IFigure content,PointList points) {
Assert.isNotNull(content);
this.space = DEFAULT_SPACE;
this.content = content;
this.points = points;
} public AIUmlConnectionRouter(IFigure content, int space) {
Assert.isNotNull(content);
Assert.isLegal(space > 0, "空间间距不能为0!"); this.content = content;
this.space = space;
} // 是否能连接
private boolean validConn(Connection conn) {
if ((conn.getSourceAnchor() == null)
|| (conn.getTargetAnchor() == null))
return false;
return true;
} //初始化连线间冲突图元集合
private void conflictRectangleJudge(Connection conn){
//获取到连线中的所有图元
List<IFigure> figures = conn.getChildren(); //这种方式获取不到连线中的所有图元,需要修改,后续完成....
///////////////////////////////////////////////////
//得到当前连线上所有图元
//所有图元周围添加拐点 ///////////////////////////////////////////////////
PointList allPoint = conn.getPoints(); //得到冲突图元
for(IFigure f : figures){
Rectangle currentR = f.getBounds().getCopy();//当前图元
f.translateToAbsolute(currentR);//
//取出当前连线所有的拐点
for(int i=0;i<allPoint.size();i++){
//最后一个点时,不能再进行检测
if(i == allPoint.size() - 1)
break;
//两个拐点之间是垂直或者平行的线段,存在有冲突的图元
Point start = allPoint.getPoint(i);
Point end = allPoint.getPoint(i+1);
//会依次检查当前图元是否跟连线冲突
if(detectionRectangleClash(currentR,start,end)){
//可能存在拐点在冲突图元内(两段线段跟当前图元冲突)の情况
//拐点在冲突图元内的情况
if(!conflictRectangleList.contains(currentR)){
conflictRectangleList.add(currentR);//存为冲突图元
} //拐点在冲突图元外的情况
Point[] segment = {start,end};
conflictPointArrayList.add(segment);//存放冲突线段
//存入关联关系
rectangleLinesRelationMap.put(currentR, conflictPointArrayList);
}
}
}
} //检测当前图元是否跟线段冲突
private boolean detectionRectangleClash(Rectangle currentR,Point start,Point end){
boolean result = false;
//垂直情况下,跟当前图元是否冲突
if(start.x == end.x){
if((currentR.x <= start.x) && (start.x <= currentR.x+currentR.width) ){
result = true;
}
}
//水平连线,是否跟当前图元冲突
else if(start.y == end.y){
if((start.y >= currentR.y) && (start.y <= currentR.y+currentR.height)){
result = true;
}
}
return result;
} /*
* 连线路由
*/
@Override
public void route(Connection conn) {
boolean isPostPoint = false;//回传当前所有点
if(null == points){
points = conn.getPoints();
isPostPoint = true;
}
points.removeAllPoints();// 清空连线 Point startPoint = getStartPoint(conn).getCopy();// 起点
conn.translateToRelative(startPoint);// 设置连接线起点
points.addPoint(startPoint);// 添加到路由连线点集合 endPoint = getEndPoint(conn).getCopy();// 终点
conn.translateToRelative(endPoint);// 设置连接线终点 // 是否能连接
if (validConn(conn)) {
Vector sdirection = getStartDirection(conn);// 得到起始方向
endDirection = getEndDirection(conn);// 终点方向 //连线方向异常情况
if(null == sdirection)
return;
else if(null == endDirection)
endDirection = sdirection; //连线水平或者垂直且源图元跟目标图元没有布局冲突时:调用直线路由算法
if(Arrays.asList(straightLineArr).contains(sdirection)
&& !sourceAcrossCenterPoint
&& !targetAcrossCenterPoint)
processPoints(startPoint, sdirection, null);//调用直线路由算法
//斜向方向、直线但源图元或者目标图元存在布局冲突:调用折线路由算法
else
polyline(startPoint, sdirection) ;//折线路由算法
} // 添加终点到连接线集合
if(null != endPoint)
points.addPoint(endPoint); /////////////////////冲突图元应该在所有拐点连线完成之后再判断、绘制////////////////////////
//当前折线上冲突图元检测
conflictRectangleJudge(conn);
//TODO 修正冲突图元周围的连线轨迹 // 通过连接点设置线轨迹
conn.setPoints(points.getCopy()); //传递当前所有的锚点到编辑器
if(isPostPoint)
FlowEditPart.list = points; //重置参数
endDirection = null;// 清空终点方向
endPoint = null;// 清空终点位置
//将判断连线障碍物冲突规则重置
rectangleAffirm = 0;// 重置图元计数器
parallelSideTarget = null;
parallelSideSource = null;
parallelEndSide = false;
parallelStartSide = false;
sourceAcrossCenterPoint = false;
targetAcrossCenterPoint = false;
sourceRect = null;
targetRect = null;
sourceSide = null;
targetSide = null;
rectangleLinesRelationMap.clear();
conflictRectangleList.clear();
conflictPointArrayList.clear(); } //折线连接
private void polyline(Point startPoint, Vector sdirection) {
//1、直线(垂直、水平)情况,源图元或者目标图元一定存在至少一个图元冲突,其余位置可能存在图元冲突
//源图元冲突
if(sourceAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有源图元冲突
//上边界向下连接
if(sdirection == DOWN){
Point first = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);//向上折点
points.addPoint(first);
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
points.addPoint(second);
Point third = new Point(second.x,endPoint.y - (DEFAULT_SPACE+1));//向下折点
Point fourth =
new Point(startPoint.x,third.y);//向左折点
//如果终点也冲突,不需要当前两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//下边界向上
else if(sdirection == UP){
Point first = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + DEFAULT_SPACE+1);//向上折点
Point fourth = new Point(endPoint.x,third.y);//向左折点 points.addPoint(first);
points.addPoint(second);
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//左边界向右
else if(sdirection == RIGHT){
Point first = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);//向左折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x + DEFAULT_SPACE + sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//右边界向左
else if(sdirection == LEFT){
Point first = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);//向右折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向左折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
}
//存在连线中布局冲突时
else{
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//目标图元冲突
if(targetAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有目标图元冲突
//上边界向下连接(终点在下边界)
if(sdirection == DOWN){
Point first = new Point(endPoint.x,endPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,targetRect.y - DEFAULT_SPACE);//向上折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
//如果源图元有冲突,不需要头两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//下边界向上(终点在上边界)
else if(sdirection == UP){
Point first = new Point(endPoint.x,endPoint.y - DEFAULT_SPACE);//向上折点
Point second =
new Point(endPoint.x + (targetRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + targetRect.width + (DEFAULT_SPACE - 1));//向下折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
///////注意:这里添加拐点的顺序决定了线的形状
//如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//左边界向右(终点在右边界)
else if(sdirection == RIGHT){
Point first = new Point(endPoint.x + DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//右边界向左(终点在左边界)
else if(sdirection == LEFT){
Point first = new Point(endPoint.x - DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x + DEFAULT_SPACE + targetRect.width,second.y);//向右折点
Point fourth = new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
}else{
//存在连线中布局冲突
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//2、折线情况,可能图元冲突也可能没有图元冲突
if(Arrays.asList(brokenLineArr).contains(sdirection)){
//没有冲突图元的情况
if(conflictRectangleList.isEmpty()){
//***************左上方向*******************
if(sdirection == LEFT_UP){
leftUpOrRightDown(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************左下方向*************
else if(sdirection == LEFT_DOWN){
leftDownOrRightUp(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************右上方向*************
else if(sdirection == RIGHT_UP){
leftDownOrRightUp(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
//***************右下方向*************
else if(sdirection == RIGHT_DOWN){
leftUpOrRightDown(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
}
// 存在冲突图元的情况
else{
//取出当前冲突图元跟冲突线段,重新设置拐点
for(Map.Entry<Rectangle,List<Point[]>> relation : rectangleLinesRelationMap.entrySet()){
Rectangle rectangle = relation.getKey();//conflictPointArrayList
List<Point[]> points = relation.getValue();
//通过冲突位置,重新绘制拐点
// TODO
}
}
}
} //左上&右下路由算法(右边图元为源图元)
private void leftUpOrRightDown(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//有上下左右四个边起点
//上边情况
if(sourceSide.equals("上") && targetSide.equals("右")){
//上右边(两种情况)
if(targetRect.y + targetRect.height <= sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
//上上边
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
//上左边
//目标图元在上方是一种连接方法,在下方是另一种连接方法
if((targetRect.y + targetRect.height) <= sourceRect.y){
//目标图元在源图元上方
Point one,two,three;
//如果左边图元的下边框在右边图元的上边框+间距之上,走目标图元的下面连线
if(sourceRect.y > (targetRect.y+targetRect.height+DEFAULT_SPACE)){
one = new Point(startPoint.x,endPoint.y + targetRect.height/2 + DEFAULT_SPACE);
two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}else{
//走目标图元的上边连线
one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}
//通过连线方向控制折点顺序
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
//走目标图元的上边连线
Point one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
Point two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
//上下边(两种情况)
if(targetRect.y < sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}
//左边情况
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three=null,four=null;
//1、左边图元下边在右边图元上边界之上
if((targetRect.y+targetRect.height) < (sourceRect.y - DEFAULT_SPACE)){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}
//2、左边图元下边在右边图元的高度范围内
else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y+targetRect.height+DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}
//右边情况
if(sourceSide.equals("右") && targetSide.equals("右")){
//两种情况
//1、目标图元的下边在源图元上边的上方
if(sourceRect.y > (targetRect.y + targetRect.height)){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
//2、目标图元的下边界在源图元高度范围内
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,startPoint.y - sourceRect.width/2 - DEFAULT_SPACE);
Point three = new Point(sourceRect.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
//两种情况:1、源图元右边界在目标图元右边界左边;2、源图元右边界在目标图元右边界右边
//1、源图元右边界在目标图元右边界左边(需要以目标图元右边界为基准)
Point one,two,three;
int sourceRectRightBorderX = sourceRect.x + sourceRect.width;
int targetRectRightBorderX = targetRect.x + targetRect.width;
if(sourceRectRightBorderX <= targetRectRightBorderX){
one = new Point(targetRectRightBorderX + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}else{
one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元下边界在源图元上边界上面
if((targetRect.y+targetRect.height) < sourceRect.y - DEFAULT_SPACE){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,sourceRect.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - targetRect.width/2 - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//下边情况
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y - DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
} //左下&右上路由算法
private void leftDownOrRightUp(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//异常处理
if(null==sourceSide || null==targetSide || null==sourceRect || null==targetRect)
return;
//起始点在源图元下边界
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)右边界
if(sourceSide.equals("右") && targetSide.equals("右")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元上边界在源图元下边界上面
if((sourceRect.y + sourceRect.height) > targetRect.y){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE + targetRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,startPoint.y + DEFAULT_SPACE + sourceRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)上边界
if(sourceSide.equals("上") && targetSide.equals("右")){
//如果目标图元的有边界在源图元的左边界右边且目标图元的有边界在源图元中心点左边,有5个拐点
if((sourceRect.x + sourceRect.width/2 > endPoint.x)
&& (endPoint.x >= sourceRect.x - DEFAULT_SPACE - DEFAULT_SPACE/2 - 2)){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,sourceRect.y + sourceRect.height + DEFAULT_SPACE);
Point four = new Point(endPoint.x + DEFAULT_SPACE,three.y);
Point five = new Point(four.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
points.addPoint(five);
}else{
points.addPoint(five);
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x ,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//右边图元左边
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three = null,four = null;
//1、右边图元中心点在左边图元上边界的上面
if(startPoint.y < targetRect.y){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y - DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y );
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
} // 设置上下左右方向
private void processPoints(Point startPoint, Vector direction,
Rectangle parallelObs) {
if (direction == UP)
processUp(startPoint, parallelObs);
else if (direction == DOWN)
processDown(startPoint, parallelObs);
else if (direction == LEFT)
processLeft(startPoint, parallelObs);
else if(direction == RIGHT)
processRight(startPoint, parallelObs);
} // 设置向右
private void processRight(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 起始位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;//布局冲突的图元
List<IFigure> list = content.getChildren();// 当前图元的子
// 遍历每个图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前子图元矩形
// 用户在矩形中连线,不操作
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.x > endPoint.x)
continue; // 用户在矩形外连线(起点和终点没有同时在一个矩形上)
int xd = fr.x - startPoint.x;// 矩形左边跟起始点x方向距离(正数:左侧;负数:右侧)
// 如果当前连线起点在图元上
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
// 图元之间水平距离控制
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;// 最后一个子图元
conflictRectangleList.add(obstracle);
}
} } if (min_xd == 0) { // no obstacles
if (parallelObs == null) {
// y坐标直线
if (newStartPoint.y == endPoint.y)
return; } else {
// 连线未到目标图元,继续折叠
if (newStartPoint.x < parallelObs.x)
newStartPoint.x -= (parallelObs.x - newStartPoint.x) / 2;// x坐标对半弯曲
}
// 连线未到目标图元
if (newStartPoint.x < endPoint.x) {
// 如果方向向上或者向下
if (isVertical(endDirection, RIGHT))
newStartPoint.x = endPoint.x;// 重新设置起始x坐标
else {
// 如果方向向右
if (endDirection.equals(RIGHT)) {
newStartPoint.x = endPoint.x + space;// 新起始点坐标 = 终点坐标 +
// 距离障碍物距离
} else
// 方向向左
newStartPoint.x += (endPoint.x - newStartPoint.x) / 2;// 折半弯曲
}
}
}
// 跟图元还有水平间距
else {
int x = newStartPoint.x + min_xd - space;// 重置水平方向
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= parallelObs.x + parallelObs.width)
newStartPoint.x = parallelObs.x + parallelObs.width + space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next
Vector newDirection = UP;
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;
} else {
if (endPoint.y > obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle); } // 处理向左的连接
private void processLeft(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;// 初始化障碍物
List<IFigure> list = content.getChildren(); for (IFigure f : list) {
Rectangle fr = f.getBounds();
// 起始点和结束点在当前图元里面,不绘制连线
// ////////////////这里代表有障碍物,需要绘制绕开障碍物的连线折点///////////////////////////
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.x + fr.width) <= endPoint.x) {
continue;
// TODO 注释掉continue,绘制避开障碍物的折点 } int xd = startPoint.x - fr.x - fr.width;
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_xd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.y == endPoint.y)
return;
} else {
if (newStartPoint.x > parallelObs.x + parallelObs.width)
newStartPoint.x -= (newStartPoint.x - parallelObs.x - parallelObs.width) / 2;
} if (newStartPoint.x > endPoint.x) {
// 水平方向
if (isVertical(endDirection, LEFT))
newStartPoint.x = endPoint.x;// 直接连接到结束的坐标点(设置横线折点x坐标)
else {
// 垂直方向
if (endDirection.equals(LEFT)) {
newStartPoint.x = endPoint.x - space;
} else
newStartPoint.x += (newStartPoint.x - endPoint.x) / 2;
}
}
} else {
int x = newStartPoint.x + min_xd - space;
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= (parallelObs.x + parallelObs.width)) {
newStartPoint.x = parallelObs.x - space;
}
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 添加转折点坐标 // next row point
Vector newDirection = UP;// 初始化连线方向
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;// 判断真实的连线方向
} else {
if (endPoint.y >= obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle);
} // 处理向下的连接
private void processDown(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 建立起始点位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;// 初始化障碍图元(默认没有)
// ///////////这里的图元获取不正确//////////////
List<IFigure> list = content.getChildren();// 得到当前连线中子图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前图元的矩形
// 如果在当前单个图元绘制,不建立连接
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.y > endPoint.y)
continue; int yd = fr.y - startPoint.y;// 当前起始点跟当前图元垂直方向距离(为负数时是起始图元,正数可能存在布局冲突)
// 判断当前图元是否是障碍物
// ////////////会把目标图元也判定成障碍物,需要修改//////////////////
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) { if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;// 设置障碍图元
conflictRectangleList.add(obstracle);
}
}
}
// 如果没有子图元或者没有障碍物
if (min_yd == 0) {
// 不需要去弯曲其他点
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
// 设置第一个弯曲点
if (parallelObs.y > startPoint.y)
newStartPoint.y += (parallelObs.y - startPoint.y) / 2;
}
// 如果还没有连线到结束点
if (newStartPoint.y < endPoint.y) {
// 当前连线绘制方向是水平方向
if (isVertical(endDirection, DOWN)) {
newStartPoint.y = endPoint.y; // 重新设置起始点y坐标
// TODO avoid itself } else {
// 当前方向是向下
if (endDirection.equals(DOWN))
newStartPoint.y = startPoint.y + space;// 转折点y坐标设置
else
newStartPoint.y += (endPoint.y - newStartPoint.y) / 2;// 取中间点位置作为折点
}
}
} else {
// 存在障碍物情况
int y = newStartPoint.y + min_yd - space;
if (y < newStartPoint.y)
y = newStartPoint.y + min_yd / 2;
newStartPoint.y = y;
}
// 父图元、障碍物都不为空
if (parallelObs != null) {
// 起始y坐标在父图元内
if (newStartPoint.y > parallelObs.y
&& newStartPoint.y < parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y + parallelObs.height + space;// 转折点y坐标赋值
}
// 添加转折点到连线集合
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 依次添加转折点 // 下一个转折点
Vector newDirection = LEFT;// 初始化方向向左
// 没有障碍物情况
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;// 连线方向判定
} else {
// 存在障碍物情况
if (endPoint.x > (obstracle.x + obstracle.width))
newDirection = RIGHT;
}
// 调用折线算法,重新设置转折点
processPoints(newStartPoint, newDirection, obstracle);
} // 是否垂直
boolean isVertical(Vector v1, Vector v2) {
double val = v1.x * v2.x + v1.y * v2.y;
if (val == 0)
return true;
return false;
} // 当前点位置是否在矩形中
boolean containPoint(Rectangle r, Point p) {
return p.x >= r.x && p.x <= r.x + r.width && p.y >= r.y
&& p.y <= r.y + r.height;
} // 处理向上的连接
private void processUp(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;
List<IFigure> list = content.getChildren();
for (IFigure f : list) {
Rectangle fr = f.getBounds();
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.y + fr.height) <= endPoint.y)
continue; int yd = startPoint.y - fr.y - fr.height;
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) {
if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_yd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
if (newStartPoint.y > parallelObs.y + parallelObs.height)
newStartPoint.y -= (newStartPoint.y - parallelObs.y - parallelObs.height) / 2;
}
if (newStartPoint.y > endPoint.y) {
if (isVertical(endDirection, UP))
newStartPoint.y = endPoint.y;
else {
if (endDirection.equals(UP)) {
newStartPoint.y = endPoint.y - space;
} else
newStartPoint.y -= (newStartPoint.y - endPoint.y) / 2;
}
}
} else {
int y = newStartPoint.y - min_yd + space;
if (y > newStartPoint.y)
y = newStartPoint.y - min_yd / 2;
newStartPoint.y = y;
}
if (parallelObs != null) {
if (newStartPoint.y >= parallelObs.y
&& newStartPoint.y <= parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y - space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next row point
Vector newDirection = LEFT;
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;
} else {
if (endPoint.x >= obstracle.x)
newDirection = RIGHT;
} processPoints(newStartPoint, newDirection, obstracle);
} //得到当前连线的斜向方向
private Vector getSlantDirection(Point p){
Vector direction = null;
//右上方
if(endPoint.x > p.x && endPoint.y < p.y){
direction = RIGHT_UP;
return direction;
}
//右下方
if(endPoint.x > p.x && endPoint.y > p.y){
direction = RIGHT_DOWN;
return direction;
}
//左上方
if(endPoint.x < p.x && endPoint.y < p.y){
direction = LEFT_UP;
return direction;
}
//左下方
if(endPoint.x < p.x && endPoint.y > p.y){
direction = LEFT_DOWN;
return direction;
}
return direction;
} // 得到当前线条的方向
protected Vector getDirection(Rectangle r, Point p, Connection conn) {
// ////////////////////////////////////////////////////
// 当前连线上只有两个图元: //
// 第一次进来的是 源图元 //
// 第二次进来的是目标图元 //
// ////////////////////////////////////////////////////
rectangleAffirm++; //1:源图元 ; 2:目标图元 Vector direction = LEFT;// 初始化方向 // 如果当前点没有在当前矩形里面,退出
if (!containPoint(r, p))
return null; // 当前连线矩形的四个顶点坐标
Point leftTop = new Point(r.x, r.y),
leftBottom = new Point(r.x, (r.y + r.height)),
rightTop = new Point((r.x + r.width), r.y),
rightBottom = new Point((r.x + r.width), (r.y + r.height)); // 根据图元类别调用判定方向的方法
// *****************************源图元***********************************//
//起点坐标跟边角坐标比较
if (rectangleAffirm == 1) {
// 在上边界的情况
if (p.y == leftTop.y) {
//起始边
sourceSide = "上";
//方向判定
if (endPoint.y == p.y && p.x < endPoint.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (endPoint.y == p.y && p.x > endPoint.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (p.x == endPoint.x && endPoint.y > p.y) {
direction = DOWN;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (p.x == endPoint.x && endPoint.y < p.y) {
direction = UP;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
if ((p.y == rightBottom.y) ||(p.y == rightBottom.y-1)) {
//设置起始边
sourceSide = "下"; //方向判定
//垂直、水平方向
if (endPoint.x == p.x && endPoint.y < leftTop.y) {
direction = UP;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.x == p.x && endPoint.y > leftBottom.y) {
direction = DOWN;
return direction;
}
if (endPoint.y == p.y && rightBottom.x > p.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
if (endPoint.y == p.y && leftBottom.x < p.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
if (p.x == leftTop.x) {
//设置起始边
sourceSide = "左"; //方向判定
//水平、垂直方向情况
if (leftTop.x == endPoint.x && leftTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (leftTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (endPoint.y == p.y && endPoint.x < leftTop.x) {
return direction;
}
if ((endPoint.y-1 == p.y || p.y==endPoint.y) && endPoint.x > rightBottom.x) {
direction = RIGHT;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
if (p.x == rightTop.x) {
//设置起始边
sourceSide = "右"; //方向判定
//水平、垂直
if (rightTop.x == endPoint.x && rightTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if (rightTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if ((endPoint.y == p.y || endPoint.y+1 == p.y) && endPoint.x < leftTop.x) {
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.y == p.y && endPoint.x > rightBottom.x) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
}
// ********************目标图元*****************************//
else {
if(null == sourceRect || null == targetRect)
return null;
//源图元、目标图元的中心点
Point sourceCentPoint =
new Point(sourceRect.x + sourceRect.width/2,sourceRect.y + sourceRect.height/2);
Point targetCentPoint =
new Point(targetRect.x + targetRect.width/2,targetRect.y + targetRect.height/2); //在上边界情况
if (p.y == leftTop.y) {
//设置终点边
targetSide = "上"; //方向判定
//水平、垂直
if (sourceCentPoint.y == targetCentPoint.y && targetCentPoint.x > sourceCentPoint.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于起始边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (sourceCentPoint.y == targetCentPoint.y && targetCentPoint.x < sourceCentPoint.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (sourceCentPoint.y < targetCentPoint.y && targetCentPoint.x == sourceCentPoint.x) {
direction = DOWN;
return direction;
}
if (sourceCentPoint.y > targetCentPoint.y && targetCentPoint.x == sourceCentPoint.x) {
direction = UP;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
else if (p.y == rightBottom.y || p.y==rightBottom.y-1) {
//设置终点边
targetSide = "下"; //方向判定
//水平、垂直
if (sourceCentPoint.y > targetCentPoint.y && targetCentPoint.x == sourceCentPoint.x) {
direction = UP;
return direction;
}
if (sourceCentPoint.y < targetCentPoint.y && targetCentPoint.x == sourceCentPoint.x) {
direction = DOWN;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if (sourceCentPoint.y == targetCentPoint.y && targetCentPoint.x > sourceCentPoint.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
if (sourceCentPoint.y == targetCentPoint.y && targetCentPoint.x < sourceCentPoint.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
else if (p.x == leftTop.x) {
//设置终点边
targetSide = "左"; //方向判定
//直线方向
if (sourceCentPoint.y > targetCentPoint.y
&& targetCentPoint.x == sourceCentPoint.x
&& sourceSide.equals(targetSide)) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if (sourceCentPoint.y < targetCentPoint.y
&& targetCentPoint.x == sourceCentPoint.x
&& sourceSide.equals(targetSide)) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if (sourceCentPoint.y == targetCentPoint.y
&& targetCentPoint.x < sourceCentPoint.x
&& sourceSide.equals(targetSide)) {
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if (sourceCentPoint.y == targetCentPoint.y
&& targetCentPoint.x > sourceCentPoint.x
&& sourceSide.equals(targetSide)) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
else if (p.x == rightTop.x) {
//设置终点边
targetSide = "右"; //方向判定
//直线方向
if (sourceCentPoint.y > targetCentPoint.y && p.x == getStartPoint(conn).getCopy().x) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if (sourceCentPoint.y < targetCentPoint.y && p.x == getStartPoint(conn).getCopy().x) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if (p.y == getStartPoint(conn).getCopy().y && targetCentPoint.x < sourceCentPoint.x) {
//p表示结束点坐标
return direction;
}
else if (p.y == getStartPoint(conn).getCopy().y && targetCentPoint.x > sourceCentPoint.x) {
direction = RIGHT;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
} return direction;
} // 得到当前连接线起始方向
protected Vector getStartDirection(Connection conn) {
ConnectionAnchor anchor = conn.getSourceAnchor();// 获取源连接锚点
Point p = getStartPoint(conn);// 通过连接线获取到起始点坐标
// 如果获取不到源连接锚点,自定义一个矩形图元
if (anchor.getOwner() == null)
sourceRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
sourceRect = conn.getSourceAnchor().getOwner().getBounds().getCopy();// 得到当前矩形
conn.getSourceAnchor().getOwner().translateToAbsolute(sourceRect);// 转换当前矩形
}
return getDirection(sourceRect, p, conn);
} // 得到当前连线的结束方向
protected Vector getEndDirection(Connection conn) {
ConnectionAnchor anchor = conn.getTargetAnchor();
Point p = getEndPoint(conn);
// Point p = endPoint;
if (anchor.getOwner() == null)
targetRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
targetRect = conn.getTargetAnchor().getOwner().getBounds().getCopy();
conn.getTargetAnchor().getOwner().translateToAbsolute(targetRect);
}
return getDirection(targetRect, p, conn);
} // 起点跟源图元冲突时
private void monitorStartCollide(Point startPoint) {
if (parallelStartSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x - bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x + bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
}
} // 终点连线跟源图元冲突时
private void monitorEndCollide(Point endPoint) {
if (parallelEndSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x - bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x + bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
}
} }

第一个版本

  BUG:

  1、垂直连线,当连线起点跟终点距离过短会出现弯曲;

  2、图元缩放会出现栈内存溢出;

  3、连线不支持用户自定义编辑;  

  version 2:

package com.sunsheen.jfids.studio.uml.modulediagram.anchorAndRouter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.eclipse.core.runtime.Assert;
import org.eclipse.draw2d.Bendpoint;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Vector; /**
* uml连接线路由算法
* 1、一旦用户对某条连线的路由方式进行了调整,就不再为其提供智能路由布线的功能。
* 2、用户是否对连线的路径进行了调整的信息是需要持久存储的。
* 3、用户在建模时,只有当发生了连线和模型的布局冲突时,才对存在布局冲突的连线进行路由调整,对其他连线不做更改。
*
* @author WangSong
*/
public class AIUmlConnectionRouter extends BendpointConnectionRouter {
private IFigure content;// 当前操作的图元
public final static int DEFAULT_SPACE = 10;// 默认点间距
private PointList points;// 连线上位置点集合
private int space; /* 离障碍物的间隙 */
private Vector endDirection;// 结束方向
private Point endPoint;// 结束位置
private Point startPoint;//起点位置 // 连线是否跟图元起点边平行
private boolean parallelStartSide;
// 连线是否跟图元终点边平行
private boolean parallelEndSide;
// 连线跟连接点平行的边(源图元)
private String parallelSideSource = ""; // 上下左右
// 连线跟连接点平行的边(目标图元)
private String parallelSideTarget = ""; // 上下左右
private int rectangleAffirm = 0;// 初始化当前图元选择 // 冲突图元、拐点、关联关系
Map<Rectangle,List<Point[]>> rectangleLinesRelationMap = new HashMap<Rectangle,List<Point[]>>();//关联关系
private List<Rectangle> conflictRectangleList = new ArrayList<Rectangle>(); //有冲突的图元
private List<Point[]> conflictPointArrayList = new ArrayList<Point[]>();//存放一对一对冲突的拐点 private boolean sourceAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(原图原)
private boolean targetAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(目标图元)
private Rectangle sourceRect;// 初始化矩形图元
private Rectangle targetRect;//初始化目標圖元
//源点位于源图元的边
private String sourceSide = "";
//目标点位于目标图元的边
private String targetSide = ""; // 初始化上下左右方向(从原点看)
private final Vector
DOWN = new Vector(0, -1),//下
UP = new Vector(0, 1), //上
LEFT = new Vector(-1, 0),//左
RIGHT = new Vector(1, 0),//右 LEFT_UP = new Vector(-1,1),//左上
RIGHT_UP = new Vector(1,1),//右上
LEFT_DOWN = new Vector(-1,-1),//左下
RIGHT_DOWN = new Vector(1,-1);//右下 //直线方向数组
private Vector[] straightLineArr = {DOWN,UP,LEFT,RIGHT};
//折线集合
private Vector[] brokenLineArr = {LEFT_UP,RIGHT_UP,LEFT_DOWN,RIGHT_DOWN}; public AIUmlConnectionRouter(IFigure content) {
this(content, DEFAULT_SPACE);
} public AIUmlConnectionRouter(IFigure content, int space) {
Assert.isNotNull(content);
Assert.isLegal(space > 0, "空间间距不能为0!"); this.content = content;
this.space = space;
} // 是否能连接
private boolean validConn(Connection conn) {
if ((conn.getSourceAnchor() == null)
|| (conn.getTargetAnchor() == null))
return false;
return true;
} //初始化连线间冲突图元集合
private void conflictRectangleJudge(Connection conn){
//获取到连线中的所有图元
List<IFigure> figures = conn.getChildren(); //这种方式获取不到连线中的所有图元,需要修改,后续完成....
///////////////////////////////////////////////////
//得到当前连线上所有图元
//所有图元周围添加拐点 ///////////////////////////////////////////////////
PointList allPoint = conn.getPoints(); //得到冲突图元
for(IFigure f : figures){
Rectangle currentR = f.getBounds().getCopy();//当前图元
f.translateToAbsolute(currentR);//
//取出当前连线所有的拐点
for(int i=0;i<allPoint.size();i++){
//最后一个点时,不能再进行检测
if(i == allPoint.size() - 1)
break;
//两个拐点之间是垂直或者平行的线段,存在有冲突的图元
Point start = allPoint.getPoint(i);
Point end = allPoint.getPoint(i+1);
//会依次检查当前图元是否跟连线冲突
if(detectionRectangleClash(currentR,start,end)){
//可能存在拐点在冲突图元内(两段线段跟当前图元冲突)の情况
//拐点在冲突图元内的情况
if(!conflictRectangleList.contains(currentR)){
conflictRectangleList.add(currentR);//存为冲突图元
} //拐点在冲突图元外的情况
Point[] segment = {start,end};
conflictPointArrayList.add(segment);//存放冲突线段
//存入关联关系
rectangleLinesRelationMap.put(currentR, conflictPointArrayList);
}
}
}
} //检测当前图元是否跟线段冲突
private boolean detectionRectangleClash(Rectangle currentR,Point start,Point end){
boolean result = false;
//垂直情况下,跟当前图元是否冲突
if(start.x == end.x){
if((currentR.x <= start.x) && (start.x <= currentR.x+currentR.width) ){
result = true;
}
}
//水平连线,是否跟当前图元冲突
else if(start.y == end.y){
if((start.y >= currentR.y) && (start.y <= currentR.y+currentR.height)){
result = true;
}
}
return result;
} /*
* 连线路由
*/
@Override
public void route(Connection conn) {
points = conn.getPoints();
points.removeAllPoints();// 清空连线 startPoint = getStartPoint(conn).getCopy();// 起点
conn.translateToRelative(startPoint);// 设置连接线起点
points.addPoint(startPoint);// 添加到路由连线点集合 endPoint = getEndPoint(conn).getCopy();// 终点
conn.translateToRelative(endPoint);// 设置连接线终点 //第一次绘制生成连线,第二次绘制可以拖动的拐点
List bendpoints = (List) getConstraint(conn);
if(null != bendpoints && bendpoints.size() != 0){
//重编辑器处拿到的拐点,添加到拐点位置
for (int i = 0; i < bendpoints.size(); i++) {
Bendpoint bp = (Bendpoint) bendpoints.get(i);
points.addPoint(bp.getLocation());
}
}else{
//第一次绘制时进入
bendpoints = Collections.EMPTY_LIST; // 能连线,绘制连接线
if (validConn(conn)) {
Vector sdirection = getStartDirection(conn);// 得到起始方向
endDirection = getEndDirection(conn);// 终点方向 //连线方向异常情况
if(null == sdirection)
return;
else if(null == endDirection || !sdirection.equals(endDirection))
endDirection = sdirection; //连线水平或者垂直且源图元跟目标图元没有布局冲突时:调用直线路由算法
if(Arrays.asList(straightLineArr).contains(sdirection)
&& !sourceAcrossCenterPoint
&& !targetAcrossCenterPoint)
// processPoints(startPoint, sdirection, null);//调用直线路由算法
super.route(conn);
//斜向方向、直线但源图元或者目标图元存在布局冲突:调用折线路由算法
else
polyline(startPoint, sdirection) ;//折线路由算法
}
} //确保起点跟终点边不为空
getStartDirection(conn);// 得到起始方向
endDirection = getEndDirection(conn);// 终点方向 // 添加终点到连接线集合
if(null != endPoint)
points.addPoint(endPoint); if(null != points && points.size() != 0){
CurrentConnectionPoints.setPoints(points);
CurrentConnectionPoints.setDirection(endDirection);
CurrentConnectionPoints.setStartPoint(startPoint);
CurrentConnectionPoints.setEndPoint(endPoint);
CurrentConnectionPoints.setSourceSide(sourceSide);
CurrentConnectionPoints.setTargetSide(targetSide);
} /////////////////////冲突图元应该在所有拐点连线完成之后再判断、绘制////////////////////////
//当前折线上冲突图元检测
conflictRectangleJudge(conn);
//TODO 修正冲突图元周围的连线轨迹 // 通过连接点设置线轨迹
conn.setPoints(points.getCopy()); //重置参数
endDirection = null;// 清空终点方向
endPoint = null;// 清空终点位置
startPoint = null;//重置起始点位置
//将判断连线障碍物冲突规则重置
rectangleAffirm = 0;// 重置图元计数器
parallelSideTarget = "";
parallelSideSource = "";
parallelEndSide = false;
parallelStartSide = false;
sourceAcrossCenterPoint = false;
targetAcrossCenterPoint = false;
sourceRect = null;
targetRect = null;
rectangleLinesRelationMap.clear();
conflictRectangleList.clear();
conflictPointArrayList.clear();
points = null;
} //折线连接
private void polyline(Point startPoint, Vector sdirection) {
//1、直线(垂直、水平)情况,源图元或者目标图元一定存在至少一个图元冲突,其余位置可能存在图元冲突
//源图元冲突
if(sourceAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有源图元冲突
//上边界向下连接
if(sdirection == DOWN){
Point first = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);//向上折点
points.addPoint(first);
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
points.addPoint(second);
Point third = new Point(second.x,endPoint.y - (DEFAULT_SPACE+1));//向下折点
Point fourth =
new Point(startPoint.x,third.y);//向左折点
//如果终点也冲突,不需要当前两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//下边界向上
else if(sdirection == UP){
Point first = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + DEFAULT_SPACE+1);//向上折点
Point fourth = new Point(endPoint.x,third.y);//向左折点 points.addPoint(first);
points.addPoint(second);
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//左边界向右
else if(sdirection == RIGHT){
Point first = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);//向左折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x + DEFAULT_SPACE + sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//右边界向左
else if(sdirection == LEFT){
Point first = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);//向右折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向左折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
}
//存在连线中布局冲突时
else{
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//目标图元冲突
if(targetAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有目标图元冲突
//上边界向下连接(终点在下边界)
if(sdirection == DOWN){
Point first = new Point(endPoint.x,endPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,targetRect.y - DEFAULT_SPACE);//向上折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
//如果源图元有冲突,不需要头两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//下边界向上(终点在上边界)
else if(sdirection == UP){
Point first = new Point(endPoint.x,endPoint.y - DEFAULT_SPACE);//向上折点
Point second =
new Point(endPoint.x + (targetRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + targetRect.width + (DEFAULT_SPACE - 1));//向下折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
///////注意:这里添加拐点的顺序决定了线的形状
//如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//左边界向右(终点在右边界)
else if(sdirection == RIGHT){
Point first = new Point(endPoint.x + DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//右边界向左(终点在左边界)
else if(sdirection == LEFT){
Point first = new Point(endPoint.x - DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x + DEFAULT_SPACE + targetRect.width,second.y);//向右折点
Point fourth = new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
}else{
//存在连线中布局冲突
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//2、折线情况,可能图元冲突也可能没有图元冲突
if(Arrays.asList(brokenLineArr).contains(sdirection)){
//没有冲突图元的情况
if(conflictRectangleList.isEmpty()){
//***************左上方向*******************
if(sdirection == LEFT_UP){
leftUpOrRightDown(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************左下方向*************
else if(sdirection == LEFT_DOWN){
leftDownOrRightUp(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************右上方向*************
else if(sdirection == RIGHT_UP){
leftDownOrRightUp(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
//***************右下方向*************
else if(sdirection == RIGHT_DOWN){
leftUpOrRightDown(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
}
// 存在冲突图元的情况
else{
//取出当前冲突图元跟冲突线段,重新设置拐点
for(Map.Entry<Rectangle,List<Point[]>> relation : rectangleLinesRelationMap.entrySet()){
Rectangle rectangle = relation.getKey();//conflictPointArrayList
List<Point[]> points = relation.getValue();
//通过冲突位置,重新绘制拐点
// TODO
}
}
}
} //左上&右下路由算法(右边图元为源图元)
private void leftUpOrRightDown(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//有上下左右四个边起点
//上边情况
if(sourceSide.equals("上") && targetSide.equals("右")){
//上右边(两种情况)
if(targetRect.y + targetRect.height <= sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
//上上边
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
//上左边
//目标图元在上方是一种连接方法,在下方是另一种连接方法
if((targetRect.y + targetRect.height) <= sourceRect.y){
//目标图元在源图元上方
Point one,two,three;
//如果左边图元的下边框在右边图元的上边框+间距之上,走目标图元的下面连线
if(sourceRect.y > (targetRect.y+targetRect.height+DEFAULT_SPACE)){
one = new Point(startPoint.x,endPoint.y + targetRect.height/2 + DEFAULT_SPACE);
two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}else{
//走目标图元的上边连线
one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}
//通过连线方向控制折点顺序
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
//走目标图元的上边连线
Point one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
Point two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
//上下边(两种情况)
if(targetRect.y < sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}
//左边情况
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three=null,four=null;
//1、左边图元下边在右边图元上边界之上
if((targetRect.y+targetRect.height) < (sourceRect.y - DEFAULT_SPACE)){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}
//2、左边图元下边在右边图元的高度范围内
else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y+targetRect.height+DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}
//右边情况
if(sourceSide.equals("右") && targetSide.equals("右")){
//两种情况
//1、目标图元的下边在源图元上边的上方
if(sourceRect.y > (targetRect.y + targetRect.height)){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
//2、目标图元的下边界在源图元高度范围内
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,startPoint.y - sourceRect.width/2 - DEFAULT_SPACE);
Point three = new Point(sourceRect.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
//两种情况:1、源图元右边界在目标图元右边界左边;2、源图元右边界在目标图元右边界右边
//1、源图元右边界在目标图元右边界左边(需要以目标图元右边界为基准)
Point one,two,three;
int sourceRectRightBorderX = sourceRect.x + sourceRect.width;
int targetRectRightBorderX = targetRect.x + targetRect.width;
if(sourceRectRightBorderX <= targetRectRightBorderX){
one = new Point(targetRectRightBorderX + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}else{
one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元下边界在源图元上边界上面
if((targetRect.y+targetRect.height) < sourceRect.y - DEFAULT_SPACE){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,sourceRect.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - targetRect.width/2 - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//下边情况
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y - DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
} //左下&右上路由算法
private void leftDownOrRightUp(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//异常处理
if(null==sourceSide || null==targetSide || null==sourceRect || null==targetRect)
return;
//起始点在源图元下边界
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)右边界
if(sourceSide.equals("右") && targetSide.equals("右")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元上边界在源图元下边界上面
if((sourceRect.y + sourceRect.height) > targetRect.y){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE + targetRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,startPoint.y + DEFAULT_SPACE + sourceRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN || endDirection == LEFT){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)上边界
if(sourceSide.equals("上") && targetSide.equals("右")){
//如果目标图元的有边界在源图元的左边界右边且目标图元的有边界在源图元中心点左边,有5个拐点
if((sourceRect.x + sourceRect.width/2 > endPoint.x)
&& (endPoint.x >= sourceRect.x - DEFAULT_SPACE - DEFAULT_SPACE/2 - 2)){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,sourceRect.y + sourceRect.height + DEFAULT_SPACE);
Point four = new Point(endPoint.x + DEFAULT_SPACE,three.y);
Point five = new Point(four.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
points.addPoint(five);
}else{
points.addPoint(five);
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x ,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//右边图元左边
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three = null,four = null;
//1、右边图元中心点在左边图元上边界的上面
if(startPoint.y < targetRect.y){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y - DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y );
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
} // 设置上下左右方向
private void processPoints(Point startPoint, Vector direction,
Rectangle parallelObs) {
if (direction == UP)
processUp(startPoint, parallelObs);
else if (direction == DOWN)
processDown(startPoint, parallelObs);
else if (direction == LEFT)
processLeft(startPoint, parallelObs);
else if(direction == RIGHT)
processRight(startPoint, parallelObs);
} // 设置向右
private void processRight(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 起始位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;//布局冲突的图元
List<IFigure> list = content.getChildren();// 当前图元的子
// 遍历每个图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前子图元矩形
// 用户在矩形中连线,不操作
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.x > endPoint.x)
continue; // 用户在矩形外连线(起点和终点没有同时在一个矩形上)
int xd = fr.x - startPoint.x;// 矩形左边跟起始点x方向距离(正数:左侧;负数:右侧)
// 如果当前连线起点在图元上
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
// 图元之间水平距离控制
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;// 最后一个子图元
conflictRectangleList.add(obstracle);
}
} } if (min_xd == 0) { // no obstacles
if (parallelObs == null) {
// y坐标直线
if (newStartPoint.y == endPoint.y)
return; } else {
// 连线未到目标图元,继续折叠
if (newStartPoint.x < parallelObs.x)
newStartPoint.x -= (parallelObs.x - newStartPoint.x) / 2;// x坐标对半弯曲
}
// 连线未到目标图元
if (newStartPoint.x < endPoint.x) {
// 如果方向向上或者向下
if (isVertical(endDirection, RIGHT))
newStartPoint.x = endPoint.x;// 重新设置起始x坐标
else {
// 如果方向向右
if (endDirection.equals(RIGHT)) {
newStartPoint.x = endPoint.x + space;// 新起始点坐标 = 终点坐标 +
// 距离障碍物距离
} else
// 方向向左
newStartPoint.x += (endPoint.x - newStartPoint.x) / 2;// 折半弯曲
}
}
}
// 跟图元还有水平间距
else {
int x = newStartPoint.x + min_xd - space;// 重置水平方向
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= parallelObs.x + parallelObs.width)
newStartPoint.x = parallelObs.x + parallelObs.width + space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next
Vector newDirection = UP;
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;
} else {
if (endPoint.y > obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle); } // 处理向左的连接
private void processLeft(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;// 初始化障碍物
List<IFigure> list = content.getChildren(); for (IFigure f : list) {
Rectangle fr = f.getBounds();
// 起始点和结束点在当前图元里面,不绘制连线
// ////////////////这里代表有障碍物,需要绘制绕开障碍物的连线折点///////////////////////////
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.x + fr.width) <= endPoint.x) {
continue;
// TODO 注释掉continue,绘制避开障碍物的折点 } int xd = startPoint.x - fr.x - fr.width;
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_xd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.y == endPoint.y)
return;
} else {
if (newStartPoint.x > parallelObs.x + parallelObs.width)
newStartPoint.x -= (newStartPoint.x - parallelObs.x - parallelObs.width) / 2;
} if (newStartPoint.x > endPoint.x) {
// 水平方向
if (isVertical(endDirection, LEFT))
newStartPoint.x = endPoint.x;// 直接连接到结束的坐标点(设置横线折点x坐标)
else {
// 垂直方向
if (endDirection.equals(LEFT)) {
newStartPoint.x = endPoint.x - space;
} else
newStartPoint.x += (newStartPoint.x - endPoint.x) / 2;
}
}
} else {
int x = newStartPoint.x + min_xd - space;
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= (parallelObs.x + parallelObs.width)) {
newStartPoint.x = parallelObs.x - space;
}
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 添加转折点坐标 // next row point
Vector newDirection = UP;// 初始化连线方向
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;// 判断真实的连线方向
} else {
if (endPoint.y >= obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle);
} // 处理向下的连接
private void processDown(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 建立起始点位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;// 初始化障碍图元(默认没有)
// ///////////这里的图元获取不正确//////////////
List<IFigure> list = content.getChildren();// 得到当前连线中子图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前图元的矩形
// 如果在当前单个图元绘制,不建立连接
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.y > endPoint.y)
continue; int yd = fr.y - startPoint.y;// 当前起始点跟当前图元垂直方向距离(为负数时是起始图元,正数可能存在布局冲突)
// 判断当前图元是否是障碍物
// ////////////会把目标图元也判定成障碍物,需要修改//////////////////
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) { if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;// 设置障碍图元
conflictRectangleList.add(obstracle);
}
}
}
// 如果没有子图元或者没有障碍物
if (min_yd == 0) {
// 不需要去弯曲其他点
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
// 设置第一个弯曲点
if (parallelObs.y > startPoint.y)
newStartPoint.y += (parallelObs.y - startPoint.y) / 2;
}
// 如果还没有连线到结束点
if (newStartPoint.y < endPoint.y) {
// 当前连线绘制方向是水平方向
if (isVertical(endDirection, DOWN)) {
newStartPoint.y = endPoint.y; // 重新设置起始点y坐标
// TODO avoid itself } else {
// 当前方向是向下
if (endDirection.equals(DOWN))
newStartPoint.y = startPoint.y + space;// 转折点y坐标设置
else
newStartPoint.y += (endPoint.y - newStartPoint.y) / 2;// 取中间点位置作为折点
}
}
} else {
// 存在障碍物情况
int y = newStartPoint.y + min_yd - space;
if (y < newStartPoint.y)
y = newStartPoint.y + min_yd / 2;
newStartPoint.y = y;
}
// 父图元、障碍物都不为空
if (parallelObs != null) {
// 起始y坐标在父图元内
if (newStartPoint.y > parallelObs.y
&& newStartPoint.y < parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y + parallelObs.height + space;// 转折点y坐标赋值
}
// 添加转折点到连线集合
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 依次添加转折点 // 下一个转折点
Vector newDirection = LEFT;// 初始化方向向左
// 没有障碍物情况
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;// 连线方向判定
} else {
// 存在障碍物情况
if (endPoint.x > (obstracle.x + obstracle.width))
newDirection = RIGHT;
}
// 调用折线算法,重新设置转折点
processPoints(newStartPoint, newDirection, obstracle);
} // 是否垂直
boolean isVertical(Vector v1, Vector v2) {
double val = v1.x * v2.x + v1.y * v2.y;
if (val == 0)
return true;
return false;
} // 当前点位置是否在矩形中
boolean containPoint(Rectangle r, Point p) {
return p.x >= r.x && p.x <= r.x + r.width && p.y >= r.y
&& p.y <= r.y + r.height;
} // 处理向上的连接
private void processUp(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;
List<IFigure> list = content.getChildren();
for (IFigure f : list) {
Rectangle fr = f.getBounds();
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.y + fr.height) <= endPoint.y)
continue; int yd = startPoint.y - fr.y - fr.height;
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) {
if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_yd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
if (newStartPoint.y > parallelObs.y + parallelObs.height)
newStartPoint.y -= (newStartPoint.y - parallelObs.y - parallelObs.height) / 2;
}
if (newStartPoint.y > endPoint.y) {
if (isVertical(endDirection, UP))
newStartPoint.y = endPoint.y;
else {
if (endDirection.equals(UP)) {
newStartPoint.y = endPoint.y - space;
} else
newStartPoint.y -= (newStartPoint.y - endPoint.y) / 2;
}
}
} else {
int y = newStartPoint.y - min_yd + space;
if (y > newStartPoint.y)
y = newStartPoint.y - min_yd / 2;
newStartPoint.y = y;
}
if (parallelObs != null) {
if (newStartPoint.y >= parallelObs.y
&& newStartPoint.y <= parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y - space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next row point
Vector newDirection = LEFT;
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;
} else {
if (endPoint.x >= obstracle.x)
newDirection = RIGHT;
} processPoints(newStartPoint, newDirection, obstracle);
} //得到当前连线的斜向方向
private Vector getSlantDirection(Point p){
Vector direction = null;
//右上方
if(endPoint.x > p.x && endPoint.y < p.y){
direction = RIGHT_UP;
return direction;
}
//右下方
if(endPoint.x > p.x && endPoint.y > p.y){
direction = RIGHT_DOWN;
return direction;
}
//左上方
if(endPoint.x < p.x && endPoint.y < p.y){
direction = LEFT_UP;
return direction;
}
//左下方
if(endPoint.x < p.x && endPoint.y > p.y){
direction = LEFT_DOWN;
return direction;
}
return direction;
} // 得到当前线条的方向
protected Vector getDirection(Rectangle r, Point p, Connection conn) {
// ////////////////////////////////////////////////////
// 当前连线上只有两个图元: //
// 第一次进来的是 源图元 //
// 第二次进来的是目标图元 //
// ////////////////////////////////////////////////////
rectangleAffirm++; //1:源图元 ; 2:目标图元 Vector direction = LEFT;// 初始化方向 // 如果当前点没有在当前矩形里面,退出
if (!containPoint(r, p))
return null; // 当前连线矩形的四个顶点坐标
Point leftTop = new Point(r.x, r.y),
leftBottom = new Point(r.x, (r.y + r.height)),
rightTop = new Point((r.x + r.width), r.y),
rightBottom = new Point((r.x + r.width), (r.y + r.height)); // 根据图元类别调用判定方向
// *****************************源图元***********************************//
//起点坐标跟边角坐标比较
if (rectangleAffirm == 1) {
// 在上边界的情况
if (p.y == leftTop.y) {
//起始边
sourceSide = "上";
//方向判定
if (endPoint.y == p.y && p.x < endPoint.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (endPoint.y == p.y && p.x > endPoint.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (p.x == endPoint.x && endPoint.y > p.y) {
direction = DOWN;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (p.x == endPoint.x && endPoint.y < p.y) {
direction = UP;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
else if ((p.y == rightBottom.y) ||(p.y == rightBottom.y-1)) {
//设置起始边
sourceSide = "下"; //方向判定
//垂直、水平方向
if (endPoint.x == p.x && endPoint.y < leftTop.y) {
direction = UP;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.x == p.x && endPoint.y > leftBottom.y) {
direction = DOWN;
return direction;
}
if (endPoint.y == p.y && rightBottom.x > p.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
if (endPoint.y == p.y && leftBottom.x < p.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
else if (p.x == leftTop.x) {
//设置起始边
sourceSide = "左"; //方向判定
//水平、垂直方向情况
if (leftTop.x == endPoint.x && leftTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (leftTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (endPoint.y == p.y && endPoint.x < leftTop.x) {
return direction;
}
if ((endPoint.y-1 == p.y || p.y==endPoint.y) && endPoint.x > rightBottom.x) {
direction = RIGHT;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
else if (p.x == rightTop.x || p.x == rightTop.x-1) {
//设置起始边
sourceSide = "右"; //方向判定
//水平、垂直
if (rightTop.x == endPoint.x && rightTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if (rightTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if ((endPoint.y == p.y || endPoint.y+1 == p.y) && endPoint.x < leftTop.x) {
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.y == p.y && endPoint.x > rightBottom.x) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
}
// ********************目标图元*****************************//
else {
if(null == sourceRect || null == targetRect)
return null;
//源图元、目标图元的中心点
Point sourceCentPoint =
new Point(sourceRect.x + sourceRect.width/2,sourceRect.y + sourceRect.height/2);
Point targetCentPoint =
new Point(targetRect.x + targetRect.width/2,targetRect.y + targetRect.height/2); Point start = getStartPoint(conn).getCopy(); //在上边界情况
if (p.y == leftTop.y) {
//设置终点边
targetSide = "上"; //方向判定
//水平、垂直
if (start.y == p.y && p.x > start.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于起始边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (start.y == p.y && p.x < start.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
return direction;
}
if (start.y > p.y && p.x == start.x) {
direction = UP;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
else if (p.y == rightBottom.y || p.y==rightBottom.y-1) {
//设置终点边
targetSide = "下"; //方向判定
//水平、垂直
if (start.y > p.y && p.x == start.x) {
direction = UP;
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if (p.y == start.y && p.x > start.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
if (p.y == start.y && p.x < start.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
else if (p.x == leftTop.x) {
//设置终点边
targetSide = "左"; //方向判定
//直线方向
if (start.y > p.y && p.x == start.x) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if ((start.y == p.y || start.y-1 == p.y) && p.x < start.x) {
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if ((start.y == p.y || start.y-1 == p.y) && p.x > start.x) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
else if (p.x == rightTop.x || p.x == rightTop.x-1) {
//设置终点边
targetSide = "右"; //方向判定
//直线方向
if (start.y > p.y && p.x == start.x) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if (start.y < p.y && p.x == start.x) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if ((p.y == start.y || p.y-1 == start.y) && p.x < start.x) {
//p表示结束点坐标
return direction;
}
else if ((p.y == start.y || p.y-1 == start.y) && p.x > start.x) {
direction = RIGHT;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
}
return direction;
} // 得到当前连接线起始方向
protected Vector getStartDirection(Connection conn) {
ConnectionAnchor anchor = conn.getSourceAnchor();// 获取源连接锚点
Point p = getStartPoint(conn);// 通过连接线获取到起始点坐标
// 如果获取不到源连接锚点,自定义一个矩形图元
if (anchor.getOwner() == null)
sourceRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
sourceRect = conn.getSourceAnchor().getOwner().getBounds().getCopy();// 得到当前矩形
conn.getSourceAnchor().getOwner().translateToAbsolute(sourceRect);// 转换当前矩形
}
return getDirection(sourceRect, p, conn);
} // 得到当前连线的结束方向
protected Vector getEndDirection(Connection conn) {
ConnectionAnchor anchor = conn.getTargetAnchor();
Point p = getEndPoint(conn);
// Point p = endPoint;
if (anchor.getOwner() == null)
targetRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
targetRect = conn.getTargetAnchor().getOwner().getBounds().getCopy();
conn.getTargetAnchor().getOwner().translateToAbsolute(targetRect);
}
return getDirection(targetRect, p, conn);
} // 起点跟源图元冲突时
private void monitorStartCollide(Point startPoint) {
if (parallelStartSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x - bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x + bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
}
} // 终点连线跟源图元冲突时
private void monitorEndCollide(Point endPoint) {
if (parallelEndSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x - bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x + bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
}
} }

第二个版本

  BUG:

  1、修复版本1中的垂直连线弯曲问题;

  2、支持用户自定义连线;

  version 3:

package com.sunsheen.jfids.studio.uml.modulediagram.anchorAndRouter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.eclipse.core.runtime.Assert;
import org.eclipse.draw2d.Bendpoint;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Vector; /**
* uml连接线路由算法
* 1、一旦用户对某条连线的路由方式进行了调整,就不再为其提供智能路由布线的功能。
* 2、用户是否对连线的路径进行了调整的信息是需要持久存储的。
* 3、用户在建模时,只有当发生了连线和模型的布局冲突时,才对存在布局冲突的连线进行路由调整,对其他连线不做更改。
*
* @author WangSong
*/
public class AIUmlConnectionRouter extends BendpointConnectionRouter {
private IFigure content;// 当前操作的图元
public final static int DEFAULT_SPACE = 10;// 默认点间距
private PointList points;// 连线上位置点集合
private int space; /* 离障碍物的间隙 */
private Vector endDirection;// 结束方向
private Point endPoint;// 结束位置
private Point startPoint;//起点位置 // 连线是否跟图元起点边平行
private boolean parallelStartSide;
// 连线是否跟图元终点边平行
private boolean parallelEndSide;
// 连线跟连接点平行的边(源图元)
private String parallelSideSource = ""; // 上下左右
// 连线跟连接点平行的边(目标图元)
private String parallelSideTarget = ""; // 上下左右
private int rectangleAffirm = 0;// 初始化当前图元选择 // 冲突图元、拐点、关联关系
Map<Rectangle,List<Point[]>> rectangleLinesRelationMap = new HashMap<Rectangle,List<Point[]>>();//关联关系
private List<Rectangle> conflictRectangleList = new ArrayList<Rectangle>(); //有冲突的图元
private List<Point[]> conflictPointArrayList = new ArrayList<Point[]>();//存放一对一对冲突的拐点 private boolean sourceAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(原图原)
private boolean targetAcrossCenterPoint;//连线是否跨过源图元或者目标图元中心点(目标图元)
private Rectangle sourceRect;// 初始化矩形图元
private Rectangle targetRect;//初始化目標圖元
//源点位于源图元的边
private String sourceSide = "";
//目标点位于目标图元的边
private String targetSide = ""; // 初始化上下左右方向(从原点看)
private final Vector
DOWN = new Vector(0, -1),//下
UP = new Vector(0, 1), //上
LEFT = new Vector(-1, 0),//左
RIGHT = new Vector(1, 0),//右 LEFT_UP = new Vector(-1,1),//左上
RIGHT_UP = new Vector(1,1),//右上
LEFT_DOWN = new Vector(-1,-1),//左下
RIGHT_DOWN = new Vector(1,-1);//右下 //直线方向数组
private Vector[] straightLineArr = {DOWN,UP,LEFT,RIGHT};
//折线集合
private Vector[] brokenLineArr = {LEFT_UP,RIGHT_UP,LEFT_DOWN,RIGHT_DOWN}; public AIUmlConnectionRouter(IFigure content) {
this(content, DEFAULT_SPACE);
} public AIUmlConnectionRouter(IFigure content, int space) {
Assert.isNotNull(content);
Assert.isLegal(space > 0, "空间间距不能为0!"); this.content = content;
this.space = space;
} // 是否能连接
private boolean validConn(Connection conn) {
if ((conn.getSourceAnchor() == null)
|| (conn.getTargetAnchor() == null))
return false;
return true;
} //初始化连线间冲突图元集合
private void conflictRectangleJudge(Connection conn){
//获取到连线中的所有图元
List<IFigure> figures = conn.getChildren(); //这种方式获取不到连线中的所有图元,需要修改,后续完成....
///////////////////////////////////////////////////
//得到当前连线上所有图元
//所有图元周围添加拐点 ///////////////////////////////////////////////////
PointList allPoint = conn.getPoints(); //得到冲突图元
for(IFigure f : figures){
Rectangle currentR = f.getBounds().getCopy();//当前图元
f.translateToAbsolute(currentR);//
//取出当前连线所有的拐点
for(int i=0;i<allPoint.size();i++){
//最后一个点时,不能再进行检测
if(i == allPoint.size() - 1)
break;
//两个拐点之间是垂直或者平行的线段,存在有冲突的图元
Point start = allPoint.getPoint(i);
Point end = allPoint.getPoint(i+1);
//会依次检查当前图元是否跟连线冲突
if(detectionRectangleClash(currentR,start,end)){
//可能存在拐点在冲突图元内(两段线段跟当前图元冲突)の情况
//拐点在冲突图元内的情况
if(!conflictRectangleList.contains(currentR)){
conflictRectangleList.add(currentR);//存为冲突图元
} //拐点在冲突图元外的情况
Point[] segment = {start,end};
conflictPointArrayList.add(segment);//存放冲突线段
//存入关联关系
rectangleLinesRelationMap.put(currentR, conflictPointArrayList);
}
}
}
} //检测当前图元是否跟线段冲突
private boolean detectionRectangleClash(Rectangle currentR,Point start,Point end){
boolean result = false;
//垂直情况下,跟当前图元是否冲突
if(start.x == end.x){
if((currentR.x <= start.x) && (start.x <= currentR.x+currentR.width) ){
result = true;
}
}
//水平连线,是否跟当前图元冲突
else if(start.y == end.y){
if((start.y >= currentR.y) && (start.y <= currentR.y+currentR.height)){
result = true;
}
}
return result;
} /*
* 连线路由
*/
@Override
public void route(Connection conn) {
points = conn.getPoints();
points.removeAllPoints();// 清空连线 startPoint = getStartPoint(conn).getCopy();// 起点
conn.translateToRelative(startPoint);// 设置连接线起点
points.addPoint(startPoint);// 添加到路由连线点集合 endPoint = getEndPoint(conn).getCopy();// 终点
conn.translateToRelative(endPoint);// 设置连接线终点 //第一次绘制生成连线,第二次绘制可以拖动的拐点
List bendpoints = (List) getConstraint(conn);
if(null != bendpoints && bendpoints.size() != 0){
//重编辑器处拿到的拐点,添加到拐点位置
for (int i = 0; i < bendpoints.size(); i++) {
Bendpoint bp = (Bendpoint) bendpoints.get(i);
points.addPoint(bp.getLocation());
}
}else{
//第一次绘制时进入
bendpoints = Collections.EMPTY_LIST; // 能连线,绘制连接线
if (validConn(conn)) {
Vector sdirection = getStartDirection(conn);// 得到起始方向
endDirection = getEndDirection(conn);// 终点方向 //连线方向异常情况
if(null == sdirection)
return;
else if(null == endDirection || !sdirection.equals(endDirection))
endDirection = sdirection; //连线水平或者垂直且源图元跟目标图元没有布局冲突时:调用直线路由算法
if(Arrays.asList(straightLineArr).contains(sdirection)
&& !sourceAcrossCenterPoint
&& !targetAcrossCenterPoint){
// processPoints(startPoint, sdirection, null);//调用直线路由算法---会出现堆栈溢出bug
// super.route(conn);//调用父类的连线路由算法
}
//斜向方向、直线但源图元或者目标图元存在布局冲突:调用折线路由算法
else
polyline(startPoint, sdirection) ;//折线路由算法
}
} //确保起点跟终点边不为空
getStartDirection(conn);// 得到起始方向
endDirection = getEndDirection(conn);// 终点方向 // 添加终点到连接线集合
if(null != endPoint)
points.addPoint(endPoint); if(null != points && points.size() != 0){
CurrentConnectionPoints.setPoints(points);
CurrentConnectionPoints.setDirection(endDirection);
CurrentConnectionPoints.setStartPoint(startPoint);
CurrentConnectionPoints.setEndPoint(endPoint);
CurrentConnectionPoints.setSourceSide(sourceSide);
CurrentConnectionPoints.setTargetSide(targetSide);
} /////////////////////冲突图元应该在所有拐点连线完成之后再判断、绘制////////////////////////
//当前折线上冲突图元检测
conflictRectangleJudge(conn);
//TODO 修正冲突图元周围的连线轨迹 // 通过连接点设置线轨迹
conn.setPoints(points.getCopy()); //重置参数
endDirection = null;// 清空终点方向
endPoint = null;// 清空终点位置
startPoint = null;//重置起始点位置
//将判断连线障碍物冲突规则重置
rectangleAffirm = 0;// 重置图元计数器
parallelSideTarget = "";
parallelSideSource = "";
parallelEndSide = false;
parallelStartSide = false;
sourceAcrossCenterPoint = false;
targetAcrossCenterPoint = false;
sourceRect = null;
targetRect = null;
rectangleLinesRelationMap.clear();
conflictRectangleList.clear();
conflictPointArrayList.clear();
points = null;
} //折线连接
private void polyline(Point startPoint, Vector sdirection) {
//1、直线(垂直、水平)情况,源图元或者目标图元一定存在至少一个图元冲突,其余位置可能存在图元冲突
//源图元冲突
if(sourceAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有源图元冲突
//上边界向下连接
if(sdirection == DOWN){
Point first = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);//向上折点
points.addPoint(first);
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
points.addPoint(second);
Point third = new Point(second.x,endPoint.y - (DEFAULT_SPACE+1));//向下折点
Point fourth =
new Point(startPoint.x,third.y);//向左折点
//如果终点也冲突,不需要当前两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//下边界向上
else if(sdirection == UP){
Point first = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + DEFAULT_SPACE+1);//向上折点
Point fourth = new Point(endPoint.x,third.y);//向左折点 points.addPoint(first);
points.addPoint(second);
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//左边界向右
else if(sdirection == RIGHT){
Point first = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);//向左折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x + DEFAULT_SPACE + sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
//右边界向左
else if(sdirection == LEFT){
Point first = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);//向右折点
Point second =
new Point(first.x,(sourceRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(startPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向左折点
Point fourth =
new Point(third.x,startPoint.y);//向上折点 points.addPoint(first);
points.addPoint(second);
//如果目标图元有冲突,不需要最后两个拐点
if(!targetAcrossCenterPoint){
points.addPoint(third);
points.addPoint(fourth);
}
}
}
//存在连线中布局冲突时
else{
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//目标图元冲突
if(targetAcrossCenterPoint){
//连线中是否存在图元冲突
if(conflictRectangleList.isEmpty()){
//连线中只有目标图元冲突
//上边界向下连接(终点在下边界)
if(sdirection == DOWN){
Point first = new Point(endPoint.x,endPoint.y + DEFAULT_SPACE);//向下折点
Point second =
new Point((startPoint.x) + (sourceRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,targetRect.y - DEFAULT_SPACE);//向上折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
//如果源图元有冲突,不需要头两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//下边界向上(终点在上边界)
else if(sdirection == UP){
Point first = new Point(endPoint.x,endPoint.y - DEFAULT_SPACE);//向上折点
Point second =
new Point(endPoint.x + (targetRect.width / 2+DEFAULT_SPACE),first.y);//向右折点
Point third = new Point(second.x,endPoint.y + targetRect.width + (DEFAULT_SPACE - 1));//向下折点
Point fourth =
new Point(endPoint.x,third.y);//向左折点
///////注意:这里添加拐点的顺序决定了线的形状
//如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//左边界向右(终点在右边界)
else if(sdirection == RIGHT){
Point first = new Point(endPoint.x + DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x - DEFAULT_SPACE - sourceRect.width,second.y);//向右折点
Point fourth =
new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
//右边界向左(终点在左边界)
else if(sdirection == LEFT){
Point first = new Point(endPoint.x - DEFAULT_SPACE,endPoint.y);//向左折点
Point second =
new Point(first.x,(targetRect.height/2 + DEFAULT_SPACE) + first.y);//向下折点
Point third = new Point(endPoint.x + DEFAULT_SPACE + targetRect.width,second.y);//向右折点
Point fourth = new Point(third.x,endPoint.y);//向上折点 //如果源图元有冲突,不需要尾两个拐点
if(!sourceAcrossCenterPoint){
points.addPoint(fourth);
points.addPoint(third);
}
points.addPoint(second);
points.addPoint(first);
}
}else{
//存在连线中布局冲突
for(Rectangle r : conflictRectangleList){
//TODO 绕开冲突图元
}
}
}
//2、折线情况,可能图元冲突也可能没有图元冲突
if(Arrays.asList(brokenLineArr).contains(sdirection)){
//没有冲突图元的情况
if(conflictRectangleList.isEmpty()){
//***************左上方向*******************
if(sdirection == LEFT_UP){
leftUpOrRightDown(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************左下方向*************
else if(sdirection == LEFT_DOWN){
leftDownOrRightUp(startPoint,endPoint,sourceSide,targetSide,sourceRect,targetRect);
}
//***************右上方向*************
else if(sdirection == RIGHT_UP){
leftDownOrRightUp(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
//***************右下方向*************
else if(sdirection == RIGHT_DOWN){
leftUpOrRightDown(endPoint,startPoint,targetSide,sourceSide,targetRect,sourceRect);
}
}
// 存在冲突图元的情况
else{
//取出当前冲突图元跟冲突线段,重新设置拐点
for(Map.Entry<Rectangle,List<Point[]>> relation : rectangleLinesRelationMap.entrySet()){
Rectangle rectangle = relation.getKey();//conflictPointArrayList
List<Point[]> points = relation.getValue();
//通过冲突位置,重新绘制拐点
// TODO
}
}
}
} //左上&右下路由算法(右边图元为源图元)
private void leftUpOrRightDown(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//有上下左右四个边起点
//上边情况
if(sourceSide.equals("上") && targetSide.equals("右")){
//上右边(两种情况)
if(targetRect.y + targetRect.height <= sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
//上上边
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
//上左边
//目标图元在上方是一种连接方法,在下方是另一种连接方法
if((targetRect.y + targetRect.height) <= sourceRect.y){
//目标图元在源图元上方
Point one,two,three;
//如果左边图元的下边框在右边图元的上边框+间距之上,走目标图元的下面连线
if(sourceRect.y > (targetRect.y+targetRect.height+DEFAULT_SPACE)){
one = new Point(startPoint.x,endPoint.y + targetRect.height/2 + DEFAULT_SPACE);
two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}else{
//走目标图元的上边连线
one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
three = new Point(two.x,endPoint.y);
}
//通过连线方向控制折点顺序
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
//走目标图元的上边连线
Point one = new Point(startPoint.x,targetRect.y - DEFAULT_SPACE);
Point two = new Point(targetRect.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
//上下边(两种情况)
if(targetRect.y < sourceRect.y){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}
//左边情况
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three=null,four=null;
//1、左边图元下边在右边图元上边界之上
if((targetRect.y+targetRect.height) < (sourceRect.y - DEFAULT_SPACE)){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}
//2、左边图元下边在右边图元的高度范围内
else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y+targetRect.height+DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}
//右边情况
if(sourceSide.equals("右") && targetSide.equals("右")){
//两种情况
//1、目标图元的下边在源图元上边的上方
if(sourceRect.y > (targetRect.y + targetRect.height)){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else{
//2、目标图元的下边界在源图元高度范围内
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,startPoint.y - sourceRect.width/2 - DEFAULT_SPACE);
Point three = new Point(sourceRect.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
//两种情况:1、源图元右边界在目标图元右边界左边;2、源图元右边界在目标图元右边界右边
//1、源图元右边界在目标图元右边界左边(需要以目标图元右边界为基准)
Point one,two,three;
int sourceRectRightBorderX = sourceRect.x + sourceRect.width;
int targetRectRightBorderX = targetRect.x + targetRect.width;
if(sourceRectRightBorderX <= targetRectRightBorderX){
one = new Point(targetRectRightBorderX + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}else{
one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y - DEFAULT_SPACE);
three = new Point(endPoint.x,two.y);
}
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元下边界在源图元上边界上面
if((targetRect.y+targetRect.height) < sourceRect.y - DEFAULT_SPACE){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,sourceRect.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y - targetRect.width/2 - DEFAULT_SPACE);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//下边情况
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(one.x - sourceRect.width - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y - DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_UP){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
} //左下&右上路由算法
private void leftDownOrRightUp(Point startPoint,Point endPoint,
String sourceSide,String targetSide,
Rectangle sourceRect,Rectangle targetRect){
//异常处理
if(null==sourceSide || null==targetSide || null==sourceRect || null==targetRect)
return;
//起始点在源图元下边界
if(sourceSide.equals("下") && targetSide.equals("右")){
Point one = new Point(startPoint.x,endPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("下") && targetSide.equals("上")){
Point one = new Point(startPoint.x,endPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("下") && targetSide.equals("下")){
Point one = new Point(startPoint.x,endPoint.y + DEFAULT_SPACE);
Point two = new Point(endPoint.x,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)右边界
if(sourceSide.equals("右") && targetSide.equals("右")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("上")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y - DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("右") && targetSide.equals("左")){
//1、目标图元上边界在源图元下边界上面
if((sourceRect.y + sourceRect.height) > targetRect.y){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE + targetRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,startPoint.y + DEFAULT_SPACE + sourceRect.height/2);
Point three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
Point four = new Point(three.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("右") && targetSide.equals("下")){
Point one = new Point(startPoint.x + DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x ,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN || endDirection == LEFT){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//起始点在源图元(右边图元)上边界
if(sourceSide.equals("上") && targetSide.equals("右")){
//如果目标图元的有边界在源图元的左边界右边且目标图元的有边界在源图元中心点左边,有5个拐点
if((sourceRect.x + sourceRect.width/2 > endPoint.x)
&& (endPoint.x >= sourceRect.x - DEFAULT_SPACE - DEFAULT_SPACE/2 - 2)){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,sourceRect.y + sourceRect.height + DEFAULT_SPACE);
Point four = new Point(endPoint.x + DEFAULT_SPACE,three.y);
Point five = new Point(four.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
points.addPoint(five);
}else{
points.addPoint(five);
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else{
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(sourceRect.x - DEFAULT_SPACE ,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
}else if(sourceSide.equals("上") && targetSide.equals("上")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x ,one.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("左")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x - DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("上") && targetSide.equals("下")){
Point one = new Point(startPoint.x,startPoint.y - DEFAULT_SPACE);
Point two = new Point(endPoint.x + targetRect.width/2 + DEFAULT_SPACE,one.y);
Point three = new Point(two.x,endPoint.y + DEFAULT_SPACE);
Point four = new Point(endPoint.x,three.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
points.addPoint(four);
}else{
points.addPoint(four);
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
//右边图元左边
if(sourceSide.equals("左") && targetSide.equals("右")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y);
Point two = new Point(one.x,endPoint.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
}else{
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("上")){
Point one = new Point(endPoint.x,startPoint.y);
points.addPoint(one);
}else if(sourceSide.equals("左") && targetSide.equals("左")){
Point one = null,two = null,three = null,four = null;
//1、右边图元中心点在左边图元上边界的上面
if(startPoint.y < targetRect.y){
one = new Point(endPoint.x - DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,endPoint.y);
}else{
one = new Point(targetRect.x+targetRect.width+DEFAULT_SPACE,startPoint.y);
two = new Point(one.x,targetRect.y - DEFAULT_SPACE);
three = new Point(endPoint.x - DEFAULT_SPACE,two.y);
four = new Point(three.x,endPoint.y);
}
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
if(null != three && null != four){
points.addPoint(three);
points.addPoint(four);
}
}else{
if(null != three && null != four){
points.addPoint(four);
points.addPoint(three);
}
points.addPoint(two);
points.addPoint(one);
}
}else if(sourceSide.equals("左") && targetSide.equals("下")){
Point one = new Point(startPoint.x - DEFAULT_SPACE,startPoint.y );
Point two = new Point(one.x,endPoint.y + DEFAULT_SPACE);
Point three = new Point(endPoint.x,two.y);
if(endDirection == LEFT_DOWN){
points.addPoint(one);
points.addPoint(two);
points.addPoint(three);
}else{
points.addPoint(three);
points.addPoint(two);
points.addPoint(one);
}
}
} // 设置上下左右方向
private void processPoints(Point startPoint, Vector direction,
Rectangle parallelObs) {
if (direction == UP)
processUp(startPoint, parallelObs);
else if (direction == DOWN)
processDown(startPoint, parallelObs);
else if (direction == LEFT)
processLeft(startPoint, parallelObs);
else if(direction == RIGHT)
processRight(startPoint, parallelObs);
} // 设置向右
private void processRight(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 起始位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;//布局冲突的图元
List<IFigure> list = content.getChildren();// 当前图元的子
// 遍历每个图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前子图元矩形
// 用户在矩形中连线,不操作
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.x > endPoint.x)
continue; // 用户在矩形外连线(起点和终点没有同时在一个矩形上)
int xd = fr.x - startPoint.x;// 矩形左边跟起始点x方向距离(正数:左侧;负数:右侧)
// 如果当前连线起点在图元上
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
// 图元之间水平距离控制
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;// 最后一个子图元
conflictRectangleList.add(obstracle);
}
} } if (min_xd == 0) { // no obstacles
if (parallelObs == null) {
// y坐标直线
if (newStartPoint.y == endPoint.y)
return; } else {
// 连线未到目标图元,继续折叠
if (newStartPoint.x < parallelObs.x)
newStartPoint.x -= (parallelObs.x - newStartPoint.x) / 2;// x坐标对半弯曲
}
// 连线未到目标图元
if (newStartPoint.x < endPoint.x) {
// 如果方向向上或者向下
if (isVertical(endDirection, RIGHT))
newStartPoint.x = endPoint.x;// 重新设置起始x坐标
else {
// 如果方向向右
if (endDirection.equals(RIGHT)) {
newStartPoint.x = endPoint.x + space;// 新起始点坐标 = 终点坐标 +
// 距离障碍物距离
} else
// 方向向左
newStartPoint.x += (endPoint.x - newStartPoint.x) / 2;// 折半弯曲
}
}
}
// 跟图元还有水平间距
else {
int x = newStartPoint.x + min_xd - space;// 重置水平方向
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= parallelObs.x + parallelObs.width)
newStartPoint.x = parallelObs.x + parallelObs.width + space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next
Vector newDirection = UP;
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;
} else {
if (endPoint.y > obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle); } // 处理向左的连接
private void processLeft(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_xd = 0;
Rectangle obstracle = null;// 初始化障碍物
List<IFigure> list = content.getChildren(); for (IFigure f : list) {
Rectangle fr = f.getBounds();
// 起始点和结束点在当前图元里面,不绘制连线
// ////////////////这里代表有障碍物,需要绘制绕开障碍物的连线折点///////////////////////////
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.x + fr.width) <= endPoint.x) {
continue;
// TODO 注释掉continue,绘制避开障碍物的折点 } int xd = startPoint.x - fr.x - fr.width;
if (xd > 0 && fr.y <= startPoint.y
&& (fr.y + fr.height) >= startPoint.y) {
if (xd < min_xd || min_xd == 0) {
min_xd = xd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_xd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.y == endPoint.y)
return;
} else {
if (newStartPoint.x > parallelObs.x + parallelObs.width)
newStartPoint.x -= (newStartPoint.x - parallelObs.x - parallelObs.width) / 2;
} if (newStartPoint.x > endPoint.x) {
// 水平方向
if (isVertical(endDirection, LEFT))
newStartPoint.x = endPoint.x;// 直接连接到结束的坐标点(设置横线折点x坐标)
else {
// 垂直方向
if (endDirection.equals(LEFT)) {
newStartPoint.x = endPoint.x - space;
} else
newStartPoint.x += (newStartPoint.x - endPoint.x) / 2;
}
}
} else {
int x = newStartPoint.x + min_xd - space;
if (x < newStartPoint.x)
x = newStartPoint.x + min_xd / 2;
newStartPoint.x = x;
}
if (parallelObs != null) {
if (newStartPoint.x >= parallelObs.x
&& newStartPoint.x <= (parallelObs.x + parallelObs.width)) {
newStartPoint.x = parallelObs.x - space;
}
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 添加转折点坐标 // next row point
Vector newDirection = UP;// 初始化连线方向
if (obstracle == null) {
if (endPoint.y > newStartPoint.y)
newDirection = DOWN;// 判断真实的连线方向
} else {
if (endPoint.y >= obstracle.y)
newDirection = DOWN;
} processPoints(newStartPoint, newDirection, obstracle);
} // 处理向下的连接
private void processDown(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint);// 建立起始点位置 //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;// 初始化障碍图元(默认没有)
// ///////////这里的图元获取不正确//////////////
List<IFigure> list = content.getChildren();// 得到当前连线中子图元
for (IFigure f : list) {
Rectangle fr = f.getBounds();// 当前图元的矩形
// 如果在当前单个图元绘制,不建立连接
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| fr.y > endPoint.y)
continue; int yd = fr.y - startPoint.y;// 当前起始点跟当前图元垂直方向距离(为负数时是起始图元,正数可能存在布局冲突)
// 判断当前图元是否是障碍物
// ////////////会把目标图元也判定成障碍物,需要修改//////////////////
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) { if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;// 设置障碍图元
conflictRectangleList.add(obstracle);
}
}
}
// 如果没有子图元或者没有障碍物
if (min_yd == 0) {
// 不需要去弯曲其他点
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
// 设置第一个弯曲点
if (parallelObs.y > startPoint.y)
newStartPoint.y += (parallelObs.y - startPoint.y) / 2;
}
// 如果还没有连线到结束点
if (newStartPoint.y < endPoint.y) {
// 当前连线绘制方向是水平方向
if (isVertical(endDirection, DOWN)) {
newStartPoint.y = endPoint.y; // 重新设置起始点y坐标
// TODO avoid itself } else {
// 当前方向是向下
if (endDirection.equals(DOWN))
newStartPoint.y = startPoint.y + space;// 转折点y坐标设置
else
newStartPoint.y += (endPoint.y - newStartPoint.y) / 2;// 取中间点位置作为折点
}
}
} else {
// 存在障碍物情况
int y = newStartPoint.y + min_yd - space;
if (y < newStartPoint.y)
y = newStartPoint.y + min_yd / 2;
newStartPoint.y = y;
}
// 父图元、障碍物都不为空
if (parallelObs != null) {
// 起始y坐标在父图元内
if (newStartPoint.y > parallelObs.y
&& newStartPoint.y < parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y + parallelObs.height + space;// 转折点y坐标赋值
}
// 添加转折点到连线集合
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint);// 依次添加转折点 // 下一个转折点
Vector newDirection = LEFT;// 初始化方向向左
// 没有障碍物情况
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;// 连线方向判定
} else {
// 存在障碍物情况
if (endPoint.x > (obstracle.x + obstracle.width))
newDirection = RIGHT;
}
// 调用折线算法,重新设置转折点
processPoints(newStartPoint, newDirection, obstracle);
} // 是否垂直
boolean isVertical(Vector v1, Vector v2) {
double val = v1.x * v2.x + v1.y * v2.y;
if (val == 0)
return true;
return false;
} // 当前点位置是否在矩形中
boolean containPoint(Rectangle r, Point p) {
return p.x >= r.x && p.x <= r.x + r.width && p.y >= r.y
&& p.y <= r.y + r.height;
} // 处理向上的连接
private void processUp(Point startPoint, Rectangle parallelObs) {
Point newStartPoint = new Point(startPoint); //源图元冲突检测
monitorStartCollide(startPoint);
//目标图元冲突检测
monitorEndCollide(endPoint); int min_yd = 0;
Rectangle obstracle = null;
List<IFigure> list = content.getChildren();
for (IFigure f : list) {
Rectangle fr = f.getBounds();
if (containPoint(fr, endPoint) || containPoint(fr, startPoint)
|| (fr.y + fr.height) <= endPoint.y)
continue; int yd = startPoint.y - fr.y - fr.height;
if (yd > 0 && fr.x <= startPoint.x
&& (fr.x + fr.width) >= startPoint.x) {
if (yd < min_yd || min_yd == 0) {
min_yd = yd;
obstracle = fr;
conflictRectangleList.add(obstracle);
}
}
}
if (min_yd == 0) { // no obstacles
// not need bend point
if (parallelObs == null) {
if (newStartPoint.x == endPoint.x)
return;
} else {
if (newStartPoint.y > parallelObs.y + parallelObs.height)
newStartPoint.y -= (newStartPoint.y - parallelObs.y - parallelObs.height) / 2;
}
if (newStartPoint.y > endPoint.y) {
if (isVertical(endDirection, UP))
newStartPoint.y = endPoint.y;
else {
if (endDirection.equals(UP)) {
newStartPoint.y = endPoint.y - space;
} else
newStartPoint.y -= (newStartPoint.y - endPoint.y) / 2;
}
}
} else {
int y = newStartPoint.y - min_yd + space;
if (y > newStartPoint.y)
y = newStartPoint.y - min_yd / 2;
newStartPoint.y = y;
}
if (parallelObs != null) {
if (newStartPoint.y >= parallelObs.y
&& newStartPoint.y <= parallelObs.y + parallelObs.height)
newStartPoint.y = parallelObs.y - space;
}
if (!newStartPoint.equals(startPoint))
points.addPoint(newStartPoint); // next row point
Vector newDirection = LEFT;
if (obstracle == null) {
if (endPoint.x > newStartPoint.x)
newDirection = RIGHT;
} else {
if (endPoint.x >= obstracle.x)
newDirection = RIGHT;
} processPoints(newStartPoint, newDirection, obstracle);
} //得到当前连线的斜向方向
private Vector getSlantDirection(Point p){
Vector direction = null;
//右上方
if(endPoint.x > p.x && endPoint.y < p.y){
direction = RIGHT_UP;
return direction;
}
//右下方
if(endPoint.x > p.x && endPoint.y > p.y){
direction = RIGHT_DOWN;
return direction;
}
//左上方
if(endPoint.x < p.x && endPoint.y < p.y){
direction = LEFT_UP;
return direction;
}
//左下方
if(endPoint.x < p.x && endPoint.y > p.y){
direction = LEFT_DOWN;
return direction;
}
return direction;
} // 得到当前线条的方向
protected Vector getDirection(Rectangle r, Point p, Connection conn) {
// ////////////////////////////////////////////////////
// 当前连线上只有两个图元: //
// 第一次进来的是 源图元 //
// 第二次进来的是目标图元 //
// ////////////////////////////////////////////////////
rectangleAffirm++; //1:源图元 ; 2:目标图元 Vector direction = LEFT;// 初始化方向 // 如果当前点没有在当前矩形里面,退出
if (!containPoint(r, p))
return null; // 当前连线矩形的四个顶点坐标
Point leftTop = new Point(r.x, r.y),
leftBottom = new Point(r.x, (r.y + r.height)),
rightTop = new Point((r.x + r.width), r.y),
rightBottom = new Point((r.x + r.width), (r.y + r.height)); // 根据图元类别调用判定方向
// *****************************源图元***********************************//
//起点坐标跟边角坐标比较
if (rectangleAffirm == 1) {
// 在上边界的情况
if (p.y == leftTop.y) {
//起始边
sourceSide = "上";
//方向判定
if (endPoint.y == p.y && p.x < endPoint.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (endPoint.y == p.y && p.x > endPoint.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "上";// 跟上边界平行
return direction;
}
if (p.x == endPoint.x && endPoint.y > p.y) {
direction = DOWN;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (p.x == endPoint.x && endPoint.y < p.y) {
direction = UP;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
else if ((p.y == rightBottom.y) ||(p.y == rightBottom.y-1)) {
//设置起始边
sourceSide = "下"; //方向判定
//垂直、水平方向
if (endPoint.x == p.x && endPoint.y < leftTop.y) {
direction = UP;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.x == p.x && endPoint.y > leftBottom.y) {
direction = DOWN;
return direction;
}
if (endPoint.y == p.y && rightBottom.x > p.x) {
direction = RIGHT;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
if (endPoint.y == p.y && leftBottom.x < p.x) {
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
else if (p.x == leftTop.x) {
//设置起始边
sourceSide = "左"; //方向判定
//水平、垂直方向情况
if (leftTop.x == endPoint.x && leftTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (leftTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "左";
return direction;
}
if (endPoint.y == p.y && endPoint.x < leftTop.x) {
return direction;
}
if ((endPoint.y-1 == p.y || p.y==endPoint.y) && endPoint.x > rightBottom.x) {
direction = RIGHT;
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
else if (p.x == rightTop.x || p.x == rightTop.x-1) {
//设置起始边
sourceSide = "右"; //方向判定
//水平、垂直
if (rightTop.x == endPoint.x && rightTop.y <= p.y) {
direction = UP;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if (rightTop.x == endPoint.x && rightBottom.y >= p.y) {
direction = DOWN;
parallelStartSide = true; // 平行于起始边界
parallelSideSource = "右";
return direction;
}
if ((endPoint.y == p.y || endPoint.y+1 == p.y) && endPoint.x < leftTop.x) {
sourceAcrossCenterPoint = true;//源图元起点冲突
return direction;
}
if (endPoint.y == p.y && endPoint.x > rightBottom.x) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
}
// ********************目标图元*****************************//
else {
if(null == sourceRect || null == targetRect)
return null;
//源图元、目标图元的中心点
Point sourceCentPoint =
new Point(sourceRect.x + sourceRect.width/2,sourceRect.y + sourceRect.height/2);
Point targetCentPoint =
new Point(targetRect.x + targetRect.width/2,targetRect.y + targetRect.height/2); Point start = getStartPoint(conn).getCopy(); //在上边界情况
if (p.y == leftTop.y) {
//设置终点边
targetSide = "上"; //方向判定
//水平、垂直
if (start.y == p.y && p.x > start.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于起始边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (start.y == p.y && p.x < start.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "上";// 跟上边界平行
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
return direction;
}
if (start.y > p.y && p.x == start.x) {
direction = UP;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在下边界的情况
else if (p.y == rightBottom.y || p.y==rightBottom.y-1) {
//设置终点边
targetSide = "下"; //方向判定
//水平、垂直
if (start.y > p.y && p.x == start.x) {
direction = UP;
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if (p.y == start.y && p.x > start.x) {
direction = RIGHT;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
if (p.y == start.y && p.x < start.x) {
parallelEndSide = true; // 平行于边界
parallelSideTarget = "下";// 跟下边界平行
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在左边界的情况
else if (p.x == leftTop.x) {
//设置终点边
targetSide = "左"; //方向判定
//直线方向
if (start.y > p.y && p.x == start.x) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if (start.y < p.y && p.x == start.x) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "左";
return direction;
}
if ((start.y == p.y || start.y-1 == p.y) && p.x < start.x) {
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
if ((start.y == p.y || start.y-1 == p.y) && p.x > start.x) {
direction = RIGHT;
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
// 在右边界的情况
else if (p.x == rightTop.x || p.x == rightTop.x-1) {
//设置终点边
targetSide = "右"; //方向判定
//直线方向
if (start.y > p.y && p.x == start.x) {
direction = UP;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if (start.y < p.y && p.x == start.x) {
direction = DOWN;
parallelEndSide = true; // 平行于边界
parallelSideTarget = "右";
return direction;
}
else if ((p.y == start.y || p.y-1 == start.y) && p.x < start.x) {
//p表示结束点坐标
return direction;
}
else if ((p.y == start.y || p.y-1 == start.y) && p.x > start.x) {
direction = RIGHT;
targetAcrossCenterPoint = true;//终点图元跟连线冲突
return direction;
}
//斜向方向的情况
direction = getSlantDirection(p);
if(null != direction)
return direction;
}
}
//重置图元计数
if(rectangleAffirm > 1)
rectangleAffirm = 0; return direction;
} // 得到当前连接线起始方向
protected Vector getStartDirection(Connection conn) {
ConnectionAnchor anchor = conn.getSourceAnchor();// 获取源连接锚点
Point p = getStartPoint(conn);// 通过连接线获取到起始点坐标
// 如果获取不到源连接锚点,自定义一个矩形图元
if (anchor.getOwner() == null)
sourceRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
sourceRect = conn.getSourceAnchor().getOwner().getBounds().getCopy();// 得到当前矩形
conn.getSourceAnchor().getOwner().translateToAbsolute(sourceRect);// 转换当前矩形
}
return getDirection(sourceRect, p, conn);
} // 得到当前连线的结束方向
protected Vector getEndDirection(Connection conn) {
ConnectionAnchor anchor = conn.getTargetAnchor();
Point p = getEndPoint(conn);
// Point p = endPoint;
if (anchor.getOwner() == null)
targetRect = new Rectangle(p.x - 1, p.y - 1, 2, 2);
else {
targetRect = conn.getTargetAnchor().getOwner().getBounds().getCopy();
conn.getTargetAnchor().getOwner().translateToAbsolute(targetRect);
}
return getDirection(targetRect, p, conn);
} // 起点跟源图元冲突时
private void monitorStartCollide(Point startPoint) {
if (parallelStartSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x, startPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x - bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideSource)) {
bendPoint = new Point(startPoint.x + bendPointSpace,
startPoint.y);
points.addPoint(bendPoint);
return;
}
}
} // 终点连线跟源图元冲突时
private void monitorEndCollide(Point endPoint) {
if (parallelEndSide) {
Point bendPoint = null;// 初始化弯曲点
int bendPointSpace = 10;// 初始化点间距
// 上边界
if ("上".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
- bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 下边界
if ("下".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x, endPoint.y
+ bendPointSpace);
points.addPoint(bendPoint);
return;
}
// 左边界
if ("左".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x - bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
// 右边界
if ("右".equals(parallelSideTarget)) {
bendPoint = new Point(endPoint.x + bendPointSpace,
endPoint.y);
points.addPoint(bendPoint);
return;
}
}
} }

第三个版本

  BUG:

  1、修复连线后,图元缩放栈内存溢出bug;

仿VISIO连线的更多相关文章

  1. Android耳机线控具体解释,蓝牙耳机button监听(仿酷狗线控效果)

    转载请注明出处:http://blog.csdn.net/fengyuzhengfan/article/details/46461253 当耳机的媒体按键被单击后.Android系统会发出一个广播.该 ...

  2. vue仿京东画线验证码,前端手指位置数据获取

    需求是这样的,京东H5移动端登录,有个安照箭头方向,画线登录的验证,看看是怎么实现的: 直接上代码了: <template> <div v-if="visible" ...

  3. visio中如何取消跨线和去掉页边距

    比较来说,写论文visio和inkscape都不可缺少. 比如visio跨线的问题,已经遇到过两次忘记了.这次截个图作为记录.其实就是在“设计”一栏里,把连接线里面的跨线显示的对勾去掉即可. *** ...

  4. DevExpress 2015.2发布 看看有哪些更新

    下面是besy翻译的部分重要更新,要查看全部更新细节请访问英文官网. | 下载DevExpress 2015.2 Diagram Control 新的DevExpress Diagram Contro ...

  5. iPhone换电池是原装电池好还是换第三方大容量电池好?

    转:https://www.xianjichina.com/news/details_60791.html 最近这段时间苹果降速门事件持续发酵,闹得满城风雨.尽管苹果公司两次致歉,很多果粉都去更换电池 ...

  6. threejs创建地球

    上个月底,在朋友圈看到一个号称“这可能是地球上最美的h5”的分享,点进入后发现这个h5还很别致,思考了一会,决定要不高仿一个? 到今天为止,高仿基本完成, 线上地址 github地址 除了手机端的me ...

  7. visio直线交叉相交跨线修改

    在使用visio画流程图时,经常会遇到两条直线相交.下面讲如何修改使得相交点变成我们想要的方式. 可以设置如下: (1)  全局直线相交,设置跨线标志. (2)  对每条线进行相交跨线设置. (一) ...

  8. 仿微信中加载网页时带线行进度条的WebView的实现

    finddreams:http://blog.csdn.net/finddreams/article/details/44172639 为了仿微信中加载网页时带进度条的WebView的实现,首先我们来 ...

  9. 使用Visio 2007画用例图没有include(包含)关系且包含关系使用的线不是虚线的解决办法

    使用Visio 2007画用例图没有include(包含)关系且包含关系使用的线不是虚线的解决办法 1 在工具栏选择UML------>选择构造型 如下操作 2 拖动 "扩展" ...

随机推荐

  1. 朴素贝叶斯算法java实现(多项式模型)

    网上有很多对朴素贝叶斯算法的说明的文章,在对算法实现前,参考了一下几篇文章: NLP系列(2)_用朴素贝叶斯进行文本分类(上) NLP系列(3)_用朴素贝叶斯进行文本分类(下) 带你搞懂朴素贝叶斯分类 ...

  2. CSS 定位总结

    目录 元素显示模式 元素模式 元素显示模式转换 CSS定位机制 静态定位static 相对定位relative 绝对定位absolute 固定定位fixed 粘性定位sticky 定位小结一图流 CS ...

  3. docker,容器,编排,和基于容器的系统设计模式

    目录 从容器说起 背景 docker实现原理 编排之争 基于容器的分布式系统设计之道 单节点协作模式 Sidecar pattern(边车模式) Ambassador pattern(外交官模式) A ...

  4. Vue $nextTick的一个使用场景

    $nextTick 官方解释 在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM 使用场景 在页面上有2个表单元素和2个按钮 btnRequiredFi ...

  5. 非确定性有穷状态决策自动机练习题Vol.1 A.扭动的回文串

    非确定性有穷状态决策自动机练习题Vol.1 A.扭动的回文串 题目描述 \(JYY\)有两个长度均为\(N\)的字符串\(A\)和\(B\). 一个"扭动字符串\(S(i,j,k)\)由\( ...

  6. Spring Security 实战干货:实现自定义退出登录

    文章目录 1. 前言 2. 我们使用 Spring Security 登录后都做了什么 2. 退出登录需要我们做什么 3. Spring Security 中的退出登录 3.1 LogoutFilte ...

  7. Go语言 | CSP并发模型与Goroutine的基本使用

    今天是golang专题的第13篇文章,我们一起来聊聊golang当中的并发与Goroutine. 在之前的文章当中我们介绍完了golang当中常用的使用方法和规范,在接下来的文章当中和大家聊聊gola ...

  8. Jmeter 常用函数(6)- 详解 __P

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 和 __property 作用一样,不 ...

  9. 基于go+etcd实现分布式锁

    原文链接:https://www.yii-china.com/topic/detail/113 package main import ( "context" "fmt& ...

  10. Federated Optimization for Heterogeneous Networks

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:1812.06127v3 [cs.LG] 11 Jul 2019 目录: Abstract 1 Introduction 2  ...