<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// common goes first
#include "common.h"

// implementation header
#include "LinkManager.h"

// system headers
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <vector>
#include <iostream>

// common headers
#include "Pack.h"
#include "Teleporter.h"
#include "ObstacleMgr.h"

// simple globbing routines
static int match_object_name (const char *string, const char *objname);
static int match_multi (const char **string, const char **objname);
static const char MATCH_MULTI  = '*'; // matches any number of characters
static const char MATCH_SINGLE = '?'; // matches a single character

LinkManager::LinkManager()
{
  // do nothing
  return;
}

LinkManager::~LinkManager()
{
  clear();
  return;
}

void LinkManager::clear()
{
  linkNames.clear();
  linkNumbers.clear();
  return;
}

void LinkManager::makeLinkName(int number, std::string& name)
{
  name = "/t";
  char buffer[8];
  sprintf(buffer, "%i", (number / 2));
  name += buffer;
  name += ":";
  if ((number % 2) == 0) {
    name += "f";
  } else {
    name += "b";
  }
  return;
}

void LinkManager::addLink(int src, int dst)
{
  LinkNameSet link;
  makeLinkName(src, link.src);
  makeLinkName(dst, link.dst);
  linkNames.push_back(link);
  return;
}

void LinkManager::addLink(const std::string& src, const std::string& dst)
{
  LinkNameSet link;
  if ((src[0] >= '0') && (src[0] <= '9')) {
    int number = atoi(src.c_str());
    makeLinkName(number, link.src);
  } else {
    link.src = src;
  }
  if ((dst[0] >= '0') && (dst[0] <= '9')) {
    int number = atoi(dst.c_str());
    makeLinkName(number, link.dst);
  } else {
    link.dst = dst;
  }
  linkNames.push_back(link);
  return;
}

static bool inIntList(int value, const std::vector<int>& list)
{
  for (unsigned int i = 0; i < list.size(); i++) {
    if (value == list[i]) {
      return true;
    }
  }
  return false;
}

void LinkManager::doLinking()
{
  unsigned int i;

  // initial the destinations
  const ObstacleList& teles = OBSTACLEMGR.getTeles();
  // findTelesByName() can not return higher then this
  linkNumbers.resize(teles.size() * 2);
  for (i = 0; i < linkNumbers.size(); i++) {
    linkNumbers[i].dsts.clear();
  }

  for (i = 0; i < linkNames.size(); i++) {
    LinkNameSet& link = linkNames[i];
    std::vector<int> srcNumbers;
    std::vector<int> dstNumbers;
    findTelesByName(link.src, srcNumbers);
    findTelesByName(link.dst, dstNumbers);

    bool broken = false;
    if (srcNumbers.size() <= 0) {
      broken = true;
      DEBUG1("broken link src: %s\n", link.src.c_str());
    }
    if (dstNumbers.size() <= 0) {
      broken = true;
      DEBUG1("broken link dst: %s\n", link.dst.c_str());
    }
    if (broken) {
      continue;
    }

    for (unsigned s = 0; s < srcNumbers.size(); s++) {
      for (unsigned d = 0; d < dstNumbers.size(); d++) {
	std::vector<int>& dstsList = linkNumbers[srcNumbers[s]].dsts;
	if (!inIntList(dstNumbers[d], dstsList)) { // no duplicates
	  dstsList.push_back(dstNumbers[d]);
	}
      }
    }
  }

  // fill in the blanks (passthru linkage)
  for (i = 0; i < linkNumbers.size(); i++) {
    std::vector<int>& dstsList = linkNumbers[i].dsts;
    if (dstsList.size() <= 0) {
      const int t = (i / 2) * 2; // tele number
      const int f = 1 - (i % 2); // opposite link
      dstsList.push_back(t + f);
    }
  }

  if (debugLevel >= 4) {
    for (i = 0; i < teles.size(); i++) {
      Teleporter* tele = (Teleporter*) teles[i];
      printf ("TELE(%i): %s\n", i, tele->getName().c_str());
    }
    for (i = 0; i < linkNames.size(); i++) {
      LinkNameSet& link = linkNames[i];
      printf ("LINKSRC: %-32sLINKDST: %s\n", link.src.c_str(), link.dst.c_str());
    }
    for (i = 0; i < linkNumbers.size(); i++) {
      printf ("SRC %3i%c:  DSTS", (i / 2), ((i % 2) == 0) ? 'f' : 'b');
      for (unsigned int j = 0; j < linkNumbers[i].dsts.size(); j++) {
	int dst = linkNumbers[i].dsts[j];
	printf (" %i%c", (dst / 2), ((dst % 2) == 0) ? 'f' : 'b');
      }
      printf ("\n");
    }
  }

  return;
}

void LinkManager::findTelesByName(const std::string& name,
				  std::vector<int>& list) const
{
  list.clear();

  std::string glob = name;

  // no chars, no service
  if (glob.size() <= 0) {
    return;
  }

  // a leading ':' might be used to indicate absolute linking if
  // links are ever included in group definintions. strip it here
  // for forwards compatibiliy.
  if (glob[0] == ':') {
    glob.erase(0, 1); // erase 1 char from position 0
  }

  // make the trailing face specification case-independent
  const unsigned int last = glob.size() - 1;
  if ((glob[last] == 'F') || (glob[last] == 'B')) {
    glob[last] = tolower(glob[last]);
  }

  // add all teleporters that have matching names
  const ObstacleList& teles = OBSTACLEMGR.getTeles();
  for (unsigned int i = 0; i < teles.size(); i++) {
    Teleporter* tele = (Teleporter*) teles[i];
    const std::string& teleName = tele->getName();

    std::string front = teleName;
    front += ":f";
    if (match_object_name(glob.c_str(), front.c_str())) {
      list.push_back((int)(i * 2) + 0);
    }

    std::string back = teleName;
    back += ":b";
    if (match_object_name(glob.c_str(), back.c_str())) {
      list.push_back((int)(i * 2) + 1);
    }
  }

  return;
}

int LinkManager::getTeleportTarget(int source) const
{
  assert(source < (int)(2 * OBSTACLEMGR.getTeles().size()));

  const std::vector<int>& dstsList = linkNumbers[source].dsts;

  if (dstsList.size() == 1) {
    return dstsList[0];
  }
  else if (dstsList.size() > 1) {
    int target = rand() % int(dstsList.size());
    return dstsList[target];
  }
  else {
    assert(false);
    return 0;
  }
}

int LinkManager::getTeleportTarget(int source, unsigned int seed) const
{
  assert(source < (int)(2 * OBSTACLEMGR.getTeles().size()));

  const std::vector<int>& dstsList = linkNumbers[source].dsts;

  if (dstsList.size() == 1) {
    return dstsList[0];
  }
  else if (dstsList.size() > 1) {
    seed = (seed * 1103515245 + 12345) >> 8; // from POSIX rand() example
    seed = seed % (dstsList.size());
    return dstsList[seed];
  }
  else {
    assert(false);
    return 0;
  }
}

void* LinkManager::pack(void* buf) const
{
  buf = nboPackUInt(buf, (uint32_t) linkNames.size());
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    buf = nboPackStdString(buf, linkNames[i].src);
    buf = nboPackStdString(buf, linkNames[i].dst);
  }
  return buf;
}

void* LinkManager::unpack(void* buf)
{
  clear(); // just in case
  unsigned int i;
  uint32_t count;
  buf = nboUnpackUInt(buf, count);
  for (i = 0; i < count; i++) {
    LinkNameSet link;
    buf = nboUnpackStdString(buf, link.src);
    buf = nboUnpackStdString(buf, link.dst);
    linkNames.push_back(link);
  }
  return buf;
}

void LinkManager::print(std::ostream& out, const std::string& indent) const
{
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    const LinkNameSet& link = linkNames[i];
    out << indent << "link" << std::endl;
    out << indent << "  from " << link.src << std::endl;
    out << indent << "  to   " << link.dst << std::endl;
    out << indent << "end" << std::endl << std::endl;
  }
  return;
}

int LinkManager::packSize() const
{
  int fullSize = sizeof(uint32_t);
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    fullSize += nboStdStringPackSize(linkNames[i].src);
    fullSize += nboStdStringPackSize(linkNames[i].dst);
  }
  return fullSize;
}

/******************************************************************************/

static int match_object_name (const char *string, const char *objname)
{
  if (string == NULL) {
    return 0;
  }
  if (objname == NULL) {
    return 0;
  }

  if ((string[0] == MATCH_MULTI) && (string[1] == '\0')) {
    return 1;
  }

  while (*string != '\0') {
    if (*string == MATCH_MULTI) {
      string++;
      switch (match_multi (&string, &objname)) {
	case +1: {
	  return 1;
	}
	case -1: {
	  return 0;
	}
      }
    }
    else if (*objname == '\0') {
      return 0;
    }
    else if ((*string == MATCH_SINGLE) || (*string == *objname)) {
      string++;
      objname++;
    }
    else {
      return 0;
    }
  }

  if (*objname == '\0') {
    return 1;
  } else {
    return 0;
  }
}

/******************************************************************************/

static int match_multi (const char **string, const char **objname)
{
  const char *str = *string;
  const char *obj = *objname;

  while ((*str != '\0') && (*str == MATCH_MULTI)) {
    str++; // get rid of multiple '*'s
  }

  if (*str == '\0') { // '*' was last, auto-match
    return +1;
  }

  const char *strtop = str;
  const char *objtop = obj;

  while (*str != '\0') {
    if (*str == MATCH_MULTI) {
      *string = str;
      *objname = obj;
      return 0; // matched this segment
    }
    else if (*obj == '\0') {
      return -1; // can't match
    }
    else {
      if ((*str == MATCH_SINGLE) || (*str == *obj)) {
	str++;
	obj++;
	if ((*str == '\0') && (*obj != '\0')) { // advanced check
	  obj++;
	  objtop++;
	  obj = objtop;
	  str = strtop;
	}
      }
      else {
	obj++;
	objtop++;
	obj = objtop;
	str = strtop;
      }
    }
  }

  *string = str;
  *objname = obj;

  return +1; // full match
}

/******************************************************************************/

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>quell warning<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// common goes first
#include "common.h"

// implementation header
#include "LinkManager.h"

// system headers
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <vector>
#include <iostream>

// common headers
#include "Pack.h"
#include "Teleporter.h"
#include "ObstacleMgr.h"

// simple globbing routines
static int match_object_name (const char *string, const char *objname);
static int match_multi (const char **string, const char **objname);
static const char MATCH_MULTI  = '*'; // matches any number of characters
static const char MATCH_SINGLE = '?'; // matches a single character

LinkManager::LinkManager()
{
  // do nothing
  return;
}

LinkManager::~LinkManager()
{
  clear();
  return;
}

void LinkManager::clear()
{
  linkNames.clear();
  linkNumbers.clear();
  return;
}

void LinkManager::makeLinkName(int number, std::string& name)
{
  name = "/t";
  char buffer[8];
  sprintf(buffer, "%i", (number / 2));
  name += buffer;
  name += ":";
  if ((number % 2) == 0) {
    name += "f";
  } else {
    name += "b";
  }
  return;
}

