text:
#include "ReportBuilder.h"
#include "ReportDBManager.h"

#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <sstream>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <unordered_map>
#include <numeric>

struct ReportBuilder::ReportStructure
{
	ReportStructure()
	{
	}

	~ReportStructure()
	{}

	std::shared_ptr<TextReport> assemble(Report::ID id)
	{return std::shared_ptr<TextReport>(new TextReport(id));}

	struct
	{
		std::string title;
		std::string heading;
		std::string footer;
		boost::optional<unsigned int> iterations;
		boost::optional<std::chrono::time_point<std::chrono::system_clock> > timestamp;
		boost::optional<std::chrono::system_clock::duration> trainingDuration;
	} general;

	struct Results
	{
		boost::optional<double> rms;
		boost::optional<double> spread;
		boost::optional<double> accurracy;
		boost::optional<double> recall;
		boost::optional<double> precision;
		boost::optional<double> fmeasure;
		boost::optional<unsigned int> correct;
		boost::optional<unsigned int> incorrect;
		boost::optional<unsigned int> trainingObjects;
		boost::optional<unsigned int> testObjects;
	} totals;

	struct ClassData
	{
		boost::optional<int> mapping;
		Results results;
		boost::optional<std::unordered_map<ClassName, std::vector<ObjectDescription> > > classifiedAs;
	};

	boost::optional<std::unordered_map<ClassName, ClassData> > details;
};

class TextReportBuilder::Printer
{
public:
	virtual void printHeader(std::ostream&, Report::ID, std::shared_ptr<ReportStructure>);
	virtual void printFooter(std::ostream&, std::shared_ptr<ReportStructure>);
	virtual void printOverallResults(std::ostream&, std::shared_ptr<ReportStructure>);
	virtual void printClassesHeader(std::ostream&);
	virtual void printSingleClassResults(std::ostream&, const ClassName&, const ReportBuilder::ReportStructure::ClassData&);
	virtual void printDetailedResults(std::ostream&, std::shared_ptr<ReportStructure>);

private:
	virtual std::string serializeObjectDescription(const ObjectDescription&);
};

template<typename T>
std::ostream& operator<<(std::ostream& str, const boost::optional<T>& opt)
{
	if(!opt)
		str << "N/A";
	else
		str << opt.get();

	return str;
}

ReportBuilder::ReportBuilder(std::shared_ptr<ReportDBManager> repDBManager) : reportDBManager(repDBManager)
{
}

ReportBuilder::~ReportBuilder()
{}

Report::ID ReportBuilder::startReport(Classifier* classifier)
{
	IR_ASSERT(pendingReports.find(classifier) == pendingReports.end(), "Trying to add same report twice");

	Report::ID reportID = reportDBManager->getNextReportID();
	std::shared_ptr<ReportStructure> report(new ReportStructure);

	pendingReports.insert(std::make_pair(classifier, reportID));
	reportsCache.insert(std::make_pair(reportID, report));

	return reportID;
}

void ReportBuilder::endReport(Classifier* classifier)
{
	IR_ASSERT(pendingReports.count(classifier) == 1, "Trying to finish already finished or not even started report");

	endReport(pendingReports.at(classifier));
	pendingReports.erase(pendingReports.find(classifier));
}

void ReportBuilder::endReport(Report::ID id)
{
	reportDBManager->putReport(id, assemble(id));
	finishedReports.push_back(reportsCache.at(id));
	reportsCache.erase(id);
}

void ReportBuilder::enableClassDetails(std::shared_ptr<ReportBuilder::ReportStructure> rs, const ClassName& cn)
{
	if(!rs->details)
		rs->details = boost::make_optional(std::unordered_map<ClassName, ReportStructure::ClassData>());

	if(rs->details.get().count(cn) == 0)
		rs->details.get().insert(std::make_pair(cn, ReportStructure::ClassData()));
}

void ReportBuilder::addTitle(Classifier* c , const std::string& s)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.title = s;
}

void ReportBuilder::addHeader(Classifier* c, const std::string& s)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.heading = s;
}

void ReportBuilder::addFooter(Classifier* c, const std::string& s)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.footer = s;
}

void ReportBuilder::addNumberOfIterations(Classifier* c, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.iterations = i;
}

void ReportBuilder::addDate(Classifier* c, std::chrono::time_point<std::chrono::system_clock> t)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.timestamp = t;
}

void ReportBuilder::addSpreadSingle(Classifier* c, const ClassName& cn, double res)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.spread = res;
}

void ReportBuilder::addSpreadTotal(Classifier* c, double res)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	rep->totals.spread = res;
}

void ReportBuilder::addAccurracySingle(Classifier* c, const ClassName& cn, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.accurracy = i;
}

void ReportBuilder::addAccurracyTotal(Classifier* c, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.accurracy = i;
}

void ReportBuilder::addRecallSingle(Classifier* c, const ClassName& cn, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.recall = i;
}

void ReportBuilder::addRecallTotal(Classifier* c, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.recall = i;
}

void ReportBuilder::addPrecisionSingle(Classifier* c, const ClassName& cn, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.precision = i;
}

void ReportBuilder::addPrecisionTotal(Classifier* c, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.precision = i;
}

void ReportBuilder::addFMeasureSingle(Classifier* c, const ClassName& cn, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.fmeasure = i;
}

void ReportBuilder::addFMeasureTotal(Classifier* c, double i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.fmeasure = i;
}

void ReportBuilder::addTrainingDuration(Classifier* c, std::chrono::system_clock::duration t)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->general.trainingDuration = t;
}

void ReportBuilder::addClassifiedCorrectSingle(Classifier* c, const ClassName& cn, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.correct = i;
}
void ReportBuilder::addClassifiedIncorrectSingle(Classifier* c, const ClassName& cn, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.incorrect = i;
}
void ReportBuilder::addClassifiedIncorrectTotal(Classifier* c, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.incorrect = i;
}
void ReportBuilder::addClassifiedCorrectTotal(Classifier* c, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.correct = i;
}
void ReportBuilder::addRMSSingle(Classifier* c, const ClassName& cn, double d)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.rms = d;
}
void ReportBuilder::addRMSTotal(Classifier* c, double d)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.rms = d;
}
void ReportBuilder::addClassToNumberMapping(Classifier* c, const ClassName& cn, int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).mapping = i;
}
void ReportBuilder::addTestObjectCount(Classifier* c, const ClassName& cn, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.testObjects = i;
}
void ReportBuilder::addTrainingObjectCount(Classifier* c, const ClassName& cn, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, cn);

	rep->details.get().at(cn).results.trainingObjects = i;
}
void ReportBuilder::addTotalTestObjectCount(Classifier* c, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.testObjects = i;
}
void ReportBuilder::addTotalTrainingObjectCount(Classifier* c, unsigned int i)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	reportsCache.at(pendingReports.at(c))->totals.trainingObjects = i;
}

void ReportBuilder::addClassificationResult(Classifier* c, const ClassName& expected, const ObjectDescription& description, const ClassName& received)
{
	IR_ASSERT(pendingReports.count(c) == 1, "No pending report for given classifier");

	std::shared_ptr<ReportStructure> rep = reportsCache.at(pendingReports.at(c));
	enableClassDetails(rep, expected);

	ReportStructure::ClassData& classData = rep->details.get().at(expected);

	if(!classData.classifiedAs)
		classData.classifiedAs = boost::make_optional(std::unordered_map<ClassName, std::vector<ObjectDescription> >());

	std::unordered_map<ClassName, std::vector<ObjectDescription> >& classifiedAs = classData.classifiedAs.get();

	if(classifiedAs.count(received) == 0)
		classifiedAs.insert(std::make_pair(received, std::vector<ObjectDescription>()));

	classifiedAs.at(received).push_back(description);
}

namespace
{
	template <typename T>
	boost::optional<T> accumulate_optional(boost::optional<T> opt, boost::optional<T> val)
	{
		if (opt.is_initialized())
			return val.get() + (opt.get());

		return val;
	}

	template <typename T>
	void divide(boost::optional<T>& t, int v)
	{
		if (t.is_initialized())
    		t = t.get() / v;
	}
}

void ReportBuilder::summarize()
{
	std::shared_ptr<ReportStructure> report(new ReportStructure);
	report->general.title = "Summary";

	for (auto& partial : finishedReports)
	{
		report->general.trainingDuration = accumulate_optional(report->general.trainingDuration, partial->general.trainingDuration);
		report->totals.rms = accumulate_optional(report->totals.rms, partial->totals.rms);
		report->totals.spread = accumulate_optional(report->totals.spread, partial->totals.spread);
		report->totals.accurracy = accumulate_optional(report->totals.accurracy, partial->totals.accurracy);
		report->totals.recall = accumulate_optional(report->totals.recall, partial->totals.recall);
		report->totals.precision = accumulate_optional(report->totals.precision, partial->totals.precision);
		report->totals.fmeasure = accumulate_optional(report->totals.fmeasure, partial->totals.fmeasure);
		report->totals.correct = accumulate_optional(report->totals.correct, partial->totals.correct);
		report->totals.incorrect = accumulate_optional(report->totals.incorrect, partial->totals.incorrect);
		report->totals.trainingObjects = accumulate_optional(report->totals.trainingObjects, partial->totals.trainingObjects);
		report->totals.testObjects = accumulate_optional(report->totals.testObjects, partial->totals.testObjects);
	}
	divide(report->totals.rms, finishedReports.size());
	divide(report->totals.spread, finishedReports.size());
	divide(report->totals.accurracy, finishedReports.size());
	divide(report->totals.recall, finishedReports.size());
	divide(report->totals.precision, finishedReports.size());
	divide(report->totals.fmeasure, finishedReports.size());
	divide(report->totals.correct, finishedReports.size());
	divide(report->totals.incorrect, finishedReports.size());
	divide(report->totals.trainingObjects, finishedReports.size());
	divide(report->totals.testObjects, finishedReports.size());

	reportsCache.insert(std::make_pair(99999, report));
	reportDBManager->putReport(99999, assemble(99999));
}

TextReportBuilder::TextReportBuilder(std::shared_ptr<ReportDBManager> mgr) : ReportBuilder(mgr), printer(new Printer)
{}

TextReportBuilder::~TextReportBuilder()
{}

std::shared_ptr<Report> TextReportBuilder::assemble(Report::ID id)
{
	IR_ASSERT(reportsCache.count(id) == 1, "Trying to assemble finished report");

	std::shared_ptr<ReportStructure> rs = reportsCache.at(id);

	std::stringstream str;
	printer->printHeader(str, id, rs);
	printer->printOverallResults(str, rs);

	if(rs->details)
	{
		printer->printClassesHeader(str);
		for(auto& i: rs->details.get())
			printer->printSingleClassResults(str, i.first, i.second);
	}

	printer->printDetailedResults(str, rs);
	printer->printFooter(str, rs);

	std::shared_ptr<TextReport> report(new TextReport(id));
	report->title = rs->general.title;
	report->text = str.str();

	return report;
}

std::shared_ptr<Report> TextReportBuilder::report(Report::ID id) const
{
	IR_ASSERT(reportsCache.count(id) == 0, "Trying to return not finished report");

	return reportDBManager->getReport(id);
}

void TextReportBuilder::Printer::printHeader(std::ostream& str, Report::ID id, std::shared_ptr<ReportStructure> rs)
{
	str << "Report ID: " << id << std::endl;
	str << rs->general.title << std::endl;
	str << rs->general.heading << std::endl;

	str << "General data" << std::endl;

	str << "Created on: ";
	if(rs->general.timestamp)
	{
		std::time_t time = std::chrono::system_clock::to_time_t(rs->general.timestamp.get());
		str << std::put_time(std::localtime(&time), "%Y-%m-%d, %H:%M:%S") << std::endl;
	}
	else
		str << "N/A" << std::endl;

	str << "Training time: " ;
	if(rs->general.trainingDuration)
		str << std::chrono::duration_cast<std::chrono::milliseconds>(rs->general.trainingDuration.get()).count() << " milliseconds" << std::endl;
	else
		str << "N/A" << std::endl;

	str << "Training iterations: " << rs->general.iterations;

	str << std::endl;
}

void TextReportBuilder::Printer::printFooter(std::ostream& str, std::shared_ptr<ReportStructure> rs)
{
	str << rs->general.footer << std::endl;
}

void TextReportBuilder::Printer::printOverallResults(std::ostream& str, std::shared_ptr<ReportStructure> rs)
{
	str << "Overall results" << std::endl;
	str << "Total training objects: " << rs->totals.trainingObjects << std::endl;
	str << "Total test objects: " << rs->totals.testObjects << std::endl;
	str << "Total correctly identified: " << rs->totals.correct << std::endl;
	str << "Total incorrectly identified: " << rs->totals.incorrect << std::endl;
	str << "Mean accurracy: " << rs->totals.accurracy << std::endl;
	str << "Mean recall: " << rs->totals.recall << std::endl;
	str << "Mean precision: " << rs->totals.precision << std::endl;
	str << "Mean F-measure: " << rs->totals.fmeasure << std::endl;
	str << "RMS: " << std::setprecision(4) << std::fixed << rs->totals.rms << std::endl;
	str << "Spread: " << std::setprecision(1) << std::fixed << rs->totals.spread << std::endl;
	str << std::endl;
}

void TextReportBuilder::Printer::printSingleClassResults(std::ostream& str, const ClassName& name, const ReportBuilder::ReportStructure::ClassData& data)
{
	str << "Class " << name << std::endl;
	str << "Mapped to number: " << data.mapping << std::endl;
	str << "Training objects: " << data.results.trainingObjects << std::endl;
	str << "Test objects: " << data.results.testObjects << std::endl;
	str << "Correctly identified: " << data.results.correct << std::endl;
	str << "Incorrectly identified: " << data.results.incorrect << std::endl;
	str << "Accurracy: " << std::setprecision(4) << std::fixed << data.results.accurracy << std::endl;
	str << "Recall: " << std::setprecision(4) << std::fixed << data.results.recall << std::endl;
	str << "Precision: " << std::setprecision(4) << std::fixed << data.results.precision << std::endl;
	str << "F-measure: " << std::setprecision(4) << std::fixed << data.results.fmeasure << std::endl;
	str << "RMS: " << std::setprecision(4) << std::fixed << data.results.rms << std::endl;
	str << "Spread: " << std::setprecision(0) << std::fixed << data.results.spread << std::endl;

	if(data.classifiedAs)
		for(auto& j: data.classifiedAs.get())
			str << j.first << ": " << j.second.size() << std::endl;

	str << std::endl;
}

void TextReportBuilder::Printer::printClassesHeader(std::ostream& str)
{
	str << "Data divided into classes" << std::endl;
}

void TextReportBuilder::Printer::printDetailedResults(std::ostream& str, std::shared_ptr<ReportStructure> rs)
{
	if(rs->details)
	{
		str << "Detailed classification data: " << std::endl;
		for(auto& expected: rs->details.get())
		{
			if(expected.second.classifiedAs)
			{
				for(auto& received: expected.second.classifiedAs.get())
					for(auto& object: received.second)
						str << serializeObjectDescription(object) << "of class " << expected.first << " classified as " << received.first << std::endl;
			}
		}
		str << std::endl;
	}
}

std::string TextReportBuilder::Printer::serializeObjectDescription(const ObjectDescription& desc)
{
	std::stringstream str;
	for(auto& i: desc)
//		str << i.real() << " " << i.imag() << " ";
		str << i << " ";

	return str.str();
}

max_stars_repo_name: Lewerow/InstrumentRecognizer

max_issues_repo_name: Lewerow/InstrumentRecognizer

max_forks_repo_name: Lewerow/InstrumentRecognizer


text:
//=======================================================================
// Copyright 2001 University of Notre Dame.
// Copyright 2003 Jeremy Siek
// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOST_GRAPHVIZ_HPP
#define BOOST_GRAPHVIZ_HPP

#include <stdio.h> // for FILE

#include <boost/algorithm/string/replace.hpp>
#include <boost/config.hpp>
#include <boost/foreach.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/dll_import_export.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/subgraph.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/static_assert.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/xpressive/xpressive_static.hpp>
#include <fstream>
#include <iostream>
#include <map>
#include <string>

namespace boost
{

template <typename directed_category>
struct graphviz_io_traits
{
    static std::string name()
    {
        return "digraph";
    }
    static std::string delimiter()
    {
        return "->";
    }
};

template <>
struct graphviz_io_traits<undirected_tag>
{
    static std::string name()
    {
        return "graph";
    }
    static std::string delimiter()
    {
        return "--";
    }
};

struct default_writer
{
    void operator()(std::ostream&) const
    {
    }
    template <class VorE>
    void operator()(std::ostream&, const VorE&) const
    {
    }
};

template <typename T>
inline std::string escape_dot_string(const T& obj)
{
    using namespace boost::xpressive;
    static sregex valid_unquoted_id =
        (((alpha | '_') >> *_w) |
         (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
    std::string s(boost::lexical_cast<std::string>(obj));
    if (regex_match(s, valid_unquoted_id))
    {
        return s;
    }
    else
    {
        boost::algorithm::replace_all(s, "\"", "\\\"");
        return "\"" + s + "\"";
    }
}

template <class Name>
class label_writer
{
  public:
    label_writer(Name _name) : name(_name)
    {
    }
    template <class VertexOrEdge>
    void operator()(std::ostream& out, const VertexOrEdge& v) const
    {
        out << "[label=" << escape_dot_string(get(name, v)) << "]";
    }

  private:
    Name name;
};
template <class Name>
inline label_writer<Name> make_label_writer(Name n)
{
    return label_writer<Name>(n);
}

enum edge_attribute_t
{
    edge_attribute = 1111
};
enum vertex_attribute_t
{
    vertex_attribute = 2222
};
enum graph_graph_attribute_t
{
    graph_graph_attribute = 3333
};
enum graph_vertex_attribute_t
{
    graph_vertex_attribute = 4444
};
enum graph_edge_attribute_t
{
    graph_edge_attribute = 5555
};

BOOST_INSTALL_PROPERTY(edge, attribute);
BOOST_INSTALL_PROPERTY(vertex, attribute);
BOOST_INSTALL_PROPERTY(graph, graph_attribute);
BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
BOOST_INSTALL_PROPERTY(graph, edge_attribute);

template <class Attribute>
inline void write_attributes(const Attribute& attr, std::ostream& out)
{
    typename Attribute::const_iterator i, iend;
    i = attr.begin();
    iend = attr.end();

    while (i != iend)
    {
        out << i->first << "=" << escape_dot_string(i->second);
        ++i;
        if (i != iend)
            out << ", ";
    }
}

template <typename Attributes>
inline void write_all_attributes(Attributes attributes, const std::string& name,
                                 std::ostream& out)
{
    typename Attributes::const_iterator i = attributes.begin(),
                                        end = attributes.end();
    if (i != end)
    {
        out << name << " [\n";
        write_attributes(attributes, out);
        out << "];\n";
    }
}

inline void write_all_attributes(detail::error_property_not_found,
                                 const std::string&, std::ostream&)
{
    // Do nothing - no attributes exist
}

template <typename GraphGraphAttributes, typename GraphNodeAttributes,
          typename GraphEdgeAttributes>
struct graph_attributes_writer
{
    graph_attributes_writer(GraphGraphAttributes gg, GraphNodeAttributes gn,
                            GraphEdgeAttributes ge) :
        g_attributes(gg),
        n_attributes(gn), e_attributes(ge)
    {
    }

    void operator()(std::ostream& out) const
    {
        write_all_attributes(g_attributes, "graph", out);
        write_all_attributes(n_attributes, "node", out);
        write_all_attributes(e_attributes, "edge", out);
    }
    GraphGraphAttributes g_attributes;
    GraphNodeAttributes n_attributes;
    GraphEdgeAttributes e_attributes;
};

template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
    make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
                                 const EAttrMap& e_attr)
{
    return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>(g_attr, n_attr,
                                                                 e_attr);
}

template <typename Graph>
graph_attributes_writer<
    typename graph_property<Graph, graph_graph_attribute_t>::type,
    typename graph_property<Graph, graph_vertex_attribute_t>::type,
    typename graph_property<Graph, graph_edge_attribute_t>::type>
    make_graph_attributes_writer(const Graph& g)
{
    typedef
        typename graph_property<Graph, graph_graph_attribute_t>::type GAttrMap;
    typedef
        typename graph_property<Graph, graph_vertex_attribute_t>::type NAttrMap;
    typedef
        typename graph_property<Graph, graph_edge_attribute_t>::type EAttrMap;
    GAttrMap gam = get_property(g, graph_graph_attribute);
    NAttrMap nam = get_property(g, graph_vertex_attribute);
    EAttrMap eam = get_property(g, graph_edge_attribute);
    graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
    return writer;
}

template <typename AttributeMap>
struct attributes_writer
{
    attributes_writer(AttributeMap attr) : attributes(attr)
    {
    }

    template <class VorE>
    void operator()(std::ostream& out, const VorE& e) const
    {
        this->write_attribute(out, attributes[e]);
    }

  private:
    template <typename AttributeSequence>
    void write_attribute(std::ostream& out, const AttributeSequence& seq) const
    {
        if (!seq.empty())
        {
            out << "[";
            write_attributes(seq, out);
            out << "]";
        }
    }

    void write_attribute(std::ostream&, detail::error_property_not_found) const
    {
    }
    AttributeMap attributes;
};

template <typename Graph>
attributes_writer<typename property_map<Graph, edge_attribute_t>::const_type>
    make_edge_attributes_writer(const Graph& g)
{
    typedef typename property_map<Graph, edge_attribute_t>::const_type
        EdgeAttributeMap;
    return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
}

template <typename Graph>
attributes_writer<typename property_map<Graph, vertex_attribute_t>::const_type>
    make_vertex_attributes_writer(const Graph& g)
{
    typedef typename property_map<Graph, vertex_attribute_t>::const_type
        VertexAttributeMap;
    return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
}

template <typename Graph, typename VertexPropertiesWriter,
          typename EdgePropertiesWriter, typename GraphPropertiesWriter,
          typename VertexID>
inline void write_graphviz(std::ostream& out, const Graph& g,
                           VertexPropertiesWriter vpw, EdgePropertiesWriter epw,
                           GraphPropertiesWriter gpw,
                           VertexID vertex_id BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
                               Graph, vertex_list_graph_tag))
{
    BOOST_CONCEPT_ASSERT((EdgeListGraphConcept<Graph>));

    typedef typename graph_traits<Graph>::directed_category cat_type;
    typedef graphviz_io_traits<cat_type> Traits;
    std::string name = "G";
    out << Traits::name() << " " << escape_dot_string(name) << " {"
        << std::endl;

    gpw(out); // print graph properties

    typename graph_traits<Graph>::vertex_iterator i, end;

    for (boost::tie(i, end) = vertices(g); i != end; ++i)
    {
        out << escape_dot_string(get(vertex_id, *i));
        vpw(out, *i); // print vertex attributes
        out << ";" << std::endl;
    }
    typename graph_traits<Graph>::edge_iterator ei, edge_end;
    for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei)
    {
        out << escape_dot_string(get(vertex_id, source(*ei, g)))
            << Traits::delimiter()
            << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
        epw(out, *ei); // print edge attributes
        out << ";" << std::endl;
    }
    out << "}" << std::endl;
}

