Skip to content

Commit

Permalink
reorganize code:
Browse files Browse the repository at this point in the history
Splitting code into header and cpp to better organize code and increase modularity.
  • Loading branch information
MDjur committed Sep 25, 2024
1 parent 935bd15 commit 95e7925
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 161 deletions.
3 changes: 2 additions & 1 deletion osgplugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ include_directories(
)

set( sources ReaderWriterCityGML.cpp )
set( headers ReaderWriterCityGML.h CityGMLSettings.h ReaderWriterCityGML.h CityGMLOSGPluginLogger.h)

add_library(${target} SHARED ${sources})
add_library(${target} SHARED ${sources} ${headers})
set_target_properties(${target} PROPERTIES PREFIX "")
if(APPLE)
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
Expand Down
39 changes: 39 additions & 0 deletions osgplugin/CityGMLOSGPluginLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <citygml/citygmllogger.h>
#include <osg/Notify>

class CityGMLOSGPluginLogger : public citygml::CityGMLLogger {
public:

virtual void log(LOGLEVEL level, const std::string& message, const char* file, int line) const
{
std::ostream& stream = getLogStreamFor(level);

if (file) {
stream << " [" << file;
if (line > -1) {
stream << ":" << line;
}
stream << "]";
}

stream << " " << message << std::endl;
}

private:
std::ostream& getLogStreamFor(LOGLEVEL level) const {
switch(level) {
case LOGLEVEL::LL_DEBUG:
return osg::notify(osg::DEBUG_INFO);
case LOGLEVEL::LL_WARNING:
return osg::notify(osg::WARN);
case LOGLEVEL::LL_TRACE:
return osg::notify(osg::DEBUG_FP);
case LOGLEVEL::LL_ERROR:
return osg::notify(osg::FATAL);
case LOGLEVEL::LL_INFO:
return osg::notify(osg::INFO);
default:
return osg::notify(osg::INFO);
}
}
};
45 changes: 45 additions & 0 deletions osgplugin/CityGMLSettings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <osgDB/Registry>
#include <osg/Texture2D>
#include <citygml/citygml.h>

class CityGMLSettings
{
public:
CityGMLSettings( void )
: _printNames(false)
, _useMaxLODOnly(false)
, _singleObject(false)
, _storeGeomIDs(false)
, _theme("")
{}

void parseOptions( const osgDB::ReaderWriter::Options* options)
{
if ( !options ) return;
std::istringstream iss( options->getOptionString() );
std::string currentOption;
while ( iss >> currentOption )
{
std::transform( currentOption.begin(), currentOption.end(), currentOption.begin(), ::tolower );
if ( currentOption == "names" ) _printNames = true;
else if ( currentOption == "mask" ) iss >> _params.objectsMask;
else if ( currentOption == "minlod" ) iss >> _params.minLOD;
else if ( currentOption == "maxlod" ) iss >> _params.maxLOD;
else if ( currentOption == "optimize" ) _params.optimize = true;
else if ( currentOption == "pruneemptyobjects" ) _params.pruneEmptyObjects = true;
else if ( currentOption == "usemaxlodonly") _useMaxLODOnly = true;
else if ( currentOption == "singleobject") _singleObject = true;
else if ( currentOption == "usetheme" ) iss >> _theme;
else if ( currentOption == "storegeomids" ) _storeGeomIDs = true;
}
}

public:
citygml::ParserParams _params;
bool _printNames;
bool _useMaxLODOnly;
bool _singleObject;
bool _storeGeomIDs;
std::map< std::string, osg::Texture2D* > _textureMap;
std::string _theme;
};
161 changes: 1 addition & 160 deletions osgplugin/ReaderWriterCityGML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// http://code.google.com/p/libcitygml
// Copyright(c) 2010 Joachim Pouderoux, BRGM
//////////////////////////////////////////////////////////////////////////
#include "ReaderWriterCityGML.h"

#include <osg/Array>
#include <osg/Node>
Expand Down Expand Up @@ -45,169 +46,9 @@
#include <citygml/material.h>
#include <citygml/texture.h>
#include <citygml/tesselator.h>
#include <citygml/citygmllogger.h>

#include <algorithm>
#include <cctype>

class CityGMLOSGPluginLogger : public citygml::CityGMLLogger {
public:

virtual void log(LOGLEVEL level, const std::string& message, const char* file, int line) const
{
std::ostream& stream = getLogStreamFor(level);

if (file) {
stream << " [" << file;
if (line > -1) {
stream << ":" << line;
}
stream << "]";
}

stream << " " << message << std::endl;
}

private:
std::ostream& getLogStreamFor(LOGLEVEL level) const {
switch(level) {
case LOGLEVEL::LL_DEBUG:
return osg::notify(osg::DEBUG_INFO);
case LOGLEVEL::LL_WARNING:
return osg::notify(osg::WARN);
case LOGLEVEL::LL_TRACE:
return osg::notify(osg::DEBUG_FP);
case LOGLEVEL::LL_ERROR:
return osg::notify(osg::FATAL);
case LOGLEVEL::LL_INFO:
return osg::notify(osg::INFO);
default:
return osg::notify(osg::INFO);
}
}
};