void LinkManager::addLink(int src, int dst)
{
  LinkNameSet link;
  makeLinkName(src, link.src);
  makeLinkName(dst, link.dst);
  linkNames.push_back(link);
  return;
}

void LinkManager::addLink(const std::string& src, const std::string& dst)
{
  LinkNameSet link;
  if ((src[0] >= '0') && (src[0] <= '9')) {
    int number = atoi(src.c_str());
    makeLinkName(number, link.src);
  } else {
    link.src = src;
  }
  if ((dst[0] >= '0') && (dst[0] <= '9')) {
    int number = atoi(dst.c_str());
    makeLinkName(number, link.dst);
  } else {
    link.dst = dst;
  }
  linkNames.push_back(link);
  return;
}

static bool inIntList(int value, const std::vector<int>& list)
{
  for (unsigned int i = 0; i < list.size(); i++) {
    if (value == list[i]) {
      return true;
    }
  }
  return false;
}

void LinkManager::doLinking()
{
  unsigned int i;

  // initial the destinations
  const ObstacleList& teles = OBSTACLEMGR.getTeles();
  // findTelesByName() can not return higher then this
  linkNumbers.resize(teles.size() * 2);
  for (i = 0; i < linkNumbers.size(); i++) {
    linkNumbers[i].dsts.clear();
  }

  for (i = 0; i < linkNames.size(); i++) {
    LinkNameSet& link = linkNames[i];
    std::vector<int> srcNumbers;
    std::vector<int> dstNumbers;
    findTelesByName(link.src, srcNumbers);
    findTelesByName(link.dst, dstNumbers);

    bool broken = false;
    if (srcNumbers.size() <= 0) {
      broken = true;
      DEBUG1("broken link src: %s\n", link.src.c_str());
    }
    if (dstNumbers.size() <= 0) {
      broken = true;
      DEBUG1("broken link dst: %s\n", link.dst.c_str());
    }
    if (broken) {
      continue;
    }

    for (unsigned s = 0; s < srcNumbers.size(); s++) {
      for (unsigned d = 0; d < dstNumbers.size(); d++) {
	std::vector<int>& dstsList = linkNumbers[srcNumbers[s]].dsts;
	if (!inIntList(dstNumbers[d], dstsList)) { // no duplicates
	  dstsList.push_back(dstNumbers[d]);
	}
      }
    }
  }

  // fill in the blanks (passthru linkage)
  for (i = 0; i < linkNumbers.size(); i++) {
    std::vector<int>& dstsList = linkNumbers[i].dsts;
    if (dstsList.size() <= 0) {
      const int t = (i / 2) * 2; // tele number
      const int f = 1 - (i % 2); // opposite link
      dstsList.push_back(t + f);
    }
  }

  if (debugLevel >= 4) {
    for (i = 0; i < teles.size(); i++) {
      Teleporter* tele = (Teleporter*) teles[i];
      printf ("TELE(%i): %s\n", i, tele->getName().c_str());
    }
    for (i = 0; i < linkNames.size(); i++) {
      LinkNameSet& link = linkNames[i];
      printf ("LINKSRC: %-32sLINKDST: %s\n", link.src.c_str(), link.dst.c_str());
    }
    for (i = 0; i < linkNumbers.size(); i++) {
      printf ("SRC %3i%c:  DSTS", (i / 2), ((i % 2) == 0) ? 'f' : 'b');
      for (unsigned int j = 0; j < linkNumbers[i].dsts.size(); j++) {
	int dst = linkNumbers[i].dsts[j];
	printf (" %i%c", (dst / 2), ((dst % 2) == 0) ? 'f' : 'b');
      }
      printf ("\n");
    }
  }

  return;
}

void LinkManager::findTelesByName(const std::string& name,
				  std::vector<int>& list) const
{
  list.clear();

  std::string glob = name;

  // no chars, no service
  if (glob.size() <= 0) {
    return;
  }

  // a leading ':' might be used to indicate absolute linking if
  // links are ever included in group definintions. strip it here
  // for forwards compatibiliy.
  if (glob[0] == ':') {
    glob.erase(0, 1); // erase 1 char from position 0
  }

  // make the trailing face specification case-independent
  const unsigned int last = (const unsigned int)glob.size() - 1;
  if ((glob[last] == 'F') || (glob[last] == 'B')) {
    glob[last] = tolower(glob[last]);
  }

  // add all teleporters that have matching names
  const ObstacleList& teles = OBSTACLEMGR.getTeles();
  for (unsigned int i = 0; i < teles.size(); i++) {
    Teleporter* tele = (Teleporter*) teles[i];
    const std::string& teleName = tele->getName();

    std::string front = teleName;
    front += ":f";
    if (match_object_name(glob.c_str(), front.c_str())) {
      list.push_back((int)(i * 2) + 0);
    }

    std::string back = teleName;
    back += ":b";
    if (match_object_name(glob.c_str(), back.c_str())) {
      list.push_back((int)(i * 2) + 1);
    }
  }

  return;
}

int LinkManager::getTeleportTarget(int source) const
{
  assert(source < (int)(2 * OBSTACLEMGR.getTeles().size()));

  const std::vector<int>& dstsList = linkNumbers[source].dsts;

  if (dstsList.size() == 1) {
    return dstsList[0];
  }
  else if (dstsList.size() > 1) {
    int target = rand() % int(dstsList.size());
    return dstsList[target];
  }
  else {
    assert(false);
    return 0;
  }
}

int LinkManager::getTeleportTarget(int source, unsigned int seed) const
{
  assert(source < (int)(2 * OBSTACLEMGR.getTeles().size()));

  const std::vector<int>& dstsList = linkNumbers[source].dsts;

  if (dstsList.size() == 1) {
    return dstsList[0];
  }
  else if (dstsList.size() > 1) {
    seed = (seed * 1103515245 + 12345) >> 8; // from POSIX rand() example
    seed = seed % (dstsList.size());
    return dstsList[seed];
  }
  else {
    assert(false);
    return 0;
  }
}

void* LinkManager::pack(void* buf) const
{
  buf = nboPackUInt(buf, (uint32_t) linkNames.size());
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    buf = nboPackStdString(buf, linkNames[i].src);
    buf = nboPackStdString(buf, linkNames[i].dst);
  }
  return buf;
}

void* LinkManager::unpack(void* buf)
{
  clear(); // just in case
  unsigned int i;
  uint32_t count;
  buf = nboUnpackUInt(buf, count);
  for (i = 0; i < count; i++) {
    LinkNameSet link;
    buf = nboUnpackStdString(buf, link.src);
    buf = nboUnpackStdString(buf, link.dst);
    linkNames.push_back(link);
  }
  return buf;
}

void LinkManager::print(std::ostream& out, const std::string& indent) const
{
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    const LinkNameSet& link = linkNames[i];
    out << indent << "link" << std::endl;
    out << indent << "  from " << link.src << std::endl;
    out << indent << "  to   " << link.dst << std::endl;
    out << indent << "end" << std::endl << std::endl;
  }
  return;
}

int LinkManager::packSize() const
{
  int fullSize = sizeof(uint32_t);
  for (unsigned int i = 0; i < linkNames.size(); i++) {
    fullSize += nboStdStringPackSize(linkNames[i].src);
    fullSize += nboStdStringPackSize(linkNames[i].dst);
  }
  return fullSize;
}

/******************************************************************************/

static int match_object_name (const char *string, const char *objname)
{
  if (string == NULL) {
    return 0;
  }
  if (objname == NULL) {
    return 0;
  }

  if ((string[0] == MATCH_MULTI) && (string[1] == '\0')) {
    return 1;
  }

  while (*string != '\0') {
    if (*string == MATCH_MULTI) {
      string++;
      switch (match_multi (&string, &objname)) {
	case +1: {
	  return 1;
	}
	case -1: {
	  return 0;
	}
      }
    }
    else if (*objname == '\0') {
      return 0;
    }
    else if ((*string == MATCH_SINGLE) || (*string == *objname)) {
      string++;
      objname++;
    }
    else {
      return 0;
    }
  }

  if (*objname == '\0') {
    return 1;
  } else {
    return 0;
  }
}

/******************************************************************************/

static int match_multi (const char **string, const char **objname)
{
  const char *str = *string;
  const char *obj = *objname;

  while ((*str != '\0') && (*str == MATCH_MULTI)) {
    str++; // get rid of multiple '*'s
  }

  if (*str == '\0') { // '*' was last, auto-match
    return +1;
  }

  const char *strtop = str;
  const char *objtop = obj;

  while (*str != '\0') {
    if (*str == MATCH_MULTI) {
      *string = str;
      *objname = obj;
      return 0; // matched this segment
    }
    else if (*obj == '\0') {
      return -1; // can't match
    }
    else {
      if ((*str == MATCH_SINGLE) || (*str == *obj)) {
	str++;
	obj++;
	if ((*str == '\0') && (*obj != '\0')) { // advanced check
	  obj++;
	  objtop++;
	  obj = objtop;
	  str = strtop;
	}
      }
      else {
	obj++;
	objtop++;
	obj = objtop;
	str = strtop;
      }
    }
  }

  *string = str;
  *objname = obj;

  return +1; // full match
}

/******************************************************************************/

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


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

  BARD: Basic Augmented Reality Demo.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.

============================================================================*/

#include <QApplication>
#include <tclap/CmdLine.h>
#include <cv.h>
#include <iostream>

#include "bardOpenCVVideoSource.h"
#include "bardArucoProcessor.h"
#include "bardPnPRegistration.h"
#include "bardTrackingModelData.h"
#include "bardMainWindow.h"
#include "bardMainRenderingWidget.h"
#include "bardVTKModelPipeline.h"
#include "bardFileIO.h"

