def test_smallest_triangle_sphere(): # this test is based on test_circum p1 = np.array((0, 0, 0)) p2 = np.array((3, 0, 0)) p3 = np.array((0, 4, 0)) exp_r = 2.5 exp_center = (1.5, 2, 0) tol = 1e-10 (r, center) = smallest_triangle_sphere(p1, p2, p3) feqok_(exp_r, r, tol) iter_ = iter(exp_center) for item in center: feqok_(next(iter_), item, tol) p1 = np.array((0, 0, 0)) p2 = np.array((3, -1, 0)) p3 = np.array((0, 4, 0)) exp_r = sqrt(34) / 2 exp_center = (1.5, 1.5, 0) tol = 1e-10 (r, center) = smallest_triangle_sphere(p1, p2, p3) feqok_(exp_r, r, tol) iter_ = iter(exp_center) for item in center: feqok_(next(iter_), item, tol)
def edge_polygon(self): e = self.ale.pop() p1 = e.start p2 = e.end p_s = (p1 + p2) / 2.0 #grd_s = norm_vec(self.func_gd(p_s)) pold = e.tri_pt v12 = p2 - p1 grd_old = np.cross(v12, pold - p2) # not like Cermak2005!!! c0 = vec_len(grd_old) / vec_len(v12) vinit = np.cross(v12, grd_old) radius = self.estimate_spining_radius(p1, p2, vinit, c0) pnew = self.search_on_plane(p_s, radius, v12, vinit) v_succ = e.succ.end - e.end v_pred = e.start - e.pred.start alpha2 = intersec_angle(v_succ, -v12) if np.cross(v12, v_succ).dot(grd_old) > 0: alpha2 = 2 * pi - alpha2 alpha1 = intersec_angle(v12, -v_pred) if np.cross(v_pred, v12).dot(grd_old) > 0: alpha1 = 2 * pi - alpha1 alpha = min(alpha1, alpha2) # MARK: alpha_n_assuming the pnew made by edge_spining is on the plan P: # P across the mid point of e # P is perpendicular to e if pnew is not None: alpha_n = intersec_angle(pnew - p1, v12) alpha_shape = alpha_n + self.alpha_shape_min else: alpha_shape = self.alpha_shape_big # neibourhood test if alpha < alpha_shape: if e.succ.succ is e.pred: self.ale.remove(e.succ) self.ale.remove(e.pred) self.triangles.append((e.end_index, e.start_index, e.pred.start_index)) return # situation a) in Fig8 & Fig9 if alpha == alpha1: case = 1 (r, center) = smallest_triangle_sphere(p1, p2, e.pred.start) except_pts = (p1, p2, e.pred.start) check_dir = p2 - e.pred.start radius_check_pts = (e.pred.pred.start, e.succ.end) else: case = 2 (r, center) = smallest_triangle_sphere(p1, p2, e.succ.end) except_pts = (p1, p2, e.succ.end) check_dir = e.succ.end - p1 radius_check_pts = (e.pred.start, e.succ.succ.end) elif pnew is None: r = vec_len(v12) * 0.5 center = (p1 + p2) * 0.5 except_pts = (p1, p2) check_dir = e radius_check_pts = (e.pred.start, e.succ.end) case = 3 else: (r, center) = smallest_triangle_sphere(p1, p2, pnew) r = r * self.dist_test_cf except_pts = (p1, p2) check_dir = e radius_check_pts = (e.pred.start, e.succ.end) case = 4 # filet out a NAEL,distance test emin = self._distance_test(e, r, center, check_dir, except_pts, radius_check_pts) if emin is e.pred.pred: emin = None case = 1 elif emin is e.succ: emin = None case = 2 if emin is None: if 1 == case: self.ale.remove(e.pred) self._add_tri_ale_A(e.pred, e) elif 2 == case: self.ale.remove(e.succ) self._add_tri_ale_A(e, e.succ) elif 3 == case: self.ale.appendleft(e) elif 4 == case: pnew_index = len(self.points) self.points.append(pnew) self.triangles.append((pnew_index, e.end_index, e.start_index)) e_new1 = _WingedEdge(e.start, pnew, e.start_index, pnew_index, e.end) e_new2 = _WingedEdge(pnew, e.end, pnew_index, e.end_index, e.start) e_new1.succ = e_new2 e_new1.pred = e.pred e_new2.pred = e_new1 e_new2.succ = e.succ e.pred.succ = e_new1 e.succ.pred = e_new2 self.ale.append(e_new1) self.ale.append(e_new2) else: emin1 = emin emin2 = emin.succ alpha_m1 = intersec_angle(emin2.end - emin2.start, e.start - emin2.start) alpha_m2 = intersec_angle(emin1.start - emin1.end, e.end - emin1.end) if alpha_m1 < alpha_m2: te = _WingedEdge(e.start, emin2.end) (r, center) = smallest_triangle_sphere(e.start, emin2.start, emin2.end) except_pts = (emin2.start, emin2.end, e.start, e.end) radius_check_pts = (emin2.succ.end, emin1.start, e.pred.start) else: te = _WingedEdge(emin1.start, e.end) (r, center) = smallest_triangle_sphere(e.end, emin1.start, emin1.end) except_pts = (emin1.start, emin1.end, e.start, e.end) radius_check_pts = (emin2.end, emin1.pred.start, e.succ.end) check_dir = te.end - te.start t_emin = self._distance_test(te, r, center, check_dir, except_pts, radius_check_pts) if t_emin is not None: self.ale.appendleft(e) return if alpha_m1 < alpha_m2: self.ale.remove(emin2) if emin2.succ is e.pred: self.ale.remove(e.pred) else: enew1 = _WingedEdge( e.start, emin2.end, e.start_index, emin2.end_index, emin2.start, e.pred, emin2.succ, ) e.pred.succ = enew1 emin2.succ.pred = enew1 self.ale.append(enew1) enew2 = _WingedEdge( emin2.start, e.end, emin2.start_index, e.end_index, e.start, emin1, e.succ, ) emin1.succ = enew2 e.succ.pred = enew2 self.ale.append(enew2) self.triangles.append((emin2.end_index, emin2.start_index, e.start_index)) else: self.ale.remove(emin1) if e.succ is emin1.pred: self.ale.remove(emin1.pred) else: enew1 = _WingedEdge( emin1.start, e.end, emin1.start_index, e.end_index, emin1.end, emin1.pred, e.succ, ) emin1.pred.succ = enew1 e.succ.pred = enew1 self.ale.append(enew1) enew2 = _WingedEdge( e.start, emin1.end, e.start_index, emin1.end_index, e.end, e.pred, emin2, ) e.pred.succ = enew2 emin2.pred = enew2 self.ale.append(enew2) self.triangles.append((emin1.end_index, emin1.start_index, e.end_index)) self.triangles.append((emin2.start_index, e.end_index, e.start_index)) pass