Change rapidxmlparser to tinyxml2 and add more extensive xml parsing and image loading

This commit is contained in:
Ylva Selling
2021-03-31 16:41:25 +02:00
parent b88d58edbb
commit b95d6e5b94
12 changed files with 5571 additions and 3839 deletions

View File

@@ -29,7 +29,7 @@ set(HEADER_FILES
skybrowsermodule.h
include/screenspaceskybrowser.h
include/screenspaceskytarget.h
rapidxmlparser/rapidxml.hpp
tinyxml2/tinyxml2.h
)
source_group("Header Files" FILES ${HEADER_FILES})
@@ -40,6 +40,7 @@ set(SOURCE_FILES
skybrowsermodule_lua.inl
src/screenspaceskybrowser.cpp
src/screenspaceskytarget.cpp
tinyxml2/tinyxml2.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -1,52 +0,0 @@
Use of this software is granted under one of the following two licenses,
to be chosen freely by the user.
1. Boost Software License - Version 1.0 - August 17th, 2003
===============================================================================
Copyright (c) 2006, 2007 Marcin Kalicinski
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
2. The MIT License
===============================================================================
Copyright (c) 2006, 2007 Marcin Kalicinski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,174 +0,0 @@
#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
#define RAPIDXML_ITERATORS_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
#include "rapidxml.hpp"
namespace rapidxml
{
//! Iterator of child nodes of xml_node
template<class Ch>
class node_iterator
{
public:
typedef typename xml_node<Ch> value_type;
typedef typename xml_node<Ch> &reference;
typedef typename xml_node<Ch> *pointer;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
node_iterator()
: m_node(0)
{
}
node_iterator(xml_node<Ch> *node)
: m_node(node->first_node())
{
}
reference operator *() const
{
assert(m_node);
return *m_node;
}
pointer operator->() const
{
assert(m_node);
return m_node;
}
node_iterator& operator++()
{
assert(m_node);
m_node = m_node->next_sibling();
return *this;
}
node_iterator operator++(int)
{
node_iterator tmp = *this;
++this;
return tmp;
}
node_iterator& operator--()
{
assert(m_node && m_node->previous_sibling());
m_node = m_node->previous_sibling();
return *this;
}
node_iterator operator--(int)
{
node_iterator tmp = *this;
++this;
return tmp;
}
bool operator ==(const node_iterator<Ch> &rhs)
{
return m_node == rhs.m_node;
}
bool operator !=(const node_iterator<Ch> &rhs)
{
return m_node != rhs.m_node;
}
private:
xml_node<Ch> *m_node;
};
//! Iterator of child attributes of xml_node
template<class Ch>
class attribute_iterator
{
public:
typedef typename xml_attribute<Ch> value_type;
typedef typename xml_attribute<Ch> &reference;
typedef typename xml_attribute<Ch> *pointer;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
attribute_iterator()
: m_attribute(0)
{
}
attribute_iterator(xml_node<Ch> *node)
: m_attribute(node->first_attribute())
{
}
reference operator *() const
{
assert(m_attribute);
return *m_attribute;
}
pointer operator->() const
{
assert(m_attribute);
return m_attribute;
}
attribute_iterator& operator++()
{
assert(m_attribute);
m_attribute = m_attribute->next_attribute();
return *this;
}
attribute_iterator operator++(int)
{
attribute_iterator tmp = *this;
++this;
return tmp;
}
attribute_iterator& operator--()
{
assert(m_attribute && m_attribute->previous_attribute());
m_attribute = m_attribute->previous_attribute();
return *this;
}
attribute_iterator operator--(int)
{
attribute_iterator tmp = *this;
++this;
return tmp;
}
bool operator ==(const attribute_iterator<Ch> &rhs)
{
return m_attribute == rhs.m_attribute;
}
bool operator !=(const attribute_iterator<Ch> &rhs)
{
return m_attribute != rhs.m_attribute;
}
private:
xml_attribute<Ch> *m_attribute;
};
}
#endif

View File

@@ -1,421 +0,0 @@
#ifndef RAPIDXML_PRINT_HPP_INCLUDED
#define RAPIDXML_PRINT_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
#include "rapidxml.hpp"
// Only include streams if not disabled
#ifndef RAPIDXML_NO_STREAMS
#include <ostream>
#include <iterator>
#endif
namespace rapidxml
{
///////////////////////////////////////////////////////////////////////
// Printing flags
const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
///////////////////////////////////////////////////////////////////////
// Internal
//! \cond internal
namespace internal
{
///////////////////////////////////////////////////////////////////////////
// Internal character operations
// Copy characters from given range to given output iterator
template<class OutIt, class Ch>
inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
{
while (begin != end)
*out++ = *begin++;
return out;
}
// Copy characters from given range to given output iterator and expand
// characters into references (&lt; &gt; &apos; &quot; &amp;)
template<class OutIt, class Ch>
inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
{
while (begin != end)
{
if (*begin == noexpand)
{
*out++ = *begin; // No expansion, copy character
}
else
{
switch (*begin)
{
case Ch('<'):
*out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('>'):
*out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('\''):
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
break;
case Ch('"'):
*out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
break;
case Ch('&'):
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
break;
default:
*out++ = *begin; // No expansion, copy character
}
}
++begin; // Step to next character
}
return out;
}
// Fill given output iterator with repetitions of the same character
template<class OutIt, class Ch>
inline OutIt fill_chars(OutIt out, int n, Ch ch)
{
for (int i = 0; i < n; ++i)
*out++ = ch;
return out;
}
// Find character
template<class Ch, Ch ch>
inline bool find_char(const Ch *begin, const Ch *end)
{
while (begin != end)
if (*begin++ == ch)
return true;
return false;
}
///////////////////////////////////////////////////////////////////////////
// Internal printing operations
// Print node
template<class OutIt, class Ch>
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
// Print proper node type
switch (node->type())
{
// Document
case node_document:
out = print_children(out, node, flags, indent);
break;
// Element
case node_element:
out = print_element_node(out, node, flags, indent);
break;
// Data
case node_data:
out = print_data_node(out, node, flags, indent);
break;
// CDATA
case node_cdata:
out = print_cdata_node(out, node, flags, indent);
break;
// Declaration
case node_declaration:
out = print_declaration_node(out, node, flags, indent);
break;
// Comment
case node_comment:
out = print_comment_node(out, node, flags, indent);
break;
// Doctype
case node_doctype:
out = print_doctype_node(out, node, flags, indent);
break;
// Pi
case node_pi:
out = print_pi_node(out, node, flags, indent);
break;
// Unknown
default:
assert(0);
break;
}
// If indenting not disabled, add line break after node
if (!(flags & print_no_indenting))
*out = Ch('\n'), ++out;
// Return modified iterator
return out;
}
// Print children of the node
template<class OutIt, class Ch>
inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
out = print_node(out, child, flags, indent);
return out;
}
// Print attributes of the node
template<class OutIt, class Ch>
inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
{
for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
{
if (attribute->name() && attribute->value())
{
// Print attribute name
*out = Ch(' '), ++out;
out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
*out = Ch('='), ++out;
// Print attribute value using appropriate quote type
if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
{
*out = Ch('\''), ++out;
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
*out = Ch('\''), ++out;
}
else
{
*out = Ch('"'), ++out;
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
*out = Ch('"'), ++out;
}
}
}
return out;
}
// Print data node
template<class OutIt, class Ch>
inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_data);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
return out;
}
// Print data node
template<class OutIt, class Ch>
inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_cdata);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'); ++out;
*out = Ch('!'); ++out;
*out = Ch('['); ++out;
*out = Ch('C'); ++out;
*out = Ch('D'); ++out;
*out = Ch('A'); ++out;
*out = Ch('T'); ++out;
*out = Ch('A'); ++out;
*out = Ch('['); ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch(']'); ++out;
*out = Ch(']'); ++out;
*out = Ch('>'); ++out;
return out;
}
// Print element node
template<class OutIt, class Ch>
inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_element);
// Print element name and attributes, if any
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
out = print_attributes(out, node, flags);
// If node is childless
if (node->value_size() == 0 && !node->first_node())
{
// Print childless node tag ending
*out = Ch('/'), ++out;
*out = Ch('>'), ++out;
}
else
{
// Print normal node tag ending
*out = Ch('>'), ++out;
// Test if node contains a single data node only (and no other nodes)
xml_node<Ch> *child = node->first_node();
if (!child)
{
// If node has no children, only print its value without indenting
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
}
else if (child->next_sibling() == 0 && child->type() == node_data)
{
// If node has a sole data child, only print its value without indenting
out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
}
else
{
// Print all children with full indenting
if (!(flags & print_no_indenting))
*out = Ch('\n'), ++out;
out = print_children(out, node, flags, indent + 1);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
}
// Print node end
*out = Ch('<'), ++out;
*out = Ch('/'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
*out = Ch('>'), ++out;
}
return out;
}
// Print declaration node
template<class OutIt, class Ch>
inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
// Print declaration start
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('?'), ++out;
*out = Ch('x'), ++out;
*out = Ch('m'), ++out;
*out = Ch('l'), ++out;
// Print attributes
out = print_attributes(out, node, flags);
// Print declaration end
*out = Ch('?'), ++out;
*out = Ch('>'), ++out;
return out;
}
// Print comment node
template<class OutIt, class Ch>
inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_comment);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('!'), ++out;
*out = Ch('-'), ++out;
*out = Ch('-'), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('-'), ++out;
*out = Ch('-'), ++out;
*out = Ch('>'), ++out;
return out;
}
// Print doctype node
template<class OutIt, class Ch>
inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_doctype);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('!'), ++out;
*out = Ch('D'), ++out;
*out = Ch('O'), ++out;
*out = Ch('C'), ++out;
*out = Ch('T'), ++out;
*out = Ch('Y'), ++out;
*out = Ch('P'), ++out;
*out = Ch('E'), ++out;
*out = Ch(' '), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('>'), ++out;
return out;
}
// Print pi node
template<class OutIt, class Ch>
inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
{
assert(node->type() == node_pi);
if (!(flags & print_no_indenting))
out = fill_chars(out, indent, Ch('\t'));
*out = Ch('<'), ++out;
*out = Ch('?'), ++out;
out = copy_chars(node->name(), node->name() + node->name_size(), out);
*out = Ch(' '), ++out;
out = copy_chars(node->value(), node->value() + node->value_size(), out);
*out = Ch('?'), ++out;
*out = Ch('>'), ++out;
return out;
}
}
//! \endcond
///////////////////////////////////////////////////////////////////////////
// Printing
//! Prints XML to given output iterator.
//! \param out Output iterator to print to.
//! \param node Node to be printed. Pass xml_document to print entire document.
//! \param flags Flags controlling how XML is printed.
//! \return Output iterator pointing to position immediately after last character of printed text.
template<class OutIt, class Ch>
inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
{
return internal::print_node(out, &node, flags, 0);
}
#ifndef RAPIDXML_NO_STREAMS
//! Prints XML to given output stream.
//! \param out Output stream to print to.
//! \param node Node to be printed. Pass xml_document to print entire document.
//! \param flags Flags controlling how XML is printed.
//! \return Output stream.
template<class Ch>
inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
{
print(std::ostream_iterator<Ch>(out), node, flags);
return out;
}
//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
//! \param out Output stream to print to.
//! \param node Node to be printed.
//! \return Output stream.
template<class Ch>
inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
{
return print(out, node);
}
#endif
}
#endif