int main(int argc, char** argv)
{
  try
  {
    TCLAP::CmdLine cmd("Basic Augmented Reality Demo", ' ', "0.1");
    TCLAP::ValueArg<std::string> intrinsicsArg("i","intrinsics","File containing (3x3) camera intrinsics then (1x4) distortion coefficients.",false,"","string");
    TCLAP::ValueArg<std::string> worldRefArg("w","world","File containing (nx4) points of a tracker board defining world coordinates.",true,"","string");
    TCLAP::ValueArg<std::string> pointerRefArg("p","pointer","File containing (nx4) points of a tracker board defining pointer coordinates.",false,"","string");
    TCLAP::ValueArg<std::string> modelArg0("m","model0","vtkPolyData file a model to be rendered in the scene.",false,"","string");
    TCLAP::ValueArg<std::string> modelArg1("n", "model1", "vtkPolyData file a model to be rendered in the scene.", false, "", "string");
    TCLAP::ValueArg<std::string> outputDirArg("d", "directory", "Output directory to dump files.", false, "", "string");
    TCLAP::ValueArg<std::string> modelAlignArg("a", "align", "File containing (4x4) transform, to align models to world.", false, "", "string");
    TCLAP::ValueArg<float> imageOpacityArg("o","opacity","Image opacity.",false,0.5,"float");
    TCLAP::ValueArg<int> imageXSizeArg("x","xsize","xsize when calibrating.",true,1,"int");
    TCLAP::ValueArg<int> imageYSizeArg("y","ysize","ysize when calibrating.",true,1,"int");
    TCLAP::ValueArg<int> openCVSourceIndex("i", "index", "Camera Index to use", false, 0, "int");
    TCLAP::SwitchArg doDistortionArg("c","correct","Do distortion correction.", false);
    TCLAP::SwitchArg flipSwitchArg("f","flip","Flip in Y-axis.", false);
    TCLAP::SwitchArg pointerRecordMatrixArg("r","record","Record pointer matrix (e.g. for pivot calib).", false);
    TCLAP::SwitchArg pointerRecordTipArg("t","tip","Record pointer tip (e.g. for registration).", false);
    cmd.add( intrinsicsArg );
    cmd.add( worldRefArg );
    cmd.add( pointerRefArg );
    cmd.add( modelArg0 );
    cmd.add( modelArg1 );
    cmd.add( outputDirArg );
    cmd.add( modelAlignArg );
    cmd.add( imageOpacityArg );
    cmd.add( imageXSizeArg );
    cmd.add( imageYSizeArg );
    cmd.add( openCVSourceIndex );
    cmd.add( doDistortionArg );
    cmd.add( flipSwitchArg );
    cmd.add( pointerRecordMatrixArg );
    cmd.add( pointerRecordTipArg );
    cmd.parse( argc, argv );
    std::string intrinsicsFile = intrinsicsArg.getValue();
    std::string worldRef = worldRefArg.getValue();
    std::string pointerRef = pointerRefArg.getValue();
    std::string modelFile0 = modelArg0.getValue();
    std::string modelFile1 = modelArg1.getValue();
    std::string outputDir = outputDirArg.getValue();
    std::string modelAlignFile = modelAlignArg.getValue();
    float opacity = imageOpacityArg.getValue();
    int xSize = imageXSizeArg.getValue();
    int ySize = imageYSizeArg.getValue();
    int sourceIndex = openCVSourceIndex.getValue();
    bool doDistortionCorrection = doDistortionArg.getValue();
    bool doFlipY = flipSwitchArg.getValue();
    bool pointerRecordMatrix = pointerRecordMatrixArg.getValue();
    bool pointerRecordTip =pointerRecordTipArg.getValue();

    if ((pointerRecordMatrix || pointerRecordTip) && pointerRef.size() == 0)
    {
      throw std::runtime_error("You asked to record pointer movement, but did not provide a pointer reference model.");
    }
    if ((pointerRecordMatrix || pointerRecordTip) && outputDir.size() == 0)
    {
      throw std::runtime_error("You asked to record pointer movement, but did not provide an output directory.");
    }

    QApplication app(argc, argv);
    app.setOrganizationName("CMIC");
    app.setApplicationName("BARD");

    bard::MainWindow mainWin;

    cv::Point2i imageSize;
    imageSize.x = xSize;
    imageSize.y = ySize;

    bard::OpenCVVideoSource mySource(sourceIndex);
    mySource.SetFlipY(doFlipY);
    mySource.SetUndistort(doDistortionCorrection);

    bard::ArucoProcessor myProcessor;
    bard::PnPRegistration myRegistration;
    bard::TrackingModelData myWorldTrackingModel(worldRef);

    bard::MainRenderingWidget myWidget;
    myWidget.SetCalibratedImageSize(imageSize);
    myWidget.SetVideoSource(&mySource);
    myWidget.SetTagProcessor(&myProcessor);
    myWidget.SetRegistrationAlgorithm(&myRegistration);
    myWidget.SetImageOpacity(opacity);
    myWidget.SetOutputDirectory(outputDir);
    myWidget.SetRecordMatrix(pointerRecordMatrix);
    myWidget.SetRecordPointOfInterest(pointerRecordTip);

    // Load intrinsic/distortion parameters
    cv::Matx33d intrinsicParameters;
    cv::Matx14d distortionParameters;
    if (intrinsicsFile.size() > 0)
    {
      bard::LoadCameraParameters(intrinsicsFile, intrinsicParameters, distortionParameters);
      myWidget.SetCameraIntrinsics(intrinsicParameters);
    }

    // Loads 4x4 registration matrix.
    cv::Matx44d registerModelsToWorld;
    if (modelAlignFile.size() > 0)
    {
      registerModelsToWorld = bard::LoadMatrixFromFile(modelAlignFile);
      myWidget.SetModelsToWorld(registerModelsToWorld);
    }

    // Adds data-files that enable us to do tag tracking of various objects.
    myWidget.AddTrackingModel(&myWorldTrackingModel);
    bard::TrackingModelData* pointerTrackingModel = NULL;
    if (pointerRef.size() > 0)
    {
      pointerTrackingModel = new bard::TrackingModelData(pointerRef);
      myWidget.AddTrackingModel(pointerTrackingModel);
    }

    // Add VTK files that enable us to visualise virtual objects in scene.
    bard::VTKModelPipeline *modelForVisualisation0 = NULL;
    if (modelFile0.size() > 0)
    {
      modelForVisualisation0 = new bard::VTKModelPipeline(modelFile0);
      myWidget.AddVTKModel(modelForVisualisation0);
    }
    bard::VTKModelPipeline *modelForVisualisation1 = NULL;
    if (modelFile1.size() > 0)
    {
      modelForVisualisation1 = new bard::VTKModelPipeline(modelFile1);
      myWidget.AddVTKModel(modelForVisualisation1);
    }
    mainWin.setCentralWidget(&myWidget);
    mainWin.show();
    mainWin.raise();
    mainWin.showMaximized();

    myWidget.GetInteractor()->Disable();
    myWidget.SetEnableImage(true);
    myWidget.SetEnableTrackingModels(true);
    myWidget.SetEnableVTKModels(true);

    int status = app.exec();

    // Tidy up.
    if (pointerTrackingModel != NULL)
    {
      delete pointerTrackingModel;
    }
    if (modelForVisualisation0 != NULL)
    {
      delete modelForVisualisation0;
    }
    if (modelForVisualisation1 != NULL)
    {
      delete modelForVisualisation1;
    }
    return status;
  }
  catch (TCLAP::ArgException &e)
  {
    std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
  }
  catch (std::exception& e)
  {
    std::cerr << "error: " << e.what() << std::endl;
  }
}
<commit_msg>Issue #1 fixed conflicting argument<commit_after>/*============================================================================

  BARD: Basic Augmented Reality Demo.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.

============================================================================*/

#include <QApplication>
#include <tclap/CmdLine.h>
#include <cv.h>
#include <iostream>

#include "bardOpenCVVideoSource.h"
#include "bardArucoProcessor.h"
#include "bardPnPRegistration.h"
#include "bardTrackingModelData.h"
#include "bardMainWindow.h"
#include "bardMainRenderingWidget.h"
#include "bardVTKModelPipeline.h"
#include "bardFileIO.h"

int main(int argc, char** argv)
{
  try
  {
    TCLAP::CmdLine cmd("Basic Augmented Reality Demo", ' ', "0.1");
    TCLAP::ValueArg<std::string> intrinsicsArg("i","intrinsics","File containing (3x3) camera intrinsics then (1x4) distortion coefficients.",false,"","string");
    TCLAP::ValueArg<std::string> worldRefArg("w","world","File containing (nx4) points of a tracker board defining world coordinates.",true,"","string");
    TCLAP::ValueArg<std::string> pointerRefArg("p","pointer","File containing (nx4) points of a tracker board defining pointer coordinates.",false,"","string");
    TCLAP::ValueArg<std::string> modelArg0("m","model0","vtkPolyData file a model to be rendered in the scene.",false,"","string");
    TCLAP::ValueArg<std::string> modelArg1("n", "model1", "vtkPolyData file a model to be rendered in the scene.", false, "", "string");
    TCLAP::ValueArg<std::string> outputDirArg("d", "directory", "Output directory to dump files.", false, "", "string");
    TCLAP::ValueArg<std::string> modelAlignArg("a", "align", "File containing (4x4) transform, to align models to world.", false, "", "string");
    TCLAP::ValueArg<float> imageOpacityArg("o","opacity","Image opacity.",false,0.5,"float");
    TCLAP::ValueArg<int> imageXSizeArg("x","xsize","xsize when calibrating.",true,1,"int");
    TCLAP::ValueArg<int> imageYSizeArg("y","ysize","ysize when calibrating.",true,1,"int");
    TCLAP::ValueArg<int> openCVSourceIndex("k", "index", "Camera Index to use", false, 0, "int");
    TCLAP::SwitchArg doDistortionArg("c","correct","Do distortion correction.", false);
    TCLAP::SwitchArg flipSwitchArg("f","flip","Flip in Y-axis.", false);
    TCLAP::SwitchArg pointerRecordMatrixArg("r","record","Record pointer matrix (e.g. for pivot calib).", false);
    TCLAP::SwitchArg pointerRecordTipArg("t","tip","Record pointer tip (e.g. for registration).", false);
    cmd.add( intrinsicsArg );
    cmd.add( worldRefArg );
    cmd.add( pointerRefArg );
    cmd.add( modelArg0 );
    cmd.add( modelArg1 );
    cmd.add( outputDirArg );
    cmd.add( modelAlignArg );
    cmd.add( imageOpacityArg );
    cmd.add( imageXSizeArg );
    cmd.add( imageYSizeArg );
    cmd.add( openCVSourceIndex );
    cmd.add( doDistortionArg );
    cmd.add( flipSwitchArg );
    cmd.add( pointerRecordMatrixArg );
    cmd.add( pointerRecordTipArg );
    cmd.parse( argc, argv );
    std::string intrinsicsFile = intrinsicsArg.getValue();
    std::string worldRef = worldRefArg.getValue();
    std::string pointerRef = pointerRefArg.getValue();
    std::string modelFile0 = modelArg0.getValue();
    std::string modelFile1 = modelArg1.getValue();
    std::string outputDir = outputDirArg.getValue();
    std::string modelAlignFile = modelAlignArg.getValue();
    float opacity = imageOpacityArg.getValue();
    int xSize = imageXSizeArg.getValue();
    int ySize = imageYSizeArg.getValue();
    int sourceIndex = openCVSourceIndex.getValue();
    bool doDistortionCorrection = doDistortionArg.getValue();
    bool doFlipY = flipSwitchArg.getValue();
    bool pointerRecordMatrix = pointerRecordMatrixArg.getValue();
    bool pointerRecordTip =pointerRecordTipArg.getValue();

    if ((pointerRecordMatrix || pointerRecordTip) && pointerRef.size() == 0)
    {
      throw std::runtime_error("You asked to record pointer movement, but did not provide a pointer reference model.");
    }
    if ((pointerRecordMatrix || pointerRecordTip) && outputDir.size() == 0)
    {
      throw std::runtime_error("You asked to record pointer movement, but did not provide an output directory.");
    }

    QApplication app(argc, argv);
    app.setOrganizationName("CMIC");
    app.setApplicationName("BARD");

    bard::MainWindow mainWin;

    cv::Point2i imageSize;
    imageSize.x = xSize;
    imageSize.y = ySize;

    bard::OpenCVVideoSource mySource(sourceIndex);
    mySource.SetFlipY(doFlipY);
    mySource.SetUndistort(doDistortionCorrection);

    bard::ArucoProcessor myProcessor;
    bard::PnPRegistration myRegistration;
    bard::TrackingModelData myWorldTrackingModel(worldRef);

    bard::MainRenderingWidget myWidget;
    myWidget.SetCalibratedImageSize(imageSize);
    myWidget.SetVideoSource(&mySource);
    myWidget.SetTagProcessor(&myProcessor);
    myWidget.SetRegistrationAlgorithm(&myRegistration);
    myWidget.SetImageOpacity(opacity);
    myWidget.SetOutputDirectory(outputDir);
    myWidget.SetRecordMatrix(pointerRecordMatrix);
    myWidget.SetRecordPointOfInterest(pointerRecordTip);

    // Load intrinsic/distortion parameters
    cv::Matx33d intrinsicParameters;
    cv::Matx14d distortionParameters;
    if (intrinsicsFile.size() > 0)
    {
      bard::LoadCameraParameters(intrinsicsFile, intrinsicParameters, distortionParameters);
      myWidget.SetCameraIntrinsics(intrinsicParameters);
    }

    // Loads 4x4 registration matrix.
    cv::Matx44d registerModelsToWorld;
    if (modelAlignFile.size() > 0)
    {
      registerModelsToWorld = bard::LoadMatrixFromFile(modelAlignFile);
      myWidget.SetModelsToWorld(registerModelsToWorld);
    }

    // Adds data-files that enable us to do tag tracking of various objects.
    myWidget.AddTrackingModel(&myWorldTrackingModel);
    bard::TrackingModelData* pointerTrackingModel = NULL;
    if (pointerRef.size() > 0)
    {
      pointerTrackingModel = new bard::TrackingModelData(pointerRef);
      myWidget.AddTrackingModel(pointerTrackingModel);
    }

    // Add VTK files that enable us to visualise virtual objects in scene.
    bard::VTKModelPipeline *modelForVisualisation0 = NULL;
    if (modelFile0.size() > 0)
    {
      modelForVisualisation0 = new bard::VTKModelPipeline(modelFile0);
      myWidget.AddVTKModel(modelForVisualisation0);
    }
    bard::VTKModelPipeline *modelForVisualisation1 = NULL;
    if (modelFile1.size() > 0)
    {
      modelForVisualisation1 = new bard::VTKModelPipeline(modelFile1);
      myWidget.AddVTKModel(modelForVisualisation1);
    }
    mainWin.setCentralWidget(&myWidget);
    mainWin.show();
    mainWin.raise();
    mainWin.showMaximized();

    myWidget.GetInteractor()->Disable();
    myWidget.SetEnableImage(true);
    myWidget.SetEnableTrackingModels(true);
    myWidget.SetEnableVTKModels(true);

    int status = app.exec();

    // Tidy up.
    if (pointerTrackingModel != NULL)
    {
      delete pointerTrackingModel;
    }
    if (modelForVisualisation0 != NULL)
    {
      delete modelForVisualisation0;
    }
    if (modelForVisualisation1 != NULL)
    {
      delete modelForVisualisation1;
    }
    return status;
  }
  catch (TCLAP::ArgException &e)
  {
    std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
  }
  catch (std::exception& e)
  {
    std::cerr << "error: " << e.what() << std::endl;
  }
}
<|endoftext|>


