// Returns the cross product of two vectors vector3 vector3::Cross(const vector3 &v2) const { vector3 r; r.x() = (y() * v2.z()) - (z() * v2.y()); r.y() = (z() * v2.x()) - (x() * v2.z()); r.z() = (x() * v2.y()) - (y() * v2.x()); return r; }
vector3 vector3::Transform(const vector3& v, const matrix& m) { vector3 result = vector3( (v.x() * m(0,0)) + (v.x() * m(1,0)) + (v.x() * m(2,0)) + m(3,0), (v.y() * m(0,1)) + (v.y() * m(1,1)) + (v.y() * m(2,1)) + m(3,1), (v.z() * m(0,2)) + (v.z() * m(1,2)) + (v.z() * m(2,2) ) + m(3,2)); return result; }
/*! Calculates the product m*v of the matrix m and the column vector represented by v */ vector3 operator *(const matrix3x3 &m,const vector3 &v) { vector3 vv; vv.x() = v.x()*m.ele[0][0] + v.y()*m.ele[0][1] + v.z()*m.ele[0][2]; vv.y() = v.x()*m.ele[1][0] + v.y()*m.ele[1][1] + v.z()*m.ele[1][2]; vv.z() = v.x()*m.ele[2][0] + v.y()*m.ele[2][1] + v.z()*m.ele[2][2]; return(vv); }
/// // CheckPoint() // // Test the point "alpha" of the way from P1 to P2 // See if it is on a face of the cube // Consider only faces in "mask" static int CheckPoint(const vector3& p1, const vector3& p2, number alpha, long mask) { vector3 plane_point; plane_point.x() = LERP(alpha, p1.x(), p2.x()); plane_point.y() = LERP(alpha, p1.y(), p2.y()); plane_point.z() = LERP(alpha, p1.z(), p2.z()); return(FacePlane(plane_point) & mask); }
vector3 transformedFractionalCoordinate(vector3 originalCoordinate) { // ensure the fractional coordinate is entirely within the unit cell vector3 returnValue(originalCoordinate); // So if we have -2.08, we take -2.08 - (-2) = -0.08 .... exactly what we want returnValue.SetX(originalCoordinate.x() - static_cast<int>(originalCoordinate.x())); returnValue.SetY(originalCoordinate.y() - static_cast<int>(originalCoordinate.y())); returnValue.SetZ(originalCoordinate.z() - static_cast<int>(originalCoordinate.z())); return returnValue; }
/// // Bevel3d() // // Which of the eight corner plane(s) is point P outside of? // static int Bevel3d(const vector3& p) { int outcode; outcode = 0; if (( p.x() + p.y() + p.z()) > 1.5) outcode |= 0x01; if (( p.x() + p.y() - p.z()) > 1.5) outcode |= 0x02; if (( p.x() - p.y() + p.z()) > 1.5) outcode |= 0x04; if (( p.x() - p.y() - p.z()) > 1.5) outcode |= 0x08; if ((-p.x() + p.y() + p.z()) > 1.5) outcode |= 0x10; if ((-p.x() + p.y() - p.z()) > 1.5) outcode |= 0x20; if ((-p.x() - p.y() + p.z()) > 1.5) outcode |= 0x40; if ((-p.x() - p.y() - p.z()) > 1.5) outcode |= 0x80; return(outcode); }
matrix4x4 translation_matrix(vector3 const& v) { return matrix4x4 (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v.x(), v.y(), v.z(), 1); }
/// // PointTriangleIntersection() // // Test if 3D point is inside 3D triangle static int PointTriangleIntersection(const vector3& p, const TRI& t) { int sign12,sign23,sign31; vector3 vect12,vect23,vect31,vect1h,vect2h,vect3h; vector3 cross12_1p,cross23_2p,cross31_3p; /// // First, a quick bounding-box test: // If P is outside triangle bbox, there cannot be an intersection. // if (p.x() > MAX3(t.m_P[0].x(), t.m_P[1].x(), t.m_P[2].x())) return(OUTSIDE); if (p.y() > MAX3(t.m_P[0].y(), t.m_P[1].y(), t.m_P[2].y())) return(OUTSIDE); if (p.z() > MAX3(t.m_P[0].z(), t.m_P[1].z(), t.m_P[2].z())) return(OUTSIDE); if (p.x() < MIN3(t.m_P[0].x(), t.m_P[1].x(), t.m_P[2].x())) return(OUTSIDE); if (p.y() < MIN3(t.m_P[0].y(), t.m_P[1].y(), t.m_P[2].y())) return(OUTSIDE); if (p.z() < MIN3(t.m_P[0].z(), t.m_P[1].z(), t.m_P[2].z())) return(OUTSIDE); /// // For each triangle side, make a vector out of it by subtracting vertexes; // make another vector from one vertex to point P. // The crossproduct of these two vectors is orthogonal to both and the // signs of its X,Y,Z components indicate whether P was to the inside or // to the outside of this triangle side. // SUB(t.m_P[0], t.m_P[1], vect12); SUB(t.m_P[0], p, vect1h); CROSS(vect12, vect1h, cross12_1p) sign12 = SIGN3(cross12_1p); /* Extract X,Y,Z signs as 0..7 or 0...63 integer */ SUB(t.m_P[1], t.m_P[2], vect23) SUB(t.m_P[1], p, vect2h); CROSS(vect23, vect2h, cross23_2p) sign23 = SIGN3(cross23_2p); SUB(t.m_P[2], t.m_P[0], vect31) SUB(t.m_P[2], p, vect3h); CROSS(vect31, vect3h, cross31_3p) sign31 = SIGN3(cross31_3p); /// // If all three crossproduct vectors agree in their component signs, / // then the point must be inside all three. // P cannot be OUTSIDE all three sides simultaneously. // return (((sign12 & sign23 & sign31) == 0) ? OUTSIDE : INSIDE); }
const vector3 vector3::operator / (const vector3 &v2) const { vector3 r; r.x() = x() / v2.x(); r.y() = y() / v2.y(); r.z() = z() / v2.z(); return r; }
// Helper function -- transform fractional coordinates to ensure they lie in the unit cell // // Copied from generic.cpp - should be defined in some header ? vector.h ? vector3 transformedFractionalCoordinate2(vector3 originalCoordinate) { // ensure the fractional coordinate is entirely within the unit cell vector3 returnValue(originalCoordinate); // So if we have -2.08, we take -2.08 - (-2) = -0.08 .... almost what we want returnValue.SetX(originalCoordinate.x() - int(originalCoordinate.x()) ); returnValue.SetY(originalCoordinate.y() - int(originalCoordinate.y()) ); returnValue.SetZ(originalCoordinate.z() - int(originalCoordinate.z()) ); if (returnValue.x() < 0.0) returnValue.SetX(returnValue.x() + 1.0); if (returnValue.y() < 0.0) returnValue.SetY(returnValue.y() + 1.0); if (returnValue.z() < 0.0) returnValue.SetZ(returnValue.z() + 1.0); return returnValue; }
/// // Bevel2d() // // Which of the twelve edge plane(s) is point P outside of? // static int Bevel2d(const vector3& p) { int outcode; outcode = 0; if ( p.x() + p.y() > 1.0) outcode |= 0x001; if ( p.x() - p.y() > 1.0) outcode |= 0x002; if (-p.x() + p.y() > 1.0) outcode |= 0x004; if (-p.x() - p.y() > 1.0) outcode |= 0x008; if ( p.x() + p.z() > 1.0) outcode |= 0x010; if ( p.x() - p.z() > 1.0) outcode |= 0x020; if (-p.x() + p.z() > 1.0) outcode |= 0x040; if (-p.x() - p.z() > 1.0) outcode |= 0x080; if ( p.y() + p.z() > 1.0) outcode |= 0x100; if ( p.y() - p.z() > 1.0) outcode |= 0x200; if (-p.y() + p.z() > 1.0) outcode |= 0x400; if (-p.y() - p.z() > 1.0) outcode |= 0x800; return(outcode); }
/// // FacePlane() // // Which of the six face-plane(s) is point P outside of? // static int FacePlane(const vector3& p) { int outcode; outcode = 0; if (p.x() > .5) outcode |= 0x01; if (p.x() < -.5) outcode |= 0x02; if (p.y() > .5) outcode |= 0x04; if (p.y() < -.5) outcode |= 0x08; if (p.z() > .5) outcode |= 0x10; if (p.z() < -.5) outcode |= 0x20; return(outcode); }
quat rotation_quat(vector3 const& axe, real const& angle ) { // create (sin(a/2)*axis, cos(a/2)) quaternion // which rotates the point a radians around "axis" quat res; vector4 u = vector4(axe.x(), axe.y(), axe.z(), 0); u.normalize(); real sina2 = sin(angle/2); real cosa2 = cos(angle/2); res.qx() = sina2 * u.x(); res.qy() = sina2 * u.y(); res.qz() = sina2 * u.z(); res.qw() = cosa2; return res; }
int CalculateNormalNoNormalize(vector3& vNormOut, Grid& grid, Edge* e, Grid::VertexAttachmentAccessor<APosition>& aaPos, Grid::FaceAttachmentAccessor<ANormal>* paaNormFACE) { Face* f[2]; int numFaces = GetAssociatedFaces(f, grid, e, 2); switch(numFaces){ case 0:{ // if there are no associated faces. // we'll assume that the edge lies in the xy plane and return its normal vector3 dir; VecSubtract(dir, aaPos[e->vertex(1)], aaPos[e->vertex(0)]); vNormOut.x() = dir.y(); vNormOut.y() = -dir.x(); vNormOut.z() = 0; }break; case 1: // if there is one face, the normal will be set to the faces normal if(paaNormFACE) vNormOut = (*paaNormFACE)[f[0]]; else{ CalculateNormalNoNormalize(vNormOut, f[0], aaPos); } break; default: // there are at least 2 associated faces if(paaNormFACE) VecAdd(vNormOut, (*paaNormFACE)[f[0]], (*paaNormFACE)[f[1]]); else{ vector3 fn0, fn1; CalculateNormalNoNormalize(fn0, f[0], aaPos); CalculateNormalNoNormalize(fn1, f[1], aaPos); VecAdd(vNormOut, fn0, fn1); VecScale(vNormOut, vNormOut, 0.5); } VecNormalize(vNormOut, vNormOut); break; } return numFaces; }
void matrix3x3::SetRow(int row, const vector3 &v) #ifdef OB_OLD_MATH_CHECKS throw(OBError) #endif { #ifdef OB_OLD_MATH_CHECKS if (row > 2) { OBError er("matrix3x3::SetRow(int row, const vector3 &v)", "The method was called with row > 2.", "This is a programming error in your application."); throw er; } #endif ele[row][0] = v.x(); ele[row][1] = v.y(); ele[row][2] = v.z(); }
void matrix3x3::SetColumn(int col, const vector3 &v) #ifdef OB_OLD_MATH_CHECKS throw(OBError) #endif { #ifdef OB_OLD_MATH_CHECKS if (col > 2) { OBError er("matrix3x3::SetColumn(int col, const vector3 &v)", "The method was called with col > 2.", "This is a programming error in your application."); throw er; } #endif ele[0][col] = v.x(); ele[1][col] = v.y(); ele[2][col] = v.z(); }
vector3 OBUnitCell::WrapFractionalCoordinate(vector3 frac) const { double x = fmod(frac.x(), 1); double y = fmod(frac.y(), 1); double z = fmod(frac.z(), 1); if (x < 0) x += 1; if (y < 0) y += 1; if (z < 0) z += 1; #define LIMIT 0.999999 if (x > LIMIT) x -= 1; if (y > LIMIT) y -= 1; if (z > LIMIT) z -= 1; #undef LIMIT return vector3(x, y, z); }
vector2 sphere::texture_at(ray_point const& rp) const { // We'll use the equations suggested at // http://en.wikipedia.org/wiki/UV_mapping : // // atan(d.z / d.x) // u = 0.5 + --------------- // 2 pi // // asin(d.y) // v = 0.5 - --------- // pi vector3 const d = -normal_at(rp).get(); double const u = 0.5 + atan2(d.z(), d.x()) / (2 * PI); double const v = 0.5 - asin(d.y()) / PI; assert(0.0 <= u && u <= 1.0); assert(0.0 <= v && v <= 1.0); return {u, v}; }
/// // CheckLine() // // Compute intersection of P1 --> P2 line segment with face planes // Then test intersection point to see if it is on cube face // Consider only face planes in "outcode_diff" // Note: Zero bits in "outcode_diff" means face line is outside of */ // static int CheckLine(const vector3& p1, const vector3& p2, int outcode_diff) { if ((0x01 & outcode_diff) != 0) if (CheckPoint(p1,p2,( .5f-p1.x())/(p2.x()-p1.x()),0x3e) == INSIDE) return(INSIDE); if ((0x02 & outcode_diff) != 0) if (CheckPoint(p1,p2,(-.5f-p1.x())/(p2.x()-p1.x()),0x3d) == INSIDE) return(INSIDE); if ((0x04 & outcode_diff) != 0) if (CheckPoint(p1,p2,( .5f-p1.y())/(p2.y()-p1.y()),0x3b) == INSIDE) return(INSIDE); if ((0x08 & outcode_diff) != 0) if (CheckPoint(p1,p2,(-.5f-p1.y())/(p2.y()-p1.y()),0x37) == INSIDE) return(INSIDE); if ((0x10 & outcode_diff) != 0) if (CheckPoint(p1,p2,( .5f-p1.z())/(p2.z()-p1.z()),0x2f) == INSIDE) return(INSIDE); if ((0x20 & outcode_diff) != 0) if (CheckPoint(p1,p2,(-.5f-p1.z())/(p2.z()-p1.z()),0x1f) == INSIDE) return(INSIDE); return(OUTSIDE); }
// Equality operations bool vector3::operator == (const vector3 &v) const { return ((x() == v.x()) && (y() == v.y()) && (z() == v.z())); }
bool operator == (const vector3 &r) const { return (_x == r.x() && _y == r.y() && _z == r.z()); }
vector3 cross(const vector3 &v) const { return vector3(_y * v.z() - _z * v.y(), _z * v.x() - _x * v.z(), _x * v.y() - _y * v.x()); }
void OBDepictPrivate::DrawAtomLabel(const std::string &label, int alignment, const vector3 &pos) { painter->SetFontSize(fontSize); OBFontMetrics metrics = painter->GetFontMetrics(label); /* cout << "FontMetrics(" << label << "):" << endl; cout << " ascent = " << metrics.ascent << endl; cout << " descent = " << metrics.descent << endl; cout << " width = " << metrics.width << endl; cout << " height = " << metrics.height << endl; painter->SetFillColor(OBColor("white")); painter->SetPenColor(OBColor("white")); painter->DrawCircle(pos.x(), pos.y(), metrics.ascent / 2); painter->SetPenColor(OBColor("black")); */ std::string str, subscript; // compute the horizontal starting position double xOffset, yOffset, yOffsetSubscript; switch (alignment) { case TopLeft: case CenterLeft: case BottomLeft: xOffset = - 0.5 * painter->GetFontMetrics(label.substr(0,1)).width; break; case TopRight: case CenterRight: case BottomRight: xOffset = 0.7 * painter->GetFontMetrics(label.substr(label.size()-1,1)).width - painter->GetFontMetrics(label).width; break; default: xOffset = - 0.5 * painter->GetFontMetrics(label).width; break; } // compute the vertical starting position switch (alignment) { case BottomLeft: case BottomCenter: case BottomRight: yOffset = 0.2 * metrics.ascent + metrics.descent; yOffsetSubscript = metrics.ascent + metrics.descent; break; default: yOffset = 0.5 * metrics.ascent; yOffsetSubscript = metrics.ascent; break; } for (int i = 0; i < label.size(); ++i) { if (!isalpha(label[i])) { if (!str.empty()) { // write the current string painter->SetFontSize(fontSize); OBFontMetrics metrics = painter->GetFontMetrics(str); painter->DrawText(pos.x() + xOffset, pos.y() + yOffset, str); xOffset += metrics.width; str.clear(); } subscript += label.substr(i, 1); } else { if (!subscript.empty()) { // write the current subscript painter->SetFontSize(subscriptSize); OBFontMetrics metrics = painter->GetFontMetrics(subscript); painter->DrawText(pos.x() + xOffset, pos.y() + yOffsetSubscript, subscript); xOffset += metrics.width; subscript.clear(); } str += label.substr(i, 1); } } if (!str.empty()) { painter->SetFontSize(fontSize); OBFontMetrics metrics = painter->GetFontMetrics(str); painter->DrawText(pos.x() + xOffset, pos.y() + yOffset, str); } if (!subscript.empty()) { painter->SetFontSize(subscriptSize); OBFontMetrics metrics = painter->GetFontMetrics(subscript); double yOffset = ispunct(subscript[subscript.size()-1]) || ispunct(subscript[0]) || ispunct(subscript[1]) ? -yOffsetSubscript : yOffsetSubscript; painter->DrawText(pos.x() + xOffset, pos.y() + yOffset, subscript); } }
void pickRandom( vector3 & v ) { pickRandom( v.x() ); pickRandom( v.y() ); pickRandom( v.z() ); }
T dot(const vector3 &v) const { return (_x * v.x() + _y * v.y() + _z * v.z()); }
vector3<T> tangent_space_to_world_space(const vector3<T>& v, const vector3<T>& nrm) { const vector3<T>& t1 = perpendicular(nrm); const vector3<T>& t2 = cross(nrm, t1); return (v.x() * t1 + v.y() * t2 + v.z() * nrm).normalized(); }
vector3 rotate_vector( vector3 const& v, quat const& q ) { quat p = quat(v.x(), v.y(), v.z(), 0); quat tp = q * p * q.inverse(); return vector3(tp.qx(), tp.qy(), tp.qz()); }
// Returns the dot product of two vectors float vector3::Dot(const vector3 &v2) const { return ((x() * v2.x()) + (y() * v2.y()) + (z() * v2.z())); }
vector4::vector4(const vector3 &v) : vector4(v.x(), v.y(), v.z()) {}
matrix4x4 scale_matrix(vector3 const& v) { return matrix4x4(v.x(), 0, 0, 0, 0, v.y(), 0, 0, 0, 0, v.z(), 0, 0, 0, 0, 1); }