<commit_before>#include <vector>
#include <cassert>

#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>

#include <boost/python.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/numeric.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/stl_iterator.hpp>

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy_boost_python.hpp"

extern "C" {
#include <metis.h>
}

//---------------------------------------------------------------------------
void pointwise_graph(
        int n, int block_size,
        const numpy_boost<int, 1> &ptr,
        const numpy_boost<int, 1> &col,
        std::vector<int> &pptr,
        std::vector<int> &pcol
        )
{
    int np = n / block_size;

    assert(np * block_size == n);

    // Create pointwise matrix
    std::vector<int> ptr1(np + 1, 0);
    std::vector<int> marker(np, -1);
    for(int ip = 0, i = 0; ip < np; ++ip) {
        for(int k = 0; k < block_size; ++k, ++i) {
            for(int j = ptr[i]; j < ptr[i+1]; ++j) {
                int cp = col[j] / block_size;
                if (marker[cp] != ip) {
                    marker[cp] = ip;
                    ++ptr1[ip+1];
                }
            }
        }
    }

    boost::partial_sum(ptr1, ptr1.begin());
    boost::fill(marker, -1);

    std::vector<int> col1(ptr1.back());

    for(int ip = 0, i = 0; ip < np; ++ip) {
        int row_beg = ptr1[ip];
        int row_end = row_beg;

        for(int k = 0; k < block_size; ++k, ++i) {
            for(int j = ptr[i]; j < ptr[i+1]; ++j) {
                int cp = col[j] / block_size;

                if (marker[cp] < row_beg) {
                    marker[cp] = row_end;
                    col1[row_end++] = cp;
                }
            }
        }
    }

    // Transpose pointwise matrix
    int nnz = ptr1.back();

    std::vector<int> ptr2(np + 1, 0);
    std::vector<int> col2(nnz);

    for(int i = 0; i < nnz; ++i)
        ++( ptr2[ col1[i] + 1 ] );

    boost::partial_sum(ptr2, ptr2.begin());

    for(int i = 0; i < np; ++i)
        for(int j = ptr1[i]; j < ptr1[i+1]; ++j)
            col2[ptr2[col1[j]]++] = i;

    std::rotate(ptr2.begin(), ptr2.end() - 1, ptr2.end());
    ptr2.front() = 0;

    // Merge both matrices.
    boost::fill(marker, -1);
    pptr.resize(np + 1, 0);

    for(int i = 0; i < np; ++i) {
        for(int j = ptr1[i]; j < ptr1[i+1]; ++j) {
            int c = col1[j];
            if (marker[c] != i) {
                marker[c] = i;
                ++pptr[i + 1];
            }
        }

        for(int j = ptr2[i]; j < ptr2[i+1]; ++j) {
            int c = col2[j];
            if (marker[c] != i) {
                marker[c] = i;
                ++pptr[i + 1];
            }
        }
    }

    boost::partial_sum(pptr, pptr.begin());
    boost::fill(marker, -1);

    pcol.resize(pptr.back());

    for(int i = 0; i < np; ++i) {
        int row_beg = pptr[i];
        int row_end = row_beg;

        for(int j = ptr1[i]; j < ptr1[i+1]; ++j) {
            int c = col1[j];

            if (marker[c] < row_beg) {
                marker[c] = row_end;
                pcol[row_end++] = c;
            }
        }

        for(int j = ptr2[i]; j < ptr2[i+1]; ++j) {
            int c = col2[j];

            if (marker[c] < row_beg) {
                marker[c] = row_end;
                pcol[row_end++] = c;
            }
        }
    }
}

//---------------------------------------------------------------------------
std::vector<int> pointwise_partition(
        int npart,
        const std::vector<int> &ptr,
        const std::vector<int> &col
        )
{
    int nrows = ptr.size() - 1;

    std::vector<int> part(nrows);

    if (npart == 1) {
        boost::fill(part, 0);
    } else {
        int wgtflag = 0;
        int numflag = 0;
        int options = 0;
        int edgecut;

        METIS_PartGraphKway(
                &nrows,
                const_cast<int*>(ptr.data()),
                const_cast<int*>(col.data()),
                NULL,
                NULL,
                &wgtflag,
                &numflag,
                &npart,
                &options,
                &edgecut,
                part.data()
                );
    }

    return part;
}

//---------------------------------------------------------------------------
PyObject* partition(
        int nparts, int block_size,
        const numpy_boost<int, 1> &ptr,
        const numpy_boost<int, 1> &col
        )
{
    int n = ptr.size() - 1;

    // Pointwise graph
    std::vector<int> pptr, pcol;
    pointwise_graph(n, block_size, ptr, col, pptr, pcol);

    // Pointwise partition
    std::vector<int> ppart = pointwise_partition(nparts, pptr, pcol);

    numpy_boost<int, 1> part(&n);
    for(int i = 0; i < n; ++i)
        part[i] = ppart[i / block_size];

    PyObject *result = part.py_ptr();
    Py_INCREF(result);
    return result;
}

//---------------------------------------------------------------------------
BOOST_PYTHON_MODULE(pymetis)
{
    using namespace boost::python;

    import_array();
    numpy_boost_python_register_type<int,    1>();
    numpy_boost_python_register_type<double, 1>();

    def("partition", partition);
}
<commit_msg>if USE_METIS_5 is defined, METIS v5 api is used<commit_after>#include <vector>
#include <cassert>

#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>

#include <boost/python.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/numeric.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/stl_iterator.hpp>

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy_boost_python.hpp"

extern "C" {
#include <metis.h>
}

//---------------------------------------------------------------------------
void pointwise_graph(
        int n, int block_size,
        const numpy_boost<int, 1> &ptr,
        const numpy_boost<int, 1> &col,
        std::vector<int> &pptr,
        std::vector<int> &pcol
        )
{
    int np = n / block_size;

    assert(np * block_size == n);

    // Create pointwise matrix
    std::vector<int> ptr1(np + 1, 0);
    std::vector<int> marker(np, -1);
    for(int ip = 0, i = 0; ip < np; ++ip) {
        for(int k = 0; k < block_size; ++k, ++i) {
            for(int j = ptr[i]; j < ptr[i+1]; ++j) {
                int cp = col[j] / block_size;
                if (marker[cp] != ip) {
                    marker[cp] = ip;
                    ++ptr1[ip+1];
                }
            }
        }
    }

    boost::partial_sum(ptr1, ptr1.begin());
    boost::fill(marker, -1);

    std::vector<int> col1(ptr1.back());

    for(int ip = 0, i = 0; ip < np; ++ip) {
        int row_beg = ptr1[ip];
        int row_end = row_beg;

        for(int k = 0; k < block_size; ++k, ++i) {
            for(int j = ptr[i]; j < ptr[i+1]; ++j) {
                int cp = col[j] / block_size;

                if (marker[cp] < row_beg) {
                    marker[cp] = row_end;
                    col1[row_end++] = cp;
                }
            }
        }
    }

    // Transpose pointwise matrix
    int nnz = ptr1.back();

    std::vector<int> ptr2(np + 1, 0);
    std::vector<int> col2(nnz);

    for(int i = 0; i < nnz; ++i)
        ++( ptr2[ col1[i] + 1 ] );

    boost::partial_sum(ptr2, ptr2.begin());

    for(int i = 0; i < np; ++i)
        for(int j = ptr1[i]; j < ptr1[i+1]; ++j)
            col2[ptr2[col1[j]]++] = i;

    std::rotate(ptr2.begin(), ptr2.end() - 1, ptr2.end());
    ptr2.front() = 0;

    // Merge both matrices.
    boost::fill(marker, -1);
    pptr.resize(np + 1, 0);

    for(int i = 0; i < np; ++i) {
        for(int j = ptr1[i]; j < ptr1[i+1]; ++j) {
            int c = col1[j];
            if (marker[c] != i) {
                marker[c] = i;
                ++pptr[i + 1];
            }
        }

        for(int j = ptr2[i]; j < ptr2[i+1]; ++j) {
            int c = col2[j];
            if (marker[c] != i) {
                marker[c] = i;
                ++pptr[i + 1];
            }
        }
    }

    boost::partial_sum(pptr, pptr.begin());
    boost::fill(marker, -1);

    pcol.resize(pptr.back());

    for(int i = 0; i < np; ++i) {
        int row_beg = pptr[i];
        int row_end = row_beg;

        for(int j = ptr1[i]; j < ptr1[i+1]; ++j) {
            int c = col1[j];

            if (marker[c] < row_beg) {
                marker[c] = row_end;
                pcol[row_end++] = c;
            }
        }

        for(int j = ptr2[i]; j < ptr2[i+1]; ++j) {
            int c = col2[j];

            if (marker[c] < row_beg) {
                marker[c] = row_end;
                pcol[row_end++] = c;
            }
        }
    }
}

//---------------------------------------------------------------------------
std::vector<int> pointwise_partition(
        int npart,
        const std::vector<int> &ptr,
        const std::vector<int> &col
        )
{
    int nrows = ptr.size() - 1;

    std::vector<int> part(nrows);

    if (npart == 1) {
        boost::fill(part, 0);
    } else {
        int wgtflag = 0;
        int numflag = 0;
        int options = 0;
        int edgecut;

#ifdef USE_METIS_5
        int nconstraints = 1;
        METIS_PartGraphKway(
                &nrows, //nvtxs
                &nconstraints, //ncon -- new
                const_cast<int*>(ptr.data()), //xadj
                const_cast<int*>(col.data()), //adjncy
                NULL, //vwgt
                NULL, //vsize -- new
                NULL, //adjwgt
                &npart,
                NULL,//real t *tpwgts,
                NULL,// real t ubvec
                NULL,
                &edgecut,
                part.data()
                );
#else
        METIS_PartGraphKway(
                &nrows,
                const_cast<int*>(ptr.data()),
                const_cast<int*>(col.data()),
                NULL,
                NULL,
                &wgtflag,
                &numflag,
                &npart,
                &options,
                &edgecut,
                part.data()
                );
#endif
    }

    return part;
}

//---------------------------------------------------------------------------
PyObject* partition(
        int nparts, int block_size,
        const numpy_boost<int, 1> &ptr,
        const numpy_boost<int, 1> &col
        )
{
    int n = ptr.size() - 1;

    // Pointwise graph
    std::vector<int> pptr, pcol;
    pointwise_graph(n, block_size, ptr, col, pptr, pcol);

    // Pointwise partition
    std::vector<int> ppart = pointwise_partition(nparts, pptr, pcol);

    numpy_boost<int, 1> part(&n);
    for(int i = 0; i < n; ++i)
        part[i] = ppart[i / block_size];

    PyObject *result = part.py_ptr();
    Py_INCREF(result);
    return result;
}

//---------------------------------------------------------------------------
BOOST_PYTHON_MODULE(pymetis)
{
    using namespace boost::python;

    import_array();
    numpy_boost_python_register_type<int,    1>();
    numpy_boost_python_register_type<double, 1>();

    def("partition", partition);
}
<|endoftext|>


<commit_before>#include "zdvidtile.h"

#include <QTransform>
#include <QtConcurrentRun>
#include <QElapsedTimer>

#include "widgets/zimagewidget.h"
#include "neutubeconfig.h"
#include "zstack.hxx"
#include "zstackfactory.h"
#include "zdvidreader.h"
#include "zimage.h"
#include "zpainter.h"
#include "zdvidbufferreader.h"
#include "zdvidurl.h"
#include "zdvidtileinfo.h"
#include "zdvidreader.h"
#include "zstackview.h"
#include "zrect2d.h"
#include "libdvidheader.h"

ZDvidTile::ZDvidTile() : m_ix(0), m_iy(0), m_z(0),
  m_view(NULL)
{
  setTarget(ZStackObject::TARGET_OBJECT_CANVAS);
  m_type = ZStackObject::TYPE_DVID_TILE;
  m_image = NULL;
}

ZDvidTile::~ZDvidTile()
{
  clear();
}