View File

@@ -1,122 +0,0 @@
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
#define RAPIDXML_UTILS_HPP_INCLUDED
// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
#include "rapidxml.hpp"
#include <vector>
#include <string>
#include <fstream>
#include <stdexcept>
namespace rapidxml
{
//! Represents data loaded from a file
template<class Ch = char>
class file
{
public:
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
//! \param filename Filename to load.
file(const char *filename)
{
using namespace std;
// Open stream
basic_ifstream<Ch> stream(filename, ios::binary);
if (!stream)
throw runtime_error(string("cannot open file ") + filename);
stream.unsetf(ios::skipws);
// Determine stream size
stream.seekg(0, ios::end);
size_t size = stream.tellg();
stream.seekg(0);
// Load data and add terminating 0
m_data.resize(size + 1);
stream.read(&m_data.front(), static_cast<streamsize>(size));
m_data[size] = 0;
}
//! Loads file into the memory. Data will be automatically destroyed by the destructor
//! \param stream Stream to load from
file(std::basic_istream<Ch> &stream)
{
using namespace std;
// Load data and add terminating 0
stream.unsetf(ios::skipws);
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
if (stream.fail() || stream.bad())
throw runtime_error("error reading stream");
m_data.push_back(0);
}
//! Gets file data.
//! \return Pointer to data of file.
Ch *data()
{
return &m_data.front();
}
//! Gets file data.
//! \return Pointer to data of file.
const Ch *data() const
{
return &m_data.front();
}
//! Gets file data size.
//! \return Size of file data, in characters.
std::size_t size() const
{
return m_data.size();
}
private:
std::vector<Ch> m_data; // File data
};
//! Counts children of node. Time complexity is O(n).
//! \return Number of children of node
template<class Ch>
inline std::size_t count_children(xml_node<Ch> *node)
{
xml_node<Ch> *child = node->first_node();
std::size_t count = 0;
while (child)
{
++count;
child = child->next_sibling();
}
return count;
}
//! Counts attributes of node. Time complexity is O(n).
//! \return Number of attributes of node
template<class Ch>
inline std::size_t count_attributes(xml_node<Ch> *node)
{
xml_attribute<Ch> *attr = node->first_attribute();
std::size_t count = 0;
while (attr)
{
++count;
attr = attr->next_attribute();
}
return count;
}
}
#endif

