<commit_before>#ifndef UTENSOR_FULLY_CONNECTED_OPS
#define UTENSOR_FULLY_CONNECTED_OPS
#include "uTensor/core/tensor.hpp"
#include "uTensor/core/uTensorBase.hpp"
#include "arm_math.h"
#include "arm_nnfunctions.h"

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch,
                         T1 byteme1, T2 byteme2, TOut byteme3)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                         q7_t byteme1, q7_t byteme2, q7_t byteme3)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q7_t* pOut_data = pOut->write<q7_t>(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_q7(iV_data, mW_data, dim_vec, num_of_rows,
            bias_shift, out_shift, bias_data, pOut_data, scratch_data);

    //Error checking
}
template<>
void FullyConnectedLayerCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                         q15_t byteme1, q15_t byteme2, q15_t byteme3)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* bias_data = b->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write<q15_t>(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_q15(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerCmsis<q15_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                         q15_t byteme1, q7_t byteme2, q7_t byteme3)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write<q15_t>(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerOptCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch,
                         T1 byteme1, T2 byteme2, TOut byteme3)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerOptCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                                           q7_t byteme1, q7_t byteme2, q7_t byteme3)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q7_t* pOut_data = pOut->write<q7_t>(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_q7_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}
template<>
void FullyConnectedLayerOptCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                                           q15_t byteme1, q15_t byteme2, q15_t byteme3)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* bias_data = b->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write<q15_t>(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_q15_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerOptCmsis<q15_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch,
                                           q15_t byteme1, q7_t byteme2, q7_t byteme3)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write<q15_t>(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template <class T1, class T2, class TOut>
class FullyConnectedLayerCmsisOp : public Operator {
  public:
  FullyConnectedLayerCmsisOp() {
    n_inputs = 6;
    n_outputs = 1;
  }
  virtual void compute() override {
    T1 x;
    T2 y;
    TOut byteme;
    FullyConnectedLayerCmsis(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], outputs[0], inputs[5], x, y, byteme);
  }
};

template <class T1, class T2, class TOut>
class FullyConnectedLayerOptCmsisOp : public Operator {
  public:
  FullyConnectedLayerOptCmsisOp() {
    n_inputs = 6;
    n_outputs = 1;
  }
  virtual void compute() override {
    T1 x;
    T2 y;
    TOut byteme;
    FullyConnectedLayerOptCmsis<T1, T2, TOut>(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], outputs[0], inputs[5], x, y, byteme);
  }
};

#endif /*UTENSOR_FULLY_CONNECTED_OPS*/
<commit_msg>Greatly simplify cmsis interface<commit_after>#ifndef UTENSOR_FULLY_CONNECTED_OPS
#define UTENSOR_FULLY_CONNECTED_OPS
#include "uTensor/core/tensor.hpp"
#include "uTensor/core/uTensorBase.hpp"
#include "arm_math.h"
#include "arm_nnfunctions.h"

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

template<typename T1, typename T2, typename T3>
void cmsis_fc_selector(const T1* iV, const T2* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const T3* bias,
                       T1* pOut, q15_t* scratch_data);