<commit_before>#include "view.h"

View::View(Type type, QWidget *parent) :
    View(type, new QGraphicsScene(parent), parent)
{}

View::View(Type type, QGraphicsScene * scene, QWidget * parent) :
    QGraphicsView(scene, parent)
  , verticalLine(nullptr), horizontalLine(nullptr), slice(nullptr)
  , sliceHeight(1), sliceWidth(1)
  , crosshairX(0), crosshairY(0), type(type)
  , aspectRatio(1.0), currentScale(1.0), minScale(1.0), minPixSize(200)
{
    setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
    setDragMode(QGraphicsView::ScrollHandDrag);
    setMouseTracking(true);
    setContextMenuPolicy(Qt::CustomContextMenu);
    setBackgroundBrush(palette().color(QPalette::Normal, QPalette::Window));
    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
        this, SLOT(showContextMenu(const QPoint&)));
    switch (type) {
    case Type::CORONAL:
        verticalColor = Qt::green;
        horizontalColor = Qt::blue;
        setStyleSheet("border: 2px solid red");
        break;
    case Type::SAGITTAL:
        verticalColor = Qt::red;
        horizontalColor = Qt::blue;
        setStyleSheet("border: 2px solid green");
        break;
    case Type::AXIAL:
        verticalColor = Qt::red;
        horizontalColor = Qt::green;
        setStyleSheet("border: 2px solid blue");
        break;
    default:
        break;
    }
}

void View::clear()
{
    QGraphicsScene *scen = scene();
    if (scen) {
        scen->clear();
        verticalLine = nullptr;
        horizontalLine = nullptr;
        slice = nullptr;
    }
}

void View::zoom(int level)
{
    // don't allow scale less than a specific value
    //int smallestSide = qMin(currentScale*sliceWidth, currentScale*sliceHeight*abs(aspectRatio));
    if ((level < 0) && (currentScale < minScale))
        return;
    double factor = qPow(1.05, level);
    currentScale *= factor;
    scale(factor, factor);
}

void View::wheelEvent(QWheelEvent *ev)
{
    int numSteps = ev->delta()/120;
    zoom(numSteps);
    emit wheelScrolled( ev );
}

void View::resetSize()
{
    /*
      let scene size be X1,Y1, viewport size be X2,Y2,
      we want the factor f to be < X2/X1 and Y2/(Y1*|r|)
      since we will scale X1 by f and Y1 by f*r
      */
    if (!this->isEnabled())
        return;
    double margin = 0.95;
    double widthRatio = double(width())/double(sliceWidth);
    double heightRatio = double(height())/double(sliceHeight);
    double factor = qMax(qMin(widthRatio, heightRatio/abs(aspectRatio))*margin,
                         minScale);
    QMatrix matrix;
    matrix.scale(factor,-factor*aspectRatio);
    setMatrix(matrix);
    currentScale = factor;
}

void View::setCrosshairLocation(int x, int y)
{
    QGraphicsScene *scen = scene();
    if (scen == nullptr)
        return;
    if (verticalLine) {
        scen->removeItem(verticalLine);
        delete verticalLine;
        verticalLine = nullptr;
    }
    if (horizontalLine) {
        scen->removeItem(horizontalLine);
        delete horizontalLine;
        horizontalLine = nullptr;
    }

    QPen pen = QPen(Qt::DashLine);
    pen.setWidthF(0.6);
    pen.setColor(horizontalColor);
    horizontalLine = scen->addLine(QLineF(0,y+0.5,sliceWidth,y+0.5),pen);
    horizontalLine->setZValue(1);
    pen.setColor(verticalColor);
    verticalLine = scen->addLine(QLineF(x+0.5,0,x+0.5,sliceHeight),pen);
    verticalLine->setZValue(1);
    crosshairX = x;
    crosshairY = y;
}

void View::updateSlice(const QPixmap& image)
{
    QGraphicsScene *scen = scene();
    if (scen == nullptr)
        return;
    if (slice) {
        scen->removeItem(slice);
        delete slice;
        slice = nullptr;
    }
    slice = scen->addPixmap(image);
    slice->setZValue(0);
    sliceHeight = image.height();
    sliceWidth = image.width();
    minScale = qMax(minPixSize/double(sliceWidth),
                            minPixSize/(double(sliceHeight*abs(aspectRatio))));
    setSceneRect(0,0,sliceWidth,sliceHeight);
}

void View::showContextMenu(const QPoint &pos)
{
    QMenu *myMenu = new QMenu;
    QAction *saveAs, *copy;
    saveAs = myMenu->addAction("Save Image As");
    copy = myMenu->addAction("Copy Image");

    QAction* selectedItem = myMenu->exec(this->mapToGlobal(pos));

    if (selectedItem != NULL) {
        QPixmap img = QPixmap::grabWidget(this->viewport(),
                                             this->mapFromScene(this->sceneRect().toRect()).boundingRect());
        if (selectedItem == copy)
            QApplication::clipboard()->setPixmap(img, QClipboard::Clipboard);
        else {
             // writes pixmap in PNG format
            QString fileName = QFileDialog::getSaveFileName(this,"Save Image", ".", "(*.png)");
            if (fileName.isEmpty()) //check for cancel press
                return;
            img.save(fileName, "PNG");
        }
    }
    // delete the menu will delete the actions
    delete myMenu;
}

void View::setAspectRatio(double r)
{
    aspectRatio = r;
    minScale = qMax(minPixSize/double(sliceWidth),
                    minPixSize/(double(sliceHeight*abs(aspectRatio))));
}
<commit_msg>remove comments<commit_after>#include "view.h"

View::View(Type type, QWidget *parent) :
    View(type, new QGraphicsScene(parent), parent)
{}

View::View(Type type, QGraphicsScene * scene, QWidget * parent) :
    QGraphicsView(scene, parent)
  , verticalLine(nullptr), horizontalLine(nullptr), slice(nullptr)
  , sliceHeight(1), sliceWidth(1)
  , crosshairX(0), crosshairY(0), type(type)
  , aspectRatio(1.0), currentScale(1.0), minScale(1.0), minPixSize(200)
{
    setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
    setDragMode(QGraphicsView::ScrollHandDrag);
    setMouseTracking(true);
    setContextMenuPolicy(Qt::CustomContextMenu);
    setBackgroundBrush(palette().color(QPalette::Normal, QPalette::Window));
    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
        this, SLOT(showContextMenu(const QPoint&)));
    switch (type) {
    case Type::CORONAL:
        verticalColor = Qt::green;
        horizontalColor = Qt::blue;
        setStyleSheet("border: 2px solid red");
        break;
    case Type::SAGITTAL:
        verticalColor = Qt::red;
        horizontalColor = Qt::blue;
        setStyleSheet("border: 2px solid green");
        break;
    case Type::AXIAL:
        verticalColor = Qt::red;
        horizontalColor = Qt::green;
        setStyleSheet("border: 2px solid blue");
        break;
    default:
        break;
    }
}

void View::clear()
{
    QGraphicsScene *scen = scene();
    if (scen) {
        scen->clear();
        verticalLine = nullptr;
        horizontalLine = nullptr;
        slice = nullptr;
    }
}

void View::zoom(int level)
{
    // don't allow scale less than a specific value
    if ((level < 0) && (currentScale < minScale))
        return;
    double factor = qPow(1.05, level);
    currentScale *= factor;
    scale(factor, factor);
}

void View::wheelEvent(QWheelEvent *ev)
{
    int numSteps = ev->delta()/120;
    zoom(numSteps);
    emit wheelScrolled( ev );
}

