def test_approximate_line_2(self): p1 = (0, -1, 0) p2 = (1, 1, 0) p3 = (2, -1, 0) p4 = (3, 1, 0) line = linear_approximation([p1, p2, p3, p4]).most_similar_line() self.assert_sverchok_data_equal(tuple(line.direction), (0.7882054448127747, 0.6154122352600098, 0.0), precision=5)
def init_guess(verts, npoints): approx = linear_approximation(verts) line = approx.most_similar_line() projections = line.projection_of_points(verts) m = projections.min(axis=0) M = projections.max(axis=0) return np.linspace(m, M, num=npoints)
def test_approximate_plane(self): p1 = (0, -1, 0) p2 = (1, 1, 0) p3 = (2, -1, 0) p4 = (3, 1, 0) plane = linear_approximation([p1, p2, p3, p4]).most_similar_plane() self.assert_sverchok_data_equal(tuple(plane.normal.normalized()), (0, 0, 1), precision=5)
def single_face_delaunay(face_verts, add_verts, epsilon=1e-6, exclude_boundary=True): n = len(face_verts) face = list(range(n)) edges = [(i, i + 1) for i in range(n - 1)] + [(n - 1, 0)] plane = linear_approximation(face_verts).most_similar_plane() face_verts_2d = [plane.point_uv_projection(v) for v in face_verts] if exclude_boundary: add_verts = [ v for v in add_verts if not is_on_face_edge(v, face_verts, epsilon) ] add_verts_2d = [plane.point_uv_projection(v) for v in add_verts] TRIANGLES = 1 res = delaunay_2d_cdt(face_verts_2d + add_verts_2d, edges, [face], TRIANGLES, epsilon) new_verts_2d = res[0] new_edges = res[1] new_faces = res[2] new_add_verts = [ tuple(plane.evaluate(p[0], p[1], normalize=True)) for p in new_verts_2d[n:] ] return face_verts + new_add_verts, new_edges, new_faces
def test_approximate_line_1(self): p1 = (0, 0, 0) p2 = (1, 0, 0) p3 = (2, 0, 0) p4 = (3, 0, 0) line = linear_approximation([p1, p2, p3, p4]).most_similar_line() self.assert_sverchok_data_equal(tuple(line.direction.normalized()), (1, 0, 0), precision=5)
def process(self): if not any(output.is_linked for output in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get(default=[[]]) out_centers = [] out_normals = [] out_directions = [] out_projections = [] out_diffs = [] out_distances = [] for vertices in vertices_s: approx = linear_approximation(vertices) out_centers.append(approx.center) if self.mode == 'Line': line = approx.most_similar_line() out_directions.append(tuple(line.direction.normalized())) projections = [] diffs = [] distances = [] for vertex in vertices: projection = line.projection_of_point(vertex) projections.append(tuple(projection)) diff = projection - Vector(vertex) diffs.append(tuple(diff)) distances.append(diff.length) out_projections.append(projections) out_diffs.append(diffs) out_distances.append(distances) elif self.mode == 'Plane': plane = approx.most_similar_plane() out_normals.append(tuple(plane.normal.normalized())) projections = [] diffs = [] distances = list( map(float, list(plane.distance_to_points(vertices)))) projections_np = plane.projection_of_points(vertices) vertices_np = np.array(vertices) projections = list(map(tuple, list(projections_np))) diffs_np = projections_np - vertices_np diffs = list(map(tuple, list(diffs_np))) out_projections.append(projections) out_diffs.append(diffs) out_distances.append(distances) self.outputs['Center'].sv_set([out_centers]) self.outputs['Normal'].sv_set([out_normals]) self.outputs['Direction'].sv_set([out_directions]) self.outputs['Projections'].sv_set(out_projections) self.outputs['Diffs'].sv_set(out_diffs) self.outputs['Distances'].sv_set(out_distances)
def process(self): if not any(output.is_linked for output in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get(default=[[]]) out_centers = [] out_normals = [] out_directions = [] out_projections = [] out_diffs = [] out_distances = [] for vertices in vertices_s: approx = linear_approximation(vertices) out_centers.append(approx.center) if self.mode == 'Line': line = approx.most_similar_line() out_directions.append(tuple(line.direction.normalized())) projections = [] diffs = [] distances = [] for vertex in vertices: projection = line.projection_of_point(vertex) projections.append(tuple(projection)) diff = projection - Vector(vertex) diffs.append(tuple(diff)) distances.append(diff.length) out_projections.append(projections) out_diffs.append(diffs) out_distances.append(distances) elif self.mode == 'Plane': plane = approx.most_similar_plane() out_normals.append(tuple(plane.normal.normalized())) projections = [] diffs = [] distances = list(map(float, list(plane.distance_to_points(vertices)))) projections_np = plane.projection_of_points(vertices) vertices_np = np.array(vertices) projections = list(map(tuple, list(projections_np))) diffs_np = projections_np - vertices_np diffs = list(map(tuple, list(diffs_np))) out_projections.append(projections) out_diffs.append(diffs) out_distances.append(distances) self.outputs['Center'].sv_set([out_centers]) self.outputs['Normal'].sv_set([out_normals]) self.outputs['Direction'].sv_set([out_directions]) self.outputs['Projections'].sv_set(out_projections) self.outputs['Diffs'].sv_set(out_diffs) self.outputs['Distances'].sv_set(out_distances)
def test_approximate_line_2(self): p1 = (0, -1, 0) p2 = (1, 1, 0) p3 = (2, -1, 0) p4 = (3, 1, 0) line = linear_approximation([p1, p2, p3, p4]).most_similar_line() self.assert_sverchok_data_equal(tuple( line.direction), (0.7882054448127747, 0.6154122352600098, 0.0), precision=5)
def nurbs_curve_matrix(curve): cpts = curve.get_control_points() approx = linear_approximation(cpts) plane = approx.most_similar_plane() normal = plane.normal xx = cpts[-1] - cpts[0] xx /= np.linalg.norm(xx) yy = np.cross(normal, xx) matrix = np.stack((xx, yy, normal)).T return matrix
def nurbs_curve_to_xoy(curve, target_normal=None): cpts = curve.get_control_points() approx = linear_approximation(cpts) plane = approx.most_similar_plane() normal = plane.normal if target_normal is not None: a = np.dot(normal, target_normal) if a > 0: normal = -normal xx = cpts[-1] - cpts[0] xx /= np.linalg.norm(xx) yy = np.cross(normal, xx) matrix = np.stack((xx, yy, normal)).T matrix = np.linalg.inv(matrix) center = approx.center new_cpts = np.array([matrix @ (cpt - center) for cpt in cpts]) return curve.copy(control_points=new_cpts)
def do_iteration(bvh, bm): verts_out = [] face_centers = np.array([face.calc_center_median() for face in bm.faces]) for bm_vert in bm.verts: co = bm_vert.co if (skip_boundary and bm_vert.is_boundary) or (mask is not None and not mask[bm_vert.index]): new_vert = tuple(co) else: normal = bm_vert.normal cs = np.array([face_centers[face.index] for face in bm_vert.link_faces]) if method == NONE: new_vert = cs.mean(axis=0) elif method == NORMAL: median = mathutils.Vector(cs.mean(axis=0)) dv = median - co dv = dv - dv.project(normal) new_vert = co + dv elif method == LINEAR: approx = linear_approximation(cs) median = mathutils.Vector(approx.center) plane = approx.most_similar_plane() dist = plane.distance_to_point(bm_vert.co) new_vert = median + plane.normal.normalized() * dist elif method == BVH: median = mathutils.Vector(cs.mean(axis=0)) new_vert, normal, idx, dist = bvh.find_nearest(median) else: raise Exception("Unsupported volume preservation method") new_vert = tuple(new_vert) new_vert = mask_axes(tuple(co), new_vert, use_axes) verts_out.append(new_vert) return verts_out
def process(self): verts = self.inputs['Vertices'].sv_get() if self.inputs['PolyEdge'].is_linked: poly_edge = self.inputs['PolyEdge'].sv_get() poly_in = True else: poly_in = False poly_edge = repeat_last([[]]) verts_out = [] poly_edge_out = [] item_order = [] poly_output = poly_in and self.outputs['PolyEdge'].is_linked order_output = self.outputs['Item order'].is_linked vert_output = self.outputs['Vertices'].is_linked if not any((vert_output, order_output, poly_output)): return if self.mode == 'XYZ': # should be user settable op_order = [(0, self.reverse_x), (1, self.reverse_y), (2, self.reverse_z)] for v, p in zip(verts, poly_edge): s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) for item_index, rev in op_order: s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'AXYZ': for v, p in zip(verts, poly_edge): matrix = linear_approximation( v).most_similar_plane().get_matrix().inverted() s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): x, y, z = matrix @ Vector(item[:3]) if self.reverse_x: x = -x if self.reverse_y: y = -y if self.reverse_z: z = -z return x, y, z # def by_axis(i): # def key(item): # v = matrix @ Vector(item[:3]) # return v[i] # return key s_v = sorted(s_v, key=key) # for i in [2,1,0]: # s_v = sorted(s_v, key=by_axis(i)) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'ADIR': for v, p in zip(verts, poly_edge): direction = linear_approximation( v).most_similar_line().direction s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): return Vector(item[:3]).dot(direction) s_v = sorted(s_v, key=key) if self.reverse: s_v = reversed(s_v) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'ACYL': for v, p in zip(verts, poly_edge): data = linear_approximation(v) matrix = data.most_similar_plane().get_matrix().inverted() center = Vector(data.center) s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): v = matrix @ (Vector(item[:3]) - center) rho, phi, z = to_cylindrical(v) return (phi, z, rho) s_v = sorted(s_v, key=key) if self.reverse: s_v = reversed(s_v) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'DIST': base_points = self.inputs['Base Point'].sv_get() bp_iter = repeat_last(base_points[0]) for v, p, v_base in zip(verts, poly_edge, bp_iter): s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base)) verts_out.append([vert[0] for vert in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'AXIS': if self.inputs['Mat'].is_linked: mat = Matrix_generate(self.inputs['Mat'].sv_get()) else: mat = [Matrix.Identity(4)] mat_iter = repeat_last(mat) def f(axis, q): if axis.dot(q.axis) > 0: return q.angle else: return -q.angle for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter): axis = m @ Vector((0, 0, 1)) axis_norm = m @ Vector((1, 0, 0)) base_point = m @ Vector((0, 0, 0)) intersect_d = [ intersect_point_line(v_c, base_point, axis) for v_c in v ] rotate_d = [ f(axis, (axis_norm + v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d) ] s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d))) s_v = sorted(s_v, key=itemgetter(0, 1)) verts_out.append([v[i[-1]].to_tuple() for i in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'USER': if self.inputs['Index Data'].is_linked: index = self.inputs['Index Data'].sv_get() else: return for v, p, i in zip(verts, poly_edge, index): s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0)) verts_out.append([obj[1] for obj in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([[v_index[k] for k in pe] for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'CONNEX': if self.inputs['PolyEdge'].is_linked: edges = self.inputs['PolyEdge'].sv_get() for v, p in zip(verts, edges): pols = [] if len(p[0]) > 2: pols = [p[:]] p = polygons_to_edges([p], True)[0] vect_new, pol_edge_new, index_new = sort_vertices_by_connexions( v, p, self.limit_mode) if len(pols) > 0: new_pols = [] for pol in pols[0]: new_pol = [] for i in pol: new_pol.append(index_new.index(i)) new_pols.append(new_pol) pol_edge_new = [new_pols] verts_out.append(vect_new) poly_edge_out.append(pol_edge_new) item_order.append(index_new) if vert_output: self.outputs['Vertices'].sv_set(verts_out) if poly_output: self.outputs['PolyEdge'].sv_set(poly_edge_out) if order_output: self.outputs['Item order'].sv_set(item_order)
def calc_value(points): approx = linear_approximation(points) line = approx.most_similar_line() line_direction = np.array(line.direction) return abs(direction.dot(line_direction))