template<>
void cmsis_fc_selector<q7_t, q7_t, q7_t>(const q7_t* iV, const q7_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q7_t* bias,
                       q7_t* pOut, q15_t* scratch_data){
    arm_fully_connected_q7(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

template<>
void cmsis_fc_selector<q15_t, q15_t, q15_t>(const q15_t* iV, const q15_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q15_t* bias,
                       q15_t* pOut, q15_t* scratch_data){
    arm_fully_connected_q15(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

template<>
void cmsis_fc_selector<q15_t, q7_t, q7_t>(const q15_t* iV, const q7_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q7_t* bias,
                       q15_t* pOut, q15_t* scratch_data){
    arm_fully_connected_mat_q7_vec_q15(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

template<typename T1, typename T2, typename T3>
void cmsis_fc_selector_opt(const T1* iV, const T2* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const T3* bias,
                       T1* pOut, q15_t* scratch_data);
template<>
void cmsis_fc_selector_opt<q7_t, q7_t, q7_t>(const q7_t* iV, const q7_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q7_t* bias,
                       q7_t* pOut, q15_t* scratch_data){
    arm_fully_connected_q7_opt(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

template<>
void cmsis_fc_selector_opt<q15_t, q15_t, q15_t>(const q15_t* iV, const q15_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q15_t* bias,
                       q15_t* pOut, q15_t* scratch_data){
    arm_fully_connected_q15_opt(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

template<>
void cmsis_fc_selector_opt<q15_t, q7_t, q7_t>(const q15_t* iV, const q7_t* mW, const uint16_t dim_vec, const uint16_t num_of_rows,
                       const uint16_t bias_shift, const uint16_t out_shift, const q7_t* bias,
                       q15_t* pOut, q15_t* scratch_data){
    arm_fully_connected_mat_q7_vec_q15_opt(iV, mW, dim_vec, num_of_rows,
            bias_shift, out_shift, bias, pOut, scratch_data);
}

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename T3>
void FullyConnectedLayerCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch,
                         T1 byteme1, T2 byteme2, T3 byteme3)
{
    const T1* iV_data  = iV->read<T1>(0, sizeof(T1)); //Read one byte
    const T2* mW_data  = mW->read<T2>(0, sizeof(T2)); //Read one byte
    const T3* bias_data = b->read<T3>(0, sizeof(T3)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    T1* pOut_data = pOut->write<T1>(0, sizeof(T1));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    cmsis_fc_selector(iV_data, mW_data, dim_vec, num_of_rows,
            bias_shift, out_shift, bias_data, pOut_data, scratch_data);

    //Error checking
}

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename T3>
void FullyConnectedLayerOptCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch,
                         T1 byteme1, T2 byteme2, T3 byteme3)
{
    const T1* iV_data  = iV->read<T1>(0, sizeof(T1)); //Read one byte
    const T2* mW_data  = mW->read<T2>(0, sizeof(T2)); //Read one byte
    const T3* bias_data = b->read<T3>(0, sizeof(T3)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    T1* pOut_data = pOut->write<T1>(0, sizeof(T1));
    q15_t* scratch_data = scratch->write<q15_t>(0, sizeof(q15_t));

    cmsis_fc_selector_opt(iV_data, mW_data, dim_vec, num_of_rows,
            bias_shift, out_shift, bias_data, pOut_data, scratch_data);

    //Error checking
}

template <class T1, class T2, class T3>
class FullyConnectedLayerCmsisOp : public Operator {
  public:
  FullyConnectedLayerCmsisOp() {
    n_inputs = 6;
    n_outputs = 1;
  }
  virtual void compute() override {
    T1 x;
    T2 y;
    T3 byteme;
    FullyConnectedLayerCmsis(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], outputs[0], inputs[5], x, y, byteme);
  }
};

template <class T1, class T2, class T3>
class FullyConnectedLayerOptCmsisOp : public Operator {
  public:
  FullyConnectedLayerOptCmsisOp() {
    n_inputs = 6;
    n_outputs = 1;
  }
  virtual void compute() override {
    T1 x;
    T2 y;
    T3 byteme;
    FullyConnectedLayerOptCmsis(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], outputs[0], inputs[5], x, y, byteme);
  }
};

#endif /*UTENSOR_FULLY_CONNECTED_OPS*/
<|endoftext|>


<commit_before>#include "merlin_image.h":

namespace merlin {

Persistent<FunctionTemplate> MerlinImage::constructor_template;

Handle<Value>
MerlinImage::New(const Arguments& args) {
    HandleScope scope;
    node::Buffer *buf = ObjectWrap::Unwrap<node::Buffer>(args[0]->ToObject());
    MerlinImage* img = new MerlinImage(buf);
    img->Wrap(args.This());
    return scope.Close(args.This());
}

Handle<Value>
MerlinImage::GetBuffer(const Arguments& args) {
    HandleScope scope;

    MerlinImage *img = ObjectWrap::Unwrap<MerlinImage>(args.This());
    Handle<Value> buf = img->buffer->handle_;

    return scope.Close(buf);
}

Handle<Value>
MerlinImage::CropImage(const Arguments& args) {
    HandleScope scope;

    MerlinImage *img = ObjectWrap::Unwrap<MerlinImage>(args.This());
    fprintf(stderr, "1\n");
    fprintf(stderr, "%i", img->buffer->length());
    fprintf(stderr, "1.5\n");
    node::Buffer* new_buffer = node::Buffer::New(img->buffer->length());
    fprintf(stderr, "2\n");
    new_buffer->Utf8Write(img->buffer->data(), 0, img->buffer->length());
    fprintf(stderr, "3\n");
    MerlinImage *new_image = new MerlinImage(new_buffer);
    fprintf(stderr, "before return\n");
    return scope.Close(new_image->handle_);
}

void
MerlinImage::Initialize(Handle<Object> target) {
    HandleScope scope;

    Handle<FunctionTemplate> f = FunctionTemplate::New(MerlinImage::New);
    constructor_template = Persistent<FunctionTemplate>::New(f);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
    constructor_template->SetClassName(String::NewSymbol("MerlinImage"));

    NODE_SET_PROTOTYPE_METHOD(constructor_template, "cropImage", MerlinImage::CropImage);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "getBuffer", MerlinImage::GetBuffer);

    target->Set(String::NewSymbol("MerlinImage"), constructor_template->GetFunction());
}

MerlinImage::MerlinImage(node::Buffer *buffer) :
    buffer(buffer)
{
    wand = NewMagickWand();
}

MerlinImage::~MerlinImage() {
    delete buffer;
    wand = DestroyMagickWand(wand);
}

}
<commit_msg>another shot at transferring buffers<commit_after>#include "merlin_image.h":

namespace merlin {

Persistent<FunctionTemplate> MerlinImage::constructor_template;

Handle<Value>
MerlinImage::New(const Arguments& args) {
    HandleScope scope;
    node::Buffer *buf = ObjectWrap::Unwrap<node::Buffer>(args[0]->ToObject());
    MerlinImage* img = new MerlinImage(buf);
    img->Wrap(args.This());
    return scope.Close(args.This());
}

Handle<Value>
MerlinImage::GetBuffer(const Arguments& args) {
    HandleScope scope;

    MerlinImage *img = ObjectWrap::Unwrap<MerlinImage>(args.This());
    Handle<Value> buf = img->buffer->handle_;

    return scope.Close(buf);
}

Handle<Value>
MerlinImage::CropImage(const Arguments& args) {
    HandleScope scope;

    MerlinImage *img = ObjectWrap::Unwrap<MerlinImage>(args.This());
    fprintf(stderr, "1\n");
    //    return scope.Close(new_image->handle_);
    Handle<String> str = String::New(img->buffer->data(), img->buffer->length());
    return scope.Close(str);
}

void
MerlinImage::Initialize(Handle<Object> target) {
    HandleScope scope;

    Handle<FunctionTemplate> f = FunctionTemplate::New(MerlinImage::New);
    constructor_template = Persistent<FunctionTemplate>::New(f);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
    constructor_template->SetClassName(String::NewSymbol("MerlinImage"));

    NODE_SET_PROTOTYPE_METHOD(constructor_template, "cropImage", MerlinImage::CropImage);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "getBuffer", MerlinImage::GetBuffer);

    target->Set(String::NewSymbol("MerlinImage"), constructor_template->GetFunction());
}

MerlinImage::MerlinImage(node::Buffer *buffer) :
    buffer(buffer)
{
    wand = NewMagickWand();
}

MerlinImage::~MerlinImage() {
    delete buffer;
    wand = DestroyMagickWand(wand);
}

}
<|endoftext|>


<commit_before>#include "editaddressdialog.h"
#include "ui_editaddressdialog.h"
#include "addresstablemodel.h"
#include "dialogwindowflags.h"
#include "guiconstants.h"
#include "guiutil.h"

#include <QDataWidgetMapper>
#include <QMessageBox>

EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) :
    QDialog(parent, DIALOGWINDOWHINTS),
    ui(new Ui::EditAddressDialog), mapper(0), mode(mode), model(0)
{
    ui->setupUi(this);

    GUIUtil::setupAddressWidget(ui->addressEdit, this);

    switch(mode)
    {
    case NewReceivingAddress:
        setWindowTitle(tr("New receiving address"));
        ui->addressEdit->setEnabled(false);
        break;
    case NewSendingAddress:
        setWindowTitle(tr("New sending address"));
        break;
    case EditReceivingAddress:
        setWindowTitle(tr("Edit receiving address"));
        ui->addressEdit->setEnabled(false);
        break;
    case EditSendingAddress:
        setWindowTitle(tr("Edit sending address"));
        break;
    }

    mapper = new QDataWidgetMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
}

EditAddressDialog::~EditAddressDialog()
{
    delete ui;
}

void EditAddressDialog::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    mapper->setModel(model);
    mapper->addMapping(ui->labelEdit, AddressTableModel::Label);
    mapper->addMapping(ui->addressEdit, AddressTableModel::Address);
}

void EditAddressDialog::loadRow(int row)
{
    mapper->setCurrentIndex(row);
}

bool EditAddressDialog::saveCurrentRow()
{
    if(!model)
        return false;

    switch(mode)
    {
    case NewReceivingAddress:
    case NewSendingAddress:
        address = model->addRow(
                mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive,
                ui->labelEdit->text(),
                ui->addressEdit->text());
        break;
    case EditReceivingAddress:
    case EditSendingAddress:
        if(mapper->submit())
        {
            address = ui->addressEdit->text();
        }
        break;
    }
    return !address.isEmpty();
}

void EditAddressDialog::accept()
{
    if(!model)
        return;

    if(!saveCurrentRow())
    {
        switch(model->getEditStatus())
        {
        case AddressTableModel::OK:
            // Failed with unknown reason. Just reject.
            break;
        case AddressTableModel::NO_CHANGES:
            // No changes were made during edit operation. Just reject.
            break;
        case AddressTableModel::INVALID_ADDRESS:
            QMessageBox::warning(this, windowTitle(),
                tr("The entered address \"%1\" is not a valid NovaCoin address.").arg(ui->addressEdit->text()),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::DUPLICATE_ADDRESS:
            QMessageBox::warning(this, windowTitle(),
                tr("The entered address \"%1\" is already in the address book.").arg(ui->addressEdit->text()),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::WALLET_UNLOCK_FAILURE:
            QMessageBox::critical(this, windowTitle(),
                tr("Could not unlock wallet."),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::KEY_GENERATION_FAILURE:
            QMessageBox::critical(this, windowTitle(),
                tr("New key generation failed."),
                QMessageBox::Ok, QMessageBox::Ok);
            break;

        }
        return;
    }
    QDialog::accept();
}

QString EditAddressDialog::getAddress() const
{
    return address;
}

void EditAddressDialog::setAddress(const QString &address)
{
    this->address = address;
    ui->addressEdit->setText(address);
}
<commit_msg>лишний #include<commit_after>#include "editaddressdialog.h"
#include "ui_editaddressdialog.h"
#include "addresstablemodel.h"
#include "dialogwindowflags.h"
#include "guiutil.h"

#include <QDataWidgetMapper>
#include <QMessageBox>

EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) :
    QDialog(parent, DIALOGWINDOWHINTS),
    ui(new Ui::EditAddressDialog), mapper(0), mode(mode), model(0)
{
    ui->setupUi(this);

    GUIUtil::setupAddressWidget(ui->addressEdit, this);

    switch(mode)
    {
    case NewReceivingAddress:
        setWindowTitle(tr("New receiving address"));
        ui->addressEdit->setEnabled(false);
        break;
    case NewSendingAddress:
        setWindowTitle(tr("New sending address"));
        break;
    case EditReceivingAddress:
        setWindowTitle(tr("Edit receiving address"));
        ui->addressEdit->setEnabled(false);
        break;
    case EditSendingAddress:
        setWindowTitle(tr("Edit sending address"));
        break;
    }

    mapper = new QDataWidgetMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
}

EditAddressDialog::~EditAddressDialog()
{
    delete ui;
}

void EditAddressDialog::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    mapper->setModel(model);
    mapper->addMapping(ui->labelEdit, AddressTableModel::Label);
    mapper->addMapping(ui->addressEdit, AddressTableModel::Address);
}

void EditAddressDialog::loadRow(int row)
{
    mapper->setCurrentIndex(row);
}

bool EditAddressDialog::saveCurrentRow()
{
    if(!model)
        return false;

    switch(mode)
    {
    case NewReceivingAddress:
    case NewSendingAddress:
        address = model->addRow(
                mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive,
                ui->labelEdit->text(),
                ui->addressEdit->text());
        break;
    case EditReceivingAddress:
    case EditSendingAddress:
        if(mapper->submit())
        {
            address = ui->addressEdit->text();
        }
        break;
    }
    return !address.isEmpty();
}

void EditAddressDialog::accept()
{
    if(!model)
        return;

    if(!saveCurrentRow())
    {
        switch(model->getEditStatus())
        {
        case AddressTableModel::OK:
            // Failed with unknown reason. Just reject.
            break;
        case AddressTableModel::NO_CHANGES:
            // No changes were made during edit operation. Just reject.
            break;
        case AddressTableModel::INVALID_ADDRESS:
            QMessageBox::warning(this, windowTitle(),
                tr("The entered address \"%1\" is not a valid NovaCoin address.").arg(ui->addressEdit->text()),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::DUPLICATE_ADDRESS:
            QMessageBox::warning(this, windowTitle(),
                tr("The entered address \"%1\" is already in the address book.").arg(ui->addressEdit->text()),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::WALLET_UNLOCK_FAILURE:
            QMessageBox::critical(this, windowTitle(),
                tr("Could not unlock wallet."),
                QMessageBox::Ok, QMessageBox::Ok);
            break;
        case AddressTableModel::KEY_GENERATION_FAILURE:
            QMessageBox::critical(this, windowTitle(),
                tr("New key generation failed."),
                QMessageBox::Ok, QMessageBox::Ok);
            break;

        }
        return;
    }
    QDialog::accept();
}

QString EditAddressDialog::getAddress() const
{
    return address;
}

void EditAddressDialog::setAddress(const QString &address)
{
    this->address = address;
    ui->addressEdit->setText(address);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_TERMINATE_HPP
#define REALM_UTIL_TERMINATE_HPP

#include <sstream>
#include <cstdlib>
#include <string>

#include <realm/util/features.h>

#define REALM_TERMINATE(msg) realm::util::terminate((msg), __FILE__, __LINE__)

namespace realm {
namespace util {
REALM_NORETURN void terminate_internal(std::stringstream&) noexcept;

REALM_NORETURN inline void terminate(const char* message, const char* file, long line) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << "\n";
    terminate_internal(ss);
}

template <typename T1, typename T2>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4, T5 info5, T6 info6) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << ", " << info5 << ", " << info6 << "]\n";
    terminate_internal(ss);
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_TERMINATE_HPP
<commit_msg>Reorganised headers in terminate.hpp<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_TERMINATE_HPP
#define REALM_UTIL_TERMINATE_HPP

#include <cstdlib>
#include <sstream>
#include <string>

#include <realm/util/features.h>

#define REALM_TERMINATE(msg) realm::util::terminate((msg), __FILE__, __LINE__)

namespace realm {
namespace util {
REALM_NORETURN void terminate_internal(std::stringstream&) noexcept;

REALM_NORETURN inline void terminate(const char* message, const char* file, long line) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << "\n";
    terminate_internal(ss);
}

template <typename T1, typename T2>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4, T5 info5, T6 info6) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << ", " << info5 << ", " << info6 << "]\n";
    terminate_internal(ss);
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_TERMINATE_HPP
<|endoftext|>


<commit_before>#include "AssetConverter.hpp"
#include <Utility/Log.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>

AssetConverter::AssetConverter() {
}

AssetConverter::~AssetConverter() {
}

void AssetConverter::Convert(const char* filepath, const char* destination, glm::vec3 scale, bool triangulate, bool importNormals, bool importTangents, bool flipUVs, bool importMaterial, Materials& materials) {
    success = true;
    errorString.clear();

    Geometry::AssetFileHandler file;

    // Return if file is not open.
    file.Open(destination, Geometry::AssetFileHandler::WRITE);

    unsigned int flags = triangulate ? aiProcess_Triangulate : 0;
    flags = importNormals ? flags : flags | aiProcess_CalcTangentSpace;
    flags = importTangents ? flags : flags | aiProcess_GenSmoothNormals;

    const aiScene* aScene = aImporter.ReadFile(filepath, flags);

    if (aScene == nullptr) {
        Log() << "Error importing mesh: " << filepath << "\n";
        Log() << aImporter.GetErrorString() << "\n";
        aImporter.FreeScene();
        aScene = aImporter.ReadFile("ErrorSign.fbx", flags);
    }

    if (importMaterial) {
        if (aScene->mMeshes[0]->mMaterialIndex >= 0) {
            aiMaterial* material = aScene->mMaterials[aScene->mMeshes[0]->mMaterialIndex];

            LoadMaterial(material, aiTextureType_DIFFUSE, materials.albedo);
            LoadMaterial(material, aiTextureType_NORMALS, materials.normal);
            LoadMaterial(material, aiTextureType_SPECULAR, materials.roughness);
            LoadMaterial(material, aiTextureType_REFLECTION, materials.metallic);
        }
    }

    ConvertMeshes(aScene, &file, scale, flipUVs);

    aImporter.FreeScene();

    file.Close();
}

bool AssetConverter::Success() const {
    return success;
}

std::string& AssetConverter::GetErrorString() {
    return errorString;
}

void AssetConverter::ConvertMeshes(const aiScene * aScene, Geometry::AssetFileHandler * file, glm::vec3 scale, bool flipUVs) {
     for (unsigned int i = 0; i < aScene->mNumMeshes; ++i)
        ConvertMesh(aScene->mMeshes[i], file, scale, flipUVs);
}

void AssetConverter::ConvertMesh(aiMesh * aMesh, Geometry::AssetFileHandler * file, glm::vec3 scale, bool flipUVs) {
    Geometry::AssetFileHandler::MeshData * meshData = new Geometry::AssetFileHandler::MeshData;

    meshData->parent = 0;

    // Convert vertices.
    unsigned int numVertices = aMesh->mNumVertices;
    meshData->numVertices = numVertices;

    // If mesh has no bones the mesh is static.
    if (aMesh->mNumBones == 0) {
        meshData->staticVertices = ConvertStaticVertices(aMesh, file, numVertices, scale, flipUVs);
        meshData->isSkinned = false;
    }
    else {
        meshData->skinnedVertices = ConvertSkinnedVertices(aMesh, file, numVertices, scale, flipUVs);
        meshData->isSkinned = true;
    }

    // Convert indicies. 3 indicies for a face/triangle.
    unsigned int numIndicies = aMesh->mNumFaces * 3;
    uint32_t * indices = new uint32_t[numIndicies];
    unsigned int indexCounter = 0;
    for (unsigned int i = 0; i < aMesh->mNumFaces; ++i) {
        const aiFace& aFace = aMesh->mFaces[i];
        if (aFace.mNumIndices != 3) {
            errorString.append("ERROR: Mesh not triangulated.\n");
            success = false;
            delete[] indices;
            delete meshData;
            return;
        }

        indices[indexCounter++] = aFace.mIndices[0];
        indices[indexCounter++] = aFace.mIndices[1];
        indices[indexCounter++] = aFace.mIndices[2];
    }

    meshData->numIndices = indexCounter;
    meshData->indices = indices;

    CalculateAABB(meshData, meshData->numVertices);

    file->SaveStaticMesh(meshData);

    delete meshData;
    meshData = nullptr;
}

Video::Geometry::VertexType::StaticVertex * AssetConverter::ConvertStaticVertices(aiMesh* aMesh, Geometry::AssetFileHandler* file, unsigned int numVertices, glm::vec3 scale, bool flipUVs) {
    Video::Geometry::VertexType::StaticVertex * vertices = new Video::Geometry::VertexType::StaticVertex[numVertices];

    // Positions.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].position, aMesh->mVertices[i]);
            vertices[i].position *= scale;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no positions yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].position = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Texture coordinates.
    if (aMesh->HasTextureCoords(0)) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].textureCoordinate, aMesh->mTextureCoords[0][i]);
            if (flipUVs)
                vertices[i].textureCoordinate.y = 1.0f - vertices[i].textureCoordinate.y;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no texture coordinates yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].textureCoordinate = glm::vec2(0.0f, 0.0f);
    }

    // Normals.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].normal, aMesh->mNormals[i]);
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no normals yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].normal = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Tangents.
    if (aMesh->HasTangentsAndBitangents()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].tangent, aMesh->mTangents[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no tangents yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].tangent = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    return vertices;
}

Video::Geometry::VertexType::SkinVertex * AssetConverter::ConvertSkinnedVertices(aiMesh * aMesh, Geometry::AssetFileHandler * file, unsigned int numVertices, glm::vec3 scale, bool flipUVs) {
    Video::Geometry::VertexType::SkinVertex * vertices = new Video::Geometry::VertexType::SkinVertex[numVertices];

    // Positions.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].position, aMesh->mVertices[i]);
            vertices[i].position *= scale;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no positions yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].position = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Texture coordinates.
    if (aMesh->HasTextureCoords(0)) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].textureCoordinate, aMesh->mTextureCoords[0][i]);
            if (flipUVs)
                vertices[i].textureCoordinate.y = 1.0f - vertices[i].textureCoordinate.y;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no texture coordinates yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].textureCoordinate = glm::vec2(0.0f, 0.0f);
    }

    // Normals.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].normal, aMesh->mNormals[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no normals yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].normal = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Tangents.
    if (aMesh->HasTangentsAndBitangents()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].tangent, aMesh->mTangents[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no tangents yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].tangent = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    std::vector<unsigned int> weightCounter(numVertices, 0);

    for (unsigned int b = 0; b < aMesh->mNumBones; ++b) {
        const aiBone * aBone = aMesh->mBones[b];
        for (unsigned int i = 0; i < aBone->mNumWeights; ++i) {
            unsigned int vertexID = aBone->mWeights[i].mVertexId;
            unsigned int& count = weightCounter[vertexID];
            vertices[vertexID].weights[count] = aBone->mWeights[i].mWeight;
            vertices[vertexID].boneIDs[count] = i;
            ++count;
        }
    }

    weightCounter.clear();

    return vertices;
}