void View::resetSize()
{
    /*
      let scene size be X1,Y1, viewport size be X2,Y2,
      we want the factor f to be < X2/X1 and Y2/(Y1*|r|)
      since we will scale X1 by f and Y1 by f*r
      */
    if (!this->isEnabled())
        return;
    double margin = 0.95;
    double widthRatio = double(width())/double(sliceWidth);
    double heightRatio = double(height())/double(sliceHeight);
    double factor = qMax(qMin(widthRatio, heightRatio/abs(aspectRatio))*margin,
                         minScale);
    QMatrix matrix;
    matrix.scale(factor,-factor*aspectRatio);
    setMatrix(matrix);
    currentScale = factor;
}

void View::setCrosshairLocation(int x, int y)
{
    QGraphicsScene *scen = scene();
    if (scen == nullptr)
        return;
    if (verticalLine) {
        scen->removeItem(verticalLine);
        delete verticalLine;
        verticalLine = nullptr;
    }
    if (horizontalLine) {
        scen->removeItem(horizontalLine);
        delete horizontalLine;
        horizontalLine = nullptr;
    }

    QPen pen = QPen(Qt::DashLine);
    pen.setWidthF(0.6);
    pen.setColor(horizontalColor);
    horizontalLine = scen->addLine(QLineF(0,y+0.5,sliceWidth,y+0.5),pen);
    horizontalLine->setZValue(1);
    pen.setColor(verticalColor);
    verticalLine = scen->addLine(QLineF(x+0.5,0,x+0.5,sliceHeight),pen);
    verticalLine->setZValue(1);
    crosshairX = x;
    crosshairY = y;
}

void View::updateSlice(const QPixmap& image)
{
    QGraphicsScene *scen = scene();
    if (scen == nullptr)
        return;
    if (slice) {
        scen->removeItem(slice);
        delete slice;
        slice = nullptr;
    }
    slice = scen->addPixmap(image);
    slice->setZValue(0);
    sliceHeight = image.height();
    sliceWidth = image.width();
    minScale = qMax(minPixSize/double(sliceWidth),
                            minPixSize/(double(sliceHeight*abs(aspectRatio))));
    setSceneRect(0,0,sliceWidth,sliceHeight);
}

void View::showContextMenu(const QPoint &pos)
{
    QMenu *myMenu = new QMenu;
    QAction *saveAs, *copy;
    saveAs = myMenu->addAction("Save Image As");
    copy = myMenu->addAction("Copy Image");

    QAction* selectedItem = myMenu->exec(this->mapToGlobal(pos));

    if (selectedItem != NULL) {
        QPixmap img = QPixmap::grabWidget(this->viewport(),
                                             this->mapFromScene(this->sceneRect().toRect()).boundingRect());
        if (selectedItem == copy)
            QApplication::clipboard()->setPixmap(img, QClipboard::Clipboard);
        else {
             // writes pixmap in PNG format
            QString fileName = QFileDialog::getSaveFileName(this,"Save Image", ".", "(*.png)");
            if (fileName.isEmpty()) //check for cancel press
                return;
            img.save(fileName, "PNG");
        }
    }
    // delete the menu will delete the actions
    delete myMenu;
}

void View::setAspectRatio(double r)
{
    aspectRatio = r;
    minScale = qMax(minPixSize/double(sliceWidth),
                    minPixSize/(double(sliceHeight*abs(aspectRatio))));
}
<|endoftext|>


<commit_before>#include <bgfx.h>
#include <bx/bx.h>
#include <bx/timer.h>
#include "../common/entry.h"
#include "../common/dbg.h"
#include "../common/math.h"
#include "../common/processevents.h"

#include "../common/font/font_manager.h"
#include "../common/font/text_buffer_manager.h"

#include <stdio.h>
#include <string.h>

inline void mtxTranslate(float* _result, float x, float y, float z)
{
	memset(_result, 0, sizeof(float)*16);
	_result[0] = _result[5] = _result[10] = _result[15] = 1.0f;
	_result[12] = x;
	_result[13] = y;
	_result[14] = z;
}

inline void mtxScale(float* _result, float x, float y, float z)
{
	memset(_result, 0, sizeof(float)*16);
	_result[0] = x;
	_result[5] = y;
	_result[10] = z;
	_result[15] = 1.0f;
}

int _main_(int /*_argc*/, char** /*_argv*/)
{
    uint32_t width = 1280;
	uint32_t height = 720;
	uint32_t debug = BGFX_DEBUG_TEXT;
	uint32_t reset = 0;

	bgfx::init();

	bgfx::reset(width, height);

	// Enable debug text.
	bgfx::setDebug(debug);

	// Set view 0 clear state.
	bgfx::setViewClear(0
		, BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
		//, 0x303030ff
		//, 0xffffffff
		, 0x000000FF
		, 1.0f
		, 0
		);

	//init the text rendering system
	FontManager* fontManager = new FontManager(512);
	TextBufferManager* textBufferManager = new TextBufferManager(fontManager);

	//load a truetype files
	/*
	"font/droidsans.ttf",
	"font/chp-fire.ttf",
	"font/bleeding_cowboys.ttf",
	"font/mias_scribblings.ttf",
	"font/ruritania.ttf",
	"font/signika-regular.ttf",
	"font/five_minutes.otf"
	*/
	TrueTypeHandle times_tt = fontManager->loadTrueTypeFromFile("font/bleeding_cowboys.ttf");

	//create a distance field font
	FontHandle distance_font = fontManager->createFontByPixelSize(times_tt, 0, 48, FONT_TYPE_DISTANCE);
	//create a scalled down version of the same font (without adding anything to the atlas)
	FontHandle smaller_font = fontManager->createScaledFontToPixelSize(distance_font, 32);

	//preload glyph and generate (generate bitmap's)
	fontManager->preloadGlyph(distance_font, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.,\" \n");

	//You can unload the truetype files at this stage, but in that case, the set of glyph's will be limited to the set of preloaded glyph
	fontManager->unloadTrueType(times_tt);

	TextBufferHandle staticText = textBufferManager->createTextBuffer(FONT_TYPE_DISTANCE, STATIC);
	textBufferManager->setTextColor(staticText, 0xDD0000FF);

	//textBufferManager->appendText(staticText, distance_font, L"The quick brown fox jumps over the lazy dog\n");
	//textBufferManager->appendText(staticText, distance_font, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
	textBufferManager->appendText(staticText, distance_font, L"BGFX  ");
	textBufferManager->appendText(staticText, smaller_font, L"bgfx");

	int64_t timeOffset = bx::getHPCounter();
    while (!processEvents(width, height, debug, reset) )
	{
		// Set view 0 default viewport.
		bgfx::setViewRect(0, 0, 0, width, height);

		// This dummy draw call is here to make sure that view 0 is cleared
		// if no other draw calls are submitted to view 0.
		bgfx::submit(0);

		int64_t now = bx::getHPCounter();
		static int64_t last = now;
		const int64_t frameTime = now - last;
		last = now;
		const double freq = double(bx::getHPFrequency() );
		const double toMs = 1000.0/freq;
		float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );

		// Use debug font to print information about this example.
		bgfx::dbgTextClear();
		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/11-fontsdf");
		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Use a single distance field font to render text of various size.");
		bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);

		float at[3] = { 0, 0, 0.0f };
		float eye[3] = {0, 0, -1.0f };

		float view[16];
		float proj[16];
		mtxLookAt(view, eye, at);
		float centering = 0.5f;
		//setup a top-left ortho matrix for screen space drawing
		mtxOrtho(proj, centering, width+centering,height+centering, centering,-1.0f, 1.0f);

		// Set view and projection matrix for view 0.
		bgfx::setViewTransform(0, view, proj);
		TextRectangle rect = textBufferManager->getRectangle(staticText);

		float mtxA[16];
		float mtxB[16];
		float mtxC[16];
		mtxRotateZ(mtxA, time*0.37f);
		mtxTranslate(mtxB, -(rect.width*0.5f), -(rect.height*0.5f), 0);

		mtxMul(mtxC, mtxB, mtxA);

		float scale=4.1f+4.0f*sinf(time);
		mtxScale(mtxA, scale, scale, 1.0f);
		mtxMul(mtxB, mtxC, mtxA);

		mtxTranslate(mtxC, ((width)*0.5f), ((height)*0.5f), 0);
		mtxMul(mtxA, mtxB, mtxC);

		// Set model matrix for rendering.
		bgfx::setTransform(mtxA);

		//draw your text
		textBufferManager->submitTextBuffer(staticText, 0);

        // Advance to next frame. Rendering thread will be kicked to
		// process submitted rendering primitives.
		bgfx::frame();
	}

	//destroy the fonts
	fontManager->destroyFont(distance_font);
	fontManager->destroyFont(smaller_font);

	textBufferManager->destroyTextBuffer(staticText);

	delete textBufferManager;
	delete fontManager;
	// Shutdown bgfx.
    bgfx::shutdown();

	return 0;
}
<commit_msg>remove blank space<commit_after>#include <bgfx.h>
#include <bx/bx.h>
#include <bx/timer.h>
#include "../common/entry.h"
#include "../common/dbg.h"
#include "../common/math.h"
#include "../common/processevents.h"

#include "../common/font/font_manager.h"
#include "../common/font/text_buffer_manager.h"

#include <stdio.h>
#include <string.h>

inline void mtxTranslate(float* _result, float x, float y, float z)
{
	memset(_result, 0, sizeof(float)*16);
	_result[0] = _result[5] = _result[10] = _result[15] = 1.0f;
	_result[12] = x;
	_result[13] = y;
	_result[14] = z;
}

inline void mtxScale(float* _result, float x, float y, float z)
{
	memset(_result, 0, sizeof(float)*16);
	_result[0] = x;
	_result[5] = y;
	_result[10] = z;
	_result[15] = 1.0f;
}