View File

@@ -23,9 +23,7 @@
****************************************************************************************/
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/rapidxmlparser/rapidxml.hpp> // For parsing xml
#include <modules/skybrowser/rapidxmlparser/rapidxml_utils.hpp> // For parsing xml
#include <modules/skybrowser/rapidxmlparser/rapidxml_print.hpp> // For parsing xml
#include <modules/skybrowser/tinyxml2/tinyxml2.h>
//#include <modules/webbrowser/webbrowsermodule.h>
//#include <modules/webbrowser/include/screenspacebrowser.h>
@@ -48,7 +46,7 @@
#include <ghoul/filesystem/filesystem.h>
#include <openspace/util/httprequest.h> // For downloading files from url
#include <fstream>
#include <filesystem> // To iterate through files in directory
namespace {
struct [[codegen::Dictionary(ScreenSpaceSkyBrowser)]] Parameters {
@@ -245,9 +243,13 @@ SkyBrowserModule::SkyBrowserModule()
}
);
}
SkyBrowserModule::~SkyBrowserModule() {
// Call destructor of all allocated xmls
xmls.clear();
}
void SkyBrowserModule::internalDeinitialize() {
}
@@ -290,75 +292,196 @@ ScreenSpaceSkyTarget* SkyBrowserModule::to_target(ScreenSpaceRenderable* ptr) {
return dynamic_cast<ScreenSpaceSkyTarget*>(ptr);
}
void SkyBrowserModule::loadImages(std::string url, std::string fileDestination) {
bool SkyBrowserModule::downloadFile(std::string& url, std::string& fileDestination) {
// Get the webpage and save to file
HttpRequest::RequestOptions opt{0};
HttpRequest::RequestOptions opt{ 5 };
SyncHttpFileDownload wtml_root(url, fileDestination, HttpFileDownload::Overwrite::Yes);
wtml_root.download(opt);
// Parse XML document
using namespace rapidxml;
rapidxml::file<> xmlFile(fileDestination.c_str()); // Default template is char
rapidxml::xml_document<> doc;
doc.parse<0>(xmlFile.data());
// Get child of node until we find the "Place" node
xml_node<>* place = getChildNode(doc.first_node(), "Place");
// Iterate through all the places and load as images
while (place) {
loadImage(place);
place = place->next_sibling();
}
LINFO(images[55].thumbnailUrl);
return wtml_root.hasSucceeded();
}
int SkyBrowserModule::loadImage(rapidxml::xml_node<>* imgNode) {
ImageData image;
using namespace rapidxml;
// Get all attributes for the <Place>
for (xml_attribute<>* attr = imgNode->first_attribute(); attr; attr = attr->next_attribute())
{
if (attr->name() == "RA") {
image.celestCoords.x = std::stof(attr->value());
void SkyBrowserModule::loadWTMLCollectionsFromURL(std::string url, std::string fileName) {
// Get file
std::string fileDestination = absPath("${MODULE_SKYBROWSER}/WWTimagedata/") + fileName + ".aspx";
if (!downloadFile(url, fileDestination)) {
LINFO("Couldn't download file " + url);
return;
}
// Parse to XML
using namespace tinyxml2;
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
doc->LoadFile(fileDestination.c_str());
XMLElement* root = doc->RootElement();
XMLElement* element = root->FirstChildElement(std::string("Folder").c_str());
// If there are no folders, or there are folder but without urls, stop recursion
if (!element || (element && !element->FindAttribute("Url"))) {
imageUrls.push_back(url);
xmls.push_back(doc);
LINFO("Saving " + url);
return;
}
// Iterate through all the folders
while (element && std::string(element->Value()) == "Folder") {
// Get all attributes for the <Folder>
std::string subUrl = element->FindAttribute("Url") ? element->FindAttribute("Url")->Value() : "";
std::string subName = element->FindAttribute("Name") ? element->FindAttribute("Name")->Value() : "";
if (subUrl != "" && subName != "") {
loadWTMLCollectionsFromURL(subUrl, subName);
}
else if (attr->name() == "DEC") {
image.celestCoords.y = std::stof(attr->value());
}
else if (attr->name() == "Classification") {
image.name = attr->value();
element = element->NextSiblingElement();
}
}
void SkyBrowserModule::loadWTMLCollectionsFromDirectory(std::string directory) {
for (const auto& entry : std::filesystem::directory_iterator(directory)) {
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
std::cout << entry.path().u8string().c_str() << std::endl;
if (doc->LoadFile(entry.path().u8string().c_str()) == tinyxml2::XMLError::XML_SUCCESS) {
xmls.push_back(doc);
}
}
xml_node<>* imageSet = getChildNode(imgNode, "ImageSet");
if (!imageSet) return -1;
// Get all attributes for the <ImageSet>
for (xml_attribute<>* attr = imageSet->first_attribute(); attr; attr = attr->next_attribute()) {
if (attr->name() == "Name") {
image.name = attr->value();
break;
}
}
std::ostream& operator<<(std::ostream& os, const ImageData& img) {
os << "Name: " << img.name << " Coords: ra: " << img.celestCoords.x << " dec: " << img.celestCoords.y << std::endl;
os << "Thumbnail: " << img.thumbnailUrl << std::endl;
os << "Collection: " << img.collection << std::endl << std::endl;
return os;
}
int SkyBrowserModule::loadAllImagesFromXMLs() {
for(tinyxml2::XMLDocument* doc : xmls) {
tinyxml2::XMLElement* root = doc->FirstChildElement();
std::string collectionName = root->FindAttribute("Name") ? root->FindAttribute("Name")->Value() : "";
loadImagesFromXML(root, collectionName);
}
// The thumbnail is the last node so traverse backwards for speed
xml_node<>* imageSetChild = imageSet->last_node();
while (imageSetChild) {
if (std::string(imageSetChild->name()) == "ThumbnailUrl") {
image.thumbnailUrl = imageSetChild->value();
break;
}
imageSetChild = imageSetChild->previous_sibling();
for (ImageData img : images) {
std::cout << img;
}
return images.size();
}
void SkyBrowserModule::printAllUrls() {
for (auto it = imageUrls.begin(); it != imageUrls.end(); it++) {
LINFO(*it);
}
}
void SkyBrowserModule::loadImagesFromXML(tinyxml2::XMLElement* node, std::string collectionName) {
// Get direct child of node called "Place"
using namespace tinyxml2;
XMLElement* folder = getChildNode(node->FirstChildElement(), "Folder");
// Terminate recursion if no folders
if (!folder) {
// When we are at leaf folder
// Iterate through all the places and load as images
// Prefer places over Image Sets as they contain same info
XMLElement* place = getChildNode(node->FirstChildElement(), "Place");
// No place found - look for images instead
if (!place) {
XMLElement* imageSet = getChildNode(node->FirstChildElement(), "ImageSet");
while (imageSet) {
loadImageSet(imageSet, collectionName);
imageSet = imageSet->NextSiblingElement();
}
}
// Place found - look through places
while (place) {
loadPlace(place, collectionName);
place = place->NextSiblingElement();
}
}
else {
// Open all folders at same level
while (folder) {
std::string newCollectionName = collectionName + "/";
if (folder->FindAttribute("Name")) {
newCollectionName += std::string(folder->FindAttribute("Name")->Value());
}
loadImagesFromXML(folder, newCollectionName);
folder = folder->NextSiblingElement();
}
}
}
int SkyBrowserModule::loadPlace(tinyxml2::XMLElement* place, std::string collectionName) {
// Only load "Sky" type images
if (std::string(place->FindAttribute("DataSetType")->Value()) != "Sky")
return - 1;
std::string url = "";
// If the place doesn't have a thumbnail url data attribute,
// Load the containing image set instead
if (!place->FindAttribute("Thumbnail")) {
// Traverse the children and look at all their first child to find ImageSet
tinyxml2::XMLElement* child = place->FirstChildElement();
tinyxml2::XMLElement* imageSet = nullptr;
while (child) {
imageSet = getChildNode(child, "ImageSet");
if (imageSet) break;
child = child->NextSiblingElement();
}
// If the place doesn't contain an image, nothing to add
if (!imageSet) return -1;
// Collect thumbnail url from ImageSet
url = getURLFromImageSet(imageSet);
if (url == "") return -1;
}
ImageData image;
// Get attributes for the image
image.name = place->FindAttribute("Name") ? place->FindAttribute("Name")->Value() : "";
image.celestCoords.x = place->FindAttribute("RA") ? std::stof(place->FindAttribute("RA")->Value()) : 0.f;
image.celestCoords.y = place->FindAttribute("Dec") ? std::stof(place->FindAttribute("Dec")->Value()) : 0.f;
image.thumbnailUrl = url == "" ? place->FindAttribute("Thumbnail")->Value() : url;
image.collection = collectionName;
images.push_back(image);
// Return index of image in vector
return images.size();
}
int SkyBrowserModule::loadImageSet(tinyxml2::XMLElement* imageSet, std::string collectionName) {
std::string type = imageSet->FindAttribute("DataSetType") ? imageSet->FindAttribute("DataSetType")->Value() : "";
// Only load "Sky" type images
if (type != "Sky")
return - 1;
ImageData image;
// Get attributes for the image
image.name = imageSet->FindAttribute("Name") ? imageSet->FindAttribute("Name")->Value() : "";
image.celestCoords.x = imageSet->FindAttribute("RA") ? std::stof(imageSet->FindAttribute("RA")->Value()) : 0.f;
image.celestCoords.y = imageSet->FindAttribute("Dec") ? std::stof(imageSet->FindAttribute("Dec")->Value()) : 0.f;
image.thumbnailUrl = getURLFromImageSet(imageSet);
image.collection = collectionName;
images.push_back(image);
// Return index of image in vector
return images.size();
}
rapidxml::xml_node<>* SkyBrowserModule::getChildNode(rapidxml::xml_node<>* node, std::string name) {
while (node && std::string(node->name()) != name) {
node = node->first_node();
std::string SkyBrowserModule::getURLFromImageSet(tinyxml2::XMLElement* imageSet) {
// FInd the thumbnail image url
// The thumbnail is the last node so traverse backwards for speed
tinyxml2::XMLElement* imageSetChild = imageSet->FirstChildElement("ThumbnailUrl");
return imageSetChild ? imageSetChild->GetText() ? imageSetChild->GetText() : "" : "";
}
tinyxml2::XMLElement* SkyBrowserModule::getChildNode(tinyxml2::XMLElement* node, std::string name) {
while (node && std::string(node->Name()) != name) {
node = node->FirstChildElement();
}
return node;
}
/*
std::vector<documentation::Documentation> SkyBrowserModule::documentations() const {
return {

View File

@@ -25,9 +25,8 @@
#ifndef __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__
#define __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__
#include <openspace/util/openspacemodule.h>
#include <modules/skybrowser/rapidxmlparser/rapidxml.hpp> // For parsing xml
#include <modules/skybrowser/tinyxml2/tinyxml2.h>
#include <openspace/documentation/documentation.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
@@ -44,8 +43,7 @@ struct ImageData {
std::string name;
std::string thumbnailUrl;
glm::vec2 celestCoords;
std::string classification;
float zoom;
std::string collection;
};
class SkyBrowserModule : public OpenSpaceModule {
@@ -53,10 +51,16 @@ public:
constexpr static const char* Name = "SkyBrowser";
SkyBrowserModule();
virtual ~SkyBrowserModule() = default;
virtual ~SkyBrowserModule();
glm::vec2 getMousePositionInScreenSpaceCoords(glm::vec2& mousePos);
void addRenderable(ScreenSpaceRenderable* object);
void loadImages(std::string url, std::string fileDestination);
// Image downloading and xml parsing
bool downloadFile(std::string& url, std::string& fileDestination);
void loadImagesFromXML(tinyxml2::XMLElement* node, std::string collectionName);
void loadWTMLCollectionsFromURL(std::string url, std::string fileName);
void loadWTMLCollectionsFromDirectory(std::string directory);
int loadAllImagesFromXMLs();
void printAllUrls();
scripting::LuaLibrary luaLibrary() const override;
//std::vector<documentation::Documentation> documentations() const override;
@@ -64,8 +68,10 @@ public:
protected:
void internalInitialize(const ghoul::Dictionary& dict) override;
void internalDeinitialize() override;
int loadImage(rapidxml::xml_node<>* imgNode);
rapidxml::xml_node<>* getChildNode(rapidxml::xml_node<>* node, std::string name);
int loadPlace(tinyxml2::XMLElement* place, std::string collectionName);
int loadImageSet(tinyxml2::XMLElement* imageSet, std::string collectionName);
std::string getURLFromImageSet(tinyxml2::XMLElement* imageSet);
tinyxml2::XMLElement* getChildNode(tinyxml2::XMLElement* node, std::string name);
// Using snake case on these casting functions to make them similar to eg std::to_string
ScreenSpaceSkyBrowser* to_browser(ScreenSpaceRenderable* ptr);
ScreenSpaceSkyTarget* to_target(ScreenSpaceRenderable* ptr);
@@ -88,6 +94,8 @@ protected:
bool currentlyDraggingObject;
std::vector<ImageData> images;
std::vector<std::string> imageUrls;
std::vector<tinyxml2::XMLDocument*> xmls;
};
} // namespace openspace

View File

@@ -47,16 +47,21 @@ namespace openspace::skybrowser::luascriptfunctions {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::followCamera");
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
std::string url = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=vampfeeds";
url = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=wise";
std::string fileDestination = absPath("${MODULE_SKYBROWSER}/WWTimagedata/wise.aspx");
module->loadImages(url, fileDestination);
std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/wwt-web-client/master/assets/webclient-explore-root.wtml";
module->loadWTMLCollectionsFromURL(root, "root");
module->printAllUrls();
LINFO(std::to_string( module->loadAllImagesFromXMLs()));
return 1;
}
int moveBrowser(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::moveBrowser");
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
module->loadWTMLCollectionsFromDirectory(absPath("${MODULE_SKYBROWSER}/WWTimagedata/"));
module->printAllUrls();
LINFO(std::to_string(module->loadAllImagesFromXMLs()));
return 1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff