<commit_before>#include <lamtram/builder-factory.h>
#include <lamtram/macros.h>
#include <dynet/model.h>
#include <dynet/rnn.h>
#include <dynet/lstm.h>
#include <dynet/gru.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace lamtram;

BuilderSpec::BuilderSpec(const std::string & spec) {
    vector<string> strs;
    boost::algorithm::split(strs, spec, boost::is_any_of(":"));
    if(strs.size() != 3)
        THROW_ERROR("Invalid layer specification \"" << spec << "\", must be layer type (rnn/lstm/gru), number of nodes, number of layers, with the three elements separated by a token.");
    type = strs[0];
    nodes = boost::lexical_cast<int>(strs[1]);
    if(nodes <= 0) nodes = GlobalVars::layer_size;
    layers = boost::lexical_cast<int>(strs[2]);
    multiplier = (type == "lstm" ? 2 : 1);
}

BuilderPtr BuilderFactory::CreateBuilder(const BuilderSpec & spec, int input_dim, dynet::Model & model) {
    // cerr << "BuilderFactor::CreateBuilder(" << spec << ", " << input_dim << ", " << (long)&model << ")" << endl;
    if(spec.type == "rnn") {
        return BuilderPtr(new dynet::SimpleRNNBuilder(spec.layers, input_dim, spec.nodes, model));
    } else if(spec.type == "lstm") {
        return BuilderPtr(new dynet::LSTMBuilder(spec.layers, input_dim, spec.nodes, model));
    } else if(spec.type == "gru") {
        THROW_ERROR("GRU spec.nodes are not supported yet.");
        // return BuilderPtr(new dynet::GRUBuilder(spec.layers, input_dim, spec.nodes, model));
    } else {
        THROW_ERROR("Unknown layer type " << spec.type);
    }
}
<commit_msg>Changed default LSTM to VanillaLSTM<commit_after>#include <lamtram/builder-factory.h>
#include <lamtram/macros.h>
#include <dynet/model.h>
#include <dynet/rnn.h>
#include <dynet/lstm.h>
#include <dynet/gru.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace lamtram;

BuilderSpec::BuilderSpec(const std::string & spec) {
    vector<string> strs;
    boost::algorithm::split(strs, spec, boost::is_any_of(":"));
    if(strs.size() != 3)
        THROW_ERROR("Invalid layer specification \"" << spec << "\", must be layer type (rnn/lstm/gru), number of nodes, number of layers, with the three elements separated by a token.");
    type = strs[0];
    nodes = boost::lexical_cast<int>(strs[1]);
    if(nodes <= 0) nodes = GlobalVars::layer_size;
    layers = boost::lexical_cast<int>(strs[2]);
    multiplier = (type == "lstm" ? 2 : 1);
}

BuilderPtr BuilderFactory::CreateBuilder(const BuilderSpec & spec, int input_dim, dynet::Model & model) {
    // cerr << "BuilderFactor::CreateBuilder(" << spec << ", " << input_dim << ", " << (long)&model << ")" << endl;
    if(spec.type == "rnn") {
        return BuilderPtr(new dynet::SimpleRNNBuilder(spec.layers, input_dim, spec.nodes, model));
    } else if(spec.type == "clstm") {
        return BuilderPtr(new dynet::LSTMBuilder(spec.layers, input_dim, spec.nodes, model));
    } else if(spec.type == "lstm") {
        return BuilderPtr(new dynet::VanillaLSTMBuilder(spec.layers, input_dim, spec.nodes, model));
    } else if(spec.type == "gru") {
        THROW_ERROR("GRU spec.nodes are not supported yet.");
        // return BuilderPtr(new dynet::GRUBuilder(spec.layers, input_dim, spec.nodes, model));
    } else {
        THROW_ERROR("Unknown layer type " << spec.type);
    }
}
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <unordered_map>
#include <memory>

namespace bt
{

class Blackboard
{
public:
    static Blackboard& GetInstance()
    {
        static Blackboard instance;
        return instance;
    }

    void SetBool(std::string key, bool value);
    bool GetBool(std::string key);
    bool HasBool(std::string key) const;

    void SetInt(std::string key, int value);
    int GetInt(std::string key);
    bool HasInt(std::string key) const;

    void SetFloat(std::string key, float value);
    float GetFloat(std::string key);
    bool HasFloat(std::string key) const;

    void SetDouble(std::string key, double value);
    double GetDouble(std::string key);
    bool HasDouble(std::string key) const;

    void SetString(std::string key, std::string value);
    std::string GetString(std::string key);
    bool HasString(std::string key) const;

    using Ptr = std::shared_ptr<Blackboard>;

protected:
    std::unordered_map<std::string, bool> bools;
    std::unordered_map<std::string, int> ints;
    std::unordered_map<std::string, float> floats;
    std::unordered_map<std::string, double> doubles;
    std::unordered_map<std::string, std::string> strings;
};

}
<commit_msg>removed singleton and made blackboard header only<commit_after>#pragma once

#include <string>
#include <unordered_map>
#include <memory>

namespace bt
{

class Blackboard
{
public:
    void SetBool(std::string key, bool value) { bools[key] = value; }
    bool GetBool(std::string key)
    {
        if (bools.find(key) == bools.end()) {
            bools[key] = false;
        }
        return bools[key];
    }
    bool HasBool(std::string key) const { return bools.find(key) != bools.end(); }

    void SetInt(std::string key, int value)  { ints[key] = value; }
    int GetInt(std::string key)
    {
        if (ints.find(key) == ints.end()) {
            ints[key] = 0;
        }
        return ints[key];
    }
    bool HasInt(std::string key) const  { return ints.find(key) != ints.end(); }

    void SetFloat(std::string key, float value)  { floats[key] = value; }
    float GetFloat(std::string key)
    {
        if (floats.find(key) == floats.end()) {
            floats[key] = 0.0f;
        }
        return floats[key];
    }
    bool HasFloat(std::string key) const  { return floats.find(key) != floats.end(); }

    void SetDouble(std::string key, double value)  { doubles[key] = value; }
    double GetDouble(std::string key)
    {
        if (doubles.find(key) == doubles.end()) {
            doubles[key] = 0.0f;
        }
        return doubles[key];
    }
    bool HasDouble(std::string key) const  { return doubles.find(key) != doubles.end(); }

    void SetString(std::string key, std::string value)  { strings[key] = value; }
    std::string GetString(std::string key)
    {
        if (strings.find(key) == strings.end()) {
            strings[key] = "";
        }
        return strings[key];
    }
    bool HasString(std::string key) const  { return strings.find(key) != strings.end(); }

    using Ptr = std::shared_ptr<Blackboard>;

protected:
    std::unordered_map<std::string, bool> bools;
    std::unordered_map<std::string, int> ints;
    std::unordered_map<std::string, float> floats;
    std::unordered_map<std::string, double> doubles;
    std::unordered_map<std::string, std::string> strings;
};

}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "AbstractDataPlugin.h"

// Marble
#include "AbstractDataPluginModel.h"
#include "AbstractDataPluginItem.h"
#include "GeoPainter.h"
#include "GeoSceneLayer.h"
#include "ViewportParams.h"
#include "MarbleDebug.h"

// Qt
#include <QtCore/QEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QRegion>

namespace Marble
{

class AbstractDataPluginPrivate
{
 public:
    AbstractDataPluginPrivate()
        : m_model( 0 ),
          m_numberOfItems( 10 )
    {
    }

    ~AbstractDataPluginPrivate() {
        delete m_model;
    }

