def make_section(self, apex, cone_dir, alpha, cone_gen, count, plane_center, plane_dir, maxd): apex = Vector(apex) cone_dir = Vector(cone_dir) plane_dir = Vector(plane_dir) cone_dir2 = cone_dir.orthogonal() if self.cone_mode == 'ANGLE': cone_vector = rotate_vector_around_vector(cone_dir, cone_dir2, alpha) else: cone_vector = Vector(cone_gen) theta = 2 * pi / count angle = 0 plane = PlaneEquation.from_normal_and_point(plane_dir, plane_center) cone_ort_plane = PlaneEquation.from_normal_and_point(cone_dir, apex) def get_branch(v): return cone_ort_plane.side_of_point(v) > 0 if plane.side_of_point(apex) == 0 or ( plane_dir.cross(cone_dir)).length < 1e-10: def get_side(v): return True else: apex_projection = plane.projection_of_point(apex) apex_ort = apex_projection - apex cone_sagital_plane = PlaneEquation.from_point_and_two_vectors( apex, apex_ort, cone_dir) def get_side(v): return cone_sagital_plane.side_of_point(v) > 0 vertices = [] branch_mask = [] side_mask = [] breaks = [] i = 0 while angle < 2 * pi: cone_line = LineEquation.from_direction_and_point( cone_vector, apex) vertex = plane.intersect_with_line(cone_line, min_det=1e-10) if vertex is not None and (vertex - apex).length <= maxd: vertices.append(tuple(vertex)) branch = get_branch(vertex) side = get_side(vertex) branch_mask.append(branch) side_mask.append(side) i += 1 else: breaks.append(i) cone_vector = rotate_vector_around_vector(cone_vector, cone_dir, theta) angle += theta return SectionData(vertices, branch_mask, side_mask, get_branch, get_side, breaks)
def test_intersect_with_plane(self): plane1 = PlaneEquation.from_coordinate_plane('XY') plane2 = PlaneEquation.from_coordinate_plane('XZ') line = plane1.intersect_with_plane(plane2) self.assert_sverchok_data_equal(tuple(line.direction.normalized()), (1, 0, 0)) self.assert_sverchok_data_equal(tuple(line.point), (0, 0, 0))
def _pre_calc(self): curve = self.curve t_min, t_max = curve.get_u_bounds() ts = np.linspace(t_min, t_max, num=self.resolution) points = curve.evaluate_array(ts) tangents, normals, binormals = curve.tangent_normal_binormal_array(ts) tangents /= np.linalg.norm(tangents, axis=1, keepdims=True) normal = normals[0] if np.linalg.norm(normal) > 1e-4: binormal = binormals[0] binormal /= np.linalg.norm(binormal) else: tangent = tangents[0] normal = Vector(tangent).orthogonal() normal = np.array(normal) binormal = np.cross(tangent, normal) binormal /= np.linalg.norm(binormal) out_normals = [normal] out_binormals = [binormal] for point, tangent in zip(points[1:], tangents[1:]): plane = PlaneEquation.from_normal_and_point(Vector(tangent), Vector(point)) normal = plane.projection_of_vector(Vector(point), Vector(point + normal)) normal = np.array(normal.normalized()) binormal = np.cross(tangent, normal) binormal /= np.linalg.norm(binormal) out_normals.append(normal) out_binormals.append(binormal) self.quats = self._make_quats(points, tangents, np.array(out_normals), np.array(out_binormals)) self.tknots = ts
def to_curve(point, curve, u1, u2, raycast=None): if support_nurbs and is_nurbs and raycast is not None: segment = curve.cut_segment(u1, u2) surface_u, surface_v = raycast.us[0], raycast.vs[0] point_on_surface = raycast.points[0] surface_normal = surface.normal(surface_u, surface_v) plane = PlaneEquation.from_normal_and_point( surface_normal, point_on_surface) r = intersect_curve_plane_nurbs(segment, plane, init_samples=2, tolerance=tolerance, maxiter=maxiter) if not r: return None else: return r[0] else: ortho = ortho_project_curve(point, curve, subdomain=(u1, u2), init_samples=2, on_fail=RETURN_NONE) if ortho is None: return None else: return ortho.nearest_u, ortho.nearest
def test_nearest_to_origin(self): p1 = (1, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 1) plane = PlaneEquation.from_three_points(p1, p2, p3) p = plane.nearest_point_to_origin() self.assert_sverchok_data_equal(tuple(p), (0.3333, 0.3333, 0.3333), precision=4)
def process(self): if not any(socket.is_linked for socket in self.outputs): return curves_s = self.inputs['Curve'].sv_get() point_s = self.inputs['Point'].sv_get() normal_s = self.inputs['Normal'].sv_get() curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve, )) points_out = [] for curves, points, normals in zip_long_repeat( curves_s, point_s, normal_s): new_points = [] for curve, point, normal in zip_long_repeat( curves, points, normals): plane = PlaneEquation.from_normal_and_point(normal, point) ps = intersect_curve_plane(curve, plane, init_samples=self.samples, ortho_samples=self.samples) new_points.extend(ps) points_out.append(new_points) self.outputs['Point'].sv_set(points_out)
def test_projection_2(self): p1 = (1, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 1) plane = PlaneEquation.from_three_points(p1, p2, p3) point = (3, 3, 3) result = plane.projection_of_point(point) self.assert_sverchok_data_equal(tuple(result), (0.3333, 0.3333, 0.3333), precision=4)
def _faces_by_plane(self, topo, center, direction, radius): plane = PlaneEquation.from_normal_and_point(direction, center) def condition(points): distances = plane.distance_to_points(points) return distances < radius return topo.get_faces_by_location_mask(condition, self.include_partial)
def __init__(self, curve, point, normal, coefficient): self.curve = curve self.point = point self.normal = normal self.coefficient = coefficient self.plane = PlaneEquation.from_normal_and_point(normal, point) self.tangent_delta = 0.001 self.__description__ = "{} casted to Plane".format(curve)
def test_plane_from_three_points(self): p1 = (1, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 1) plane = PlaneEquation.from_three_points(p1, p2, p3) self.assertEquals(plane.a, 1) self.assertEquals(plane.b, 1) self.assertEquals(plane.c, 1) self.assertEquals(plane.d, -1)
def test_projection_3(self): plane = PlaneEquation.from_coordinate_plane('XY') point1 = (1, 2, 3) point2 = (4, 5, 6) point3 = (7, 8, 9) point4 = (2, 5, 9) result = plane.projection_of_points([point1, point2, point3, point4]) expected = np.array([[1, 2, 0], [4, 5, 0], [7, 8, 0], [2, 5, 0]]) self.assert_numpy_arrays_equal(result, expected)
def test_two_vectors(self): p1 = (2, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 2) plane = PlaneEquation.from_three_points(p1, p2, p3) normal = plane.normal v1, v2 = plane.two_vectors() self.assertTrue(abs(normal.dot(v1)) < 1e-8) self.assertTrue(abs(normal.dot(v2)) < 1e-8) self.assertTrue(abs(v1.dot(v2)) < 1e-8)
def get_ridges_per_site(voronoi): result = defaultdict(list) for ridge_idx in range(len(voronoi.ridge_points)): site1_idx, site2_idx = tuple(voronoi.ridge_points[ridge_idx]) site1 = voronoi.points[site1_idx] site2 = voronoi.points[site2_idx] middle = (site1 + site2) * 0.5 normal = site2 - site1 plane = PlaneEquation.from_normal_and_point(normal, middle) result[site1_idx].append(plane) result[site2_idx].append(plane) return result
def test_projection_4(self): p1 = (1, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 1) plane = PlaneEquation.from_three_points(p1, p2, p3) point1 = (-3, -3, -3) point2 = (2, 1, 1) point3 = (1, 1, 2) point4 = (1, 2, 1) result = plane.projection_of_points([point1, point2, point3, point4]) expected = np.array([[0.3333, 0.3333, 0.3333], [1,0,0], [0, 0, 1], [0, 1, 0]]) info(result) self.assert_numpy_arrays_equal(result, expected, precision=4)
def test_projection_4(self): p1 = (1, 0, 0) p2 = (0, 1, 0) p3 = (0, 0, 1) plane = PlaneEquation.from_three_points(p1, p2, p3) point1 = (-3, -3, -3) point2 = (2, 1, 1) point3 = (1, 1, 2) point4 = (1, 2, 1) result = plane.projection_of_points([point1, point2, point3, point4]) expected = np.array([[0.3333, 0.3333, 0.3333], [1, 0, 0], [0, 0, 1], [0, 1, 0]]) info(result) self.assert_numpy_arrays_equal(result, expected, precision=4)
def process(self): if not any(socket.is_linked for socket in self.outputs): return curves_s = self.inputs['Curve'].sv_get() point_s = self.inputs['Point'].sv_get() normal_s = self.inputs['Normal'].sv_get() curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve, )) points_out = [] t_out = [] tolerance = 10**(-self.accuracy) for curves, points, normals in zip_long_repeat( curves_s, point_s, normal_s): new_points = [] new_ts = [] for curve, point, normal in zip_long_repeat( curves, points, normals): method = EQUATION if self.use_nurbs: c = SvNurbsCurve.to_nurbs(curve) if c is not None: curve = c method = NURBS plane = PlaneEquation.from_normal_and_point(normal, point) ps = intersect_curve_plane(curve, plane, method=method, init_samples=self.samples, tolerance=tolerance) ts = [p[0] for p in ps] points = [p[1].tolist() for p in ps] if self.join: new_points.extend(points) new_ts.extend(ts) else: new_points.append(points) new_ts.append(ts) points_out.append(new_points) t_out.append(new_ts) self.outputs['Point'].sv_set(points_out) self.outputs['T'].sv_set(t_out)
def _cast_nurbs(self, curve, center, direction, radius, coeff): curve = SvNurbsCurve.to_nurbs(curve) if curve is None: raise Exception("Provided curve is not a NURBS") if self.form == 'PLANE': target = PlaneEquation.from_normal_and_point(direction, center) elif self.form == 'SPHERE': target = SphereEquation(center, radius) elif self.form == 'CYLINDER': target = CylinderEquation.from_point_direction_radius(center, direction, radius) else: raise Exception("Unsupported target form") return cast_nurbs_curve(curve, target, coeff=coeff)
def process(self): if not any(socket.is_linked for socket in self.outputs): return surfaces_s = self.inputs['Surface'].sv_get() point_s = self.inputs['Point'].sv_get() normal_s = self.inputs['Normal'].sv_get() samples_u_s = self.inputs['SamplesU'].sv_get() samples_v_s = self.inputs['SamplesV'].sv_get() surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface, )) need_points = self.outputs['Points'].is_linked uv_out = [] points_out = [] for surfaces, points, normals, samples_u_i, samples_v_i in zip_long_repeat( surfaces_s, point_s, normal_s, samples_u_s, samples_v_s): uv_new = [] points_new = [] for surface, point, normal, samples_u, samples_v in zip_long_repeat( surfaces, points, normals, samples_u_i, samples_v_i): plane = PlaneEquation.from_normal_and_point(normal, point) if self.algorithm == 'skimage': uv_new, points_new = intersect_surface_plane_msquares( surface, plane, need_points=need_points, samples_u=samples_u, samples_v=samples_v) else: points_new = intersect_surface_plane_uv( surface, plane, samples_u=samples_u, samples_v=samples_v, init_samples=self.init_samples, ortho_samples=self.init_samples) points_new = [points_new] uv_out.extend(uv_new) points_out.extend(points_new) self.outputs['Points'].sv_set(points_out) self.outputs['UVPoints'].sv_set(uv_out)
def cut_cell(verts, faces, planes, site): src_mesh = bmesh_from_pydata(verts, [], faces, normal_update=True) n_cuts = 0 for plane in planes: if len(src_mesh.verts) == 0: break geom_in = src_mesh.verts[:] + src_mesh.edges[:] + src_mesh.faces[:] plane_co = plane.projection_of_point(site) plane_no = plane.normal.normalized() if plane.side_of_point(site) > 0: plane_no = -plane_no plane_co = plane_co - 0.5 * spacing * plane_no current_verts = np.array([tuple(v.co) for v in src_mesh.verts]) signs = PlaneEquation.from_normal_and_point( plane_no, plane_co).side_of_points(current_verts) #print(f"Plane co {plane_co}, no {plane_no}, signs {signs}") if (signs <= 0).all(): # or (signs <= 0).all(): continue res = bmesh.ops.bisect_plane(src_mesh, geom=geom_in, dist=precision, plane_co=plane_co, plane_no=plane_no, use_snap_center=False, clear_outer=True, clear_inner=False) n_cuts += 1 if fill: surround = [ e for e in res['geom_cut'] if isinstance(e, bmesh.types.BMEdge) ] if surround: fres = bmesh.ops.edgenet_prepare(src_mesh, edges=surround) if fres['edges']: bmesh.ops.edgeloop_fill(src_mesh, edges=fres['edges']) if n_cuts == 0: return None return pydata_from_bmesh(src_mesh)
def matrix_to_curve(curve, matrix, z_axis, init_samples=10, tolerance=1e-3, maxiter=50): plane = PlaneEquation.from_matrix(matrix, normal_axis=z_axis) # Or take nearest point? solutions = intersect_curve_plane(curve, plane, init_samples=init_samples, tolerance=tolerance, maxiter=maxiter) t, point = nearest_solution(matrix.translation, solutions) if t is None: raise Exception( f"Can't project the matrix {matrix} to the {curve}!") #matrix.translation = Vector(point) return t, matrix.to_quaternion()
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() edges_s = self.inputs['Edges'].sv_get() faces_s = self.inputs['Faces'].sv_get() vertex_weight_s = self.inputs['VertexWeight'].sv_get() edge_weight_s = self.inputs['EdgeWeight'].sv_get() face_weight_s = self.inputs['FaceWeight'].sv_get() tangent_weight_s = self.inputs['TangentWeight'].sv_get() degree_u_s = self.inputs['DegreeU'].sv_get() degree_v_s = self.inputs['DegreeV'].sv_get() surface_out = [] control_points_out = [] weights_out = [] inputs = zip_long_repeat(vertices_s, edges_s, faces_s, degree_u_s, degree_v_s, vertex_weight_s, edge_weight_s, face_weight_s, tangent_weight_s) for vertices, edges, faces, degree_u, degree_v, vertex_weights, edge_weights, face_weights, tangent_weights in inputs: fullList(degree_u, len(faces)) fullList(degree_v, len(faces)) if not edges: edges = polygons_to_edges([faces], True)[0] fullList(vertex_weights, len(vertices)) fullList(tangent_weights, len(vertices)) fullList(edge_weights, len(edges)) fullList(face_weights, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_edge_data=True) normals = [vertex.normal for vertex in bm.verts] edge_planes_dict = dict() for edge in bm.edges: edge_v = edge.verts[1].co - edge.verts[0].co edge_c = (edge.verts[0].co + edge.verts[1].co) / 2.0 edge_ort_plane = PlaneEquation.from_normal_and_point( edge_v, edge_c) face_normals = [face.normal for face in edge.link_faces] faces_normal = sum(face_normals, Vector()) projected_faces_normal = edge_ort_plane.projection_of_point( faces_normal) #print("EV: %s, No.sum: %s, Pr.N: %s" % (edge_v, faces_normal, projected_faces_normal)) edge_plane = PlaneEquation.from_normal_and_point( projected_faces_normal, edge_c) edge_planes_dict[(edge.verts[0].index, edge.verts[1].index)] = edge_plane edge_planes_dict[(edge.verts[1].index, edge.verts[0].index)] = edge_plane bm.free() vert_planes = [ PlaneEquation.from_normal_and_point(normal, point) for normal, point in zip(normals, vertices) ] edge_weights_dict = dict() #edge_planes_dict = dict() for (i, j), edge_weight in zip(edges, edge_weights): edge_weights_dict[(i, j)] = edge_weight edge_weights_dict[(j, i)] = edge_weight #edge_planes_dict[(i, j)] = edge_plane #edge_planes_dict[(j, i)] = edge_plane for i, (face, degree_u, degree_v, face_weight) in enumerate( zip(faces, degree_u, degree_v, face_weights)): if len(face) != 4: self.info("Face #%s is not a Quad, skip it", i) continue face_verts = [vertices[i] for i in face] face_planes = [vert_planes[i] for i in face] face_vert_weights = [vertex_weights[i] for i in face] face_tangent_weights = [tangent_weights[i] for i in face] #face_edges = list(zip(face, face[1:])) + [(face[-1], face[0])] #face_edge_weights = [edge_weights_dict[edge] for edge in face_edges] surface, ctrlpts, weights = self.make_surface( face, degree_u, degree_v, face_verts, face_planes, face_vert_weights, face_tangent_weights, face_weight, edge_weights_dict, edge_planes_dict) surface_out.append(surface) control_points_out.append(list(map(tuple, ctrlpts))) weights_out.append(weights) self.outputs['Surfaces'].sv_set(surface_out) self.outputs['ControlPoints'].sv_set(control_points_out) self.outputs['Weights'].sv_set(weights_out)
def _verts_by_plane(self, topo, center, direction, radius): plane = PlaneEquation.from_normal_and_point(direction, center) condition = lambda v: plane.distance_to_point(v) < radius return topo.get_vertices_by_location_mask(condition)
def test_projection_1(self): plane = PlaneEquation.from_coordinate_plane('XY') point = (1, 2, 3) result = plane.projection_of_point(point) self.assert_sverchok_data_equal(tuple(result), (1, 2, 0))
def test_intersect_with_line(self): plane = PlaneEquation.from_coordinate_plane('XY') line = LineEquation.from_direction_and_point((1, 1, 1), (1, 1, 1)) point = plane.intersect_with_line(line) self.assert_sverchok_data_equal(tuple(point), (0, 0, 0))
def test_check_no(self): plane = PlaneEquation.from_coordinate_plane('XY') p = (7, 8, 1) self.assertFalse(plane.check(p))
def test_check_yes(self): plane = PlaneEquation.from_coordinate_plane('XY') p = (7, 8, 0) self.assertTrue(plane.check(p))
def test_distance_to_points(self): plane = PlaneEquation.from_coordinate_plane('XY') points = [(1, 2, 3), (4, 5, 6)] distances = plane.distance_to_points(points) self.assert_numpy_arrays_equal(distances, np.array([3, 6]))
def test_distance_to_point(self): plane = PlaneEquation.from_coordinate_plane('XY') point = (1, 2, 3) distance = plane.distance_to_point(point) self.assertEquals(distance, 3)