]> git.mxchange.org Git - flightgear.git/blob - src/Navaids/PositionedBinding.cxx
Fix win32 build
[flightgear.git] / src / Navaids / PositionedBinding.cxx
1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4
5 #include "PositionedBinding.hxx"
6
7 #include <map>
8
9 #include <simgear/props/props.hxx>
10 #include <simgear/debug/logstream.hxx>
11 #include <simgear/structure/exception.hxx>
12
13 #include <Main/fg_props.hxx>
14 #include <Navaids/navrecord.hxx>
15 #include <Airports/simple.hxx>
16 #include <Airports/runways.hxx>
17 #include <ATC/CommStation.hxx>
18
19 typedef std::map<SGPropertyNode*, flightgear::PositionedBinding*> BindingMap;
20 static BindingMap static_bindings;
21     
22 namespace {
23     
24 class PropertyDeleteObserver : public SGPropertyChangeListener
25 {
26 public:
27     virtual void childRemoved(SGPropertyNode*, SGPropertyNode* node)
28     {
29         BindingMap::iterator it = static_bindings.find(node);
30         if (it != static_bindings.end()) {
31             SG_LOG(SG_GENERAL, SG_INFO, "saw remove of:" << node->getPath() << ", deleting binding");
32             delete it->second;
33             static_bindings.erase(it);
34         }
35     }
36 };
37     
38 static PropertyDeleteObserver* static_deleteObserver = NULL;
39     
40 } // of anonymous namespace
41     
42 namespace flightgear
43 {
44
45 PositionedBinding::PositionedBinding(const FGPositioned* pos, SGPropertyNode* nd) :
46     p(const_cast<FGPositioned*>(pos)),
47     tied(nd)
48 {
49     if (!static_deleteObserver) {
50         static_deleteObserver = new PropertyDeleteObserver;
51         globals->get_props()->addChangeListener(static_deleteObserver, false);
52     }
53     
54     nd->setDoubleValue("latitude-deg", p->latitude());
55     nd->setDoubleValue("longitude-deg", p->longitude());
56     
57     if (p->elevation() > -1000) {
58         nd->setDoubleValue("elevation-ft", p->elevation());
59     }
60     
61     nd->setStringValue("ident", p->ident());
62     if (!p->name().empty()) {
63         nd->setStringValue("name", p->name());
64     }
65     
66     nd->setStringValue("type", FGPositioned::nameForType(p->type()));
67 }
68
69 PositionedBinding::~PositionedBinding()
70 {
71     tied.Untie();
72 }
73
74 void PositionedBinding::bind(FGPositioned* pos, SGPropertyNode* node)
75 {
76     BindingMap::iterator it = static_bindings.find(node);
77     if (it != static_bindings.end()) {
78         throw sg_exception("duplicate positioned binding", node->getPath());
79     }
80     
81     PositionedBinding* binding = pos->createBinding(node);
82     static_bindings.insert(it, std::make_pair(node, binding));
83 }
84
85 NavaidBinding::NavaidBinding(const FGNavRecord* nav, SGPropertyNode* nd) :
86     PositionedBinding(nav, nd)
87 {
88     FGPositioned::Type ty = nav->type();
89     if (ty == FGPositioned::NDB) {
90         nd->setDoubleValue("frequency-khz", nav->get_freq() / 100.0);
91     } else {
92         nd->setDoubleValue("frequency-mhz", nav->get_freq() / 100.0);
93     }
94     
95     if ((ty == FGPositioned::LOC) || (ty == FGPositioned::ILS)) {
96       nd->setDoubleValue("loc-course-deg", nav->get_multiuse());
97     }
98     
99     if (ty == FGPositioned::GS) {
100         nd->setDoubleValue("gs-angle-deg", nav->get_multiuse());
101     }
102     
103     nd->setDoubleValue("range-nm", nav->get_range());
104     
105     if (nav->runway()) {
106         // don't want to create a cycle in the graph, so we don't re-bind
107         // the airport/runway node here - just expose the IDs
108         nd->setStringValue("airport", nav->runway()->airport()->ident());
109         nd->setStringValue("runway", nav->runway()->ident());
110     }
111 };
112
113 RunwayBinding::RunwayBinding(const FGRunway* rwy, SGPropertyNode* nd) :
114     PositionedBinding(rwy, nd)
115 {
116     nd->setDoubleValue("length-ft", rwy->lengthFt());
117     nd->setDoubleValue("length-m", rwy->lengthM());
118     nd->setDoubleValue("width-ft", rwy->widthFt());
119     nd->setDoubleValue("width-m", rwy->widthM());
120     nd->setDoubleValue("heading-deg", rwy->headingDeg());
121     nd->setBoolValue("hard-surface", rwy->isHardSurface());
122     
123     nd->setDoubleValue("threshold-displacement-m", rwy->displacedThresholdM());
124     nd->setDoubleValue("stopway-m", rwy->stopwayM());
125     
126     if (rwy->ILS()) {
127         SGPropertyNode* ilsNode = nd->getChild("ils", 0, true);
128         PositionedBinding::bind(rwy->ILS(), ilsNode);
129     }
130 }
131
132 AirportBinding::AirportBinding(const FGAirport* apt, SGPropertyNode* nd) :
133     PositionedBinding(apt, nd)
134 {
135     nd->setIntValue("num-runways", apt->numRunways());
136     
137     SGGeod tower = apt->getTowerLocation();
138     nd->setDoubleValue("tower/latitude-deg", tower.getLatitudeDeg());
139     nd->setDoubleValue("tower/longitude-deg", tower.getLongitudeDeg());
140     nd->setDoubleValue("tower/elevation-ft", tower.getElevationFt());
141     
142     for (unsigned int r=0; r<apt->numRunways(); ++r) {
143         SGPropertyNode* rn = nd->getChild("runway", r, true);
144         FGRunway* rwy = apt->getRunwayByIndex(r);
145         PositionedBinding::bind(rwy, rn);
146     }
147     
148     for (unsigned int c=0; c<apt->commStations().size(); ++c) {
149         flightgear::CommStation* comm = apt->commStations()[c];
150         std::string tynm = FGPositioned::nameForType(comm->type());
151         int count = nd->getChildren(tynm).size();
152         
153         SGPropertyNode* commNode = nd->getChild(tynm, count, true);
154         commNode->setStringValue("ident", comm->ident());
155         commNode->setDoubleValue("frequency-mhz", comm->freqMHz());
156     }
157 }
158
159 CommStationBinding::CommStationBinding(const CommStation* sta, SGPropertyNode* node) :
160     PositionedBinding(sta, node)
161 {
162     node->setIntValue("range-nm", sta->rangeNm());
163     node->setDoubleValue("frequency-mhz", sta->freqMHz());
164     
165     if (sta->airport()) {
166         // don't want to create a cycle in the graph, so we don't re-bind
167         // the airport/runway node here - just expose the IDs
168         node->setStringValue("airport", sta->airport()->ident());
169     }
170 }
171
172 } // of namespace flightgear
173