<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include <set>

#include "StroikaConfig.h"

#include "../Characters/Format.h"
#include "../Characters/SDKString.h"
#include "../Execution/Exceptions.h"
#include "../Execution/Throw.h"

#include "Locale.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Configuration;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 *********** Configuration::UsePlatformDefaultLocaleAsDefaultLocale *************
 ********************************************************************************
 */
void Configuration::UsePlatformDefaultLocaleAsDefaultLocale ()
{
    locale::global (GetPlatformDefaultLocale ());
}

/*
 ********************************************************************************
 ************************* Configuration::GetAvailableLocales *******************
 ********************************************************************************
 */
#if 0
EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED);
// the enumeration callback function
BOOL CALLBACK EnumLocalesProc(LPTSTR lpLocaleString)
{
    LCID uiCurLocale;
    TCHAR szCurNam[STR_LEN];
    if (!lpLocaleString)
        return FALSE;
// This enumeration returns the LCID as a character string while
// we will be using numbers in other NLS calls.
    uiCurLocale = uiConvertStrToInt(lpLocaleString);
// Get the language name associated with this locale ID.
    GetLocaleInfo(uiCurLocale, LOCALE_SLANGUAGE, szCurName, STR_LEN);
    return TRUE;
}
#endif
vector<Characters::String> Configuration::GetAvailableLocales ()
{
    // @todo
    // horrible!!!! - see TOOD
    vector<Characters::String> result;
    result.reserve (10);
    IgnoreExceptionsForCall (result.push_back (FindLocaleName (L"en"sv, L"us"sv)));
    return result;
}

/*
 ********************************************************************************
 ************************* Configuration::FindLocaleName ************************
 ********************************************************************************
 */
Characters::String Configuration::FindLocaleName (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    if (auto r = FindLocaleNameQuietly (iso2LetterLanguageCode, iso2LetterTerritoryCode)) {
        return *r;
    }
    Execution::Throw (Execution::RuntimeErrorException{Characters::Format (L"Locale (%s-%s) not found", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ())});
}

optional<Characters::String> Configuration::FindLocaleNameQuietly (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    using namespace Characters;
    Require (iso2LetterLanguageCode.length () == 2);
    Require (iso2LetterTerritoryCode.length () == 2); // may lift this in the future and make it optional

#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx ("Configuration::FindLocaleName");
    DbgTrace (L"(%s,%s)", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ());
#endif

    // This is a HORRIBLE way - but I know of no better (especially no better portable way).
    // See todo for planned fixes
    //  --LGP 2013-03-02
    //
    // Could make less heinous with memoizing, but not currently used much, and I plan todo much better impl...
    set<String> part1{
        iso2LetterLanguageCode,
        iso2LetterLanguageCode.ToLowerCase (),
        iso2LetterLanguageCode.ToUpperCase (),
    };
    static const set<String> part2{
        L"-"sv,
        L"_"sv,
        L"."sv,
        L" "sv,
    };
    set<String> part3{
        iso2LetterTerritoryCode,
        iso2LetterTerritoryCode.ToLowerCase (),
        iso2LetterTerritoryCode.ToUpperCase (),
    };
    static const set<String> part4{
        String{},
        L".utf8"sv,
    };
    for (const auto& i1 : part1) {
        for (const auto& i2 : part2) {
            for (const auto& i3 : part3) {
                for (const auto& i4 : part4) {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
                    DbgTrace (L"***trying locale (i1 + i2 + i3 + i4).AsUTF8 ().c_str ()=%s", (i1 + i2 + i3 + i4).c_str ());
#endif
                    IgnoreExceptionsForCall (return String::FromNarrowSDKString (locale{(i1 + i2 + i3 + i4).AsUTF8 ().c_str ()}.name ()));
                }
            }
        }
    }
    return nullopt;
}

/*
 ********************************************************************************
 *************************** Configuration::FindNamedLocale *********************
 ********************************************************************************
 */
locale Configuration::FindNamedLocale (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    return locale{FindLocaleName (iso2LetterLanguageCode, iso2LetterTerritoryCode).AsNarrowSDKString ().c_str ()};
}
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include <set>

#include "StroikaConfig.h"

#include "../Characters/Format.h"
#include "../Characters/SDKString.h"
#include "../Execution/Exceptions.h"
#include "../Execution/Throw.h"

#include "Locale.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Configuration;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 *********** Configuration::UsePlatformDefaultLocaleAsDefaultLocale *************
 ********************************************************************************
 */
void Configuration::UsePlatformDefaultLocaleAsDefaultLocale ()
{
    locale::global (GetPlatformDefaultLocale ());
}

/*
 ********************************************************************************
 ************************* Configuration::GetAvailableLocales *******************
 ********************************************************************************
 */
#if 0
EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED);
// the enumeration callback function
BOOL CALLBACK EnumLocalesProc(LPTSTR lpLocaleString)
{
    LCID uiCurLocale;
    TCHAR szCurNam[STR_LEN];
    if (!lpLocaleString)
        return FALSE;
// This enumeration returns the LCID as a character string while
// we will be using numbers in other NLS calls.
    uiCurLocale = uiConvertStrToInt(lpLocaleString);
// Get the language name associated with this locale ID.
    GetLocaleInfo(uiCurLocale, LOCALE_SLANGUAGE, szCurName, STR_LEN);
    return TRUE;
}
#endif
vector<Characters::String> Configuration::GetAvailableLocales ()
{
    // @todo
    // horrible!!!! - see TOOD
    vector<Characters::String> result;
    result.reserve (10);
    IgnoreExceptionsForCall (result.push_back (FindLocaleName (L"en"sv, L"us"sv)));
    return result;
}

/*
 ********************************************************************************
 ************************* Configuration::FindLocaleName ************************
 ********************************************************************************
 */
Characters::String Configuration::FindLocaleName (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    if (auto r = FindLocaleNameQuietly (iso2LetterLanguageCode, iso2LetterTerritoryCode)) {
        return *r;
    }
    Execution::Throw (Execution::RuntimeErrorException{Characters::Format (L"Locale (%s-%s) not found", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ())});
}

optional<Characters::String> Configuration::FindLocaleNameQuietly (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    using namespace Characters;
    Require (iso2LetterLanguageCode.length () == 2);
    Require (iso2LetterTerritoryCode.length () == 2); // may lift this in the future and make it optional

#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx{"Configuration::FindLocaleName"};
    DbgTrace (L"(%s,%s)", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ());
#endif

    // This is a HORRIBLE way - but I know of no better (especially no better portable way).
    // See todo for planned fixes
    //  --LGP 2013-03-02
    //
    // Could make less heinous with memoizing, but not currently used much, and I plan todo much better impl...
    set<String> part1{
        iso2LetterLanguageCode,
        iso2LetterLanguageCode.ToLowerCase (),
        iso2LetterLanguageCode.ToUpperCase (),
    };
    static const set<String> part2{
        L"-"sv,
        L"_"sv,
        L"."sv,
        L" "sv,
    };
    set<String> part3{
        iso2LetterTerritoryCode,
        iso2LetterTerritoryCode.ToLowerCase (),
        iso2LetterTerritoryCode.ToUpperCase (),
    };
    static const set<String> part4{
        String{},
        L".utf8"sv,
    };
    for (const auto& i1 : part1) {
        for (const auto& i2 : part2) {
            for (const auto& i3 : part3) {
                for (const auto& i4 : part4) {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
                    DbgTrace (L"***trying locale (i1 + i2 + i3 + i4).AsUTF8 ().c_str ()=%s", (i1 + i2 + i3 + i4).c_str ());
#endif
                    IgnoreExceptionsForCall (return String::FromNarrowSDKString (locale{(i1 + i2 + i3 + i4).AsUTF8 ().c_str ()}.name ()));
                }
            }
        }
    }
    return nullopt;
}

/*
 ********************************************************************************
 *************************** Configuration::FindNamedLocale *********************
 ********************************************************************************
 */
locale Configuration::FindNamedLocale (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    return locale{FindLocaleName (iso2LetterLanguageCode, iso2LetterTerritoryCode).AsNarrowSDKString ().c_str ()};
}
<|endoftext|>


<commit_before>/*
    open source routing machine
    Copyright (C) Dennis Luxen, others 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
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 Affero 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
or see http://www.gnu.org/licenses/agpl.txt.
 */
#ifdef STXXL_VERBOSE_LEVEL
#undef STXXL_VERBOSE_LEVEL
#endif
#define STXXL_VERBOSE_LEVEL -1000

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include <libxml/xmlreader.h>
#include <google/sparse_hash_map>
#include <unistd.h>
#include <stxxl.h>

#include "typedefs.h"
#include "DataStructures/InputReaderFactory.h"
#include "DataStructures/ExtractorCallBacks.h"
#include "DataStructures/ExtractorStructs.h"
#include "DataStructures/PBFParser.h"
#include "DataStructures/XMLParser.h"
#include "Util/BaseConfiguration.h"
#include "Util/InputFileUtil.h"

typedef BaseConfiguration ExtractorConfiguration;

unsigned globalRelationCounter = 0;
ExtractorCallbacks * extractCallBacks;

bool nodeFunction(_Node n);
bool adressFunction(_Node n, HashTable<std::string, std::string> keyVals);
bool relationFunction(_Relation r);
bool wayFunction(_Way w);

template<class ClassT>
bool removeIfUnused(ClassT n) { return (false == n.used); }