int _main_(int /*_argc*/, char** /*_argv*/)
{
    uint32_t width = 1280;
	uint32_t height = 720;
	uint32_t debug = BGFX_DEBUG_TEXT;
	uint32_t reset = 0;

	bgfx::init();

	bgfx::reset(width, height);

	// Enable debug text.
	bgfx::setDebug(debug);

	// Set view 0 clear state.
	bgfx::setViewClear(0
		, BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
		//, 0x303030ff
		//, 0xffffffff
		, 0x000000FF
		, 1.0f
		, 0
		);

	//init the text rendering system
	FontManager* fontManager = new FontManager(512);
	TextBufferManager* textBufferManager = new TextBufferManager(fontManager);

	//load a truetype files
	/*
	"font/droidsans.ttf",
	"font/chp-fire.ttf",
	"font/bleeding_cowboys.ttf",
	"font/mias_scribblings.ttf",
	"font/ruritania.ttf",
	"font/signika-regular.ttf",
	"font/five_minutes.otf"
	*/
	TrueTypeHandle times_tt = fontManager->loadTrueTypeFromFile("font/bleeding_cowboys.ttf");

	//create a distance field font
	FontHandle distance_font = fontManager->createFontByPixelSize(times_tt, 0, 48, FONT_TYPE_DISTANCE);
	//create a scalled down version of the same font (without adding anything to the atlas)
	FontHandle smaller_font = fontManager->createScaledFontToPixelSize(distance_font, 32);

	//preload glyph and generate (generate bitmap's)
	fontManager->preloadGlyph(distance_font, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.,\" \n");

	//You can unload the truetype files at this stage, but in that case, the set of glyph's will be limited to the set of preloaded glyph
	fontManager->unloadTrueType(times_tt);

	TextBufferHandle staticText = textBufferManager->createTextBuffer(FONT_TYPE_DISTANCE, STATIC);
	textBufferManager->setTextColor(staticText, 0xDD0000FF);

	//textBufferManager->appendText(staticText, distance_font, L"The quick brown fox jumps over the lazy dog\n");
	//textBufferManager->appendText(staticText, distance_font, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
	textBufferManager->appendText(staticText, distance_font, L"BGFX ");
	textBufferManager->appendText(staticText, smaller_font, L"bgfx");

	int64_t timeOffset = bx::getHPCounter();
    while (!processEvents(width, height, debug, reset) )
	{
		// Set view 0 default viewport.
		bgfx::setViewRect(0, 0, 0, width, height);

		// This dummy draw call is here to make sure that view 0 is cleared
		// if no other draw calls are submitted to view 0.
		bgfx::submit(0);

		int64_t now = bx::getHPCounter();
		static int64_t last = now;
		const int64_t frameTime = now - last;
		last = now;
		const double freq = double(bx::getHPFrequency() );
		const double toMs = 1000.0/freq;
		float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );

		// Use debug font to print information about this example.
		bgfx::dbgTextClear();
		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/11-fontsdf");
		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Use a single distance field font to render text of various size.");
		bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);

		float at[3] = { 0, 0, 0.0f };
		float eye[3] = {0, 0, -1.0f };

		float view[16];
		float proj[16];
		mtxLookAt(view, eye, at);
		float centering = 0.5f;
		//setup a top-left ortho matrix for screen space drawing
		mtxOrtho(proj, centering, width+centering,height+centering, centering,-1.0f, 1.0f);

		// Set view and projection matrix for view 0.
		bgfx::setViewTransform(0, view, proj);
		TextRectangle rect = textBufferManager->getRectangle(staticText);

		float mtxA[16];
		float mtxB[16];
		float mtxC[16];
		mtxRotateZ(mtxA, time*0.37f);
		mtxTranslate(mtxB, -(rect.width*0.5f), -(rect.height*0.5f), 0);

		mtxMul(mtxC, mtxB, mtxA);

		float scale=4.1f+4.0f*sinf(time);
		mtxScale(mtxA, scale, scale, 1.0f);
		mtxMul(mtxB, mtxC, mtxA);

		mtxTranslate(mtxC, ((width)*0.5f), ((height)*0.5f), 0);
		mtxMul(mtxA, mtxB, mtxC);

		// Set model matrix for rendering.
		bgfx::setTransform(mtxA);

		//draw your text
		textBufferManager->submitTextBuffer(staticText, 0);

        // Advance to next frame. Rendering thread will be kicked to
		// process submitted rendering primitives.
		bgfx::frame();
	}

	//destroy the fonts
	fontManager->destroyFont(distance_font);
	fontManager->destroyFont(smaller_font);

	textBufferManager->destroyTextBuffer(staticText);

	delete textBufferManager;
	delete fontManager;
	// Shutdown bgfx.
    bgfx::shutdown();

	return 0;
}
<|endoftext|>


<commit_before>/* -*- mode:C++; -*- */
/* MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2016 Randolf Rotta, Maik Krüger, Robert Kuban, and contributors, BTU Cottbus-Senftenberg
 */
#include "host/MemMapperPci.hh"
#include "mythos/HostInfoTable.hh"
#include "mythos/PciMsgQueueMPSC.hh"
#include "cpu/clflush.hh"
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <unordered_map>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>

using namespace mythos;

// Environmental variables set if program is called by sudo
static const constexpr char* ENV_UID = "SUDO_UID";
static const constexpr char* ENV_GID = "SUDO_GID";

  template<typename T>
void parsenum(char const *str, T& val)
{
  std::stringstream s;
  if (str[0] == '0' && str[1] == 'x')
    s << std::hex << str;
  else
    s << str;
  s >> val;
}

std::string deviceKNC(int adapter)
{
  std::stringstream s;
  // choose the aperture memory file with the write combining enabled.
  s << "/sys/class/mic/mic" << adapter << "/device/resource0"; /// @todo or _wc ???
  return s.str();
}

void drop_root() {
  if (getuid() != 0) {
    std::cerr << "Cannot drop root when not root.\n";
    return;
  }
  if (setgid(atoi(std::getenv(ENV_GID))) != 0) {
    std::cerr << "Could not restore Group ID.\n";
  }
  if (setuid(atoi(std::getenv(ENV_UID))) != 0) {
    std::cerr << "Could not restore User ID.\n";
  }
  if (getuid() == 0) {
    std::cerr << "Dropping root unsuccessful\n";
  }
}

struct InfoPtr {
  uint64_t info;
  uint64_t debug;
};

/// Class logs into files, opening new file for every sending channel id.
class file_logger {
  public:

