Added a distance off route routine (works best with 2d cartesian coordinates.)
This commit is contained in:
parent
e4653be9a1
commit
c39e08cb2a
@ -30,9 +30,53 @@
|
|||||||
#include "vector.hxx"
|
#include "vector.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
|
// find the closest point (p1) on the line
|
||||||
|
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||||
|
const sgVec3 d ) {
|
||||||
|
|
||||||
|
sgVec3 u, u1;
|
||||||
|
|
||||||
|
// u = p - p0
|
||||||
|
sgSubVec3(u, p, p0);
|
||||||
|
|
||||||
|
// calculate the projection, u1, of u along d.
|
||||||
|
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||||
|
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||||
|
|
||||||
|
// calculate the point p1 along the line that is closest to p
|
||||||
|
// p0 = p1 + u1
|
||||||
|
sgAddVec3(p1, p0, u1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
|
// find the closest point (p1) on the line
|
||||||
|
void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||||
|
const sgdVec3 d ) {
|
||||||
|
|
||||||
|
sgdVec3 u, u1;
|
||||||
|
|
||||||
|
// u = p - p0
|
||||||
|
sgdSubVec3(u, p, p0);
|
||||||
|
|
||||||
|
// calculate the projection, u1, of u along d.
|
||||||
|
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||||
|
double ud = sgdScalarProductVec3(u, d);
|
||||||
|
double dd = sgdScalarProductVec3(d, d);
|
||||||
|
double tmp = ud / dd;
|
||||||
|
|
||||||
|
sgdScaleVec3(u1, d, tmp);;
|
||||||
|
|
||||||
|
// calculate the point p1 along the line that is closest to p
|
||||||
|
// p0 = p1 + u1
|
||||||
|
sgdAddVec3(p1, p0, u1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Given a point p, and a line through p0 with direction vector d,
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
// find the shortest distance (squared) from the point to the line
|
// find the shortest distance (squared) from the point to the line
|
||||||
double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||||
const sgVec3 d ) {
|
const sgVec3 d ) {
|
||||||
|
|
||||||
sgVec3 u, u1, v;
|
sgVec3 u, u1, v;
|
||||||
@ -54,20 +98,19 @@ double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
|||||||
|
|
||||||
// Given a point p, and a line through p0 with direction vector d,
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
// find the shortest distance (squared) from the point to the line
|
// find the shortest distance (squared) from the point to the line
|
||||||
double sgdPointLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||||
const sgdVec3 d ) {
|
const sgdVec3 d ) {
|
||||||
|
|
||||||
sgdVec3 u, u1, v;
|
sgdVec3 u, u1, v;
|
||||||
double ud, dd, tmp;
|
|
||||||
|
|
||||||
// u = p - p0
|
// u = p - p0
|
||||||
sgdSubVec3(u, p, p0);
|
sgdSubVec3(u, p, p0);
|
||||||
|
|
||||||
// calculate the projection, u1, of u along d.
|
// calculate the projection, u1, of u along d.
|
||||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||||
ud = sgdScalarProductVec3(u, d);
|
double ud = sgdScalarProductVec3(u, d);
|
||||||
dd = sgdScalarProductVec3(d, d);
|
double dd = sgdScalarProductVec3(d, d);
|
||||||
tmp = ud / dd;
|
double tmp = ud / dd;
|
||||||
|
|
||||||
sgdScaleVec3(u1, d, tmp);;
|
sgdScaleVec3(u1, d, tmp);;
|
||||||
|
|
||||||
|
@ -92,14 +92,24 @@ inline void sgCopyNegateVec4( sgVec4 dst, sgVec4 src )
|
|||||||
dst [ 3 ] = -src [ 3 ] ;
|
dst [ 3 ] = -src [ 3 ] ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
|
// find the closest point (p1) on the line
|
||||||
|
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||||
|
const sgVec3 d );
|
||||||
|
|
||||||
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
|
// find the closest point (p1) on the line
|
||||||
|
void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||||
|
const sgdVec3 d );
|
||||||
|
|
||||||
// Given a point p, and a line through p0 with direction vector d,
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
// find the shortest distance (squared) from the point to the line
|
// find the shortest distance (squared) from the point to the line
|
||||||
double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||||
const sgVec3 d );
|
const sgVec3 d );
|
||||||
|
|
||||||
// Given a point p, and a line through p0 with direction vector d,
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
// find the shortest distance (squared) from the point to the line
|
// find the shortest distance (squared) from the point to the line
|
||||||
double sgdPointLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||||
const sgdVec3 d );
|
const sgdVec3 d );
|
||||||
|
|
||||||
// This is same as
|
// This is same as
|
||||||
|
@ -10,7 +10,7 @@ libsgroute_a_SOURCES = \
|
|||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)
|
INCLUDES += -I$(top_srcdir)
|
||||||
|
|
||||||
noinst_PROGRAMS = waytest
|
noinst_PROGRAMS = waytest routetest
|
||||||
|
|
||||||
waytest_SOURCES = waytest.cxx
|
waytest_SOURCES = waytest.cxx
|
||||||
|
|
||||||
@ -18,3 +18,10 @@ waytest_LDADD = \
|
|||||||
$(top_builddir)/simgear/route/libsgroute.a \
|
$(top_builddir)/simgear/route/libsgroute.a \
|
||||||
$(top_builddir)/simgear/math/libsgmath.a \
|
$(top_builddir)/simgear/math/libsgmath.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||||
|
|
||||||
|
routetest_SOURCES = routetest.cxx
|
||||||
|
|
||||||
|
routetest_LDADD = \
|
||||||
|
$(top_builddir)/simgear/route/libsgroute.a \
|
||||||
|
$(top_builddir)/simgear/math/libsgmath.a \
|
||||||
|
$(top_builddir)/simgear/debug/libsgdebug.a
|
@ -21,6 +21,10 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
|
||||||
|
#include <simgear/math/vector.hxx>
|
||||||
|
|
||||||
#include "route.hxx"
|
#include "route.hxx"
|
||||||
|
|
||||||
|
|
||||||
@ -33,3 +37,34 @@ SGRoute::SGRoute() {
|
|||||||
// destructor
|
// destructor
|
||||||
SGRoute::~SGRoute() {
|
SGRoute::~SGRoute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate perpendicular distance from the current route segment
|
||||||
|
// This routine assumes all points are laying on a flat plane and
|
||||||
|
// ignores the altitude (or Z) dimension. For best results, use with
|
||||||
|
// CARTESIAN way points.
|
||||||
|
double SGRoute::distance_off_route( double x, double y ) const {
|
||||||
|
if ( current_wp > 0 ) {
|
||||||
|
int n0 = current_wp - 1;
|
||||||
|
int n1 = current_wp;
|
||||||
|
sgdVec3 p, p0, p1, d;
|
||||||
|
sgdSetVec3( p, x, y, 0.0 );
|
||||||
|
sgdSetVec3( p0,
|
||||||
|
route[n0].get_target_lon(), route[n0].get_target_lat(),
|
||||||
|
0.0 );
|
||||||
|
sgdSetVec3( p1,
|
||||||
|
route[n1].get_target_lon(), route[n1].get_target_lat(),
|
||||||
|
0.0 );
|
||||||
|
sgdSubVec3( d, p0, p1 );
|
||||||
|
|
||||||
|
return sqrt( sgdClosestPointToLineDistSquared( p, p0, d ) );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// We are tracking the first waypoint so there is no route
|
||||||
|
// segment. If you add the current location as the first
|
||||||
|
// waypoint and the actual waypoint as the second, then we
|
||||||
|
// will have a route segment and calculate distance from it.
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -127,6 +127,12 @@ public:
|
|||||||
route.erase( route.begin() );
|
route.erase( route.begin() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate perpendicular distance from the current route segment
|
||||||
|
// This routine assumes all points are laying on a flat plane and
|
||||||
|
// ignores the altitude (or Z) dimension. For best results, use
|
||||||
|
// with CARTESIAN way points.
|
||||||
|
double distance_off_route( double x, double y ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
27
simgear/route/routetest.cxx
Normal file
27
simgear/route/routetest.cxx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <simgear/constants.h>
|
||||||
|
|
||||||
|
#include "route.hxx"
|
||||||
|
#include "waypoint.hxx"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
SGRoute route;
|
||||||
|
|
||||||
|
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||||
|
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||||
|
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||||
|
route.add_waypoint( SGWayPoint(2, 2, 0, SGWayPoint::CARTESIAN, "3") );
|
||||||
|
route.add_waypoint( SGWayPoint(4, 2, 0, SGWayPoint::CARTESIAN, "4") );
|
||||||
|
|
||||||
|
route.set_current( 1 );
|
||||||
|
|
||||||
|
cout << "( 0.5, 0 ) = " << route.distance_off_route( 0.5, 0 ) << endl;
|
||||||
|
cout << "( 0.5, 1 ) = " << route.distance_off_route( 0.5, 1 ) << endl;
|
||||||
|
cout << "( 0.5, -1 ) = " << route.distance_off_route( 0.5, 1 ) << endl;
|
||||||
|
|
||||||
|
route.set_current( 3 );
|
||||||
|
|
||||||
|
cout << "( 2, 4 ) = " << route.distance_off_route( 2, 4 ) << endl;
|
||||||
|
cout << "( 2.5, 4 ) = " << route.distance_off_route( 2.5, 4 ) << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user