int main (int argc, char *argv[]) {
    if(argc <= 1) {
        std::cerr << "usage: " << endl << argv[0] << " <file.osm>" << std::endl;
        exit(-1);
    }

    std::cout << "[extractor] extracting data from input file " << argv[1] << std::endl;
    bool isPBF = false;
    std::string outputFileName(argv[1]);
    std::string::size_type pos = outputFileName.find(".osm.bz2");
    if(pos==string::npos) {
        pos = outputFileName.find(".osm.pbf");
        if(pos!=string::npos) {
            isPBF = true;
        }
    }
    if(pos!=string::npos) {
        outputFileName.replace(pos, 8, ".osrm");
    } else {
        pos=outputFileName.find(".osm");
        if(pos!=string::npos) {
            outputFileName.replace(pos, 5, ".osrm");
        } else {
            outputFileName.append(".osrm");
        }
    }
    std::string adressFileName(outputFileName);

    unsigned amountOfRAM = 1;
    unsigned installedRAM = (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
    if(installedRAM < 2097422336) {
        std::cout << "[Warning] Machine has less than 2GB RAM." << std::endl;
    }
    if(testDataFile("extractor.ini")) {
        ExtractorConfiguration extractorConfig("extractor.ini");
        unsigned memoryAmountFromFile = atoi(extractorConfig.GetParameter("Memory").c_str());
        if( memoryAmountFromFile != 0 && memoryAmountFromFile <= installedRAM/(1024*1024*1024))
            amountOfRAM = memoryAmountFromFile;
        std::cout << "[extractor] using " << amountOfRAM << " GB of RAM for buffers" << std::endl;
    }

    STXXLNodeIDVector usedNodeIDs;
    STXXLNodeVector   allNodes;
    STXXLEdgeVector   allEdges;
    STXXLAddressVector adressVector;
    STXXLStringVector  nameVector;
    unsigned usedNodeCounter = 0;
    unsigned usedEdgeCounter = 0;

    StringMap * stringMap = new StringMap();
    Settings settings;
    settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+14);
    settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+14);

    double time = get_timestamp();

    stringMap->set_empty_key(GetRandomString());
    stringMap->insert(std::make_pair("", 0));
    extractCallBacks = new ExtractorCallbacks(&allNodes, &usedNodeIDs, &allEdges,  &nameVector, &adressVector, settings, stringMap);

    BaseParser<_Node, _Relation, _Way> * parser;
    if(isPBF) {
        parser = new PBFParser(argv[1]);
    } else {
        parser = new XMLParser(argv[1]);
    }
    parser->RegisterCallbacks(&nodeFunction, &relationFunction, &wayFunction, &adressFunction);
    if(parser->Init()) {
        parser->Parse();
    } else {
        std::cerr << "[error] parser not initialized!" << std::endl;
        exit(-1);
    }
    delete parser;

    try {
        //        std::cout << "[info] raw no. of names:     " << nameVector.size()    << std::endl;
        //        std::cout << "[info] raw no. of nodes:     " << allNodes.size()      << std::endl;
        //        std::cout << "[info] no. of used nodes:    " << usedNodeIDs.size()     << std::endl;
        //        std::cout << "[info] raw no. of edges:     " << allEdges.size()      << std::endl;
        //        std::cout << "[info] raw no. of relations: " << globalRelationCounter << std::endl;
        //        std::cout << "[info] raw no. of addresses: " << adressVector.size()  << std::endl;

        std::cout << "[extractor] parsing finished after " << get_timestamp() - time << "seconds" << std::endl;
        time = get_timestamp();
        unsigned memory_to_use = amountOfRAM * 1024 * 1024 * 1024;

        std::cout << "[extractor] Sorting used nodes        ... " << std::flush;
        stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

        time = get_timestamp();
        std::cout << "[extractor] Erasing duplicate nodes   ... " << std::flush;
        stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
        usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
        cout << "ok, after " << get_timestamp() - time << "s" << endl;
        time = get_timestamp();

        std::cout << "[extractor] Sorting all nodes         ... " << std::flush;
        stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::ofstream fout;
        fout.open(outputFileName.c_str(), std::ios::binary);
        fout.write((char*)&usedNodeCounter, sizeof(unsigned));

        std::cout << "[extractor] Confirming used nodes     ... " << std::flush;
        STXXLNodeVector::iterator nodesIT = allNodes.begin();
        STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
        while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
            if(*usedNodeIDsIT < nodesIT->id){
                usedNodeIDsIT++;
                continue;
            }
            if(*usedNodeIDsIT > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(*usedNodeIDsIT == nodesIT->id) {
                fout.write((char*)&(nodesIT->id), sizeof(unsigned));
                fout.write((char*)&(nodesIT->lon), sizeof(int));
                fout.write((char*)&(nodesIT->lat), sizeof(int));
                usedNodeCounter++;
                usedNodeIDsIT++;
                nodesIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] setting number of nodes   ... " << std::flush;
        std::ios::pos_type positionInFile = fout.tellp();
        fout.seekp(std::ios::beg);
        fout.write((char*)&usedNodeCounter, sizeof(unsigned));
        fout.seekp(positionInFile);

        std::cout << "ok" << std::endl;
        time = get_timestamp();

        // Sort edges by start.
        std::cout << "[extractor] Sorting edges by start    ... " << std::flush;
        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] Setting start coords      ... " << std::flush;
        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
        // Traverse list of edges and nodes in parallel and set start coord
        nodesIT = allNodes.begin();
        STXXLEdgeVector::iterator edgeIT = allEdges.begin();
        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
            if(edgeIT->start < nodesIT->id){
                edgeIT++;
                continue;
            }
            if(edgeIT->start > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(edgeIT->start == nodesIT->id) {
                edgeIT->startCoord.lat = nodesIT->lat;
                edgeIT->startCoord.lon = nodesIT->lon;
                edgeIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        // Sort Edges by target
        std::cout << "[extractor] Sorting edges by target   ... " << std::flush;
        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] Setting target coords     ... " << std::flush;
        // Traverse list of edges and nodes in parallel and set target coord
        nodesIT = allNodes.begin();
        edgeIT = allEdges.begin();
        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
            if(edgeIT->target < nodesIT->id){
                edgeIT++;
                continue;
            }
            if(edgeIT->target > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(edgeIT->startCoord.lat != INT_MIN && edgeIT->target == nodesIT->id) {
                edgeIT->targetCoord.lat = nodesIT->lat;
                edgeIT->targetCoord.lon = nodesIT->lon;

                double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
                if(edgeIT->speed == -1)
                    edgeIT->speed = settings.speedProfile.speed[edgeIT->type];
                double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
                int intWeight = max(1, (int) weight);
                int intDist = max(1, (int)distance);
                int ferryIndex = settings.indexInAccessListOf("ferry");
                assert(ferryIndex != -1);
                short zero = 0;
                short one = 1;

                fout.write((char*)&edgeIT->start, sizeof(unsigned));
                fout.write((char*)&edgeIT->target, sizeof(unsigned));
                fout.write((char*)&intDist, sizeof(int));
                switch(edgeIT->direction) {
                case _Way::notSure:
                    fout.write((char*)&zero, sizeof(short));
                    break;
                case _Way::oneway:
                    fout.write((char*)&one, sizeof(short));
                    break;
                case _Way::bidirectional:
                    fout.write((char*)&zero, sizeof(short));

                    break;
                case _Way::opposite:
                    fout.write((char*)&one, sizeof(short));
                    break;
                default:
                    std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
                    assert(false);
                    break;
                }
                fout.write((char*)&intWeight, sizeof(int));
                short edgeType = edgeIT->type;
                fout.write((char*)&edgeType, sizeof(short));
                fout.write((char*)&edgeIT->nameID, sizeof(unsigned));

                usedEdgeCounter++;
                edgeIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] setting number of edges   ... " << std::flush;
        fout.seekp(positionInFile);
        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
        fout.close();
        std::cout << "ok" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] writing street name index ... " << std::flush;
        std::vector<unsigned> * nameIndex = new std::vector<unsigned>(nameVector.size()+1, 0);
        outputFileName.append(".names");
        std::ofstream nameOutFile(outputFileName.c_str(), std::ios::binary);
        unsigned sizeOfNameIndex = nameIndex->size();
        nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));

        for(STXXLStringVector::iterator it = nameVector.begin(); it != nameVector.end(); it++) {
            unsigned lengthOfRawString = strlen(it->c_str());
            nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
            nameOutFile.write(it->c_str(), lengthOfRawString);
        }

        nameOutFile.close();
        delete nameIndex;
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

        //        time = get_timestamp();
        //        std::cout << "[extractor] writing address list      ... " << std::flush;
        //
        //        adressFileName.append(".address");
        //        std::ofstream addressOutFile(adressFileName.c_str());
        //        for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
        //            addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
        //        }
        //        addressOutFile.close();
        //        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

    } catch ( const std::exception& e ) {
        std::cerr <<  "Caught Execption:" << e.what() << std::endl;
        return false;
    }

    delete extractCallBacks;
    std::cout << "[extractor] finished." << std::endl;
    return 0;
}

bool nodeFunction(_Node n) {
    extractCallBacks->nodeFunction(n);
    return true;
}

bool adressFunction(_Node n, HashTable<std::string, std::string> keyVals){
    extractCallBacks->adressFunction(n, keyVals);
    return true;
}

bool relationFunction(_Relation r) {
    globalRelationCounter++;
    return true;
}
bool wayFunction(_Way w) {
    extractCallBacks->wayFunction(w);
    return true;
}

<commit_msg>fixing a silly endless loop that occurred when an edge had a starting node that was not present in node data (Thanks Frederik)<commit_after>/*
    open source routing machine
    Copyright (C) Dennis Luxen, others 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
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 Affero 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
or see http://www.gnu.org/licenses/agpl.txt.
 */
