我正在构建一个使用jointjs / rappid的应用程序,我希望能够避免在多个单元格之间出现循环。
Jointjs已经有了一些关于如何在单个单元格中避免这种情况的示例(将"out“端口连接到同一单元格的”端口“中),但对于如何检测和防止循环在链中更高的位置上的发生没有任何了解。
为了帮助理解,想象一下论文中的每个单元格都是要完成的一步。每一步只能运行一次。如果最后一步有一个连接到第一个单元格的"in“端口的"out”端口,那么它将永远循环。这就是我想要避免的。
任何帮助都是非常感谢的。
发布于 2018-03-07 09:39:40
图解库
基于Adam图库解,而不是findCycles
来测试循环,图库文档建议使用函数,它:
如果图没有循环,则返回
true
,如果有循环,则返回false
。该算法在检测到第一个循环时立即返回。
因此,这一条件:
if(graphlib.alg.findCycles(graph.toGraphLib()).length > 0)
可缩短为:
if(!graphlib.alg.isAcyclic(graph))
JointJS函数解
// invoke inside an event which tests if a specific `connectedElement` is part of a loop
function isElementPartOfLoop (graph, connectedElement) {
var elemSuccessors = graph.getSuccessors(connectedElement, {deep: true});
var elemAncestors = connectedElement.getAncestors();
// *** OR *** graph.getPredecessors(connectedElement, {deep: true});
var commonElements = _.intersection(elemSuccessors, elemAncestors);
// if an element is repeated (non-empty intersection), then it's part of a loop
return !_.isEmpty(commonElements);
}
我还没有对此进行测试,但是您试图完成的测试背后的理论应该是相似的。这个解决方案不如直接使用图库函数有效。
预防
防止将链接添加到图中的一种方法是在事件中处理链接:
graph.on('add', _.bind(addCellOps, graph));
function addCellOps (cell, collection, opt) {
if (cell.isLink()){
// test link's target element: if it is part of a loop, remove the link
var linkTarget = cell.getTargetElement();
// `this` is the graph
if(target && isElementPartOfLoop(this, linkTarget)){
cell.remove();
}
}
// other operations ....
}
发布于 2018-03-08 10:53:53
实际上,我找到了一种非常简单的方法来实现这一点,对于任何希望实现同样目标的人来说。只需包含图形库依赖项,并使用以下内容:
paper.on("link:connect", function(linkView) {
if(graphlib.alg.findCycles(graph.toGraphLib()).length > 0) {
linkView.model.remove();
// show some error message here
}
});
这一行:
graphlib.alg.findCycles(graph.toGraphLib())
返回一个包含任何循环的数组,因此,通过检查长度,我们可以确定纸张是否包含任何循环,如果是,则删除用户试图创建的链接。
注意:,这并不是完全证明的,因为如果文件已经包含一个循环(在用户添加链接之前),那么简单地删除用户创建的链接就不会删除存在的任何循环。对我来说,这很好,因为我所有的论文都是从零开始创建的,所以只要这个逻辑始终正确,就永远不能创建循环。
https://stackoverflow.com/questions/49089419
复制相似问题