157 lines
7.1 KiB
C++
157 lines
7.1 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2009 Daniel Chappuis *
|
|
****************************************************************************
|
|
* This file is part of ReactPhysics3D. *
|
|
* *
|
|
* ReactPhysics3D is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as published *
|
|
* by the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* ReactPhysics3D 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 Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with ReactPhysics3D. If not, see <http://www.gnu.org/licenses/>. *
|
|
***************************************************************************/
|
|
|
|
// TODO : Mathematics library : Check everywhere that in member methods we use attributes access instead of getter and setter.
|
|
|
|
#ifndef MATHEMATICS_H
|
|
#define MATHEMATICS_H
|
|
|
|
// Libraries
|
|
#include "Matrix.h"
|
|
#include "Matrix3x3.h"
|
|
#include "Polygon3D.h"
|
|
#include "Quaternion.h"
|
|
#include "Segment3D.h"
|
|
#include "Vector.h"
|
|
#include "Vector3D.h"
|
|
#include "constants.h"
|
|
#include "exceptions.h"
|
|
#include "mathematics_functions.h"
|
|
#include <cstdio>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
|
|
// ---------- Mathematics functions ---------- //
|
|
|
|
// TODO : Test this method
|
|
// Rotate a vector according to a rotation quaternion.
|
|
// The function returns the vector rotated according to the quaternion in argument
|
|
inline reactphysics3d::Vector3D rotateVectorWithQuaternion(const reactphysics3d::Vector3D& vector, const reactphysics3d::Quaternion& quaternion) {
|
|
// Convert the vector into a quaternion
|
|
reactphysics3d::Quaternion vectorQuaternion(0, vector);
|
|
|
|
// Compute the quaternion rotation result
|
|
reactphysics3d::Quaternion quaternionResult = (quaternion * vectorQuaternion) * quaternion.getInverse();
|
|
|
|
// Convert the result quaternion into a vector
|
|
return quaternionResult.vectorV();
|
|
}
|
|
|
|
// TODO : Test this method
|
|
// Given two lines (given by the points "point1", "point2" and the vectors "d1" and "d2" that are not parallel, this method returns the values
|
|
// "alpha" and "beta" such that the two points P1 and P2 are the two closest point between the two lines and such that
|
|
// P1 = point1 + alpha * d1
|
|
// P2 = point2 + beta * d2
|
|
inline void closestPointsBetweenTwoLines(const reactphysics3d::Vector3D& point1, const reactphysics3d::Vector3D& d1, const reactphysics3d::Vector3D& point2,
|
|
const reactphysics3d::Vector3D& d2, double* alpha, double* beta) {
|
|
|
|
reactphysics3d::Vector3D r = point1 - point2;
|
|
double a = d1.scalarProduct(d1);
|
|
double b = d1.scalarProduct(d2);
|
|
double c = d1.scalarProduct(r);
|
|
double e = d2.scalarProduct(d2);
|
|
double f = d2.scalarProduct(r);
|
|
double d = a*e-b*b;
|
|
|
|
// The two lines must not be parallel
|
|
assert(!reactphysics3d::approxEqual(d, 0.0));
|
|
|
|
// Compute the "alpha" and "beta" values
|
|
*alpha = (b*f -c*e)/d;
|
|
*beta = (a*f-b*c)/d;
|
|
}
|
|
|
|
/*
|
|
// TODO : Test this method
|
|
// Move a set of points by a given vector.
|
|
// The method returns a set of points moved by the given vector.
|
|
inline std::vector<reactphysics3d::Vector3D> movePoints(const std::vector<reactphysics3d::Vector3D>& points, const reactphysics3d::Vector3D& vector) {
|
|
std::vector<reactphysics3d::Vector3D> result;
|
|
|
|
// For each point of the set
|
|
for (unsigned int i=0; i<points.size(); ++i) {
|
|
// Move the point
|
|
result.push_back(points.at(i) + vector);
|
|
}
|
|
|
|
// Return the result set of points
|
|
return result;
|
|
}
|
|
*/
|
|
|
|
// TODO : Test this method
|
|
// Compute the intersection between two parallel segments (the first segment is between the points "seg1PointA" and "seg1PointB" and the second
|
|
// segment is between the points "seg2PointA" and "seg2PointB"). The result is the segment intersection (represented by the points "resultPointA"
|
|
// and "resultPointB". Because the two given segments don't have to be on the same exact line, the result intersection segment will a segment
|
|
// halway between the first and the second given segments.
|
|
inline void computeParallelSegmentsIntersection(const reactphysics3d::Vector3D& seg1PointA, const reactphysics3d::Vector3D& seg1PointB
|
|
const reactphysics3d::Vector3D& seg2PointA, const reactphysics3d::Vector3D& seg2PointB,
|
|
reactphysics3d::Vector3D& resultPointA, reactphysics3d::Vector3D& resultPointB) {
|
|
// Compute the segment vectors
|
|
reactphysics3d::Vector3D d1 = seg1PointB - seg1PointA;
|
|
reactphysics3d::Vector3D d2 = seg2PointB - seg2PointA;
|
|
|
|
// The two segments should be parallel
|
|
assert(d1.isParallelWith(d2));
|
|
|
|
// Compute the projection of the two points of the second segment onto the vector of segment 1
|
|
double projSeg2PointA = d1.getUnit().scalarProduct(seg2PointA() - seg1PointA());
|
|
double projSeg2PointB = d1.getUnit().scalarProduct(seg2PointB() - seg1PointA());
|
|
|
|
// The projections intervals should intersect
|
|
assert(!(projSeg2PointA < 0.0 && projSegment2PointB < 0.0));
|
|
assert(!(projSeg2PointA > d1.length() && projSeg2PointB > d1.length()));
|
|
|
|
// Compute the distance between the two segments
|
|
double distance = computeDistanceBetweenPointAndLine(seg2PointA, seg1PointA, d1);
|
|
|
|
// Return the segment intersection according to the configuration of two projection intervals
|
|
if (projSeg2PointA >= 0 && projSeg2PointA <= d1.length() && projSeg2PointB >= d1.length()) {
|
|
resultPointA = seg2PointA;
|
|
resultPointB = seg1PointB;
|
|
|
|
// Move the contact points halfway between the two segments
|
|
|
|
}
|
|
else if (projSeg2PointA <= 0 && projSeg2PointB >= 0 && projSeg2PointB <= d1.length()) {
|
|
resultPointA = seg1PointA;
|
|
resultPointB = seg2PointB;
|
|
}
|
|
else if (projSeg2PointA <= 0 && projSeg2PointB >= d1.length()) {
|
|
resultPointA = seg1PointA;
|
|
resultPointB = seg1PointB;
|
|
}
|
|
else if (projSegment2PointA <= segment1.getLength() && projSegment2PointB <= segment1.getLength()) {
|
|
resultPointA = seg2PointA;
|
|
resultPointB = seg2PointB;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
// Compute the distance between a point "pointP" and a line (given by a point "pointA" and a vector "v")
|
|
inline double computeDistanceBetweenPointAndLine(const reactphysics3d::Vector3D& pointP, const reactphysics3d::Vector3D& pointA, const reactphysics3d::Vector3D& v) {
|
|
assert(v.length() != 0);
|
|
return ((pointP-pointA).crossProduct(v).length() / (v.length()));
|
|
}
|
|
|
|
#endif
|