Exemplo n.º 1
0
def test_dot_product():
    """Check dot product of two Vectors."""
    Ω = Point(0, 0, 'Ω')
    A = Point(1, 1, 'A')
    with pytest.raises(TypeError) as excinfo:
        Vector(0, 1).dot(Bipoint(Ω, A))
    assert str(excinfo.value) == 'Can only calculate the dot product of a '\
        'Vector by another Vector. '\
        'Found Bipoint(Point Ω(0, 0), Point A(1, 1)) instead.'
    u = Vector(1, 1)
    v = Vector(3, -7)
    assert u.dot(v) == -4
    u = Vector(2, 5, -7)
    v = Vector(3, -7, 2)
    assert u.dot(v) == -43
Exemplo n.º 2
0
    def __init__(self, point, vertex, point_or_measure, decoration=None,
                 mark_right=False, second_point_name='auto', label=None,
                 color=None, thickness='thick', armspoints=None,
                 label_vertex=False, draw_vertex=False,
                 label_armspoints=False, draw_armspoints=False,
                 label_endpoints=False, draw_endpoints=False,
                 naming_mode='from_endpoints', decoration2=None):
        """
        :param point: a Point of an arm of the Angle
        :type point: Point
        :param vertex: the Angle's vertex
        :type vertex: Point
        :param point_or_measure: either a Point of the other arm of the Angle,
        or the measure of the Angle
        :type point_or_measure: Point or number
        :param decoration: the decoration of the Angle
        :type decoration: None or AngleDecoration
        :param mark_right: to tell whether to mark the angle as a right angle
        :type mark_right: bool
        :param second_point_name: Only used if point_or_measure is a measure,
        this is the name of the 2d arm's Point. If set to 'auto', then the name
        of the first Point will be used, concatenated to a '.
        :type second_point_name: str
        :param thickness: the Angle's arms' thickness. Available values are
        TikZ's ones.
        :type thickness: str
        :param color: the color of the Angle's arms.
        :type color: str
        :param naming_mode: how to build the name. Possible modes are:
        'from_endpoints', 'from_armspoints', 'from_vertex'. Note that if no
        armspoints are defined, then trying to get the Angle.name will raise an
        error
        :type naming_mode: str
        """
        self.color = color
        self.thickness = thickness
        self.naming_mode = naming_mode
        self.decoration = decoration
        self.decoration2 = decoration2
        # The label must be set *after* the possible decoration, because it
        # will actually be handled by self.decoration
        if (self.decoration is None
            or self.decoration.label in [None, 'default']):
            self.label = label
        else:
            if label is not None:
                raise ValueError('The label has been set twice, as Angle\'s '
                                 'keyword argument ({}) and as its '
                                 'AngleDecoration\'s keyword argument ({}).'
                                 .format(repr(label),
                                         repr(self.decoration.label_value)))
        self.mark_right = mark_right
        self.label_vertex = label_vertex
        self.label_endpoints = label_endpoints
        self.draw_endpoints = draw_endpoints
        self.label_armspoints = label_armspoints
        self.draw_armspoints = draw_armspoints
        self.draw_vertex = draw_vertex
        if not (isinstance(point, Point)
                and isinstance(vertex, Point)
                and (isinstance(point_or_measure, Point)
                     or is_number(point_or_measure))):
            raise TypeError('Three Points, or two Points and the measure of '
                            'the angle are required to build an Angle. '
                            'Found instead: {}, {} and {}.'
                            .format(type(point), type(vertex),
                                    type(point_or_measure)))
        self._points = [point, vertex]
        if isinstance(point_or_measure, Point):
            self._points.append(point_or_measure)
        else:
            self._points.append(point.rotate(vertex, point_or_measure,
                                             rename=second_point_name))

        if any([p.three_dimensional for p in self._points]):
            self._three_dimensional = True
        else:
            self._three_dimensional = False

        # Measure of the angle:
        if self._three_dimensional:
            u = Vector(self.points[1], self.points[0])
            v = Vector(self.points[1], self.points[2])
            self._measure = Number(str(degrees(atan2(u.cross(v).length,
                                                     u.dot(v)))))
        else:  # 2D angles measure
            p0 = Point(self._points[0].x - self._points[1].x,
                       self._points[0].y - self._points[1].y,
                       None)
            p2 = Point(self._points[2].x - self._points[1].x,
                       self._points[2].y - self._points[1].y,
                       None)
            α0 = Number(str(degrees(atan2(p0.y, p0.x))))
            α2 = Number(str(degrees(atan2(p2.y, p2.x))))
            self._measure = α2 - α0

        if self._measure < 0:
            self._measure += 360

        # This is not like the matching Triangle!
        if shoelace_formula(*self.points) > 0:
            self.winding = 'clockwise'
        else:
            self.winding = 'anticlockwise'

        arm0 = Bipoint(self._points[1], self._points[0])
        arm1 = Bipoint(self._points[1], self._points[2])
        self._arms = [arm0, arm1]
        self.armspoints = armspoints

        # Only 2D: labels positioning
        if not self.three_dimensional:
            # Vertex' label positioning
            bisector = Vector(self._points[0], self.vertex)\
                .bisector(Vector(self._points[2], self.vertex),
                          new_endpoint_name=None)
            try:
                self._points[1].label_position = \
                    tikz_approx_position(bisector.slope360)
            except ZeroVector:
                self._points[1].label_position = \
                    tikz_approx_position(
                        Bipoint(self.vertex,
                                self._points[0].rotate(self.vertex, -90,
                                                       rename=None)
                                ).slope360)

            # Endpoints labels positioning
            direction = 1 if self.winding == 'anticlockwise' else -1
            self.endpoints[0].label_position = \
                tikz_approx_position(arm0.slope360 - direction * 55)
            self.endpoints[1].label_position = \
                tikz_approx_position(arm1.slope360 + direction * 55)