GEF连线优化 支持额外检测功能的存储线路径的PointList(合并同终点线,分离重合线)
2015-10-27 10:32
399 查看
还存在一些问题 需要不断的优化
PointList 是存储线路径的集合 也是寻路算法router的最终输出结果
如果额外考虑线与线之间的相互影响 则会进一步提高画面的显示效果
我原创的CheckPointList可以支持一些对线间关系的相互处理 注:只是针对于水平,竖直四方向的对线处理线
具体支持的机制如下:
1.支持同终点的连线如果在行进时如果靠的很近,则自动合并。
2.如果是终点不同的连线 则可以将重合的线 进行平移。
3.将直角弯进行圆弧处理,(现在的代码只是最后一个直角弯)
完整代码如下:
PointList 是存储线路径的集合 也是寻路算法router的最终输出结果
如果额外考虑线与线之间的相互影响 则会进一步提高画面的显示效果
我原创的CheckPointList可以支持一些对线间关系的相互处理 注:只是针对于水平,竖直四方向的对线处理线
具体支持的机制如下:
1.支持同终点的连线如果在行进时如果靠的很近,则自动合并。
2.如果是终点不同的连线 则可以将重合的线 进行平移。
3.将直角弯进行圆弧处理,(现在的代码只是最后一个直角弯)
完整代码如下:
import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.Connection; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; @SuppressWarnings("serial") public class CheckedPointList2 extends PointList { // 检测为重合的距离 private int CHECK_DISTANCE = 2; // X方向重合 X方向偏转的距离 private int LINE_OFFSET_X = 1; // Y方向重合和偏转距离 private int LINE_OFFSET_Y = 1; // 机制开关 private boolean on_off = true; // 顺路开关 private boolean on_the_way = false; /****** shoulder *******************************************************/ // 肩膀开关 private boolean shoulder_on_off = true; // shoulder x偏移量 private int SHOULDER_OFFSET_X = 3; // shoulder y偏移量 private int SHOULDER_OFFSET_Y = 3; /****** bridge *******************************************************/ // bridge 开关 private Connection conn; // 其他的线 private List<Connection> othersConnections = new ArrayList<Connection>(); // 记录终点 为顺路提供服务 顺路开关关闭就无需关注了 private Point endPoint; // 候选添加的点 private Point caditatePoint; // 已经添加到List中的最后的点 这个点是可以改变的 private Point lastPoint; public void setConn(Connection conn) { this.conn = conn; refreshConnections(); } public void setOnOffMergeLine(boolean on_off_MergeLine) { on_the_way = on_off_MergeLine; } public void setEndPoint(Point endPoint) { this.endPoint = endPoint; } @SuppressWarnings("unchecked") // 刷新其他线的数据 public void refreshConnections() { othersConnections.clear(); List<Connection> allConnections = conn.getParent().getChildren(); for (int i = 0; i < allConnections.size(); i++) { // 由于不能跟自己比较位置 所以移除自己 if (allConnections.get(i) != conn) { othersConnections.add(allConnections.get(i)); } } } // 添加候选点 public void addCandidatePoint(Point point) { addCandidatePoint(point.x, point.y); } public void addCandidatePoint(int x, int y) { caditatePoint = new Point(x, y); // 如果这是增加的第一或者第二个点,就不用检测了 // 如果这是增加的第一条线就不用了 if (othersConnections.size() == 0 || size() < 2) { addPoint(caditatePoint); } else// 需要校验 { // 取出最后一个 lastPoint = getLastPoint(); removePoint(size() - 1); if (on_off) { if (lastPoint.x == caditatePoint.x) { checkCaditateX(); } else if (lastPoint.y == caditatePoint.y) { checkCaditateY(); } } addCheckedPoints(); } } // 最后点和候选点通过了检验 添加到list中 private void addCheckedPoints() { addPoint(lastPoint); addPoint(caditatePoint); } // 检测准备添加的线的点是否和已有线重叠 X方向 private void checkCaditateX() { // 由于线只有水平竖直两种情况 所以可以区分添加线的类型 // 遍历已有的线 for (int i = 0; i < othersConnections.size(); i++) { Connection conn = othersConnections.get(i); // 获取线的所有的点 PointList pointList = conn.getPoints(); // 遍历线的所有的点 // -1的原因是避免溢出 由于线是水平竖直的 所以相邻点必然是X相同,或是Y相同 我们关注的是两个点的X和检测的点的X相同 // 一个点命中无意义 所以无需检测最后一个 for (int j = 0; j < pointList.size() - 1; j++) { // 由于只有x相同才可能存在重叠 更准确的说是两个相邻的点的x相同 if (Math.abs(pointList.getPoint(j).x - lastPoint.x) <= CHECK_DISTANCE && pointList.getPoint(j).x == pointList.getPoint(j + 1).x)// 这个判断是为了当线与桥重合时,不用来判断为重合 { // 更加详细的判断 // 排序 int y1 = Math.min(pointList.getPoint(j).y, pointList.getPoint(j + 1).y); int y2 = Math.max(pointList.getPoint(j).y, pointList.getPoint(j + 1).y); int y3 = Math.min(lastPoint.y, caditatePoint.y); int y4 = Math.max(lastPoint.y, caditatePoint.y); // 竖直位置相同但不重叠 if (y1 > y4 || y2 < y3) { break; } else // 重叠调整位置 { // 检测是否顺路 如果顺路就停止遍历 并且调整到已有路线的位置 if (on_the_way) { if (endPoint.equals(pointList.getLastPoint().x, pointList.getLastPoint().y)) { lastPoint.x = pointList.getPoint(j).x; caditatePoint.x = pointList.getPoint(j).x; return; } } // 延续已有的方向 偏移 Point frontLastPoint = getLastPoint(); // x增大的趋势 if (frontLastPoint.x < lastPoint.x) { // 右移 lastPoint.x += LINE_OFFSET_X; caditatePoint.x += LINE_OFFSET_X; } else { // 左移 lastPoint.x -= LINE_OFFSET_X; caditatePoint.x -= LINE_OFFSET_X; } // 递归检测新位置 是否有重叠 checkCaditateX(); } } } } } // 检测准备添加的线的点是否和已有线重叠 Y方向 private void checkCaditateY() { // 遍历已有的线 for (int i = 0; i < othersConnections.size(); i++) { Connection conn = othersConnections.get(i); // 判断已有的线是否存在重叠 PointList pointList = conn.getPoints(); // 遍历线的所有的点 for (int j = 0; j < pointList.size() - 1; j++) { // 由于只有x相同才可能存在重叠 更准确的说是两个相邻的点的x相同 if (Math.abs(pointList.getPoint(j).y - lastPoint.y) <= CHECK_DISTANCE && pointList.getPoint(j).y == pointList.getPoint(j + 1).y) { // 更加详细的判断 // 排序 int x1 = Math.min(pointList.getPoint(j).x, pointList.getPoint(j + 1).x); int x2 = Math.max(pointList.getPoint(j).x, pointList.getPoint(j + 1).x); int x3 = Math.min(lastPoint.x, caditatePoint.x); int x4 = Math.max(lastPoint.x, caditatePoint.x); // 竖直位置相同但不重叠 if (x1 > x4 || x2 < x3) { break; } else // 重叠调整位置 { // 检测是否顺路 如果顺路就停止遍历 并且调整到已有路线的位置 if (on_the_way) { if (endPoint.equals(pointList.getLastPoint().x, pointList.getLastPoint().y)) { lastPoint.y = pointList.getPoint(j).y; caditatePoint.y = pointList.getPoint(j).y; return; } } // 延续已有的方向 偏移 Point frontLastPoint = getLastPoint(); if (frontLastPoint.y < lastPoint.y) { // 下移 lastPoint.y += LINE_OFFSET_Y; caditatePoint.y += LINE_OFFSET_Y; } else { // 上移 lastPoint.y -= LINE_OFFSET_Y; caditatePoint.y -= LINE_OFFSET_Y; } checkCaditateY(); } } } } } // shoulder的意思是最后到达终点前避免直角弯 而且提供一个过渡 public void addShoulder() { if (shoulder_on_off == false) { return; } // 如果是直上直下则不用 if (size() > 2) { // 取出后三个点 删除后两个点 int size = size(); Point frontPoint = getPoint(size - 3); Point middlePoint = getPoint(size - 2); Point lastPoint = getPoint(size - 1); // 只有竖直进入的情况 if (lastPoint.x == middlePoint.x && Math.abs(frontPoint.x - middlePoint.x) >= SHOULDER_OFFSET_X) // 安全监测 { Point middleFrontPoint = middlePoint.getCopy(); if (frontPoint.x < middlePoint.x) // "7"形状 { // 左移动两个像素 middleFrontPoint.x = middlePoint.x - SHOULDER_OFFSET_X; } else { // 右移动两个像素 middleFrontPoint.x = middlePoint.x + SHOULDER_OFFSET_X; } // 移除原有拐点 removePoint(size - 2); // 添加中前点 insertPoint(middleFrontPoint, size - 2); Point middleNextPoint = middlePoint.getCopy(); middleNextPoint.y = middlePoint.y + SHOULDER_OFFSET_Y; // 添加中后点 insertPoint(middleNextPoint, size - 1); } } } }使用方式 和需要的基本数据
private CheckedPointList2 points = new CheckedPointList2(); @Override public void route(Connection conn) { // 1. prepare startPoint = getStartPoint(conn).getCopy(); endPoint = getEndPoint(conn).getCopy(); points.removeAllPoints(); points.setConn(conn); points.setOnOffMergeLine(on_off_MergeLine); points.setEndPoint(endPoint); points.addPoint(startPoint); ..... }添加需要进行检测的点
points.addCandidatePoint(x,y);//或 points.addCandidatePoint(new Point(x,y));为最后直角弯添加 肩膀 发生在endPoint 已经被添加之后
points.addPoint(endPoint); points.addShoulder();
相关文章推荐
- rync工具在ssh下使用时遇到的问题
- eclipse常用快捷键
- 通过vnc访问无显卡服务器的图形环境
- Python pip命令
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter
- spring UrlFilter