1
0
Fork 0

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.
This commit is contained in:
david 2002-07-23 14:33:53 +00:00
parent 0349ab6241
commit 7f957c2269
6 changed files with 340 additions and 1 deletions

View file

@ -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 \

View file

@ -7,4 +7,5 @@ SUBDIRS = \
MergerClipper \
Photo \
ShapeFile \
TGVPF
TGVPF \
UserDef

View file

@ -0,0 +1,4 @@
.deps
Makefile
Makefile.in
tguserdef

View file

@ -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

107
src/Prep/UserDef/sample.xml Normal file
View file

@ -0,0 +1,107 @@
<?xml version="1.0"?>
<!--
************************************************************************
This is a sample file for adding user-defined land-use data.
There are three types of data that you can add: points, lines, and
polygons. All of these get turned into polygons for scenery
generation. Use a file like this to add missing roads, towns,
villages, lakes etc. for your own scenery with tguserdef.
************************************************************************
-->
<PropertyList>
<!--
First we'll add some small towns missing from vmap0.
For each point, we need to specify a single geographical
location in degrees (lon/lat), the width of the area in meters,
and the area material (see $FG_ROOT/materials.xml). The first
example adds a small town 1km x 1km, and the following ones add
small towns 500m x 500m. The name is optional, but you'll find
it useful for keeping track of things.
Don't try too hard to be exact. I find two decimal places (about
1km) to be as accurate as I can usually manage from sectional
charts; if you go to three decimal places, you'll have 100m
accuracy, which should almost always be good enough.
-->
<point>
<name>North Gower</name>
<material>Town</material>
<v>-75.72 45.13</v>
<width>1000</width>
</point>
<point>
<name>Carp</name>
<material>Town</material>
<v>-76.04 45.35</v>
<width>500</width>
</point>
<point>
<name>Kinburn</name>
<material>Town</material>
<v>-76.20 45.38</v>
<width>500</width>
</point>
<point>
<name>Galetta</name>
<material>Town</material>
<v>-76.27 45.42</v>
<width>500</width>
</point>
<!--
Next, we'll add a missing county road.
You need to specify the points (lon/lat) that the line will pass
through, the material type, and the width in meters. By switching the
material, you could make (say) a river or railroad instead of a
road.
Again, don't try to hard to get every bend in the road; add points
only for major changes in direction.
-->
<line>
<name>Ottawa-Carleton Road 6</name>
<material>Road</material>
<width>10</width>
<v>
-75.72 45.13
-75.77 45.11
-75.90 45.03
</v>
</line>
<!--
Finally, we'll add a missing urban area.
A polygon can contain multiple contours, some of which can be holds
(say, to create a donut shape). Simply specify the lon/lat points
around the outside of each contour, and try to capture the rough
shape of the area. By switching types, you could use this to add
a park, forest or lake.
-->
<polygon>
<name>Kanata (north end)</name>
<contour>
<hole>false</hole>
<v>
-75.90 45.34
-75.91 45.34
-75.92 45.33
-75.91 45.32
-75.90 45.33
-75.91 45.33
</v>
</contour>
</polygon>
</PropertyList>

View file

@ -0,0 +1,215 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/math/point3d.hxx>
#include <simgear/misc/exception.hxx>
#include <simgear/misc/props_io.hxx>
#include <simgear/misc/props.hxx>
#include <Geometry/util.hxx>
#include <Polygon/index.hxx>
#include <Polygon/names.hxx>
#include <Polygon/polygon.hxx>
#include <Polygon/split.hxx>
#include <stdlib.h>
#include <vector>
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<SGPropertyNode_ptr> 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] <file>");
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());
}
}
}