Пример #1
0
    def __init__(self, curve1, curve2):
        """
        Give the graph of the surface between the two lines.

        The lines are needed to have a starting and ending point
        that will be joined by straight lines.
        """
        from yanntricks.src.segment import Segment
        # By convention, the first line goes from left to right and the second one to right to left.

        ObjectGraph.__init__(self, self)

        if curve1.I.x > curve1.F.x:
            curve1 = curve1.reverse()
        if curve2.I.x > curve2.F.x:
            curve2 = curve2.reverse()

        self.curve1 = curve1
        self.curve2 = curve2

        self.I1 = curve1.I
        self.I2 = curve2.I

        self.F1 = curve1.F
        self.F2 = curve2.F

        self.Isegment = Segment(self.I1, self.I2)
        self.Fsegment = Segment(self.F1, self.F2)
Пример #2
0
    def projection(self, seg, direction=None, advised=False):
        """
        Return the projection of the point on the given segment.

        INPUT:

        - ``seg`` - a segment
        - ``direction`` - (default=None) a vector.
        If given, we use a projection parallel to 
        `vector` instead of the orthogonal projection.

        OUTPUT:

        a point.
        """
        from yanntricks.src.SingleAxeGraph import SingleAxe
        from yanntricks.src.affine_vector import AffineVector
        from yanntricks.src.segment import Segment
        from yanntricks.src.Utilities import Intersection
        if isinstance(seg, AffineVector):
            seg = seg.segment
        if isinstance(seg, SingleAxe):
            seg = seg.segment()
        if direction is None:
            if seg.is_vertical:
                direction = Segment(self, self + (1, 0))
            elif seg.is_horizontal:
                direction = Segment(self, self + (0, 1))
            else:
                direction = Segment(self, self + (1, -1 / seg.slope))

        P = Intersection(seg, direction)[0]
        if advised:
            P._advised_mark_angle = seg.angle().degree + 90
        return P
Пример #3
0
 def __init__(self, bb=None):
     from yanntricks.src.BoundingBox import BoundingBox
     if bb is None:
         bb = BoundingBox()
     ObjectGraph.__init__(self, self)
     self.BB = bb
     self.separator_name = "GRID"
     # Default values, have to be integer.
     self.add_option({"Dx": 1, "Dy": 1})
     self.Dx = self.options.DicoOptions["Dx"]
     self.Dy = self.options.DicoOptions["Dy"]
     self.num_subX = 2
     self.num_subY = 2
     self.draw_border = False
     self.draw_horizontal_grid = True
     self.draw_vertical_grid = True
     self.main_horizontal = Segment(Point(0, 1), Point(1, 1))
     self.main_horizontal.parameters.color = "gray"
     self.main_horizontal.parameters.style = "solid"
     self.main_vertical = Segment(Point(0, 1), Point(1, 1))
     self.main_vertical.parameters.color = "gray"
     self.main_vertical.parameters.style = "solid"
     self.sub_vertical = Segment(Point(0, 1), Point(1, 1))
     self.sub_vertical.parameters.color = "gray"
     self.sub_vertical.parameters.style = "dotted"
     self.sub_horizontal = Segment(Point(0, 1), Point(1, 1))
     self.sub_horizontal.parameters.color = "gray"
     self.sub_horizontal.parameters.style = "dotted"
     self.border = Segment(Point(0, 1), Point(1, 1))
     self.border.parameters.color = "gray"
     self.border.parameters.style = "dotted"
