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

Post on 19-Nov-2020

14 views 0 download

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

o

o

o

o

o

o

β

••

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]:

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)

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

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

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

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

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()

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

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

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)

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])

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

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))

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

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

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])

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

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]:

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]:

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))

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]])

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))

Out[1]:

regionActual

regionActual

regionActual

regionActual

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

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]

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))

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:

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:

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]])

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]:

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]:

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))

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

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)

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

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)

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)]

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)]

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)]

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)]

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)]

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)])

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.

#!/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)

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()

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:

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()

# 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]

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)

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

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')

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'))

# 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:

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)

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]))

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)

# 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]])

# 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

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

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)

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]])

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)

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

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]

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 = []

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)

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])

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))

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

oooooo

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

EMAILADDRESS=camanager@fi.upm.es, 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)