C# 如何确定点在立方体内部或外部?
给定三维空间中具有8个顶点的立方体。如何确定C# 如何确定点在立方体内部或外部?,c#,geometry,C#,Geometry,给定三维空间中具有8个顶点的立方体。如何确定myPoint在多维数据集内部还是外部 cube[0] = (x0, y0, z0); cube[1] = (x1, y1, z1); cube[2] = (x2, y2, z2); cube[3] = (x3, y3, z3); cube[4] = (x4, y4, z4); cube[5] = (x5, y5, z5); cube[6] = (x6, y6, z6); cube[7] = (x7, y7, z7); myPoint = (x, y
myPoint
在多维数据集内部还是外部
cube[0] = (x0, y0, z0);
cube[1] = (x1, y1, z1);
cube[2] = (x2, y2, z2);
cube[3] = (x3, y3, z3);
cube[4] = (x4, y4, z4);
cube[5] = (x5, y5, z5);
cube[6] = (x6, y6, z6);
cube[7] = (x7, y7, z7);
myPoint = (x, y, z);
我正试图在3D中实现这一点,可能最简单的方法是为绑定立方体的6个平面中的每个平面计算平面方程,将点插入每个平面,并确保得到的符号为正(或负,取决于计算的平面是向内还是向外)。平面方程为p*法线+k=0,通过取两条边之间的叉积计算法线,然后将其中一个点插入平面方程得到k
更高级的方法是想象立方体定义X、Y和Z轴以及偏移量(由立方体[0]定义),并将其插入矩阵,以转换两个空间之间的点。用这个矩阵的倒数来转换你的点会把它放在“立方体空间”中,立方体与x/y/z轴对齐,这样你就可以对边做一个幅度比较。 如果你想从链接的帖子中实现思想,那么考虑轴对齐立方体(实际上是平行六面体)是有意义的。在这种情况下,检查是
xmin1。从立方体的四条对角线中选择任意一条
2.检查您的点是否在对角线点的范围内。
例如。您选择了开始(0,9,1)和结束(10,3,-1)的对角线
P1(5,6,0)的So
P.x(5)>Start.x(0)&P.x(5)End.x(3)
P.z(0)End.x(-1)
P1在里面
对于P2(5,6,6)
P.x(5)>Start.x(0)&P.x(5)End.x(3)
P.z(6)>Start.x(1)&P.z(6)>End.x(-1)这是我用来解决类似问题的算法,我的立方体没有与三维空间的轴对齐。这可能不是最快的选择,但它确实有效
拾取点a、b、c、d,这样a将成为立方体的原点,而b、c、d将形成立方体的轴(a和b通过边连接,与a和c以及a和d相同)。它不必与3D空间的轴对齐
使用以下公式计算立方体的边长(例如从a到b的距离):
distance = sqrt(sqr(a.X - b.X) + (a.Y - b.Y) + (a.Z - b.Z))
确定点是否在立方体内部
double latA = a DistanceTo(myPoint);
double latB = b.DistanceTo(myPoint);
if (Math.Abs(latA + latB - edgeLength) < 0.0001)
{
return true;
}
double angleA = CalculateAngleA(latA, latB, edgeLength);
if (angleA > 90.0001) return false;
double angleB = CalculateAngleA(latB, latA, edgeLength);
if (angleB > 90.0001) return false;
latB = e.DistanceTo(myPoint);
if (Math.Abs(latA + latB - edgeLength) < 0.0001)
{
return true;
}
angleA = CalculateAngleA(latA, latB, edgeLength);
if (angleA > 90.0001) return false;
angleB = CalculateAngleA(latB, latA, edgeLength);
if (angleB > 90.0001) return false;
latB = d.DistanceTo(myPoint);
if (Math.Abs(latA + latB - edgeLength) < 0.001)
{
return true;
}
angleA = CalculateAngleA(latA, latB, edgeLength);
if (angleA > 90.0001) return false;
angleB = CalculateAngleA(latB, latA, edgeLength);
if (angleB > 90.0001) return false;
//if all validations pass
return true;
特殊情况#1(轴对齐立方体):
如图所示,您可以简单地检查所考虑点的X、Y、Z坐标是否位于立方体的X、Y、Z坐标的最小值和最大值
X_min <= X <= X_max and Y_min <= Y <= Y_max and Z_min <= Z <= Z_max
1)确定每个面(F1,F2,…)的平面方程(ax+by+cz+d=0)
1.1计算F1的法向量(将该向量指向对象的外部!!!):
n1=(n1x,n1y,n1z)
1.2在F1平面方程中的系数上设置n1
n1xPx+n1yPy+n1z*Pz-d=val
在java中,它如下所示:
private Vector3f normal;
private float d;
public PlaneEquation(Vector3f normal, Vector v1){
this.normal = normal;
this.d = normal.x*v1x + normal.y*v1y+ normal.z*v1z;
}
public float relativePosition(Vector3f p){
return normal.x*p.x + normal.y*p.y+ normal.z*p.z - d;
}
这个方程是一个函数F1(Px,Py,Pz),因此p是一个测试点
1.3通过在上述等式上设置F1的共面点来计算d的值。我选择v1,因此:
d=n1xv1x+n1yv1y+n1z*v1z
2)使用平面函数法relativePosition(矢量3F p)在对象的所有面上执行循环,测试点坐标为F1(Px,Py,Pz),F2(Px,Py,Pz)等。
boolean OUT = false;
boolean IN = false;
boolean ON = false;
for(PlaneEquation plane : planeList){
if(plane.relativePosition(point) > 0){
OUT = true;
ON = false;
break;
}
if(plane.relativePosition(point) == 0){
ON = true;
}
}
if(OUT == false && ON == false){
IN = true;
}
2.2)如果所有结果F1(p),F2(p)。。。都是负数,所以点在OBCT内,否则为OUT或ON。或者,如果某个结果是肯定的,那么这一点就指出了。
boolean OUT = false;
boolean IN = false;
boolean ON = false;
for(PlaneEquation plane : planeList){
if(plane.relativePosition(point) > 0){
OUT = true;
ON = false;
break;
}
if(plane.relativePosition(point) == 0){
ON = true;
}
}
if(OUT == false && ON == false){
IN = true;
}
2.3)如果没有结果为正,但至少有一个结果为零,则该点位于对象上。
boolean OUT = false;
boolean IN = false;
boolean ON = false;
for(PlaneEquation plane : planeList){
if(plane.relativePosition(point) > 0){
OUT = true;
ON = false;
break;
}
if(plane.relativePosition(point) == 0){
ON = true;
}
}
if(OUT == false && ON == false){
IN = true;
}
方法2-重心坐标
import org.joml.Vector3f;
public class HexaedronEquation {
// a is origin point
private Vector3f a,b,c,d;//vertices of parallelepiped
private Vector3f u,v,w; //direction vectors
private Vector3f vXu; //v cross u
private Vector3f wXu; //w croos u
public HexaedronEquation(Vector3f a,Vector3f b,Vector3f c,Vector3f d ) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.u = this.b.sub(a,new Vector3f()); // b - a
this.v = this.c.sub(a, new Vector3f()); // c - a
this.w = this.d.sub(a, new Vector3f()); // d - a
this.vXu = this.v.cross(u, new Vector3f());
this.wXu = this.w.cross(u, new Vector3f());
}
public float[] getParams(Vector3f p) {
/* baricentric coordinates
* solve the system
* px = ax +t1*ux +t2*vx + t3*wx
* py = ay +t1*uy +t2*vy + t3*wy
* pz = az +t1*uz +t2*vz + t3*wz
*/
float t1 = 0;
float t2 = 0;
float t3 = 0;
Vector3f s = p.sub(a, new Vector3f());
Vector3f sXu = s.cross(u, new Vector3f());
if(vXu.length() != 0 && w.length()!=0) {
t3 = s.dot(vXu)/w.dot(vXu);
}
if(vXu.x != 0) {
t2 = (sXu.x - t3*wXu.x)/vXu.x;
}
if(vXu.y != 0) {
t2 = (sXu.y - t3*wXu.y)/vXu.y;
}
if(vXu.z != 0) {
t2 = (sXu.z - t3*wXu.z)/vXu.z;
}
if(u.x != 0) {
t1 = (s.x - v.x*t2 -w.x*t3)/u.x;
}
if(u.y != 0) {
t1 = (s.y - v.y*t2 -w.y*t3)/u.y;
}
if(u.z != 0) {
t1 = (s.z - v.z*t2 -w.z*t3)/u.z;
}
return new float[] {t1, t2, t3};
}
public boolean isInside(Vector3f p) {
float[] params = getParams(p);
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
if(params[0]>0 || params[0] <1) return true;
if(params[1]>0 || params[1] <1) return true;
if(params[2]>0 || params[2] <1) return true;
return false;
}
public boolean isOn(Vector3f p) {
float[] params = getParams(p);
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
if(params[0]==0 || params[0] ==1) return true;
if(params[1]==0 || params[1] ==1) return true;
if(params[2]==0 || params[2] ==1) return true;
return false;
}
public boolean isOnInside(Vector3f p) {
float[] params = getParams(p);
System.out.println("params: "+ getParamsString(params));
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
return true;
}
public boolean isOut(Vector3f p) {
float[] params = getParams(p);
if(params[0]<0 || params[0] >1) return true;
if(params[1]<0 || params[1] >1) return true;
if(params[2]<0 || params[2] >1) return true;
return false;
}
import org.joml.Vector3f;
公共类六面体方程{
//a是原点
私有向量3f a,b,c,d;//平行六面体的顶点
私有向量3f u,v,w;//方向向量
专用向量3f vXu;//v交叉u
私有向量3f wXu;//w croos u
公共六面体方程(向量3F a,向量3F b,向量3F c,向量3F d){
这个a=a;
这个.b=b;
这个.c=c;
这个。d=d;
this.u=this.b.sub(a,新向量3f());//b-a
this.v=this.c.sub(a,新向量3f());//c-a
this.w=this.d.sub(a,新向量3f());//d-a
this.vXu=this.v.cross(u,新向量3f());
this.wXu=this.w.cross(u,新向量3f());
}
公共浮点[]获取参数(向量3f p){
/*重心坐标
*解系统
*px=ax+t1*ux+t2*vx+t3*wx
*py=ay+t1*uy+t2*vy+t3*wy
*pz=az+t1*uz+t2*vz+t3*wz
*/
浮点数t1=0;
浮动t2=0;
浮动t3=0;
向量3f s=p.sub(a,新向量3f());
向量3f sXu=s.cross(u,新向量3f());
如果(vXu.length()!=0和&w.length()!=0){
t3=s.dot(vXu)/w.dot(vXu);
}
如果(vXu.x!=0){
t2=(sXu.x-t3*wXu.x)/vXu.x;
}
如果(vXu.y!=0){
t2=(sXu.y-t3*wXu.y)/vXu.y;
}
如果(vXu.z!=0){
t2=(sXu.z-t3*wXu.z)/vXu.z;
}
如果(u.x!=0){
t1=(s.x-v.x*t2-w.x*t3)/u.x;
}
如果(u.y!=0){
t1=(s.y-v.y*t2-w.y*t3)/u.y;
}
如果(u.z!=0){
t1=(s.z-v.z*t2-w.z*t3)/u.z;
}
返回新的浮点[]{t1,t2,t3};
}
公共布尔isInside(向量3f p){
float[]params=getParams(p);
if(params[0]<0 | | params[0]>1)返回false;
if(params[1]<0 | | params[1]>1)返回false;
import org.joml.Vector3f;
public class HexaedronEquation {
// a is origin point
private Vector3f a,b,c,d;//vertices of parallelepiped
private Vector3f u,v,w; //direction vectors
private Vector3f vXu; //v cross u
private Vector3f wXu; //w croos u
public HexaedronEquation(Vector3f a,Vector3f b,Vector3f c,Vector3f d ) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.u = this.b.sub(a,new Vector3f()); // b - a
this.v = this.c.sub(a, new Vector3f()); // c - a
this.w = this.d.sub(a, new Vector3f()); // d - a
this.vXu = this.v.cross(u, new Vector3f());
this.wXu = this.w.cross(u, new Vector3f());
}
public float[] getParams(Vector3f p) {
/* baricentric coordinates
* solve the system
* px = ax +t1*ux +t2*vx + t3*wx
* py = ay +t1*uy +t2*vy + t3*wy
* pz = az +t1*uz +t2*vz + t3*wz
*/
float t1 = 0;
float t2 = 0;
float t3 = 0;
Vector3f s = p.sub(a, new Vector3f());
Vector3f sXu = s.cross(u, new Vector3f());
if(vXu.length() != 0 && w.length()!=0) {
t3 = s.dot(vXu)/w.dot(vXu);
}
if(vXu.x != 0) {
t2 = (sXu.x - t3*wXu.x)/vXu.x;
}
if(vXu.y != 0) {
t2 = (sXu.y - t3*wXu.y)/vXu.y;
}
if(vXu.z != 0) {
t2 = (sXu.z - t3*wXu.z)/vXu.z;
}
if(u.x != 0) {
t1 = (s.x - v.x*t2 -w.x*t3)/u.x;
}
if(u.y != 0) {
t1 = (s.y - v.y*t2 -w.y*t3)/u.y;
}
if(u.z != 0) {
t1 = (s.z - v.z*t2 -w.z*t3)/u.z;
}
return new float[] {t1, t2, t3};
}
public boolean isInside(Vector3f p) {
float[] params = getParams(p);
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
if(params[0]>0 || params[0] <1) return true;
if(params[1]>0 || params[1] <1) return true;
if(params[2]>0 || params[2] <1) return true;
return false;
}
public boolean isOn(Vector3f p) {
float[] params = getParams(p);
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
if(params[0]==0 || params[0] ==1) return true;
if(params[1]==0 || params[1] ==1) return true;
if(params[2]==0 || params[2] ==1) return true;
return false;
}
public boolean isOnInside(Vector3f p) {
float[] params = getParams(p);
System.out.println("params: "+ getParamsString(params));
if(params[0]< 0 || params[0] > 1) return false;
if(params[1]< 0 || params[1] > 1) return false;
if(params[2]< 0 || params[2] > 1) return false;
return true;
}
public boolean isOut(Vector3f p) {
float[] params = getParams(p);
if(params[0]<0 || params[0] >1) return true;
if(params[1]<0 || params[1] >1) return true;
if(params[2]<0 || params[2] >1) return true;
return false;
}