Handle points, lines and conics by using algebraic geometry.
Project description
pyConics
pyConics
handles points, lines and conics by using algebraic geometry
and homogeneous coordinates (projective geometry).
Installation
From a local directory clones this project:
git clone https://github.com/osowsky/pyConics.git (by using http)
or
git clone git@github.com:osowsky/pyConics.git (by using ssh)
You can install this package, as well:
pip install pyConics
Usage
pyConics
can be used to handle points, lines and conics by using algebraic
geometry and homogeneous coordinates.
Working with points
The representation in homogeneous coordinates of a Cartesian point $p = (\enspace\alpha,\enspace\beta\enspace)$, where $\alpha,\enspace\beta\enspace\in\enspace\mathcal{R}$, is given by the following vector in $\mathcal{R}^3$:
$$ p=\left[\begin{array}{cc} \enspace\alpha & \beta & 1.0\enspace \end{array}\right]^{T} $$
If you want to represent a point $p$ at infinity, you must define a vector as follows:
$$ p=\left[\begin{array}{cc} \enspace\alpha & \beta & 0.0\enspace \end{array}\right]^{T}, $$
where $\enspace\alpha,\enspace\beta\enspace\in\enspace\mathcal{R}$
How to work with points in pyConics
.
from pyConics import Point
p1 = Point( ( 0.0, 1.0 ), 'p1' ) # p1 = ( 0.0, 1.0 ).
p2 = Point( ( 1.0, 1.0 ), 'p2' ) # p2 = ( 1.0, 1.0 ).
print( p1 ) # -> p1: [0.0000e+00 1.0000e+00 1.0000e+00].
print( p2 ) # -> p2: [1.0000e+00 1.0000e+00 1.0000e+00].
print()
print( f'Are p1 and p2 the same? {p1 == p2}\n' ) # -> False.
d12 = p1.distance( p2 )
print( f'Distance from {p1}\nto {p2} is {d12:.4f}.\n' ) # -> d12 = 1.0.
p3 = Point( ( 1, 1, 0 ), 'p3' ) # Point at the infinity.
print( p3 ) # -> p3: [1.0000e+00 1.0000e+00 0.0000e+00] -> point at the infinity.
print()
print( f'Is p3 a point at infinity? {p3.at_infinity()}.\n' ) # -> True.
d13 = p1.distance( p3 )
print( f'Distance from {p1} to\n{p3} is {d13:.4f}.\n' ) # -> d13 = Inf.
Working with lines
The representation in homogeneous coordinates of a Cartesian line $l:\beta y=\alpha x + \gamma$, where $\alpha,\enspace\beta,\enspace\gamma\in\enspace\mathcal{R}$, is given by the following vector in $\mathcal{R}^3$:
$$ l=\left[\begin{array}{cc} \enspace\alpha & -\beta & \gamma\enspace \end{array}\right]^{T} $$
The vector above satisfies the following homogeneous expression for straight lines in projective geometry:
$$ l:\left\lbrace\enspace (\enspace x,\enspace y\enspace)\enspace|\enspace \left[\begin{array}{cc} \enspace\alpha & -\beta & \gamma\enspace \end{array}\right]\times \left[\begin{array}{c} \enspace\ x \enspace\ \enspace\ y \enspace\ \enspace\ 1 \enspace\ \end{array}\right]\enspace=\enspace 0 \enspace\right\rbrace $$
If you want to represent a line $l$ at infinity, you must define a vector as follows:
$$ l\enspace=\left[\begin{array}{cc} \enspace 0.0 & 0.0 & \gamma\enspace \end{array}\right]^{T}, $$
where $\enspace\gamma\enspace\in\enspace\mathcal{R}$
How to work with lines in pyConics
.
from pyConics import Line
l1 = Line( ( 1, -1, 1 ), 'l1' ) # l1: y = x + 1
l2 = Line( ( 1.5, -1.5, -1.5 ), 'l2' ) # l2: 1.5y = 1.5x - 1.5
l3 = Line( ( -1, -1, 1 ), 'l3' ) # l3: y = -x + 1
l4 = Line( ( 2, 2, -2 ), 'l4' ) # l4: 2y = -2x + 2
print( l1 ) # -> l1: ( x, y ) | [1.0000e+00 -1.0000e+00 1.0000e+00] * [ x y 1 ]' = 0.
print( l2 ) # -> l2: ( x, y ) | [1.5000e+00 -1.5000e+00 -1.5000e+00] * [ x y 1 ]' = 0.
print( l3 ) # -> l3: ( x, y ) | [-1.0000e+00 -1.0000e+00 1.0000e+00] * [ x y 1 ]' = 0.
print( l4 ) # -> l4: ( x, y ) | [2.0000e+00 2.0000e+00 -2.0000e+00] * [ x y 1 ]' = 0.
print()
# The relationships between two lines lx and ly can be:
# 1) coincident lines: lx == ly or lx.are_coincident( ly ).
# Notice that l4 = -2 * l3. From the projective geometry both lines are
# coincident because they satisfy the same equation.
print( f'Is l1 == l1? {l1 == l1}.' )
print( f'Is l3 == l4? {l3 == l4}.' )
print( f'Is l1 == l2? {l1 == l2}.\n' )
# 2) parallel lines: lx // ly or lx.are_parallel( ly ).
# Notice that coincident lines are parallel ones, as well.
print( f'Is l1 // l2? {l1 // l2}.' )
print( f'Is l2 // l3? {l2 // l3}.' )
print( f'Is l3 // l4? {l3 // l4}.\n' )
# 3) concurrent lines: lx.are_concurrent( ly )
print( f'Are l1 and l2 concurrent lines? {l1.are_concurrent( l2 )}.' )
print( f'Are l2 and l3 concurrent lines? {l2.are_concurrent( l3 )}.' )
print( f'Are l3 and l4 concurrent lines? {l3.are_concurrent( l4 )}.\n' )
# 4) perpendicular lines: lx + ly or lx.are_perpendicular( ly ).
print( f'Is l1 + l3? {l1 + l3}.' )
print( f'Is l2 + l4? {l2 + l4}.' )
print( f'Is l3 + l4? {l3 + l4}.\n' )
# Euclidean distance between lines.
# Notice that, from the theory the distance between two concurrent
# lines is equal to zero.
print( f'Distance from l1 to l2 is {l1.distance( l2 ):.4f}.' )
print( f'Distance from l2 to l3 is {l2.distance( l3 ):.4f}.' )
print( f'Distance from l3 to l4 is {l3.distance( l4 ):.4f}.\n' )
# Lines at infinity.
l5 = Line( ( 0, 0, 2 ), 'l5' )
l6 = Line( ( 1, -1, 1 ), 'l6' )
print( l5 )
print( l6 )
print( f'Is l5 a line at infinity? {l5.at_infinity()}.' )
print( f'Is l6 a line at infinity? {l6.at_infinity()}.\n' )
# Distance from l5 at infinity and l6.
d56 = l5.distance( l6 )
print( f'Distance from {l5} to {l6} is {d56}.\n' )
Working with points and lines
Now that I have introduced you to the concepts of points and lines in projective geometry and how you should work with them. The next step is to know how to use both geometric shapes together.
However, before we start this step I must answer a question that you may be wondering. If points and lines have the same vector representation, i.e., they are both vectors in $\mathcal{R}^3$, how will I know if I am using a point or a line?
A generic answer would be: The context will tell you whether the vectors in $\mathcal{R}^3$ are points or lines. For instance, the cross product operation can be used with the following operands:
- two points: The result is a straight line $l$ that passes through both points.
- two lines: The result is the point of intersection $p$ between both lines.
- a point $p$ and a line $l$: The result is a line that is perpendicular to the straight line $l$ and passes through the point $p$.
Finally, the Table below shows six interesting interpretations about vector representation of points and lines, four of which are not well-posed in two-dimensional Euclidean Geometry, namely point and line at infinity.
$$ % \def\arraystretch{2.5} \begin{array}{ccc} \text{vector in }\mathcal{R}^3 & \text{point} & \text{line}\newline \hline\hline [\begin{array}{ccc} \alpha & \beta & 0.0 \end{array}]^{T} & \text{point at infinity} & \text{line passing through the origin}\newline \hline [\begin{array}{ccc} 0.0 & 0.0 & \gamma \end{array}]^{T} & \text{point at origin with }\gamma=1.0 & \text{line at infinity}\newline \hline [\begin{array}{ccc} 0.0 & 0.0 & 0.0 \end{array}]^{T} & \text{point at infinity} & \text{line at infinity}\newline \hline \end{array} $$
How to work with points and lines in pyConics
.
from pyConics import Point, Line
# Points.
p1 = Point( ( 1, 3 ), 'p1' ) # p1 = ( 1, 3 )
p2 = Point( ( 0, 4 ), 'p2' ) # p2 = ( 0, 4 )
p3 = Point( ( -2, 0 ), 'p3' ) # p3 = ( -2, 0 )
p4 = Point( ( 2, 0 ), 'p4' ) # p4 = ( 2, 0 )
p5 = Point( ( 0, -4 ), 'p5' ) # p5 = ( 0, -4 )
# Lines.
l1 = Line( ( 2, -1, 4 ), 'l1' ) #l1: y = 2x + 4
l2 = Line( ( 2, -1, -4 ), 'l2' ) #l2: y = 2x - 4
l3 = Line( ( 2, 1, 0 ), 'l3' ) #l3: y = -2x
l4 = Line( ( 1, 0, -2 ), 'l4' ) #l4: x = 2
l5 = Line( ( 0, 1, -4 ), 'l5' ) #l5: y = 4
l6 = Line( ( 3, -1, 0 ), 'l6' ) #l6: y = 3x
# Test whether a point is in or is not in a Line.
print( l1, p1, p2, p3, sep='\n' )
print( f'Is p1 in l1? {p1 in l1}.' ) # p1 belongs to l1: False
print( f'Is p2 in l1? {p2 in l1}.' ) # p2 belongs to l1: True
print( f'Is p3 in l1? {p3 in l1}.\n' ) # p3 belongs to l1: True
print( l6, p1, p4, sep='\n' )
print( f'Is p1 in l6? {p1 in l6}.' ) # p1 belongs to l6: True
print( f'Is p4 in l6? {p4 in l6}.\n' ) # p4 belongs to l6: False
print( l4, p4, sep='\n' )
print( f'Is p4 in l4? {p4 in l4}.\n' ) # p4 belongs to l4: True
print( l5, p2, sep='\n' )
print( f'Is p2 in l5? {p2 in l5}.\n' ) # p2 belongs to l5: True
# Use the cross product to handle points and lines.
# 1) the cross product between two points gives us a line that
# passes through these points.
l: Line = p2 * p3
l.name = 'l'
print( l1, l, sep='\n' )
print( f'Are l and l1 coincident? {l==l1}.\n' )
l: Line = p4 * p5
l.name = 'l'
print( l2, l, sep='\n' )
print( f'Are l and l2 coincident? {l==l2}.\n' )
# 2) the cross product between two lines gives us their point
# of intersection.
p: Point = l1 * l3
p.name = 'p'
print( l1, l3, p, sep='\n' )
print( f'Is p in l1? {p in l1}.' )
print( f'Is p in l3? {p in l3}.\n' )
p: Point = l2 * l4
p.name = 'p'
print( l2, l4, p4, p, sep='\n' )
print( f'Is p in l2? {p in l2}.' )
print( f'Is p in l4? {p in l4}.' )
print( f'Are p and p4 coincident? {p==p4}.\n' )
# Two parallel lines have their point of intersection at infinity.
# So, ...
p: Point = l1 * l2
p.name = 'p'
print( l1, l2, p, sep='\n' )
print( f'Is p in l1? {p in l1}.' )
print( f'Is p in l2? {p in l2}.' )
print( f'Is p in l4? {p in l4}.' )
print( f'Is p at infinity? {p.at_infinity()}.\n' )
# 3) the cross product between a point and a line gives us a
# line which is perpendicular to that line and passes
# through that point.
l: Line = l2 * p2
l.name = 'l'
print( p2, l2, l, sep='\n' )
print( f'Is p2 in l? {p2 in l}.' )
print( f'Are l2 and l perpendicular? {l2 + l}.\n' )
p: Point = l2 * l
p.name = 'p'
print( l2, l, p, sep='\n' )
print( f'Is p in l? {p in l}.' )
print( f'Is p in l2? {p in l2}.' )
# Getting the distance between p2 and l2.
print( f'Distance from p2 to l2 = {p2.distance( l2 ):.4f}.' )
print( f'Distance from p2 to p = {p2.distance( p ):.4f}.\n' )
Contributing
Interested in contributing? Check out the contributing guidelines. Please note that this project is released with a Code of Conduct. By contributing to this project, you agree to abide by its terms.
License
pyConics
was created by Jefferson Osowsky.
It is licensed under the terms of the GNU General Public License v3.0 license.
Credits
pyConics
was created with cookiecutter
and the py-pkgs-cookiecutter
template.
pyConics
has used the following Python packages since its first release:
numpy
pytest
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.