void AssetConverter::CalculateAABB(Geometry::AssetFileHandler::MeshData * meshData, unsigned int numVertices) {
    glm::vec3 minValues, maxValues, origin, dim;
    minValues = maxValues = origin = glm::vec3(0.f, 0.f, 0.f);

    // Find minimum/maximum bounding points.
    for (std::size_t i = 0; i < numVertices; ++i) {
        const glm::vec3& pos = meshData->isSkinned ? meshData->skinnedVertices[i].position : meshData->staticVertices[i].position;
        if (pos.x > maxValues.x)
            maxValues.x = pos.x;
        else if (pos.x < minValues.x)
            minValues.x = pos.x;

        if (pos.y > maxValues.y)
            maxValues.y = pos.y;
        else if (pos.y < minValues.y)
            minValues.y = pos.y;

        if (pos.z > maxValues.z)
            maxValues.z = pos.z;
        else if (pos.z < minValues.z)
            minValues.z = pos.z;
    }

    // Set origin.
    origin.x = (minValues.x + maxValues.x) / 2.f;
    origin.y = (minValues.y + maxValues.y) / 2.f;
    origin.z = (minValues.z + maxValues.z) / 2.f;

    // Dimensions.
    dim.x = maxValues.x - minValues.x;
    dim.y = maxValues.y - minValues.y;
    dim.z = maxValues.z - minValues.z;

    meshData->aabbDim = dim;
    meshData->aabbOrigin = origin;
    meshData->aabbMaxpos = maxValues;
    meshData->aabbMinpos = minValues;
}

void AssetConverter::LoadMaterial(aiMaterial* material, aiTextureType type, std::string& path) {
    if (material->GetTextureCount(type) > 0) {
        aiString p;
        material->GetTexture(type, 0, &p);
        path = p.C_Str();
    }
}
<commit_msg>Update AssetConverter.cpp<commit_after>#include "AssetConverter.hpp"
#include <Utility/Log.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Util/FileSystem.hpp>

AssetConverter::AssetConverter() {
}

AssetConverter::~AssetConverter() {
}