#ifdef STXXL_VERBOSE_LEVEL
#undef STXXL_VERBOSE_LEVEL
#endif
#define STXXL_VERBOSE_LEVEL -1000

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include <libxml/xmlreader.h>
#include <google/sparse_hash_map>
#include <unistd.h>
#include <stxxl.h>

#include "typedefs.h"
#include "DataStructures/InputReaderFactory.h"
#include "DataStructures/ExtractorCallBacks.h"
#include "DataStructures/ExtractorStructs.h"
#include "DataStructures/PBFParser.h"
#include "DataStructures/XMLParser.h"
#include "Util/BaseConfiguration.h"
#include "Util/InputFileUtil.h"

typedef BaseConfiguration ExtractorConfiguration;

unsigned globalRelationCounter = 0;
ExtractorCallbacks * extractCallBacks;

bool nodeFunction(_Node n);
bool adressFunction(_Node n, HashTable<std::string, std::string> keyVals);
bool relationFunction(_Relation r);
bool wayFunction(_Way w);

template<class ClassT>
bool removeIfUnused(ClassT n) { return (false == n.used); }

int main (int argc, char *argv[]) {
    if(argc <= 1) {
        std::cerr << "usage: " << endl << argv[0] << " <file.osm>" << std::endl;
        exit(-1);
    }

    std::cout << "[extractor] extracting data from input file " << argv[1] << std::endl;
    bool isPBF = false;
    std::string outputFileName(argv[1]);
    std::string::size_type pos = outputFileName.find(".osm.bz2");
    if(pos==string::npos) {
        pos = outputFileName.find(".osm.pbf");
        if(pos!=string::npos) {
            isPBF = true;
        }
    }
    if(pos!=string::npos) {
        outputFileName.replace(pos, 8, ".osrm");
    } else {
        pos=outputFileName.find(".osm");
        if(pos!=string::npos) {
            outputFileName.replace(pos, 5, ".osrm");
        } else {
            outputFileName.append(".osrm");
        }
    }
    std::string adressFileName(outputFileName);

    unsigned amountOfRAM = 1;
    unsigned installedRAM = (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
    if(installedRAM < 2097422336) {
        std::cout << "[Warning] Machine has less than 2GB RAM." << std::endl;
    }
    if(testDataFile("extractor.ini")) {
        ExtractorConfiguration extractorConfig("extractor.ini");
        unsigned memoryAmountFromFile = atoi(extractorConfig.GetParameter("Memory").c_str());
        if( memoryAmountFromFile != 0 && memoryAmountFromFile <= installedRAM/(1024*1024*1024))
            amountOfRAM = memoryAmountFromFile;
        std::cout << "[extractor] using " << amountOfRAM << " GB of RAM for buffers" << std::endl;
    }

    STXXLNodeIDVector usedNodeIDs;
    STXXLNodeVector   allNodes;
    STXXLEdgeVector   allEdges;
    STXXLAddressVector adressVector;
    STXXLStringVector  nameVector;
    unsigned usedNodeCounter = 0;
    unsigned usedEdgeCounter = 0;

    StringMap * stringMap = new StringMap();
    Settings settings;
    settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+14);
    settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+14);

    double time = get_timestamp();

    stringMap->set_empty_key(GetRandomString());
    stringMap->insert(std::make_pair("", 0));
    extractCallBacks = new ExtractorCallbacks(&allNodes, &usedNodeIDs, &allEdges,  &nameVector, &adressVector, settings, stringMap);

    BaseParser<_Node, _Relation, _Way> * parser;
    if(isPBF) {
        parser = new PBFParser(argv[1]);
    } else {
        parser = new XMLParser(argv[1]);
    }
    parser->RegisterCallbacks(&nodeFunction, &relationFunction, &wayFunction, &adressFunction);
    if(parser->Init()) {
        parser->Parse();
    } else {
        std::cerr << "[error] parser not initialized!" << std::endl;
        exit(-1);
    }
    delete parser;

    try {
        //        std::cout << "[info] raw no. of names:     " << nameVector.size()    << std::endl;
        //        std::cout << "[info] raw no. of nodes:     " << allNodes.size()      << std::endl;
        //        std::cout << "[info] no. of used nodes:    " << usedNodeIDs.size()     << std::endl;
        //        std::cout << "[info] raw no. of edges:     " << allEdges.size()      << std::endl;
        //        std::cout << "[info] raw no. of relations: " << globalRelationCounter << std::endl;
        //        std::cout << "[info] raw no. of addresses: " << adressVector.size()  << std::endl;

        std::cout << "[extractor] parsing finished after " << get_timestamp() - time << "seconds" << std::endl;
        time = get_timestamp();
        unsigned memory_to_use = amountOfRAM * 1024 * 1024 * 1024;

        std::cout << "[extractor] Sorting used nodes        ... " << std::flush;
        stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

        time = get_timestamp();
        std::cout << "[extractor] Erasing duplicate nodes   ... " << std::flush;
        stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
        usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
        cout << "ok, after " << get_timestamp() - time << "s" << endl;
        time = get_timestamp();

        std::cout << "[extractor] Sorting all nodes         ... " << std::flush;
        stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::ofstream fout;
        fout.open(outputFileName.c_str(), std::ios::binary);
        fout.write((char*)&usedNodeCounter, sizeof(unsigned));

        std::cout << "[extractor] Confirming used nodes     ... " << std::flush;
        STXXLNodeVector::iterator nodesIT = allNodes.begin();
        STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
        while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
            if(*usedNodeIDsIT < nodesIT->id){
                usedNodeIDsIT++;
                continue;
            }
            if(*usedNodeIDsIT > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(*usedNodeIDsIT == nodesIT->id) {
                fout.write((char*)&(nodesIT->id), sizeof(unsigned));
                fout.write((char*)&(nodesIT->lon), sizeof(int));
                fout.write((char*)&(nodesIT->lat), sizeof(int));
                usedNodeCounter++;
                usedNodeIDsIT++;
                nodesIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] setting number of nodes   ... " << std::flush;
        std::ios::pos_type positionInFile = fout.tellp();
        fout.seekp(std::ios::beg);
        fout.write((char*)&usedNodeCounter, sizeof(unsigned));
        fout.seekp(positionInFile);

        std::cout << "ok" << std::endl;
        time = get_timestamp();

        // Sort edges by start.
        std::cout << "[extractor] Sorting edges by start    ... " << std::flush;
        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] Setting start coords      ... " << std::flush;
        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
        // Traverse list of edges and nodes in parallel and set start coord
        nodesIT = allNodes.begin();
        STXXLEdgeVector::iterator edgeIT = allEdges.begin();
        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
            if(edgeIT->start < nodesIT->id){
                edgeIT++;
                continue;
            }
            if(edgeIT->start > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(edgeIT->start == nodesIT->id) {
                edgeIT->startCoord.lat = nodesIT->lat;
                edgeIT->startCoord.lon = nodesIT->lon;
                edgeIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        // Sort Edges by target
        std::cout << "[extractor] Sorting edges by target   ... " << std::flush;
        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] Setting target coords     ... " << std::flush;
        // Traverse list of edges and nodes in parallel and set target coord
        nodesIT = allNodes.begin();
        edgeIT = allEdges.begin();
        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
            if(edgeIT->target < nodesIT->id){
                edgeIT++;
                continue;
            }
            if(edgeIT->target > nodesIT->id) {
                nodesIT++;
                continue;
            }
            if(edgeIT->target == nodesIT->id) {
                if(edgeIT->startCoord.lat != INT_MIN) {
                    edgeIT->targetCoord.lat = nodesIT->lat;
                    edgeIT->targetCoord.lon = nodesIT->lon;

                    double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
                    if(edgeIT->speed == -1)
                        edgeIT->speed = settings.speedProfile.speed[edgeIT->type];
                    double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
                    int intWeight = max(1, (int) weight);
                    int intDist = max(1, (int)distance);
                    int ferryIndex = settings.indexInAccessListOf("ferry");
                    assert(ferryIndex != -1);
                    short zero = 0;
                    short one = 1;

                    fout.write((char*)&edgeIT->start, sizeof(unsigned));
                    fout.write((char*)&edgeIT->target, sizeof(unsigned));
                    fout.write((char*)&intDist, sizeof(int));
                    switch(edgeIT->direction) {
                    case _Way::notSure:
                        fout.write((char*)&zero, sizeof(short));
                        break;
                    case _Way::oneway:
                        fout.write((char*)&one, sizeof(short));
                        break;
                    case _Way::bidirectional:
                        fout.write((char*)&zero, sizeof(short));

                        break;
                    case _Way::opposite:
                        fout.write((char*)&one, sizeof(short));
                        break;
                    default:
                        std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
                        assert(false);
                        break;
                    }
                    fout.write((char*)&intWeight, sizeof(int));
                    short edgeType = edgeIT->type;
                    fout.write((char*)&edgeType, sizeof(short));
                    fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
                }
                usedEdgeCounter++;
                edgeIT++;
            }
        }
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] setting number of edges   ... " << std::flush;
        fout.seekp(positionInFile);
        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
        fout.close();
        std::cout << "ok" << std::endl;
        time = get_timestamp();

        std::cout << "[extractor] writing street name index ... " << std::flush;
        std::vector<unsigned> * nameIndex = new std::vector<unsigned>(nameVector.size()+1, 0);
        outputFileName.append(".names");
        std::ofstream nameOutFile(outputFileName.c_str(), std::ios::binary);
        unsigned sizeOfNameIndex = nameIndex->size();
        nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));

        for(STXXLStringVector::iterator it = nameVector.begin(); it != nameVector.end(); it++) {
            unsigned lengthOfRawString = strlen(it->c_str());
            nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
            nameOutFile.write(it->c_str(), lengthOfRawString);
        }

        nameOutFile.close();
        delete nameIndex;
        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

        //        time = get_timestamp();
        //        std::cout << "[extractor] writing address list      ... " << std::flush;
        //
        //        adressFileName.append(".address");
        //        std::ofstream addressOutFile(adressFileName.c_str());
        //        for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
        //            addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
        //        }
        //        addressOutFile.close();
        //        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;

    } catch ( const std::exception& e ) {
        std::cerr <<  "Caught Execption:" << e.what() << std::endl;
        return false;
    }

    delete extractCallBacks;
    std::cout << "[extractor] finished." << std::endl;
    return 0;
}

bool nodeFunction(_Node n) {
    extractCallBacks->nodeFunction(n);
    return true;
}

bool adressFunction(_Node n, HashTable<std::string, std::string> keyVals){
    extractCallBacks->adressFunction(n, keyVals);
    return true;
}

bool relationFunction(_Relation r) {
    globalRelationCounter++;
    return true;
}
bool wayFunction(_Way w) {
    extractCallBacks->wayFunction(w);
    return true;
}

<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxSuperElastixFilterCustomComponents.h"

#include "selxRegistrationController.h"

#include "selxNiftyregReadImageComponent.h"
#include "selxNiftyregWriteImageComponent.h"
#include "selxNiftyregWriteImageComponent.h"
#include "selxItkToNiftiImageSourceReferenceComponent.h"
#include "selxNiftiToItkImageSinkComponent.h"
#include "selxItkImageSource.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "selxNiftyregf3dComponent.h"
#include "selxDataManager.h"
#include "gtest/gtest.h"

namespace selx
{
class NiftyregComponentTest : public ::testing::Test
{
public:

  typedef std::unique_ptr< Blueprint >                       BlueprintPointer;
  typedef itk::UniquePointerDataObjectDecorator< Blueprint > BlueprintITKType;
  typedef BlueprintITKType::Pointer                          BlueprintITKPointer;
  typedef Blueprint::ParameterMapType                        ParameterMapType;
  typedef Blueprint::ParameterValueType                      ParameterValueType;
  typedef DataManager                                        DataManagerType;

  /** register all example components */
  typedef TypeList < Niftyregf3dComponent< float >,
    NiftyregReadImageComponent< float >,
    NiftyregWriteImageComponent< float >,
    ItkToNiftiImageSourceReferenceComponent< 3, float >,
    NiftiToItkImageSinkComponent<3, float>,
    ItkImageSourceComponent<3, float>,
    RegistrationControllerComponent< >> RegisterComponents;

  typedef SuperElastixFilterCustomComponents< RegisterComponents > SuperElastixFilterType;
  virtual void SetUp()
  {
    // Instantiate SuperElastixFilter before each test and
    // register the components we want to have available in SuperElastix
    superElastixFilter = SuperElastixFilterType::New();
    dataManager        = DataManagerType::New();
  }

  virtual void TearDown()
  {
    // Unregister all components after each test
    itk::ObjectFactoryBase::UnRegisterAllFactories();
    // Delete the SuperElastixFilter after each test
    superElastixFilter = nullptr;
  }