Пример #4
0
    def __init__(self, op, P, a, b, c):
        from yanntricks.src.segment import Segment
        from yanntricks.src.point import Point
        ObjectGraph.__init__(self, self)
        self.op = op
        self.P = P
        self.Px = P[0]
        self.Py = P[1]
        self.a = a
        self.b = b
        self.c = c
        self.transparent = True

        self.A = [
            Point(self.Px, self.Py + b),
            Point(self.Px + a, self.Py + b),
            Point(self.Px + a, self.Py),
            Point(self.Px, self.Py)
        ]

        # The points on the first and second rectangle
        self.c1 = [self.op.point(P.x, P.y, 0) for P in self.A]
        self.c2 = [self.op.point(P.x, P.y, self.c) for P in self.A]

        self.A = self.c1[0]
        self.B = self.c1[1]
        self.C = self.c1[2]
        self.D = self.c1[3]
        self.E = self.c2[0]
        self.F = self.c2[1]
        self.G = self.c2[2]
        self.H = self.c2[3]

        for P in self.c1:
            P.parameters.symbol = ""
        for P in self.c2:
            P.parameters.symbol = ""

        # The edges.
        self.segP = [
            Segment(self.c1[i], self.c2[i]) for i in range(0, len(self.c1))
        ]
        self.segc1 = [
            Segment(self.c1[i], self.c1[(i + 1) % len(self.c1)])
            for i in range(0, len(self.c1))
        ]
        self.segc2 = [
            Segment(self.c2[i], self.c2[(i + 1) % len(self.c2)])
            for i in range(0, len(self.c2))
        ]

        if op.alpha < 90:
            self.segP[3].parameters.style = "dashed"
            self.segc2[2].parameters.style = "dashed"
            self.segc2[3].parameters.style = "dashed"
        else:
            self.segP[2].parameters.style = "dashed"
            self.segc2[2].parameters.style = "dashed"
            self.segc2[1].parameters.style = "dashed"
Пример #5
0
def CircularSector(center, radius, a, b):
    from yanntricks.src.segment import Segment
    circle = Circle(center, radius)
    P = circle.get_point(a)
    Q = circle.get_point(b)
    l1 = Segment(circle.center, P)
    l2 = circle.graph(a, b)
    l3 = Segment(Q, circle.center)
    return CustomSurface(l1, l2, l3)
Пример #6
0
 def getEdge(self, pos):
     from yanntricks.src.segment import Segment
     if pos == "NORTH":
         return Segment(self.getVertex("NW"), self.getVertex("NE"))
     if pos == "SOUTH":
         return Segment(self.getVertex("SW"), self.getVertex("SE"))
     if pos == "EAST":
         return Segment(self.getVertex("NE"), self.getVertex("SE"))
     if pos == "WEST":
         return Segment(self.getVertex("NW"), self.getVertex("SW"))
 def __init__(self, seg, dist=0.1):
     try:
         self.segment = seg.segment
     except AttributeError:
         self.segment = seg
     self.dist = dist
     self.delta = seg.rotation(-90).fix_size(self.dist)
     self.mseg = seg.translate(self.delta)
     Segment.__init__(self, self.mseg.I, self.mseg.F)
     self.mI = self.mseg.I
     self.mF = self.mseg.F
Пример #8
0
def PolarSegment(P, r, theta):
    """
    return a segment on the base point P (class Point) of 
    length r and angle theta (degree)
    """
    alpha = radian(theta)
    return Segment(P, Point(P.x + r * cos(alpha), P.y + r * sin(alpha)))
Пример #9
0
def CircleAB(A, B):
    """
    return a circle with diameter [AB]
    """
    from yanntricks.src.segment import Segment
    center = Segment(A, B).midpoint()
    return CircleOA(center, A)
Пример #10
0
 def get_tangent_segment(self, llam):
     """
     Return a tangent segment of length 2 centred at the given point.
     It is essentially two times get_tangent_vector.
     """
     from yanntricks.src.segment import Segment
     v = self.get_tangent_vector(llam)
     mv = -v
     return Segment(mv.F, v.F)
