1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
#include <iostream>
#include <sstream>
#include <cmath>
using namespace std;
//======================================================================
struct Pt { double x, y, z; };
Pt operator + ( Pt p, Pt q ) { return { p.x + q.x, p.y + q.y, p.z + q.z }; }
Pt operator - ( Pt p, Pt q ) { return { p.x - q.x, p.y - q.y, p.z - q.z }; }
Pt operator * ( double r, Pt p ) { return { r * p.x, r * p.y, r * p.z }; }
Pt operator / ( Pt p, double r ) { return { p.x / r, p.y / r, p.z / r }; }
double dot( Pt p, Pt q ) { return p.x * q.x + p.y * q.y + p.z * q.z; }
Pt cross( Pt p, Pt q ) { return { p.y * q.z - p.z * q.y, p.z * q.x - p.x * q.z, p.x * q.y - p.y * q.x }; }
double abs( Pt p ) { return sqrt( dot( p, p ) ); }
ostream &operator << ( ostream &out, const Pt &p ) { return out << p.x << '\t' << p.y << '\t' << p.z; }
istream &operator >> ( istream &in , Pt &p ) { return in >> p.x >> p.y >> p.z; }
bool getPt2d ( istream &in , Pt &p ) { p.z = 0.0; return (bool)( in >> p.x >> p.y ); }
//======================================================================
double perpendicularDistance( Pt p1, Pt p2, Pt p )
{
return abs( cross( p - p1, p2 - p1 ) ) / abs( p2 - p1 ); // distance is r sin( angle )
}
//======================================================================
double distanceToLineSegment( Pt p1, Pt p2, Pt p )
{
double segLength = abs( p2 - p1 );
if ( segLength < 1.0e-30 ) return abs( p - p1 ); // paranoia
double d = dot( p - p1, p2 - p1 ) / segLength; // signed distance to projection
if ( d < 0.0 ) return abs( p - p1 ); // projection is to "left" of p1
else if ( d > segLength ) return abs( p - p2 ); // projection is to "right" of p2
else return abs( p - ( p1 + d * ( p2 - p1 ) / segLength ) ); // distance to projection
}
//======================================================================
int main()
{
stringstream in( "12 7 1 3 0 14 \n"
"13 17 14 12 17 17 \n"
"3 15 1 19 4 1 \n"
"19 8 17 16 10 4 \n"
"3 0 18 2 18 19 \n"
"17 19 5 18 6 19 \n" );
cout << "Distance to segment vs perpendicular distance ...\n";
for ( Pt p1, p2, p; getPt2d( in, p1 ) && getPt2d( in, p2 ) && getPt2d( in, p ); )
cout << distanceToLineSegment( p1, p2, p ) << "\t\t" << perpendicularDistance( p1, p2, p ) << '\n';
}
|