空间中两个3D磁盘之间的碰撞检测
我想开发一种算法来执行3D空间中两个3D磁盘之间的碰撞检测。有没有可能建议一种分析方法,这样我就可以开发这个程序空间中两个3D磁盘之间的碰撞检测,3d,collision,detection,disk,3d,Collision,Detection,Disk,我想开发一种算法来执行3D空间中两个3D磁盘之间的碰撞检测。有没有可能建议一种分析方法,这样我就可以开发这个程序 谢谢,所以每个磁盘都位于一个无限平面的顶部,每个磁盘都有一个法向量和到原点的距离。在两个平面相交的地方,它们形成一条线 这条线将中心c1和c2投影为线p1和p2上的两个点,垂直距离为h1和h2。投影点之间的距离为l 如果磁盘接触,公共线将包含接触点。如果它们不接触,或相互渗透,则该点pC是同时距离两个磁盘中心最近的线上的点 要找到从p1到pC的距离t1,请使用类似的三角形来求解(
谢谢,所以每个磁盘都位于一个无限平面的顶部,每个磁盘都有一个法向量和到原点的距离。在两个平面相交的地方,它们形成一条线 这条线将中心c1和c2投影为线p1和p2上的两个点,垂直距离为h1和h2。投影点之间的距离为l 如果磁盘接触,公共线将包含接触点。如果它们不接触,或相互渗透,则该点pC是同时距离两个磁盘中心最近的线上的点 要找到从p1到pC的距离t1,请使用类似的三角形来求解(t1)/h1=(l-t1)/h2 从距离t1和公共线方向,计算点pC,然后如果两个圆盘到其中心的距离等于或小于其半径,则两个圆盘相交 圆盘 上面的数学是基于 更新
- 将厚度添加到磁盘属性,并使用它检查磁盘是否包含点
- 链接到我很久以前写的MATALB代码。可能会遗漏一些东西,但这可能会给你一个良好的起点。关于磁盘没有什么特别的,只是具有齐次坐标的几何体的框架
Disk.Containts()
函数以检查DistanceTo(point)@jAlex再次感谢您的回答。我将在MATLAB中重写这段代码,因为我在其中生成了随机数。请在我的答案中查看我的更新,并链接到MATLAB
code以了解一般几何知识。
t_1 = h_1*ell/(h_1+h_2)
intersect = ( distance(c_1-p_C)<=R_1 ) && ( distance(c_2-p_C)<=R_2 )
static void Main(string[] args)
{
var disk_1 = new Disk(Point.Origin, Vector3.UnitZ, 1);
var disk_2 = new Disk(
Point.Origin + Vector3.UnitY,
Vector3.UnitY,
0.6f);
if (Disk.Intersect(disk_1, disk_2))
{
Debug.WriteLine($"Crash");
}
}
using System.Numerics;
public class Disk : Plane
{
public Disk(Point center, Vector3 normal, float radius, float thickness)
: base(center, normal)
{
this.Center=center;
this.Radius=radius;
this.Thickness = thickness;
}
public Point Center { get; }
public float Radius { get; }
public float Thickness { get; }
public bool Containts(Point point)
{
if (DistanceTo(point)<= Thickness/2)
{
var d = (point - Center).Length();
return d<=Radius;
}
return false;
}
public static bool Intersect(Disk disk_1, Disk disk_2)
{
var commonLine = Line.Meet(disk_1, disk_2);
var p_1 = commonLine.Project(disk_1.Center);
var p_2 = commonLine.Project(disk_2.Center);
var ell = p_1.DistanceTo(p_2);
var h_1 = commonLine.DistanceTo(disk_1.Center);
var h_2 = commonLine.DistanceTo(disk_2.Center);
if (Math.Abs(h_1+h_2)>1e-8)
{
var t_1 = h_1*ell/(h_1+h_2);
var contact = p_1 - commonLine.Direction * t_1;
return disk_1.Containts(contact) && disk_2.Containts(contact);
}
else
{
return ell <= disk_1.Radius + disk_2.Radius;
}
}
}
using System.Numerics;
public class Point
{
public Vector3 Vector { get; }
public float Scalar { get; }
public Point(Vector3 position)
: this(position, 1) { }
public Point(Vector3 vector, float scalar)
{
this.Vector = vector;
this.Scalar=scalar;
}
public Point(Vector4 coordinates)
: this(new Vector3(coordinates.X, coordinates.Y, coordinates.Z), coordinates.W)
{ }
public Point(Plane plane)
: this(-plane.Scalar*plane.Vector, plane.Vector.LengthSquared())
{ }
public Point(Line line)
: this(Vector3.Cross(line.Vector, line.Moment), line.Vector.LengthSquared())
{ }
public static implicit operator Point(Vector3 position)
=> new Point(position, 1);
public static implicit operator Point(Vector4 coordinates)
=> new Point(coordinates);
public static readonly Point Origin = new Point(Vector3.Zero, 1);
public static Point Meet(Plane plane, Line line)
{
return new Point(
Vector3.Cross(line.Moment, plane.Vector)+plane.Scalar*line.Vector,
-Vector3.Dot(plane.Vector, line.Vector));
}
public static Point Meet(Plane plane_1, Plane plane_2, Plane plane_3)
{
return Meet(plane_1, Line.Meet(plane_2, plane_3));
}
public float Magnitude { get => Math.Abs(Scalar); }
public Vector3 Position { get => Vector/Scalar; }
public float DistanceTo(Point point)
=> (Scalar*point.Vector - point.Scalar*Vector).Length()/(Scalar*point.Scalar);
public float DistanceTo(Plane plane)
=> (Vector3.Dot(plane.Vector, Vector) + Scalar*plane.Scalar)/(Scalar*plane.Vector.Length());
public float DistanceTo(Line line)
=> (Vector3.Cross(line.Vector, Vector) + Scalar * line.Moment).Length()/(Scalar*line.Vector.Length());
public static Point operator +(Point point, Vector3 delta)
=> new Point(point.Vector + point.Scalar*delta, point.Scalar);
public static Vector3 operator -(Point point, Point @base)
=> point.Position - @base.Position;
}
public class Plane
{
public Vector3 Vector { get; }
public float Scalar { get; }
public Plane(Vector3 vector, float scalar)
{
this.Vector=vector;
this.Scalar=scalar;
}
public Plane(Vector4 coordinates)
: this(new Vector3(coordinates.X, coordinates.Y, coordinates.Z), coordinates.W)
{ }
public Plane(Point point, Vector3 normal)
: this(normal, -Vector3.Dot(point.Position, normal))
{ }
public Plane(Point point)
: this(-point.Scalar*point.Vector, point.Vector.LengthSquared())
{ }
public Plane(Line line)
: this(Vector3.Cross(line.Moment, line.Vector), line.Moment.LengthSquared())
{ }
public static implicit operator Plane(Vector4 coordinates)
=> new Plane(coordinates);
public static Plane Join(Point point, Line line)
{
return new Plane(
Vector3.Cross(line.Vector, point.Position) + line.Moment,
-Vector3.Dot(point.Position, line.Moment));
}
public static Plane Join(Point point_1, Point point_2, Point point_3)
{
return Join(point_1, Line.Join(point_2, point_3));
}
public float Magnitude { get => Vector.Length(); }
public Vector3 Normal { get => Vector3.Normalize(Vector); }
public float Offset { get => -Scalar/Magnitude; }
public Vector3 Position
{
get => Normal*Offset;
}
public float DistanceTo(Point point)
=> point.DistanceTo(this);
public Point Project(Point point)
{
float t = Vector3.Dot(Normal, point.Position)-Offset;
return point.Position - Normal*t;
}
}
public class Line
{
public Vector3 Vector { get; }
public Vector3 Moment { get; }
public Line(Vector3 vector, Vector3 moment)
{
this.Vector=vector;
this.Moment=moment;
}
public static Line Ray(Point point, Vector3 direction)
{
return new Line(direction,
Vector3.Cross(point.Position, direction));
}
public static Line Join(Point point_1, Point point_2)
{
return new Line(
point_2.Position-point_1.Position,
Vector3.Cross(point_1.Position, point_2.Position));
}
public static Line Meet(Plane plane_1, Plane plane_2)
{
return new Line(
Vector3.Cross(plane_1.Vector, plane_2.Vector),
plane_2.Vector*plane_1.Scalar-plane_1.Vector*plane_2.Scalar);
}
public Point Along(float travel)
=> Position.Position + Direction * travel;
public float Magnitude { get => Vector.Length(); }
public Vector3 Direction { get => Vector3.Normalize(Vector); }
public Point Position
{
get => new Point(this);
}
public float DistanceTo(Point point)
=> point.DistanceTo(this);
public float DistanceTo(Line line)
=> (Vector3.Dot(Vector, line.Moment) + Vector3.Dot(line.Vector, Moment))/Vector3.Cross(Vector, line.Vector).Length();
public Point Project(Point point)
{
return Along(Vector3.Dot(Direction, point.Position-Position.Position));
}
}