summaryrefslogtreecommitdiffstats
path: root/vector/vector3d.C
diff options
context:
space:
mode:
Diffstat (limited to 'vector/vector3d.C')
-rw-r--r--vector/vector3d.C468
1 files changed, 468 insertions, 0 deletions
diff --git a/vector/vector3d.C b/vector/vector3d.C
new file mode 100644
index 0000000..78575ae
--- /dev/null
+++ b/vector/vector3d.C
@@ -0,0 +1,468 @@
+// Copyright (C) 1999-2018
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <tk.h>
+
+#include "vector3d.h"
+#include "vector.h"
+#include "fuzzy.h"
+
+// Vector3d
+
+Vector3d::Vector3d(const Vector& a)
+{
+ v[0]=a.v[0];
+ v[1]=a.v[1];
+ v[2]=0;
+ v[3]=1;
+}
+
+Vector3d::Vector3d(const Vector& a, double z)
+{
+ v[0]=a.v[0];
+ v[1]=a.v[1];
+ v[2]=z;
+ v[3]=1;
+}
+
+Vector3d& Vector3d::operator=(const Vector& a)
+{
+ v[0]=a.v[0];
+ v[1]=a.v[1];
+ v[2]=0;
+ v[3]=1;
+ return *this;
+}
+
+ostream& operator<<(ostream& os, const Vector3d& v)
+{
+ unsigned char sep = (unsigned char)os.iword(Vector::separator);
+ if (!sep)
+ sep = ' ';
+
+ unsigned char unit = (unsigned char)os.iword(Vector::unit);
+ if (!unit)
+ os << v.v[0] << sep << v.v[1] << sep << v.v[2];
+ else
+ os << v.v[0] << unit << v.v[1] << unit << v.v[2] << unit;
+
+ // reset unit
+ os.iword(Vector::unit) = '\0';
+
+ return os;
+}
+
+istream& operator>>(istream& s, Vector3d& v)
+{
+ s >> v.v[0] >> v.v[1] >> v.v[2];
+ return s;
+}
+
+// Vertex3d
+
+ostream& operator<<(ostream& os, const Vertex3d& v)
+{
+ os << v.vector;
+ return os;
+}
+
+// Matrix3d
+
+Matrix3d& Matrix3d::operator*=(const Matrix3d& a)
+{
+ Matrix3d r;
+ for (int ii=0; ii<4; ii++)
+ for (int jj=0; jj<4; jj++)
+ r.m[ii][jj] =
+ m[ii][0]*a.m[0][jj] +
+ m[ii][1]*a.m[1][jj] +
+ m[ii][2]*a.m[2][jj] +
+ m[ii][3]*a.m[3][jj];
+
+ return *this=r;
+}
+
+Matrix3d::Matrix3d(const Matrix& a)
+{
+ m[0][0]=a.m[0][0];
+ m[0][1]=a.m[0][1];
+ m[0][2]=0;
+ m[0][3]=0;
+
+ m[1][0]=a.m[1][0];
+ m[1][1]=a.m[1][1];
+ m[1][2]=0;
+ m[1][3]=0;
+
+ m[2][0]=0;
+ m[2][1]=0;
+ m[2][2]=1;
+ m[2][3]=0;
+
+ m[3][0]=a.m[2][0];
+ m[3][1]=a.m[2][1];
+ m[3][2]=0;
+ m[3][3]=1;
+}
+
+Matrix3d Matrix3d::invert()
+{
+ Matrix3d cc = this->cofactor();
+ Matrix3d aa = cc.adjoint();
+ double dd = m[0][0]*aa.m[0][0] + m[0][1]*aa.m[1][0] +
+ m[0][2]*aa.m[2][0] + m[0][3]*aa.m[3][0];
+
+ Matrix3d rr;
+ for (int ii=0; ii<4; ii++ )
+ for (int jj=0; jj<4; jj++)
+ rr.m[ii][jj] = aa.m[ii][jj]/dd;
+
+ return rr;
+}
+
+Matrix3d Matrix3d::cofactor()
+{
+ Matrix3d rr;
+
+ rr.m[0][0] = +det2d(m[1][1],m[1][2],m[1][3],
+ m[2][1],m[2][2],m[2][3],
+ m[3][1],m[3][2],m[3][3]);
+ rr.m[0][1] = -det2d(m[1][0],m[1][2],m[1][3],
+ m[2][0],m[2][2],m[2][3],
+ m[3][0],m[3][2],m[3][3]);
+ rr.m[0][2] = +det2d(m[1][0],m[1][1],m[1][3],
+ m[2][0],m[2][1],m[2][3],
+ m[3][0],m[3][1],m[3][3]);
+ rr.m[0][3] = -det2d(m[1][0],m[1][1],m[1][2],
+ m[2][0],m[2][1],m[2][2],
+ m[3][0],m[3][1],m[3][2]);
+
+ rr.m[1][0] = -det2d(m[0][1],m[0][2],m[0][3],
+ m[2][1],m[2][2],m[2][3],
+ m[3][1],m[3][2],m[3][3]);
+ rr.m[1][1] = +det2d(m[0][0],m[0][2],m[0][3],
+ m[2][0],m[2][2],m[2][3],
+ m[3][0],m[3][2],m[3][3]);
+ rr.m[1][2] = -det2d(m[0][0],m[0][1],m[0][3],
+ m[2][0],m[2][1],m[2][3],
+ m[3][0],m[3][1],m[3][3]);
+ rr.m[1][3] = +det2d(m[0][0],m[0][1],m[0][2],
+ m[2][0],m[2][1],m[2][2],
+ m[3][0],m[3][1],m[3][2]);
+
+ rr.m[2][0] = +det2d(m[0][1],m[0][2],m[0][3],
+ m[1][1],m[1][2],m[1][3],
+ m[3][1],m[3][2],m[3][3]);
+ rr.m[2][1] = -det2d(m[0][0],m[0][2],m[0][3],
+ m[1][0],m[1][2],m[1][3],
+ m[3][0],m[3][2],m[3][3]);
+ rr.m[2][2] = +det2d(m[0][0],m[0][1],m[0][3],
+ m[1][0],m[1][1],m[1][3],
+ m[3][0],m[3][1],m[3][3]);
+ rr.m[2][3] = -det2d(m[0][0],m[0][1],m[0][2],
+ m[1][0],m[1][1],m[1][2],
+ m[3][0],m[3][1],m[3][2]);
+
+ rr.m[3][0] = -det2d(m[0][1],m[0][2],m[0][3],
+ m[1][1],m[1][2],m[1][3],
+ m[2][1],m[2][2],m[2][3]);
+ rr.m[3][1] = +det2d(m[0][0],m[0][2],m[0][3],
+ m[1][0],m[1][2],m[1][3],
+ m[2][0],m[2][2],m[2][3]);
+ rr.m[3][2] = -det2d(m[0][0],m[0][1],m[0][3],
+ m[1][0],m[1][1],m[1][3],
+ m[2][0],m[2][1],m[2][3]);
+ rr.m[3][3] = +det2d(m[0][0],m[0][1],m[0][2],
+ m[1][0],m[1][1],m[1][2],
+ m[2][0],m[2][1],m[2][2]);
+
+ return rr;
+}
+
+Matrix3d Matrix3d::adjoint()
+{
+ Matrix3d rr;
+ for (int ii=0; ii<4; ii++)
+ for (int jj=0; jj<4; jj++)
+ rr.m[jj][ii] = m[ii][jj];
+
+ return rr;
+}
+
+double Matrix3d::det()
+{
+ Matrix3d cc = this->cofactor();
+ Matrix3d aa = cc.adjoint();
+ return m[0][0]*aa.m[0][0] + m[0][1]*aa.m[1][0]
+ + m[0][2]*aa.m[2][0] + m[0][3]*aa.m[3][0];
+}
+
+void Matrix3d::dump()
+{
+ for (int ii=0; ii<4; ii++) {
+ for (int jj=0; jj<4; jj++)
+ cerr << m[ii][jj] << ' ';
+ cerr << endl;
+ }
+ cerr << endl;
+}
+
+ostream& operator<<(ostream& os, const Matrix3d& m)
+{
+ os << ' ';
+ for (int ii=0; ii<4; ii++)
+ for (int jj=0; jj<3; jj++)
+ os << m.m[ii][jj] << ' ';
+
+ return os;
+}
+
+istream& operator>>(istream& s, Matrix3d& m)
+{
+ for (int ii=0; ii<4; ii++ )
+ for (int jj=0; jj<3; jj++)
+ s >> m.m[ii][jj];
+
+ return s;
+}
+
+// Translate3d
+
+Translate3d::Translate3d(const Vector& v)
+{
+ m[3][0]=v.v[0];
+ m[3][1]=v.v[1];
+ m[3][2]=0;
+}
+
+Translate3d::Translate3d(const Vector& v, double z)
+{
+ m[3][0]=v.v[0];
+ m[3][1]=v.v[1];
+ m[3][2]=z;
+}
+
+ostream& operator<<(ostream& os, const Translate3d& m)
+{
+ os << ' ' << m.m[3][0] << ' ' << m.m[3][1] << ' ' << m.m[3][2] << ' ';
+ return os;
+}
+
+istream& operator>>(istream& s, Translate3d& m)
+{
+ s >> m.m[3][0] >> m.m[3][1] >> m.m[3][2];
+ return s;
+}
+
+// Scale3d
+
+Scale3d::Scale3d(const Vector& v)
+{
+ m[0][0]=v.v[0]; m[1][1]=v.v[1]; m[2][2]=1;
+}
+
+Scale3d::Scale3d(const Vector& v, double c)
+{
+ m[0][0]=v.v[0]; m[1][1]=v.v[1]; m[2][2]=c;
+}
+
+ostream& operator<<(ostream& os, const Scale3d& m)
+{
+ os << ' ' << m.m[0][0] << ' ' << m.m[1][1] << ' ' << m.m[2][2] << ' ';
+ return os;
+}
+
+istream& operator>>(istream& s, Scale3d& m)
+{
+ s >> m.m[0][0] >> m.m[1][1] >> m.m[2][2];
+ return s;
+}
+
+// RotateX3d
+
+RotateX3d::RotateX3d(double a) : Matrix3d()
+{
+ m[1][1] = cos(a);
+ m[1][2] = sin(a);
+ m[2][1] = -sin(a);
+ m[2][2] = cos(a);
+
+ // this fixes a problem with numbers too small and tring to invert the matrix
+ tzero(&m[1][1]);
+ tzero(&m[1][2]);
+ tzero(&m[2][1]);
+ tzero(&m[2][2]);
+}
+
+ostream& operator<<(ostream& os, const RotateX3d& m)
+{
+ os << ' ' << m.m[1][1] << ' ' << m.m[1][2]
+ << ' ' << m.m[2][1] << ' ' << m.m[2][2] << ' ';
+ return os;
+}
+
+istream& operator>>(istream& s, RotateX3d& m)
+{
+ s >> m.m[1][1] >> m.m[1][2] >> m.m[2][1] >> m.m[2][2];
+ return s;
+}
+
+// RotateY3d
+
+RotateY3d::RotateY3d(double a) : Matrix3d()
+{
+ m[0][0] = cos(a);
+ m[0][2] = -sin(a);
+ m[2][0] = sin(a);
+ m[2][2] = cos(a);
+
+ // this fixes a problem with numbers too small and tring to invert the matrix
+ tzero(&m[0][0]);
+ tzero(&m[0][2]);
+ tzero(&m[2][0]);
+ tzero(&m[2][2]);
+}
+
+ostream& operator<<(ostream& os, const RotateY3d& m)
+{
+ os << ' ' << m.m[0][0] << ' ' << m.m[0][2]
+ << ' ' << m.m[2][0] << ' ' << m.m[2][2] << ' ';
+ return os;
+}
+
+istream& operator>>(istream& s, RotateY3d& m)
+{
+ s >> m.m[0][0] >> m.m[0][2] >> m.m[2][0] >> m.m[2][2];
+ return s;
+}
+
+// RotateZ3d
+
+RotateZ3d::RotateZ3d(double a) : Matrix3d()
+{
+ m[0][0] = cos(a);
+ m[0][1] = sin(a);
+ m[1][0] = -sin(a);
+ m[1][1] = cos(a);
+
+ // this fixes a problem with numbers too small and tring to invert the matrix
+ tzero(&m[0][0]);
+ tzero(&m[0][1]);
+ tzero(&m[1][0]);
+ tzero(&m[1][1]);
+}
+
+ostream& operator<<(ostream& os, const RotateZ3d& m)
+{
+ os << ' ' << m.m[0][0] << ' ' << m.m[0][1]
+ << ' ' << m.m[1][0] << ' ' << m.m[1][1] << ' ';
+ return os;
+}
+
+istream& operator>>(istream& s, RotateZ3d& m)
+{
+ s >> m.m[0][0] >> m.m[0][1] >> m.m[1][0] >> m.m[1][1];
+ return s;
+}
+
+// BBox3d
+
+BBox3d::BBox3d(double a, double b, double c, double d, double e, double f)
+{
+ // we want a 'positive' cube
+ ll.v[0] = a < d ? a : d;
+ ll.v[1] = b < e ? b : e;
+ ll.v[2] = c < f ? c : f;
+ ur.v[0] = a < d ? d : a;
+ ur.v[1] = b < e ? e : b;
+ ur.v[2] = c < f ? f : c;
+}
+
+BBox3d::BBox3d(const Vector3d& l, const Vector3d& h)
+{
+ // we want a 'positive' cube
+ ll.v[0] = l.v[0] < h.v[0] ? l.v[0] : h.v[0];
+ ll.v[1] = l.v[1] < h.v[1] ? l.v[1] : h.v[1];
+ ll.v[2] = l.v[2] < h.v[2] ? l.v[2] : h.v[2];
+ ur.v[0] = l.v[0] < h.v[0] ? h.v[0] : l.v[0];
+ ur.v[1] = l.v[1] < h.v[1] ? h.v[1] : l.v[1];
+ ur.v[2] = l.v[2] < h.v[2] ? h.v[2] : l.v[2];
+}
+
+int BBox3d::isIn(const Vector3d& v) const
+{
+ return !(v.v[0] < ll.v[0] || v.v[1] < ll.v[1] || v.v[2] < ll.v[2] ||
+ v.v[0] > ur.v[0] || v.v[1] > ur.v[1] || v.v[2] > ur.v[2]);
+}
+
+double BBox3d::volume()
+{
+ Vector3d aa =ur-ll;
+ return aa[0]*aa[1]*aa[2];
+}
+
+BBox3d& BBox3d::bound(const Vector3d& vv)
+{
+ // expand bbox3d to include vector3d
+ if (vv.v[0] < ll[0])
+ ll[0] = vv.v[0];
+ if (vv.v[1] < ll[1])
+ ll[1] = vv.v[1];
+ if (vv.v[2] < ll[2])
+ ll[2] = vv.v[2];
+
+ if (vv.v[0] > ur[0])
+ ur[0] = vv.v[0];
+ if (vv.v[1] > ur[1])
+ ur[1] = vv.v[1];
+ if (vv.v[2] > ur[2])
+ ur[2] = vv.v[2];
+
+ return *this;
+}
+
+ostream& operator<<(ostream& os, const BBox3d& b)
+{
+ os << b.ll << ' ' << b.ur;
+ return os;
+}
+
+// WorldToView
+
+Matrix3d WorldToView3d(const Vector3d& cop,
+ const Vector3d& vpn,
+ const Vector3d& vup)
+{
+ Vector3d zv = ((Vector3d)vpn).normalize();
+ Vector3d xv = cross(zv,(Vector3d&)vup).normalize();
+ Vector3d yv = cross(xv,zv).normalize();
+
+ return Translate3d(-cop) *
+ Matrix3d(xv[0],yv[0],zv[0],
+ xv[1],yv[1],zv[1],
+ xv[2],yv[2],zv[2],
+ 0, 0, 0);
+}
+
+Matrix3d WorldToView3d(const Vector3d& cop,
+ double head, double pitch, double bank)
+{
+ return Translate3d(-cop) *
+ RotateY3d(head) *
+ RotateX3d(pitch) *
+ RotateZ3d(bank) *
+ Scale3d(1,1,-1);
+}
+
+Matrix3d WorldToView3d(const Vector3d& cop, const Vector3d& vpn, double bank)
+{
+ Vector3d zv = -((Vector3d)vpn).normalize();
+ double l=sqrt(zv[0]*zv[0]+zv[2]*zv[2]);
+
+ return Translate3d(-cop) *
+ RotateY3d(zv[2]/l,zv[0]/l,-zv[0]/l,zv[2]/l) *
+ RotateX3d(l,zv[1],-zv[1],l) *
+ RotateZ3d(bank) *
+ Scale3d(1,1,-1);
+}