def append(self, point: 'Vertex', tangent1: 'Vertex', tangent2: 'Vertex' = None, segments: int = 20): """ Append a control point with two control tangents. Args: point: the control point tangent1: first control tangent as vector *left* of point tangent2: second control tangent as vector *right* of point, if omitted tangent2 = -tangent1 segments: count of line segments for polyline approximation, count of line segments from previous control point to this point. """ tangent1 = Vector(tangent1) if tangent2 is None: tangent2 = -tangent1 else: tangent2 = Vector(tangent2) self.points.append((point, tangent1, tangent2, int(segments)))
def test_project(): v = Vector(10, 0, 0) assert v.project((5, 0, 0)) == (5, 0, 0) assert v.project((5, 5, 0)) == (5, 0, 0) assert v.project((5, 5, 5)) == (5, 0, 0) v = Vector(10, 10, 0) assert v.project((10, 0, 0)) == (5, 5, 0)
def _setup(self) -> None: """ Calc setup values and determines the point order of the dimension line points. """ self.measure_points = [Vector(point) for point in self.measure_points] # type: List[Vector] dimlineray = ConstructionRay(self.dimlinepos, angle=radians(self.angle)) # Type: ConstructionRay self.dimline_points = [self._get_point_on_dimline(point, dimlineray) for point in self.measure_points] # type: List[Vector] self.point_order = self._indices_of_sorted_points(self.dimline_points) # type: List[int] self._build_vectors()
def slice(self, step=1): points = [Vector(self.entity.dxf.start), Vector(self.entity.dxf.end)] sliced = [points[0]] for start, end in pairwise(points): dist = start.distance(end) n_steps = int(dist / step) try: param_step = step / dist except ZeroDivisionError: continue v = Vector() for i in range(n_steps): v = start.lerp(end, param_step * (i + 1)) sliced.append(v) if not v.isclose(end): sliced.append(end) self.points = sliced self.sliced = True self._length = None
def centroid(self): try: return self._centroid except AttributeError: points = [Vector(point) for point in self.entity.points()] centroid = NULLVEC for p1, p2 in pairwise(points): centroid += p1.lerp(p2) self._centroid = centroid return centroid
def set_location(self, insert: 'Vertex', rotation: float = None, attachment_point: int = None) -> 'MText': self.dxf.insert = Vector(insert) if rotation is not None: self.set_rotation(rotation) if attachment_point is not None: self.dxf.attachment_point = attachment_point return self
def __init__(self, pos: 'Vertex', center: 'Vertex', start: 'Vertex', end: 'Vertex', dimstyle: str = 'angle.deg', layer: str = None, roundval: int = None): """ AngularDimension constructor. Args: pos: location as (x, y) tuple of dimension line, line goes through this point center: center point as (x, y) tuple of angle start: line from center to start is the first side of the angle end: line from center to end is the second side of the angle dimstyle: dimstyle name, 'Default' - style is the default value layer: dimension line layer, override the default value of dimstyle roundval: count of decimal places """ super().__init__(dimstyle, layer, roundval) self.dimlinepos = Vector(pos) self.center = Vector(center) self.start = Vector(start) self.end = Vector(end)
def test_vector_as_tuple(): v = Vector(1, 2, 3) assert v[0] == 1 assert v[1] == 2 assert v[2] == 3 assert tuple(v) == (1, 2, 3) assert isinstance(v[:2], tuple) assert v[:2] == (1, 2) assert v[1:] == (2, 3) assert isinstance(v.xyz, tuple) assert v.xyz == (1, 2, 3)
def __init__(self, center: 'Vertex', target: 'Vertex', length: float = 1., dimstyle: str = 'Default', layer: str = None, roundval: int = None): """ Args: center: center point of radius target: target point of radius length: length of radius arrow (drawing length) dimstyle: dimstyle name, 'Default' - style is the default value layer: dimension line layer, override the default value of dimstyle roundval: count of decimal places """ super().__init__(dimstyle, layer, roundval) self.center = Vector(center) self.target = Vector(target) self.length = float(length)
def append(self, point: 'Vertex', tangent1: 'Vertex', tangent2: 'Vertex' = None, segments: int = 20): """ Append a control point with two control tangents. Args: point: control point as :class:`~ezdxf.math.Vector` or ``(x, y, z)`` tuple tangent1: first control tangent as vector "left" of control point tangent2: second control tangent as vector "right" of control point, if omitted `tangent2` = `-tangent1` segments: count of line segments for polyline approximation, count of line segments from previous control point to appended control point. """ tangent1 = Vector(tangent1) if tangent2 is None: tangent2 = -tangent1 else: tangent2 = Vector(tangent2) self.points.append((point, tangent1, tangent2, int(segments)))
def test_angle_between(): v1 = Vector(0, 1) v2 = Vector(1, 1) angle = v1.angle_between(v2) assert math.isclose(angle, math.pi / 4) # reverse order, same result angle = v2.angle_between(v1) assert math.isclose(angle, math.pi / 4)
def test_angle_between_outside_domain(): v1 = Vector(721.046967113573, 721.0469671135688, 0.0) v2 = Vector(-721.0469671135725, -721.0469671135688, 0.0) angle = v1.angle_between(v2) assert math.isclose(angle, math.pi) # reverse order, same result angle = v2.angle_between(v1) assert math.isclose(angle, math.pi)
def test_deep_copy(): import copy v = Vector(1, 2, 3) l1 = [v, v, v] l2 = copy.copy(l1) assert l2[0] is l2[1] assert l2[1] is l2[2] assert l2[0] is v l3 = copy.deepcopy(l1) assert l3[0] is l3[1] assert l3[1] is l3[2] assert l3[0] is not v
def slice(self, step=1): """ Нарезать элемент на более менее линии с заданным шагом :param float step: шаг нарезки :return: """ sliced = [self.points[0]] for start, end in pairwise(self.points): dist = start.distance(end) n_steps = int(dist / step) try: param_step = step / dist except ZeroDivisionError: continue v = Vector() for i in range(n_steps): v = start.lerp(end, param_step * (i + 1)) sliced.append(v) if not v.isclose(end): sliced.append(end) self.points = sliced self.sliced = True self._length = None
def point(self, t: float) -> Tuple[Vector, Vector, Vector]: """ Returns (point, 1st derivative, 2nd derivative) tuple for location `t` at the `Bézier curve`_, all values as :class:`Vector` objects. Args: t: parameter in range ``[0, 1]`` """ if t < 0. or t > 1.: raise ValueError('parameter t in range [0, 1]') if (1.0 - t) < 5e-6: t = 1.0 defpoints = self._defpoints npts = len(defpoints) npts0 = npts - 1 point = [0., 0., 0.] d1 = [0., 0., 0.] d2 = [0., 0., 0.] for axis in (0, 1, 2): if t == 0.0: d1[axis] = npts0 * (defpoints[1][axis] - defpoints[0][axis]) d2[axis] = npts0 * (npts0 - 1) * (defpoints[0][axis] - 2. * defpoints[1][axis] + defpoints[2][axis]) for i in range(len(defpoints)): tempbasis = bernstein_basis(npts0, i, t) point[axis] += tempbasis * defpoints[i][axis] if 0.0 < t < 1.0: d1[axis] += ((i - npts0 * t) / (t * (1. - t))) * tempbasis * defpoints[i][axis] temp1 = (i - npts0 * t) ** 2 temp2 = temp1 - npts0 * t ** 2 - i * (1. - 2. * t) d2[axis] += (temp2 / (t ** 2 * (1. - t) ** 2)) * tempbasis * defpoints[i][axis] if t == 1.0: d1[axis] = npts0 * (defpoints[npts0][axis] - defpoints[npts0 - 1][axis]) d2[axis] = npts0 * (npts0 - 1) * (defpoints[npts0][axis] - 2 * defpoints[npts0 - 1][axis] + defpoints[npts0 - 2][axis]) return Vector(point), Vector(d1), Vector(d2)
def __init__(self, pos: 'Vertex', measure_points: Iterable['Vertex'], angle: float = 0., dimstyle: str = 'Default', layer: str = None, roundval: int = None): """ LinearDimension Constructor. Args: pos: location as (x, y) tuple of dimension line, line goes through this point measure_points: list of points as (x, y) tuples to dimension (two or more) angle: angle (in degree) of dimension line dimstyle: dimstyle name, 'Default' - style is the default value layer: dimension line layer, override the default value of dimstyle roundval: count of decimal places """ super().__init__(dimstyle, layer, roundval) self.angle = angle self.measure_points = list(measure_points) self.text_override = [""] * self.section_count self.dimlinepos = Vector(pos) self.layout = None
def point(self, t: float) -> Vector: """ Returns point at BezierCurve(t) as tuple (x, y, z) Args: t: parameter in range [0, 1] Returns: Vector(x, y, z) """ if t < 0. or t > 1.: raise ValueError('parameter t in range [0, 1]') if (1.0 - t) < 5e-6: t = 1.0 point = [0., 0., 0.] defpoints = self._defpoints len_defpoints = len(defpoints) for axis in (0, 1, 2): for i in range(len_defpoints): bsf = bernstein_basis(len_defpoints - 1, i, t) point[axis] += bsf * defpoints[i][axis] return Vector(point)
def point(self, t: float) -> Vector: """ Returns a point for location `t` at the `Bézier curve`_ as :class:`Vector` object. A `Bézier curve`_ is a parametric curve, parameter `t` goes from ``0`` to ``1``, where ``0`` is the first definition point anf ``1`` is the last definition point. Args: t: parameter in range ``[0, 1]`` """ if t < 0. or t > 1.: raise ValueError('parameter t in range [0, 1]') if (1.0 - t) < 5e-6: t = 1.0 point = [0., 0., 0.] defpoints = self._defpoints len_defpoints = len(defpoints) for axis in (0, 1, 2): for i in range(len_defpoints): bsf = bernstein_basis(len_defpoints - 1, i, t) point[axis] += bsf * defpoints[i][axis] return Vector(point)
def test_rot_z(): assert Vector(2, 2, 7).rotate_deg(90) == (-2, 2, 7)
def test_cross_product(): v1 = Vector(2, 7, 9) v2 = Vector(3, 9, 1) assert v1.cross(v2) == (-74, 25, -3)
def test_get_angle(): v = Vector(3, 3) assert math.isclose(v.angle_deg, 45) assert math.isclose(v.angle, math.radians(45))
def test_round(): v = Vector(1.123, 2.123, 3.123) v2 = v.round(1) assert v2 == (1.1, 2.1, 3.1)
def test_iter(): assert sum(Vector(1, 2, 3)) == 6
def test_vec2(): v = Vector(1, 2, 3) assert len(v) == 3 v2 = v.vec2 assert len(v2) == 2 assert v2 == (1, 2)
def test_replace(): v = Vector(1, 2, 3) assert v.replace(x=7) == (7, 2, 3) assert v.replace(y=7) == (1, 7, 3) assert v.replace(z=7) == (1, 2, 7) assert v.replace(x=7, z=7) == (7, 2, 7)
def test_from_angle(): angle = math.radians(50) length = 3. assert Vector.from_angle(angle, length) == (math.cos(angle) * length, math.sin(angle) * length, 0)
def test_init_no_params(): v = Vector() assert v == (0, 0, 0) assert v == Vector()
def test_init_three_params(): v = Vector(1, 2, 3) assert v == (1, 2, 3)
def __init__(self, defpoints: Iterable['Vertex']): self._defpoints = [Vector(p) for p in defpoints] # type: List[Vector]
def test_lerp(): v1 = Vector(1, 1, 1) v2 = Vector(4, 4, 4) assert v1.lerp(v2, .5) == (2.5, 2.5, 2.5) assert v1.lerp(v2, 0) == (1, 1, 1) assert v1.lerp(v2, 1) == (4, 4, 4)