空间点,线,面(c++)

空间点、线和面:

实现三维解析几何中的点、直线和平面类

(1) 能够实现直线的不同创建方式(例如,两个点确定一条直 线,两个相交的平面确定一条直线,空间曲线的点斜式)和平面的 不同创建方式(例如,三个不共线的点确定一个平面,一个点和一 个法向量确定一个平面); (2) 能够计算相应的距离:两点之间的距离,点到直线的距离, 点到平面的距离; (3) 能够计算空间直线的单位方向向量(长度为1),空间平面的 单位法向量(长度为1); (4) 能够判断点和线的关系,线和线的关系,点和平面的关系, 线和平面的关系,平面和平面的关系。  (5)注意:要考虑计算机中实数计算的精度误差(不同精度的数 值相等判断不能使用==)。

提示: 1.点、直线和平面分别用类来封装,每个类的数据为该表示该类 需要的参数,例如,对于空间平面的一般方程为ax+by+cz+d = 0,那么私有数据成员为a, b, c和d; 2.空间直线和平面的不同创建方式定义为对应类的成员函数; 3.空间点和点、点和直线、点和平面、直线和直线、直线和平 面、平面和平面位置关系的判断定义为一般的函数; 4. 要在main函数中对上述功能进行调用和验证

 分别定义Point类,Plane类,Line类MyVector类(向量类),以及tools(函数类)

point.h

#pragma once
#include<iostream>
using namespace std;
class Line;
class plane;
class Point {
private:
	double x;
	double y;
	double z;

public:
	//friend double pointToPlaneDis(Point pt, Plane p);
	//friend double pointToLineDis(Point p, Line l);
	friend class Plane;
	friend void lineAndPlane(Line l, Plane p);
	friend void lineAndLine(Line l1, Line l2);
	friend void pointAndPlane(Point pt, Plane p);
	friend void pointAndLine(Point p, Line l);
	friend double pointDistance(Point p1, Point p2);

	double getX() { return x; }
	double getY() { return y; }
	double getZ() { return z; }

	void setX(double t) { x = t;}
	void setY(double t) { y = t;}
	void setZ(double t) { z = t;}


	Point() = default;

	Point(double x, double y, double z)
		: x(x), y(y), z(z)
	{
	}

	bool operator==(const Point& other) const
	{
		return x == other.x && y == other.y && z == other.z;
	}
};

point.cpp

#include"point.h"

line.h

#pragma once
#include "Plane.h"
#include "myVector.h"
using namespace std;
class Point;
class Line
{
private:
	//(x-x₀)/a = (y-y₀)/b = (z-z₀)/c
	double a;
	double b;
	double c;
	double x0;
	double y0;
	double z0;

	//Point p1, p2;
public:
    friend void lineAndLine(Line l1,Line l2);
    friend void pointAndLine(Point p, Line l);
    friend double pointToLineDis(Point p, Line l);
    friend void lineAndPlane(Line l, Plane p);
    friend MyVector lineUnitDirVector(Line l);
	//两个点确定一条直线
	Line TwoPointToLine(Point p1, Point p2);

	//两个相交的平面确定一条直线
	Line TwoPlaneToLine(Plane p1, Plane p2);

    double getA() {
        return a;
    }

    void setA(double a) {
        this->a = a;
    }

    double getB() {
        return b;
    }

    void setB(double b) {
        this->b = b;
    }

    double getC() {
        return c;
    }

    void setC(double c) {
        this->c = c;
    }

    double getX0() {
        return x0;
    }


    void setX0(double x0) {
        this->x0 = x0;
    }

    double getY0() {
        return y0;
    }

    void setY0(double y0) {
        this->y0 = y0;
    }

    double getZ0() {
        return z0;
    }

    void setZ0(double z0) {
        this->z0 = z0;
    }

	Line() = default;

	Line(double a, double b, double c, double x0, double y0, double z0)
		: a(a), b(b), c(c), x0(x0), y0(y0), z0(z0){}

	
};

ostream& operator<<(ostream& out,Line& l);

line.cpp

#include "line.h"

Line Line::TwoPointToLine(Point p1, Point p2){
    return Line(p1.getX() - p2.getX(), p1.getY() - p2.getY(), p1.getZ() - p2.getZ(),p1.getX(),p1.getY(),p1.getZ());
}

