summaryrefslogtreecommitdiffstats
path: root/src/proj_pt.h
blob: 226c182ccd4279930e36017ca932f9262642678b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
 * 3x4 transformation matrix to map points from projective 3-space into the projective plane
 *
 * Authors:
 *   Maximilian Albert <Anhalter42@gmx.de>
 *
 * Copyright (C) 2007  Authors
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#ifndef SEEN_PROJ_PT_H
#define SEEN_PROJ_PT_H

#include <2geom/point.h>
#include <gtk/gtk.h>

namespace Proj {

const double epsilon = 1E-6;

// TODO: Catch the case when the constructors are called with only zeros
class Pt2 {
public:
    Pt2 () { pt[0] = 0; pt[1] = 0; pt[2] = 1.0; } // we default to (0 : 0 : 1)
    Pt2 (double x, double y, double w) { pt[0] = x; pt[1] = y; pt[2] = w; }
    Pt2 (Geom::Point const &point) { pt[0] = point[Geom::X]; pt[1] = point[Geom::Y]; pt[2] = 1; }
    Pt2 (const gchar *coord_str);

    inline double operator[] (unsigned int index) const {
        if (index > 2) { return Geom::infinity(); }
        return pt[index];
    }
    inline double &operator[] (unsigned int index) {
        // FIXME: How should we handle wrong indices?
        //if (index > 2) { return Geom::infinity(); }
        return pt[index];
    }
    inline bool operator== (Pt2 &rhs) {
        normalize();
        rhs.normalize();
        return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
                fabs(pt[1] - rhs.pt[1]) < epsilon &&
                fabs(pt[2] - rhs.pt[2]) < epsilon);
    }
    inline bool operator!= (Pt2 &rhs) {
        return !((*this) == rhs);
    }

    /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
         the result for finite points is the same as if the affine points were addes ***/
    inline Pt2 &operator+(Pt2 &rhs) const {
        Pt2 *result = new Pt2 (*this);
        result->normalize();
        rhs.normalize();
        for ( unsigned i = 0 ; i < 2 ; ++i ) {
            result->pt[i] += rhs.pt[i];
        }
        return *result;
    }

    inline Pt2 &operator-(Pt2 &rhs) const {
        Pt2 *result = new Pt2 (*this);
        result->normalize();
        rhs.normalize();
        for ( unsigned i = 0 ; i < 2 ; ++i ) {
            result->pt[i] -= rhs.pt[i];
        }
        return *result;
    }

    inline Pt2 &operator*(double const s) const {
        Pt2 *result = new Pt2 (*this);
        result->normalize();
        for ( unsigned i = 0 ; i < 2 ; ++i ) {
            result->pt[i] *= s;
        }
        return *result;
    }

    void normalize();
    Geom::Point affine();
    inline bool is_finite() { return pt[2] != 0; } // FIXME: Should we allow for some tolerance?
    gchar *coord_string();
    inline void print(gchar const *s) const { g_print ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); }

private:
    double pt[3];
};


class Pt3 {
public:
    Pt3 () { pt[0] = 0; pt[1] = 0; pt[2] = 0; pt[3] = 1.0; } // we default to (0 : 0 : 0 : 1)
    Pt3 (double x, double y, double z, double w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; }
    Pt3 (const gchar *coord_str);

    inline bool operator== (Pt3 &rhs) {
        normalize();
        rhs.normalize();
        return (fabs(pt[0] - rhs.pt[0]) < epsilon &&
                fabs(pt[1] - rhs.pt[1]) < epsilon &&
                fabs(pt[2] - rhs.pt[2]) < epsilon &&
                fabs(pt[3] - rhs.pt[3]) < epsilon);
    }

    /*** For convenience, we define addition/subtraction etc. as "affine" operators (i.e.,
         the result for finite points is the same as if the affine points were addes ***/
    inline Pt3 &operator+(Pt3 &rhs) const {
        Pt3 *result = new Pt3 (*this);
        result->normalize();
        rhs.normalize();
        for ( unsigned i = 0 ; i < 3 ; ++i ) {
            result->pt[i] += rhs.pt[i];
        }
        return *result;
    }

    inline Pt3 &operator-(Pt3 &rhs) const {
        Pt3 *result = new Pt3 (*this);
        result->normalize();
        rhs.normalize();
        for ( unsigned i = 0 ; i < 3 ; ++i ) {
            result->pt[i] -= rhs.pt[i];
        }
        return *result;
    }

    inline Pt3 &operator*(double const s) const {
        Pt3 *result = new Pt3 (*this);
        result->normalize();
        for ( unsigned i = 0 ; i < 3 ; ++i ) {
            result->pt[i] *= s;
        }
        return *result;
    }
    
    inline double operator[] (unsigned int index) const {
        if (index > 3) { return Geom::infinity(); }
        return pt[index];
    }
    inline double &operator[] (unsigned int index) {
        // FIXME: How should we handle wrong indices?
        //if (index > 3) { return Geom::infinity(); }
        return pt[index];
    }
    void normalize();
    inline bool is_finite() { return pt[3] != 0; } // FIXME: Should we allow for some tolerance?
    gchar *coord_string();
    inline void print(gchar const *s) const {
        g_print ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]);
    }

private:
    double pt[4];
};

} // namespace Proj

#endif // !SEEN_PROJ_PT_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :