c - 如何在给定边长的情况下找到斜角四面体的面的角度

标签 c computational-geometry tetrahedra

我正在用 C 语言编写一个程序,以在给定所有边的长度的情况下确定四面体的顶点。四面体具有等边底面和斜角面。为了完成公式,我需要一种方法来获取面与等边底面之间的角度。我知道其中一个面的高度的高度,一旦我能得到面和底面之间的角度,我就可以将高度旋转该角度并得到顶点的位置。

我有 0 想法从哪里开始计算角度的公式(见下面的 theta),以及如何将它转化为 C。

我知道黄色线段的长度,正在尝试找到蓝色线段的角度 B I know the lengths of the segments in yellow and am trying to find angle B in blue

到目前为止,这是我的代码:

#include <math.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

typedef struct {
  float x;
  float y;
  float z;
} Point;

typedef struct {
  float edgeA, edgeB, edgeC;
  float legA, legB, legC;
  Point vertexBaseA, vertexBaseB, vertexBaseC;
  Point apex;
} scaleneTetrahedron;

Point p(float x,float y) {
    Point pt; pt.x = x; pt.y = y; pt.z =0;return pt;
}

Point pZ(float x, float y, float z) {
      Point pt; pt.x = x; pt.y = y;pt.z =z; return pt;
}

void printPoint(char *identifier, Point p){
  printf("(%s: %f, %f, %f)\n",identifier, p.x,p.y,p.z);
}

void printFloat(float n) {
  printf("%f",n);
}

scaleneTetrahedron sT_Hedron(float lengthsEdges[3],float lengthsLegs[3],Point vertexBases[3]) {
  scaleneTetrahedron h;
  h.edgeA = lengthsEdges[0], h.edgeB = lengthsEdges[2], h.edgeC = lengthsEdges[2];
  h.legA = lengthsLegs[0], h.legB = lengthsLegs[1],h.legC = lengthsLegs[2];
  h.vertexBaseA = vertexBases[0], h.vertexBaseB = vertexBases[1], h.vertexBaseC = vertexBases[2];
  return h;
}

#define rt(n) (sqrt(n))
float SQUARE(float n) {return n*n;}
float PERP(float slope) { return 1/slope * -1;}
float Rad_To_Deg(float angle) {return angle*57.29577951f;}

#define ANGLE_FOR(rangX,rangY)      ( Rad_To_Deg(atan2(rangX,rangY))     )

float DISTANCE(Point v1, Point v2){
  return sqrtf(SQUARE(v1.x-v2.x) + SQUARE(v1.y-v2.y));

}

float WIDTH(float leg1,float leg2,float base){
  float ret = ((SQUARE(leg1) - SQUARE(leg2)) + SQUARE(base)) / (2 * base);
  printf("Ret is:%f\n",ret);
  return ret;
}

float HEIGHT(float width,float leg1){
  float ret = sqrtf(SQUARE(leg1) - SQUARE(width));
  return ret;
}

float slopeFor(Point A, Point B) {
  return (B.y-A.y) / (B.x - A.x);
}

float yInterceptFor(float slope, Point A) {
  return (A.y - (slope * A.x));
}

float map(float range1_A, float range1_B, float range2_A, float range2_B, float value) {
    float  inMin = range1_A;
    float  inMax = range1_B;

    float  outMin = range2_A;
    float  outMax = range2_B;

    float input = value;
    float output = outMin + (outMax - outMin) * (input - inMin) / (inMax - inMin);

    return output;
}

Point XYAltitude(float leg1, float leg2, float base) {

  float width = WIDTH(leg1,leg2,base); 
  float height = HEIGHT(width,leg1);
  return p(width, height);
}

Point APEX_OF(scaleneTetrahedron shape) {
  Point altitude1 = XYAltitude(shape.legA,shape.legB, shape.edgeA);//Getting the x position of the altitude of faceA and the height of the altitude. 
  printPoint("Altitude face:",altitude1);
  float 
  x = altitude1.x,
  baseX1 = x,
  baseX2 = x,
  baseY1 = 0,
  baseY2 = 10
  ; 

  float slopeBase = slopeFor(shape.vertexBaseC, shape.vertexBaseB), yIntBase = yInterceptFor(slopeBase,shape.vertexBaseB);
  printf("slope is:%f ,yint is:%f, point of intersection:%f\n",slopeBase,yIntBase, (slopeBase * x)+yIntBase);
  Point intersectionBase = p(x, (slopeBase * x) + yIntBase);


  printPoint("IntersectionBase:",intersectionBase);

  float zIntersectionBase = (slopeBase * x) + yIntBase;//it is "y" because we are switching from a topdown to a side view
  float zHypotenuse = (shape.edgeC* intersectionBase.y)/shape.vertexBaseC.y; //THIS IS THROWING OFF THE MEASUREMENT: sqrtf(SQUARE(zIntersectionBase) + SQUARE(altitude1.y));
  Point zAltitude   = XYAltitude(altitude1.y,zHypotenuse,zIntersectionBase);
  float theta       = Rad_To_Deg(atan2(zAltitude.x,zAltitude.y));//Here's where I am having trouble.
  float y = Rad_To_Deg(sin(theta)) * altitude1.x;
  float z = Rad_To_Deg(cos(theta)) * altitude1.x;
  printFloat(theta);
  Point rtd;
  rtd.x = x;
  rtd.z = y; //Only now did I learn that z and y are swapped in 3D. But, this is no problem due to abstraction. 
  rtd.y = z;

  return rtd;
}

