def random_3d_path(steps: int = 100, max_step_size: float = 1.0, max_heading: float = math.pi / 2.0, max_pitch: float = math.pi / 8.0, retarget: int = 20) -> Iterable[Vector]: """ Returns a random 3D path as iterable of :class:`~ezdxf.math.Vector` objects. Args: steps: count of vertices to generate max_step_size: max step size max_heading: limit heading angle change per step to ± max_heading/2, rotation about the z-axis in radians max_pitch: limit pitch angle change per step to ± max_pitch/2, rotation about the x-axis in radians retarget: specifies steps before changing global walking target """ max_ = max_step_size * steps def next_global_target(): return Vector((rnd(max_), rnd(max_), rnd(max_))) walker = Vector() target = next_global_target() for i in range(steps): if i % retarget == 0: target = target + next_global_target() angle = (target - walker).angle length = max_step_size * random.random() heading_angle = angle + rnd_perlin(max_heading, walker) next_step = Vector.from_angle(heading_angle, length) pitch_angle = rnd_perlin(max_pitch, walker) walker += Matrix44.x_rotate(pitch_angle).transform(next_step) yield walker
def test_x_rotation(self, msp): mline = msp.add_mline([(0, 5), (10, 5)]) m = Matrix44.x_rotate(math.pi / 2) mline.transform(m) assert mline.start_location().isclose((0, 0, 5)) assert mline.dxf.extrusion == (0, -1, 0) assert mline.dxf.scale_factor == 1
def get_transformation(self) -> Matrix44: """Returns the transformation matrix to transform the source entity located with the minimum extension corner of its bounding box in (0, 0, 0) to the final location including the required rotation. """ x, y, z = self.position rt = self.rotation_type if rt == RotationType.WHD: # width, height, depth return Matrix44.translate(x, y, z) if rt == RotationType.HWD: # height, width, depth return Matrix44.z_rotate(PI_2) @ Matrix44.translate( x + self.height, y, z) if rt == RotationType.HDW: # height, depth, width return Matrix44.xyz_rotate(PI_2, 0, PI_2) @ Matrix44.translate( x + self.height, y + self.depth, z) if rt == RotationType.DHW: # depth, height, width return Matrix44.y_rotate(-PI_2) @ Matrix44.translate( x + self.depth, y, z) if rt == RotationType.DWH: # depth, width, height return Matrix44.xyz_rotate(0, PI_2, PI_2) @ Matrix44.translate( x, y, z) if rt == RotationType.WDH: # width, depth, height return Matrix44.x_rotate(PI_2) @ Matrix44.translate( x, y + self.depth, z) raise TypeError(rt)
def rotate_x(self, angle: float) -> "DXFGraphic": """Rotate entity inplace about x-axis, returns `self` (floating interface). Args: angle: rotation angle in radians """ return self.transform(Matrix44.x_rotate(angle))
def rotate_x(self, angle: float): """ Rotate mesh around x-axis about `angle` inplace. Args: angle: rotation angle in radians """ self.vertices = list( Matrix44.x_rotate(angle).transform_vertices(self.vertices)) return self
def test_to_polylines2d_with_ocs(self, path1): m = Matrix44.x_rotate(math.pi / 4) path = path1.transform(m) extrusion = m.transform((0, 0, 1)) polylines = list(to_polylines2d(path, extrusion=extrusion)) p0 = polylines[0] assert p0.dxf.elevation.isclose((0, 0, 1)) assert p0.dxf.extrusion.isclose(extrusion) assert p0[0].dxf.location.isclose((0, 0, 1)) assert p0[-1].dxf.location.isclose((4, 0, 1))
def test_to_lwpolylines_with_ocs(self, path1): m = Matrix44.x_rotate(math.pi / 4) path = path1.transform(m) extrusion = m.transform((0, 0, 1)) polylines = list(to_lwpolylines(path, extrusion=extrusion)) p0 = polylines[0] assert p0.dxf.elevation == pytest.approx(1) assert p0.dxf.extrusion.isclose(extrusion) assert p0[0] == (0, 0, 0, 0, 0) assert p0[-1] == (4, 0, 0, 0, 0)
def test_to_hatches_with_ocs(self, path1): m = Matrix44.x_rotate(math.pi / 4) path = path1.transform(m) extrusion = m.transform((0, 0, 1)) hatches = list(to_hatches(path, extrusion=extrusion)) h0 = hatches[0] assert h0.dxf.elevation == (0, 0, 1) assert h0.dxf.extrusion.isclose(extrusion) polypath0 = h0.paths[0] assert polypath0.vertices[0] == (0, 0, 0) # x, y, bulge assert polypath0.vertices[-1] == (0, 0, 0), "should be closed automatically"
def test_to_lwpolylines_with_ocs(self, path1): m = Matrix44.x_rotate(math.pi / 4) path = path1.transform(m) extrusion = m.transform((0, 0, 1)) polylines = list(to_lwpolylines(path, extrusion=extrusion)) p0 = polylines[0] assert p0.dxf.elevation == pytest.approx(1) assert p0.dxf.extrusion.isclose(extrusion) assert (all( math.isclose(a, b, abs_tol=1e-12) for a, b in zip(p0[0], (0, 0, 0, 0, 0))) is True) assert (all( math.isclose(a, b, abs_tol=1e-12) for a, b in zip(p0[-1], (4, 0, 0, 0, 0))) is True)
def test_to_poly_path_hatches_with_ocs(self, path1): m = Matrix44.x_rotate(math.pi / 4) path = path1.transform(m) extrusion = m.transform((0, 0, 1)) hatches = list(to_hatches(path, edge_path=False, extrusion=extrusion)) h0 = hatches[0] assert h0.dxf.elevation.isclose((0, 0, 1)) assert h0.dxf.extrusion.isclose(extrusion) polypath0 = h0.paths[0] assert (all(abs(a) < 1e-12 for a in polypath0.vertices[0]) is True # ~(0, 0, 0) ) # x, y, bulge assert (all(abs(a) < 1e-12 for a in polypath0.vertices[-1]) is True # ~(0, 0, 0) ), "should be closed automatically"
def matrix(self): return Matrix44.chain( Matrix44.x_rotate(0.75), Matrix44.translate(2, 3, 4), )