我想创建一个函数来知道一条线是否到达一个点。有没有这样的功能?我还想以厘米为单位设置我的 3D 点的大小,但不知道该怎么做。
我感谢您的帮助。
例如:
假设这些点有一个半径并且这些线不会恰好在中间命中该点,如果一条线命中该点,该函数是否会显示我?
我想创建一个函数来知道一条线是否到达一个点。有没有这样的功能?我还想以厘米为单位设置我的 3D 点的大小,但不知道该怎么做。
我感谢您的帮助。
例如:
假设这些点有一个半径并且这些线不会恰好在中间命中该点,如果一条线命中该点,该函数是否会显示我?
好的,我有适用于任何维度的经典解决方案。
首先,你有一个球体和一条线,你需要对它们有很好的模型。Sphere 很简单,您只需一个 Vector.center
和.diameter
.
class Sphere:
def __init__( sphere, center, diameter ):
sphere.center=Vector(center)
sphere.diameter=float(diameter)
线条对于初学者来说可能会更成问题,因为它可以通过多种方式定义。最有用的来自参数方程,你在 Vector 中有一个方向.direction
和一些凝视点.center
。我们假设它.direction
是单位长度,并且.center
是距离(0,0)最近的点。在大多数情况下,我们需要创建一条线,必须指向向量:
def line_on_two_points( A, B ):
return Line( direction= Vector(B)-A, center=A )
所以我们必须修复构造函数中的direction
and center
。.direction
很容易解决我们需要使它成为单位长度。为了找到.center
,我们需要标量投影。这是 D 的向量:
作为.direction
单位长度 A 到 B 以及center
从 C 到 A,我们可以将我们的行初始化为:
class Line:
def __init__( line, direction, center ):
line.direction= Vector(direction) / length(direction)
line.center= center - line.direction*dot(center,line.direction)
如果我们没有一条线,我们可以只做两点:
#class Sphere:
def colide_line_on_two_points( sphere, A, B ):
line=line_on_two_points( A-sphere.center, B-sphere.center)
return length(line.center) < sphere.diameter
但是当我们有一条线时,我们会尝试将其优化为:
#class Sphere:
def colide_line( sphere, line ):
return line.distance_to(sphere.center) < sphere.diameter
该.distance_to()
功能有点棘手:
#class Line:
def vector_to( line, P ):
return line.center + line.direction * dot(line.direction,P) - P
def distance_to( line, P ):
return length( line.center + line.direction * dot(line.direction,P) - P )
def move_to( line, P ):
line.center += line.direction * dot(line.direction,P) - P
最后但并非最不重要的是Vector
类型,我尝试使用 numpy,但对于 2D、3D 来说它相当慢:
from numpy import array as Vector
from numpy import dot
from numpy.linalg import norm as length
您正在寻找的是一种算法来查找线和球体之间的交点。这是图形编程中常见的问题,有很多文章可能比我解释得更好。在http://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/有一个
基本思想是将球体投影到直线上,然后使用勾股定理求解由交点、球体中心和投影点形成的直角三角形 。
这是我在路径跟踪渲染器中使用的代码:
hitdata intersectwith(Sphere sphere)
{
d3Vector projected;
float t = V.dot(sphere.pos.subtract(O));
projected = V.normalize().scalarmultiply(t); //the projected vector
float distnce = (projected.subtract(sphere.pos.subtract(O))).magnitude();
//the length between the center of your sphere and the projected point
hitdata outdata; // a class containing the results of the intersection
outdata.hit = false;
outdata.t = 110;
if(t<=0)
{
return outdata;
}
if(distnce<sphere.r)
{// the line is less distant from the center of the sphere than the surface
outdata.hit = true;
float deltaT = sqrtf((sphere.r*sphere.r)-(distnce*distnce));//Pythagorean theorem
outdata.coord = O.add(V.scalarmultiply(t-deltaT));
//calculating intersection coordinates
outdata.normal = outdata.coord.subtract(sphere.pos);
outdata.normal = outdata.normal.normalize();//calculating surface normals
outdata.material = sphere.material;
outdata.t = t-deltaT;
}
return outdata;
}