xyc
2024-09-13 23b4b0e764ba8d7bf73f9c7d999f4144427d31cd
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/service/ModelLineService.java
@@ -1,5 +1,6 @@
package com.zt.life.modules.mainPart.taskReliability.service;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.zt.common.service.BaseService;
@@ -172,23 +173,174 @@
        // 6. 递归计算RBD的布局空间大小
        calcLayoutSize(modelRbd, algorithmList, modelNodeAndVnodeList);
        Collections.reverse(algorithmList);
        RbdTreeNode root2 = listToTree(algorithmList.get(0).getComputerList(), algorithmList, modelNodeAndVnodeList);
        RbdTreeNode root = new RbdTreeNode();
        root.setId(Convert.toLong("20000"));
        root.setName("end");
        root.setNodeType("vnode");
        root.setAlgorithmType("parallel");
        root.setPicId("20000");
        root.setPairStartNodeId("10000");
        root.setBlockWidthNum(root2.getBlockWidthNum() + 2);
        root.setBlockHeightNum(root2.getBlockHeightNum());
        root.getChildren().add(root2);
        // 7. 递归计算RBD的布局空间参数(x、y坐标)
        calcLayoutPosition(modelRbd, algorithmList, modelNodeAndVnodeList);
        root.setBlockX(0);
        root.setBlockY(0);
        calcPosition(rbdJsonArray, root);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("cells", rbdJsonArray);
        modelRbd.setContent(jsonObject.toString());
        //        calcLayoutPosition(modelRbd, algorithmList, modelNodeAndVnodeList);
        // 8. 保存自动布局模型
        // 更新RBD数据
//        modelRbd.setAutoLayoutContent("测试文字");
        modelRbdDao.updateById(modelRbd);
