bool LineStringElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("LineStringElementParser::parseChildElementEndTag called before LineStringElementParser::parseElementStartTag"); } if (node == NodeType::GML_PosListNode || node == NodeType::GML_PosNode) { if (m_model->getDimensions() < 0) { CITYGML_LOG_ERROR(m_logger, "No srsDimension given for LineString before or as attribute of <" << NodeType::GML_PosListNode << "> child element at " << getDocumentLocation()); } else if (m_model->getDimensions() == 2) { m_model->setVertices2D(parseVecList<TVec2d>(characters, m_logger, getDocumentLocation())); } else if (m_model->getDimensions() == 3) { m_model->setVertices3D(parseVecList<TVec3d>(characters, m_logger, getDocumentLocation())); } else { CITYGML_LOG_WARN(m_logger, "Unsupported dimension of LineString positions at " << getDocumentLocation() << ". Only 2 and 3 dimensions are supported."); } return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); }
std::shared_ptr<const CityModel> load( const std::string& fname, const ParserParams& params , std::shared_ptr<CityGMLLogger> logger) { if (!logger) { logger = std::make_shared<StdLogger>(); } if (!initXerces(logger)) { return nullptr; } std::shared_ptr<XMLCh> fileName = toXercesString(fname); #ifdef NDEBUG try { #endif xercesc::LocalFileInputSource fileSource(fileName.get()); return parse(fileSource, params, logger, fname); #ifdef NDEBUG } catch (xercesc::XMLException& e) { CITYGML_LOG_ERROR(logger, "Error parsing file " << fname << ": " << e.getMessage()); return nullptr; } #endif }
bool AddressParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (k_rootElements.count(node) == 0) { CITYGML_LOG_ERROR(m_logger, "Expected an address start tag but got <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_address = make_unique<Address>(attributes.getCityGMLIDAttribute()); return true; }
void Tesselator::addContour(const std::vector<TVec3d>& pts, std::vector<std::vector<TVec2f> > textureCoordinatesLists ) { unsigned int len = pts.size(); if ( len < 3 ) return; for (size_t i = 0; i < textureCoordinatesLists.size(); i++) { std::vector<TVec2f>& texCoords = textureCoordinatesLists.at(i); if (texCoords.size() != pts.size()) { if (!texCoords.empty()) { CITYGML_LOG_ERROR(_logger, "Invalid call to 'addContour'. The number of texture coordinates in list " << i << " (" << texCoords.size() << ") " "does not match the number of vertices (" << pts.size() << "). The texture coordinates list will be resized which may cause invalid texture coordinates."); } texCoords.resize(pts.size(), TVec2f(0.f, 0.f)); } } for (size_t i = 0; i < std::max(_texCoordsLists.size(), textureCoordinatesLists.size()); i++) { if (i >= _texCoordsLists.size()) { std::vector<TVec2f> texCoords(_vertices.size(), TVec2f(0.f, 0.f)); texCoords.insert(texCoords.end(), textureCoordinatesLists.at(i).begin(), textureCoordinatesLists.at(i).end()); _texCoordsLists.push_back(texCoords); } else if (i >= textureCoordinatesLists.size()) { _texCoordsLists.at(i).resize(_texCoordsLists.at(i).size() + pts.size(), TVec2f(0.f, 0.f)); } else { _texCoordsLists.at(i).insert(_texCoordsLists.at(i).end(), textureCoordinatesLists.at(i).begin(), textureCoordinatesLists.at(i).end()); } } unsigned int pos = _vertices.size(); gluTessBeginContour( _tobj ); for ( unsigned int i = 0; i < len; i++ ) { _vertices.push_back( pts[i] ); _indices.push_back(pos + i); gluTessVertex( _tobj, &(_vertices.back()[0]), &_indices.back() ); } gluTessEndContour( _tobj ); #ifndef NDEBUG for (size_t i = 0; i < _texCoordsLists.size(); i++) { assert(_texCoordsLists.at(i).size() == _vertices.size()); } #endif }
bool PolygonElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of PolygonObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createPolygon(attributes.getCityGMLIDAttribute()); return true; }
GeoTransform( const std::string& destURN, std::shared_ptr<citygml::CityGMLLogger> logger ) : m_destSRSURN(destURN) , m_sourceURN("") , m_transformation(nullptr) , m_logger(logger) { OGRErr err = m_destSRS.SetFromUserInput(destURN.c_str()); if (err != OGRERR_NONE) { CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for destination SRS " << destURN << ". OGR error code: " << err << "."); throw std::runtime_error("Invalid destination spatial reference system."); } }
bool SequenceParser::endElement(const NodeType::XMLNode& node, const std::string&) { if (node != m_containerType) { CITYGML_LOG_ERROR(m_logger, "Sequence parser was bound to container element <" << m_containerType << "> but found unexpected" " end tag <" << node << "> at " << getDocumentLocation() << ". Ignoring tag..."); return false; } else { m_documentParser.removeCurrentElementParser(this); } return true; }
void setSourceSRS(const std::string& sourceURN) { if (m_transformation != nullptr) { OCTDestroyCoordinateTransformation(m_transformation); m_transformation = nullptr; } OGRSpatialReference sourceSRS; OGRErr err = sourceSRS.SetFromUserInput(sourceURN.c_str()); if (err != OGRERR_NONE) { CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for source SRS " << sourceURN << ". OGR error code: " << err << "."); return; } m_transformation = OGRCreateCoordinateTransformation(&sourceSRS, &m_destSRS); if (m_transformation == nullptr) { CITYGML_LOG_ERROR(m_logger, "Could not create transformation from source SRS " << sourceURN << " to destination SRS " << m_destSRSURN << "."); return; } m_sourceURN = sourceURN; }
bool CityGMLElementParser::startElement(const NodeType::XMLNode& node, Attributes& attributes) { if (!node.valid()) { CITYGML_LOG_ERROR(m_logger, "Invalid xml start tag (no name) found at " << getDocumentLocation()); throw std::runtime_error("Error parsing xml document. Invalid start tag."); } if (!m_boundElement.valid()) { m_boundElement = node; return parseElementStartTag(node, attributes); } else { return parseChildElementStartTag(node, attributes); } }
bool LineStringElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::GML_LineStringNode << "> or <" << NodeType::GML_PointNode << "> but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createLineString(attributes.getCityGMLIDAttribute()); parseDimension(attributes); return true; }
std::shared_ptr<const CityModel> parse(xercesc::InputSource& stream, const ParserParams& params, std::shared_ptr<CityGMLLogger> logger, std::string filename = "") { CityGMLHandlerXerces handler( params, filename, logger ); xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader(); parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpaces, false); parser->setContentHandler( &handler ); parser->setErrorHandler( &handler ); #ifdef NDEBUG try { #endif parser->parse(stream); #ifdef NDEBUG } catch ( const xercesc::XMLException& e ) { CITYGML_LOG_ERROR(logger, "XML Exception occured: " << toStdString(e.getMessage())); } catch ( const xercesc::SAXParseException& e ) { CITYGML_LOG_ERROR(logger, "SAXParser Exception occured: " << toStdString(e.getMessage())); } catch ( const std::exception& e ) { CITYGML_LOG_ERROR(logger, "Unexpected Exception occured: " << e.what()); } #endif delete parser; return handler.getModel(); }
bool CityObjectElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { initializeTypeIDTypeMap(); auto it = typeIDTypeMap.find(node.typeID()); if (it == typeIDTypeMap.end()) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of CityObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createCityObject(attributes.getCityGMLIDAttribute(), static_cast<CityObject::CityObjectsType>(it->second)); return true; }
bool CityGMLElementParser::endElement(const NodeType::XMLNode& node, const std::string& characters) { if (!m_boundElement.valid()) { // This might happen if an container element that usally contains a child element links to an exting object using XLink an thus // uses a combined start/end element: e.g.: <surfaceMember xlink:href="#..."/> // For such elements a child parser must only be created if there is no xlink attribute. CITYGML_LOG_ERROR(m_logger, "CityGMLElementParser::endElement called on unbound " << elementParserName() << " object for element <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("CityGMLElementParser::endElement called on unbound CityGMLElementParser object."); } if (m_boundElement == node) { m_documentParser.removeCurrentElementParser(this); return parseElementEndTag(node, characters); } else { return parseChildElementEndTag(node, characters); } }
bool initXerces(std::shared_ptr<CityGMLLogger> logger) { if (xerces_initialized) { return true; } try { xerces_init_mutex.lock(); // Check xerces_initialized again... it could have changed while waiting for the mutex if (!xerces_initialized) { xercesc::XMLPlatformUtils::Initialize(); xerces_initialized = true; } xerces_init_mutex.unlock(); } catch (const xercesc::XMLException& e) { CITYGML_LOG_ERROR(logger, "Could not initialize xercesc XMLPlatformUtils, a XML Exception occured : " << toStdString(e.getMessage())); return false; } return true; }
void LinearRing::removeDuplicateVertices(const std::vector<TextureTargetDefinition*>& targets, std::shared_ptr<CityGMLLogger> logger ) { // Currently TextureCoordinates sharing via xlink is not supported (every TextureTargetDefinition is the // sole owner of its TextureCoordinate objects... if this ever changes use an unordered_set for the texture coordinates std::vector<std::shared_ptr<TextureCoordinates>> coordinatesList; bool textureCoordinatesVerticesMismatch = false; for (auto& texTarget : targets) { for (unsigned int i = 0; i < texTarget->getTextureCoordinatesCount(); i++) { auto texCoords = texTarget->getTextureCoordinates(i); if (texCoords->targets(*this)) { coordinatesList.push_back(texCoords); if (m_vertices.size() != texCoords->getCoords().size()) { CITYGML_LOG_WARN(logger, "Number of vertices in LinearRing with id '" << this->getId() << "' (" << m_vertices.size() << ") does not match with number of texture coordinates in coordinates list " << " with id '" << texCoords->getId() << "' (" << texCoords->getCoords().size() << ")"); textureCoordinatesVerticesMismatch = true; } } } } // Remove duplicated vertex unsigned int len = m_vertices.size(); if ( len < 2 ) return; unsigned int i = 0; while ( i < m_vertices.size() && m_vertices.size() > 2 ) { if ( ( m_vertices[i] - m_vertices[ ( i + 1 ) % m_vertices.size() ] ).sqrLength() <= DBL_EPSILON ) { m_vertices.erase( m_vertices.begin() + i ); for (auto coordinates : coordinatesList) { coordinates->eraseCoordinate(i); } } else { i++; } } #ifndef NDEBUG // Check integrity after duplicate removel... no need when the input was already corrupted if (textureCoordinatesVerticesMismatch) { return; } for (auto coordinates : coordinatesList) { if (coordinates->getCoords().size() != m_vertices.size()) { CITYGML_LOG_ERROR(logger, "Broken implementation. Duplicate vertex removal in LinearRing with id '" << this->getId() << "' caused a mismatch of texture coordinates in coordinates list with id '" << coordinates->getId() << "' (" << m_vertices.size() << " != " <<coordinates->getCoords().size() << ")"); } } #endif }
void CALLBACK Tesselator::errorCallback( GLenum errorCode, void* userData ) { Tesselator *tess = static_cast<Tesselator*>(userData); CITYGML_LOG_ERROR(tess->_logger, "Tesselator error: " << gluErrorString( errorCode )); }