template <typename Graph, typename VertexPropertiesWriter,
          typename EdgePropertiesWriter, typename GraphPropertiesWriter>
inline void
    write_graphviz(std::ostream& out, const Graph& g,
                   VertexPropertiesWriter vpw, EdgePropertiesWriter epw,
                   GraphPropertiesWriter gpw BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
                       Graph, vertex_list_graph_tag))
{
    write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g));
}

template <typename Graph>
inline void write_graphviz(std::ostream& out,
                           const Graph& g BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
                               Graph, vertex_list_graph_tag))
{
    default_writer dw;
    default_writer gw;
    write_graphviz(out, g, dw, dw, gw);
}

template <typename Graph, typename VertexWriter>
inline void write_graphviz(std::ostream& out, const Graph& g,
                           VertexWriter vw BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
                               Graph, vertex_list_graph_tag))
{
    default_writer dw;
    default_writer gw;
    write_graphviz(out, g, vw, dw, gw);
}

template <typename Graph, typename VertexWriter, typename EdgeWriter>
inline void write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw,
                           EdgeWriter ew BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
                               Graph, vertex_list_graph_tag))
{
    default_writer gw;
    write_graphviz(out, g, vw, ew, gw);
}

namespace detail
{

template <class Graph_, class RandomAccessIterator, class VertexID>
void write_graphviz_subgraph(std::ostream& out, const subgraph<Graph_>& g,
                             RandomAccessIterator vertex_marker,
                             RandomAccessIterator edge_marker,
                             VertexID vertex_id)
{
    typedef subgraph<Graph_> Graph;
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
    typedef typename graph_traits<Graph>::directed_category cat_type;
    typedef graphviz_io_traits<cat_type> Traits;

    typedef typename graph_property<Graph, graph_name_t>::type NameType;
    const NameType& g_name = get_property(g, graph_name);

    if (g.is_root())
        out << Traits::name();
    else
        out << "subgraph";

    out << " " << escape_dot_string(g_name) << " {" << std::endl;

    typename Graph::const_children_iterator i_child, j_child;

    // print graph/node/edge attributes
    make_graph_attributes_writer(g)(out);

    // print subgraph
    for (boost::tie(i_child, j_child) = g.children(); i_child != j_child;
         ++i_child)
        write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
                                vertex_id);

    // Print out vertices and edges not in the subgraphs.

    typename graph_traits<Graph>::vertex_iterator i, end;
    typename graph_traits<Graph>::edge_iterator ei, edge_end;

    for (boost::tie(i, end) = vertices(g); i != end; ++i)
    {
        Vertex v = g.local_to_global(*i);
        int pos = get(vertex_id, v);
        if (vertex_marker[pos])
        {
            vertex_marker[pos] = false;
            out << escape_dot_string(pos);
            make_vertex_attributes_writer(g.root())(out, v);
            out << ";" << std::endl;
        }
    }

    for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei)
    {
        Vertex u = g.local_to_global(source(*ei, g)),
               v = g.local_to_global(target(*ei, g));
        int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
        if (edge_marker[pos])
        {
            edge_marker[pos] = false;
            out << escape_dot_string(get(vertex_id, u)) << " "
                << Traits::delimiter() << " "
                << escape_dot_string(get(vertex_id, v));
            make_edge_attributes_writer(g)(out, *ei); // print edge properties
            out << ";" << std::endl;
        }
    }
    out << "}" << std::endl;
}
} // namespace detail

// requires graph_name graph property
template <typename Graph>
void write_graphviz(std::ostream& out, const subgraph<Graph>& g)
{
    std::vector<bool> edge_marker(num_edges(g), true);
    std::vector<bool> vertex_marker(num_vertices(g), true);

    detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
                                    edge_marker.begin(), get(vertex_index, g));
}

template <typename Graph>
void write_graphviz(const std::string& filename, const subgraph<Graph>& g)
{
    std::ofstream out(filename.c_str());
    std::vector<bool> edge_marker(num_edges(g), true);
    std::vector<bool> vertex_marker(num_vertices(g), true);

    detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
                                    edge_marker.begin(), get(vertex_index, g));
}

template <typename Graph, typename VertexID>
void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
                    VertexID vertex_id)
{
    std::vector<bool> edge_marker(num_edges(g), true);
    std::vector<bool> vertex_marker(num_vertices(g), true);

    detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
                                    edge_marker.begin(), vertex_id);
}

template <typename Graph, typename VertexID>
void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
                    VertexID vertex_id)
{
    std::ofstream out(filename.c_str());
    std::vector<bool> edge_marker(num_edges(g), true);
    std::vector<bool> vertex_marker(num_vertices(g), true);

    detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
                                    edge_marker.begin(), vertex_id);
}

#if 0
  // This interface has not worked for a long time
  typedef std::map<std::string, std::string> GraphvizAttrList;

  typedef property<vertex_attribute_t, GraphvizAttrList>
          GraphvizVertexProperty;

  typedef property<edge_attribute_t, GraphvizAttrList,
                   property<edge_index_t, int> >
          GraphvizEdgeProperty;

  typedef property<graph_graph_attribute_t, GraphvizAttrList,
                   property<graph_vertex_attribute_t, GraphvizAttrList,
                   property<graph_edge_attribute_t, GraphvizAttrList,
                   property<graph_name_t, std::string> > > >
          GraphvizGraphProperty;

  typedef subgraph<adjacency_list<vecS,
                   vecS, directedS,
                   GraphvizVertexProperty,
                   GraphvizEdgeProperty,
                   GraphvizGraphProperty> >
          GraphvizDigraph;

  typedef subgraph<adjacency_list<vecS,
                   vecS, undirectedS,
                   GraphvizVertexProperty,
                   GraphvizEdgeProperty,
                   GraphvizGraphProperty> >
          GraphvizGraph;

  // These four require linking the BGL-Graphviz library: libbgl-viz.a
  // from the /src directory.
  // Library has not existed for a while
  extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
  extern void read_graphviz(FILE* file, GraphvizDigraph& g);

  extern void read_graphviz(const std::string& file, GraphvizGraph& g);
  extern void read_graphviz(FILE* file, GraphvizGraph& g);
#endif

class dynamic_properties_writer
{
  public:
    dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp)
    {
    }

    template <typename Descriptor>
    void operator()(std::ostream& out, Descriptor key) const
    {
        bool first = true;
        for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
             ++i)
        {
            if (typeid(key) == i->second->key())
            {
                if (first)
                    out << " [";
                else
                    out << ", ";
                first = false;

                out << i->first << "="
                    << escape_dot_string(i->second->get_string(key));
            }
        }

        if (!first)
            out << "]";
    }

  private:
    const dynamic_properties* dp;
};

class dynamic_vertex_properties_writer
{
  public:
    dynamic_vertex_properties_writer(const dynamic_properties& dp,
                                     const std::string& node_id) :
        dp(&dp),
        node_id(&node_id)
    {
    }

    template <typename Descriptor>
    void operator()(std::ostream& out, Descriptor key) const
    {
        bool first = true;
        for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
             ++i)
        {
            if (typeid(key) == i->second->key() && i->first != *node_id)
            {
                if (first)
                    out << " [";
                else
                    out << ", ";
                first = false;

                out << i->first << "="
                    << escape_dot_string(i->second->get_string(key));
            }
        }

        if (!first)
            out << "]";
    }

  private:
    const dynamic_properties* dp;
    const std::string* node_id;
};

template <typename Graph>
class dynamic_graph_properties_writer
{
  public:
    dynamic_graph_properties_writer(const dynamic_properties& dp,
                                    const Graph& g) :
        g(&g),
        dp(&dp)
    {
    }

    void operator()(std::ostream& out) const
    {
        for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
             ++i)
        {
            if (typeid(Graph*) == i->second->key())
            {
                // const_cast here is to match interface used in read_graphviz
                out << i->first << "="
                    << escape_dot_string(
                           i->second->get_string(const_cast<Graph*>(g)))
                    << ";\n";
            }
        }
    }

  private:
    const Graph* g;
    const dynamic_properties* dp;
};

namespace graph
{
namespace detail
{

template <typename Vertex>
struct node_id_property_map
{
    typedef std::string value_type;
    typedef value_type reference;
    typedef Vertex key_type;
    typedef readable_property_map_tag category;

    node_id_property_map()
    {
    }

    node_id_property_map(const dynamic_properties& dp,
                         const std::string& node_id) :
        dp(&dp),
        node_id(&node_id)
    {
    }

    const dynamic_properties* dp;
    const std::string* node_id;
};

template <typename Vertex>
inline std::string get(node_id_property_map<Vertex> pm,
                       typename node_id_property_map<Vertex>::key_type v)
{
    return get(*pm.node_id, *pm.dp, v);
}

} // namespace detail
} // namespace graph

template <typename Graph>
inline void write_graphviz_dp(
    std::ostream& out, const Graph& g, const dynamic_properties& dp,
    const std::string& node_id = "node_id" BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
        Graph, vertex_list_graph_tag))
{
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
    write_graphviz_dp(out, g, dp, node_id,
                      graph::detail::node_id_property_map<Vertex>(dp, node_id));
}