  // Blueprint holds a configuration for SuperElastix
  BlueprintPointer            blueprint;
  SuperElastixFilterBase::Pointer superElastixFilter;
  // Data manager provides the paths to the input and output data for unit tests
  DataManagerType::Pointer dataManager;
};

TEST_F( NiftyregComponentTest, Register2d )
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer( new Blueprint() );
  blueprint->SetComponent( "FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile( "r16slice.nii.gz" ) } } } );
  blueprint->SetComponent( "MovingImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile( "r64slice.nii.gz" ) } } } );
  blueprint->SetComponent( "RegistrationMethod", { { "NameOfClass", { "Niftyregf3dComponent" } } } );
  blueprint->SetComponent( "ResultImage", { { "NameOfClass", { "NiftyregWriteImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("Nifty_warped_r64to16.nii.gz") } } });
  blueprint->SetComponent( "Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } } );

  blueprint->SetConnection("FixedImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregReferenceImageInterface" } } });
  blueprint->SetConnection( "MovingImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregFloatingImageInterface" } } });
  blueprint->SetConnection("RegistrationMethod", "ResultImage", { {} }); //{ { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection( "RegistrationMethod", "Controller", { {} } );
  blueprint->SetConnection("ResultImage", "Controller", { {} });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set( blueprint );
  EXPECT_NO_THROW( superElastixFilter->SetBlueprint( superElastixFilterBlueprint ) );

  EXPECT_NO_THROW( superElastixFilter->Update() );
}
TEST_F(NiftyregComponentTest, ItkToNiftiImage)
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer(new Blueprint());
  blueprint->SetComponent("FixedImage", { { "NameOfClass", { "ItkToNiftiImageSourceReferenceComponent" } }, { "Dimensionality", { "3" } }, { "PixelType", { "float" } } } );
  blueprint->SetComponent("ResultImage", { { "NameOfClass", { "NiftyregWriteImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz") } } });
  blueprint->SetComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });

  blueprint->SetConnection("FixedImage", "ResultImage", { { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection("ResultImage", "Controller", { { "NameOfInterface", { "AfterRegistrationInterface" } } });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set(blueprint);
  EXPECT_NO_THROW(superElastixFilter->SetBlueprint(superElastixFilterBlueprint));

  // Set up the readers and writers
  auto fixedImageReader = itk::ImageFileReader<itk::Image<float, 3>>::New();
  fixedImageReader->SetFileName(dataManager->GetInputFile("sphereA3d.mhd"));

  // Connect SuperElastix in an itk pipeline
  superElastixFilter->SetInput("FixedImage", fixedImageReader->GetOutput());

  //EXPECT_NO_THROW(superElastixFilter->Update());
  superElastixFilter->Update();
}

TEST_F(NiftyregComponentTest, NiftiToItkImage)
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer(new Blueprint());
  // TODO proper 3d nii.gz input data
  //blueprint->SetComponent("FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile("r16slice.nii.gz") } } });
  blueprint->SetComponent("FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz") } } });
  blueprint->SetComponent("ResultDomainImage", { { "NameOfClass", { "ItkImageSourceComponent" } } });
  blueprint->SetComponent("ResultImage", { { "NameOfClass", { "NiftiToItkImageSinkComponent" } }, { "Dimensionality", { "3" } }, { "PixelType", { "float" } } });
  blueprint->SetComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });

  blueprint->SetConnection("FixedImage", "ResultImage", { { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection("ResultDomainImage", "ResultImage", { { "NameOfInterface", { "itkImageDomainFixedInterface" } } });
  blueprint->SetConnection("ResultImage", "Controller", { { "NameOfInterface", { "AfterRegistrationInterface" } } });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set(blueprint);
  EXPECT_NO_THROW(superElastixFilter->SetBlueprint(superElastixFilterBlueprint));

  // Set up the readers and writers
  auto fixedDomainImageReader = itk::ImageFileReader<itk::Image<float, 3>>::New();
  fixedDomainImageReader->SetFileName(this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz"));

  superElastixFilter->SetInput("ResultDomainImage", fixedDomainImageReader->GetOutput());

  auto fixedImageWriter = itk::ImageFileWriter<itk::Image<float, 3>>::New();
  fixedImageWriter->SetFileName(dataManager->GetOutputFile("NiftiToItkImage_converted.mhd"));

  // Connect SuperElastix in an itk pipeline
  fixedImageWriter->SetInput(superElastixFilter->GetOutput<itk::Image<float, 3>>("ResultImage") );

  //EXPECT_NO_THROW(superElastixFilter->Update());
  fixedImageWriter->Update();

}
}
<commit_msg>ENH: added niftyreg test running on WBIR demo data. #45<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxSuperElastixFilterCustomComponents.h"

#include "selxRegistrationController.h"

#include "selxNiftyregReadImageComponent.h"
#include "selxNiftyregWriteImageComponent.h"
#include "selxNiftyregWriteImageComponent.h"
#include "selxItkToNiftiImageSourceReferenceComponent.h"
#include "selxNiftiToItkImageSinkComponent.h"
#include "selxItkImageSource.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "selxNiftyregf3dComponent.h"
#include "selxDataManager.h"
#include "gtest/gtest.h"

namespace selx
{
class NiftyregComponentTest : public ::testing::Test
{
public:

  typedef std::unique_ptr< Blueprint >                       BlueprintPointer;
  typedef itk::UniquePointerDataObjectDecorator< Blueprint > BlueprintITKType;
  typedef BlueprintITKType::Pointer                          BlueprintITKPointer;
  typedef Blueprint::ParameterMapType                        ParameterMapType;
  typedef Blueprint::ParameterValueType                      ParameterValueType;
  typedef DataManager                                        DataManagerType;

  /** register all example components */
  typedef TypeList < Niftyregf3dComponent< float >,
    NiftyregReadImageComponent< float >,
    NiftyregWriteImageComponent< float >,
    ItkToNiftiImageSourceReferenceComponent< 2, float >,
    NiftiToItkImageSinkComponent<2, float>,
    ItkImageSourceComponent<2, float>,
    ItkToNiftiImageSourceReferenceComponent< 3, float >,
    NiftiToItkImageSinkComponent<3, float>,
    ItkImageSourceComponent<3, float>,
    RegistrationControllerComponent< >> RegisterComponents;

  typedef SuperElastixFilterCustomComponents< RegisterComponents > SuperElastixFilterType;
  virtual void SetUp()
  {
    // Instantiate SuperElastixFilter before each test and
    // register the components we want to have available in SuperElastix
    superElastixFilter = SuperElastixFilterType::New();
    dataManager        = DataManagerType::New();
  }

  virtual void TearDown()
  {
    // Unregister all components after each test
    itk::ObjectFactoryBase::UnRegisterAllFactories();
    // Delete the SuperElastixFilter after each test
    superElastixFilter = nullptr;
  }

  // Blueprint holds a configuration for SuperElastix
  BlueprintPointer            blueprint;
  SuperElastixFilterBase::Pointer superElastixFilter;
  // Data manager provides the paths to the input and output data for unit tests
  DataManagerType::Pointer dataManager;
};

TEST_F( NiftyregComponentTest, Register2d_nifti )
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer( new Blueprint() );
  blueprint->SetComponent( "FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile( "r16slice.nii.gz" ) } } } );
  blueprint->SetComponent( "MovingImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile( "r64slice.nii.gz" ) } } } );
  blueprint->SetComponent( "RegistrationMethod", { { "NameOfClass", { "Niftyregf3dComponent" } } } );
  blueprint->SetComponent( "ResultImage", { { "NameOfClass", { "NiftyregWriteImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("Nifty_warped_r64to16.nii.gz") } } });
  blueprint->SetComponent( "Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } } );

  blueprint->SetConnection("FixedImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregReferenceImageInterface" } } });
  blueprint->SetConnection( "MovingImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregFloatingImageInterface" } } });
  blueprint->SetConnection("RegistrationMethod", "ResultImage", { {} }); //{ { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection( "RegistrationMethod", "Controller", { {} } );
  blueprint->SetConnection("ResultImage", "Controller", { {} });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set( blueprint );
  EXPECT_NO_THROW( superElastixFilter->SetBlueprint( superElastixFilterBlueprint ) );

  EXPECT_NO_THROW( superElastixFilter->Update() );
}
TEST_F(NiftyregComponentTest, ItkToNiftiImage)
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer(new Blueprint());
  blueprint->SetComponent("FixedImage", { { "NameOfClass", { "ItkToNiftiImageSourceReferenceComponent" } }, { "Dimensionality", { "3" } }, { "PixelType", { "float" } } } );
  blueprint->SetComponent("ResultImage", { { "NameOfClass", { "NiftyregWriteImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz") } } });
  blueprint->SetComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });

  blueprint->SetConnection("FixedImage", "ResultImage", { { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection("ResultImage", "Controller", { { "NameOfInterface", { "AfterRegistrationInterface" } } });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set(blueprint);
  EXPECT_NO_THROW(superElastixFilter->SetBlueprint(superElastixFilterBlueprint));

  // Set up the readers and writers
  auto fixedImageReader = itk::ImageFileReader<itk::Image<float, 3>>::New();
  fixedImageReader->SetFileName(dataManager->GetInputFile("sphereA3d.mhd"));

  // Connect SuperElastix in an itk pipeline
  superElastixFilter->SetInput("FixedImage", fixedImageReader->GetOutput());

  //EXPECT_NO_THROW(superElastixFilter->Update());
  superElastixFilter->Update();
}

TEST_F(NiftyregComponentTest, NiftiToItkImage)
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer(new Blueprint());
  // TODO proper 3d nii.gz input data
  //blueprint->SetComponent("FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetInputFile("r16slice.nii.gz") } } });
  blueprint->SetComponent("FixedImage", { { "NameOfClass", { "NiftyregReadImageComponent" } }, { "FileName", { this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz") } } });
  blueprint->SetComponent("ResultDomainImage", { { "NameOfClass", { "ItkImageSourceComponent" } } });
  blueprint->SetComponent("ResultImage", { { "NameOfClass", { "NiftiToItkImageSinkComponent" } }, { "Dimensionality", { "3" } }, { "PixelType", { "float" } } });
  blueprint->SetComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });

  blueprint->SetConnection("FixedImage", "ResultImage", { { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection("ResultDomainImage", "ResultImage", { { "NameOfInterface", { "itkImageDomainFixedInterface" } } });
  blueprint->SetConnection("ResultImage", "Controller", { { "NameOfInterface", { "AfterRegistrationInterface" } } });

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set(blueprint);
  EXPECT_NO_THROW(superElastixFilter->SetBlueprint(superElastixFilterBlueprint));

  // Set up the readers and writers
  auto fixedDomainImageReader = itk::ImageFileReader<itk::Image<float, 3>>::New();
  fixedDomainImageReader->SetFileName(this->dataManager->GetOutputFile("ItkToNiftiImage_converted.nii.gz"));

  superElastixFilter->SetInput("ResultDomainImage", fixedDomainImageReader->GetOutput());

  auto fixedImageWriter = itk::ImageFileWriter<itk::Image<float, 3>>::New();
  fixedImageWriter->SetFileName(dataManager->GetOutputFile("NiftiToItkImage_converted.mhd"));

  // Connect SuperElastix in an itk pipeline
  fixedImageWriter->SetInput(superElastixFilter->GetOutput<itk::Image<float, 3>>("ResultImage") );

  //EXPECT_NO_THROW(superElastixFilter->Update());
  fixedImageWriter->Update();

}

TEST_F(NiftyregComponentTest, Register2d_itkImages)
{
  /** make example blueprint configuration */
  // todo: like WBIRDEMO, but set max iterations to 1 for speedy tests.
}

TEST_F(NiftyregComponentTest, WBIRDemo)
{
  /** make example blueprint configuration */
  BlueprintPointer blueprint = BlueprintPointer(new Blueprint());

  blueprint->SetComponent("RegistrationMethod", { { "NameOfClass", { "Niftyregf3dComponent" } } });
  blueprint->SetComponent("FixedImage", { { "NameOfClass", { "ItkToNiftiImageSourceReferenceComponent" } }, { "Dimensionality", { "2" } }, { "PixelType", { "float" } } });
  blueprint->SetComponent("MovingImage", { { "NameOfClass", { "ItkToNiftiImageSourceReferenceComponent" } }, { "Dimensionality", { "2" } }, { "PixelType", { "float" } } });
  blueprint->SetComponent("ResultImage", { { "NameOfClass", { "NiftiToItkImageSinkComponent" } }, { "Dimensionality", { "2" } }, { "PixelType", { "float" } } });
  blueprint->SetComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });

  blueprint->SetConnection("FixedImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregReferenceImageInterface" } } });
  blueprint->SetConnection("MovingImage", "RegistrationMethod", { { "NameOfInterface", { "NiftyregFloatingImageInterface" } } });
  blueprint->SetConnection("FixedImage", "ResultImage", { { "NameOfInterface", { "itkImageDomainFixedInterface" } } });
  blueprint->SetConnection("RegistrationMethod", "ResultImage", { { "NameOfInterface", { "NiftyregWarpedImageInterface" } } });
  blueprint->SetConnection("RegistrationMethod", "Controller", { {} });
  blueprint->SetConnection("ResultImage", "Controller", { {} });

  blueprint->Write(dataManager->GetOutputFile("Niftyreg_WBIR.dot"));

  // Set up the readers and writers
  typedef itk::Image< float, 2 >              Image2DType;
  typedef itk::ImageFileReader< Image2DType > ImageReader2DType;
  typedef itk::ImageFileWriter< Image2DType > ImageWriter2DType;

  ImageReader2DType::Pointer fixedImageReader = ImageReader2DType::New();
  fixedImageReader->SetFileName(dataManager->GetInputFile("coneA2d64.mhd"));

  ImageReader2DType::Pointer movingImageReader = ImageReader2DType::New();
  movingImageReader->SetFileName(dataManager->GetInputFile("coneB2d64.mhd"));

  ImageWriter2DType::Pointer resultImageWriter = ImageWriter2DType::New();
  resultImageWriter->SetFileName(dataManager->GetOutputFile("Niftyreg_WBIR_Image.mhd"));

  //DisplacementImageWriter2DType::Pointer resultDisplacementWriter = DisplacementImageWriter2DType::New();
  //resultDisplacementWriter->SetFileName(dataManager->GetOutputFile("Niftyreg_WBIR_Displacement.mhd"));

  // Connect SuperElastix in an itk pipeline
  superElastixFilter->SetInput("FixedImage", fixedImageReader->GetOutput());
  superElastixFilter->SetInput("MovingImage", movingImageReader->GetOutput());
  resultImageWriter->SetInput(superElastixFilter->GetOutput< Image2DType >("ResultImage"));
  //resultDisplacementWriter->SetInput(superElastixFilter->GetOutput< DisplacementImage2DType >("ResultDisplacementFieldSink"));

  BlueprintITKPointer superElastixFilterBlueprint = BlueprintITKType::New();
  superElastixFilterBlueprint->Set(blueprint);
  EXPECT_NO_THROW(superElastixFilter->SetBlueprint(superElastixFilterBlueprint));

  //Optional Update call
  //superElastixFilter->Update();

  // Update call on the writers triggers SuperElastix to configure and execute
  EXPECT_NO_THROW(resultImageWriter->Update());
  //EXPECT_NO_THROW(resultDisplacementWriter->Update());
}
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Shantanu Tushar <shaan7in@gmail.com>
 * Copyright (C) 2010 Laszlo Papp <lpapp@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "commentitemsmodel.h"

#include "allgameitemsmodel.h"
#include "gamemanager.h"

#include "serviceprovider.h"
#include <commentslistjob.h>
#include <commentuploadjob.h>

#include <engine/gameproject.h>

#include <core/gluonobject.h>
#include <core/gdlserializer.h>
#include <gluon_global.h>

#include <attica/listjob.h>

#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QDir>

using namespace GluonCore;
using namespace GluonPlayer;

class CommentItemsModel::Private
{
    public:
    Private()
    {
    }

    GluonCore::GluonObject* m_rootNode;
    QStringList m_columnNames;
    bool m_isOnline;
    QString m_gameId;
    QList<GluonCore::GluonObject*> m_nodes;
};

CommentItemsModel::CommentItemsModel( QString gameId, QObject* parent )
    : QAbstractListModel( parent )
    , d(new Private)
{
    d->m_rootNode = new GluonObject( "Comment", this );
    d->m_isOnline = false;
    d->m_gameId = gameId;
    d->m_columnNames << tr( "Author" ) << tr( "Title" ) << tr( "Body" ) << tr( "DateTime" ) << tr( "Rating" );

    loadData();     // Load comments stored locally
    updateData();   // Fetch latest comments from the web service

}

QHash<int, QByteArray> CommentItemsModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[AuthorRole] = "author";
    roles[TitleRole] = "title";
    roles[BodyRole] = "body";
    roles[DateTimeRole] = "dateTime";
    roles[RatingRole] = "rating";
    roles[DepthRole] = "depth";
    roles[ParentIdRole] = "parentId";
    return roles;
}

