From 1399eb9de36fe68fc37f7e43f29b1527b1d8d450 Mon Sep 17 00:00:00 2001 From: curt Date: Thu, 8 Apr 2004 19:47:39 +0000 Subject: [PATCH] Rename tgSplitPolygon() -> tgChopPolygon() which is slightly more descriptive and doesn't sound so much like the split long edges function. --- README | 175 +++++++++++++----- src/Airports/GenAirports/build.cxx | 6 +- src/Lib/Polygon/Makefile.am | 2 +- .../Polygon/{split-bin.cxx => chop-bin.cxx} | 20 +- src/Lib/Polygon/{split.hxx => chop.hxx} | 19 +- src/Prep/E00Lines/main.cxx | 8 +- src/Prep/GSHHS/gshhs_split.cxx | 8 +- src/Prep/GSHHS/main.cxx | 1 - src/Prep/Photo/photo.cxx | 4 +- src/Prep/ShapeFile/noaa-decode.cxx | 12 +- src/Prep/ShapeFile/shape-decode.cxx | 12 +- src/Prep/TGVPF/tgvpf.cxx | 9 +- src/Prep/UserDef/tguserdef.cxx | 8 +- 13 files changed, 191 insertions(+), 93 deletions(-) rename src/Lib/Polygon/{split-bin.cxx => chop-bin.cxx} (93%) rename src/Lib/Polygon/{split.hxx => chop.hxx} (61%) diff --git a/README b/README index 253e47e0..422b31e0 100644 --- a/README +++ b/README @@ -1,75 +1,164 @@ -FG Scenery Tools README -======================= +TerraGear Scenery Tools README +============================== -Contained here-in are the FG scenery creation tools. These can be -used to convert 3 arcsec ASCII format DEM files and 30 arcsec binary -format DEM files into Flight Gear scenery. +TerraGear is a collection of tools for building scenery for the +FlightGear project. Generally, the process is done in two steps: -Eventually these tools will expand to support insertion of airports, -roads, rivers, lakes, etc. + 1. Preprocess the original raw data. This chops up the data into + the FG tiling scheme and saves it in a simple, intermediate + format. + + 2. Collect all the different pieces of intermediate data and + assemble them into a 3d model of the terrain. + +There is currently no graphical front end for these tools so you will +need to run them from the command line. Be prepaired, when building +scenery on a world wide scale, be prepaired to burn through multiple +gigabytes of disk space and days or weeks of crunching. Building +smaller chunks is much more doable though. Building the Tools ================== -These tools are compiled and tested under Linux. I'm all for -portability, but I just haven't been as motivated to port these tools, -since scenery creation is less of a general need ... especially at -this stage. However, if anyone wants to work on porting to other -platforms, I will be happy to incorporate patches. +These tools are primarily compiled and tested under Unix with the gnu +compilers. I believe they also build and run on windows with Cygwin. +If anyone has patches for supporting other platforms, I will be happy +to incorporate them. The process for building these tools is very similar to building the main FG source code. -1. Set the FG_ROOT, FG_ROOT_SRC, and FG_ROOT_LIB environment - variables. +1. If you are using the CVS version of the source, run the + "autogen.sh" script. If you downloaded the source tarball, then + don't. -2. Run ``make depend'' +2. Run the "configure" script, with optional arguments for setting + the install prefix, etc.. -3. Run ``make clean'' +3. Run "make" -4. Run ``make'' +4. Run "make install" -3 Arcsec ASCII DEM files -======================== +Preprocessing Terrain +===================== -Data files for the USA are available in this format from: +TerraGear supports several terrain data sources: - http://edcwww.cr.usgs.gov/doc/edchome/ndcdb/ndcdb.html +1. 30-arcsec SRTM based terrain data covering the world (recommended + over other 30-arcsec data sources): -To generate FG scenery from one of these dem files, run: + ftp://edcsgs9.cr.usgs.gov/pub/data/srtm/SRTM30/ - ./process-dem.pl dem-file-1 [ dem-file-2 ...] + I don't recall the details at the moment for processing this data. + Probably similar to the processing of the GLOBE data. -You can vary the error tolerance to control the level of detail (and -size) of the resulting scenery. Note, you must specify the error -tolerance squared. So, if you wish to allow up to a 10 meter error -margin (very high level of detail) you would specify a value of 100. -If you desire an error tolerance of 200 meters (medium detail level) -you would specify a value of 40000. +2. 30-arcsec world wide data: GLOBE project: -The process-dem.pl script will automatically dump the resulting .obj -files in the proper directory tree. + http://www.ngdc.noaa.gov/seg/topo/globe.shtml + + a) First convert the "bin" DEM format to "ascii" DEM format using + "Prep/DemRaw2ascii/raw2ascii" + + b) Then process the resulting files with "Prep/DemChop/demchop" -30 Arcsec Binary DEM files -========================== +3. 30-arcsec world wide data: GTOPO30 data: -These data files have world wide coverage and are available from: + http://edcwww.cr.usgs.gov/landdaac/gtopo30/gtopo30.html - http://edcwww.cr.usgs.gov/landdaac/gtopo30/gtopo30.html + a) First convert the "bin" DEM format to "ascii" DEM format using + "Prep/DemRaw2ascii/raw2ascii" -To process these data files, you must first run: + b) Then process the resulting files with "Prep/DemChop/demchop" - DemRaw2Ascii/raw2ascii -For example: +4. SRTM (1 and 3-arcsec nearly world wide coverage): - DemRaw2Ascii/raw2ascii /tmp/W020N90 asciidems/ + ftp://edcsgs9.cr.usgs.gov/pub/data/srtm/ -This will create ASCII DEM files for each 1 degree x 1 degree area in -the specified output dir. + a) Chop up the .zip files using "Prep/DemChop/hgtchop" -Then, you can take these ascii dem files and feed them through the -same procedure you use with the 3 arcsec dem files. \ No newline at end of file + +5. 3-arcsec ASCII DEM files: + + Generally, I recommend using the SRTM data over this older data + set, however in places like Alaska, there is no SRTM coverage so + this data is better than the 30 arcsec data. + + http://edcwww.cr.usgs.gov/doc/edchome/ndcdb/ndcdb.html + + a) Create the .arr.gz files using the "Prep/DemChop/demchop" utility. + + +The result for any of these terrain sources should be a "work" tree +with a .arr.gz file for each FG tile. + +6. After you create the .arr.gz files you have to create a + corresponding .fit.gz file for each of these. This is a data + reduction step which fits a set of polygons to the raw terrain with + a set of constraints on the maximum error allowed relative to the + original data set, and a max/min number of allowed nodes in the + fitted set. The provided tools use a scheme that produces an + adaptive fit which means fewer polygons in smooth flat areas, and + more polygons in complex rough areas. The end result is a *much* + better fit with fewer polygons than you could achieve by just keeping + every "nth" point from the original array. + + To walk through an entire tree of .arr.gz files and produce the + corresponding .fit.gz files, use the "Prep/TerraFit/terrafit.py" + utility. Please ignore the old "ArrayFit" tools which use a stupid + algorithm and are basically useless in comparison to TerraFit. + + +You should now have a large tree of .arr.gz files with a corresponding +.fit.gz file for each .arr.gz file. It's worth double checking the +contents of your directory and counting all files of each type to make +sure you do have a one to one match and didn't miss anything. + + +Generating Airports +=================== + +Robin Peel maintains a world wide database of airports and navaids for +the X-Plane and FlightGear projects: + + http://www.x-plane.org/users/robinp/ + +Robin's apt.dat needs to be run through two scripts + + cat apt.dat | ./xp2simpleapt.pl > basic.dat + cat apt.dat | ./xp2runway.pl > runways.dat + +Compress these and copy them to $FG_ROOT/data/Airports + +Now run the runways.dat through the getapt utility: + + genapts --input=runways.dat --work=$FG_WORK_DIR + +Note: this creates a last_apt file which shows you the airport genapts +is currently working on. + + - if genapts crashes (which is possible if you try to run through the + entire runways.dat file) you can look at last_apt to see where to start + up again. + + - You can start in midstream using the --start-id=KABC option to genapts. + + - If you get a consistant crash on a particular airport, you probably + found a bug in genapts, or there is some degenerate information at that + airport (40 mile long runways, 2 runways spaced miles apart, etc.) + Often you can fix the data and proceed. Sometimes you can "nudge" + things around to get past a genapts bug. For instance, if you crahs + consistantly on a valid looking runway, try nudging the heading or + position by a least significant digit. Sometimes we can get numerical + problems with the polygon cliper and this often works around it. + +Other considerations: + + - Airport generation pre-depends on terrain data being preped and ready + so airport surfaces can be built properly. + + - If you prep new terrain data, you should probably rerun the airport + generation step. diff --git a/src/Airports/GenAirports/build.cxx b/src/Airports/GenAirports/build.cxx index b52cf1c3..dbe87bb8 100644 --- a/src/Airports/GenAirports/build.cxx +++ b/src/Airports/GenAirports/build.cxx @@ -50,9 +50,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -1210,8 +1210,8 @@ void build_airport( string airport_id, float alt_m, string holepath = root + "/AirportArea"; // long int poly_index = poly_index_next(); // write_boundary( holepath, b, hull, poly_index ); - tgSplitPolygon( holepath, HoleArea, divided_base, true ); - tgSplitPolygon( holepath, AirportArea, apt_clearing, false ); + tgChopPolygon( holepath, HoleArea, divided_base, true ); + tgChopPolygon( holepath, AirportArea, apt_clearing, false ); } diff --git a/src/Lib/Polygon/Makefile.am b/src/Lib/Polygon/Makefile.am index 6c69fc01..4f9a8511 100644 --- a/src/Lib/Polygon/Makefile.am +++ b/src/Lib/Polygon/Makefile.am @@ -1,11 +1,11 @@ noinst_LIBRARIES = libPolygon.a libPolygon_a_SOURCES = \ + chop-bin.cxx chop.hxx \ index.cxx index.hxx \ names.cxx names.hxx \ polygon.cxx polygon.hxx \ simple_clip.cxx simple_clip.hxx \ - split-bin.cxx split.hxx \ superpoly.cxx superpoly.hxx INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/Lib diff --git a/src/Lib/Polygon/split-bin.cxx b/src/Lib/Polygon/chop-bin.cxx similarity index 93% rename from src/Lib/Polygon/split-bin.cxx rename to src/Lib/Polygon/chop-bin.cxx index 804516a6..3f7ac8d6 100644 --- a/src/Lib/Polygon/split-bin.cxx +++ b/src/Lib/Polygon/chop-bin.cxx @@ -1,8 +1,10 @@ -// split.cxx -- polygon splitting utils +// chop-bin.hxx -- routine to chop a polygon up along tile boundaries and +// write the individual pieces to the TG working polygon +// file format. // // Written by Curtis Olson, started February 1999. // -// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 1999-2004 Curtis L. Olson - curt@flightgear.org // // 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 @@ -20,6 +22,7 @@ // // $Id$ + #ifdef HAVE_CONFIG_H # include #endif @@ -39,7 +42,7 @@ #include "index.hxx" #include "names.hxx" #include "simple_clip.hxx" -#include "split.hxx" +#include "chop.hxx" static void clip_and_write_poly( string root, long int p_index, AreaType area, @@ -144,9 +147,10 @@ static void clip_and_write_poly( string root, long int p_index, AreaType area, } -// process shape (write polygon to all intersecting tiles) -void tgSplitPolygon( const string& path, AreaType area, - const TGPolygon& shape, bool preserve3d ) +// process polygon shape (chop up along tile boundaries and write each +// polygon piece to a file) +void tgChopPolygon( const string& path, AreaType area, + const TGPolygon& shape, bool preserve3d ) { Point3D min, max, p; // point2d min, max; @@ -264,7 +268,7 @@ void tgSplitPolygon( const string& path, AreaType area, bottom_clip = horizontal_clip( shape, clip_line, Below ); } - tgSplitPolygon( path, area, bottom_clip, preserve3d ); + tgChopPolygon( path, area, bottom_clip, preserve3d ); } { @@ -293,6 +297,6 @@ void tgSplitPolygon( const string& path, AreaType area, top_clip = horizontal_clip( shape, clip_line, Above ); } - tgSplitPolygon( path, area, top_clip, preserve3d ); + tgChopPolygon( path, area, top_clip, preserve3d ); } } diff --git a/src/Lib/Polygon/split.hxx b/src/Lib/Polygon/chop.hxx similarity index 61% rename from src/Lib/Polygon/split.hxx rename to src/Lib/Polygon/chop.hxx index 92156af5..b1579b25 100644 --- a/src/Lib/Polygon/split.hxx +++ b/src/Lib/Polygon/chop.hxx @@ -1,8 +1,10 @@ -// split.hxx -- polygon splitting utils +// chop.hxx -- routine to chop a polygon up along tile boundaries and +// write the individual pieces to the TG working polygon +// file format. // // Written by Curtis Olson, started February 1999. // -// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 1999-2004 Curtis L. Olson - curt@flightgear.org // // 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 @@ -21,19 +23,20 @@ // $Id$ -#ifndef _SPLIT_HXX -#define _SPLIT_HXX +#ifndef _TG_CHOP_HXX +#define _TG_CHOP_HXX #include "names.hxx" #include "polygon.hxx" -// process shape (write polygon to all intersecting tiles) -void tgSplitPolygon( const string& path, AreaType area, - const TGPolygon& shape, bool preserve3d ); +// process polygon shape (chop up along tile boundaries and write each +// polygon piece to a file) +void tgChopPolygon( const string& path, AreaType area, + const TGPolygon& shape, bool preserve3d ); -#endif // _SPLIT_HXX +#endif // _TG_CHOP_HXX diff --git a/src/Prep/E00Lines/main.cxx b/src/Prep/E00Lines/main.cxx index 710b91bb..ac3301c5 100644 --- a/src/Prep/E00Lines/main.cxx +++ b/src/Prep/E00Lines/main.cxx @@ -44,10 +44,10 @@ SG_USING_STD(vector); #include #include +#include #include #include #include -#include #include #ifdef _MSC_VER @@ -179,7 +179,7 @@ processPoints (const E00 &data, const tg::Rectangle &bounds, } tg::makePolygon(p, width, shape); - tgSplitPolygon(workDir, areaType, shape, false); + tgChopPolygon(workDir, areaType, shape, false); } } @@ -242,7 +242,7 @@ processLines (const E00 &data, const tg::Rectangle &bounds, cout << " Minimum angle: " << (shape.minangle_contour(0) * SGD_RADIANS_TO_DEGREES) << endl; - tgSplitPolygon(workDir, areaType, shape, false); + tgChopPolygon(workDir, areaType, shape, false); } cout << "Done lines" << endl; } @@ -309,7 +309,7 @@ processPolygons (const E00 &data, const tg::Rectangle &bounds, 0.0)); } } - tgSplitPolygon(workDir, areaType, shape, false); + tgChopPolygon(workDir, areaType, shape, false); } } diff --git a/src/Prep/GSHHS/gshhs_split.cxx b/src/Prep/GSHHS/gshhs_split.cxx index 2478a41b..6f9db972 100644 --- a/src/Prep/GSHHS/gshhs_split.cxx +++ b/src/Prep/GSHHS/gshhs_split.cxx @@ -31,10 +31,10 @@ #include #include +#include #include #include #include -#include #include #include "gshhs_split.hxx" @@ -86,13 +86,13 @@ void split_and_shift_chunk( const string& path, AreaType area, upper_shape.shift( -360, 0 ); SG_LOG ( SG_GENERAL, SG_INFO, "Processing lower shape" ); - tgSplitPolygon(path, area, lower_shape, false); + tgChopPolygon(path, area, lower_shape, false); SG_LOG ( SG_GENERAL, SG_INFO, "Processing center shape" ); - tgSplitPolygon(path, area, center_shape, false); + tgChopPolygon(path, area, center_shape, false); SG_LOG ( SG_GENERAL, SG_INFO, "Processing upper shape" ); - tgSplitPolygon(path, area, upper_shape, false); + tgChopPolygon(path, area, upper_shape, false); } diff --git a/src/Prep/GSHHS/main.cxx b/src/Prep/GSHHS/main.cxx index f96573e8..cb777968 100644 --- a/src/Prep/GSHHS/main.cxx +++ b/src/Prep/GSHHS/main.cxx @@ -38,7 +38,6 @@ #include #include #include -#include #ifdef _MSC_VER # include diff --git a/src/Prep/Photo/photo.cxx b/src/Prep/Photo/photo.cxx index e99e08a7..c8dd9d76 100644 --- a/src/Prep/Photo/photo.cxx +++ b/src/Prep/Photo/photo.cxx @@ -39,8 +39,8 @@ #include #include #include +#include #include -#include #include SG_USING_STD(string); @@ -329,7 +329,7 @@ int main( int argc, char **argv ) { poly_index_init( counter_file ); string holepath = root + "/PhotoArea"; - tgSplitPolygon( holepath, HoleArea, hole, false ); + tgChopPolygon( holepath, HoleArea, hole, false ); return 0; } diff --git a/src/Prep/ShapeFile/noaa-decode.cxx b/src/Prep/ShapeFile/noaa-decode.cxx index 1b885d92..7234065b 100644 --- a/src/Prep/ShapeFile/noaa-decode.cxx +++ b/src/Prep/ShapeFile/noaa-decode.cxx @@ -29,10 +29,10 @@ #include +#include #include #include #include -#include #include #ifdef _MSC_VER @@ -417,7 +417,7 @@ int main( int argc, char **argv ) { // holes are preserved area = get_area_type( force_area_type ); - tgSplitPolygon(work_dir, area, shape, false); + tgChopPolygon(work_dir, area, shape, false); } else if ( area == OceanArea ) { // interior of polygon is ocean, holes are islands @@ -425,7 +425,7 @@ int main( int argc, char **argv ) { // Ocean data now comes from GSHHS so we want to ignore // all other ocean data - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else if ( area == VoidArea ) { // interior is ???? @@ -437,7 +437,7 @@ int main( int argc, char **argv ) { // exit(-1); } - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else if ( area == NullArea ) { // interior is ???? @@ -449,9 +449,9 @@ int main( int argc, char **argv ) { // exit(-1); } - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else { - tgSplitPolygon(work_dir, area, shape, false); + tgChopPolygon(work_dir, area, shape, false); } } diff --git a/src/Prep/ShapeFile/shape-decode.cxx b/src/Prep/ShapeFile/shape-decode.cxx index ef1cd380..76b3b182 100644 --- a/src/Prep/ShapeFile/shape-decode.cxx +++ b/src/Prep/ShapeFile/shape-decode.cxx @@ -29,10 +29,10 @@ #include +#include #include #include #include -#include #include #ifdef _MSC_VER @@ -299,7 +299,7 @@ int main( int argc, char **argv ) { // holes are preserved area = get_area_type( force_area_type ); - tgSplitPolygon(work_dir, area, shape, false); + tgChopPolygon(work_dir, area, shape, false); } else if ( area == OceanArea ) { // interior of polygon is ocean, holes are islands @@ -307,7 +307,7 @@ int main( int argc, char **argv ) { // Ocean data now comes from GSHHS so we want to ignore // all other ocean data - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else if ( area == VoidArea ) { // interior is ???? @@ -319,7 +319,7 @@ int main( int argc, char **argv ) { // exit(-1); } - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else if ( area == NullArea ) { // interior is ???? @@ -331,9 +331,9 @@ int main( int argc, char **argv ) { // exit(-1); } - // tgSplitPolygon(work_dir, area, shape, false); + // tgChopPolygon(work_dir, area, shape, false); } else { - tgSplitPolygon(work_dir, area, shape, false); + tgChopPolygon(work_dir, area, shape, false); } } diff --git a/src/Prep/TGVPF/tgvpf.cxx b/src/Prep/TGVPF/tgvpf.cxx index 0bb212e1..413c642d 100644 --- a/src/Prep/TGVPF/tgvpf.cxx +++ b/src/Prep/TGVPF/tgvpf.cxx @@ -44,10 +44,10 @@ SG_USING_STD(vector); #include #include +#include #include #include #include -#include #include #ifdef _MSC_VER @@ -537,7 +537,7 @@ main (int argc, const char **argv) if ( max_segment > 1.0 ) { shape = tgPolygonSplitLongEdges( shape, max_segment ); } - tgSplitPolygon(work_dir, material_type, shape, false); + tgChopPolygon(work_dir, material_type, shape, false); } } } @@ -550,7 +550,10 @@ main (int argc, const char **argv) if (mask.total_size() >= 3) { cout << "Inverse polygon with " << mask.total_size() << " points in " << mask.contours() << " contour(s)" << endl; - tgSplitPolygon(work_dir, material_type, mask, false); + if ( max_segment > 1.0 ) { + mask = tgPolygonSplitLongEdges( mask, max_segment ); + } + tgChopPolygon(work_dir, material_type, mask, false); } else { cout << "Inverse polygon is empty" << endl; } diff --git a/src/Prep/UserDef/tguserdef.cxx b/src/Prep/UserDef/tguserdef.cxx index 5f027be1..36f27fc0 100644 --- a/src/Prep/UserDef/tguserdef.cxx +++ b/src/Prep/UserDef/tguserdef.cxx @@ -9,10 +9,10 @@ #include #include +#include #include #include #include -#include #include @@ -65,7 +65,7 @@ add_point (SGPropertyNode_ptr node) TGPolygon poly; tg::makePolygon(p, node->getIntValue("width", 500), poly); poly = tgPolygonInt(poly, bounds_poly); - tgSplitPolygon(".", material, poly, false); + tgChopPolygon(".", material, poly, false); } static void @@ -86,7 +86,7 @@ add_line (SGPropertyNode_ptr node) TGPolygon poly; tg::makePolygon(line, node->getIntValue("width", 10), poly); poly = tgPolygonInt(poly, bounds_poly); - tgSplitPolygon(".", material, poly, false); + tgChopPolygon(".", material, poly, false); } static void @@ -108,7 +108,7 @@ add_polygon (SGPropertyNode_ptr node) poly.set_hole_flag(i, contour_node->getBoolValue("hole", false)); } poly = tgPolygonInt(poly, bounds_poly); - tgSplitPolygon(".", material, poly, false); + tgChopPolygon(".", material, poly, false); } void