summaryrefslogtreecommitdiffstats
path: root/src/proj_pt.h
blob: 1d1ec473d620889cd00bade80f52c21293813279 (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
172
// SPDX-License-Identifier: GPL-2.0-or-later
/**
 * 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 v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_PROJ_PT_H
#define SEEN_PROJ_PT_H

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

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 char *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 added ***/
    inline Pt2 operator+(Pt2 &rhs) const {
        Pt2 result (*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 (*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 (*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?
    char *coord_string();
    inline void print(char const *s) const { printf ("%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 char *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 added ***/
    inline Pt3 operator+(Pt3 &rhs) const {
        Pt3 result(*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 (*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 (*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?
    char *coord_string();
    inline void print(char const *s) const {
        printf ("%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 :