class CityGMLSettings
{
public:
CityGMLSettings( void )
: _printNames(false)
, _useMaxLODOnly(false)
, _singleObject(false)
, _storeGeomIDs(false)
, _theme("")
{}

void parseOptions( const osgDB::ReaderWriter::Options* options)
{
if ( !options ) return;
std::istringstream iss( options->getOptionString() );
std::string currentOption;
while ( iss >> currentOption )
{
std::transform( currentOption.begin(), currentOption.end(), currentOption.begin(), ::tolower );
if ( currentOption == "names" ) _printNames = true;
else if ( currentOption == "mask" ) iss >> _params.objectsMask;
else if ( currentOption == "minlod" ) iss >> _params.minLOD;
else if ( currentOption == "maxlod" ) iss >> _params.maxLOD;
else if ( currentOption == "optimize" ) _params.optimize = true;
else if ( currentOption == "pruneemptyobjects" ) _params.pruneEmptyObjects = true;
else if ( currentOption == "usemaxlodonly") _useMaxLODOnly = true;
else if ( currentOption == "singleobject") _singleObject = true;
else if ( currentOption == "usetheme" ) iss >> _theme;
else if ( currentOption == "storegeomids" ) _storeGeomIDs = true;
}
}

public:
citygml::ParserParams _params;
bool _printNames;
bool _useMaxLODOnly;
bool _singleObject;
bool _storeGeomIDs;
std::map< std::string, osg::Texture2D* > _textureMap;
std::string _theme;
};

struct MaterialArrays
{
MaterialArrays(int sizehint = 3) :
vertices(new osg::Vec3Array(sizehint)),
texCoords(new osg::Vec2Array(sizehint)),
indices(sizehint)
{}

std::string textureName;
osg::ref_ptr<osg::Texture2D> texture = nullptr;
osg::ref_ptr<osg::Vec3Array> vertices;
osg::ref_ptr<osg::Vec2Array> texCoords;
std::vector<GLuint> indices;
};
typedef std::map<std::string, MaterialArrays*> MaterialArraysMap;

class ReaderWriterCityGML : public osgDB::ReaderWriter
{
public:
ReaderWriterCityGML( void )
{
supportsExtension( "citygml", "CityGML format" );
supportsExtension( "gml", "CityGML format" );

supportsOption( "names", "Add the name of the city objects on top of them" );
supportsOption( "mask", "Set the objects mask" );
supportsOption( "minLOD", "Minimum LOD level to fetch" );
supportsOption( "maxLOD", "Maximum LOD level to fetch" );
supportsOption( "optimize", "Optimize the geometries & polygons of the CityGML model to reduce the number of instanced objects" );
supportsOption( "pruneEmptyObjects", "Prune empty objects (ie. without -supported- geometry)" );
supportsOption( "destSRS", "Transform geometry to given reference system" );
supportsOption( "useMaxLODonly", "Use the highest available LOD for geometry of one object" );
supportsOption( "appearanceTheme", "Name of the appearance theme to use" );
supportsOption( "storegeomids", "Store the citygml id of geometry objects in the corresponding osg::Geometry object as a description string." );

m_logger = std::make_shared<CityGMLOSGPluginLogger>();
}

virtual const char* className( void ) const override { return "CityGML Reader"; }

virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const override;
virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const override;
virtual ReadResult readObject(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const override
{
return readObjectAdapter(fileName, options);
}

virtual ReadResult readObject(std::istream& fin, const Options* options) const override
{
return readObjectAdapter(fin, options);
}

private:

std::shared_ptr<citygml::CityGMLLogger> m_logger;
static unsigned int getHighestLodForObject(const citygml::CityObject& object);

template<typename T>
ReadResult readObjectAdapter(T&& input, const osgDB::ReaderWriter::Options* options) const;
ReadResult readCity(std::shared_ptr<const citygml::CityModel>, CityGMLSettings& ) const;
bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const;
bool createSingleCityObject(const citygml::CityObject&, CityGMLSettings&, MaterialArraysMap&, const osg::Vec3d& offset, osg::MatrixTransform* root, unsigned int minimumLODToConsider = 0) const;
void createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object, MaterialArraysMap &, const citygml::Geometry& geometry, CityGMLSettings& settings, const osg::Vec3d& offset) const;
void getCenterAndDirection(const citygml::CityObject& object, const citygml::Geometry& geometry, float& minz, const citygml::Geometry*& minGeometry) const;
void getCenterAndDirection(const citygml::CityObject& object, osg::Vec3d& position, osg::Vec3& direction) const;
void handleCityAsSingleObject(CityGMLSettings& settings, const citygml::ConstCityObjects& roots, const osg::Vec3d& offset, osg::MatrixTransform* root) const;
void applyMaterialForSingleObject(MaterialArraysMap &matMap, osg::ref_ptr<osg::Geode> geode) const;
};

