def cutting_plane(mesh, ry=10, rz=-50): plane = Plane(mesh.centroid(), Vector(1, 0, 0)) Ry = Rotation.from_axis_and_angle(Vector(0, 1, 0), radians(ry), plane.point) Rz = Rotation.from_axis_and_angle(Vector(0, 0, 1), radians(rz), plane.point) plane.transform(Rz * Ry) return plane
def test_from_euler_angles(): ea1 = 1.4, 0.5, 2.3 args = False, 'xyz' R1 = Rotation.from_euler_angles(ea1, *args) ea2 = R1.euler_angles(*args) assert allclose(ea1, ea2) alpha, beta, gamma = ea1 xaxis, yaxis, zaxis = [1, 0, 0], [0, 1, 0], [0, 0, 1] Rx = Rotation.from_axis_and_angle(xaxis, alpha) Ry = Rotation.from_axis_and_angle(yaxis, beta) Rz = Rotation.from_axis_and_angle(zaxis, gamma) R2 = Rx * Ry * Rz assert np.allclose(R1, R2)
def draw(network, point, vector, s, step, last_node=None): for i, c in enumerate(s): if c == 'A': point = point + vector * step a = network.add_node(x=point.x, y=point.y, z=point.z) if last_node: network.add_edge(last_node, a) last_node = a elif c == '-': R = Rotation.from_axis_and_angle((0, 0, 1), math.radians(60)) vector.transform(R) elif c == '+': R = Rotation.from_axis_and_angle((0, 0, 1), math.radians(-60)) vector.transform(R)
def test_axis_and_angle(): axis1 = normalize_vector([-0.043, -0.254, 0.617]) angle1 = 0.1 R = Rotation.from_axis_and_angle(axis1, angle1) axis2, angle2 = R.axis_and_angle assert allclose(axis1, axis2) assert allclose([angle1], [angle2])
def test_remeshing(): FILE = os.path.join(HERE, '../..', 'data', 'Bunny.ply') # ============================================================================== # Get the bunny and construct a mesh # ============================================================================== bunny = TriMesh.from_ply(FILE) bunny.cull_vertices() # ============================================================================== # Move the bunny to the origin and rotate it upright. # ============================================================================== vector = scale_vector(bunny.centroid, -1) T = Translation.from_vector(vector) S = Scale.from_factors([100, 100, 100]) R = Rotation.from_axis_and_angle(Vector(1, 0, 0), math.radians(90)) bunny.transform(R * S * T) # ============================================================================== # Remesh # ============================================================================== length = bunny.average_edge_length bunny.remesh(4 * length) bunny.to_mesh()
def calculate(FILE_IN, plot_flag): for file in FILE_IN: #print("Calculating",file) assembly = Assembly.from_json(file) # ============================================================================== # Identify interfaces # ============================================================================== assembly_interfaces_numpy(assembly, tmax=0.02) # ============================================================================== # Equilibrium # ============================================================================== compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=False) #compute_interface_forces_cvx(assembly, solver='ECOS', verbose=True) # ============================================================================== # Export # ============================================================================== assembly.to_json(output_path(file)) if plot_flag: R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2) assembly.transform(R) plotter = AssemblyPlotter(assembly, figsize=(16, 10), tight=True) plotter.draw_nodes(radius=0.05) plotter.draw_edges() plotter.draw_blocks( facecolor={ key: '#ff0000' for key in assembly.nodes_where({'is_support': True}) }) plotter.show()
def blocks(self): """Compute the blocks. Returns ------- list A list of blocks defined as simple meshes. Notes ----- This method is used by the ``from_geometry`` constructor of the assembly data structure to create an assembly "from geometry". """ if self.rise > self.span / 2: raise Exception("Not a semicircular arch.") radius = self.rise / 2 + self.span**2 / (8 * self.rise) # base = [0.0, 0.0, 0.0] top = [0.0, 0.0, self.rise] left = [-self.span / 2, 0.0, 0.0] center = [0.0, 0.0, self.rise - radius] vector = subtract_vectors(left, center) springing = angle_vectors(vector, [-1.0, 0.0, 0.0]) sector = radians(180) - 2 * springing angle = sector / self.n a = top b = add_vectors(top, [0, self.depth, 0]) c = add_vectors(top, [0, self.depth, self.thickness]) d = add_vectors(top, [0, 0, self.thickness]) R = Rotation.from_axis_and_angle([0, 1.0, 0], 0.5 * sector, center) bottom = transform_points([a, b, c, d], R) blocks = [] for i in range(self.n): R = Rotation.from_axis_and_angle([0, 1.0, 0], -angle, center) top = transform_points(bottom, R) vertices = bottom + top faces = [[0, 1, 2, 3], [7, 6, 5, 4], [3, 7, 4, 0], [6, 2, 1, 5], [7, 3, 2, 6], [5, 1, 0, 4]] mesh = Mesh.from_vertices_and_faces(vertices, faces) blocks.append(mesh) bottom = top return blocks
def __iter__(self): yield self.axis alphas = arange(self.max_alpha / self.step, self.max_alpha + self.max_alpha / self.step, self.max_alpha / self.step) radii = [math.sin(alpha) for alpha in alphas] x, y = math.cos(alphas[0]), math.sin(alphas[0]) d = math.sqrt((1 - x)**2 + y**2) # get any vector normal to axis axis2 = Frame.from_plane(Plane((0, 0, 0), self.axis)).xaxis for alpha, r in zip(alphas, radii): R1 = Rotation.from_axis_and_angle(axis2, alpha) amount = int(round(2 * math.pi * r / d)) betas = arange(0, 2 * math.pi, 2 * math.pi / amount) for beta in betas: R2 = Rotation.from_axis_and_angle(self.axis, beta) yield self.axis.transformed(R2 * R1)
def test___str__(): s = '[[ 0.9345, -0.0798, 0.3469, -0.8157],\n' + \ ' [ -0.1624, 0.7716, 0.6150, -1.2258],\n' + \ ' [ -0.3168, -0.6311, 0.7081, 2.4546],\n' + \ ' [ 0.0000, 0.0000, 0.0000, 1.0000]]\n' trans = [1, 2, 3] axes = [-2.142, 1.141, -0.142] angle = 0.7854 R = Rotation.from_axis_and_angle(axes, angle, point=trans) assert s == str(R)
def calculate_continous_transformation(self, position): """Returns a transformation of a continous joint. A continous joint rotates about the axis and has no upper and lower limits. Args: position (float): the angle in radians """ return Rotation.from_axis_and_angle(self.axis.vector, position, self.origin.point)
def gluepath_creator(int_surf, path_width): def interval_checker(dimension): underflow = dimension % path_width if underflow > 0.2: no_paths = dimension // path_width + 1 new_path_width = dimension / no_paths return new_path_width else: return path_width wid_gap = int_surf[1] - int_surf[0] wid_vec = Vector(wid_gap[0], wid_gap[1], wid_gap[2]) wid = wid_vec.length wid_vec.unitize() len_gap = int_surf[2] - int_surf[1] len_vec = Vector(len_gap[0], len_gap[1], len_gap[2]) len = len_vec.length len_vec.unitize() wid_path = interval_checker(wid) len_path = interval_checker(len) path_dims = [wid_path, len_path] path_points = [] iteration = 0 path_unfinished = True current_pt = int_surf[0] + scale_vector( wid_vec, wid_path / 2) + scale_vector(len_vec, len_path / 2) current_vec = len_vec.unitized() len_left = len - len_path wid_left = wid - wid_path dims_left = [len_left, wid_left] path_points.append(current_pt) R = Rotation.from_axis_and_angle([0, 0, 1], -math.pi / 2) while path_unfinished: current_index = iteration % 2 current_dim = dims_left[current_index] if iteration > 2: current_dim -= path_dims[current_index] dims_left[current_index] = current_dim if current_dim < path_width * 0.95: break current_pt = current_pt + scale_vector(current_vec, current_dim) path_points.append(current_pt) current_vec.transform(R) current_vec.unitize() iteration += 1 if not is_point_in_polygon_xy(current_pt, int_surf): print("Error: Point not in polygon") return path_points
def __iter__(self): if self.start_vector: # correct start_vector self.start_vector = (self.axis.cross( self.start_vector.unitized())).cross(self.axis) for alpha in arange(0, 2 * math.pi, self.angle_step): R = Rotation.from_axis_and_angle(self.axis, alpha) yield self.start_vector.transformed(R) else: f = Frame.from_plane(Plane((0, 0, 0), self.axis)) for alpha in arange(0, 2 * math.pi, self.angle_step): x = math.cos(alpha) y = math.sin(alpha) yield f.to_world_coordinates(Vector(x, y, 0))
def calculate_continuous_transformation(self, position): """Returns a transformation of a continuous joint. A continuous joint rotates about the axis and has no upper and lower limits. Parameters ---------- position : :obj:`float` Angle in radians Returns ------- :class:`Rotation` Transformation of type rotation for the continuous joint. """ return Rotation.from_axis_and_angle(self.current_axis.vector, position, self.current_origin.point)
def get_forward_transformations(self, configuration): """Calculate the transformations according to the configuration. Args: configuration (:class:`Configuration`): The robot's configuration. Returns: transformations (:obj:`list` of :class:`Transformation`): The transformations for each link. """ q0, q1, q2, q3, q4, q5 = configuration.values j0, j1, j2, j3, j4, j5 = self.j0, self.j1, self.j2, self.j3, self.j4, self.j5 T0 = Rotation.from_axis_and_angle(subtract_vectors(j0[1], j0[0]), q0, j0[1]) j1 = transform_points(j1, T0) T1 = Rotation.from_axis_and_angle(subtract_vectors(j1[1], j1[0]), q1, j1[1]) * T0 j2 = transform_points(j2, T1) T2 = Rotation.from_axis_and_angle(subtract_vectors(j2[1], j2[0]), q2, j2[1]) * T1 j3 = transform_points(j3, T2) T3 = Rotation.from_axis_and_angle(subtract_vectors(j3[1], j3[0]), q3, j3[1]) * T2 j4 = transform_points(j4, T3) T4 = Rotation.from_axis_and_angle(subtract_vectors(j4[1], j4[0]), q4, j4[1]) * T3 j5 = transform_points(j5, T4) T5 = Rotation.from_axis_and_angle(subtract_vectors(j5[1], j5[0]), q5, j5[1]) * T4 # now apply the transformation to the base T0 = self.transformation_WCS_RCS * T0 T1 = self.transformation_WCS_RCS * T1 T2 = self.transformation_WCS_RCS * T2 T3 = self.transformation_WCS_RCS * T3 T4 = self.transformation_WCS_RCS * T4 T5 = self.transformation_WCS_RCS * T5 return T0, T1, T2, T3, T4, T5
# ============================================================================== # Load assembly from file # ============================================================================== assembly = Assembly.from_json(FILE_I) # ============================================================================== # Identify interfaces # ============================================================================== assembly_interfaces_numpy(assembly, tmax=0.05) # ============================================================================== # Export # ============================================================================== assembly.to_json(FILE_O) # ============================================================================== # Visualize # ============================================================================== R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2, [0, 0, 0]) assembly.transform(R) plotter = AssemblyPlotter(assembly, figsize=(16, 10), tight=True) plotter.draw_nodes(radius=0.05) plotter.draw_edges() plotter.draw_blocks(facecolor={key: '#ff0000' for key in assembly.nodes_where({'is_support': True})}) plotter.show()
from math import radians from compas.geometry import Pointcloud from compas.geometry import Rotation from compas.geometry import Translation from compas.geometry import Frame from compas.geometry import Point, Vector, Line from compas.geometry import closest_point_on_line from compas.rpc import Proxy import compas_rhino from compas_rhino.artists import PointArtist from compas_rhino.artists import FrameArtist from compas_rhino.artists import LineArtist numerical = Proxy('compas.numerical') pcl = Pointcloud.from_bounds(10, 5, 3, 100) Rz = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], radians(60)) Ry = Rotation.from_axis_and_angle([0.0, 1.0, 0.0], radians(20)) Rx = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], radians(10)) T = Translation.from_vector([2.0, 5.0, 8.0]) pcl.transform(T * Rz * Ry * Rx) PointArtist.draw_collection(pcl, layer="ITA20::PCL", clear=True)
if __name__ == "__main__": from compas.geometry import Translation from compas.geometry import Rotation point = RhinoPoint.from_selection() # point = RhinoPoint.from_geometry(Point3d(0, 0, 0)) # point = RhinoPoint.from_geometry(Point(0, 0, 0)) print(point.guid) print(point.object) print(point.geometry) print(point.type) print(point.name) print(point.xyz) p = point.to_compas() print(p) T = Translation([1.0, 1.0, 0.0]) R = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], 0.5 * 3.14159) X = R * T point.transform(X) p = point.to_compas() print(p)
from math import sqrt import compas from compas.datastructures import Mesh from compas.geometry import Rotation from compas.geometry import Translation from compas.geometry import distance_point_point_xy from compas_plotters import MeshPlotter mesh = Mesh.from_polyhedron(6) origin = [0.0, 0.0, 0.0] corner = mesh.vertex_attributes(mesh.get_any_vertex(), 'xyz') d = distance_point_point_xy(origin, corner) R = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], radians(45)) T = Translation([d, d, 0.0]) X = T * R mesh.transform(X) mesh.add_vertex(x=0.0, y=0.0) plotter = MeshPlotter(mesh, figsize=(8, 5)) plotter.draw_vertices() plotter.draw_edges() plotter.draw_faces() plotter.show()
def test___repr__(): trans = [1, 2, 3] axes = [-2.142, 1.141, -0.142] angle = 0.7854 R = Rotation.from_axis_and_angle(axes, angle, point=trans) assert R == eval(repr(R))
def R(): return Rotation.from_axis_and_angle([0, 1, 0], radians(-90))
return network_copy # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from math import pi from compas.utilities import print_profile from compas.geometry import Box from compas.geometry import matrix_from_translation from compas.geometry import Translation from compas.geometry import Rotation from compas.datastructures import network network_transform = print_profile(network_transform) box = Box.from_corner_corner_height([0.0, 0.0, 0.0], [1.0, 1.0, 0.0], 1.0) network = network.from_vertices_and_faces(box.vertices, box.faces) T = matrix_from_translation([-2.0, 0.0, 3.0]) T = Translation([-2.0, 0.0, 3.0]) R = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], pi / 2) network_transform(network, R) print(network.get_vertices_attribute('x'))
"""Example: Decompose transformations """ from compas.geometry import Translation from compas.geometry import Rotation from compas.geometry import Scale scale_factors = [0.1, 0.3, 0.4] A = Scale.from_factors(scale_factors) # create Scale axis, angle = [-0.8, 0.35, 0.5], 2.2 B = Rotation.from_axis_and_angle(axis, angle) # create Rotation translation = [1, 2, 3] C = Translation.from_vector(translation) # create Translation # Concatenate transformations M = C * B * A # A matrix can also be decomposed into its components of Scale, # Shear, Rotation, Translation and Perspective Sc, Sh, R, T, P = M.decomposed() # Check, must be all `True` print(A == Sc) print(B == R) print(C == T) print(P * T * R * Sh * Sc == M)
"""Transformation examples """ from compas.geometry import Rotation from compas.geometry import Translation from compas.geometry import Scale from compas.geometry import Reflection from compas.geometry import Projection from compas.geometry import Shear axis, angle = [0.2, 0.4, 0.1], 0.3 R = Rotation.from_axis_and_angle(axis, angle) print("Rotation:\n", R) translation_vector = [5, 3, 1] T = Translation(translation_vector) print("Translation:\n", T) scale_factors = [0.1, 0.3, 0.4] S = Scale(scale_factors) print("Scale:\n", S) point, normal = [0.3, 0.2, 1], [0.3, 0.1, 1] R = Reflection(point, normal) print("Reflection:\n", R) point, normal = [0, 0, 0], [0, 0, 1] perspective = [1, 1, 0] P = Projection.perspective(point, normal, perspective) print("Perspective projection:\n", R) angle, direction = 0.1, [0.1, 0.2, 0.3]
Point(3, 2, 0), Point(4, 2, 0) ], [ Point(0, 3, 0), Point(1, 3, 0), Point(2, 3, 0), Point(3, 3, 0), Point(4, 3, 0) ], ] surface = OCCNurbsSurface.from_points(points=points) T = Translation.from_vector([0, -1.5, 0]) R = Rotation.from_axis_and_angle([0, 0, 1], radians(45)) surface.transform(R * T) # ============================================================================== # AABB # ============================================================================== box = surface.aabb() # ============================================================================== # Visualisation # ============================================================================== view = App()
"""Example: pre- vs. post- multiplication """ import math from compas.geometry import Translation from compas.geometry import Rotation from compas.geometry import Scale R = Rotation.from_axis_and_angle([0, 0, 1], math.radians(30)) T = Translation([2, 0, 0]) S = Scale([0.5] * 3) X1 = S * T * R X2 = R * T * S print(X1) print(X2) print(X1 == X2) # should not be the same!
'color': (0, 255, 0) }, { 'start': origin, 'end': zaxis, 'color': (0, 0, 255) }] compas_rhino.draw_points(points, layer=layer, clear=True) compas_rhino.draw_lines(lines, layer=layer, clear=False) cloud1 = pointcloud(30, (0, 10), (0, 3), (0, 5)) bbox1 = bounding_box(cloud1) Rz = Rotation.from_axis_and_angle([ 0., 0., 1., ], radians(30)) Ry = Rotation.from_axis_and_angle([ 0., 1., 0., ], radians(20)) Rx = Rotation.from_axis_and_angle([ 1., 0., 0., ], radians(50)) T = Translation([2., 5., 8.])
import math import compas_libigl as igl from compas.datastructures import Mesh from compas.utilities import Colormap, rgb_to_hex from compas.geometry import Line, Polyline, Rotation, Scale from compas_viewers.objectviewer import ObjectViewer # ============================================================================== # Input geometry # ============================================================================== mesh = Mesh.from_off(igl.get_beetle()) Rx = Rotation.from_axis_and_angle([1, 0, 0], math.radians(90)) Rz = Rotation.from_axis_and_angle([0, 0, 1], math.radians(90)) S = Scale.from_factors([10, 10, 10]) mesh.transform(S * Rz * Rx) # ============================================================================== # Isolines # ============================================================================== scalars = mesh.vertices_attribute('z') vertices, edges = igl.trimesh_isolines(mesh.to_vertices_and_faces(), scalars, 10) isolines = igl.groupsort_isolines(vertices, edges) # ============================================================================== # Visualisation # ==============================================================================
PATH = os.path.join(DATA, 'stack.json') # load assembly assembly = Assembly.from_json(PATH) # compute interface forces compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=True) # serialise assembly.to_json(PATH) # visualise R = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], -pi / 2) assembly_transform(assembly, R) plotter = AssemblyPlotter(assembly, figsize=(10, 7)) plotter.draw_vertices(text={key: str(key) for key in assembly.vertices()}) plotter.draw_edges() plotter.draw_blocks(facecolor={ key: (255, 0, 0) for key in assembly.vertices_where({'is_support': True}) }) plotter.show()
before = Mesh.from_ply(compas.get_bunny()) # ============================================================================== # Clean up # ============================================================================== before.cull_vertices() # ============================================================================== # Transform # ============================================================================== T = Translation.from_vector(Point(0, 0, 0) - Point(*before.centroid())) S = Scale.from_factors([100, 100, 100]) R = Rotation.from_axis_and_angle([1, 0, 0], radians(90)) before.transform(R * S * T) # ============================================================================== # Remesh # ============================================================================== L = sum(before.edge_length(*edge) for edge in before.edges()) / before.number_of_edges() V, F = trimesh_remesh(before.to_vertices_and_faces(), 3 * L) after = Mesh.from_vertices_and_faces(V, F) # ============================================================================== # Viz
def arch_from_rise_and_span(height, span, depth, thickness, n): """Create a semicircular arch from rise and span. Parameters ---------- height : float ... span : float Dimension of the span in meter measured at the impost level (intrados-intrados). depth : float Depth in meter of the arch perpendicular to the front view plane. thickness : float Thickness in meter of the arch. n: int number of voussoirs. Returns ------- Assembly Data structure of the semicircular arch. """ assembly = Assembly() if height > span / 2: raise Exception("Not a semicircular arch.") radius = height / 2 + (span**2 / (8 * height)) base = [0.0, 0.0, 0.0] top = [0.0, 0.0, height] left = [-span / 2, 0.0, 0.0] center = [0.0, 0.0, height - radius] vector = subtract_vectors(left, center) springing = angle_vectors(vector, [-1.0, 0.0, 0.0]) sector = radians(180) - 2 * springing angle = sector / n a = top b = add_vectors(top, [0, depth, 0]) c = add_vectors(top, [0, depth, thickness]) d = add_vectors(top, [0, 0, thickness]) R = Rotation.from_axis_and_angle([0, 1.0, 0], 0.5 * sector, center) bottom = transform_points([a, b, c, d], R) blocks = [] for i in range(n): R = Rotation.from_axis_and_angle([0, 1.0, 0], -angle, center) top = transform_points(bottom, R) vertices = bottom + top faces = [[0, 1, 2, 3], [7, 6, 5, 4], [3, 7, 4, 0], [6, 2, 1, 5], [7, 3, 2, 6], [5, 1, 0, 4]] block = Block.from_vertices_and_faces(vertices, faces) assembly.add_block(block) bottom = top assembly.node_attribute(0, 'is_support', True) assembly.node_attribute(n - 1, 'is_support', True) return assembly