Navigation: Up, Table of Contents, Bibliography, Index, Title Page

2D Point, Vector and Direction

We strictly distinguish between points, vectors and directions. A point is a point in the two-dimensional Euclidean plane E2, a vector is the difference of two points p2, p1 and denotes the direction and the distance from p1 to p2 in the vector space R2, and a direction is a vector where we forget about its length. They are different mathematical concepts. For example, they behave different under affine transformations and an addition of two points is meaningless in affine geometry. By putting them in different classes we not only get cleaner code, but also type checking by the compiler which avoids ambiguous expressions. Hence, it pays twice to make this distinction.

CGAL defines a symbolic constant CGAL_ORIGIN of type CGAL_Origin which denotes the point at the origin. This constant is used in the conversion between points and vectors, cf. reference arrow.

Point Conversion

For convenience, CGAL provides functions for conversion of points between homogeneous and Cartesian representation.

#include <CGAL/cartesian_homogeneous_conversion.h>

Conversion from Cartesian representation to homogeneous representation with the same number type is straightforward. The homogenizing coordinate is set to 1, all other homogeneous coordinates are copied from the corresponding Cartesian coordinate.

CGAL_Point_2< CGAL_Homogeneous<RT> >
CGAL_cartesian_to_homogeneous ( CGAL_Point_2< CGAL_Cartesian<RT> > cp)
converts 2d point cp with Cartesian representation into a 2d point with homogeneous representation with the same number type.

Conversion from homogeneous representation to Cartesian representation with the same number type involves division by the homogenizing coordinate.

CGAL_Point_2< CGAL_Cartesian<FT> >
CGAL_homogeneous_to_cartesian ( CGAL_Point_2< CGAL_Homogeneous<FT> > hp)
converts 2d point hp with homogeneous representation into a 2d point with Cartesian representation with the same number type.

Since conversion involves division, concerning exactness, the correspondence is rather between homogeneous representation with number type RT and Cartesian representation with number type CGAL_Quotient<RT> than between representation with the same number type.

CGAL_Point_2< CGAL_Cartesian<CGAL_Quotient<RT> > >
CGAL_homogeneous_to_quotient_cartesian ( CGAL_Point_2<CGAL_Homogeneous<RT> > hp)
converts the 2d point hp with homogeneous representation with number type RT into a 2d point with Cartesian representation with number type CGAL_Quotient<RT>.

CGAL_Point_2< CGAL_Homogeneous<RT> >
CGAL_quotient_cartesian_to_homogeneous ( CGAL_Point_2< CGAL_Cartesian< CGAL_Quotient<RT> > > cp)
converts 2d point cp with Cartesian representation with number type CGAL_Quotient<RT> into a 2d point with homogeneous representation with number type RT.

Of the last two functions, the conversion from homogeneous representation to Cartesian representation with quotients is always exact. The Conversion from Cartesian representation with quotients to homogeneous representation, however, might be inexact with some number types due to overflow or rounding in multiplications.

Conversion between Points and Vectors

We stated earlier that it does not make sense to add two points, but it does make sense to subtract them and the result should be a vector. CGAL defines a symbolic constant CGAL_ORIGIN which denotes the point at the origin. Subtracting it from a point p results in the locus vector of p.

  CGAL_Point_2< CGAL_Cartesian<double> >  p(1.0, 1.0), q;
  CGAL_Vector2< CGAL_Cartesian<double> >  v;
  v = p - CGAL_ORIGIN;
  q = CGAL_ORIGIN + v;  
  assert( p == q );

In order to obtain the point corresponding to a vector v you simply have to add v to CGAL_ORIGIN. If you want to determine the point q in the middle between two points p1 and p2, you can write


  q = p_1 + (p_2 - p_1) / 2.0;

Note that these constructions do not involve any performance overhead for the conversion with the currently available representation classes, if compiler optimisation is used, see also below.

Implementation

Points, vectors and directions use a handle/representative mechanism. A handle is an intelligent pointer, a representative is an object with a reference counter. The three classes have the same internal representation, namely a tuple of coordinates (plus a homogenizing coordinate in the case of homogeneous coordinates), which makes assignment, copy constructors and type conversion cheap.

An assignment makes the handle of the left hand side point to the representative the handle on the right hand sidepoints to. The copy constructor creates a new handle which points to the same representative. This especially pays if your coordinates are of non-constant size.

What about conversion? We explained that you convert by subtracting the origin from a point to obtain its locus vector, or by adding a vector to the origin to obtain the corresponding point. Although the origin behaves like a point, CGAL_ORIGIN is not an object of the class CGAL_Point_2<R> but of the class CGAL_Origin. All constructors and operators taking a point as argument are overloaded with the origin class in order to avoid memory allocation (for a point with coordinates zero), and arithmetic operations (where numbers would be added to zero). To give an example: when you ``add'' a vector v to the origin, only a new handle is created which points to the representation of v.


Next chapter: 2D Line, Ray and Segment
Navigation: Up, Table of Contents, Bibliography, Index, Title Page
The CGAL Project. Wed, January 20, 1999.