void AssetConverter::Convert(const char* filepath, const char* destination, glm::vec3 scale, bool triangulate, bool importNormals, bool importTangents, bool flipUVs, bool importMaterial, Materials& materials) {
    success = true;
    errorString.clear();

    Geometry::AssetFileHandler file;

    // Return if file is not open.
    file.Open(destination, Geometry::AssetFileHandler::WRITE);

    unsigned int flags = triangulate ? aiProcess_Triangulate : 0;
    flags = importNormals ? flags : flags | aiProcess_CalcTangentSpace;
    flags = importTangents ? flags : flags | aiProcess_GenSmoothNormals;

    const aiScene* aScene = aImporter.ReadFile(filepath, flags);

    if (aScene == nullptr) {
        Log() << "Error importing mesh: " << filepath << "\n";
        Log() << aImporter.GetErrorString() << "\n";
        aImporter.FreeScene();
        aScene = aImporter.ReadFile("ErrorSign.fbx", flags);
    }

    if (importMaterial) {
        if (aScene->mMeshes[0]->mMaterialIndex >= 0) {
            aiMaterial* material = aScene->mMaterials[aScene->mMeshes[0]->mMaterialIndex];
            LoadMaterial(material, aiTextureType_DIFFUSE, materials.albedo);
            LoadMaterial(material, aiTextureType_NORMALS, materials.normal);
            LoadMaterial(material, aiTextureType_SPECULAR, materials.roughness);
            LoadMaterial(material, aiTextureType_REFLECTION, materials.metallic);
        }
    }

    ConvertMeshes(aScene, &file, scale, flipUVs);

    aImporter.FreeScene();

    file.Close();
}

bool AssetConverter::Success() const {
    return success;
}

std::string& AssetConverter::GetErrorString() {
    return errorString;
}

void AssetConverter::ConvertMeshes(const aiScene * aScene, Geometry::AssetFileHandler * file, glm::vec3 scale, bool flipUVs) {
     for (unsigned int i = 0; i < aScene->mNumMeshes; ++i)
        ConvertMesh(aScene->mMeshes[i], file, scale, flipUVs);
}

void AssetConverter::ConvertMesh(aiMesh * aMesh, Geometry::AssetFileHandler * file, glm::vec3 scale, bool flipUVs) {
    Geometry::AssetFileHandler::MeshData * meshData = new Geometry::AssetFileHandler::MeshData;

    meshData->parent = 0;

    // Convert vertices.
    unsigned int numVertices = aMesh->mNumVertices;
    meshData->numVertices = numVertices;

    // If mesh has no bones the mesh is static.
    if (aMesh->mNumBones == 0) {
        meshData->staticVertices = ConvertStaticVertices(aMesh, file, numVertices, scale, flipUVs);
        meshData->isSkinned = false;
    }
    else {
        meshData->skinnedVertices = ConvertSkinnedVertices(aMesh, file, numVertices, scale, flipUVs);
        meshData->isSkinned = true;
    }

    // Convert indicies. 3 indicies for a face/triangle.
    unsigned int numIndicies = aMesh->mNumFaces * 3;
    uint32_t * indices = new uint32_t[numIndicies];
    unsigned int indexCounter = 0;
    for (unsigned int i = 0; i < aMesh->mNumFaces; ++i) {
        const aiFace& aFace = aMesh->mFaces[i];
        if (aFace.mNumIndices != 3) {
            errorString.append("ERROR: Mesh not triangulated.\n");
            success = false;
            delete[] indices;
            delete meshData;
            return;
        }

        indices[indexCounter++] = aFace.mIndices[0];
        indices[indexCounter++] = aFace.mIndices[1];
        indices[indexCounter++] = aFace.mIndices[2];
    }

    meshData->numIndices = indexCounter;
    meshData->indices = indices;

    CalculateAABB(meshData, meshData->numVertices);

    file->SaveStaticMesh(meshData);

    delete meshData;
    meshData = nullptr;
}

Video::Geometry::VertexType::StaticVertex * AssetConverter::ConvertStaticVertices(aiMesh* aMesh, Geometry::AssetFileHandler* file, unsigned int numVertices, glm::vec3 scale, bool flipUVs) {
    Video::Geometry::VertexType::StaticVertex * vertices = new Video::Geometry::VertexType::StaticVertex[numVertices];

    // Positions.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].position, aMesh->mVertices[i]);
            vertices[i].position *= scale;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no positions yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].position = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Texture coordinates.
    if (aMesh->HasTextureCoords(0)) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].textureCoordinate, aMesh->mTextureCoords[0][i]);
            if (flipUVs)
                vertices[i].textureCoordinate.y = 1.0f - vertices[i].textureCoordinate.y;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no texture coordinates yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].textureCoordinate = glm::vec2(0.0f, 0.0f);
    }

    // Normals.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].normal, aMesh->mNormals[i]);
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no normals yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].normal = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Tangents.
    if (aMesh->HasTangentsAndBitangents()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].tangent, aMesh->mTangents[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no tangents yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].tangent = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    return vertices;
}

Video::Geometry::VertexType::SkinVertex * AssetConverter::ConvertSkinnedVertices(aiMesh * aMesh, Geometry::AssetFileHandler * file, unsigned int numVertices, glm::vec3 scale, bool flipUVs) {
    Video::Geometry::VertexType::SkinVertex * vertices = new Video::Geometry::VertexType::SkinVertex[numVertices];

    // Positions.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].position, aMesh->mVertices[i]);
            vertices[i].position *= scale;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no positions yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].position = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Texture coordinates.
    if (aMesh->HasTextureCoords(0)) {
        for (unsigned int i = 0; i < numVertices; ++i) {
            Geometry::CpyVec(vertices[i].textureCoordinate, aMesh->mTextureCoords[0][i]);
            if (flipUVs)
                vertices[i].textureCoordinate.y = 1.0f - vertices[i].textureCoordinate.y;
        }
    } else {
        success = false;
        errorString.append("WARNING: The model has no texture coordinates yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].textureCoordinate = glm::vec2(0.0f, 0.0f);
    }

    // Normals.
    if (aMesh->HasNormals()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].normal, aMesh->mNormals[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no normals yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].normal = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    // Tangents.
    if (aMesh->HasTangentsAndBitangents()) {
        for (unsigned int i = 0; i < numVertices; ++i)
            Geometry::CpyVec(vertices[i].tangent, aMesh->mTangents[i]);
    } else {
        success = false;
        errorString.append("WARNING: The model has no tangents yet the user is trying to import them.\n");
        for (unsigned int i = 0; i < numVertices; ++i)
            vertices[i].tangent = glm::vec3(1.0f, 0.0f, 0.0f);
    }

    std::vector<unsigned int> weightCounter(numVertices, 0);

    for (unsigned int b = 0; b < aMesh->mNumBones; ++b) {
        const aiBone * aBone = aMesh->mBones[b];
        for (unsigned int i = 0; i < aBone->mNumWeights; ++i) {
            unsigned int vertexID = aBone->mWeights[i].mVertexId;
            unsigned int& count = weightCounter[vertexID];
            vertices[vertexID].weights[count] = aBone->mWeights[i].mWeight;
            vertices[vertexID].boneIDs[count] = i;
            ++count;
        }
    }

    weightCounter.clear();

    return vertices;
}

void AssetConverter::CalculateAABB(Geometry::AssetFileHandler::MeshData * meshData, unsigned int numVertices) {
    glm::vec3 minValues, maxValues, origin, dim;
    minValues = maxValues = origin = glm::vec3(0.f, 0.f, 0.f);

    // Find minimum/maximum bounding points.
    for (std::size_t i = 0; i < numVertices; ++i) {
        const glm::vec3& pos = meshData->isSkinned ? meshData->skinnedVertices[i].position : meshData->staticVertices[i].position;
        if (pos.x > maxValues.x)
            maxValues.x = pos.x;
        else if (pos.x < minValues.x)
            minValues.x = pos.x;

        if (pos.y > maxValues.y)
            maxValues.y = pos.y;
        else if (pos.y < minValues.y)
            minValues.y = pos.y;

        if (pos.z > maxValues.z)
            maxValues.z = pos.z;
        else if (pos.z < minValues.z)
            minValues.z = pos.z;
    }

    // Set origin.
    origin.x = (minValues.x + maxValues.x) / 2.f;
    origin.y = (minValues.y + maxValues.y) / 2.f;
    origin.z = (minValues.z + maxValues.z) / 2.f;

    // Dimensions.
    dim.x = maxValues.x - minValues.x;
    dim.y = maxValues.y - minValues.y;
    dim.z = maxValues.z - minValues.z;

    meshData->aabbDim = dim;
    meshData->aabbOrigin = origin;
    meshData->aabbMaxpos = maxValues;
    meshData->aabbMinpos = minValues;
}

void AssetConverter::LoadMaterial(aiMaterial* material, aiTextureType type, std::string& path) {
    if (material->GetTextureCount(type) > 0) {
        aiString p;
        material->GetTexture(type, 0, &p);
        path = p.C_Str();
    }
}
<|endoftext|>


<commit_before>/** \file circularize_main.cpp
 *
 * Defines the "vg circularize" subcommand
 */

#include <omp.h>
#include <unistd.h>
#include <getopt.h>

#include <iostream>

#include "subcommand.hpp"

#include "../utility.hpp"
#include "../handle.hpp"
#include "../vg.hpp"
#include <vg/io/stream.hpp>
#include <vg/io/vpkg.hpp>

using namespace std;
using namespace vg;
using namespace vg::subcommand;

void help_circularize(char** argv){
    cerr << "usage: " << argv[0] << " circularize [options] <graph.vg> > [circularized.vg]" << endl
        << "Makes specific paths or nodes in a graph circular." << endl
        << endl
        << "options:" << endl
        << "    -p  --path  <PATHNAME>  circularize the path by connecting its head/tail node." << endl
        << "    -P, --pathfile <PATHSFILE> circularize all paths in the provided file." << endl
        << "    -a, --head  <node_id>   circularize a head and tail node (must provide a tail)." << endl
        << "    -z, --tail  <tail_id>   circularize a head and tail node (must provide a head)." << endl
        << "    -d  --describe          list all the paths in the graph."   << endl
        << endl;
    exit(1);
}