Line Line::TwoPlaneToLine(Plane p1, Plane p2){
    MyVector v(p1.b*p2.c-p2.b*p1.c, p1.c * p2.a - p2.a * p1.c, p1.a * p2.b - p2.a * p1.b);
    double x = (p2.b * p1.d - p1.b * p2.d) / (p2.a * p1.b - p1.a * p2.b);
    double y = (p2.d * p1.a - p1.d * p2.a) / (p2.a * p1.b - p1.a * p2.b);
    double z = 0.0;
    return Line(v.getX(), v.getY(), v.getZ(), x, y, z);
}

ostream& operator<<(ostream& out, Line& l)
{
    //(x-x₀)/a = (y-y₀)/b = (z-z₀)/c
    Line t(l);
    l.setY0(l.getY0()<0?-1.0 * l.getY0():l.getY0());
    l.setX0(l.getX0() < 0 ? -1.0 * l.getX0() : l.getX0());
    out << (t.getY0() > 0 ? "(x-" : "(x+") << l.getX0() << ")/" << l.getA() 
        << " = " << (t.getY0()>0?"(y-":"(y+") << l.getY0() << ")/" << l.getB() 
        << " = " << "(z-" << l.getZ0() << ")/" << l.getC() << endl;
    return out;
}

plane.h

#pragma once
#include "point.h"
#include <cmath>
class MyVector;
class Plane{
private:
	double a;
	double b;
	double c;
	double d;
public:

    friend class Line;
    friend double pointToPlaneDis(Point pt, Plane p);
    friend void pointAndPlane(Point pt, Plane p);
    friend void lineAndPlane(Line l, Plane p); 
    friend MyVector planeUnitfVector(Plane p);
    friend void planeAndPlane(Plane p1, Plane p2);
    friend ostream& operator<<(ostream& out, Plane p);

	//三个不共线的点确定一个平面
    Plane threePointToPlane(Point p1,Point p2,Point p3);
    //一个点和一个法向量确定一个平面
    Plane pointAndVectorToPlane(Point p, MyVector v);

    double getA() {
        return a;
    }

    void setA(double a) {
        this->a = a;
    }

    double getB() {
        return b;
    }

    void setB(double b) {
        this->b = b;
    }

    double getC() {
        return c;
    }

    void setC(double c) {
        this->c = c;
    }

    double getD() {
        return d;
    }

    void setD(double d) {
        this->d = d;
    }

	Plane() = default;

	Plane(double a, double b, double c, double d)
		: a(a), b(b), c(c), d(d)
	{
	}

};

ostream& operator<<(ostream& out, Plane p);

plane.cpp

#include "plane.h"
#include "myVector.h"
//已知3点坐标,求平面ax+by+cz+d=0;
Plane Plane::threePointToPlane(Point p1, Point p2, Point p3){
    double a, b, c, d;
    a = (p2.y - p1.y) * (p3.z - p1.z) - (p2.z - p1.z) * (p3.y - p1.y);
    b = (p2.z - p1.z) * (p3.x - p1.x) - (p2.x - p1.x) * (p3.z - p1.z);
    c = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
    d = 0 - (a * p1.x + b * p1.y + c * p1.z);
    return Plane(a, b, c, d);
}

Plane Plane::pointAndVectorToPlane(Point p, MyVector v)
{
    double d = -(p.x * v.x + p.y * v.y + p.z * v.z);
    return Plane(v.x, v.y, v.z, d);
}

ostream& operator<<(ostream& out, Plane p) {
    out << p.a << "x+" << p.b << "y+" << p.c << "z+" << p.d << " = 0" << endl;
    return out;
}





// 已知三点坐标,求法向量
/*Vec3 get_Normal(Point p1, Point p2, Point p3) {

    a = (p2.y - p1.y) * (p3.z - p1.z) - (p2.z - p1.z) * (p3.y - p1.y);

    b = (p2.z - p1.z) * (p3.x - p1.x) - (p2.x - p1.x) * (p3.z - p1.z);

    c = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);

    return Vec3(a, b, c);

}*/



myVector.h

#pragma once
class MyVector{
public:
	double x;
	double y;
	double z;
public:
	double getX() { return x; }
	double getY() { return y; }
	double getZ() { return z; }

	void setX(double t) { x = t; }
	void setY(double t) { y = t; }
	void setZ(double t) { z = t; }

	MyVector() = default;

