def test_project_point_to_plane_validation(): with pytest.raises( ValueError, match= r"Expected points to be an array with shape \(3,\) or \(-1, 3\); got \(1, 1, 1\)", ): project_point_to_plane( points=np.array([[[1.0]]]), plane_equations=Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, ) with pytest.raises( ValueError, match= r"^Expected plane_equations to be an array with shape \(4,\) or \(3, 4\); got \(2, 4\)$", ): project_point_to_plane( points=np.array([vg.basis.x, vg.basis.x, vg.basis.x]), plane_equations=np.array([ Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, ]), )
def test_project_point_to_plane_vectorized_both(): np.testing.assert_array_equal( project_point_to_plane( points=np.array([[10, 20, -5], [10, 30, -5]]), plane_equations=np.array([ Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, ]), ), np.array([[10, 10, -5], [10, 10, -5]]), )
def test_mirror_point_across_plane_vectorized_points(): np.testing.assert_array_equal( mirror_point_across_plane( points=np.array([[10, 20, -5], [2, 7, 203]]), plane_equations=Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, ), np.array([[10, 0, -5], [2, 13, 203]]), )
def test_project_point_to_plane(): np.testing.assert_array_equal( project_point_to_plane( points=np.array([10, 20, -5]), plane_equations=Plane(point_on_plane=np.array([0, 10, 0]), unit_normal=vg.basis.y).equation, ), np.array([10, 10, -5]), )
def test_vertices_on_or_in_front_of_plane(): assert_subcube( submesh=cube_at_origin.keeping_vertices_on_or_in_front_of_plane( Plane(np.array([1.0, 1.0, 1.0]), vg.basis.z)), expected_vertex_indices=[2, 3, 6, 7], expected_face_indices=[8, 9], ) assert_subcube( submesh=cube_at_origin.keeping_vertices_on_or_in_front_of_plane( Plane(np.array([1.0, 1.0, 3.0]), vg.basis.z)), expected_vertex_indices=[2, 3, 6, 7], expected_face_indices=[8, 9], ) assert_subcube( submesh=cube_at_origin.keeping_vertices_on_or_in_front_of_plane( Plane(np.array([1.0, 1.0, -1.0]), vg.basis.z)), expected_vertex_indices=range(8), expected_face_indices=range(12), )
def test_vertices_behind_plane(): assert_subcube( submesh=cube_at_origin.keeping_vertices_behind_plane( Plane(np.array([1.0, 1.0, 1.0]), vg.basis.z)), expected_vertex_indices=[0, 1, 4, 5], expected_face_indices=[4, 5], ) assert_subcube( submesh=cube_at_origin.keeping_vertices_behind_plane( Plane(np.array([1.0, 1.0, 0.0]), vg.basis.z)), expected_vertex_indices=[], expected_face_indices=[], ) assert_subcube( submesh=cube_at_origin.keeping_vertices_behind_plane( Plane(np.array([1.0, 1.0, 4.0]), vg.basis.z)), expected_vertex_indices=range(8), expected_face_indices=range(12), )
def test_render_longest_xsection_to_svg(): mesh = lacecore.load_obj( "examples/vitra/vitra_without_materials.obj", triangulate=True ) plane = Plane( point_on_plane=np.array([-0.869231, 60.8882, -20.1071]), unit_normal=vg.normalize(np.array([0.0, 0.1, -1.0])), ) xs = render_longest_xsection_to_svg( mesh=mesh, plane=plane, filename="vitra_cross_section.svg" ) Scene().add_meshes(mesh).add_lines(xs).write("vitra_with_cross_section.dae")
def test_signed_distances_for_diagonal_plane(): np.testing.assert_array_almost_equal( signed_distance_to_plane( points=np.array([[425.0, 425.0, 25.0], [-500.0, -500.0, 25.0]]), # Diagonal plane @ origin - draw a picture! plane_equations=Plane( point_on_plane=np.array([1.0, 1.0, 0.0]), unit_normal=vg.normalize(np.array([1.0, 1.0, 0.0])), ).equation, ), np.array([ math.sqrt(2 * (425.0 - 1.0)**2), -math.sqrt(2 * (500.0 + 1.0)**2) ]), )
def main(): # from hobart.svg import write_polyline_3d import numpy as np from polliwog import Plane import vg from .inflection_points import point_of_max_acceleration from entente.landmarks._mesh import add_landmark_points np.set_printoptions(suppress=False) mesh = load_front_torso_mesh() mid_bust = np.average(mesh.v, axis=0) mid_bust[2] = np.amin(mesh.v[:, 2]) + 3.0 # to_left = vg.basis.x # to_center = vg.basis.z result_points = [] # plot = True for i, x_coord in enumerate(np.linspace(-15.0, 15.0, num=20)): # for i, ratio in enumerate(np.linspace(0.0, 1.0, num=20)): # if i != 12: # continue # mid_bust_to_bust_line = ratio * to_center + (1 - ratio) * to_left # cut_plane = Plane(mid_bust, vg.perpendicular(mid_bust_to_bust_line, vg.basis.y)) cut_plane = Plane(np.array([x_coord, 0.0, 0.0]), vg.basis.x) xss = mesh.intersect_plane(cut_plane) longest_xs = next(reversed(sorted( xss, key=lambda xs: xs.total_length))).aligned_with(vg.basis.neg_y) # axis = vg.normalize(np.array([0.0, -0.15, 1.0])) try: result = point_of_max_acceleration( # longest_xs.v, axis, vg.perpendicular(axis, vg.basis.x), span_spacing=0.001 longest_xs.v, vg.basis.z, vg.basis.y, subdivide_by_length=0.001, ) result_points.append(result) except ValueError: pass add_landmark_points(mesh, result_points) mesh.write("with_inflection.dae")
def horizontal_xs(mesh_path, heights, out, reference): """ Find the horizontal cross section at the given height and write it to an SVG file. Optionally write a COLLADA reference with the mesh and cross section. """ import os import lacecore import numpy as np from polliwog import Plane from tri_again import Scene import vg from .core import render_longest_xsection_to_svg if reference and not reference.endswith(".dae"): raise ValueError("reference-mesh should end with .dae") mesh = lacecore.load_obj(mesh_path, triangulate=True) reference_lines = [] for height in heights: if out is None: filename, extension = os.path.splitext(os.path.basename(mesh_path)) out_path = "{}_cross_section_at_{}.svg".format(filename, height) plane = Plane(point_on_plane=np.array([0.0, height, 0.0]), unit_normal=vg.basis.neg_y) xs = render_longest_xsection_to_svg(mesh=mesh, plane=plane, filename=out or out_path) reference_lines.append(xs) if reference: Scene().add_meshes(mesh).add_lines(*reference_lines).write(reference)
import numpy as np from polliwog import Plane import pytest from vg.compat import v2 as vg from ._slice_by_plane import slice_open_polyline_by_plane point_on_plane = np.array([1.0, 2.0, 3.0]) plane_normal = vg.normalize(np.array([3.0, 4.0, 5.0])) plane = Plane(point_on_plane=point_on_plane, unit_normal=plane_normal) def rand_nonzero(*shape): return 128 * np.random.rand(*shape) + 1e-6 def vertices_with_signs(signs): num_verts = len(signs) random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3)) random_displacement_along_normal = ( rand_nonzero(num_verts).reshape(-1, 1) * plane_normal) vertices = (random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal) # Because of rounding, the random points don't necessarily return 0 for # sign, so pick one that does. vertices[signs == 0] = plane.reference_point np.testing.assert_array_equal(plane.sign(vertices), signs) return vertices def intersect_segment_with_plane(p1, p2): from ..plane import intersect_segment_with_plane as _intersect_segment_with_plane