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 #include <osgEarthSymbology/GeometryFactory> 00020 #include <osgEarth/GeoMath> 00021 00022 #define LC "[GeometryFactory] " 00023 00024 using namespace osgEarth; 00025 using namespace osgEarth::Symbology; 00026 00027 GeometryFactory::GeometryFactory( const SpatialReference* srs ) : 00028 _srs( srs ) 00029 { 00030 //nop 00031 } 00032 00033 Geometry* 00034 GeometryFactory::createCircle(const osg::Vec3d& center, 00035 const Linear& radius, 00036 unsigned numSegments) 00037 { 00038 Polygon* geom = new Polygon(); 00039 00040 if ( numSegments == 0 ) 00041 { 00042 // automatically calculate 00043 double segLen = radius.as(Units::METERS) / 8.0; 00044 double circumference = 2*osg::PI*radius.as(Units::METERS); 00045 numSegments = (unsigned)::ceil(circumference / segLen); 00046 } 00047 00048 double segAngle = (2.0*osg::PI)/(double)numSegments; 00049 00050 if ( _srs.valid() && _srs->isGeographic() ) 00051 { 00052 double earthRadius = _srs->getEllipsoid()->getRadiusEquator(); 00053 double lat = osg::DegreesToRadians(center.y()); 00054 double lon = osg::DegreesToRadians(center.x()); 00055 double rM = radius.as(Units::METERS); 00056 00057 for( unsigned i=0; i<numSegments; ++i ) 00058 { 00059 double angle = segAngle * (double)i; 00060 double clat, clon; 00061 GeoMath::destination( lat, lon, angle, rM, clat, clon, earthRadius ); 00062 geom->push_back( osg::Vec3d(osg::RadiansToDegrees(clon), osg::RadiansToDegrees(clat), center.z()) ); 00063 } 00064 } 00065 00066 else 00067 { 00068 double rM = radius.as(Units::METERS); 00069 00070 for( unsigned i=0; i<numSegments; ++i ) 00071 { 00072 double angle = segAngle * (double)i; 00073 double x, y; 00074 x = center.x() + sin(angle)*rM; 00075 y = center.y() + cos(angle)*rM; 00076 geom->push_back( osg::Vec3d(x, y, center.z()) ); 00077 } 00078 } 00079 00080 return geom; 00081 } 00082 00083 Geometry* 00084 GeometryFactory::createArc(const osg::Vec3d& center, 00085 const Linear& radius, 00086 const Angular& start, 00087 const Angular& end, 00088 unsigned numSegments) 00089 { 00090 Geometry* geom = new LineString(); 00091 00092 if ( numSegments == 0 ) 00093 { 00094 // automatically calculate 00095 double segLen = radius.as(Units::METERS) / 8.0; 00096 double circumference = 2*osg::PI*radius.as(Units::METERS); 00097 numSegments = (unsigned)::ceil(circumference / segLen); 00098 } 00099 00100 double startRad = std::min( start.as(Units::RADIANS), end.as(Units::RADIANS) ); 00101 double endRad = std::max( start.as(Units::RADIANS), end.as(Units::RADIANS) ); 00102 double span = endRad - startRad; 00103 double step = span/(double)numSegments; 00104 00105 if ( _srs.valid() && _srs->isGeographic() ) 00106 { 00107 double earthRadius = _srs->getEllipsoid()->getRadiusEquator(); 00108 double lat = osg::DegreesToRadians(center.y()); 00109 double lon = osg::DegreesToRadians(center.x()); 00110 double rM = radius.as(Units::METERS); 00111 00112 for( unsigned i=0; i<=numSegments; ++i ) 00113 { 00114 double angle = startRad + step*(double)i; 00115 double clat, clon; 00116 GeoMath::destination( lat, lon, angle, rM, clat, clon, earthRadius ); 00117 geom->push_back( osg::Vec3d(osg::RadiansToDegrees(clon), osg::RadiansToDegrees(clat), center.z()) ); 00118 } 00119 } 00120 00121 else 00122 { 00123 double rM = radius.as(Units::METERS); 00124 00125 for( unsigned i=0; i<=numSegments; ++i ) 00126 { 00127 double angle = startRad + step*(double)i; 00128 double x, y; 00129 x = center.x() + sin(angle)*rM; 00130 y = center.y() + cos(angle)*rM; 00131 geom->push_back( osg::Vec3d(x, y, center.z()) ); 00132 } 00133 } 00134 00135 return geom; 00136 } 00137 00138 Geometry* 00139 GeometryFactory::createEllipse(const osg::Vec3d& center, 00140 const Linear& radiusMajor, 00141 const Linear& radiusMinor, 00142 const Angular& rotationAngle, 00143 unsigned numSegments) 00144 { 00145 Polygon* geom = new Polygon(); 00146 00147 if ( numSegments == 0 ) 00148 { 00149 // automatically calculate 00150 double ravgM = 0.5*(radiusMajor.as(Units::METERS) + radiusMinor.as(Units::METERS)); 00151 double segLen = ravgM / 8.0; 00152 double circumference = 2*osg::PI*ravgM; 00153 numSegments = (unsigned)::ceil(circumference / segLen); 00154 } 00155 00156 double segAngle = 2.0*osg::PI/(double)numSegments; 00157 00158 if ( _srs.valid() && _srs->isGeographic() ) 00159 { 00160 double earthRadius = _srs->getEllipsoid()->getRadiusEquator(); 00161 double lat = osg::DegreesToRadians(center.y()); 00162 double lon = osg::DegreesToRadians(center.x()); 00163 double a = radiusMajor.as(Units::METERS); 00164 double b = radiusMinor.as(Units::METERS); 00165 double g = rotationAngle.as(Units::RADIANS) - osg::PI_2; 00166 00167 for( unsigned i=0; i<numSegments; ++i ) 00168 { 00169 double angle = segAngle * (double)i; 00170 double t = angle - osg::PI_2; 00171 double clat, clon; 00172 00173 double rA = (b*b-a*a)*cos(2*t - 2*g) + a*a + b*b; 00174 double q = sqrt(2.0)*a*b*sqrt(rA); 00175 double r = q/rA; 00176 00177 GeoMath::destination( lat, lon, angle, r, clat, clon, earthRadius ); 00178 geom->push_back( osg::Vec3d(osg::RadiansToDegrees(clon), osg::RadiansToDegrees(clat), center.z()) ); 00179 } 00180 } 00181 else 00182 { 00183 double a = radiusMajor.as(Units::METERS); 00184 double b = radiusMinor.as(Units::METERS); 00185 double g = rotationAngle.as(Units::RADIANS) - osg::PI_2; 00186 double sing = sin(g), cosg = cos(g); 00187 00188 for( unsigned i=0; i<numSegments; ++i ) 00189 { 00190 double angle = segAngle * (double)i; 00191 double t = angle - osg::PI_2; 00192 double cost = cos(t), sint = sin(t); 00193 double x = center.x() + a*cost*cosg - b*sint*sing; 00194 double y = center.y() + a*cost*sing + b*sint*cosg; 00195 00196 geom->push_back( osg::Vec3d(x, y, center.z()) ); 00197 } 00198 } 00199 00200 return geom; 00201 }