C 给定边长的不等边四面体的面角求法
我正在用C写一个程序,在给定所有边的长度的情况下,确定一个四面体的顶点。四面体具有等边底面和不等边。为了完成这个公式,我需要一种得到面和等边基之间的角度的方法。我知道其中一个面高度的高度,一旦我可以得到面和底部之间的角度,我就可以通过这个角度旋转高度,得到顶点的位置 我有0的想法,从哪里开始计算角度的公式(见下面的θ),以及如何将其转换为C 我知道黄色部分的长度,我正试图找到蓝色部分的角度B 以下是我目前的代码:C 给定边长的不等边四面体的面角求法,c,computational-geometry,tetrahedra,C,Computational Geometry,Tetrahedra,我正在用C写一个程序,在给定所有边的长度的情况下,确定一个四面体的顶点。四面体具有等边底面和不等边。为了完成这个公式,我需要一种得到面和等边基之间的角度的方法。我知道其中一个面高度的高度,一旦我可以得到面和底部之间的角度,我就可以通过这个角度旋转高度,得到顶点的位置 我有0的想法,从哪里开始计算角度的公式(见下面的θ),以及如何将其转换为C 我知道黄色部分的长度,我正试图找到蓝色部分的角度B 以下是我目前的代码: #include <math.h> #include <std
#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;
}
#包括
#包括
#包括
#包括
类型定义结构{
浮动x;
浮动y;
浮动z;
}点;
类型定义结构{
浮动edgeA、edgeB、edgeC;
浮动法A、法B、法C;
顶点A、顶点B、顶点C;
尖端;
}鳞片四面体;
点p(浮动x,浮动y){
点pt;pt.x=x;pt.y=y;pt.z=0;返回pt;
}
点pZ(浮动x、浮动y、浮动z){
点pt;pt.x=x;pt.y=y;pt.z=z;返回pt;
}
无效打印点(字符*标识符,点p){
printf((%s:%f,%f,%f)\n“,标识符,p.x,p.y,p.z);
}
无效打印浮点(浮点n){
printf(“%f”,n);
}
scaleneTetrahedron sT_Hedron(浮动长度sedges[3],浮动长度sedges[3],点顶点基底[3]){
鳞片四面体h;
h、 edgeA=长莎草[0],h.edgeB=长莎草[2],h.edgeC=长莎草[2];
h、 legA=长度[0],h.legB=长度[1],h.legC=长度[2];
h、 vertexBaseA=VertexBase[0],h.vertexBaseB=VertexBase[1],h.vertexBaseC=VertexBase[2];
返回h;
}
#定义rt(n)(sqrt(n))
浮点数平方(float n){返回n*n;}
浮动PERP(浮动斜率){return 1/slope*-1;}
浮动半径到度(浮动角度){返回角度*57.29577951f;}
#定义(rangX,rangY)的角度(Rad_到_Deg(atan2(rangX,rangY)))
浮动距离(点v1,点v2){
返回sqrtf(平方(v1.x-v2.x)+平方(v1.y-v2.y));
}
浮动宽度(浮动段1、浮动段2、浮动底座){
浮点数=((平方(leg1)-平方(leg2))+平方(基数))/(2*基数);
printf(“Ret是:%f\n”,Ret);
返回ret;
}
浮动高度(浮动宽度、浮动段1){
浮动ret=sqrtf(正方形(leg1)-正方形(宽度));
返回ret;
}
浮动坡度F(点A、点B){
回报率(B.y-A.y)/(B.x-A.x);
}
浮标yInterceptFor(浮标坡度,点A){
回报率(A.y-(斜率*A.x));
}
浮动贴图(浮动范围1_A、浮动范围1_B、浮动范围2_A、浮动范围2_B、浮动值){
最小浮动=范围1_A;
浮动inMax=范围1_B;
浮动输出最小值=范围2_A;
浮点输出最大值=范围2_B;
浮点输入=数值;
浮点输出=输出最小值+(输出最大值-输出最小值)*(输入-输入最小值)/(输入最大值-输入最小值);
返回输出;
}
点XY高度(浮动梯段1、浮动梯段2、浮动基座){
浮动宽度=宽度(leg1、leg2、底座);
浮动高度=高度(宽度,leg1);
返回p(宽度、高度);
}
点顶点_(四面体形状){
Point altitude1=XY高度(shape.legA,shape.legB,shape.edgeA);//获取面A高度的x位置和高度的高度。
打印点(“高度面:”,高度1);
浮动
x=高度1.x,
baseX1=x,
baseX2=x,
基数1=0,
基准2=10
;
float slopeBase=slopeFor(shape.vertexBaseC,shape.vertexBaseB),yIntBase=yInterceptFor(slopeBase,shape.vertexBaseB);
printf(“坡度为:%f,yint为:%f,交点为:%f\n”,坡度基,yIntBase,(坡度基*x)+yIntBase);
点相交基=p(x,(斜率基*x)+yIntBase);
打印点(“IntersectionBase:”,IntersectionBase);
float zIntersectionBase=(slopeBase*x)+yIntBase;//它是“y”,因为我们正在从自顶向下切换到侧视图
float z斜边=(shape.edgeC*intersectionBase.y)/shape.vertexBaseC.y;//这是在放弃测量值:sqrtf(SQUARE(zIntersectionBase)+SQUARE(altitude1.y));
Zalitute点=XY高度(高度1.y,斜边,基准面);
float theta=Rad_To_Deg(atan2(zalitude.x,zalitude.y));//这里是我遇到麻烦的地方。
浮动y=Rad_至_Deg(sin(θ))*高度1.x;
浮动z=弧度到度(cos(θ))*高度1.x;
打印浮点(θ);
点rtd;
rtd.x=x;
rtd.z=y;//直到现在我才知道z和y在3D中是交换的。但是,由于抽象,这并没有问题。
rtd.y=z;
返回rtd;
}
int main(int argc,const char*argv[]{
//srand(时间(空));
顶点=p(0,0);
顶点b=p(3,0.f);
点vertexC=p(1.5,2.6);
顶点=pZ(1.5,0.87,2.45);
浮动基准a=距离(顶点a、顶点b);
浮动基准B=距离(顶点B、顶点C);
float baseC=距离(vertexC,vertexA);
浮动legA=距离(顶点、顶点);
float legB=距离(顶点b,顶点);
float legC=距离(顶点顶点顶点);
鳞片四面体;
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;
打印点(“顶点:,顶点(toSend));
返回0;
}
根据编辑的问题回答:
这个答案是基于你在照片上引用的内容。
您用蓝色标记的角度是线段AH(参考您的图片)和平面之间的角度(我看不到您的坐标系,所以我假设这是XZ平面)
如果这个答案还不够,因为它对你当前的问题是正确的,你最好问一个新问题
旧答案: 你不准确: 其中一个面的高度 两者都可能表示四面体的高度,或从顶部顶点开始将面切成一半的线的长度 如果你知道:
- 四面体的高度(段AH)
//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()) ) ); }
//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); }
//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); }
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); }
/** A / |\ / | \ / | \ / | \ / | ___ \ / _____--- | H / B ---___ / ---___ / H' ----C */