[英]How to prevent loops in jointjs / rappid
我正在构建一个使用jointjs / rappid的应用程序,并且我希望能够避免在多个单元之间发生循环。
Jointjs已经有一些示例,说明如何在单个单元中避免这种情况(将“ out”端口连接到同一单元的“ in”端口),但是对于如何检测和防止链中进一步出现环路一无所知。
为了帮助理解,假设本文中的每个单元格都是要完成的步骤。 每个步骤只能运行一次。 如果最后一步有一个“ out”端口连接到第一个单元格的“ in”端口,它将永远循环。 这就是我要避免的。
任何帮助是极大的赞赏。
实际上,对于所有希望实现同一目标的人,我确实找到了一种非常简单的方法。 只需包括graphlib依赖关系并使用以下命令:
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())
返回一个包含任何循环的数组,因此,通过检查长度,我们可以确定纸张是否包含任何循环,如果存在,则删除用户尝试创建的链接。
注意:这不是完全完全的证明,因为如果纸张已经包含一个循环(在用户添加链接之前),则仅删除用户正在创建的链接不会删除存在的任何循环。 对我而言,这很好,因为我的所有论文都会从头开始创建,只要始终保持这种逻辑,就不会创建循环。
基于Adam的graphlib解决方案 ,graphlib文档建议使用isAcyclic
函数 ,而不是使用findCycles
来测试循环,该函数 :
返回
true
如果图没有周期,并返回false
,如果它。 该算法在检测到第一个周期后立即返回 。
因此,这种情况:
if(graphlib.alg.findCycles(graph.toGraphLib()).length > 0)
可以缩短为:
if(!graphlib.alg.isAcyclic(graph))
// 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);
}
我还没有测试过,但是您要完成的测试背后的理论应该是相似的。 该解决方案的效率不如直接使用graphlib函数。
防止链接添加到图形的一种方法是在事件中进行处理:
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 ....
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.