1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| # coding: utf-8
# calcul Chemins par DFS J.P octobre 2021
from __future__ import unicode_literals
#from apso_utils import console, msgbox,mri
import os, uno, unohelper
from com.sun.star.awt import XActionListener
from com.sun.star.awt import ActionEvent
from com.sun.star.lang import EventObject
class ActionListener(unohelper.Base, XActionListener):
""" Listen to & count button clicks """
def __init__(self,odlg):
self.count = 0
self.oDlg = odlg
def actionPerformed(self, evt):
#msgbox('actionPerformed')
#msgbox(str(self.oDlg))
calculerChemin(self.oDlg)
return
def disposing(self, evt): # mandatory routine
pass
class Vertex:
"""The vertex used in the graph below"""
def __init__(self, key, data):
self.adjancencyList = {}
self.key = key
self.data = data
self.currCost = 0 # stores own weight added with followers in path
def connect(self, otherVertex, weight):
self.adjancencyList[otherVertex] = weight
def get_connections(self):
return self.adjancencyList.keys()
def get_cost(self, vertex):
return self.adjancencyList[vertex]
"""
This class is a weighted directed graph that is
supposed to be able to find all paths between two nodes
* The graph sorts all the paths by weight
* The graphs vertices uses keys to allow duplicates of data
* The graphs depth first search is based on recursion
"""
class Graph:
"""graph used to find all paths between two nodes using DFS"""
def __init__(self):
self.numberOfVertices = 0
self.vertices = {}
def add(self, key, data):
"""adds a vertex to graph and saves vertex based on unique key"""
if key not in self.vertices:
self.numberOfVertices += 1
self.vertices[key] = Vertex(key, data)
return True
return False
def addEdge(self, fromVertex, toVertex, weight):
"""connects two vertices"""
if fromVertex in self.vertices and toVertex in self.vertices:
self.vertices[fromVertex].connect(toVertex, weight)
return True
return False
def getAllPaths(self, start, end):
return self.dfs(start, end, [], [], [])
def getAllPathsSorted(self, start, end):
res = self.dfs(start, end, [], [], [])
return sorted(res, key=lambda k: k['poids'])
def dfs(self, currVertex, destVertex, visited, path, fullPath):
"""finds all paths between two nodes, returns all paths with their respective cost"""
# get vertex, it is now visited and should be added to path
vertex = self.vertices[currVertex]
visited.append(currVertex)
path.append(vertex.data)
# save current path if we found end
if currVertex == destVertex:
fullPath.append({"chemin": list(path), "poids": vertex.currCost})
for i in vertex.get_connections():
if i not in visited:
self.vertices[i].currCost = vertex.get_cost(i) + vertex.currCost
self.dfs(i, destVertex, visited, path, fullPath)
# continue finding paths by popping path and visited to get accurate paths
path.pop()
visited.pop()
if not path:
return fullPath
class Dialogue():
def __init__(self):
model = XSCRIPTCONTEXT.getDocument()
smgr = XSCRIPTCONTEXT.getComponentContext().ServiceManager
dp = smgr.createInstanceWithArguments( "com.sun.star.awt.DialogProvider", (model,))
self.oDlg = dp.createDialog( "vnd.sun.star.script:Standard.Dialog1?location=document")
ctl = self.oDlg.getControl('CalChemin')
act = ActionListener(self.oDlg)
ctl.addActionListener(act)
def AfficheDialog(self,*args):
self.oDlg.execute()
self.oDlg.dispose()
oDlg=None
def calculerChemin(oDlg):
#msgbox('CalculerChemin')
gr = Graph()
doc = XSCRIPTCONTEXT.getDocument()
oDP = doc.getDrawPages().getByIndex(0)
count = oDP.Count
for i in range(0,count):
oItem = oDP.getByIndex(i)
if oItem.ShapeType == "com.sun.star.drawing.ConnectorShape":
gr.addEdge(oItem.StartShape.Name,oItem.EndShape.Name,1)
#msgbox(oItem.StartShape.Name+ ":" + oItem.EndShape.Name)
else:
gr.add(oItem.Name,oItem.Name)
#msgbox(oItem.Name)
dep = oDlg.getControl("Dep")
arr = oDlg.getControl("Arr")
res = gr.getAllPathsSorted(dep.getText(), arr.getText())
#msgbox('résultat : ' + str(res))
chemins = ""
for chemin in res:
chemins += str(chemin) + os.linesep
oDlg.getControl('Resultat').setText(chemins)
def calculCheminDlg():
dial = Dialogue()
oDlg = dial.oDlg
dial.AfficheDialog()
g_exportedScripts = (calculCheminDlg,) |
Partager