Пример #11
0
    def __init__(self,
                 curve1,
                 curve2,
                 interval1=None,
                 interval2=None,
                 reverse1=False,
                 reverse2=True):
        from yanntricks.src.segment import Segment
        # TODO: I think that the parameters reverse1 and reverse2 are no more useful
        #   since I enforce the condition curve1 : left -> right by hand.
        ObjectGraph.__init__(self, self)

        self.curve1 = curve1
        self.curve2 = curve2

        #self.f1=self.curve1       # TODO: Soon or later, one will have to fusion these two
        #self.f2=self.curve2

        self.mx1 = interval1[0]
        self.mx2 = interval1[1]
        self.Mx1 = interval2[0]
        self.Mx2 = interval2[1]

        for attr in [self.mx1, self.mx2, self.Mx1, self.Mx2]:
            if attr == None:
                raise TypeError(
                    "At this point, initial and final values have to be already chosen"
                )
        self.curve1.llamI = self.mx1
        self.curve1.llamF = self.Mx1
        self.curve2.llamI = self.mx2
        self.curve2.llamF = self.Mx2

        self.draw_Isegment = True
        self.draw_Fsegment = True
        self.Isegment = Segment(self.curve2.get_point(self.mx2, advised=False),
                                self.curve1.get_point(self.mx1, advised=False))
        self.Fsegment = Segment(self.curve1.get_point(self.Mx1, advised=False),
                                self.curve2.get_point(self.Mx2, advised=False))

        self.add_option("fillstyle=vlines")
        self.parameters.color = None
Пример #12
0
    def get_tangent_segment(self, theta):
        """
        Return a tangent segment at point (x,f(x)).

        The difference with self.get_tangent_vector is that self.get_tangent_segment returns a segment that will
        be symmetric. The point (x,f(x)) is the center of self.get_tangent_segment.
        """
        from yanntricks.src.segment import Segment
        v = self.get_tangent_vector(theta)
        mv = -v
        return Segment(mv.F, v.F)
Пример #13
0
    def segment(self, projection=False, pspict=None):
        # pylint:disable=unused-argument
        if self.mx == 0 and self.Mx == 0:
            # I think that we only pass here in order either to do
            # a projection either to create an initial bounding box.
            # If xunit or yunit are very low, then returning something like
            #   Segment(self.C-self.base.visual_length(1,pspict=pspict),
            #           self.C+self.base.visual_length(1,pspict=pspict))
            # causes bounding box to be too large.
            # This is why I return a small segment.

            if projection:
                return Segment(self.C, self.C.translate(self.base))
            pt_I = self.C.translate(-self.base.normalize(1))
            pt_F = self.C.translate(self.base.normalize(1))
            return Segment(pt_I, pt_F)

        # The axes have to cross at (0,0)
        if self.mx > 0:
            self.mx = 0
        return Segment(self.C.translate(self.mx*self.base),
                       self.C.translate(self.Mx*self.base))
Пример #14
0
    def norm(self):
        """
        Return the norm of the segment between (0,0) and self.

        This is the radial component in polar coordinates.

        EXAMPLES::

        sage: from yanntricks import *
        sage: Point(1,1).norm()
        sqrt(2)
        sage: Point(-pi,sqrt(2)).norm()
        sqrt(pi^2 + 2)
        """
        from yanntricks.src.segment import Segment
        return Segment(Point(0, 0), self).length
Пример #15
0
 def action_on_pspict(self, pspict):
     from yanntricks.src.Constructors import Circle
     from yanntricks.src.segment import Segment
     if self.denominator == self.numerator:
         cs = Circle(self.center, self.radius)
         cs.parameters.filled()
         cs.parameters.fill.color = "lightgray"
         l = [cs]
     else:
         import numpy
         l = [self.circular_sector()]
         for k in numpy.linspace(0, 360, self.denominator, endpoint=False):
             s = Segment(self.circle.get_point(k), self.center)
             s.parameters.style = "dashed"
             l.append(s)
         l.append(self.circle)
     pspict.DrawGraphs(l)
Пример #16
0
    def action_on_pspict(self, pspict):
        from yanntricks.src.segment import Segment

        # self.intersection is the point where the angle is located.

        P1 = self.inter_point(self.intersection, self.d1.F, self.n1, pspict)
        P2 = self.inter_point(self.intersection, self.d2.F, self.n2, pspict)

        Q = P1 + P2 - self.intersection
        l1 = Segment(Q, P1)
        l2 = Segment(Q, P2)

        l1.parameters = self.parameters.copy()
        l2.parameters = self.parameters.copy()
        pspict.DrawGraphs(l1, l2)
