实现三维解析几何中的点、直线和平面类1 能够实现直线的不同创建方式例如两个点确定一条直线两个相交的平面确定一条直线空间曲线的点斜式和平面的不同创建方式例如三个不共线的点确定一个平面一个点和一个法向量确定一个平面;2 能够计算相应的距离:两点之间的距离点到直线的距离点到平面的距离;3 能够计算空间直线的单位方向向量长度为1空间平面的单位法向量长度为1;4 能够判断点和线的关系线和线的关系点和平面的关
#include <iostream>
#include <cmath>
const double EPSILON = 1e-6; // 精度误差
class Point {
private:
    double x, y, z;
public:
    Point(double xVal = 0, double yVal = 0, double zVal = 0): x(xVal), y(yVal), z(zVal) {}
    double getX() const { return x; }
    double getY() const { return y; }
    double getZ() const { return z; }
    // 两点之间的距离
    double distanceTo(const Point& other) const {
        double dx = x - other.x;
        double dy = y - other.y;
        double dz = z - other.z;
        return std::sqrt(dx * dx + dy * dy + dz * dz);
    }
};
class Line {
private:
    double a, b, c; // 直线的方向向量
    double x0, y0, z0; // 直线上的一点
public:
    Line(double aVal = 0, double bVal = 0, double cVal = 0, double xVal = 0, double yVal = 0, double zVal = 0)
        : a(aVal), b(bVal), c(cVal), x0(xVal), y0(yVal), z0(zVal) {}
    // 通过两点确定一条直线
    static Line createByTwoPoints(const Point& p1, const Point& p2) {
        double dx = p2.getX() - p1.getX();
        double dy = p2.getY() - p1.getY();
        double dz = p2.getZ() - p1.getZ();
        return Line(dx, dy, dz, p1.getX(), p1.getY(), p1.getZ());
    }
    // 点斜式确定一条直线
    static Line createByPointSlope(const Point& p, double slopeX, double slopeY, double slopeZ) {
        return Line(slopeX, slopeY, slopeZ, p.getX(), p.getY(), p.getZ());
    }
    // 线线相交得到一条直线
    static Line createByIntersection(const Line& l1, const Line& l2) {
        double dx = l1.b * l2.c - l1.c * l2.b;
        double dy = l1.c * l2.a - l1.a * l2.c;
        double dz = l1.a * l2.b - l1.b * l2.a;
        double x0 = (l1.b * l2.z0 - l1.z0 * l2.b) / dx;
        double y0 = (l1.z0 * l2.a - l1.a * l2.z0) / dy;
        double z0 = (l1.a * l2.b - l1.b * l2.a) / dz;
        return Line(dx, dy, dz, x0, y0, z0);
    }
    double getA() const { return a; }
    double getB() const { return b; }
    double getC() const { return c; }
    double getX0() const { return x0; }
    double getY0() const { return y0; }
    double getZ0() const { return z0; }
    // 点到直线的距离
    double distanceTo(const Point& p) const {
        double numerator = a * (p.getX() - x0) + b * (p.getY() - y0) + c * (p.getZ() - z0);
        double denominator = std::sqrt(a * a + b * b + c * c);
        return std::abs(numerator / denominator);
    }
    // 直线的单位方向向量
    void getUnitDirection(double& dx, double& dy, double& dz) const {
        double length = std::sqrt(a * a + b * b + c * c);
        dx = a / length;
        dy = b / length;
        dz = c / length;
    }
};
class Plane {
private:
    double a, b, c, d; // 平面的一般方程
public:
    Plane(double aVal = 0, double bVal = 0, double cVal = 0, double dVal = 0)
        : a(aVal), b(bVal), c(cVal), d(dVal) {}
    // 通过三个不共线的点确定一个平面
    static Plane createByThreePoints(const Point& p1, const Point& p2, const Point& p3) {
        double a = (p2.getY() - p1.getY()) * (p3.getZ() - p1.getZ()) - (p2.getZ() - p1.getZ()) * (p3.getY() - p1.getY());
        double b = (p2.getZ() - p1.getZ()) * (p3.getX() - p1.getX()) - (p2.getX() - p1.getX()) * (p3.getZ() - p1.getZ());
        double c = (p2.getX() - p1.getX()) * (p3.getY() - p1.getY()) - (p2.getY() - p1.getY()) * (p3.getX() - p1.getX());
        double d = -(a * p1.getX() + b * p1.getY() + c * p1.getZ());
        return Plane(a, b, c, d);
    }
    // 通过一个点和法向量确定一个平面
    static Plane createByPointNormal(const Point& p, double normalX, double normalY, double normalZ) {
        double d = -(normalX * p.getX() + normalY * p.getY() + normalZ * p.getZ());
        return Plane(normalX, normalY, normalZ, d);
    }
    double getA() const { return a; }
    double getB() const { return b; }
    double getC() const { return c; }
    double getD() const { return d; }
    // 点到平面的距离
    double distanceTo(const Point& p) const {
        double numerator = a * p.getX() + b * p.getY() + c * p.getZ() + d;
        double denominator = std::sqrt(a * a + b * b + c * c);
        return std::abs(numerator / denominator);
    }
    // 平面的单位法向量
    void getUnitNormal(double& normalX, double& normalY, double& normalZ) const {
        double length = std::sqrt(a * a + b * b + c * c);
        normalX = a / length;
        normalY = b / length;
        normalZ = c / length;
    }
};
// 判断两个浮点数是否相等
bool isEqual(double x, double y) {
    return std::abs(x - y) < EPSILON;
}
// 判断点和线的关系
int pointLineRelation(const Point& p, const Line& l) {
    double dx, dy, dz;
    l.getUnitDirection(dx, dy, dz);
    double x0 = l.getX0();
    double y0 = l.getY0();
    double z0 = l.getZ0();
    double numerator = (p.getX() - x0) / dx - (p.getY() - y0) / dy + (p.getZ() - z0) / dz;
    if (isEqual(numerator, 0)) {
        return 0; // 点在直线上
    } else {
        return numerator > 0 ? 1 : -1; // 点在直线的一侧(正侧或负侧)
    }
}
// 判断线和线的关系
int lineLineRelation(const Line& l1, const Line& l2) {
    double dx1, dy1, dz1;
    l1.getUnitDirection(dx1, dy1, dz1);
    double dx2, dy2, dz2;
    l2.getUnitDirection(dx2, dy2, dz2);
    double numerator = dx1 * dx2 + dy1 * dy2 + dz1 * dz2;
    if (isEqual(numerator, 1)) {
        return 0; // 两直线平行
    } else {
        return 1; // 两直线相交
    }
}
// 判断点和平面的关系
int pointPlaneRelation(const Point& p, const Plane& plane) {
    double normalX, normalY, normalZ;
    plane.getUnitNormal(normalX, normalY, normalZ);
    double d = -plane.getD();
    double distance = normalX * p.getX() + normalY * p.getY() + normalZ * p.getZ() + d;
    if (isEqual(distance, 0)) {
        return 0; // 点在平面上
    } else {
        return distance > 0 ? 1 : -1; // 点在平面的一侧(正侧或负侧)
    }
}
// 判断线和平面的关系
int linePlaneRelation(const Line& line, const Plane& plane) {
    double normalX, normalY, normalZ;
    plane.getUnitNormal(normalX, normalY, normalZ);
    double d = -plane.getD();
    double dx, dy, dz;
    line.getUnitDirection(dx, dy, dz);
    double numerator = normalX * dx + normalY * dy + normalZ * dz;
    if (isEqual(numerator, 0)) {
        return 0; // 直线与平面平行
    } else {
        return 1; // 直线与平面相交
    }
}
// 判断平面和平面的关系
int planePlaneRelation(const Plane& plane1, const Plane& plane2) {
    double normalX1, normalY1, normalZ1;
    plane1.getUnitNormal(normalX1, normalY1, normalZ1);
    double normalX2, normalY2, normalZ2;
    plane2.getUnitNormal(normalX2, normalY2, normalZ2);
    double numerator = normalX1 * normalX2 + normalY1 * normalY2 + normalZ1 * normalZ2;
    if (isEqual(numerator, 1)) {
        return 0; // 两平面重合
    } else {
        return 1; // 两平面相交
    }
}
int main() {
    // 创建点对象
    Point p1(1, 2, 3);
    Point p2(4, 5, 6);
    Point p3(7, 8, 9);
    // 创建直线对象
    Line l1 = Line::createByTwoPoints(p1, p2);
    Line l2 = Line::createByPointSlope(p1, 2, 3, 4);
    // 创建平面对象
    Plane plane1 = Plane::createByThreePoints(p1, p2, p3);
    Plane plane2 = Plane::createByPointNormal(p1, 1, 2, 3);
    // 计算距离
    double distance1 = p1.distanceTo(p2);
    double distance2 = p1.distanceTo(l1);
    double distance3 = p1.distanceTo(plane1);
    // 计算单位方向向量
    double dx, dy, dz;
    l1.getUnitDirection(dx, dy, dz);
    // 判断关系
    int relation1 = pointLineRelation(p1, l1);
    int relation2 = lineLineRelation(l1, l2);
    int relation3 = pointPlaneRelation(p1, plane1);
    int relation4 = linePlaneRelation(l1, plane1);
    int relation5 = planePlaneRelation(plane1, plane2);
    return 0;
}
这是一个简单的三维解析几何的实现,包括了点、直线和平面类的封装,以及各种功能的实现和调用。注意在判断浮点数相等时,使用了一个精度误差常量EPSILON来进行判断,避免了计算机中实数计算的精度误差
原文地址: https://www.cveoy.top/t/topic/iJPT 著作权归作者所有。请勿转载和采集!