// construct.cxx -- Class to manage the primary data used in the // construction process // // Written by Curtis Olson, started May 1999. // // Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id: construct.cxx,v 1.4 2004-11-19 22:25:49 curt Exp $ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <iomanip> //#include <boost/foreach.hpp> //#include <simgear/compiler.h> //#include <simgear/constants.h> //#include <simgear/math/sg_geodesy.hxx> //#include <simgear/math/SGGeometry.hxx> //#include <simgear/misc/sg_dir.hxx> //#include <simgear/misc/texcoord.hxx> //#include <simgear/io/sg_binobj.hxx> //#include <simgear/structure/exception.hxx> #include <simgear/debug/logstream.hxx> //#include <CGAL/Plane_3.h> //#include <Geometry/poly_support.hxx> //#include <Geometry/poly_extra.hxx> #include "tgconstruct.hxx" //#include "usgs.hxx" //using std::string; // Constructor TGConstruct::TGConstruct(): useUKGrid(false), ignoreLandmass(false), debug_all(false), ds_id((void*)-1) { } // Destructor TGConstruct::~TGConstruct() { array.close(); // land class polygons polys_in.clear(); polys_clipped.clear(); // All Nodes nodes.clear(); } // TGConstruct: Setup void TGConstruct::set_paths( const std::string work, const std::string share, const std::string output, const std::vector<std::string> load ) { work_base = work; share_base = share; output_base = output; load_dirs = load; } void TGConstruct::set_options( bool uk_grid, bool ignore_lm, double n ) { useUKGrid = uk_grid; ignoreLandmass = ignore_lm; nudge = n; } // master construction routine // TODO : Split each step into its own function, and move // into seperate files by major functionality // loading, clipping, tesselating, normals, and output // Also, we are still calculating some thing more than one // (like face area - need to move this into superpoly ) void TGConstruct::ConstructBucketStage1() { // First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); /* If we have some debug IDs, create a datasource */ if ( debug_shapes.size() || debug_all ) { sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); } else { strcpy( ds_name, "" ); } // STEP 1) // Load grid of elevation data (Array) LoadElevationArray(); // STEP 2) // Clip 2D polygons against one another if ( LoadLandclassPolys() == 0 ) { // don't build the tile if there is no 2d data ... it *must* // be ocean and the sim can build the tile on the fly. return; } // STEP 3) // Load the land use polygons if the --cover option was specified if ( get_cover().size() > 0 ) { load_landcover(); } // STEP 4) // Clip the Landclass polygons ClipLandclassPolys(); // STEP 5) // Clean the polys - after this, we shouldn't change their shape (other than slightly for // fix T-Junctions - as This is the end of the first pass for multicore design CleanClippedPolys(); // STEP 6) // Save the tile boundary info for stage 2 (just x,y coords of points on the boundary) SaveSharedEdgeData( 1 ); } void TGConstruct::ConstructBucketStage2() { // First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); /* If we have some debug IDs, create a datasource */ if ( debug_shapes.size() || debug_all ) { sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); } else { strcpy( ds_name, "" ); } // STEP 7) // Need the array of elevation data for stage 2 LoadElevationArray(); // STEP 6) // Merge in Shared data - should just be x,y nodes on the borders from stage1 LoadSharedEdgeData( 1 ); // STEP 7) // Fix T-Junctions by finding nodes that lie close to polygon edges, and // inserting them into the edge FixTJunctions(); // STEP 8) // Generate triangles - we can't generate the node-face lookup table // until all polys are tesselated, as extra nodes can still be generated TesselatePolys(); // STEP 9) // Generate triangle vertex coordinates to node index lists // NOTE: After this point, no new nodes can be added LookupNodesPerVertex(); // STEP 10) // Interpolate elevations, and flatten stuff CalcElevations(); // STEP 11) // Generate face_connected list LookupFacesPerNode(); // STEP 12) // Save the tile boundary info for stage 3 // includes elevation info, and a list of connected triangles SaveSharedEdgeData( 2 ); } void TGConstruct::ConstructBucketStage3() { // First, set the precision of floating point logging: SG_LOG(SG_GENERAL, SG_ALERT, std::setprecision(12) << std::fixed); SG_LOG(SG_GENERAL, SG_ALERT, "\nConstructing tile ID " << bucket.gen_index_str() << " in " << bucket.gen_base_path() ); /* If we have some debug IDs, create a datasource */ if ( debug_shapes.size() || debug_all ) { sprintf(ds_name, "%s/constructdbg_%s", debug_path.c_str(), bucket.gen_index_str().c_str() ); SG_LOG(SG_GENERAL, SG_ALERT, "Debug_string: " << ds_name ); } else { strcpy( ds_name, "" ); } // Load in the neighbor faces and elevation data LoadSharedEdgeDataStage2(); // STEP 12) // Average out the elevation for nodes on tile boundaries AverageEdgeElevations(); // STEP 12) // Calculate Face Normals CalcFaceNormals(); // STEP 13) // Calculate Point Normals CalcPointNormals(); #if 0 if ( c.get_cover().size() > 0 ) { // Now for all the remaining "default" land cover polygons, assign // each one it's proper type from the land use/land cover // database. fix_land_cover_assignments( c ); } #endif // STEP 14) // Calculate Texture Coordinates CalcTextureCoordinates(); // STEP 16) // Generate the btg file WriteBtgFile(); // STEP 17) // Write Custom objects to .stg file AddCustomObjects(); }