1 // positioned.cxx - base class for objects which are positioned
3 // Copyright (C) 2008 James Turner
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "positioned.hxx"
29 #include <algorithm> // for sort
33 #include <boost/algorithm/string/case_conv.hpp>
34 #include <boost/algorithm/string/predicate.hpp>
36 #include <osg/Math> // for osg::isNaN
38 #include <simgear/timing/timestamp.hxx>
39 #include <simgear/debug/logstream.hxx>
40 #include <simgear/structure/exception.hxx>
41 #include <simgear/math/SGGeometry.hxx>
42 #include <simgear/sg_inlines.h>
44 #include "Navaids/PositionedOctree.hxx"
47 using namespace flightgear;
49 static void validateSGGeod(const SGGeod& geod)
51 if (osg::isNaN(geod.getLatitudeDeg()) ||
52 osg::isNaN(geod.getLongitudeDeg()))
54 throw sg_range_exception("position is invalid, NaNs");
59 ///////////////////////////////////////////////////////////////////////////////
61 FGPositioned::FGPositioned(PositionedID aGuid, Type ty, const std::string& aIdent, const SGGeod& aPos) :
64 mCart(SGVec3d::fromGeod(mPosition)),
70 FGPositioned::~FGPositioned()
72 // std::cout << "destroying:" << mIdent << "/" << nameForType(mType) << std::endl;
76 FGPositioned::createUserWaypoint(const std::string& aIdent, const SGGeod& aPos)
78 PositionedID id = NavDataCache::instance()->createUserWaypoint(aIdent, aPos);
79 return NavDataCache::instance()->loadById(id);
83 FGPositioned::cart() const
88 FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
90 if (aName.empty() || (aName == "")) {
99 const NameTypeEntry names[] = {
100 {"airport", AIRPORT},
112 {"tower", FREQ_TOWER},
113 {"ground", FREQ_GROUND},
114 {"approach", FREQ_APP_DEP},
115 {"departure", FREQ_APP_DEP},
117 {"gnd", FREQ_GROUND},
119 {"waypoint", WAYPOINT},
128 std::string lowerName(boost::to_lower_copy(aName));
130 for (const NameTypeEntry* n = names; (n->_name != NULL); ++n) {
131 if (::strcmp(n->_name, lowerName.c_str()) == 0) {
136 SG_LOG(SG_GENERAL, SG_WARN, "FGPositioned::typeFromName: couldn't match:" << aName);
140 const char* FGPositioned::nameForType(Type aTy)
143 case RUNWAY: return "runway";
144 case TAXIWAY: return "taxiway";
145 case PAVEMENT: return "pavement";
146 case PARKING: return "parking stand";
147 case FIX: return "fix";
148 case VOR: return "VOR";
149 case NDB: return "NDB";
150 case ILS: return "ILS";
151 case LOC: return "localiser";
152 case GS: return "glideslope";
153 case OM: return "outer-marker";
154 case MM: return "middle-marker";
155 case IM: return "inner-marker";
156 case AIRPORT: return "airport";
157 case HELIPORT: return "heliport";
158 case SEAPORT: return "seaport";
159 case WAYPOINT: return "waypoint";
160 case DME: return "dme";
161 case TACAN: return "tacan";
162 case FREQ_TOWER: return "tower";
163 case FREQ_ATIS: return "atis";
164 case FREQ_AWOS: return "awos";
165 case FREQ_GROUND: return "ground";
166 case FREQ_CLEARANCE: return "clearance";
167 case FREQ_UNICOM: return "unicom";
168 case FREQ_APP_DEP: return "approach-departure";
169 case TAXI_NODE: return "taxi-node";
175 ///////////////////////////////////////////////////////////////////////////////
176 // search / query functions
179 FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
181 validateSGGeod(aPos);
182 return NavDataCache::instance()->findClosestWithIdent(aIdent, aPos, aFilter);
186 FGPositioned::findFirstWithIdent(const std::string& aIdent, Filter* aFilter)
188 if (aIdent.empty()) {
192 List r = NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, true);
201 FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter)
203 validateSGGeod(aPos);
206 Octree::findAllWithinRange(SGVec3d::fromGeod(aPos),
207 aRangeNm * SG_NM_TO_METER, aFilter, result);
212 FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter, bool aExact)
214 return NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, aExact);
218 FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter, bool aExact)
220 return NavDataCache::instance()->findAllWithName(aName, aFilter, aExact);
224 FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter)
226 validateSGGeod(aPos);
228 List l(findClosestN(aPos, 1, aCutoffNm, aFilter));
233 assert(l.size() == 1);
238 FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter)
240 validateSGGeod(aPos);
243 Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result);
248 FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
250 validateSGGeod(aPos);
252 SGVec3d cartPos(SGVec3d::fromGeod(aPos));
253 // computer ordering values
254 Octree::FindNearestResults r;
255 List::iterator it = aResult.begin(), lend = aResult.end();
256 for (; it != lend; ++it) {
257 double d2 = distSqr((*it)->cart(), cartPos);
258 r.push_back(Octree::OrderedPositioned(*it, d2));
262 std::sort(r.begin(), r.end());
264 // convert to a plain list
265 unsigned int count = aResult.size();
266 for (unsigned int i=0; i<count; ++i) {
267 aResult[i] = r[i].get();
271 void FGPositioned::modifyPosition(const SGGeod& newPos)
273 const_cast<SGGeod&>(mPosition) = newPos;
274 const_cast<SGVec3d&>(mCart) = SGVec3d::fromGeod(newPos);
277 FGPositioned::TypeFilter::TypeFilter(Type aTy) :
284 void FGPositioned::TypeFilter::addType(Type aTy)
286 if (aTy == INVALID) {
290 types.push_back(aTy);
291 mMinType = std::min(mMinType, aTy);
292 mMaxType = std::max(mMaxType, aTy);
296 FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
302 std::vector<Type>::const_iterator it = types.begin(),
304 for (; it != end; ++it) {
305 return aPos->type() == *it;