Пример #17
0
    def graduation_bars(self, pspict):
        """
        Return the list of bars that makes the graduation of the axes

        By default, it is one at each multiple of self.base.
        If an user-defined axes_unit is given, then self.base is modified.

        This function also enlarges the axe by half a *visual* centimeter.
        """
        # bars_list contains in the same time marks
        # (for the numbering) and segments (for the bars itself)
        if not self.graduation:
            return []
        bars_list = []
        bar_angle = SR(self.mark_angle).n(digits=7)  # Latex does not accept
        # too much digits.
        for x, symbol in self.axes_unit.place_list(self.mx, self.Mx, self.Dx, self.mark_origin):
            P = (x*self.base).F
            if self.numbering:
                mark_angle = self.mark_angle
                if self.segment().is_horizontal:
                    position = "N"
                    mark_angle = None
                if self.segment().is_vertical:
                    position = "E"
                    mark_angle = None
                # The 0.2 here is hard coded in Histogram, see 71011299

                m = P.get_mark(0.2, mark_angle, symbol, pspict=pspict,
                               position=position)
                bars_list.append(m)

            a = visual_polar(P, 0.1, bar_angle, pspict)
            b = visual_polar(P, 0.1, bar_angle+180, pspict)
            seg = Segment(a, b)
            bars_list.append(seg)
        return bars_list
Пример #18
0
def SurfaceUnderFunction(f, mx, Mx):
    """
    Represent a surface under a function.

    This is a particular case of SurfaceBetweenFunctions when
    the second function is the y=0 axis.

    The function `f` becomes `self.f1` while self.f2 will be the
    function 0 (this is a consequence of inheritance).
    The function f will also be recorded as self.f.

    INPUT:

    - ``f`` - a function
    - ``mx,Mx`` - initial and final values 

    EXAMPLES:

    .. literalinclude:: yanntricksSurfaceFunction.py
    .. image:: Picture_FIGLabelFigSurfaceFunctionPICTSurfaceFunction-for_eps.png


    .. literalinclude:: yanntricksChiSquaresQuantile.py
    .. image:: Picture_FIGLabelFigChiSquaresQuantilePICTChiSquaresQuantile-for_eps.png

    """
    from yanntricks.src.NonAnalytic import NonAnalyticFunctionGraph
    from yanntricks.src.segment import Segment
    from yanntricks.src.SurfacesGraph import SurfaceBetweenLines
    if isinstance(f, NonAnalyticFunctionGraph):
        line1 = Segment(Point(mx, 0), Point(Mx, 0))
        line2 = f.parametric_curve(mx, Mx)
        surf = SurfaceBetweenLines(line1, line2)
        return surf
    f2 = phyFunction(0)
    f2.nul_function = True  # See 2252914222
    return SurfaceBetweenFunctions(f, f2, mx=mx, Mx=Mx)
Пример #19
0
    def __init__(self, points_list):
        ObjectGraph.__init__(self, self)
        self.edges = []
        self.vertices = points_list
        self.points_list = self.vertices

        for i in range(0, len(self.points_list)):
            segment = Segment(
                self.points_list[i],
                self.points_list[(i + 1) % len(self.points_list)])
            self.edges.append(segment)
        self.draw_edges = True
        self.independent_edge = False
        self.parameters = None

        from yanntricks.src.parameters.Parameters import Parameters
        from yanntricks.src.parameters.HatchParameters import HatchParameters
        from yanntricks.src.parameters.FillParameters import FillParameters

        self.edges_parameters = Parameters(self)
        self.hatch_parameters = HatchParameters()
        self.fill_parameters = FillParameters()
        self._hatched = False
        self._filled = False
