Hyperbolic Geodesics#
This module implements the abstract base class for geodesics in hyperbolic space of arbitrary dimension. It also contains the implementations for specific models of hyperbolic geometry.
AUTHORS:
Greg Laun (2013): initial version
EXAMPLES:
We can construct geodesics in the upper half plane model, abbreviated UHP for convenience:
sage: g = HyperbolicPlane().UHP().get_geodesic(2, 3)
sage: g
Geodesic in UHP from 2 to 3
This geodesic can be plotted using plot()
, in this example we will show
the axis.
sage: g.plot(axes=True) # optional - sage.plot
Graphics object consisting of 2 graphics primitives
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3 + I)
sage: g.length()
arccosh(11/2)
sage: g.plot(axes=True) # optional - sage.plot
Graphics object consisting of 2 graphics primitives
Geodesics of both types in UHP are supported:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3*I)
sage: g
Geodesic in UHP from I to 3*I
sage: g.plot() # optional - sage.plot
Graphics object consisting of 2 graphics primitives
Geodesics are oriented, which means that two geodesics with the same graph will only be equal if their starting and ending points are the same:
sage: g1 = HyperbolicPlane().UHP().get_geodesic(1,2)
sage: g2 = HyperbolicPlane().UHP().get_geodesic(2,1)
sage: g1 == g2
False
Todo
Implement a parent for all geodesics of the hyperbolic plane? Or implement geodesics as a parent in the subobjects category?
- class sage.geometry.hyperbolic_space.hyperbolic_geodesic.HyperbolicGeodesic(model, start, end, **graphics_options)#
Bases:
SageObject
Abstract base class for oriented geodesics that are not necessarily complete.
INPUT:
start
– a HyperbolicPoint or coordinates of a point in hyperbolic space representing the start of the geodesicend
– a HyperbolicPoint or coordinates of a point in hyperbolic space representing the end of the geodesic
EXAMPLES:
We can construct a hyperbolic geodesic in any model:
sage: HyperbolicPlane().UHP().get_geodesic(1, 0) Geodesic in UHP from 1 to 0 sage: HyperbolicPlane().PD().get_geodesic(1, 0) Geodesic in PD from 1 to 0 sage: HyperbolicPlane().KM().get_geodesic((0,1/2), (1/2, 0)) Geodesic in KM from (0, 1/2) to (1/2, 0) sage: HyperbolicPlane().HM().get_geodesic((0,0,1), (0,1, sqrt(2))) Geodesic in HM from (0, 0, 1) to (0, 1, sqrt(2))
- angle(other)#
Return the angle between any two given geodesics if they intersect.
INPUT:
other
– a hyperbolic geodesic in the same model asself
OUTPUT:
the angle in radians between the two given geodesics
EXAMPLES:
sage: PD = HyperbolicPlane().PD() sage: g = PD.get_geodesic(3/5*I + 4/5, 15/17*I + 8/17) sage: h = PD.get_geodesic(4/5*I + 3/5, I) sage: g.angle(h) 1/2*pi
- common_perpendicula(other)#
Return the unique hyperbolic geodesic perpendicular to two given geodesics, if such a geodesic exists. If none exists, raise a
ValueError
.INPUT:
other
– a hyperbolic geodesic in the same model asself
OUTPUT:
a hyperbolic geodesic
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(2,3) sage: h = HyperbolicPlane().UHP().get_geodesic(4,5) sage: g.common_perpendicular(h) Geodesic in UHP from 1/2*sqrt(3) + 7/2 to -1/2*sqrt(3) + 7/2
It is an error to ask for the common perpendicular of two intersecting geodesics:
sage: g = HyperbolicPlane().UHP().get_geodesic(2,4) sage: h = HyperbolicPlane().UHP().get_geodesic(3, infinity) sage: g.common_perpendicular(h) Traceback (most recent call last): ... ValueError: geodesics intersect; no common perpendicular exists
- complete()#
Return the geodesic with ideal endpoints in bounded models. Raise a
NotImplementedError
in models that are not bounded. In the following examples we represent complete geodesics by a dashed line.EXAMPLES:
sage: H = HyperbolicPlane() sage: UHP = H.UHP() sage: UHP.get_geodesic(1 + I, 1 + 3*I).complete() Geodesic in UHP from 1 to +Infinity
sage: PD = H.PD() sage: PD.get_geodesic(0, I/2).complete() Geodesic in PD from -I to I sage: PD.get_geodesic(0.25*(-1-I),0.25*(1-I)).complete() Geodesic in PD from -0.895806416477617 - 0.444444444444444*I to 0.895806416477617 - 0.444444444444444*I
sage: KM = H.KM() sage: KM.get_geodesic((0,0), (0,1/2)).complete() Geodesic in KM from (0, -1) to (0, 1)
sage: KM.get_geodesic(-I, 1).complete() Geodesic in KM from -I to 1
sage: HM = H.HM() sage: HM.get_geodesic((0,0,1), (1, 0, sqrt(2))).complete() Geodesic in HM from (0, 0, 1) to (1, 0, sqrt(2))
sage: g = HM.get_geodesic((0,0,1), (1, 0, sqrt(2))).complete() sage: g.is_complete() True
- dist(other)#
Return the hyperbolic distance from a given hyperbolic geodesic to another geodesic or point.
INPUT:
other
– a hyperbolic geodesic or hyperbolic point in the same model
OUTPUT:
the hyperbolic distance
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(2, 4.0) sage: h = HyperbolicPlane().UHP().get_geodesic(5, 7.0) sage: bool(abs(g.dist(h).n() - 1.92484730023841) < 10**-9) True
If the second object is a geodesic ultraparallel to the first, or if it is a point on the boundary that is not one of the first object’s endpoints, then return +infinity
sage: g = HyperbolicPlane().UHP().get_geodesic(2, 2+I) sage: p = HyperbolicPlane().UHP().get_point(5) sage: g.dist(p) +Infinity
- end()#
Return the starting point of the geodesic.
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3*I) sage: g.end() Point in UHP 3*I
- endpoints()#
Return a list containing the start and endpoints.
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3*I) sage: g.endpoints() [Point in UHP I, Point in UHP 3*I]
- graphics_options()#
Return the graphics options of
self
.EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 2*I, color="red") sage: g.graphics_options() {'color': 'red'}
- ideal_endpoints()#
Return the ideal endpoints in bounded models. Raise a
NotImplementedError
in models that are not bounded.EXAMPLES:
sage: H = HyperbolicPlane() sage: UHP = H.UHP() sage: UHP.get_geodesic(1 + I, 1 + 3*I).ideal_endpoints() [Boundary point in UHP 1, Boundary point in UHP +Infinity] sage: PD = H.PD() sage: PD.get_geodesic(0, I/2).ideal_endpoints() [Boundary point in PD -I, Boundary point in PD I] sage: KM = H.KM() sage: KM.get_geodesic((0,0), (0, 1/2)).ideal_endpoints() [Boundary point in KM (0, -1), Boundary point in KM (0, 1)] sage: HM = H.HM() sage: HM.get_geodesic((0,0,1), (1, 0, sqrt(2))).ideal_endpoints() Traceback (most recent call last): ... NotImplementedError: boundary points are not implemented in the HM model
- intersection(other)#
Return the point of intersection of two geodesics (if such a point exists).
INPUT:
other
– a hyperbolic geodesic in the same model asself
OUTPUT:
a hyperbolic point or geodesic
EXAMPLES:
sage: PD = HyperbolicPlane().PD()
- is_asymptotically_parallel(other)#
Return
True
ifself
andother
are asymptotically parallel andFalse
otherwise.INPUT:
other
– a hyperbolic geodesic
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: h = HyperbolicPlane().UHP().get_geodesic(-2,4) sage: g.is_asymptotically_parallel(h) True
Ultraparallel geodesics are not asymptotically parallel:
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: h = HyperbolicPlane().UHP().get_geodesic(-1,4) sage: g.is_asymptotically_parallel(h) False
No hyperbolic geodesic is asymptotically parallel to itself:
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: g.is_asymptotically_parallel(g) False
- is_complete()#
Return
True
ifself
is a complete geodesic (that is, both endpoints are on the ideal boundary) andFalse
otherwise.If we represent complete geodesics using green color and incomplete using red colors we have the following graphic:
Notice, that there is no visual indication that the vertical geodesic is complete
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: UHP.get_geodesic(1.5*I, 2.5*I).is_complete() False sage: UHP.get_geodesic(0, I).is_complete() False sage: UHP.get_geodesic(3, infinity).is_complete() True sage: UHP.get_geodesic(2,5).is_complete() True
- is_parallel(other)#
Return
True
if the two given hyperbolic geodesics are either ultra parallel or asymptotically parallel and``False`` otherwise.INPUT:
other
– a hyperbolic geodesic in any model
OUTPUT:
True
if the given geodesics are either ultra parallel or asymptotically parallel,False
if not.EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: h = HyperbolicPlane().UHP().get_geodesic(5,12) sage: g.is_parallel(h) True
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: h = HyperbolicPlane().UHP().get_geodesic(-2,4) sage: g.is_parallel(h) True
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,2) sage: h = HyperbolicPlane().UHP().get_geodesic(-1,4) sage: g.is_parallel(h) False
No hyperbolic geodesic is either ultra parallel or asymptotically parallel to itself:
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: g.is_parallel(g) False
- is_ultra_parallel(other)#
Return
True
ifself
andother
are ultra parallel andFalse
otherwise.INPUT:
other
– a hyperbolic geodesic
EXAMPLES:
sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic \ ....: import * sage: g = HyperbolicPlane().UHP().get_geodesic(0,1) sage: h = HyperbolicPlane().UHP().get_geodesic(-3,-1) sage: g.is_ultra_parallel(h) True
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: h = HyperbolicPlane().UHP().get_geodesic(2,6) sage: g.is_ultra_parallel(h) False
sage: g = HyperbolicPlane().UHP().get_geodesic(-2,5) sage: g.is_ultra_parallel(g) False
- length()#
Return the Hyperbolic length of the hyperbolic line segment.
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(2 + I, 3 + I/2) sage: g.length() arccosh(9/4)
- midpoint()#
Return the (hyperbolic) midpoint of a hyperbolic line segment.
EXAMPLES:
sage: g = HyperbolicPlane().UHP().random_geodesic() sage: m = g.midpoint() sage: end1, end2 = g.endpoints() sage: bool(abs(m.dist(end1) - m.dist(end2)) < 10**-9) True
Complete geodesics have no midpoint:
sage: HyperbolicPlane().UHP().get_geodesic(0,2).midpoint() Traceback (most recent call last): ... ValueError: the length must be finite
- model()#
Return the model to which the
HyperbolicGeodesic
belongs.EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: UHP.get_geodesic(I, 2*I).model() Hyperbolic plane in the Upper Half Plane Model sage: PD = HyperbolicPlane().PD() sage: PD.get_geodesic(0, I/2).model() Hyperbolic plane in the Poincare Disk Model sage: KM = HyperbolicPlane().KM() sage: KM.get_geodesic((0, 0), (0, 1/2)).model() Hyperbolic plane in the Klein Disk Model sage: HM = HyperbolicPlane().HM() sage: HM.get_geodesic((0, 0, 1), (0, 1, sqrt(2))).model() Hyperbolic plane in the Hyperboloid Model
- perpendicular_bisector()#
Return the perpendicular bisector of
self
ifself
has finite length. Here distance is hyperbolic distance.EXAMPLES:
sage: PD = HyperbolicPlane().PD() sage: g = PD.get_geodesic(-0.3+0.4*I,+0.7-0.1*I) sage: h = g.perpendicular_bisector().complete() sage: P = g.plot(color='blue')+h.plot(color='orange');P Graphics object consisting of 4 graphics primitives
Complete geodesics cannot be bisected:
sage: g = HyperbolicPlane().PD().get_geodesic(0, 1) sage: g.perpendicular_bisector() Traceback (most recent call last): ... ValueError: the length must be finite
- reflection_involution()#
Return the involution fixing
self
.EXAMPLES:
sage: H = HyperbolicPlane() sage: gU = H.UHP().get_geodesic(2,4) sage: RU = gU.reflection_involution(); RU Isometry in UHP [ 3 -8] [ 1 -3] sage: RU*gU == gU True sage: gP = H.PD().get_geodesic(0, I) sage: RP = gP.reflection_involution(); RP Isometry in PD [ 1 0] [ 0 -1] sage: RP*gP == gP True sage: gK = H.KM().get_geodesic((0,0), (0,1)) sage: RK = gK.reflection_involution(); RK Isometry in KM [-1 0 0] [ 0 1 0] [ 0 0 1] sage: RK*gK == gK True sage: HM = H.HM() sage: g = HM.get_geodesic((0,0,1), (1,0, n(sqrt(2)))) sage: A = g.reflection_involution() sage: B = diagonal_matrix([1, -1, 1]) sage: bool((B - A.matrix()).norm() < 10**-9) True
The above tests go through the Upper Half Plane. It remains to test that the matrices in the models do what we intend.
sage: from sage.geometry.hyperbolic_space.hyperbolic_isometry \ ....: import moebius_transform sage: R = H.PD().get_geodesic(-1,1).reflection_involution() sage: bool(moebius_transform(R.matrix(), 0) == 0) True
- start()#
Return the starting point of the geodesic.
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3*I) sage: g.start() Point in UHP I
- to_model(model)#
Convert the current object to image in another model.
INPUT:
model
– the image model
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: PD = HyperbolicPlane().PD() sage: UHP.get_geodesic(I, 2*I).to_model(PD) Geodesic in PD from 0 to 1/3*I sage: UHP.get_geodesic(I, 2*I).to_model('PD') Geodesic in PD from 0 to 1/3*I
- update_graphics(update=False, **options)#
Update the graphics options of
self
.INPUT:
update
– ifTrue
, the original option are updated rather than overwritten
EXAMPLES:
sage: g = HyperbolicPlane().UHP().get_geodesic(I, 2*I) sage: g.graphics_options() {} sage: g.update_graphics(color = "red"); g.graphics_options() {'color': 'red'} sage: g.update_graphics(color = "blue"); g.graphics_options() {'color': 'blue'} sage: g.update_graphics(True, size = 20); g.graphics_options() {'color': 'blue', 'size': 20}
- class sage.geometry.hyperbolic_space.hyperbolic_geodesic.HyperbolicGeodesicHM(model, start, end, **graphics_options)#
Bases:
HyperbolicGeodesic
A geodesic in the hyperboloid model.
Valid points in the hyperboloid model satisfy \(x^2 + y^2 - z^2 = -1\)
INPUT:
start
– aHyperbolicPoint
in hyperbolic space representing the start of the geodesicend
– aHyperbolicPoint
in hyperbolic space representing the end of the geodesic
EXAMPLES:
sage: HM = HyperbolicPlane().HM() sage: p1 = HM.get_point((4, -4, sqrt(33))) sage: p2 = HM.get_point((-3,-3,sqrt(19))) sage: g = HM.get_geodesic(p1, p2) sage: g = HM.get_geodesic((4, -4, sqrt(33)), (-3, -3, sqrt(19)))
- plot(show_hyperboloid=True, **graphics_options)#
Plot
self
.EXAMPLES:
sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic \ ....: import * sage: g = HyperbolicPlane().HM().random_geodesic() sage: g.plot() # optional - sage.plot Graphics3d Object
- class sage.geometry.hyperbolic_space.hyperbolic_geodesic.HyperbolicGeodesicKM(model, start, end, **graphics_options)#
Bases:
HyperbolicGeodesic
A geodesic in the Klein disk model.
Geodesics are represented by the chords, straight line segments with ideal endpoints on the boundary circle.
INPUT:
start
– aHyperbolicPoint
in hyperbolic space representing the start of the geodesicend
– aHyperbolicPoint
in hyperbolic space representing the end of the geodesic
EXAMPLES:
sage: KM = HyperbolicPlane().KM() sage: g = KM.get_geodesic((0.1,0.9),(-0.1,-0.9)) sage: h = KM.get_geodesic((-0.707106781,-0.707106781),(0.707106781,-0.707106781)) sage: P = g.plot(color='orange')+h.plot(); P # optional - sage.plot Graphics object consisting of 4 graphics primitives
- plot(boundary=True, **options)#
Plot
self
.EXAMPLES:
sage: HyperbolicPlane().KM().get_geodesic(0, 1).plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives
- class sage.geometry.hyperbolic_space.hyperbolic_geodesic.HyperbolicGeodesicPD(model, start, end, **graphics_options)#
Bases:
HyperbolicGeodesic
A geodesic in the Poincaré disk model.
Geodesics in this model are represented by segments of circles contained within the unit disk that are orthogonal to the boundary of the disk, plus all diameters of the disk.
INPUT:
start
– aHyperbolicPoint
in hyperbolic space representing the start of the geodesicend
– aHyperbolicPoint
in hyperbolic space representing the end of the geodesic
EXAMPLES:
sage: PD = HyperbolicPlane().PD() sage: g = PD.get_geodesic(PD.get_point(I), PD.get_point(-I/2)) sage: g = PD.get_geodesic(I,-I/2) sage: h = PD.get_geodesic(-1/2+I/2,1/2+I/2)
- plot(boundary=True, **options)#
Plot
self
.EXAMPLES:
First some lines:
sage: PD = HyperbolicPlane().PD() sage: PD.get_geodesic(0, 1).plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives
sage: PD.get_geodesic(0, 0.3+0.8*I).plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives
Then some generic geodesics:
sage: PD.get_geodesic(-0.5, 0.3+0.4*I).plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives sage: g = PD.get_geodesic(-1, exp(3*I*pi/7)) sage: G = g.plot(linestyle="dashed",color="red"); G # optional - sage.plot Graphics object consisting of 2 graphics primitives sage: h = PD.get_geodesic(exp(2*I*pi/11), exp(1*I*pi/11)) sage: H = h.plot(thickness=6, color="orange"); H # optional - sage.plot Graphics object consisting of 2 graphics primitives sage: show(G+H) # optional - sage.plot
- class sage.geometry.hyperbolic_space.hyperbolic_geodesic.HyperbolicGeodesicUHP(model, start, end, **graphics_options)#
Bases:
HyperbolicGeodesic
Create a geodesic in the upper half plane model.
The geodesics in this model are represented by circular arcs perpendicular to the real axis (half-circles whose origin is on the real axis) and straight vertical lines ending on the real axis.
INPUT:
start
– aHyperbolicPoint
in hyperbolic space representing the start of the geodesicend
– aHyperbolicPoint
in hyperbolic space representing the end of the geodesic
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(UHP.get_point(I), UHP.get_point(2 + I)) sage: g = UHP.get_geodesic(I, 2 + I) sage: h = UHP.get_geodesic(-1, -1+2*I)
- angle(other)#
Return the angle between the completions of any two given geodesics if they intersect.
INPUT:
other
– a hyperbolic geodesic in the UHP model
OUTPUT:
the angle in radians between the two given geodesics
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(2, 4) sage: h = UHP.get_geodesic(3, 3 + I) sage: g.angle(h) 1/2*pi sage: numerical_approx(g.angle(h)) 1.57079632679490
If the geodesics are identical, return angle 0:
sage: g.angle(g) 0
It is an error to ask for the angle of two geodesics that do not intersect:
sage: g = UHP.get_geodesic(2, 4) sage: h = UHP.get_geodesic(5, 7) sage: g.angle(h) Traceback (most recent call last): ... ValueError: geodesics do not intersect
- common_perpendicular(other)#
Return the unique hyperbolic geodesic perpendicular to
self
andother
, if such a geodesic exists; otherwise raise aValueError
.INPUT:
other
– a hyperbolic geodesic in current model
OUTPUT:
a hyperbolic geodesic
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(2, 3) sage: h = UHP.get_geodesic(4, 5) sage: g.common_perpendicular(h) Geodesic in UHP from 1/2*sqrt(3) + 7/2 to -1/2*sqrt(3) + 7/2
It is an error to ask for the common perpendicular of two intersecting geodesics:
sage: g = UHP.get_geodesic(2, 4) sage: h = UHP.get_geodesic(3, infinity) sage: g.common_perpendicular(h) Traceback (most recent call last): ... ValueError: geodesics intersect; no common perpendicular exists
- ideal_endpoints()#
Determine the ideal (boundary) endpoints of the complete hyperbolic geodesic corresponding to
self
.OUTPUT:
a list of 2 boundary points
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: UHP.get_geodesic(I, 2*I).ideal_endpoints() [Boundary point in UHP 0, Boundary point in UHP +Infinity] sage: UHP.get_geodesic(1 + I, 2 + 4*I).ideal_endpoints() [Boundary point in UHP -sqrt(65) + 9, Boundary point in UHP sqrt(65) + 9]
- intersection(other)#
Return the point of intersection of
self
andother
(if such a point exists).INPUT:
other
– a hyperbolic geodesic in the current model
OUTPUT:
a list of hyperbolic points or a hyperbolic geodesic
EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(3, 5) sage: h = UHP.get_geodesic(4, 7) sage: g.intersection(h) [Point in UHP 2/3*sqrt(-2) + 13/3]
If the given geodesics do not intersect, the function returns an empty list:
sage: g = UHP.get_geodesic(4, 5) sage: h = UHP.get_geodesic(6, 7) sage: g.intersection(h) []
If the given geodesics are asymptotically parallel, the function returns the common boundary point:
sage: g = UHP.get_geodesic(4, 5) sage: h = UHP.get_geodesic(5, 7) sage: g.intersection(h) [Boundary point in UHP 5.00000000000000]
If the given geodesics are identical, return that geodesic:
sage: g = UHP.get_geodesic(4 + I, 18*I) sage: h = UHP.get_geodesic(4 + I, 18*I) sage: g.intersection(h) Geodesic in UHP from I + 4 to 18*I
- midpoint()#
Return the (hyperbolic) midpoint of
self
if it exists.EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.random_geodesic() sage: m = g.midpoint() sage: d1 = UHP.dist(m, g.start()) sage: d2 = UHP.dist(m, g.end()) sage: bool(abs(d1 - d2) < 10**-9) True
Infinite geodesics have no midpoint:
sage: UHP.get_geodesic(0, 2).midpoint() Traceback (most recent call last): ... ValueError: the length must be finite
- perpendicular_bisector()#
Return the perpendicular bisector of the hyperbolic geodesic
self
if that geodesic has finite length.EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.random_geodesic() sage: h = g.perpendicular_bisector().complete() sage: c = lambda x: x.coordinates() sage: bool(c(g.intersection(h)[0]) - c(g.midpoint()) < 10**-9) True
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(1+I,2+0.5*I) sage: h = g.perpendicular_bisector().complete() sage: show(g.plot(color='blue')+h.plot(color='orange'))
Infinite geodesics cannot be bisected:
sage: UHP.get_geodesic(0, 1).perpendicular_bisector() Traceback (most recent call last): ... ValueError: the length must be finite
- plot(boundary=True, **options)#
Plot
self
.EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: UHP.get_geodesic(0, 1).plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives
sage: UHP.get_geodesic(I, 3+4*I).plot(linestyle="dashed", color="brown") # optional - sage.plot Graphics object consisting of 2 graphics primitives
sage: UHP.get_geodesic(1, infinity).plot(color='orange') # optional - sage.plot Graphics object consisting of 2 graphics primitives
- reflection_involution()#
Return the isometry of the involution fixing the geodesic
self
.EXAMPLES:
sage: UHP = HyperbolicPlane().UHP() sage: g1 = UHP.get_geodesic(0, 1) sage: g1.reflection_involution() Isometry in UHP [ 1 0] [ 2 -1] sage: UHP.get_geodesic(I, 2*I).reflection_involution() Isometry in UHP [ 1 0] [ 0 -1]