template <typename Graph, typename VertexID>
void write_graphviz_dp(
    std::ostream& out, const Graph& g, const dynamic_properties& dp,
    const std::string& node_id,
    VertexID id BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
{
    write_graphviz(
        out, g,
        /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
        /*edge_writer=*/dynamic_properties_writer(dp),
        /*graph_writer=*/dynamic_graph_properties_writer<Graph>(dp, g), id);
}

/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
struct graph_exception : public std::exception
{
    virtual ~graph_exception() throw()
    {
    }
    virtual const char* what() const throw() = 0;
};

struct bad_parallel_edge : public graph_exception
{
    std::string from;
    std::string to;
    mutable std::string statement;
    bad_parallel_edge(const std::string& i, const std::string& j) :
        from(i), to(j)
    {
    }

    virtual ~bad_parallel_edge() throw()
    {
    }
    const char* what() const throw()
    {
        if (statement.empty())
            statement = std::string("Failed to add parallel edge: (") + from +
                        "," + to + ")\n";

        return statement.c_str();
    }
};

struct directed_graph_error : public graph_exception
{
    virtual ~directed_graph_error() throw()
    {
    }
    virtual const char* what() const throw()
    {
        return "read_graphviz: "
               "Tried to read a directed graph into an undirected graph.";
    }
};

struct undirected_graph_error : public graph_exception
{
    virtual ~undirected_graph_error() throw()
    {
    }
    virtual const char* what() const throw()
    {
        return "read_graphviz: "
               "Tried to read an undirected graph into a directed graph.";
    }
};

struct bad_graphviz_syntax : public graph_exception
{
    std::string errmsg;
    bad_graphviz_syntax(const std::string& errmsg) : errmsg(errmsg)
    {
    }
    const char* what() const throw()
    {
        return errmsg.c_str();
    }
    ~bad_graphviz_syntax() throw(){};
};

namespace detail
{
namespace graph
{

typedef std::string id_t;
typedef id_t node_t;

// edges are not uniquely determined by adjacent nodes
class edge_t
{
    int idx_;
    explicit edge_t(int i) : idx_(i)
    {
    }

  public:
    static edge_t new_edge()
    {
        static int idx = 0;
        return edge_t(idx++);
    };

    bool operator==(const edge_t& rhs) const
    {
        return idx_ == rhs.idx_;
    }
    bool operator<(const edge_t& rhs) const
    {
        return idx_ < rhs.idx_;
    }
};

class mutate_graph
{
  public:
    virtual ~mutate_graph()
    {
    }
    virtual bool is_directed() const = 0;
    virtual void do_add_vertex(const node_t& node) = 0;

    virtual void do_add_edge(const edge_t& edge, const node_t& source,
                             const node_t& target) = 0;

    virtual void set_node_property(const id_t& key, const node_t& node,
                                   const id_t& value) = 0;

    virtual void set_edge_property(const id_t& key, const edge_t& edge,
                                   const id_t& value) = 0;

    virtual void // RG: need new second parameter to support BGL subgraphs
        set_graph_property(const id_t& key, const id_t& value) = 0;

    virtual void finish_building_graph() = 0;
};

template <typename MutableGraph>
class mutate_graph_impl : public mutate_graph
{
    typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
    typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;

  public:
    mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
                      std::string node_id_prop) :
        graph_(graph),
        dp_(dp), node_id_prop_(node_id_prop)
    {
    }

    ~mutate_graph_impl()
    {
    }

    bool is_directed() const
    {
        return boost::is_convertible<
            typename boost::graph_traits<MutableGraph>::directed_category,
            boost::directed_tag>::value;
    }

    virtual void do_add_vertex(const node_t& node)
    {
        // Add the node to the graph.
        bgl_vertex_t v = add_vertex(graph_);

        // Set up a mapping from name to BGL vertex.
        bgl_nodes.insert(std::make_pair(node, v));

        // node_id_prop_ allows the caller to see the real id names for nodes.
        put(node_id_prop_, dp_, v, node);
    }

    void do_add_edge(const edge_t& edge, const node_t& source,
                     const node_t& target)
    {
        std::pair<bgl_edge_t, bool> result =
            add_edge(bgl_nodes[source], bgl_nodes[target], graph_);

        if (!result.second)
        {
            // In the case of no parallel edges allowed
            boost::throw_exception(bad_parallel_edge(source, target));
        }
        else
        {
            bgl_edges.insert(std::make_pair(edge, result.first));
        }
    }

    void set_node_property(const id_t& key, const node_t& node,
                           const id_t& value)
    {
        put(key, dp_, bgl_nodes[node], value);
    }

    void set_edge_property(const id_t& key, const edge_t& edge,
                           const id_t& value)
    {
        put(key, dp_, bgl_edges[edge], value);
    }

    void set_graph_property(const id_t& key, const id_t& value)
    {
        /* RG: pointer to graph prevents copying */
        put(key, dp_, &graph_, value);
    }

    void finish_building_graph()
    {
    }

  protected:
    MutableGraph& graph_;
    dynamic_properties& dp_;
    std::string node_id_prop_;
    std::map<node_t, bgl_vertex_t> bgl_nodes;
    std::map<edge_t, bgl_edge_t> bgl_edges;
};

template <typename Directed, typename VertexProperty, typename EdgeProperty,
          typename GraphProperty, typename Vertex, typename EdgeIndex>
class mutate_graph_impl<compressed_sparse_row_graph<
    Directed, VertexProperty, EdgeProperty, GraphProperty, Vertex, EdgeIndex>>
    : public mutate_graph
{
    typedef compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty,
                                        GraphProperty, Vertex, EdgeIndex>
        CSRGraph;
    typedef typename graph_traits<CSRGraph>::vertices_size_type bgl_vertex_t;
    typedef typename graph_traits<CSRGraph>::edges_size_type bgl_edge_t;
    typedef typename graph_traits<CSRGraph>::edge_descriptor edge_descriptor;

  public:
    mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp,
                      std::string node_id_prop) :
        graph_(graph),
        dp_(dp), vertex_count(0), node_id_prop_(node_id_prop)
    {
    }

    ~mutate_graph_impl()
    {
    }

    void finish_building_graph()
    {
        typedef compressed_sparse_row_graph<directedS, no_property, bgl_edge_t,
                                            GraphProperty, Vertex, EdgeIndex>
            TempCSRGraph;
        TempCSRGraph temp(edges_are_unsorted_multi_pass, edges_to_add.begin(),
                          edges_to_add.end(), counting_iterator<bgl_edge_t>(0),
                          vertex_count);
        set_property(temp, graph_all, get_property(graph_, graph_all));
        graph_.assign(temp); // Copies structure, not properties
        std::vector<edge_descriptor> edge_permutation_from_sorting(
            num_edges(temp));
        BGL_FORALL_EDGES_T(e, temp, TempCSRGraph)
        {
            edge_permutation_from_sorting[temp[e]] = e;
        }
        typedef boost::tuple<id_t, bgl_vertex_t, id_t> v_prop;
        BOOST_FOREACH (const v_prop& t, vertex_props)
        {
            put(boost::get<0>(t), dp_, boost::get<1>(t), boost::get<2>(t));
        }
        typedef boost::tuple<id_t, bgl_edge_t, id_t> e_prop;
        BOOST_FOREACH (const e_prop& t, edge_props)
        {
            put(boost::get<0>(t), dp_,
                edge_permutation_from_sorting[boost::get<1>(t)],
                boost::get<2>(t));
        }
    }

    bool is_directed() const
    {
        return boost::is_convertible<
            typename boost::graph_traits<CSRGraph>::directed_category,
            boost::directed_tag>::value;
    }

    virtual void do_add_vertex(const node_t& node)
    {
        // Add the node to the graph.
        bgl_vertex_t v = vertex_count++;

        // Set up a mapping from name to BGL vertex.
        bgl_nodes.insert(std::make_pair(node, v));

        // node_id_prop_ allows the caller to see the real id names for nodes.
        vertex_props.push_back(boost::make_tuple(node_id_prop_, v, node));
    }

    void do_add_edge(const edge_t& edge, const node_t& source,
                     const node_t& target)
    {
        bgl_edge_t result = edges_to_add.size();
        edges_to_add.push_back(
            std::make_pair(bgl_nodes[source], bgl_nodes[target]));
        bgl_edges.insert(std::make_pair(edge, result));
    }

    void set_node_property(const id_t& key, const node_t& node,
                           const id_t& value)
    {
        vertex_props.push_back(boost::make_tuple(key, bgl_nodes[node], value));
    }

    void set_edge_property(const id_t& key, const edge_t& edge,
                           const id_t& value)
    {
        edge_props.push_back(boost::make_tuple(key, bgl_edges[edge], value));
    }

    void set_graph_property(const id_t& key, const id_t& value)
    {
        /* RG: pointer to graph prevents copying */
        put(key, dp_, &graph_, value);
    }

  protected:
    CSRGraph& graph_;
    dynamic_properties& dp_;
    bgl_vertex_t vertex_count;
    std::string node_id_prop_;
    std::vector<boost::tuple<id_t, bgl_vertex_t, id_t>> vertex_props;
    std::vector<boost::tuple<id_t, bgl_edge_t, id_t>> edge_props;
    std::vector<std::pair<bgl_vertex_t, bgl_vertex_t>> edges_to_add;
    std::map<node_t, bgl_vertex_t> bgl_nodes;
    std::map<edge_t, bgl_edge_t> bgl_edges;
};

} // namespace graph
} // namespace detail
} // namespace boost

#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
#ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
#define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
#endif
#include <boost/graph/detail/read_graphviz_spirit.hpp>
#else // New default parser
#include <boost/graph/detail/read_graphviz_new.hpp>
#endif // BOOST_GRAPH_USE_SPIRIT_PARSER

namespace boost
{

// Parse the passed string as a GraphViz dot file.
template <typename MutableGraph>
bool read_graphviz(const std::string& data, MutableGraph& graph,
                   dynamic_properties& dp,
                   std::string const& node_id = "node_id")
{
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
    return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
#else // Non-Spirit parser
    return read_graphviz_new(data, graph, dp, node_id);
#endif
}

// Parse the passed iterator range as a GraphViz dot file.
template <typename InputIterator, typename MutableGraph>
bool read_graphviz(InputIterator user_first, InputIterator user_last,
                   MutableGraph& graph, dynamic_properties& dp,
                   std::string const& node_id = "node_id")
{
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
    typedef InputIterator is_t;
    typedef boost::spirit::classic::multi_pass<is_t> iterator_t;

    iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
    iterator_t last(boost::spirit::classic::make_multi_pass(user_last));

    return read_graphviz_spirit(first, last, graph, dp, node_id);
#else // Non-Spirit parser
    return read_graphviz_new(std::string(user_first, user_last), graph, dp,
                             node_id);
#endif
}

// Parse the passed stream as a GraphViz dot file.
template <typename MutableGraph>
bool read_graphviz(std::istream& in, MutableGraph& graph,
                   dynamic_properties& dp,
                   std::string const& node_id = "node_id")
{
    typedef std::istream_iterator<char> is_t;
    in >> std::noskipws;
    return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
}

} // namespace boost

#ifdef BOOST_GRAPH_USE_MPI
#include <boost/graph/distributed/graphviz.hpp>
#endif

#endif // BOOST_GRAPHVIZ_HPP

ext: hpp

max_stars_repo_name: sotaoverride/backup

max_issues_repo_name: sotaoverride/backup

max_forks_repo_name: sotaoverride/backup


text:
#include <iostream>
#include <stdio.h>
#include <string.h>

#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <iostream>

#include <GL/glew.h>
#include <GL/freeglut.h>

#include <pangolin/pangolin.h>
#include <pangolin/utils/timer.h>

#include <Eigen/Dense>

#include <cuda_runtime.h>
#include <vector_types.h>

// Uncomment this line if you want to use RealSense
//#include "depth_sources/realsense_depth_source.h"
#include "depth_sources/kinectv2_depth_source.h"

