計算幾何算法三:直線

包括:二直線是否相交及交點、線段與直線是否相交、點通過直線的對稱點、點到直線的距離。

// RtLine.h: interface for the CRtLine class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_RTLINE_H__7BD6B35E_17E9_4258_A70C_1099AA129DD6__INCLUDED_)
#define AFX_RTLINE_H__7BD6B35E_17E9_4258_A70C_1099AA129DD6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "RtVector.h"
#include "RtPoint.h"

// a * x + b * y + c = 0 
template<class T>
class CRtLine
{
public:
 //constructor
 CRtLine()
 {}
 CRtLine( const double a, const double b, const double c ): mvd_a( a ), mvd_b( b ), mvd_c( c )
 {
 }
 CRtLine( CRtPoint<T>& start, CRtPoint<T>& stop )
 {
  setData( start, stop );
 }
 CRtLine( CRtVector<T>& vector )
 {
  setData( vector[0], vector[1] );
 }

 //copy constructor
 CRtLine( const CRtLine& in)
 {
  mvd_a = in.mvd_a;
  mvd_b = in.mvd_b;
  mvd_c = in.mvd_c;
 }

 //desconstructor
 virtual ~CRtLine()
 {}

//operators overload:
 //line Equality, epsilon used due to numerical imprecision
 bool operator == ( const CRtLine& in )
 {
  return ( src0.mvd_a == src1.mvd_a ) && ( src0.mvd_b == src1.mvd_b ) && ( src0.mvd_c == src1.mvd_c );    
 }

 //evaluate to line
 const CRtLine& operator = (const CRtLine& in)
 {
  mvd_a = in.mvd_a;
  mvd_b = in.mvd_b;
  mvd_c = in.mvd_c;

  return *this;
 }
 
 //the two straight lines intersect
 bool Intersect( CRtLine& in, CRtPoint<double>& out );

 //Intersects with the straight line segment
 bool Intersect( CRtVector<T>& in, CRtPoint<double>& out );
 
 //Point on a straight line symmetry point
 CRtPoint<T> SymmetryPoint( CRtPoint<T>& in );

 //Points to the straight line distance from
 double DistancePoint( CRtPoint<T>& in , CRtPoint<double>& out);

private:
 //Calculation of member variables
 void setData( CRtPoint<T>& start, CRtPoint<T>& stop )
 {
  int sign = (mvd_a = stop[1] - start[1]) < 0 ? -1 : 1;
  
  mvd_a *= sign;
  mvd_b = sign * ( start[0] - stop[0] );  
  mvd_c = sign * ( start[1] * stop[0] - start[0] * stop[1] );
 }

private:
 double mvd_a;
 double mvd_b;
 double mvd_c;
};

//If the two straight lines intersect, return true, and return to the intersection of p
template<class T>
bool CRtLine<T>::Intersect( CRtLine& in, CRtPoint<double>& out )
{
 double d = mvd_a * in.mvd_b - in.mvd_a * mvd_b;
 
 if( fabs(d) < MINERR )  return false; //non-intersect
 
 double data[2];
 data[0] = ( in.mvd_c * mvd_b - mvd_c * in.mvd_b ) / d; 
 data[1] = ( in.mvd_a * mvd_c - mvd_a * in.mvd_c ) / d;
 out.SetData(data);
 
 return true;
}
//Intersects with the straight line segment
template<class T>
bool CRtLine<T>::Intersect( CRtVector<T>& in, CRtPoint<double>& out )
{
  if( ( mvd_a * in[0][0] + mvd_b * in[0][1] + mvd_c ) * ( mvd_a * in[1][0] + mvd_b * in[1][1] + mvd_c ) > 0 )
   return false;

  return Intersect(CRtLine<T>(in),out); 
}

//Point on a straight line symmetry point
template<class T>
CRtPoint<T> CRtLine<T>::SymmetryPoint( CRtPoint<T>& in )

 T data[2];
 data[0] = ( ( pow( mvd_b, 2 ) - pow( mvd_a, 2) ) * in[0] - 2 * mvd_a * mvd_b * in[1] - 2 * mvd_a * mvd_c )
        / ( pow( mvd_b, 2 ) + pow( mvd_a, 2)); 
 data[1] = ( ( pow( mvd_b, 2 ) - pow( mvd_a, 2) ) * in[1] - 2 * mvd_a * mvd_b * in[0] - 2 * mvd_b * mvd_c )
        / ( pow( mvd_b, 2 ) + pow( mvd_a, 2));  

 return CRtPoint<T>(data);
}

/****************************************************************************** 
Points to the straight line distance from and return to the pedal of point

A straight line: Ax + By + C = 0 Dian (x0, y0) to the straight line "distance" as follows:

      A * x0 + B * y0 + C
d = -------------------
        A * A + B * B

This "distance" are symbols that point in a straight line at the top or the bottom, take the absolute value of said Euclidean distance.

Point (x0, y0) to the pedal line (x1, y1) to meet the

Ax1 + By1 + C = 0

(y0-y1) / (x0-x1) = B / A

Solution was:
     B * B * x - A * B * y-AC
x1 = ------------------
        A * A + B * B

-A * B + A * A * y - B * C
y1 = -------------------
        A * A + B * B

======================================
Three-dimensional case: http://hi.baidu.com/irmosgarden/blog/item/25bfd433b097d946ad4b5f7b.html
*******************************************************************************/
template<class T>
double CRtLine<T>::DistancePoint( CRtPoint<T>& in , CRtPoint<double>& out)
{
 double data[2];
 data[0] = ( pow(mvd_b, 2) * in[0] - mvd_a * mvd_b * in[1] - mvd_a * mvd_c )
       /( pow(mvd_a, 2) + pow(mvd_b, 2) );
 data[1] = ( pow(mvd_a, 2) * in[1] - mvd_a * mvd_b * in[0] - mvd_b * mvd_c )
       /( pow(mvd_a, 2) + pow(mvd_b, 2) );
 out.SetData(data);

 return ( mvd_a * in[0] + mvd_b * in[1] + mvd_c ) / ( pow(mvd_a, 2) + pow(mvd_b, 2) );
}

#endif // !defined(AFX_RTLINE_H__7BD6B35E_17E9_4258_A70C_1099AA129DD6__INCLUDED_)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章