osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 00020 #include <osgEarth/ECEF> 00021 00022 using namespace osgEarth; 00023 00024 #define LC "[ECEF] " 00025 00026 // -------------------------------------------------------------------------- 00027 00028 00029 osg::Matrixd 00030 ECEF::createInverseRefFrame( const osg::Vec3d& input ) 00031 { 00032 // convert to geocentric first: 00033 double X = input.x(), Y = input.y(), Z = input.z(); 00034 00035 osg::Matrixd localToWorld; 00036 localToWorld.makeTranslate(X,Y,Z); 00037 00038 // normalize X,Y,Z 00039 double inverse_length = 1.0/sqrt(X*X + Y*Y + Z*Z); 00040 00041 X *= inverse_length; 00042 Y *= inverse_length; 00043 Z *= inverse_length; 00044 00045 double length_XY = sqrt(X*X + Y*Y); 00046 double inverse_length_XY = 1.0/length_XY; 00047 00048 // Vx = |(-Y,X,0)| 00049 localToWorld(0,0) = -Y*inverse_length_XY; 00050 localToWorld(0,1) = X*inverse_length_XY; 00051 localToWorld(0,2) = 0.0; 00052 00053 // Vy = /(-Z*X/(sqrt(X*X+Y*Y), -Z*Y/(sqrt(X*X+Y*Y),sqrt(X*X+Y*Y))| 00054 double Vy_x = -Z*X*inverse_length_XY; 00055 double Vy_y = -Z*Y*inverse_length_XY; 00056 double Vy_z = length_XY; 00057 inverse_length = 1.0/sqrt(Vy_x*Vy_x + Vy_y*Vy_y + Vy_z*Vy_z); 00058 localToWorld(1,0) = Vy_x*inverse_length; 00059 localToWorld(1,1) = Vy_y*inverse_length; 00060 localToWorld(1,2) = Vy_z*inverse_length; 00061 00062 // Vz = (X,Y,Z) 00063 localToWorld(2,0) = X; 00064 localToWorld(2,1) = Y; 00065 localToWorld(2,2) = Z; 00066 00067 return localToWorld; 00068 } 00069 00070 void 00071 ECEF::transformAndLocalize(const osg::Vec3d& input, 00072 osg::Vec3d& output, 00073 const SpatialReference* srs, 00074 const osg::Matrixd& world2local) 00075 { 00076 osg::Vec3d ecef; 00077 srs->transformToECEF( input, ecef ); 00078 output = ecef * world2local; 00079 } 00080 00081 00082 void 00083 ECEF::transformAndLocalize(const std::vector<osg::Vec3d>& input, 00084 osg::Vec3Array* output, 00085 const SpatialReference* srs, 00086 const osg::Matrixd& world2local ) 00087 { 00088 output->reserve( output->size() + input.size() ); 00089 for( std::vector<osg::Vec3d>::const_iterator i = input.begin(); i != input.end(); ++i ) 00090 { 00091 osg::Vec3d ecef; 00092 srs->transformToECEF( *i, ecef ); 00093 output->push_back( ecef * world2local ); 00094 } 00095 } 00096 00097 void 00098 ECEF::transformAndGetRotationMatrix(const SpatialReference* srs, 00099 const osg::Vec3d& input, 00100 osg::Vec3d& out_point, 00101 osg::Matrixd& out_rotation ) 00102 { 00103 osg::Vec3d geod_point; 00104 if ( !srs->isGeographic() ) 00105 srs->transform( input, srs->getGeographicSRS(), geod_point ); 00106 else 00107 geod_point = input; 00108 00109 const osg::EllipsoidModel* em = srs->getEllipsoid(); 00110 00111 em->convertLatLongHeightToXYZ( 00112 osg::DegreesToRadians( geod_point.y() ), 00113 osg::DegreesToRadians( geod_point.x() ), 00114 geod_point.z(), 00115 out_point.x(), out_point.y(), out_point.z() ); 00116 00117 em->computeCoordinateFrame( 00118 osg::DegreesToRadians( geod_point.y() ), 00119 osg::DegreesToRadians( geod_point.x() ), 00120 out_rotation ); 00121 }