--- Begin Message ---
Hello,

answering to Nick Prudent's proposal for a Windows front-end for osgdem, I would suggest to create an XML configuration file parser. XML files are easily editable from specialized XML editor given a schema definition of the file content.

Advantages over a specialized front end are:
- cross platform for free
- repeatability (can rerun a configuration file on error)
- documentation (can extract configuration in a human readable form for reports) - maintenance and expansibility (only need to update configuration file parser and XML schema)


I am using a similar approach within my pet project, Le Petit Poucet GPS software (petit-poucet.org). Main application is downloading and geo-referencing images, then writing an XML configuration file (attached, conf.ptig), then a specialized version of osgdem called pti_gen, it is parsing this XML file and generating .osga (attached is the crude parser I wrote based on Expat, parse_config.cpp).

My parser is not covering all features of osgdem command line and vpb::DataSet but could be extended easily.

Note that I am using extensively GDAL's VRT format to add geo-referencing to image files but this geo-referencing could be included into the osgdem configuration. It is possible to pass to GDAL a string containing XML corresponding to a VRT file.


Antoine
<?xml version="1.0"?>
<pti_gen version='1.0'>
<archive_file>/home/tonio/.pti/cache/orig/YosemiteFall_gpx.osga</archive_file>
<srs>GEOGCS[&quot;WGS 84&quot;,DATUM[&quot;WGS_1984&quot;,SPHEROID[&quot;WGS 84&quot;,6378137,298.257223563,AUTHORITY[&quot;EPSG&quot;,&quot;7030&quot;]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[&quot;EPSG&quot;,&quot;6326&quot;]],PRIMEM[&quot;Greenwich&quot;,0,AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],UNIT[&quot;degree&quot;,0.0174532925199433,AUTHORITY[&quot;EPSG&quot;,&quot;9108&quot;]],AXIS[&quot;Lat&quot;,NORTH],AXIS[&quot;Long&quot;,EAST],AUTHORITY[&quot;EPSG&quot;,&quot;4326&quot;]]</srs>
<geospatial_extents min_x='-119.631' min_y='37.7228' max_x='-119.57' max_y='37.781' geographic='1' />
<source image='1'>/home/tonio/.pti/cache/imagery/landsat/YosemiteFall_gpx_landsat.vrt</source>
<source image='0'>/home/tonio/.pti/cache/imagery/srtm/YosemiteFall_gpx_srtm.vrt</source>
<source image='1'>/home/tonio/.pti/cache/imagery/usgs_drg/YosemiteFall_gpx_usgs_drg.vrt</source>
<source image='0'>/home/tonio/.pti/cache/imagery/us_ned/YosemiteFall_gpx_us_ned.vrt</source>
</pti_gen>
///@file pti_gen.cpp
/// 3D terrain generator config file parser
///
///@author Antoine Hue
///@date 26.06.2007

/*
  This file is part of Le-Petit-Poucet
    
  Le-Petit-Poucet 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <string>
#include <vpb/DataSet>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>


#include <ogr_spatialref.h>
#include <cpl_conv.h>

#include <expat.h>

#include <iostream>

typedef enum {
  tt_unknown = 0,

  tt_pti_gen,
  tt_bin_path,
  tt_archive_file,
  tt_gdal_data,
  tt_srs,
  tt_geospatial_extents,
  tt_source
} tag_type_t;

typedef struct tag_mapping {
  tag_type_t tag_type;              /* enum from above for this tag */
  const char *tag_name;           /* xpath-ish tag name */
} tag_mapping;

/*
 * xpath(ish) mappings between full tag paths and internal identifers.
 * These appear in the order they appear in the GPX specification.
 * If it's not a tag we explictly handle, it doesn't go here.
 */

tag_mapping tag_path_map[] = {

  {tt_pti_gen, "/pti_gen"},
  {tt_bin_path, "/pti_gen/bin_path"},
  {tt_archive_file, "/pti_gen/archive_file"},
  {tt_gdal_data, "/pti_gen/gdal_data"},
  {tt_srs, "/pti_gen/srs"},
  {tt_geospatial_extents, "/pti_gen/geospatial_extents"},
  {tt_source, "/pti_gen/source"},
  
  {tt_unknown}
};

static tag_type_t get_tag(const char *t)
{
  tag_mapping *tm;
  for (tm = tag_path_map; tm->tag_type != tt_unknown; tm++)
	if (0 == strcmp(tm->tag_name, t))
	  return tm->tag_type;
  return tt_unknown;
}

static tag_type_t current_tag = tt_unknown;
static std::string xpath;
static std::string c_cdata;
static bool image_source = false;
static int n_source = 0;

static const char *get_attr ( const char **attr, const char *key )
{
  while ( *attr ) {
	if ( strcmp(*attr,key) == 0 )
	  return *(attr + 1);
	attr += 2;
  }
  return NULL;
}

