第一个版本代码,不用额外的库,手搓一些Utility函数,透彻了解原理:
#include<iostream>
#include<cmath>
using namespace std;
struct Point
{
double x, y, z;
// Overloading the multiplication operator
Point operator*(double k) const
{
return {k*x, k*y, k*z};
}
Point operator+(Point A) const
{
return {A.x + x, A.y + y, A.z + z};
}
bool operator==(Point A) const
{
if (A.x == x and A.y == y and A.z == z)
{
return true;
}
else
{
return false;
}
}
};
double dotProduct(Point A, Point B)
{
return A.x * B.x + A.y * B.y + A.z * B.z;
}
Point crossProduct(Point A, Point B)
{
return {A.y * B.z - A.z * B.y,
A.x * B.z - A.z * B.x,
A.x * B.y - A.y * B.x};
}
float calcNorm(Point A)
{
return sqrt(A.x * A.x + A.y * A.y + A.z * A.z);
}
Point calcProjection(Point A, Point B, Point P)
{
Point AB = {B.x - A.x, B.y - A.y, B.z - A.z};
Point AP = {P.x - A.x, P.y - A.y, P.z - A.z};
double dot_product = dotProduct(AB, AP);
double k = dot_product / dotProduct(AB, AB);
Point C = A + (AB * k);
return C;
}
bool verifyProjection(Point A, Point B, Point P, Point C)
{
Point AC = {C.x - A.x, C.y - A.y, C.z - A.z};
Point AB = {B.x - A.x, B.y - A.y, B.z - A.z};
Point PC = {C.x - P.x, C.y - P.y, C.z - P.z};
double dot_product = dotProduct(PC, AB);
Point cross_product = crossProduct(AC, AB);
Point zero_vec = {0, 0, 0};
if (dot_product == 0 and cross_product == zero_vec)
{
return true;
}
else
{
return false;
}
}
float calcDistance(Point A, Point B, Point P)
{
Point AB = {B.x - A.x, B.y - A.y, B.z - A.z};
Point AP = {P.x - A.x, P.y - A.y, P.z - A.z};
Point cross_product = crossProduct(AB, AP);
float area_parallelogram = calcNorm(cross_product);
return (area_parallelogram / calcNorm(AB));
}
int main()
{
// Line segment AB
Point A = {0, 0, 0};
Point B = {4, 0, 0};
// Point P
Point P = {5, 8, 0};
// Project P to AB and get point C
Point C = calcProjection(A, B, P);
cout << "Projection Point C: (" << C.x << ", " << C.y << ", " << C.z << ")" << endl;
if (verifyProjection(A, B, P, C))
{
cout << "Correct!" << endl;
}
else
{
cout << "Incorrect." << endl;
}
cout << "Distance from P to AB is: " << calcDistance(A, B, P) << endl;
return 0;
}
另外一个版本,通过使用Eigen库来避免自己写Utility函数,行数大大减少(君子生非异也,善假于物也。):
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
Vector3d calcProjection(Vector3d A, Vector3d B, Vector3d P)
{
Vector3d AB = B - A;
Vector3d AP = P - A;
float AC_norm = AB.dot(AP) / AB.norm();
Vector3d C = A + AC_norm / AB.norm() * AB;
return C;
}
bool verifyProjection(Vector3d A, Vector3d B, Vector3d P, Vector3d C)
{
Vector3d AB = B - A;
Vector3d PC = P - C;
Vector3d AC = C - A;
Vector3d zero_vec = {0, 0, 0};
Vector3d cross_product = AB.cross(AC);
float dot_product = PC.dot(AB);
if (dot_product == 0 and cross_product == zero_vec)
{
return true;
}
else
{
return false;
}
}
float calcDistance(const Vector3d A, const Vector3d B, const Vector3d P)
{
Vector3d AB = B - A;
Vector3d AP = P - A;
Vector3d cross_product = AB.cross(AP);
float area_parallelogram = cross_product.norm();
return area_parallelogram / AB.norm();
}
int main()
{
Eigen::Vector3d A = {0, 0, 0};
Eigen::Vector3d B = {2, 0, 0};
Eigen::Vector3d P = {1, 3, 0};
Vector3d C = calcProjection(A, B, P);
cout << "Projection point is: " << C.x() << ", " << C.y() << ", " << C.z() << endl;
if (verifyProjection(A, B, P, C))
{
cout << "Verification passes!" << endl;
}
else
{
cout << "Verification failed." << endl;
}
cout << "Distance from P to AB is: " << calcDistance(A, B, P) << endl;
}
有问题欢迎一起评论交流,我会回复或更新文章,谢谢!