ZSTACKOBJECT_DEFINE_CLASS_NAME(ZDvidTile)

void ZDvidTile::clear()
{
  m_dvidTarget.clear();
  delete m_image;
  m_image = NULL;
}

void ZDvidTile::loadDvidSlice(const uchar *buf, int length, int z)
{
  bool loading = true;
  if (m_view != NULL) {
    if (m_view->getZ(NeuTube::COORD_STACK) != z) {
      loading = false;
    }
  }

  bool modified = false;
  if (loading) {
    if (m_image == NULL) {
      m_image = new ZImage;
    }

    m_image->loadFromData(buf, length);
    m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
    m_image->setOffset(-getX(), -getY());

    modified = true;

    m_image->enhanceContrast(
          hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));

#ifdef _DEBUG_2
    std::cout << "Format: " << m_image->format() << std::endl;
    setVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
#endif
    m_z = z;
  }

  if (modified) {
    updatePixmap();
  }
}

void ZDvidTile::updatePixmap()
{
  m_pixmap.cleanUp();
  m_pixmap.convertFromImage(*m_image);
  m_pixmap.setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
  m_pixmap.setOffset(-getX(), -getY());
}

void ZDvidTile::enhanceContrast(bool high)
{
  if (high != hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST)) {
    if (high) {
      addVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
    } else {
      removeVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
    }
    m_image->enhanceContrast(
          hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));
    updatePixmap();
  }
}
/*
void ZDvidTile::setImageData(const uint8_t *data, int width, int height)
{
  if (width <= 0 || height <= 0) {
    return;
  }

  if (m_image != NULL) {
    if (m_image->width() != width || m_image->height() != height) {
      delete m_image;
      m_image = NULL;
    }
  }

  if (m_image == NULL) {
    m_image = new ZImage(width, height);
  }

  m_image->setData(data);
  m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
  m_image->setOffset(-getX(), -getY());
}
*/
void ZDvidTile::loadDvidSlice(const QByteArray &buffer, int z)
{
  loadDvidSlice((const uchar *) buffer.data(), buffer.length(), z);
#if 0
  bool loading = true;
  if (m_view != NULL) {
    if (m_view->getZ(NeuTube::COORD_STACK) != z) {
      loading = false;
    }
  }
  if (loading) {
#ifdef _DEBUG_2
      std::cout << z << " Loaded." << std::endl;
#endif

    m_image.loadFromData(buffer);
//    m_image.enhanceContrast();

//    m_image.setOffset();
    m_z = z;
  }
#endif

//  m_image.save((GET_TEST_DATA_DIR + "/test.tif").c_str());
}

void ZDvidTile::display(
    ZPainter &painter, int slice, EDisplayStyle /*option*/) const
{
  bool isProj = false;
  int z = painter.getZOffset() + slice;
  if (slice < 0) {
    isProj = true;
    z = painter.getZOffset() - slice - 1;
  }
  //if (!m_image.isNull()) {
//  bool isProj = (slice < 0);

//  int z = painter.getZOffset() + slice;
  m_latestZ = z;

//  tic();
  const_cast<ZDvidTile&>(*this).update(z);
//  std::cout << "tile update time: " << toc() << std::endl;

  if ((z == m_z)  && (m_image != NULL)) {
#ifdef _DEBUG_2
    std::cout << "Display " << z << std::endl;
#endif
    //      ZImage image = getImage();
    //int dx = getX() - painter.getOffset().x();
    //int dy = getY() - painter.getOffset().y();

    //      QRect sourceRect = QRect(0, 0, m_image.width(), m_image.height());
    //      QRect targetRect = QRect(getX(), getY(), m_image.width() * m_res.getScale(),
    //                         m_image.height() * m_res.getScale());
#if 0
    if (m_res.getScale() == 1) {
      m_image.save((GET_DATA_DIR + "/test.tif").c_str());
    }
#endif

//    m_image->enhanceContrast(
//          hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));
//    QElapsedTimer timer;
//    timer.start();
//    tic();
    painter.drawPixmap(getX(), getY(), m_pixmap);
//    painter.drawImage(getX(), getY(), *m_image);
//    std::cout << "Draw image time: " << toc() << std::endl;
//    std::cout << "Draw image time: " << timer.elapsed() << std::endl;

//      ZIntPoint pt = m_offset - painter.getOffset().toIntPoint();

//      painter.save();

//      QTransform transform;

//      transform.scale(m_res.getScale(), m_res.getScale());
//      transform.translate(getX(), getY());

//      //transform.translate(pt.x(), pt.y());
//      painter.setTransform(transform);
//      painter.drawImage(m_image);

//      painter.restore();
    //}
  }
}
#if 0
void ZDvidTile::update(int x, int y, int z, int width, int height)
{

  bool updating = false;
  if (m_stack == NULL) {
    m_stack = ZStackFactory::makeZeroStack(GREY, width, height, 1);
    m_stack->setOffset(x, y, z);
    updating = true;
  } else if (m_stack->getOffset().getZ() != z ||
             m_stack->getOffset().getX() != x ||
             m_stack->getOffset().getZ() != z ||
             m_stack->width() != width || m_stack->height() != height) {
    updating = true;
  }

  if (updating) {
    ZDvidReader reader;
    if (reader.open(m_dvidTarget)) {
      Stack *stack = reader.readTile(x, y, z, width, heigth, m_res.getLevel());
    }
  }

}
#endif
void ZDvidTile::setTileIndex(int ix, int iy)
{
  m_ix = ix;
  m_iy = iy;
}

void ZDvidTile::update(int z)
{
  if (m_z != z || m_image == NULL) {
#if defined(_ENABLE_LIBDVIDCPP_2)
    std::vector<int> offset(3);
    offset[0] = m_ix;
    offset[1] = m_iy;
    offset[2] = z;

    tic();
    try {
      libdvid::DVIDNodeService service(getDvidTarget().getAddressWithPort(),
                                       getDvidTarget().getUuid());
      libdvid::BinaryDataPtr data =
          service.get_tile_slice_binary(
            "tiles", libdvid::XY, m_res.getLevel(), offset);
      if (data->length() > 0) {
        loadDvidSlice(data->get_raw(), data->length(), z);
        m_image.setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
        m_image.setOffset(-getX(), -getY());
      }
    } catch (std::exception &e) {
      std::cout << e.what() << std::endl;===
    }
    std::cout << "Tile level: " << m_res.getLevel() << std::endl;
    std::cout << "Tile reading time: " << toc() << std::endl;
#else
    ZDvidUrl dvidUrl(getDvidTarget());
    ZDvidBufferReader bufferReader;

    /*
    QFuture<void> result = QtConcurrent::run(
          &bufferReader, &ZDvidBufferReader::read,
          QString(dvidUrl.getTileUrl("graytiles", m_res.getLevel(), m_ix, m_iy, z).c_str()));
    result.waitForFinished();
    */

    tic();
    bufferReader.read(
          dvidUrl.getTileUrl(getDvidTarget().getMultiscale2dName(),
                             m_res.getLevel(), m_ix, m_iy, z).c_str());
    QByteArray buffer = bufferReader.getBuffer();
    std::cout << "Tile reading time: " << toc() << std::endl;

//    ZDvidTileInfo tileInfo = readTileInfo("graytiles");

    if (!buffer.isEmpty()) {
      loadDvidSlice(buffer, z);
//      m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
//      m_image->setOffset(-getX(), -getY());
      //      setResolutionLevel(m_res.getLevel());
    }
#endif
  }
  //m_z = z;
}
#if 0
void ZDvidTile::setTileOffset(int x, int y, int z)
{
  m_offset.set(x, y, z);
}
#endif

void ZDvidTile::printInfo() const
{
  std::cout << "Dvid tile: " << std::endl;
  m_res.print();
  std::cout << "Offset: " << getX() << ", " << getY() << ", " << getZ() << std::endl;
  if (m_image != NULL) {
    std::cout << "Size: " << m_image->width() << " x " << m_image->height()
              << std::endl;
  }

}

void ZDvidTile::setResolutionLevel(int level)
{
  m_res.setLevel(level);
}

void ZDvidTile::setDvidTarget(const ZDvidTarget &target)
{
  m_dvidTarget = target;
  if (!m_tilingInfo.isValid()) {
    ZDvidReader reader;
    if (reader.open(target)) {
      m_tilingInfo = reader.readTileInfo(target.getMultiscale2dName());
    }
  }
}

int ZDvidTile::getX() const
{
  return m_ix * m_tilingInfo.getWidth() * m_res.getScale();
}

int ZDvidTile::getWidth() const
{
  return m_tilingInfo.getWidth() * m_res.getScale();
}

int ZDvidTile::getHeight() const
{
  return m_tilingInfo.getHeight() * m_res.getScale();
}

int ZDvidTile::getY() const
{
  return m_iy * m_tilingInfo.getHeight() * m_res.getScale();
}

int ZDvidTile::getZ() const
{
  return m_z;
}

void ZDvidTile::attachView(ZStackView *view)
{
  m_view = view;
}

ZRect2d ZDvidTile::getBoundBox() const
{
  ZRect2d rect;
  rect.set(getX(), getY(), getWidth(), getHeight());

  return rect;
}

<commit_msg>fix tile crash problem<commit_after>#include "zdvidtile.h"

#include <QTransform>
#include <QtConcurrentRun>
#include <QElapsedTimer>

#include "widgets/zimagewidget.h"
#include "neutubeconfig.h"
#include "zstack.hxx"
#include "zstackfactory.h"
#include "zdvidreader.h"
#include "zimage.h"
#include "zpainter.h"
#include "zdvidbufferreader.h"
#include "zdvidurl.h"
#include "zdvidtileinfo.h"
#include "zdvidreader.h"
#include "zstackview.h"
#include "zrect2d.h"
#include "libdvidheader.h"

ZDvidTile::ZDvidTile() : m_ix(0), m_iy(0), m_z(0),
  m_view(NULL)
{
  setTarget(ZStackObject::TARGET_OBJECT_CANVAS);
  m_type = ZStackObject::TYPE_DVID_TILE;
  m_image = NULL;
}

ZDvidTile::~ZDvidTile()
{
  clear();
}

ZSTACKOBJECT_DEFINE_CLASS_NAME(ZDvidTile)

void ZDvidTile::clear()
{
  m_dvidTarget.clear();
  delete m_image;
  m_image = NULL;
}

void ZDvidTile::loadDvidSlice(const uchar *buf, int length, int z)
{
  bool loading = true;
  if (m_view != NULL) {
    if (m_view->getZ(NeuTube::COORD_STACK) != z) {
      loading = false;
    }
  }

  bool modified = false;
  if (loading) {
    if (m_image == NULL) {
      m_image = new ZImage;
    }

    m_image->loadFromData(buf, length);
    m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
    m_image->setOffset(-getX(), -getY());

    modified = true;

    m_image->enhanceContrast(
          hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));

#ifdef _DEBUG_2
    std::cout << "Format: " << m_image->format() << std::endl;
    setVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
#endif
    m_z = z;
  }

  if (modified) {
    updatePixmap();
  }
}

void ZDvidTile::updatePixmap()
{
  m_pixmap.cleanUp();
  m_pixmap.convertFromImage(*m_image);
  m_pixmap.setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
  m_pixmap.setOffset(-getX(), -getY());
}

void ZDvidTile::enhanceContrast(bool high)
{
  if (high != hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST)) {
    if (high) {
      addVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
    } else {
      removeVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST);
    }

    if (m_image != NULL) {
      m_image->enhanceContrast(
            hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));
      updatePixmap();
    }
  }
}
/*
void ZDvidTile::setImageData(const uint8_t *data, int width, int height)
{
  if (width <= 0 || height <= 0) {
    return;
  }

  if (m_image != NULL) {
    if (m_image->width() != width || m_image->height() != height) {
      delete m_image;
      m_image = NULL;
    }
  }

  if (m_image == NULL) {
    m_image = new ZImage(width, height);
  }

  m_image->setData(data);
  m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
  m_image->setOffset(-getX(), -getY());
}
*/
void ZDvidTile::loadDvidSlice(const QByteArray &buffer, int z)
{
  loadDvidSlice((const uchar *) buffer.data(), buffer.length(), z);
#if 0
  bool loading = true;
  if (m_view != NULL) {
    if (m_view->getZ(NeuTube::COORD_STACK) != z) {
      loading = false;
    }
  }
  if (loading) {
#ifdef _DEBUG_2
      std::cout << z << " Loaded." << std::endl;
#endif

    m_image.loadFromData(buffer);
//    m_image.enhanceContrast();

//    m_image.setOffset();
    m_z = z;
  }
#endif

//  m_image.save((GET_TEST_DATA_DIR + "/test.tif").c_str());
}

void ZDvidTile::display(
    ZPainter &painter, int slice, EDisplayStyle /*option*/) const
{
  bool isProj = false;
  int z = painter.getZOffset() + slice;
  if (slice < 0) {
    isProj = true;
    z = painter.getZOffset() - slice - 1;
  }
  //if (!m_image.isNull()) {
//  bool isProj = (slice < 0);

//  int z = painter.getZOffset() + slice;
  m_latestZ = z;

//  tic();
  const_cast<ZDvidTile&>(*this).update(z);
//  std::cout << "tile update time: " << toc() << std::endl;

  if ((z == m_z)  && (m_image != NULL)) {
#ifdef _DEBUG_2
    std::cout << "Display " << z << std::endl;
#endif
    //      ZImage image = getImage();
    //int dx = getX() - painter.getOffset().x();
    //int dy = getY() - painter.getOffset().y();

    //      QRect sourceRect = QRect(0, 0, m_image.width(), m_image.height());
    //      QRect targetRect = QRect(getX(), getY(), m_image.width() * m_res.getScale(),
    //                         m_image.height() * m_res.getScale());
#if 0
    if (m_res.getScale() == 1) {
      m_image.save((GET_DATA_DIR + "/test.tif").c_str());
    }
#endif

//    m_image->enhanceContrast(
//          hasVisualEffect(NeuTube::Display::Image::VE_HIGH_CONTRAST));
//    QElapsedTimer timer;
//    timer.start();
//    tic();
    painter.drawPixmap(getX(), getY(), m_pixmap);
//    painter.drawImage(getX(), getY(), *m_image);
//    std::cout << "Draw image time: " << toc() << std::endl;
//    std::cout << "Draw image time: " << timer.elapsed() << std::endl;

//      ZIntPoint pt = m_offset - painter.getOffset().toIntPoint();

//      painter.save();

//      QTransform transform;

//      transform.scale(m_res.getScale(), m_res.getScale());
//      transform.translate(getX(), getY());

//      //transform.translate(pt.x(), pt.y());
//      painter.setTransform(transform);
//      painter.drawImage(m_image);

//      painter.restore();
    //}
  }
}
#if 0
void ZDvidTile::update(int x, int y, int z, int width, int height)
{

  bool updating = false;
  if (m_stack == NULL) {
    m_stack = ZStackFactory::makeZeroStack(GREY, width, height, 1);
    m_stack->setOffset(x, y, z);
    updating = true;
  } else if (m_stack->getOffset().getZ() != z ||
             m_stack->getOffset().getX() != x ||
             m_stack->getOffset().getZ() != z ||
             m_stack->width() != width || m_stack->height() != height) {
    updating = true;
  }

  if (updating) {
    ZDvidReader reader;
    if (reader.open(m_dvidTarget)) {
      Stack *stack = reader.readTile(x, y, z, width, heigth, m_res.getLevel());
    }
  }

}
#endif
void ZDvidTile::setTileIndex(int ix, int iy)
{
  m_ix = ix;
  m_iy = iy;
}

void ZDvidTile::update(int z)
{
  if (m_z != z || m_image == NULL) {
#if defined(_ENABLE_LIBDVIDCPP_2)
    std::vector<int> offset(3);
    offset[0] = m_ix;
    offset[1] = m_iy;
    offset[2] = z;

    tic();
    try {
      libdvid::DVIDNodeService service(getDvidTarget().getAddressWithPort(),
                                       getDvidTarget().getUuid());
      libdvid::BinaryDataPtr data =
          service.get_tile_slice_binary(
            "tiles", libdvid::XY, m_res.getLevel(), offset);
      if (data->length() > 0) {
        loadDvidSlice(data->get_raw(), data->length(), z);
        m_image.setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
        m_image.setOffset(-getX(), -getY());
      }
    } catch (std::exception &e) {
      std::cout << e.what() << std::endl;===
    }
    std::cout << "Tile level: " << m_res.getLevel() << std::endl;
    std::cout << "Tile reading time: " << toc() << std::endl;
#else
    ZDvidUrl dvidUrl(getDvidTarget());
    ZDvidBufferReader bufferReader;

    /*
    QFuture<void> result = QtConcurrent::run(
          &bufferReader, &ZDvidBufferReader::read,
          QString(dvidUrl.getTileUrl("graytiles", m_res.getLevel(), m_ix, m_iy, z).c_str()));
    result.waitForFinished();
    */

    tic();
    bufferReader.read(
          dvidUrl.getTileUrl(getDvidTarget().getMultiscale2dName(),
                             m_res.getLevel(), m_ix, m_iy, z).c_str());
    QByteArray buffer = bufferReader.getBuffer();
    std::cout << "Tile reading time: " << toc() << std::endl;

//    ZDvidTileInfo tileInfo = readTileInfo("graytiles");

    if (!buffer.isEmpty()) {
      loadDvidSlice(buffer, z);
//      m_image->setScale(1.0 / m_res.getScale(), 1.0 / m_res.getScale());
//      m_image->setOffset(-getX(), -getY());
      //      setResolutionLevel(m_res.getLevel());
    }
#endif
  }
  //m_z = z;
}
#if 0
void ZDvidTile::setTileOffset(int x, int y, int z)
{
  m_offset.set(x, y, z);
}
#endif

void ZDvidTile::printInfo() const
{
  std::cout << "Dvid tile: " << std::endl;
  m_res.print();
  std::cout << "Offset: " << getX() << ", " << getY() << ", " << getZ() << std::endl;
  if (m_image != NULL) {
    std::cout << "Size: " << m_image->width() << " x " << m_image->height()
              << std::endl;
  }

}

void ZDvidTile::setResolutionLevel(int level)
{
  m_res.setLevel(level);
}

void ZDvidTile::setDvidTarget(const ZDvidTarget &target)
{
  m_dvidTarget = target;
  if (!m_tilingInfo.isValid()) {
    ZDvidReader reader;
    if (reader.open(target)) {
      m_tilingInfo = reader.readTileInfo(target.getMultiscale2dName());
    }
  }
}

int ZDvidTile::getX() const
{
  return m_ix * m_tilingInfo.getWidth() * m_res.getScale();
}

int ZDvidTile::getWidth() const
{
  return m_tilingInfo.getWidth() * m_res.getScale();
}

int ZDvidTile::getHeight() const
{
  return m_tilingInfo.getHeight() * m_res.getScale();
}

int ZDvidTile::getY() const
{
  return m_iy * m_tilingInfo.getHeight() * m_res.getScale();
}

int ZDvidTile::getZ() const
{
  return m_z;
}

void ZDvidTile::attachView(ZStackView *view)
{
  m_view = view;
}

ZRect2d ZDvidTile::getBoundBox() const
{
  ZRect2d rect;
  rect.set(getX(), getY(), getWidth(), getHeight());

  return rect;
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <chrono>
#include <memory>

#if defined __gnu_linux__ || defined __APPLE__
	#include <unistd.h>
	#include <sys/time.h>
	#include <termios.h>
	#include <fcntl.h>
#endif

#if defined WIN32 || defined WIN64
	#include <Windows.h>
#endif

// http://stackoverflow.com/questions/1413445/read-a-password-from-stdcin
void SetStdinEcho(bool enable = true) {
#if defined WIN32 || defined WIN64
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);

    if( !enable )
        mode &= ~ENABLE_ECHO_INPUT;
    else
        mode |= ENABLE_ECHO_INPUT;

    SetConsoleMode(hStdin, mode);
#endif
#if defined __gnu_linux__ || defined __APPLE__
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    if( !enable )
        tty.c_lflag &= ~ECHO;
    else
        tty.c_lflag |= ECHO;

    (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty);
#endif
}

bool testForComment(std::string& line) {
  std::regex testRegex("^//.*$", std::regex_constants::extended);
  return std::regex_match(line, testRegex);
}

void readQuestions(std::ifstream& questionFile, std::vector<std::string>& questions) {
  while(questionFile) {
    std::string line;
    std::getline(questionFile, line);
    if (line.length() > 0 && !testForComment(line))
      questions.push_back(line);
  }
  std::sort(questions.begin(), questions.end());
}

