// Copyright 2002, 2004 David Hilvert , // /* 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