proj_pt.h revision cd8e8082c747cc529d5bf595b4102e88224a1811
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti#ifndef __PROJ_PT_H__
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti#define __PROJ_PT_H__
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti/*
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti * 3x4 transformation matrix to map points from projective 3-space into the projective plane
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti *
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti * Authors:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti * Maximilian Albert <Anhalter42@gmx.de>
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti *
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti * Copyright (C) 2007 Authors
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti *
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti * Released under GNU GPL, read the file 'COPYING' for more information
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti */
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti#include <2geom/point.h>
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti#include <gtk/gtk.h>
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchettinamespace Proj {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetticonst double epsilon = 1E-6;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti// TODO: Catch the case when the constructors are called with only zeros
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetticlass Pt2 {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchettipublic:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 () { pt[0] = 0; pt[1] = 0; pt[2] = 1.0; } // we default to (0 : 0 : 1)
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 (double x, double y, double w) { pt[0] = x; pt[1] = y; pt[2] = w; }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 (Geom::Point const &point) { pt[0] = point[Geom::X]; pt[1] = point[Geom::Y]; pt[2] = 1; }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 (const gchar *coord_str);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline double operator[] (unsigned int index) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti if (index > 2) { return Geom::infinity(); }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return pt[index];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline double &operator[] (unsigned int index) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti // FIXME: How should we handle wrong indices?
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti //if (index > 2) { return Geom::infinity(); }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return pt[index];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline bool operator== (Pt2 &rhs) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fabs(pt[1] - rhs.pt[1]) < epsilon &&
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fabs(pt[2] - rhs.pt[2]) < epsilon);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline bool operator!= (Pt2 &rhs) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return !((*this) == rhs);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti the result for finite points is the same as if the affine points were addes ***/
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt2 &operator+(Pt2 &rhs) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 *result = new Pt2 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 2 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] += rhs.pt[i];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt2 &operator-(Pt2 &rhs) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 *result = new Pt2 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 2 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] -= rhs.pt[i];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt2 &operator*(double const s) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt2 *result = new Pt2 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 2 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] *= s;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti void normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Geom::Point affine();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline bool is_finite() { return pt[2] != 0; } // FIXME: Should we allow for some tolerance?
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti gchar *coord_string();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline void print(gchar const *s) const { g_print ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchettiprivate:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti double pt[3];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti};
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetticlass Pt3 {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchettipublic:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 () { pt[0] = 0; pt[1] = 0; pt[2] = 0; pt[3] = 1.0; } // we default to (0 : 0 : 0 : 1)
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 (double x, double y, double z, double w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 (const gchar *coord_str);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline bool operator== (Pt3 &rhs) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fabs(pt[1] - rhs.pt[1]) < epsilon &&
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fabs(pt[2] - rhs.pt[2]) < epsilon &&
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fabs(pt[3] - rhs.pt[3]) < epsilon);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti the result for finite points is the same as if the affine points were addes ***/
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt3 &operator+(Pt3 &rhs) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 *result = new Pt3 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 3 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] += rhs.pt[i];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt3 &operator-(Pt3 &rhs) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 *result = new Pt3 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti rhs.normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 3 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] -= rhs.pt[i];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline Pt3 &operator*(double const s) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Pt3 *result = new Pt3 (*this);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti for ( unsigned i = 0 ; i < 3 ; ++i ) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti result->pt[i] *= s;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return *result;
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline double operator[] (unsigned int index) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti if (index > 3) { return Geom::infinity(); }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return pt[index];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline double &operator[] (unsigned int index) {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti // FIXME: How should we handle wrong indices?
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti //if (index > 3) { return Geom::infinity(); }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti return pt[index];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti void normalize();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline bool is_finite() { return pt[3] != 0; } // FIXME: Should we allow for some tolerance?
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti gchar *coord_string();
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti inline void print(gchar const *s) const {
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti g_print ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]);
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti }
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchettiprivate:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti double pt[4];
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti};
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti} // namespace Proj
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti#endif /* __PROJ_PT_H__ */
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti/*
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti Local Variables:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti mode:c++
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti c-file-style:"stroustrup"
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti indent-tabs-mode:nil
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti fill-column:99
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti End:
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti*/
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
6e16a663ee96cd1329e48518138efb415046d9f6mcecchetti