Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 6d37580

Browse files
author
Matthias Koeppe
committed
Merge #22081
2 parents e29006b + 3f367ec commit 6d37580

File tree

6 files changed

+746
-217
lines changed

6 files changed

+746
-217
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,10 @@ REFERENCES:
13841384
.. [CFI1992] Cai, JY., Fürer, M. & Immerman, N. Combinatorica (1992) 12: 389.
13851385
:doi:`10.1007/BF01305232`
13861386
1387+
.. [CFKP1997] James W. Cannon, William J. Floyd, Richard Kenyon and Walter R. Parry.
1388+
*Hyperbolic Geometry*. Flavors of Geometry, MSRI Publications,
1389+
Volume 31, 1997.
1390+
13871391
.. [CFKPR2010] Ioannis Caragiannis, Afonso Ferreira, Christos Kaklamanis,
13881392
Stéphane Pérennes, Hervé Rivano.
13891393
*Fractional Path Coloring in Bounded Degree Trees with
@@ -5308,6 +5312,9 @@ REFERENCES:
53085312
Variable I. Lecture Notes in Mathematics,
53095313
vol 320. (1973), Springer, Berlin, Heidelberg
53105314
5315+
.. [Sta1993] Stahl, Saul: *The Poincaré Half-plane: A Gateway to Modern Geometry*
5316+
Jones & Bartlett Learning, 1993. ISBN 086720298X, 9780867202984
5317+
53115318
.. [Sta1995] \R. P. Stanley, *A symmetric function generalization
53125319
of the chromatic polynomial of a graph*, Adv. Math., ***111***
53135320
no.1 (1995), 166-194. :doi:`10.1006/aima.1995.1020`.

src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
from sage.misc.lazy_import import lazy_import
9292
lazy_import("sage.plot.arc", "arc")
9393
lazy_import("sage.plot.line", "line")
94+
lazy_import("sage.plot.arc", "arc")
95+
lazy_import("sage.plot.bezier_path", "bezier_path")
9496
from sage.symbolic.constants import pi
9597
from sage.modules.free_module_element import vector
9698
from 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

Comments
 (0)