From 7f957c22698a1f062b5d05f65bc6428c2b2106ac Mon Sep 17 00:00:00 2001 From: david Date: Tue, 23 Jul 2002 14:33:53 +0000 Subject: [PATCH] Added tguserdef, a utility for adding user-defined points, lines, and polygons to scenery. It uses the regular XML property format, which users can create easily in a text editor. See src/Prep/UserDef/sample.xml for examples. --- configure.in | 1 + src/Prep/Makefile.am | 3 +- src/Prep/UserDef/.cvsignore | 4 + src/Prep/UserDef/Makefile.am | 11 ++ src/Prep/UserDef/sample.xml | 107 ++++++++++++++++ src/Prep/UserDef/tguserdef.cxx | 215 +++++++++++++++++++++++++++++++++ 6 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 src/Prep/UserDef/.cvsignore create mode 100644 src/Prep/UserDef/Makefile.am create mode 100644 src/Prep/UserDef/sample.xml create mode 100644 src/Prep/UserDef/tguserdef.cxx diff --git a/configure.in b/configure.in index ce192f61..791651da 100644 --- a/configure.in +++ b/configure.in @@ -337,6 +337,7 @@ AC_OUTPUT( \ src/Prep/Photo/Makefile \ src/Prep/ShapeFile/Makefile \ src/Prep/TGVPF/Makefile \ + src/Prep/UserDef/Makefile \ src/Utils/Makefile \ src/Utils/cdrom/Makefile \ src/Utils/download-map/Makefile \ diff --git a/src/Prep/Makefile.am b/src/Prep/Makefile.am index 0a0ee2da..c6fa7377 100644 --- a/src/Prep/Makefile.am +++ b/src/Prep/Makefile.am @@ -7,4 +7,5 @@ SUBDIRS = \ MergerClipper \ Photo \ ShapeFile \ - TGVPF + TGVPF \ + UserDef diff --git a/src/Prep/UserDef/.cvsignore b/src/Prep/UserDef/.cvsignore new file mode 100644 index 00000000..8c0055fd --- /dev/null +++ b/src/Prep/UserDef/.cvsignore @@ -0,0 +1,4 @@ +.deps +Makefile +Makefile.in +tguserdef diff --git a/src/Prep/UserDef/Makefile.am b/src/Prep/UserDef/Makefile.am new file mode 100644 index 00000000..49ac5715 --- /dev/null +++ b/src/Prep/UserDef/Makefile.am @@ -0,0 +1,11 @@ +bin_PROGRAMS = tguserdef + +tguserdef_SOURCES = tguserdef.cxx + +tguserdef_LDADD = \ + $(top_builddir)/src/Lib/Geometry/libGeometry.a \ + $(top_builddir)/src/Lib/Polygon/libPolygon.a \ + $(top_builddir)/src/Lib/poly2tri/libpoly2tri.a \ + -lsgbucket -lsgmisc -lsgmath -lsgio -lsgxml -lsgdebug -lgenpolyclip -lz + +INCLUDES += -I$(top_srcdir)/src/Lib diff --git a/src/Prep/UserDef/sample.xml b/src/Prep/UserDef/sample.xml new file mode 100644 index 00000000..a2e01064 --- /dev/null +++ b/src/Prep/UserDef/sample.xml @@ -0,0 +1,107 @@ + + + + + + + + + North Gower + Town + -75.72 45.13 + 1000 + + + + Carp + Town + -76.04 45.35 + 500 + + + + Kinburn + Town + -76.20 45.38 + 500 + + + + Galetta + Town + -76.27 45.42 + 500 + + + + + + Ottawa-Carleton Road 6 + Road + 10 + + -75.72 45.13 + -75.77 45.11 + -75.90 45.03 + + + + + + + Kanata (north end) + + false + + -75.90 45.34 + -75.91 45.34 + -75.92 45.33 + -75.91 45.32 + -75.90 45.33 + -75.91 45.33 + + + + + diff --git a/src/Prep/UserDef/tguserdef.cxx b/src/Prep/UserDef/tguserdef.cxx new file mode 100644 index 00000000..9ec7d23d --- /dev/null +++ b/src/Prep/UserDef/tguserdef.cxx @@ -0,0 +1,215 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +SG_USING_STD(vector); + +static string prog_name; +static string work_dir = "."; +static Rectangle bounds(Point3D(-180, -90, 0), Point3D(180, 90, 0)); +static FGPolygon bounds_poly; + + +/** + * Parse two vertices from a string. + */ +static const char * +parse_point (const char * s, Point3D &p) +{ + char * endptr; + float x = strtof(s, &endptr); + if (endptr == s) + return 0; + else + s = endptr; + float y = strtof(s, &endptr); + if (endptr == s) { + SG_LOG(SG_TERRAIN, SG_WARN, "Uneven number of vertices!!"); + return 0; + } + p.setx(x); + p.sety(y); + return endptr; +} + +static void +add_point (SGPropertyNode_ptr node) +{ + AreaType material = + get_area_type(node->getStringValue("material", "Default")); + Point3D p, dummy; + const char * s = node->getStringValue("v"); + s = parse_point(s, p); + if (s == 0) { + SG_LOG(SG_TERRAIN, SG_WARN, "No point supplied; skipped"); + return; + } + s = parse_point(s, dummy); + if (s != 0) + SG_LOG(SG_TERRAIN, SG_WARN, "More than one vertex supplied for point"); + FGPolygon poly; + makePolygon(p, node->getIntValue("width", 500), poly); + poly = polygon_int(poly, bounds_poly); + split_polygon(".", material, poly); +} + +static void +add_line (SGPropertyNode_ptr node) +{ + AreaType material = + get_area_type(node->getStringValue("material", "Default")); + const char * s = node->getStringValue("v"); + + Point3D p; + Line line; + s = parse_point(s, p); + while (s != 0) { + line.addPoint(p); + s = parse_point(s, p); + } + + FGPolygon poly; + makePolygon(line, node->getIntValue("width", 10), poly); + poly = polygon_int(poly, bounds_poly); + split_polygon(".", material, poly); +} + +static void +add_polygon (SGPropertyNode_ptr node) +{ + FGPolygon poly; + AreaType material = + get_area_type(node->getStringValue("material", "Default")); + vector contour_nodes = node->getChildren("contour"); + for (int i = 0; i < contour_nodes.size(); i++) { + SGPropertyNode_ptr contour_node = contour_nodes[i]; + Point3D p; + const char * s = contour_node->getStringValue("v"); + s = parse_point(s, p); + while (s != 0) { + poly.add_node(i, p); + s = parse_point(s, p); + } + poly.set_hole_flag(i, contour_node->getBoolValue("hole", false)); + } + poly = polygon_int(poly, bounds_poly); + split_polygon(".", material, poly); +} + +void +usage () +{ + SG_LOG(SG_TERRAIN, SG_ALERT, "Usage: " << prog_name << " [opts] "); + exit(2); +} + +int +main (int ac, char ** av) +{ + sglog().setLogLevels( SG_ALL, SG_DEBUG ); + + poly_index_init( "../poly_counter" ); + + prog_name = av[0]; + + // + // Process command-line options. + // + int argPos = 1; + while (argPos < ac) { + string arg = av[argPos]; + + if (arg.find("--chunk=") == 0) { + bounds = parseChunk(arg.substr(8)); + argPos++; + } + + else if (arg.find("--min-lon=") == 0) { + bounds.getMin().setx(strtod(arg.substr(10).c_str(), 0)); + argPos++; + } + + else if (arg.find("--min-lat=") == 0) { + bounds.getMin().sety(strtod(arg.substr(10).c_str(), 0)); + argPos++; + } + + else if (arg.find("--max-lon=") == 0) { + bounds.getMax().setx(strtod(arg.substr(10).c_str(), 0)); + argPos++; + } + + else if (arg.find("--max-lat=") == 0) { + bounds.getMax().sety(strtod(arg.substr(10).c_str(), 0)); + argPos++; + } + + else if (arg.find("--work-dir=") == 0) { + work_dir = arg.substr(11); + argPos++; + } + + else if (arg == "--") { + argPos++; + break; + } + + else if (arg.find("-") == 0) { + cerr << "Unrecognized option: " << arg << endl; + usage(); + } + + else { + break; + } + } + + bounds.sanify(); + bounds_poly = bounds.toPoly(); + + SGPropertyNode props; + if (argPos == ac) { + usage(); + return 2; + } + + for (int i = argPos; i < ac; i++) { + try { + readProperties(av[i], &props); + } catch (const sg_throwable &ex) { + SG_LOG(SG_TERRAIN, SG_ALERT, "Fatal error loading " << av[1] << ": " + << ex.getFormattedMessage()); + return 1; + } + + int nChildren = props.nChildren(); + for (int j = 0; j < nChildren; j++) { + SGPropertyNode_ptr child = props.getChild(j); + if (!strcmp("point", child->getName())) + add_point(child); + else if (!strcmp("line", child->getName())) + add_line(child); + else if (!strcmp("polygon", child->getName())) + add_polygon(child); + else + SG_LOG(SG_TERRAIN, SG_WARN, "Unrecognized shape type " + << child->getName()); + } + } +} +