Code

Fixed signed/unsigned problem with precision calc. Fixes bug #399604.
[inkscape.git] / src / proj_pt.h
1 #ifndef __PROJ_PT_H__
2 #define __PROJ_PT_H__
4 /*
5  * 3x4 transformation matrix to map points from projective 3-space into the projective plane
6  *
7  * Authors:
8  *   Maximilian Albert <Anhalter42@gmx.de>
9  *
10  * Copyright (C) 2007  Authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #include <2geom/point.h>
16 #include "libnr/nr-values.h"
17 #include <gtk/gtk.h>
19 namespace Proj {
21 const double epsilon = 1E-6;
23 // TODO: Catch the case when the constructors are called with only zeros
24 class Pt2 {
25 public:
26     Pt2 () { pt[0] = 0; pt[1] = 0; pt[2] = 1.0; } // we default to (0 : 0 : 1)
27     Pt2 (double x, double y, double w) { pt[0] = x; pt[1] = y; pt[2] = w; }
28     Pt2 (Geom::Point const &point) { pt[0] = point[Geom::X]; pt[1] = point[Geom::Y]; pt[2] = 1; }
29     Pt2 (const gchar *coord_str);
31     inline double operator[] (unsigned int index) const {
32         if (index > 2) { return NR_HUGE; }
33         return pt[index];
34     }
35     inline double &operator[] (unsigned int index) {
36         // FIXME: How should we handle wrong indices?
37         //if (index > 2) { return NR_HUGE; }
38         return pt[index];
39     }
40     inline bool operator== (Pt2 &rhs) {
41         normalize();
42         rhs.normalize();
43         return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
44                 fabs(pt[1] - rhs.pt[1]) < epsilon &&
45                 fabs(pt[2] - rhs.pt[2]) < epsilon);
46     }
47     inline bool operator!= (Pt2 &rhs) {
48         return !((*this) == rhs);
49     }
51     /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
52          the result for finite points is the same as if the affine points were addes ***/
53     inline Pt2 &operator+(Pt2 &rhs) const {
54         Pt2 *result = new Pt2 (*this);
55         result->normalize();
56         rhs.normalize();
57         for ( unsigned i = 0 ; i < 2 ; ++i ) {
58             result->pt[i] += rhs.pt[i];
59         }
60         return *result;
61     }
63     inline Pt2 &operator-(Pt2 &rhs) const {
64         Pt2 *result = new Pt2 (*this);
65         result->normalize();
66         rhs.normalize();
67         for ( unsigned i = 0 ; i < 2 ; ++i ) {
68             result->pt[i] -= rhs.pt[i];
69         }
70         return *result;
71     }
73     inline Pt2 &operator*(double const s) const {
74         Pt2 *result = new Pt2 (*this);
75         result->normalize();
76         for ( unsigned i = 0 ; i < 2 ; ++i ) {
77             result->pt[i] *= s;
78         }
79         return *result;
80     }
82     void normalize();
83     Geom::Point affine();
84     inline bool is_finite() { return pt[2] != 0; } // FIXME: Should we allow for some tolerance?
85     gchar *coord_string();
86     inline void print(gchar const *s) const { g_print ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); }
88 private:
89     double pt[3];
90 };
93 class Pt3 {
94 public:
95     Pt3 () { pt[0] = 0; pt[1] = 0; pt[2] = 0; pt[3] = 1.0; } // we default to (0 : 0 : 0 : 1)
96     Pt3 (double x, double y, double z, double w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; }
97     Pt3 (const gchar *coord_str);
99     inline bool operator== (Pt3 &rhs) {
100         normalize();
101         rhs.normalize();
102         return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
103                 fabs(pt[1] - rhs.pt[1]) < epsilon &&
104                 fabs(pt[2] - rhs.pt[2]) < epsilon &&
105                 fabs(pt[3] - rhs.pt[3]) < epsilon);
106     }
108     /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
109          the result for finite points is the same as if the affine points were addes ***/
110     inline Pt3 &operator+(Pt3 &rhs) const {
111         Pt3 *result = new Pt3 (*this);
112         result->normalize();
113         rhs.normalize();
114         for ( unsigned i = 0 ; i < 3 ; ++i ) {
115             result->pt[i] += rhs.pt[i];
116         }
117         return *result;
118     }
120     inline Pt3 &operator-(Pt3 &rhs) const {
121         Pt3 *result = new Pt3 (*this);
122         result->normalize();
123         rhs.normalize();
124         for ( unsigned i = 0 ; i < 3 ; ++i ) {
125             result->pt[i] -= rhs.pt[i];
126         }
127         return *result;
128     }
130     inline Pt3 &operator*(double const s) const {
131         Pt3 *result = new Pt3 (*this);
132         result->normalize();
133         for ( unsigned i = 0 ; i < 3 ; ++i ) {
134             result->pt[i] *= s;
135         }
136         return *result;
137     }
138     
139     inline double operator[] (unsigned int index) const {
140         if (index > 3) { return NR_HUGE; }
141         return pt[index];
142     }
143     inline double &operator[] (unsigned int index) {
144         // FIXME: How should we handle wrong indices?
145         //if (index > 3) { return NR_HUGE; }
146         return pt[index];
147     }
148     void normalize();
149     inline bool is_finite() { return pt[3] != 0; } // FIXME: Should we allow for some tolerance?
150     gchar *coord_string();
151     inline void print(gchar const *s) const {
152         g_print ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]);
153     }
155 private:
156     double pt[4];
157 };
159 } // namespace Proj
161 #endif /* __PROJ_PT_H__ */
163 /*
164   Local Variables:
165   mode:c++
166   c-file-style:"stroustrup"
167   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
168   indent-tabs-mode:nil
169   fill-column:99
170   End:
171 */
172 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :