?.1B.1< 2; .A2:HA60.@ 2 ;3

119
',# $/&#) ?.1B.1< 2; .A2:HA60.@ 2 ;3<?:HA60. /E@M<IJ@;8; *FC@KS:E@:8 ;< '8;I@; J:L<C8 .S:E@:8 -LG<I@FI ;< #E><E@<IFJ #E=FIDRK@:FJ &$" ! $" ,<GLCJ@VE <E I<>@FE<J GFC@>FE8C<J LKFI8 '8IT8 G8I@:@F ,F;IT>L<Q @I<:KFI '8EL<C 9<CC8E8J )8I

Transcript of ?.1B.1< 2; .A2:HA60.@ 2 ;3

Page 1: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 2: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 3: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 4: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 5: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 6: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 7: ?.1B.1< 2; .A2:HA60.@ 2 ;3

o

o

Page 8: ?.1B.1< 2; .A2:HA60.@ 2 ;3

o

o

Page 9: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 10: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 11: ?.1B.1< 2; .A2:HA60.@ 2 ;3

o

o

Page 12: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 13: ?.1B.1< 2; .A2:HA60.@ 2 ;3

β

Page 14: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 15: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 16: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 17: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 18: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 19: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 20: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 21: ?.1B.1< 2; .A2:HA60.@ 2 ;3

••

Page 22: ?.1B.1< 2; .A2:HA60.@ 2 ;3

P Conjunto de puntos A Actuador Concavos Lista con todos los vértices cóncavos Proyecciones Array de tuplas cuyo primer elemento son todas las aristas en las que se cumple que la proyección del actuador sobre el segmento que las contiene pertenece a la arista. El segundo elemento determina el número de intersecciones con el polígono que presenta la arista (A, proyección). numInters Número de intersecciones de una arista con un polígono.

angulo(punto) Calcula el ángulo del vértice del polígono (a), teniendo en cuenta los otros dos vértices que van unidos a él y siguiendo el orden que marca el polígono (b y c). De los dos ángulos que se obtienen (bac y cab), se escoge el interior. ang(A,B,C) Obtiene el ángulo ABC. segmentIntersection(A,B) Devuelve una tupla. El primer elemento es False si no cortan o forman una T y True si intersecan. El segundo es el punto de intersección. intersecciona(Pol, segmento) Devuelve una tupla. El primer elemento es un booleano que indica si un segmento tiene intersección con alguna arista de un polígono, Pol. El segundo elemento es el número de intersecciones de un segmento con las aristas de un polígono (Pol). dibujarPunto(p) Dibuja el punto p. dibujarSegmento(p) Dibuja el segmento p. aristas(Pol) Aristas del polígono. nuevaRegion(reg) Crea una nueva región y la añade al conjunto reg. colorearRegion(reg) Colorea la región reg de un color distinto de los ya usados para distinguirla de las demás.

anterior = Pol[Pol.index(punto) - 1] siguiente = Pol[Pol.index(punto) + 1] segmentos, regiones = [],[] For each punto in Pol: dibujarPunto(punto) dibujarSegmento((anterior, punto)) segmentos.append((anterior, punto)) proy proyección del actuador sobre la recta (anterior, punto) If angulo(punto) > 180 and ang(anterior, punto, A) > 90 and ang(A, punto, siguiente) > 90: Concavos.append(punto)

If segmentIntersection((proy, A), (anterior, punto)): Inte = intersecciona(Pol,(proy, A)) If Inte[0]:

Page 23: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Proyecciones.append((anterior, punto), proy, Inte[1]) Else: Proyecciones.append((anterior,punto), proy, 0) anterior = punto

siguiente = Pol[Pol.index(punto) + 2] For each punto in Proyecciones:

interseccionAux = (punto,A) If Proyecciones[2] == 0: segmentos.append(A, Proyecciones[1]) dibujarSegmento(A, Proyecciones[1]) Else: For arista in aristas(Pol):