    AbstractDataPluginModel *m_model;
    QString m_name;
    quint32 m_numberOfItems;
};

AbstractDataPlugin::AbstractDataPlugin()
    : RenderPlugin(),
      d( new AbstractDataPluginPrivate )
{
}

AbstractDataPlugin::~AbstractDataPlugin()
{
    delete d;
}

QStringList AbstractDataPlugin::backendTypes() const
{
    return QStringList( name() );
}

QString AbstractDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList AbstractDataPlugin::renderPosition() const
{
    return QStringList( "HOVERS_ABOVE_SURFACE" );
}

bool AbstractDataPlugin::isInitialized() const
{
    return true;
}

bool AbstractDataPlugin::render( GeoPainter *painter, ViewportParams *viewport,
             const QString& renderPos, GeoSceneLayer * layer)
{
    if ( ( 0 == d->m_model ) || !isInitialized() ) {
        return true;
    }

    if ( renderPos != "HOVERS_ABOVE_SURFACE" ) {
        return true;
    }

    QList<AbstractDataPluginItem*> items = d->m_model->items( viewport,
                                                              dataFacade(),
                                                              numberOfItems() );
    painter->save();

    // Paint the most important item at last
    for( int i = items.size() - 1; i >= 0; --i ) {
        items.at( i )->paintEvent( painter, viewport, renderPos, layer );
    }

    painter->restore();

    return true;
}

AbstractDataPluginModel *AbstractDataPlugin::model() const
{
    return d->m_model;
}

void AbstractDataPlugin::setModel( AbstractDataPluginModel* model )
{
    if ( d->m_model ) {
        disconnect( d->m_model, SIGNAL( itemsUpdated() ), this, SLOT( requestRepaint() ) );
        delete d->m_model;
    }
    d->m_model = model;

    connect( d->m_model, SIGNAL( itemsUpdated() ), this, SLOT( requestRepaint() ) );
}

QString AbstractDataPlugin::nameId() const
{
    return d->m_name;
}

void AbstractDataPlugin::setNameId( const QString& name )
{
    d->m_name = name;
}

quint32 AbstractDataPlugin::numberOfItems() const
{
    return d->m_numberOfItems;
}

void AbstractDataPlugin::setNumberOfItems( quint32 number )
{
    bool changed = ( number != d->m_numberOfItems );
    d->m_numberOfItems = number;

    if ( changed )
        emit changedNumberOfItems( number );
}

QList<AbstractDataPluginItem *> AbstractDataPlugin::whichItemAt( const QPoint& curpos )
{
    if ( enabled() && visible() ) {
        return d->m_model->whichItemAt( curpos );
    }
    else {
        return QList<AbstractDataPluginItem *>();
    }
}

void AbstractDataPlugin::requestRepaint()
{
    emit repaintNeeded( QRegion() );
}

} // namespace Marble

#include "AbstractDataPlugin.moc"
<commit_msg>Fix crash when model is null.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "AbstractDataPlugin.h"

// Marble
#include "AbstractDataPluginModel.h"
#include "AbstractDataPluginItem.h"
#include "GeoPainter.h"
#include "GeoSceneLayer.h"
#include "ViewportParams.h"
#include "MarbleDebug.h"

// Qt
#include <QtCore/QEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QRegion>

namespace Marble
{

class AbstractDataPluginPrivate
{
 public:
    AbstractDataPluginPrivate()
        : m_model( 0 ),
          m_numberOfItems( 10 )
    {
    }

    ~AbstractDataPluginPrivate() {
        delete m_model;
    }

    AbstractDataPluginModel *m_model;
    QString m_name;
    quint32 m_numberOfItems;
};

AbstractDataPlugin::AbstractDataPlugin()
    : RenderPlugin(),
      d( new AbstractDataPluginPrivate )
{
}

AbstractDataPlugin::~AbstractDataPlugin()
{
    delete d;
}

QStringList AbstractDataPlugin::backendTypes() const
{
    return QStringList( name() );
}

QString AbstractDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList AbstractDataPlugin::renderPosition() const
{
    return QStringList( "HOVERS_ABOVE_SURFACE" );
}

bool AbstractDataPlugin::isInitialized() const
{
    return true;
}

bool AbstractDataPlugin::render( GeoPainter *painter, ViewportParams *viewport,
             const QString& renderPos, GeoSceneLayer * layer)
{
    if ( ( 0 == d->m_model ) || !isInitialized() ) {
        return true;
    }

    if ( renderPos != "HOVERS_ABOVE_SURFACE" ) {
        return true;
    }

    QList<AbstractDataPluginItem*> items = d->m_model->items( viewport,
                                                              dataFacade(),
                                                              numberOfItems() );
    painter->save();

    // Paint the most important item at last
    for( int i = items.size() - 1; i >= 0; --i ) {
        items.at( i )->paintEvent( painter, viewport, renderPos, layer );
    }

    painter->restore();

    return true;
}

AbstractDataPluginModel *AbstractDataPlugin::model() const
{
    return d->m_model;
}

void AbstractDataPlugin::setModel( AbstractDataPluginModel* model )
{
    if ( d->m_model ) {
        disconnect( d->m_model, SIGNAL( itemsUpdated() ), this, SLOT( requestRepaint() ) );
        delete d->m_model;
    }
    d->m_model = model;

    connect( d->m_model, SIGNAL( itemsUpdated() ), this, SLOT( requestRepaint() ) );
}

QString AbstractDataPlugin::nameId() const
{
    return d->m_name;
}

void AbstractDataPlugin::setNameId( const QString& name )
{
    d->m_name = name;
}

quint32 AbstractDataPlugin::numberOfItems() const
{
    return d->m_numberOfItems;
}

void AbstractDataPlugin::setNumberOfItems( quint32 number )
{
    bool changed = ( number != d->m_numberOfItems );
    d->m_numberOfItems = number;

    if ( changed )
        emit changedNumberOfItems( number );
}

QList<AbstractDataPluginItem *> AbstractDataPlugin::whichItemAt( const QPoint& curpos )
{
    if ( d->m_model && enabled() && visible()) {
        return d->m_model->whichItemAt( curpos );
    }
    else {
        return QList<AbstractDataPluginItem *>();
    }
}

void AbstractDataPlugin::requestRepaint()
{
    emit repaintNeeded( QRegion() );
}

} // namespace Marble

#include "AbstractDataPlugin.moc"
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <math.h>
#include "WP3PageFormatGroup.h"
#include "WP3FileStructure.h"
#include "libwpd_internal.h"
#include "libwpd_math.h"
#include "WP3Listener.h"

WP3PageFormatGroup::WP3PageFormatGroup(WPXInputStream *input, WPXEncryption *encryption) :
	WP3VariableLengthGroup(),
	m_leftMargin(0),
	m_rightMargin(0),
	m_lineSpacing(1.0),
	m_isRelative(false),
	m_tabStops(),
	m_topMargin(0),
	m_bottomMargin(0),
	m_justification(0),
	m_suppressCode(0),
	m_indent(0)
{
	_read(input, encryption);
}

WP3PageFormatGroup::~WP3PageFormatGroup()
{
}

void WP3PageFormatGroup::_readContents(WPXInputStream *input, WPXEncryption *encryption)
{
	// this group can contain different kinds of data, thus we need to read
	// the contents accordingly
	int8_t tmpTabType = 0;
	double tmpTabPosition = 0.0;
	WPXTabStop tmpTabStop = WPXTabStop();

	switch (getSubGroup())
	{
	case WP3_PAGE_FORMAT_GROUP_HORIZONTAL_MARGINS:
		// skip 8 bytes (old values of no interest for us)
		input->seek(8, WPX_SEEK_CUR);
		m_leftMargin = readU32(input, encryption, true);
		m_rightMargin = readU32(input, encryption, true);
		WPD_DEBUG_MSG(("WordPerfect: Page format group horizontal margins\n"));
		break;

	case WP3_PAGE_FORMAT_GROUP_LINE_SPACING:
		// skip 4 bytes (old spacing of no interest for us)
		input->seek(4, WPX_SEEK_CUR);
		{
			uint32_t lineSpacing = readU32(input, encryption, true);
			int16_t lineSpacingIntegerPart = (int16_t)((lineSpacing & 0xFFFF0000) >> 16);
			double lineSpacingFractionalPart = (double)((double)(lineSpacing & 0xFFFF)/(double)0xFFFF);
			WPD_DEBUG_MSG(("WordPerfect: Page format group line spacing - integer part: %i fractional part: %f (original value: %i)\n",
			               lineSpacingIntegerPart, lineSpacingFractionalPart, lineSpacing));
			m_lineSpacing = lineSpacingIntegerPart + lineSpacingFractionalPart;
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_SET_TABS:
		// skip old condensed tab table if the first value is not 0xFF
		if (0xFF != readU8(input, encryption))
		{
			while (readU8(input, encryption) != 0xFF)
				input->seek(4, WPX_SEEK_CUR);
		}

		m_isRelative = (readU8(input, encryption) & 0x01);

		while ((tmpTabType = (int8_t)readU8(input, encryption))  != (int8_t)0xff)
		{
			if (input->atEOS())
				throw FileException();
			tmpTabPosition = fixedPointToDouble(readU32(input, encryption, true)) / 72.0;

			if (tmpTabType < 0)
			{
				for (int8_t i = tmpTabType; i < 0; i++)
				{
					tmpTabStop.m_position += tmpTabPosition;
					m_tabStops.push_back(tmpTabStop);
				}
			}
			else
			{
				tmpTabStop.m_position = tmpTabPosition;

				switch (tmpTabType & 0x0f)
				{
				case 0:
					tmpTabStop.m_alignment = LEFT;
					break;
				case 1:
					tmpTabStop.m_alignment = CENTER;
					break;
				case 2:
					tmpTabStop.m_alignment = RIGHT;
					break;
				case 3:
					tmpTabStop.m_alignment = DECIMAL;
					break;
				case 4:
					tmpTabStop.m_alignment = BAR;
					break;
				default:
					tmpTabStop.m_alignment = LEFT;
					break;
				}

				switch ((tmpTabType & 0x70) >> 4 )
				{
				case 0:
					tmpTabStop.m_leaderCharacter = '\0';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				case 1:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 1;
					break;
				case 2:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				case 3:
					tmpTabStop.m_leaderCharacter = '-';
					tmpTabStop.m_leaderNumSpaces = 1;
					break;
				case 4:
					tmpTabStop.m_leaderCharacter = '_';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				default:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				}

				m_tabStops.push_back(tmpTabStop);
			}
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_VERTICAL_MARGINS:
		// skip 8 bytes (old values of no interest for us)
		input->seek(8, WPX_SEEK_CUR);
		m_topMargin = readU32(input, encryption, true);
		m_bottomMargin = readU32(input, encryption, true);
		WPD_DEBUG_MSG(("WordPerfect: Page format group vertical margins\n"));
		break;

	case WP3_PAGE_FORMAT_GROUP_JUSTIFICATION_MODE:
		// skip 1 byte (old justifcation value of no interest for us)
		input->seek(1, WPX_SEEK_CUR);
		m_justification = readU8(input, encryption);
		break;

	case WP3_PAGE_FORMAT_GROUP_SUPPRESS_PAGE:
		// skip 2 bytes (old suppress code)
		input->seek(2, WPX_SEEK_CUR);
		m_suppressCode = readU16(input, encryption, true);
		break;

	case WP3_PAGE_FORMAT_GROUP_INDENT_AT_BEGINNING_OF_PARAGRAPH:
		// skip 4 bytes (old indent indent value of no interest for us)
		input->seek(4, WPX_SEEK_CUR);
		m_indent = readU32(input, encryption, true);
		break;

	default: /* something else we don't support, since it isn't in the docs */
		break;
	}
}

void WP3PageFormatGroup::parse(WP3Listener *listener)
{
	WPD_DEBUG_MSG(("WordPerfect: handling a Page Format group\n"));

#ifdef DEBUG
	std::vector<WPXTabStop>::const_iterator tabStopsIter;
#endif

	switch (getSubGroup())
	{
	case WP3_PAGE_FORMAT_GROUP_HORIZONTAL_MARGINS:
		if (m_leftMargin != 0x80000000)
		{
			listener->marginChange(WPX_LEFT, fixedPointToWPUs(m_leftMargin));
			WPD_DEBUG_MSG(("WordPerfect: Page format group left margin - WPUs: %i (original value: %i)\n",
			               fixedPointToWPUs(m_leftMargin), m_leftMargin));
		}
		if (m_rightMargin != 0x8000000)
		{
			listener->marginChange(WPX_RIGHT, fixedPointToWPUs(m_rightMargin));
			WPD_DEBUG_MSG(("WordPerfect: Page format group right margin - integer part: WPUs: %i (original value: %i)\n",
			               fixedPointToWPUs(m_rightMargin), m_rightMargin));
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_LINE_SPACING:
		WPD_DEBUG_MSG(("WordPerfect: parsing a line spacing change of: %f\n", m_lineSpacing));
		listener->lineSpacingChange(m_lineSpacing);
		break;

	case WP3_PAGE_FORMAT_GROUP_SET_TABS:
#ifdef DEBUG
		WPD_DEBUG_MSG(("Parsing Set Tabs Group (positions: "));
		for(tabStopsIter = m_tabStops.begin(); tabStopsIter != m_tabStops.end(); tabStopsIter++)
		{
			WPD_DEBUG_MSG((" %.4f", (*tabStopsIter).m_position));
		}
		WPD_DEBUG_MSG((")\n"));
#endif
		listener->setTabs(m_isRelative, m_tabStops);
		break;

	case WP3_PAGE_FORMAT_GROUP_VERTICAL_MARGINS:
		if (m_topMargin != 0x80000000)
			listener->pageMarginChange(WPX_TOP, fixedPointToWPUs(m_topMargin));
		if (m_bottomMargin != 0x80000000)
			listener->pageMarginChange(WPX_BOTTOM, fixedPointToWPUs(m_bottomMargin));
		break;

	case WP3_PAGE_FORMAT_GROUP_JUSTIFICATION_MODE:
		listener->justificationChange(m_justification);
		break;

	case WP3_PAGE_FORMAT_GROUP_SUPPRESS_PAGE:
		listener->suppressPage(m_suppressCode);
		break;

	case WP3_PAGE_FORMAT_GROUP_INDENT_AT_BEGINNING_OF_PARAGRAPH:
		listener->indentFirstLineChange(fixedPointToWPUs(m_indent));
		break;

	default: // something else we don't support, since it isn't in the docs
		break;
	}
}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
<commit_msg>MSVC warning C4310: cast truncates constant value<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <math.h>
#include "WP3PageFormatGroup.h"
#include "WP3FileStructure.h"
#include "libwpd_internal.h"
#include "libwpd_math.h"
#include "WP3Listener.h"

WP3PageFormatGroup::WP3PageFormatGroup(WPXInputStream *input, WPXEncryption *encryption) :
	WP3VariableLengthGroup(),
	m_leftMargin(0),
	m_rightMargin(0),
	m_lineSpacing(1.0),
	m_isRelative(false),
	m_tabStops(),
	m_topMargin(0),
	m_bottomMargin(0),
	m_justification(0),
	m_suppressCode(0),
	m_indent(0)
{
	_read(input, encryption);
}

WP3PageFormatGroup::~WP3PageFormatGroup()
{
}

void WP3PageFormatGroup::_readContents(WPXInputStream *input, WPXEncryption *encryption)
{
	// this group can contain different kinds of data, thus we need to read
	// the contents accordingly
	uint8_t tmpTmp = 0xff;
	int8_t tmpTabType = 0;
	double tmpTabPosition = 0.0;
	WPXTabStop tmpTabStop = WPXTabStop();

	switch (getSubGroup())
	{
	case WP3_PAGE_FORMAT_GROUP_HORIZONTAL_MARGINS:
		// skip 8 bytes (old values of no interest for us)
		input->seek(8, WPX_SEEK_CUR);
		m_leftMargin = readU32(input, encryption, true);
		m_rightMargin = readU32(input, encryption, true);
		WPD_DEBUG_MSG(("WordPerfect: Page format group horizontal margins\n"));
		break;

	case WP3_PAGE_FORMAT_GROUP_LINE_SPACING:
		// skip 4 bytes (old spacing of no interest for us)
		input->seek(4, WPX_SEEK_CUR);
		{
			uint32_t lineSpacing = readU32(input, encryption, true);
			int16_t lineSpacingIntegerPart = (int16_t)((lineSpacing & 0xFFFF0000) >> 16);
			double lineSpacingFractionalPart = (double)((double)(lineSpacing & 0xFFFF)/(double)0xFFFF);
			WPD_DEBUG_MSG(("WordPerfect: Page format group line spacing - integer part: %i fractional part: %f (original value: %i)\n",
			               lineSpacingIntegerPart, lineSpacingFractionalPart, lineSpacing));
			m_lineSpacing = lineSpacingIntegerPart + lineSpacingFractionalPart;
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_SET_TABS:
		// skip old condensed tab table if the first value is not 0xFF
		if (0xFF != readU8(input, encryption))
		{
			while (readU8(input, encryption) != 0xFF)
				input->seek(4, WPX_SEEK_CUR);
		}

		m_isRelative = (readU8(input, encryption) & 0x01);

		while ((tmpTmp = readU8(input, encryption)) != 0xff)
		{
			tmpTabType = (int8_t) tmpTmp;
			if (input->atEOS())
				throw FileException();
			tmpTabPosition = fixedPointToDouble(readU32(input, encryption, true)) / 72.0;

			if (tmpTabType < 0)
			{
				for (int8_t i = tmpTabType; i < 0; i++)
				{
					tmpTabStop.m_position += tmpTabPosition;
					m_tabStops.push_back(tmpTabStop);
				}
			}
			else
			{
				tmpTabStop.m_position = tmpTabPosition;

				switch (tmpTabType & 0x0f)
				{
				case 0:
					tmpTabStop.m_alignment = LEFT;
					break;
				case 1:
					tmpTabStop.m_alignment = CENTER;
					break;
				case 2:
					tmpTabStop.m_alignment = RIGHT;
					break;
				case 3:
					tmpTabStop.m_alignment = DECIMAL;
					break;
				case 4:
					tmpTabStop.m_alignment = BAR;
					break;
				default:
					tmpTabStop.m_alignment = LEFT;
					break;
				}

				switch ((tmpTabType & 0x70) >> 4 )
				{
				case 0:
					tmpTabStop.m_leaderCharacter = '\0';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				case 1:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 1;
					break;
				case 2:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				case 3:
					tmpTabStop.m_leaderCharacter = '-';
					tmpTabStop.m_leaderNumSpaces = 1;
					break;
				case 4:
					tmpTabStop.m_leaderCharacter = '_';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				default:
					tmpTabStop.m_leaderCharacter = '.';
					tmpTabStop.m_leaderNumSpaces = 0;
					break;
				}

				m_tabStops.push_back(tmpTabStop);
			}
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_VERTICAL_MARGINS:
		// skip 8 bytes (old values of no interest for us)
		input->seek(8, WPX_SEEK_CUR);
		m_topMargin = readU32(input, encryption, true);
		m_bottomMargin = readU32(input, encryption, true);
		WPD_DEBUG_MSG(("WordPerfect: Page format group vertical margins\n"));
		break;

	case WP3_PAGE_FORMAT_GROUP_JUSTIFICATION_MODE:
		// skip 1 byte (old justifcation value of no interest for us)
		input->seek(1, WPX_SEEK_CUR);
		m_justification = readU8(input, encryption);
		break;

	case WP3_PAGE_FORMAT_GROUP_SUPPRESS_PAGE:
		// skip 2 bytes (old suppress code)
		input->seek(2, WPX_SEEK_CUR);
		m_suppressCode = readU16(input, encryption, true);
		break;

	case WP3_PAGE_FORMAT_GROUP_INDENT_AT_BEGINNING_OF_PARAGRAPH:
		// skip 4 bytes (old indent indent value of no interest for us)
		input->seek(4, WPX_SEEK_CUR);
		m_indent = readU32(input, encryption, true);
		break;

	default: /* something else we don't support, since it isn't in the docs */
		break;
	}
}

void WP3PageFormatGroup::parse(WP3Listener *listener)
{
	WPD_DEBUG_MSG(("WordPerfect: handling a Page Format group\n"));

#ifdef DEBUG
	std::vector<WPXTabStop>::const_iterator tabStopsIter;
#endif

	switch (getSubGroup())
	{
	case WP3_PAGE_FORMAT_GROUP_HORIZONTAL_MARGINS:
		if (m_leftMargin != 0x80000000)
		{
			listener->marginChange(WPX_LEFT, fixedPointToWPUs(m_leftMargin));
			WPD_DEBUG_MSG(("WordPerfect: Page format group left margin - WPUs: %i (original value: %i)\n",
			               fixedPointToWPUs(m_leftMargin), m_leftMargin));
		}
		if (m_rightMargin != 0x8000000)
		{
			listener->marginChange(WPX_RIGHT, fixedPointToWPUs(m_rightMargin));
			WPD_DEBUG_MSG(("WordPerfect: Page format group right margin - integer part: WPUs: %i (original value: %i)\n",
			               fixedPointToWPUs(m_rightMargin), m_rightMargin));
		}
		break;

	case WP3_PAGE_FORMAT_GROUP_LINE_SPACING:
		WPD_DEBUG_MSG(("WordPerfect: parsing a line spacing change of: %f\n", m_lineSpacing));
		listener->lineSpacingChange(m_lineSpacing);
		break;

	case WP3_PAGE_FORMAT_GROUP_SET_TABS:
#ifdef DEBUG
		WPD_DEBUG_MSG(("Parsing Set Tabs Group (positions: "));
		for(tabStopsIter = m_tabStops.begin(); tabStopsIter != m_tabStops.end(); tabStopsIter++)
		{
			WPD_DEBUG_MSG((" %.4f", (*tabStopsIter).m_position));
		}
		WPD_DEBUG_MSG((")\n"));
#endif
		listener->setTabs(m_isRelative, m_tabStops);
		break;

	case WP3_PAGE_FORMAT_GROUP_VERTICAL_MARGINS:
		if (m_topMargin != 0x80000000)
			listener->pageMarginChange(WPX_TOP, fixedPointToWPUs(m_topMargin));
		if (m_bottomMargin != 0x80000000)
			listener->pageMarginChange(WPX_BOTTOM, fixedPointToWPUs(m_bottomMargin));
		break;

	case WP3_PAGE_FORMAT_GROUP_JUSTIFICATION_MODE:
		listener->justificationChange(m_justification);
		break;

	case WP3_PAGE_FORMAT_GROUP_SUPPRESS_PAGE:
		listener->suppressPage(m_suppressCode);
		break;

	case WP3_PAGE_FORMAT_GROUP_INDENT_AT_BEGINNING_OF_PARAGRAPH:
		listener->indentFirstLineChange(fixedPointToWPUs(m_indent));
		break;

	default: // something else we don't support, since it isn't in the docs
		break;
	}
}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
<|endoftext|>


<commit_before>// Filename: actorNode.cxx
// Created by:  charles (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "actorNode.h"
#include "config_physics.h"
#include "physicsObject.h"

#include "transformState.h"

TypeHandle ActorNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Constructor
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const string &name) :
  PhysicalNode(name) {
  add_physical(new Physical(1, true));
  _mass_center = get_physical(0)->get_phys_body();
  _mass_center->set_active(true);
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Copy Constructor.
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const ActorNode &copy) :
  PhysicalNode(copy) {
  _ok_to_callback = true;
  _mass_center = get_physical(0)->get_phys_body();
}

////////////////////////////////////////////////////////////////////
//     Function : ~ActorNode
//       Access : public
//  Description : destructor
////////////////////////////////////////////////////////////////////
ActorNode::
~ActorNode() {
}

////////////////////////////////////////////////////////////////////
//     Function : update_transform
//       Access : public
//  Description : this sets the transform generated by the contained
//                Physical, moving the node and subsequent geometry.
////////////////////////////////////////////////////////////////////
void ActorNode::
update_transform() {
  LMatrix4f lcs = _mass_center->get_lcs();

  // lock the callback so that this doesn't call transform_changed.
  _ok_to_callback = false;
  set_transform(TransformState::make_mat(lcs));
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : transform_changed
//       Access : private, virtual
//  Description : node hook.  This function handles outside
//                (non-physics) actions on the actor
//                and updates the internal representation of the node.
////////////////////////////////////////////////////////////////////
void ActorNode::
transform_changed() {
  // this callback could be triggered by update_transform, BAD.
  if (_ok_to_callback == false) {
    return;
  }

  // get the transform
  CPT(TransformState) transform = get_transform();

  // extract the position
  LPoint3f pos;
  transform->get_mat().get_row3(pos,3);

  // extract the orientation
  if (_mass_center->get_oriented() == true) {
    LOrientationf orientation(transform->get_mat());
    _mass_center->set_orientation(orientation);
  }

  // apply
  _mass_center->set_position(pos);
}

////////////////////////////////////////////////////////////////////
//     Function : output
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
output(ostream &out) const {
  #ifndef NDEBUG //[
  out<<"ActorNode";
  #endif //] NDEBUG
}

////////////////////////////////////////////////////////////////////
//     Function : write
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
write(ostream &out, unsigned int indent) const {
  #ifndef NDEBUG //[
  out.width(indent); out<<""; out<<"ActorNode:\n";
  out.width(indent+2); out<<""; out<<"_mass_center "<<_mass_center<<"\n";
  out.width(indent+2); out<<""; out<<"_ok_to_callback "<<_ok_to_callback<<"\n";
  PhysicalNode::write(out, indent+2);
  #endif //] NDEBUG
}
<commit_msg>minor tweaks for new scene graph stuff<commit_after>// Filename: actorNode.cxx
// Created by:  charles (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "actorNode.h"
#include "config_physics.h"
#include "physicsObject.h"

#include "transformState.h"

TypeHandle ActorNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Constructor
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const string &name) :
  PhysicalNode(name) {
  add_physical(new Physical(1, true));
  _mass_center = get_physical(0)->get_phys_body();
  _mass_center->set_active(true);
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Copy Constructor.
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const ActorNode &copy) :
  PhysicalNode(copy) {
  _ok_to_callback = true;
  _mass_center = get_physical(0)->get_phys_body();
}

////////////////////////////////////////////////////////////////////
//     Function : ~ActorNode
//       Access : public
//  Description : destructor
////////////////////////////////////////////////////////////////////
ActorNode::
~ActorNode() {
}

////////////////////////////////////////////////////////////////////
//     Function : update_transform
//       Access : public
//  Description : this sets the transform generated by the contained
//                Physical, moving the node and subsequent geometry.
////////////////////////////////////////////////////////////////////
void ActorNode::
update_transform() {
  LMatrix4f lcs = _mass_center->get_lcs();

  // lock the callback so that this doesn't call transform_changed.
  _ok_to_callback = false;
  set_transform(TransformState::make_mat(lcs));
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : transform_changed
//       Access : private, virtual
//  Description : node hook.  This function handles outside
//                (non-physics) actions on the actor
//                and updates the internal representation of the node.
////////////////////////////////////////////////////////////////////
void ActorNode::
transform_changed() {
  // this callback could be triggered by update_transform, BAD.
  if (_ok_to_callback == false) {
    return;
  }

  // get the transform
  CPT(TransformState) transform = get_transform();

  // extract the orientation
  if (_mass_center->get_oriented() == true) {
    _mass_center->set_orientation(transform->get_quat());
  }

  // apply
  _mass_center->set_position(transform->get_pos());
}

////////////////////////////////////////////////////////////////////
//     Function : output
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
output(ostream &out) const {
  #ifndef NDEBUG //[
  out<<"ActorNode";
  #endif //] NDEBUG
}

////////////////////////////////////////////////////////////////////
//     Function : write
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
write(ostream &out, unsigned int indent) const {
  #ifndef NDEBUG //[
  out.width(indent); out<<""; out<<"ActorNode:\n";
  out.width(indent+2); out<<""; out<<"_mass_center "<<_mass_center<<"\n";
  out.width(indent+2); out<<""; out<<"_ok_to_callback "<<_ok_to_callback<<"\n";
  PhysicalNode::write(out, indent+2);
  #endif //] NDEBUG
}
<|endoftext|>


<commit_before>#include <algorithm> // std::max
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>

#include "allocore/types/al_MsgQueue.hpp"

namespace al{

MsgQueue :: MsgQueue(int size, malloc_func mfunc, free_func ffunc)
:	mHead(NULL), mTail(NULL), mPool(NULL),
	mLen(0), mChunkSize(0), mNow(0),
	mMalloc(mfunc ? mfunc : malloc), mFree(ffunc ? ffunc : free)
{
	growPool(size);
}

MsgQueue :: ~MsgQueue() {
	Msg * m;
	while (mHead) {
		m = mHead->next;
		recycle(mHead);
		mHead = m;
	}
	while (mPool) {
		m = mPool->next;
		mFree(mPool);
		mPool = m;
	}
}

void MsgQueue :: growPool(int size) {
	assert(!mPool); // LJP
	mPool = (Msg *)mMalloc(sizeof(Msg));
	Msg * m = mPool;
	while (size--) {
		m->next = (Msg *)mMalloc(sizeof(Msg));
		m = m->next;
	}
	m->next = NULL;
}

/* push a message back into the pool */
void MsgQueue :: recycle(Msg * m) {
	assert(mLen); // LJP
	m->next = mPool;
	mPool = m;
	if (m->isBigMessage()) {
		char * args = *(char **)(m->mArgs);
		mFree(args);
	}
	mLen--;
}

/* schedule a new message */
void MsgQueue :: sched(al_sec at, msg_func func, char * data, size_t size) {
	assert(mPool);
	// get a message-holder from the pool:
	Msg * m = mPool;
	mPool= m->next;

	// prepare Msg:
	m->next = NULL;
	m->t = at;
	m->func = func;
	m->size = size;
	if (m->isBigMessage()) {
		// too big to fit in the Msg.
		char * args = (char *)mMalloc(size);
		memcpy(args, data, size);
		*(char **)(m->mArgs) = args;
	} else {
		memcpy(m->mArgs, data, size);
	}

	// insert into queue

	// empty queue? set as new head and tail:
	if (mHead == NULL) {
		mHead = m;
		mTail = m;
		mLen = 1;
		return;
	}

	// prepend case? insert as new head:
	if (at < mHead->t) {
		m->next = mHead;
		mHead = m;
		mLen++;
		return;
	}

	// append case? add as new tail:
	if (at >= mTail->t) {
		mTail->next = m;
		mTail = m;
		mLen++;
		return;
	}

	// else: insert somewhere between head and tail:
	Msg * p = mHead;
	Msg * n = p->next;
	// compare with <= so that events with same timestamp will be in order of insertion
	while (n && n->t <= at) {
		p = n;
		n = n->next;
	}
	m->next = n;
	p->next = m;
	mLen++;
}

void MsgQueue :: update(al_sec until, bool defer) {
	Msg * m = mHead;
	while (m && m->t <= until) {
		mHead = m->next;

//		if (defer && m->retry > 0.) {
//			m->msg.t = x->now + m->retry;
//			al_pq_sched_msg(x, m);
//		} else {

		// only call if it has data associated:
		//if (m->args) {
			mNow = std::max(mNow, m->t);
			(m->func)(mNow, m->args());
		//}

		recycle(m);
		m = mHead;
	}
	mNow = until;
}

void MsgQueue :: clear() {
	// recycle everything:
	Msg * m = mHead;
	while (m) {
		mHead = m->next;
		recycle(m);
		m = mHead;
	}
	// reset clock:
	mNow = 0;
	mHead = NULL;
	mTail = NULL;
}

} // al::
<commit_msg>MsgQueue: change assertion to conditional<commit_after>#include <algorithm> // std::max
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>

#include "allocore/types/al_MsgQueue.hpp"

namespace al{

MsgQueue :: MsgQueue(int size, malloc_func mfunc, free_func ffunc)
:	mHead(NULL), mTail(NULL), mPool(NULL),
	mLen(0), mChunkSize(0), mNow(0),
	mMalloc(mfunc ? mfunc : malloc), mFree(ffunc ? ffunc : free)
{
	growPool(size);
}

MsgQueue :: ~MsgQueue() {
	Msg * m;
	while (mHead) {
		m = mHead->next;
		recycle(mHead);
		mHead = m;
	}
	while (mPool) {
		m = mPool->next;
		mFree(mPool);
		mPool = m;
	}
}

void MsgQueue :: growPool(int size) {
	assert(!mPool); // LJP
	mPool = (Msg *)mMalloc(sizeof(Msg));
	Msg * m = mPool;
	while (size--) {
		m->next = (Msg *)mMalloc(sizeof(Msg));
		m = m->next;
	}
	m->next = NULL;
}

/* push a message back into the pool */
void MsgQueue :: recycle(Msg * m) {
	m->next = mPool;	// Place msg at head ...
	mPool = m;			// ... of pool
	if (m->isBigMessage()) {
		char * args = *(char **)(m->mArgs);
		mFree(args);
	}
	// LJP: Add check in case this was called (accidently) with an empty queue
	if(mLen) --mLen;
}

/* schedule a new message */
void MsgQueue :: sched(al_sec at, msg_func func, char * data, size_t size) {
	assert(mPool);
	// get a message-holder from the pool:
	Msg * m = mPool;
	mPool= m->next;

	// prepare Msg:
	m->next = NULL;
	m->t = at;
	m->func = func;
	m->size = size;
	if (m->isBigMessage()) {
		// too big to fit in the Msg.
		char * args = (char *)mMalloc(size);
		memcpy(args, data, size);
		*(char **)(m->mArgs) = args;
	} else {
		memcpy(m->mArgs, data, size);
	}

	// insert into queue

	// empty queue? set as new head and tail:
	if (mHead == NULL) {
		mHead = m;
		mTail = m;
		mLen = 1;
		return;
	}

	// prepend case? insert as new head:
	if (at < mHead->t) {
		m->next = mHead;
		mHead = m;
		mLen++;
		return;
	}

	// append case? add as new tail:
	if (at >= mTail->t) {
		mTail->next = m;
		mTail = m;
		mLen++;
		return;
	}

	// else: insert somewhere between head and tail:
	Msg * p = mHead;
	Msg * n = p->next;
	// compare with <= so that events with same timestamp will be in order of insertion
	while (n && n->t <= at) {
		p = n;
		n = n->next;
	}
	m->next = n;
	p->next = m;
	mLen++;
}

void MsgQueue :: update(al_sec until, bool defer) {
	Msg * m = mHead;
	while (m && m->t <= until) {
		mHead = m->next;

//		if (defer && m->retry > 0.) {
//			m->msg.t = x->now + m->retry;
//			al_pq_sched_msg(x, m);
//		} else {

		// only call if it has data associated:
		//if (m->args) {
			mNow = std::max(mNow, m->t);
			(m->func)(mNow, m->args());
		//}

		recycle(m);
		m = mHead;
	}
	mNow = until;
}

void MsgQueue :: clear() {
	// recycle everything:
	Msg * m = mHead;
	while (m) {
		mHead = m->next;
		recycle(m);
		m = mHead;
	}
	// reset clock:
	mNow = 0;
	mHead = NULL;
	mTail = NULL;
}

} // al::
<|endoftext|>


<commit_before>#ifndef AMGCL_MPI_REPARTITION_PARMETIS_HPP
#define AMGCL_MPI_REPARTITION_PARMETIS_HPP

/*
The MIT License

Copyright (c) 2012-2018 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/mpi/repartition/parmetis.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  ParMETIS repartitioner.
 */

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>

#include <amgcl/backend/interface.hpp>
#include <amgcl/value_type/interface.hpp>
#include <amgcl/mpi/util.hpp>
#include <amgcl/mpi/distributed_matrix.hpp>
#include <amgcl/mpi/repartition/util.hpp>

#include <parmetis.h>

namespace amgcl {
namespace mpi {
namespace repartition {

template <class Backend>
struct parmetis {
    typedef typename Backend::value_type value_type;
    typedef distributed_matrix<Backend>  matrix;

    struct params {
        bool      enable;
        ptrdiff_t min_per_proc;
        int       shrink_ratio;

        params() :
            enable(false), min_per_proc(10000), shrink_ratio(8)
        {}

        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_VALUE(p, enable),
              AMGCL_PARAMS_IMPORT_VALUE(p, min_per_proc),
              AMGCL_PARAMS_IMPORT_VALUE(p, shrink_ratio)
        {
            AMGCL_PARAMS_CHECK(p, (enable)(min_per_proc)(shrink_ratio));
        }

        void get(
                boost::property_tree::ptree &p,
                const std::string &path = ""
                ) const
        {
            AMGCL_PARAMS_EXPORT_VALUE(p, path, enable);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, min_per_proc);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, shrink_ratio);
        }
    } prm;

    parmetis(const params &prm = params()) : prm(prm) {}

    bool is_needed(const matrix &A) const {
        if (!prm.enable) return false;

        communicator comm = A.comm();
        ptrdiff_t n = A.loc_rows();
        std::vector<ptrdiff_t> row_dom = mpi::exclusive_sum(comm, n);

        int non_empty = 0;
        ptrdiff_t min_n = std::numeric_limits<ptrdiff_t>::max();
        for(int i = 0; i < comm.size; ++i) {
            ptrdiff_t m = row_dom[i+1] - row_dom[i];
            if (m) {
                min_n = std::min(min_n, m);
                ++non_empty;
            }
        }

        return (non_empty > 1) && (min_n <= prm.min_per_proc);
    }

    boost::shared_ptr<matrix> operator()(const matrix &A) const {
        communicator comm = A.comm();
        idx_t n = A.loc_rows();
        ptrdiff_t row_beg = A.loc_col_shift();

        std::vector<idx_t> vtxdist = mpi::exclusive_sum(comm, n);

        // Partition the graph.
        int active = (n > 0);
        int active_ranks;
        MPI_Allreduce(&active, &active_ranks, 1, MPI_INT, MPI_SUM, comm);

        idx_t npart = std::max(1, active_ranks / prm.shrink_ratio);

        if (comm.rank == 0)
            std::cout << "Repartitioning[ParMETIS] " << active_ranks << " -> " << npart << std::endl;

        std::vector<ptrdiff_t> perm(n);
        ptrdiff_t col_beg, col_end;

        if (npart == 1) {
            col_beg = (comm.rank == 0) ? 0 : A.glob_rows();
            col_end = A.glob_rows();

            for(ptrdiff_t i = 0; i < n; ++i) {
                perm[i] = row_beg + i;
            }
        } else {
            std::vector<idx_t> ptr;
            std::vector<idx_t> col;

            symm_graph(A, ptr, col);

            idx_t wgtflag = 0;
            idx_t numflag = 0;
            idx_t options = 0;
            idx_t edgecut = 0;
            idx_t ncon    = 1;

            std::vector<real_t> tpwgts(npart, 1.0 / npart);
            std::vector<real_t> ubvec(ncon, 1.05);
            std::vector<idx_t>  part(std::max<ptrdiff_t>(1, n));

            MPI_Comm mpi_comm = comm;
            amgcl::mpi::precondition(comm,
                    METIS_OK == ParMETIS_V3_PartKway(
                        &vtxdist[0], &ptr[0], &col[0],
                        NULL, NULL, &wgtflag, &numflag, &ncon, &npart,
                        &tpwgts[0], &ubvec[0], &options, &edgecut, &part[0],
                        &mpi_comm),
                    "Error in ParMETIS"
                    );

            boost::tie(col_beg, col_end) = graph_perm_index(comm, npart, part, perm);
        }

        return graph_perm_matrix<Backend>(comm, col_beg, col_end, perm);
    }

    static void check(communicator comm, int ierr) {
        amgcl::mpi::precondition(comm, ierr == 0, "SCOTCH error");
    }
};

} // namespace repartition
} // namespace mpi
} // namespace amgcl

#endif
<commit_msg>ParMETIS can not deal with empty graph partitions<commit_after>#ifndef AMGCL_MPI_REPARTITION_PARMETIS_HPP
#define AMGCL_MPI_REPARTITION_PARMETIS_HPP

/*
The MIT License

Copyright (c) 2012-2018 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/mpi/repartition/parmetis.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  ParMETIS repartitioner.
 */

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>

#include <amgcl/backend/interface.hpp>
#include <amgcl/value_type/interface.hpp>
#include <amgcl/mpi/util.hpp>
#include <amgcl/mpi/distributed_matrix.hpp>
#include <amgcl/mpi/repartition/util.hpp>

#include <parmetis.h>

namespace amgcl {
namespace mpi {
namespace repartition {

template <class Backend>
struct parmetis {
    typedef typename Backend::value_type value_type;
    typedef distributed_matrix<Backend>  matrix;

    struct params {
        bool      enable;
        ptrdiff_t min_per_proc;
        int       shrink_ratio;

        params() :
            enable(false), min_per_proc(10000), shrink_ratio(8)
        {}

        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_VALUE(p, enable),
              AMGCL_PARAMS_IMPORT_VALUE(p, min_per_proc),
              AMGCL_PARAMS_IMPORT_VALUE(p, shrink_ratio)
        {
            AMGCL_PARAMS_CHECK(p, (enable)(min_per_proc)(shrink_ratio));
        }

        void get(
                boost::property_tree::ptree &p,
                const std::string &path = ""
                ) const
        {
            AMGCL_PARAMS_EXPORT_VALUE(p, path, enable);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, min_per_proc);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, shrink_ratio);
        }
    } prm;

    parmetis(const params &prm = params()) : prm(prm) {}

    bool is_needed(const matrix &A) const {
        if (!prm.enable) return false;

        communicator comm = A.comm();
        ptrdiff_t n = A.loc_rows();
        std::vector<ptrdiff_t> row_dom = mpi::exclusive_sum(comm, n);

        int non_empty = 0;
        ptrdiff_t min_n = std::numeric_limits<ptrdiff_t>::max();
        for(int i = 0; i < comm.size; ++i) {
            ptrdiff_t m = row_dom[i+1] - row_dom[i];
            if (m) {
                min_n = std::min(min_n, m);
                ++non_empty;
            }
        }

        return (non_empty > 1) && (min_n <= prm.min_per_proc);
    }

    boost::shared_ptr<matrix> operator()(const matrix &A) const {
        communicator comm = A.comm();
        idx_t n = A.loc_rows();
        ptrdiff_t row_beg = A.loc_col_shift();

        std::vector<idx_t> vtxdist = mpi::exclusive_sum(comm, n);

        // Partition the graph.
        int active = (n > 0);
        int active_ranks;
        MPI_Allreduce(&active, &active_ranks, 1, MPI_INT, MPI_SUM, comm);

        idx_t npart = std::max(1, active_ranks / prm.shrink_ratio);

        if (comm.rank == 0)
            std::cout << "Repartitioning[ParMETIS] " << active_ranks << " -> " << npart << std::endl;

        std::vector<ptrdiff_t> perm(n);
        ptrdiff_t col_beg, col_end;

        if (npart == 1) {
            col_beg = (comm.rank == 0) ? 0 : A.glob_rows();
            col_end = A.glob_rows();

            for(ptrdiff_t i = 0; i < n; ++i) {
                perm[i] = row_beg + i;
            }
        } else {
            std::vector<idx_t> ptr;
            std::vector<idx_t> col;

            symm_graph(A, ptr, col);

            idx_t wgtflag = 0;
            idx_t numflag = 0;
            idx_t options = 0;
            idx_t edgecut = 0;
            idx_t ncon    = 1;

            std::vector<real_t> tpwgts(npart, 1.0 / npart);
            std::vector<real_t> ubvec(ncon, 1.05);
            std::vector<idx_t>  part(std::max<ptrdiff_t>(1, n));

            MPI_Comm scomm;
            MPI_Comm_split(comm, active ? 0 : MPI_UNDEFINED, comm.rank, &scomm);

            if (active) {
                amgcl::mpi::precondition(scomm,
                        METIS_OK == ParMETIS_V3_PartKway( &vtxdist[0], &ptr[0],
                            &col[0], NULL, NULL, &wgtflag, &numflag, &ncon,
                            &npart, &tpwgts[0], &ubvec[0], &options, &edgecut,
                            &part[0], &scomm),
                        "Error in ParMETIS"
                        );

                MPI_Comm_free(&scomm);
            }

            boost::tie(col_beg, col_end) = graph_perm_index(comm, npart, part, perm);
        }

        return graph_perm_matrix<Backend>(comm, col_beg, col_end, perm);
    }

    static void check(communicator comm, int ierr) {
        amgcl::mpi::precondition(comm, ierr == 0, "SCOTCH error");
    }
};

} // namespace repartition
} // namespace mpi
} // namespace amgcl

#endif
<|endoftext|>


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

#include <gtest/gtest.h>

#include <algorithm>
#include <memory>
#include <vector>

#include <SurgSim/Framework/Runtime.h>
#include <SurgSim/Framework/Scene.h>
#include <SurgSim/Graphics/OsgMeshRepresentation.h>
#include <SurgSim/Graphics/OsgManager.h>
#include <SurgSim/Graphics/OsgBoxRepresentation.h>
#include <SurgSim/Graphics/OsgViewElement.h>
#include <SurgSim/Graphics/OsgShader.h>
#include <SurgSim/Graphics/OsgMaterial.h>
#include <SurgSim/Graphics/OsgAxesRepresentation.h>
#include <SurgSim/Graphics/OsgUniform.h>

#include <SurgSim/DataStructures/Vertices.h>
#include <SurgSim/Blocks/BasicSceneElement.h>

#include <SurgSim/Math/Quaternion.h>
#include <SurgSim/Math/Vector.h>
#include <SurgSim/Math/RigidTransform.h>

#include <SurgSim/Testing/MathUtilities.h>

#include <SurgSim/Graphics/RenderTests/RenderTest.h>
#include <SurgSim/Graphics/RenderTests/TestCube.h>

using SurgSim::Math::Vector3d;
using SurgSim::Math::Vector4d;
using SurgSim::Math::Vector2d;
using SurgSim::Math::Quaterniond;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::makeRigidTransform;
using SurgSim::Math::makeRotationQuaternion;

using SurgSim::Testing::interpolate;
using SurgSim::Testing::interpolatePose;
using SurgSim::Testing::makeRigidTransformFromAngles;

#include <SurgSim/Framework/SceneElement.h>
#include <SurgSim/Framework/Behavior.h>
#include <utility>

namespace SurgSim
{
namespace Graphics
{

struct OsgMeshrepresentationRenderTests : public RenderTest
{

protected:

	std::vector<Vector3d> cubeVertices;
	std::vector<unsigned int> cubeTriangles;
	std::vector<Vector4d> cubeColors;
	std::vector<Vector2d> cubeTextures;

	std::shared_ptr<Mesh> makeMesh(const std::vector<Vector3d>& vertices,
								   const std::vector<Vector4d>& colors,
								   const std::vector<Vector2d>& textures,
								   const std::vector<unsigned int>& triangles)
	{
		std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
		size_t i = 0;
		for (auto it = std::begin(vertices); it != std::end(vertices); ++it)
		{
			VertexData data;
			if (! colors.empty())
			{
				data.color.setValue(colors[i]);
			}
			if (! textures.empty())
			{
				data.texture.setValue(textures[i]);
			}
			mesh->addVertex(Mesh::VertexType(*it, data));
			++i;
		}

		for (size_t i = 0; i < triangles.size()/3; ++i )
		{
			Mesh::TriangleType::IdType ids = {triangles[3*i], triangles[3*i+1],triangles[3*i+2]};
			Mesh::TriangleType triangle(ids, SurgSim::Graphics::TriangleData());
			mesh->addTriangle(triangle);
		}

		return mesh;
	}

	std::shared_ptr<MeshRepresentation> makeRepresentation(std::shared_ptr<Mesh> mesh, const std::string& name)
	{
		auto meshRepresentation = std::make_shared<OsgMeshRepresentation>(name);

		EXPECT_TRUE(mesh->isValid());

		meshRepresentation->setMesh(mesh);
		meshRepresentation->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(0.0,0.0,0.0)));

		//meshRepresentation->setDrawAsWireFrame(true);

		return meshRepresentation;
	}
};

TEST_F(OsgMeshrepresentationRenderTests, StaticRotateDynamicScale)
{
	std::shared_ptr<SurgSim::Blocks::BasicSceneElement> element =
		std::make_shared<SurgSim::Blocks::BasicSceneElement>("Scene");
	scene->addSceneElement(element);

	SurgSim::Testing::Cube::makeCube(&cubeVertices, &cubeColors, &cubeTextures, &cubeTriangles);

	std::shared_ptr<SurgSim::Graphics::MeshRepresentation> meshRepresentation1;
	meshRepresentation1 = makeRepresentation(
		makeMesh(cubeVertices, cubeColors, std::vector<Vector2d>(), cubeTriangles), "colormesh");
	meshRepresentation1->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(0.0,0.0,0.0)));

	// make a textured cube
	std::shared_ptr<SurgSim::Graphics::MeshRepresentation> meshRepresentation2;
	meshRepresentation2 = makeRepresentation(makeMesh
		(cubeVertices, std::vector<Vector4d>(), cubeTextures, cubeTriangles), "texturemesh");
	meshRepresentation2->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(-0.0,0.0,-0.0)));
	auto material = std::make_shared<OsgMaterial>();
	auto texture = std::make_shared<OsgTexture2d>();
	texture->loadImage(applicationData->findFile("OsgMeshRepresentationRenderTests/cube.png"));

	auto uniform2d = std::make_shared<OsgUniform<std::shared_ptr<SurgSim::Graphics::OsgTexture2d>>>("oss_diffuseMap");
	uniform2d->set(texture);
	material->addUniform(uniform2d);
	meshRepresentation2->setMaterial(material);

	element->addComponent(meshRepresentation1);
	element->addComponent(meshRepresentation2);

	auto axes = std::make_shared<OsgAxesRepresentation>("Origin");
	viewElement->addComponent(axes);

	struct InterpolationData
	{
	public:
		RigidTransform3d transform;
		double scale;
	};

	typedef std::pair<InterpolationData, InterpolationData> Interpolator;

	std::vector<Interpolator> interpolators;
	Interpolator interpolator;

	interpolator.first.transform =
		makeRigidTransformFromAngles(Vector3d(0.0, 0.0, 0.0), Vector3d(-0.1, 0.0, -0.2));
	interpolator.first.scale = 0.001;
	interpolator.second.transform =
		makeRigidTransformFromAngles(Vector3d(M_PI_4, M_PI_4, M_PI_4), Vector3d(0.1, 0.0, -0.2));
	interpolator.second.scale = 0.03;
	interpolators.push_back(interpolator);

	interpolator.first.transform =
		makeRigidTransformFromAngles(Vector3d(-M_PI_2, -M_PI_2, -M_PI_2), Vector3d(0.0, -0.1, -0.2));
	interpolator.first.scale = 0.001;
	interpolator.second.transform =
		makeRigidTransformFromAngles(Vector3d(M_PI_2, M_PI_2, M_PI_2), Vector3d(0.0, 0.1, -0.2));
	interpolator.second.scale = 0.03;
	interpolators.push_back(interpolator);

	std::vector<std::shared_ptr<Mesh>> meshes;
	meshes.push_back(meshRepresentation1->getMesh());
	meshes.push_back(meshRepresentation2->getMesh());

	/// Run the thread
	runtime->start();
	EXPECT_TRUE(graphicsManager->isInitialized());
	EXPECT_TRUE(viewElement->isInitialized());

	boost::this_thread::sleep(boost::posix_time::milliseconds(2000));

	int numSteps = 1000;

	std::vector<Vector3d> newVertices(cubeVertices.size());

	for (int i = 0; i < numSteps; ++i)
	{
		double t = static_cast<double>(i) / numSteps;

		for (size_t j = 0; j < interpolators.size(); ++j)
		{
			InterpolationData from = interpolators[j].first;
			InterpolationData to = interpolators[j].second;

			double scale = interpolate(from.scale, to.scale, t);
			RigidTransform3d transform = interpolate(from.transform, to.transform, t);
			for (size_t index = 0; index < cubeVertices.size(); ++index)
			{
				newVertices[index] =  transform * (cubeVertices[index] * scale);
			}
			meshes[j]->setVertexPositions(newVertices,true);
		}

		/// The total number of steps should complete in 1 second
		boost::this_thread::sleep(boost::posix_time::milliseconds(1000 / numSteps)*4);
	}
}

}; // namespace Graphics
}; // namespace SurgSim
<commit_msg>fix linux build warning<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <algorithm>
#include <memory>
#include <vector>

#include <SurgSim/Framework/Runtime.h>
#include <SurgSim/Framework/Scene.h>
#include <SurgSim/Graphics/OsgMeshRepresentation.h>
#include <SurgSim/Graphics/OsgManager.h>
#include <SurgSim/Graphics/OsgBoxRepresentation.h>
#include <SurgSim/Graphics/OsgViewElement.h>
#include <SurgSim/Graphics/OsgShader.h>
#include <SurgSim/Graphics/OsgMaterial.h>
#include <SurgSim/Graphics/OsgAxesRepresentation.h>
#include <SurgSim/Graphics/OsgUniform.h>

#include <SurgSim/DataStructures/Vertices.h>
#include <SurgSim/Blocks/BasicSceneElement.h>

#include <SurgSim/Math/Quaternion.h>
#include <SurgSim/Math/Vector.h>
#include <SurgSim/Math/RigidTransform.h>

#include <SurgSim/Testing/MathUtilities.h>

#include <SurgSim/Graphics/RenderTests/RenderTest.h>
#include <SurgSim/Graphics/RenderTests/TestCube.h>

using SurgSim::Math::Vector3d;
using SurgSim::Math::Vector4d;
using SurgSim::Math::Vector2d;
using SurgSim::Math::Quaterniond;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::makeRigidTransform;
using SurgSim::Math::makeRotationQuaternion;

using SurgSim::Testing::interpolate;
using SurgSim::Testing::interpolatePose;
using SurgSim::Testing::makeRigidTransformFromAngles;

#include <SurgSim/Framework/SceneElement.h>
#include <SurgSim/Framework/Behavior.h>
#include <utility>

namespace SurgSim
{
namespace Graphics
{

struct OsgMeshrepresentationRenderTests : public RenderTest
{

protected:

	std::vector<Vector3d> cubeVertices;
	std::vector<unsigned int> cubeTriangles;
	std::vector<Vector4d> cubeColors;
	std::vector<Vector2d> cubeTextures;

	std::shared_ptr<Mesh> makeMesh(const std::vector<Vector3d>& vertices,
								   const std::vector<Vector4d>& colors,
								   const std::vector<Vector2d>& textures,
								   const std::vector<unsigned int>& triangles)
	{
		std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
		size_t i = 0;
		for (auto it = std::begin(vertices); it != std::end(vertices); ++it)
		{
			VertexData data;
			if (! colors.empty())
			{
				data.color.setValue(colors[i]);
			}
			if (! textures.empty())
			{
				data.texture.setValue(textures[i]);
			}
			mesh->addVertex(Mesh::VertexType(*it, data));
			++i;
		}

		for (size_t i = 0; i < triangles.size()/3; ++i )
		{
			Mesh::TriangleType::IdType ids = {{triangles[3*i], triangles[3*i+1],triangles[3*i+2]}};
			Mesh::TriangleType triangle(ids, SurgSim::Graphics::TriangleData());
			mesh->addTriangle(triangle);
		}

		return mesh;
	}