Пример #20
0
    def action_on_pspict(self, pspict=None):
        from yanntricks.src.segment import Segment
        from yanntricks.src.Constructors import CustomSurface
        from yanntricks.src.Exceptions import ShouldNotHappenException
        c1 = self.curve1.graph(self.mx1, self.Mx1)
        c2 = self.curve2.graph(self.mx2, self.Mx2)

        # By convention, the first line goes from left to right
        # and the second one to right to left.
        # The same is followed in SurfaceBetweenLines

        if c1.I.x > c1.F.x:
            c1 = c1.reverse()
        if c2.I.x < c2.F.x:
            c2 = c2.reverse()

        reIsegment = Segment(c2.F, c1.I)
        reFsegment = Segment(c1.F, c2.I)
        reIsegment.parameters = self.Isegment.parameters
        reFsegment.parameters = self.Fsegment.parameters

        if self.parameters._filled or self.parameters._hatched:
            custom = CustomSurface(c1, reFsegment, c2, reIsegment)
            custom.parameters = self.parameters.copy()
            pspict.DrawGraphs(custom)
        else:
            raise ShouldNotHappenException(
                "You are speaking of a surface but you don't want neither to fill it neither to hatch it ?"
            )

        if self.parameters.color != None:
            self.Isegment.parameters.color = self.parameters.color
            self.Fsegment.parameters.color = self.parameters.color
            self.curve1.parameters.color = self.parameters.color
            self.curve2.parameters.color = self.parameters.color

        pspict.DrawGraphs(self.curve1, self.curve2)

        if self.draw_Isegment:
            pspict.DrawGraphs(reIsegment)
        if self.draw_Fsegment:
            pspict.DrawGraphs(reFsegment)
Пример #21
0
 def action_on_pspict(self, pspict):
     from yanntricks.src.SmallComputations import MainGridArray
     from yanntricks.src.SmallComputations import SubGridArray
     a = []
     # ++++++++++++ Border ++++++++
     if self.draw_border:
         # Right border
         if self.draw_vertical_grid:
             if self.BB.xmax != int(self.BB.xmax):
                 S = self.BB.east_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Left border
         if self.draw_vertical_grid:
             if self.BB.xmin != int(self.BB.xmin):
                 S = self.BB.west_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Upper border
         if self.draw_horizontal_grid:
             if self.BB.ymax != int(self.BB.ymax):
                 S = self.BB.north_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Lower border
         if self.draw_horizontal_grid:
             if self.BB.ymin != int(self.BB.ymin):
                 S = self.BB.south_segment()
                 S.merge_options(self.border)
                 a.append(S)
     if self.draw_vertical_grid:
         # ++++++++++++ Principal vertical lines ++++++++
         for x in MainGridArray(self.BB.xmin, self.BB.xmax, self.Dx):
             S = Segment(Point(x, self.BB.ymin), Point(x, self.BB.ymax))
             S.merge_options(self.main_vertical)
             a.append(S)
         # ++++++++++++ The vertical sub grid ++++++++
         if self.num_subX != 0:
             for x in SubGridArray(self.BB.xmin, self.BB.xmax, self.Dx,
                                   self.num_subX):
                 S = Segment(Point(x, self.BB.ymin), Point(x, self.BB.ymax))
                 S.merge_options(self.sub_vertical)
                 a.append(S)
     if self.draw_horizontal_grid:
         # ++++++++++++ The horizontal sub grid ++++++++
         if self.num_subY != 0:
             for y in SubGridArray(self.BB.ymin, self.BB.ymax, self.Dy,
                                   self.num_subY):
                 S = Segment(Point(self.BB.xmin, y), Point(self.BB.xmax, y))
                 S.merge_options(self.sub_horizontal)
                 a.append(S)
         # ++++++++++++ Principal horizontal lines ++++++++
         for y in MainGridArray(self.BB.ymin, self.BB.ymax, self.Dy):
             S = Segment(Point(self.BB.xmin, y), Point(self.BB.xmax, y))
             S.merge_options(self.main_horizontal)
             a.append(S)
     pspict.DrawGraphs(a, separator_name=self.separator_name)
Пример #22
0
def RightAngleAOB(A, O, B, n1=0, n2=1, r=0.3):
    """
    return the right angle between Segment(A,O) and Segment(O,B)
    """
    from yanntricks.src.segment import Segment
    return RightAngle(Segment(A, O), Segment(O, B), n1, n2, r)
Пример #23
0
 def S(self):
     from yanntricks.src.segment import Segment
     return Segment(self.getVertex("SW"), self.getVertex("SE")).midpoint()
Пример #24
0
class AffineVector(ObjectGraph):
    """
    Describe an affine vector.

    An affine vector is a vector whose origin is not specifically (0,0).
    """
    def __init__(self, I, F):
        ObjectGraph.__init__(self, self)
        self.I = I
        self.F = F
        self.segment = Segment(self.I, self.F)

    @lazy_attribute
    def Dx(self):
        return self.F.x - self.I.x

    @lazy_attribute
    def Dy(self):
        return self.F.y - self.I.y

    @lazy_attribute
    def is_horizontal(self):
        return self.segment.is_horizontal

    @lazy_attribute
    def is_vertical(self):
        return self.segment.is_vertical

    @lazy_attribute
    def slope(self):
        return self.segment.slope

    @lazy_attribute
    def length(self):
        """
        Return a numerical approximation of the length.
        """
        return self.segment.length

    def fix_visual_size(self, l, xunit=None, yunit=None, pspict=None):
        s = self.segment.fix_visual_size(l, xunit, yunit, pspict)
        return AffineVector(s.I, s.F)

    def exact_length(self):
        return self.segment.exact_length

    def angle(self):
        return self.segment.angle()

    def numerical_approx(self):
        from yanntricks.src.Constructors import AffineVector
        I = Point(numerical_approx(self.I.x), numerical_approx(self.I.y))
        F = Point(numerical_approx(self.F.x), numerical_approx(self.F.y))
        return AffineVector(I, F)

    def orthogonal(self):
        from yanntricks.src.Constructors import AffineVector
        ortho_seg = self.segment.orthogonal()
        I = ortho_seg.I
        F = ortho_seg.F
        return AffineVector(I, F)

    def rotation(self, angle):
        from yanntricks.src.Constructors import AffineVector
        s = self.segment.rotation(angle)
        return AffineVector(s.I, s.F)

    def projection(self, seg):
        """
        Return the projection of 'self' on the segment 'seg' (you can also
        pass a vector).
        """
        from yanntricks.src.Constructors import AffineVector
        I = self.I.projection(seg)
        F = self.F.projection(seg)
        return AffineVector(I, F)

    ##
    # Return the decomposition of `self` into a `v`-component and
    # a normal (to v) component.
    #
    #        INPUT:
    #
    #        - ``v`` - a segment or a vector
    #
    #        OUTPUT:
    #
    #        A tuple :
    #        - the first element is the orthogonale component
    #        - the second element is the parallel component
    #
    #        NOTE:
    #
    #        The result does not depend on `v`, but only on the direction of `v`.
    def decomposition(self, seg):
        # we make the computations with vectors based at (0,0)
        # and then translate the answer.
        from yanntricks.src.Constructors import Vector
        s0 = self.fix_origin(Point(0, 0))
        if isinstance(seg, AffineVector):
            v = seg.segment()
        seg0 = seg.fix_origin(Point(0, 0))

        A = s0.F.projection(seg0)
        paral0 = Vector(A)

        perp0 = s0 - paral0

        ans_paral = paral0.fix_origin(self.I)
        ans_perp = perp0.fix_origin(self.I)

        return ans_perp, ans_paral

    def inner_product(self, other):
        from yanntricks.src.Utilities import inner_product
        return inner_product(self, other)

    def copy(self):
        return AffineVector(self.I, self.F)

    def translate(self, v):
        return AffineVector(self.I.translate(v), self.F.translate(v))

    def advised_mark_angle(self, pspict=None):
        return self.segment.advised_mark_angle(pspict)

    def midpoint(self, advised=True):
        return self.segment.midpoint(advised)

    @copy_parameters
    def fix_origin(self, P):
        """
        Return the affine vector that is equal to 'self' but attached
        to point P.
        """
        return AffineVector(P, Point(P.x + self.Dx, P.y + self.Dy))

    def normalize(self, l=1):
        """
        Return a new affine vector with
        - same starting point
        - same direction (if 'l' is negative, change the direction)
        - size l

        By default, normalize to 1.
        """
        L = self.length
        if L < 0.001:  # epsilon
            print("This vector is too small to normalize. I return a copy.")
            return self.copy()
        return (l * self).__div__(L)

    def _bounding_box(self, pspict):
        return self.segment.bounding_box(pspict=pspict)

    def __str__(self):
        return "<AffineVectorGraph I=%s F=%s>" % (str(self.I), str(self.F))

    # \brief put the vector `other` on the end of `self`
    #
    # This is the usual vector sum, but here we accept two vector that have
    # not the same initial point.
    #
    # \return a vector with same initial point as `self`.
    def extend(self, other):
        I = self.I
        F = self.F.translate(other.Dx, other.Dy)
        return AffineVector(I, F)

    # \brief add two vectors based on the same point.
    #
    # The function checks if the vectors `self` and `other` are based
    # on the same point. Sometimes, it causes strange problems. When
    # one of the coordinates has the form
    # a=3.00000000000000*cos(0.111111111111111*pi)
    # Checking equalities with that kind of numbers causes
    # OverflowError: Python int too large to convert to C long
    #
    # If you know that `v1` and `v2` have the same origin and want to sum them
    # you can also do `v1.extend(v2)`
    def __add__(self, other):
        from yanntricks.src.Constructors import Vector
        if isinstance(other, tuple):
            if len(other) == 2:
                I = self.I
                Dx = self.Dx + other[0]
                Dy = self.Dy + other[1]
                return AffineVector(self.I, self.I.translate(Vector(Dx, Dy)))
        if other.I != self.I:
            raise OperationNotPermitedException("You can only add vectors\
                            with same base point.")
        I = self.I
        Dx = self.Dx + other.Dx
        Dy = self.Dy + other.Dy
        return AffineVector(self.I, self.I.translate(Vector(Dx, Dy)))

    def __sub__(self, other):
        return self + (-other)

    def __mul__(self, coef):
        I = self.I
        nx = self.I.x + self.Dx * coef
        ny = self.I.y + self.Dy * coef
        F = Point(nx, ny)
        return AffineVector(I, F)

    def __rmul__(self, coef):
        return self * coef

    def __truediv__(self, coef):
        return self * (1 / coef)

    def __div__(self, coef):
        # The real division is __truedev__. This one is
        # for legacy.
        return self / coef

    def __rdiv__(self, coef):
        return self * (1 / coef)

    def __neg__(self):
        """
        return -self. 

        That is an affine vector attached to the same point, but
        with the opposite direction.
        """
        nx = self.I.x - self.Dx
        ny = self.I.y - self.Dy
        return AffineVector(self.I, Point(nx, ny))

    def __eq__(self, other):
        if self.I != other.I:
            return False
        if self.F != other.F:
            return False
        return True

    def is_almost_equal(self, other):
        if not self.I.is_almost_equal(other.I):
            return False
        if not self.F.is_almost_equal(other.F):
            return False
        return True

    def __ne__(self, other):
        return not self == other

    def mark_point(self, pspict=None):
        return self.F.copy()

    def tikz_code(self, pspict=None):
        params = self.params(language="tikz")
        params = params + ",->,>=latex"
        I_coord = self.I.coordinates(digits=5, pspict=pspict)
        F_coord = self.F.coordinates(digits=5, pspict=pspict)
        a = "\draw [{0}] {1} -- {2};".format(params,
                                             I_coord,
                                             F_coord,
                                             pspict=pspict)
        return a

    def latex_code(self, language=None, pspict=None):
        if self.parameters.style == "none":
            return ""
        if language == "tikz":
            return self.tikz_code(pspict=pspict)
