void SetInvalid() { vec.SetInvalid(); start.SetInvalid(); }
void PolyhedralLineOfSightNode::updateSamples() { if ( _geode->getNumDrawables() == 0 ) rebuildGeometry(); osg::Geometry* geom = _geode->getDrawable(0)->asGeometry(); osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() ); double distance = _distance.as(Units::METERS); // get the world coords and a l2w transform for the origin: osg::Vec3d originWorld; osg::Matrix local2world, world2local; Terrain* t = getMapNode()->getTerrain(); GeoPoint origin = getPosition(); origin.makeAbsolute( t ); origin.toWorld( originWorld, t ); origin.createLocalToWorld( local2world ); world2local.invert( local2world ); // set up an intersector: osgUtil::LineSegmentIntersector* lsi = new osgUtil::LineSegmentIntersector( originWorld, originWorld ); osgUtil::IntersectionVisitor iv( lsi ); // intersect the verts (skip the origin point) with the map node. for( osg::Vec3Array::iterator v = verts->begin()+1; v != verts->end(); ++v ) { osg::Vec3d unit = *v; unit.normalize(); unit *= distance; osg::Vec3d world = unit * local2world; if ( osg::equivalent(unit.length(), 0.0) ) { OE_WARN << "problem." << std::endl; } lsi->reset(); lsi->setStart( originWorld ); lsi->setEnd( world ); OE_DEBUG << LC << "Ray: " << originWorld.x() << "," << originWorld.y() << "," << originWorld.z() << " => " << world.x() << "," << world.y() << "," << world.z() << std::endl; getMapNode()->getTerrain()->accept( iv ); osgUtil::LineSegmentIntersector::Intersections& hits = lsi->getIntersections(); if ( !hits.empty() ) { const osgUtil::LineSegmentIntersector::Intersection& hit = *hits.begin(); osg::Vec3d newV = hit.getWorldIntersectPoint() * world2local; if ( newV.length() > 1.0 ) *v = newV; else *v = unit; } else { *v = unit; } //OE_NOTICE << "Radial point = " << v->x() << ", " << v->y() << ", " << v->z() << std::endl; } verts->dirty(); geom->dirtyBound(); }
std::string GeodeticGraticule::getText(const GeoPoint& location, bool lat) { double value = lat ? location.y() : location.x(); return _formatter->format(value, lat); }
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 ); }
void TerrainProfileGraph::drawHoverCursor(const QPointF& position) { if (_hoverLine) { _scene->removeItem(_hoverLine); delete _hoverLine; _hoverLine = 0L; } if (_graphField.width() < 2 || _graphField.height() < 2) return; double xPos = position.x() < _graphField.x() ? _graphField.x() : (position.x() > _graphField.x() + _graphField.width() ? _graphField.x() + _graphField.width() : position.x()); QLineF vLine(xPos, _graphField.y(), xPos, _graphField.y() + _graphField.height()); QPointF* intersect = new QPointF; bool foundIntersect = false; for (int i=0; i < _graphLines.count(); i++) { if (vLine.intersect(_graphLines[i], intersect) == QLineF::BoundedIntersection) { foundIntersect = true; break; } } if (foundIntersect) { // Draw the upper line segment. Also serves as the parent item. _hoverLine = new QGraphicsLineItem(xPos, _graphField.y(), xPos, intersect->y() - 3); _hoverLine->setPen(_hoverPen); _hoverLine->setZValue(OVERLAY_Z); _scene->addItem(_hoverLine); // Draw the box around the intersect point QGraphicsRectItem* hoverBox = new QGraphicsRectItem(xPos - 3, intersect->y() - 3, 6, 6); hoverBox->setPen(_hoverPen); hoverBox->setBrush(Qt::NoBrush); hoverBox->setZValue(OVERLAY_Z); hoverBox->setParentItem(_hoverLine); // Draw the lower line segment QGraphicsLineItem* lowerLine = new QGraphicsLineItem(xPos, intersect->y() + 3, xPos, _graphField.y() + _graphField.height() + 5); lowerLine->setPen(_hoverPen); lowerLine->setZValue(OVERLAY_Z); lowerLine->setParentItem(_hoverLine); // Draw the text and background double y = (1.0 - ((intersect->y() - _graphField.y()) / _graphField.height())) * (_graphMaxY - _graphMinY) + _graphMinY; int textOffset = 10; QGraphicsSimpleTextItem* hoverText = new QGraphicsSimpleTextItem(QString::number(y) + tr("m")); hoverText->setBrush(QBrush(_axesColor)); hoverText->setFont(_graphFont); hoverText->setZValue(OVERLAY_Z); if (intersect->x() + textOffset + hoverText->boundingRect().width() < _graphField.x() + _graphField.width()) hoverText->setPos(intersect->x() + textOffset, intersect->y() - hoverText->boundingRect().height()); else hoverText->setPos(intersect->x() - textOffset - hoverText->boundingRect().width(), intersect->y() - hoverText->boundingRect().height()); QGraphicsRectItem* hoverTextBackground = new QGraphicsRectItem(hoverText->x() - 3, hoverText->y() - 1, hoverText->boundingRect().width() + 6, hoverText->boundingRect().height() + 1); hoverTextBackground->setPen(_axesPen); hoverTextBackground->setBrush(QBrush(_graphColor)); hoverTextBackground->setZValue(OVERLAY_Z); hoverTextBackground->setParentItem(_hoverLine); hoverText->setParentItem(_hoverLine); // Update callback if (_positionCallback.valid()) { double distanceFactor = ((xPos - _graphField.x()) / (double)_graphField.width()); osg::Vec3d worldStart, worldEnd; _calculator->getStart(ALTMODE_ABSOLUTE).toWorld(worldStart); _calculator->getEnd(ALTMODE_ABSOLUTE).toWorld(worldEnd); double worldX = (worldEnd.x() - worldStart.x()) * distanceFactor + worldStart.x(); double worldY = (worldEnd.y() - worldStart.y()) * distanceFactor + worldStart.y(); double worldZ = (worldEnd.z() - worldStart.z()) * distanceFactor + worldStart.z(); GeoPoint mapPos; mapPos.fromWorld(_calculator->getStart().getSRS(), osg::Vec3d(worldX, worldY, worldZ)); _positionCallback->updatePosition(mapPos.y(), mapPos.x(), hoverText->text().toStdString()); } } else { // No intersect found so just draw the full line at xPos _hoverLine = new QGraphicsLineItem(xPos, _graphField.y(), xPos, _graphField.y() + _graphField.height() + 5); _hoverLine->setPen(_hoverPen); _hoverLine->setZValue(OVERLAY_Z); _scene->addItem(_hoverLine); } // Draw distance text double x = ((xPos - _graphField.x()) / _graphField.width()) * _totalDistance; BoxedSimpleTextItem* distanceText = new BoxedSimpleTextItem(QString::number(x / 1000.0, 'f', 2) + tr("km"), _backgroundColor); distanceText->setBrush(QBrush(_axesColor)); distanceText->setFont(_graphFont); distanceText->setZValue(OVERLAY_Z); if(xPos - 2 - distanceText->boundingRect().width() > _graphField.x()) { distanceText->setPos(xPos - 2 - distanceText->boundingRect().width(), _graphField.y() + _graphField.height() + 2); } else { distanceText->setPos(xPos + 2, _graphField.y() + _graphField.height() + 2); } distanceText->setParentItem(_hoverLine); // Draw selection box drawSelectionBox(xPos); delete intersect; }
int Ardb::GeoSearch(const DBID& db, const Slice& key, const GeoSearchOptions& options, ValueDataDeque& results) { uint64 start_time = get_current_epoch_micros(); GeoHashBitsSet ress; double x = options.x, y = options.y; if (options.coord_type == GEO_WGS84_TYPE) { x = GeoHashHelper::GetMercatorX(options.x); y = GeoHashHelper::GetMercatorY(options.y); } if (options.by_member) { ValueData score, attr; int err = ZGetNodeValue(db, key, options.member, score, attr); if (0 != err) { return err; } Buffer attr_content(const_cast<char*>(attr.bytes_value.data()), 0, attr.bytes_value.size()); GeoPoint point; point.Decode(attr_content); x = point.x; y = point.y; } ZSetCacheElementSet subset; if (options.in_members) { StringSet::const_iterator sit = options.submembers.begin(); while (sit != options.submembers.end()) { ZSetCaheElement ele; ValueData score, attr; if (0 == ZGetNodeValue(db, key, *sit, score, attr)) { ele.score = score.NumberValue(); Buffer buf1, buf2; ValueData vv; vv.SetValue(*sit, true); vv.Encode(buf1); attr.Encode(buf2); ele.value.assign(buf1.GetRawReadBuffer(), buf1.ReadableBytes()); ele.attr.assign(buf2.GetRawReadBuffer(), buf2.ReadableBytes()); subset.insert(ele); } sit++; } } GeoHashHelper::GetAreasByRadius(GEO_MERCATOR_TYPE, y, x, options.radius, ress); /* * Merge areas if possible to avoid disk search */ std::vector<ZRangeSpec> range_array; GeoHashBitsSet::iterator rit = ress.begin(); GeoHashBitsSet::iterator next_it = ress.begin(); next_it++; while (rit != ress.end()) { GeoHashBits& hash = *rit; GeoHashBits next = hash; next.bits++; while (next_it != ress.end() && next.bits == next_it->bits) { next.bits++; next_it++; rit++; } ZRangeSpec range; range.contain_min = true; range.contain_max = false; range.min.SetIntValue(GeoHashHelper::Allign52Bits(hash)); range.max.SetIntValue(GeoHashHelper::Allign52Bits(next)); range_array.push_back(range); rit++; next_it++; } DEBUG_LOG("After areas merging, reduce searching area size from %u to %u", ress.size(), range_array.size()); GeoPointArray points; std::vector<ZRangeSpec>::iterator hit = range_array.begin(); Iterator* iter = NULL; while (hit != range_array.end()) { ZSetQueryOptions z_options; z_options.withscores = false; z_options.withattr = true; ValueDataArray values; if (options.in_members) { ZSetCache::GetRangeInZSetCache(subset, *hit, z_options.withscores, z_options.withattr, ZSetValueStoreCallback, &values); } else { ZRangeByScoreRange(db, key, *hit, iter, z_options, true, ZSetValueStoreCallback, &values); } ValueDataArray::iterator vit = values.begin(); while (vit != values.end()) { GeoPoint point; vit->ToString(point.value); //attributes vit++; Buffer content(const_cast<char*>(vit->bytes_value.data()), 0, vit->bytes_value.size()); if (point.Decode(content)) { if (GeoHashHelper::GetDistanceSquareIfInRadius(GEO_MERCATOR_TYPE, x, y, point.x, point.y, options.radius, point.distance)) { /* * filter by exclude/include */ if (!options.includes.empty() || !options.excludes.empty()) { ValueData subst; subst.SetValue(point.value, false); bool matched = options.includes.empty() ? true : false; if (!options.includes.empty()) { StringStringMap::const_iterator sit = options.includes.begin(); while (sit != options.includes.end()) { ValueData mv; if (0 != MatchValueByPattern(db, sit->first, sit->second, subst, mv)) { matched = false; break; } else { matched = true; } sit++; } } if (matched && !options.excludes.empty()) { StringStringMap::const_iterator sit = options.excludes.begin(); while (sit != options.excludes.end()) { ValueData mv; if (0 == MatchValueByPattern(db, sit->first, sit->second, subst, mv)) { matched = false; break; } else { matched = true; } sit++; } } if (matched) { points.push_back(point); } } else { points.push_back(point); } } else { //DEBUG_LOG("%s is not in radius:%.2fm", point.value.c_str(), options.radius); } } else { WARN_LOG("Failed to decode geo point."); } vit++; } hit++; } DELETE(iter); if (!options.nosort) { std::sort(points.begin(), points.end(), options.asc ? less_by_distance : great_by_distance); } if (options.offset > 0) { if ((uint32) options.offset > points.size()) { points.clear(); } else { GeoPointArray::iterator start = points.begin() + options.offset; points.erase(points.begin(), start); } } if (options.limit > 0) { if ((uint32) options.limit < points.size()) { GeoPointArray::iterator end = points.begin() + options.limit; points.erase(end, points.end()); } } GeoPointArray::iterator pit = points.begin(); while (pit != points.end()) { ValueData v; v.SetValue(pit->value, false); results.push_back(v); GeoGetOptionDeque::const_iterator ait = options.get_patterns.begin(); while (ait != options.get_patterns.end()) { ValueData attr; if (ait->get_distances) { attr.SetDoubleValue(sqrt(pit->distance)); results.push_back(attr); } else if (ait->get_coodinates) { if (options.coord_type == GEO_WGS84_TYPE) { pit->x = GeoHashHelper::GetWGS84X(pit->x); pit->y = GeoHashHelper::GetWGS84Y(pit->y); } attr.SetDoubleValue(pit->x); results.push_back(attr); attr.SetDoubleValue(pit->y); results.push_back(attr); } else if (ait->get_attr) { StringStringMap::iterator found = pit->attrs.find(ait->get_pattern); if (found != pit->attrs.end()) { attr.SetValue(found->second, false); } results.push_back(attr); } else { GetValueByPattern(db, ait->get_pattern, v, attr); results.push_back(attr); } ait++; } pit++; } uint64 end_time = get_current_epoch_micros(); DEBUG_LOG("Cost %llu microseconds to search.", end_time - start_time); return 0; }
void RadialLineOfSightNode::compute_fill(osg::Node* node, bool backgroundThread) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 2); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 2 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { //Get the current hit DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d currEnd = los->getEnd(); bool currHasLOS = hits.empty(); osg::Vec3d currHit = currHasLOS ? osg::Vec3d() : hits.begin()->getWorldIntersectPoint(); //Get the next hit unsigned int nextIndex = i + 1; if (nextIndex == _numSpokes) nextIndex = 0; DPLineSegmentIntersector* losNext = static_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[nextIndex].get()); DPLineSegmentIntersector::Intersections& hitsNext = losNext->getIntersections(); osg::Vec3d nextEnd = losNext->getEnd(); bool nextHasLOS = hitsNext.empty(); osg::Vec3d nextHit = nextHasLOS ? osg::Vec3d() : hitsNext.begin()->getWorldIntersectPoint(); if (currHasLOS && nextHasLOS) { //Both rays have LOS verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); } else if (!currHasLOS && !nextHasLOS) { //Both rays do NOT have LOS //Draw the "good triangle" verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the two bad triangles verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (!currHasLOS && nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (currHasLOS && !nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } } geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); if (!backgroundThread) { //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); } else { _pendingNode = mt; } for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
PyObject* xcsoar_Airspaces_addPolygon(Pyxcsoar_Airspaces *self, PyObject *args) { PyObject *py_points = nullptr, *py_name = nullptr, *py_as_class = nullptr, *py_base_ref = nullptr, *py_top_ref = nullptr; double base_alt, top_alt; if (!PyArg_ParseTuple(args, "OOOdOdO", &py_points, &py_name, &py_as_class, &base_alt, &py_base_ref, &top_alt, &py_top_ref)) { return nullptr; } /* Parse points */ std::vector<GeoPoint> points; if (!PySequence_Check(py_points)) { PyErr_SetString(PyExc_ValueError, "First argument is no sequence"); return nullptr; } Py_ssize_t num_items = PySequence_Fast_GET_SIZE(py_points); for (Py_ssize_t i = 0; i < num_items; ++i) { PyObject *py_location = PySequence_Fast_GET_ITEM(py_points, i); GeoPoint location = Python::ReadLonLat(py_location); if (!location.IsValid()) { if (PyErr_Occurred() == nullptr) PyErr_SetString(PyExc_RuntimeError, "Unknown error while parsing location"); return nullptr; } points.push_back(location); } if (points.size() < 3) { PyErr_SetString(PyExc_ValueError, "Polygon has not enough points"); return nullptr; } /* Parse airspace name */ tstring name; if (!Python::PyStringToString(py_name, name)) { PyErr_SetString(PyExc_ValueError, "Can't parse airspace name."); return nullptr; } /* Parse airspace class */ tstring as_class; AirspaceClass type = AirspaceClass::OTHER; if (!Python::PyStringToString(py_as_class, as_class)) { PyErr_SetString(PyExc_ValueError, "Can't parse airspace class."); return nullptr; } for (unsigned i = 0; i < ARRAY_SIZE(airspace_class_strings); i++) { if (as_class.compare(airspace_class_strings[i].string) == 0) type = airspace_class_strings[i].type; } /* Parse airspace base and top */ tstring base_ref, top_ref; AirspaceAltitude base, top; if (!Python::PyStringToString(py_base_ref, base_ref)) { PyErr_SetString(PyExc_ValueError, "Can't parse airspace base reference."); return nullptr; } if (!Python::PyStringToString(py_top_ref, top_ref)) { PyErr_SetString(PyExc_ValueError, "Can't parse airspace top reference."); return nullptr; } if (base_ref.compare("MSL") == 0) { base.reference = AltitudeReference::MSL; base.altitude = base_alt; } else if (base_ref.compare("FL") == 0) { base.reference = AltitudeReference::STD; base.flight_level = base_alt; } else if (base_ref.compare("AGL") == 0) { base.reference = AltitudeReference::AGL; base.altitude_above_terrain = base_alt; } else { PyErr_SetString(PyExc_ValueError, "Can't parse airspace base."); return nullptr; } if (top_ref.compare("MSL") == 0) { top.reference = AltitudeReference::MSL; top.altitude = top_alt; } else if (top_ref.compare("FL") == 0) { top.reference = AltitudeReference::STD; top.flight_level = top_alt; } else if (top_ref.compare("AGL") == 0) { top.reference = AltitudeReference::AGL; top.altitude_above_terrain = top_alt; } else { PyErr_SetString(PyExc_ValueError, "Can't parse airspace top."); return nullptr; } /* Create airspace and save it into the database */ AbstractAirspace *as = new AirspacePolygon(points); as->SetProperties(std::move(name), type, base, top); self->airspace_database->Add(as); Py_RETURN_NONE; }
GeoVector::GeoVector(const GeoPoint &source, const GeoPoint &target) { *this = source.DistanceBearing(target); }
bool AirspaceCircle::Inside(const GeoPoint &loc) const { return (loc.Distance(m_center) <= m_radius); }
osg::Geometry* GeometryPool::createGeometry(const TileKey& tileKey, const MapInfo& mapInfo, MaskGenerator* maskSet) const { // Establish a local reference frame for the tile: osg::Vec3d centerWorld; GeoPoint centroid; tileKey.getExtent().getCentroid( centroid ); centroid.toWorld( centerWorld ); osg::Matrix world2local, local2world; centroid.createWorldToLocal( world2local ); local2world.invert( world2local ); // Attempt to calculate the number of verts in the surface geometry. bool createSkirt = _options.heightFieldSkirtRatio() > 0.0f; unsigned numVertsInSurface = (_tileSize*_tileSize); unsigned numVertsInSkirt = createSkirt ? _tileSize*4u - 4u : 0; unsigned numVerts = numVertsInSurface + numVertsInSkirt; unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6; unsigned numIncidesInSkirt = getNumSkirtElements(); // TODO: reconsider this ... GLenum mode = (_options.gpuTessellation() == true) ? GL_PATCHES : GL_TRIANGLES; // Pre-allocate enough space for all triangles. osg::DrawElements* primSet = new osg::DrawElementsUShort(mode); primSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt); osg::BoundingSphere tileBound; // the geometry: osg::Geometry* geom = new osg::Geometry(); geom->setUseVertexBufferObjects(true); geom->setUseDisplayList(false); geom->addPrimitiveSet( primSet ); // the vertex locations: osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve( numVerts ); geom->setVertexArray( verts ); // the surface normals (i.e. extrusion vectors) osg::Vec3Array* normals = new osg::Vec3Array(); normals->reserve( numVerts ); geom->setNormalArray( normals ); geom->setNormalBinding( geom->BIND_PER_VERTEX ); #if 0 // colors osg::Vec4Array* colors = new osg::Vec4Array(); colors->push_back(osg::Vec4f(1,1,1,1)); geom->setColorArray(colors); geom->setColorBinding(osg::Geometry::BIND_OVERALL); #endif osg::Vec3Array* neighbors = 0L; if ( _options.morphTerrain() == true ) { // neighbor positions (for morphing) neighbors = new osg::Vec3Array(); neighbors->reserve( numVerts ); geom->setTexCoordArray( 1, neighbors ); } // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the // vert is masked: 0=yes, 1=no #ifdef SHARE_TEX_COORDS bool populateTexCoords = false; if ( !_sharedTexCoords.valid() ) { _sharedTexCoords = new osg::Vec3Array(); _sharedTexCoords->reserve( numVerts ); populateTexCoords = true; } osg::Vec3Array* texCoords = _sharedTexCoords.get(); #else bool populateTexCoords = true; osg::Vec3Array* texCoords = new osg::Vec3Array(); texCoords->reserve( numVerts ); #endif geom->setTexCoordArray( 0, texCoords ); float delta = 1.0/(_tileSize-1); osg::Vec3d tdelta(delta,0,0); tdelta.normalize(); osg::Vec3d vZero(0,0,0); osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( tileKey, mapInfo ); for(unsigned row=0; row<_tileSize; ++row) { float ny = (float)row/(float)(_tileSize-1); for(unsigned col=0; col<_tileSize; ++col) { float nx = (float)col/(float)(_tileSize-1); osg::Vec3d model; locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model); osg::Vec3d modelLTP = model*world2local; verts->push_back( modelLTP ); tileBound.expandBy( verts->back() ); if ( populateTexCoords ) { // if masked then set textCoord z-value to 0.0 float marker = maskSet ? maskSet->getMarker(nx, ny) : MASK_MARKER_NORMAL; texCoords->push_back( osg::Vec3f(nx, ny, marker) ); } osg::Vec3d modelPlusOne; locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne); osg::Vec3d normal = (modelPlusOne*world2local)-modelLTP; normal.normalize(); normals->push_back( normal ); // neighbor: if ( neighbors ) { osg::Vec3d modelNeighborLTP = (*verts)[verts->size() - getMorphNeighborIndexOffset(col, row, _tileSize)]; neighbors->push_back(modelNeighborLTP); } } } // Now tessellate the surface. // TODO: do we really need this?? bool swapOrientation = !locator->orientationOpenGL(); for(unsigned j=0; j<_tileSize-1; ++j) { for(unsigned i=0; i<_tileSize-1; ++i) { int i00; int i01; if (swapOrientation) { i01 = j*_tileSize + i; i00 = i01+_tileSize; } else { i00 = j*_tileSize + i; i01 = i00+_tileSize; } int i10 = i00+1; int i11 = i01+1; // skip any triangles that have a discarded vertex: bool discard = maskSet && ( maskSet->isMasked( (*texCoords)[i00] ) || maskSet->isMasked( (*texCoords)[i11] ) ); if ( !discard ) { discard = maskSet && maskSet->isMasked( (*texCoords)[i01] ); if ( !discard ) { primSet->addElement(i01); primSet->addElement(i00); primSet->addElement(i11); } discard = maskSet && maskSet->isMasked( (*texCoords)[i10] ); if ( !discard ) { primSet->addElement(i00); primSet->addElement(i10); primSet->addElement(i11); } } } } if ( createSkirt ) { // SKIRTS: // calculate the skirt extrusion height double height = tileBound.radius() * _options.heightFieldSkirtRatio().get(); unsigned skirtIndex = verts->size(); // first, create all the skirt verts, normals, and texcoords. for(int c=0; c<(int)_tileSize-1; ++c) addSkirtDataForIndex( c, height ); //top for(int r=0; r<(int)_tileSize-1; ++r) addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right for(int c=_tileSize-1; c>=0; --c) addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom for(int r=_tileSize-1; r>=0; --r) addSkirtDataForIndex( r*_tileSize, height ); //left // then create the elements indices: int i; for(i=skirtIndex; i<(int)verts->size()-2; i+=2) addSkirtTriangles( i, i+2 ); addSkirtTriangles( i, skirtIndex ); } // create mask geometry if (maskSet) { osg::ref_ptr<osg::DrawElementsUInt> maskPrim = maskSet->createMaskPrimitives(mapInfo, verts, texCoords, normals, neighbors); if (maskPrim) geom->addPrimitiveSet( maskPrim ); } return geom; }
bool LocalizedNode::updateTransforms( const GeoPoint& p, osg::Node* patch ) { if ( p.isValid() ) { GeoPoint absPos(p); if ( !makeAbsolute(absPos, patch) ) return false; OE_DEBUG << LC << "Update transforms for position: " << absPos.x() << ", " << absPos.y() << ", " << absPos.z() << std::endl; osg::Matrixd local2world; absPos.createLocalToWorld( local2world ); // apply the local offsets local2world.preMult( osg::Matrix::translate(_localOffset) ); if ( _autoTransform ) { static_cast<osg::AutoTransform*>(_xform.get())->setPosition( local2world.getTrans() ); static_cast<osg::AutoTransform*>(_xform.get())->setScale( _scale ); static_cast<osg::AutoTransform*>(_xform.get())->setRotation( _localRotation ); } else { static_cast<osg::MatrixTransform*>(_xform.get())->setMatrix( osg::Matrix::scale(_scale) * osg::Matrix::rotate(_localRotation) * local2world ); } CullNodeByHorizon* culler = dynamic_cast<CullNodeByHorizon*>(_xform->getCullCallback()); if ( culler ) culler->_world = local2world.getTrans(); } else { osg::Vec3d absPos = p.vec3d() + _localOffset; if ( _autoTransform ) { static_cast<osg::AutoTransform*>(_xform.get())->setPosition( absPos ); static_cast<osg::AutoTransform*>(_xform.get())->setScale( _scale ); static_cast<osg::AutoTransform*>(_xform.get())->setRotation( _localRotation ); } else { static_cast<osg::MatrixTransform*>(_xform.get())->setMatrix( osg::Matrix::scale(_scale) * osg::Matrix::rotate(_localRotation) * osg::Matrix::translate(absPos) ); } } dirtyBound(); return true; }
bool IsValid() const { return center.IsValid(); }
msr::airlib::MultirotorState to() const { return msr::airlib::MultirotorState(collision.to(), kinematics_estimated.to(), gps_location.to(), timestamp, landed_state, rc_data.to()); }
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 ( _patchLayers.size() > 0 ) { osgUtil::IntersectionVisitor iv; if ( _ivrc.valid() ) iv.setReadCallback(_ivrc.get()); 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 = (float)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 = 257; // yes? // default LOD: unsigned lod = 23u; // attempt to map the requested resolution to an LOD: if (desiredResolution > 0.0) { int level = _mapf.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 = _mapf.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; }
GeoPoint GeoVector::IntermediatePoint(const GeoPoint &source, const fixed distance) const { return source.IntermediatePoint(EndPoint(source), distance); }
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 = _tileCache.get( key ); if ( record.valid() ) 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; }
void RasterMap::ScanLine(const GeoPoint &start, const GeoPoint &end, short *buffer, unsigned size, bool interpolate) const { assert(buffer != NULL); assert(size > 0); const short invalid = RasterBuffer::TERRAIN_INVALID; const fixed total_distance = start.DistanceS(end); if (!positive(total_distance)) { std::fill_n(buffer, size, invalid); return; } /* clip the line to the map bounds */ GeoPoint clipped_start = start, clipped_end = end; const GeoClip clip(GetBounds()); if (!clip.ClipLine(clipped_start, clipped_end)) { std::fill_n(buffer, size, invalid); return; } fixed clipped_start_distance = std::max(clipped_start.DistanceS(start), fixed(0)); fixed clipped_end_distance = std::max(clipped_end.DistanceS(start), fixed(0)); /* calculate the offsets of the clipped range within the buffer */ unsigned clipped_start_offset = (unsigned)(size * clipped_start_distance / total_distance); unsigned clipped_end_offset = uround(size * clipped_end_distance / total_distance); if (clipped_end_offset > size) clipped_end_offset = size; if (clipped_start_offset + 2 > clipped_end_offset) { std::fill_n(buffer, size, invalid); return; } assert(clipped_start_offset < size); assert(clipped_end_offset <= size); /* fill the two regions which are outside the map */ std::fill(buffer, buffer + clipped_start_offset, invalid); std::fill(buffer + clipped_end_offset, buffer + size, invalid); /* now scan the middle part which is within the map */ const unsigned max_x = raster_tile_cache.GetFineWidth(); const unsigned max_y = raster_tile_cache.GetFineHeight(); RasterLocation raster_start = projection.ProjectFine(clipped_start); if (raster_start.x >= max_x) raster_start.x = max_x - 1; if (raster_start.y >= max_y) raster_start.y = max_y - 1; RasterLocation raster_end = projection.ProjectFine(clipped_end); if (raster_end.x >= max_x) raster_end.x = max_x - 1; if (raster_end.y >= max_y) raster_end.y = max_y - 1; raster_tile_cache.ScanLine(raster_start, raster_end, buffer + clipped_start_offset, clipped_end_offset - clipped_start_offset, interpolate); }
void RadialLineOfSightNode::compute_line(osg::Node* node, bool backgroundThread) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 5); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 5 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::Vec3d previousEnd; osg::Vec3d firstEnd; osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d start = los->getStart(); osg::Vec3d end = los->getEnd(); osg::Vec3d hit; bool hasLOS = hits.empty(); if (!hasLOS) { hit = hits.begin()->getWorldIntersectPoint(); } if (hasLOS) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); } else { if (_displayMode == LineOfSight::MODE_SPLIT) { verts->push_back( start - _centerWorld ); verts->push_back( hit - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); verts->push_back( hit - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } else if (_displayMode == LineOfSight::MODE_SINGLE) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } } if (i > 0) { verts->push_back( end - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( _outlineColor ); colors->push_back( _outlineColor ); } else { firstEnd = end; } previousEnd = end; } //Add the last outside of circle verts->push_back( firstEnd - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( osg::Vec4(1,1,1,1)); colors->push_back( osg::Vec4(1,1,1,1)); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); if (!backgroundThread) { //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); } else { _pendingNode = mt; } for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
bool OLCTriangle::FindClosingPairs(unsigned old_size) { if (predict) { return closing_pairs.insert(ClosingPair(0, n_points-1)); } struct TracePointNodeAccessor { gcc_pure int GetX(const TracePointNode &node) const { return node.point->GetFlatLocation().longitude; } gcc_pure int GetY(const TracePointNode &node) const { return node.point->GetFlatLocation().latitude; } }; QuadTree<TracePointNode, TracePointNodeAccessor> search_point_tree; for (unsigned i = old_size; i < n_points; ++i) { TracePointNode node; node.point = &GetPoint(i); node.index = i; search_point_tree.insert(node); } search_point_tree.Optimise(); bool new_pair = false; for (unsigned i = old_size; i < n_points; ++i) { TracePointNode point; point.point = &GetPoint(i); point.index = i; const unsigned max_range = trace_master.ProjectRange(GetPoint(i).GetLocation(), max_distance); const GeoPoint start = GetPoint(i).GetLocation(); const int min_altitude = GetMinimumFinishAltitude(GetPoint(i)); const int max_altitude = GetMaximumStartAltitude(GetPoint(i)); unsigned last = 0, first = i; const auto visitor = [this, i, start, min_altitude, max_altitude, &first, &last] (const TracePointNode &node) { const SearchPoint dest = GetPoint(node.index); if (node.index + 2 < i && GetPoint(node.index).GetIntegerAltitude() <= max_altitude && start.Distance(dest.GetLocation()) <= max_distance) { // point i is last point first = std::min(node.index, first); last = i; } else if (node.index > i + 2 && GetPoint(node.index).GetIntegerAltitude() >= min_altitude && start.Distance(dest.GetLocation()) <= max_distance) { // point i is first point first = i; last = std::max(node.index, last); } }; search_point_tree.VisitWithinRange(point, max_range, visitor); if (last != 0 && closing_pairs.insert(ClosingPair(first, last))) new_pair = true; } return new_pair; }
void ModelSplatter::operator()(const TileKey& key, osg::Node* node) { TerrainTileNode* tile = osgEarth::findTopMostNodeOfType<TerrainTileNode>(node); if ( !tile ) return; if ( key.getLOD() >= _minLOD && _model.valid() ) { // make sure the correct model is loaded establish(); // elevation texture and matrix are required osg::Texture* elevationTex = tile->getElevationTexture(); if ( !elevationTex ) { //OE_WARN << LC << "No elevation texture for key " << key.str() << "\n"; return; } osg::RefMatrix* elevationTexMat = tile->getElevationTextureMatrix(); if ( !elevationTexMat ) { //OE_WARN << LC << "No elevation texture matrix for key " << key.str() << "\n"; return; } tile->addChild( _model.get() ); osg::StateSet* ss = tile->getOrCreateStateSet(); // first, a rotation vector to make trees point up. GeoPoint p; key.getExtent().getCentroid(p); osg::Vec3d up; p.createWorldUpVector(up); osg::Quat q; q.makeRotate(osg::Vec3d(0,0,1), up); osg::Matrixd zup = osg::Matrixd::rotate(q); // matrices to resolve the weird terrain localization into a usable LTP. osg::Matrix tile2world = tile->getMatrix(); osg::Matrix world2ltp; p.createWorldToLocal(world2ltp); osg::Matrix local2ltp = tile2world * world2ltp; osg::Matrix ltp2local; ltp2local.invert(local2ltp); // after inverting the matrix, combine the ZUP (optimization) local2ltp.preMult( zup ); ss->addUniform( new osg::Uniform("oe_trees_local2ltp", osg::Matrixf(local2ltp)) ); ss->addUniform( new osg::Uniform("oe_trees_ltp2local", osg::Matrixf(ltp2local)) ); // calculate the scatter area: float h = key.getExtent().height() * 111320.0f; float w = key.getExtent().width() * 111320.0f * cos(fabs(osg::DegreesToRadians(p.y()))); ss->addUniform( new osg::Uniform("oe_trees_span", osg::Vec2f(w,h)) ); ss->setTextureAttributeAndModes(2, tile->getElevationTexture(), 1); ss->addUniform( new osg::Uniform("oe_terrain_tex_matrix", osg::Matrixf(*elevationTexMat)) ); } }
/** * distance from this to the reference */ fixed DistanceTo(const GeoPoint &ref) const { return reference.Distance(ref); }
void MapNode::traverse( osg::NodeVisitor& nv ) { if ( nv.getVisitorType() == nv.EVENT_VISITOR ) { unsigned int numBlacklist = Registry::instance()->getNumBlacklistedFilenames(); if (numBlacklist != _lastNumBlacklistedFilenames) { //Only remove the blacklisted filenames if new filenames have been added since last time. _lastNumBlacklistedFilenames = numBlacklist; RemoveBlacklistedFilenamesVisitor v; _terrainEngine->accept( v ); } // traverse: std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); } else if ( nv.getVisitorType() == nv.CULL_VISITOR ) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); if ( cv ) { // insert traversal data for this camera: osg::ref_ptr<osg::Referenced> oldUserData = cv->getUserData(); MapNodeCullData* cullData = getCullData( cv->getCurrentCamera() ); cv->setUserData( cullData ); cullData->_mapNode = this; // calculate altitude: osg::Vec3d eye = cv->getViewPoint(); const SpatialReference* srs = getMapSRS(); if ( srs && !srs->isProjected() ) { GeoPoint ecef; ecef.fromWorld( srs, eye ); cullData->_cameraAltitude = ecef.alt(); } else { cullData->_cameraAltitude = eye.z(); } // window scale matrix: osg::Matrix m4 = cv->getWindowMatrix(); osg::Matrix3 m3( m4(0,0), m4(1,0), m4(2,0), m4(0,1), m4(1,1), m4(2,1), m4(0,2), m4(1,2), m4(2,2) ); cullData->_windowScaleMatrixUniform->set( m3 ); // traverse: cv->pushStateSet( cullData->_stateSet.get() ); std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); cv->popStateSet(); // restore: cv->setUserData( oldUserData.get() ); } } else { osg::Group::traverse( nv ); } }
bool WaypointReaderSeeYou::ParseLine(const TCHAR* line, const unsigned linenum, Waypoints &waypoints) { TCHAR ctemp[4096]; const TCHAR *params[20]; static const unsigned int max_params = ARRAY_SIZE(params); size_t n_params; const unsigned iName = 0; const unsigned iLatitude = 3, iLongitude = 4, iElevation = 5; const unsigned iStyle = 6, iRWDir = 7, iRWLen = 8; const unsigned iFrequency = 9, iDescription = 10; static bool ignore_following; if (linenum == 0) ignore_following = false; // If (end-of-file or comment) if (line[0] == '\0' || line[0] == 0x1a || _tcsstr(line, _T("**")) == line || _tcsstr(line, _T("*")) == line) // -> return without error condition return true; if (_tcslen(line) >= ARRAY_SIZE(ctemp)) /* line too long for buffer */ return false; // Skip first line if it doesn't begin with a quotation character // (usually the field order line) if (linenum == 0 && line[0] != _T('\"')) return true; // If task marker is reached ignore all following lines if (_tcsstr(line, _T("-----Related Tasks-----")) == line) ignore_following = true; if (ignore_following) return true; // Get fields n_params = ExtractParameters(line, ctemp, params, max_params, true, _T('"')); // Check if the basic fields are provided if (iName >= n_params) return false; if (iLatitude >= n_params) return false; if (iLongitude >= n_params) return false; GeoPoint location; // Latitude (e.g. 5115.900N) if (!ParseAngle(params[iLatitude], location.latitude, true)) return false; // Longitude (e.g. 00715.900W) if (!ParseAngle(params[iLongitude], location.longitude, false)) return false; location.Normalize(); // ensure longitude is within -180:180 Waypoint new_waypoint(location); new_waypoint.file_num = file_num; new_waypoint.original_id = 0; // Name (e.g. "Some Turnpoint") if (*params[iName] == _T('\0')) return false; new_waypoint.name = params[iName]; // Elevation (e.g. 458.0m) /// @todo configurable behaviour if ((iElevation >= n_params || !ParseAltitude(params[iElevation], new_waypoint.elevation)) && !CheckAltitude(new_waypoint)) return false; // Style (e.g. 5) /// @todo include peaks with peak symbols etc. if (iStyle < n_params) ParseStyle(params[iStyle], new_waypoint); // Frequency & runway direction/length (for airports and landables) // and description (e.g. "Some Description") if (new_waypoint.IsLandable()) { if (iFrequency < n_params) new_waypoint.radio_frequency = RadioFrequency::Parse(params[iFrequency]); // Runway length (e.g. 546.0m) fixed rwlen = fixed_minus_one; if (iRWLen < n_params && ParseDistance(params[iRWLen], rwlen) && positive(rwlen)) new_waypoint.runway.SetLength(uround(rwlen)); if (iRWDir < n_params && *params[iRWDir]) { TCHAR *end; int direction =_tcstol(params[iRWDir], &end, 10); if (end == params[iRWDir] || direction < 0 || direction > 360 || (direction == 0 && !positive(rwlen))) direction = -1; else if (direction == 360) direction = 0; if (direction >= 0) new_waypoint.runway.SetDirectionDegrees(direction); } } if (iDescription < n_params) new_waypoint.comment = params[iDescription]; waypoints.Append(new_waypoint); return true; }
bool MapInfo::toMapPoint( const GeoPoint& input, GeoPoint& output ) const { return input.isValid() ? input.transform(_profile->getSRS(), output) : false; }
NearWaypoint(const Waypoint &_waypoint, const GeoPoint& _location) :waypoint(_waypoint), location(_location), leg_in(0), actual_in(0) { range = location.Distance(waypoint.location); }
void GeodeticGraticule::cull(osgUtil::CullVisitor* cv) { osg::Matrixd viewMatrix = *cv->getModelViewMatrix(); osg::Vec3d vp = cv->getViewPoint(); CameraData& cdata = getCameraData(cv->getCurrentCamera()); // Only update if the view matrix has changed. if (viewMatrix != cdata._lastViewMatrix && _mapNode.valid()) { GeoPoint eyeGeo; eyeGeo.fromWorld(_mapNode->getMapSRS(), vp); cdata._lon = eyeGeo.x(); cdata._lat = eyeGeo.y(); osg::Viewport* viewport = cv->getViewport(); float centerX = viewport->x() + viewport->width() / 2.0; float centerY = viewport->y() + viewport->height() / 2.0; float offsetCenterX = centerX; float offsetCenterY = centerY; bool hitValid = false; // Try the center of the screen. osg::Vec3d focalPoint; if (_mapNode->getTerrain()->getWorldCoordsUnderMouse(cv->getCurrentCamera()->getView(), centerX, centerY, focalPoint)) { hitValid = true; } if (hitValid) { GeoPoint focalGeo; focalGeo.fromWorld(_mapNode->getMapSRS(), focalPoint); cdata._lon = focalGeo.x(); cdata._lat = focalGeo.y(); // We only store the previous view matrix if we actually got a hit. Otherwise we still need to update. cdata._lastViewMatrix = viewMatrix; } // Get the view extent. cdata._viewExtent = getViewExtent(cv); double targetResolution = (cdata._viewExtent.height() / 180.0) / options().gridLines().get(); double resolution = _resolutions[0]; for (unsigned int i = 0; i < _resolutions.size(); i++) { resolution = _resolutions[i]; if (resolution <= targetResolution) { break; } } // Trippy //resolution = targetResolution; // Try to compute an approximate meters to pixel value at this view. double dist = osg::clampAbove(eyeGeo.z(), 1.0); double halfWidth; const osg::Matrix& proj = *cv->getProjectionMatrix(); bool isOrtho = osg::equivalent(proj(3,3), 1.0); if (isOrtho) { double L, R, B, T, N, F; proj.getOrtho(L, R, B, T, N, F); halfWidth = 0.5*(R-L); } else // perspective { double fovy, aspectRatio, zNear, zFar; cv->getProjectionMatrix()->getPerspective(fovy, aspectRatio, zNear, zFar); halfWidth = osg::absolute(tan(osg::DegreesToRadians(fovy / 2.0)) * dist); } cdata._metersPerPixel = (2.0 * halfWidth) / (double)viewport->height(); if (cdata._resolution != resolution) { cdata._resolution = (float)resolution; cdata._resolutionUniform->set(cdata._resolution); } OE_TEST << "EW=" << cdata._viewExtent.width() << ", ortho=" << isOrtho << ", hW=" << halfWidth << ", res=" << resolution << ", mPP=" << cdata._metersPerPixel << std::endl; } // traverse the label pool for this camera. cv->pushStateSet(cdata._labelStateset.get()); for (std::vector< osg::ref_ptr< LabelNode > >::iterator i = cdata._labelPool.begin(); i != cdata._labelPool.end(); ++i) { i->get()->accept(*cv); } cv->popStateSet(); }
NearWaypoint(const Waypoint &_waypoint, const GeoPoint& _location, const NearWaypoint& previous): waypoint(_waypoint), location(_location) { range = location.Distance(waypoint.location); update_leg(previous); }
static bool ReadCoords(const TCHAR *buffer, GeoPoint &point) { // Format: 53:20:41 N 010:24:41 E // Alternative Format: 53:20.68 N 010:24.68 E TCHAR *endptr; // ToDo, add more error checking and making it more tolerant/robust double deg = _tcstod(buffer, &endptr); if ((buffer == endptr) || (*endptr == '\0')) return false; if (*endptr == ':') { endptr++; double min = _tcstod(endptr, &endptr); if (*endptr == '\0') return false; deg += min / 60; if (*endptr == ':') { endptr++; double sec = _tcstod(endptr, &endptr); if (*endptr == '\0') return false; deg += sec / 3600; } } point.latitude = Angle::Degrees(deg); if (*endptr == ' ') endptr++; if (*endptr == '\0') return false; if ((*endptr == 'S') || (*endptr == 's')) point.latitude.Flip(); endptr++; if (*endptr == '\0') return false; deg = _tcstod(endptr, &endptr); if ((buffer == endptr) || (*endptr == '\0')) return false; if (*endptr == ':') { endptr++; double min = _tcstod(endptr, &endptr); if (*endptr == '\0') return false; deg += min / 60; if (*endptr == ':') { endptr++; double sec = _tcstod(endptr, &endptr); if (*endptr == '\0') return false; deg += sec / 3600; } } point.longitude = Angle::Degrees(deg); if (*endptr == ' ') endptr++; if (*endptr == '\0') return false; if ((*endptr == 'W') || (*endptr == 'w')) point.longitude.Flip(); point.Normalize(); // ensure longitude is within -180:180 return true; }
void MapNode::traverse( osg::NodeVisitor& nv ) { if ( nv.getVisitorType() == nv.EVENT_VISITOR ) { unsigned int numBlacklist = Registry::instance()->getNumBlacklistedFilenames(); if (numBlacklist != _lastNumBlacklistedFilenames) { //Only remove the blacklisted filenames if new filenames have been added since last time. _lastNumBlacklistedFilenames = numBlacklist; RemoveBlacklistedFilenamesVisitor v; _terrainEngine->accept( v ); } // traverse: std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); } else if ( nv.getVisitorType() == nv.UPDATE_VISITOR ) { osg::ref_ptr<osg::Referenced> oldUserData = nv.getUserData(); nv.setUserData( this ); std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); nv.setUserData( oldUserData.get() ); } else if ( nv.getVisitorType() == nv.CULL_VISITOR ) { osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv); if ( cv ) { #if 1 osg::ref_ptr<osg::Referenced> oldUserData = cv->getUserData(); TraversalData* data = new TraversalData(); cv->setUserData( data ); std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); cv->setUserData( oldUserData.get() ); #else // insert traversal data for this camera: osg::ref_ptr<osg::Referenced> oldUserData = cv->getUserData(); MapNodeCullData* cullData = getCullData( cv->getCurrentCamera() ); cv->setUserData( cullData ); cullData->_mapNode = this; osg::Vec3d eye = cv->getViewPoint(); // horizon: if ( !cullData->_horizonInitialized ) { cullData->_horizonInitialized = true; cullData->_horizon.setEllipsoid( *getMapSRS()->getEllipsoid() ); } cullData->_horizon.setEye( eye ); // calculate altitude: const SpatialReference* srs = getMapSRS(); if ( srs && !srs->isProjected() ) { GeoPoint lla; lla.fromWorld( srs, eye ); cullData->_cameraAltitude = lla.alt(); cullData->_cameraAltitudeUniform->set( (float)lla.alt() ); } else { cullData->_cameraAltitude = eye.z(); cullData->_cameraAltitudeUniform->set( (float)eye.z() ); } // window matrix: cullData->_windowMatrixUniform->set( cv->getWindowMatrix() ); // traverse: cv->pushStateSet( cullData->_stateSet.get() ); std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); cv->popStateSet(); // restore: cv->setUserData( oldUserData.get() ); #endif } } else { osg::Group::traverse( nv ); } }