int main_circularize(int argc, char** argv){
    if (argc == 2){
        help_circularize(argv);
        exit(1);
    }

    string path = "";
    string pathfile = "";
    bool describe = false;
    vg::id_t head = -1;
    vg::id_t tail = -1;

    int c;
    optind = 2;
    while (true){
        static struct option long_options[] =
        {
            {"path", required_argument, 0, 'p'},
            {"pathfile", required_argument, 0, 'P'},
            {"head", required_argument, 0, 'a'},
            {"tail", required_argument, 0, 'z'},
            {"describe", required_argument, 0, 'd'},
            {0,0,0,0}
        };

    int option_index = 0;
    c = getopt_long (argc, argv, "hdp:P:a:z:",
            long_options, &option_index);
    if (c == -1){
        break;
    }

        switch(c){
            case 'a':
                head = parse<int>(optarg);
                break;
            case 'z':
                tail = parse<int>(optarg);
                break;
            case 'p':
                path = optarg;
                break;
            case 'P':
                pathfile = optarg;
                break;
            case 'd':
                describe = true;
                break;
            case 'h':
            case '?':
                help_circularize(argv);
                exit(1);
                break;

            default:
                abort();
        }
    }

    vector<string> paths_to_circularize;
    if (!((head * tail) > 0)){
        cerr << "Both a head and tail node must be provided" << endl;
        help_circularize(argv);
        exit(1);
    }
    if  (pathfile != ""){
        string line;
        ifstream pfi;
        pfi.open(pathfile);
        if (!pfi.good()){
            cerr << "There is an error with the input file." << endl;
            help_circularize(argv);
        }
        while (getline(pfi, line)){
            paths_to_circularize.push_back(line);
        }
        pfi.close();

    }
    else if (path != ""){
        paths_to_circularize.push_back(path);
    }

    // TODO: if we settle on a uniform serialzation method that covers the VG class, the code is ready to be switched
    VG* graph;
    get_input_file(optind, argc, argv, [&](istream& in) {
        graph = new VG(in);
    });

    // Check if paths are in graph:
    for (const string& p : paths_to_circularize){
        if (!graph->has_path(p)){
            cerr << "ERROR: PATH NOT IN GRAPH - " << p << endl;
            exit(1);
        }
    }

    if (describe){
        graph->for_each_path_handle([&](const path_handle_t& path_handle) {
            cout << graph->get_path_name(path_handle) << endl;
        });
       exit(0);
    }

    if (head > 0 && tail > head){
        graph->create_edge(graph->get_handle(tail), graph->get_handle(head));
    }
    else{
        for (const auto& path_name : paths_to_circularize) {
            graph->set_circularity(graph->get_path_handle(path_name), true);
        }
    }

    graph->serialize_to_ostream(cout);
//    SerializableHandleGraph* to_serialize = dynamic_cast<SerializableHandleGraph*>(&(*graph));
//    if (!to_serialize) {
//        cerr << "error: graph format is not serializable!" << endl;
//        return 1;
//    }
//    to_serialize->serialize(std::cout);

    return 0;
}

// Register subcommand
static Subcommand vg_circularize("circularize", "circularize a path within a graph", main_circularize);

<commit_msg>restore previous circularize behavior<commit_after>/** \file circularize_main.cpp
 *
 * Defines the "vg circularize" subcommand
 */

#include <omp.h>
#include <unistd.h>
#include <getopt.h>

#include <iostream>

#include "subcommand.hpp"

#include "../utility.hpp"
#include "../handle.hpp"
#include "../vg.hpp"
#include <vg/io/stream.hpp>
#include <vg/io/vpkg.hpp>

using namespace std;
using namespace vg;
using namespace vg::subcommand;

void help_circularize(char** argv){
    cerr << "usage: " << argv[0] << " circularize [options] <graph.vg> > [circularized.vg]" << endl
        << "Makes specific paths or nodes in a graph circular." << endl
        << endl
        << "options:" << endl
        << "    -p  --path  <PATHNAME>  circularize the path by connecting its head/tail node." << endl
        << "    -P, --pathfile <PATHSFILE> circularize all paths in the provided file." << endl
        << "    -a, --head  <node_id>   circularize a head and tail node (must provide a tail)." << endl
        << "    -z, --tail  <tail_id>   circularize a head and tail node (must provide a head)." << endl
        << "    -d  --describe          list all the paths in the graph."   << endl
        << endl;
    exit(1);
}

int main_circularize(int argc, char** argv){
    if (argc == 2){
        help_circularize(argv);
        exit(1);
    }

    string path = "";
    string pathfile = "";
    bool describe = false;
    vg::id_t head = -1;
    vg::id_t tail = -1;

    int c;
    optind = 2;
    while (true){
        static struct option long_options[] =
        {
            {"path", required_argument, 0, 'p'},
            {"pathfile", required_argument, 0, 'P'},
            {"head", required_argument, 0, 'a'},
            {"tail", required_argument, 0, 'z'},
            {"describe", required_argument, 0, 'd'},
            {0,0,0,0}
        };

    int option_index = 0;
    c = getopt_long (argc, argv, "hdp:P:a:z:",
            long_options, &option_index);
    if (c == -1){
        break;
    }

        switch(c){
            case 'a':
                head = parse<int>(optarg);
                break;
            case 'z':
                tail = parse<int>(optarg);
                break;
            case 'p':
                path = optarg;
                break;
            case 'P':
                pathfile = optarg;
                break;
            case 'd':
                describe = true;
                break;
            case 'h':
            case '?':
                help_circularize(argv);
                exit(1);
                break;

            default:
                abort();
        }
    }

    vector<string> paths_to_circularize;
    if (!((head * tail) > 0)){
        cerr << "Both a head and tail node must be provided" << endl;
        help_circularize(argv);
        exit(1);
    }
    if  (pathfile != ""){
        string line;
        ifstream pfi;
        pfi.open(pathfile);
        if (!pfi.good()){
            cerr << "There is an error with the input file." << endl;
            help_circularize(argv);
        }
        while (getline(pfi, line)){
            paths_to_circularize.push_back(line);
        }
        pfi.close();

    }
    else if (path != ""){
        paths_to_circularize.push_back(path);
    }

    // TODO: if we settle on a uniform serialzation method that covers the VG class, the code is ready to be switched
    VG* graph;
    get_input_file(optind, argc, argv, [&](istream& in) {
        graph = new VG(in);
    });

    // Check if paths are in graph:
    for (const string& p : paths_to_circularize){
        if (!graph->has_path(p)){
            cerr << "ERROR: PATH NOT IN GRAPH - " << p << endl;
            exit(1);
        }
    }

    if (describe){
        graph->for_each_path_handle([&](const path_handle_t& path_handle) {
            cout << graph->get_path_name(path_handle) << endl;
        });
       exit(0);
    }

    if (head > 0 && tail > head){
        graph->create_edge(graph->get_handle(tail), graph->get_handle(head));
    }
    else{
        for (const auto& path_name : paths_to_circularize) {
            path_handle_t path = graph->get_path_handle(path_name);
            if (graph->get_step_count(path) > 0) {
                graph->create_edge(graph->get_handle_of_step(graph->path_back(path)),
                                   graph->get_handle_of_step(graph->path_begin(path)));
            }
            graph->set_circularity(path, true);
        }
    }

    graph->serialize_to_ostream(cout);
//    SerializableHandleGraph* to_serialize = dynamic_cast<SerializableHandleGraph*>(&(*graph));
//    if (!to_serialize) {
//        cerr << "error: graph format is not serializable!" << endl;
//        return 1;
//    }
//    to_serialize->serialize(std::cout);

    return 0;
}

// Register subcommand
static Subcommand vg_circularize("circularize", "circularize a path within a graph", main_circularize);

<|endoftext|>


<commit_before>#include "MainDialog.h"

#include "../common/bouncing.h"
#include "../common/paths.h"
#include "../common/timing.h"

#include <agge/blenders_simd.h>
#include <agge/clipper.h>
#include <agge/dash.h>
#include <agge/math.h>
#include <agge/rasterizer.h>
#include <agge/renderer_parallel.h>
#include <agge/stroke.h>
#include <agge/stroke_features.h>

#include <aggx/blenders.h>

#include <aggx/aggx_ellipse.h>

#include <agg_conv_stroke.h>
#include <agg_rasterizer_sl_clip.h>
#include <agg_ellipse.h>
#include <agg_pixfmt_rgba.h>
#include <agg_renderer_base.h>
#include <agg_scanline_u.h>
#include <agg_rasterizer_scanline_aa.h>
#include <agg_renderer_scanline.h>

using namespace std;
using namespace demo;

const int c_thread_count = 1;
const bool c_use_original_agg = false;
const int c_balls_number = 0;
typedef agge::simd::blender_solid_color blender_used;

namespace
{
	class unlimited_miter : public agge::stroke::join
	{
	public:
		virtual void calc(agge::points &output, agge::real_t w, const agge::point_r &v0, agge::real_t d01,
			const agge::point_r &v1, agge::real_t d12, const agge::point_r &v2) const
		{
			using namespace agge;

			d01 = w / d01;
			d12 = w / d12;

			const real_t dx1 = d01 * (v1.y - v0.y);
			const real_t dy1 = d01 * (v1.x - v0.x);
			const real_t dx2 = d12 * (v2.y - v1.y);
			const real_t dy2 = d12 * (v2.x - v1.x);

			real_t xi, yi;

			if (calc_intersection(v0.x + dx1, v0.y - dy1, v1.x + dx1, v1.y - dy1,
				v1.x + dx2, v1.y - dy2, v2.x + dx2, v2.y - dy2, &xi, &yi))
			{
				output.push_back(create_point(xi, yi));
			}
		}