#include "geometry/plane_fitting.h"
#include "img_proc/img_ops.h"
#include "optimization/priors.h"
#include "tracker.h"
#include "util/dart_io.h"
#include "util/gl_dart.h"
#include "util/ostream_operators.h"
#include "util/string_format.h"
#include <util/cpptoml.h>
#include "visualization/color_ramps.h"
#include "visualization/data_association_viz.h"
#include "visualization/gradient_viz.h"
#include "visualization/sdf_viz.h"

#define EIGEN_DONT_ALIGN

using namespace std;

enum PointColorings {
    PointColoringNone = 0,
    PointColoringRGB,
    PointColoringErr,
    PointColoringDA,
    NumPointColorings
};

enum DebugImgs {
    DebugColor=0,
    DebugObsDepth,
    DebugPredictedDepth,
    DebugObsToModDA,
    DebugModToObsDA,
    DebugObsToModErr,
    DebugModToObsErr,
    DebugJTJ,
    DebugN
};

const static int panelWidth = 180;

void setSlidersFromTransform(dart::SE3& transform, pangolin::Var<float>** sliders) {
    *sliders[0] = transform.r0.w; transform.r0.w = 0;
    *sliders[1] = transform.r1.w; transform.r1.w = 0;
    *sliders[2] = transform.r2.w; transform.r2.w = 0;
    dart::se3 t = dart::se3FromSE3(transform);
    *sliders[3] = t.p[3];
    *sliders[4] = t.p[4];
    *sliders[5] = t.p[5];
}
void setSlidersFromTransform(const dart::SE3& transform, pangolin::Var<float>** sliders) {
    dart::SE3 mutableTransform = transform;
    setSlidersFromTransform(mutableTransform,sliders);
}
const static dart::SE3 T_wh = dart::SE3FromRotationY(M_PI)*dart::SE3FromRotationX(-M_PI_2)*dart::SE3FromTranslation(make_float3(0,0,0.138));//dart::SE3Fromse3(dart::se3(0,0,0.1,0,2.22144,2.22144)); //dart::SE3art::SE3Fromse3(dart::se3(0, 0.108385,-0.108385, 1.5708, 0, 0)); // = dart::SE3Invert(dart::SE3Fromse3(dart::se3(0, 0.115, -0.115, 1.5708, 0, 0)));
const static dart::SE3 T_hw = dart::SE3Invert(T_wh);
const static dart::SE3 T_wc = dart::SE3FromTranslation(make_float3(-0.2,0.8,0))*
        dart::SE3Fromse3(dart::se3(0,0,0,0,M_PI_2,0))*
        dart::SE3Fromse3(dart::se3(0,0,0, 2.1,0,0));

static float3 initialTableNorm = make_float3(0.0182391, 0.665761, -0.745942);
static float initialTableIntercept = -0.705196;

std::ofstream* pose_output;

