Exemple #1
0
    def _hyperbolic_arc_d(self, z0, z3, first=False):
        """
        Function to construct Bezier path as an approximation to
        the hyperbolic arc between the complex numbers z0 and z3 in the
        hyperbolic plane.
        """
        w0 = self._cayley_transform(z0)
        w3 = self._cayley_transform(z3)
        if w0.real()==0 and w3.real() == 0:
            y = (w0.imag() + w0.imag())/2
            #self.path.append([(0,w0.imag()),CC(0,y), (0,w3.imag())])
            self._graphics.add_primitive(BezierPath([(0,w0.imag()),CC(0,y), (0,w3.imag())],self._options))
            return
        z0,z3 = CC(z0), CC(z3) 
        if z0.imag() == 0 and z3.imag() == 0:
            p = (z0.real()+z3.real())/2
            r = abs(z0-p)
            zm = CC(p, r)
            self._hyperbolic_arc_d(z0, zm, first)
            self._hyperbolic_arc_d(zm, z3)
            return
        else:
            p = (abs(z0)*abs(z0)-abs(z3)*abs(z3))/(z0-z3).real()/2 # center of the circle in H
            r = abs(z0-p) # radius of the circle in H
            zm = ((z0+z3)/2-p)/abs((z0+z3)/2-p)*r+p
            t = (8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()
            z1 = z0 + t*CC(z0.imag(), (p-z0.real()))
            z2 = z3 - t*CC(z3.imag(), (p-z3.real()))
            zm = self._cayley_transform(zm)
            w1 = self._cayley_transform(z1)
            w2 = self._cayley_transform(z2)

            c = self._cayley_transform(CC(p,0)) # center of circle on the unit disk.
            r = abs(w1-c) # radius
            theta = t
        self._graphics.add_primitive(Arc((zm.real(),zm.imag()),r,sector=(-t,t),options=self._options))
Exemple #2
0
def _geodesic_between_two_points_d(x1,y1,x2,y2,z0=I):
    r""" Geodesic path between two points represented in the unit disc
         by the map w = (z-I)/(z+I)
    INPUTS:
    - ''(x1,y1)'' -- starting point (0<y1<=infinity)
    - ''(x2,y2)'' -- ending point   (0<y2<=infinity)
    - ''z0''  -- (default I) the point in the upper corresponding
                 to the point 0 in the disc. I.e. the transform is
                 w -> (z-I)/(z+I)
    OUTPUT:
    - ''ca'' -- a polygonal approximation of a circular arc centered
    at c and radius r, starting at t0 and ending at t1

    
    EXAMPLES::

        sage: l=_geodesic_between_two_points_d(0.1,0.2,0.0,0.5)
    
    """
    pi=RR.pi()
    from sage.plot.plot import line
    from sage.functions.trig import (cos,sin)    
    # First compute the points
    if(y1<0  or y2<0 ):
        raise ValueError,"Need points in the upper half-plane! Got y1=%s, y2=%s" %(y1,y2)
    if(y1==infinity):
        P1=CC(1 )
    else:
        P1=CC((x1+I*y1-z0)/(x1+I*y1-z0.conjugate()))
    if(y2==infinity):
        P2=CC(1 )
    else:
        P2=CC((x2+I*y2-z0)/(x2+I*y2-z0.conjugate()))
        # First find the endpoints of the completed geodesic in D
    if(x1==x2):
        a=CC((x1-z0)/(x1-z0.conjugate()))
        b=CC(1 )
    else:
        c=RR(y1**2 -y2**2 +x1**2 -x2**2 )/RR(2 *(x1-x2))
        r=RR(sqrt(y1**2 +(x1-c)**2 ))
        a=c-r
        b=c+r
        a=CC((a-z0)/(a-z0.conjugate()))
        b=CC((b-z0)/(b-z0.conjugate()))
    if( abs(a+b) < 1E-10 ): # On a diagonal
        return line([[P1.real(),P1.imag()],[P2.real(),P2.imag()]])
    th_a=a.argument()
    th_b=b.argument()
    # Compute the center of the circle in the disc model
    if( min(abs(b-1 ),abs(b+1 ))< 1E-10  and  min(abs(a-1 ),abs(a+1 ))>1E-10 ):
        c=b+I*(1 -b*cos(th_a))/sin(th_a)
    elif( min(abs(b-1 ),abs(b+1 ))> 1E-10  and  min(abs(a-1 ),abs(a+1 ))<1E-10 ):
        c=a+I*(1 -a*cos(th_b))/RR(sin(th_b))
    else:
        cx=(sin(th_b)-sin(th_a))/sin(th_b-th_a)
        c=cx+I*(1 -cx*cos(th_b))/RR(sin(th_b))
    # First find the endpoints of the completed geodesic
    r=abs(c-a)
    t1=CC(P1-c).argument()
    t2=CC(P2-c).argument()
    #print "t1,t2=",t1,t2
    return _circ_arc(t1,t2,c,r)
Exemple #3
0
    def _hyperbolic_arc_d(self, z0, z3, first=False):
        """
        Function to construct Bezier path as an approximation to
        the hyperbolic arc between the complex numbers z0 and z3 in the
        hyperbolic plane.
        """

        w0 = self._cayley_transform(z0)
        w3 = self._cayley_transform(z3)
        if self._verbose>0:
            print "in plane z0,z3=",z0,z3
            print "in disc: ",w0,w3
        npts = self._npts
        if z0 == infinity or z0==CC(infinity):
            zm = [z3 + CC(0,j+0.5) for j in range(npts-2)]
            wm = [self._cayley_transform(x) for x in zm]
            pts = [w3]
            pts.extend(wm)
            pts.append(w0)
            opt = self._options
            opt['fill']=False
            self._graphics.add_primitive(BezierPath([[(x.real(),x.imag()) for x in pts ]],opt))
            return 
        if z3 == infinity  or z3==CC(infinity):
            zm = [z0 + CC(0,j+0.5) for j in range(npts-2)]
            wm = [self._cayley_transform(x) for x in zm]
            pts = [w0]
            pts.extend(wm)
            pts.append(w3)
            opt = self._options
            opt['fill']=False
            self._graphics.add_primitive(BezierPath([[(x.real(),x.imag()) for x in pts ]],opt))
            #self._graphics.add_primitive(Line([w1.real(),w2.real()],[w1.imag(),w2.imag()],self._options))
            #self.path.append([(0,w0.imag()),CC(0,y), (0,w3.imag())])
            return
        x0=z0.real(); y0 = z0.imag()
        x3=z3.real(); y3 = z3.imag()
        if y0 == 0 and y3 == 0:
            p = (z0.real()+z3.real())/2
            r = abs(z0-p)
            zm = CC(p, r)
            self._hyperbolic_arc_d(z0, zm, first)
            self._hyperbolic_arc_d(zm, z3)
            return                   
        else:
            if abs(x0-x3)<1e-10:  ## on the same vertical line
                xmid = (x0+x3)*0.5; h = y3-y0
                zm = [ CC(xmid,y0+t*h/(npts-1)) for t in range(npts) ]
            else:
                p = RR((x0+x3)*(x3-x0)+(y0+y3)*(y3-y0))/(2*(x3-x0)) 
                r = RR((p - x0)**2 + y0**2).sqrt()  # radius of the circle in H
                zm = ((z0+z3)/2-p)/abs((z0+z3)/2-p)*r+p  # midpoint (at least approximately) of geodesic between z0 and z3
                t0 = CC(z0 - p).argument()
                t3 = CC(z3 - p).argument()
                if self._verbose>1:
                    print "x0,x3=",x0,x3
                    print "t0,t3=",t0,t3
                    print "r=",r
                    print "opt=",self._options
                if x0 <= x3:
                    zm = [p + r*CC(0,(t0+t*(t3-t0)/(npts-1))).exp() for t in range(npts)]
                else:
                    zm = [p + r*CC(0,(t0+t*(t3-t0)/(npts-1))).exp() for t in range(npts)]            
                #print "zm=",zm
                #zm.insert(0,z0)
                #zm.append(z3)
            pts = [self._cayley_transform(x) for x in zm]
            opt = self._options
            opt['fill']=False
            #w0 = self._cayley_transform(z0)
            #w3 = self._cayley_transform(z3)

            if self._verbose>2:
                print "pts=",pts
            self._graphics.add_primitive(BezierPath([[(x.real(),x.imag()) for x in pts ]],opt))
            return 
            #print "z0_test=",(p+r*exp(t0*I))
                #print "z3_test=",(p+r*exp(t3*I))
#t = (8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()
            # I have no idea what these points should represent....
            #z1 = z0 + t*CC(z0.imag(), (p-z0.real()))
            #z2 = z3 - t*CC(z3.imag(), (p-z3.real()))
            wm = [self._cayley_transform(x) for x in zm]
            pp = self._cayley_transform(CC(p,0))
            w1 = self._cayley_transform(z0)
            w2 = self._cayley_transform(z3)
            c = self._cayley_transform(CC(p,0)) # center of circle on the unit disk.
            if self._verbose>2:
                print "p,r=",p,r     
                print "zm=",zm
                #print "t=",t
                #print "tt=",(8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()

                print "C(c)=",pp
                print "C(zm)=",wm
                print "C(z0)=",w1
                print "C(z3)=",w2
                #print "z2=",z2
            
            r = abs(w1-c) # radius
            t0 = CC(w0 - pp).argument()
            t3 = CC(w3 - pp).argument()
            t = abs(t0-t3)
        if self._verbose>0:
            print "adding a:rc ",zm.real(),zm.imag(),r,r,t,t0,t3
        self._graphics.add_primitive(Line([w1.real(),w2.real(),wm.real()],[w1.imag(),w2.imag(),wm.imag()],{'thickness':2,'alpha':1,
                                                                                       'rgbcolor':'blue',
                                                                                                         'legend_label':""}))
        self._graphics.add_primitive(Point([w1.real(),w2.real(),wm.real()],[w1.imag(),w2.imag(),wm.imag()],{'size':10,'alpha':1,
                                                                                                            'faceted':True,
                                                                                                            'rgbcolor':'red',
                                                                                                            'legend_label':""}))
Exemple #4
0
def _geodesic_between_two_points_d(x1, y1, x2, y2, z0=I):
    r""" Geodesic path between two points represented in the unit disc
         by the map w = (z-I)/(z+I)
    INPUTS:
    - ''(x1,y1)'' -- starting point (0<y1<=infinity)
    - ''(x2,y2)'' -- ending point   (0<y2<=infinity)
    - ''z0''  -- (default I) the point in the upper corresponding
                 to the point 0 in the disc. I.e. the transform is
                 w -> (z-I)/(z+I)
    OUTPUT:
    - ''ca'' -- a polygonal approximation of a circular arc centered
    at c and radius r, starting at t0 and ending at t1

    
    EXAMPLES::

        sage: l=_geodesic_between_two_points_d(0.1,0.2,0.0,0.5)
    
    """
    pi = RR.pi()
    from sage.plot.plot import line
    from sage.functions.trig import (cos, sin)
    # First compute the points
    if (y1 < 0 or y2 < 0):
        raise ValueError, "Need points in the upper half-plane! Got y1=%s, y2=%s" % (
            y1, y2)
    if (y1 == infinity):
        P1 = CC(1)
    else:
        P1 = CC((x1 + I * y1 - z0) / (x1 + I * y1 - z0.conjugate()))
    if (y2 == infinity):
        P2 = CC(1)
    else:
        P2 = CC((x2 + I * y2 - z0) / (x2 + I * y2 - z0.conjugate()))
        # First find the endpoints of the completed geodesic in D
    if (x1 == x2):
        a = CC((x1 - z0) / (x1 - z0.conjugate()))
        b = CC(1)
    else:
        c = RR(y1**2 - y2**2 + x1**2 - x2**2) / RR(2 * (x1 - x2))
        r = RR(sqrt(y1**2 + (x1 - c)**2))
        a = c - r
        b = c + r
        a = CC((a - z0) / (a - z0.conjugate()))
        b = CC((b - z0) / (b - z0.conjugate()))
    if (abs(a + b) < 1E-10):  # On a diagonal
        return line([[P1.real(), P1.imag()], [P2.real(), P2.imag()]])
    th_a = a.argument()
    th_b = b.argument()
    # Compute the center of the circle in the disc model
    if (min(abs(b - 1), abs(b + 1)) < 1E-10
            and min(abs(a - 1), abs(a + 1)) > 1E-10):
        c = b + I * (1 - b * cos(th_a)) / sin(th_a)
    elif (min(abs(b - 1), abs(b + 1)) > 1E-10
          and min(abs(a - 1), abs(a + 1)) < 1E-10):
        c = a + I * (1 - a * cos(th_b)) / RR(sin(th_b))
    else:
        cx = (sin(th_b) - sin(th_a)) / sin(th_b - th_a)
        c = cx + I * (1 - cx * cos(th_b)) / RR(sin(th_b))
    # First find the endpoints of the completed geodesic
    r = abs(c - a)
    t1 = CC(P1 - c).argument()
    t2 = CC(P2 - c).argument()
    #print "t1,t2=",t1,t2
    return _circ_arc(t1, t2, c, r)
Exemple #5
0
    def _hyperbolic_arc_d(self, z0, z3, first=False):
        """
        Function to construct Bezier path as an approximation to
        the hyperbolic arc between the complex numbers z0 and z3 in the
        hyperbolic plane.
        """

        w0 = self._cayley_transform(z0)
        w3 = self._cayley_transform(z3)
        if self._verbose > 0:
            print "in plane z0,z3=", z0, z3
            print "in disc: ", w0, w3
        npts = self._npts
        if z0 == infinity or z0 == CC(infinity):
            zm = [z3 + CC(0, j + 0.5) for j in range(npts - 2)]
            wm = [self._cayley_transform(x) for x in zm]
            pts = [w3]
            pts.extend(wm)
            pts.append(w0)
            opt = self._options
            opt['fill'] = False
            self._graphics.add_primitive(
                BezierPath([[(x.real(), x.imag()) for x in pts]], opt))
            return
        if z3 == infinity or z3 == CC(infinity):
            zm = [z0 + CC(0, j + 0.5) for j in range(npts - 2)]
            wm = [self._cayley_transform(x) for x in zm]
            pts = [w0]
            pts.extend(wm)
            pts.append(w3)
            opt = self._options
            opt['fill'] = False
            self._graphics.add_primitive(
                BezierPath([[(x.real(), x.imag()) for x in pts]], opt))
            #self._graphics.add_primitive(Line([w1.real(),w2.real()],[w1.imag(),w2.imag()],self._options))
            #self.path.append([(0,w0.imag()),CC(0,y), (0,w3.imag())])
            return
        x0 = z0.real()
        y0 = z0.imag()
        x3 = z3.real()
        y3 = z3.imag()
        if y0 == 0 and y3 == 0:
            p = (z0.real() + z3.real()) / 2
            r = abs(z0 - p)
            zm = CC(p, r)
            self._hyperbolic_arc_d(z0, zm, first)
            self._hyperbolic_arc_d(zm, z3)
            return
        else:
            if abs(x0 - x3) < 1e-10:  ## on the same vertical line
                xmid = (x0 + x3) * 0.5
                h = y3 - y0
                zm = [CC(xmid, y0 + t * h / (npts - 1)) for t in range(npts)]
            else:
                p = RR((x0 + x3) * (x3 - x0) + (y0 + y3) *
                       (y3 - y0)) / (2 * (x3 - x0))
                r = RR((p - x0)**2 + y0**2).sqrt()  # radius of the circle in H
                zm = ((z0 + z3) / 2 - p) / abs(
                    (z0 + z3) / 2 - p
                ) * r + p  # midpoint (at least approximately) of geodesic between z0 and z3
                t0 = CC(z0 - p).argument()
                t3 = CC(z3 - p).argument()
                if self._verbose > 1:
                    print "x0,x3=", x0, x3
                    print "t0,t3=", t0, t3
                    print "r=", r
                    print "opt=", self._options
                if x0 <= x3:
                    zm = [
                        p + r * CC(0, (t0 + t * (t3 - t0) / (npts - 1))).exp()
                        for t in range(npts)
                    ]
                else:
                    zm = [
                        p + r * CC(0, (t0 + t * (t3 - t0) / (npts - 1))).exp()
                        for t in range(npts)
                    ]
                #print "zm=",zm
                #zm.insert(0,z0)
                #zm.append(z3)
            pts = [self._cayley_transform(x) for x in zm]
            opt = self._options
            opt['fill'] = False
            #w0 = self._cayley_transform(z0)
            #w3 = self._cayley_transform(z3)

            if self._verbose > 2:
                print "pts=", pts
            self._graphics.add_primitive(
                BezierPath([[(x.real(), x.imag()) for x in pts]], opt))
            return
            #print "z0_test=",(p+r*exp(t0*I))
            #print "z3_test=",(p+r*exp(t3*I))
            #t = (8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()
            # I have no idea what these points should represent....
            #z1 = z0 + t*CC(z0.imag(), (p-z0.real()))
            #z2 = z3 - t*CC(z3.imag(), (p-z3.real()))
            wm = [self._cayley_transform(x) for x in zm]
            pp = self._cayley_transform(CC(p, 0))
            w1 = self._cayley_transform(z0)
            w2 = self._cayley_transform(z3)
            c = self._cayley_transform(CC(
                p, 0))  # center of circle on the unit disk.
            if self._verbose > 2:
                print "p,r=", p, r
                print "zm=", zm
                #print "t=",t
                #print "tt=",(8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()

                print "C(c)=", pp
                print "C(zm)=", wm
                print "C(z0)=", w1
                print "C(z3)=", w2
                #print "z2=",z2

            r = abs(w1 - c)  # radius
            t0 = CC(w0 - pp).argument()
            t3 = CC(w3 - pp).argument()
            t = abs(t0 - t3)
        if self._verbose > 0:
            print "adding a:rc ", zm.real(), zm.imag(), r, r, t, t0, t3
        self._graphics.add_primitive(
            Line([w1.real(), w2.real(), wm.real()],
                 [w1.imag(), w2.imag(), wm.imag()], {
                     'thickness': 2,
                     'alpha': 1,
                     'rgbcolor': 'blue',
                     'legend_label': ""
                 }))
        self._graphics.add_primitive(
            Point(
                [w1.real(), w2.real(), wm.real()],
                [w1.imag(), w2.imag(), wm.imag()], {
                    'size': 10,
                    'alpha': 1,
                    'faceted': True,
                    'rgbcolor': 'red',
                    'legend_label': ""
                }))