static void start(vpb::DataSet *ds, const char *el, const char **attr)
{
  xpath += '/';
  xpath += el;
  current_tag = get_tag ( xpath.c_str() );

  c_cdata.clear();
  
  switch ( current_tag ) 
    {
    case tt_pti_gen:
    case tt_bin_path:
    case tt_archive_file:
    case tt_gdal_data:
    case tt_srs:
      break;

    case tt_geospatial_extents:
      {
	double xMin, yMin, xMax, yMax;
	bool geo;
	xMin = strtod(get_attr(attr, "min_x"), NULL);
	yMin = strtod(get_attr(attr, "min_y"), NULL);
	xMax = strtod(get_attr(attr, "max_x"), NULL);
	yMax = strtod(get_attr(attr, "max_y"), NULL);
	geo  =   atoi(get_attr(attr, "geographic"));
	
	vpb::GeospatialExtents extents(xMin, yMin, xMax, yMax, geo);
	
	if(extents.valid())
	  {
	    ds->setDestinationExtents(extents);  // Needed before addition of other sources
	  }
      }
      break;
      
    case tt_source:
      image_source = atoi(get_attr(attr, "image"));
      break;
      
    default: 
      // Error or not ?
      std::cerr << "Unknown tag '"  << el << "'\n";
      break;
    }
}

static void end(vpb::DataSet *ds, const char *el)
{
  //static struct tm tm;
 // g_string_truncate ( xpath, el);
  std::string sel(el);
  size_t pos = xpath.find(sel);
  xpath.erase(pos-1, sel.length()+1);

  switch ( current_tag ) {

	case tt_pti_gen:
	  
	  break;

  case tt_bin_path:
    if(c_cdata.length() > 0)
      {
	osgDB::FilePathList binPaths;
	binPaths.push_back(c_cdata);
	osgDB::appendPlatformSpecificLibraryFilePaths(binPaths);
	osgDB::setLibraryFilePathList(binPaths);
      }
    break;

  case tt_archive_file:
    if(c_cdata.length() > 0)
    {
      std::string strippedName = osgDB::getStrippedName(c_cdata);
      std::string path = osgDB::getFilePath(c_cdata);
      std::string dbFile = (strippedName + ".ive");
      std::string archiveName;
      if(path.length() > 0)
	archiveName = path  + "/" + strippedName + ".osga";
      else
	archiveName = strippedName + ".osga";

  
      // Set output, to clean and to push into the cache
      ds->setDestinationTileBaseName(strippedName);
      ds->setDestinationTileExtension(".ive");
      ds->setArchiveName(archiveName);

      std::cerr << "pti_gen: archive name='" 
			     << archiveName << "'\n";
    }
    else
      {
	// Error handling needed
      }
    break;

  case tt_gdal_data:
    if(c_cdata.length() > 0)
      CPLSetConfigOption("GDAL_DATA", c_cdata.c_str());
    std::cerr << "Setting GDAL_DATA to " << c_cdata << std::endl;
    break;

	case tt_srs:
	{
	  std::cerr << "Setting SRS to " << c_cdata << std::endl;
	  OGRSpatialReference *SRS = new OGRSpatialReference();
	  OSRSetFromUserInput((OGRSpatialReferenceH) SRS, c_cdata.c_str());
  
	  if(SRS->IsGeographic())
	  {
		ds->setConvertFromGeographicToGeocentric(true);
		ds->setEllipsoidModel(new osg::EllipsoidModel(SRS->GetSemiMajor(),
								   SRS->GetSemiMinor()));
	  }
 
	  ds->setDestinationCoordinateSystem(c_cdata.c_str());	  
	}
	  break;

	case tt_geospatial_extents:
	break;

	case tt_source:
	{
	  vpb::DataSet::Source::Type type = (image_source)?
		  vpb::DataSet::Source::IMAGE : vpb::DataSet::Source::HEIGHT_FIELD;
	  vpb::DataSet::Source *source = new vpb::DataSet::Source(type, c_cdata);
	  ds->addSource(source);
	  n_source++;
	 }
	 break;	

	  default: break;
  }

  current_tag = get_tag (xpath.c_str());
}

static void cdata(vpb::DataSet *ds, const XML_Char *s, int len)
{
  switch ( current_tag ) {
  case tt_bin_path:
  case tt_archive_file:
  case tt_gdal_data:
  case tt_srs:
  case tt_source:
    c_cdata.append(s, len);
    break;
    
  default: break;  /* ignore cdata from other things */
  }
}

/// Read config file
int read_ptig( vpb::DataSet *ds, const std::string& ptig ) {
  n_source = 0;
  
  XML_Parser parser = XML_ParserCreate(NULL);
  int done=0, len;

  XML_SetElementHandler(parser, (XML_StartElementHandler) start, (XML_EndElementHandler) end);
  XML_SetUserData(parser, ds); 
  XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler) cdata);

  char buf[4096];
  
  FILE* fh = fopen(ptig.c_str(), "r");
  
  if(!fh)
	return -1;
  
  while (!done) {
	len = fread(buf, 1, sizeof(buf)-7, fh);
	done = feof(fh) || !len;
	XML_Parse(parser, buf, len, done);
  }
  
  return n_source;
}

--- End Message ---
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to