计算空间两直线公垂线段的两个垂足

在欧氏三维空间中,当给定两条不平行的直线,可以通过计算它们方向向量的叉乘得到公垂线方向。通过对基点连线在公垂线方向上的投影,可以确定公垂线段上两个垂足的位置。
摘要由CSDN通过智能技术生成

计算空间两直线公垂线段的两个垂足

在欧氏空间中,如果已知一点P0以及一个方向,则沿该方向通过点P0的直线方程可以记为:

  P = P0 + t * v

其中v是直线单位方向向量,P0是基点坐标,P是直线上任意一点坐标,t是P点与基点的距离。如果将直线看作一个一维线性空间,v看作空间的单位基底,那么t 是P点在这个空间中的坐标。

 在三维欧式空间中,如果两个线段不平行,两个线段的方向向量叉乘得到它们的公垂线方向向量,
将两个线段的方向向量和公垂线方向向量单位化。


将两基点连线与此线段的单位方向向量点乘,也就是将两基点连线向该线段方向坐标轴投影,
就得到基点连线在这个坐标轴方向上的坐标值t。
 

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include<stdbool.h>
 
#ifndef __cplusplus
#define _Bool bool
typedef _Bool  bool; 
#endif/* __cplusplus */

static double ESP = 0.0001;

bool isSame( double* v1, double* v2 )
{
    if( ( NULL == v1 ) || ( NULL == v2 )  )
    {
         printf( "isSame: ERROR -- v1 or v2 invalid.\n");
         return false;
    }

    if( fabs( v1[0] - v2[0]) > ESP )
    {
         return false;
    }
    if( fabs( v1[1] - v2[1]) > ESP )
    {
         return false;
    }
    if( fabs( v1[2] - v2[2]) > ESP )
    {
         return false;
    }
    return true;
}

void crossMultiply( double* v1, double* v2, double* result)
{
    if( ( NULL == v1 ) || ( NULL == v2 ) || ( NULL == result ))
    {
         printf( "crossMultiply: ERROR -- v1, v2 or result invalid.\n");
         return ;
    }
    result[0] = v1[1] * v2[2] - v1[2] * v2[1];
    result[1] = v1[2] * v2[0] - v1[0] * v2[2];
    result[2] = v1[0] * v2[1] - v1[1] * v2[0];
    return;
}


double dotMultiply( double* v1, double* v2 )
{
    if( ( NULL == v1 ) || ( NULL == v2 )  )
    {
         printf( "dotMultiply: ERROR -- v1 or v2 invalid.\n");
         return 0.0;
    }
    double v;
    v = v1[0]*v2[0] + v1[1] * v2[1] - v1[2] * v2[2];
    return v;
}

void perpend(double* root1, double* v1, double* root2, double* v2, double* t1, double* t2)
{
    if( ( NULL == root1 ) || ( NULL == root2 )  )
    {
         printf( "perpend: ERROR -- root1 or root2 invalid.\n");
         return ;
    }
    if( ( NULL == v1 ) || ( NULL == v2 )  )
    {
         printf( "perpend: ERROR -- v1 or v2 invalid.\n");
         return ;
    }

    double v1Xv2[3];
    crossMultiply( v1, v2, v1Xv2 );
    double n = dotMultiply( v1Xv2, v1Xv2 );
    if( fabs( 0.0 - n ) < ESP )
    {
         printf( "perpend: v1 and v2 parallel.\n");
         return  ;
    }

    double p1p2[3];
    p1p2[0] = root2[0] - root1[0]; 
    p1p2[1] = root2[1] - root1[1]; 
    p1p2[2] = root2[2] - root1[2]; 

    *t1 = dotMultiply( v1 , p1p2 ) / n ;
    *t2 = dotMultiply( v2 , p1p2 ) / n ;
}



void test()
{
    double v1[3] = { 1, 0, 0 };
    double v2[3] = { 0, 1, 0 };  
    double v[3];
    crossMultiply( v1, v2, v );

    printf("v = [%f, %f, %f] \n", v[0], v[1], v[2] );

    double p1[3] = { 10, 0, 0 };
    double p2[3] = { 1, 10, 0 };    

    double t1;
    double t2;

    perpend( p1, v1, p2, v2, &t1, &t2 );

    printf( "t1 = %f \n", t1 );
    printf( "t2 = %f \n", t2 );
}


int main( int argc, char* argv[] )
{
    test();
    printf("Hello \n");
    return 0;
}

计算结果:

v  = [0.000000, 0.000000, 1.000000]
t1 = 9.000000
t2 = -10.000000
Hello

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值