void CommentItemsModel::updateData()
{
    clear();
    CommentsListJob *commentListJob = ServiceProvider::instance()->fetchCommentList(d->m_gameId, 0, 0);
    connect(commentListJob, SIGNAL(succeeded()), SLOT(processFetchedComments()));
    connect(commentListJob, SIGNAL(failed()), SIGNAL(commentListFetchFailed()));
    commentListJob->start();
}

void CommentItemsModel::processFetchedComments()
{
    QList<CommentItem*> list = qobject_cast<CommentsListJob*>(sender())->data().value< QList<CommentItem*> >();
    qDebug() << list.count() << " comments Successfully Fetched from the server!";
    foreach(CommentItem *comment, list) {
        addComment(comment, d->m_rootNode);
    }

    beginResetModel();
    treeTraversal(d->m_rootNode);
    endResetModel();
    d->m_isOnline = true;
}

void CommentItemsModel::addCommentFinished( Attica::BaseJob* job )
{
    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment>*>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        updateData();
    }
    else
    {
        emit addCommentFailed();
    }
}

GluonObject* CommentItemsModel::addComment( CommentItem* comment, GluonObject* parent )
{
    GluonObject* newComment = new GluonObject( comment->id(), parent );
    newComment->setProperty( "Author", comment->user() );
    newComment->setProperty( "Title", comment->subject() );
    newComment->setProperty( "Body", comment->text() );
    newComment->setProperty( "DateTime", comment->dateTime().toString() );
    newComment->setProperty( "Rating", comment->score() );
    newComment->setProperty( "Depth", parent->property("Depth").toInt() + 1 );
    newComment->setProperty( "ParentId", parent->name() );

    foreach( QObject *child, comment->children() ) {
        addComment( static_cast<CommentItem*>(child), newComment );
    }

    return newComment;
}

void CommentItemsModel::treeTraversal( GluonCore::GluonObject* obj )
{
    if( !obj )
        return;

    foreach( QObject * child, obj->children() )
    {
        GluonObject* gobj = qobject_cast<GluonObject*>( child );
        if( gobj )
        {
            d->m_nodes.append( gobj );
            treeTraversal( gobj );
        }
    }
}

bool dateTimeLessThan( GluonCore::GluonObject* go1, GluonCore::GluonObject* go2 )
{
    return go1->property( "DateTime" ).toString() < go2->property( "DateTime" ).toString();
}

void CommentItemsModel::loadData()
{
    AllGameItemsModel *model = qobject_cast<AllGameItemsModel*>(GameManager::instance()->allGamesModel());
    QString gameCachePath = model->data(d->m_gameId, AllGameItemsModel::CacheUriRole).toUrl().toLocalFile();

    GluonCore::GluonObjectList list;
    if( gameCachePath.isEmpty() || !GluonCore::GDLSerializer::instance()->read( QUrl( gameCachePath + "/comments.gdl" ), list ) )
        return;

    d->m_rootNode = list.at( 0 );
    treeTraversal( d->m_rootNode );
    qSort( d->m_nodes.begin(), d->m_nodes.end(), dateTimeLessThan );
}

void CommentItemsModel::saveData()
{
    if (d->m_gameId.isEmpty()) {
        qDebug() << "Failed to save the comment data for empty game id.";
        return;
    }

    qDebug() << "Saving data!";

    AllGameItemsModel *model = qobject_cast<AllGameItemsModel*>(GameManager::instance()->allGamesModel());
    QString gameCachePath = model->data(d->m_gameId, AllGameItemsModel::CacheUriRole).toUrl().toLocalFile();

    QDir gameCacheDir;
    gameCacheDir.mkpath( gameCachePath );
    gameCacheDir.cd( gameCachePath );
    QString filename = gameCacheDir.absoluteFilePath( "comments.gdl" );

    GluonCore::GDLSerializer::instance()->write( QUrl::fromLocalFile(filename), GluonCore::GluonObjectList() << d->m_rootNode );
}

CommentItemsModel::~CommentItemsModel()
{
    saveData();     //Save data before exiting
}

QVariant CommentItemsModel::data( const QModelIndex& index, int role ) const
{
    if (index.row() >= rowCount())
        return QVariant();

    switch (role) {
        case AuthorRole:
            return d->m_nodes.at(index.row())->property( "Author" );
        case TitleRole:
            return d->m_nodes.at(index.row())->property( "Title" );
        case BodyRole:
            return d->m_nodes.at(index.row())->property( "Body" );
        case DateTimeRole:
            return d->m_nodes.at(index.row())->property( "DateTime" );
        case RatingRole:
            return d->m_nodes.at(index.row())->property( "Rating" );
        case DepthRole:
            return d->m_nodes.at(index.row())->property( "Depth" );
        case ParentIdRole:
            return d->m_nodes.at(index.row())->property( "ParentId" );
    }

    return QVariant();
}

int CommentItemsModel::rowCount( const QModelIndex& /* parent */ ) const
{
    return d->m_nodes.count();
}

QVariant CommentItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
        return d->m_columnNames.at( section );

    return QVariant();
}

Qt::ItemFlags CommentItemsModel::flags( const QModelIndex& index ) const
{
    if( !index.isValid() )
        return Qt::ItemIsEnabled;

    return QAbstractItemModel::flags( index );
}

void CommentItemsModel::uploadComment( const QModelIndex& parentIndex, const QString& subject, const QString& message )
{
    uploadComment(d->m_nodes.at(parentIndex.row())->name(), subject, message);
}

void CommentItemsModel::uploadComment( const QString &parentId, const QString& subject, const QString& message )
{
    if( d->m_gameId.isEmpty() )
    {
        qDebug() << "Invalid game id, can't upload comment";
        return;
    } else {
        qDebug() << "id: " << parentId << " | subject:" << subject << " | message:" << message << "\n";
    }
    CommentUploadJob *commentsUploadJob = ServiceProvider::instance()->uploadComment(d->m_gameId,
                                                                                parentId,
                                                                                subject, message);
    connect(commentsUploadJob, SIGNAL(succeeded()), SLOT(uploadCommentFinished()));
    connect(commentsUploadJob, SIGNAL(failed()), SIGNAL(addCommentFailed()));
    commentsUploadJob->start();
}

QString CommentItemsModel::gameId() const
{
    return d->m_gameId;
}

void CommentItemsModel::setGameId( const QString& id )
{
    if (id.isEmpty())
        return;
    d->m_gameId = id;
    updateData();   // Fetch latest comments from the web serviceprovider
    emit gameIdChanged();
}

void CommentItemsModel::clear()
{
    if (d->m_rootNode) {
        qDeleteAll(d->m_rootNode->children());
    }
    d->m_nodes.clear();
}

void CommentItemsModel::uploadCommentFinished()
{
    qDebug() << "upload comment went well";
    updateData();
}
<commit_msg>deleted 2 useless qdebugs<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Shantanu Tushar <shaan7in@gmail.com>
 * Copyright (C) 2010 Laszlo Papp <lpapp@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "commentitemsmodel.h"

#include "allgameitemsmodel.h"
#include "gamemanager.h"

#include "serviceprovider.h"
#include <commentslistjob.h>
#include <commentuploadjob.h>

#include <engine/gameproject.h>

#include <core/gluonobject.h>
#include <core/gdlserializer.h>
#include <gluon_global.h>

#include <attica/listjob.h>

#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QDir>

using namespace GluonCore;
using namespace GluonPlayer;

class CommentItemsModel::Private
{
    public:
    Private()
    {
    }

    GluonCore::GluonObject* m_rootNode;
    QStringList m_columnNames;
    bool m_isOnline;
    QString m_gameId;
    QList<GluonCore::GluonObject*> m_nodes;
};

CommentItemsModel::CommentItemsModel( QString gameId, QObject* parent )
    : QAbstractListModel( parent )
    , d(new Private)
{
    d->m_rootNode = new GluonObject( "Comment", this );
    d->m_isOnline = false;
    d->m_gameId = gameId;
    d->m_columnNames << tr( "Author" ) << tr( "Title" ) << tr( "Body" ) << tr( "DateTime" ) << tr( "Rating" );

    loadData();     // Load comments stored locally
    updateData();   // Fetch latest comments from the web service

}