    file_logger(const char *directory_)
      :directory(directory_) {
        if (mkdir( (std::string(getenv("PWD")) + std::string("/") + directory).c_str(),
              S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
        {
          std::cerr << "Error creating directory for logs.\n";
        }
      }

    ~file_logger() {
      for (auto f : files) {
        f.second->close();
        delete f.second;
      }
    }

    void log(uint16_t vchannel, std::string msg) {
      auto found = files.find(vchannel);
      if (found != files.end()) {
        *found->second << msg << "\n";
        found->second->flush();
      } else {
        std::ofstream *file_stream = new std::ofstream(
            directory + std::string("/") + std::to_string(vchannel),
            std::ios::out | std::ios::trunc);
        if (!file_stream->is_open()) {
          std::cerr << "Could not open file " << (std::to_string(vchannel)) << "\n";
          return;
        }
        files.insert({vchannel, file_stream});
        *file_stream << msg << "\n";
        file_stream->flush();
      }
    }

  private:
    std::string directory;
    std::unordered_map<uint16_t, std::ofstream*> files;
};

int main(int argc, char** argv)
{
  int adapter;
  if (argc < 2) {
    std::cerr << argv[0] << " adapter" << std::endl;
    return -1;
  }
  parsenum(argv[1], adapter);
  std::cerr << "will read from adapter " << adapter
    << " file " << deviceKNC(adapter) << std::endl;
  MemMapperPci micmem(deviceKNC(adapter));

  // wait until the _host_info_ptr pointer at address 2MiB actually contains something
  auto info_ptr = micmem.access(PhysPtr<InfoPtr>(0x200000ull));
  do {
    cpu::clflush(info_ptr.addr());
    std::cout << "info: " << (void*)info_ptr->info << " debug: " << (void*)info_ptr->debug << " " << info_ptr->debug << std::endl;
    if (info_ptr->info == 0) sleep(1);
  } while (info_ptr->info == 0);
  std::cerr << "host info is at physical address "
    << (void*)info_ptr->info << std::endl;

  auto info = micmem.access(PhysPtr<HostInfoTable>(info_ptr->info));
  cpu::clflush(info.addr());
  std::cerr << "debug stream is at physical address "
    << (void*)info->debugOut << std::endl;

  auto debugOutChannel = micmem.access(PhysPtr<HostInfoTable::DebugChannel>(info->debugOut));
  PCIeRingConsumer<HostInfoTable::DebugChannel> debugOut(debugOutChannel.addr());

  // drop root to allow file logger access to user specific directories
  drop_root();

  // collect messages until whole message arrived
  std::unordered_map<uint16_t, std::stringstream*> messages;

  // log to directory debug
  file_logger logger("debug");

  while (true) {
    //typedef HostInfoTable::DebugChannel::handle_t handle_t;
    auto handle = debugOut.acquireRecv();
    auto& msg = debugOut.get<DebugMsg>(handle);

    auto found = messages.find(msg.vchannel);
    if (found != messages.end()) { // a message already there, have to merge them
      if (msg.msgbytes < DebugMsg::PAYLOAD) { // output merged messages
        found->second->write(msg.data, msg.msgbytes);
        auto str = found->second->str();
        std::cout << found->first  << "(" << str.length() << "): ";
        std::cout << str << "\n";
        logger.log(found->first, str);
        messages.erase(msg.vchannel);
      } else { // append another message
        found->second->write(msg.data, DebugMsg::PAYLOAD);
      }
    } else { // message not in buffer
      if (msg.msgbytes < DebugMsg::PAYLOAD) { // message displayed directly
        std::cout << msg.vchannel << "(" << msg.msgbytes << "): ";
        std::cout.write(msg.data, msg.msgbytes);
        std::cout << std::endl;
        logger.log(msg.vchannel, std::string(msg.data, msg.msgbytes));

      } else { // new buffer
        std::stringstream *s = new std::stringstream();
        s->write(msg.data, DebugMsg::PAYLOAD);
        messages.insert({msg.vchannel, s});
      }
    }
    debugOut.finishRecv(handle);
  }

  return 0;
}
<commit_msg>added error handling when not able to drop root privileges<commit_after>/* -*- mode:C++; -*- */
/* MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2016 Randolf Rotta, Maik Krüger, Robert Kuban, and contributors, BTU Cottbus-Senftenberg
 */
#include "host/MemMapperPci.hh"
#include "mythos/HostInfoTable.hh"
#include "mythos/PciMsgQueueMPSC.hh"
#include "cpu/clflush.hh"
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <unordered_map>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>

using namespace mythos;

// Environmental variables set if program is called by sudo
static const constexpr char* ENV_UID = "SUDO_UID";
static const constexpr char* ENV_GID = "SUDO_GID";

  template<typename T>
void parsenum(char const *str, T& val)
{
  std::stringstream s;
  if (str[0] == '0' && str[1] == 'x')
    s << std::hex << str;
  else
    s << str;
  s >> val;
}

std::string deviceKNC(int adapter)
{
  std::stringstream s;
  // choose the aperture memory file with the write combining enabled.
  s << "/sys/class/mic/mic" << adapter << "/device/resource0"; /// @todo or _wc ???
  return s.str();
}

void drop_root() {
  if (getuid() != 0) {
    std::cerr << "Cannot drop root when not root.\n";
    return;
  }
  char *gid = std::getenv(ENV_GID);
  char *uid = std::getenv(ENV_UID);
  if (gid == nullptr || uid == nullptr) {
    std::cerr << "No environment variables. Application has to be run with sudo.\n";
    return;
  }
  if (setgid(atoi(std::getenv(ENV_GID))) != 0) {
    std::cerr << "Could not restore Group ID.\n";
  }
  if (setuid(atoi(std::getenv(ENV_UID))) != 0) {
    std::cerr << "Could not restore User ID.\n";
  }
  if (getuid() == 0) {
    std::cerr << "Dropping root unsuccessful\n";
  }
}

struct InfoPtr {
  uint64_t info;
  uint64_t debug;
};

/// Class logs into files, opening new file for every sending channel id.
class file_logger {
  public:

    file_logger(const char *directory_)
      :directory(directory_) {
        std::stringstream s;
        s << getenv("PWD") << "/" << directory;
        if (mkdir(s.str().c_str(),
              S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
        {
          std::cerr << "Error creating directory for logs.\n";
        }
      }

    ~file_logger() {
      for (auto f : files) {
        f.second->close();
        delete f.second;
      }
    }

    void log(uint16_t vchannel, std::string msg) {
      auto found = files.find(vchannel);
      if (found != files.end()) {
        *found->second << msg << "\n";
        found->second->flush();
      } else {
        std::ofstream *file_stream = new std::ofstream(
            directory + std::string("/") + std::to_string(vchannel),
            std::ios::out | std::ios::trunc);
        if (!file_stream->is_open()) {
          std::cerr << "Could not open file " << (std::to_string(vchannel)) << "\n";
          return;
        }
        files.insert({vchannel, file_stream});
        *file_stream << msg << "\n";
        file_stream->flush();
      }
    }

  private:
    const std::string directory;
    std::unordered_map<uint16_t, std::ofstream*> files;
};

int main(int argc, char** argv)
{
  int adapter;
  if (argc < 2) {
    std::cerr << argv[0] << " adapter" << std::endl;
    return -1;
  }
  parsenum(argv[1], adapter);
  std::cerr << "will read from adapter " << adapter
    << " file " << deviceKNC(adapter) << std::endl;
  MemMapperPci micmem(deviceKNC(adapter));

  // wait until the _host_info_ptr pointer at address 2MiB actually contains something
  auto info_ptr = micmem.access(PhysPtr<InfoPtr>(0x200000ull));
  do {
    cpu::clflush(info_ptr.addr());
    std::cout << "info: " << (void*)info_ptr->info << " debug: " << (void*)info_ptr->debug << " " << info_ptr->debug << std::endl;
    if (info_ptr->info == 0) sleep(1);
  } while (info_ptr->info == 0);
  std::cerr << "host info is at physical address "
    << (void*)info_ptr->info << std::endl;

  auto info = micmem.access(PhysPtr<HostInfoTable>(info_ptr->info));
  cpu::clflush(info.addr());
  std::cerr << "debug stream is at physical address "
    << (void*)info->debugOut << std::endl;

  auto debugOutChannel = micmem.access(PhysPtr<HostInfoTable::DebugChannel>(info->debugOut));
  PCIeRingConsumer<HostInfoTable::DebugChannel> debugOut(debugOutChannel.addr());

  // drop root to allow file logger access to user specific directories
  drop_root();

  // collect messages until whole message arrived
  std::unordered_map<uint16_t, std::stringstream*> messages;

  // log to directory debug
  file_logger logger("debug");

  while (true) {
    //typedef HostInfoTable::DebugChannel::handle_t handle_t;
    auto handle = debugOut.acquireRecv();
    auto& msg = debugOut.get<DebugMsg>(handle);

    auto found = messages.find(msg.vchannel);
    if (found != messages.end()) { // a message already there, have to merge them
      if (msg.msgbytes < DebugMsg::PAYLOAD) { // output merged messages
        found->second->write(msg.data, msg.msgbytes);
        auto str = found->second->str();
        std::cout << found->first  << "(" << str.length() << "): ";
        std::cout << str << "\n";
        logger.log(found->first, str);
        messages.erase(msg.vchannel);
      } else { // append another message
        found->second->write(msg.data, DebugMsg::PAYLOAD);
      }
    } else { // message not in buffer
      if (msg.msgbytes < DebugMsg::PAYLOAD) { // message displayed directly
        std::cout << msg.vchannel << "(" << msg.msgbytes << "): ";
        std::cout.write(msg.data, msg.msgbytes);
        std::cout << std::endl;
        logger.log(msg.vchannel, std::string(msg.data, msg.msgbytes));

      } else { // new buffer
        std::stringstream *s = new std::stringstream();
        s->write(msg.data, DebugMsg::PAYLOAD);
        messages.insert({msg.vchannel, s});
      }
    }
    debugOut.finishRecv(handle);
  }

  return 0;
}
<|endoftext|>


<commit_before>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    combined_solver.cpp

Abstract:

    Implements the solver API by combining two solvers.

    This is a replacement for the strategic_solver class.

Author:

    Leonardo (leonardo) 2012-12-11

Notes:

--*/
#include"solver.h"
#include"scoped_timer.h"
#include"combined_solver_params.hpp"
#define PS_VB_LVL 15

/**
   \brief Implementation of the solver API that combines two given solvers.

   The combined solver has two modes:
       - non-incremental
       - incremental
   In non-incremental mode, the first solver is used.
   In incremental mode, the second one is used.

   A timeout for the second solver can be specified.
   If the timeout is reached, then the first solver is executed.

   The object switches to incremental when:
       - push is used
       - assertions are peformed after a check_sat
       - parameter ignore_solver1==false
*/
class combined_solver : public solver {
public:
    // Behavior when the incremental solver returns unknown.
    enum inc_unknown_behavior {
        IUB_RETURN_UNDEF,      // just return unknown
        IUB_USE_TACTIC_IF_QF,  // invoke tactic if problem is quantifier free
        IUB_USE_TACTIC         // invoke tactic
    };

private:
    bool                 m_inc_mode;
    bool                 m_check_sat_executed;
    bool                 m_use_solver1_results;
    ref<solver>          m_solver1;
    ref<solver>          m_solver2;
    // We delay sending assertions to solver 2
    // This is relevant for big benchmarks that are meant to be solved
    // by a non-incremental solver.
    bool                 m_solver2_initialized;

    bool                 m_ignore_solver1;
    inc_unknown_behavior m_inc_unknown_behavior;
    unsigned             m_inc_timeout;

    void init_solver2_assertions() {
        if (m_solver2_initialized)
            return;
        unsigned sz = m_solver1->get_num_assertions();
        for (unsigned i = 0; i < sz; i++) {
            m_solver2->assert_expr(m_solver1->get_assertion(i));
        }
        m_solver2_initialized = true;
    }

    void switch_inc_mode() {
        m_inc_mode = true;
        init_solver2_assertions();
    }

    struct aux_timeout_eh : public event_handler {
        solver *        m_solver;
        volatile bool   m_canceled;
        aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {}
        virtual void operator()() {
            m_solver->get_manager().limit().cancel();
            m_canceled = true;
        }
    };

    void updt_local_params(params_ref const & _p) {
        combined_solver_params p(_p);
        m_inc_timeout    = p.solver2_timeout();
        m_ignore_solver1 = p.ignore_solver1();
        m_inc_unknown_behavior = static_cast<inc_unknown_behavior>(p.solver2_unknown());
    }

    virtual ast_manager& get_manager() { return m_solver1->get_manager(); }

    bool has_quantifiers() const {
        unsigned sz = get_num_assertions();
        for (unsigned i = 0; i < sz; i++) {
            if (::has_quantifiers(get_assertion(i)))
                return true;
        }
        return false;
    }

    bool use_solver1_when_undef() const {
        switch (m_inc_unknown_behavior) {
        case IUB_RETURN_UNDEF: return false;
        case IUB_USE_TACTIC_IF_QF: return !has_quantifiers();
        case IUB_USE_TACTIC: return true;
        default:
            UNREACHABLE();
            return false;
        }
    }

public:
    combined_solver(solver * s1, solver * s2, params_ref const & p) {
        m_solver1 = s1;
        m_solver2 = s2;
        updt_local_params(p);
        m_solver2_initialized = false;
        m_inc_mode            = false;
        m_check_sat_executed  = false;
        m_use_solver1_results = true;
    }

    solver* translate(ast_manager& m, params_ref const& p) {
        solver* s1 = m_solver1->translate(m, p);
        solver* s2 = m_solver2->translate(m, p);
        combined_solver* r = alloc(combined_solver, s1, s2, p);
        r->m_solver2_initialized = m_solver2_initialized;
        r->m_inc_mode = m_inc_mode;
        r->m_check_sat_executed = m_check_sat_executed;
        r->m_use_solver1_results = m_use_solver1_results;
        return r;
    }

    virtual void updt_params(params_ref const & p) {
        m_solver1->updt_params(p);
        m_solver2->updt_params(p);
        updt_local_params(p);
    }

    virtual void collect_param_descrs(param_descrs & r) {
        m_solver1->collect_param_descrs(r);
        m_solver2->collect_param_descrs(r);
        combined_solver_params::collect_param_descrs(r);
    }

    virtual void set_produce_models(bool f) {
        m_solver1->set_produce_models(f);
        m_solver2->set_produce_models(f);
    }

    virtual void assert_expr(expr * t) {
        if (m_check_sat_executed)
            switch_inc_mode();
        m_solver1->assert_expr(t);
        if (m_solver2_initialized)
            m_solver2->assert_expr(t);
    }

    virtual void assert_expr(expr * t, expr * a) {
        if (m_check_sat_executed)
            switch_inc_mode();
        m_solver1->assert_expr(t, a);
        init_solver2_assertions();
        m_solver2->assert_expr(t, a);
    }

    virtual void push() {
        switch_inc_mode();
        m_solver1->push();
        m_solver2->push();
    }

    virtual void pop(unsigned n) {
        switch_inc_mode();
        m_solver1->pop(n);
        m_solver2->pop(n);
    }

    virtual unsigned get_scope_level() const {
        return m_solver1->get_scope_level();
    }

    virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
        m_check_sat_executed  = true;
        m_use_solver1_results = false;

        if (get_num_assumptions() != 0 ||
            num_assumptions > 0 || // assumptions were provided
            m_ignore_solver1)  {
            // must use incremental solver
            switch_inc_mode();
            return m_solver2->check_sat(num_assumptions, assumptions);
        }

        if (m_inc_mode) {
            if (m_inc_timeout == UINT_MAX) {
                IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";);
                lbool r = m_solver2->check_sat(0, 0);
                if (r != l_undef || !use_solver1_when_undef()) {
                    return r;
                }
            }
            else {
                IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (with timeout)\")\n";);
                aux_timeout_eh eh(m_solver2.get());
                lbool r;
                {
                    scoped_timer timer(m_inc_timeout, &eh);
                    r = m_solver2->check_sat(0, 0);
                }
                if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) {
                    return r;
                }
                if (eh.m_canceled) {
                    m_solver1->get_manager().limit().reset_cancel();
                }
            }
            IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";);
        }

        IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";);
        m_use_solver1_results = true;
        return m_solver1->check_sat(0, 0);
    }

    virtual void set_progress_callback(progress_callback * callback) {
        m_solver1->set_progress_callback(callback);
        m_solver2->set_progress_callback(callback);
    }

    virtual unsigned get_num_assertions() const {
        return m_solver1->get_num_assertions();
    }

    virtual expr * get_assertion(unsigned idx) const {
        return m_solver1->get_assertion(idx);
    }

    virtual unsigned get_num_assumptions() const {
        return m_solver1->get_num_assumptions() + m_solver2->get_num_assumptions();
    }

    virtual expr * get_assumption(unsigned idx) const {
        unsigned c1 = m_solver1->get_num_assumptions();
        if (idx < c1) return m_solver1->get_assumption(idx);
        return m_solver2->get_assumption(idx - c1);
    }

    virtual void display(std::ostream & out) const {
        m_solver1->display(out);
    }

    virtual void collect_statistics(statistics & st) const {
        if (m_use_solver1_results)
            m_solver1->collect_statistics(st);
        else
            m_solver2->collect_statistics(st);
    }

    virtual void get_unsat_core(ptr_vector<expr> & r) {
        if (m_use_solver1_results)
            m_solver1->get_unsat_core(r);
        else
            m_solver2->get_unsat_core(r);
    }

    virtual void get_model(model_ref & m) {
        if (m_use_solver1_results)
            m_solver1->get_model(m);
        else
            m_solver2->get_model(m);
    }

    virtual proof * get_proof() {
        if (m_use_solver1_results)
            return m_solver1->get_proof();
        else
            return m_solver2->get_proof();
    }

    virtual std::string reason_unknown() const {
        if (m_use_solver1_results)
            return m_solver1->reason_unknown();
        else
            return m_solver2->reason_unknown();
    }

    virtual void set_reason_unknown(char const* msg) {
        m_solver1->set_reason_unknown(msg);
        m_solver2->set_reason_unknown(msg);
    }

    virtual void get_labels(svector<symbol> & r) {
        if (m_use_solver1_results)
            return m_solver1->get_labels(r);
        else
            return m_solver2->get_labels(r);
    }

};

solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p) {
    return alloc(combined_solver, s1, s2, p);
}