unsigned int getRnd(void) {
  unsigned int rndNumber = 0;
#if defined __gnu_linux__ || defined __APPLE__
  int urandom = open("/dev/urandom", O_RDONLY);
  assert(urandom);
  read(urandom, &rndNumber, sizeof(unsigned int));
  close(urandom);
#endif
#ifdef WIN32
  HCRYPTPROV hprovider = 0;
  CryptAcquireContext(&hprovider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  CryptGenRandom(hprovider, sizeof(unsigned int), reinterpret_cast<byte*>(&rndNumber));
  CryptReleaseContext(hprovider, 0);
#endif
  return rndNumber;
}

void usage(void) {
    std::cout << "usage: ./question filename" << std::endl;
}

int main(int argc, char ** argv) {
  if (argc != 2) {
      usage();
      return EXIT_FAILURE;
  }

  typedef std::vector<std::string> StringVector;
  typedef std::shared_ptr<StringVector> StringVector_Ptr;

  std::string filename(argv[1]);
  StringVector_Ptr questions(new StringVector);

  std::ifstream questionFile(filename.c_str());
  if (questionFile.good())
	  readQuestions(questionFile, *questions);
  else {
      std::cerr << "Can't open given file " << filename << std::endl;
      return EXIT_FAILURE;
  }
  questionFile.close();

  // Do we have any questions? % todo->size is DIV_BY_ZERO otherwise
  if (questions->size() == 0) {
	  std::cerr << "No question provided!" << std::endl;
	  return EXIT_FAILURE;
  }

  StringVector_Ptr todo(new StringVector(*questions));
  StringVector_Ptr done(new StringVector);

  typedef std::chrono::high_resolution_clock clock;
  typedef std::chrono::milliseconds milliseconds;
  clock::time_point t0;
  clock::time_point t1;
  std::string question;
  int id = 0;
  while(true) {
    id = getRnd() % todo->size();
    question = (*todo)[id];
    todo->erase(std::find(todo->begin(), todo->end(), question));
    done->push_back(question);

    std::cout << question << std::endl;
	SetStdinEcho(false);
	t0 = clock::now();
    std::cin.get();
	t1 = clock::now();
    SetStdinEcho(true);
    milliseconds total_ms = std::chrono::duration_cast<milliseconds>(t1 - t0);
    std::cout <<  total_ms.count() / 1000.0 << " seconds for answer!" << std::endl;
    if (todo->empty()) {
        std::swap(todo, done);
        std::cout << "### Complete, starting again. ###" << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>workaround for incorrect working regex library in stdlibc++<commit_after>#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <memory>

#if defined __gnu_linux__ || defined __APPLE__
	#include <unistd.h>
	#include <sys/time.h>
	#include <termios.h>
	#include <fcntl.h>
  #include <regex.h>
#endif

#if defined WIN32 || defined WIN64
	#include <Windows.h>
  #include <regex>
#endif

// http://stackoverflow.com/questions/1413445/read-a-password-from-stdcin
void SetStdinEcho(bool enable = true) {
#if defined WIN32 || defined WIN64
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);

    if( !enable )
        mode &= ~ENABLE_ECHO_INPUT;
    else
        mode |= ENABLE_ECHO_INPUT;

    SetConsoleMode(hStdin, mode);
#endif
#if defined __gnu_linux__ || defined __APPLE__
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    if( !enable )
        tty.c_lflag &= ~ECHO;
    else
        tty.c_lflag |= ECHO;

    (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty);
#endif
}

bool testForComment(std::string& line) {
  #if defined WIN32 || defined WIN64
    std::regex testRegex("^//.*$", std::regex_constants::extended);
    return std::regex_match(line, testRegex);
  #endif

  // stdlibc++ wasn't feature complete for C++11 at the time writing this code
  // FIXME: if c++ lib supports this, remove the following code

  #if defined __gnu_linux__ || defined __APPLE__
    int rv;
    regex_t * exp = new regex_t;
    rv = regcomp(exp, "^//.*", REG_EXTENDED);
    if (rv != 0) {
      std::cout << "regcomp failed with " << rv << std::endl;
    }
    bool match = regexec(exp, line.c_str(), 0, NULL, 0) == 0;
    regfree(exp);
    return match;
  #endif
}

void readQuestions(std::ifstream& questionFile, std::vector<std::string>& questions) {
  while(questionFile) {
    std::string line;
    std::getline(questionFile, line);
    if (line.length() > 0 && !testForComment(line))
      questions.push_back(line);
  }
  std::sort(questions.begin(), questions.end());
}

unsigned int getRnd(void) {
  unsigned int rndNumber = 0;
#if defined __gnu_linux__ || defined __APPLE__
  int urandom = open("/dev/urandom", O_RDONLY);
  assert(urandom);
  read(urandom, &rndNumber, sizeof(unsigned int));
  close(urandom);
#endif
#ifdef WIN32
  HCRYPTPROV hprovider = 0;
  CryptAcquireContext(&hprovider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  CryptGenRandom(hprovider, sizeof(unsigned int), reinterpret_cast<byte*>(&rndNumber));
  CryptReleaseContext(hprovider, 0);
#endif
  return rndNumber;
}

void usage(void) {
    std::cout << "usage: ./question filename" << std::endl;
}

int main(int argc, char ** argv) {
  if (argc != 2) {
      usage();
      return EXIT_FAILURE;
  }

  typedef std::vector<std::string> StringVector;
  typedef std::shared_ptr<StringVector> StringVector_Ptr;

  std::string filename(argv[1]);
  StringVector_Ptr questions(new StringVector);

  std::ifstream questionFile(filename.c_str());
  if (questionFile.good())
	  readQuestions(questionFile, *questions);
  else {
      std::cerr << "Can't open given file " << filename << std::endl;
      return EXIT_FAILURE;
  }
  questionFile.close();

  // Do we have any questions? % todo->size is DIV_BY_ZERO otherwise
  if (questions->size() == 0) {
	  std::cerr << "No question provided!" << std::endl;
	  return EXIT_FAILURE;
  }

  StringVector_Ptr todo(new StringVector(*questions));
  StringVector_Ptr done(new StringVector);

  typedef std::chrono::high_resolution_clock clock;
  typedef std::chrono::milliseconds milliseconds;
  clock::time_point t0;
  clock::time_point t1;
  std::string question;
  int id = 0;
  while(true) {
    id = getRnd() % todo->size();
    question = (*todo)[id];
    todo->erase(std::find(todo->begin(), todo->end(), question));
    done->push_back(question);

    std::cout << question << std::endl;
	SetStdinEcho(false);
	t0 = clock::now();
    std::cin.get();
	t1 = clock::now();
    SetStdinEcho(true);
    milliseconds total_ms = std::chrono::duration_cast<milliseconds>(t1 - t0);
    std::cout <<  total_ms.count() / 1000.0 << " seconds for answer!" << std::endl;
    if (todo->empty()) {
        std::swap(todo, done);
        std::cout << "### Complete, starting again. ###" << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <memory>

#if defined __gnu_linux__ || defined __APPLE__
	#include <unistd.h>
	#include <sys/time.h>
	#include <termios.h>
	#include <fcntl.h>
  #include <regex.h>
#endif

#if defined WIN32 || defined WIN64
	#include <Windows.h>
  #include <regex>
#endif

// http://stackoverflow.com/questions/1413445/read-a-password-from-stdcin
void SetStdinEcho(bool enable = true) {
#if defined WIN32 || defined WIN64
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);

    if( !enable )
        mode &= ~ENABLE_ECHO_INPUT;
    else
        mode |= ENABLE_ECHO_INPUT;

    SetConsoleMode(hStdin, mode);
#endif
#if defined __gnu_linux__ || defined __APPLE__
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    if( !enable )
        tty.c_lflag &= ~ECHO;
    else
        tty.c_lflag |= ECHO;

    (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty);
#endif
}

bool testForComment(std::string& line) {
  #if defined WIN32 || defined WIN64
    std::regex testRegex("^//.*$", std::regex_constants::extended);
    return std::regex_match(line, testRegex);
  #endif

  // stdlibc++ wasn't feature complete for C++11 at the time writing this code
  // FIXME: if c++ lib supports this, remove the following code

  #if defined __gnu_linux__ || defined __APPLE__
    int rv;
    regex_t * exp = new regex_t;
    rv = regcomp(exp, "^//.*", REG_EXTENDED);
    if (rv != 0) {
      std::cout << "regcomp failed with " << rv << std::endl;
    }
    bool match = regexec(exp, line.c_str(), 0, NULL, 0) == 0;
    regfree(exp);
    return match;
  #endif
}

void readQuestions(std::ifstream& questionFile, std::vector<std::string>& questions) {
  while(questionFile) {
    std::string line;
    std::getline(questionFile, line);
    if (line.length() > 0 && !testForComment(line))
      questions.push_back(line);
  }
  std::sort(questions.begin(), questions.end());
}

unsigned int getRnd(void) {
  unsigned int rndNumber = 0;
#if defined __gnu_linux__ || defined __APPLE__
  int urandom = open("/dev/urandom", O_RDONLY);
  assert(urandom);
  read(urandom, &rndNumber, sizeof(unsigned int));
  close(urandom);
#endif
#ifdef WIN32
  HCRYPTPROV hprovider = 0;
  CryptAcquireContext(&hprovider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  CryptGenRandom(hprovider, sizeof(unsigned int), reinterpret_cast<byte*>(&rndNumber));
  CryptReleaseContext(hprovider, 0);
#endif
  return rndNumber;
}

void usage(void) {
    std::cout << "usage: ./question filename" << std::endl;
}

int main(int argc, char ** argv) {
  if (argc != 2) {
      usage();
      return EXIT_FAILURE;
  }

  typedef std::vector<std::string> StringVector;
  typedef std::shared_ptr<StringVector> StringVector_Ptr;

  std::string filename(argv[1]);
  StringVector_Ptr questions(new StringVector);

  std::ifstream questionFile(filename.c_str());
  if (questionFile.good())
	  readQuestions(questionFile, *questions);
  else {
      std::cerr << "Can't open given file " << filename << std::endl;
      return EXIT_FAILURE;
  }
  questionFile.close();

  // Do we have any questions? % todo->size is DIV_BY_ZERO otherwise
  if (questions->size() == 0) {
	  std::cerr << "No question provided!" << std::endl;
	  return EXIT_FAILURE;
  }

  StringVector_Ptr todo(new StringVector(*questions));
  StringVector_Ptr done(new StringVector);

  typedef std::chrono::high_resolution_clock clock;
  typedef std::chrono::milliseconds milliseconds;
  clock::time_point t0;
  clock::time_point t1;
  std::string question;
  int id = 0;
  while(true) {
    id = getRnd() % todo->size();
    question = (*todo)[id];
    todo->erase(std::find(todo->begin(), todo->end(), question));
    done->push_back(question);

    std::cout << question << std::endl;
	SetStdinEcho(false);
	t0 = clock::now();
    std::cin.get();
	t1 = clock::now();
    SetStdinEcho(true);
    milliseconds total_ms = std::chrono::duration_cast<milliseconds>(t1 - t0);
    std::cout <<  total_ms.count() / 1000.0 << " seconds for answer!" << std::endl;
    if (todo->empty()) {
        std::swap(todo, done);
        std::cout << "### Complete, starting again. ###" << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>added linebreak<commit_after>#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <memory>

#ifdef __APPLE__
#include <unistd.h>
#include <sys/time.h>
#include <termios.h>
#include <fcntl.h>
#include <regex>
#endif

#if defined __gnu_linux__
  #include <unistd.h>
  #include <sys/time.h>
  #include <termios.h>
  #include <fcntl.h>
  #include <regex.h>
#endif

#if defined WIN32 || defined WIN64
  #include <Windows.h>
  #include <regex>
#endif

// http://stackoverflow.com/questions/1413445/read-a-password-from-stdcin
void SetStdinEcho(bool enable = true) {
#if defined WIN32 || defined WIN64
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);

    if( !enable )
        mode &= ~ENABLE_ECHO_INPUT;
    else
        mode |= ENABLE_ECHO_INPUT;

    SetConsoleMode(hStdin, mode);
#endif
#if defined __gnu_linux__ || defined __APPLE__
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    if( !enable )
        tty.c_lflag &= ~ECHO;
    else
        tty.c_lflag |= ECHO;

    (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty);
#endif
}

bool testForComment(std::string& line) {
  #if defined WIN32 || defined WIN64 || defined __APPLE__
    std::regex testRegex("^//.*$", std::regex_constants::extended);
    return std::regex_match(line, testRegex);
  #endif

  // stdlibc++ wasn't feature complete for C++11 at the time writing this code
  // FIXME: if c++ lib supports this, remove the following code

  #if defined __gnu_linux__
    int rv;
    regex_t * exp = new regex_t;
    rv = regcomp(exp, "^//.*", REG_EXTENDED);
    if (rv != 0) {
      std::cout << "regcomp failed with " << rv << std::endl;
    }
    bool match = regexec(exp, line.c_str(), 0, NULL, 0) == 0;
    regfree(exp);
    return match;
  #endif
}

void readQuestions(std::ifstream& questionFile, std::vector<std::string>& questions) {
  while(questionFile) {
    std::string line;
    std::getline(questionFile, line);
    if (line.length() > 0 && !testForComment(line))
      questions.push_back(line);
  }
  std::sort(questions.begin(), questions.end());
}

unsigned int getRnd(void) {
  unsigned int rndNumber = 0;
#if defined __gnu_linux__ || defined __APPLE__
  int urandom = open("/dev/urandom", O_RDONLY);
  assert(urandom);
  read(urandom, &rndNumber, sizeof(unsigned int));
  close(urandom);
#endif
#ifdef WIN32
  HCRYPTPROV hprovider = 0;
  CryptAcquireContext(&hprovider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  CryptGenRandom(hprovider, sizeof(unsigned int), reinterpret_cast<byte*>(&rndNumber));
  CryptReleaseContext(hprovider, 0);
#endif
  return rndNumber;
}

void usage(void) {
    std::cout << "usage: ./question filename" << std::endl;
}

int main(int argc, char ** argv) {
  if (argc != 2) {
      usage();
      return EXIT_FAILURE;
  }

  typedef std::vector<std::string> StringVector;
  typedef std::shared_ptr<StringVector> StringVector_Ptr;

  std::string filename(argv[1]);
  StringVector_Ptr questions(new StringVector);

  std::ifstream questionFile(filename.c_str());
  if (questionFile.good())
	  readQuestions(questionFile, *questions);
  else {
      std::cerr << "Can't open given file " << filename << std::endl;
      return EXIT_FAILURE;
  }
  questionFile.close();

  // Do we have any questions? % todo->size is DIV_BY_ZERO otherwise
  if (questions->size() == 0) {
	  std::cerr << "No question provided!" << std::endl;
	  return EXIT_FAILURE;
  }

  StringVector_Ptr todo(new StringVector(*questions));
  StringVector_Ptr done(new StringVector);

  typedef std::chrono::high_resolution_clock clock;
  typedef std::chrono::milliseconds milliseconds;
  clock::time_point t0;
  clock::time_point t1;
  std::string question;
  int id = 0;
  while(true) {
    id = getRnd() % todo->size();
    question = (*todo)[id];
    todo->erase(std::find(todo->begin(), todo->end(), question));
    done->push_back(question);

    std::cout << question << std::endl;
	SetStdinEcho(false);
	t0 = clock::now();
    std::cin.get();
	t1 = clock::now();
    SetStdinEcho(true);
    milliseconds total_ms = std::chrono::duration_cast<milliseconds>(t1 - t0);
    std::cout << total_ms.count() / 1000.0 << " seconds for answer!" << std::endl;
    std::cout << std::endl;
    if (todo->empty()) {
        std::swap(todo, done);
        std::cout << "### Complete, starting again. ###" << std::endl;
        std::cout << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdlib.h>
#include "io/PPMLoader.hpp"
#include "converter/RGBToYCbCrConverter.hpp"
#include "converter/YCbCrToRGBConverter.hpp"
#include "helper/Test.hpp"
#include "Huffman.hpp"
#include "DCT.hpp"

#include "bitstream/Bitstream.hpp"

#include "segments/JPEGSegments.hpp"

using namespace JPEGSegments;

#define TEST_ITERATIONS 10000000
#define TEST_REPEAT 10

//  ---------------------------------------------------------------
// |
// |  PPM Image Processing
// |
//  ---------------------------------------------------------------

void testImage() {
	std::cout << "Loading image ..." << std::endl;
	Test::performance([]{
		PPMLoader loader;
		auto image = loader.load("../data/singapore4k.test.ppm");

		//		RGBToYCbCrConverter converter1;
		//		converter1.convert(image);
		//
		//		image->print();
		//
		//		image->channel2->reduceBySubSampling( image->imageSize.width, image->imageSize.height );
		//		image->channel3->reduceBySubSampling( image->imageSize.width, image->imageSize.height );
		//
		//		YCbCrToRGBConverter converter2;
		//		converter2.convert(image);
		//
		//		image->reduceBySubSample(2, 2);
		//		image->reduceByAverage(2, 2);
		//		image->print();

		//		Test::performance([&loader, &image]{
		//			loader.write("data/output.test.ppm", image);
		//		});
	});
}

//  ---------------------------------------------------------------
// |
// |  JPEG Writer
// |
//  ---------------------------------------------------------------

void testJPEGWriter() {

	Bitstream bitStream;
	bitStream.add(1);
	bitStream.add(0);
	bitStream.add(1);
	bitStream.add(1);
	bitStream.add(0);
	bitStream.print();
	bitStream.fillup(1);
	bitStream.print();
	bitStream.saveToFile("out.txt");

	std::cout << "Testing, Bitstream" << std::endl;

	std::cout << "Write single bit: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [](size_t numberOfElements){
		Bitstream bitstream;
		while (numberOfElements--) {
			bitstream.add(numberOfElements % 2);
		}
	});

	std::cout << "Write byte bits: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [](size_t numberOfElements){
		Bitstream bitstream;
		// bitstream.add(1);
		while (numberOfElements--) {
			bitstream.add(0xd2, 8);
		}
	});

	// create random bitstream for reading
	Bitstream testStream;
	size_t fillRandom = TEST_ITERATIONS;
	while (fillRandom--)
		testStream.add( arc4random() % 2 );

	std::cout << "Read single bit: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [&testStream](size_t numberOfElements){
		size_t maxRead = testStream.numberOfBits() - 2;
		size_t idx = 0;
		while (numberOfElements--) {
			testStream.read(idx++);
			if (idx > maxRead)
				idx = 0;
		}
	});

	std::cout << "Write file: ";
	Test::performance([&testStream] {
		testStream.saveToFile("data/writeOleg.txt");
	});

	PPMLoader loader;
	auto image = loader.load("data/very_small.ppm");

	JPEGWriter writer;
	writer.writeJPEGImage(image, "Test.test.jpg");
}

std::vector<Symbol> getWord() {
	std::vector<Symbol> input;
	input.push_back(1);
	input.push_back(4);
	input.push_back(6);

	return input;
}

void addTestSymbol(int amount, int symbol, std::vector<int> &input) {
	for (int i = 0; i < amount; ++i) {
		input.push_back(symbol);
	}
}

std::vector<int> generateTestHuffman() {
	std::vector<int>input;
	addTestSymbol(5, 1, input);
	addTestSymbol(12, 5, input);
	addTestSymbol(13, 6, input);
	addTestSymbol(6, 2, input);
	addTestSymbol(8, 3, input);
	addTestSymbol(8, 4, input);
	return input;
}

std::vector<int> generateTestHuffman2() {
	std::vector<int>input;
	addTestSymbol(5, 1, input);
	addTestSymbol(5, 2, input);
	addTestSymbol(6, 3, input);
	addTestSymbol(11, 4, input);
	addTestSymbol(12, 5, input);
	addTestSymbol(12, 6, input);
	addTestSymbol(26, 7, input);
	return input;
}

void testhuffmann() {
	std::vector<Symbol> testData;

	auto input = generateTestHuffman();

	Huffman huffman = Huffman(input);
	huffman.preventAllOnesPath(true);
//	auto encodingTable = huffman.canonicalEncoding();
	auto encodingTable = huffman.canonicalEncoding(4);
//	Node* rootTree = huffman.standardTree();
	Node* rootTree = huffman.treeFromEncodingTable(encodingTable);

	for (auto pair: encodingTable) {
		std::cout << pair.first << ": " << pair.second << std::endl;
	}
	rootTree->print();
	rootTree->exportTree();
	Bitstream bitsteam;
	std::vector<Symbol> word = getWord();
	for (int i = 0; i < word.size(); ++i) {
		Encoding enc = encodingTable.at(word[i]);
		std::cout << "füge " << enc << " hinzu (" << word[i] << ")" << std::endl;
		bitsteam.add(enc.code, enc.numberOfBits);
	}
	bitsteam.print();
}

void testDirectDCT() {
	Mat input(2);
	for (int i = 0; i < input.rows; ++i) {
		for (int j = 0; j < input.cols; ++j) {
			input.set(i , j, 2);
		}
	}
	DCT dct;
	Mat out = dct.transform(input);

	for (int i = 0; i < input.rows; ++i) {
		for (int j = 0; j < input.cols; ++j) {
			printf("%f ", out.get(i , j));
		}
		printf("\n");
	}
}

void testIDCT() {
	Mat input(2);
	for (int i = 0; i < input.rows; ++i) {
		for (int j = 0; j < input.cols; ++j) {
			input.set(i , j , 2);
		}
	}

	DCT test;
	Mat out = test.transform2DDCT(input);

	Mat inverse = test.transform(out);

	for (int i = 0; i < input.rows; ++i) {
		for (int j = 0; j < input.cols; ++j) {
			printf("%f ", inverse.get(i , j));
		}
		printf("\n");
	}

}

void testMat() {
	Mat a;
	a.initiate((float[]){
		1, 2, 3,
		3, 1, 1}, 2 , 3);

	Mat b;
	b.initiate((float[]){
		2, 1,
		1, 2,
		2, 1
	}, 3 , 2);

	Mat c = a * b;
	c.print();
}

// ################################################################
// #
// #  Main
// #
// ################################################################

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

	//testhuffmann();
	//testJPEGWriter();

	//testDirectDCT();
	testIDCT();
//	testMat();
//	testImage();

	return 0;
}
<commit_msg>Refactor mat initiation<commit_after>#include <iostream>
#include <stdlib.h>
#include "io/PPMLoader.hpp"
#include "converter/RGBToYCbCrConverter.hpp"
#include "converter/YCbCrToRGBConverter.hpp"
#include "helper/Test.hpp"
#include "Huffman.hpp"
#include "DCT.hpp"

#include "bitstream/Bitstream.hpp"

#include "segments/JPEGSegments.hpp"

using namespace JPEGSegments;

#define TEST_ITERATIONS 10000000
#define TEST_REPEAT 10

//  ---------------------------------------------------------------
// |
// |  PPM Image Processing
// |
//  ---------------------------------------------------------------

void testImage() {
	std::cout << "Loading image ..." << std::endl;
	Test::performance([]{
		PPMLoader loader;
		auto image = loader.load("../data/singapore4k.test.ppm");

		//		RGBToYCbCrConverter converter1;
		//		converter1.convert(image);
		//
		//		image->print();
		//
		//		image->channel2->reduceBySubSampling( image->imageSize.width, image->imageSize.height );
		//		image->channel3->reduceBySubSampling( image->imageSize.width, image->imageSize.height );
		//
		//		YCbCrToRGBConverter converter2;
		//		converter2.convert(image);
		//
		//		image->reduceBySubSample(2, 2);
		//		image->reduceByAverage(2, 2);
		//		image->print();

		//		Test::performance([&loader, &image]{
		//			loader.write("data/output.test.ppm", image);
		//		});
	});
}

//  ---------------------------------------------------------------
// |
// |  JPEG Writer
// |
//  ---------------------------------------------------------------

void testJPEGWriter() {

	Bitstream bitStream;
	bitStream.add(1);
	bitStream.add(0);
	bitStream.add(1);
	bitStream.add(1);
	bitStream.add(0);
	bitStream.print();
	bitStream.fillup(1);
	bitStream.print();
	bitStream.saveToFile("out.txt");

	std::cout << "Testing, Bitstream" << std::endl;

	std::cout << "Write single bit: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [](size_t numberOfElements){
		Bitstream bitstream;
		while (numberOfElements--) {
			bitstream.add(numberOfElements % 2);
		}
	});

	std::cout << "Write byte bits: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [](size_t numberOfElements){
		Bitstream bitstream;
		// bitstream.add(1);
		while (numberOfElements--) {
			bitstream.add(0xd2, 8);
		}
	});

	// create random bitstream for reading
	Bitstream testStream;
	size_t fillRandom = TEST_ITERATIONS;
	while (fillRandom--)
		testStream.add( arc4random() % 2 );

	std::cout << "Read single bit: ";
	Test::performance(TEST_ITERATIONS, TEST_REPEAT, [&testStream](size_t numberOfElements){
		size_t maxRead = testStream.numberOfBits() - 2;
		size_t idx = 0;
		while (numberOfElements--) {
			testStream.read(idx++);
			if (idx > maxRead)
				idx = 0;
		}
	});

	std::cout << "Write file: ";
	Test::performance([&testStream] {
		testStream.saveToFile("data/writeOleg.txt");
	});

	PPMLoader loader;
	auto image = loader.load("data/very_small.ppm");

	JPEGWriter writer;
	writer.writeJPEGImage(image, "Test.test.jpg");
}

std::vector<Symbol> getWord() {
	std::vector<Symbol> input;
	input.push_back(1);
	input.push_back(4);
	input.push_back(6);

	return input;
}

void addTestSymbol(int amount, int symbol, std::vector<int> &input) {
	for (int i = 0; i < amount; ++i) {
		input.push_back(symbol);
	}
}

std::vector<int> generateTestHuffman() {
	std::vector<int>input;
	addTestSymbol(5, 1, input);
	addTestSymbol(12, 5, input);
	addTestSymbol(13, 6, input);
	addTestSymbol(6, 2, input);
	addTestSymbol(8, 3, input);
	addTestSymbol(8, 4, input);
	return input;
}

std::vector<int> generateTestHuffman2() {
	std::vector<int>input;
	addTestSymbol(5, 1, input);
	addTestSymbol(5, 2, input);
	addTestSymbol(6, 3, input);
	addTestSymbol(11, 4, input);
	addTestSymbol(12, 5, input);
	addTestSymbol(12, 6, input);
	addTestSymbol(26, 7, input);
	return input;
}

void testhuffmann() {
	std::vector<Symbol> testData;

	auto input = generateTestHuffman();

	Huffman huffman = Huffman(input);
	huffman.preventAllOnesPath(true);
//	auto encodingTable = huffman.canonicalEncoding();
	auto encodingTable = huffman.canonicalEncoding(4);
//	Node* rootTree = huffman.standardTree();
	Node* rootTree = huffman.treeFromEncodingTable(encodingTable);

	for (auto pair: encodingTable) {
		std::cout << pair.first << ": " << pair.second << std::endl;
	}
	rootTree->print();
	rootTree->exportTree();
	Bitstream bitsteam;
	std::vector<Symbol> word = getWord();
	for (int i = 0; i < word.size(); ++i) {
		Encoding enc = encodingTable.at(word[i]);
		std::cout << "füge " << enc << " hinzu (" << word[i] << ")" << std::endl;
		bitsteam.add(enc.code, enc.numberOfBits);
	}
	bitsteam.print();
}

void testDirectDCT() {
	Mat input;
	input.initiate((float[]){
		2, 2,
		2, 2
	}, 2, 2);

	DCT dct;
	Mat out = dct.transform(input);

	out.print();
}

void testIDCT() {
	Mat input;
	input.initiate((float[]){
		2, 2,
		2, 2
	}, 2, 2);

	DCT test;
	Mat out = test.transform2DDCT(input);

	Mat inverse = test.inverse(out);
	inverse.print();
}

void testMat() {
	Mat a;
	a.initiate((float[]){
		1, 2, 3,
		3, 1, 1}, 2 , 3);

	Mat b;
	b.initiate((float[]){
		2, 1,
		1, 2,
		2, 1
	}, 3 , 2);

	Mat c = a * b;
	c.print();
}

// ################################################################
// #
// #  Main
// #
// ################################################################

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

	//testhuffmann();
	//testJPEGWriter();

	//testDirectDCT();
	testIDCT();
//	testMat();
//	testImage();

	return 0;
}
<|endoftext|>


<commit_before>#include "Utils.h"

#include <SDL\SDL_timer.h>
#include <SOIL\SOIL.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

namespace cogs
{
		namespace utils
		{
				float getTime()
				{
						return static_cast<float>(SDL_GetTicks());
				}

				void sleep(const float _millis)
				{
						SDL_Delay(static_cast<Uint32>(_millis));
				}

				bool loadTexture(const char * _filePath, bool _alpha, int * _width, int * _height, unsigned int * _id)
				{
						unsigned char* image = SOIL_load_image(_filePath, _width, _height, 0, _alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);

						if (image == nullptr)
						{
								return false;
						}

						//Generate the openGL texture object
						glGenTextures(1, _id);

						//Bind the texture object
						glBindTexture(GL_TEXTURE_2D, *_id);

						//Upload the pixels to the texture
						glTexImage2D(GL_TEXTURE_2D, 0, _alpha ? GL_RGBA : GL_RGB, *_width, *_height, 0, _alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
						//Generate the mipmaps
						glGenerateMipmap(GL_TEXTURE_2D);

						//Set some texture parameters
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

						//Unbind the texture
						glBindTexture(GL_TEXTURE_2D, 0);

						SOIL_free_image_data(image);

						return true;
				}

				std::vector<graphics::Mesh> loadModel(const std::string & _filePath)
				{
						Assimp::Importer importer;

						const aiScene* scene = importer.ReadFile(_filePath.c_str(),
								aiProcess_Triangulate |
								aiProcess_GenSmoothNormals |
								aiProcess_FlipUVs |
								aiProcess_CalcTangentSpace);

						if (!scene)
						{
								printf("Mesh failed to load");
								assert(false);
						}

						const std::string directory = _filePath.substr(0, _filePath.find_last_of('/'));

						std::vector<graphics::Mesh> meshes;
						meshes.reserve(scene->mNumMeshes);

						for (unsigned int currMesh = 0; currMesh < scene->mNumMeshes; ++currMesh)
						{
								const aiMesh* mesh = scene->mMeshes[currMesh];

								std::vector<glm::vec3> positions(mesh->mNumVertices);
								std::vector<glm::vec2> uvs(mesh->mNumVertices);
								std::vector<glm::vec3> normals(mesh->mNumVertices);
								std::vector<glm::vec3> tangents(mesh->mNumVertices);
								std::vector<unsigned int> indices;
								indices.reserve(mesh->mNumFaces * 3);

								std::vector<graphics::GLTexture> textures;

								const aiVector3D aiZeroVector(0.0f, 0.0f, 0.0f);

								//load all the per-vertex data
								for (unsigned int currVert = 0; currVert < mesh->mNumVertices; ++currVert)
								{
										const aiVector3D pos = mesh->mVertices[currVert];
										const aiVector3D normal = mesh->mNormals[currVert];
										const aiVector3D uv = mesh->HasTextureCoords(0) ? mesh->mTextureCoords[0][currVert] : aiZeroVector;
										const aiVector3D tangent = mesh->mTangents[currVert];

										positions.at(currVert) = (glm::vec3(pos.x, pos.y, pos.z));
										uvs.at(currVert)							= (glm::vec2(uv.x, uv.y));
										normals.at(currVert)		 = (glm::vec3(normal.x, normal.y, normal.z));
										tangents.at(currVert)		= (glm::vec3(tangent.x, tangent.y, tangent.z));
								}

								//load all the indices for indexed rendering
								for (unsigned int currFace = 0; currFace < mesh->mNumFaces; ++currFace)
								{
										const aiFace& face = mesh->mFaces[currFace];
										assert(face.mNumIndices == 3);
										indices.push_back(face.mIndices[0]);
										indices.push_back(face.mIndices[1]);
										indices.push_back(face.mIndices[2]);
								}

								//load all the textures for this mesh
								if (mesh->mMaterialIndex > 0)
								{
										aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];

										auto loadMaterialTextures = [&directory](aiMaterial * _mat, const aiTextureType & _type, const std::string & _name)
										{
												std::vector<graphics::GLTexture> textures;

												for (GLuint i = 0; i < _mat->GetTextureCount(_type); i++)
												{
														aiString str;
														_mat->GetTexture(_type, i, &str);
														graphics::GLTexture texture(_name, directory + "/" + str.C_Str());
														textures.push_back(texture);
												}
												return textures;
										};

										// 1. Diffuse maps
										std::vector<graphics::GLTexture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
										textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());

										// 2. Specular maps
										std::vector<graphics::GLTexture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
										textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());

										// 3. Ambient maps
										std::vector<graphics::GLTexture> ambientMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_ambient");
										textures.insert(textures.end(), ambientMaps.begin(), ambientMaps.end());

										// 4. Normal maps
										std::vector<graphics::GLTexture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
										textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
								}

								meshes.emplace_back(indices, positions, uvs, normals, tangents, textures);
						}

						return meshes;
				}
		}
}<commit_msg>utils loadModel now loads textures as weak pointers to follow the new resource manager design<commit_after>#include "Utils.h"

#include "ResourceManager.h"

#include <SDL\SDL_timer.h>
#include <SOIL\SOIL.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <GL\glew.h>

namespace cogs
{
		namespace utils
		{
				float getTime()
				{
						return static_cast<float>(SDL_GetTicks());
				}

				void sleep(const float _millis)
				{
						SDL_Delay(static_cast<Uint32>(_millis));
				}

				bool loadTexture(const char * _filePath, bool _alpha, int * _width, int * _height, unsigned int * _id)
				{
						unsigned char* image = SOIL_load_image(_filePath, _width, _height, 0, _alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);

						if (image == nullptr)
						{
								return false;
						}

						//Generate the openGL texture object
						glGenTextures(1, _id);

						//Bind the texture object
						glBindTexture(GL_TEXTURE_2D, *_id);

						//Upload the pixels to the texture
						glTexImage2D(GL_TEXTURE_2D, 0, _alpha ? GL_RGBA : GL_RGB, *_width, *_height, 0, _alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
						//Generate the mipmaps
						glGenerateMipmap(GL_TEXTURE_2D);

						//Set some texture parameters
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

						//Unbind the texture
						glBindTexture(GL_TEXTURE_2D, 0);

						SOIL_free_image_data(image);

						return true;
				}

				std::vector<graphics::Mesh> loadModel(const std::string & _filePath)
				{
						Assimp::Importer importer;

						const aiScene* scene = importer.ReadFile(_filePath.c_str(),
								aiProcess_Triangulate |
								aiProcess_GenSmoothNormals |
								aiProcess_FlipUVs |
								aiProcess_CalcTangentSpace);

						if (!scene)
						{
								printf("Mesh failed to load");
								assert(false);
						}

						const std::string directory = _filePath.substr(0, _filePath.find_last_of('/'));

						std::vector<graphics::Mesh> meshes;
						meshes.reserve(scene->mNumMeshes);

						for (unsigned int currMesh = 0; currMesh < scene->mNumMeshes; ++currMesh)
						{
								const aiMesh* mesh = scene->mMeshes[currMesh];

								std::vector<glm::vec3> positions(mesh->mNumVertices);
								std::vector<glm::vec2> uvs(mesh->mNumVertices);
								std::vector<glm::vec3> normals(mesh->mNumVertices);
								std::vector<glm::vec3> tangents(mesh->mNumVertices);
								std::vector<unsigned int> indices;
								indices.reserve(mesh->mNumFaces * 3);

								std::vector<std::weak_ptr<graphics::GLTexture2D>> textures;

								const aiVector3D aiZeroVector(0.0f, 0.0f, 0.0f);

								//load all the per-vertex data
								for (unsigned int currVert = 0; currVert < mesh->mNumVertices; ++currVert)
								{
										const aiVector3D pos = mesh->mVertices[currVert];
										const aiVector3D normal = mesh->mNormals[currVert];
										const aiVector3D uv = mesh->HasTextureCoords(0) ? mesh->mTextureCoords[0][currVert] : aiZeroVector;
										const aiVector3D tangent = mesh->mTangents[currVert];

										positions.at(currVert) = (glm::vec3(pos.x, pos.y, pos.z));
										uvs.at(currVert)							= (glm::vec2(uv.x, uv.y));
										normals.at(currVert)		 = (glm::vec3(normal.x, normal.y, normal.z));
										tangents.at(currVert)		= (glm::vec3(tangent.x, tangent.y, tangent.z));
								}

								//load all the indices for indexed rendering
								for (unsigned int currFace = 0; currFace < mesh->mNumFaces; ++currFace)
								{
										const aiFace& face = mesh->mFaces[currFace];
										assert(face.mNumIndices == 3);
										indices.push_back(face.mIndices[0]);
										indices.push_back(face.mIndices[1]);
										indices.push_back(face.mIndices[2]);
								}

								//load all the textures for this mesh
								if (mesh->mMaterialIndex > 0)
								{
										aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];

										auto loadMaterialTextures = [&directory](aiMaterial * _mat, const aiTextureType & _type, const std::string & _name)
										{
												std::vector<std::weak_ptr<graphics::GLTexture2D>> textures;

												for (size_t i = 0; i < _mat->GetTextureCount(_type); i++)
												{
														aiString str;
														_mat->GetTexture(_type, i, &str);
														std::weak_ptr<graphics::GLTexture2D> texture = ResourceManager::getGLTexture2D(directory + "/" + str.C_Str(), _name);
														textures.push_back(texture);
												}
												return textures;
										};

										// 1. Diffuse maps
										std::vector<std::weak_ptr<graphics::GLTexture2D>> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
										textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());

										// 2. Specular maps
										std::vector<std::weak_ptr<graphics::GLTexture2D>> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
										textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());

										// 3. Ambient maps
										std::vector<std::weak_ptr<graphics::GLTexture2D>> ambientMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_ambient");
										textures.insert(textures.end(), ambientMaps.begin(), ambientMaps.end());

										// 4. Normal maps
										std::vector<std::weak_ptr<graphics::GLTexture2D>> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
										textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
								}

								meshes.emplace_back(indices, positions, uvs, normals, tangents, textures);
						}

						return meshes;
				}
		}
}<|endoftext|>


<commit_before>/* Copyright (c) 2008-2017 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "command.h"
#include "progressbar.h"
#include "header.h"
#include "dwi/directions/file.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"

using namespace MR;
using namespace App;

void usage ()
{
  AUTHOR = "J-Donald Tournier (jdtournier@gmail.com)";

  SYNOPSIS = "Report statistics on a direction set";

  DESCRIPTION
    + "This command will accept as inputs:"
    + "- directions file in spherical coordinates (ASCII text, [ az el ] space-separated values, one per line);"
    + "- directions file in Cartesian coordinates (ASCII text, [ x y z ] space-separated values, one per line);"
    + "- DW gradient files (MRtrix format: ASCII text, [ x y z b ] space-separated values, one per line);"
    + "- image files, using the DW gradient scheme found in the header (or provided using the appropriate command line options below)."

    + "By default, this produces all relevant metrics for the direction set "
    "provided. If the direction set contains multiple shells, metrics are "
    "provided for each shell separately."

    + "Metrics are produced assuming a unipolar or bipolar electrostatic "
    "repulsion model, producing the potential energy (total, mean, min & max), "
    "and the nearest-neighbour angles (mean, min & max). The condition "
    "number is also produced for the spherical harmonic fits up to the highest "
    "harmonic order supported by the number of volumes. Finally, the norm of the "
    "mean direction vector is provided as a measure of the overall symmetry of "
    "the direction set (important with respect to eddy-current resilience)."

    + "Specific metrics can also be queried independently via the \"-output\" "
    "option, using these shorthands: U/B for unipolar/bipolar model, E/N "
    "for energy and nearest-neighbour respectively, t/-/+ for total/min/max "
    "respectively (mean implied otherwise); SHn for condition number of SH fit "
    "at order n (with n an even integer); ASYM for asymmetry index (norm of "
    "mean direction vector); and N for the number of directions. For example:"
    + "-output BN,BN-,BN+   requests the mean, min and max nearest-neighour "
    "angles assuming a bipolar model."
    + "-output UE,SH8,SYM   requests the mean unipolar electrostatic energy, "
    "condition number of SH fit at order 8, and the asymmetry index.";

  ARGUMENTS
    + Argument ("dirs", "the text file or image containing the directions.").type_file_in();

  OPTIONS
    + Option ("output", "output selected metrics as a space-delimited list, "
        "suitable for use in scripts. This will produce one line of values per "
        "selected shell. Valid metrics are as specified in the description "
        "above.")
    +   Argument ("list")
    + DWI::ShellsOption
    + DWI::GradImportOptions();
}

int precision = 6;

void report (const std::string& title, Eigen::MatrixXd& directions);

void run ()
{
  Eigen::MatrixXd directions;

  try {
    directions = DWI::Directions::load_cartesian (argument[0]);
  }
  catch (Exception& E) {
    try {
      directions = load_matrix<double> (argument[0]);
    }
    catch (Exception& E) {
      auto header = Header::open (argument[0]);
      directions = DWI::get_valid_DW_scheme (header);
    }
  }

  if (directions.cols() >= 4) {
    int n_start = 0;
    auto shells = DWI::Shells (directions).select_shells (false, false, false);
    if (get_options ("shells").empty() && shells.has_bzero() && shells.count() > 1) {
      n_start = 1;
      if (get_options("output").empty())
        print (std::string (argument[0]) + " (b=0) [ " + str(shells.smallest().count(), precision) + " volumes ]\n\n");
    }

    Eigen::MatrixXd dirs;

    for (size_t n = n_start; n < shells.count(); ++n) {
      dirs.resize (shells[n].count(), 3);
      for (size_t idx = 0; idx < shells[n].count(); ++idx)
        dirs.row (idx) = directions.row (shells[n].get_volumes()[idx]).head (3);

      report (std::string (argument[0]) + " (b=" + str(shells[n].get_mean()) + ")", dirs);
    }

  }
  else
    report (argument[0], directions);
}

vector<default_type> summarise_NN (const vector<double>& NN)
{
  double NN_min = std::numeric_limits<double>::max();
  double NN_mean = 0.0;
  double NN_max = 0.0;
  for (auto a : NN) {
    a = (180.0/Math::pi) * std::acos (a);
    NN_mean += a;
    NN_min = std::min (NN_min, a);
    NN_max = std::max (NN_max, a);
  }
  NN_mean /= NN.size();

  return { NN_mean, NN_min, NN_max };
}

vector<default_type> summarise_E (const vector<double>& E)
{
  double E_min = std::numeric_limits<double>::max();
  double E_total = 0.0;
  double E_max = 0.0;
  for (auto e : E) {
    E_total += e;
    E_min = std::min (E_min, e);
    E_max = std::max (E_max, e);
  }

  return { 0.5*E_total, E_total/E.size(), E_min, E_max };
}

class Metrics {
  public:
    vector<default_type> BN, UN, BE, UE, SH;
    default_type ASYM;
    size_t ndirs;
};

Metrics compute (Eigen::MatrixXd& directions)
{
  if (directions.cols() < 3)
    throw Exception ("unexpected matrix size for scheme \"" + str(argument[0]) + "\"");
  DWI::normalise_grad (directions);

  vector<double> NN_bipolar (directions.rows(), -1.0);
  vector<double> NN_unipolar (directions.rows(), -1.0);

  vector<double> E_bipolar (directions.rows(), 0.0);
  vector<double> E_unipolar (directions.rows(), 0.0);

  for (ssize_t i = 0; i < directions.rows()-1; ++i) {
    for (ssize_t j = i+1; j < directions.rows(); ++j) {
      double cos_angle = directions.row(i).head(3).normalized().dot (directions.row(j).head(3).normalized());
      NN_unipolar[i] = std::max (NN_unipolar[i], cos_angle);
      NN_unipolar[j] = std::max (NN_unipolar[j], cos_angle);
      cos_angle = std::abs (cos_angle);
      NN_bipolar[i] = std::max (NN_bipolar[i], cos_angle);
      NN_bipolar[j] = std::max (NN_bipolar[j], cos_angle);

      double E = 1.0 / (directions.row(i).head(3) - directions.row(j).head(3)).norm();

      E_unipolar[i] += E;
      E_unipolar[j] += E;

      E += 1.0 / (directions.row(i).head(3) + directions.row(j).head(3)).norm();

      E_bipolar[i] += E;
      E_bipolar[j] += E;

    }
  }

  Metrics metrics;
  metrics.ndirs = directions.rows();
  metrics.UN = summarise_NN (NN_unipolar);
  metrics.BN = summarise_NN (NN_bipolar);
  metrics.UE = summarise_E (E_unipolar);
  metrics.BE = summarise_E (E_bipolar);

  for (size_t lmax = 2; lmax <= Math::SH::LforN (directions.rows()); lmax += 2)
    metrics.SH.push_back (DWI::condition_number_for_lmax (directions, lmax));

  metrics.ASYM = directions.leftCols(3).colwise().mean().norm();

  return metrics;
}

void output_selected (const Metrics& metrics, const std::string& selection)
{
  auto select = split (selection, ", \t\n", true);

  for (const auto& x : select) {
    const auto xl = lowercase(x);
    if (xl == "uet")       std::cout << metrics.UE[0] << " ";
    else if (xl == "ue")   std::cout << metrics.UE[1] << " ";
    else if (xl == "ue-")  std::cout << metrics.UE[2] << " ";
    else if (xl == "ue+")  std::cout << metrics.UE[3] << " ";
    else if (xl == "bet")  std::cout << metrics.BE[0] << " ";
    else if (xl == "be")   std::cout << metrics.BE[1] << " ";
    else if (xl == "be-")  std::cout << metrics.BE[2] << " ";
    else if (xl == "be+")  std::cout << metrics.BE[3] << " ";
    else if (xl == "un")   std::cout << metrics.UN[0] << " ";
    else if (xl == "un-")  std::cout << metrics.UN[1] << " ";
    else if (xl == "un+")  std::cout << metrics.UN[2] << " ";
    else if (xl == "bn")   std::cout << metrics.BN[0] << " ";
    else if (xl == "bn-")  std::cout << metrics.BN[1] << " ";
    else if (xl == "bn+")  std::cout << metrics.BN[2] << " ";
    else if (xl == "asym") std::cout << metrics.ASYM << " ";
    else if (xl == "n")    std::cout << metrics.ndirs << " ";
    else if (xl.substr(0,2) == "sh") {
      size_t order = to<size_t>(x.substr(2));
      if (order & 1U || order < 2)
        throw Exception ("spherical harmonic order must be an even positive integer");
      order = (order/2)-1;
      if (order >= metrics.SH.size())
        throw Exception ("spherical harmonic order requested is too large given number of directions");
      std::cout << metrics.SH[order] << " ";
    }
    else
      throw Exception ("unknown output specifier \"" + x + "\"");
  }

  std::cout << "\n";
}

void report (const std::string& title, Eigen::MatrixXd& directions)
{
  auto metrics = compute (directions);

  auto opt = get_options ("output");
  if (opt.size()) {
    output_selected (metrics, opt[0][0]);
    return;
  }

  std::string output = title + " [ " + str(metrics.ndirs, precision) + " directions ]\n";

  output += "\n  Bipolar electrostatic repulsion model:\n";
  output += "    nearest-neighbour angles: mean = " + str(metrics.BN[0], precision) + ", range [ " + str(metrics.BN[1], precision) + " - " + str(metrics.BN[2], precision) + " ]\n";
  output += "    energy: total = " + str(metrics.BE[0], precision) + ", mean = " + str(metrics.BE[1], precision) + ", range [ " + str(metrics.BE[2], precision) + " - " + str(metrics.BE[3], precision) + " ]\n";

  output += "\n  Unipolar electrostatic repulsion model:\n";
  output += "    nearest-neighbour angles: mean = " + str(metrics.UN[0], precision) + ", range [ " + str(metrics.UN[1], precision) + " - " + str(metrics.UN[2], precision) + " ]\n";
  output += "    energy: total = " + str(metrics.UE[0], precision) + ", mean = " + str(metrics.UE[1], precision) + ", range [ " + str(metrics.UE[2], precision) + " - " + str(metrics.UE[3], precision) + " ]\n";

  output += "\n  Spherical Harmonic fit:\n    condition numbers for lmax = 2 -> " + str(metrics.SH.size()*2) + ": " + str(metrics.SH, precision) + "\n";

  output += "\n  Asymmetry of sampling:\n    norm of mean direction vector = " + str(metrics.ASYM, precision) + "\n";
  if (metrics.ASYM >= 0.1)
    output += std::string("    WARNING: sampling is ") + ( metrics.ASYM >= 0.4 ? "strongly" : "moderately" )
            + " asymmetric - this may affect resiliance to eddy-current distortions\n";

  output += "\n";
  print (output);
}

<commit_msg>dirstat: fix memalign issue<commit_after>/* Copyright (c) 2008-2017 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "command.h"
#include "progressbar.h"
#include "header.h"
#include "dwi/directions/file.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"

using namespace MR;
using namespace App;

void usage ()
{
  AUTHOR = "J-Donald Tournier (jdtournier@gmail.com)";

  SYNOPSIS = "Report statistics on a direction set";

  DESCRIPTION
    + "This command will accept as inputs:"
    + "- directions file in spherical coordinates (ASCII text, [ az el ] space-separated values, one per line);"
    + "- directions file in Cartesian coordinates (ASCII text, [ x y z ] space-separated values, one per line);"
    + "- DW gradient files (MRtrix format: ASCII text, [ x y z b ] space-separated values, one per line);"
    + "- image files, using the DW gradient scheme found in the header (or provided using the appropriate command line options below)."

    + "By default, this produces all relevant metrics for the direction set "
    "provided. If the direction set contains multiple shells, metrics are "
    "provided for each shell separately."

    + "Metrics are produced assuming a unipolar or bipolar electrostatic "
    "repulsion model, producing the potential energy (total, mean, min & max), "
    "and the nearest-neighbour angles (mean, min & max). The condition "
    "number is also produced for the spherical harmonic fits up to the highest "
    "harmonic order supported by the number of volumes. Finally, the norm of the "
    "mean direction vector is provided as a measure of the overall symmetry of "
    "the direction set (important with respect to eddy-current resilience)."

    + "Specific metrics can also be queried independently via the \"-output\" "
    "option, using these shorthands: U/B for unipolar/bipolar model, E/N "
    "for energy and nearest-neighbour respectively, t/-/+ for total/min/max "
    "respectively (mean implied otherwise); SHn for condition number of SH fit "
    "at order n (with n an even integer); ASYM for asymmetry index (norm of "
    "mean direction vector); and N for the number of directions. For example:"
    + "-output BN,BN-,BN+   requests the mean, min and max nearest-neighour "
    "angles assuming a bipolar model."
    + "-output UE,SH8,SYM   requests the mean unipolar electrostatic energy, "
    "condition number of SH fit at order 8, and the asymmetry index.";

  ARGUMENTS
    + Argument ("dirs", "the text file or image containing the directions.").type_file_in();

  OPTIONS
    + Option ("output", "output selected metrics as a space-delimited list, "
        "suitable for use in scripts. This will produce one line of values per "
        "selected shell. Valid metrics are as specified in the description "
        "above.")
    +   Argument ("list")
    + DWI::ShellsOption
    + DWI::GradImportOptions();
}

int precision = 6;

void report (const std::string& title, Eigen::MatrixXd& directions);

void run ()
{
  Eigen::MatrixXd directions;

  try {
    directions = DWI::Directions::load_cartesian (argument[0]);
  }
  catch (Exception& E) {
    try {
      directions = load_matrix<double> (argument[0]);
    }
    catch (Exception& E) {
      auto header = Header::open (argument[0]);
      directions = DWI::get_valid_DW_scheme (header);
    }
  }

  if (directions.cols() >= 4) {
    int n_start = 0;
    auto shells = DWI::Shells (directions).select_shells (false, false, false);
    if (get_options ("shells").empty() && shells.has_bzero() && shells.count() > 1) {
      n_start = 1;
      if (get_options("output").empty())
        print (std::string (argument[0]) + " (b=0) [ " + str(shells.smallest().count(), precision) + " volumes ]\n\n");
    }

    Eigen::MatrixXd dirs;

    for (size_t n = n_start; n < shells.count(); ++n) {
      dirs.resize (shells[n].count(), 3);
      for (size_t idx = 0; idx < shells[n].count(); ++idx)
        dirs.row (idx) = directions.row (shells[n].get_volumes()[idx]).head (3);

      report (std::string (argument[0]) + " (b=" + str(shells[n].get_mean()) + ")", dirs);
    }

  }
  else
    report (argument[0], directions);
}

vector<default_type> summarise_NN (const vector<double>& NN)
{
  double NN_min = std::numeric_limits<double>::max();
  double NN_mean = 0.0;
  double NN_max = 0.0;
  for (auto a : NN) {
    a = (180.0/Math::pi) * std::acos (a);
    NN_mean += a;
    NN_min = std::min (NN_min, a);
    NN_max = std::max (NN_max, a);
  }
  NN_mean /= NN.size();

  return { NN_mean, NN_min, NN_max };
}

vector<default_type> summarise_E (const vector<double>& E)
{
  double E_min = std::numeric_limits<double>::max();
  double E_total = 0.0;
  double E_max = 0.0;
  for (auto e : E) {
    E_total += e;
    E_min = std::min (E_min, e);
    E_max = std::max (E_max, e);
  }

  return { 0.5*E_total, E_total/E.size(), E_min, E_max };
}

class Metrics
{ MEMALIGN (Metrics)
  public:
    vector<default_type> BN, UN, BE, UE, SH;
    default_type ASYM;
    size_t ndirs;
};

Metrics compute (Eigen::MatrixXd& directions)
{
  if (directions.cols() < 3)
    throw Exception ("unexpected matrix size for scheme \"" + str(argument[0]) + "\"");
  DWI::normalise_grad (directions);

  vector<double> NN_bipolar (directions.rows(), -1.0);
  vector<double> NN_unipolar (directions.rows(), -1.0);

  vector<double> E_bipolar (directions.rows(), 0.0);
  vector<double> E_unipolar (directions.rows(), 0.0);

  for (ssize_t i = 0; i < directions.rows()-1; ++i) {
    for (ssize_t j = i+1; j < directions.rows(); ++j) {
      double cos_angle = directions.row(i).head(3).normalized().dot (directions.row(j).head(3).normalized());
      NN_unipolar[i] = std::max (NN_unipolar[i], cos_angle);
      NN_unipolar[j] = std::max (NN_unipolar[j], cos_angle);
      cos_angle = std::abs (cos_angle);
      NN_bipolar[i] = std::max (NN_bipolar[i], cos_angle);
      NN_bipolar[j] = std::max (NN_bipolar[j], cos_angle);

      double E = 1.0 / (directions.row(i).head(3) - directions.row(j).head(3)).norm();

      E_unipolar[i] += E;
      E_unipolar[j] += E;

      E += 1.0 / (directions.row(i).head(3) + directions.row(j).head(3)).norm();

      E_bipolar[i] += E;
      E_bipolar[j] += E;

    }
  }

  Metrics metrics;
  metrics.ndirs = directions.rows();
  metrics.UN = summarise_NN (NN_unipolar);
  metrics.BN = summarise_NN (NN_bipolar);
  metrics.UE = summarise_E (E_unipolar);
  metrics.BE = summarise_E (E_bipolar);

  for (size_t lmax = 2; lmax <= Math::SH::LforN (directions.rows()); lmax += 2)
    metrics.SH.push_back (DWI::condition_number_for_lmax (directions, lmax));

  metrics.ASYM = directions.leftCols(3).colwise().mean().norm();

  return metrics;
}

void output_selected (const Metrics& metrics, const std::string& selection)
{
  auto select = split (selection, ", \t\n", true);

  for (const auto& x : select) {
    const auto xl = lowercase(x);
    if (xl == "uet")       std::cout << metrics.UE[0] << " ";
    else if (xl == "ue")   std::cout << metrics.UE[1] << " ";
    else if (xl == "ue-")  std::cout << metrics.UE[2] << " ";
    else if (xl == "ue+")  std::cout << metrics.UE[3] << " ";
    else if (xl == "bet")  std::cout << metrics.BE[0] << " ";
    else if (xl == "be")   std::cout << metrics.BE[1] << " ";
    else if (xl == "be-")  std::cout << metrics.BE[2] << " ";
    else if (xl == "be+")  std::cout << metrics.BE[3] << " ";
    else if (xl == "un")   std::cout << metrics.UN[0] << " ";
    else if (xl == "un-")  std::cout << metrics.UN[1] << " ";
    else if (xl == "un+")  std::cout << metrics.UN[2] << " ";
    else if (xl == "bn")   std::cout << metrics.BN[0] << " ";
    else if (xl == "bn-")  std::cout << metrics.BN[1] << " ";
    else if (xl == "bn+")  std::cout << metrics.BN[2] << " ";
    else if (xl == "asym") std::cout << metrics.ASYM << " ";
    else if (xl == "n")    std::cout << metrics.ndirs << " ";
    else if (xl.substr(0,2) == "sh") {
      size_t order = to<size_t>(x.substr(2));
      if (order & 1U || order < 2)
        throw Exception ("spherical harmonic order must be an even positive integer");
      order = (order/2)-1;
      if (order >= metrics.SH.size())
        throw Exception ("spherical harmonic order requested is too large given number of directions");
      std::cout << metrics.SH[order] << " ";
    }
    else
      throw Exception ("unknown output specifier \"" + x + "\"");
  }

  std::cout << "\n";
}

void report (const std::string& title, Eigen::MatrixXd& directions)
{
  auto metrics = compute (directions);

  auto opt = get_options ("output");
  if (opt.size()) {
    output_selected (metrics, opt[0][0]);
    return;
  }

  std::string output = title + " [ " + str(metrics.ndirs, precision) + " directions ]\n";

  output += "\n  Bipolar electrostatic repulsion model:\n";
  output += "    nearest-neighbour angles: mean = " + str(metrics.BN[0], precision) + ", range [ " + str(metrics.BN[1], precision) + " - " + str(metrics.BN[2], precision) + " ]\n";
  output += "    energy: total = " + str(metrics.BE[0], precision) + ", mean = " + str(metrics.BE[1], precision) + ", range [ " + str(metrics.BE[2], precision) + " - " + str(metrics.BE[3], precision) + " ]\n";

  output += "\n  Unipolar electrostatic repulsion model:\n";
  output += "    nearest-neighbour angles: mean = " + str(metrics.UN[0], precision) + ", range [ " + str(metrics.UN[1], precision) + " - " + str(metrics.UN[2], precision) + " ]\n";
  output += "    energy: total = " + str(metrics.UE[0], precision) + ", mean = " + str(metrics.UE[1], precision) + ", range [ " + str(metrics.UE[2], precision) + " - " + str(metrics.UE[3], precision) + " ]\n";

  output += "\n  Spherical Harmonic fit:\n    condition numbers for lmax = 2 -> " + str(metrics.SH.size()*2) + ": " + str(metrics.SH, precision) + "\n";

  output += "\n  Asymmetry of sampling:\n    norm of mean direction vector = " + str(metrics.ASYM, precision) + "\n";
  if (metrics.ASYM >= 0.1)
    output += std::string("    WARNING: sampling is ") + ( metrics.ASYM >= 0.4 ? "strongly" : "moderately" )
            + " asymmetric - this may affect resiliance to eddy-current distortions\n";

  output += "\n";
  print (output);
}

<|endoftext|>


<commit_before>// File: btBoostDynamics.hpp
#ifndef _btBoostDynamics_hpp
#define _btBoostDynamics_hpp

#include "btBoostDynamicsDbvtBroadphase.hpp"
#include "btBoostDynamicsDefaultCollisionConfiguration.hpp"
#include "btBoostDynamicsCollisionDispatcher.hpp"
#include "btBoostDynamicsSequentialImpulseConstraintSolver.hpp"
#include "btBoostDynamicsDiscreteDynamicsWorld.hpp"
#include "btBoostDynamicsShapes.hpp"
#include "btBoostDynamicsRigidBody.hpp"

void defineDynamics()
{
    defineDbvtBroadphase();
    defineDefaultCollisionConfiguration();
    defineCollisionDispatcher();
    defineSequentialImpulseConstraintSolver();
    defineDiscreteDynamicsWorld();
    defineShapes();
    defineRigidBody();
}

#endif // _btBoostDynamics_hpp
<commit_msg>Add call to define pair caches<commit_after>// File: btBoostDynamics.hpp
#ifndef _btBoostDynamics_hpp
#define _btBoostDynamics_hpp

#include "btBoostDynamicsDbvtBroadphase.hpp"
#include "btBoostDynamicsDefaultCollisionConfiguration.hpp"
#include "btBoostDynamicsCollisionDispatcher.hpp"
#include "btBoostDynamicsSequentialImpulseConstraintSolver.hpp"
#include "btBoostDynamicsDiscreteDynamicsWorld.hpp"
#include "btBoostDynamicsShapes.hpp"
#include "btBoostDynamicsRigidBody.hpp"
#include "btBoostCollisionOverLappingPairCache.hpp"

void defineDynamics()
{
    defineDbvtBroadphase();
    defineDefaultCollisionConfiguration();
    defineCollisionDispatcher();
    defineSequentialImpulseConstraintSolver();
    defineDiscreteDynamicsWorld();
    defineShapes();
    defineRigidBody();
    defineOverlappingPairCaches();
}

#endif // _btBoostDynamics_hpp
<|endoftext|>