void EllipseNodeEditor::updateDraggers() { LocalizedNodeEditor::updateDraggers(); if (_majorDragger && _minorDragger) { const osg::EllipsoidModel* em = _node->getMapNode()->getMap()->getProfile()->getSRS()->getEllipsoid(); //Get the current location of the center of the circle GeoPoint location = _node->getPosition(); //Get the raddi of the ellipse in meters EllipseNode* ellipse = static_cast<EllipseNode*>(_node.get()); double majorR = ellipse->getRadiusMajor().as(Units::METERS); double minorR = ellipse->getRadiusMinor().as(Units::METERS); double rotation = ellipse->getRotationAngle().as( Units::RADIANS ); double lat, lon; GeoMath::destination(osg::DegreesToRadians( location.y() ), osg::DegreesToRadians( location.x() ), osg::PI_2 - rotation, minorR, lat, lon, em->getRadiusEquator()); _minorDragger->setPosition( GeoPoint(location.getSRS(), osg::RadiansToDegrees( lon ), osg::RadiansToDegrees( lat ), 0, ALTMODE_ABSOLUTE), false); GeoMath::destination(osg::DegreesToRadians( location.y() ), osg::DegreesToRadians( location.x() ), -rotation, majorR, lat, lon, em->getRadiusEquator()); _majorDragger->setPosition( GeoPoint(location.getSRS(), osg::RadiansToDegrees( lon ), osg::RadiansToDegrees( lat ), 0, ALTMODE_ABSOLUTE), false); } }
void ClipSpace::clampToLeft(GeoPoint& p) { p.transformInPlace(p.getSRS()->getGeographicSRS()); osg::Vec3d world; p.toWorld(world); osg::Vec3d clip = world * _worldToClip; clip.x() = -1.0; world = clip * _clipToWorld; p.fromWorld(p.getSRS(), world); }
bool getIsectPoint( const GeoPoint& p1, const GeoPoint& p2, const GeoPoint& p3, const GeoPoint& p4, GeoPoint& out ) { double denom = (p4.y()-p3.y())*(p2.x()-p1.x()) - (p4.x()-p3.x())*(p2.y()-p1.y()); if ( denom == 0.0 ) { out = GeoPoint::invalid(); // parallel lines return false; } double ua_num = (p4.x()-p3.x())*(p1.y()-p3.y()) - (p4.y()-p3.y())*(p1.x()-p3.x()); double ub_num = (p2.x()-p1.x())*(p1.y()-p3.y()) - (p2.y()-p1.y())*(p1.x()-p3.x()); double ua = ua_num/denom; double ub = ub_num/denom; if ( ua < 0.0 || ua > 1.0 ) // || ub < 0.0 || ub > 1.0 ) { out = GeoPoint::invalid(); // isect point is on line, but not on line segment return false; } double x = p1.x() + ua*(p2.x()-p1.x()); double y = p1.y() + ua*(p2.y()-p1.y()); double z = p1.getDim() > 2? p1.z() + ua*(p2.z()-p1.z()) : 0.0; //right? out = GeoPoint( x, y, z, p1.getSRS() ); return true; }
void CircleNodeEditor::updateDraggers() { LocalizedNodeEditor::updateDraggers(); if (_radiusDragger) { const osg::EllipsoidModel* em = _node->getMapNode()->getMapSRS()->getEllipsoid(); // Get the current location of the center of the circle (in lat/long, absolute Z) GeoPoint location = _node->getPosition(); location.makeGeographic(); //location.makeAbsolute( _node->getMapNode()->getTerrain() ); //Get the radius of the circle in meters double r = static_cast<CircleNode*>(_node.get())->getRadius().as(Units::METERS); double lat, lon; GeoMath::destination( osg::DegreesToRadians( location.y() ), osg::DegreesToRadians( location.x() ), _bearing, r, lat, lon, em->getRadiusEquator() ); GeoPoint draggerLocation( location.getSRS(), osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat)); draggerLocation.z() = 0; _radiusDragger->setPosition( draggerLocation, false ); } }
bool MapInfo::toWorldPoint( const GeoPoint& input, osg::Vec3d& output ) const { return input.isValid() ? input.getSRS()->transformToWorld(input.vec3d(), output) : false; }
void EllipseNodeEditor::updateDraggers() { LocalizedNodeEditor::updateDraggers(); if (_majorDragger && _minorDragger) { const osg::EllipsoidModel* em = _node->getMapNode()->getMap()->getProfile()->getSRS()->getEllipsoid(); //Get the current location of the center of the circle GeoPoint location = _node->getPosition(); //Get the raddi of the ellipse in meters EllipseNode* ellipse = static_cast<EllipseNode*>(_node.get()); double majorR = ellipse->getRadiusMajor().as(Units::METERS); double minorR = ellipse->getRadiusMinor().as(Units::METERS); double rotation = ellipse->getRotationAngle().as( Units::RADIANS ); double latRad, lonRad; // minor dragger: end of the rotated +Y axis: GeoMath::destination( osg::DegreesToRadians( location.y() ), osg::DegreesToRadians( location.x() ), rotation, minorR, latRad, lonRad, em->getRadiusEquator()); GeoPoint minorLocation(location.getSRS(), osg::RadiansToDegrees( lonRad ), osg::RadiansToDegrees( latRad )); minorLocation.z() = 0; _minorDragger->setPosition( minorLocation, false ); // major dragger: end of the rotated +X axis GeoMath::destination( osg::DegreesToRadians( location.y() ), osg::DegreesToRadians( location.x() ), rotation + osg::PI_2, majorR, latRad, lonRad, em->getRadiusEquator()); GeoPoint majorLocation(location.getSRS(), osg::RadiansToDegrees( lonRad ), osg::RadiansToDegrees( latRad )); majorLocation.z() = 0; _majorDragger->setPosition( majorLocation, false); } }
bool GeoPoint::operator == ( const GeoPoint& rhs ) const { return isValid() && rhs.isValid() && SpatialReference::equivalent( getSRS(), rhs.getSRS() ) && getDim() == rhs.getDim() && x() == rhs.x() && (getDim() < 2 || y() == rhs.y()) && (getDim() < 3 || z() == rhs.z()); }
GeoPoint RectangleNode::getCorner( Corner corner ) const { GeoPoint center = getPosition(); double earthRadius = center.getSRS()->getEllipsoid()->getRadiusEquator(); double lat = osg::DegreesToRadians(center.y()); double lon = osg::DegreesToRadians(center.x()); double halfWidthMeters = _width.as(Units::METERS) / 2.0; double halfHeightMeters = _height.as(Units::METERS) / 2.0; double eastLon, eastLat; double westLon, westLat; double northLon, northLat; double southLon, southLat; GeoMath::destination( lat, lon, osg::DegreesToRadians( 90.0 ), halfWidthMeters, eastLat, eastLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( -90.0 ), halfWidthMeters, westLat, westLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( 0.0 ), halfHeightMeters, northLat, northLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( 180.0 ), halfHeightMeters, southLat, southLon, earthRadius ); if (corner == CORNER_LOWER_LEFT) { return GeoPoint(center.getSRS(), osg::RadiansToDegrees(westLon), osg::RadiansToDegrees(southLat), 0, ALTMODE_RELATIVE); } else if (corner == CORNER_LOWER_RIGHT) { return GeoPoint(center.getSRS(), osg::RadiansToDegrees(eastLon), osg::RadiansToDegrees(southLat), 0, ALTMODE_RELATIVE); } else if (corner == CORNER_UPPER_LEFT) { return GeoPoint(center.getSRS(), osg::RadiansToDegrees(westLon), osg::RadiansToDegrees(northLat), 0, ALTMODE_RELATIVE); } else if (corner == CORNER_UPPER_RIGHT) { return GeoPoint(center.getSRS(), osg::RadiansToDegrees(eastLon), osg::RadiansToDegrees(northLat), 0, ALTMODE_RELATIVE); } return GeoPoint(); }
void RectangleNode::setLowerLeft( const GeoPoint& lowerLeft ) { GeoPoint center = getPosition(); //Figure out the new width and height double earthRadius = center.getSRS()->getEllipsoid()->getRadiusEquator(); double lat = osg::DegreesToRadians(center.y()); double lon = osg::DegreesToRadians(center.x()); double halfWidthMeters = _width.as(Units::METERS) / 2.0; double halfHeightMeters = _height.as(Units::METERS) / 2.0; double eastLon, eastLat; double westLon, westLat; double northLon, northLat; double southLon, southLat; //Get the current corners GeoMath::destination( lat, lon, osg::DegreesToRadians( 90.0 ), halfWidthMeters, eastLat, eastLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( -90.0 ), halfWidthMeters, westLat, westLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( 0.0 ), halfHeightMeters, northLat, northLon, earthRadius ); GeoMath::destination( lat, lon, osg::DegreesToRadians( 180.0 ), halfHeightMeters, southLat, southLon, earthRadius ); if (osg::DegreesToRadians(lowerLeft.x()) < eastLon && osg::DegreesToRadians(lowerLeft.y()) < northLat) { westLon = osg::DegreesToRadians(lowerLeft.x()); southLat = osg::DegreesToRadians(lowerLeft.y()); double x = ( eastLon + westLon ) / 2.0; double y = ( southLat + northLat) / 2.0; setPosition(GeoPoint( center.getSRS(), osg::RadiansToDegrees(x), osg::RadiansToDegrees(y))); double width = GeoMath::distance( y, westLon, y, eastLon, earthRadius); double height = GeoMath::distance( southLat, x, northLat, x, earthRadius); setWidth( Linear(width, Units::METERS )); setHeight( Linear(height, Units::METERS )); } }
bool ElevationQuery::getElevation(const GeoPoint& point, double& out_elevation, double desiredResolution, double* out_actualResolution) { sync(); if ( point.altitudeMode() == ALTMODE_ABSOLUTE ) { return getElevationImpl( point, out_elevation, desiredResolution, out_actualResolution ); } else { GeoPoint point_abs( point.getSRS(), point.x(), point.y(), 0.0, ALTMODE_ABSOLUTE ); return getElevationImpl( point_abs, out_elevation, desiredResolution, out_actualResolution ); } }
bool AnnotationNode::makeAbsolute( GeoPoint& mapPoint, osg::Node* patch ) const { // in terrain-clamping mode, force it to HAT=0: if ( _altitude.valid() && ( _altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) ) { mapPoint.altitudeMode() = ALTMODE_RELATIVE; //If we're clamping to the terrain if (_altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN) { mapPoint.z() = 0.0; } } // if the point's already absolute and we're not clamping it, nop. if ( mapPoint.altitudeMode() == ALTMODE_ABSOLUTE ) { return true; } // calculate the absolute Z of the map point. if ( getMapNode() ) { // find the terrain height at the map point: double hamsl; if (getMapNode()->getTerrain()->getHeight(patch, mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), &hamsl, 0L)) { // apply any scale/offset in the symbology: if ( _altitude.valid() ) { if ( _altitude->verticalScale().isSet() ) hamsl *= _altitude->verticalScale()->eval(); if ( _altitude->verticalOffset().isSet() ) hamsl += _altitude->verticalOffset()->eval(); } mapPoint.z() += hamsl; } mapPoint.altitudeMode() = ALTMODE_ABSOLUTE; return true; } return false; }
float ElevationQuery::getElevation(const GeoPoint& point, double desiredResolution, double* out_actualResolution) { float result = NO_DATA_VALUE; sync(); if ( point.altitudeMode() == ALTMODE_ABSOLUTE ) { getElevationImpl( point, result, desiredResolution, out_actualResolution ); } else { GeoPoint point_abs( point.getSRS(), point.x(), point.y(), 0.0, ALTMODE_ABSOLUTE ); getElevationImpl( point_abs, result, desiredResolution, out_actualResolution ); } return result; }
void CircleNodeEditor::computeBearing() { _bearing = osg::DegreesToRadians( 90.0 ); //Get the radius dragger's position if (!_radiusDragger->getMatrix().isIdentity()) { // Get the current location of the center of the circle (in lat/long) GeoPoint location = _node->getPosition(); location.makeGeographic(); // location of the radius dragger (in lat/long) GeoPoint radiusLocation; radiusLocation.fromWorld( location.getSRS(), _radiusDragger->getMatrix().getTrans() ); // calculate the bearing b/w the _bearing = GeoMath::bearing( osg::DegreesToRadians(location.y()), osg::DegreesToRadians(location.x()), osg::DegreesToRadians(radiusLocation.y()), osg::DegreesToRadians(radiusLocation.x())); } }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, float& out_elevation, double desiredResolution, double* out_actualResolution) { // assertion. if ( !point.isAbsolute() ) { OE_WARN << LC << "Assertion failure; input must be absolute" << std::endl; return false; } osg::Timer_t begin = osg::Timer::instance()->tick(); // first try the terrain patches. if ( _terrainModelLayers.size() > 0 ) { osgUtil::IntersectionVisitor iv; if ( _ivrc.valid() ) iv.setReadCallback(_ivrc.get()); for(LayerVector::iterator i = _terrainModelLayers.begin(); i != _terrainModelLayers.end(); ++i) { // find the scene graph for this layer: Layer* layer = i->get(); osg::Node* node = layer->getNode(); if ( node ) { // configure for intersection: osg::Vec3d surface; point.toWorld( surface ); // trivial bounds check: if ( node->getBound().contains(surface) ) { osg::Vec3d nvector; point.createWorldUpVector(nvector); osg::Vec3d start( surface + nvector*5e5 ); osg::Vec3d end ( surface - nvector*5e5 ); // first time through, set up the intersector on demand if ( !_lsi.valid() ) { _lsi = new osgUtil::LineSegmentIntersector(start, end); _lsi->setIntersectionLimit( _lsi->LIMIT_NEAREST ); } else { _lsi->reset(); _lsi->setStart( start ); _lsi->setEnd ( end ); } // try it. iv.setIntersector( _lsi.get() ); node->accept( iv ); // check for a result!! if ( _lsi->containsIntersections() ) { osg::Vec3d isect = _lsi->getIntersections().begin()->getWorldIntersectPoint(); // transform back to input SRS: GeoPoint output; output.fromWorld( point.getSRS(), isect ); out_elevation = (float)output.z(); if ( out_actualResolution ) *out_actualResolution = 0.0; return true; } } else { //OE_INFO << LC << "Trivial rejection (bounds check)" << std::endl; } } } } if (_elevationLayers.empty()) { // this means there are no heightfields. out_elevation = NO_DATA_VALUE; return true; } // secure map pointer: osg::ref_ptr<const Map> map; if (!_map.lock(map)) { return false; } // tile size (resolution of elevation tiles) unsigned tileSize = 257; // yes? // default LOD: unsigned lod = 23u; // attempt to map the requested resolution to an LOD: if (desiredResolution > 0.0) { int level = map->getProfile()->getLevelOfDetailForHorizResolution(desiredResolution, tileSize); if ( level > 0 ) lod = level; } // do we need a new ElevationEnvelope? if (!_envelope.valid() || !point.getSRS()->isHorizEquivalentTo(_envelope->getSRS()) || lod != _envelope->getLOD()) { _envelope = map->getElevationPool()->createEnvelope(point.getSRS(), lod); } // sample the elevation, and if requested, the resolution as well: if (out_actualResolution) { std::pair<float, float> result = _envelope->getElevationAndResolution(point.x(), point.y()); out_elevation = result.first; *out_actualResolution = result.second; } else { out_elevation = _envelope->getElevation(point.x(), point.y()); } return out_elevation != NO_DATA_VALUE; }
void AutoClipPlaneCullCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) { if ( _active ) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); if ( cv ) { osgEarth::Map* map = _mapNode.valid() ? _mapNode->getMap() : 0; osg::Camera* cam = cv->getCurrentCamera(); osg::ref_ptr<osg::CullSettings::ClampProjectionMatrixCallback>& clamper = _clampers.get(cam); if ( !clamper.valid() ) { clamper = new CustomProjClamper(); cam->setClampProjectionMatrixCallback( clamper.get() ); OE_INFO << LC << "Installed custom projeciton matrix clamper" << std::endl; } else { CustomProjClamper* c = static_cast<CustomProjClamper*>(clamper.get()); osg::Vec3d eye, center, up; cam->getViewMatrixAsLookAt( eye, center, up ); // clamp the far clipping plane to the approximate horizon distance if ( _autoFarPlaneClamping ) { double d = eye.length(); c->_maxFar = sqrt( d*d - _rp2 ); } else { c->_maxFar = DBL_MAX; } // get the height-above-ellipsoid. If we need to be more accurate, we can use // ElevationQuery in the future.. //osg::Vec3d loc; GeoPoint loc; if ( map ) { loc.fromWorld( map->getSRS(), eye ); //map->worldPointToMapPoint( eye, loc ); } else { static osg::EllipsoidModel em; osg::Vec3d t; em.convertXYZToLatLongHeight( eye.x(), eye.y(), eye.z(), loc.y(), loc.x(), loc.z() ); } //double hae = loc.z(); double hae = loc.z(); if (_mapNode.valid()) { double height = 0.0; _mapNode->getTerrain()->getHeight(loc.getSRS(), loc.x(), loc.y(), &height); //OE_NOTICE << "got height " << height << std::endl; hae -= height; //OE_NOTICE << "HAE=" << hae << std::endl; } // ramp a new near/far ratio based on the HAE. c->_nearFarRatio = Utils::remap( hae, 0.0, _haeThreshold, _minNearFarRatio, _maxNearFarRatio ); } #if 0 { double n, f, a, v; cv->getProjectionMatrix()->getPerspective(v, a, n, f); OE_INFO << std::setprecision(16) << "near = " << n << ", far = " << f << ", ratio = " << n/f << std::endl; } #endif } } traverse( node, nv ); }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, double& out_elevation, double desiredResolution, double* out_actualResolution) { osg::Timer_t start = osg::Timer::instance()->tick(); if ( _maxDataLevel == 0 || _tileSize == 0 ) { // this means there are no heightfields. out_elevation = 0.0; return true; } //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, _tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } osg::ref_ptr<osg::HeightField> tile; // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } // Check the tile cache. Note that the TileSource already likely has a MemCache // attached to it. We employ a secondary cache here for a couple reasons. One, this // cache will store not only the heightfield, but also the tesselated tile in the event // that we're using GEOMETRIC mode. Second, since the call the getHeightField can // fallback on a lower resolution, this cache will hold the final resolution heightfield // instead of trying to fetch the higher resolution one each item. TileCache::Record record; if ( _tileCache.get(key, record) ) { tile = record.value().get(); } // if we didn't find it, build it. if ( !tile.valid() ) { // generate the heightfield corresponding to the tile key, automatically falling back // on lower resolution if necessary: _mapf.getHeightField( key, true, tile, 0L ); // bail out if we could not make a heightfield a all. if ( !tile.valid() ) { OE_WARN << LC << "Unable to create heightfield for key " << key.str() << std::endl; return false; } _tileCache.insert(key, tile.get()); } OE_DEBUG << LC << "LRU Cache, hit ratio = " << _tileCache.getStats()._hitRatio << std::endl; // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = (double)tile->getXInterval(); bool result = true; const GeoExtent& extent = key.getExtent(); double xInterval = extent.width() / (double)(tile->getNumColumns()-1); double yInterval = extent.height() / (double)(tile->getNumRows()-1); out_elevation = (double) HeightFieldUtils::getHeightAtLocation( tile.get(), mapPoint.x(), mapPoint.y(), extent.xMin(), extent.yMin(), xInterval, yInterval, _mapf.getMapInfo().getElevationInterpolation() ); osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( start, end ); return result; }
bool GeoTransform::setPosition(const GeoPoint& position) { if ( !position.isValid() ) return false; _position = position; // relative Z or reprojection require a terrain: osg::ref_ptr<Terrain> terrain; _terrain.lock(terrain); // relative Z requires a terrain: if (position.altitudeMode() == ALTMODE_RELATIVE && !terrain.valid()) { OE_TEST << LC << "setPosition failed condition 1\n"; return false; } GeoPoint p; // transform into terrain SRS if neccesary: if (terrain.valid() && !terrain->getSRS()->isEquivalentTo(position.getSRS())) p = position.transform(terrain->getSRS()); else p = position; // bail if the transformation failed: if ( !p.isValid() ) { OE_TEST << LC << "setPosition failed condition 2\n"; return false; } // convert to absolute height: if ( !p.makeAbsolute(_terrain.get()) ) { OE_TEST << LC << "setPosition failed condition 3\n"; return false; } // assemble the matrix: osg::Matrixd local2world; p.createLocalToWorld( local2world ); this->setMatrix( local2world ); // install auto-recompute? if (_autoRecompute && _position.altitudeMode() == ALTMODE_RELATIVE && !_autoRecomputeReady) { // by using the adapter, there's no need to remove // the callback then this object destructs. terrain->addTerrainCallback( new TerrainCallbackAdapter<GeoTransform>(this) ); _autoRecomputeReady = true; } return true; }
bool OGR_SpatialReference::transformInPlace( GeoPoint& input ) const { if ( !handle || !input.isValid() ) { osgGIS::notify( osg::WARN ) << "Spatial reference or input point is invalid" << std::endl; return false; } OGR_SpatialReference* input_sr = (OGR_SpatialReference*)input.getSRS(); if ( !input_sr ) { osgGIS::notify( osg::WARN ) << "SpatialReference: input point has no SRS" << std::endl; return false; } // first check whether the input point is geocentric - and if so, pre-convert it to geographic: if ( input_sr->isGeocentric() ) { input.set( input * input_sr->getInverseReferenceFrame() ); osg::Vec3d temp = input_sr->getEllipsoid().geocentricToLatLong( input ); input = GeoPoint( temp, input_sr->getGeographicSRS() ); input_sr = static_cast<OGR_SpatialReference*>( input.getSRS() ); } osg::Vec3d input_vec = input; bool crs_equiv = false; bool mat_equiv = false; testEquivalence( input_sr, /*out*/crs_equiv, /*out*/mat_equiv ); // pull it out of its source frame: if ( !mat_equiv ) { input.set( input * input_sr->inv_ref_frame ); } bool result = false; if ( !crs_equiv ) { OGR_SCOPE_LOCK(); //TODO: some kind of per-thread cache void* xform_handle = OCTNewCoordinateTransformation( input_sr->handle, this->handle ); if ( !xform_handle ) { osgGIS::notify( osg::WARN ) << "Spatial Reference: SRS xform not possible" << std::endl << " From => " << input_sr->getWKT() << std::endl << " To => " << this->getWKT() << std::endl; return false; } //TODO: figure out why xforming GEOCS x=-180 to another GEOCS doesn't work if ( OCTTransform( xform_handle, 1, &input.x(), &input.y(), &input.z() ) ) { result = true; } else { osgGIS::notify( osg::WARN ) << "Spatial Reference: Failed to xform a point from " << input_sr->getName() << " to " << this->getName() << std::endl; } OCTDestroyCoordinateTransformation( xform_handle ); } else { result = true; } // put it into the new ref frame: if ( !mat_equiv ) { input.set( input * ref_frame ); } if ( result == true ) { applyTo( input ); } return result; }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, double& out_elevation, double desiredResolution, double* out_actualResolution) { osg::Timer_t start = osg::Timer::instance()->tick(); if ( _mapf.elevationLayers().empty() ) { // this means there are no heightfields. out_elevation = 0.0; return true; } // tile size (resolution of elevation tiles) unsigned tileSize = std::max(_mapf.getMapOptions().elevationTileSize().get(), 2u); //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << LC << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isHorizEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } bool result = false; while (!result) { GeoHeightField geoHF; TileCache::Record record; // Try to get the hf from the cache if ( _cache.get( key, record ) ) { geoHF = record.value(); } else { // Create it osg::ref_ptr<osg::HeightField> hf = new osg::HeightField(); hf->allocate( tileSize, tileSize ); // Initialize the heightfield to nodata for (unsigned int i = 0; i < hf->getFloatArray()->size(); i++) { hf->getFloatArray()->at( i ) = NO_DATA_VALUE; } if (_mapf.populateHeightField( hf, key ) ) { geoHF = GeoHeightField( hf.get(), key.getExtent() ); _cache.insert( key, geoHF ); } } if (geoHF.valid()) { float elevation = 0.0f; result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation); if (result && elevation != NO_DATA_VALUE) { // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = geoHF.getXInterval(); out_elevation = (double)elevation; break; } else { result = false; } } if (!result) { key = key.createParentKey(); if (!key.valid()) { break; } } } osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( start, end ); return result; }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */ double& out_elevation, double desiredResolution, double* out_actualResolution) { // assertion. if ( !point.isAbsolute() ) { OE_WARN << LC << "Assertion failure; input must be absolute" << std::endl; return false; } osg::Timer_t begin = osg::Timer::instance()->tick(); // first try the terrain patches. if ( _patchLayers.size() > 0 ) { osgUtil::IntersectionVisitor iv; for(std::vector<ModelLayer*>::iterator i = _patchLayers.begin(); i != _patchLayers.end(); ++i) { // find the scene graph for this layer: osg::Node* node = (*i)->getSceneGraph( _mapf.getUID() ); if ( node ) { // configure for intersection: osg::Vec3d surface; point.toWorld( surface ); // trivial bounds check: if ( node->getBound().contains(surface) ) { osg::Vec3d nvector; point.createWorldUpVector(nvector); osg::Vec3d start( surface + nvector*5e5 ); osg::Vec3d end ( surface - nvector*5e5 ); // first time through, set up the intersector on demand if ( !_patchLayersLSI.valid() ) { _patchLayersLSI = new DPLineSegmentIntersector(start, end); _patchLayersLSI->setIntersectionLimit( _patchLayersLSI->LIMIT_NEAREST ); } else { _patchLayersLSI->reset(); _patchLayersLSI->setStart( start ); _patchLayersLSI->setEnd ( end ); } // try it. iv.setIntersector( _patchLayersLSI.get() ); node->accept( iv ); // check for a result!! if ( _patchLayersLSI->containsIntersections() ) { osg::Vec3d isect = _patchLayersLSI->getIntersections().begin()->getWorldIntersectPoint(); // transform back to input SRS: GeoPoint output; output.fromWorld( point.getSRS(), isect ); out_elevation = output.z(); if ( out_actualResolution ) *out_actualResolution = 0.0; return true; } } else { //OE_INFO << LC << "Trivial rejection (bounds check)" << std::endl; } } } } if ( _mapf.elevationLayers().empty() ) { // this means there are no heightfields. out_elevation = 0.0; return true; } // tile size (resolution of elevation tiles) unsigned tileSize = std::max(_mapf.getMapOptions().elevationTileSize().get(), 2u); //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << LC << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isHorizEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } bool result = false; while (!result) { GeoHeightField geoHF; TileCache::Record record; // Try to get the hf from the cache if ( _cache.get( key, record ) ) { geoHF = record.value(); } else { // Create it osg::ref_ptr<osg::HeightField> hf = new osg::HeightField(); hf->allocate( tileSize, tileSize ); // Initialize the heightfield to nodata for (unsigned int i = 0; i < hf->getFloatArray()->size(); i++) { hf->getFloatArray()->at( i ) = NO_DATA_VALUE; } if (_mapf.populateHeightField(hf, key, false)) { geoHF = GeoHeightField( hf.get(), key.getExtent() ); _cache.insert( key, geoHF ); } } if (geoHF.valid()) { float elevation = 0.0f; result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation); if (result && elevation != NO_DATA_VALUE) { // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = geoHF.getXInterval(); out_elevation = (double)elevation; break; } else { result = false; } } if (!result) { key = key.createParentKey(); if (!key.valid()) { break; } } } osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( begin, end ); return result; }