QHash<int, QByteArray> CommentItemsModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[AuthorRole] = "author";
    roles[TitleRole] = "title";
    roles[BodyRole] = "body";
    roles[DateTimeRole] = "dateTime";
    roles[RatingRole] = "rating";
    roles[DepthRole] = "depth";
    roles[ParentIdRole] = "parentId";
    return roles;
}

void CommentItemsModel::updateData()
{
    clear();
    CommentsListJob *commentListJob = ServiceProvider::instance()->fetchCommentList(d->m_gameId, 0, 0);
    connect(commentListJob, SIGNAL(succeeded()), SLOT(processFetchedComments()));
    connect(commentListJob, SIGNAL(failed()), SIGNAL(commentListFetchFailed()));
    commentListJob->start();
}

void CommentItemsModel::processFetchedComments()
{
    QList<CommentItem*> list = qobject_cast<CommentsListJob*>(sender())->data().value< QList<CommentItem*> >();
    qDebug() << list.count() << " comments Successfully Fetched from the server!";
    foreach(CommentItem *comment, list) {
        addComment(comment, d->m_rootNode);
    }

    beginResetModel();
    treeTraversal(d->m_rootNode);
    endResetModel();
    d->m_isOnline = true;
}

void CommentItemsModel::addCommentFinished( Attica::BaseJob* job )
{
    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment>*>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        updateData();
    }
    else
    {
        emit addCommentFailed();
    }
}

GluonObject* CommentItemsModel::addComment( CommentItem* comment, GluonObject* parent )
{
    GluonObject* newComment = new GluonObject( comment->id(), parent );
    newComment->setProperty( "Author", comment->user() );
    newComment->setProperty( "Title", comment->subject() );
    newComment->setProperty( "Body", comment->text() );
    newComment->setProperty( "DateTime", comment->dateTime().toString() );
    newComment->setProperty( "Rating", comment->score() );
    newComment->setProperty( "Depth", parent->property("Depth").toInt() + 1 );
    newComment->setProperty( "ParentId", parent->name() );

    foreach( QObject *child, comment->children() ) {
        addComment( static_cast<CommentItem*>(child), newComment );
    }

    return newComment;
}

void CommentItemsModel::treeTraversal( GluonCore::GluonObject* obj )
{
    if( !obj )
        return;

    foreach( QObject * child, obj->children() )
    {
        GluonObject* gobj = qobject_cast<GluonObject*>( child );
        if( gobj )
        {
            d->m_nodes.append( gobj );
            treeTraversal( gobj );
        }
    }
}

bool dateTimeLessThan( GluonCore::GluonObject* go1, GluonCore::GluonObject* go2 )
{
    return go1->property( "DateTime" ).toString() < go2->property( "DateTime" ).toString();
}

void CommentItemsModel::loadData()
{
    AllGameItemsModel *model = qobject_cast<AllGameItemsModel*>(GameManager::instance()->allGamesModel());
    QString gameCachePath = model->data(d->m_gameId, AllGameItemsModel::CacheUriRole).toUrl().toLocalFile();

    GluonCore::GluonObjectList list;
    if( gameCachePath.isEmpty() || !GluonCore::GDLSerializer::instance()->read( QUrl( gameCachePath + "/comments.gdl" ), list ) )
        return;

    d->m_rootNode = list.at( 0 );
    treeTraversal( d->m_rootNode );
    qSort( d->m_nodes.begin(), d->m_nodes.end(), dateTimeLessThan );
}

void CommentItemsModel::saveData()
{
    if (d->m_gameId.isEmpty()) {
        qDebug() << "Failed to save the comment data for empty game id.";
        return;
    }

    qDebug() << "Saving data!";

    AllGameItemsModel *model = qobject_cast<AllGameItemsModel*>(GameManager::instance()->allGamesModel());
    QString gameCachePath = model->data(d->m_gameId, AllGameItemsModel::CacheUriRole).toUrl().toLocalFile();

    QDir gameCacheDir;
    gameCacheDir.mkpath( gameCachePath );
    gameCacheDir.cd( gameCachePath );
    QString filename = gameCacheDir.absoluteFilePath( "comments.gdl" );

    GluonCore::GDLSerializer::instance()->write( QUrl::fromLocalFile(filename), GluonCore::GluonObjectList() << d->m_rootNode );
}

CommentItemsModel::~CommentItemsModel()
{
    saveData();     //Save data before exiting
}

QVariant CommentItemsModel::data( const QModelIndex& index, int role ) const
{
    if (index.row() >= rowCount())
        return QVariant();

    switch (role) {
        case AuthorRole:
            return d->m_nodes.at(index.row())->property( "Author" );
        case TitleRole:
            return d->m_nodes.at(index.row())->property( "Title" );
        case BodyRole:
            return d->m_nodes.at(index.row())->property( "Body" );
        case DateTimeRole:
            return d->m_nodes.at(index.row())->property( "DateTime" );
        case RatingRole:
            return d->m_nodes.at(index.row())->property( "Rating" );
        case DepthRole:
            return d->m_nodes.at(index.row())->property( "Depth" );
        case ParentIdRole:
            return d->m_nodes.at(index.row())->property( "ParentId" );
    }

    return QVariant();
}

int CommentItemsModel::rowCount( const QModelIndex& /* parent */ ) const
{
    return d->m_nodes.count();
}

QVariant CommentItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
        return d->m_columnNames.at( section );

    return QVariant();
}

Qt::ItemFlags CommentItemsModel::flags( const QModelIndex& index ) const
{
    if( !index.isValid() )
        return Qt::ItemIsEnabled;

    return QAbstractItemModel::flags( index );
}

void CommentItemsModel::uploadComment( const QModelIndex& parentIndex, const QString& subject, const QString& message )
{
    uploadComment(d->m_nodes.at(parentIndex.row())->name(), subject, message);
}

void CommentItemsModel::uploadComment( const QString &parentId, const QString& subject, const QString& message )
{
    if( d->m_gameId.isEmpty() )
    {
        qDebug() << "Invalid game id, can't upload comment";
        return;
    }
    CommentUploadJob *commentsUploadJob = ServiceProvider::instance()->uploadComment(d->m_gameId,
                                                                                parentId,
                                                                                subject, message);
    connect(commentsUploadJob, SIGNAL(succeeded()), SLOT(uploadCommentFinished()));
    connect(commentsUploadJob, SIGNAL(failed()), SIGNAL(addCommentFailed()));
    commentsUploadJob->start();
}

QString CommentItemsModel::gameId() const
{
    return d->m_gameId;
}

void CommentItemsModel::setGameId( const QString& id )
{
    if (id.isEmpty())
        return;
    d->m_gameId = id;
    updateData();   // Fetch latest comments from the web serviceprovider
    emit gameIdChanged();
}

void CommentItemsModel::clear()
{
    if (d->m_rootNode) {
        qDeleteAll(d->m_rootNode->children());
    }
    d->m_nodes.clear();
}

void CommentItemsModel::uploadCommentFinished()
{
    updateData();
}
<|endoftext|>


<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/
#include <mitkContourModelMapper3D.h>

#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkProperty.h>

mitk::ContourModelMapper3D::ContourModelMapper3D()
{
}

mitk::ContourModelMapper3D::~ContourModelMapper3D()
{
}

const mitk::ContourModel *mitk::ContourModelMapper3D::GetInput(void)
{
  // convient way to get the data from the dataNode
  return static_cast<const mitk::ContourModel *>(GetDataNode()->GetData());
}

vtkProp *mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer *renderer)
{
  // return the actor corresponding to the renderer
  return m_LSH.GetLocalStorage(renderer)->m_Actor;
}

void mitk::ContourModelMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
  /* First convert the contourModel to vtkPolyData, then tube filter it and
   * set it input for our mapper
   */

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  auto *inputContour = static_cast<mitk::ContourModel *>(GetDataNode()->GetData());

  localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour);

  this->ApplyContourProperties(renderer);

  // tube filter the polyData
  localStorage->m_TubeFilter->SetInputData(localStorage->m_OutlinePolyData);

  float lineWidth(1.0);
  if (this->GetDataNode()->GetFloatProperty("contour.3D.width", lineWidth, renderer))
  {
    localStorage->m_TubeFilter->SetRadius(lineWidth);
  }
  else
  {
    localStorage->m_TubeFilter->SetRadius(0.5);
  }
  localStorage->m_TubeFilter->CappingOn();
  localStorage->m_TubeFilter->SetNumberOfSides(10);
  localStorage->m_TubeFilter->Update();
  localStorage->m_Mapper->SetInputConnection(localStorage->m_TubeFilter->GetOutputPort());
}