If segmentIntersection(arista, (A, Proyecciones[1])) [0] and dist(segmentIntersection(arista, (A, Proyecciones[1])) [1]) < dist(segmentIntersection(arista, interseccionAux):

interseccionAux = (segmentIntersection(arista, (A, Proyecciones[1])) [1], Proyecciones[1])

segmentos.append(interseccionAux)

dibujarSegmento(interseccionAux) inicio = A For each segmento in segmentos: If segmento[1] == inicio: Regiones[len(Regiones)].append(segmento) colorearRegion(Regiones[len(Regiones)]) nuevaRegion(Regiones) Else: Regiones[len(Regiones)].append(segmento)

Page 24: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def dist2(A,B): return (B[0] - A[0])**2 + (B[1] - A[1])**2

In [1]: dist2((1,2),(3,8)) Out[1]: 40

1 | def dist(A,B): return mth.sqrt(dist2(A,B))

In [1]: dist((1,2),(3,8)) Out[1]: 6.324555320336759

1 | def aleatorio(n, rango): return np.random.rand(n)*rango

nrango

In [1]: aleatorio(3, 4) Out[1]: array([0.48648661, 1.17395347, 1.56141467])

1 | def angulo(A,B,C): 2 | a,b,c = np.array([A[0], A[1]]), np.array([B[0], B[1]]), np.array([C[0], C[1]]) 3 | angulo = round(np.degrees(np.arccos(np.dot(a - b, c - b) / (np.linalg.norm(a - b) * np.linalg.norm(c - b)))), 3) 4 | if sarea(A,B,C) <= 0: return angulo 5 | else: return 360 - angulo

Page 25: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: angulo((50,25),(25,15),(5,10)) Out[1]: 172.235 In [1]: angulo((5,10),(25,15),(50,25)) Out[1]: 187.765

1 | def maxAbscisa(P): 2 | maxA = P[0] 3 | for x in P: 4 | if x[0] > maxA[0] or (x[0] == maxA[0] and x[1] > maxA[1]): maxA= x 5 | return maxA In [1]: maxAbscisa([(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10)]) Out[1]: (95,25)

1 | def minAbscisa(P): 2 | minA = P[0] 3 | for x in P: 4 | if x[0] < minA[0] or (x[0] == minA[0] and x[1] < minA[1]): minA = x 5 | return minA In [1]: minAbscisa([(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10)]) Out[1]: (0,30)

1 | def maxOrdenada(P): 2 | maxO = P[0] 3 | for x in P: 4 | if x[1] > maxO[1] or (x[1] == maxO[1] and x[0] > maxO[0]): maxO = x 5 | return maxO

Page 26: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: maxOrdenada([(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10)]) Out[1]: (30,58)

1 | def minOrdenada(P): 2 | minO = P[0] 3 | for x in P: 4 | if x[1] < minO[1] or (x[1] == minO[1] and x[0] < minO[0]): minO = x 5 | return minO In [1]: minOrdenada([(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10)]) Out[1]: (35,3)

1 | def sarea(A,B,C): 2 | sarea = (1/2)*(A[0]*(B[1]-C[1]) + B[0]*(C[1]-A[1]) + C[0]*(A[1]- B[1])) 3 | if - 0.0001 < sarea < 0.0001: return 0 4 | else: return sarea

Page 27: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: sarea([1,1.5],[0.5,3],[-1,2.5]) Out[1]: 1.25 In [2]: sarea([-0.25,0.5],[-1,4],[8,5]) Out[2]: -16.125 In [3]: sarea([0.5,0.5],[-1.5,2.5],[0.5,0.5]) Out[3]: 0.0

1 | def orient(A,B,C): return np.sign(sarea(A,B,C))

In [1]: orient([1,1.5],[0.5,3],[-1,2.5]) Out[1]: 1.0 In [2]: orient([-1,1.5],[-0.5,0.5],[-1.5,-0.5]) Out[2]: -1.0

Page 28: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [3]: orient([0.5,0.5],[-1.5,2.5],[0.5,0.5]) Out[3]: 0.0

1 | def poligoniza(P): 2 | LPositivos, LNegativos, Max, Min = [], [], max(P), min(P) 3 | for i in range(len(P)): 4 | if sarea(Max,P[i],Min) >= 0: LPositivos.append(P[i]) 5 | else: LNegativos.append(P[i]) 6 | LPositivos = sorted(LPositivos) 7 | LPositivos.reverse() 8 | return sorted(LNegativos) + LPositivos

poligoniza()

Page 29: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: dibujarAristas( [(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10), (-5,20), (30,20), (15,25), (0,-4)].

In [1]: dibujarAristas( poligoniza( [(0,30), (50,35), (95,25), (50,20), (35,3), (30,10), (35,25), (35,10), (30,58), (15,10), (22,15), (40,10), (-5,20), (30,20), (15,25), (0,-4)]).

1 | def sareaPolygon(p): 2 | a = 0 3 | for i in range(len(p)): a += sarea(p[0], p[i-1], p[i]) 4 | return a

In [1]: sareaPolygon(poligoniza([(2.8, 1.4), (2.2, 1.7), (1, 1),(0.5, 0.9),(0.1, 2.2),(0.4, 0.3)])) Out[1]: 1.995

1 | def orientaPositivamente(Pol): 2 | if sareaPolygon(Pol) > 0: Pol.reverse() 3 | return Pol

Page 30: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: orientaPositivamente(poligoniza([(2.8, 1.4), (2.2, 1.7), (1, 1),(0.5, 0.9),(0.1, 2.2),(0.4, 0.3)])) Out[1]: [(0.1, 2.2), (2.2, 1.7), (2.8, 1.4), (1, 1), (0.5, 0.9), (0.4, 0.3)]

rango

1 | def poligonoAleatorio(p, rango): 2 | Pol = [] 3 | for i in range(p): Pol.append((round(aleatorio(1, rango)[0], 4), round(aleatorio(1, rango)[0], 4))) 4 | return orientaPositivamente(poligoniza(Pol))

In [1]: poligonoAleatorio(6,3) Out[1]: [(0.899, 0.935), (0.9731, 1.7247), (0.9763, 2.3443), (1.7132, 2.3991), (2.1516, 2.6612), (2.9494, 1.0971)]

return

1 | def enSegmento(P,s): 2 | if (sarea(P,s[0],s[1]) == 0) and max(s[0][0],s[1][0]) >= P[0] and max(s[0][1],s[1][1]) >= P[1] and min(s[0][0],s[1][0]) <= P[0] and min(s[0][1],s[1][1]) <= P[1]: return 1

Page 31: ?.1B.1< 2; .A2:HA60.@ 2 ;3

3 | else: return 0 In [1]: (enSegmento([-2,3],[[-1,2],[-2.5,3.5]]), #P está contenido en s ...: enSegmento([-3,4],[[-1,2],[-3,4]]), #P es un extremo de s ...: enSegmento([-3,4],[[-1,2],[-2.5,3.5]]), #P pertenece a la recta que contiene s, pero no a s ...: enSegmento([-2,2],[[-1,2],[-2.5,3.5]])) #P no contenido en s Out[1]: (1, 1, 0, 0)

Page 32: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def proyeccionPuntoRecta(r,P): 2 | v = [r[1][0]-r[0][0],r[1][1]-r[0][1]] 3 | v /= np.linalg.norm(v, 2) 4 | nuevoPunto = r[0] + v * np.dot([P[0]-r[0][0],P[1]-r[0][1]], v) 5 | return (nuevoPunto[0],nuevoPunto[1])

In [1]: proyeccionPuntoRecta([[-2,4],[-2,1]],[0,3]) # Recta vertical Out[1]: (-2.0, 3.0) In [2]: proyeccionPuntoRecta([[-1,1],[3,1]],[0,3]) # Recta horizontalOut[2]: (0.0, 1.0) In [3]: proyeccionPuntoRecta([[3,2],[4,5]],[9,2]) # Recta diagonal Out[3]: (3.6, 3.8)

1| def proyeccionPuntoRecta(r,P): 2 | if ((r[0][0] - r[1][0]) != 0) and ((r[0][1] - r[1][1]) != 0): 3 | m = (r[0][1] - r[1][1]) / (r[0][0] - r[1][0]) 4 | A, b = np.array([[m,-1],[-1/(m),-1]]), np.array([m*r[0][0] - r[0][1],- (P[1] + (1/m)*P[0])]) 5 | z = np.linalg.solve(A,b) z = (round(z[0],2),round(z[1],2) 7 | return z 8 | elif (r[0][0] - r[1][0]) == 0: return (r[0][0],P[1]) 9 | else: return (P[0],r[0][1])

Page 33: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def aristas(Pol): 2 | aristas, anterior = [], Pol[len(Pol) - 1] 3 | for punto in Pol: 4 | aristas.insert(len(aristas),(anterior,punto)) 5 | anterior = punto 6 | return aristas

In [1]: aristas([(0,30), (50,35), (55,25), (50,20), (35,30)]) Out[1]: [((35, 30), (0, 30)), ((0, 30), (50, 35)), ((50, 35), (55, 25)), ((55, 25), (50, 20)), ((50, 20), (35, 30))]

1 | def segmentIntersectionTest(a,b): 2 | if (enSegmento(a[0], b) and enSegmento(a[1], b)) or (enSegmento(b[0], a) and enSegmento(b[1], a)): return (True, 1) 3 | elif b[0] == a[0] or b[0] == a[1] or b[1] == a[0] or b[1] == a[1]: return (True, 2) 4 | elif enSegmento(b[0], a) or enSegmento(b[1], a) or enSegmento(a[0], b) or enSegmento(a[1], b): return (False, 3) 5 | elif orient(a[0], a[1], b[0]) != orient(a[0], a[1], b[1]) and orient(b[0], b[1], a[0]) != orient(b[0], b[1], a[1]): return (True, 4) 6 | else: return (False, 5)

True False

Page 34: ?.1B.1< 2; .A2:HA60.@ 2 ;3

False

12345

In [1]: segmentIntersectionTest([(2,0),(1,3)],[(3,3),(-2,1)]) Out[1]: (True, 4) # Se cruzan In [2]: segmentIntersectionTest([(1,0),(-2,6)],[(-1,1),(-1,4)]) Out[2]: (False, 3) # Forman una T In [3]: segmentIntersectionTest([(2,4),(-2,6)],[(-1,1),(-1,4)]) Out[3]: (False, 5) # No se cruzan In [4]: segmentIntersectionTest([(7,0),(4,2)],[(4,2),(2,6)]) Out[4]: (True, 2) # Comparten vertex In [5]: segmentIntersectionTest([(7,0),(4,6)],[(6,2),(5,4)]) Out[5]: (True, 1) # Contenido dentro del otro

1 | def lineIntersection(a, b): 2 | def det(a, b): 3 | return a[0] * b[1] - a[1] * b[0] 4 | xD = (a[0][0] - a[1][0], b[0][0] - b[1][0]) 5 | yD = (a[0][1] - a[1][1], b[0][1] - b[1][1]) 6 | div = det(xD, yD) 7 | if div == 0: 8 | return 'Son la misma recta' 9 | d = (det(*a), det(*b))

Page 35: ?.1B.1< 2; .A2:HA60.@ 2 ;3

10| x = det(d, xD) / det(xD, yD) 11| y = det(d, yD) / det(xD, yD) 12| return (x, y)

1 | def puntoEnPol(P,p): 2 | if p in P: return True 3 | maximo = (P[0], P[0][1]) 4 | for punto in P: 5 | if punto[1] > maximo[1]: maximo = (punto, max(maximo[1], punto[1])) 6 | contador, vertice = 0, (maximo[0][0], maximo[0][1] + 2) 7 | segmento = [p, vertice] 8 | for arista in aristas(P): 9 | if enSegmento(p,arista): return True 10| if (segmentIntersectionTest(arista, segmento)[0] and segmentIntersectionTest(arista,segmento)[1] != 1): contador += 1 11| if contador % 2 == 0: return False 12| else: return True

False True

Page 36: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 37: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: puntoEnPol([(3,8),(-1,5),(7,7),(-1,3),(2,0),(-5,3),(-5,7),(-3,5),(-2,7)],(-2,7)) Out[1]: True In [2]: puntoEnPol([(3,8),(-1,5),(7,7),(-1,3),(2,0),(-5,3),(-5,7),(-3,5),(-2,7)],(2,5)) Out[2]: True In [3]: puntoEnPol([(3,8),(-1,5),(7,7),(-1,3),(2,0),(-5,3),(-5,7),(-3,5),(-2,7)],(-3,0)) Out[3]: False In [4]: puntoEnPol([(3,8),(-1,5),(7,7),(-1,3),(2,0),(-5,3),(-5,7),(-3,5),(-2,7)],(-4,4)) Out[4]: True

Page 38: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def puntoDelPol(Pol): 2 | p = (0,0) 3 | while not puntoEnPol(Pol,p) or p == (0,0): p = aleatorio(1, maxAbscisa(Pol))[0], aleatorio(1, maxAbscisa(Pol))[0]) 4 | print(p) 5 | return p

In [1]: puntoDelPol(poligoniza([(2.8, 1.4), (2.2, 1.7), (1, 1),(0.5, 0.9),(0.1, 2.2),(0.4, 0.3)])) Out[1]: (1.893, 1.5839) In [2]: puntoDelPol(poligoniza([(2.8, 1.4), (2.2, 1.7), (1, 1),(0.5, 0.9),(0.1, 2.2),(0.4, 0.3)])) Out[2]: (0.6882, 1.1393)

while

1 | def segmentoEnPol(Pol, s): 2 | for arista in aristas(Pol): 3 | if segmentIntersectionTest(arista, s)[0] or (segmentIntersectionTest(arista, s)[1] == 3 and not puntoEnPol(Pol, (((s[0][0] + s[1][0])/2), ((s[0][1] + s[1][1])/2)))): return False 4 | return puntoEnPol(Pol, s[0])

Page 39: ?.1B.1< 2; .A2:HA60.@ 2 ;3

True

False

True

In [1]: segmentoEnPol([(-1,8),(1,4),(3,3),(1,1),(-2,0),(-7,5),(-1,3),(-4,7),(-3,9)],[(-2,7),(1,7)]) Out[1]: False In [2]: segmentoEnPol([(-1,8),(1,4),(3,3),(1,1),(-2,0),(-7,5),(-1,3),(-4,7),(-3,9)],[(1,3),(-1,2)]) Out[2]: True In [3]: segmentoEnPol([(-1,8),(1,4),(3,3),(1,1),(-2,0),(-7,5),(-1,3),(-4,7),(-3,9)],[(-6,4),(-4,2)]) Out[3]: False In [4]: segmentoEnPol([(-1,8),(1,4),(3,3),(1,1),(-2,0),(-7,5),(-1,3),(-4,7),(-3,9)],[(1,4),(3,4)]) Out[4]: False

Page 40: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def dibujarVertices(Pol): 2 | fig, ax = plt.subplots() 3 | for punto in Pol: ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) 4 | # Representación 5 | plt.axis('on') 6 | plt.axis('equal') 7 | return plt.show()

In [1]: dibujarVertices([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)])

Out[1]:

Page 41: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def dibujarAristas(Pol): 2 | fig, ax = plt.subplots() 3 | anterior = Pol[len(Pol) - 1] 4 | for punto in Pol: 5 | ax.plot(punto[0], punto[1], '.', color ='#000000', ms = 10) 6 | ax.add_artist(ConnectionPatch(xyA = (anterior[0], anterior[1]), xyB = (punto[0], punto[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 7 | anterior = punto 8 | # Representación 9 | plt.axis('on') 10| plt.axis('equal') 11| return plt.show()

In [1]: dibujarAristas([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)])

Out[1]:

Page 42: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def rellenarAristas(Pol, A): 2 | fig, ax = plt.subplots() 3 | patches, pol, anterior = [], [], Pol[len(Pol) - 1] 4 | ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) #Actuador 5 | for punto in Pol: 6 | ax.plot(punto[0], punto[1], '.', color ='#000000', ms = 10) 7 | pol.insert(len(pol),[punto[0],punto[1]]) 8 | ax.add_artist(ConnectionPatch(xyA = (anterior[0], anterior[1]), xyB = (punto[0], punto[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 9 | anterior = punto 10| # Representación 11| patches.append(Polygon(pol, True, color = (0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4))) 12| ax.add_collection(PatchCollection(patches, match_original = True)) 13| ax.legend([Line2D([0],[0], marker = 'o', linestyle = ':', color = '#47ECFF', markersize = 7)], ['Actuador']) 14| plt.axis('on') 15| plt.axis('equal') 16| return plt.show()

pol

In [1]: rellenarAristas([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Page 43: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Out[1]:

1 | def dibujarPerpendiculares(Pol, A):2 | fig, ax = plt.subplots() 3 | patches, pol, anterior = [], [], Pol[len(Pol) - 1] 4 | ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) #Actuador 5 | for punto in Pol: 6 | ax.plot(punto[0], punto[1], '.', color ='#000000', ms = 10) 7 | pol.insert(len(pol),[punto[0], punto[1]])

Page 44: ?.1B.1< 2; .A2:HA60.@ 2 ;3

8 | ax.add_artist(ConnectionPatch(xyA = (anterior[0], anterior[1]), xyB = (punto[0], punto[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 9 | # Vértices cóncavos 10| index = Pol.index(punto) 11| ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] 12| if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): 13| if angulo(ant, punto, sig) > 180: ax.add_artist( ConnectionPatch( xyA = (A[0], A[1]), xyB = (punto[0], punto[1]), linestyle = '-.', coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#6666FF') 14| # Proyecciones 15| proy = proyeccionPuntoRecta((anterior, punto), A) 16| if enSegmento(proy,(anterior, punto)): 17| if not segmentoEnPol(Pol, (proy, A)): ax.add_artist( ConnectionPatch( xyA = (A[0], A[1]), xyB = (proy[0], proy[1]), linestyle = '-.', coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#CC9900')) 18| else: ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0], proy[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 19| anterior = punto 20| # Representación 21| patches.append(Polygon(pol, True, color = (0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4))) 22| ax.add_collection(PatchCollection(patches, match_original = True)) 23| ax.legend([Line2D([0],[0], linestyle = '-.', color = '#CC9900', lw = 1.5), Line2D([0],[0], linestyle = '-.', color = '#6666FF', lw = 1.5), Line2D([0],[0], color = '#000000', lw = 2)], ['Proyecciones con intersección', 'Vértices cóncavos', 'Proyecciones sin intersección']) 24| plt.axis('on') 25| plt.axis('equal') 26| return plt.show()

In [1]: dibujarPerpendiculares([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Page 45: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Out[1]:

regionActual

regionActual

regionActual

regionActual

Page 46: ?.1B.1< 2; .A2:HA60.@ 2 ;3

1 | def colorearRegiones(Pol, A): 2 | fig, ax = plt.subplots() 3 | ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) #Actuador 4 | patches, proyecciones, anterior = [], [], Pol[len(Pol) - 1] 5 | for punto in Pol: 6 | ax.plot(punto[0], punto[1], '.', color ='#000000', ms = 10) 7 | ax.add_artist(ConnectionPatch(xyA = (anterior[0], anterior[1]), xyB = (punto[0], punto[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 8 | # Vértices cóncavos 9 | index = Pol.index(punto) 10| ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] 11| if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): 12| if angulo(ant, punto, sig) > 180: 13| anteriorAux, inters = Pol[len(Pol) - 1], 0

Page 47: ?.1B.1< 2; .A2:HA60.@ 2 ;3

14| for puntoAux in Pol: 15| if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters + 1 16| anteriorAux = puntoAux 17| if inters%2 == 0 or inters == 1: ax.add_artist( ConnectionPatch( xyA = (A[0], A[1]), xyB = (punto[0], punto[1]), linestyle = '-.', coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 18| # Proyecciones 19| proy = proyeccionPuntoRecta((anterior, punto),A) 20| or1, or2 = orient(ant, punto, A), orient(A, punto, sig) 21| if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): 22| proyecciones.append(((anterior,punto), False, proy)) 23| ant, inters = Pol[len(Pol) - 1], 0 24| for pun in Pol: 25| if segmentIntersectionTest((ant, pun),(proy,A))[0]: inters = inters+1 26| ant = pun 27| if inters%2 == 0: ax.add_artist(ConnectionPatch(xyA = (A[0], A[1]), xyB = (punto[0], punto[1]), linestyle = '-.', coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 28| elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): 29| proyecciones.append(((anterior,punto), True, proy)) 30| ax.add_artist( ConnectionPatch( xyA = (A[0], A[1]), xyB =(punto[0], punto[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 31| else: 32| proyecciones.append(((anterior,punto), False, proy)) 33| anterior = punto 34| # Se crean las regiones 35| regionActual, regiones = [], [] 36| while not proyecciones[0][1]: 37| proyecciones.append(proyecciones[0]) 38| proyecciones.remove(proyecciones[0]) 39| for x in proyecciones: 40| if x == proyecciones[len(proyecciones) - 1]: 41| if x[1]: 42| regionActual[len(regionActual): len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] 43| regiones.insert(len(regiones),regionActual) 44| regionActual = [] 45| regionActual[len(regionActual): len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] 46| y = proyecciones[0]

Page 48: ?.1B.1< 2; .A2:HA60.@ 2 ;3

47| while not y[1]: 48| regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) 49| y = proyecciones[proyecciones.index(y) + 1] 50| regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) 51| regiones.insert(len(regiones),regionActual) 52| elif not x[1]: 53| regionActual[len(regionActual): len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] 54| y = proyecciones[0] 55| while not y[1]: 56| regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) 57| y = proyecciones[proyecciones.index(y) + 1] 58| regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) 59| regiones.insert(len(regiones),regionActual) 60| elif x[1]: 61| if x != proyecciones[0]: 62| regionActual[len(regionActual): len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] 63| regiones.insert(len(regiones),regionActual) 64| regionActual = [] 65| regionActual[len(regionActual): len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] 66| elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]]) 67| # Representación 68| colores = [(0.650980... ...0.4)] 69| for region in regiones: patches.append(Polygon(region, True, color = colores[regiones.index(region)%12])) 70| ax.add_collection(PatchCollection(patches, match_original = True)) 71| plt.axis('on') 72| plt.axis('equal') 73| return plt.show()

while

for while

In [1]: colorearRegiones([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Page 49: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Out[1]:

proyeccionesConInters concavos

1 | def colorearTodasRegiones(Pol, A): 2 | . . # Mismo código que colorearRegiones(Pol, A) 66| . 67| # REGIONES DE VÉRTICES CÓNCAVOS Y PROYECCIONES QUE INTERSECAN 68| # Vértices cóncavos 69| calculados = [] 70| for vertice in concavos: 71| for region in regiones: 72| if [vertice[0], vertice[1]] in region and vertice not in calculados:

Page 50: ?.1B.1< 2; .A2:HA60.@ 2 ;3

73| calculados.append(vertice) 74| while region[0] != [vertice[0], vertice[1]]: 75| region.append(region[0]) 76| region.remove(region[0]) 77| anterior, interseccion = (region[len(region)-1][0], region[len(region)-1][1]), A 78| for punto in region: 79| punto = (punto[0], punto[1]) 80| lineI = lineIntersection((anterior, punto), (vertice, A)) 81| if orient(vertice, punto, A) != orient(vertice, anterior, A) and vertice != anterior and vertice != punto and A != anterior and A != punto: 82| if dist(vertice, interseccion) > dist(vertice, lineI) and dist(A, lineI) < dist(A, vertice): interseccion = lineI 83| anterior = (punto[0], punto[1]) 84| region1, region2, pasado, pasad = [],[], False, False 85| ant = (region[(len(region)-1)][0], region[(len(region)-1)][1]) 86| for punt in region: 87| if interseccion == A: 88| if (punt[0], punt[1]) == A: 89| pasad = True 90| region1.append(punt) 91| region2.append(punt) 92| elif not pasad: region1.append(punt) 93| elif pasad: region2.append(punt) 94| elif enSegmento(interseccion, (ant,(punt[0],punt[1]))) == 0 and not pasado: 95| region1.append(punt) 96| ant = (punt[0], punt[1]) 97| elif enSegmento(interseccion, (ant,(punt[0],punt[1]))) == 1 and not pasado: 98| region1.append([interseccion[0],interseccion[1]]) 99| region2.append([interseccion[0],interseccion[1]]) 100| region2.append(punt) 101| ant, pasado = (punt[0], punt[1]), True 102| elif enSegmento(interseccion, (ant, (punt[0], punt[1]))) == 0 and pasado: 103| region2.append(punt) 104| ant = (punt[0], punt[1]) 105| region2.append([vertice[0],vertice[1]]) 106| ax.add_artist(ConnectionPatch(xyA = (vertice[0], vertice[1]), xyB = (interseccion[0], interseccion[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000') 107| regiones.insert(0, region1) 108| regiones.insert(0, region2) 109| regiones.remove(region) 110| # Proyecciones que intersecan 111| calculados = [] 112| for proy in proyeccionesConInters:

Page 51: ?.1B.1< 2; .A2:HA60.@ 2 ;3

113| regionEncontrada, aristaProyeccion, interseccion = False, (proy,proy), A 114| for region in regiones: 115| if not regionEncontrada and proy not in calculados: 116| anterior=(region[len(region)-1][0], region[len(región)-1][1]) 117| for punto in region: 118| punto = (punto[0], punto[1]) 119| if enSegmento(proy, (anterior,punto)) == 1: 120| regionEncontrada, aristaProyeccion = True, (anterior,punto) 121| anterior = punto 122| if regionEncontrada and proy not in calculados: 123| anterior=(region[len(region)-1][0], region[len(region)-1][1]) 124| for punto in region: 125| punto = (punto[0],punto[1]) 126| if lineIntersection((anterior,punto), (proy,A)) == 'Son la misma recta': 127| print((anterior, punto), (proy, A)) 128| return 'No es posible realizar el cálculo' 129| if proy not in [punto, anterior] and A not in [punto, anterior] and dist(proy, interseccion) > dist(proy, lineIntersection((anterior, punto), (proy, A))) and not enSegmento(proy, (anterior, punto)) and segmentoEnPol(region, (proy,lineIntersection((anterior, punto), (proy, A)))) and enSegmento(lineIntersection((anterior, punto), (proy, A)),(anterior, punto)): 130| interseccion= lineIntersection((anterior, punto),(proy,A)) 131| calculados.append(proy) 132| anterior = punto 133| region1, region2, pasadaInt = [], [], False 134| while [aristaProyeccion[1][0],aristaProyeccion[1][1]] in region and region[0] != [aristaProyeccion[1][0], aristaProyeccion[1][1]]: 135| region.append(region[0]) 136| region.remove(region[0]) 137| ant = (region[(len(region)-1)][0], region[(len(region)-1)][1]) 138| region1.append([proy[0],proy[1]]) 139| for punt in region: 140| punt = (punt[0],punt[1]) 141| if enSegmento(interseccion,(ant,punt))== 0 and not pasaInt: region1.append([punt[0],punt[1]]) 142| elif enSegmento(interseccion,(ant,punt)) == 0 and pasaInt: region2.append([punt[0],punt[1]]) 143| elif enSegmento(interseccion,(ant,punt)) == 0: 144| region1.append([interseccion[0],interseccion[1]]) 145| region2.append([interseccion[0],interseccion[1]]) 146| region2.append([punt[0],punt[1]]) 147| pasaInt = True 148| ant = punt 149| region2.append([proy[0],proy[1]])

Page 52: ?.1B.1< 2; .A2:HA60.@ 2 ;3

150| ax.add_artist(ConnectionPatch(xyA = (proy[0],proy[1]), xyB = (interseccion[0], interseccion[1]), coordsA = "data", coordsB = "data", axesA = ax, axesB = ax, color = '#000000')) 151| regiones.insert(0, region1) 152| regiones.insert(0, region2) 153| regiones.remove(region) 154| . In [1]: colorearTodasRegiones([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Out[1]:

Page 53: ?.1B.1< 2; .A2:HA60.@ 2 ;3

155| # SUMIDEROS 156| for region in regiones: 157| if region[0] != [A[0], A[1]]: sumidero = region[0] 158| else: sumidero = region[1] 159| for punto in region: 160| if dist(sumidero, A) < dist(punto, A) and punto != [A[0], A[1]]: sumidero = punto 161| ax.plot(sumidero[0], sumidero[1], '.', color = '#FF0000', ms = 15) 162| ax.legend([Line2D([0], [0], marker = 'o', linestyle = ':', color = '#FF0000', markersize = 7)], ['Sumidero'])

In [1]: sumideros([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Out[1]:

Page 54: ?.1B.1< 2; .A2:HA60.@ 2 ;3

163| # PESOS 164| pesos = [] 165| for region in regiones: 166| pesos.append(abs(sareaPolygon(region))) 167| patches.append(Polygon(region, True, color = colores[ regiones.index(region)%12])) 168| ax.add_collection( PatchCollection(patches, match_original = True)) 169| sumaPesos = 0 170| for i in range(len(pesos)): 171| sumaPesos = sumaPesos + pesos[i] 172| handles = [] 173| d = maxAbscisa(Pol)[0]/40 174| for i in range(len(patches)): 175| handles.append(Polygon([(0,0), (10,0), (0,-10)], color = colores[i%12], label = 'Region %i con peso %.2f'%(i, pesos[i]*100 /sumaPesos))) 176| plt.text(sumideros[i][0] + d, sumideros[i][1], 'S%i'%(i), fontsize = 10, backgroundcolor = '#FFFFFF') 177| plt.legend(handles = handles)

In [1]: pesos([(0,30), (50,35), (55,25), (50,20), (35,30), (30,10), (35,20), (35,10), (30,5), (20,10), (25,15), (0,0), (-5,20), (20,20), (15,25), (0,30)],(50,25))

Page 55: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Out[1]:

1 | def algoritmo(Pol,A): return dibujarVertices(Pol), dibujarAristas(Pol), rellenarAristas(Pol, A), dibujarPerpendiculares(Pol, A), colorearRegiones(Pol, A), colorearTodasRegiones(Pol, A), sumideros(Pol, A), pesos(Pol, A)

1 | def algoritmo(Pol,A): 2 | tiempoAlg = time.time() 3 | a = dibujarVertices(Pol), dibujarAristas(Pol), rellenarAristas(Pol, A), dibujarPerpendiculares(Pol, A), colorearRegiones(Pol, A), colorearTodasRegiones(Pol, A), sumideros(Pol, A), pesos(Pol, A) 4 | print("--- %s segundos ---" % (time.time() - tiempoAlg)) 5 | return a

Page 56: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 57: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: P = poligonoAleatorio(40,1000)7 ...: algoritmo(orientaPositivamente(P),puntoDelPol(P)8)

7 [(35.0518,557.3612),(61.2634,804.161),(122.5194,626.9445),(205.9359,774.7975),(244.8546,586.9942),(474.3921,743.3997),(502.2977,781.3135),(514.5571,871.8481),(535.553,636.5163),(649.1036,756.8398),(658.9725,719.2369),(817.7288,846.3793),(864.6986,617.7473),(887.2021,781.0394),(970.1844,722.359),(990.9597,564.7283),(937.4871,444.2785),(934.7842,94.0779),(917.2405,247.5733),(898.8095,3.3181),(831.4185,556.2786),(768.9319,243.926),(756.8456,463.4774),(712.2239,45.5638),(665.0743,187.0879),(596.0902,309.7179),(569.7714,315.1157),(506.9287,299.2279),(485.1122,220.732),(458.5994,301.6584),(457.856,480.638),(442.7824,312.0101),(327.8922,136.9081),(243.9177,4.797),(162.2541,224.714),(140.9158,152.2883),(139.2709,41.2121),(118.9602,443.6981),(82.8532,260.0023),(60.632,336.5281)] 8 (683.2492, 414.4106)

Page 58: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 59: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 60: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 61: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 62: ?.1B.1< 2; .A2:HA60.@ 2 ;3

146| # SUMIDEROS 147| sumideros = [] 148| for region in regiones: 149| if region[0] != [A[0], A[1]]: sumidero = region[0] 150| else: sumidero = region[1] 151| for punto in region: 152| if dist(sumidero, A) < dist(punto, A) and punto != [A[0], A[1]]: sumidero = punto 153| sumideros.append(sumidero) 154| # PESOS PONDERADOS

Page 63: ?.1B.1< 2; .A2:HA60.@ 2 ;3

155| pesos = [] 156| sumaPesos = 0 157| for i in range(len(regiones)): 158| pesos.append(abs(sareaPolygon(regiones[i]))) 159| sumaPesos = sumaPesos + pesos[i] 160| for i in range(len(pesos)): pesos[i] = pesos[i] * 100 / sumaPesos 161| return sumideros, pesos In [1]: P = poligonoAleatorio(10,100)9 ...: sumPesAux(orientaPositivamente(P),puntoDelPol(P)10) Out[1]: ([[10.7985, 33.5152], [55.9147, 55.9029], [85.2335, 94.2526], [29.2745, 0.2785]], [12.53987558012299, 28.695812507805783, 52.61223093055434, 6.152080981516908])

1 | def sumiderosConMasPeso(Pol): 2 | diccionario, top = {}, 8*len(Pol) 3 | for i in range(top): 4 | print(i, top) 5 | punto = puntoDelPol(Pol) 6 | if sumPesAux(Pol, punto) != 'No es posible realizar el cálculo': 7 | [sumideros,pesos] = sumPesAux(Pol,punto) 8 | for i in range(len(sumideros)): 9 | sumi = str(sumideros[i])

9 [(10.7985, 33.5152), (24.9005, 35.9632), (55.9147, 55.9029), (60.5667, 40.7435), (70.3306, 28.8277), (74.4264, 35.6038), (85.2335, 94.2526), (89.7027, 27.0905), (51.6547, 14.3591), (29.2745, 0.2785)] 10 (33.1436, 16.7417)

Page 64: ?.1B.1< 2; .A2:HA60.@ 2 ;3

10| if sumi not in diccionario: diccionario[sumi] = pesos[i] 11| else: diccionario[sumi] = diccionario[sumi] + pesos[i] 12| return sorted(diccionario.items(), key = lambda x : x[1]) In [1]: P = poligonoAleatorio(10,100)11 ...: sumiderosConMasPeso(P) Out[1]: [('[29.3172, 74.0129]', 432.2975512100845), ('[56.1188, 2.7766]', 1307.0357463770392), ('[94.595, 42.4725]', 1352.7141371492964), ('[10.9988, 95.562]', 1396.6193084137603), ('[86.9467, 95.5351]', 2567.2770927294464), ('[0.8177, 14.6341]', 2944.0561641203735)]

11 [(0.8177, 14.6341), (10.9988, 95.562), (23.0761, 66.6419), (29.3172, 74.0129), (42.7353, 67.6216), (51.6871, 64.492), (86.9467, 95.5351), (94.595, 42.4725), (61.6237, 19.3788), (56.1188, 2.7766)]

Page 65: ?.1B.1< 2; .A2:HA60.@ 2 ;3

FESTIVAL 1[(1.38,7.37), (1.82,7.67), (4.12,9.17), (4.22,8.83), (4.4,8.81), (4.68,8.37), (4.68,8.23), (5,8), (5.34,7.93), (5.54,8.23), (6.64,8.95), (7.36,7.83), (8.96,3.83), (10.96,4.43), (11.3,4.25), (11.92,4.25), (12,4.43), (12.72,4.65), (12.86,4.57), (13.42,4.95), (13.62,5.27), (14.26,5.49), (15.54,1.83), (11.58,0.51), (11.3,1.27), (10.24,0.97), (9.78,2.33), (4.84,2.99), (4.12,5.71), (4.98,6.37), (4.56,6.75), (2.84,5.51)]

In [1]: sumiderosConMasPeso(orientaPositivamente(FESTIVAL_1)) Out[1]: . . . ('[10.24, 0.97]', 1395.317), ('[11.58, 0.51]', 1685.137), ('[5.54, 8.23]', 2103.474), ('[4.12, 9.17]', 2204.421), ('[4.84, 2.99]', 2741.651), ('[14.26, 5.49]', 2985.392), ('[6.64, 8.95]', 5474.396), ('[4.12, 5.71]', 16478.792), ('[1.38, 7.37]', 18655.143), ('[15.54, 1.83]', 44486.604)]

Page 66: ?.1B.1< 2; .A2:HA60.@ 2 ;3

FESTIVAL 2 [(1.02,11.24), (0.66,10.99), (0.64,9.79), (3.34,9.75), (3.68,9.41), (3.74,7.87), (4.04,7.57), (6.1,7.53), (6.12,5.69), (5.1,5.67), (4.86,6.11), (4.86,4.97), (5.6,5.01), (8.22,5.01), (10,4.97), (11.02,7.24), (11.02,8.24), (12.46,9.75), (12.26,11.33), (13.72,12.33), (16.04,12.69), (16.08,14.07), (14.5,14.13), (14.44,13.69), (13.42,13.67), (13.18,13.33), (12.5,13.35), (12.24,13.69), (10.68,13.69), (10.72,13.39), (10.4,13.01), (10.22,12.71), (9.54,12.73), (9.2,13.31), (9.2,14.09), (7.78,14.09), (7.76,13.75), (7.5,13.51), (7.2,13.15), (6.54,13.15), (6.24,13.49), (4.92,13.49), (4.58,13.29), (5.16,12.29), (6.98,11.53), (5.22,12.21), (3.72,14.59), (4.56,14.65),(4.52,15.37), (3.1,15.39), (2.78,15.19), (3.06,13.89), (4.06,12.67), (4.02,12.24), (1,14.03), (0.68,13.67), (1.3,12.81), (3.06,11.77), (4.04,11.77), (4.06,11.11), (2.26,11.05), (2.02,11.24)]

In [1]: sumiderosConMasPeso(orientaPositivamente(FESTIVAL_2)) Out[1]: . . . ('[12.24, 13.69]', 307.192), ('[12.46, 9.75]', 342.046), ('[0.68, 13.67]', 342.185), ('[2.78, 15.19]', 355.048), ('[4.58, 13.29]', 382.369), ('[0.64, 9.79]', 447.423), ('[0.66, 10.99]', 473.192), ('[3.74, 7.87]', 473.737), ('[10, 4.97]', 833.535), ('[4.86, 4.97]', 1014.580), ('[16.08, 14.07]', 1123.947)]

Page 67: ?.1B.1< 2; .A2:HA60.@ 2 ;3

FESTIVAL 3 [(12.38,6.2), (12.63,6.12), (13.07,6.16),(13.28,6.02), (14.21,5.89), (14.45,5.69), (14.51,5.46), (14.51,4.2), (14.67,4.18),(14.62,4.37), (14.65,5.55), (15.82,5.57), (15.79,5.01), (16.48,4.99), (17.15,4.98), (17.14,4.16), (17.78,4.16), (17.8,2.79), (17.11,2.79), (17.12,2.38), (16.92,2.38), (16.91,1.04), (18.22,1.0), (18.23,0.39), (16.09,0.41), (16.08,1.51), (14.6,1.52), (14.62,1.84), (14.28,1.83), (14.27,2.64), (14.73,2.64), (14.66,2.82), (13.98,2.66), (13.96,3.46), (13.45,3.71), (13.33,4.03), (13.31,4.36), (13.3,5.43), (12.72,5.43), (12.67,5.75)]

In [1]: sumiderosConMasPeso(orientaPositivamente(FESTIVAL_3)) Out[1]: . . . ('[16.09, 0.41]', 1846.406), ('[15.82, 5.57]', 2137.547), ('[14.28, 1.83]', 2177.032), ('[13.98, 2.66]', 2610.138), ('[14.6, 1.52]', 3466.698), ('[17.78, 4.16]', 4566.936), ('[17.15, 4.98]', 5719.699), ('[17.8, 2.79]', 6637.593), ('[14.65, 5.55]', 9662.228), ('[12.38, 6.2]', 17237.710), ('[18.23, 0.39]', 17582.739)]

Page 68: ?.1B.1< 2; .A2:HA60.@ 2 ;3

FESTIVAL 4 [(3.4,11.21), (8.94,9.59), (9.84,9.97), (10.3,10.39), (14.06,9.81), (15.02,8.73), (15.16,8.41), (15.32,8.33), (15.14,7.71), (14.38,7.25), (14.4,6.91), (13.98,6.87), (14.28,6.25), (15.14,5.09), (15.82,4.57), (15.46,4.01), (13.28,2.81), (12.46,2.47), (8.38,3.43), (8.44,3.81), (8.28,3.87), (8.44,4.43), (8.18,5.75), (5.86,5.51), (5.78,5.97), (4.64,5.95), (3.18,6.83), (2.66,7.61)]

In [1]: sumiderosConMasPeso(orientaPositivamente(FESTIVAL_4)) Out[1]: [('[15.16, 8.41]', 0.0), ('[13.28, 2.81]', 114.087), ('[4.64, 5.95]', 296.727), ('[3.18, 6.83]', 326.168), ('[15.14, 7.71]', 481.238), ('[15.02, 8.73]', 881.821), ('[14.4, 6.91]', 1189.501), ('[8.28, 3.87]', 2074.913), ('[5.86, 5.51]', 2226.611), ('[12.46, 2.47]', 3433.485), ('[14.06, 9.81]', 3582.103), ('[15.46, 4.01]', 4038.347), ('[10.3, 10.39]', 4261.846), ('[8.38, 3.43]', 4929.795), ('[2.66, 7.61]', 11821.574), ('[15.32, 8.33]', 14293.007), ('[15.82, 4.57]', 22104.111), ('[3.4, 11.21]', 23944.666)]

Page 69: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 70: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 71: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 72: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 73: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 74: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 75: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 76: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 77: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 78: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 79: ?.1B.1< 2; .A2:HA60.@ 2 ;3

In [1]: P = orientaPositivamente(poligonoAleatorio(10,30)) ...: dibujarAristas(P), P Out[1]: (None, [(1.0489, 2.7481), (2.0137, 21.4315), (3.0444, 28.9138), (8.7533, 13.7644), (11.1853, 22.5188), (13.0792, 13.7907), (26.2547, 19.699), (27.2322, 3.0924), (10.9594, 2.4939), (10.5524, 0.386)])

Page 80: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 81: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 82: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 83: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 84: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 85: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 86: ?.1B.1< 2; .A2:HA60.@ 2 ;3

P Punto a investigar A Actuador Cóncavos Lista con todos los vértices cóncavos Proyecciones Array con la proyección del punto sobre cada arista en la dirección del vector formado por el actuador y el punto.

angulo(punto) Calcula el vértice del polígono (a), teniendo en cuenta los otros dos vértices que van unidos a él y siguiendo el orden que marca el polígono (b y c). De los dos ángulos que se obtienen (bac y cab), se escoge el interior. ang(A,B,C) Obtiene el ángulo ABC. proyección(P, A, arista) Proyección del punto sobre la arista en la dirección del vector que une A y P. aristas(Pol) Aristas del polígono

# Se debe calcular la intersección de la recta que pasa por P y A con la arista más cercana a P. La intersección debe estar fuera del segmento AP y se llamará I. # P se desplaza hasta I y se dibuja el segmento PI. # Una vez P alcanza I, puede desplazarse en dos direcciones. Se debe calcular en qué dirección P maximiza más su distancia con A y desplazar P por las aristas del polígono hasta alcanzar un sumidero. Todos los segmentos de este recorrido se van dibujando hasta que se alcanza el sumidero y finaliza el recorrido.

Page 87: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 88: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 89: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 90: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 91: ?.1B.1< 2; .A2:HA60.@ 2 ;3
Page 92: ?.1B.1< 2; .A2:HA60.@ 2 ;3

#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: mariaaparicio """ # LIBRERÍAS ___________________________________________________________________ import math as mth import numpy as np import matplotlib.pyplot as plt import time plt.rcParams.update({'font.size': 16}) from matplotlib.lines import Line2D from matplotlib.patches import Polygon, ConnectionPatch from matplotlib.collections import PatchCollection start_time = time.time() # FUNCIONES AUXILIARES ________________________________________________________ # dist(A,B) --> Devuelve la distancia entre dos puntos. def dist(A,B): return mth.sqrt(dist2(A,B)) # dist2(A,B) --> Calcula el cuadrado de la distancia entre dos puntos. def dist2(A,B): return (B[0] - A[0])**2 + (B[1] - A[1])**2 # aleatorio(n,rango) --> Devuelve n números aleatorios del 0 al rango def aleatorio(n,rango): return np.random.rand(n) * rango # angulo(A,B,C) --> Devuelve el ángulo ABC def angulo(A,B,C): a, b, c = np.array([A[0],A[1]]), np.array([B[0],B[1]]), np.array([C[0],C[1]]) angulo = round(np.degrees(np.arccos(np.dot(a-b, c-b) / (np.linalg.norm(a-b) * np.linalg.norm(c-b)))),3)

Page 93: ?.1B.1< 2; .A2:HA60.@ 2 ;3

if sarea(A,B,C) <= 0: return angulo else: return 360 - angulo # maxAbscisa(P), minAbscisa(P), maxOrdenada(P), minOrdenada(P) --> Devuelven la máxima y mínima abscisa y la máxima y mínima ordenada de un grupo de puntos def maxAbscisa(P): maxA = P[0] for x in P: if x[0] > maxA[0] or (x[0] == maxA[0] and x[1] > maxA[1]): maxA = x return maxA def minAbscisa(P): minA = P[0] for x in P: if x[0] < minA[0] or (x[0] == minA[0] and x[1] < minA[1]): minA = x return minA def maxOrdenada(P): maxO = P[0] for x in P: if x[1] > maxO[1] or (x[1] == maxO[1] and x[0] > maxO[0]): maxO = x return maxO def minOrdenada(P): minO = P[0] for x in P: if x[1] < minO[1] or (x[1] == minO[1] and x[0] < minO[0]): minO = x return minO # sarea(A,B,C) --> Calcula el área signada de tres puntos. Positiva --> sentido antihorario. Negativa --> sentido horario. 0 --> puntos alineados. def sarea(A,B,C): sarea = (1/2)*(A[0]*(B[1]-C[1]) + B[0]*(C[1]-A[1]) + C[0]*(A[1]-B[1])) if -0.0001 < sarea < 0.0001: return 0 else: return sarea # orient(A,B,C) --> Calcula la orientación de un triángulo usando el área signada. Positiva --> Devuelve 1. Negativa --> Devuelve -1. Puntos alineados --> Devuelve 0 def orient(A,B,C): return np.sign(sarea(A,B,C)) # poligoniza(P) --> Genera una lista de puntos ordenada, que forma un polígono. def poligoniza(P): LPositivos, LNegativos, Max, Min = [], [], max(P), min(P) for i in range(len(P)): if sarea(Max,P[i],Min) >= 0: LPositivos.append(P[i]) else: LNegativos.append(P[i]) LPositivos = sorted(LPositivos) LPositivos.reverse() return sorted(LNegativos) + LPositivos # sareaPolygon(p) --> Calcula el área signada de un polígono def sareaPolygon(p): a = 0 for i in range(len(p)): a += sarea(p[0], p[i-1], p[i]) return a # orientaPositivamente(Pol) --> Orienta los puntos de un polígono positivamente def orientaPositivamente(Pol): if sareaPolygon(Pol) > 0: Pol.reverse()

Page 94: ?.1B.1< 2; .A2:HA60.@ 2 ;3

return Pol # poligonoAleatorio(p, rango) --> Genera un polígono aleatorio de p puntos del 0 al rango def poligonoAleatorio(p,rango): Pol = [] for i in range(p): Pol.append((round(aleatorio(1,rango)[0],4),round(aleatorio(1,rango)[0],4))) return orientaPositivamente(poligoniza(Pol)) # enSegmento(P,s) --> Calcula si un punto está en un segmento. El área signada de dos puntos del segmento y el punto en cuestión debe ser 0. El punto debe estar entre los dos extremos del segmento. Devuelve 1 si está contenido y 0 si no lo está. def enSegmento(P,s): if (sarea(P, s[0], s[1]) == 0) and max(s[0][0], s[1][0]) >= P[0] and max(s[0][1], s[1][1]) >= P[1] and min(s[0][0], s[1][0]) <= P[0] and min(s[0][1], s[1][1]) <= P[1]: return 1 else: return 0 # proyeccionPuntoRecta(r,P) --> Devuelve la proyección de un punto, P, en una recta, r. def proyeccionPuntoRecta(r,P): v = [r[1][0] - r[0][0], r[1][1] - r[0][1]] v /= np.linalg.norm(v, 2) nuevoPunto = r[0] + v * np.dot([P[0] - r[0][0], P[1] - r[0][1]], v) return (nuevoPunto[0], nuevoPunto[1]) # Devuelve una lista de aristas del polígono def aristas(Pol): aristas, anterior = [], Pol[len(Pol)-1] for punto in Pol: aristas.insert(len(aristas),(anterior,punto)) anterior = punto return aristas # segmentIntersection(A,B) --> Devuelve 1 si intersecan. 0 si no cortan. Si cortan en el extremo, también nos interesa que devuelva cero por lo que no tenemos que contemplar el caso degenerado. def segmentIntersectionTest(a,b): if (enSegmento(a[0],b) and enSegmento(a[1],b)) or (enSegmento(b[0],a) and enSegmento(b[1],a)): return (True, 1) # Contenido dentro del otro elif b[0] == a[0] or b[0] == a[1] or b[1] == a[0] or b[1] == a[1]: return (True, 2) # Comparten vertex elif enSegmento(b[0],a) or enSegmento(b[1],a) or enSegmento(a[0],b) or enSegmento(a[1],b): return (False, 3) # Forman una T elif orient(a[0],a[1],b[0]) != orient(a[0],a[1],b[1]) and orient(b[0],b[1],a[0]) != orient(b[0],b[1],a[1]): return (True, 4) # Se cruzan else: return (False, 5) # No se cruzan # lineIntersection(a, b) --> Calcula el punto de intersección de dos rectas # Sacado de https://stackoverflow.com/questions/20677795/how-do-i-compute-the-intersection-point-of-two-lines-in-python def lineIntersection(a, b): def det(a, b): return a[0] * b[1] - a[1] * b[0] xD, yD = (a[0][0] - a[1][0], b[0][0] - b[1][0]), (a[0][1] - a[1][1], b[0][1] - b[1][1]) div = det(xD, yD) if div == 0:

Page 95: ?.1B.1< 2; .A2:HA60.@ 2 ;3

return 'Son la misma recta' d = (det(*a), det(*b)) x = det(d, xD) / det(xD, yD) y = det(d, yD) / det(xD, yD) return (x, y) # puntoEnPol(Pol,Punto) --> Devuelve True si un punto se encuentra dentro de un polígono y False si está fuera def puntoEnPol(P,p): # Si el punto es un vértice, ya está en P if p in P: return True # Se busca el vértice con el mayor valor de y maximo = (P[0],P[0][1]) for punto in P: if punto[1] > maximo[1]: maximo = (punto, max(maximo[1], punto[1])) # Se une el punto con un punto de fuera del polígono contador, vertice = 0, (maximo[0][0],maximo[0][1]+2) segmento = [p,vertice] # Si el punto pertenece a una arista está en el polígono for arista in aristas(P): if enSegmento(p,arista): return True # Si los segmentos se cruzan, pero no están contenidos uno dentro del otro... if (segmentIntersectionTest(arista,segmento)[0]) and segmentIntersectionTest(arista,segmento)[1] != 1: contador += 1 # Número de cruces par, no se cuenta if contador % 2 == 0: return False # Número de cruces impar, se cuenta else: return True # puntoDelPol(Pol) --> Devuelve un punto perteneciente al polígono def puntoDelPol(Pol): p = (0,0) while not puntoEnPol(Pol,p) or p == (0,0): p = (round(aleatorio(1,maxAbscisa(Pol))[0],4),round(aleatorio(1,maxAbscisa(Pol))[0],4)) print(p) return p # segmentoEnPol(Pol,segmento) --> Devuelve True si un segmento está contenido en un polígono y False si parte de él está fuera. def segmentoEnPol(Pol, segmento): for arista in aristas(Pol): if segmentIntersectionTest(arista,segmento)[0] or (segmentIntersectionTest(arista,segmento)[1] == 3 and not puntoEnPol(Pol,(((segmento[0][0]+segmento[1][0])/2),((segmento[0][1]+segmento[1][1])/2)))): return False return puntoEnPol(Pol,segmento[0]) # PASOS DEL ALGORITMO _________________________________________________________ # Dibuja los vértices del polígono def dibujarVertices(Pol): fig, ax = plt.subplots()

Page 96: ?.1B.1< 2; .A2:HA60.@ 2 ;3

# Se añaden los puntos for punto in Pol: ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) plt.axis('on') plt.axis('equal') return plt.show() # Dibuja las aristas y los vértices del polígono def dibujarAristas(Pol): fig, ax = plt.subplots() anterior = Pol[len(Pol)-1] for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color='#000000', ms = 10) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) anterior = punto plt.axis('on') plt.axis('equal') return plt.show() # Rellena el polígono def rellenarAristas(Pol,A): patches, pol, anterior = [], [], Pol[len(Pol)-1] fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color='#000000', ms = 10) pol.insert(len(pol),[punto[0],punto[1]]) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) anterior = punto # Se representa patches.append(Polygon(pol, True, color = (0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4))) ax.add_collection(PatchCollection(patches, match_original = True)) ax.legend([Line2D([0],[0], marker = 'o', linestyle=':', color = '#47ECFF', markersize = 7)], ['Actuador']) plt.axis('on') plt.axis('equal') return plt.show() # Dibuja el actuador y las perpendiculares del polígono def dibujarPerpendiculares(Pol,A): patches, pol, anterior = [], [], Pol[len(Pol)-1]

Page 97: ?.1B.1< 2; .A2:HA60.@ 2 ;3

fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) pol.insert(len(pol),[punto[0],punto[1]]) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Vértices cóncavos index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (punto[0],punto[1]), linestyle='-.', coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#6666FF')) # Proyecciones con y sin intersección proy = proyeccionPuntoRecta((anterior, punto),A) if enSegmento(proy,(anterior,punto)): # Proyecciones con intersección if not segmentoEnPol(Pol, (proy, A)): ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), linestyle='-.', coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#CC9900')) # Proyecciones sin intersección else: ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) anterior = punto # Se representa patches.append(Polygon(pol, True, color = (0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4))) ax.add_collection(PatchCollection(patches, match_original = True)) ax.legend([Line2D([0],[0], linestyle='-.',color = '#CC9900', lw = 1.5), Line2D([0],[0], linestyle='-.',color = '#6666FF', lw = 1.5), Line2D([0],[0], color = '#000000', lw = 2)], ['Proyecciones con intersección', 'Vértices cóncavos', 'Proyecciones sin intersección']) plt.axis('on') plt.axis('equal') return plt.show() # Colorea las regiones según un actuador dado def colorearRegiones(Pol,A): patches, proyecciones, anterior = [], [], Pol[len(Pol)-1] fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15)

Page 98: ?.1B.1< 2; .A2:HA60.@ 2 ;3

for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se depuran los vértices cóncavos y se dibujan sus aristas index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: anteriorAux, inters = Pol[len(Pol)-1], 0 for puntoAux in Pol: if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters+1 anteriorAux = puntoAux # Si el vértice está dentro del polígono... if inters%2 == 0 or inters == 1: ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (punto[0],punto[1]), linestyle='-.', coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se dibujan las aristas de proyecciones con intersección y se crea la lista de proyecciones proy = proyeccionPuntoRecta((anterior, punto),A) or1, or2 = orient(ant, punto, A), orient(A, punto, sig) # Se añade la proyección con intersección - Segmento, proyección en segmento, proyección if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): proyecciones.append(((anterior,punto),False,proy)) ant, inters = Pol[len(Pol)-1], 0 for pun in Pol: if segmentIntersectionTest((ant, pun), (proy, A))[0]: inters = inters+1 ant = pun if inters%2 == 0: ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), linestyle='-.', coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se añade la proyección sin intersección - Segmento, proyección en segmento, proyección elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): proyecciones.append(((anterior,punto),True,proy)) ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se añaden los puntos sin proyección - Segmento, proyección en segmento, proyección else: proyecciones.append(((anterior,punto),False,proy)) anterior = punto # REGIONES regionActual, regiones = [], [] # Se pone primero un caso con proyección

Page 99: ?.1B.1< 2; .A2:HA60.@ 2 ;3

while not proyecciones[0][1]: proyecciones.append(proyecciones[0]) proyecciones.remove(proyecciones[0]) # Se crean las regiones for x in proyecciones: # Último caso if x == proyecciones[len(proyecciones)-1]: if x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) elif not x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) # True elif x[1]: if x != proyecciones[0]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] # False elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]]) # Se representa colores = [(0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4), (0.12156862745098039, 0.47058823529411764, 0.7058823529411765, 0.4), (0.6980392156862745, 0.8745098039215686, 0.5411764705882353, 0.4), (0.2, 0.6274509803921569, 0.17254901960784313, 0.4), (0.984313725490196, 0.6039215686274509, 0.6, 0.4), (0.8901960784313725, 0.10196078431372549, 0.10980392156862745, 0.4), (0.9921568627450981, 0.7490196078431373, 0.43529411764705883, 0.4), (1.0, 0.4980392156862745, 0.0, 0.4), (0.792156862745098, 0.6980392156862745, 0.8392156862745098, 0.4), (0.41568627450980394, 0.23921568627450981, 0.6039215686274509, 0.4), (1.0, 1.0, 0.6, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4)] for region in regiones: patches.append(Polygon(region, True, color = colores[regiones.index(region)%12])) ax.add_collection(PatchCollection(patches, match_original = True)) plt.axis('on') plt.axis('equal')

Page 100: ?.1B.1< 2; .A2:HA60.@ 2 ;3

return plt.show() """SIMPLIFICADA - cambiar""" # Colorea las regiones según un actuador dado def colorearTodasRegiones(Pol,A): colorearTodasRegionesInicio = time.time() patches, proyecciones, proyeccionesConInters, concavos, anterior = [], [], [], [], Pol[len(Pol)-1] fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se depuran los vértices cóncavos y se dibujan sus aristas index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: anteriorAux, inters = Pol[len(Pol)-1], 0 for puntoAux in Pol: if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters + 1 anteriorAux = puntoAux # Si el vértice está dentro del polígono... if inters%2 == 0 or inters == 1: concavos.insert(len(concavos), punto) # Se dibujan las aristas de proyecciones con intersección y se crea la lista de proyecciones proy = proyeccionPuntoRecta((anterior, punto),A) or1, or2 = orient(ant, punto, A), orient(A, punto, sig) # Se añade la proyección con intersección - Segmento, proyección en segmento, proyección if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): proyecciones.append(((anterior,punto),False,proy)) ant, inters = Pol[len(Pol)-1], 0 for pun in Pol: if segmentIntersectionTest((ant, pun), (proy, A))[0]: inters = inters+1 ant = pun if inters%2 == 0: proyeccionesConInters.insert(len(proyeccionesConInters),proy) # Se añade la proyección sin intersección - Segmento, proyección en segmento, proyección elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): proyecciones.append(((anterior,punto),True,proy)) ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000'))

Page 101: ?.1B.1< 2; .A2:HA60.@ 2 ;3

# Se añaden los puntos sin proyección - Segmento, proyección en segmento, proyección else: proyecciones.append(((anterior,punto),False,proy)) anterior = punto # REGIONES regionActual, regiones = [], [] # Se pone primero un caso con proyección while not proyecciones[0][1]: proyecciones.append(proyecciones[0]) proyecciones.remove(proyecciones[0]) # Se crean las regiones for x in proyecciones: # Último caso if x == proyecciones[len(proyecciones)-1]: if x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) elif not x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) # True elif x[1]: if x != proyecciones[0]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] # False elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]]) # REGIONES DE VÉRTICES CÓNCAVOS Y PROYECCIONES QUE INTERSECAN # Vértices cóncavos calculados = [] for vertice in concavos: for region in regiones: if [vertice[0],vertice[1]] in region and vertice not in calculados:

Page 102: ?.1B.1< 2; .A2:HA60.@ 2 ;3

calculados.append(vertice) while region[0] != [vertice[0],vertice[1]]: region.append(region[0]) region.remove(region[0]) interseccion, anterior = A, (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) lineI = lineIntersection((anterior,punto), (vertice,A)) if orient(vertice,punto,A) != orient(vertice,anterior,A) and vertice != anterior and vertice != punto and A != anterior and A != punto: if dist(vertice,interseccion) > dist(vertice,lineI) and dist(A,lineI) < dist(A,vertice): interseccion = lineI anterior = (punto[0],punto[1]) region1, region2, pasado, pasad = [],[], False, False ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) for punt in region: if interseccion == A: if (punt[0],punt[1]) == A: pasad = True region1.append(punt) region2.append(punt) elif not pasad: region1.append(punt) elif pasad: region2.append(punt) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and not pasado: region1.append(punt) ant = (punt[0],punt[1]) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 1 and not pasado: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append(punt) ant, pasado = (punt[0],punt[1]), True elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and pasado: region2.append(punt) ant = (punt[0],punt[1]) region2.append([vertice[0],vertice[1]]) ax.add_artist(ConnectionPatch(xyA = (vertice[0],vertice[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # Proyecciones que intersecan calculados = [] for proy in proyeccionesConInters: regionEncontrada, aristaProyeccion, interseccion = False, (proy,proy), A for region in regiones: if not regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if enSegmento(proy,(anterior,punto)) == 1: regionEncontrada, aristaProyeccion = True, (anterior,punto)

Page 103: ?.1B.1< 2; .A2:HA60.@ 2 ;3

anterior = punto if regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if lineIntersection((anterior,punto), (proy,A)) == 'Son la misma recta': print((anterior,punto), (proy,A)) return 'No es posible realizar el cálculo' if proy not in [punto, anterior] and A not in [punto, anterior] and dist(proy,interseccion) > dist(proy,lineIntersection((anterior,punto), (proy,A))) and not enSegmento(proy,(anterior,punto)) and segmentoEnPol(region,(proy,lineIntersection((anterior,punto), (proy,A)))) and enSegmento(lineIntersection((anterior,punto), (proy,A)),(anterior,punto)): interseccion = lineIntersection((anterior,punto), (proy,A)) calculados.append(proy) anterior = punto region1, region2, pasadaInterseccion = [], [], False while [aristaProyeccion[1][0],aristaProyeccion[1][1]] in region and region[0] != [aristaProyeccion[1][0],aristaProyeccion[1][1]]: region.append(region[0]) region.remove(region[0]) ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) region1.append([proy[0],proy[1]]) for punt in region: punt = (punt[0],punt[1]) if enSegmento(interseccion,(ant,punt)) == 0 and not pasadaInterseccion: region1.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 0 and pasadaInterseccion: region2.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 1: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append([punt[0],punt[1]]) pasadaInterseccion = True ant = punt region2.append([proy[0],proy[1]]) ax.add_artist(ConnectionPatch(xyA = (proy[0],proy[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # Dibuja regiones colores = [(0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4), (0.12156862745098039, 0.47058823529411764, 0.7058823529411765, 0.4), (0.6980392156862745, 0.8745098039215686, 0.5411764705882353, 0.4), (0.2, 0.6274509803921569, 0.17254901960784313, 0.4), (0.984313725490196, 0.6039215686274509, 0.6, 0.4), (0.8901960784313725, 0.10196078431372549, 0.10980392156862745, 0.4), (0.9921568627450981, 0.7490196078431373, 0.43529411764705883, 0.4), (1.0, 0.4980392156862745, 0.0, 0.4), (0.792156862745098, 0.6980392156862745, 0.8392156862745098, 0.4), (0.41568627450980394, 0.23921568627450981, 0.6039215686274509, 0.4), (1.0, 1.0, 0.6, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4)] # Dibuja regiones for region in regiones: patches.append(Polygon(region, True, color = colores[regiones.index(region)%12]))

Page 104: ?.1B.1< 2; .A2:HA60.@ 2 ;3

ax.add_collection(PatchCollection(patches, match_original = True)) plt.axis('on') plt.axis('equal') print("--- %s segundos colorearTodasRegiones ---" % (time.time() - colorearTodasRegionesInicio)) return plt.show() """SIMPLIFICADA - cambiar""" # Obtiene los sumideros de un polígono def sumideros(Pol,A): sumiderosInicio = time.time() patches, proyecciones, proyeccionesConInters, concavos, anterior = [], [], [], [], Pol[len(Pol)-1] fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se depuran los vértices cóncavos y se dibujan sus aristas index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: anteriorAux, inters = Pol[len(Pol)-1], 0 for puntoAux in Pol: if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters + 1 anteriorAux = puntoAux # Si el vértice está dentro del polígono... if inters%2 == 0 or inters == 1: concavos.insert(len(concavos), punto) # Se dibujan las aristas de proyecciones con intersección y se crea la lista de proyecciones proy = proyeccionPuntoRecta((anterior, punto),A) or1, or2 = orient(ant, punto, A), orient(A, punto, sig) # Se añade la proyección con intersección - Segmento, proyección en segmento, proyección if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): proyecciones.append(((anterior,punto),False,proy)) ant, inters = Pol[len(Pol)-1], 0 for pun in Pol: if segmentIntersectionTest((ant, pun), (proy, A))[0]: inters = inters+1 ant = pun if inters%2 == 0: proyeccionesConInters.insert(len(proyeccionesConInters),proy)

Page 105: ?.1B.1< 2; .A2:HA60.@ 2 ;3

# Se añade la proyección sin intersección - Segmento, proyección en segmento, proyección elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): proyecciones.append(((anterior,punto),True,proy)) ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se añaden los puntos sin proyección - Segmento, proyección en segmento, proyección else: proyecciones.append(((anterior,punto),False,proy)) anterior = punto # REGIONES regionActual, regiones = [], [] # Se pone primero un caso con proyección while not proyecciones[0][1]: proyecciones.append(proyecciones[0]) proyecciones.remove(proyecciones[0]) # Se crean las regiones for x in proyecciones: # Último caso if x == proyecciones[len(proyecciones)-1]: if x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) elif not x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) # True elif x[1]: if x != proyecciones[0]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] # False elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]])

Page 106: ?.1B.1< 2; .A2:HA60.@ 2 ;3

# REGIONES DE VÉRTICES CÓNCAVOS Y PROYECCIONES QUE INTERSECAN # Vértices cóncavos calculados = [] for vertice in concavos: for region in regiones: if [vertice[0],vertice[1]] in region and vertice not in calculados: calculados.append(vertice) while region[0] != [vertice[0],vertice[1]]: region.append(region[0]) region.remove(region[0]) interseccion, anterior = A, (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) lineI = lineIntersection((anterior,punto), (vertice,A)) if orient(vertice,punto,A) != orient(vertice,anterior,A) and vertice != anterior and vertice != punto and A != anterior and A != punto: if dist(vertice,interseccion) > dist(vertice,lineI) and dist(A,lineI) < dist(A,vertice): interseccion = lineI anterior = (punto[0],punto[1]) region1, region2, pasado, pasad = [],[], False, False ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) for punt in region: if interseccion == A: if (punt[0],punt[1]) == A: pasad = True region1.append(punt) region2.append(punt) elif not pasad: region1.append(punt) elif pasad: region2.append(punt) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and not pasado: region1.append(punt) ant = (punt[0],punt[1]) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 1 and not pasado: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append(punt) ant, pasado = (punt[0],punt[1]), True elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and pasado: region2.append(punt) ant = (punt[0],punt[1]) region2.append([vertice[0],vertice[1]]) ax.add_artist(ConnectionPatch(xyA = (vertice[0],vertice[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # Proyecciones que intersecan calculados = [] for proy in proyeccionesConInters: regionEncontrada, aristaProyeccion, interseccion = False, (proy,proy), A

Page 107: ?.1B.1< 2; .A2:HA60.@ 2 ;3

for region in regiones: if not regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if enSegmento(proy,(anterior,punto)) == 1: regionEncontrada, aristaProyeccion = True, (anterior,punto) anterior = punto if regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if lineIntersection((anterior,punto), (proy,A)) == 'Son la misma recta': print((anterior,punto), (proy,A)) return 'No es posible realizar el cálculo' if proy not in [punto, anterior] and A not in [punto, anterior] and dist(proy,interseccion) > dist(proy,lineIntersection((anterior,punto), (proy,A))) and not enSegmento(proy,(anterior,punto)) and segmentoEnPol(region,(proy,lineIntersection((anterior,punto), (proy,A)))) and enSegmento(lineIntersection((anterior,punto), (proy,A)),(anterior,punto)): interseccion = lineIntersection((anterior,punto), (proy,A)) calculados.append(proy) anterior = punto region1, region2, pasadaInterseccion = [], [], False while [aristaProyeccion[1][0],aristaProyeccion[1][1]] in region and region[0] != [aristaProyeccion[1][0],aristaProyeccion[1][1]]: region.append(region[0]) region.remove(region[0]) ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) region1.append([proy[0],proy[1]]) for punt in region: punt = (punt[0],punt[1]) if enSegmento(interseccion,(ant,punt)) == 0 and not pasadaInterseccion: region1.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 0 and pasadaInterseccion: region2.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 1: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append([punt[0],punt[1]]) pasadaInterseccion = True ant = punt region2.append([proy[0],proy[1]]) ax.add_artist(ConnectionPatch(xyA = (proy[0],proy[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # SUMIDEROS for region in regiones: if region[0] != [A[0],A[1]]: sumidero = region[0] else: sumidero = region[1] for punto in region: if dist(sumidero,A) < dist(punto,A) and punto != [A[0],A[1]]: sumidero = punto

Page 108: ?.1B.1< 2; .A2:HA60.@ 2 ;3

ax.plot(sumidero[0], sumidero[1], '.', color='#FF0000', ms = 15) # Dibuja regiones colores = [(0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4), (0.12156862745098039, 0.47058823529411764, 0.7058823529411765, 0.4), (0.6980392156862745, 0.8745098039215686, 0.5411764705882353, 0.4), (0.2, 0.6274509803921569, 0.17254901960784313, 0.4), (0.984313725490196, 0.6039215686274509, 0.6, 0.4), (0.8901960784313725, 0.10196078431372549, 0.10980392156862745, 0.4), (0.9921568627450981, 0.7490196078431373, 0.43529411764705883, 0.4), (1.0, 0.4980392156862745, 0.0, 0.4), (0.792156862745098, 0.6980392156862745, 0.8392156862745098, 0.4), (0.41568627450980394, 0.23921568627450981, 0.6039215686274509, 0.4), (1.0, 1.0, 0.6, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4)] # Dibuja regiones for region in regiones: patches.append(Polygon(region, True, color = colores[regiones.index(region)%12])) ax.add_collection(PatchCollection(patches, match_original = True)) ax.legend([Line2D([0],[0], marker = 'o', linestyle=':', color = '#FF0000', markersize = 7)], ['Sumidero']) plt.axis('on') plt.axis('equal') print("--- %s segundos sumideros ---" % (time.time() - sumiderosInicio)) return plt.show() def pesos(Pol,A): pesosInicio = time.time() patches, proyecciones, proyeccionesConInters, concavos, anterior = [], [], [], [], Pol[len(Pol)-1] fig, ax = plt.subplots() # Se añade el actuador ax.plot(A[0], A[1], '.', color = '#47ECFF', ms = 15) for punto in Pol: # Se añaden los puntos ax.plot(punto[0], punto[1], '.', color = '#000000', ms = 10) # Se añaden las aristas ax.add_artist(ConnectionPatch(xyA = (anterior[0],anterior[1]), xyB = (punto[0],punto[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se depuran los vértices cóncavos y se dibujan sus aristas index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: anteriorAux, inters = Pol[len(Pol)-1], 0 for puntoAux in Pol: if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters + 1 anteriorAux = puntoAux # Si el vértice está dentro del polígono... if inters%2 == 0 or inters == 1: concavos.insert(len(concavos), punto) # Se dibujan las aristas de proyecciones con intersección y se crea la lista de proyecciones proy = proyeccionPuntoRecta((anterior, punto),A)

Page 109: ?.1B.1< 2; .A2:HA60.@ 2 ;3

or1, or2 = orient(ant, punto, A), orient(A, punto, sig) # Se añade la proyección con intersección - Segmento, proyección en segmento, proyección if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): proyecciones.append(((anterior,punto),False,proy)) ant, inters = Pol[len(Pol)-1], 0 for pun in Pol: if segmentIntersectionTest((ant, pun), (proy, A))[0]: inters = inters+1 ant = pun if inters%2 == 0: proyeccionesConInters.insert(len(proyeccionesConInters),proy) # Se añade la proyección sin intersección - Segmento, proyección en segmento, proyección elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): proyecciones.append(((anterior,punto),True,proy)) ax.add_artist(ConnectionPatch(xyA = (A[0],A[1]), xyB = (proy[0],proy[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) # Se añaden los puntos sin proyección - Segmento, proyección en segmento, proyección else: proyecciones.append(((anterior,punto),False,proy)) anterior = punto # REGIONES regionActual, regiones = [], [] # Se pone primero un caso con proyección while not proyecciones[0][1]: proyecciones.append(proyecciones[0]) proyecciones.remove(proyecciones[0]) # Se crean las regiones for x in proyecciones: # Último caso if x == proyecciones[len(proyecciones)-1]: if x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) elif not x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]])

Page 110: ?.1B.1< 2; .A2:HA60.@ 2 ;3

y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) # True elif x[1]: if x != proyecciones[0]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] # False elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]]) # REGIONES DE VÉRTICES CÓNCAVOS Y PROYECCIONES QUE INTERSECAN # Vértices cóncavos calculados = [] for vertice in concavos: for region in regiones: if [vertice[0],vertice[1]] in region and vertice not in calculados: calculados.append(vertice) while region[0] != [vertice[0],vertice[1]]: region.append(region[0]) region.remove(region[0]) interseccion, anterior = A, (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) lineI = lineIntersection((anterior,punto), (vertice,A)) if orient(vertice,punto,A) != orient(vertice,anterior,A) and vertice != anterior and vertice != punto and A != anterior and A != punto: if dist(vertice,interseccion) > dist(vertice,lineI) and dist(A,lineI) < dist(A,vertice): interseccion = lineI anterior = (punto[0],punto[1]) region1, region2, pasado, pasad = [],[], False, False ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) for punt in region: if interseccion == A: if (punt[0],punt[1]) == A: pasad = True region1.append(punt) region2.append(punt) elif not pasad: region1.append(punt) elif pasad: region2.append(punt) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and not pasado: region1.append(punt) ant = (punt[0],punt[1]) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 1 and not pasado: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append(punt) ant, pasado = (punt[0],punt[1]), True elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and pasado: region2.append(punt)

Page 111: ?.1B.1< 2; .A2:HA60.@ 2 ;3

ant = (punt[0],punt[1]) region2.append([vertice[0],vertice[1]]) ax.add_artist(ConnectionPatch(xyA = (vertice[0],vertice[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # Proyecciones que intersecan calculados = [] for proy in proyeccionesConInters: regionEncontrada, aristaProyeccion, interseccion = False, (proy,proy), A for region in regiones: if not regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if enSegmento(proy,(anterior,punto)) == 1: regionEncontrada, aristaProyeccion = True, (anterior,punto) anterior = punto if regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if lineIntersection((anterior,punto), (proy,A)) == 'Son la misma recta': print((anterior,punto), (proy,A)) return 'No es posible realizar el cálculo' if proy not in [punto, anterior] and A not in [punto, anterior] and dist(proy,interseccion) > dist(proy,lineIntersection((anterior,punto), (proy,A))) and not enSegmento(proy,(anterior,punto)) and segmentoEnPol(region,(proy,lineIntersection((anterior,punto), (proy,A)))) and enSegmento(lineIntersection((anterior,punto), (proy,A)),(anterior,punto)): interseccion = lineIntersection((anterior,punto), (proy,A)) calculados.append(proy) anterior = punto region1, region2, pasadaInterseccion = [], [], False while [aristaProyeccion[1][0],aristaProyeccion[1][1]] in region and region[0] != [aristaProyeccion[1][0],aristaProyeccion[1][1]]: region.append(region[0]) region.remove(region[0]) ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) region1.append([proy[0],proy[1]]) for punt in region: punt = (punt[0],punt[1]) if enSegmento(interseccion,(ant,punt)) == 0 and not pasadaInterseccion: region1.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 0 and pasadaInterseccion: region2.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 1: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append([punt[0],punt[1]]) pasadaInterseccion = True ant = punt

Page 112: ?.1B.1< 2; .A2:HA60.@ 2 ;3

region2.append([proy[0],proy[1]]) ax.add_artist(ConnectionPatch(xyA = (proy[0],proy[1]), xyB = (interseccion[0],interseccion[1]), coordsA="data", coordsB="data", axesA=ax, axesB=ax, color='#000000')) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # SUMIDEROS sumideros = [] for region in regiones: if region[0] != [A[0],A[1]]: sumidero = region[0] else: sumidero = region[1] for punto in region: if dist(sumidero,A) < dist(punto,A) and punto != [A[0],A[1]]: sumidero = punto ax.plot(sumidero[0], sumidero[1], '.', color='#FF0000', ms = 15) sumideros.append(sumidero) # PESOS pesos = [] colores = [(0.6509803921568628, 0.807843137254902, 0.8901960784313725, 0.4), (0.12156862745098039, 0.47058823529411764, 0.7058823529411765, 0.4), (0.6980392156862745, 0.8745098039215686, 0.5411764705882353, 0.4), (0.2, 0.6274509803921569, 0.17254901960784313, 0.4), (0.984313725490196, 0.6039215686274509, 0.6, 0.4), (0.8901960784313725, 0.10196078431372549, 0.10980392156862745, 0.4), (0.9921568627450981, 0.7490196078431373, 0.43529411764705883, 0.4), (1.0, 0.4980392156862745, 0.0, 0.4), (0.792156862745098, 0.6980392156862745, 0.8392156862745098, 0.4), (0.41568627450980394, 0.23921568627450981, 0.6039215686274509, 0.4), (1.0, 1.0, 0.6, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4), (0.6941176470588235, 0.34901960784313724, 0.1568627450980392, 0.4)] for region in regiones: pesos.append(abs(sareaPolygon(region))) patches.append(Polygon(region, True, color = colores[regiones.index(region)%12])) ax.add_collection(PatchCollection(patches, match_original = True)) sumaPesos = 0 for i in range(len(pesos)): sumaPesos = sumaPesos + pesos[i] handles = [] d = maxAbscisa(Pol)[0]/40 for i in range(len(patches)): handles.append(Polygon([(0,0),(10,0),(0,-10)], color = colores[i%12], label = 'Region %i con peso %.2f'%(i,pesos[i]*100/sumaPesos))) plt.text(sumideros[i][0]+d, sumideros[i][1], 'S%i'%(i), fontsize = 10, backgroundcolor = '#FFFFFF') plt.legend(handles = handles) plt.axis('on') plt.axis('equal') print("--- %s segundos pesos ---" % (time.time() - pesosInicio)) return plt.show() def sumPesAux(Pol,A): sumPesAuxInicio = time.time() proyecciones, proyeccionesConInters, concavos, anterior = [], [], [], [], Pol[len(Pol)-1]

Page 113: ?.1B.1< 2; .A2:HA60.@ 2 ;3

for punto in Pol: # Se depuran los vértices cóncavos y se dibujan sus aristas index = Pol.index(punto) ant, sig = Pol[(index - 1)%len(Pol)], Pol[(index + 1)%len(Pol)] if angulo(ant, punto, A) > 90 and angulo(A, punto, sig) > 90 and (sarea(A, punto, sig) < 0 or sarea(ant, punto, A) < 0): if angulo(ant, punto, sig) > 180: anteriorAux, inters = Pol[len(Pol)-1], 0 for puntoAux in Pol: if segmentIntersectionTest((anteriorAux,puntoAux), (punto,A))[0]: inters = inters + 1 anteriorAux = puntoAux # Si el vértice está dentro del polígono... if inters%2 == 0 or inters == 1: concavos.insert(len(concavos), punto) # Se dibujan las aristas de proyecciones con intersección y se crea la lista de proyecciones proy = proyeccionPuntoRecta((anterior, punto),A) or1, or2 = orient(ant, punto, A), orient(A, punto, sig) # Se añade la proyección con intersección - Segmento, proyección en segmento, proyección if enSegmento(proy,(anterior,punto)) and not segmentoEnPol(Pol, (proy, A)) and not (proy in [anterior, punto]): proyecciones.append(((anterior,punto),False,proy)) ant, inters = Pol[len(Pol)-1], 0 for pun in Pol: if segmentIntersectionTest((ant, pun), (proy, A))[0]: inters = inters+1 ant = pun if inters%2 == 0: proyeccionesConInters.insert(len(proyeccionesConInters),proy) # Se añade la proyección sin intersección - Segmento, proyección en segmento, proyección elif enSegmento(proy,(anterior,punto)) and segmentoEnPol(Pol, (proy, A)) or (proy in [anterior, punto] and or1 == or2 == -1): proyecciones.append(((anterior,punto),True,proy)) # Se añaden los puntos sin proyección - Segmento, proyección en segmento, proyección else: proyecciones.append(((anterior,punto),False,proy)) anterior = punto # REGIONES regionActual, regiones = [], [] # Se pone primero un caso con proyección while not proyecciones[0][1]: proyecciones.append(proyecciones[0]) proyecciones.remove(proyecciones[0]) # Se crean las regiones for x in proyecciones: # Último caso if x == proyecciones[len(proyecciones)-1]: if x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = []

Page 114: ?.1B.1< 2; .A2:HA60.@ 2 ;3

regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) elif not x[1]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[0][1][0], x[0][1][1]]] y = proyecciones[0] while not y[1]: regionActual.insert(len(regionActual),[y[0][1][0], y[0][1][1]]) y = proyecciones[proyecciones.index(y) + 1] regionActual.insert(len(regionActual),[y[2][0], y[2][1]]) regiones.insert(len(regiones),regionActual) # True elif x[1]: if x != proyecciones[0]: regionActual[len(regionActual):len(regionActual)] = [[x[0][0][0], x[0][0][1]],[x[2][0], x[2][1]]] regiones.insert(len(regiones),regionActual) regionActual = [] regionActual[len(regionActual):len(regionActual)] = [[A[0],A[1]],[x[2][0], x[2][1]]] # False elif not x[1]: regionActual.insert(len(regionActual),[x[0][0][0], x[0][0][1]]) # REGIONES DE VÉRTICES CÓNCAVOS Y PROYECCIONES QUE INTERSECAN # Vértices cóncavos calculados = [] for vertice in concavos: for region in regiones: if [vertice[0],vertice[1]] in region and vertice not in calculados: calculados.append(vertice) while region[0] != [vertice[0],vertice[1]]: region.append(region[0]) region.remove(region[0]) interseccion, anterior = A, (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) lineI = lineIntersection((anterior,punto), (vertice,A)) if orient(vertice,punto,A) != orient(vertice,anterior,A) and vertice != anterior and vertice != punto and A != anterior and A != punto: if dist(vertice,interseccion) > dist(vertice,lineI) and dist(A,lineI) < dist(A,vertice): interseccion = lineI anterior = (punto[0],punto[1]) region1, region2, pasado, pasad = [],[], False, False ant = (region[(len(region)-1)][0],region[(len(region)-1)][1]) for punt in region: if interseccion == A: if (punt[0],punt[1]) == A: pasad = True region1.append(punt)

Page 115: ?.1B.1< 2; .A2:HA60.@ 2 ;3

region2.append(punt) elif not pasad: region1.append(punt) elif pasad: region2.append(punt) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and not pasado: region1.append(punt) ant = (punt[0],punt[1]) elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 1 and not pasado: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append(punt) ant, pasado = (punt[0],punt[1]), True elif enSegmento(interseccion,(ant,(punt[0],punt[1]))) == 0 and pasado: region2.append(punt) ant = (punt[0],punt[1]) region2.append([vertice[0],vertice[1]]) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # Proyecciones que intersecan calculados = [] for proy in proyeccionesConInters: regionEncontrada, aristaProyeccion, interseccion = False, (proy,proy), A for region in regiones: if not regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if enSegmento(proy,(anterior,punto)) == 1: regionEncontrada, aristaProyeccion = True, (anterior,punto) anterior = punto if regionEncontrada and proy not in calculados: anterior = (region[len(region)-1][0],region[len(region)-1][1]) for punto in region: punto = (punto[0],punto[1]) if lineIntersection((anterior,punto), (proy,A)) == 'Son la misma recta': print((anterior,punto), (proy,A)) return 'No es posible realizar el cálculo' if proy not in [punto, anterior] and A not in [punto, anterior] and dist(proy,interseccion) > dist(proy,lineIntersection((anterior,punto), (proy,A))) and not enSegmento(proy,(anterior,punto)) and segmentoEnPol(region,(proy,lineIntersection((anterior,punto), (proy,A)))) and enSegmento(lineIntersection((anterior,punto), (proy,A)),(anterior,punto)): interseccion = lineIntersection((anterior,punto), (proy,A)) calculados.append(proy) anterior = punto region1, region2, pasadaInterseccion = [], [], False while [aristaProyeccion[1][0],aristaProyeccion[1][1]] in region and region[0] != [aristaProyeccion[1][0],aristaProyeccion[1][1]]: region.append(region[0]) region.remove(region[0]) ant = (region[(len(region)-1)][0],region[(len(region)-1)][1])

Page 116: ?.1B.1< 2; .A2:HA60.@ 2 ;3

region1.append([proy[0],proy[1]]) for punt in region: punt = (punt[0],punt[1]) if enSegmento(interseccion,(ant,punt)) == 0 and not pasadaInterseccion: region1.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 0 and pasadaInterseccion: region2.append([punt[0],punt[1]]) elif enSegmento(interseccion,(ant,punt)) == 1: region1.append([interseccion[0],interseccion[1]]) region2.append([interseccion[0],interseccion[1]]) region2.append([punt[0],punt[1]]) pasadaInterseccion = True ant = punt region2.append([proy[0],proy[1]]) regiones.insert(0,region1) regiones.insert(0,region2) regiones.remove(region) # SUMIDEROS sumideros = [] for region in regiones: if region[0] != [A[0],A[1]]: sumidero = region[0] else: sumidero = region[1] for punto in region: if dist(sumidero,A) < dist(punto,A) and punto != [A[0],A[1]]: sumidero = punto sumideros.append(sumidero) # PESOS PONDERADOS pesos = [] sumaPesos = 0 for i in range(len(regiones)): pesos.append(abs(sareaPolygon(regiones[i]))) sumaPesos = sumaPesos + pesos[i] for i in range(len(pesos)): pesos[i] = pesos[i]*100/sumaPesos print("--- %s segundos sumPesAux ---" % (time.time() - sumPesAuxInicio)) return sumideros, pesos def sumiderosConMasPeso(Pol): diccionario, top = {}, 100 for i in range(top): print(i,top) punto = puntoDelPol(Pol) if sumPesAux(Pol,punto) != 'No es posible realizar el cálculo': [sumideros,pesos] = sumPesAux(Pol,punto) for i in range(len(sumideros)): sumi = str(sumideros[i]) if sumi not in diccionario: diccionario[sumi] = pesos[i] else: diccionario[sumi] = diccionario[sumi] + pesos[i] return sorted(diccionario.items(), key=lambda x: x[1]) def algoritmo(Pol,A): return dibujarVertices(Pol), dibujarAristas(Pol), rellenarAristas(Pol,A), dibujarPerpendiculares(Pol,A), colorearRegiones(Pol,A), colorearTodasRegiones(Pol,A), sumideros(Pol,A), pesos(Pol,A) def algo(Pol,A): tiempoAlg = time.time() a = dibujarVertices(Pol), dibujarAristas(Pol), rellenarAristas(Pol, A), dibujarPerpendiculares(Pol, A), colorearRegiones(Pol, A), colorearTodasRegiones(Pol, A), sumideros(Pol, A), pesos(Pol, A) print("--- %s segundos ---" % (time.time() - tiempoAlg))

Page 117: ?.1B.1< 2; .A2:HA60.@ 2 ;3

return a # P = poligonoAleatorio(20,0.5) # algoritmo(orientaPositivamente(P),puntoDelPol(P)) print("--- %s seconds ---" % (time.time() - start_time))

Page 118: ?.1B.1< 2; .A2:HA60.@ 2 ;3

oooooo

Page 119: ?.1B.1< 2; .A2:HA60.@ 2 ;3

Este documento esta firmado porFirmante CN=tfgm.fi.upm.es, OU=CCFI, O=Facultad de Informatica - UPM,

C=ES

Fecha/Hora Mon Jul 08 16:28:08 CEST 2019

Emisor delCertificado

[email protected], CN=CA Facultad deInformatica, O=Facultad de Informatica - UPM, C=ES

Numero de Serie 630

Metodo urn:adobe.com:Adobe.PPKLite:adbe.pkcs7.sha1 (AdobeSignature)