[Triangulation」湖に島があってその中に池がある
- 昨日は、輪郭(Aの字の外周〜湖があって、その中に「なかぬけ」として島(Aの字のぐるり)があるときに、Triangulationを使ってプロットした。
- それを扱うためのオブジェクトとしてdict(dictionaryタイプ)というのを使っているので、それの使い方に慣れつつ、トポロジー的に一段階複雑な、「湖に島があって、その中に池」というのを作ってみる
import numpy as np # ベクトル・行列・高次元アレイを使う import scipy as sp # 線形代数・関数・数値計算 # matplotlibのpylabインタフェースは、MATLABの利用経験があるユーザがmatplotlibを簡単に習得できるように設計されている。というわけで以下2つを入れる import matplotlib as mp import pylab as pl import os # コンピュータのファイルの出し入れのため os.chdir('C:\\Users\\ryamada\\Desktop\\python') # Windowsでは'\'が'\\'になることに注意 #from numpy import array R = 1 n = 100 #t = np.linspace(0,1,n) * 2 * np.pi t = np.arange(n) * 2 * np.pi/n x = R * sp.cos(t) y = R * sp.sin(t) mp.pyplot.plot(x,y) mp.pyplot.xlim(x.min()-0.01, x.max()+0.01) # x,y軸の範囲を存在点座標の範囲より0.01広げる mp.pyplot.ylim(y.min()-0.01, y.max()+0.01) mp.pyplot.axis('off') mp.pyplot.axes().set_aspect('equal') # x,y軸の長さを揃える mp.pyplot.plot(x,y, 'b.') R2 = 0.3 ctr_2x = 0.2 ctr_2y = 0.1 x2 = R2 * sp.cos(t) + ctr_2x y2 = R2 * sp.sin(t) + ctr_2y R3 = 0.1 ctr_3x = 0.22 ctr_3y = 0.11 x3 = R3 * sp.cos(t) + ctr_3x y3 = R3 * sp.sin(t) + ctr_3y output = {'vertices': None, 'holes': None, 'segments': None} vertices = [] for i in range(n) : vertices.append([float(x[i]), float(y[i])]) for i in range(n) : vertices.append([float(x2[i]), float(y2[i])]) for i in range(n) : vertices.append([float(x3[i]), float(y3[i])]) output['vertices']=np.array(vertices) segments = [] for i in range(n) : tmp = i-1 if(i==0) : tmp = n-1 segments.append([tmp,i]) for i in range(n) : tmp = i-1 if(i==0): tmp = n-1 segments.append([n+tmp, n+i]) for i in range(n) : tmp = i-1 if(i==0): tmp = n-1 segments.append([2*n+tmp, 2*n+i]) output['segments']=np.array(segments) holes = [] N_holes = 1 for k in range(N_holes): holes.append([ctr_3x+R3*1.5, ctr_3y]) output['holes'] = np.array(holes) from scipy.spatial import ConvexHull import matplotlib.pyplot as plt %matplotlib inline lake_superior = output vertices_ls = lake_superior['vertices'] vertices_ls.shape %time hull = ConvexHull(vertices_ls) plt.figure(figsize=(18, 18)) # 図のサイズ指定 plt.xlim(vertices_ls[:,0].min()-0.01, vertices_ls[:,0].max()+0.01) # x,y軸の範囲を存在点座標の範囲より0.01広げる plt.ylim(vertices_ls[:,1].min()-0.01, vertices_ls[:,1].max()+0.01) plt.axis('off') plt.axes().set_aspect('equal') # x,y軸の長さを揃える plt.plot(vertices_ls[:,0], vertices_ls[:,1], 'b.') for simplex in hull.simplices: # hull.simplicesの要素(辺)を一つずつ描く plt.plot(vertices_ls[simplex, 0], vertices_ls[simplex, 1], 'r-') plt.show() from scipy.spatial import Voronoi, voronoi_plot_2d vor = Voronoi(vertices_ls) plt.figure(figsize=(10, 10)) ax = plt.subplot(111, aspect='equal') voronoi_plot_2d(vor, ax=ax) plt.xlim(-3,3) # 範囲は、適当に描かれた絵を見たあとで調整使用 plt.ylim(-3,3) plt.show() from scipy.spatial import Delaunay, delaunay_plot_2d tri = Delaunay(vertices_ls) plt.figure(figsize=(18, 18)) ax = plt.subplot(111, aspect='equal') delaunay_plot_2d(tri, ax=ax) plt.show() from triangle import triangulate, plot as tplot cndt = triangulate(lake_superior, 'p') plt.figure(figsize=(18, 18)) ax = plt.subplot(111, aspect='equal') tplot.plot(ax, **cndt) plt.show() cncfq20adt = triangulate(lake_superior, 'pq20a.001D') plt.figure(figsize=(18, 18)) ax = plt.subplot(111, aspect='equal') tplot.plot(ax, **cncfq20adt) plt.show() from scipy.spatial import minkowski_distance X = cncfq20adt['triangles'][:,0] Y = cncfq20adt['triangles'][:,1] Z = cncfq20adt['triangles'][:,2] Xvert = [cncfq20adt['vertices'][x] for x in X] Yvert = [cncfq20adt['vertices'][y] for y in Y] Zvert = [cncfq20adt['vertices'][z] for z in Z] lengthsXY = minkowski_distance(Xvert, Yvert) lengthsXZ = minkowski_distance(Xvert, Zvert) lengthsYZ = minkowski_distance(Yvert, Zvert) from scipy.sparse import lil_matrix from scipy.sparse.csgraph import shortest_path nvert = len(cncfq20adt['vertices']) G = lil_matrix((nvert, nvert)) for k in range(len(X)): G[X[k], Y[k]] = G[Y[k], X[k]] = lengthsXY[k] G[X[k], Z[k]] = G[Z[k], X[k]] = lengthsXZ[k] G[Y[k], Z[k]] = G[Z[k], Y[k]] = lengthsYZ[k] dist_matrix, pred = shortest_path(G, return_predecessors=True, directed=True, unweighted=False) index = 2 # ウェブサイトで使っている指定番地では数が大きすぎるので適当な数を入れる path = [2] # 同上 while index != 45: # ウェブサイトで使っている指定番地では数が大きすぎるので適当な数を入れる index = pred[45, index] # 同上 path.append(index) Xs = [cncfq20adt['vertices'][x][0] for x in path] Ys = [cncfq20adt['vertices'][x][1] for x in path] plt.figure(figsize=(18,18)) ax = plt.subplot(111, aspect='equal') tplot.plot(ax, **cncfq20adt) ax.plot(Xs, Ys, '-', linewidth=5, color='blue'); \ plt.show()
http://www.cs.cmu.edu/~quake/triangle.refine.html
http://docs.scipy.org/doc/scipy-0.14.0/reference/sparse.csgraph.html