diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index fef8eda..ed77c0c 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,13 +5,10 @@
-
-
-
-
-
+
-
+
+
@@ -43,7 +40,11 @@
"keyToString": {
"Python.CompareViews.executor": "Run",
"Python.CompareWindow.executor": "Run",
+ "Python.DAGGraph (1).executor": "Run",
"Python.DAGGraph.executor": "Run",
+ "Python.DAGLayout (1).executor": "Run",
+ "Python.DAGLayout.executor": "Run",
+ "Python.DAGPresent.executor": "Run",
"Python.MergeView.executor": "Run",
"Python.MileStone.executor": "Run",
"Python.NovelManage.executor": "Debug",
@@ -54,10 +55,11 @@
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
- "last_opened_file_path": "D:/Projects/Python/StoryCheckTools"
+ "last_opened_file_path": "D:/Projects/Python/StoryCheckTools",
+ "settings.editor.selected.configurable": "reference.settings.ide.settings.new.ui"
}
}]]>
-
+
@@ -80,7 +82,7 @@
-
+
@@ -89,11 +91,11 @@
-
+
-
+
@@ -102,7 +104,7 @@
-
+
@@ -111,12 +113,12 @@
-
+
-
-
+
+
@@ -146,49 +148,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
+
diff --git a/graph/__pycache__/DataType.cpython-312.pyc b/graph/__pycache__/DataType.cpython-312.pyc
index 4ec0844..9c16c97 100644
Binary files a/graph/__pycache__/DataType.cpython-312.pyc and b/graph/__pycache__/DataType.cpython-312.pyc differ
diff --git a/graph/__pycache__/__init__.cpython-312.pyc b/graph/__pycache__/__init__.cpython-312.pyc
index b6096b1..37ebf26 100644
Binary files a/graph/__pycache__/__init__.cpython-312.pyc and b/graph/__pycache__/__init__.cpython-312.pyc differ
diff --git a/graph/dagpresent/DAGGraph.py b/graph/directed_acyclic_graph/DAGLayout.py
similarity index 88%
rename from graph/dagpresent/DAGGraph.py
rename to graph/directed_acyclic_graph/DAGLayout.py
index 268d403..1c042ec 100644
--- a/graph/dagpresent/DAGGraph.py
+++ b/graph/directed_acyclic_graph/DAGLayout.py
@@ -1,11 +1,5 @@
from graph.DataType import Point, Arrow
from typing import List, Dict, Tuple
-from enum import Enum
-
-
-class Direction(Enum):
- RankLR = 0,
- RankTB = 1,
class DAGLayerHelper:
@@ -46,6 +40,7 @@ class DAGOrderHelper:
def __init__(self, level:int = 0, relate:DAGLayerHelper|None = None, bind: DAGLayerHelper|None = None):
self.layer_bind = bind
self.relate_bind = relate
+
self.layer_number = level
self.sort_number:float = 0
self.__prev_layer_nodes: List['DAGOrderHelper'] = []
@@ -67,8 +62,7 @@ class DAGOrderHelper:
class DAGGraph:
- def __init__(self, orie: Direction):
- self.orientation = orie
+ def __init__(self):
self.graph_inst: Dict[str, DAGLayerHelper] = {}
self.nodes_with_layout: List[DAGOrderHelper] = []
pass
@@ -99,37 +93,39 @@ class DAGGraph:
pass
pass
- def __spawns_peak(self, refset: List[DAGLayerHelper]) -> Tuple[DAGLayerHelper, List[DAGLayerHelper]] | None:
+ def __spawns_peak(self, ref_set: List[DAGLayerHelper]) -> Tuple[DAGLayerHelper, List[DAGLayerHelper]] | None:
"""
拓扑排序迭代处理
- :param refset:
+ :param ref_set:
:return:
"""
- for inst in refset:
+ for inst in ref_set:
if inst.input_count == 0:
for it_nxt in inst.next_nodes():
- refset.append(it_nxt)
it_nxt.input_count -= 1
+ if it_nxt not in ref_set:
+ ref_set.append(it_nxt)
+ pass
pass
- refset.remove(inst)
- if inst.bind_point().point_name in self.graph_inst:
- self.graph_inst.pop(inst.bind_point().point_name)
-
- return inst, refset
+ ref_set.remove(inst)
+ self.graph_inst.pop(inst.bind_point().point_name)
+ return inst, ref_set
for inst in self.graph_inst.values():
if inst.input_count == 0:
- if inst in refset:
- refset.remove(inst)
+ if inst in ref_set:
+ ref_set.remove(inst)
for it_nxt in inst.next_nodes():
- refset.append(it_nxt)
it_nxt.input_count -= 1
+ if it_nxt not in ref_set:
+ ref_set.append(it_nxt)
+ pass
pass
self.graph_inst.pop(inst.bind_point().point_name)
- return inst, refset
+ return inst, ref_set
pass
if len(self.graph_inst) > 0:
@@ -254,7 +250,6 @@ class DAGGraph:
self.__graph_layer_nodes_sort(layer_index + 1, nodes)
pass
-
def graph_layout(self):
sort_seqs = []
@@ -299,17 +294,22 @@ class DAGGraph:
if __name__ == "__main__":
- graph = DAGGraph(Direction.RankLR)
+ graph = DAGGraph()
arrows = [
Arrow(Point('a'), Point('b')),
Arrow(Point('a'), Point('c')),
Arrow(Point('c'), Point('d')),
Arrow(Point('a'), Point('d')),
+ Arrow(Point('c'), Point('e')),
+ Arrow(Point('c'), Point('f')),
]
graph.rebuild_from_edges(arrows)
graph.graph_layout()
- points = graph.visible_nodes()
+ points = graph.nodes_with_layout
for p in points:
- print(f"{p.layer_bind.bind_point().point_name},level{p.layer_number},sort{p.sort_number}")
\ No newline at end of file
+ if not p.is_fake_node():
+ print(f"{p.layer_bind.bind_point().point_name},level{p.layer_number},sort{p.sort_number}")
+ else:
+ print(f"'{p.relate_bind.bind_point().point_name}',level{p.layer_number},sort{p.sort_number}")
\ No newline at end of file
diff --git a/graph/directed_acyclic_graph/DAGPresent.py b/graph/directed_acyclic_graph/DAGPresent.py
new file mode 100644
index 0000000..d962529
--- /dev/null
+++ b/graph/directed_acyclic_graph/DAGPresent.py
@@ -0,0 +1,82 @@
+from graph.directed_acyclic_graph.DAGLayout import DAGGraph
+from graph.DataType import Arrow, Point
+from typing import List
+from PyQt5.QtWidgets import QWidget, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
+from PyQt5.QtCore import QRectF, Qt
+from PyQt5.QtGui import QFont, QBrush
+import sys
+from enum import Enum
+
+
+class StoryFragmentNode(QGraphicsItem):
+ """
+ 故事情节名称节点
+ """
+ def __init__(self, name:str, font: QFont, parent):
+ QGraphicsItem.__init__(self, parent)
+
+ self.fragment_name = name
+ self.font_bind = font
+ self.data_bind: object = None
+ pass
+
+ def boundingRect(self) -> QRectF:
+ size = self.font_bind.pixelSize()
+ return QRectF(0, 0, size * len(self.fragment_name) + 10, size + 10)
+
+ def paint(self, painter, option, widget = ...):
+ outline = self.boundingRect()
+ text_rect = QRectF(outline.x()+5, outline.y()+5, outline.width()-10, outline.height() - 10)
+
+ painter.save()
+ painter.fillRect(outline, QBrush(Qt.gray))
+ painter.drawRect(outline)
+ painter.setFont(self.font_bind)
+ painter.drawText(text_rect, self.fragment_name)
+ painter.restore()
+
+
+ # 添加自定义功能函数
+ def attach_data(self, data_inst: object):
+ self.data_bind = data_inst
+ pass
+
+ def get_data(self) -> object:
+ return self.data_bind
+
+
+class Direction(Enum):
+ RankLR = 0,
+ RankTB = 1,
+
+
+class DAGActiveView(QGraphicsView):
+ def __init__(self, orie: Direction, parent):
+ QGraphicsView.__init__(self, parent)
+
+ self.orientation = orie
+ self.scene_bind = QGraphicsScene(self)
+ self.setScene(self.scene_bind)
+
+ font_global = QFont()
+ font_global.setPixelSize(20)
+ self.scene_bind.addItem(StoryFragmentNode("实例节点:示例情节", font_global, None))
+
+ pass
+
+ def update_with_edges(self, arrows: List[Arrow]) -> None:
+ tools = DAGGraph()
+ tools.rebuild_from_edges(arrows)
+ tools.graph_layout()
+
+ total_nodes = tools.nodes_with_layout
+
+
+ pass
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ view = DAGActiveView(Direction.RankLR, None)
+ view.show()
+ app.exec()
\ No newline at end of file
diff --git a/graph/dagpresent/__init__.py b/graph/directed_acyclic_graph/__init__.py
similarity index 100%
rename from graph/dagpresent/__init__.py
rename to graph/directed_acyclic_graph/__init__.py
diff --git a/graph/directed_acyclic_graph/__pycache__/DAGLayout.cpython-312.pyc b/graph/directed_acyclic_graph/__pycache__/DAGLayout.cpython-312.pyc
new file mode 100644
index 0000000..de3f886
Binary files /dev/null and b/graph/directed_acyclic_graph/__pycache__/DAGLayout.cpython-312.pyc differ
diff --git a/graph/directed_acyclic_graph/__pycache__/__init__.cpython-312.pyc b/graph/directed_acyclic_graph/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..ad685ac
Binary files /dev/null and b/graph/directed_acyclic_graph/__pycache__/__init__.cpython-312.pyc differ