class combined_solver_factory : public solver_factory {
    scoped_ptr<solver_factory> m_f1;
    scoped_ptr<solver_factory> m_f2;
public:
    combined_solver_factory(solver_factory * f1, solver_factory * f2):m_f1(f1), m_f2(f2) {}
    virtual ~combined_solver_factory() {}

    virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) {
        return mk_combined_solver((*m_f1)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic),
                                  (*m_f2)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic),
                                  p);
    }
};

solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2) {
    return alloc(combined_solver_factory, f1, f2);
}
<commit_msg>add exception handling for making solver-1 discontinuation transparent, thanks to Martin, #497<commit_after>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    combined_solver.cpp

Abstract:

    Implements the solver API by combining two solvers.

    This is a replacement for the strategic_solver class.

Author:

    Leonardo (leonardo) 2012-12-11

Notes:

--*/
#include"solver.h"
#include"scoped_timer.h"
#include"combined_solver_params.hpp"
#define PS_VB_LVL 15

/**
   \brief Implementation of the solver API that combines two given solvers.

   The combined solver has two modes:
       - non-incremental
       - incremental
   In non-incremental mode, the first solver is used.
   In incremental mode, the second one is used.

   A timeout for the second solver can be specified.
   If the timeout is reached, then the first solver is executed.

   The object switches to incremental when:
       - push is used
       - assertions are peformed after a check_sat
       - parameter ignore_solver1==false
*/
class combined_solver : public solver {
public:
    // Behavior when the incremental solver returns unknown.
    enum inc_unknown_behavior {
        IUB_RETURN_UNDEF,      // just return unknown
        IUB_USE_TACTIC_IF_QF,  // invoke tactic if problem is quantifier free
        IUB_USE_TACTIC         // invoke tactic
    };

private:
    bool                 m_inc_mode;
    bool                 m_check_sat_executed;
    bool                 m_use_solver1_results;
    ref<solver>          m_solver1;
    ref<solver>          m_solver2;
    // We delay sending assertions to solver 2
    // This is relevant for big benchmarks that are meant to be solved
    // by a non-incremental solver.
    bool                 m_solver2_initialized;

    bool                 m_ignore_solver1;
    inc_unknown_behavior m_inc_unknown_behavior;
    unsigned             m_inc_timeout;

    void init_solver2_assertions() {
        if (m_solver2_initialized)
            return;
        unsigned sz = m_solver1->get_num_assertions();
        for (unsigned i = 0; i < sz; i++) {
            m_solver2->assert_expr(m_solver1->get_assertion(i));
        }
        m_solver2_initialized = true;
    }

    void switch_inc_mode() {
        m_inc_mode = true;
        init_solver2_assertions();
    }

    struct aux_timeout_eh : public event_handler {
        solver *        m_solver;
        volatile bool   m_canceled;
        aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {}
        virtual void operator()() {
            m_solver->get_manager().limit().cancel();
            m_canceled = true;
        }
    };

    void updt_local_params(params_ref const & _p) {
        combined_solver_params p(_p);
        m_inc_timeout    = p.solver2_timeout();
        m_ignore_solver1 = p.ignore_solver1();
        m_inc_unknown_behavior = static_cast<inc_unknown_behavior>(p.solver2_unknown());
    }

    virtual ast_manager& get_manager() { return m_solver1->get_manager(); }

    bool has_quantifiers() const {
        unsigned sz = get_num_assertions();
        for (unsigned i = 0; i < sz; i++) {
            if (::has_quantifiers(get_assertion(i)))
                return true;
        }
        return false;
    }

    bool use_solver1_when_undef() const {
        switch (m_inc_unknown_behavior) {
        case IUB_RETURN_UNDEF: return false;
        case IUB_USE_TACTIC_IF_QF: return !has_quantifiers();
        case IUB_USE_TACTIC: return true;
        default:
            UNREACHABLE();
            return false;
        }
    }

public:
    combined_solver(solver * s1, solver * s2, params_ref const & p) {
        m_solver1 = s1;
        m_solver2 = s2;
        updt_local_params(p);
        m_solver2_initialized = false;
        m_inc_mode            = false;
        m_check_sat_executed  = false;
        m_use_solver1_results = true;
    }

    solver* translate(ast_manager& m, params_ref const& p) {
        solver* s1 = m_solver1->translate(m, p);
        solver* s2 = m_solver2->translate(m, p);
        combined_solver* r = alloc(combined_solver, s1, s2, p);
        r->m_solver2_initialized = m_solver2_initialized;
        r->m_inc_mode = m_inc_mode;
        r->m_check_sat_executed = m_check_sat_executed;
        r->m_use_solver1_results = m_use_solver1_results;
        return r;
    }

    virtual void updt_params(params_ref const & p) {
        m_solver1->updt_params(p);
        m_solver2->updt_params(p);
        updt_local_params(p);
    }

    virtual void collect_param_descrs(param_descrs & r) {
        m_solver1->collect_param_descrs(r);
        m_solver2->collect_param_descrs(r);
        combined_solver_params::collect_param_descrs(r);
    }

    virtual void set_produce_models(bool f) {
        m_solver1->set_produce_models(f);
        m_solver2->set_produce_models(f);
    }

    virtual void assert_expr(expr * t) {
        if (m_check_sat_executed)
            switch_inc_mode();
        m_solver1->assert_expr(t);
        if (m_solver2_initialized)
            m_solver2->assert_expr(t);
    }

    virtual void assert_expr(expr * t, expr * a) {
        if (m_check_sat_executed)
            switch_inc_mode();
        m_solver1->assert_expr(t, a);
        init_solver2_assertions();
        m_solver2->assert_expr(t, a);
    }

    virtual void push() {
        switch_inc_mode();
        m_solver1->push();
        m_solver2->push();
    }

    virtual void pop(unsigned n) {
        switch_inc_mode();
        m_solver1->pop(n);
        m_solver2->pop(n);
    }

    virtual unsigned get_scope_level() const {
        return m_solver1->get_scope_level();
    }

    virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
        m_check_sat_executed  = true;
        m_use_solver1_results = false;

        if (get_num_assumptions() != 0 ||
            num_assumptions > 0 || // assumptions were provided
            m_ignore_solver1)  {
            // must use incremental solver
            switch_inc_mode();
            return m_solver2->check_sat(num_assumptions, assumptions);
        }

        if (m_inc_mode) {
            if (m_inc_timeout == UINT_MAX) {
                IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";);
                lbool r = m_solver2->check_sat(0, 0);
                if (r != l_undef || !use_solver1_when_undef()) {
                    return r;
                }
            }
            else {
                IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (with timeout)\")\n";);
                aux_timeout_eh eh(m_solver2.get());
                lbool r = l_undef;
                try {
                    scoped_timer timer(m_inc_timeout, &eh);
                    r = m_solver2->check_sat(0, 0);
                }
                catch (z3_exception&) {
                    if (!eh.m_canceled) {
                        throw;
                    }
                }
                if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) {
                    return r;
                }
                if (eh.m_canceled) {
                    m_solver1->get_manager().limit().reset_cancel();
                }
            }
            IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";);
        }

        IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";);
        m_use_solver1_results = true;
        return m_solver1->check_sat(0, 0);
    }

    virtual void set_progress_callback(progress_callback * callback) {
        m_solver1->set_progress_callback(callback);
        m_solver2->set_progress_callback(callback);
    }

    virtual unsigned get_num_assertions() const {
        return m_solver1->get_num_assertions();
    }

    virtual expr * get_assertion(unsigned idx) const {
        return m_solver1->get_assertion(idx);
    }

    virtual unsigned get_num_assumptions() const {
        return m_solver1->get_num_assumptions() + m_solver2->get_num_assumptions();
    }

    virtual expr * get_assumption(unsigned idx) const {
        unsigned c1 = m_solver1->get_num_assumptions();
        if (idx < c1) return m_solver1->get_assumption(idx);
        return m_solver2->get_assumption(idx - c1);
    }

    virtual void display(std::ostream & out) const {
        m_solver1->display(out);
    }

    virtual void collect_statistics(statistics & st) const {
        if (m_use_solver1_results)
            m_solver1->collect_statistics(st);
        else
            m_solver2->collect_statistics(st);
    }

    virtual void get_unsat_core(ptr_vector<expr> & r) {
        if (m_use_solver1_results)
            m_solver1->get_unsat_core(r);
        else
            m_solver2->get_unsat_core(r);
    }

    virtual void get_model(model_ref & m) {
        if (m_use_solver1_results)
            m_solver1->get_model(m);
        else
            m_solver2->get_model(m);
    }

    virtual proof * get_proof() {
        if (m_use_solver1_results)
            return m_solver1->get_proof();
        else
            return m_solver2->get_proof();
    }

    virtual std::string reason_unknown() const {
        if (m_use_solver1_results)
            return m_solver1->reason_unknown();
        else
            return m_solver2->reason_unknown();
    }

    virtual void set_reason_unknown(char const* msg) {
        m_solver1->set_reason_unknown(msg);
        m_solver2->set_reason_unknown(msg);
    }

    virtual void get_labels(svector<symbol> & r) {
        if (m_use_solver1_results)
            return m_solver1->get_labels(r);
        else
            return m_solver2->get_labels(r);
    }

};

solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p) {
    return alloc(combined_solver, s1, s2, p);
}

class combined_solver_factory : public solver_factory {
    scoped_ptr<solver_factory> m_f1;
    scoped_ptr<solver_factory> m_f2;
public:
    combined_solver_factory(solver_factory * f1, solver_factory * f2):m_f1(f1), m_f2(f2) {}
    virtual ~combined_solver_factory() {}

    virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) {
        return mk_combined_solver((*m_f1)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic),
                                  (*m_f2)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic),
                                  p);
    }
};

solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2) {
    return alloc(combined_solver_factory, f1, f2);
}
<|endoftext|>