5 |
namespace Coords { |
namespace Coords { |
6 |
DBGVAR(dbg, "Coords.general"); |
DBGVAR(dbg, "Coords.general"); |
7 |
|
|
8 |
|
// The (STL-like) concept of transform: |
9 |
|
// enum { NParams = n }; |
10 |
|
// void tr(const ZPt &from, ZPt &to) const |
11 |
|
// bool canPerformGL() |
12 |
|
// bool performGL() |
13 |
|
// float nonlinearity(const ZPt &p, float radius) |
14 |
|
// void setParams(array/iterator i) |
15 |
|
// typedef X InverseType; |
16 |
|
// |
17 |
|
// This approach is needed because inverse transforms and transforms need |
18 |
|
// to call their parents at different points. |
19 |
|
// |
20 |
|
// XXX Nonlinearity is calculated wrong! |
21 |
|
|
22 |
|
template<class Transform> class TransformCoordSysBase : public CoordSys { |
23 |
|
protected: |
24 |
|
Transform t; |
25 |
|
public: |
26 |
|
TransformCoordSysBase() : t() { } |
27 |
|
TransformCoordSysBase(const Transform &tr) : t(tr) { } |
28 |
|
virtual void setParams(float *params) { |
29 |
|
t.setParams(params); |
30 |
|
} |
31 |
|
bool canPerformGL() { |
32 |
|
return t.canPerformGL() && super->canPerformGL(); |
33 |
|
} |
34 |
|
}; |
35 |
|
|
36 |
|
template<class Transform> class InverseTransformCoordSys; |
37 |
|
|
38 |
|
template<class Transform> class TransformCoordSys : public TransformCoordSysBase<Transform> { |
39 |
|
public: |
40 |
|
virtual ZPt transform(const ZPt &p) const { |
41 |
|
ZPt mp; |
42 |
|
t.tr(p, mp); |
43 |
|
return super->transform(mp); |
44 |
|
} |
45 |
|
virtual void vertex(const ZPt &p) const { |
46 |
|
ZPt mp; |
47 |
|
t.tr(p, mp); |
48 |
|
super->vertex(mp); |
49 |
|
} |
50 |
|
virtual bool performGL() { |
51 |
|
if(!super->performGL()) return false; |
52 |
|
return t.performGL(); |
53 |
|
} |
54 |
|
|
55 |
|
virtual CoordSys *createInverse() { |
56 |
|
CoordSys *sinv = super->createInverse(); |
57 |
|
typedef InverseTransformCoordSys<typename Transform::InverseType> Inv; |
58 |
|
Inv *ret = new Inv(sinv, t); |
59 |
|
ret->setOriginal(this); |
60 |
|
return ret; |
61 |
|
} |
62 |
|
|
63 |
|
}; |
64 |
|
|
65 |
|
template<class Transform> class InverseTransformCoordSys : public TransformCoordSysBase<Transform> { |
66 |
|
public: |
67 |
|
template<class Original> InverseTransformCoordSys(CoordSys *s, Original &o) : |
68 |
|
TransformCoordSysBase<Transform>(o.inverseTransform()) { |
69 |
|
super = s; |
70 |
|
} |
71 |
|
|
72 |
|
virtual ZPt transform(const ZPt &p) const { |
73 |
|
ZPt mp = super->transform(p); |
74 |
|
ZPt res; |
75 |
|
t.tr(mp, res); |
76 |
|
return res; |
77 |
|
} |
78 |
|
virtual void vertex(const ZPt &p) const { |
79 |
|
ZPt mp = transform(p); |
80 |
|
glVertex3f(mp.x, mp.y, mp.z); |
81 |
|
} |
82 |
|
virtual bool performGL() { |
83 |
|
if(!t.performGL()) return false; |
84 |
|
return super->performGL(); |
85 |
|
} |
86 |
|
void setOriginal(CoordSys *orig) { inverse = orig; } |
87 |
|
|
88 |
|
}; |
89 |
|
|
90 |
class RootCoords : public CoordSys { |
class RootCoords : public CoordSys { |
91 |
public: |
public: |
92 |
|
virtual void setParams(float *params) { } |
93 |
virtual ZPt transform(const ZPt &p) const { |
virtual ZPt transform(const ZPt &p) const { |
94 |
return p; |
return p; |
95 |
} |
} |
108 |
/** Affine coordinate system (in xy), offset in z. |
/** Affine coordinate system (in xy), offset in z. |
109 |
* Parameter layout: x, y, depth, xx, xy, yx, yy |
* Parameter layout: x, y, depth, xx, xy, yx, yy |
110 |
*/ |
*/ |
111 |
class AffineXYCoords : public CoordSys { |
class AffineXYCoords { |
112 |
float params[7]; |
float params[7]; |
113 |
public: |
public: |
114 |
enum { NParams = 7 }; |
enum { NParams = 7 }; |
115 |
virtual void setParams(float *params) { |
template<class Ptr> void setParams(Ptr p) { |
116 |
for(int i=0; i<7; i++) |
for(int i=0; i<7; i++) |
117 |
this->params[i] = params[i]; |
params[i] = p[i]; |
118 |
} |
} |
119 |
/** Perform the internal transformation of this |
/** Perform the internal transformation of this |
120 |
* coordsys. |
* coordsys. |
124 |
to.y = params[1] + from.x * params[5] + from.y * params[6]; |
to.y = params[1] + from.x * params[5] + from.y * params[6]; |
125 |
to.z = params[2] + from.z; |
to.z = params[2] + from.z; |
126 |
} |
} |
127 |
virtual ZPt transform(const ZPt &p) const { |
bool canPerformGL() { return true; } |
128 |
ZPt mp; |
bool performGL() { |
|
tr(p, mp); |
|
|
return super->transform(mp); |
|
|
} |
|
|
virtual void vertex(const ZPt &p) const { |
|
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
super->vertex(mp); |
|
|
} |
|
|
virtual bool canPerformGL() { return super->canPerformGL(); } |
|
|
virtual bool performGL() { |
|
|
if(!super->performGL()) return false; |
|
129 |
GLfloat matrix[16] = { |
GLfloat matrix[16] = { |
130 |
params[3], params[5], 0, 0, |
params[3], params[5], 0, 0, |
131 |
params[4], params[6], 0, 0, |
params[4], params[6], 0, 0, |
135 |
glMultMatrixf(matrix); |
glMultMatrixf(matrix); |
136 |
return true; |
return true; |
137 |
} |
} |
138 |
virtual float nonlinearity(const ZPt &p, float radius) { |
float nonlinearity(const ZPt &p, float radius) { |
139 |
float mult = 0.5 * (fabs(params[3]) + fabs(params[6])); |
return 0; |
|
ZPt p2; |
|
|
tr(p, p2); |
|
|
return mult * super->nonlinearity(p2, mult * radius); |
|
140 |
} |
} |
141 |
|
|
142 |
protected: |
typedef AffineXYCoords InverseType; |
143 |
virtual CoordSys *createInverse() { |
AffineXYCoords inverseTransform() { |
144 |
CoordSys *sup = super->createInverse(); |
AffineXYCoords inv; |
|
AffineXYCoords *inv = new AffineXYCoords(); |
|
|
inv->setSuper(sup); |
|
145 |
double det = params[3] * params[6] - params[4] * params[5]; |
double det = params[3] * params[6] - params[4] * params[5]; |
146 |
// XXX If det small, trouble!! |
// XXX If det small, trouble!! |
147 |
inv->params[3] = params[6] / det; |
inv.params[3] = params[6] / det; |
148 |
inv->params[4] = -params[4] / det; |
inv.params[4] = -params[4] / det; |
149 |
inv->params[5] = -params[5] / det; |
inv.params[5] = -params[5] / det; |
150 |
inv->params[6] = params[3] / det; |
inv.params[6] = params[3] / det; |
151 |
|
|
152 |
inv->params[0] = -(params[0] * inv->params[3] + |
inv.params[0] = -(params[0] * inv.params[3] + |
153 |
params[1] * inv->params[4]); |
params[1] * inv.params[4]); |
154 |
inv->params[1] = -(params[0] * inv->params[5] + |
inv.params[1] = -(params[0] * inv.params[5] + |
155 |
params[1] * inv->params[6]); |
params[1] * inv.params[6]); |
156 |
inv->params[2] = -params[2]; |
inv.params[2] = -params[2]; |
157 |
return inv; |
return inv; |
158 |
} |
} |
159 |
|
|
162 |
/** Rotation clockwise. |
/** Rotation clockwise. |
163 |
* Parameter layout: angle (degrees) |
* Parameter layout: angle (degrees) |
164 |
*/ |
*/ |
165 |
class RotateXYCoords : public CoordSys { |
class RotateXYCoords { |
166 |
float s, c; |
float a, s, c; |
167 |
public: |
public: |
168 |
enum { NParams = 1 }; |
enum { NParams = 1 }; |
169 |
virtual void setParams(float *params) { |
template<class Ptr> void setParams(Ptr p) { |
170 |
CoordSys::setParams(params); |
a = p[0]; |
171 |
s = sin(params[0] * M_PI / 180); |
} |
172 |
c = cos(params[0] * M_PI / 180); |
void angleWasSet() { |
173 |
|
s = sin(a * M_PI / 180); |
174 |
|
c = cos(a * M_PI / 180); |
175 |
} |
} |
176 |
/** Perform the internal transformation of this |
/** Perform the internal transformation of this |
177 |
* coordsys. |
* coordsys. |
181 |
to.y = -s * from.x + c * from.y; |
to.y = -s * from.x + c * from.y; |
182 |
to.z = from.z; |
to.z = from.z; |
183 |
} |
} |
184 |
virtual ZPt transform(const ZPt &p) const { |
bool canPerformGL() { return true; } |
185 |
ZPt mp; |
bool performGL() { |
186 |
tr(p, mp); |
glRotatef(a, 0, 0, 1); |
187 |
return super->transform(mp); |
return true; |
188 |
} |
} |
189 |
virtual void vertex(const ZPt &p) const { |
typedef RotateXYCoords InverseType; |
190 |
ZPt mp; |
RotateXYCoords inverseTransform() { |
191 |
tr(p, mp); |
RotateXYCoords inv; |
192 |
super->vertex(mp); |
inv.a = -a; |
193 |
|
inv.angleWasSet(); |
194 |
|
return inv; |
195 |
} |
} |
196 |
virtual bool canPerformGL() { return super->canPerformGL(); } |
float nonlinearity(const ZPt &p, float radius) { |
197 |
virtual bool performGL() { |
return 0; |
|
if(!super->performGL()) return false; |
|
|
glRotatef(params[0], 0, 0, 1); |
|
|
return true; |
|
198 |
} |
} |
199 |
}; |
}; |
200 |
|
|
201 |
/** Rotation around 3D vector. |
/** Rotation around 3D vector. |
202 |
* Params: x, y, z, angle |
* Params: x, y, z, angle |
203 |
*/ |
*/ |
204 |
class RotateXYZCoords : public CoordSys { |
class RotateXYZCoords { |
205 |
ZVec vec; float s, c; |
ZVec vec; float a, s, c; |
206 |
public: |
public: |
207 |
enum { NParams = 4 }; |
enum { NParams = 4 }; |
208 |
virtual void setParams(float *params) { |
template<class Ptr> void setParams(Ptr p) { |
209 |
CoordSys::setParams(params); |
vec.x = p[0]; |
210 |
vec.x = params[0]; |
vec.y = p[1]; |
211 |
vec.y = params[1]; |
vec.z = p[2]; |
|
vec.z = params[2]; |
|
212 |
vec = vec.normalized(); |
vec = vec.normalized(); |
213 |
|
a = p[3]; |
214 |
|
|
215 |
|
angleWasSet(); |
216 |
|
|
217 |
s = sin(params[3] * M_PI / 180); |
} |
218 |
c = cos(params[3] * M_PI / 180); |
void angleWasSet() { |
219 |
|
s = sin(a * M_PI / 180); |
220 |
|
c = cos(a * M_PI / 180); |
221 |
} |
} |
222 |
/** Perform the internal transformation of this |
/** Perform the internal transformation of this |
223 |
* coordsys. |
* coordsys. |
231 |
ZVec ortho = para.crossp(vec).normalized(); |
ZVec ortho = para.crossp(vec).normalized(); |
232 |
to = ZPt( same * vec + paral * (c * para - s * ortho) ); |
to = ZPt( same * vec + paral * (c * para - s * ortho) ); |
233 |
} |
} |
234 |
virtual ZPt transform(const ZPt &p) const { |
virtual bool canPerformGL() { return true; } |
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
return super->transform(mp); |
|
|
} |
|
|
virtual void vertex(const ZPt &p) const { |
|
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
super->vertex(mp); |
|
|
} |
|
|
virtual bool canPerformGL() { return super->canPerformGL(); } |
|
235 |
virtual bool performGL() { |
virtual bool performGL() { |
236 |
if(!super->performGL()) return false; |
glRotatef(a, vec.x, vec.y, vec.z); |
|
glRotatef(params[3], vec.x, vec.y, vec.z); |
|
237 |
return true; |
return true; |
238 |
} |
} |
239 |
} ; |
typedef RotateXYZCoords InverseType; |
240 |
; |
RotateXYZCoords inverseTransform() { |
241 |
|
RotateXYZCoords inv; |
242 |
|
inv.vec = vec; |
243 |
|
inv.a = -a; |
244 |
|
inv.angleWasSet(); |
245 |
|
return inv; |
246 |
|
} |
247 |
|
float nonlinearity(const ZPt &p, float radius) { |
248 |
|
return 0; |
249 |
|
} |
250 |
|
}; |
251 |
|
|
252 |
/** Scale. |
/** Scale. |
253 |
* Params: sx, sy, sz |
* Params: sx, sy, sz |
254 |
*/ |
*/ |
255 |
class ScaleXYZCoords : public CoordSys { |
class ScaleXYZCoords { |
256 |
ZVec vec; |
ZVec vec; |
257 |
|
friend class DistortCoords; |
258 |
public: |
public: |
259 |
enum { NParams = 3 }; |
enum { NParams = 3 }; |
260 |
virtual void setParams(float *params) { |
template<class Ptr> void setParams(Ptr p) { |
261 |
CoordSys::setParams(params); |
vec.x = p[0]; |
262 |
vec.x = params[0]; |
vec.y = p[1]; |
263 |
vec.y = params[1]; |
vec.z = p[2]; |
|
vec.z = params[2]; |
|
264 |
} |
} |
265 |
/** Perform the internal transformation of this |
/** Perform the internal transformation of this |
266 |
* coordsys. |
* coordsys. |
270 |
to.y = from.y * vec.y; |
to.y = from.y * vec.y; |
271 |
to.z = from.z * vec.z; |
to.z = from.z * vec.z; |
272 |
} |
} |
273 |
virtual ZPt transform(const ZPt &p) const { |
virtual bool canPerformGL() { return true; } |
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
return super->transform(mp); |
|
|
} |
|
|
virtual void vertex(const ZPt &p) const { |
|
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
super->vertex(mp); |
|
|
} |
|
|
virtual bool canPerformGL() { return super->canPerformGL(); } |
|
274 |
virtual bool performGL() { |
virtual bool performGL() { |
|
if(!super->performGL()) return false; |
|
275 |
glScalef(vec.x, vec.y, vec.z); |
glScalef(vec.x, vec.y, vec.z); |
276 |
return true; |
return true; |
277 |
} |
} |
278 |
|
typedef ScaleXYZCoords InverseType; |
279 |
|
ScaleXYZCoords inverseTransform() { |
280 |
|
ScaleXYZCoords inv; |
281 |
|
inv.vec.x = 1/vec.x; // XXX Numerical accuracy? |
282 |
|
inv.vec.y = 1/vec.y; |
283 |
|
inv.vec.z = 1/vec.z; |
284 |
|
return inv; |
285 |
|
} |
286 |
|
float nonlinearity(const ZPt &p, float radius) { |
287 |
|
return 0; |
288 |
|
} |
289 |
} ; |
} ; |
|
; |
|
290 |
|
|
291 |
|
|
292 |
/** Distorted coordinate system. |
/** Distorted coordinate system. |
294 |
* W and h give the width and height in the inside coordinate system |
* W and h give the width and height in the inside coordinate system |
295 |
* of the zoomed area. |
* of the zoomed area. |
296 |
*/ |
*/ |
297 |
class DistortCoords : public CoordSys { |
class DistortCoords { |
298 |
float x, y; |
float x, y; |
299 |
float w, h; |
float w, h; |
300 |
float mmin; |
float mmin; |
302 |
Fisheye::vector_mag_isotropic<Fisheye::scalar_mag_atan> distort; |
Fisheye::vector_mag_isotropic<Fisheye::scalar_mag_atan> distort; |
303 |
public: |
public: |
304 |
enum { NParams = 6 }; |
enum { NParams = 6 }; |
305 |
virtual void setParams(float *params) { |
template<class Ptr> void setParams(Ptr p) { |
306 |
CoordSys::setParams(params); |
x = p[0]; |
307 |
x = params[0]; |
y = p[1]; |
308 |
y = params[1]; |
mmax = exp(p[2]); |
309 |
mmax = exp(params[2]); |
mmin = exp(p[3]); |
310 |
mmin = exp(params[3]); |
w = p[4]; |
311 |
w = params[4]; |
h = p[5]; |
|
h = params[5]; |
|
312 |
distort.f = Fisheye::scalar_mag_atan(mmax / mmin); |
distort.f = Fisheye::scalar_mag_atan(mmax / mmin); |
313 |
} |
} |
|
virtual ZPt transform(const ZPt &p) const { |
|
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
return super->transform(mp); |
|
|
} |
|
|
virtual void vertex(const ZPt &p) const { |
|
|
ZPt mp; |
|
|
tr(p, mp); |
|
|
super->vertex(mp); |
|
|
} |
|
314 |
void tr(const ZPt &from, ZPt &to) const { |
void tr(const ZPt &from, ZPt &to) const { |
315 |
ZPt p = ZPt((from.x-x) / w, (from.y-y)/ h, from.z); |
ZPt p = ZPt((from.x-x) / w, (from.y-y)/ h, from.z); |
316 |
to = distort(p); |
to = distort(p); |
319 |
to.y *= mmin; |
to.y *= mmin; |
320 |
to.x += x; to.y += y; |
to.x += x; to.y += y; |
321 |
} |
} |
322 |
virtual float nonlinearity(const ZPt &p, float radius) { |
typedef ScaleXYZCoords InverseType; // XXX !!! |
323 |
|
ScaleXYZCoords inverseTransform() { |
324 |
|
ScaleXYZCoords inv; |
325 |
|
inv.vec = ZVec(1,1,1); // XXX! |
326 |
|
return inv; |
327 |
|
} |
328 |
|
bool canPerformGL() { return false; } |
329 |
|
bool performGL() { return false; } |
330 |
|
|
331 |
|
float nonlinearity(const ZPt &p, float radius) { |
332 |
float wh = 0.5*(w+h); |
float wh = 0.5*(w+h); |
333 |
float dist = hypot((p.x-x)/w, (p.y-y)/h) - radius/wh; |
float dist = hypot((p.x-x)/w, (p.y-y)/h) - radius/wh; |
334 |
if(dist < 0) dist = 0; |
if(dist < 0) dist = 0; |
343 |
template<class C> class Factory : public SomeFactory { |
template<class C> class Factory : public SomeFactory { |
344 |
public: |
public: |
345 |
virtual int nparams() { return C::NParams; } |
virtual int nparams() { return C::NParams; } |
346 |
virtual CoordSys *create() { return new C(); } |
virtual CoordSys *create() { return new TransformCoordSys<C>(); } |
347 |
}; |
}; |
348 |
|
|
349 |
extern SomeFactory* facs[]; |
extern SomeFactory* facs[]; |