Пример #25
0
 def __init__(self, I, F):
     ObjectGraph.__init__(self, self)
     self.I = I
     self.F = F
     self.segment = Segment(self.I, self.F)
Пример #26
0
class SurfaceBetweenLines(ObjectGraph):
    def __init__(self, curve1, curve2):
        """
        Give the graph of the surface between the two lines.

        The lines are needed to have a starting and ending point
        that will be joined by straight lines.
        """
        from yanntricks.src.segment import Segment
        # By convention, the first line goes from left to right and the second one to right to left.

        ObjectGraph.__init__(self, self)

        if curve1.I.x > curve1.F.x:
            curve1 = curve1.reverse()
        if curve2.I.x > curve2.F.x:
            curve2 = curve2.reverse()

        self.curve1 = curve1
        self.curve2 = curve2

        self.I1 = curve1.I
        self.I2 = curve2.I

        self.F1 = curve1.F
        self.F2 = curve2.F

        self.Isegment = Segment(self.I1, self.I2)
        self.Fsegment = Segment(self.F1, self.F2)

    def _bounding_box(self, pspict=None):
        bb = BoundingBox()
        bb.append(self.curve1, pspict)
        bb.append(self.curve2, pspict)
        return bb

    def _math_bounding_box(self, pspict):
        return self.bounding_box(pspict)

    def latex_code(self, language=None, pspict=None):
        from yanntricks.src.segment import Segment
        a = []

        c1 = self.curve1
        c2 = self.curve2.reverse()

        custom = CustomSurface(c1, self.Fsegment, c2, self.Isegment)
        self.parameters.add_to(
            custom.parameters
        )  # This curve is essentially dedicated to the colors
        custom.options = self.options

        a.append("%--- begin of Surface between lines ---")
        a.append("% Custom surface")
        a.append(custom.latex_code(language=language, pspict=pspict))

        a.append("% Curve 1")
        a.append(self.curve1.latex_code(language=language, pspict=pspict))
        a.append("% Curve 2")
        a.append(self.curve2.latex_code(language=language, pspict=pspict))
        a.append("% Isegment")
        a.append(self.Isegment.latex_code(language=language, pspict=pspict))
        a.append("% Fsegment")
        a.append(self.Fsegment.latex_code(language=language, pspict=pspict))
        a.append("%--- end of Surface between lines ---")
        return "\n".join(a)
Пример #27
0
def point_to_box_intersection(P, box, pspict=None):
    """
    The intersection between the line from the given point and
    the center of the given box.

    P : a point
    box : a box, which means a duck which has attributes
                  `xmin`, `xmax`, `ymin`, `ymax`

    Consider the line from `P` to the center of the box
    and return the intersection
    points.

    return a list of `Point`.

    - The list always contains exactly 2 points
    - They are sorted by order of distance to `P`
    """
    from yanntricks.src.point import Point
    from yanntricks.src.segment import Segment
    A = Point(box.xmin, box.ymin)
    B = Point(box.xmax, box.ymin)
    C = Point(box.xmax, box.ymax)
    D = Point(box.xmin, box.ymax)
    center = (A + B + C + D) / 4
    line = Segment(P, center)

    edges = [Segment(A, B), Segment(B, C), Segment(C, D), Segment(D, A)]
    inter = []
    for ed in edges:
        c = Intersection(line, ed)
        if len(c) > 0:
            S = c[0]

            # We deal with the case in which the line travers the corner.
            # In this case, the line passes trough the other one.
            if S == A:
                inter = [A, C]
            if S == B:
                inter = [B, D]
            if S == C:
                inter = [A, C]
            if S == D:
                inter = [B, D]
            # The last two tests are to know if S lies
            # between ed.I and ed.F
            # We use numerical approximations in order to avoid some
            # OverflowError: Python int too large to convert to C long
            elif numerical_approx((S.x - ed.I.x) * (S.x - ed.F.x)) < 0:
                inter.append(S)
            elif numerical_approx((S.y - ed.I.y) * (S.y - ed.F.y)) < 0:
                inter.append(S)

    if len(inter) == 2:
        inter.sort(key=lambda Q: distance_sq(Q, P, numerical=True))

    if pspict:
        for i, S in enumerate(inter):
            S.put_mark(0.2,
                       angle=None,
                       added_angle=0,
                       text=str(i),
                       pspict=pspict)
        pspict.DrawGraphs(inter, line, center, box)

    return inter