	MyVector(double x, double y, double z)
		: x(x), y(y), z(z)
	{
	}

};

myVector.cpp

#include "myVector.h"

tool.h

#pragma once
#include "line.h"
#include "myVector.h"
#include "plane.h"
#include "point.h"
using namespace std;

//两点之间的距离
double pointDistance(Point p1, Point p2) {
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)
		+ (p1.z - p2.z) * (p1.z - p2.z));
}

//点到平面距离
double pointToPlaneDis(Point pt, Plane p) {
	return abs(p.a * pt.getX() + p.b * pt.getY() + p.c * pt.getZ() + p.d) / sqrt(p.a * p.a + p.b * p.b + p.c * p.c);
}

//点到直线的距离
double pointToLineDis(Point p, Line l) {
	MyVector mv(l.x0 - p.getX(), l.y0 - p.getY(), l.z0 - p.getZ());
	MyVector f(mv.y * l.c - l.b * mv.z, l.a * mv.z - mv.x * l.c, mv.x * l.b - l.a * mv.y);
	return sqrt(mv.x * mv.x + mv.y * mv.y + mv.z * mv.z) / sqrt(f.x * f.x + f.y * f.y + f.z * f.z);
}

//计算空间直线的单位方向向量
MyVector lineUnitDirVector(Line l) {
	//(1,1,1)
	double su = sqrt(l.a * l.a + l.b * l.b + l.c * l.c);
	return MyVector(l.a / su, l.b / su, l.c / su);
}

//计算平面的单位法向量
MyVector planeUnitfVector(Plane p) {
	double su = sqrt(p.a * p.a + p.b * p.b + p.c * p.c);
	return MyVector(p.a / su, p.b / su, p.c / su);
}

//点和点的关系
void pointAndPoint(Point p1, Point p2) {
	if (p1 == p2) {
		cout << "同一点" << endl;
	}
	else cout << "不为同一点" << endl;
}

//点和直线的关系
void pointAndLine(Point p, Line l) {
	if ((p.x - l.x0) / l.a - (p.y - l.y0) / l.b < 0.001 && (p.z - l.z0) / l.c - (p.y - l.y0) / l.b < 0.001) {
		cout << "点在直线上" << endl;
	}
	else cout << "点在直线外" << endl;

}

//点和平面的关系
void pointAndPlane(Point pt, Plane p) {
	//ax+by+cz+d = 0
	if (p.a * pt.x + p.b * pt.y + p.c * pt.z + p.d - 0 < 0.001) {
		cout << "点在平面上" << endl;
	}
	else cout << "点在平面外" << endl;
}

//计算向量×积
MyVector crossProduct(const MyVector& v1, const MyVector& v2) {
	MyVector result;
	result.x = v1.y * v2.z - v1.z * v2.y;
	result.y = v1.z * v2.x - v1.x * v2.z;
	result.z = v1.x * v2.y - v1.y * v2.x;
	return result;
}

//直线和直线的关系
void lineAndLine(Line l1, Line l2) {
	Point p1(l1.x0, l1.y0, l1.z0);
	Point p2(l2.x0, l2.y0, l2.z0);
	MyVector v1(l1.a, l1.b, l1.c), v2(l2.a, l2.b, l2.c);
	MyVector diff = { p2.x - p1.x, p2.y - p1.y, p2.z - p1.z };
	MyVector cross = crossProduct(v1,v2);

	if (cross.x == 0 && cross.y == 0 && cross.z == 0) {
		// 方向向量平行,再判断是否共线
		if ((diff.x * v2.y - diff.y * v2.x) == 0 && (diff.x * v2.z - diff.z * v2.x) == 0 && (diff.y * v2.z - diff.z * v2.y) == 0) {
			cout << "两直线平行或重合" << endl;
		}
		else {
			cout << "两直线平行" << endl;
		}
	}
	else {
		// 计算联立方程判断是否相交
		double t1 = 0.0, t2;
		if (v1.x != 0) {
			t2 = (p1.x + t1 * v1.x - p2.x) / v2.x;
		}
		else if (v1.y != 0) {
			t2 = (p1.y + t1 * v1.y - p2.y) / v2.y;
		}
		else if (v1.z != 0) {
			t2 = (p1.z + t1 * v1.z - p2.z) / v2.z;
		}
		// 代入直线方程求解 t1
		if ((p1.x + t1 * v1.x == p2.x + t2 * v2.x) && (p1.y + t1 * v1.y == p2.y + t2 * v2.y) && (p1.z + t1 * v1.z == p2.z + t2 * v2.z)) {
			cout << "两直线相交" << endl;
		}
		else {
			cout << "两直线异面" << endl;
		}
	}
}

// 计算两个向量的点积
double dotProduct(const MyVector& v1, const MyVector& v2) {
	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

//得到平面上一点
Point getPointOnPlane(Plane& p) {
	//ax+by+cz+d=0;
	//另x = 0, y = 0;
	double x = 0.0, y = 0.0;
	double z = -1.0 * p.getD() / p.getC();
	return Point(0, 0, z);
}

//直线和平面的关系
void lineAndPlane(Line l, Plane p) {
	//ax+by+cz+d=0;
	MyVector f(p.a, p.b, p.c);
	MyVector dir(l.a, l.b, l.c);
	double dot = dotProduct(f, dir);
	Point pointOnLine(l.x0, l.y0, l.z0);
	Point pointOnPlane = getPointOnPlane(p);
	double D = -(p.a * pointOnPlane.x + p.b * pointOnPlane.y + p.c * pointOnPlane.z);
	double result = p.a * pointOnLine.x + p.b * pointOnLine.y + p.c * pointOnLine.z + D;
	/*cerr << p.a << " " << p.b << " " << p.c << endl;
	cerr << l.a << " " << l.b << " " << l.c << endl;
	cerr << dot << "***" << result << endl;*/
	if (dot == 0 && result == 0) {
		cout << "直线在平面内" << endl;
	}
	else if (dot == 0 && result != 0) {
		cout << "直线与平面平行" << endl;
	}
	else {
		cout << "直线与平面相交" << endl;
	}
}


//平面和平面的关系
void planeAndPlane(Plane p1, Plane p2) {
	if (p1.a == p2.a && p1.b == p2.b && p1.c == p2.c && p1.b == p2.b && p1.d == p2.d) {
		cout << "重合" << endl;
	}
	else if (p1.a / p2.a - p1.b / p2.b < 0.001 && p1.b / p2.b - p1.c / p2.c < 0.001) {
		cout << "平行" << endl;
	}
	else {
		cout << "相交" << endl;
	}
}

测试代码main类

#include "tool.h"

int main() {
	Point p1(1, -1, -1);
	Point p2(0, 0, 5);
	

	Line l1 = (new Line())->TwoPointToLine(p1,p2);		//两点确定一条直线
	cout <<"l1的方程为:" << l1;	//

	Plane pl1(1, 1, 1, -1), pl2(1,-1,1,1);
	Line l2 = (new Line())->TwoPlaneToLine(pl1, pl2);	//两个相交的平面确定一条直线
	cout << "l2的方程为:" << l2;

	Line l3(2, -2, -12, 0, 0, 0);		//空间曲线的点斜式
	cout << "l3的方程为:" << l3;
	cout << endl;

	Point p3(1, 1, 1);
	Plane pl3 = (new Plane())->threePointToPlane(p1, p2, p3);	//三个不共线的点确定一个平面
	cout << "pl3的方程为:" << pl3;

	MyVector v(1, 1, 1);
	Plane pl4 = (new Plane())->pointAndVectorToPlane(p1, v);	//一个点和一个法向量确定一个平面
	cout << "pl4的方程为:" << pl4;
	cout << endl;
 
	//两点之间的距离,点到直线的距离,点到平面的距离
	cout <<"点p1到面pl1的距离:"<< pointToPlaneDis(p2, pl1) << endl;
	cout << "点p1到直线l2的距离为:" << pointToLineDis(p1, l2) << endl;
	cout << "点p1和点p2的距离:" << pointDistance(p2, p1) << endl;
	cout << endl;

	//空间直线的单位方向向量
	cout << "线l1的单位方向向量为:";
	MyVector v1 = lineUnitDirVector(l1);
	cout << "(" << v1.x << "," << v1.y << "," << v1.z << ")" << endl;
	//空间平面的单位法向量
	cout << "面pl1的单位法向量为:";
	MyVector v2 = planeUnitfVector(pl1);
	cout << "(" << v2.x << "," << v2.y << "," << v2.z << ")" << endl;
	cout << endl;

	//空间点和点、点和直线、点和平面、直线和直线、直线和平面、平面和平面位置关系的判断
	Point p4(1, -1, -1);
	cout << "点p1和点p2的关系是:";
	pointAndPoint(p1, p2);
	cout << "点p1和点p4的关系是:";
	pointAndPoint(p1, p4);

	cout << "点p1和线l1的关系是:";
	pointAndLine(p1, l1);
	cout << "点p1和线l2的关系是:";
	pointAndLine(p1, l2);

	cout << "点p3和面pl3的关系:";
	pointAndPlane(p3, pl3);
	cout << "点p2和面pl1的关系:";
	pointAndPlane(p2, pl1);

	cout << "线l1和线l2的关系:";
	lineAndLine(l1, l2);
	cout << "线l1和线l3的关系:";
	lineAndLine(l1, l3);
	cout << "线l2和线l2的关系:";
	lineAndLine(l2, l3);

	//cerr << "*************************" << endl;
	//pl4:1x+1y+1z+1 = 0 
	Line l4(2,-1,-1,0,0,0);
	cout << "线l2和平面pl2之间的关系:";
	lineAndPlane(l2, pl2);  //pl1:x + y + z + 1 = 0(1,1,1)(2,0,1)   l2: (x+3)/2 = z
	cout << "线l1和平面pl2之间的关系:";
	lineAndPlane(l1, pl2);
	cout << "线l4和平面pl4之间的关系:";
	lineAndPlane(l4, pl4);
	//cerr << "*************************" << endl;

	Plane pl5(2, 2, 2, 5);
	Plane pl6(2, 2, 2, 5);
	cout << "面pl1和面pl2的关系:";
	planeAndPlane(pl1, pl2);
	cout << "面pl1和面pl5的关系:";
	planeAndPlane(pl1, pl5);
	cout << "面pl5和面pl6的关系:";
	planeAndPlane(pl6, pl5);

	return 0;
}

仅供参考,代码在测试中有些小问题,祝大家学习进步

总结

本文的难点

1.友元函数:在类的内部使用 “friend” 关键字声明一个非成员函数为友元函数,这个函数可以访问该类的私有成员和保护成员。

2.友元类:一个类可以将另一个类声明为友元类,友元类的成员函数可以访问该类的私有成员和保护成员。

3.封装:在面向对象编程中,封装是指将数据和操作数据的方法绑定在一起,形成一个类,并通过访问控制机制来限制对类内部数据的直接访问,只允许通过特定的方法来访问和修改这些数据。

4.引用:引用是一个对象的别名,它为一个已存在的对象起了另外一个名字。引用并非一个独立的对象,它必须在创建时被初始化,并且一旦初始化后就不能再指向其他对象。

STP(Spanning Tree Protocol,生成树协议)是一种用于在以太网网络中防止环路并确保冗余链路可靠性的协议。它的基本原理是通过选择一个根交换机,并在网络中的各个交换机之间建立一棵生成树,从而实现环路的消除。 STP基于以下几个核心概念: 1. 根交换机(Root Switch):在STP网络中,选举一个交换机作为根交换机,该交换机将成为生成树的根节点。根交换机具有最低的桥优先级(Bridge Priority),桥优先级是一个用于选举根交换机的参数。 2. 桥优先级(Bridge Priority):每个交换机都有一个桥优先级,用于确定其在选举根交换机过程中的优先级。较低的桥优先级将使得交换机更有可能成为根交换机。 3. 端口优先级(Port Priority):每个交换机上的端口都有一个端口优先级,用于确定在生成树中的路径选择。较低的端口优先级将使得该端口更有可能成为根交换机到其他交换机之间的路径。 4. 生成树(Spanning Tree):生成树是一棵由交换机和链路组成的树状结构,用于连接网络中的所有交换机,并确保没有环路。生成树中的某些链路被标记为指定端口(Designated Port),用于传输数据;其他链路被标记为阻塞端口(Blocked Port),用于防止环路的发生。 STP的工作原理是通过交换机之间的BPDU(Bridge Protocol Data Unit)交换来实现的。交换机会通过BPDU消息进行根交换机选举、生成树构建和端口状态转换等过程。BPDU消息包含了交换机的标识信息、路径开销和优先级等参数。 总结起来,STP通过选举根交换机、构建生成树和阻塞冗余链路的方式,确保以太网网络中没有环路,并提供冗余链路的可靠性。这样可以提高网络的可用性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值