void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer *renderer)
{
  bool visible = true;
  GetDataNode()->GetVisibility(visible, renderer, "visible");

  auto *data = static_cast<mitk::ContourModel *>(GetDataNode()->GetData());
  if (data == nullptr)
  {
    return;
  }

  // Calculate time step of the input data for the specified renderer (integer value)
  this->CalculateTimeStep(renderer);

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
  // Check if time step is valid
  const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
  if ((dataTimeGeometry == nullptr) || (dataTimeGeometry->CountTimeSteps() == 0) ||
      (!dataTimeGeometry->IsValidTimeStep(renderer->GetTimeStep())) || (this->GetTimestep() == -1))
  {
    // clear the rendered polydata
    localStorage->m_Mapper->SetInputData(vtkSmartPointer<vtkPolyData>::New());
    return;
  }

  const DataNode *node = this->GetDataNode();
  data->UpdateOutputInformation();

  // check if something important has changed and we need to rerender
  if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified?
      ||
      (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified?
      ||
      (localStorage->m_LastUpdateTime <
       renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified?
      ||
      (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) ||
      (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified?
      ||
      (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()))
  {
    this->GenerateDataForRenderer(renderer);
  }

  // since we have checked that nothing important has changed, we can set
  // m_LastUpdateTime to the current time
  localStorage->m_LastUpdateTime.Modified();
}

vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel *inputContour)
{
  unsigned int timestep = this->GetTimestep();

  // the points to draw
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  // the lines to connect the points
  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
  // Create a polydata to store everything in
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  // iterate over the control points
  auto current = inputContour->IteratorBegin(timestep);
  auto next = inputContour->IteratorBegin(timestep);
  if (next != inputContour->IteratorEnd(timestep))
  {
    next++;

    auto end = inputContour->IteratorEnd(timestep);

    while (next != end)
    {
      mitk::ContourModel::VertexType *currentControlPoint = *current;
      mitk::ContourModel::VertexType *nextControlPoint = *next;

      if (!(currentControlPoint->Coordinates[0] == nextControlPoint->Coordinates[0] &&
            currentControlPoint->Coordinates[1] == nextControlPoint->Coordinates[1] &&
            currentControlPoint->Coordinates[2] == nextControlPoint->Coordinates[2]))
      {
        vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0],
                                               currentControlPoint->Coordinates[1],
                                               currentControlPoint->Coordinates[2]);
        vtkIdType p2 = points->InsertNextPoint(
          nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
        // add the line between both contorlPoints
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
      current++;
      next++;
    }

    if (inputContour->IsClosed(timestep))
    {
      // If the contour is closed add a line from the last to the first control point
      mitk::ContourModel::VertexType *firstControlPoint = *(inputContour->IteratorBegin(timestep));
      mitk::ContourModel::VertexType *lastControlPoint = *(--(inputContour->IteratorEnd(timestep)));
      if (lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] ||
          lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] ||
          lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2])
      {
        vtkIdType p2 = points->InsertNextPoint(
          lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
        vtkIdType p1 = points->InsertNextPoint(
          firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);

        // add the line to the cellArray
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
    }

    // Add the points to the dataset
    polyData->SetPoints(points);
    // Add the lines to the dataset
    polyData->SetLines(lines);
  }
  return polyData;
}

void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer *renderer)
{
  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ColorProperty::Pointer colorprop =
    dynamic_cast<mitk::ColorProperty *>(GetDataNode()->GetProperty("contour.color", renderer));
  if (colorprop)
  {
    // set the color of the contour
    double red = colorprop->GetColor().GetRed();
    double green = colorprop->GetColor().GetGreen();
    double blue = colorprop->GetColor().GetBlue();
    localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
  }
}

/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/

mitk::ContourModelMapper3D::LocalStorage *mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer *renderer)
{
  return m_LSH.GetLocalStorage(renderer);
}

mitk::ContourModelMapper3D::LocalStorage::LocalStorage()
{
  m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  m_Actor = vtkSmartPointer<vtkActor>::New();
  m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
  m_TubeFilter = vtkSmartPointer<vtkTubeFilter>::New();

  // set the mapper for the actor
  m_Actor->SetMapper(m_Mapper);
}

void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode *node,
                                                      mitk::BaseRenderer *renderer,
                                                      bool overwrite)
{
  node->AddProperty("color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
  node->AddProperty("contour.3D.width", mitk::FloatProperty::New(0.5), renderer, overwrite);

  Superclass::SetDefaultProperties(node, renderer, overwrite);
}
<commit_msg>Fixed T27517<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/
#include <mitkContourModelMapper3D.h>

#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkProperty.h>

mitk::ContourModelMapper3D::ContourModelMapper3D()
{
}

mitk::ContourModelMapper3D::~ContourModelMapper3D()
{
}

const mitk::ContourModel *mitk::ContourModelMapper3D::GetInput(void)
{
  // convient way to get the data from the dataNode
  return static_cast<const mitk::ContourModel *>(GetDataNode()->GetData());
}

vtkProp *mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer *renderer)
{
  // return the actor corresponding to the renderer
  return m_LSH.GetLocalStorage(renderer)->m_Actor;
}

void mitk::ContourModelMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
  /* First convert the contourModel to vtkPolyData, then tube filter it and
   * set it input for our mapper
   */

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  auto *inputContour = static_cast<mitk::ContourModel *>(GetDataNode()->GetData());

  localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour);

  this->ApplyContourProperties(renderer);

  // tube filter the polyData
  localStorage->m_TubeFilter->SetInputData(localStorage->m_OutlinePolyData);

  float lineWidth(1.0);
  if (this->GetDataNode()->GetFloatProperty("contour.3D.width", lineWidth, renderer))
  {
    localStorage->m_TubeFilter->SetRadius(lineWidth);
  }
  else
  {
    localStorage->m_TubeFilter->SetRadius(0.5);
  }
  localStorage->m_TubeFilter->CappingOn();
  localStorage->m_TubeFilter->SetNumberOfSides(10);
  localStorage->m_TubeFilter->Update();
  localStorage->m_Mapper->SetInputConnection(localStorage->m_TubeFilter->GetOutputPort());
}

void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer *renderer)
{
  bool visible = true;
  GetDataNode()->GetVisibility(visible, renderer, "visible");

  auto *data = static_cast<mitk::ContourModel *>(GetDataNode()->GetData());
  if (data == nullptr)
  {
    return;
  }

  // Calculate time step of the input data for the specified renderer (integer value)
  this->CalculateTimeStep(renderer);

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
  // Check if time step is valid
  const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
  if ((dataTimeGeometry == nullptr) || (dataTimeGeometry->CountTimeSteps() == 0) ||
      (!dataTimeGeometry->IsValidTimePoint(renderer->GetTime())) || (this->GetTimestep() == -1))
  {
    // clear the rendered polydata
    localStorage->m_Mapper->SetInputData(vtkSmartPointer<vtkPolyData>::New());
    return;
  }

  const DataNode *node = this->GetDataNode();
  data->UpdateOutputInformation();

  // check if something important has changed and we need to rerender
  if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified?
      ||
      (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified?
      ||
      (localStorage->m_LastUpdateTime <
       renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified?
      ||
      (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) ||
      (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified?
      ||
      (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()))
  {
    this->GenerateDataForRenderer(renderer);
  }

  // since we have checked that nothing important has changed, we can set
  // m_LastUpdateTime to the current time
  localStorage->m_LastUpdateTime.Modified();
}

vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel *inputContour)
{
  unsigned int timestep = this->GetTimestep();

  // the points to draw
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  // the lines to connect the points
  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
  // Create a polydata to store everything in
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  // iterate over the control points
  auto current = inputContour->IteratorBegin(timestep);
  auto next = inputContour->IteratorBegin(timestep);
  if (next != inputContour->IteratorEnd(timestep))
  {
    next++;

    auto end = inputContour->IteratorEnd(timestep);

    while (next != end)
    {
      mitk::ContourModel::VertexType *currentControlPoint = *current;
      mitk::ContourModel::VertexType *nextControlPoint = *next;

      if (!(currentControlPoint->Coordinates[0] == nextControlPoint->Coordinates[0] &&
            currentControlPoint->Coordinates[1] == nextControlPoint->Coordinates[1] &&
            currentControlPoint->Coordinates[2] == nextControlPoint->Coordinates[2]))
      {
        vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0],
                                               currentControlPoint->Coordinates[1],
                                               currentControlPoint->Coordinates[2]);
        vtkIdType p2 = points->InsertNextPoint(
          nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
        // add the line between both contorlPoints
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
      current++;
      next++;
    }

    if (inputContour->IsClosed(timestep))
    {
      // If the contour is closed add a line from the last to the first control point
      mitk::ContourModel::VertexType *firstControlPoint = *(inputContour->IteratorBegin(timestep));
      mitk::ContourModel::VertexType *lastControlPoint = *(--(inputContour->IteratorEnd(timestep)));
      if (lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] ||
          lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] ||
          lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2])
      {
        vtkIdType p2 = points->InsertNextPoint(
          lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
        vtkIdType p1 = points->InsertNextPoint(
          firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);

        // add the line to the cellArray
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
    }

    // Add the points to the dataset
    polyData->SetPoints(points);
    // Add the lines to the dataset
    polyData->SetLines(lines);
  }
  return polyData;
}

void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer *renderer)
{
  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ColorProperty::Pointer colorprop =
    dynamic_cast<mitk::ColorProperty *>(GetDataNode()->GetProperty("contour.color", renderer));
  if (colorprop)
  {
    // set the color of the contour
    double red = colorprop->GetColor().GetRed();
    double green = colorprop->GetColor().GetGreen();
    double blue = colorprop->GetColor().GetBlue();
    localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
  }
}

/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/

mitk::ContourModelMapper3D::LocalStorage *mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer *renderer)
{
  return m_LSH.GetLocalStorage(renderer);
}

mitk::ContourModelMapper3D::LocalStorage::LocalStorage()
{
  m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  m_Actor = vtkSmartPointer<vtkActor>::New();
  m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
  m_TubeFilter = vtkSmartPointer<vtkTubeFilter>::New();

  // set the mapper for the actor
  m_Actor->SetMapper(m_Mapper);
}

void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode *node,
                                                      mitk::BaseRenderer *renderer,
                                                      bool overwrite)
{
  node->AddProperty("color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
  node->AddProperty("contour.3D.width", mitk::FloatProperty::New(0.5), renderer, overwrite);

  Superclass::SetDefaultProperties(node, renderer, overwrite);
}
<|endoftext|>