int main(int argc, const char *argv[]){
  // srand(time(NULL));   

  Point vertexA  = p(0,0); 
  Point vertexB  = p(3,0.f);
  Point vertexC  = p(1.5,2.6); 
  Point apex =   pZ(1.5,0.87,2.45);

  float baseA = DISTANCE(vertexA,vertexB);
  float baseB = DISTANCE(vertexB,vertexC);
  float baseC = DISTANCE(vertexC,vertexA);
  float legA  = DISTANCE(vertexA,apex);
  float legB  = DISTANCE(vertexB,apex);
  float legC  = DISTANCE(vertexC,apex);

  scaleneTetrahedron toSend;
  toSend.edgeA = baseA;
  toSend.edgeB = baseB;
  toSend.edgeC = baseC;

  toSend.legA = legA; 
  toSend.legB = legB;
  toSend.legC = legC;

  toSend.vertexBaseA = vertexA;
  toSend.vertexBaseB = vertexB;
  toSend.vertexBaseC = vertexC;
  printPoint("APEX:",APEX_OF(toSend));

  return 0;

}

最佳答案

根据编辑后的问题回答:

此答案基于您在图片中引用的内容。 你用蓝色标记的角度是 AH 段(引用你的图片)和平面(我没有看到你的坐标系所以我假设这是 XZ 平面)之间的角度

//I use Point instead of Vector3, semantically no difference here
//but it is wrong conceptually.
Point getUpVector(){
     Point Up;
     Up.y = 1.0f;
     Up.x = Up.z = 0.0f;
     return Up;
}

Point getOrigin(){
    Point O;
    Up.x=Up.y=Up.z=0.0f;
    return O;         
}

Point getDirection(Point P1, Point P2){
    Point P3;
    P3.x = P1.x-P2.x; P3.y = P1.y-P2.y; P3.z = P1.z-P2.z;
    return P3;
}

double dotProduct(Point A, Point B){
    return A.x*B.x + A.y*B.y + A.z*B.z;
}


double distanceOfPoints(Point P1, Point P2){
    double x = P1.x - P2.x;
    double y = P1.y - P2.y;
    double z = P1.z - P2.z;
    return sqrt(x*x + y*y + z*z);
}

Point normalize(Point A){
    double L =  distanceOfPoints(A,GetOrigin());
    A.x/= L; A.y/=L; A.z/=L;
    return A;
}

//the function you have to call requires to know coordinates of points H and A
// it is impossible to compute that angle using only distances, because distances
// are indpendent of rotation while that angle requires to know the rotation..!!
double angleOnThePlane(Point H, Point A){
    Point D = getDirection(H,A);
    P = normalize(D);
    return asin( dotProduct(P,getUpVector())/
                 (distanceOfPoints(getUpVector,getOrigin()) +
                  distanceOfPoints(P,getOrigin())  
                 )
               );
}

如果这个答案还不够,因为它对您当前的问题是正确的,您最好提出一个新问题。


旧答案:

你不准确:

height of one of the faces

可能都表示四面体的高度,或者从顶部顶点开始将面切成两半的线的长度。

如果你知道:

  • 四面体的高度(AH 段)
  • 底边之一的长度(CB 段)

那么你知道有一个三角形A(Apex)-C-H

//since the base is equilateral you can compute CH with:
double computeCH(double CB){
    return CB*sqrt(3.0)/3.0
}

//the missing edge is then CA, you need pitagora this time:
double computeCA(double CB, double AH){
    double CH = computeCH(CB);
    return sqrt(AH*AH+CH*CH);
}

现在,您需要知道 A 中三角形 ABC 的角度(pex)。你已经有了 CB、AB 和 AC。

//just compute the height of the triangle ABC
double computeHeight(double CB, double AB){
    return sqrt(AB*AB - 0.25*CB*CB);
}

//then angle is trivial
double computeAngle(double Height, double AB){
    return 2.0*acos(Height/AB);
}

引用图片:

A Tetrahedron with some vertices and points marked


如果你知道:

  • 从顶部顶点 (H'A) 开始将面切成两半的线的长度
  • 底边之一的长度(CB,其中 H' 属于 CB)

公式更简单,基本上你从 Height 和 CB 开始,你只错过 AB

double computeAB(double Height, double CB){
    return sqrt( CB*CB*0.25 + Height*Height);
}

//just need to compute the angle now
double computeAngle(double Height, double AB){
    return 2.0*acos(Height/AB);
}

在这两种情况下,您都不需要知道顶点位置(假设底边是等边的并且是三角形),如果您出于特定原因需要它们,那么只需将问题重写为更具体的内容即可。

这是 Tetraheder 的 ASCII-Art 版本,因此您可以记录您的代码:

/**

              A
            / |\
          /   |  \
        /     |    \
      /       |      \
    /         |    ___ \
  / _____---  | H      /
  B ---___            /
          ---___     /
        H'      ----C
*/     

关于c - 如何在给定边长的情况下找到斜角四面体的面的角度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27672882/

相关文章:

c# - 如何检查点是否在四面体中?

python - 给定一个点和大量的四面体,如何高效判断该点在哪个四面体中

c - 在 C 中使用动态数组分配动态结构数组

c++ - 渐进下溢程序的表示

algorithm - 动态简单多边形三角剖分

检查多边形是否是多面体投影的算法

python - 如何通过 matplotlib 绘制四面体网格?

C 编程错误处理

c++ - 使用 malloc 安全吗?

algorithm - 如何将几何体分解成 block ?