Difference between revisions of "User:Caron/memo"
Jump to navigation
Jump to search
(added fix_non_convex method.) |
|||
Line 87: | Line 87: | ||
== Convex Quadrilaterals or not== | == Convex Quadrilaterals or not== | ||
[[File:Caron is cq.jpg|800px]] | [[File:Caron is cq.jpg|800px]] | ||
− | <br> | + | <br>緑の角度の総和が2πになればよい。4πの場合はConvex Quadrilateralsではない。 |
<nowiki> | <nowiki> | ||
− | def is_convex(pt1: np.ndarray, pt2: np.ndarray) -> bool: | + | def is_convex( |
+ | pt1: np.ndarray, | ||
+ | pt2: np.ndarray, | ||
+ | return_data: bool=False | ||
+ | )-> Union[bool, Tuple[bool, Optional[np.ndarray]]]: | ||
pos = np.vstack([pt1.reshape(2,2), pt2.reshape(2,2)[::-1]]) | pos = np.vstack([pt1.reshape(2,2), pt2.reshape(2,2)[::-1]]) | ||
flat = pos.flatten() | flat = pos.flatten() | ||
if flat.shape[0] != np.unique(flat).shape[0]: | if flat.shape[0] != np.unique(flat).shape[0]: | ||
− | return False | + | return False if not return_data else (False, None) |
vector = np.vstack( | vector = np.vstack( | ||
Line 100: | Line 104: | ||
).T | ).T | ||
res = np.arctan2(vector[1], vector[0])*180/np.pi | res = np.arctan2(vector[1], vector[0])*180/np.pi | ||
− | res = (res-np.roll(res, 4))[:4] | + | res = 180 - (res - np.roll(res, 4))[:4] |
− | res = np.where(res | + | res = np.where(res>=360, res-360, res) |
− | if int(np.sum(res)) == 360: | + | if not int(np.sum(res)) == 360: |
− | return | + | return False if not return_data else (False, res) |
− | return | + | return True if not return_data else (True, res) |
</nowiki> | </nowiki> | ||
Line 116: | Line 120: | ||
<b>非凸の頂点</b>...簡単。反時計回りで行くなら時計回りになっている点を見つければそれが非凸の頂点。<br> | <b>非凸の頂点</b>...簡単。反時計回りで行くなら時計回りになっている点を見つければそれが非凸の頂点。<br> | ||
<b>二等分線</b>...非凸の頂点と隣の2点から二等分線を求める<br> | <b>二等分線</b>...非凸の頂点と隣の2点から二等分線を求める<br> | ||
− | <b>移動距離</b>... | + | <b>移動距離</b>...少しづつ移動させる |
− | + | <nowiki> | |
− | + | def fix_non_convex(pt1: np.ndarray, pt2: np.ndarray): | |
− | + | isconvec, res = is_convex(pt1, pt2, True) | |
+ | if isconvec or res is None: | ||
+ | return pt1, pt2 | ||
+ | |||
+ | pos = np.vstack([pt1.reshape(2,2), pt2.reshape(2,2)[::-1]]) | ||
+ | vector = np.vstack( | ||
+ | [np.roll(pos, 2)-pos, np.roll(pos, -2)-pos] | ||
+ | ) | ||
+ | |||
+ | uvec, vvec = vector[:4], vector[4:] | ||
+ | a, b = np.linalg.norm(uvec, axis=1), np.linalg.norm(vvec, axis=1) | ||
+ | apb = a+b | ||
+ | a_apb, b_apb = (a/apb), (b/apb) | ||
+ | |||
+ | uvec_i2 = np.tile(b_apb, (2,1)).T * uvec | ||
+ | vvec_i2 = np.tile(a_apb, (2,1)).T * vvec | ||
+ | vector_i2 = uvec_i2 + vvec_i2 | ||
+ | |||
+ | f_index = np.where(res>180)[0][0] | ||
+ | target_index = [f_index, f_index+1] if f_index != 3 else [f_index, 0] | ||
+ | |||
+ | param = 0.1 | ||
+ | for i in range(1, 20): | ||
+ | k = pos.copy() | ||
+ | k[target_index] = k[target_index] + (vector_i2[target_index] * param * i) | ||
+ | p0, p1 = np.vsplit(k, 2) | ||
+ | p0 = p0.flatten() | ||
+ | p1 = p1[::-1].flatten() | ||
+ | if is_convex(p0, p1): | ||
+ | break | ||
+ | return p0, p1 | ||
+ | |||
+ | </nowiki> | ||
== Internal nodes == | == Internal nodes == | ||
<b>チェックポイントのパス構造には内部ノードは存在してはいけない</b>(自身のコース製作で経験済み)。CPUとアイテムルートは別にパス関係が木構造になっていてもok. | <b>チェックポイントのパス構造には内部ノードは存在してはいけない</b>(自身のコース製作で経験済み)。CPUとアイテムルートは別にパス関係が木構造になっていてもok. |
Revision as of 13:38, 19 June 2021
Graphviz
import graphviz # type: ignore dgraph = graphviz.Digraph(**kwargs) for i, _ in enumerate(self._data): dgraph.node(self._gn(i)) for i, _data in enumerate(self._data): label = str(_data[1]-_data[0]) for nxt in np.unique(_data[8:14])[:-1]: # 255は除外 dgraph.edge(self._gn(i), self._gn(nxt), label=label) if render: dgraph.render(view=view) elif view: dgraph.view()
Smoothing:Catmull–Clark
faceは不要なのでCatmull-clarkの途中処理まで
not tested yet
counts = round(counts) if isinstance(counts, float) else counts for _ in range(counts): data_size = len(target) smoothed = create_new_data(self._sectionname, 2, 2*data_size-1) smoothed[::2,:] = target # type: ignore # Center position smoothed[1::2,0:3] = ((target[:-1,0:3] + target[1:,0:3])/2) # Average((cur + center_1 + center_2)/3) smoothed[2:-2:2,0:3] = (smoothed[1:-2:2,0:3] + smoothed[3::2,0:3] + smoothed[2:-2:2,0:3])/3 # update settings smoothed = update_settings( iter = range(1, len(smoothed)-1), old_array=target, new_array=smoothed ) # clone array for next iteration. target = smoothed.copy()
Smoothing:Spline interpolation
こっちの方が元の曲線に近くフィットしてくれる
not tested yet
pos = target[:, :3].T m = len(pos[0]) # create knots vector tck, _ = interpolate.splprep(pos, s=m+np.sqrt(m), k=4) u_counts = np.linspace(0,1,round(m*counts)) # fitting fitted = np.vstack(interpolate.splev(u_counts, tck)).T ### update settings: start data_size = len(fitted) update_idx = np.zeros(data_size) # find nearest positions for idx in range(m): old_vec = np.tile(pos.T[idx], (data_size, 1)) norm = np.linalg.norm(old_vec - fitted, axis=-1) update_idx[idx] = np.argmin(norm) smoothed = create_new_data(self._sectionname, 2, data_size) smoothed[:,:3] = fitted # POTI Setting is start at target[3:], but ENPT, ITPT are target[4:]. start = 4 if self._sectionname != 'POTI' else 3 smoothed[update_idx,start:] = target[:,start:] smoothed = update_settings( iter=range(1, m), old_array=target, new_array=smoothed, spline_index=update_idx )
Convex Quadrilaterals or not
緑の角度の総和が2πになればよい。4πの場合はConvex Quadrilateralsではない。
def is_convex( pt1: np.ndarray, pt2: np.ndarray, return_data: bool=False )-> Union[bool, Tuple[bool, Optional[np.ndarray]]]: pos = np.vstack([pt1.reshape(2,2), pt2.reshape(2,2)[::-1]]) flat = pos.flatten() if flat.shape[0] != np.unique(flat).shape[0]: return False if not return_data else (False, None) vector = np.vstack( [np.roll(pos, 2)-pos, np.roll(pos, -2)-pos] ).T res = np.arctan2(vector[1], vector[0])*180/np.pi res = 180 - (res - np.roll(res, 4))[:4] res = np.where(res>=360, res-360, res) if not int(np.sum(res)) == 360: return False if not return_data else (False, res) return True if not return_data else (True, res)
Fix Non-convex Quadrilaterals
非凸の頂点...簡単。反時計回りで行くなら時計回りになっている点を見つければそれが非凸の頂点。
二等分線...非凸の頂点と隣の2点から二等分線を求める
移動距離...少しづつ移動させる
def fix_non_convex(pt1: np.ndarray, pt2: np.ndarray): isconvec, res = is_convex(pt1, pt2, True) if isconvec or res is None: return pt1, pt2 pos = np.vstack([pt1.reshape(2,2), pt2.reshape(2,2)[::-1]]) vector = np.vstack( [np.roll(pos, 2)-pos, np.roll(pos, -2)-pos] ) uvec, vvec = vector[:4], vector[4:] a, b = np.linalg.norm(uvec, axis=1), np.linalg.norm(vvec, axis=1) apb = a+b a_apb, b_apb = (a/apb), (b/apb) uvec_i2 = np.tile(b_apb, (2,1)).T * uvec vvec_i2 = np.tile(a_apb, (2,1)).T * vvec vector_i2 = uvec_i2 + vvec_i2 f_index = np.where(res>180)[0][0] target_index = [f_index, f_index+1] if f_index != 3 else [f_index, 0] param = 0.1 for i in range(1, 20): k = pos.copy() k[target_index] = k[target_index] + (vector_i2[target_index] * param * i) p0, p1 = np.vsplit(k, 2) p0 = p0.flatten() p1 = p1[::-1].flatten() if is_convex(p0, p1): break return p0, p1
Internal nodes
チェックポイントのパス構造には内部ノードは存在してはいけない(自身のコース製作で経験済み)。CPUとアイテムルートは別にパス関係が木構造になっていてもok.