// use forwarding reference to avoid code duplication and to preserve type
template<typename T>
osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readObjectAdapter(T&& input, const osgDB::ReaderWriter::Options* options) const
{
ReadResult result = readNode(std::forward<T>(input), options);
osg::Node* node = result.getNode();
if (node) return node;
else return result;
}

// Register with Registry to instantiate the above reader/writer.
REGISTER_OSGPLUGIN( citygml, ReaderWriterCityGML )

Expand Down
87 changes: 87 additions & 0 deletions osgplugin/ReaderWriterCityGML.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <osg/Texture2D>
#include <osgDB/Registry>
#include <citygml/citygml.h>
#include <citygml/citymodel.h>

#include "CityGMLSettings.h"
#include "CityGMLOSGPluginLogger.h"

class ReaderWriterCityGML : public osgDB::ReaderWriter
{
public:

struct MaterialArrays
{
MaterialArrays(int sizehint = 3) :
vertices(new osg::Vec3Array(sizehint)),
texCoords(new osg::Vec2Array(sizehint)),
indices(sizehint)
{}

std::string textureName;
osg::ref_ptr<osg::Texture2D> texture = nullptr;
osg::ref_ptr<osg::Vec3Array> vertices;
osg::ref_ptr<osg::Vec2Array> texCoords;
std::vector<GLuint> indices;
};

typedef std::map<std::string, MaterialArrays*> MaterialArraysMap;
ReaderWriterCityGML( void )
{
supportsExtension( "citygml", "CityGML format" );
supportsExtension( "gml", "CityGML format" );

supportsOption( "names", "Add the name of the city objects on top of them" );
supportsOption( "mask", "Set the objects mask" );
supportsOption( "minLOD", "Minimum LOD level to fetch" );
supportsOption( "maxLOD", "Maximum LOD level to fetch" );
supportsOption( "optimize", "Optimize the geometries & polygons of the CityGML model to reduce the number of instanced objects" );
supportsOption( "pruneEmptyObjects", "Prune empty objects (ie. without -supported- geometry)" );
supportsOption( "destSRS", "Transform geometry to given reference system" );
supportsOption( "useMaxLODonly", "Use the highest available LOD for geometry of one object" );
supportsOption( "appearanceTheme", "Name of the appearance theme to use" );
supportsOption( "storegeomids", "Store the citygml id of geometry objects in the corresponding osg::Geometry object as a description string." );

m_logger = std::make_shared<CityGMLOSGPluginLogger>();
}

virtual const char* className( void ) const override { return "CityGML Reader"; }

virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const override;
virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const override;
virtual ReadResult readObject(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const override
{
return readObjectAdapter(fileName, options);
}

virtual ReadResult readObject(std::istream& fin, const Options* options) const override
{
return readObjectAdapter(fin, options);
}

private:

std::shared_ptr<citygml::CityGMLLogger> m_logger;
static unsigned int getHighestLodForObject(const citygml::CityObject& object);

template<typename T>
ReadResult readObjectAdapter(T&& input, const osgDB::ReaderWriter::Options* options) const;
ReadResult readCity(std::shared_ptr<const citygml::CityModel>, CityGMLSettings& ) const;
bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const;
bool createSingleCityObject(const citygml::CityObject&, CityGMLSettings&, MaterialArraysMap&, const osg::Vec3d& offset, osg::MatrixTransform* root, unsigned int minimumLODToConsider = 0) const;
void createSingleOsgGeometryFromCityGMLGeometry(const citygml::CityObject& object, MaterialArraysMap &, const citygml::Geometry& geometry, CityGMLSettings& settings, const osg::Vec3d& offset) const;
void getCenterAndDirection(const citygml::CityObject& object, const citygml::Geometry& geometry, float& minz, const citygml::Geometry*& minGeometry) const;
void getCenterAndDirection(const citygml::CityObject& object, osg::Vec3d& position, osg::Vec3& direction) const;
void handleCityAsSingleObject(CityGMLSettings& settings, const citygml::ConstCityObjects& roots, const osg::Vec3d& offset, osg::MatrixTransform* root) const;
void applyMaterialForSingleObject(MaterialArraysMap &matMap, osg::ref_ptr<osg::Geode> geode) const;
};

// use forwarding reference to avoid code duplication and to preserve type
template<typename T>
osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readObjectAdapter(T&& input, const osgDB::ReaderWriter::Options* options) const
{
ReadResult result = readNode(std::forward<T>(input), options);
osg::Node* node = result.getNode();
if (node) return node;
else return result;
}

0 comments on commit 95e7925

Please sign in to comment.