	private:
		AGGE_INLINE static bool calc_intersection(agge::real_t ax, agge::real_t ay, agge::real_t bx, agge::real_t by,
			agge::real_t cx, agge::real_t cy, agge::real_t dx, agge::real_t dy, agge::real_t *x, agge::real_t *y)
		{
			using namespace agge;

			real_t num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
			real_t den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
			if (fabs(den) < distance_epsilon)
				return false;
			real_t r = num / den;
			*x = ax + r * (bx-ax);
			*y = ay + r * (by-ay);
			return true;
		}
	};

	agge::simd::blender_solid_color::pixel make_pixel(aggx::rgba8 color)
	{
		agge::simd::blender_solid_color::pixel p = { color.b, color.g, color.r, 0 };
		return p;
	}

	template <typename BlenderT>
	class blender : public BlenderT
	{
	public:
		blender(aggx::rgba8 color)
			: BlenderT(make_pixel(color), color.a)
		{	}
	};

	template <int precision>
	struct calculate_alpha
	{
		unsigned int operator ()(int area) const
		{
			area >>= precision + 1;
			if (area < 0)
				area = -area;
			if (area > 255)
				area = 255;
			return area;
		}
	};

	template <typename LinesSinkT, typename PathT>
	void add_path(LinesSinkT &sink, PathT &path)
	{
		using namespace agge;

		real_t x, y;

		path.rewind(0);
		for (int command; command = path.vertex(&x, &y), path_command_stop != command; )
		{
			if (path_command_line_to == (command & path_command_mask))
				sink.line_to(x, y);
			else if (path_command_move_to == (command & path_command_mask))
				sink.move_to(x, y);
			if (command & path_flag_close)
				sink.close_polygon();
		}
	}

	class bitmap_rendering_buffer
	{
	public:
		typedef unsigned int pixel_type;
		typedef agg::const_row_info<pixel_type> row_data;

	public:
		bitmap_rendering_buffer(::bitmap &target)
			: _target(target)
		{	}

		pixel_type *row_ptr(int, int y, int)
		{	return reinterpret_cast<pixel_type *>(_target.row_ptr(y));	}

		unsigned int width() const
		{	return _target.width();	}

		unsigned int height() const
		{	return _target.height();	}

	private:
		::bitmap &_target;
	};

	class agg_drawer : public Drawer
	{
	public:
		typedef blender<blender_used> solid_color_brush;
		typedef agg::pixfmt_alpha_blend_rgba<agg::blender_bgra32, bitmap_rendering_buffer> pixfmt;
		typedef agg::rgba8 color_type;
		typedef agg::order_bgra component_order;
		typedef agg::renderer_base<pixfmt> renderer_base;
		typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;

	public:
		agg_drawer()
			: _balls(c_balls)
		{ _balls.resize(c_balls_number);	}

	private:
		virtual void draw(::bitmap &surface, Timings &timings)
		{
			LARGE_INTEGER counter;
			const float dt = 0.3f * (float)stopwatch(_balls_timer);

			stopwatch(counter);
				agge::fill(surface, solid_color_brush(aggx::rgba8(255, 255, 255)));
			timings.clearing += stopwatch(counter);

			stopwatch(counter);
				agg_path_adaptor p(_spiral);

				if (!_stroke.get())
					_stroke.reset(new agg::conv_stroke<agg_path_adaptor>(p));
				else
					_stroke->attach(p);

				_stroke->width(3);
				_stroke->line_join(agg::bevel_join);
				_spiral_flattened.clear();
				flatten<double>(_spiral_flattened, *_stroke);
			timings.stroking += stopwatch(counter);

			bitmap_rendering_buffer rbuf(surface);
			pixfmt pixf(rbuf);
			renderer_base rb(pixf);
			renderer_aa ren_aa(rb);

			if (_balls.empty())
			{
				stopwatch(counter);
				_rasterizer.add_path(agg_path_adaptor(_spiral_flattened));
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				ren_aa.color(agg::rgba8(0, 154, 255, 255));
				agg::render_scanlines(_rasterizer, _scanline, ren_aa);
				timings.rendition += stopwatch(counter);
			}

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				demo::move_and_bounce(b, dt, surface.width(), surface.height());
			});

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				agg::ellipse e(b.x, b.y, b.radius, b.radius);

				_rasterizer.reset();

				stopwatch(counter);
				_rasterizer.add_path(e);
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				ren_aa.color(agg::rgba8(b.color.r, b.color.g, b.color.b, b.color.a));
				agg::render_scanlines(_rasterizer, _scanline, ren_aa);
				timings.rendition += stopwatch(counter);
			});
		}

		virtual void resize(int width, int height)
		{
			_spiral.clear();
			spiral(_spiral, width / 2, height / 2, 5, (std::min)(width, height) / 2 - 10, 1, 0);
		}

	private:
		agg::rasterizer_scanline_aa<agg::rasterizer_sl_no_clip> _rasterizer;
		agg::scanline_u8 _scanline;
		AggPath _spiral, _spiral_flattened;
		LARGE_INTEGER _balls_timer;
		vector<demo::ball> _balls;
		auto_ptr< agg::conv_stroke<agg_path_adaptor> > _stroke;
	};

	class agge_drawer : public Drawer
	{
	public:
		typedef blender<blender_used> solid_color_brush;

	public:
		agge_drawer()
			: _renderer(c_thread_count), _balls(c_balls)
		{
			_balls.resize(c_balls_number);
			_dash.add_dash(15.0f, 4.0f);
		}

	private:
		virtual void draw(::bitmap &surface, Timings &timings)
		{
			LARGE_INTEGER counter;
			const float dt = 0.3f * (float)stopwatch(_balls_timer);

			_rasterizer.reset();

			stopwatch(counter);
				agge::fill(surface, solid_color_brush(aggx::rgba8(255, 255, 255)));
			timings.clearing += stopwatch(counter);

			if (_balls.empty())
			{
				stopwatch(counter);
					agg_path_adaptor p(_spiral);
					agge::path_generator_adapter<agg_path_adaptor, agge::stroke> path_stroke1(p, _stroke1);
					agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::stroke>, agge::stroke> path_stroke2(path_stroke1, _stroke2);

					agge::path_generator_adapter<agg_path_adaptor, agge::dash> path_stroke3(p, _dash);
					agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::dash>, agge::stroke> path_stroke4(path_stroke3, _stroke1);
					agge::path_generator_adapter<agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::dash>, agge::stroke>, agge::stroke> path_stroke5(path_stroke4, _stroke2);

					_stroke1.width(3.0f);
					_stroke1.set_cap(agge::caps::butt());
					_stroke1.set_join(unlimited_miter());

					_stroke2.width(1.2f);
					_stroke2.set_cap(agge::caps::butt());
					_stroke2.set_join(unlimited_miter());

					_spiral_flattened.clear();
					flatten<agge::real_t>(_spiral_flattened, path_stroke5);
				timings.stroking += stopwatch(counter);

				solid_color_brush brush(aggx::rgba8(0, 154, 255, 230));

				stopwatch(counter);
				add_path(_rasterizer, agg_path_adaptor(_spiral_flattened));
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				_renderer(surface, 0, _rasterizer, brush, calculate_alpha<agge::vector_rasterizer::_1_shift>());
				timings.rendition += stopwatch(counter);
			}

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				demo::move_and_bounce(b, dt, surface.width(), surface.height());
			});

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				aggx::ellipse e(b.x, b.y, b.radius, b.radius);

				_rasterizer.reset();

				stopwatch(counter);
				add_path(_rasterizer, e);
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				_renderer(surface, 0, _rasterizer, agge_drawer::solid_color_brush(b.color), calculate_alpha<agge::vector_rasterizer::_1_shift>());
				timings.rendition += stopwatch(counter);
			});
		}

		virtual void resize(int width, int height)
		{
			_spiral.clear();
			spiral(_spiral, width / 2, height / 2, 5, (std::min)(width, height) / 2 - 10, 1, 0);
		}

	private:
		agge::rasterizer< agge::clipper<int> > _rasterizer;
		__declspec(align(16)) agge::renderer_parallel _renderer;
		AggPath _spiral, _spiral_flattened;
		LARGE_INTEGER _balls_timer;
		vector<demo::ball> _balls;
		agge::stroke _stroke1, _stroke2;
		agge::dash _dash;
	};
}

int main()
{
	delete new int;

	agg_drawer d1;
	agge_drawer d2;

	MainDialog dlg(c_use_original_agg ? (Drawer &)d1 : (Drawer &)d2);

	MainDialog::PumpMessages();
}
<commit_msg>Sandbox app is now DPI-aware<commit_after>#include "MainDialog.h"

#include "../common/bouncing.h"
#include "../common/paths.h"
#include "../common/timing.h"

#include <agge/blenders_simd.h>
#include <agge/clipper.h>
#include <agge/dash.h>
#include <agge/math.h>
#include <agge/rasterizer.h>
#include <agge/renderer_parallel.h>
#include <agge/stroke.h>
#include <agge/stroke_features.h>

#include <aggx/blenders.h>

#include <aggx/aggx_ellipse.h>

#include <agg_conv_stroke.h>
#include <agg_rasterizer_sl_clip.h>
#include <agg_ellipse.h>
#include <agg_pixfmt_rgba.h>
#include <agg_renderer_base.h>
#include <agg_scanline_u.h>
#include <agg_rasterizer_scanline_aa.h>
#include <agg_renderer_scanline.h>

using namespace std;
using namespace demo;

const int c_thread_count = 1;
const bool c_use_original_agg = false;
const int c_balls_number = 0;
typedef agge::simd::blender_solid_color blender_used;

