+void GroundRadar::addRunwayVertices(const FGRunwayBase* aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices)
+{
+ double az1, az2, dist_m;
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, aRunway->latitude(), aRunway->longitude(), &az1, &az2, &dist_m);
+
+ osg::Vec3 center = fromPolar(az1, dist_m * aScale) + osg::Vec3(TextureHalfSize, TextureHalfSize, 0);
+ osg::Vec3 leftcenter = fromPolar(aRunway->headingDeg(), aRunway->lengthM() * aScale / 2) + center;
+ osg::Vec3 lefttop = fromPolar(aRunway->headingDeg() - 90, aRunway->widthM() * aScale / 2) + leftcenter;
+ osg::Vec3 leftbottom = leftcenter * 2 - lefttop;
+ osg::Vec3 rightbottom = center * 2 - lefttop;
+ osg::Vec3 righttop = center * 2 - leftbottom;
+
+ aVertices->push_back(lefttop);
+ aVertices->push_back(leftbottom);
+ aVertices->push_back(rightbottom);
+ aVertices->push_back(righttop);
+}
+
+osg::Geometry *GroundRadar::addPavementGeometry(const FGPavement* aPavement, double aTowerLat, double aTowerLon, double aScale)
+{
+
+ osg::ref_ptr<osgUtil::Tessellator> tess = new osgUtil::Tessellator;
+ osg::ref_ptr<osg::Geometry> polygon = new osg::Geometry;
+ osg::ref_ptr<osg::Vec3Array> pts = new osg::Vec3Array;
+
+ double az1, az2, dist_m;
+ const FGPavement::NodeList &nodeLst = aPavement->getNodeList();
+ FGPavement::NodeList::const_iterator it = nodeLst.begin(),
+ loopBegin = it;
+ while ( it != nodeLst.end() )
+ {
+ bool close = (*it)->mClose;
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, (*it)->mPos.getLatitudeDeg(), (*it)->mPos.getLongitudeDeg(), &az1, &az2, &dist_m);
+ osg::Vec3 p1 = fromPolar(az1, dist_m * aScale) + osg::Vec3(TextureHalfSize, TextureHalfSize, 0);
+ const FGPavement::BezierNode *bn = dynamic_cast<const FGPavement::BezierNode *>( it->ptr() );
+ if ( bn != 0 )
+ {
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, bn->mControl.getLatitudeDeg(), bn->mControl.getLongitudeDeg(), &az1, &az2, &dist_m);
+ osg::Vec3 p2 = fromPolar(az1, dist_m * aScale) + osg::Vec3(TextureHalfSize, TextureHalfSize, 0),
+ p3;
+ ++it;
+ if ( it == nodeLst.end() || close )
+ {
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, (*loopBegin)->mPos.getLatitudeDeg(), (*loopBegin)->mPos.getLongitudeDeg(), &az1, &az2, &dist_m);
+ }
+ else
+ {
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, (*it)->mPos.getLatitudeDeg(), (*it)->mPos.getLongitudeDeg(), &az1, &az2, &dist_m);
+ }
+ p3 = fromPolar(az1, dist_m * aScale) + osg::Vec3(TextureHalfSize, TextureHalfSize, 0);
+ simgear::BezierCurve<osg::Vec3> bCurv( p1, p2, p3 );
+ simgear::BezierCurve<osg::Vec3>::PointList &ptList = bCurv.pointList();
+ for ( simgear::BezierCurve<osg::Vec3>::PointList::iterator ii = ptList.begin(); ii != ptList.end(); ++ii )
+ {
+ pts->push_back( *ii );
+ }
+ pts->pop_back(); // Last point belongs to next segment
+ }
+ else
+ {
+ pts->push_back( p1 );
+ ++it;
+ }
+
+ if ( close ) // One loop for the moment
+ break;
+ }
+ geo_inverse_wgs_84(aTowerLat, aTowerLon, (*loopBegin)->mPos.getLatitudeDeg(), (*loopBegin)->mPos.getLongitudeDeg(), &az1, &az2, &dist_m);
+ osg::Vec3 p1 = fromPolar(az1, dist_m * aScale) + osg::Vec3(TextureHalfSize, TextureHalfSize, 0);
+ pts->push_back( p1 );
+ polygon->setVertexArray( pts.get() );
+
+ polygon->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::POLYGON, 0, pts->size() ) );
+
+ tess->setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
+ tess->setBoundaryOnly( false );
+ tess->setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
+ tess->retessellatePolygons( *polygon );
+ return polygon.release();
+}
+