	std::shared_ptr<MeshRepresentation> makeRepresentation(std::shared_ptr<Mesh> mesh, const std::string& name)
	{
		auto meshRepresentation = std::make_shared<OsgMeshRepresentation>(name);

		EXPECT_TRUE(mesh->isValid());

		meshRepresentation->setMesh(mesh);
		meshRepresentation->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(0.0,0.0,0.0)));

		//meshRepresentation->setDrawAsWireFrame(true);

		return meshRepresentation;
	}
};

TEST_F(OsgMeshrepresentationRenderTests, StaticRotateDynamicScale)
{
	std::shared_ptr<SurgSim::Blocks::BasicSceneElement> element =
		std::make_shared<SurgSim::Blocks::BasicSceneElement>("Scene");
	scene->addSceneElement(element);

	SurgSim::Testing::Cube::makeCube(&cubeVertices, &cubeColors, &cubeTextures, &cubeTriangles);

	std::shared_ptr<SurgSim::Graphics::MeshRepresentation> meshRepresentation1;
	meshRepresentation1 = makeRepresentation(
		makeMesh(cubeVertices, cubeColors, std::vector<Vector2d>(), cubeTriangles), "colormesh");
	meshRepresentation1->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(0.0,0.0,0.0)));

	// make a textured cube
	std::shared_ptr<SurgSim::Graphics::MeshRepresentation> meshRepresentation2;
	meshRepresentation2 = makeRepresentation(makeMesh
		(cubeVertices, std::vector<Vector4d>(), cubeTextures, cubeTriangles), "texturemesh");
	meshRepresentation2->setInitialPose(makeRigidTransform(Quaterniond::Identity(), Vector3d(-0.0,0.0,-0.0)));
	auto material = std::make_shared<OsgMaterial>();
	auto texture = std::make_shared<OsgTexture2d>();
	texture->loadImage(applicationData->findFile("OsgMeshRepresentationRenderTests/cube.png"));

	auto uniform2d = std::make_shared<OsgUniform<std::shared_ptr<SurgSim::Graphics::OsgTexture2d>>>("oss_diffuseMap");
	uniform2d->set(texture);
	material->addUniform(uniform2d);
	meshRepresentation2->setMaterial(material);

	element->addComponent(meshRepresentation1);
	element->addComponent(meshRepresentation2);

	auto axes = std::make_shared<OsgAxesRepresentation>("Origin");
	viewElement->addComponent(axes);

	struct InterpolationData
	{
	public:
		RigidTransform3d transform;
		double scale;
	};

	typedef std::pair<InterpolationData, InterpolationData> Interpolator;

	std::vector<Interpolator> interpolators;
	Interpolator interpolator;

	interpolator.first.transform =
		makeRigidTransformFromAngles(Vector3d(0.0, 0.0, 0.0), Vector3d(-0.1, 0.0, -0.2));
	interpolator.first.scale = 0.001;
	interpolator.second.transform =
		makeRigidTransformFromAngles(Vector3d(M_PI_4, M_PI_4, M_PI_4), Vector3d(0.1, 0.0, -0.2));
	interpolator.second.scale = 0.03;
	interpolators.push_back(interpolator);

	interpolator.first.transform =
		makeRigidTransformFromAngles(Vector3d(-M_PI_2, -M_PI_2, -M_PI_2), Vector3d(0.0, -0.1, -0.2));
	interpolator.first.scale = 0.001;
	interpolator.second.transform =
		makeRigidTransformFromAngles(Vector3d(M_PI_2, M_PI_2, M_PI_2), Vector3d(0.0, 0.1, -0.2));
	interpolator.second.scale = 0.03;
	interpolators.push_back(interpolator);

	std::vector<std::shared_ptr<Mesh>> meshes;
	meshes.push_back(meshRepresentation1->getMesh());
	meshes.push_back(meshRepresentation2->getMesh());

	/// Run the thread
	runtime->start();
	EXPECT_TRUE(graphicsManager->isInitialized());
	EXPECT_TRUE(viewElement->isInitialized());

	boost::this_thread::sleep(boost::posix_time::milliseconds(2000));

	int numSteps = 1000;

	std::vector<Vector3d> newVertices(cubeVertices.size());

	for (int i = 0; i < numSteps; ++i)
	{
		double t = static_cast<double>(i) / numSteps;

		for (size_t j = 0; j < interpolators.size(); ++j)
		{
			InterpolationData from = interpolators[j].first;
			InterpolationData to = interpolators[j].second;

			double scale = interpolate(from.scale, to.scale, t);
			RigidTransform3d transform = interpolate(from.transform, to.transform, t);
			for (size_t index = 0; index < cubeVertices.size(); ++index)
			{
				newVertices[index] =  transform * (cubeVertices[index] * scale);
			}
			meshes[j]->setVertexPositions(newVertices,true);
		}

		/// The total number of steps should complete in 1 second
		boost::this_thread::sleep(boost::posix_time::milliseconds(1000 / numSteps)*4);
	}
}

}; // namespace Graphics
}; // namespace SurgSim
<|endoftext|>