namespace
{
	class unlimited_miter : public agge::stroke::join
	{
	public:
		virtual void calc(agge::points &output, agge::real_t w, const agge::point_r &v0, agge::real_t d01,
			const agge::point_r &v1, agge::real_t d12, const agge::point_r &v2) const
		{
			using namespace agge;

			d01 = w / d01;
			d12 = w / d12;

			const real_t dx1 = d01 * (v1.y - v0.y);
			const real_t dy1 = d01 * (v1.x - v0.x);
			const real_t dx2 = d12 * (v2.y - v1.y);
			const real_t dy2 = d12 * (v2.x - v1.x);

			real_t xi, yi;

			if (calc_intersection(v0.x + dx1, v0.y - dy1, v1.x + dx1, v1.y - dy1,
				v1.x + dx2, v1.y - dy2, v2.x + dx2, v2.y - dy2, &xi, &yi))
			{
				output.push_back(create_point(xi, yi));
			}
		}

	private:
		AGGE_INLINE static bool calc_intersection(agge::real_t ax, agge::real_t ay, agge::real_t bx, agge::real_t by,
			agge::real_t cx, agge::real_t cy, agge::real_t dx, agge::real_t dy, agge::real_t *x, agge::real_t *y)
		{
			using namespace agge;

			real_t num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
			real_t den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
			if (fabs(den) < distance_epsilon)
				return false;
			real_t r = num / den;
			*x = ax + r * (bx-ax);
			*y = ay + r * (by-ay);
			return true;
		}
	};

	agge::simd::blender_solid_color::pixel make_pixel(aggx::rgba8 color)
	{
		agge::simd::blender_solid_color::pixel p = { color.b, color.g, color.r, 0 };
		return p;
	}

	template <typename BlenderT>
	class blender : public BlenderT
	{
	public:
		blender(aggx::rgba8 color)
			: BlenderT(make_pixel(color), color.a)
		{	}
	};

	template <int precision>
	struct calculate_alpha
	{
		unsigned int operator ()(int area) const
		{
			area >>= precision + 1;
			if (area < 0)
				area = -area;
			if (area > 255)
				area = 255;
			return area;
		}
	};

	template <typename LinesSinkT, typename PathT>
	void add_path(LinesSinkT &sink, PathT &path)
	{
		using namespace agge;

		real_t x, y;

		path.rewind(0);
		for (int command; command = path.vertex(&x, &y), path_command_stop != command; )
		{
			if (path_command_line_to == (command & path_command_mask))
				sink.line_to(x, y);
			else if (path_command_move_to == (command & path_command_mask))
				sink.move_to(x, y);
			if (command & path_flag_close)
				sink.close_polygon();
		}
	}

	class bitmap_rendering_buffer
	{
	public:
		typedef unsigned int pixel_type;
		typedef agg::const_row_info<pixel_type> row_data;

	public:
		bitmap_rendering_buffer(::bitmap &target)
			: _target(target)
		{	}

		pixel_type *row_ptr(int, int y, int)
		{	return reinterpret_cast<pixel_type *>(_target.row_ptr(y));	}

		unsigned int width() const
		{	return _target.width();	}

		unsigned int height() const
		{	return _target.height();	}

	private:
		::bitmap &_target;
	};

	class agg_drawer : public Drawer
	{
	public:
		typedef blender<blender_used> solid_color_brush;
		typedef agg::pixfmt_alpha_blend_rgba<agg::blender_bgra32, bitmap_rendering_buffer> pixfmt;
		typedef agg::rgba8 color_type;
		typedef agg::order_bgra component_order;
		typedef agg::renderer_base<pixfmt> renderer_base;
		typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;

	public:
		agg_drawer()
			: _balls(c_balls)
		{ _balls.resize(c_balls_number);	}

	private:
		virtual void draw(::bitmap &surface, Timings &timings)
		{
			LARGE_INTEGER counter;
			const float dt = 0.3f * (float)stopwatch(_balls_timer);

			stopwatch(counter);
				agge::fill(surface, solid_color_brush(aggx::rgba8(255, 255, 255)));
			timings.clearing += stopwatch(counter);

			stopwatch(counter);
				agg_path_adaptor p(_spiral);

				if (!_stroke.get())
					_stroke.reset(new agg::conv_stroke<agg_path_adaptor>(p));
				else
					_stroke->attach(p);

				_stroke->width(3);
				_stroke->line_join(agg::bevel_join);
				_spiral_flattened.clear();
				flatten<double>(_spiral_flattened, *_stroke);
			timings.stroking += stopwatch(counter);

			bitmap_rendering_buffer rbuf(surface);
			pixfmt pixf(rbuf);
			renderer_base rb(pixf);
			renderer_aa ren_aa(rb);

			if (_balls.empty())
			{
				stopwatch(counter);
				_rasterizer.add_path(agg_path_adaptor(_spiral_flattened));
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				ren_aa.color(agg::rgba8(0, 154, 255, 255));
				agg::render_scanlines(_rasterizer, _scanline, ren_aa);
				timings.rendition += stopwatch(counter);
			}

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				demo::move_and_bounce(b, dt, surface.width(), surface.height());
			});

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				agg::ellipse e(b.x, b.y, b.radius, b.radius);

				_rasterizer.reset();

				stopwatch(counter);
				_rasterizer.add_path(e);
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				ren_aa.color(agg::rgba8(b.color.r, b.color.g, b.color.b, b.color.a));
				agg::render_scanlines(_rasterizer, _scanline, ren_aa);
				timings.rendition += stopwatch(counter);
			});
		}

		virtual void resize(int width, int height)
		{
			_spiral.clear();
			spiral(_spiral, width / 2, height / 2, 5, (std::min)(width, height) / 2 - 10, 1, 0);
		}

	private:
		agg::rasterizer_scanline_aa<agg::rasterizer_sl_no_clip> _rasterizer;
		agg::scanline_u8 _scanline;
		AggPath _spiral, _spiral_flattened;
		LARGE_INTEGER _balls_timer;
		vector<demo::ball> _balls;
		auto_ptr< agg::conv_stroke<agg_path_adaptor> > _stroke;
	};

	class agge_drawer : public Drawer
	{
	public:
		typedef blender<blender_used> solid_color_brush;

	public:
		agge_drawer()
			: _renderer(c_thread_count), _balls(c_balls)
		{
			_balls.resize(c_balls_number);
			_dash.add_dash(15.0f, 4.0f);
		}

	private:
		virtual void draw(::bitmap &surface, Timings &timings)
		{
			LARGE_INTEGER counter;
			const float dt = 0.3f * (float)stopwatch(_balls_timer);

			_rasterizer.reset();

			stopwatch(counter);
				agge::fill(surface, solid_color_brush(aggx::rgba8(255, 255, 255)));
			timings.clearing += stopwatch(counter);

			if (_balls.empty())
			{
				stopwatch(counter);
					agg_path_adaptor p(_spiral);
					agge::path_generator_adapter<agg_path_adaptor, agge::stroke> path_stroke1(p, _stroke1);
					agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::stroke>, agge::stroke> path_stroke2(path_stroke1, _stroke2);

					agge::path_generator_adapter<agg_path_adaptor, agge::dash> path_stroke3(p, _dash);
					agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::dash>, agge::stroke> path_stroke4(path_stroke3, _stroke1);
					agge::path_generator_adapter<agge::path_generator_adapter<agge::path_generator_adapter<agg_path_adaptor, agge::dash>, agge::stroke>, agge::stroke> path_stroke5(path_stroke4, _stroke2);

					_stroke1.width(3.0f);
					_stroke1.set_cap(agge::caps::butt());
					_stroke1.set_join(unlimited_miter());

					_stroke2.width(1.2f);
					_stroke2.set_cap(agge::caps::butt());
					_stroke2.set_join(unlimited_miter());

					_spiral_flattened.clear();
					flatten<agge::real_t>(_spiral_flattened, path_stroke5);
				timings.stroking += stopwatch(counter);

				solid_color_brush brush(aggx::rgba8(0, 154, 255, 230));

				stopwatch(counter);
				add_path(_rasterizer, agg_path_adaptor(_spiral_flattened));
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				_renderer(surface, 0, _rasterizer, brush, calculate_alpha<agge::vector_rasterizer::_1_shift>());
				timings.rendition += stopwatch(counter);
			}

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				demo::move_and_bounce(b, dt, surface.width(), surface.height());
			});

			for_each(_balls.begin(), _balls.end(), [&] (ball &b) {
				aggx::ellipse e(b.x, b.y, b.radius, b.radius);

				_rasterizer.reset();

				stopwatch(counter);
				add_path(_rasterizer, e);
				_rasterizer.sort();
				timings.rasterization += stopwatch(counter);
				_renderer(surface, 0, _rasterizer, agge_drawer::solid_color_brush(b.color), calculate_alpha<agge::vector_rasterizer::_1_shift>());
				timings.rendition += stopwatch(counter);
			});
		}

		virtual void resize(int width, int height)
		{
			_spiral.clear();
			spiral(_spiral, width / 2, height / 2, 5, (std::min)(width, height) / 2 - 10, 1, 0);
		}

	private:
		agge::rasterizer< agge::clipper<int> > _rasterizer;
		__declspec(align(16)) agge::renderer_parallel _renderer;
		AggPath _spiral, _spiral_flattened;
		LARGE_INTEGER _balls_timer;
		vector<demo::ball> _balls;
		agge::stroke _stroke1, _stroke2;
		agge::dash _dash;
	};
}

