计算几何中线line的表示
这类比于y=bt+a
b表示斜率,这里将b用向量ab来代替,因为向量ab也表示方向,而斜率b也是一种方向的表示,所以可以得到图中表示的方法。
分情况讨论:
0<t<1: t在线段ab之间
t>1:t在向量ab的正向延长线
t<0:t在向量ab的反向延长线
那么
0<t<1: 可以说明这是个线段
t>0:可以说明这是个射线
t在±∞:可以说明这是个线
推出
找出相交点:
当t=s时候是相交点求出t=s=1
所以相交点为(6,9,6)
法线
template <typename coord_type, size_t dim= DIM3>
class Line
{
Vector<coord_type, dim> dir;
Vector<coord_type, dim> point;
public:
Line() {}
Line(Vector<coord_type, dim> &p1,
Vector<coord_type, dim> &p2)
: dir(p2 - p1), point(p1)
{
}
public:
Vector<coord_type,dim> getPoint();
Vector<coord_type,dim> getDir();
};
template <typename coord_type, size_t dim>
inline Vector<coord_type,dim> Line<coord_type,dim>::getPoint()
{
return point;
}
template <typename coord_type, size_t dim>
inline Vector<coord_type,dim> Line<coord_type,dim>::getDir()
{
return dir;
}
求线的交点
在程序上要关注两个问题:
1.两条线是否相交
2.两条线的交点是哪个
一个线段有两端点,分别判断这两个端点相对于另一条直线所处的位置。
利用上面判断点相对于线位置的程序即可。
bool intersection(const Point2d &a, const Point2d &b,
const Point2d &c, const Point2d &d)
{
auto ab_c = orientation2d(a, b, c);
auto ab_d = orientation2d(a, b, d);
auto cd_a = orientation2d(c, d, a);
auto cd_b = orientation2d(c, d, b);
if (ab_c == BETWEEN || ab_c == ORIGIN || ab_c == DESTINATION ||
ab_d == BETWEEN || ab_d == ORIGIN || ab_d == DESTINATION ||
cd_a == BETWEEN || cd_a == ORIGIN || cd_a == DESTINATION ||
cd_b == BETWEEN || cd_b == ORIGIN || cd_b == DESTINATION)
return true;
return _xor(ab_c == LEFT, ab_d == LEFT) &&
_xor(cd_a == LEFT, cd_b == LEFT);
}
求两线段的交点
假设ab与cd的交点为p
那么之间p(t)=cp·t+c
那么cp直线的方向向量为p(t)-c=cp·t
再假设n为cd的法线n
这里将P(t)用(b-a)t+a去代,为啥?因为求交点当t=x,交点的横坐标的时候(b-a)x+a在P(t)
推出
t=n·(c-a)/n·(b-a)
bool Intersection(const Point2d &a, const Point2d &b,
const Point2d &c, const Point2d &d,
Point2d &intersection)
{
Vector2f AB = b - a;
Vector2f CD = d - c;
Vector2f n(CD[Y], -CD[X]); // 自定义法线
auto deno = dotProduct(n, AB);
if (!isEqualDouble(deno, ZERO))
{
auto AC = c - a;
auto numer = dotProduct(n, AC);
auto t = numer / deno;
auto x = a[X] + t * AB[X];
auto y = a[Y] + t * AB[Y];
intersection.assign(X, x);
intersection.assign(Y, y);
return true;
}
else
return false;
}
bool Intersection(const Line2d &l1, const Line2d &l2,
Point2d &intersection)
{
auto l1_start = l1.getPoint();
auto l1_end = l1_start + l1.getDir(); // 假设t=1取的一个任一点
auto l2_start = l2.getPoint();
auto l2_end = l2_start + l2.getDir(); // 假设t=1取的一个任一点
return Intersection(l1_start, l1_end, l2_start, l2_end);
}
求两条线的角度
利用两条向量的点积
float AngleLine2D(const Line2d &l1, const Line2d &l2)
{
auto l1_mag = l1.getDir().magnitude();
auto l2_mag = l2.getDir().magnitude();
auto dot = dotProduct(l1.getDir(),l2.getDir())
auto theta = acos(fabs(dot)/l1_mag*l2_mag);
return RadianceToDegrees(theta);
}
线与平面的交点
90°-线与法线相交
两个平面的交点
两个平面的法线相交
template <typename T, size_t dim>
static float getAngle(const Vector<T, dim> &v1,
const Vector<T, dim> &v2)
{
auto dot = dotProduct(v1, v2);
auto theta = acos(fabs(dot));
return RadianceToDegrees(theta);
}
float AngleLines2d(const Line2d &l1, const Line2d &l2)
{
return getAngle(l1.getDir(),l2.getDir());
}
float AngleLines3d(const Line3d &l1, const Line3d &l2)
{
return getAngle(l1.getDir(), l2.getDir());
}
float AngleLinePlane(const Line3d &l1, const Planef &p)
{
auto angle = getAngle(l1.getDir(), p.getNormal());
return 90 - angle;
}
float AnglePlanes(const Planef&p1,const Planef&p2)
{
return getAngle(p1.getNormal(),p2.getNormal());
}
判断共线与共面的情况
注意共线的情况是包括平行
四面体的体积->可以判断四个点或者三条向量是否共面的问题,即判断四面体的体积是否为0
bool coplaner(const Point3d &a, const Point3d &b, const Point3d &c, const Point3d &d)
{
auto AB = b-a;
auto AC = c-a;
auto AD = d-a;
return coplaner(AB,AC,AD);
}
bool coplaner(const Vector3f &a, const Vector3f &b, const Vector3f &c)
{
float value = scalerTripleProduct(a,b,c);
return isEqualDouble(value,ZERO);
}
点与线之间的距离
V是x(t)的方向向量,即Y(t)的法线向量
已知t1就可以求出X(t)->这是表示一个点。两个点相减得到的向量 模就是距离。
float distance(Line3d &line, Point3d &c)
{
auto AC = c - line.getPoint();
auto t = dotProduct(line.getDir(),AC);
auto xt = line.getPoint() + line.getDir()*t;
auto dist_vec = xt - c;
return dist_vec.magnitude();
}
0<t<1:找到的距离点是在线段之间。
t<0:找到的距离点是在起始点之外。
t>1:找到的距离点是在终点之外。
点到面之间的距离
float distance(Planef &p, Point3d &q)
{
auto result = dotProduct(p.getNormal(), q) - p.getD();
return result;
}