//        modelRbdDao.updateById(modelRbd);
        return result;
    }
    private void setNodePositionXY(JSONArray rbdJsonArray, RbdTreeNode block) {
        Double x = block.getBlockX() + (block.getBlockWidth() - block.getMyWidth()) / 2;
        Double y = block.getBlockY() + (block.getBlockHeight() - block.getMyHeight()) / 2;
        setRbdNodePosition(rbdJsonArray, block.getPicId(), x, y);
    }
    private void calcPosition(JSONArray rbdJsonArray, RbdTreeNode block) {
        if (block.getNodeType().equals("node")) {
            setNodePositionXY(rbdJsonArray, block);
        } else {
            double blockWidth = block.getBlockWidthNum() * LAYOUT_CELL_SIZE_X;
            double blockHeight = block.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y;
            Double descentWidth = block.getDescentWidth();
            if (descentWidth == null || descentWidth == 0.0) {
                descentWidth = blockWidth;
            }
            Double descentHeight = block.getDescentHeight();
            if (descentHeight == null || descentHeight == 0.0) {
                descentHeight = blockHeight;
            }
            block.setBlockWidth(blockWidth);
            block.setBlockHeight(blockHeight);
            List<RbdTreeNode> children = block.getChildren();
            if (OPE_TYPE_SERIES.equals(block.getAlgorithmType())) {
                Double subBlockX = block.getBlockX();
                for (RbdTreeNode child : children) {
                    child.setDescentWidth(blockWidth);
                    child.setDescentHeight(blockHeight);
                    double selfWidth = child.getBlockWidthNum() * LAYOUT_CELL_SIZE_X * descentWidth / blockWidth;
                    child.setBlockWidth(selfWidth);
                    child.setBlockHeight(blockHeight);
                    child.setBlockY(block.getBlockY());
                    child.setBlockX(subBlockX);
                    calcPosition(rbdJsonArray, child);
                    subBlockX = subBlockX + selfWidth;
                }
            } else {
                Double subBlockY = block.getBlockY()+(descentHeight-blockHeight)/2;
                Double firstSubBlockY = subBlockY;
                // 设置connect的位置
                RbdTreeNode connectBlock = new RbdTreeNode();
                connectBlock.setMyWidth(getRbdNodeInfo(rbdJsonArray, block.getPairStartNodeId(), "size/width"));
                connectBlock.setMyHeight(getRbdNodeInfo(rbdJsonArray, block.getPairStartNodeId(), "size/height"));
                connectBlock.setPicId(block.getPairStartNodeId());
                connectBlock.setBlockX(block.getBlockX());
                connectBlock.setBlockY(firstSubBlockY);
                connectBlock.setBlockWidth(LAYOUT_CELL_SIZE_X);
                connectBlock.setBlockHeight(blockHeight);
                setNodePositionXY(rbdJsonArray, connectBlock);
                for (RbdTreeNode child : children) {
                    child.setDescentWidth(block.getBlockWidth() - 2 * LAYOUT_CELL_SIZE_X);
                    child.setDescentHeight(blockHeight);
                    child.setBlockWidth(block.getBlockWidth() - 2 * LAYOUT_CELL_SIZE_X);
                    child.setBlockHeight(child.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y);
                    child.setBlockX(block.getBlockX() + LAYOUT_CELL_SIZE_X);
                    child.setBlockY(subBlockY);
                    subBlockY = subBlockY + child.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y;
                    calcPosition(rbdJsonArray, child);
                }
                // 设置运算符的位置
                RbdTreeNode opeBlock = new RbdTreeNode();
                opeBlock.setPicId(block.getPicId());
                opeBlock.setMyWidth(getRbdNodeInfo(rbdJsonArray, block.getPicId(), "size/width"));
                opeBlock.setMyHeight(getRbdNodeInfo(rbdJsonArray, block.getPicId(), "size/height"));
                opeBlock.setBlockX(block.getBlockX() + blockWidth - LAYOUT_CELL_SIZE_X);
                opeBlock.setBlockY(firstSubBlockY);
                opeBlock.setBlockWidth(LAYOUT_CELL_SIZE_X);
                opeBlock.setBlockHeight(blockHeight);
                setNodePositionXY(rbdJsonArray, opeBlock);
            }
        }
    }
    private RbdTreeNode listToTree(String id,
                                   List<Algorithm> algorithmList,
                                   List<ModelNode> modelNodeAndVnodeList) {
        List<Algorithm> algos = algorithmList.stream().filter(item ->
                id.equals(item.getId().toString())).collect(Collectors.toList());
        RbdTreeNode subNode = new RbdTreeNode();
        subNode.setId(Convert.toLong(id));
        ModelNode nd = modelNodeAndVnodeList.stream().filter(item ->
                id.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
        subNode.setName(nd.getName());
        subNode.setNodeType(nd.getNodeType());
        subNode.setPicId(nd.getPicId());
        if (!"vnode".equals(nd.getNodeType())) {
            subNode.setMyWidth(nd.getWidth());
            subNode.setMyHeight(nd.getHeight());
        }
        subNode.setBlockWidthNum(nd.getVnodeCellNumX());
        subNode.setBlockHeightNum(nd.getVnodeCellNumY());
        subNode.setPairStartNodeId(nd.getPairStartNodeId());
        subNode.setPairEndNodeId(nd.getPairEndNodeId());
        if (algos.size() > 0) {
            Algorithm algo = algos.get(0);
            subNode.setAlgorithmType(algo.getAlgorithmType());
            String str = algo.getComputerList();
            String[] ids = str.split(",");
            for (String subId : ids) {
                subNode.getChildren().add(listToTree(subId, algorithmList, modelNodeAndVnodeList));
            }
        }
        return subNode;
    }
    /*
     */
    /**
     * 根据顶层RBD的位置(x,y),自顶向下递归计算各个节点的位置(x,y)
     *
     * @param modelRbd
     * @param algorithmList
     * @param modelNodeAndVnodeList
     */
     *//*
    private void calcLayoutPosition(ModelRbd modelRbd,
            List<Algorithm> algorithmList,
            List<ModelNode> modelNodeAndVnodeList) {
@@ -200,152 +352,153 @@
                endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
        Algorithm topAlgo = algorithmList.stream().filter(item ->
                endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
        // 将toNode的中心坐标定为(0,0),反算所有节点的坐标
        // 1. 计算并设置start的位置
        double x = -topNode.getVnodeCellNumX()*LAYOUT_CELL_SIZE_X/2 - LAYOUT_START_END_SIZE_X;
        double y = -LAYOUT_START_END_SIZE_Y/2;
        setRbdNodePosition(rbdJsonArray, "10000", x, y);
        // 2. 计算并设置节点的位置
        calcNodeLayoutPosition(rbdJsonArray, algorithmList, modelNodeAndVnodeList, topNode, topAlgo, 0, 0);
        // 3. 计算并设置end的位置
        x = topNode.getVnodeCellNumX()*LAYOUT_CELL_SIZE_X/2;
        // 将topNode的坐标定为Cell(0,0),反算所有节点的坐标
        // 1. 计算节点的Cell位置
        calcNodeLayoutPositionCell(rbdJsonArray, algorithmList, modelNodeAndVnodeList, topNode, topAlgo, 0, 0,
                topNode.getVnodeCellNumX(), topNode.getVnodeCellNumY());
        // 2. 计算节点的x,y坐标位置
        calcNodeLayoutPosition(rbdJsonArray, algorithmList, modelNodeAndVnodeList, topNode, topAlgo);
        // 3. 设置start的位置
        double distance = 200.0;
        double y = (topNode.getPositionCellY() + topNode.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_START_END_SIZE_Y) / 2;
        setRbdNodePosition(rbdJsonArray, "10000", 0 - distance, y);
        // 4. 设置end的位置
        double x = topNode.getVnodeCellNumX() * LAYOUT_CELL_SIZE_X + distance - LAYOUT_START_END_SIZE_X;
        setRbdNodePosition(rbdJsonArray, "20000", x ,y);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("cells", rbdJsonArray);
        modelRbd.setContent(jsonObject.toString());
    }
*/
    // 递归函数
/*
    // 递归函数(计算各节点的x,y坐标位置)
    private void calcNodeLayoutPosition(JSONArray rbdJsonArray,
                                        List<Algorithm> algorithmList,
                                        List<ModelNode> modelNodeAndVnodeList,
                                        ModelNode node,
                                        Algorithm algo,
                                        double x,
                                        double y) {
                                        Algorithm algo) {
        // 未使用设备的实际宽、高
        double x;
        double y;
        if ("node".equals(node.getNodeType())) {
            //设置node(设备节点)布局信息
            node.setPositionX(x - node.getCellNumX()*LAYOUT_CELL_SIZE_X/2);
            node.setPositionY(y - node.getCellNumY()*LAYOUT_CELL_SIZE_Y/2);
            setRbdNodePosition(rbdJsonArray, node.getPicId().toString(), node.getPositionX(), node.getPositionY());
            x = node.getPositionCellX() * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_DEVICE_NODE_SIZE_X) / 2;
            y = node.getPositionCellY() * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_DEVICE_NODE_SIZE_Y) / 2;
            node.setPositionX(x);
            node.setPositionY(y);
            setRbdNodePosition(rbdJsonArray, node.getPicId(), node.getPositionX(), node.getPositionY());
        } else if ("vnode".equals(node.getNodeType())) {
            String[] computerNodeListStr = algo.getComputerList().split(",");
            switch (algo.getAlgorithmType()) {
                case OPE_TYPE_SERIES:
                    int sumCellNumX = 0;
                    for (String nodeStr : computerNodeListStr) {
                        ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                                nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        sumCellNumX += childNode.getVnodeCellNumX();
                    }
                    for (int i=0; i<computerNodeListStr.length; i++) {
                        int idx = i;
                        ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                                computerNodeListStr[idx].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        if (0==i) {
                            double childNodeX = x - sumCellNumX * LAYOUT_CELL_SIZE_X / 2;
                            double childNodeY = y - childNode.getVnodeCellNumY() * LAYOUT_CELL_SIZE_Y / 2;
                            if ("node".equals(childNode.getNodeType())) {
                                childNode.setPositionX(childNodeX);
                                childNode.setPositionY(childNodeY);
                                setRbdNodePosition(rbdJsonArray, childNode.getPicId().toString(), childNode.getPositionX(), childNode.getPositionY());
                            } else {
                                Algorithm childAlgo = algorithmList.stream().filter(item ->
                                        childNode.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                                calcNodeLayoutPosition(rbdJsonArray,
                                        algorithmList,
                                        modelNodeAndVnodeList,
                                        childNode,
                                        childAlgo,
                                        childNodeX,
                                        childNodeY);
                            }
                        } else {
                            int idxPre = i - 1;
                            ModelNode childNodePre = modelNodeAndVnodeList.stream().filter(item ->
                                    computerNodeListStr[idxPre].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                            int idxMe = i;
                            double childNodeX = childNodePre.getPositionX() + childNodePre.getVnodeCellNumX()*LAYOUT_CELL_SIZE_X;
                            double childNodeY = y - childNode.getVnodeCellNumY()*LAYOUT_CELL_SIZE_Y/2;
                            if ("node".equals(childNode.getNodeType())) {
                                childNode.setPositionX(childNodeX);
                                childNode.setPositionY(childNodeY);
                                setRbdNodePosition(rbdJsonArray, childNode.getPicId().toString(), childNode.getPositionX(), childNode.getPositionY());
                            } else {
                                ModelNode childNodeMe = modelNodeAndVnodeList.stream().filter(item ->
                                        computerNodeListStr[idxMe].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                                Algorithm childAlgoMe = algorithmList.stream().filter(item ->
                                        childNodeMe.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                                calcNodeLayoutPosition(rbdJsonArray,
                                        algorithmList,
                                        modelNodeAndVnodeList,
                                        childNode,
                                        childAlgoMe,
                                        childNodePre.getPositionX() + childNodePre.getVnodeCellNumX() * LAYOUT_CELL_SIZE_X,
                                        y - childNodeMe.getVnodeCellNumY() * LAYOUT_CELL_SIZE_Y / 2);
                            }
                        }
                    }
                    break;
                case OPE_TYPE_PARALLEL:
                case OPE_TYPE_SWITCH:
                case OPE_TYPE_VOTE:
                    int sumCellNumY = 0;
                    for (String nodeStr : computerNodeListStr) {
                        ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                                nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        sumCellNumY += childNode.getVnodeCellNumY();
                    }
                    for (int i=0; i<computerNodeListStr.length; i++) {
                        int idx = i;
                        ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                                computerNodeListStr[idx].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        if (0==i) {
                            double childNodeX = x - childNode.getVnodeCellNumX()*LAYOUT_CELL_SIZE_X/2;
                            double childNodeY = y - sumCellNumY*LAYOUT_CELL_SIZE_Y/2;
                            if ("node".equals(childNode.getNodeType())) {
                                childNode.setPositionX(childNodeX);
                                childNode.setPositionY(childNodeY);
                                setRbdNodePosition(rbdJsonArray, childNode.getPicId(), childNode.getPositionX(), childNode.getPositionY());
                            } else {
                                Algorithm childAlgo = algorithmList.stream().filter(item ->
                                        childNode.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
                                childNode.getId().equals(item.getId())).collect(Collectors.toList());
                        Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
                                calcNodeLayoutPosition(rbdJsonArray,
                                        algorithmList,
                                        modelNodeAndVnodeList,
                                        childNode,
                                        childAlgo,
                                        childNodeX,
                                        childNodeY);
                                childAlgo);
                            }
                        } else {
                            int idxPre = i - 1;
                            ModelNode childNodePre = modelNodeAndVnodeList.stream().filter(item ->
                                    computerNodeListStr[idxPre].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                            int idxMe = i;
                            ModelNode childNodeMe = modelNodeAndVnodeList.stream().filter(item ->
                                    computerNodeListStr[idxMe].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                            double childNodeX = x - childNodeMe.getVnodeCellNumY() * LAYOUT_CELL_SIZE_Y / 2;
                            double childNodeY = childNodePre.getPositionY() + childNodePre.getVnodeCellNumY() * LAYOUT_CELL_SIZE_Y;
                            if ("node".equals(childNodeMe.getNodeType())) {
                                childNodeMe.setPositionX(childNodeX);
                                childNodeMe.setPositionY(childNodeY);
                                setRbdNodePosition(rbdJsonArray, childNodeMe.getPicId(), childNodeMe.getPositionX(), childNodeMe.getPositionY());
                            } else {
                                Algorithm childAlgoMe = algorithmList.stream().filter(item ->
                                        childNodeMe.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                                calcNodeLayoutPosition(rbdJsonArray,
                                        algorithmList,
                                        modelNodeAndVnodeList,
                                        childNodeMe,
                                        childAlgoMe,
                                        childNodeX,
                                        childNodeY);
                            }
                        }
                    if (OPE_TYPE_PARALLEL.equals(algo.getAlgorithmType())
                            || OPE_TYPE_SWITCH.equals(algo.getAlgorithmType())
                            || OPE_TYPE_VOTE.equals(algo.getAlgorithmType())) {
                        // 设置connect的位置
                        x = node.getPositionCellX() * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_CONNECT_SIZE_X) / 2;
                        y = (node.getPositionCellY() + node.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_CONNECT_SIZE_Y) / 2;
                        setRbdNodePosition(rbdJsonArray, node.getPairStartNodeId(), x, y);
                        // 设置运算符的位置
                        x = (node.getPositionCellX() + node.getVnodeCellNumX() - 1) * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_OPE_NODE_SIZE_X) / 2;
                        y = (node.getPositionCellY() + node.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_OPE_NODE_SIZE_Y) / 2;
                        setRbdNodePosition(rbdJsonArray, node.getPicId(), x, y);
                    }
                    break;
                case OPE_TYPE_BRIDGE:
                    break;
                default:
                    break;
            }
        }
    }
    // 递归函数(计算各节点的Cell位置,以左上角为Cell位置0,0)
    private void calcNodeLayoutPositionCell(JSONArray rbdJsonArray,
                                            List<Algorithm> algorithmList,
                                            List<ModelNode> modelNodeAndVnodeList,
                                            ModelNode node,
                                            Algorithm algo,
                                            double originCellX,
                                            double originCellY,
                                            double maxX,
                                            double maxY) {
        if ("node".equals(node.getNodeType())) {
            //设置node(设备节点)Cell位置
            double width = LAYOUT_DEVICE_NODE_SIZE_X * maxX;
            double hight = LAYOUT_DEVICE_NODE_SIZE_Y * maxY;
            double x = originCellX + (width - LAYOUT_DEVICE_NODE_SIZE_X) / 2;
            double y = originCellY + (hight - LAYOUT_DEVICE_NODE_SIZE_Y) / 2;
            node.setPositionCellX(x);
            node.setPositionCellY(y);
        } else if ("vnode".equals(node.getNodeType())) {
            String[] computerNodeListStr = algo.getComputerList().split(",");
            switch (algo.getAlgorithmType()) {
                case OPE_TYPE_SERIES:
                case OPE_TYPE_PARALLEL:
                case OPE_TYPE_SWITCH:
                case OPE_TYPE_VOTE:
                    double preNodeCellX = 0.0;
                    double preNodeCellY = 0.0;
                    for (String nodeStr : computerNodeListStr) {
                        ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                                nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                        List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
                                childNode.getId().equals(item.getId())).collect(Collectors.toList());
                        Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
                        if (OPE_TYPE_SERIES.equals(algo.getAlgorithmType())) {
                            calcNodeLayoutPositionCell(rbdJsonArray,
                                    algorithmList,
                                    modelNodeAndVnodeList,
                                    childNode,
                                    childAlgo,
                                    originCellX + preNodeCellX,
                                    originCellY, node.getVnodeCellNumX(), node.getVnodeCellNumY()
                            );
                            preNodeCellX += childNode.getVnodeCellNumX();
                        } else {
                            calcNodeLayoutPositionCell(rbdJsonArray,
                                    algorithmList,
                                    modelNodeAndVnodeList,
                                    childNode,
                                    childAlgo,
                                    originCellX + 1,
                                    originCellY + preNodeCellY, node.getVnodeCellNumX(), node.getVnodeCellNumY());
                            preNodeCellY += childNode.getVnodeCellNumY();
                        }
                    }
*/
/*
                    // 设置运算符的Cell位置
                    if (OPE_TYPE_SERIES.equals(algo.getAlgorithmType())) {
                        node.setPositionCellX(originCellX);
                    } else {
                        node.setPositionCellX(originCellX + node.getVnodeCellNumX() - 1);
                    }
                    node.setPositionCellY(originCellY + node.getVnodeCellNumY()/2);
*//*
                    // 需节点代表整个逻辑单元,因此其坐标为originCellX和originCellX
                    node.setPositionCellX(originCellX);
                    node.setPositionCellY(originCellX);
                    break;
                case OPE_TYPE_BRIDGE:
*/
/*
                    ModelNode node1 = modelNodeAndVnodeList.stream().filter(item ->
                            computerNodeListStr[0].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                    ModelNode node2 = modelNodeAndVnodeList.stream().filter(item ->
@@ -373,55 +526,58 @@
                    int secondRowCellNumY = node3.getVnodeCellNumY();
                    // 1.3 计算第三行两个节点的高度
                    int thirdRowCellNumY = Math.max(node4.getVnodeCellNumY(), node5.getVnodeCellNumY());
                    int totalCellNumY = firstRowCellNumY + secondRowCellNumY + thirdRowCellNumY;
//                    int totalCellNumY = firstRowCellNumY + secondRowCellNumY + thirdRowCellNumY;
                    // 2. 计算三行各节点的坐标
                    // 2.1 计算第一行两个节点的坐标
                    calcNodeLayoutPosition(rbdJsonArray,
                    calcNodeLayoutPositionCell(rbdJsonArray,
                            algorithmList,
                            modelNodeAndVnodeList,
                            node1,
                            algo1,
                            x - (node1.getVnodeCellNumX() + node2.getVnodeCellNumX())*LAYOUT_CELL_SIZE_X/2,
                            y - (totalCellNumY-firstRowCellNumY+node1.getVnodeCellNumY())*LAYOUT_CELL_SIZE_Y/2);
                    calcNodeLayoutPosition(rbdJsonArray,
                            originCellX + 1,
                            originCellY);
                    calcNodeLayoutPositionCell(rbdJsonArray,
                            algorithmList,
                            modelNodeAndVnodeList,
                            node2,
                            algo2,
                            x + (node1.getVnodeCellNumX() + node2.getVnodeCellNumX())*LAYOUT_CELL_SIZE_X/2,
                            y - (totalCellNumY-firstRowCellNumY+node2.getVnodeCellNumY())*LAYOUT_CELL_SIZE_Y/2);
                            originCellX + 1 + node1.getPositionCellX(),
                            originCellY);
                    // 2.2 计算第二行桥联节点的坐标
                    calcNodeLayoutPosition(rbdJsonArray,
                    calcNodeLayoutPositionCell(rbdJsonArray,
                            algorithmList,
                            modelNodeAndVnodeList,
                            node2,
                            algo2,
                            x - node3.getVnodeCellNumX()*LAYOUT_CELL_SIZE_X/2,
                            y - (totalCellNumY/2-firstRowCellNumY)*LAYOUT_CELL_SIZE_Y);
                            node3,
                            algo3,
                            originCellX + 1,
                            originCellY + firstRowCellNumY);
                    // 2.3 计算第三行两个节点的坐标
                    calcNodeLayoutPosition(rbdJsonArray,
                    calcNodeLayoutPositionCell(rbdJsonArray,
                            algorithmList,
                            modelNodeAndVnodeList,
                            node1,
                            algo1,
                            x - (node1.getVnodeCellNumX() + node2.getVnodeCellNumX())*LAYOUT_CELL_SIZE_X/2,
                            y - (totalCellNumY-firstRowCellNumY+node1.getVnodeCellNumY())*LAYOUT_CELL_SIZE_Y/2);
                    calcNodeLayoutPosition(rbdJsonArray,
                            node4,
                            algo4,
                            originCellX + 1,
                            originCellY + firstRowCellNumY + secondRowCellNumY);
                    calcNodeLayoutPositionCell(rbdJsonArray,
                            algorithmList,
                            modelNodeAndVnodeList,
                            node2,
                            algo2,
                            x + (node1.getVnodeCellNumX() + node2.getVnodeCellNumX())*LAYOUT_CELL_SIZE_X/2,
                            y - (totalCellNumY-firstRowCellNumY+node2.getVnodeCellNumY())*LAYOUT_CELL_SIZE_Y/2);
                            node5,
                            algo5,
                            originCellX + 1 + node4.getPositionCellX(),
                            originCellY + firstRowCellNumY + secondRowCellNumY);
                    // 2.4 计算桥联运算符的坐标
                    // 2.5 计算左侧配对的connect的坐标
                    node.setPositionCellX(originCellX + 1);
                    node.setPositionCellY(originCellY + node.getVnodeCellNumY()/2);
*//*
                    break;
                default:
                    break;
            }
        }
    }
*/
    private void setRbdNodePosition(JSONArray rbdJsonArray,
                                    String id,
                                    double x,
@@ -435,8 +591,21 @@
        }
    }
    private Double getRbdNodeInfo(JSONArray rbdJsonArray,
                                  String picId,
                                  String path) {
        for (int i = 0; i < rbdJsonArray.size(); i++) {
            JSONObject jsonObject = rbdJsonArray.getJSONObject(i);
            if (picId.equals(jsonObject.get("id").toString())) {
                return Convert.toDouble(JsonUtils2.getJsonValueByPath(jsonObject, path.split("/")));
            }
        }
        return null;
    }
    /**
     * 自底向上递归合计出整个RBD的大小(横向及纵向所占单元格的数量)
     *
     * @param modelRbd
     * @param algorithmList
     * @param modelNodeAndVnodeList
@@ -461,16 +630,16 @@
                          Algorithm algo) {
        if ("node".equals(node.getNodeType())) {
            //设置node(设备节点)布局信息
            node.setWidth(LAYOUT_DEVICE_NODE_SIZE_X);
            node.setHeight(LAYOUT_DEVICE_NODE_SIZE_Y);
//            node.setWidth(LAYOUT_DEVICE_NODE_SIZE_X);
//            node.setHeight(LAYOUT_DEVICE_NODE_SIZE_Y);
            node.setCellNumX(LAYOUT_CELL_NUM_NODE_X);
            node.setCellNumY(LAYOUT_CELL_NUM_NODE_Y);
            node.setVnodeCellNumX(node.getCellNumX());
            node.setVnodeCellNumY(node.getCellNumY());
        } else if ("vnode".equals(node.getNodeType())) {
            // 1. 设置vnode(运算节点)布局信息(其实串联没有运算符,不需要设置,但是设置了也没有坏处,所有不作区分)
            node.setWidth(LAYOUT_OPE_NODE_SIZE_X);
            node.setHeight(LAYOUT_OPE_NODE_SIZE_Y);
            // 1. 设置vnode(运算节点)布局信息(其实串联没有运算符,不需要设置,但是设置了也没有坏处,所以不作区分)
//            node.setWidth(LAYOUT_OPE_NODE_SIZE_X);
//            node.setHeight(LAYOUT_OPE_NODE_SIZE_Y);
            node.setCellNumX(LAYOUT_CELL_NUM_NODE_X);
            node.setCellNumY(LAYOUT_CELL_NUM_NODE_Y);
@@ -480,21 +649,13 @@
            for (String nodeStr : computerNodeListStr) {
                ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
                        nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                if ("node".equals(childNode.getNodeType())) {
                    childNode.setWidth(LAYOUT_DEVICE_NODE_SIZE_X);
                    childNode.setHeight(LAYOUT_DEVICE_NODE_SIZE_Y);
                    childNode.setCellNumX(LAYOUT_CELL_NUM_NODE_X);
                    childNode.setCellNumY(LAYOUT_CELL_NUM_NODE_Y);
                    childNode.setVnodeCellNumX(node.getCellNumX());
                    childNode.setVnodeCellNumY(node.getCellNumY());
                } else {
                    Algorithm childAlgo = algorithmList.stream().filter(item ->
                            childNode.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
                List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
                        childNode.getId().equals(item.getId())).collect(Collectors.toList());
                Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
                    calcNodeLayoutSize(algorithmList,
                            modelNodeAndVnodeList,
                            childNode,
                            childAlgo);
                }
            }
            // 2.2 设置虚节点总的布局信息到运算节点中
            setVnodeLayoutNum(computerNodeListStr, modelNodeAndVnodeList, node, algo);
@@ -513,14 +674,14 @@
                    nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
            switch (algo.getAlgorithmType()) {
                case OPE_TYPE_SERIES:
                    numX += childNode.getCellNumX();
                    numY = childNode.getCellNumY() > numY ? childNode.getCellNumY() : numY;
                    numX += childNode.getVnodeCellNumX();
                    numY = childNode.getVnodeCellNumY() > numY ? childNode.getVnodeCellNumY() : numY;
                    break;
                case OPE_TYPE_PARALLEL:
                case OPE_TYPE_SWITCH:
                case OPE_TYPE_VOTE:
                    numX = childNode.getCellNumX() > numX ? childNode.getCellNumX() : numX;
                    numY += childNode.getCellNumY();
                    numX = childNode.getVnodeCellNumX() > numX ? childNode.getVnodeCellNumX() : numX;
                    numY += childNode.getVnodeCellNumY();
                    break;
                default:
                    break;
@@ -529,14 +690,8 @@
        if (OPE_TYPE_PARALLEL.equals(algo.getAlgorithmType())
            || OPE_TYPE_SWITCH.equals(algo.getAlgorithmType())
            || OPE_TYPE_VOTE.equals(algo.getAlgorithmType())) {
            // 设置connect的大小
            ModelNode connect = modelNodeAndVnodeList.stream().filter(item ->
                    vnode.getPairStartNodeId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
            connect.setWidth(LAYOUT_CONNECT_SIZE_X);
            connect.setHeight(LAYOUT_CONNECT_SIZE_Y);
            connect.setCellNumX(LAYOUT_CELL_NUM_CONNECT_X);
            connect.setCellNumY(LAYOUT_CELL_NUM_CONNECT_Y);
            numX += connect.getCellNumX();
            // 加上connect的大小
            numX += LAYOUT_CELL_NUM_CONNECT_X;
            numX += vnode.getCellNumX();
        }
        // 2. 计算桥联
@@ -563,14 +718,8 @@
            int numY3 = node4.getCellNumY() > node5.getCellNumY() ? node4.getCellNumY() : node5.getCellNumY();
            numX = Math.max(Math.max(numX1, numX2), numX3);
            numY = numY1 + numY2 + numY3;
            // 2.4 设置connect的大小
            ModelNode connect = modelNodeAndVnodeList.stream().filter(item ->
                    vnode.getPairStartNodeId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
            connect.setWidth(LAYOUT_CONNECT_SIZE_X);
            connect.setHeight(LAYOUT_CONNECT_SIZE_Y);
            connect.setCellNumX(LAYOUT_CELL_NUM_CONNECT_X);
            connect.setCellNumY(LAYOUT_CELL_NUM_CONNECT_Y);
            numX += connect.getCellNumX();
            // 2.4 加上connect的大小
            numX += LAYOUT_CELL_NUM_CONNECT_X;
            numX += vnode.getCellNumX();
        }
        vnode.setVnodeCellNumX(numX);
@@ -1593,6 +1742,8 @@
                modelNode.setNodeType(JsonUtils2.getJsonValueByPath(jsonObject, "data/nodeType".split("/")).toString());
                modelNode.setPositionX(Double.valueOf(JsonUtils2.getJsonValueByPath(jsonObject, "position/x".split("/")).toString()));
                modelNode.setPositionY(Double.valueOf(JsonUtils2.getJsonValueByPath(jsonObject, "position/y".split("/")).toString()));
                modelNode.setWidth(new Double(JsonUtils2.getJsonValueByPath(jsonObject, "size/width".split("/")).toString()));
                modelNode.setHeight(new Double(JsonUtils2.getJsonValueByPath(jsonObject, "size/height".split("/")).toString()));
                jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/voteNum".split("/"));
                if (jsonValue!=null && StringUtils.isNotBlank(jsonValue.toString())) {
                    modelNode.setVoteNum(Integer.valueOf(jsonValue.toString()));