296 lines
5.3 KiB
C++
296 lines
5.3 KiB
C++
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
|
// <dhilvert@ugcs.caltech.edu>
|
|
|
|
/* This file is part of the Anti-Lamenessing Engine.
|
|
|
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifndef __d3point_h__
|
|
#define __d3point_h__
|
|
|
|
/*
|
|
* Structure to describe a point in three dimensions.
|
|
*/
|
|
class point {
|
|
private:
|
|
ale_pos x[3];
|
|
|
|
public:
|
|
point() {
|
|
x[0] = 0;
|
|
x[1] = 0;
|
|
x[2] = 0;
|
|
}
|
|
|
|
point(ale_pos x0, ale_pos x1, ale_pos x2) {
|
|
x[0] = x0;
|
|
x[1] = x1;
|
|
x[2] = x2;
|
|
}
|
|
|
|
point(const point &p) {
|
|
x[0] = p[0];
|
|
x[1] = p[1];
|
|
x[2] = p[2];
|
|
}
|
|
|
|
static point unit(int dimension) {
|
|
if (dimension == 0)
|
|
return point(1, 0, 0);
|
|
if (dimension == 1)
|
|
return point(0, 1, 0);
|
|
if (dimension == 2)
|
|
return point(0, 0, 1);
|
|
|
|
assert(0);
|
|
}
|
|
|
|
static point undefined() {
|
|
double a = 0;
|
|
|
|
point p(0, 0, 0);
|
|
|
|
return p / a;
|
|
}
|
|
|
|
static point posinf() {
|
|
double a = +1;
|
|
double z = +0;
|
|
|
|
a = a / z;
|
|
|
|
assert (isinf(a) && a > 0);
|
|
|
|
return point(a, a, a);
|
|
}
|
|
|
|
static point neginf() {
|
|
point n = -posinf();
|
|
|
|
assert (isinf(n[0]) && n[0] < 0);
|
|
|
|
return n;
|
|
}
|
|
|
|
void accumulate_max(point p) {
|
|
for (int d = 0; d < 3; d++)
|
|
if (p[d] > x[d])
|
|
x[d] = p[d];
|
|
}
|
|
|
|
void accumulate_min(point p) {
|
|
for (int d = 0; d < 3; d++)
|
|
if (p[d] < x[d])
|
|
x[d] = p[d];
|
|
}
|
|
|
|
int defined() const {
|
|
return (!isnan(x[0])
|
|
&& !isnan(x[1])
|
|
&& !isnan(x[2]));
|
|
}
|
|
|
|
int finite() const {
|
|
return (::finite(x[0])
|
|
&& ::finite(x[1])
|
|
&& ::finite(x[2]));
|
|
}
|
|
|
|
static int defined(const point &p) {
|
|
return p.defined();
|
|
}
|
|
|
|
/*
|
|
* Z-values of zero are almost never the right thing to do ...
|
|
*/
|
|
point(d2::point p, ale_pos z = 0) {
|
|
x[0] = p[0];
|
|
x[1] = p[1];
|
|
x[2] = z;
|
|
}
|
|
|
|
const ale_pos &operator[](int i) const {
|
|
assert (i >= 0);
|
|
assert (i < 3);
|
|
|
|
return x[i];
|
|
}
|
|
|
|
ale_pos &operator[](int i) {
|
|
assert (i >= 0);
|
|
assert (i < 3);
|
|
|
|
return x[i];
|
|
}
|
|
|
|
d2::point xy() const {
|
|
d2::point result;
|
|
|
|
result[0] = x[0];
|
|
result[1] = x[1];
|
|
|
|
return result;
|
|
}
|
|
|
|
point operator+(point p) const {
|
|
return point(x[0] + p[0], x[1] + p[1], x[2] + p[2]);
|
|
}
|
|
|
|
point operator-(point p) const {
|
|
return point(x[0] - p[0], x[1] - p[1], x[2] - p[2]);
|
|
}
|
|
|
|
point operator-() const {
|
|
return point(-x[0], -x[1], -x[2]);
|
|
}
|
|
|
|
point operator/(ale_pos r) const {
|
|
return point(x[0] / r, x[1] / r, x[2] / r);
|
|
}
|
|
|
|
point operator /=(ale_pos r) {
|
|
x[0] /= r;
|
|
x[1] /= r;
|
|
x[2] /= r;
|
|
|
|
return *this;
|
|
}
|
|
|
|
point operator *=(ale_pos r) {
|
|
x[0] *= r;
|
|
x[1] *= r;
|
|
x[2] *= r;
|
|
|
|
return *this;
|
|
}
|
|
|
|
point operator +=(point p) {
|
|
x[0] += p[0];
|
|
x[1] += p[1];
|
|
x[2] += p[2];
|
|
|
|
return *this;
|
|
}
|
|
|
|
point operator -=(point p) {
|
|
x[0] -= p[0];
|
|
x[1] -= p[1];
|
|
x[2] -= p[2];
|
|
|
|
return *this;
|
|
}
|
|
|
|
int operator !=(point p) {
|
|
return (x[0] != p[0]
|
|
|| x[1] != p[1]
|
|
|| x[2] != p[2]);
|
|
}
|
|
|
|
point mult(ale_pos d) const {
|
|
return point(x[0] * d, x[1] * d, x[2] * d);
|
|
}
|
|
|
|
point operator*(point p) const {
|
|
return point(x[0] * p[0], x[1] * p[1], x[2] * p[2]);
|
|
}
|
|
|
|
ale_pos normsq() const {
|
|
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2];
|
|
}
|
|
|
|
ale_pos norm() const {
|
|
return sqrt(normsq());
|
|
}
|
|
|
|
point normalize() const {
|
|
return operator/(norm());
|
|
}
|
|
|
|
ale_pos lengthtosq(point p) const {
|
|
point diff = operator-(p);
|
|
return diff.normsq();
|
|
}
|
|
|
|
ale_pos lengthto(point p) const {
|
|
return sqrt(lengthtosq(p));
|
|
}
|
|
|
|
ale_pos anglebetw(point p, point q) {
|
|
/*
|
|
* by the law of cosines, the cosine is equal to:
|
|
*
|
|
* (lengthtosq(p) + lengthtosq(q) - p.lengthtosq(q))
|
|
* / (2 * lengthto(p) * lengthto(q))
|
|
*/
|
|
|
|
ale_pos to_p = lengthtosq(p);
|
|
ale_pos to_q = lengthtosq(q);
|
|
|
|
ale_pos cos_of = (double) (to_p + to_q - p.lengthtosq(q))
|
|
/ (double) (2 * sqrt(to_p) * sqrt(to_q));
|
|
|
|
/*
|
|
* XXX: is the fabs() required?
|
|
*/
|
|
|
|
return fabs(acos(cos_of));
|
|
}
|
|
|
|
|
|
/*
|
|
* Determine the cross product
|
|
*/
|
|
point xproduct(point p, point q) {
|
|
point pp = p;
|
|
point qq = q;
|
|
|
|
pp -= *this;
|
|
qq -= *this;
|
|
|
|
return point(pp[1] * qq[2] - pp[2] * qq[1],
|
|
pp[2] * qq[0] - pp[0] * qq[2],
|
|
pp[0] * qq[1] - pp[1] * qq[0]);
|
|
}
|
|
|
|
/*
|
|
* Determine the dot product
|
|
*/
|
|
ale_pos dproduct(const point &p) {
|
|
return x[0] * p[0] + x[1] * p[1] + x[2] * p[2];
|
|
}
|
|
|
|
/*
|
|
* Determine whether the point is inside a given volume
|
|
*/
|
|
int inside(const point &min, const point &max) {
|
|
for (int d = 0; d < 3; d++) {
|
|
if (min[d] > x[d])
|
|
return 0;
|
|
if (max[d] < x[d])
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
inline point operator*(const point &p, double d) {
|
|
return p.mult(d);
|
|
}
|
|
inline point operator*(double d, const point &p) {
|
|
return p.mult(d);
|
|
}
|
|
#endif
|