int main(int argc, char* argv[]) {

    if (argc != 2)
    {
        std::cerr << "The only allowed input is a single config file" << std::endl;
    }
    auto toml_config = cpptoml::parse_file(argv[1]);

    bool isLive = *toml_config->get_qualified_as<bool>("camera.live");
    std::string saveDir = *toml_config->get_as<std::string>("save_directory");
    std::string loadDir = *toml_config->get_as<std::string>("load_directory");
    std::string modelDir = *toml_config->get_as<std::string>("model_directory");
    // Let's always save joint angles no matter what
    pose_output = new std::ofstream(saveDir + "/pose.txt");

    const float objObsSdfRes = 0.0025;
    const float3 objObsSdfOffset = make_float3(0,0,0);

    // -=-=-=- initializations -=-=-=-
    cudaSetDevice(0);
    cudaDeviceReset();

    pangolin::CreateWindowAndBind("Main",640+4*panelWidth+1,2*480+1);

    char *myargv [1];
    int myargc=1;
    myargv[0] = strdup("Myappname");
    glutInit(&myargc, myargv);

    glewInit();
    dart::Tracker tracker;

    // -=-=-=- pangolin window setup -=-=-=-

    pangolin::CreatePanel("lim").SetBounds(0.0,1.0,1.0,pangolin::Attach::Pix(-panelWidth));
    pangolin::CreatePanel("ui").SetBounds(0.0, 1.0, 0.0, pangolin::Attach::Pix(panelWidth));
    pangolin::CreatePanel("opt").SetBounds(0.0,1.0,pangolin::Attach::Pix(panelWidth), pangolin::Attach::Pix(2*panelWidth));
    pangolin::CreatePanel("pose").SetBounds(0.0,1.0,pangolin::Attach::Pix(-panelWidth), pangolin::Attach::Pix(-2*panelWidth));

    int glWidth = 640;
    int glHeight= 480;
    int glFL = 400;
    int glPPx = glWidth/2;
    int glPPy = glHeight/2;
    pangolin::OpenGlMatrixSpec glK = pangolin::ProjectionMatrixRDF_BottomLeft(glWidth,glHeight,glFL,glFL,glPPx,glPPy,0.01,1000);
    pangolin::OpenGlRenderState camState(glK);
    pangolin::View & camDisp = pangolin::Display("cam").SetAspect(640.0f/480.0f).SetHandler(new pangolin::Handler3D(camState));

    pangolin::View & imgDisp = pangolin::Display("img").SetAspect(640.0f/480.0f);
    pangolin::GlTexture imgTexDepthSize(320,240);
    pangolin::GlTexture imgTexPredictionSize(160,120);

    pangolin::DataLog infoLog;
    {
        std::vector<std::string> infoLogLabels;
        infoLogLabels.push_back("errObsToMod");
        infoLogLabels.push_back("errModToObs");
        infoLogLabels.push_back("stabilityThreshold");
        infoLogLabels.push_back("resetThreshold");
        infoLog.SetLabels(infoLogLabels);
    }

    pangolin::Display("multi")
            .SetBounds(1.0, 0.0, pangolin::Attach::Pix(2*panelWidth), pangolin::Attach::Pix(-2*panelWidth))
            .SetLayout(pangolin::LayoutEqual)
            .AddDisplay(camDisp)
            //            .AddDisplay(infoPlotter)
            .AddDisplay(imgDisp);

//    imgDisp.Show(false);

    float defaultModelSdfPadding = 0.07;

    std::vector<pangolin::Var<float> *> sizeVars;

    // Initialize Kinect depth source
    dart::KinectV2DepthSource<ushort,uchar3> *depthSource = new dart::KinectV2DepthSource<ushort,uchar3>();

    // Uncomment this line if you want to use RealSense
    //dart::RealSenseDepthSource<ushort,uchar3> *depthSource = new dart::RealSenseDepthSource<ushort,uchar3>();

    depthSource->initialize(isLive,saveDir,loadDir);
    tracker.addDepthSource(depthSource);

    dart::Optimizer & optimizer = *tracker.getOptimizer();

    const static int obsSdfSize = 64;
    const static float obsSdfResolution = 0.01*32/obsSdfSize;
    const static float defaultModelSdfResolution = 2e-3; //1.5e-3;
    const static float3 obsSdfOffset = make_float3(0,0,0.1);

    pangolin::Var<float> modelSdfResolution("lim.modelSdfResolution",defaultModelSdfResolution,defaultModelSdfResolution/2,defaultModelSdfResolution*2);
    pangolin::Var<float> modelSdfPadding("lim.modelSdfPadding",defaultModelSdfPadding,defaultModelSdfPadding/2,defaultModelSdfPadding*2);

    dart::ParamMapPoseReduction * handPoseReduction = dart::loadParamMapPoseReduction("../models/" + modelDir + "/" + modelDir + "ParamMap.txt");

    tracker.addModel("../models/" + modelDir + "/" + modelDir + ".xml",
                     modelSdfResolution,
                     modelSdfPadding,
                     obsSdfSize,
                     obsSdfResolution,
                     make_float3(-0.5*obsSdfSize*obsSdfResolution) + obsSdfOffset, //);
                     handPoseReduction);

    dart::PosePrior reportedPosePrior(tracker.getPose(0).getReducedDimensions());
    memset(reportedPosePrior.getWeights(),0,6*sizeof(float));

    std::vector<pangolin::Var<float> * *> poseVars;

    pangolin::Var<bool> sliderControlled("pose.sliderControl",false,true);
    for (int m=0; m<tracker.getNumModels(); ++m) {

        const int dimensions = tracker.getModel(m).getPoseDimensionality();

        pangolin::Var<float> * * vars = new pangolin::Var<float> *[dimensions];
        poseVars.push_back(vars);
        poseVars[m][0] = new pangolin::Var<float>(dart::stringFormat("pose.%d x",m),0,-0.5,0.5);
        poseVars[m][1] = new pangolin::Var<float>(dart::stringFormat("pose.%d y",m),0,-0.5,0.5);
        poseVars[m][2] = new pangolin::Var<float>(dart::stringFormat("pose.%d z",m),0.3,0.5,1.5);
        poseVars[m][3] = new pangolin::Var<float>(dart::stringFormat("pose.%d wx",m),    0,-M_PI,M_PI);
        poseVars[m][4] = new pangolin::Var<float>(dart::stringFormat("pose.%d wy",m),    0,-M_PI,M_PI);
        poseVars[m][5] = new pangolin::Var<float>(dart::stringFormat("pose.%d wz",m), M_PI,-M_PI,M_PI);

        const dart::Pose & pose = tracker.getPose(m);
        for (int i=0; i<pose.getReducedArticulatedDimensions(); ++i) {
            poseVars[m][i+6] = new pangolin::Var<float>(dart::stringFormat("pose.%d %s",m,pose.getReducedName(i).c_str()),0,pose.getReducedMin(i),pose.getReducedMax(i));
        }

    }

    // pangolin variables
    static pangolin::Var<bool> trackFromVideo("ui.track",false,false,true);
    static pangolin::Var<bool> recordData("ui.record",false,false,true);
    static pangolin::Var<bool> stepVideo("ui.stepVideo",false,false);
    static pangolin::Var<bool> stepVideoBack("ui.stepVideoBack",false,false);

    static pangolin::Var<float> sigmaPixels("ui.sigmaPixels",3.0,0.01,4);
    static pangolin::Var<float> sigmaDepth("ui.sigmaDepth",0.1,0.001,1);
    static pangolin::Var<float> focalLength("ui.focalLength",depthSource->getFocalLength().x,0.8*depthSource->getFocalLength().x,1.2*depthSource->getFocalLength().x);//475,525); //525.0,450.0,600.0);
    static pangolin::Var<bool> showCameraPose("ui.showCameraPose",false,true);
    static pangolin::Var<bool> showEstimatedPose("ui.showEstimate",true,true);
    static pangolin::Var<bool> showReported("ui.showReported",false,true);

    static pangolin::Var<bool> showTablePlane("ui.showTablePlane",false,true);

    static pangolin::Var<bool> showVoxelized("ui.showVoxelized",false,true);
    static pangolin::Var<float> levelSet("ui.levelSet",0.0,-10.0,10.0);
    static pangolin::Var<bool> showTrackedPoints("ui.showPoints",true,true);
    static pangolin::Var<int> pointColoringObs("ui.pointColoringObs",0,0,NumPointColorings-1);
    static pangolin::Var<int> pointColoringPred("ui.pointColoringPred",0,0,NumPointColorings-1);

    static pangolin::Var<float> planeOffset("ui.planeOffset",-0.03,-0.05,0);

    static pangolin::Var<int> debugImg("ui.debugImg",DebugN,0,DebugN);

    static pangolin::Var<bool> showObsSdf("ui.showObsSdf",false,true);
    static pangolin::Var<bool> showPredictedPoints("ui.showPredictedPoints",false,true);
    static pangolin::Var<bool> showCollisionClouds("ui.showCollisionClouds",false,true);

    static pangolin::Var<float> fps("ui.fps",0);

    // optimization options
    pangolin::Var<bool> iterateButton("opt.iterate",false,false);
    pangolin::Var<int> itersPerFrame("opt.itersPerFrame",3,0,30);
    pangolin::Var<float> normalThreshold("opt.normalThreshold",-1.01,-1.01,1.0);
    pangolin::Var<float> distanceThreshold("opt.distanceThreshold",0.035,0.0,0.1);
    pangolin::Var<float> handRegularization("opt.handRegularization",0.1,0,10); // 1.0
    pangolin::Var<float> objectRegularization("opt.objectRegularization",0.1,0,10); // 1.0
    pangolin::Var<float> resetInfoThreshold("opt.resetInfoThreshold",1.0e-5,1e-5,2e-5);
    pangolin::Var<float> stabilityThreshold("opt.stabilityThreshold",7.5e-6,5e-6,1e-5);
    pangolin::Var<float> lambdaModToObs("opt.lambdaModToObs",0.5,0,1);
    pangolin::Var<float> lambdaObsToMod("opt.lambdaObsToMod",1,0,1);
    pangolin::Var<float> lambdaIntersection("opt.lambdaIntersection",1.f,0,40);

    pangolin::Var<float> infoAccumulationRate("opt.infoAccumulationRate",0.1,0.0,1.0); // 0.8
    pangolin::Var<float> maxRotationDamping("opt.maxRotationalDamping",50,0,200);
    pangolin::Var<float> maxTranslationDamping("opt.maxTranslationDamping",5,0,10);

    pangolin::Var<float> tableNormX("opt.tableNormX",initialTableNorm.x,-1,1);
    pangolin::Var<float> tableNormY("opt.tableNormY",initialTableNorm.y,-1,1);
    pangolin::Var<float> tableNormZ("opt.tableNormZ",initialTableNorm.z,-1,1);
    pangolin::Var<float> tableIntercept("opt.tableIntercept",initialTableIntercept,-1,1);

    static pangolin::Var<bool> subtractTable("opt.subtractTable",true,true);

    int fpsWindow = 10;
    pangolin::basetime lastTime = pangolin::TimeNow();

    const int depthWidth = depthSource->getDepthWidth();
    const int depthHeight = depthSource->getDepthHeight();

    const int predWidth = tracker.getPredictionWidth();
    const int predHeight = tracker.getPredictionHeight();

    dart::MirroredVector<uchar3> imgDepthSize(depthWidth*depthHeight);
    dart::MirroredVector<uchar3> imgPredSize(predWidth*predHeight);
    dart::MirroredVector<const uchar3 *> allSdfColors(tracker.getNumModels());
    for (int m=0; m<tracker.getNumModels(); ++m) {
        allSdfColors.hostPtr()[m] = tracker.getModel(m).getDeviceSdfColors();
    }
    allSdfColors.syncHostToDevice();

    // set up VBO to display point cloud
    GLuint pointCloudVbo,pointCloudColorVbo,pointCloudNormVbo;
    glGenBuffersARB(1,&pointCloudVbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudVbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(float4),tracker.getHostVertMap(),GL_DYNAMIC_DRAW_ARB);
    glGenBuffersARB(1,&pointCloudColorVbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudColorVbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(uchar3),imgDepthSize.hostPtr(),GL_DYNAMIC_DRAW_ARB);
    glGenBuffersARB(1,&pointCloudNormVbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudNormVbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(float4),tracker.getHostNormMap(),GL_DYNAMIC_DRAW_ARB);

    dart::OptimizationOptions & opts = tracker.getOptions();
    opts.lambdaObsToMod = 1;
    memset(opts.lambdaIntersection.data(),0,tracker.getNumModels()*tracker.getNumModels()*sizeof(float));
    opts.planeNormal[0] =  make_float3(0,0,1);
    opts.planeNormal[2] = make_float3(0,0,1);
    opts.planeNormal[1] = make_float3(0,0,0);
    opts.regularization[0] = opts.regularization[1] = opts.regularization[2] = 0.01;

    dart::MirroredModel & arm = tracker.getModel(0);
    dart::Pose & armPose = tracker.getPose(0);

    // -=-=-=-=- set up initial poses -=-=-=-=-
    armPose.getReducedArticulation()[0] = -0.25;
    armPose.getReducedArticulation()[1] = 0.2;
    armPose.getReducedArticulation()[2] = 0.88;
    armPose.getReducedArticulation()[3] = -0.92;
    armPose.setTransformModelToCamera(dart::SE3Fromse3(dart::se3(-0.25, 0.21, 0.88,0,0,0))*
                            dart::SE3Fromse3(dart::se3(0,0,0,0,0,0)));

    arm.setPose(armPose);

    // ------------------- main loop ---------------------
    for (int pangolinFrame=1; !pangolin::ShouldQuit(); ++pangolinFrame) {
        static pangolin::Var<bool> filteredNorms("ui.filteredNorms",false,true);
        static pangolin::Var<bool> filteredVerts("ui.filteredVerts",false,true);

        static pangolin::Var<bool> shouldQuit("ui.Quit",false,false);
        if (pangolin::Pushed(shouldQuit))
        {
            break;
        }

        if (pangolin::HasResized()) {
            pangolin::DisplayBase().ActivateScissorAndClear();
        }

        opts.focalLength = focalLength;
        opts.normThreshold = normalThreshold;
        for (int m=0; m<tracker.getNumModels(); ++m) {
            opts.distThreshold[m] = distanceThreshold;
        }
        opts.regularization[0] = opts.regularization[1] = opts.regularization[2] = 0.01;
        opts.regularizationScaled[0] = handRegularization;
        opts.regularizationScaled[1] = objectRegularization;
        opts.regularizationScaled[2] = handRegularization;
        opts.planeOffset[2] = planeOffset;
        opts.lambdaObsToMod = lambdaObsToMod;
        opts.lambdaModToObs = lambdaModToObs;
        opts.planeOffset[0] = planeOffset;
        opts.debugObsToModDA = pointColoringObs == PointColoringDA || (debugImg == DebugObsToModDA);
        opts.debugModToObsDA = debugImg == DebugModToObsDA;
        opts.debugObsToModErr = ((pointColoringObs == PointColoringErr) || (debugImg == DebugObsToModErr));
        opts.debugModToObsErr = ((pointColoringPred == PointColoringErr) || (debugImg == DebugModToObsErr));
        opts.debugJTJ = (debugImg == DebugJTJ);
        opts.numIterations = itersPerFrame;

        if (pangolin::Pushed(stepVideoBack)) {
            tracker.stepBackward();
        }

        bool iteratePushed = Pushed(iterateButton);

        if (pangolinFrame % fpsWindow == 0) {
            pangolin::basetime time = pangolin::TimeNow();
            if (trackFromVideo) {
                static int totalFrames = 0;
                static double totalTime = 0;
                totalFrames += fpsWindow;
                totalTime += pangolin::TimeDiff_s(lastTime,time);
                fps = totalFrames / totalTime;
            } else {
                fps = fpsWindow / pangolin::TimeDiff_s(lastTime,time);
            }
            lastTime = time;
        }

        if (recordData.GuiChanged())
        {
            depthSource->setRecordStatus(recordData);
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////
        //
        //
        // Process this frame                                                                                //
        //                                                                                //
        //////////////////////////////////////////////////////////////////////////////////////////////////////////
        {

            if (filteredNorms.GuiChanged()) {
                tracker.setFilteredNorms(filteredNorms);
            } else if (filteredVerts.GuiChanged()) {
                tracker.setFilteredVerts(filteredVerts);
            } else if (sigmaDepth.GuiChanged()) {
                tracker.setSigmaDepth(sigmaDepth);
            } else if (sigmaPixels.GuiChanged()) {
                tracker.setSigmaPixels(sigmaPixels);
            }

            // update pose based on sliders
            if (sliderControlled) {
                for (int m=0; m<tracker.getNumModels(); ++m) {
                    for (int i=0; i<tracker.getPose(m).getReducedArticulatedDimensions(); ++i) {
                        tracker.getPose(m).getReducedArticulation()[i] = *poseVars[m][i+6];
                    }
                    tracker.getPose(m).setTransformModelToCamera(dart::SE3Fromse3(dart::se3(*poseVars[m][0],*poseVars[m][1],*poseVars[m][2],0,0,0))*
                            dart::SE3Fromse3(dart::se3(0,0,0,*poseVars[m][3],*poseVars[m][4],*poseVars[m][5])));
                    tracker.updatePose(m);
                }
            }

            // run optimization method
            if (trackFromVideo || iteratePushed ) {

                tracker.optimizePoses();

                // update accumulated info
                for (int m=0; m<tracker.getNumModels(); ++m) {
                    const Eigen::MatrixXf & JTJ = *tracker.getOptimizer()->getJTJ(m);
                    if (JTJ.rows() == 0) { continue; }
                    Eigen::MatrixXf & dampingMatrix = tracker.getDampingMatrix(m);
                    for (int i=0; i<3; ++i) {
                        dampingMatrix(i,i) = std::min((float)maxTranslationDamping,dampingMatrix(i,i) + infoAccumulationRate*JTJ(i,i));
                    }
                    for (int i=3; i<tracker.getPose(m).getReducedDimensions(); ++i) {
                        dampingMatrix(i,i) = std::min((float)maxRotationDamping,dampingMatrix(i,i) + infoAccumulationRate*JTJ(i,i));
                    }
                }

                float errPerObsPoint = optimizer.getErrPerObsPoint(1,0);
                float errPerModPoint = optimizer.getErrPerModPoint(1,0);

                infoLog.Log(errPerObsPoint,errPerObsPoint+errPerModPoint,stabilityThreshold,resetInfoThreshold);

                for (int m=0; m<tracker.getNumModels(); ++m) {
                    for (int i=0; i<tracker.getPose(m).getReducedArticulatedDimensions(); ++i) {
                        *poseVars[m][i+6] = tracker.getPose(m).getReducedArticulation()[i];
                    }
                    dart::SE3 T_cm = tracker.getPose(m).getTransformModelToCamera();
                    *poseVars[m][0] = T_cm.r0.w; T_cm.r0.w = 0;
                    *poseVars[m][1] = T_cm.r1.w; T_cm.r1.w = 0;
                    *poseVars[m][2] = T_cm.r2.w; T_cm.r2.w = 0;
                    dart::se3 t_cm = dart::se3FromSE3(T_cm);
                    *poseVars[m][3] = t_cm.p[3];
                    *poseVars[m][4] = t_cm.p[4];
                    *poseVars[m][5] = t_cm.p[5];
                }

            }

        }

        std::vector<float> vec;
        std::ostringstream oss;
        if (recordData)
        {
            float3 this_joint = tracker.getModel(0).getJointOrientation(1);
            vec.push_back(this_joint.x);
            vec.push_back(this_joint.y);
            vec.push_back(this_joint.z);

            if (!vec.empty())
            {
            // Convert all but the last element to avoid a trailing ","
            std::copy(vec.begin(), vec.end()-1,
                std::ostream_iterator<int>(oss, ","));

            // Now add the last element with no delimiter
            oss << vec.back();
            }

            std::cout << oss.str() << std::endl;
            *pose_output << oss.str() << std::endl;
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////
        //                                                                                //
        // Render this frame                                                                                //
        //                                                                                //
        //////////////////////////////////////////////////////////////////////////////////////////////////////////

        glClearColor (1.0, 1.0, 1.0, 1.0);
        glShadeModel (GL_SMOOTH);
        float4 lightPosition = make_float4(normalize(make_float3(-0.4405,-0.5357,-0.619)),0);
        glLightfv(GL_LIGHT0, GL_POSITION, (float*)&lightPosition);

        camDisp.ActivateScissorAndClear(camState);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LIGHT0);
        glEnable(GL_NORMALIZE);
        glEnable(GL_LIGHTING);

        camDisp.ActivateAndScissor(camState);

        glPushMatrix();

        if (showCameraPose) {

            glColor3f(0,0,0);
            glPushMatrix();

//            glRotatef(180,0,1,0);
//            glutSolidCube(0.02);

//            glTranslatef(0,0,-0.02);
//            glutSolidCone(0.0125,0.02,10,1);

            glPopMatrix();

        }

        glColor4ub(0xff,0xff,0xff,0xff);
        if (showEstimatedPose) {

            glEnable(GL_COLOR_MATERIAL);

            glPushMatrix();

            if (showVoxelized) {
                glColor3f(0.2,0.3,1.0);

                for (int m=0; m<tracker.getNumModels(); ++m) {
                    tracker.updatePose(m);
                    tracker.getModel(m).renderVoxels(levelSet);
                }
            }
            else{
                for (int m=0; m<tracker.getNumModels(); ++m) {
                    tracker.updatePose(m);
                    tracker.getModel(m).render();
                }
            }

            glPopMatrix();

        }

        glPointSize(1.0f);

        if (showTablePlane) {

            float3 normal = normalize(make_float3(tableNormX,tableNormY,tableNormZ));
            tableNormX = normal.x;
            tableNormY = normal.y;
            tableNormZ = normal.z;

            float3 ipv1 = cross(normal,normal.x == 1 ? make_float3(0,1,0) : make_float3(1,0,0));
            float3 ipv2 = cross(normal,ipv1);

            float3 pts[4] = { operator+(operator *( 0.5,ipv1),operator *( 0.5,ipv2)),
                              operator+(operator *( 0.5,ipv1),operator *(-0.5,ipv2)),
                              operator+(operator *(-0.5,ipv1),operator *(-0.5,ipv2)),
                              operator+(operator *(-0.5,ipv1),operator *( 0.5,ipv2))};

            glColor3ub(120,100,100);
            glBegin(GL_QUADS);
            glNormal3f(-normal.x,-normal.y,-normal.z);
            for (int i=0; i<4; ++i) {
                glVertex3f(tableIntercept*normal.x + pts[i].x,
                           tableIntercept*normal.y + pts[i].y,
                           tableIntercept*normal.z + pts[i].z);
            }
            glEnd();

        }

        if (showObsSdf) {
            static pangolin::Var<float> levelSet("ui.levelSet",0,-10,10);

            for (int m=0; m<tracker.getNumModels(); ++m) {

                glPushMatrix();
                dart::glMultSE3(tracker.getModel(m).getTransformModelToCamera());
                tracker.getModel(m).syncObsSdfDeviceToHost();
                dart::Grid3D<float> * obsSdf = tracker.getModel(m).getObsSdf();
                tracker.getModel(m).renderSdf(*obsSdf,levelSet);
                glPopMatrix();
            }
        }

        if (showTrackedPoints) {

            glPointSize(4.0f);
            glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudVbo);
            glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(float4),tracker.getHostVertMap(),GL_DYNAMIC_DRAW_ARB);

            glEnableClientState(GL_VERTEX_ARRAY);
            glDisableClientState(GL_NORMAL_ARRAY);
            glVertexPointer(4, GL_FLOAT, 0, 0);

            switch (pointColoringObs) {
            case PointColoringNone:
                glColor3f(0.25,0.25,0.25);
                glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudNormVbo);
                glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(float4),tracker.getHostNormMap(),GL_DYNAMIC_DRAW_ARB);

                glNormalPointer(GL_FLOAT, 4*sizeof(float), 0);
                glEnableClientState(GL_NORMAL_ARRAY);
                break;
            case PointColoringRGB:
                glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudColorVbo);
                glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(uchar3),depthSource->getColor(),GL_DYNAMIC_DRAW_ARB);
                glColorPointer(3,GL_UNSIGNED_BYTE, 0, 0);
                glEnableClientState(GL_COLOR_ARRAY);
                glDisable(GL_LIGHTING);
                break;
            case PointColoringErr:
                {
                    static float errorMin = 0.0;
                    static float errorMax = 0.1;
                    float * dErr;
                    cudaMalloc(&dErr,depthWidth*depthHeight*sizeof(float));
                    dart::imageSquare(dErr,tracker.getDeviceDebugErrorObsToMod(),depthWidth,depthHeight);
                    dart::colorRampHeatMapUnsat(imgDepthSize.devicePtr(),dErr,depthWidth,depthHeight,errorMin,errorMax);
                    cudaFree(dErr);
                    imgDepthSize.syncDeviceToHost();
                    glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudColorVbo);
                    glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(uchar3),imgDepthSize.hostPtr(),GL_DYNAMIC_DRAW_ARB);
                    glColorPointer(3,GL_UNSIGNED_BYTE, 0, 0);
                    glEnableClientState(GL_COLOR_ARRAY);
                    glDisable(GL_LIGHTING);
                }
                break;
            case PointColoringDA:
                {
                    const int * dDebugDA = tracker.getDeviceDebugDataAssociationObsToMod();
                    dart::colorDataAssociationMultiModel(imgDepthSize.devicePtr(),dDebugDA,allSdfColors.devicePtr(),depthWidth,depthHeight);
                    imgDepthSize.syncDeviceToHost();
                    glBindBufferARB(GL_ARRAY_BUFFER_ARB,pointCloudColorVbo);
                    glBufferDataARB(GL_ARRAY_BUFFER_ARB,depthWidth*depthHeight*sizeof(uchar3),imgDepthSize.hostPtr(),GL_DYNAMIC_DRAW_ARB);
                    glColorPointer(3,GL_UNSIGNED_BYTE, 0, 0);
                    glEnableClientState(GL_COLOR_ARRAY);
                    glDisable(GL_LIGHTING);
                }
                break;
            }

            glDrawArrays(GL_POINTS,0,depthWidth*depthHeight);
            glBindBuffer(GL_ARRAY_BUFFER_ARB,0);

            glDisableClientState(GL_VERTEX_ARRAY);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_NORMAL_ARRAY);

            glPointSize(1.0f);

        }

        if (showPredictedPoints) {

            glPointSize(4.0f);

            const float4 * dPredictedVertMap = tracker.getDevicePredictedVertMap();
            const int nPoints = tracker.getPredictionWidth()*tracker.getPredictionHeight();
            float4 * hPredictedVertMap = new float4[nPoints];
            cudaMemcpy(hPredictedVertMap,dPredictedVertMap,nPoints*sizeof(float4),cudaMemcpyDeviceToHost);

            glDisable(GL_LIGHTING);
            glBegin(GL_POINTS);

            if (pointColoringPred == PointColoringErr) {
                static pangolin::Var<float> errMin("ui.errMin",0,0,0.05);
                static pangolin::Var<float> errMax("ui.errMax",0.01,0,0.05);
                dart::MirroredVector<uchar3> debugImg(tracker.getPredictionWidth()*tracker.getPredictionHeight());
                dart::colorRampHeatMapUnsat(debugImg.devicePtr(),
                                            tracker.getDeviceDebugErrorModToObs(),
                                            depthWidth,depthHeight,
                                            errMin,errMax);
                debugImg.syncDeviceToHost();

                for (int i=0; i<nPoints; ++i) {
                    if (hPredictedVertMap[i].z > 0) {
                        uchar3 color = debugImg.hostPtr()[i];
                        glColor3ubv((unsigned char*)&color);
                        glVertex3f(hPredictedVertMap[i].x,hPredictedVertMap[i].y,hPredictedVertMap[i].z);
                    }
                }

            } else {

                for (int i=0; i<nPoints; ++i) {
                    if (hPredictedVertMap[i].z > 0) {
                        int id = round(hPredictedVertMap[i].w);
                        int model = id >> 16;
                        int sdf = id & 65535;
                        uchar3 color = tracker.getModel(model).getSdfColor(sdf);
                        glColor3ubv((unsigned char*)&color);
                        glVertex3f(hPredictedVertMap[i].x,hPredictedVertMap[i].y,hPredictedVertMap[i].z);
                    }
                }
            }

            glEnd();
            delete [] hPredictedVertMap;

            glPointSize(1.0f);
        }

        if (showCollisionClouds) {
            glPointSize(10);
            glColor3f(0,0,1.0f);
            glDisable(GL_LIGHTING);
            glBegin(GL_POINTS);
            for (int m=0; m<tracker.getNumModels(); ++m) {
                const float4 * collisionCloud = tracker.getCollisionCloud(m);
                for (int i=0; i<tracker.getCollisionCloudSize(m); ++i) {
                    int grid = round(collisionCloud[i].w);
                    int frame = tracker.getModel(m).getSdfFrameNumber(grid);
                    float4 v = tracker.getModel(m).getTransformModelToCamera()*
                               tracker.getModel(m).getTransformFrameToModel(frame)*
                               make_float4(make_float3(collisionCloud[i]),1.0);
                    glVertex3fv((float*)&v);
                }
            }
            glEnd();
            glEnable(GL_LIGHTING);

            glPointSize(1);
            glColor3f(1,1,1);
        }

        glPopMatrix();

        imgDisp.ActivateScissorAndClear();
        glDisable(GL_LIGHTING);
        glColor4ub(255,255,255,255);

        switch (debugImg) {
            case DebugColor:
            {
                if (depthSource->hasColor()) {
                    imgTexDepthSize.Upload(depthSource->getColor(),GL_RGB,GL_UNSIGNED_BYTE);
                    imgTexDepthSize.RenderToViewport();
                }
            }
            break;
        case DebugObsDepth:
            {

                static const float depthMin = 0.1;
                static const float depthMax = 4.0;

                const unsigned short * depth = depthSource->getDepth();

                for (int i=0; i<depthSource->getDepthWidth()*depthSource->getDepthHeight(); ++i) {
                    if (depth[i] == 0) {
                        imgDepthSize[i] = make_uchar3(128,0,0);
                    } else {
                        unsigned char g = std::max(0,std::min((int)(255*(depth[i]*depthSource->getScaleToMeters()-depthMin)/(float)(depthMax - depthMin)),255));
                        imgDepthSize[i] = make_uchar3(g,g,g);
                    }

                }

                imgTexDepthSize.Upload(imgDepthSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
                imgTexDepthSize.RenderToViewport();
            }
        case DebugPredictedDepth:
            {
                static const float depthMin = 0.3;
                static const float depthMax = 1.0;

                const float4 * dPredictedVertMap = tracker.getDevicePredictedVertMap();
                static std::vector<float4> hPredictedVertMap(predWidth*predHeight);

                cudaMemcpy(hPredictedVertMap.data(),dPredictedVertMap,predWidth*predHeight*sizeof(float4),cudaMemcpyDeviceToHost);

                for (int i=0; i<predHeight*predWidth; ++i) {
                    const float depth = hPredictedVertMap[i].z;
                    if (depth == 0) {
                        imgPredSize[i] = make_uchar3(128,0,0);
                    } else {
                        unsigned char g = std::max(0,std::min((int)(255*(depth-depthMin)/(float)(depthMax - depthMin)),255));
                        imgPredSize[i] = make_uchar3(g,g,g);
                    }
                }

                imgTexPredictionSize.Upload(imgPredSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
                imgTexPredictionSize.RenderToViewport();
            }
            break;
        case DebugObsToModDA:
        {
            dart::colorDataAssociationMultiModel(imgDepthSize.devicePtr(),
                                                 tracker.getDeviceDebugDataAssociationObsToMod(),
                                                 allSdfColors.devicePtr(),depthWidth,depthHeight);\
            imgDepthSize.syncDeviceToHost();
            imgTexDepthSize.Upload(imgDepthSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
            imgTexDepthSize.RenderToViewport();
            break;
        }
        case DebugModToObsDA:
        {
            dart::colorDataAssociationMultiModel(imgPredSize.devicePtr(),
                                                 tracker.getDeviceDebugDataAssociationModToObs(),
                                                 allSdfColors.devicePtr(),predWidth,predHeight);\
            imgPredSize.syncDeviceToHost();
            imgTexPredictionSize.Upload(imgPredSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
            imgTexPredictionSize.RenderToViewport();
            break;
        }
        case DebugObsToModErr:
            {
                static const float errMax = 0.01;
                dart::colorRampHeatMapUnsat(imgDepthSize.devicePtr(),
                                            tracker.getDeviceDebugErrorObsToMod(),
                                            depthWidth,depthHeight,
                                            0.f,errMax);
                imgDepthSize.syncDeviceToHost();
                imgTexDepthSize.Upload(imgDepthSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
                imgTexDepthSize.RenderToViewport();
            }
            break;
        case DebugModToObsErr:
            {
                static const float errMax = 0.01;
                dart::colorRampHeatMapUnsat(imgPredSize.devicePtr(),
                                            tracker.getDeviceDebugErrorModToObs(),
                                            depthWidth,depthHeight,
                                            0.f,errMax);
                imgPredSize.syncDeviceToHost();
                imgTexPredictionSize.Upload(imgPredSize.hostPtr(),GL_RGB,GL_UNSIGNED_BYTE);
                imgTexPredictionSize.RenderToViewport();
            }
            break;
        case DebugJTJ:
            imgTexDepthSize.Upload(tracker.getOptimizer()->getJTJimg(),GL_RGB,GL_UNSIGNED_BYTE);
            imgTexDepthSize.RenderToViewportFlipY();
            break;
        default:
            break;
        }

        cudaError_t err = cudaGetLastError();
        if (err != cudaSuccess) {
            std::cerr << cudaGetErrorString(err) << std::endl;
        }

        pangolin::FinishFrame();

        if (pangolin::Pushed(stepVideo) || trackFromVideo || pangolinFrame == 1) {

            tracker.stepForward();

            // update table
            {
                float4 tableNorm = make_float4(normalize(make_float3(tableNormX,tableNormY,tableNormZ)),0.f);
                float4 tablePoint = make_float4(make_float3(tableIntercept*tableNorm),1.f); // + make_Float4(0,tableNorm.z,-tableNorm.Y,1.f);
                tableNormX = tableNorm.x;
                tableNormY = tableNorm.y;
                tableNormZ = tableNorm.z;
                tableIntercept = dot(make_float3(tablePoint),make_float3(tableNorm));
            }

            static pangolin::Var<float> planeFitNormThresh("opt.planeNormThresh",0.25,-1,1);
            static pangolin::Var<float> planeFitDistThresh("opt.planeDistThresh",0.005,0.0001,0.005);

            if (subtractTable) {
                tracker.subtractPlane(make_float3(tableNormX,tableNormY,tableNormZ),
                                      tableIntercept,0.005,-1.01);
            }

            float totalPerPointError = optimizer.getErrPerObsPoint(1,0) + optimizer.getErrPerModPoint(1,0);
        }
    }
    delete depthSource;
    pose_output->close();
    glutDestroyWindow(myargc);
    glDeleteBuffersARB(1,&pointCloudVbo);
    glDeleteBuffersARB(1,&pointCloudColorVbo);
    glDeleteBuffersARB(1,&pointCloudNormVbo);

    for (int m=0; m<tracker.getNumModels(); ++m) {
        for (int i=0; i<tracker.getPose(m).getReducedDimensions(); ++i) {
            delete poseVars[m][i];
        }
        delete [] poseVars[m];
    }

    for (uint i=0; i<sizeVars.size(); ++i) {
        delete sizeVars[i];
    }

    return 0;
}

ext: cpp

max_stars_repo_name: JonathanAMichaels/DARTPrimate

max_issues_repo_name: JonathanAMichaels/DARTPrimate

max_forks_repo_name: JonathanAMichaels/DARTPrimate


text:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define MAX_BUF 1024

#include <sstream>
#include <iostream>
#include <string>
#include <chrono>
using namespace std;
#include <boost/property_tree/json_parser.hpp>

const static double PI = 3.14159265;
const static int iConstRound = 60;
const static double iConstRoundLimit = sin(iConstRound*PI/180.0);
const static double dConstDifferMin = sin(PI/180.0);

static int fd = -1;
#include <signal.h>
#include <stdio.h>
void sigcatch(int) {
	if(fd > 0) {
		close(fd);
	}
	exit(0);
}
int main(int ac,char*av[])
{
	system("rm -f /tmp/mpu.6050.unix.domain");
	if (SIG_ERR == signal(SIGINT, sigcatch)) {
		printf("failed to set signal handler.n");
		exit(1);
	}
     fd = socket( AF_LOCAL, SOCK_DGRAM, 0 );

	struct sockaddr_un addr;
	bzero( &addr, sizeof(addr) );
	addr.sun_family = AF_LOCAL;
	strcpy( addr.sun_path, "/tmp/mpu.6050.unix.domain" );

   int use = 1;
   if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &use, sizeof(int)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
   }

	struct timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec = 1000;
   	if (::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
	    	perror("setsockopt(SO_RCVTIMEO) failed");
   	}

   if(::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {

     printf(" cannot bind socket: %d. \n",errno);
     close(fd);

     return 0;

   }

    char buf[MAX_BUF];
    double degree = 90.0;
    if(ac > 1) {
    	degree = ::atof(av[1]);
    }
    degree = std::fabs(degree);
    int iRound = degree/iConstRound;
    double dRemain = degree - (iRound *iConstRound);
    double startDeg = 0.0;
    bool restartBase = true;
    chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
    int msRun = 0;
    // 1000 ms
    while(msRun < 1000) {
    	chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    	msRun = chrono::duration_cast<chrono::milliseconds>(end - start).count();
    	//printf("msRun=<%d>\n",msRun);

    	socklen_t len = sizeof(addr);
        int ret = ::recvfrom(fd, buf, MAX_BUF, 0, (struct sockaddr *)&addr, &len);
        if(ret>0){
            //printf("Received: %s\n", buf);
            string recvStr(buf,ret);
            //std::cout << recvStr << std::endl;
            std::stringstream ss;
            ss << recvStr;
            try {
            	boost::property_tree::ptree pt;
            	boost::property_tree::read_json(ss, pt);
            	auto current = pt.get<double>("yaw");
            	//std::cout <<  current << std::endl;
            	if(restartBase) {
            		startDeg = current;
            		restartBase = false;
            		continue;
            	}
            	double dRoundRad = 0.0;
            	if(iRound >0) {
            		dRoundRad = iConstRoundLimit;
            	} else {
            		dRoundRad = sin(PI*dRemain/180.0);
            	}
            	double diffDeg = std::fabs(current - startDeg);
            	std::cout <<  "diffDeg=<" << diffDeg <<">"<< std::endl;
            	/// over
            	if(diffDeg > iConstRound) {
            		diffDeg = std::fabs(360 -diffDeg);
            	}
            	std::cout <<  "diffDeg=<" << diffDeg <<">"<< std::endl;
            	double diffRad = (PI*diffDeg/180.0);
            	double diff = dRoundRad - sin(diffRad);
            	std::cout <<  "diff=<" << diff <<">"<< std::endl;
            	if(diff <= dConstDifferMin) {
            		std::cout <<  "iRound=<" << iRound <<">"<< std::endl;
            		if(iRound >0) {
            			iRound--;
	            		restartBase = true;
            		}
            		else {
            			break;
            		}
            	}
            } catch(std::exception e) {
            	std::cout << e.what() << std::endl;
            }
        } else if (ret==0){
        	//printf("ret=<%d>\n",ret);
        } else {
        	//printf("ret=<%d>\n",ret);
        }
    }
    close(fd);

    return 0;
}


text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 * 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.
 *
 *************************************************************/

#ifndef SD_SIDEBAR_PANELS_PANEL_BASE_HXX
#define SD_SIDEBAR_PANELS_PANEL_BASE_HXX

#include "IDisposable.hxx"
#include "ISidebarReceiver.hxx"
#include <sfx2/sidebar/ILayoutableWindow.hxx>

#include <vcl/ctrl.hxx>

#include <boost/scoped_ptr.hpp>

namespace css = ::com::sun::star;
namespace cssu = ::com::sun::star::uno;

namespace sd {
    class ViewShellBase;
}

namespace sd { namespace sidebar {

class PanelBase
    : public Control,
      public sfx2::sidebar::ILayoutableWindow,
      public IDisposable,
      public ISidebarReceiver
{
public:
    PanelBase (
        ::Window* pParentWindow,
        ViewShellBase& rViewShellBase);
    virtual ~PanelBase (void);

    virtual void Resize (void);

    // IDisposable
    virtual void Dispose (void);

    // ILayoutableWindow
    virtual css::ui::LayoutSize GetHeightForWidth (const sal_Int32 nWidth);

    // ISidebarReceiver
    virtual void SetSidebar (const cssu::Reference<css::ui::XSidebar>& rxSidebar);

    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible > CreateAccessibleObject (
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::accessibility::XAccessible>& rxParent);

protected:
    ::boost::scoped_ptr< ::Window> mpWrappedControl;
    virtual ::Window* CreateWrappedControl (
        ::Window* pParentWindow,
        ViewShellBase& rViewShellBase) = 0;

private:
    cssu::Reference<css::ui::XSidebar> mxSidebar;
    ViewShellBase& mrViewShellBase;

    bool ProvideWrappedControl (void);
};

} } // end of namespace sd::sidebar

#endif

ext: hxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice