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 @@ - - - - - + - + + - + - + - + - - - - + + - - - + + - - - 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