Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
suliangchun
dbeaver
提交
0b4efec5
D
dbeaver
项目概览
suliangchun
/
dbeaver
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dbeaver
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
0b4efec5
编写于
4月 25, 2022
作者:
G
Gvinepadze Georgy
提交者:
Georgy Gvinepadze
4月 27, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#15755 implement poc for MikimiTabuchi routing
上级
49648342
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
144 addition
and
106 deletion
+144
-106
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/part/DiagramPart.java
...erd.ui/src/org/jkiss/dbeaver/erd/ui/part/DiagramPart.java
+6
-3
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/part/NodePart.java
...er.erd.ui/src/org/jkiss/dbeaver/erd/ui/part/NodePart.java
+1
-1
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/router/MikamiTabuchiConnectionRouter.java
.../dbeaver/erd/ui/router/MikamiTabuchiConnectionRouter.java
+11
-9
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/router/MikamiTabuchiRouter.java
.../org/jkiss/dbeaver/erd/ui/router/MikamiTabuchiRouter.java
+126
-93
未找到文件。
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/part/DiagramPart.java
浏览文件 @
0b4efec5
...
...
@@ -16,7 +16,10 @@
*/
package
org.jkiss.dbeaver.erd.ui.part
;
import
org.eclipse.draw2dl.*
;
import
org.eclipse.draw2dl.ConnectionLayer
;
import
org.eclipse.draw2dl.FanRouter
;
import
org.eclipse.draw2dl.IFigure
;
import
org.eclipse.draw2dl.PolylineConnection
;
import
org.eclipse.draw2dl.geometry.Point
;
import
org.eclipse.draw2dl.geometry.Rectangle
;
import
org.eclipse.gef3.*
;
...
...
@@ -146,9 +149,9 @@ public class DiagramPart extends PropertyAwarePart {
router
.
setSeparation
(
15
);
//router.setNextRouter(new BendpointConnectionRouter());
router
.
setNextRouter
(
new
MikamiTabuchiConnectionRouter
(
figure
));
router
.
setNextRouter
(
new
ManhattanConnectionRouter
());
//
router.setNextRouter(new ManhattanConnectionRouter());
//router.setNextRouter(new BendpointConnectionRouter());
cLayer
.
setConnectionRouter
(
new
ShortestPathConnectionRouter
(
figure
)
);
cLayer
.
setConnectionRouter
(
router
);
return
figure
;
}
...
...
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/part/NodePart.java
浏览文件 @
0b4efec5
...
...
@@ -18,6 +18,6 @@ package org.jkiss.dbeaver.erd.ui.part;
import
org.eclipse.gef3.NodeEditPart
;
abstract
class
NodePart
extends
CustomisablePart
implements
NodeEditPart
{
public
abstract
class
NodePart
extends
CustomisablePart
implements
NodeEditPart
{
}
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/router/MikamiTabuchiConnectionRouter.java
浏览文件 @
0b4efec5
...
...
@@ -62,13 +62,21 @@ public class MikamiTabuchiConnectionRouter extends AbstractRouter {
}
private
void
queueRerouting
()
{
if
(
this
.
connectionToPaths
!=
null
&&
!
this
.
connectionToPaths
.
isEmpty
())
{
try
{
this
.
ignoreInvalidate
=
true
;
((
Connection
)
this
.
connectionToPaths
.
keySet
().
iterator
().
next
()).
revalidate
();
}
finally
{
this
.
ignoreInvalidate
=
false
;
}
}
}
void
addChild
(
IFigure
child
)
{
if
(
this
.
connectionToPath
!=
null
)
{
if
(!
this
.
figuresToBounds
.
containsKey
(
child
))
{
Rectangle
bounds
=
child
.
getBounds
().
getCopy
();
child
.
translateToRelative
(
container
.
getBounds
());
this
.
algorithm
.
addObstacle
(
bounds
);
this
.
figuresToBounds
.
put
(
child
,
bounds
);
child
.
addFigureListener
(
this
.
figureListener
);
...
...
@@ -103,17 +111,12 @@ public class MikamiTabuchiConnectionRouter extends AbstractRouter {
constraint
=
Collections
.
EMPTY_LIST
;
}
Point
start
=
conn
.
getSourceAnchor
().
getReferencePoint
().
getCopy
();
Point
end
=
conn
.
getTargetAnchor
().
getReferencePoint
().
getCopy
();
this
.
container
.
translateToRelative
(
start
);
this
.
container
.
translateToRelative
(
end
);
path
.
setStartPoint
(
start
);
path
.
setEndPoint
(
end
);
path
.
setStartPoint
(
conn
.
getSourceAnchor
().
getOwner
().
getBounds
().
getCenter
());
path
.
setEndPoint
(
conn
.
getTargetAnchor
().
getOwner
().
getBounds
().
getCenter
());
if
(
constraint
.
isEmpty
())
{
path
.
setBendPoints
(
null
);
}
else
{
PointList
bends
=
new
PointList
(
constraint
.
size
());
for
(
Object
o
:
constraint
)
{
Bendpoint
bp
=
(
Bendpoint
)
o
;
bends
.
addPoint
(
bp
.
getLocation
());
...
...
@@ -205,7 +208,6 @@ public class MikamiTabuchiConnectionRouter extends AbstractRouter {
void
removeChild
(
IFigure
child
)
{
if
(
this
.
connectionToPath
!=
null
)
{
Rectangle
bounds
=
child
.
getBounds
().
getCopy
();
child
.
translateToRelative
(
container
.
getBounds
());
boolean
change
=
this
.
algorithm
.
removeObstacle
(
bounds
);
this
.
figuresToBounds
.
remove
(
child
);
child
.
removeFigureListener
(
this
.
figureListener
);
...
...
plugins/org.jkiss.dbeaver.erd.ui/src/org/jkiss/dbeaver/erd/ui/router/MikamiTabuchiRouter.java
浏览文件 @
0b4efec5
...
...
@@ -21,8 +21,8 @@ import org.eclipse.draw2dl.geometry.Point;
import
org.eclipse.draw2dl.geometry.PointList
;
import
org.eclipse.draw2dl.geometry.PrecisionPoint
;
import
org.eclipse.draw2dl.geometry.Rectangle
;
import
org.eclipse.jgit.annotations.Nullable
;
import
org.jkiss.code.NotNull
;
import
org.jkiss.code.Nullable
;
import
org.jkiss.utils.Pair
;
import
java.util.ArrayList
;
...
...
@@ -43,14 +43,13 @@ import java.util.stream.Collectors;
//multi-dimensional arrays for trial lines?
public
class
MikamiTabuchiRouter
{
private
int
spacing
=
0
;
private
int
spacing
=
15
;
private
List
<
Rectangle
>
obstacles
=
new
ArrayList
<>();
private
PrecisionPoint
start
,
finish
;
private
final
List
<
OrthogonalPath
>
userPaths
=
new
ArrayList
<>();
//Increase for performance, increasing this parameter lowers accuracy.
private
static
final
int
STEP_SIZE
=
4
;
private
static
final
int
STEP_SIZE
=
1
;
private
static
final
int
SOURCE_VERTICAL_LINES
=
0
;
private
static
final
int
SOURCE_HORIZONTAL_LINES
=
1
;
...
...
@@ -61,7 +60,7 @@ public class MikamiTabuchiRouter {
//In worst case scenarios line search may become laggy,
//if after this amount iterations nothing was found -> stop
private
static
final
int
MAX_ITER
=
2
;
private
static
final
int
MAX_ITER
=
3
;
Rectangle
clientArea
;
...
...
@@ -73,25 +72,36 @@ public class MikamiTabuchiRouter {
this
.
clientArea
=
clientArea
;
}
private
Pair
<
TrialLine
,
TrialLine
>
result
;
private
void
createLinesFromTrial
(
TrialLine
pos
,
int
iter
)
{
//possible optimisation
//We don't want to create line if line of the same orientation already crosses this point.
float
from
=
pos
.
vertical
?
pos
.
from
.
y
:
pos
.
from
.
x
;
float
start
=
pos
.
start
;
float
end
=
pos
.
finish
;
for
(
float
i
=
start
;
i
<
end
;
i
+=
STEP_SIZE
)
{
TrialLine
trialLine
=
createTrialLine
(
i
,
!
pos
.
vertical
,
pos
);
getLinesMap
(
trialLine
,
iter
).
add
(
trialLine
);
final
TrialLine
interception
=
trialLine
.
findInterception
();
// We found needed line, finish execution
if
(
interception
!=
null
)
{
result
=
new
Pair
<>(
trialLine
,
interception
);
break
;
for
(
float
i
=
(
pos
.
hasForbiddenRange
()
?
pos
.
creationForbiddenStart
-
1
:
from
);
i
>=
start
;
i
-=
STEP_SIZE
)
{
if
(
createTrial
(
pos
,
iter
,
i
))
{
return
;
}
}
for
(
float
i
=
(
pos
.
hasForbiddenRange
()
?
pos
.
creationForbiddenFinish
+
1
:
from
);
i
<
end
;
i
+=
STEP_SIZE
)
{
if
(
createTrial
(
pos
,
iter
,
i
))
{
return
;
}
}
}
private
boolean
createTrial
(
TrialLine
pos
,
int
iter
,
float
i
)
{
TrialLine
trialLine
=
createTrialLine
(
i
,
!
pos
.
vertical
,
pos
);
getLinesMap
(
trialLine
,
iter
).
add
(
trialLine
);
final
TrialLine
interception
=
trialLine
.
findIntersection
();
// We found needed line, finish execution
if
(
interception
!=
null
)
{
result
=
new
Pair
<>(
trialLine
,
interception
);
return
true
;
}
return
false
;
}
@NotNull
...
...
@@ -112,7 +122,7 @@ public class MikamiTabuchiRouter {
}
}
private
Point
getInterceptionPoint
(
TrialLine
source
,
TrialLine
target
)
{
private
P
recisionP
oint
getInterceptionPoint
(
TrialLine
source
,
TrialLine
target
)
{
if
(
source
.
vertical
)
{
return
new
PrecisionPoint
(
source
.
from
.
x
,
target
.
from
.
y
);
}
else
{
...
...
@@ -120,14 +130,13 @@ public class MikamiTabuchiRouter {
}
}
private
TrialLine
createTrialLine
(
float
pos
,
boolean
vertical
,
@N
ullable
TrialLine
parentLine
)
{
private
TrialLine
createTrialLine
(
float
pos
,
boolean
vertical
,
@N
otNull
TrialLine
parentLine
)
{
final
TrialLine
trialLine
;
if
(
vertical
)
{
trialLine
=
new
TrialLine
(
new
PrecisionPoint
(
pos
,
0
),
parentLine
);
trialLine
=
new
TrialLine
(
new
PrecisionPoint
(
pos
,
parentLine
.
from
.
y
),
parentLine
);
}
else
{
trialLine
=
new
TrialLine
(
new
PrecisionPoint
(
0
,
pos
),
parentLine
);
trialLine
=
new
TrialLine
(
new
PrecisionPoint
(
parentLine
.
from
.
x
,
pos
),
parentLine
);
}
trialLine
.
cutByObstacles
();
return
trialLine
;
}
...
...
@@ -152,21 +161,27 @@ public class MikamiTabuchiRouter {
private
PointList
traceback
()
{
PointList
points
=
new
PointList
();
TrialLine
line
=
result
.
getFirst
();
do
{
points
.
addPoint
(
line
.
from
);
PrecisionPoint
point
=
null
;
while
(
line
!=
null
)
{
if
(
point
==
null
||
!
point
.
equals
(
line
.
from
))
{
points
.
addPoint
(
line
.
from
);
}
point
=
line
.
from
;
line
=
line
.
getParent
();
}
while
(
line
!=
null
);
}
points
.
reverse
();
points
.
addPoint
(
getInterceptionPoint
(
result
.
getFirst
(),
result
.
getSecond
()));
point
=
getInterceptionPoint
(
result
.
getFirst
(),
result
.
getSecond
());
points
.
addPoint
(
point
);
line
=
result
.
getSecond
();
do
{
points
.
addPoint
(
line
.
from
);
while
(
line
!=
null
)
{
if
(!
line
.
from
.
equals
(
point
))
{
points
.
addPoint
(
line
.
from
);
}
line
=
line
.
getParent
();
}
while
(
line
!=
null
);
}
return
points
;
}
public
List
<
OrthogonalPath
>
solve
()
{
List
<
OrthogonalPath
>
updated
=
new
ArrayList
<>();
for
(
OrthogonalPath
userPath
:
userPaths
.
stream
().
filter
(
OrthogonalPath:
:
isDirty
).
collect
(
Collectors
.
toList
()))
{
...
...
@@ -182,6 +197,7 @@ public class MikamiTabuchiRouter {
if
(
start
.
equals
(
finish
))
{
return
null
;
}
//Client are
if
(!
clientArea
.
contains
(
start
)
||
!
clientArea
.
contains
(
finish
))
{
return
null
;
}
...
...
@@ -191,9 +207,6 @@ public class MikamiTabuchiRouter {
this
.
finish
=
new
PrecisionPoint
(
finish
);
int
iter
=
0
;
initStartingTrialLines
();
if
(
result
!=
null
)
{
return
traceback
();
}
while
(
iter
!=
MAX_ITER
&&
result
==
null
)
{
linesMap
.
put
(
iter
+
1
,
new
HashMap
<>());
initNewLayer
(
iter
+
1
);
...
...
@@ -210,21 +223,21 @@ public class MikamiTabuchiRouter {
return
null
;
}
private
void
initStartingTrialLines
()
{
//Deviation from an original algorithm, we want only lines what connect with point horizontally
final
TrialLine
horizontalStartTrial
=
new
TrialLine
(
start
,
true
,
false
);
final
TrialLine
verticalStartTrial
=
new
TrialLine
(
start
,
true
,
true
);
final
TrialLine
horizontalFinishTrial
=
new
TrialLine
(
finish
,
false
,
false
);
final
TrialLine
verticalFinishTrial
=
new
TrialLine
(
finish
,
false
,
true
);
linesMap
.
put
(
0
,
new
HashMap
<>());
initNewLayer
(
0
);
//TODO this is bad and awful
linesMap
.
get
(
0
).
get
(
SOURCE_HORIZONTAL_LINES
).
add
(
horizontalStartTrial
);
linesMap
.
get
(
0
).
get
(
TARGET_HORIZONTAL_LINES
).
add
(
horizontalFinishTrial
);
}
/**
* inits list for each type of
* @param iter number of algorithm iteration
*/
private
void
initNewLayer
(
int
iter
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
linesMap
.
get
(
iter
).
put
(
i
,
new
ArrayList
<>());
...
...
@@ -241,108 +254,128 @@ public class MikamiTabuchiRouter {
private
class
TrialLine
{
float
start
=
-
1
;
float
finish
=
-
1
;
float
start
=
Integer
.
MIN_VALUE
;
float
finish
=
Integer
.
MIN_VALUE
;
boolean
fromSource
;
int
creationForbiddenStart
=
Integer
.
MIN_VALUE
;
int
creationForbiddenFinish
=
Integer
.
MIN_VALUE
;
final
PrecisionPoint
from
;
boolean
vertical
;
//Starting line is always inside figure, we don't want to create trial line inside it
private
void
calculateForbiddenRange
()
{
for
(
Rectangle
it
:
obstacles
)
{
if
(
isInsideFigure
(
it
,
true
))
{
if
(
vertical
)
{
creationForbiddenStart
=
it
.
getTop
().
y
-
spacing
;
creationForbiddenFinish
=
it
.
getBottom
().
y
+
spacing
;
}
else
{
creationForbiddenStart
=
it
.
getLeft
().
x
-
spacing
;
creationForbiddenFinish
=
it
.
getRight
().
x
+
spacing
;
}
}
}
}
public
boolean
hasForbiddenRange
()
{
return
creationForbiddenFinish
!=
Integer
.
MIN_VALUE
;
}
@Nullable
TrialLine
parent
;
TrialLine
(
PrecisionPoint
start
,
TrialLine
parent
)
{
TrialLine
(
PrecisionPoint
start
,
@NotNull
TrialLine
parent
)
{
this
.
from
=
start
;
this
.
parent
=
parent
;
this
.
fromSource
=
parent
.
fromSource
;
this
.
vertical
=
!
parent
.
vertical
;
cutByObstacles
();
cutByObstacles
(
false
);
}
TrialLine
(
PrecisionPoint
start
,
boolean
fromSource
,
boolean
vertical
)
{
this
.
from
=
start
;
this
.
vertical
=
vertical
;
this
.
fromSource
=
fromSource
;
cutByObstacles
(
);
this
.
cutByObstacles
(
true
);
this
.
calculateForbiddenRange
();
}
//Resize line if obstacle encountered, if none were encountered make line length equal to client area
//TODO refactor and optimization &
//possible optimisations
//change data structure for bounds
private
boolean
isInsideFigure
(
Rectangle
it
,
boolean
ignoreOffset
)
{
int
offset
=
spacing
;
if
(
ignoreOffset
)
{
offset
=
0
;
}
return
(
it
.
getLeft
().
x
-
offset
<=
from
.
x
&&
it
.
getRight
().
x
+
offset
>
from
.
x
&&
it
.
getTop
().
y
-
offset
<=
from
.
y
&&
it
.
getBottom
().
y
+
offset
>
from
.
y
);
}
private
void
cutByObstacles
()
{
private
void
cutByObstacles
(
boolean
startingLine
)
{
//Check if object is on axis with line, if it is, reduce line size
for
(
Rectangle
it
:
obstacles
)
{
if
(
vertical
&&
it
.
x
-
spacing
<=
from
.
x
&&
it
.
x
+
it
.
width
+
spacing
>
from
.
x
)
{
//object is below need to cut start
if
(
from
.
y
>
it
.
y
+
it
.
height
+
spacing
)
{
if
(
start
==
-
1
||
start
<
it
.
y
+
spacing
)
{
start
=
it
.
y
+
it
.
height
+
spacing
;
}
}
//object is above, need to cut finish
if
(
from
.
y
<=
it
.
y
-
spacing
)
{
if
(
finish
==
-
1
||
finish
>
it
.
y
-
spacing
)
{
finish
=
it
.
y
-
spacing
;
}
if
(
isInsideFigure
(
it
,
false
))
{
if
(
startingLine
)
{
continue
;
}
else
{
cut
(
it
);
}
}
if
(!
vertical
&&
it
.
y
-
spacing
<=
from
.
y
&&
it
.
y
+
it
.
height
+
spacing
>
from
.
y
)
{
//object is behind need to cut start
if
(
from
.
x
>
it
.
x
+
it
.
width
+
spacing
)
{
if
(
start
==
-
1
||
start
<
it
.
x
+
spacing
)
{
start
=
it
.
x
+
it
.
width
+
spacing
;
}
}
//object is ahead, need to cut finish
if
(
from
.
x
<=
it
.
x
-
spacing
)
{
if
(
finish
==
-
1
||
finish
>
it
.
x
-
spacing
)
{
finish
=
it
.
x
-
spacing
;
}
}
if
(
finish
==
-
1
)
{
finish
=
clientArea
.
width
-
spacing
;
}
if
(
vertical
&&
it
.
getLeft
().
x
-
spacing
<=
from
.
x
&&
it
.
getRight
().
x
+
spacing
>
from
.
x
||
!
vertical
&&
it
.
getTop
().
y
-
spacing
<=
from
.
y
&&
it
.
getBottom
().
y
+
spacing
>
from
.
y
)
{
//object is below need to cut start
cut
(
it
);
}
}
if
(
finish
==
-
1
)
{
if
(
finish
==
Integer
.
MIN_VALUE
)
{
if
(
vertical
)
{
finish
=
clientArea
.
height
-
spacing
;
finish
=
clientArea
.
getBottom
().
y
;
}
else
{
finish
=
clientArea
.
width
-
spacing
;
finish
=
clientArea
.
getRight
().
x
;
}
}
if
(
start
==
-
1
)
{
start
=
spacing
;
if
(
start
==
Integer
.
MIN_VALUE
)
{
start
=
vertical
?
clientArea
.
getTop
().
y
:
clientArea
.
getLeft
().
x
;
}
}
private
void
cut
(
Rectangle
bound
)
{
int
fromPosition
=
vertical
?
from
.
y
:
from
.
x
;
int
startPoint
=
vertical
?
bound
.
getTop
().
y
:
bound
.
getLeft
().
x
;
int
endPoint
=
vertical
?
bound
.
getBottom
().
y
:
bound
.
getRight
().
x
;
if
(
fromPosition
>
endPoint
)
{
if
(
start
==
Integer
.
MIN_VALUE
||
start
<
endPoint
+
spacing
)
{
start
=
endPoint
+
spacing
;
}
}
if
(
fromPosition
<=
startPoint
)
{
if
(
finish
==
Integer
.
MIN_VALUE
||
finish
>
startPoint
-
spacing
)
{
finish
=
startPoint
-
spacing
;
}
}
}
@Nullable
public
TrialLine
findInter
cep
tion
()
{
public
TrialLine
findInter
sec
tion
()
{
for
(
int
i
=
linesMap
.
values
().
size
()
-
1
;
i
>=
0
;
i
--)
{
for
(
TrialLine
trialLine
:
getOpposingLinesMap
(
this
,
i
))
{
if
(
vertical
)
{
if
(
this
.
from
.
x
>=
this
.
start
&&
this
.
from
.
x
<
this
.
finish
)
{
if
(
this
.
start
<
this
.
from
.
y
&&
this
.
finish
>=
this
.
from
.
y
)
{
return
trialLine
;
}
}
}
else
{
if
(
this
.
from
.
y
>=
this
.
start
&&
this
.
from
.
y
<
this
.
finish
)
{
if
(
this
.
start
<
this
.
from
.
x
&&
this
.
finish
>=
this
.
from
.
x
)
{
return
trialLine
;
}
}
if
(
intersect
(
trialLine
))
{
return
trialLine
;
}
}
}
return
null
;
}
private
boolean
intersect
(
TrialLine
line
)
{
int
firstLinePos
=
vertical
?
from
.
x
:
from
.
y
;
int
secondLinePos
=
vertical
?
line
.
from
.
y
:
line
.
from
.
x
;
return
firstLinePos
>=
line
.
start
&&
firstLinePos
<
line
.
finish
&&
secondLinePos
>=
start
&&
secondLinePos
<
finish
;
}
@Nullable
public
TrialLine
getParent
()
{
return
parent
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录