-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrafos_jme.jmes
230 lines (217 loc) · 6.07 KB
/
grafos_jme.jmes
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
##############################################
# Visor de grafos JME, v0.1.1
#
# Dibuja grafos/digrafos/pseudografos
# (no multigrafos) para una expresión JME
# que devuelva un pseudotipo grafo
#---------------------------------------------
# JMEScript 0.2.0
##############################################
# Miguel Alejandro Moreno Barrientos, (C)2021
##############################################
# BOTON3: nueva expresión
# BOTON1: arrastrar nodos
# BOTON3: cerrar
##############################################
# tamaño ventana
_tama := 700
# tamaño letra nodos
_letra_tama := 20
# array de nodos gráficos, posición del ratón en ventana, nodo seleccionado para 'drag'
nodos, mousepos, nodo_elegido := nulo
# iniciar visor
ctx2d iniciar _tama _tama titulo 'Grafos JME'
llamar a solicitar_grafo()
# bucle principal
mientras verdadero inicio:
# leer ratón
ctx2d click en mouseclick
si !indefinido(['mouseclick']) inicio:
seleccionar mouseclick><'id' inicio:
caso 'RELEASED' inicio:
seleccionar mouseclick><'boton' inicio:
# dejar de arrastrar nodo
caso 'BOTON1' inicio:
nodo_elegido, mousepos := nulo
llamar a pintar_grafo()
fin
# cerrar script
caso 'BOTON2' inicio:
ctx2d finalizar
devolver
fin
# introducir grafo
caso 'BOTON3' inicio:
llamar a solicitar_grafo()
fin
fin
fin # caso released
caso 'PRESSED' inicio:
# seleccionar nodo
si mouseclick><'boton' = 'BOTON1' inicio:
mousepos := mouseclick><'posicion'
llamar a pinchar_nodo()
si nodo_elegido == nulo inicio:
mousepos := nulo
fin
fin
fin # caso pressed
caso 'DRAGGED' inicio:
# arrastrar nodo seleccionado
si nodo_elegido != nulo inicio:
pos := mouseclick><'posicion'
# establecer posición del nodo siempre dentro del visor
nodo_elegido{'pos'} := [ min( max( pos><0, 0 ), _tama ),
> min( max( pos><1, 0 ), _tama ) ]
pos :=
llamar a pintar_grafo()
fin
fin # caso dragged
fin # seleccionar
fin # si
fin # mientras
# obtener nodo seleccionado o 'nulo' si se pincha fuera de cualquier nodo
procedimiento global pinchar_nodo() inicio:
si nodos = nulo inicio:
romper rutina
fin
# comprobar click dentro de un nodo
para cada nodo en revertir(nodos) inicio:
si mod( nodo><'pos' - mousepos ) <= nodo><'radio' inicio:
nodo_elegido := nodo
romper rutina
fin
fin
# no se pinchó dentro de ninguno
nodo_elegido := nulo
fin
# solicitar grafo a usuario
procedimiento global solicitar_grafo() inicio:
# pedir expresión JME
ctx2d leer en entrada
> tipo 'expresion'
> msj 'Grafo'
# entrada cancelada
si entrada = __error1__ inicio:
ctx2d finalizar
devolver
fin
# error en la expresión JME
si no, si entrada = __error2__ inicio:
ctx2d msj 'Error en la expresión'
> tipo 'error'
> toast 1000
fin
# iniciar grafo, nodos gráficos y redibujar
si no, si gr_esgrafo(entrada) inicio:
grafo := entrada
llamar a iniciar_nodos()
llamar a pintar_grafo()
fin
# entrada válida pero no grafo, mostrar resultado
si no inicio:
ctx2d msj entrada
> tipo 'info'
fin
entrada :=
fin
# iniciar información de nodos gráficos en el visor
procedimiento global iniciar_nodos() inicio:
nn := gr_orden(grafo)
# establecer tamaño en pantalla de las etiquetas de cada nodo
etiquetas_dim := []
para cada etiqueta en grafo><'etiquetas' inicio:
ctx2d texto etiqueta dimension en txtdim
> tama _letra_tama
etiquetas_dim ;= txtdim
fin
# crear diccionarios de nodos
nodos := sucesion( dic( 'idx', i,
> 'etiqueta', gr_etiquetas( grafo, i ),
> 'pos',
> 0.4*_tama*[cos(pi2/nn*i),sin(pi2/nn*i)]
> + [ _tama/2, _tama/2 ],
> 'color',
> 255[rand(0.2,1,-1),rand(0.2,1,-1),rand(0.2,1,-1)],
> 'radio',
> hypot( etiquetas_dim><i><0, etiquetas_dim><i><1 )/2,
> 'txtdim',
> etiquetas_dim><i ),
> i, 0, nn-- )
etiqueta, etiquetas_dim, nn, txtdim :=
fin
# pintar nodos, aristas/arcos y pesos en pantalla
procedimiento global pintar_grafo() inicio:
ctx2d entorno en ent
ctx2d limpiar color ent><'lienzo.color.fondo'
ent :=
si nodos = nulo inicio:
romper rutina
fin
# pintar aristas/arcos
nn := gr_orden(grafo)
para i := 0 hasta nn-- inicio:
para j := if( grafo><'esDirigido', 0, i ) hasta nn-- inicio:
si gr_adyacente(grafo,i,j) inicio:
ctx2d color linea '#FFEEAA'
> relleno '#FFEEAA'
# dibujar arcos que no son bucles
si i != j inicio:
p, q :== [ nodos><i><'pos', nodos><j><'pos' ]
upq := unit(q-p)
a := p + upq*nodos><i><'radio'
b := q - upq*nodos><j><'radio'
ctx2d segmento inicio a final b
si grafo><'esDirigido' inicio:
ctx2d circunferencia
> centro q - upq*( nodos><j><'radio' + 4 )
> radio 4
> relleno verdadero
fin
ctx2d color linea '#AAFFAA'
si grafo><'esPonderado' inicio:
ctx2d texto stexto( grafo><'ady'><i><j )
> posicion (a+b)/2
> tama 14
fin
fin
# dibujar bucles
si no inicio:
p, r :== [ nodos><i><'pos', nodos><i><'radio' ]
ctx2d circunferencia
> centro p - [0,r]
> radio r
> angulo -30
> arco 240
si grafo><'esDirigido' inicio:
ctx2d circunferencia
> centro p + unit(-30º)*(r+4)
> radio 4
> relleno verdadero
fin
si grafo><'esPonderado' inicio:
ctx2d color linea '#AAFFAA'
ctx2d texto stexto( grafo><'ady'><i><j )
> posicion p - [0,2r+11]
> tama 14
fin
fin
fin
fin # para
fin # para
# pintar nodos
para i := 0 hasta nn-- inicio:
nodo := nodos><i
ctx2d color linea nodo><'color'
> relleno nodo><'color'*0.5
ctx2d circunferencia centro nodo><'pos'
> radio nodo><'radio'
> relleno verdadero
ctx2d texto nodo><'etiqueta'
> posicion nodo><'pos'
> - [ nodo><'txtdim'><0 / 2, nodo><'txtdim'><1 / 2 ]
> tama _letra_tama
fin
nn, i, j, r, a, b, p, q, upq, nodo :=
ctx2d repintar
fin