What is a figure, anyway?¶
Vladimir V Kisil¶
Classic geometric constructions by compass and straightedge are implemented as figures. Their building blocks are cycles and the cement gluing cycles together is cycle relations. In short:
Definition. Ref.4 Ref.5 Figure is a collection of cycles interconnected by Mobius invariant relation.
We illustrate the concept by a basic example below. For simplicity the entire figure is build on a (virtually) single cycle relation—orthogonality.
Note: to execute the notebook you may need to install software.
Table of contents of this notebook¶
Back to the top-level Table of Contents.
Example: the midpoint of an interval¶
As an illustration we are considering a construction of the midpoint of an interval. As usually, we need to load the software.
from figure import *
from IPython.display import Image
show_asy_off()
F=figure()
Now we define two points A
and B
, which are endpoints of the interval to be bisected.
A=F.add_point([0,0], "A") # Origin
B=F.add_point([1,0], "B") # Point (1,0)
The special role is played by infinity. For example, a cycle is a straight line if it passes the infinity. We can always access the infinity point of the figure as F.get_infinity()
. However, to make our construction conformally invariant we take infinity as the third parameter of the figure. This cycle is provided by listing its all coefficients $(k, l, n, m)$, see notebook on cycles.
inf=F.add_cycle(cycle_data(0, [0,0], 1), "inf", "\\infty") # Infinity
Add cycles by relations: parents and generations¶
Here our construction starts. We add a cycle l
with the following properties:
- It passes
A
, that is it is orthogonal to it. - It passes
B
, that is it is orthogonal to it. - It is a straight line, i.e it passes the infinity (that is it is orthogonal to it).
l=F.add_cycle_rel([is_orthogonal(A),
is_orthogonal(B),
is_orthogonal(inf)],
"l");
Cycle l
was added through its relations to cycles A
, B
, and inf
. If they are pairwise distinct, then l
is uniquely defined and all its coefficients are numeric. If some given points coincide, then coefficients of l
will depend on free parameter(s). Given points A
, B
, and inf
can depend on free parameters (C++ class GiNaC::symbols
) themselves, then l
will inherit such a dependence of course.
We say that A
, B
, and inf
are parents of l
to denote that l
is defined through relations to the three given cycles. Cycles in a figure are belonging to certain generations. and predefined cycles (that is A
, B
, and inf
in our example) are always in "generation-0*. We want to avoid dangerous loops in parenthood those each new cycle is assigned to the next generation for its latest (in terms of generations) parent. For example, since all parents of l
are in generation-0, the new cycle belongs to the generation-1.
In a similar way we add a cycle c
passing A
and B
and orthogonal to l
, this will be assigned to generation-2.
c=F.add_cycle_rel([is_orthogonal(A),
is_orthogonal(B),
is_orthogonal(l)],
"c")
Next cycle p
is orthogonal to l
and c
and is a straight line (orthogonal to inf
), it is in generation-3.
p=F.add_cycle_rel([is_orthogonal(inf),
is_orthogonal(l),
is_orthogonal(c)],
"p")
Finally the midpoint is the intersection of p
and l
, that is it is orthogonal to these two cycles. Furthermore to be a point it shall be orthogonal to itself, which is written as is_orthogonal()
(no other parent for this orthogonality). Equivalently, self-orthogonality can be written as is_orthogonal()
. We shall note that p
and l
also intersect in point inf
, to avoid this value we add the relation ``to be different'' written as is_different(inf)
.
M = F.add_cycle_rel([is_orthogonal(l),
is_orthogonal(p),
is_orthogonal(), # self-orthogonality
is_different(inf)],
"midpoint")
print(F)
For example, it says that cycle l
has children c
, p
and midpoint
—these are cycles which directly relate to l
as a parent. The list of relations for l
is (A|o,B|o,inf|o)
which means orthogonality to each of the three parents.
A graphical presentation of the figure can be seen as follows. It will also save the graphic file "midpoint1.png" on the local disk. Alternative popular formats, defined by the last parameter of the call asy_write()
can be "pdf", "eps", "jpg".
F.asy_write(300,-.5,1.5,-1,1,"midpoint1","png")
Image("midpoint1.png")
Alternatively we can write an Asymptote file can be saved on the disk. It is a human-readable command drawing script. It can be fine-tuned for the appearance and then converted to PDF/PNG/PS/JPEG formats by asymptote
tool.
F.asy_print("midpoint", "", -.5,1.5,-1,1)
We also can also save the figure in a binary format (non-editable or human-read). The next command will create a local file "midpoint.gar", which can be subsequently read from a command. For illustration of this, we will create another figure F1
identical to the original one and show it on the screen (which shall be the same as above).
F.save("midpoint") # The extansion ".gar" will be automatically added
F1 = figure("midpoint") # the actual file is named "midpoint.gar"
F1.asy_write(300,-.5,1.5,-1,1,"midpoint2","png")
Image("midpoint2.png")
Measuring on a figure¶
We can measure that the constructed point is the midpoint indeed. The respective quantity is known as a Steiner power:
def check_equality():
Res1 = F.measure(M, A, "steiner_power")
Res2 = F.measure(M, B, "steiner_power")
for i in range(len(Res1)):
print(f'Tangent distance are equal: {(Res2[i]-Res1[i]).normal().is_zero()}')
check_equality()
Here we need to run a list because a "cycle" within a figure can encapsulate several quadrics, thus the result of measurement is given by a list with answers for all respective quadrics.
Geometrically the Steiner power is equal to the square of tangential distance between cycles. Could it be that our midpoint construction works beyond points (zero radius cycles). We can check this for the unit circle and some other circle:
F.move_cycle(A, cycle_data(1, [0, 0], -1)) # unit circle
F.move_cycle(B, cycle_data(1, [2, 2], 4)) # center (2.2) and the radius 2
check_equality()
We can even make a check for two generic cycles:
k=realsymbol("k")
l=realsymbol("l")
n=realsymbol("n")
m=realsymbol("m")
k1=realsymbol("k1", "{k'}")
l1=realsymbol("l1", "{l'}")
n1=realsymbol("n1", "{n'}")
m1=realsymbol("m1", "{m'}")
F.move_cycle(A, cycle_data(k, [l, n], m)) # unit circle
F.move_cycle(B, cycle_data(k1, [l1, n1], m1)) # center (2.2) and the radius 2
check_equality()
Thus our claim is demonstrated by analytic computations. However a synthetic geometric proof is straightforward as well.
Modifying a figure¶
Figures are not cut in marble, instead they can be efficiently edited or transformed. For our figure an interesting feature is that midpoint is well defined not only for endpoints of an interval. In fact, A
and B
can be any cycles. Let us replace A
by the unit circle (cycle $(1,0,0,-1)$) and move B
to the point (2,1):
F.move_cycle(A, cycle_data(1, [-1, 0], -1))
F.move_point(B, [2,1])
How does it look like?
F.asy_write(300,-1.5,2.5,-1.5,2,"midpoint3","png")
Image("midpoint3.png")
To clarify the role of the inf
in the midpoint construction we can make a fractional linear transformation of the entire figure
F.reflection(cycle2D(1, [numeric(-1,4), numeric(-1,4)], numeric(-7,8)))
F.asy_write(300,-1.5,2.5,-1.5,2,"midpoint4","png")
Image("midpoint4.png")
It is a fun to find correspondence between two pictures and mediate on the performed transformation.
Another puzzle is achieved if we change the cycle metric from Euclidean (elliptic) to hyperbolic and output the image to look which meaning does it have.
F.set_metric([-1,1])
F.asy_write(300,-1.5,2.5,-1.5,2,"midpoint5","png")
Image("midpoint5.png")
Finally, we may replace in our construction all Euclidean line by Lobachevsky, that is lines will be defined by orthogonality to the real line rather than to infinity. This can be easily achieved by moving inf
cycle to the real line:
F.set_metric([-1,-1])
F.move_point(A, [0,.5])
F.move_point(B, [2,1.5])
F.move_cycle(inf, cycle_data(0, [0, 1], 0))
F.asy_write(300,-1,3,-.5,3,"midpoint6","png")
Image("midpoint6.png")
It can be checked that the construction indeed delivers the midpoint of the interval in the Lobachevsky half-plane geometry.
There is a plenty of space for experiments and discoveries, which is the main aim the present software.
Further Reading¶
We presented a simple example of the figure which essentially based on the single cycle relations (orthogonality). Although it may cover the main geometrical properties there are is versatile set of other cycle relations. Geometric construction often require repeated sequences of operations, which can be efficiently realised by subfigures.
Back to the top-level Table of Contents.
References¶
- V.V. Kisil. Starting with the group SL2(R). Notices Amer. Math. Soc., 54(11):1458–1465, 2007. arXiv:math/0607387, Zbl # 1137.22006.
2. V.V. Kisil. Geometry of Möbius Transformations: Elliptic, Parabolic and Hyperbolic Actions of $SL_2(\mathbb{R})$. Imperial College Press, London, 2012. Includes a live DVD.
3. V.V. Kisil, MoebInv notebooks, started at 2019.
4. V. V. Kisil. An extension of Mobius–Lie geometry with conformal ensembles of cycles and its implementation in a GiNaC library. Proc. Int. Geom. Cent., 11 (3):45–67, 2018. E-print: arXiv:1512.02960. Project page: http://moebinv.sourceforge.net/.
5. V. V. Kisil. Möbius–Lie geometry and its extension. In I. M. Mladenov, G. Meng, and A. Yoshioka (eds.) Geometry, integrability and quantization XX, pages 13–61, Bulgar. Acad. Sci., Sofia, 2019. E-print: arXiv:1811.10499.
6. V. V. Kisil. MoebInv: C++ libraries for manipulations in non-Euclidean geometry. SoftwareX, 11:100385, 2020. doi: 10.1016/j.softx.2019.100385.
Back to the top-level Table of Contents.