91
91
from sage .misc .lazy_import import lazy_import
92
92
lazy_import ("sage.plot.arc" , "arc" )
93
93
lazy_import ("sage.plot.line" , "line" )
94
+ lazy_import ("sage.plot.arc" , "arc" )
95
+ lazy_import ("sage.plot.bezier_path" , "bezier_path" )
94
96
from sage .symbolic .constants import pi
95
97
from sage .modules .free_module_element import vector
96
98
from sage .matrix .constructor import matrix
@@ -696,15 +698,27 @@ def complete(self):
696
698
::
697
699
698
700
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()
700
702
Geodesic in KM from (0, -1) to (0, 1)
701
703
702
704
.. PLOT::
703
705
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))
705
718
h = g.complete()
706
719
sphinx_plot(g.plot()+h.plot(linestyle='dashed'))
707
720
721
+
708
722
::
709
723
710
724
sage: HM = H.HM()
@@ -1186,12 +1200,15 @@ def plot(self, boundary=True, **options):
1186
1200
elif end_2 == CC (infinity ):
1187
1201
end_2 = (real (end_1 ), (imag (end_1 ) + 10 ))
1188
1202
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 )
1190
1207
if boundary :
1191
1208
cent = min (bd_1 , bd_2 )
1192
1209
bd_dict = {'bd_min' : cent - 3 , 'bd_max' : cent + 3 }
1193
1210
bd_pic = self ._model .get_background_graphic (** bd_dict )
1194
- pic = bd_pic + pic
1211
+ pic + = bd_pic
1195
1212
return pic
1196
1213
else :
1197
1214
center = (bd_1 + bd_2 ) / 2 # Circle center
@@ -1213,7 +1230,7 @@ def plot(self, boundary=True, **options):
1213
1230
bd_dict = {'bd_min' : midpoint - length , 'bd_max' : midpoint +
1214
1231
length }
1215
1232
bd_pic = self ._model .get_background_graphic (** bd_dict )
1216
- pic = bd_pic + pic
1233
+ pic + = bd_pic
1217
1234
return pic
1218
1235
1219
1236
def ideal_endpoints (self ):
@@ -1244,10 +1261,10 @@ def ideal_endpoints(self):
1244
1261
M = self ._model
1245
1262
# infinity is the first endpoint, so the other ideal endpoint
1246
1263
# is just the real part of the second coordinate
1247
- if start == infinity :
1264
+ if CC ( start ). is_infinity () :
1248
1265
return [M .get_point (start ), M .get_point (x2 )]
1249
1266
# Same idea as above
1250
- if end == infinity :
1267
+ if CC ( end ). is_infinity () :
1251
1268
return [M .get_point (x1 ), M .get_point (end )]
1252
1269
# We could also have a vertical line with two interior points
1253
1270
if x1 == x2 :
@@ -2174,11 +2191,9 @@ class HyperbolicGeodesicPD(HyperbolicGeodesic):
2174
2191
g = PD.get_geodesic(I,-I/2)
2175
2192
h = PD.get_geodesic(-0.5+I*0.5,0.5+I*0.5)
2176
2193
sphinx_plot(g.plot()+h.plot(color='green'))
2177
-
2178
2194
"""
2179
2195
2180
2196
def plot (self , boundary = True , ** options ):
2181
-
2182
2197
r"""
2183
2198
Plot ``self``.
2184
2199
@@ -2235,7 +2250,7 @@ def plot(self, boundary=True, **options):
2235
2250
bd_1 , bd_2 = [CC (k .coordinates ()) for k in self .ideal_endpoints ()]
2236
2251
# Check to see if it's a line
2237
2252
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 )
2239
2254
else :
2240
2255
# If we are here, we know it's not a line
2241
2256
# So we compute the center and radius of the circle
@@ -2276,20 +2291,18 @@ class HyperbolicGeodesicKM(HyperbolicGeodesic):
2276
2291
EXAMPLES::
2277
2292
2278
2293
sage: KM = HyperbolicPlane().KM()
2279
- sage: g = KM.get_geodesic(KM.get_point((0.1,0.9)), KM.get_point((-0.1,-0.9)))
2280
2294
sage: g = KM.get_geodesic((0.1,0.9),(-0.1,-0.9))
2281
2295
sage: h = KM.get_geodesic((-0.707106781,-0.707106781),(0.707106781,-0.707106781))
2282
2296
sage: P = g.plot(color='orange')+h.plot(); P # optional - sage.plot
2283
2297
Graphics object consisting of 4 graphics primitives
2284
2298
2285
-
2286
2299
.. PLOT::
2287
2300
2288
2301
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))
2293
2306
sphinx_plot(g.plot(color='orange')+h.plot())
2294
2307
2295
2308
"""
@@ -2300,19 +2313,24 @@ def plot(self, boundary=True, **options):
2300
2313
2301
2314
EXAMPLES::
2302
2315
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
2304
2317
Graphics object consisting of 2 graphics primitives
2305
2318
2306
2319
.. PLOT::
2307
2320
2308
2321
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())
2310
2323
2311
2324
"""
2312
2325
opts = {'axes' : False , 'aspect_ratio' : 1 }
2313
2326
opts .update (self .graphics_options ())
2314
2327
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 )
2316
2334
if boundary :
2317
2335
pic += self ._model .get_background_graphic ()
2318
2336
return pic
@@ -2334,7 +2352,6 @@ class HyperbolicGeodesicHM(HyperbolicGeodesic):
2334
2352
2335
2353
EXAMPLES::
2336
2354
2337
- sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic import *
2338
2355
sage: HM = HyperbolicPlane().HM()
2339
2356
sage: p1 = HM.get_point((4, -4, sqrt(33)))
2340
2357
sage: p2 = HM.get_point((-3,-3,sqrt(19)))
@@ -2350,6 +2367,51 @@ class HyperbolicGeodesicHM(HyperbolicGeodesic):
2350
2367
sphinx_plot(g.plot(color='blue'))
2351
2368
2352
2369
"""
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
2353
2415
2354
2416
def plot (self , show_hyperboloid = True , ** graphics_options ):
2355
2417
r"""
0 commit comments