9191from sage .misc .lazy_import import lazy_import
9292lazy_import ("sage.plot.arc" , "arc" )
9393lazy_import ("sage.plot.line" , "line" )
94+ lazy_import ("sage.plot.arc" , "arc" )
95+ lazy_import ("sage.plot.bezier_path" , "bezier_path" )
9496from sage .symbolic .constants import pi
9597from sage .modules .free_module_element import vector
9698from sage .matrix .constructor import matrix
@@ -696,15 +698,27 @@ def complete(self):
696698 ::
697699
698700 sage: KM = H.KM()
699- sage: KM.get_geodesic((0,0), (0, 1/2)).complete()
701+ sage: KM.get_geodesic((0,0), (0,1/2)).complete()
700702 Geodesic in KM from (0, -1) to (0, 1)
701703
702704 .. PLOT::
703705
704- g = HyperbolicPlane().KM().get_geodesic((0.0,0.0), (0.0, 0.5))
706+ g = HyperbolicPlane().KM().get_geodesic(CC(0,0), CC(0, 0.5))
707+ h = g.complete()
708+ sphinx_plot(g.plot()+h.plot(linestyle='dashed'))
709+
710+ ::
711+
712+ sage: KM.get_geodesic(-I, 1).complete()
713+ Geodesic in KM from -I to 1
714+
715+ .. PLOT::
716+
717+ g = HyperbolicPlane().KM().get_geodesic(CC(0,-1), CC(1, 0))
705718 h = g.complete()
706719 sphinx_plot(g.plot()+h.plot(linestyle='dashed'))
707720
721+
708722 ::
709723
710724 sage: HM = H.HM()
@@ -1186,12 +1200,15 @@ def plot(self, boundary=True, **options):
11861200 elif end_2 == CC (infinity ):
11871201 end_2 = (real (end_1 ), (imag (end_1 ) + 10 ))
11881202 end_1 = (real (end_1 ), imag (end_1 ))
1189- pic = line ((end_1 , end_2 ), ** opts )
1203+ else :
1204+ end_1 = (real (end_1 ), imag (end_1 ))
1205+ end_2 = (real (end_2 ), imag (end_2 ))
1206+ pic = bezier_path ([[end_1 , end_2 ]], ** opts )
11901207 if boundary :
11911208 cent = min (bd_1 , bd_2 )
11921209 bd_dict = {'bd_min' : cent - 3 , 'bd_max' : cent + 3 }
11931210 bd_pic = self ._model .get_background_graphic (** bd_dict )
1194- pic = bd_pic + pic
1211+ pic + = bd_pic
11951212 return pic
11961213 else :
11971214 center = (bd_1 + bd_2 ) / 2 # Circle center
@@ -1213,7 +1230,7 @@ def plot(self, boundary=True, **options):
12131230 bd_dict = {'bd_min' : midpoint - length , 'bd_max' : midpoint +
12141231 length }
12151232 bd_pic = self ._model .get_background_graphic (** bd_dict )
1216- pic = bd_pic + pic
1233+ pic + = bd_pic
12171234 return pic
12181235
12191236 def ideal_endpoints (self ):
@@ -1244,10 +1261,10 @@ def ideal_endpoints(self):
12441261 M = self ._model
12451262 # infinity is the first endpoint, so the other ideal endpoint
12461263 # is just the real part of the second coordinate
1247- if start == infinity :
1264+ if CC ( start ). is_infinity () :
12481265 return [M .get_point (start ), M .get_point (x2 )]
12491266 # Same idea as above
1250- if end == infinity :
1267+ if CC ( end ). is_infinity () :
12511268 return [M .get_point (x1 ), M .get_point (end )]
12521269 # We could also have a vertical line with two interior points
12531270 if x1 == x2 :
@@ -2174,11 +2191,9 @@ class HyperbolicGeodesicPD(HyperbolicGeodesic):
21742191 g = PD.get_geodesic(I,-I/2)
21752192 h = PD.get_geodesic(-0.5+I*0.5,0.5+I*0.5)
21762193 sphinx_plot(g.plot()+h.plot(color='green'))
2177-
21782194 """
21792195
21802196 def plot (self , boundary = True , ** options ):
2181-
21822197 r"""
21832198 Plot ``self``.
21842199
@@ -2235,7 +2250,7 @@ def plot(self, boundary=True, **options):
22352250 bd_1 , bd_2 = [CC (k .coordinates ()) for k in self .ideal_endpoints ()]
22362251 # Check to see if it's a line
22372252 if abs (bd_1 + bd_2 ) < EPSILON :
2238- pic = line ([ end_1 , end_2 ], ** opts )
2253+ pic = bezier_path ([[( real ( end_1 ), imag ( end_1 )), ( real ( end_2 ), imag ( end_2 ))] ], ** opts )
22392254 else :
22402255 # If we are here, we know it's not a line
22412256 # So we compute the center and radius of the circle
@@ -2276,20 +2291,18 @@ class HyperbolicGeodesicKM(HyperbolicGeodesic):
22762291 EXAMPLES::
22772292
22782293 sage: KM = HyperbolicPlane().KM()
2279- sage: g = KM.get_geodesic(KM.get_point((0.1,0.9)), KM.get_point((-0.1,-0.9)))
22802294 sage: g = KM.get_geodesic((0.1,0.9),(-0.1,-0.9))
22812295 sage: h = KM.get_geodesic((-0.707106781,-0.707106781),(0.707106781,-0.707106781))
22822296 sage: P = g.plot(color='orange')+h.plot(); P # optional - sage.plot
22832297 Graphics object consisting of 4 graphics primitives
22842298
2285-
22862299 .. PLOT::
22872300
22882301 KM = HyperbolicPlane().KM()
2289- g = KM.get_geodesic((0.1,0.9),
2290- (-0.1,-0.9))
2291- h = KM.get_geodesic((-0.707106781,-0.707106781),
2292- (0.707106781,-0.707106781))
2302+ g = KM.get_geodesic(CC (0.1,0.9),
2303+ CC (-0.1,-0.9))
2304+ h = KM.get_geodesic(CC (-0.707106781,-0.707106781),
2305+ CC (0.707106781,-0.707106781))
22932306 sphinx_plot(g.plot(color='orange')+h.plot())
22942307
22952308 """
@@ -2300,19 +2313,24 @@ def plot(self, boundary=True, **options):
23002313
23012314 EXAMPLES::
23022315
2303- sage: HyperbolicPlane().KM().get_geodesic((0,0), (1,0) ).plot() # optional - sage.plot
2316+ sage: HyperbolicPlane().KM().get_geodesic(0, 1 ).plot() # optional - sage.plot
23042317 Graphics object consisting of 2 graphics primitives
23052318
23062319 .. PLOT::
23072320
23082321 KM = HyperbolicPlane().KM()
2309- sphinx_plot(KM.get_geodesic((0,0), (1,0)).plot())
2322+ sphinx_plot(KM.get_geodesic(CC (0,0), CC (1,0)).plot())
23102323
23112324 """
23122325 opts = {'axes' : False , 'aspect_ratio' : 1 }
23132326 opts .update (self .graphics_options ())
23142327 opts .update (options )
2315- pic = line ([k .coordinates () for k in self .endpoints ()], ** opts )
2328+ def map_pt (pt ):
2329+ if pt in CC :
2330+ return CC (pt )
2331+ return CC (* pt )
2332+ end_1 , end_2 = [map_pt (k .coordinates ()) for k in self .endpoints ()]
2333+ pic = bezier_path ([[(real (end_1 ), imag (end_1 )), (real (end_2 ), imag (end_2 ))]], ** opts )
23162334 if boundary :
23172335 pic += self ._model .get_background_graphic ()
23182336 return pic
@@ -2334,7 +2352,6 @@ class HyperbolicGeodesicHM(HyperbolicGeodesic):
23342352
23352353 EXAMPLES::
23362354
2337- sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic import *
23382355 sage: HM = HyperbolicPlane().HM()
23392356 sage: p1 = HM.get_point((4, -4, sqrt(33)))
23402357 sage: p2 = HM.get_point((-3,-3,sqrt(19)))
@@ -2350,6 +2367,51 @@ class HyperbolicGeodesicHM(HyperbolicGeodesic):
23502367 sphinx_plot(g.plot(color='blue'))
23512368
23522369 """
2370+ def _plot_vertices (self , points = 75 ):
2371+ r"""
2372+ Return ``self`` plotting vertices in `\RR^3`.
2373+
2374+ Auxiliary function needed to plot polygons.
2375+
2376+ EXAMPLES::
2377+
2378+ sage: HM = HyperbolicPlane().HM()
2379+ sage: p1 = HM.get_point((4, -4, sqrt(33)))
2380+ sage: p2 = HM.get_point((-3,-3,sqrt(19)))
2381+ sage: g = HM.get_geodesic(p1, p2)
2382+ sage: g._plot_vertices(5)
2383+ [(4.0, -4.0, 5.744562646538029),
2384+ (1.3632131724692114, -1.6370738298435326, 2.353372235315133),
2385+ (0.13856858387448234, -0.9699800871213693, 1.4000223647674197),
2386+ (-0.9425338542843988, -1.3076813974501533, 1.8969450977056184),
2387+ (-3.0, -3.0, 4.358898943540652)]
2388+ """
2389+ from sage .plot .misc import setup_for_eval_on_grid
2390+ from sage .arith .srange import xsrange
2391+
2392+ x = SR .var ('x' )
2393+ v1 , u2 = [vector (k .coordinates ()) for k in self .endpoints ()]
2394+ # Lorentzian Gram Shmidt. The original vectors will be
2395+ # u1, u2 and the orthogonal ones will be v1, v2. Except
2396+ # v1 = u1, and I don't want to declare another variable,
2397+ # hence the odd naming convention above.
2398+ # We need the Lorentz dot product of v1 and u2.
2399+ v1_ldot_u2 = u2 [0 ]* v1 [0 ] + u2 [1 ]* v1 [1 ] - u2 [2 ]* v1 [2 ]
2400+ v2 = u2 + v1_ldot_u2 * v1
2401+ v2_norm = sqrt (v2 [0 ]** 2 + v2 [1 ]** 2 - v2 [2 ]** 2 )
2402+ v2 = v2 / v2_norm
2403+ v2_ldot_u2 = u2 [0 ]* v2 [0 ] + u2 [1 ]* v2 [1 ] - u2 [2 ]* v2 [2 ]
2404+ # Now v1 and v2 are Lorentz orthogonal, and |v1| = -1, |v2|=1
2405+ # That is, v1 is unit timelike and v2 is unit spacelike.
2406+ # This means that cosh(x)*v1 + sinh(x)*v2 is unit timelike.
2407+ hyperbola = tuple (cosh (x )* v1 + sinh (x )* v2 )
2408+ endtime = arcsinh (v2_ldot_u2 )
2409+ # mimic the function _parametric_plot3d_curve using a bezier3d instead of a line3d
2410+ # this is required in order to be able to plot hyperbolic polygons whithin the plot library
2411+ g , ranges = setup_for_eval_on_grid (hyperbola , [(x , 0 , endtime )], points )
2412+ f_x , f_y , f_z = g
2413+ points = [(f_x (u ), f_y (u ), f_z (u )) for u in xsrange (* ranges [0 ], include_endpoint = True )]
2414+ return points
23532415
23542416 def plot (self , show_hyperboloid = True , ** graphics_options ):
23552417 r"""
0 commit comments