int main()
{
	::SetProcessDPIAware();

	agg_drawer d1;
	agge_drawer d2;

	MainDialog dlg(c_use_original_agg ? (Drawer &)d1 : (Drawer &)d2);

	MainDialog::PumpMessages();
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_CORE_GLOBAL_FORCE_FIELD_HPP
#define MJOLNIR_CORE_GLOBAL_FORCE_FIELD_HPP
#include <mjolnir/core/GlobalInteractionBase.hpp>
#include <mjolnir/util/logger.hpp>
#include <vector>
#include <array>
#include <memory>

namespace mjolnir
{

template<typename traitsT>
class GlobalForceField
{
  public:
    using traits_type      = traitsT;
    using real_type        = typename traits_type::real_type;
    using coordinate_type  = typename traits_type::coordinate_type;
    using boundary_type    = typename traits_type::boundary_type;
    using system_type      = System<traits_type>;
    using topology_type    = Topology;
    using interaction_base = GlobalInteractionBase<traitsT>;
    using interaction_ptr  = std::unique_ptr<interaction_base>;
    using container_type   = std::vector<interaction_ptr>;
    using iterator         = typename container_type::iterator;
    using const_iterator   = typename container_type::const_iterator;

  public:
    GlobalForceField() = default;
    ~GlobalForceField() = default;
    GlobalForceField(GlobalForceField&&)            = default;
    GlobalForceField& operator=(GlobalForceField&&) = default;

    GlobalForceField(const GlobalForceField& other)
        : interactions_(other.size())
    {
        std::transform(other.begin(), other.end(), this->interactions_.begin(),
            [](const interaction_ptr& interaction) -> interaction_ptr {
                return interaction_ptr(interaction->clone());
            });
    }
    GlobalForceField& operator=(const GlobalForceField& other)
    {
        this->interactions_.clear();
        this->interactions_.reserve(other.size());
        for(const auto& interaction : other)
        {
            this->emplace(interaction_ptr(interaction->clone()));
        }
        return *this;
    }

    void emplace(interaction_ptr&& inter)
    {
        interactions_.emplace_back(std::move(inter));
        return;
    }

    void initialize(const system_type& sys, const topology_type& topol)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();
        for(auto& item : this->interactions_)
        {
            MJOLNIR_LOG_INFO("initializing ", item->name());
            item->initialize(sys, topol);
        }
        return;
    }

    // to re-calculate parameters like temperature, ionic concentration, etc...
    void update(const system_type& sys, const topology_type& topol)
    {
        for(auto& item : this->interactions_)
        {
            item->update(sys, topol);
        }
        return;
    }

    // to reduce margin of neighbor list, and re-construct the list if needed
    void reduce_margin(const real_type dmargin, const system_type& sys)
    {
        for(auto& item : this->interactions_)
        {
            item->reduce_margin(dmargin, sys);
        }
        return;
    }
    void scale_margin(const real_type scale, const system_type& sys)
    {
        for(auto& item : this->interactions_)
        {
            item->scale_margin(scale, sys);
        }
        return;
    }

    void calc_force(system_type& sys) const noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER_DEBUG();
        MJOLNIR_LOG_FUNCTION_DEBUG();

        for(const auto& item : this->interactions_)
        {
            MJOLNIR_LOG_DEBUG("interaction name is ", item->name());
            item->calc_force(sys);
        }
        return;
    }
    real_type calc_energy(const system_type& sys) const noexcept
    {
        real_type energy = 0.;
        for(const auto& item : this->interactions_)
        {
            energy += item->calc_energy(sys);
        }
        return energy;
    }
    real_type calc_force_and_energy(system_type& sys) const noexcept
    {
        // TODO speedup
        real_type energy = 0.;
        for(const auto& item : this->interactions_)
        {
            item->calc_force(sys);
            energy += item->calc_energy(sys);
        }
        return energy;
    }

    // basically, it is called only once at the begenning of a simulation.
    // this function do a lot of stuff, such as memory allocation, but it does
    // not affect runtime efficiency so much.
    std::vector<std::string> list_energy() const
    {
        std::vector<std::string> retval;
        for(const auto& i : interactions_)
        {
            retval.push_back(i->name());
        }
        return retval;
    }

    std::vector<real_type> dump_energy(const system_type& sys) const
    {
        std::vector<real_type> retval;
        for(const auto& i : interactions_)
        {
            retval.push_back(i->calc_energy(sys));
        }
        return retval;
    }

    bool           empty()  const noexcept {return interactions_.empty();}
    std::size_t    size()   const noexcept {return interactions_.size();}
    iterator       begin()        noexcept {return interactions_.begin();}
    iterator       end()          noexcept {return interactions_.end();}
    const_iterator begin()  const noexcept {return interactions_.begin();}
    const_iterator end()    const noexcept {return interactions_.end();}
    const_iterator cbegin() const noexcept {return interactions_.begin();}
    const_iterator cend()   const noexcept {return interactions_.end();}

  private:

    container_type interactions_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class GlobalForceField<SimulatorTraits<double, UnlimitedBoundary>>;
extern template class GlobalForceField<SimulatorTraits<float,  UnlimitedBoundary>>;
extern template class GlobalForceField<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class GlobalForceField<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif /* MJOLNIR_GLOBAL_FORCE_FIELD */
<commit_msg>feat: use global calc_force_and_energy<commit_after>#ifndef MJOLNIR_CORE_GLOBAL_FORCE_FIELD_HPP
#define MJOLNIR_CORE_GLOBAL_FORCE_FIELD_HPP
#include <mjolnir/core/GlobalInteractionBase.hpp>
#include <mjolnir/util/logger.hpp>
#include <vector>
#include <array>
#include <memory>

namespace mjolnir
{

template<typename traitsT>
class GlobalForceField
{
  public:
    using traits_type      = traitsT;
    using real_type        = typename traits_type::real_type;
    using coordinate_type  = typename traits_type::coordinate_type;
    using boundary_type    = typename traits_type::boundary_type;
    using system_type      = System<traits_type>;
    using topology_type    = Topology;
    using interaction_base = GlobalInteractionBase<traitsT>;
    using interaction_ptr  = std::unique_ptr<interaction_base>;
    using container_type   = std::vector<interaction_ptr>;
    using iterator         = typename container_type::iterator;
    using const_iterator   = typename container_type::const_iterator;

  public:
    GlobalForceField() = default;
    ~GlobalForceField() = default;
    GlobalForceField(GlobalForceField&&)            = default;
    GlobalForceField& operator=(GlobalForceField&&) = default;

    GlobalForceField(const GlobalForceField& other)
        : interactions_(other.size())
    {
        std::transform(other.begin(), other.end(), this->interactions_.begin(),
            [](const interaction_ptr& interaction) -> interaction_ptr {
                return interaction_ptr(interaction->clone());
            });
    }
    GlobalForceField& operator=(const GlobalForceField& other)
    {
        this->interactions_.clear();
        this->interactions_.reserve(other.size());
        for(const auto& interaction : other)
        {
            this->emplace(interaction_ptr(interaction->clone()));
        }
        return *this;
    }

    void emplace(interaction_ptr&& inter)
    {
        interactions_.emplace_back(std::move(inter));
        return;
    }

    void initialize(const system_type& sys, const topology_type& topol)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();
        for(auto& item : this->interactions_)
        {
            MJOLNIR_LOG_INFO("initializing ", item->name());
            item->initialize(sys, topol);
        }
        return;
    }

    // to re-calculate parameters like temperature, ionic concentration, etc...
    void update(const system_type& sys, const topology_type& topol)
    {
        for(auto& item : this->interactions_)
        {
            item->update(sys, topol);
        }
        return;
    }

    // to reduce margin of neighbor list, and re-construct the list if needed
    void reduce_margin(const real_type dmargin, const system_type& sys)
    {
        for(auto& item : this->interactions_)
        {
            item->reduce_margin(dmargin, sys);
        }
        return;
    }
    void scale_margin(const real_type scale, const system_type& sys)
    {
        for(auto& item : this->interactions_)
        {
            item->scale_margin(scale, sys);
        }
        return;
    }

    void calc_force(system_type& sys) const noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER_DEBUG();
        MJOLNIR_LOG_FUNCTION_DEBUG();

        for(const auto& item : this->interactions_)
        {
            MJOLNIR_LOG_DEBUG("interaction name is ", item->name());
            item->calc_force(sys);
        }
        return;
    }
    real_type calc_energy(const system_type& sys) const noexcept
    {
        real_type energy = 0.;
        for(const auto& item : this->interactions_)
        {
            energy += item->calc_energy(sys);
        }
        return energy;
    }
    real_type calc_force_and_energy(system_type& sys) const noexcept
    {
        real_type energy = 0.;
        for(const auto& item : this->interactions_)
        {
            energy += item->calc_force_and_energy(sys);
        }
        return energy;
    }

    // basically, it is called only once at the begenning of a simulation.
    // this function do a lot of stuff, such as memory allocation, but it does
    // not affect runtime efficiency so much.
    std::vector<std::string> list_energy() const
    {
        std::vector<std::string> retval;
        for(const auto& i : interactions_)
        {
            retval.push_back(i->name());
        }
        return retval;
    }

    std::vector<real_type> dump_energy(const system_type& sys) const
    {
        std::vector<real_type> retval;
        for(const auto& i : interactions_)
        {
            retval.push_back(i->calc_energy(sys));
        }
        return retval;
    }

    bool           empty()  const noexcept {return interactions_.empty();}
    std::size_t    size()   const noexcept {return interactions_.size();}
    iterator       begin()        noexcept {return interactions_.begin();}
    iterator       end()          noexcept {return interactions_.end();}
    const_iterator begin()  const noexcept {return interactions_.begin();}
    const_iterator end()    const noexcept {return interactions_.end();}
    const_iterator cbegin() const noexcept {return interactions_.begin();}
    const_iterator cend()   const noexcept {return interactions_.end();}

  private:

    container_type interactions_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class GlobalForceField<SimulatorTraits<double, UnlimitedBoundary>>;
extern template class GlobalForceField<SimulatorTraits<float,  UnlimitedBoundary>>;
extern template class GlobalForceField<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class GlobalForceField<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif /* MJOLNIR_GLOBAL_FORCE_FIELD */
<|endoftext|>