1 // fgelev.cxx -- compute scenery elevation
3 // Copyright (C) 2009 - 2012 Mathias Froehlich
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.
27 #include <osg/ArgumentParser>
30 #include <simgear/props/props.hxx>
31 #include <simgear/props/props_io.hxx>
32 #include <simgear/misc/sg_path.hxx>
33 #include <simgear/misc/ResourceManager.hxx>
34 #include <simgear/bvh/BVHNode.hxx>
35 #include <simgear/bvh/BVHLineSegmentVisitor.hxx>
36 #include <simgear/bvh/BVHPager.hxx>
37 #include <simgear/bvh/BVHPageNode.hxx>
38 #include <simgear/scene/material/matlib.hxx>
39 #include <simgear/scene/model/BVHPageNodeOSG.hxx>
40 #include <simgear/scene/model/ModelRegistry.hxx>
41 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
42 #include <simgear/scene/util/OptionsReadFileCallback.hxx>
43 #include <simgear/scene/tgdb/userdata.hxx>
45 namespace sg = simgear;
47 class Visitor : public sg::BVHLineSegmentVisitor {
49 Visitor(const SGLineSegmentd& lineSegment, sg::BVHPager& pager) :
50 BVHLineSegmentVisitor(lineSegment, 0),
55 virtual void apply(sg::BVHPageNode& node)
57 // we have a non threaded pager so load just right here.
59 BVHLineSegmentVisitor::apply(node);
65 // Short circuit reading image files.
66 class ReadFileCallback : public sg::OptionsReadFileCallback {
68 virtual ~ReadFileCallback()
71 virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& name, const osgDB::Options*)
72 { return new osg::Image; }
76 intersect(sg::BVHNode& node, sg::BVHPager& pager,
77 const SGVec3d& start, SGVec3d& end, double offset)
79 SGVec3d perp = offset*perpendicular(start - end);
80 Visitor visitor(SGLineSegmentd(start + perp, end + perp), pager);
84 end = visitor.getLineSegment().getEnd();
89 main(int argc, char** argv)
91 /// Read arguments and environment variables.
93 // use an ArgumentParser object to manage the program arguments.
94 osg::ArgumentParser arguments(&argc, argv);
97 if (arguments.read("--fg-root", fg_root)) {
98 } else if (const char *fg_root_env = std::getenv("FG_ROOT")) {
99 fg_root = fg_root_env;
104 std::string fg_scenery;
105 if (arguments.read("--fg-scenery", fg_scenery)) {
106 } else if (const char *fg_scenery_env = std::getenv("FG_SCENERY")) {
107 fg_scenery = fg_scenery_env;
109 SGPath path(fg_root);
110 path.append("Scenery");
111 fg_scenery = path.str();
114 SGSharedPtr<SGPropertyNode> props = new SGPropertyNode;
116 SGPath preferencesFile = fg_root;
117 preferencesFile.append("preferences.xml");
118 readProperties(preferencesFile.str(), props);
120 // In case of an error, at least make summer :)
121 props->getNode("sim/startup/season", true)->setStringValue("summer");
123 SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear preferences.\n"
124 << "Probably FG_ROOT is not properly set.");
127 /// now set up the simgears required model stuff
129 simgear::ResourceManager::instance()->addBasePath(fg_root, simgear::ResourceManager::PRIORITY_DEFAULT);
130 // Just reference simgears reader writer stuff so that the globals get
131 // pulled in by the linker ...
132 simgear::ModelRegistry::instance();
134 sgUserDataInit(props.get());
135 SGMaterialLib* ml = new SGMaterialLib;
136 SGPath mpath(fg_root);
137 mpath.append("Materials/default/materials.xml");
139 ml->load(fg_root, mpath.str(), props);
141 SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear materials.\n"
142 << "Probably FG_ROOT is not properly set.");
144 simgear::SGModelLib::init(fg_root, props);
146 // Set up the reader/writer options
147 osg::ref_ptr<simgear::SGReaderWriterOptions> options;
148 if (osgDB::Options* ropt = osgDB::Registry::instance()->getOptions())
149 options = new simgear::SGReaderWriterOptions(*ropt);
151 options = new simgear::SGReaderWriterOptions;
152 osgDB::convertStringPathIntoFilePathList(fg_scenery,
153 options->getDatabasePathList());
154 options->setMaterialLib(ml);
155 options->setPropertyNode(props);
156 options->setReadFileCallback(new ReadFileCallback);
157 options->setPluginStringData("SimGear::FG_ROOT", fg_root);
158 // we do not need the builtin boundingvolumes
159 options->setPluginStringData("SimGear::BOUNDINGVOLUMES", "OFF");
160 // And we only want terrain, no objects on top.
161 options->setPluginStringData("SimGear::FG_ONLY_TERRAIN", "ON");
162 props->getNode("sim/rendering/random-objects", true)->setBoolValue(false);
163 props->getNode("sim/rendering/random-vegetation", true)->setBoolValue(false);
165 // Here, all arguments are processed
166 arguments.reportRemainingOptionsAsUnrecognized();
167 arguments.writeErrorMessages(std::cerr);
169 // Get the whole world bvh tree
170 SGSharedPtr<sg::BVHNode> node;
171 node = sg::BVHPageNodeOSG::load("w180s90-360x180.spt", options);
173 // if no model has been successfully loaded report failure.
175 SG_LOG(SG_GENERAL, SG_ALERT, arguments.getApplicationName()
176 << ": No data loaded");
180 // We assume that the above is a paged database.
183 while (std::cin.good()) {
184 // Increment the paging relevant number
185 pager.setUseStamp(1 + pager.getUseStamp());
186 // and expire everything not accessed for the past 30 requests
192 std::cin >> lon >> lat;
195 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
197 SGVec3d start = SGVec3d::fromGeod(SGGeod::fromDegM(lon, lat, 10000));
198 SGVec3d end = SGVec3d::fromGeod(SGGeod::fromDegM(lon, lat, -1000));
200 // Try to find an intersection
201 bool found = intersect(*node, pager, start, end, 0);
203 while (!found && scale <= 1) {
204 found = intersect(*node, pager, start, end, scale);
208 std::cerr << "Found hole of minimum diameter "
209 << scale << "m at lon = " << lon
210 << "deg lat = " << lat << "deg" << std::endl;
212 std::cout << id << ": ";
214 std::cout << "-1000" << std::endl;
216 SGGeod geod = SGGeod::fromCart(end);
217 std::cout << std::fixed << std::setprecision(3) << geod.getElevationM() << std::endl;