diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 4baa140..a3d2687 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -449,8 +449,8 @@ // create resource vertices for (ResourceNode resNode: dataFlowGraph.getRootResourceNodes()) { - int w = 300; - int h = 200; + int w = 80; + int h = 30; ResourcePath res = resNode.getOutSideResource(); Object resource = graph.insertVertex(parent, null, res.getResourceName(), 20, 20, w, h, @@ -500,17 +500,17 @@ public void getChildResource(Object resource, ResourceNode resNode, Map resources, int w, int h) { for (ResourceNode c: resNode.getChildren()) { - w = w - 100; - if(w <= 0) { - w = 100; - } - h = (2 * w) / 3; +// w = w - 100; +// if(w <= 0) { +// w = 100; +// } +// h = (2 * w) / 3; ResourcePath chRes = c.getOutSideResource(); Object chResource = graph.insertVertex(resource, null, - chRes.getName(), 110, 90, w, h, + chRes.getName(), 0, 0, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex resources.put(chRes, chResource); - getChildResource(chResource, c, resources, w, h); + getChildResource(chResource, c, resources, w, h); } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java index d493d10..62c120e 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java +++ b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java @@ -1,8 +1,12 @@ package application.layouts; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import com.mxgraph.layout.mxGraphLayout; import com.mxgraph.model.mxCell; @@ -13,131 +17,669 @@ import com.mxgraph.view.mxGraphView; public class DAGLayout extends mxGraphLayout { + private mxIGraphModel graphModel; + private mxGraphView view; + private Map> dotEdges; + private List> lines; + private List order; + private Map> hierarchicalRecursionOrder; + private Set usedLineIndex; + private List cells; + private Set roots; + private Map myRoot; + private Set resources; + private Set channels; + private Set eventChannels; + private Map vertexToDist; + private Map> cellToLineIndex; + private Map> cellGeo; + final double MOVE_X = 100; + final double MOVE_Y = 50; + final double WIDTH = 80; + final double HEIGHT = 30; + final double SHIFT = WIDTH / 4; + final double SPACE = 10; + final double MARGIN_WIDTH = 30; + final double MARGIN_HEIGHT = 30; + final double delta = Math.pow(10, -3); public DAGLayout(mxGraph graph) { super(graph); + + graphModel = graph.getModel(); + view = graph.getView(); + dotEdges = new HashMap<>(); + lines = new ArrayList<>(); + order = new ArrayList<>(); + hierarchicalRecursionOrder = new HashMap<>(); + usedLineIndex = new HashSet<>(); + cells = new ArrayList<>(); + roots = new HashSet<>(); + myRoot = new HashMap<>(); + resources = new HashSet<>(); + channels = new HashSet<>(); + eventChannels = new HashSet<>(); + vertexToDist = new HashMap<>(); + cellToLineIndex = new HashMap<>(); + cellGeo = new HashMap<>(); } public void execute(Object parent) { - mxIGraphModel model = graph.getModel(); - - model.beginUpdate(); + graphModel.beginUpdate(); try { - List> map = new ArrayList>(); - List moved = new ArrayList<>(); - - for (int i = 0; i < model.getChildCount(parent); i++) { + // ���f������resource, channel, eventChannel�ɕ����� + for (int i = 0; i < graphModel.getChildCount(parent); i++) { + mxCell cell = (mxCell) graphModel.getChildAt(parent, i); - mxCell cell = (mxCell) model.getChildAt(parent, i); - - if (model.isVertex(cell)) { - mxGraphView view = graph.getView(); + if (graphModel.isVertex(cell)) { mxCellState state = view.getState(cell); + cells.add(cell); - if (!"ellipse".equals(state.getStyle().get("shape")) && (cell.getEdgeCount() == 1) && !"true".equals(state.getStyle().get("dashed"))) { - List newline = new ArrayList(); - map.add(newline); - lines(map, cell); + // cell��resource�ł��� + if ("ellipse".equals(state.getStyle().get("shape"))) { + roots.add(cell); + hierarchicalRecursionOrder.put(cell, new ArrayList<>()); + familySearch(cell, cell, 0); + } + + if ("rectangle".equals(state.getStyle().get("shape"))) { + if ("true".equals(state.getStyle().get("dashed"))) { + continue; + } + + // cell��eventChannel�ł��� + if (cell.getEdgeCount() == 1) { + eventChannels.add(cell); + hierarchicalRecursionOrder.put(cell, new ArrayList<>()); + } else { + // cell��channel�ł��� + channels.add(cell); + hierarchicalRecursionOrder.put(cell, new ArrayList<>()); + } } } } - sort(map, 0, false); - - // layout - int count; - int skip = 0; - mxGraphView view = graph.getView(); - for (int i = 0; i < map.size(); i++) { - count = 0; - for (int j = 0; j < map.get(i).size(); j++) { - mxGeometry geom = (mxGeometry) map.get(i).get(j).getGeometry().clone(); - mxCellState state = view.getState(map.get(i).get(j)); - if (checkmoved(moved, map.get(i).get(j))) { - if ("ellipse".equals(state.getStyle().get("shape"))){ - geom.setX(50 + j*200); - } else { - geom.setX(100 + j*200); - } - geom.setY(100 + (i-skip)*100); - model.setGeometry(map.get(i).get(j), geom); - moved.add(map.get(i).get(j).getId()); - } else if (geom.getX() < 100 + j*150) { - if ("ellipse".equals(state.getStyle().get("shape"))){ - geom.setX(50 + j*200); - } else { - geom.setX(100 + j*200); - } - geom.setY(100 + (i-skip)*100); - model.setGeometry(map.get(i).get(j), geom); - } else { - count++; - } + // �S�Ă�cell�̍��W�A�傫���Ȃǂ������� + for (mxCell c : cells) { + c.getGeometry().setX(0); + c.getGeometry().setY(0); + + if (resources.contains(c)) { + view.getState(c).getStyle().put("verticalAlign", "top"); + c.getGeometry().setWidth(WIDTH); + c.getGeometry().setHeight(HEIGHT); } - if (count >= map.get(i).size())skip++; } + // dotEdges�������� + for (mxCell c : cells) { + dotEdges.put(c, new HashSet<>()); + } + + // line���\�z���� + for (mxCell ec : eventChannels) { + List newline = new ArrayList(); + lines.add(newline); + constructionLine(ec, 0); + } + + // cell�̐[�����Čv�Z + reculcDist(); + + // cell��������line��index�����߂� + for (int i = 0; i < lines.size(); i++) { + for (mxCell cell : lines.get(i)) { + if (cellToLineIndex.get(cell) == null) { + cellToLineIndex.put(cell, new ArrayList<>()); + } + cellToLineIndex.get(cell).add(i); + } + } + + // ���ׂ�line�̏��Ԃ��\�[�g���� + sortLines(); + + // cell��z�u���� + layout((mxCell) parent); + } finally { - model.endUpdate(); + graphModel.endUpdate(); } } + // �K�w�\�����ċA�I�ɒT�� + public void familySearch(mxCell r, mxCell p, int d) { + int childNum = graphModel.getChildCount(p); + + myRoot.put(p, r); + resources.add(p); + if (r != p) { + hierarchicalRecursionOrder.get(r).add(p); + } + + for (int i = 0; i < childNum; i++) { + mxCell child = (mxCell) graphModel.getChildAt(p, i); + cells.add(child); + resources.add(child); + familySearch(r, child, d + 1); + } + } - public void lines(List> mapping, mxCell next) { - mapping.get(mapping.size()-1).add(next); - int tagcount = 0; - mxCell edge; - mxGraphView view = graph.getView(); - for (int i = 0; i < next.getEdgeCount(); i++) { - edge = (mxCell) next.getEdgeAt(i); + // line���\�z���� + public void constructionLine(mxCell cur, int d) { + // vertexToDist{key : cell, value : �[��} �������� + if (vertexToDist.get(cur) == null) { + vertexToDist.put(cur, d); + } else { + // ���g���܂܂��line�̒��ň�ԑ傫���[����ۑ� + vertexToDist.put(cur, Math.max(vertexToDist.get(cur), d)); + } + + lines.get(lines.size() - 1).add(cur); + + int tagCount = 0; // edge�̎n�_�ƂȂ�cell�Ƃ��ĎQ�Ƃ��ꂽ�� + for (int i = 0; i < cur.getEdgeCount(); i++) { + mxCell edge = (mxCell) cur.getEdgeAt(i); mxCellState state = view.getState(edge); - if (next != (mxCell) edge.getTarget() && ((mxCell) edge.getTarget() != null) && !"true".equals(state.getStyle().get("dashed"))) { - tagcount++; - if (tagcount > 1) { - List newline = new ArrayList(mapping.get(mapping.size()-1)); - while (newline.get(newline.size()-1).getId() != next.getId()) { - newline.remove(newline.size()-1); - } - mapping.add(newline); - lines(mapping, (mxCell) edge.getTarget()); - + mxCell target = (mxCell) edge.getTarget(); + + // cur���n�_�ƂȂ�edge�̏I�_�ƂȂ�target�����g�A�������͑��݂��Ȃ��ꍇ������ + if ((cur != target) && (target != null)) { + // edge�̎�ނ�"dashed"�̏ꍇ + if ("true".equals(state.getStyle().get("dashed"))) { + state.getStyle().put("strokeColor", "#800080"); // edge�̐F��ύX + dotEdges.get(cur).add(target); // dotEdges{key : �n�_�ƂȂ�cell, value : �I�_�ƂȂ�cell} } else { - lines(mapping, (mxCell) edge.getTarget()); + tagCount++; + // �n�_�Ƃ��ĕ�����Q�Ƃ���Ă���ꍇ + if (tagCount > 1) { + // cur�܂ł�line�̏����č\�z���āA��������V����line���\�z���� + List newline = new ArrayList(lines.get(lines.size() - 1)); + while (newline.get(newline.size() - 1).getId() != cur.getId()) { + newline.remove(newline.size() - 1); + } + lines.add(newline); + constructionLine(target, d + 1); + // �n�_�Ƃ��ď��߂ĎQ�Ƃ��ꂽ�ꍇ + } else { + constructionLine(target, d + 1); + } } } } } - public boolean checkmoved(List list, mxCell cell) { - for (int i = 0; i < list.size(); i++) { - if (list.get(i).equals(cell.getId()))return false; + // cell�̐[�����Čv�Z���� + public void reculcDist() { + boolean isChanging = false; + + // �[���̍X�V���s���Ȃ��Ȃ�܂ŌJ��Ԃ� + while (true) { + // �����line�Ɋ܂܂�鎩�g��1�Ž�O�̐[���Ǝ��g�̐[�����r���āA�������[�����v�Z + for (List line : lines) { + for (int i = 1; i < line.size(); i++) { + mxCell cur = line.get(i); + mxCell pre = line.get(i - 1); + if (!(resources.contains(cur) && resources.contains(pre))) { + if (vertexToDist.get(cur) < vertexToDist.get(pre) + 1) { + vertexToDist.replace(cur, vertexToDist.get(pre) + 1); + isChanging = true; + } + } + } + } + + // �K�w�\�����l������cell�̐[�����v�Z + for (mxCell r : roots) { + for (mxCell c : hierarchicalRecursionOrder.get(r)) { + mxCell p = (mxCell) graphModel.getParent(c); + if (!vertexToDist.containsKey(c)) { + vertexToDist.put(c, vertexToDist.get(p)); + } else { + if (vertexToDist.get(p) > vertexToDist.get(c)) { + vertexToDist.replace(c, vertexToDist.get(p)); + isChanging = true; + } + } + } + } + + // 1�x���ύX�������ƃ��[�v�𔲂��� + if (!isChanging) { + break; + } } - return true; } - public void sort(List> map, int n, boolean check) { - int msize = -1; - int mnum = -1; - if (check) { - for (int i = n; i < map.size(); i++) { - if (map.get(i).size() > msize && (map.get(n-1).get(0).getId().equals(map.get(i).get(0).getId()))) { - mnum = i; + // line���\�[�g����(�������A���ۂɂ�lines���̗v�f�̏��Ԃ͓���ւ����A�Ăяo�����Ԃ�ۑ�����order���쐬) + public void sortLines() { + for (int i = 0; i < lines.size(); i++) { + List line = lines.get(i); + + // eventChannel����̏o�͐悪root�ł���ꍇ + if (roots.contains(line.get(1))) { + for (mxCell c : line) { + addLine(c); // order��line��index���i�[���� } } + } + } + + // order��line��index���i�[���� + public void addLine(mxCell c) { + if (cellToLineIndex.get(c) != null) { + for (int i : cellToLineIndex.get(c)) { + if (!usedLineIndex.contains(i)) { + order.add(i); + } + usedLineIndex.add(i); + } + } + + // root��������line��index���i�[������A�q����������line��index�������i�[���� + for (int i = 0; i < graphModel.getChildCount(c); i++) { + mxCell child = (mxCell) graphModel.getChildAt(c, i); + addLine(child); + } + } + + // cell��z�u���� + public void layout(mxCell s) { + /* cell�̍��W�́Acell��parent�̍���̍��W�����x��y���ǂꂾ�����炷���Œ�`����Ă��� + ����Čv�Z�̓s����Aid=1 ��cell(���C�A�E�g���)�̍������ɂ������W��ۑ����Ă��� */ + + Set movedSet = new HashSet<>(); + List movedList = new ArrayList<>(); + Map> movedMap = new TreeMap<>(); + Map distToMaxX = new HashMap<>(); + double maxY = 0; + int maxD = 0; + + putCellGeo(s, 0, 0); + + // �[���̍ő�l�����߂� + for (mxCell c : cells) { + maxD = Math.max(maxD, vertexToDist.get(c)); + } + + // ������ + distToMaxX.put(-1, 0.0); + for (int d = 0; d <= maxD; d++) { + movedMap.put(d, new ArrayList<>()); + distToMaxX.put(d, -1.0); + } + + for (int i : order) { + double centerY = -1; // �z�u�\���y���W(����) + for (mxCell cur : lines.get(i)) { + // ���ɔz�u�ς݂Ȃ�X�L�b�v + if (movedSet.contains(cur)) { + continue; + } + + int d = vertexToDist.get(cur); // cur�̐[�� + double x = distToMaxX.get(d - 1) + MOVE_X; // �z�u�\���x���W + double endX = 0; // �z�u����cell�̉E�[��x���W + double endY = 0; // �z�u����cell�̉��[��y���W + + // cur��root, channel, eventChannel�ɑ�����cell�ł���ꍇ + if (roots.contains(cur) || channels.contains(cur) || eventChannels.contains(cur)) { + if (centerY == -1) { + centerY = maxY + MOVE_Y + cur.getGeometry().getHeight() / 2; + } + double y = centerY - cur.getGeometry().getHeight() / 2; // �z�u�\���y���W + double ny = y; + double nx = x; + + // �\�肵�Ă�����W�ɔz�u����Ƒ��̃��\�[�X�����ɔz�u����Ă��܂��ꍇ�A���ɂ��炷 + for (mxCell m : movedSet) { + if (roots.contains(m) || channels.contains(m)) { + if (cellOverlap(m.getGeometry().getX(), m.getGeometry().getY(), m.getGeometry().getWidth(), m.getGeometry().getHeight(), x, y, cur.getGeometry().getWidth(), cur.getGeometry().getHeight())) { + ny = m.getGeometry().getY() + m.getGeometry().getHeight() + MOVE_Y; + } + } + } + + // �\��̍��W�ɔz�u���āA�e�폈�����s�� + cur.getGeometry().setX(nx); + cur.getGeometry().setY(ny); + endX = nx + cur.getGeometry().getWidth(); + endY = ny + cur.getGeometry().getHeight(); + putCellGeo(cur, nx, ny); + addMoved(movedSet, movedList, movedMap, cur, d); + graphModel.setGeometry(cur, (mxGeometry) cur.getGeometry().clone()); + + // �[����d�̍ő��x���W���X�V�����ꍇ�A���ɔz�u�ς݂�cell������ɉ����ĉE�ɂ��炷 + if (distToMaxX.get(d) < endX) { + updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); + } + maxY = Math.max(maxY, endY); // �z�u�ς݂�cell�̒��ł̉��[�̍��W�̍ő� + + // root�̎q�����܂Ƃ߂Ĕz�u���� + for (mxCell c : hierarchicalRecursionOrder.get(cur)) { + d = vertexToDist.get(c); + nx = x; // �z�u�\���x���W + mxCell parent = (mxCell) graphModel.getParent(c); + + // �[�����e�Ɠ������ꍇ�A�e��x���W��菭���傫������ + if (d == vertexToDist.get(parent)) { + nx = cellGeo.get(parent).get("x") + MARGIN_WIDTH; + } else { + nx = distToMaxX.get(d - 1) + MOVE_X; + } + + // �z�u�ς݂Ő[�����������Z�킪�v��ꍇ�A���ɂ��炷 + double brotherMaxY = MOVE_Y; + for (int k = 0; k < graphModel.getChildCount(parent); k++) { + mxCell child = (mxCell) graphModel.getChildAt(parent, k); + if (child == c) { + continue; + } + + if (movedSet.contains(child) && (d == vertexToDist.get(child))) { + brotherMaxY = Math.max(brotherMaxY, child.getGeometry().getY() + child.getGeometry().getHeight() + SPACE); + } + } + + // �\��̍��W�ɔz�u���āA�e�폈�����s�� + c.getGeometry().setX(nx - cellGeo.get(parent).get("x")); + c.getGeometry().setY(brotherMaxY); + graphModel.setGeometry(c, (mxGeometry) c.getGeometry().clone()); + addMoved(movedSet, movedList, movedMap, c, d); + putCellGeo(c, nx, cellGeo.get(parent).get("y") + brotherMaxY); + + endX = cellGeo.get(c).get("x") + c.getGeometry().getWidth(); + endY = cellGeo.get(c).get("y") + c.getGeometry().getHeight(); + endY = resize(parent, endX, endY); // �q�����e�̓����Ɋ܂܂�Ȃ��ꍇ�A�e�̑傫����ύX���� + + // �[����d�̍ő��x���W���X�V�����ꍇ�A���ɔz�u�ς݂�cell������ɉ����ĉE�ɂ��炷 + if (distToMaxX.get(vertexToDist.get(c)) < endX) { + updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); + } + maxY = Math.max(maxY, endY); + } + } + } + } + + // �_���̕ӂ��d�Ȃ��Ă���ꍇ�A�E�ɂ��炷 + for (mxCell c : resources) { + for (mxCell cc : dotEdges.get(c)) { + for (Map.Entry> entry : dotEdges.entrySet()) { + mxCell u = entry.getKey(); + for (mxCell v : entry.getValue()) { + double []posC = {cellGeo.get(c).get("x") + c.getGeometry().getWidth() / 2, cellGeo.get(c).get("y") + c.getGeometry().getHeight() / 2}; + double []posCC = {cellGeo.get(cc).get("x") + cc.getGeometry().getWidth() / 2, cellGeo.get(cc).get("y") + cc.getGeometry().getHeight() / 2}; + double []posU = {cellGeo.get(u).get("x") + u.getGeometry().getWidth() / 2, cellGeo.get(u).get("y") + u.getGeometry().getHeight() / 2}; + double []posV = {cellGeo.get(v).get("x") + v.getGeometry().getWidth() / 2, cellGeo.get(v).get("y") + v.getGeometry().getHeight() / 2}; + + if (isStraightLine(posC, posCC, posU, posV)) { + c.getGeometry().setX(c.getGeometry().getX() + SHIFT); + cellGeo.get(c).replace("x", cellGeo.get(c).get("x")); + cc.getGeometry().setX(cc.getGeometry().getX() + SHIFT); + cellGeo.get(cc).replace("x", cellGeo.get(cc).get("x") + SHIFT); + graphModel.setGeometry(c, c.getGeometry()); + graphModel.setGeometry(cc, cc.getGeometry()); + } + } + } + } + } + + // eventChannel���o�͐��y���W�ɑ����� + for (int i : order) { + mxCell cur = lines.get(i).get(1); + List ecs = new ArrayList<>(); + for (int j : cellToLineIndex.get(cur)) { + if (!ecs.contains(lines.get(j).get(0)) && cur == lines.get(j).get(1)) { + ecs.add(lines.get(j).get(0)); + } + } + + double centerY = cellGeo.get(cur).get("y") + cur.getGeometry().getHeight() / 2; + double y = 0; + if (ecs.size() % 2 != 0) { + y = centerY - ecs.size()*HEIGHT / 2 - ((ecs.size() - 1) / 2)*SPACE; + } else { + y = centerY - ecs.size()*HEIGHT / 2 - (ecs.size() - 1)*SPACE / 2; + } + + for (int j : order) { + mxCell other = lines.get(j).get(0); + if (ecs.contains(other)) { + continue; + } + } + + for (mxCell ec : ecs) { + ec.getGeometry().setY(y); + graphModel.setGeometry(ec, ec.getGeometry()); + cellGeo.get(ec).replace("y", y); + y += HEIGHT + SPACE; + } + } + + // ����resource�ɕ�����eventChannel���o�͂��Ă���ꍇ�A�d�Ȃ��Ă��܂��̂ʼn��ɂ��炷 + Map> ecToLineIndex = new HashMap<>(); + for (mxCell ec : eventChannels) { + ecToLineIndex.put(ec, new ArrayList<>()); + } + for (int i = 0; i < lines.size(); i++) { + mxCell ec = lines.get(i).get(0); + ecToLineIndex.get(ec).add(i); + } + + Set usedEventChannels = new HashSet<>(); + List sortedEventChannels = new ArrayList<>(); + List eventChannelOut = new ArrayList<>(); + for (int i : order) { + mxCell cur = lines.get(i).get(1); + mxCell ec = lines.get(i).get(0); + if (!roots.contains(cur) || usedEventChannels.contains(ec)) { + continue; + } + + sortedEventChannels.add(ec); + eventChannelOut.add(cur); + usedEventChannels.add(ec); + + for (mxCell c : hierarchicalRecursionOrder.get(cur)) { + if (!cellToLineIndex.containsKey(c)) { + continue; + } + + for (int j : cellToLineIndex.get(c)) { + if (c == lines.get(j).get(1)) { + if (!usedEventChannels.contains(lines.get(j).get(0))) { + sortedEventChannels.add(lines.get(j).get(0)); + eventChannelOut.add(cur); + usedEventChannels.add(lines.get(j).get(0)); + } + } + } + } + } + + for (int i = 1; i < sortedEventChannels.size(); i++) { + mxCell pre = sortedEventChannels.get(i - 1); + mxCell preOut = eventChannelOut.get(i - 1); + mxCell cur = sortedEventChannels.get(i); + mxCell curOut = eventChannelOut.get(i); + double dy = 0; + + if (myRoot.get(preOut) == myRoot.get(curOut)) { + dy = SPACE; + } else { + dy = MOVE_Y; + } + + if (cellGeo.get(cur).get("y") < cellGeo.get(pre).get("y") + pre.getGeometry().getHeight() + dy) { + cur.getGeometry().setY(cellGeo.get(pre).get("y") + pre.getGeometry().getHeight() + dy); + cellGeo.get(cur).replace("y", cellGeo.get(pre).get("y") + pre.getGeometry().getHeight() + dy); + } + + if (cellGeo.get(cur).get("y") + cur.getGeometry().getHeight() / 2 == cellGeo.get(curOut).get("y") + curOut.getGeometry().getHeight() / 2 + && vertexToDist.get(curOut) != 1) { + cur.getGeometry().setY(cellGeo.get(cur).get("y") + cur.getGeometry().getHeight() + dy); + cellGeo.get(cur).replace("y", cellGeo.get(cur).get("y") + cur.getGeometry().getHeight() + dy); + } + graphModel.setGeometry(cur, cur.getGeometry()); + } + } + + public void putCellGeo(mxCell c, double x, double y) { + cellGeo.put(c, new HashMap<>()); + cellGeo.get(c).put("x", x); + cellGeo.get(c).put("y", y); + } + + public void addMoved(Set ms, List ml, Map> mm, mxCell c, int d) { + ms.add(c); + ml.add(c); + mm.get(d).add(c); + } + + // 2�‚̕ӂ��d�Ȃ��Ă��邩���� + public boolean isStraightLine(double []u1, double []v1, double []u2, double []v2) { + double gradient1 = 0; + double length1 = Math.pow(u1[0] - v1[0], 2) + Math.pow(u1[1] - v1[1], 2); + double gradient2 = 0; + double length2 = Math.pow(u2[0] - v2[0], 2) + Math.pow(u2[1] - v2[1], 2); + boolean isVertical = false; + + if (u1[0] == v1[0]) { + isVertical = true; + } else { + gradient1 = (u1[1] - v1[1]) / (u1[0] - v1[0]); + } + + if (isVertical) { + if (u2[0] != v2[0]) { + return false; + } else { + gradient2 = (u2[1] - v2[1]) / (u2[0] - v2[0]); + } } else { - for (int i = n; i < map.size(); i++) { - if (map.get(i).size() > msize) { - mnum = i; + if (gradient1 - gradient2 > delta) { + return false; + } + } + + double [][]a = {u1, v1}; + double [][]b = {u2, v2}; + double maxLength = 0; + for (double []c1 : a) { + for (double []c2 : b) { + double gradient3 = 0; + double length3 = Math.pow(c1[0] - c2[0], 2) + Math.pow(c1[1] - c2[1], 2); + + if(isVertical) { + if (c1[0] == c2[0]) { + maxLength = Math.max(maxLength, length3); + } else { + return false; + } + } else { + if (c1[0] == c2[0]) { + return false; + } else { + gradient3 = (c2[1] - c1[1]) / (c2[0] - c1[0]); + if (gradient1 - gradient3 > delta) { + return false; + } + maxLength = Math.max(maxLength, length3); + } } } } - if (mnum >= 0) { - Collections.swap(map, n, mnum); - sort(map, n+1, true); - } else if(n < map.size()) { - sort(map, n+1, false); + + if (length1 + length2 < maxLength) { + return false; + } else { + return true; } } + // 2�‚�resource���d�Ȃ��Ă��邩���� + public boolean cellOverlap(double ax, double ay, double aw, double ah, double bx, double by, double bw, double bh) { + if (((ax <= bx) && (bx <= ax + aw)) || ((bx <= ax) && (ax <= bx + bw))) { + if (((ay <= by) && (by <= ay + ah)) || ((by <= ay) && (ay <= by + bh))) { + return true; + } + } + return false; + } + // �[�����Ƃ̍ő��x���W���ύX���ꂽ�Ƃ��̏��� + public void updateDistToMaxX(Map distToMaxX, Set movedSet, Map> movedMap, int d, int md, double endX) { + double preEndX = distToMaxX.get(d); + distToMaxX.replace(d, endX); + for (int i = d + 1; i <= md; i++) { + if (distToMaxX.get(i) == -1) { + distToMaxX.replace(i, endX); + } + } + + for (Map.Entry> entry : movedMap.entrySet()) { + if (entry.getKey() <= d) { + continue; + } + + for (mxCell cell : entry.getValue()) { + double newX = cellGeo.get(cell).get("x") + endX - preEndX; + mxCell cp = (mxCell) cell.getParent(); + relocateX(cell, newX, cellGeo.get(cp).get("x")); + + if (!(roots.contains(cell) || channels.contains(cell))) { + mxCell ancestor = (mxCell) graphModel.getParent(cell); + resize(ancestor, cellGeo.get(cell).get("x") + cell.getGeometry().getWidth(), cellGeo.get(cell).get("y") + cell.getGeometry().getHeight()); + } + if (distToMaxX.get(entry.getKey()) < cellGeo.get(cell).get("x") + cell.getGeometry().getWidth()) { + distToMaxX.replace(entry.getKey(), cellGeo.get(cell).get("x") + cell.getGeometry().getWidth()); + for (int i = entry.getKey() + 1; i <= md; i++) { + if (distToMaxX.get(i) == -1) { + distToMaxX.replace(i, cellGeo.get(cell).get("x") + cell.getGeometry().getWidth()); + } + } + } + } + } + } + + // �e�̑傫����ύX + public double resize(mxCell ancestor, double endX, double endY) { + while (true) { + boolean isChanging = false; + + if (ancestor.getGeometry().getWidth() < endX - cellGeo.get(ancestor).get("x") + MARGIN_WIDTH) { + ancestor.getGeometry().setWidth(endX - cellGeo.get(ancestor).get("x") + MARGIN_WIDTH); + isChanging = true; + } + if (ancestor.getGeometry().getHeight() < endY - cellGeo.get(ancestor).get("y") + MARGIN_HEIGHT) { + ancestor.getGeometry().setHeight(endY - cellGeo.get(ancestor).get("y") + MARGIN_HEIGHT); + isChanging = true; + } + if (isChanging) { + graphModel.setGeometry(ancestor, ancestor.getGeometry()); + } + + endX = cellGeo.get(ancestor).get("x") + ancestor.getGeometry().getWidth(); + endY = cellGeo.get(ancestor).get("y") + ancestor.getGeometry().getHeight(); + + if (roots.contains(ancestor)) { + break; + } + ancestor = (mxCell) ancestor.getParent(); + } + + return endY; + } + + // x���W��ύX + public void relocateX(mxCell c, double nx, double dx) { + c.getGeometry().setX(nx - dx); + graphModel.setGeometry(c, (mxGeometry) c.getGeometry().clone()); + cellGeo.get(c).replace("x", nx); + } } \ No newline at end of file