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("--expire", expire)) {
101 if (arguments.read("--fg-root", fg_root)) {
102 } else if (const char *fg_root_env = std::getenv("FG_ROOT")) {
103 fg_root = fg_root_env;
108 std::string fg_scenery;
109 if (arguments.read("--fg-scenery", fg_scenery)) {
110 } else if (const char *fg_scenery_env = std::getenv("FG_SCENERY")) {
111 fg_scenery = fg_scenery_env;
113 SGPath path(fg_root);
114 path.append("Scenery");
115 fg_scenery = path.str();
118 SGSharedPtr<SGPropertyNode> props = new SGPropertyNode;
120 SGPath preferencesFile = fg_root;
121 preferencesFile.append("preferences.xml");
122 readProperties(preferencesFile.str(), props);
124 // In case of an error, at least make summer :)
125 props->getNode("sim/startup/season", true)->setStringValue("summer");
127 SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear preferences.\n"
128 << "Probably FG_ROOT is not properly set.");
131 /// now set up the simgears required model stuff
133 simgear::ResourceManager::instance()->addBasePath(fg_root, simgear::ResourceManager::PRIORITY_DEFAULT);
134 // Just reference simgears reader writer stuff so that the globals get
135 // pulled in by the linker ...
136 simgear::ModelRegistry::instance();
138 sgUserDataInit(props.get());
139 SGMaterialLibPtr ml = new SGMaterialLib;
140 SGPath mpath(fg_root);
141 mpath.append("Materials/default/materials.xml");
143 ml->load(fg_root, mpath.str(), props);
145 SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear materials.\n"
146 << "Probably FG_ROOT is not properly set.");
148 simgear::SGModelLib::init(fg_root, props);
150 // Set up the reader/writer options
151 osg::ref_ptr<simgear::SGReaderWriterOptions> options;
152 if (osgDB::Options* ropt = osgDB::Registry::instance()->getOptions())
153 options = new simgear::SGReaderWriterOptions(*ropt);
155 options = new simgear::SGReaderWriterOptions;
156 osgDB::convertStringPathIntoFilePathList(fg_scenery,
157 options->getDatabasePathList());
158 options->setMaterialLib(ml);
159 options->setPropertyNode(props);
160 options->setReadFileCallback(new ReadFileCallback);
161 options->setPluginStringData("SimGear::FG_ROOT", fg_root);
162 // we do not need the builtin boundingvolumes
163 options->setPluginStringData("SimGear::BOUNDINGVOLUMES", "OFF");
164 // And we only want terrain, no objects on top.
165 options->setPluginStringData("SimGear::FG_ONLY_TERRAIN", "ON");
166 props->getNode("sim/rendering/random-objects", true)->setBoolValue(false);
167 props->getNode("sim/rendering/random-vegetation", true)->setBoolValue(false);
169 // Here, all arguments are processed
170 arguments.reportRemainingOptionsAsUnrecognized();
171 arguments.writeErrorMessages(std::cerr);
173 // Get the whole world bvh tree
174 SGSharedPtr<sg::BVHNode> node;
175 node = sg::BVHPageNodeOSG::load("w180s90-360x180.spt", options);
177 // if no model has been successfully loaded report failure.
179 SG_LOG(SG_GENERAL, SG_ALERT, arguments.getApplicationName()
180 << ": No data loaded");
184 // We assume that the above is a paged database.
187 while (std::cin.good()) {
188 // Increment the paging relevant number
189 pager.setUseStamp(1 + pager.getUseStamp());
190 // and expire everything not accessed for the past 30 requests
191 pager.update(expire);
196 std::cin >> lon >> lat;
199 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
201 SGVec3d start = SGVec3d::fromGeod(SGGeod::fromDegM(lon, lat, 10000));
202 SGVec3d end = SGVec3d::fromGeod(SGGeod::fromDegM(lon, lat, -1000));
204 // Try to find an intersection
205 bool found = intersect(*node, pager, start, end, 0);
207 while (!found && scale <= 1) {
208 found = intersect(*node, pager, start, end, scale);
212 std::cerr << "Found hole of minimum diameter "
213 << scale << "m at lon = " << lon
214 << "deg lat = " << lat << "deg" << std::endl;
216 std::cout << id << ": ";
218 std::cout << "-1000" << std::endl;
220 SGGeod geod = SGGeod::fromCart(end);
221 std::cout << std::fixed << std::setprecision(3) << geod.getElevationM() << std::endl;