<commit_before>// Some ideas of how to implement hierarchical ("sub-command") completion with
// readline, where each sub-command can have its own completion options.
//
// Eli Bendersky [http://eli.thegreenplace.net]
// This code is in the public domain.
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>

#include <readline/readline.h>
#include <readline/history.h>

#include "utils.h"

const char* WHITESPACE = " \t";

// TODO: simple registration of subcommands in some way, each with its own
// subcommands (?) Maybe with a flag to complete filenames for certain commands
std::vector<std::string> vocabulary{"file",   "cat", "dog",
                                    "canary", "cow", "hamster"};

bool is_file_command(const std::vector<Token>& tokens, int cursor) {
  if (tokens.size() == 0) {
    return false;
  }
  const Token& command = tokens[0];
  if (static_cast<size_t>(cursor) > command.buf_index + command.text.size() &&
      command.text == "file") {
    return true;
  } else {
    return false;
  }
}

char** completer(const char* text, int start, int end) {
  std::vector<Token> line_tokens = tokenize_line_buffer(rl_line_buffer);
  if (is_file_command(line_tokens, start)) {
    // Request filename completion.
    return nullptr;
  }

  // Disable default filename completion even if we don't find completion
  // matches.
  rl_attempted_completion_over = 1;

  // Filter out all words in the vocabulary that do not begin with `text`.
  std::string textstr(text);
  std::vector<std::string> matches;
  std::copy_if(vocabulary.begin(), vocabulary.end(),
               std::back_inserter(matches), [&textstr](const std::string& s) {
                 return (s.size() >= textstr.size() &&
                         s.compare(0, textstr.size(), textstr) == 0);
               });
  if (matches.empty()) {
    return nullptr;
  }

  char** array =
      static_cast<char**>(malloc((2 + matches.size()) * sizeof(*array)));
  array[0] = strdup(longest_common_prefix(textstr, matches).c_str());
  size_t ptr = 1;
  for (const auto& m : matches) {
    array[ptr++] = strdup(m.c_str());
  }
  array[ptr] = nullptr;
  return array;
}

int main(int argc, char** argv) {
  printf("Welcome! You can exit by pressing Ctrl+C at any time...\n");

  // Register our custom comleter with readline.
  rl_attempted_completion_function = completer;

  char* buf;
  while ((buf = readline(">> ")) != nullptr) {
    if (strlen(buf) > 0) {
      add_history(buf);
    }

    printf("[%s]\n", buf);

    // readline malloc's a new buffer every time.
    free(buf);
  }

  return 0;
}
<commit_msg>Implement basic subcommand completion here, "for real"<commit_after>// Some ideas of how to implement hierarchical ("sub-command") completion with
// readline, where each sub-command can have its own completion options.
//
// This is a very simple implementation just to demonstrate a point. In a
// realistic program things would be better factored out. Note that using
// globals at least to some degree is unavoidable since readline takes bare
// functions pointers into C code, so there's no way to pass in state/context.
// Luckily, command-line completion is handled in a singple place in an
// application anyway.
//
// Eli Bendersky [http://eli.thegreenplace.net]
// This code is in the public domain.
#include <algorithm>
#include <iostream>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>

#include <readline/readline.h>
#include <readline/history.h>

#include "utils.h"

const char* WHITESPACE = " \t";

using CommandVocabulary = std::map<std::string, std::vector<std::string>>;

CommandVocabulary command_vocabulary = {
    {"file", {}},
    {"eat", {"breakfast", "dinner", "lunch", "snack"}},
    {"play", {"cards", "chess", "go"}},
    {"walk", {"left", "right", "straight"}}};

// All supported commands - populated from command_vocabulary in main().
std::vector<std::string> all_commands;

// Determines if we're supposed to complete a sub-command now. Takes the input
// line typed in so far, split to tokens, and the cursor location. Returns the
// command name if a subcommand is expected (the command is always the first
// token on the line), and "" if it seems like we're still completing the
// command itself.
std::string find_command(const std::vector<Token>& tokens, int cursor) {
  if (tokens.size() == 0) {
    return "";
  }
  const Token& command = tokens[0];
  if (static_cast<size_t>(cursor) > command.buf_index + command.text.size()) {
    return command.text;
  } else {
    return "";
  }
}

char** completer(const char* text, int start, int end) {
  std::vector<Token> line_tokens = tokenize_line_buffer(rl_line_buffer);
  std::string command = find_command(line_tokens, start);
  // The "file" command is special and must be intercepted early, so that we
  // can return nullptr from here before setting rl_attempted_completion_over.
  if (command == "file") {
    // Request filename completion.
    return nullptr;
  }

  // Disable default filename completion even if we don't find completion
  // matches.
  rl_attempted_completion_over = 1;

  // Find which vocabulary to auto-complete from; if we're now completing the
  // command, point to all_commands. If the command was already entered, find
  // the subcommands vocabulary to complete.
  std::vector<std::string>* vocabulary;
  if (command == "") {
    vocabulary = &all_commands;
  } else {
    auto command_iter = command_vocabulary.find(command);
    if (command_iter == command_vocabulary.end()) {
      return nullptr;
    }
    vocabulary = &(command_iter->second);
  }

  // Filter out all words in the vocabulary that do not begin with `text`.
  std::string textstr(text);
  std::vector<std::string> matches;
  std::copy_if(vocabulary->begin(), vocabulary->end(),
               std::back_inserter(matches), [&textstr](const std::string& s) {
                 return (s.size() >= textstr.size() &&
                         s.compare(0, textstr.size(), textstr) == 0);
               });
  if (matches.empty()) {
    return nullptr;
  }

  char** array =
      static_cast<char**>(malloc((2 + matches.size()) * sizeof(*array)));
  array[0] = strdup(longest_common_prefix(textstr, matches).c_str());
  size_t ptr = 1;
  for (const auto& m : matches) {
    array[ptr++] = strdup(m.c_str());
  }
  array[ptr] = nullptr;
  return array;
}

int main(int argc, char** argv) {
  printf("Welcome! You can exit by pressing Ctrl+C at any time...\n");

  for (auto const& kv : command_vocabulary) {
    all_commands.push_back(kv.first);
  }

  // Register our custom comleter with readline.
  rl_attempted_completion_function = completer;

  char* buf;
  while ((buf = readline(">> ")) != nullptr) {
    if (strlen(buf) > 0) {
      add_history(buf);
    }

    printf("[%s]\n", buf);

    // readline malloc's a new buffer every time.
    free(buf);
  }

  return 0;
}
<|endoftext|>


<commit_before>/**
 * Created by Jian Chen
 * @since  2015.07.29
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#pragma once

#include <ostream>
#include <cstdio>
#include <vector>
#include <string>
#include <mutex>

namespace chen
{
    class str
    {
    public:
        /**
         * Format string using std::vsnprintf
         * @thread-safe
         */
        static std::string format(const char *fmt)
        {
            // to improve performance, return fmt if no other params
            return fmt;
        }

        template <typename ...Args>
        static std::string format(const char *fmt, Args... args)
        {
            auto size = ::snprintf(nullptr, 0, fmt, args...);
            if (size <= 0)
                return "";

            std::string ret(++size, '\0');

			size = ::snprintf(&ret[0], size, fmt, args...);
			if (size <= 0)  // re-check
				return "";

			ret.resize(size);
			return ret;
        }

        /**
         * Print string to standard output or custom stream, the output order is guaranteed
         * @thread-safe
         */
        template <typename ...Args>
        static void printf(const char *fmt, Args... args)
        {
            str::print(str::format(fmt, args...), false);
        }

        template <typename ...Args>
        static void printf(std::ostream &out, const char *fmt, Args... args)
        {
            str::print(out, str::format(fmt, args...), false);
        }

        template <typename ...Args>
        static void printf(std::ostream &out, std::mutex &mutex, const char *fmt, Args... args)
        {
            str::print(out, mutex, str::format(fmt, args...), false);
        }

        static void print(const std::string &text, bool br = true);
        static void print(std::ostream &out, const std::string &text, bool br = true);
        static void print(std::ostream &out, std::mutex &mutex, const std::string &text, bool br = true);

        /**
         * Test if two strings are equal
         */
        static bool equal(const char *str1, std::size_t size1,
                          const char *str2, std::size_t size2);

        /**
         * Check prefix & suffix
         */
        static bool prefix(const std::string &text, const std::string &prefix);
        static bool suffix(const std::string &text, const std::string &suffix);

        /**
         * Test if text contains a string
         */
        static bool contain(const std::string &text, const std::string &search);

        /**
         * Check the number of occurrences in the string
         */
        static std::size_t count(const std::string &text, const std::string &search);

        /**
         * Split a string to vector
         */
        static std::vector<std::string> split(const std::string &text, const std::string &delimiter);

        /**
         * Join a string vector to single string
         */
        static std::string join(const std::vector<std::string> &text, const std::string &delimiter);

        /**
         * Replace text
         */
        static std::string& replace(std::string &text, const std::string &search, const std::string &replace, bool all = true);
        static std::string& remove(std::string &text, const std::string &search, bool all = true);

        static std::string replace(const std::string &text, const std::string &search, const std::string &replace, bool all = true);
        static std::string remove(const std::string &text, const std::string &search, bool all = true);

        /**
         * Trim white spaces
         */
        static std::string& trim(std::string &text);
        static std::string& ltrim(std::string &text);
        static std::string& rtrim(std::string &text);

        static std::string trim(const std::string &text);
        static std::string ltrim(const std::string &text);
        static std::string rtrim(const std::string &text);

        /**
         * Transform string
         */
        static std::string& lowercase(std::string &text);
        static std::string& uppercase(std::string &text);
        static std::string& capitalize(std::string &text);

        static std::string lowercase(const std::string &text);
        static std::string uppercase(const std::string &text);
        static std::string capitalize(const std::string &text);

        /**
         * Levenshtein distance
         * @link https://en.wikipedia.org/wiki/Levenshtein_distance
         */
        static std::size_t levenshtein(const char *s, std::size_t len_s, const char *t, std::size_t len_t);
    };
}<commit_msg>str: static cast size<commit_after>/**
 * Created by Jian Chen
 * @since  2015.07.29
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#pragma once

#include <ostream>
#include <cstdio>
#include <vector>
#include <string>
#include <mutex>

namespace chen
{
    class str
    {
    public:
        /**
         * Format string using std::vsnprintf
         * @thread-safe
         */
        static std::string format(const char *fmt)
        {
            // to improve performance, return fmt if no other params
            return fmt;
        }

        template <typename ...Args>
        static std::string format(const char *fmt, Args... args)
        {
            auto size = ::snprintf(nullptr, 0, fmt, args...);
            if (size <= 0)
                return "";

            std::string ret(++size, '\0');

			size = ::snprintf(&ret[0], static_cast<std::size_t>(size), fmt, args...);
			if (size <= 0)  // re-check
				return "";

			ret.resize(static_cast<std::size_t>(size));
			return ret;
        }

        /**
         * Print string to standard output or custom stream, the output order is guaranteed
         * @thread-safe
         */
        template <typename ...Args>
        static void printf(const char *fmt, Args... args)
        {
            str::print(str::format(fmt, args...), false);
        }

        template <typename ...Args>
        static void printf(std::ostream &out, const char *fmt, Args... args)
        {
            str::print(out, str::format(fmt, args...), false);
        }

        template <typename ...Args>
        static void printf(std::ostream &out, std::mutex &mutex, const char *fmt, Args... args)
        {
            str::print(out, mutex, str::format(fmt, args...), false);
        }

        static void print(const std::string &text, bool br = true);
        static void print(std::ostream &out, const std::string &text, bool br = true);
        static void print(std::ostream &out, std::mutex &mutex, const std::string &text, bool br = true);

        /**
         * Test if two strings are equal
         */
        static bool equal(const char *str1, std::size_t size1,
                          const char *str2, std::size_t size2);

        /**
         * Check prefix & suffix
         */
        static bool prefix(const std::string &text, const std::string &prefix);
        static bool suffix(const std::string &text, const std::string &suffix);

        /**
         * Test if text contains a string
         */
        static bool contain(const std::string &text, const std::string &search);

        /**
         * Check the number of occurrences in the string
         */
        static std::size_t count(const std::string &text, const std::string &search);

        /**
         * Split a string to vector
         */
        static std::vector<std::string> split(const std::string &text, const std::string &delimiter);

        /**
         * Join a string vector to single string
         */
        static std::string join(const std::vector<std::string> &text, const std::string &delimiter);

        /**
         * Replace text
         */
        static std::string& replace(std::string &text, const std::string &search, const std::string &replace, bool all = true);
        static std::string& remove(std::string &text, const std::string &search, bool all = true);

        static std::string replace(const std::string &text, const std::string &search, const std::string &replace, bool all = true);
        static std::string remove(const std::string &text, const std::string &search, bool all = true);

        /**
         * Trim white spaces
         */
        static std::string& trim(std::string &text);
        static std::string& ltrim(std::string &text);
        static std::string& rtrim(std::string &text);

        static std::string trim(const std::string &text);
        static std::string ltrim(const std::string &text);
        static std::string rtrim(const std::string &text);

        /**
         * Transform string
         */
        static std::string& lowercase(std::string &text);
        static std::string& uppercase(std::string &text);
        static std::string& capitalize(std::string &text);

        static std::string lowercase(const std::string &text);
        static std::string uppercase(const std::string &text);
        static std::string capitalize(const std::string &text);

        /**
         * Levenshtein distance
         * @link https://en.wikipedia.org/wiki/Levenshtein_distance
         */
        static std::size_t levenshtein(const char *s, std::size_t len_s, const char *t, std::size_t len_t);
    };
}<|endoftext|>


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

// ospray
#include "lights/Light.h"
#include "common/Data.h"
#include "RaycastVolumeRenderer.h"
#include "RaycastVolumeMaterial.h"
// ospcommon
#include "ospcommon/tasking/parallel_for.h"

// ours
// ispc exports
#include "RaycastVolumeRenderer_ispc.h"

#include "mpiCommon/MPICommon.h"
#include "../../fb/DistributedFrameBuffer.h"
#include "../../volume/DataDistributedBlockedVolume.h"
#include "render/LoadBalancer.h"

#define TILE_CACHE_SAFE_MUTEX 0

namespace ospray {

  using namespace mpicommon;

  Material *RaycastVolumeRenderer::createMaterial(const char *type)
  {
    UNUSED(type);
    return new RaycastVolumeMaterial;
  }

  struct CacheForBlockTiles
  {
    CacheForBlockTiles(size_t numBlocks)
      : numBlocks(numBlocks), blockTile(new Tile *[numBlocks])
    {
      for (size_t i = 0; i < numBlocks; i++)
        blockTile[i] = nullptr;
    }

    ~CacheForBlockTiles()
    {
      for (size_t i = 0; i < numBlocks; i++) {
        if (blockTile[i])
          delete blockTile[i];
      }

      delete [] blockTile;
    }

    Tile *allocTile()
    {
      float infinity = std::numeric_limits<float>::infinity();
      Tile *tile = new Tile;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->r[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->g[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->b[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->a[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->z[i] = infinity;
      return tile;
    }

    Tile *getTileForBlock(size_t blockID)
    {
#if TILE_CACHE_SAFE_MUTEX
      mutex.lock();
      Tile *tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#else
      Tile *tile = blockTile[blockID];
      if (tile != nullptr) return tile;
      mutex.lock();
      tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#endif
    }

    std::mutex mutex;
    size_t numBlocks;
    Tile *volatile *blockTile;
  };

  /*! extern exported function so even ISPC code can access this cache */
  extern "C" Tile *
  CacheForBlockTiles_getTileForBlock(CacheForBlockTiles *cache,
                                     uint32 blockID)
  {
    return cache->getTileForBlock(blockID);
  }

  struct DPRenderTask
  {
    mutable Ref<Renderer>     renderer;
    mutable Ref<FrameBuffer>  fb;
    size_t                    numTiles_x;
    size_t                    numTiles_y;
    uint32                    channelFlags;
    const DataDistributedBlockedVolume *dpv;

    void operator()(int taskIndex) const;
  };

  void DPRenderTask::operator()(int taskIndex) const
  {
    const int &tileID = taskIndex;
    const int tile_y  = tileID / numTiles_x;
    const int tile_x  = tileID - tile_y*numTiles_x;
    const vec2i tileId(tile_x, tile_y);
    const int accumID = fb->accumID(tileId);
    Tile bgTile(tileId, fb->size, accumID);
    Tile fgTile(bgTile);

    int numBlocks = dpv->numDDBlocks;
    CacheForBlockTiles blockTileCache(numBlocks);
    bool *blockWasVisible = STACK_BUFFER(bool, numBlocks);

    for (int i = 0; i < numBlocks; i++)
      blockWasVisible[i] = false;

    bool renderForeAndBackground =
        (tileID % mpicommon::numWorkers()) == mpicommon::workerRank();

    const int numJobs = (TILE_SIZE*TILE_SIZE)/RENDERTILE_PIXELS_PER_JOB;

    tasking::parallel_for(numJobs, [&](int tid){
      ispc::DDDVRRenderer_renderTile(renderer->getIE(),
                                     (ispc::Tile&)fgTile,
                                     (ispc::Tile&)bgTile,
                                     &blockTileCache,
                                     numBlocks,
                                     dpv->ddBlock,
                                     blockWasVisible,
                                     tileID,
                                     mpicommon::workerRank(),
                                     renderForeAndBackground,
                                     tid);
    });

    if (renderForeAndBackground) {
      // this is a tile owned by me - i'm responsible for writing
      // generaition #0, and telling the fb how many more tiles will
      // be coming in generation #1

      size_t totalBlocksInTile = 0;
      for (size_t blockID = 0; blockID < numBlocks; blockID++) {
        if (blockWasVisible[blockID])
          totalBlocksInTile++;
      }

      size_t nextGenTiles
          = 1 /* expect one additional tile for background tile. */
          + totalBlocksInTile /* plus how many blocks map to this
                                     tile, IN TOTAL (ie, INCLUDING blocks
                                     on other nodes)*/;

      // set background tile
      bgTile.generation = 0;
      bgTile.children   = nextGenTiles;
      fb->setTile(bgTile);

      // set foreground tile
      fgTile.generation = 1;
      fgTile.children   = 0; //nextGenTiles-1;
      fb->setTile(fgTile);
      // all other tiles for gen #1 will be set below, no matter whether
      // it's mine or not
    }

    // now, send all block cache tiles that were generated on this
    // node back to master, too. for this, it doesn't matter if this
    // is our tile or not; it's the job of the owner of this tile to
    // tell the DFB how many tiles will arrive for the final thile
    // _across_all_clients_, but we only have to send ours (assuming
    // that all clients together send exactly as many as the owner
    // told the DFB to expect)
    for (int blockID = 0; blockID < numBlocks; blockID++) {
      Tile *tile = blockTileCache.blockTile[blockID];
      if (tile == nullptr)
        continue;

      tile->region = bgTile.region;
      tile->fbSize = bgTile.fbSize;
      tile->rcp_fbSize = bgTile.rcp_fbSize;
      tile->accumID = accumID;
      tile->generation = 1;
      tile->children   = 0;

      fb->setTile(*tile);
    }
  }

  /*! try if we are running in data-parallel mode, and if
    data-parallel is even required. if not (eg, if there's no
    data-parallel volumes in the scene) return nullptr and render only
    in regular mode; otherwise, compute some precomputations and
    return pointer to that (which'll switch the main renderframe fct
    to render data parallel) */
  float RaycastVolumeRenderer::renderFrame(FrameBuffer *fb,
                                           const uint32 channelFlags)
  {
    using DDBV = DataDistributedBlockedVolume;
    std::vector<const DDBV*> ddVolumeVec;
    for (size_t volumeID = 0; volumeID < model->volume.size(); volumeID++) {
      const DDBV* ddv = dynamic_cast<const DDBV*>(model->volume[volumeID].ptr);
      if (!ddv) continue;
      ddVolumeVec.push_back(ddv);
    }

    if (ddVolumeVec.empty()) {
      static WarnOnce warning("no data parallel volumes, rendering in "
                              "traditional raycast_volume_render mode");
      return Renderer::renderFrame(fb,channelFlags);
    }

    // =======================================================
    // OK, we _need_ data-parallel rendering ....
    static WarnOnce dataParMsg("#dvr: at least one dp volume ->"
                               " needs data-parallel rendering ...");

    // check if we're even in mpi parallel mode (can't do
    // data-parallel otherwise)
    if (!mpicommon::isMpiParallel()) {
      throw std::runtime_error("#dvr: need data-parallel rendering, "
                               "but not running in mpi mode!?");
    }

    // switch (distributed) frame buffer into compositing mode
    DistributedFrameBuffer *dfb = dynamic_cast<DistributedFrameBuffer *>(fb);
    if (!dfb) {
      throw std::runtime_error("OSPRay data parallel rendering error. "
                               "this is a data-parallel scene, but we're "
                               "not using the distributed frame buffer!?");
    }

    dfb->setFrameMode(DistributedFrameBuffer::ALPHA_BLEND);

    Renderer::beginFrame(fb);

    dfb->startNewFrame(errorThreshold);

    if (ddVolumeVec.size() > 1) {
      /* note: our assumption below is that all blocks together are
         contiguous, and fill a convex region (ie, any point on a
         given ray is either entirely before any block, entirely
         behind any block, or inside one of the blocks) - if we have
         multiple data distributed volumes that is no longer the case,
         so we're not currently supporting this ... */
      throw std::runtime_error("currently supporting only ONE data parallel "
                               "volume in scene");
    }

    // create the render task
    DPRenderTask renderTask;
    renderTask.fb = fb;
    renderTask.renderer = this;
    renderTask.numTiles_x = divRoundUp(dfb->size.x, TILE_SIZE);
    renderTask.numTiles_y = divRoundUp(dfb->size.y, TILE_SIZE);
    renderTask.channelFlags = channelFlags;
    renderTask.dpv = ddVolumeVec[0];

    size_t NTASKS = renderTask.numTiles_x * renderTask.numTiles_y;
    tasking::parallel_for(NTASKS, renderTask);

    dfb->waitUntilFinished();
    Renderer::endFrame(nullptr, channelFlags);
    return fb->endFrame(0.f);
  }

  void RaycastVolumeRenderer::commit()
  {
    // Create the equivalent ISPC RaycastVolumeRenderer object.
    if (ispcEquivalent == nullptr) {
      ispcEquivalent = ispc::RaycastVolumeRenderer_createInstance();
    }

    // Set the lights if any.
    Data *lightsData = (Data *)getParamData("lights", nullptr);

    lights.clear();

    if (lightsData) {
      for (size_t i=0; i<lightsData->size(); i++)
        lights.push_back(((Light **)lightsData->data)[i]->getIE());
    }

    ispc::RaycastVolumeRenderer_setLights(ispcEquivalent,
                                          lights.empty() ? nullptr : &lights[0],
                                          lights.size());

    // Initialize state in the parent class, must be called after the ISPC
    // object is created.
    Renderer::commit();
  }

  // A renderer type for volumes with embedded surfaces.
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, raycast_volume_renderer);
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, dvr);

} // ::ospray

<commit_msg>Kind of a hacky fix for now to fix data-parallel volume rendering<commit_after>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospray
#include "lights/Light.h"
#include "common/Data.h"
#include "RaycastVolumeRenderer.h"
#include "RaycastVolumeMaterial.h"
// ospcommon
#include "ospcommon/tasking/parallel_for.h"

// ours
// ispc exports
#include "RaycastVolumeRenderer_ispc.h"

#include "mpiCommon/MPICommon.h"
#include "../../fb/DistributedFrameBuffer.h"
#include "../../volume/DataDistributedBlockedVolume.h"
#include "render/LoadBalancer.h"

#define TILE_CACHE_SAFE_MUTEX 0

namespace ospray {

  using namespace mpicommon;

  Material *RaycastVolumeRenderer::createMaterial(const char *type)
  {
    UNUSED(type);
    return new RaycastVolumeMaterial;
  }

  struct CacheForBlockTiles
  {
    CacheForBlockTiles(size_t numBlocks)
      : numBlocks(numBlocks), blockTile(new Tile *[numBlocks])
    {
      for (size_t i = 0; i < numBlocks; i++)
        blockTile[i] = nullptr;
    }

    ~CacheForBlockTiles()
    {
      for (size_t i = 0; i < numBlocks; i++) {
        if (blockTile[i])
          delete blockTile[i];
      }

      delete [] blockTile;
    }

    Tile *allocTile()
    {
      float infinity = std::numeric_limits<float>::infinity();
      Tile *tile = new Tile;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->r[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->g[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->b[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->a[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->z[i] = infinity;
      return tile;
    }

    Tile *getTileForBlock(size_t blockID)
    {
#if TILE_CACHE_SAFE_MUTEX
      mutex.lock();
      Tile *tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#else
      Tile *tile = blockTile[blockID];
      if (tile != nullptr) return tile;
      mutex.lock();
      tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#endif
    }

    std::mutex mutex;
    size_t numBlocks;
    Tile *volatile *blockTile;
  };

  /*! extern exported function so even ISPC code can access this cache */
  extern "C" Tile *
  CacheForBlockTiles_getTileForBlock(CacheForBlockTiles *cache,
                                     uint32 blockID)
  {
    return cache->getTileForBlock(blockID);
  }

  struct DPRenderTask
  {
    mutable Ref<Renderer>     renderer;
    mutable Ref<FrameBuffer>  fb;
    size_t                    numTiles_x;
    size_t                    numTiles_y;
    uint32                    channelFlags;
    const DataDistributedBlockedVolume *dpv;

    void operator()(int taskIndex) const;
  };

  void DPRenderTask::operator()(int taskIndex) const
  {
    const int &tileID = taskIndex;
    const int tile_y  = tileID / numTiles_x;
    const int tile_x  = tileID - tile_y*numTiles_x;
    const vec2i tileId(tile_x, tile_y);
    const int accumID = fb->accumID(tileId);
    Tile bgTile(tileId, fb->size, accumID);
    Tile fgTile(bgTile);

    int numBlocks = dpv->numDDBlocks;
    CacheForBlockTiles blockTileCache(numBlocks);
    bool *blockWasVisible = STACK_BUFFER(bool, numBlocks);

    for (int i = 0; i < numBlocks; i++)
      blockWasVisible[i] = false;

    bool renderForeAndBackground =
        (tileID % mpicommon::numWorkers()) == mpicommon::workerRank();

    const int numJobs = (TILE_SIZE*TILE_SIZE)/RENDERTILE_PIXELS_PER_JOB;

    tasking::parallel_for(numJobs, [&](int tid){
      ispc::DDDVRRenderer_renderTile(renderer->getIE(),
                                     (ispc::Tile&)fgTile,
                                     (ispc::Tile&)bgTile,
                                     &blockTileCache,
                                     numBlocks,
                                     dpv->ddBlock,
                                     blockWasVisible,
                                     tileID,
                                     mpicommon::workerRank(),
                                     renderForeAndBackground,
                                     tid);
    });

    if (renderForeAndBackground) {
      // this is a tile owned by me - i'm responsible for writing
      // generaition #0, and telling the fb how many more tiles will
      // be coming in generation #1

      size_t totalBlocksInTile = 0;
      for (size_t blockID = 0; blockID < numBlocks; blockID++) {
        if (blockWasVisible[blockID])
          totalBlocksInTile++;
      }

      size_t nextGenTiles
          = 1 /* expect one additional tile for background tile. */
          + totalBlocksInTile /* plus how many blocks map to this
                                     tile, IN TOTAL (ie, INCLUDING blocks
                                     on other nodes)*/;

      // set background tile
      bgTile.generation = 0;
      bgTile.children   = nextGenTiles;
      fb->setTile(bgTile);

      // set foreground tile
      fgTile.generation = 1;
      fgTile.children   = 0; //nextGenTiles-1;
      fb->setTile(fgTile);
      // all other tiles for gen #1 will be set below, no matter whether
      // it's mine or not
    }

    // now, send all block cache tiles that were generated on this
    // node back to master, too. for this, it doesn't matter if this
    // is our tile or not; it's the job of the owner of this tile to
    // tell the DFB how many tiles will arrive for the final thile
    // _across_all_clients_, but we only have to send ours (assuming
    // that all clients together send exactly as many as the owner
    // told the DFB to expect)
    for (int blockID = 0; blockID < numBlocks; blockID++) {
      Tile *tile = blockTileCache.blockTile[blockID];
      if (tile == nullptr)
        continue;

      tile->region = bgTile.region;
      tile->fbSize = bgTile.fbSize;
      tile->rcp_fbSize = bgTile.rcp_fbSize;
      tile->accumID = accumID;
      tile->generation = 1;
      tile->children   = 0;

      fb->setTile(*tile);
    }
  }

  /*! try if we are running in data-parallel mode, and if
    data-parallel is even required. if not (eg, if there's no
    data-parallel volumes in the scene) return nullptr and render only
    in regular mode; otherwise, compute some precomputations and
    return pointer to that (which'll switch the main renderframe fct
    to render data parallel) */
  float RaycastVolumeRenderer::renderFrame(FrameBuffer *fb,
                                           const uint32 channelFlags)
  {
    // The master has no data and doesn't participate in rendering, so just
    // hand back to the Master load balancer.
    if (globalRank() == 0) {
      return TiledLoadBalancer::instance->renderFrame(this, fb, channelFlags);
    }
    using DDBV = DataDistributedBlockedVolume;
    std::vector<const DDBV*> ddVolumeVec;
    for (size_t volumeID = 0; volumeID < model->volume.size(); volumeID++) {
      const DDBV* ddv = dynamic_cast<const DDBV*>(model->volume[volumeID].ptr);
      if (!ddv) continue;
      ddVolumeVec.push_back(ddv);
    }

    if (ddVolumeVec.empty()) {
      static WarnOnce warning("no data parallel volumes, rendering in "
                              "traditional raycast_volume_render mode");
      return Renderer::renderFrame(fb,channelFlags);
    }

    // =======================================================
    // OK, we _need_ data-parallel rendering ....
    static WarnOnce dataParMsg("#dvr: at least one dp volume ->"
                               " needs data-parallel rendering ...");

    // check if we're even in mpi parallel mode (can't do
    // data-parallel otherwise)
    if (!mpicommon::isMpiParallel()) {
      throw std::runtime_error("#dvr: need data-parallel rendering, "
                               "but not running in mpi mode!?");
    }

    // switch (distributed) frame buffer into compositing mode
    DistributedFrameBuffer *dfb = dynamic_cast<DistributedFrameBuffer *>(fb);
    if (!dfb) {
      throw std::runtime_error("OSPRay data parallel rendering error. "
                               "this is a data-parallel scene, but we're "
                               "not using the distributed frame buffer!?");
    }

    dfb->setFrameMode(DistributedFrameBuffer::ALPHA_BLEND);

    Renderer::beginFrame(fb);

    dfb->startNewFrame(errorThreshold);

    if (ddVolumeVec.size() > 1) {
      /* note: our assumption below is that all blocks together are
         contiguous, and fill a convex region (ie, any point on a
         given ray is either entirely before any block, entirely
         behind any block, or inside one of the blocks) - if we have
         multiple data distributed volumes that is no longer the case,
         so we're not currently supporting this ... */
      throw std::runtime_error("currently supporting only ONE data parallel "
                               "volume in scene");
    }

    // create the render task
    DPRenderTask renderTask;
    renderTask.fb = fb;
    renderTask.renderer = this;
    renderTask.numTiles_x = divRoundUp(dfb->size.x, TILE_SIZE);
    renderTask.numTiles_y = divRoundUp(dfb->size.y, TILE_SIZE);
    renderTask.channelFlags = channelFlags;
    renderTask.dpv = ddVolumeVec[0];

    size_t NTASKS = renderTask.numTiles_x * renderTask.numTiles_y;
    tasking::parallel_for(NTASKS, renderTask);

    dfb->waitUntilFinished();
    Renderer::endFrame(nullptr, channelFlags);
    return fb->endFrame(0.f);
  }

  void RaycastVolumeRenderer::commit()
  {
    // Create the equivalent ISPC RaycastVolumeRenderer object.
    if (ispcEquivalent == nullptr) {
      ispcEquivalent = ispc::RaycastVolumeRenderer_createInstance();
    }

    // Set the lights if any.
    Data *lightsData = (Data *)getParamData("lights", nullptr);

    lights.clear();

    if (lightsData) {
      for (size_t i=0; i<lightsData->size(); i++)
        lights.push_back(((Light **)lightsData->data)[i]->getIE());
    }

    ispc::RaycastVolumeRenderer_setLights(ispcEquivalent,
                                          lights.empty() ? nullptr : &lights[0],
                                          lights.size());

    // Initialize state in the parent class, must be called after the ISPC
    // object is created.
    Renderer::commit();
  }

  // A renderer type for volumes with embedded surfaces.
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, raycast_volume_renderer);
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, dvr);

} // ::ospray

<|endoftext|>


<commit_before>/*
 * callbacks.hpp - Framework support of callback functions
 *
 *   Copyright 2010-2011 Jesús Torres <jmtorres@ull.es>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CALLBACKS_HPP_
#define CALLBACKS_HPP_

#include <string>
#include <vector>

#include <boost/function.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/type_traits.hpp>

#include <cli/exceptions.hpp>

//
// Macro CLI_DECLARE_CALLBACKS
//
// Helps to add the support for callbacks to a class declaration.
//

#define CLI_DECLARE_CALLBACKS_FILLER_0(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_1
#define CLI_DECLARE_CALLBACKS_FILLER_1(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_0
#define CLI_DECLARE_CALLBACKS_FILLER_0_END
#define CLI_DECLARE_CALLBACKS_FILLER_1_END

#define CLI_DECLARE_CALLBACK_MEMBER(r, TYPE, DECLARATION_TUPLE)     \
    typedef typename cli::callback::                                \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACKS(TYPE, DECLARATIONS_SEQ)               \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER,                                \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

//
// Macro CLI_CALLBACK_SIGNATURE_ASSERT
//
// Tests if the function signature of FUNCTOR match the expected by CALLBACK.
//

#define CLI_CALLBACK_SIGNATURE_ASSERT(CALLBACK, FUNCTOR)                \
    typedef typename CALLBACK<Type>::Type ExpectedSignature;            \
    typedef typename                                                    \
        boost::function_types::function_type<FUNCTOR>::type Signature;  \
    BOOST_MPL_ASSERT((boost::is_same<ExpectedSignature, Signature>))

namespace cli { namespace callback
{
    //
    // Base template for callback function setter implementation
    //

    template <template <typename> class Callback>
    struct SetCallbackImpl
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
        {
            throw cli::exception::UnknownCallbackException(
                Callback<T>::name());
        }
    };

    //
    // DoCommandCallback
    //

    template <typename T>
    struct DoCommandCallback
    {
        typedef bool (Type)(const std::string&,
            typename T::CommandDetailsType const&);
        static const char* name() { return "DoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<DoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.defaultDoCommandCallback_ = function; }
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function,
            const std::string& command)
            { interpreter.doCommandCallbacks_[command] = function; }
    };

    //
    // EmptyLineCallback
    //

    template <typename T>
    struct EmptyLineCallback
    {
        typedef bool (Type)();
        static const char* name() { return "EmptyLineCallback"; }
    };

    template<>
    struct SetCallbackImpl<EmptyLineCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.emptyLineCallback_ = function; }
    };

    //
    // PreDoCommandCallback
    //

    template <typename T>
    struct PreDoCommandCallback
    {
        typedef void (Type)(std::string&);
        static const char* name() { return "PreDoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<PreDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preDoCommandCallback_ = function; }
    };

    //
    // PostDoCommandCallback
    //

    template <typename T>
    struct PostDoCommandCallback
    {
        typedef bool (Type)(bool, const std::string&);
        static const char* name() { return "PostDoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<PostDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postDoCommandCallback_ = function; }
    };

    //
    // ParserErrorCallback
    //

    template <typename T>
    struct ParserErrorCallback
    {
            typedef bool (Type)(typename T::ParserErrorType const&,
                const std::string&);
            static const char* name() { return "ParserErrorCallback"; }
    };

    template<>
    struct SetCallbackImpl<ParserErrorCallback>
    {
            template <typename T, typename Functor>
            static void setCallback(T& interpreter, Functor function)
            { interpreter.parserErrorCallback_ = function; }
    };

    //
    // PreLoopCallback
    //

    template <typename T>
    struct PreLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PreLoopCallback"; }
    };

    template<>
    struct SetCallbackImpl<PreLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preLoopCallback_ = function; }
    };

    //
    // PostLoopCallback
    //

    template <typename T>
    struct PostLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PostLoopCallback"; }
    };

    template<>
    struct SetCallbackImpl<PostLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postLoopCallback_ = function; }
    };

    //
    // VariableLookupCallback
    //

    template <typename T>
    struct VariableLookupCallback
    {
        typedef std::string (Type)(const std::string&);
        static const char* name() { return "VariableLookupCallback"; }
    };

    template<>
    struct SetCallbackImpl<VariableLookupCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->variableLookupCallback_ = function; }
    };

    //
    // PathnameExpansionCallback
    //

    template <typename T>
    struct PathnameExpansionCallback
    {
        typedef std::vector<std::string> (Type)(const std::string&);
        static const char* name() { return "PathnameExpansionCallback"; }
    };

    template<>
    struct SetCallbackImpl<PathnameExpansionCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->PathnameExpansionCallback_ = function; }
    };
}}

#endif /* CALLBACKS_HPP_ */
<commit_msg>enhance callback signature assert to include function objects as checkable<commit_after>/*
 * callbacks.hpp - Framework support of callback functions
 *
 *   Copyright 2010-2011 Jesús Torres <jmtorres@ull.es>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CALLBACKS_HPP_
#define CALLBACKS_HPP_

#include <string>
#include <vector>

#include <boost/function.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/type_traits.hpp>

#include <cli/exceptions.hpp>

//
// Macro CLI_DECLARE_CALLBACKS
//
// Helps to add the support for callbacks to a class declaration.
//

#define CLI_DECLARE_CALLBACKS_FILLER_0(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_1
#define CLI_DECLARE_CALLBACKS_FILLER_1(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_0
#define CLI_DECLARE_CALLBACKS_FILLER_0_END
#define CLI_DECLARE_CALLBACKS_FILLER_1_END

#define CLI_DECLARE_CALLBACK_MEMBER(r, TYPE, DECLARATION_TUPLE)     \
    typedef typename cli::callback::                                \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACKS(TYPE, DECLARATIONS_SEQ)               \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER,                                \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

//
// Macro CLI_CALLBACK_SIGNATURE_ASSERT
//
// Tests if the function signature of FUNCTOR match the expected by CALLBACK.
//

#define CLI_CALLBACK_SIGNATURE_ASSERT(CALLBACK, FUNCTOR)                \
    BOOST_MPL_ASSERT((boost::is_convertible<FUNCTOR,                    \
        boost::function<typename CALLBACK<Type>::Type> >))

namespace cli { namespace callback
{
    //
    // Base template for callback function setter implementation
    //

    template <template <typename> class Callback>
    struct SetCallbackImpl
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
        {
            throw cli::exception::UnknownCallbackException(
                Callback<T>::name());
        }
    };

    //
    // DoCommandCallback
    //

    template <typename T>
    struct DoCommandCallback
    {
        typedef bool (Type)(const std::string&,
            typename T::CommandDetailsType const&);
        static const char* name() { return "DoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<DoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.defaultDoCommandCallback_ = function; }
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function,
            const std::string& command)
            { interpreter.doCommandCallbacks_[command] = function; }
    };

    //
    // EmptyLineCallback
    //

    template <typename T>
    struct EmptyLineCallback
    {
        typedef bool (Type)();
        static const char* name() { return "EmptyLineCallback"; }
    };

    template<>
    struct SetCallbackImpl<EmptyLineCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.emptyLineCallback_ = function; }
    };

    //
    // PreDoCommandCallback
    //

    template <typename T>
    struct PreDoCommandCallback
    {
        typedef void (Type)(std::string&);
        static const char* name() { return "PreDoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<PreDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preDoCommandCallback_ = function; }
    };

    //
    // PostDoCommandCallback
    //

    template <typename T>
    struct PostDoCommandCallback
    {
        typedef bool (Type)(bool, const std::string&);
        static const char* name() { return "PostDoCommandCallback"; }
    };

    template<>
    struct SetCallbackImpl<PostDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postDoCommandCallback_ = function; }
    };

    //
    // ParserErrorCallback
    //

    template <typename T>
    struct ParserErrorCallback
    {
            typedef bool (Type)(typename T::ParserErrorType const&,
                const std::string&);
            static const char* name() { return "ParserErrorCallback"; }
    };

    template<>
    struct SetCallbackImpl<ParserErrorCallback>
    {
            template <typename T, typename Functor>
            static void setCallback(T& interpreter, Functor function)
            { interpreter.parserErrorCallback_ = function; }
    };

    //
    // PreLoopCallback
    //

    template <typename T>
    struct PreLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PreLoopCallback"; }
    };

    template<>
    struct SetCallbackImpl<PreLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preLoopCallback_ = function; }
    };

    //
    // PostLoopCallback
    //

    template <typename T>
    struct PostLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PostLoopCallback"; }
    };

    template<>
    struct SetCallbackImpl<PostLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postLoopCallback_ = function; }
    };

    //
    // VariableLookupCallback
    //

    template <typename T>
    struct VariableLookupCallback
    {
        typedef std::string (Type)(const std::string&);
        static const char* name() { return "VariableLookupCallback"; }
    };

    template<>
    struct SetCallbackImpl<VariableLookupCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->variableLookupCallback_ = function; }
    };

    //
    // PathnameExpansionCallback
    //

    template <typename T>
    struct PathnameExpansionCallback
    {
        typedef std::vector<std::string> (Type)(const std::string&);
        static const char* name() { return "PathnameExpansionCallback"; }
    };

    template<>
    struct SetCallbackImpl<PathnameExpansionCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->PathnameExpansionCallback_ = function; }
    };
}}

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


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/PointsPrimitive.h"
#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/MessageHandler.h"

#include "IECoreGL/ToGLPointsConverter.h"
#include "IECoreGL/PointsPrimitive.h"

using namespace IECoreGL;

ToGLPointsConverter::ToGLPointsConverter( IECore::ConstPointsPrimitivePtr toConvert )
	:	ToGLConverter( "Converts IECore::PointsPrimitive objects to IECoreGL::PointsPrimitive objects.", IECore::PointsPrimitiveTypeId )
{
	srcParameter()->setValue( IECore::constPointerCast<IECore::PointsPrimitive>( toConvert ) );
}

ToGLPointsConverter::~ToGLPointsConverter()
{
}

IECore::RunTimeTypedPtr ToGLPointsConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	IECore::PointsPrimitive::ConstPtr pointsPrim = IECore::staticPointerCast<const IECore::PointsPrimitive>( src ); // safe because the parameter validated it for us

	IECore::V3fVectorData::ConstPtr points = pointsPrim->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex );
	if( !points )
	{
		throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." );
	}

	// get type
	PointsPrimitive::Type type = PointsPrimitive::Disk;
	if( IECore::ConstStringDataPtr t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Uniform ) )
	{
		if( t->readable()=="particle" || t->readable()=="disk" || t->readable()=="blobby" )
		{
			type = PointsPrimitive::Disk;
		}
		else if( t->readable()=="sphere" )
		{
			type = PointsPrimitive::Sphere;
		}
		else if( t->readable()=="patch" )
		{
			type = PointsPrimitive::Quad;
		}
		else if( t->readable()=="gl:point" )
		{
			type = PointsPrimitive::Point;
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter::doConversion", boost::format( "Unknown type \"%s\" - reverting to particle type." ) % t->readable() );
		}
	}

	PointsPrimitive::Ptr result = new PointsPrimitive( type );

	for ( IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.begin(); pIt != pointsPrim->variables.end(); ++pIt )
	{
		if ( pIt->first == "type" )
			continue;

		if ( pIt->second.data )
		{
			result->addPrimitiveVariable( pIt->first, pIt->second );
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first );
		}
	}

	IECore::ConstFloatVectorDataPtr widths = pointsPrim->variableData<IECore::FloatVectorData>( "width" );
	IECore::ConstFloatDataPtr width = pointsPrim->variableData<IECore::FloatData>( "width", IECore::PrimitiveVariable::Constant );

	// use "constantwidth" as "width"
	if ( pointsPrim->variables.find( "width" ) == pointsPrim->variables.end() )
	{
		IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.find( "constantwidth" );
		if ( pIt != pointsPrim->variables.end() )
		{
			result->addPrimitiveVariable( "width", pIt->second );
			width = IECore::runTimeCast< const IECore::FloatData >(pIt->second.data);
		}
	}

	// compute heights
	IECore::ConstFloatDataPtr constantAspectData = pointsPrim->variableData<IECore::FloatData>( "patchaspectratio", IECore::PrimitiveVariable::Constant );
	IECore::ConstFloatVectorDataPtr aspectData = pointsPrim->variableData<IECore::FloatVectorData>( "patchaspectratio" );

	if( !constantAspectData && !aspectData )
	{
		// heights = width
		if ( widths )
		{
			result->addPrimitiveVariable( "height", pointsPrim->variables.find( "width" )->second );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() ) ) );
		}
	}
	else if( constantAspectData )
	{
		float aspect = constantAspectData->readable();
		if ( widths )
		{
			IECore::FloatVectorDataPtr h = widths->copy();
			std::vector<float> &hV = h->writable();
			for( unsigned int i=0; i<hV.size(); i++ )
			{
				hV[i] /= aspect;
			}
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("width")->second.interpolation, h ) );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() / aspect) ) );
		}
	}
	else
	{
		// we have varying aspect data
		IECore::FloatVectorDataPtr h = aspectData->copy();
		std::vector<float> &hV = h->writable();
		float defaultWidth = 1;
		const float *widthsP = &defaultWidth;
		unsigned int widthStride = 0;
		if( widths )
		{
			widthsP = &widths->readable()[0];
			if ( widths->readable().size() == aspectData->readable().size() )
				widthStride = 1;
		}
		else if ( width )
		{
			widthsP = &width->readable();
			widthStride = 0;
		}
		for( unsigned int i=0; i<hV.size(); i++ )
		{
			hV[i] = *widthsP / hV[i];
			widthsP += widthStride;
		}
		result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("patchaspectratio")->second.interpolation, h ) );
	}
	return result;
}
<commit_msg>Testing "type" primvar as Constant, and if it's not there, then test as Uniform. Should be Constant because if it's Uniform than arePrimitiveVariablesValid() returns False.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/PointsPrimitive.h"
#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/MessageHandler.h"

#include "IECoreGL/ToGLPointsConverter.h"
#include "IECoreGL/PointsPrimitive.h"

using namespace IECoreGL;

ToGLPointsConverter::ToGLPointsConverter( IECore::ConstPointsPrimitivePtr toConvert )
	:	ToGLConverter( "Converts IECore::PointsPrimitive objects to IECoreGL::PointsPrimitive objects.", IECore::PointsPrimitiveTypeId )
{
	srcParameter()->setValue( IECore::constPointerCast<IECore::PointsPrimitive>( toConvert ) );
}

ToGLPointsConverter::~ToGLPointsConverter()
{
}

IECore::RunTimeTypedPtr ToGLPointsConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	IECore::PointsPrimitive::ConstPtr pointsPrim = IECore::staticPointerCast<const IECore::PointsPrimitive>( src ); // safe because the parameter validated it for us

	IECore::V3fVectorData::ConstPtr points = pointsPrim->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex );
	if( !points )
	{
		throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." );
	}

	// get type
	PointsPrimitive::Type type = PointsPrimitive::Disk;
	IECore::ConstStringDataPtr t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Constant );
	if ( !t )
	{
		t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Uniform );
	}
	if( t )
	{
		if( t->readable()=="particle" || t->readable()=="disk" || t->readable()=="blobby" )
		{
			type = PointsPrimitive::Disk;
		}
		else if( t->readable()=="sphere" )
		{
			type = PointsPrimitive::Sphere;
		}
		else if( t->readable()=="patch" )
		{
			type = PointsPrimitive::Quad;
		}
		else if( t->readable()=="gl:point" )
		{
			type = PointsPrimitive::Point;
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter::doConversion", boost::format( "Unknown type \"%s\" - reverting to particle type." ) % t->readable() );
		}
	}

	PointsPrimitive::Ptr result = new PointsPrimitive( type );

	for ( IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.begin(); pIt != pointsPrim->variables.end(); ++pIt )
	{
		if ( pIt->first == "type" )
			continue;

		if ( pIt->second.data )
		{
			result->addPrimitiveVariable( pIt->first, pIt->second );
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first );
		}
	}

	IECore::ConstFloatVectorDataPtr widths = pointsPrim->variableData<IECore::FloatVectorData>( "width" );
	IECore::ConstFloatDataPtr width = pointsPrim->variableData<IECore::FloatData>( "width", IECore::PrimitiveVariable::Constant );

	// use "constantwidth" as "width"
	if ( pointsPrim->variables.find( "width" ) == pointsPrim->variables.end() )
	{
		IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.find( "constantwidth" );
		if ( pIt != pointsPrim->variables.end() )
		{
			result->addPrimitiveVariable( "width", pIt->second );
			width = IECore::runTimeCast< const IECore::FloatData >(pIt->second.data);
		}
	}

	// compute heights
	IECore::ConstFloatDataPtr constantAspectData = pointsPrim->variableData<IECore::FloatData>( "patchaspectratio", IECore::PrimitiveVariable::Constant );
	IECore::ConstFloatVectorDataPtr aspectData = pointsPrim->variableData<IECore::FloatVectorData>( "patchaspectratio" );

	if( !constantAspectData && !aspectData )
	{
		// heights = width
		if ( widths )
		{
			result->addPrimitiveVariable( "height", pointsPrim->variables.find( "width" )->second );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() ) ) );
		}
	}
	else if( constantAspectData )
	{
		float aspect = constantAspectData->readable();
		if ( widths )
		{
			IECore::FloatVectorDataPtr h = widths->copy();
			std::vector<float> &hV = h->writable();
			for( unsigned int i=0; i<hV.size(); i++ )
			{
				hV[i] /= aspect;
			}
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("width")->second.interpolation, h ) );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() / aspect) ) );
		}
	}
	else
	{
		// we have varying aspect data
		IECore::FloatVectorDataPtr h = aspectData->copy();
		std::vector<float> &hV = h->writable();
		float defaultWidth = 1;
		const float *widthsP = &defaultWidth;
		unsigned int widthStride = 0;
		if( widths )
		{
			widthsP = &widths->readable()[0];
			if ( widths->readable().size() == aspectData->readable().size() )
				widthStride = 1;
		}
		else if ( width )
		{
			widthsP = &width->readable();
			widthStride = 0;
		}
		for( unsigned int i=0; i<hV.size(); i++ )
		{
			hV[i] = *widthsP / hV[i];
			widthsP += widthStride;
		}
		result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("patchaspectratio")->second.interpolation, h ) );
	}
	return result;
}
<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2012, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Ioan Sucan */

#include <moveit/warehouse/planning_scene_storage.h>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/variables_map.hpp>
#include <moveit/planning_scene_monitor/planning_scene_monitor.h>

#include <ros/ros.h>

static const std::string ROBOT_DESCRIPTION="robot_description";

int main(int argc, char **argv)
{
  ros::init(argc, argv, "save_warehouse_as_text", ros::init_options::AnonymousName);

  boost::program_options::options_description desc;
  desc.add_options()
    ("help", "Show help message")
    ("host", boost::program_options::value<std::string>(), "Host for the MongoDB.")
    ("port", boost::program_options::value<std::size_t>(), "Port for the MongoDB.");

  boost::program_options::variables_map vm;
  boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
  boost::program_options::notify(vm);

  if (vm.count("help"))
  {
    std::cout << desc << std::endl;
    return 1;
  }

  ros::AsyncSpinner spinner(1);
  spinner.start();

  planning_scene_monitor::PlanningSceneMonitor psm(ROBOT_DESCRIPTION);

  moveit_warehouse::PlanningSceneStorage pss(vm.count("host") ? vm["host"].as<std::string>() : "",
                                             vm.count("port") ? vm["port"].as<std::size_t>() : 0);

  std::vector<std::string> scene_names;
  pss.getPlanningSceneNames(scene_names);

  for (std::size_t i = 0 ; i < scene_names.size() ; ++i)
  {
    moveit_warehouse::PlanningSceneWithMetadata pswm;
    if (pss.getPlanningScene(pswm, scene_names[i]))
    {
      ROS_INFO("Saving scene '%s'", scene_names[i].c_str());
      psm.getPlanningScene()->setPlanningSceneMsg(static_cast<const moveit_msgs::PlanningScene&>(*pswm));
      std::ofstream fout((scene_names[i] + ".scene").c_str());
      psm.getPlanningScene()->saveGeometryToStream(fout);
      fout.close();
    }
  }

  ROS_INFO("Done.");

  return 0;
}
<commit_msg>Make moveit_warehouse_save_as_text save the queries as well as the scenes.<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2012, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Ioan Sucan */

#include <moveit/warehouse/planning_scene_storage.h>
#include <moveit/warehouse/state_storage.h>
#include <moveit/warehouse/constraints_storage.h>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/variables_map.hpp>
#include <moveit/planning_scene_monitor/planning_scene_monitor.h>
#include <moveit/kinematic_state/conversions.h>
#include <ros/ros.h>

static const std::string ROBOT_DESCRIPTION="robot_description";

typedef std::pair<geometry_msgs::Point, geometry_msgs::Quaternion> LinkConstraintPair;
typedef std::map<std::string, LinkConstraintPair > LinkConstraintMap;

LinkConstraintMap collectLinkConstraints(moveit_msgs::Constraints constraints)
{
  LinkConstraintMap lcmap;
  for(int i=0; i<constraints.position_constraints.size(); i++){
    LinkConstraintPair lcp;
    const moveit_msgs::PositionConstraint &pc = constraints.position_constraints[i];
    lcp.first = pc.constraint_region.primitive_poses[0].position;
    lcmap[constraints.position_constraints[i].link_name] = lcp;
  }

  for(int i=0; i<constraints.orientation_constraints.size(); i++){
    if(lcmap.count(constraints.orientation_constraints[i].link_name)){
      lcmap[constraints.orientation_constraints[i].link_name].second = constraints.orientation_constraints[i].orientation;
    }else{
      ROS_WARN("Orientation constraint for %s has no matching position constraint", constraints.orientation_constraints[i].link_name.c_str());
    }
  }

  return lcmap;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "save_warehouse_as_text", ros::init_options::AnonymousName);

  boost::program_options::options_description desc;
  desc.add_options()
    ("help", "Show help message")
    ("host", boost::program_options::value<std::string>(), "Host for the MongoDB.")
    ("port", boost::program_options::value<std::size_t>(), "Port for the MongoDB.");

  boost::program_options::variables_map vm;
  boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
  boost::program_options::notify(vm);

  if (vm.count("help"))
  {
    std::cout << desc << std::endl;
    return 1;
  }

  ros::AsyncSpinner spinner(1);
  spinner.start();

  planning_scene_monitor::PlanningSceneMonitor psm(ROBOT_DESCRIPTION);

  moveit_warehouse::PlanningSceneStorage pss(vm.count("host") ? vm["host"].as<std::string>() : "",
                                             vm.count("port") ? vm["port"].as<std::size_t>() : 0);

  moveit_warehouse::RobotStateStorage rss(vm.count("host") ? vm["host"].as<std::string>() : "",
                                             vm.count("port") ? vm["port"].as<std::size_t>() : 0);

  moveit_warehouse::ConstraintsStorage cs(vm.count("host") ? vm["host"].as<std::string>() : "",
                                             vm.count("port") ? vm["port"].as<std::size_t>() : 0);

  std::vector<std::string> scene_names;
  pss.getPlanningSceneNames(scene_names);

  for (std::size_t i = 0 ; i < scene_names.size() ; ++i)
  {
    moveit_warehouse::PlanningSceneWithMetadata pswm;
    if (pss.getPlanningScene(pswm, scene_names[i]))
    {
      ROS_INFO("Saving scene '%s'", scene_names[i].c_str());
      psm.getPlanningScene()->setPlanningSceneMsg(static_cast<const moveit_msgs::PlanningScene&>(*pswm));
      std::ofstream fout((scene_names[i] + ".scene").c_str());
      psm.getPlanningScene()->saveGeometryToStream(fout);
      fout.close();

      std::ofstream qfout((scene_names[i] + ".queries").c_str());
      qfout << scene_names[i] << std::endl;

      std::vector<std::string> robotStateNames;
      kinematic_model::KinematicModelConstPtr km = psm.getKinematicModel();
      // Get start states for scene
      std::stringstream rsregex;
      rsregex << ".*" << scene_names[i] << ".*";
      rss.getKnownRobotStates(rsregex.str(), robotStateNames);
      if(robotStateNames.size())
      {
        qfout << "start" << std::endl;
        qfout << robotStateNames.size() << std::endl;
        for(int k = 0; k < robotStateNames.size(); k++)
        {
          ROS_INFO("Saving start state %s for scene %s", robotStateNames[k].c_str(), scene_names[i].c_str());
          qfout << robotStateNames[k] << std::endl;
          moveit_warehouse::RobotStateWithMetadata robotState;
          rss.getRobotState(robotState, robotStateNames[k]);
          kinematic_state::KinematicState ks(km);
          kinematic_state::robotStateToKinematicState(*robotState, ks, false);
          ks.printStateInfo(qfout);
          qfout << "." << std::endl;
        }
      }

      // Get goal constraints for scene
      std::vector<std::string> constraintNames;

      std::stringstream csregex;
      csregex << ".*" << scene_names[i] << ".*";
      cs.getKnownConstraints(csregex.str(), constraintNames);
      if(constraintNames.size())
      {
        qfout << "goal" << std::endl;
        qfout << constraintNames.size() << std::endl;
        for(int k = 0; k < constraintNames.size(); k++)
        {
          ROS_INFO("Saving goal %s for scene %s", constraintNames[k].c_str(), scene_names[i].c_str());
          qfout << "link_constraint" << std::endl;
          qfout << constraintNames[k] << std::endl;
          moveit_warehouse::ConstraintsWithMetadata constraints;
          cs.getConstraints(constraints, constraintNames[k]);

          LinkConstraintMap lcmap = collectLinkConstraints(*constraints);
          for(LinkConstraintMap::iterator iter = lcmap.begin(); iter != lcmap.end(); iter++)
          {
            std::string link_name = iter->first;
            LinkConstraintPair lcp = iter->second;
            qfout << link_name << std::endl;
            qfout << "xyz " << lcp.first.x << " " << lcp.first.y << " " << lcp.first.z << std::endl;
            Eigen::Quaterniond orientation(lcp.second.w, lcp.second.x, lcp.second.y, lcp.second.z);
            Eigen::Vector3d rpy = orientation.matrix().eulerAngles(0, 1, 2);
            qfout << "rpy " << rpy[0] << " " << rpy[1] << " " << rpy[2] << std::endl;

          }
          qfout << "." << std::endl;
        }
      }

      qfout.close();
    }

  }

  ROS_INFO("Done.");

  return 0;
}
<|endoftext|>


<commit_before>//     Copyright 2013, Kay Hayen, mailto:kay.hayen@gmail.com
//
//     Part of "Nuitka", an optimizing Python compiler that is compatible and
//     integrates with CPython, but also works on its own.
//
//     Licensed under the Apache License, Version 2.0 (the "License");
//     you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//     Unless required by applicable law or agreed to in writing, software
//     distributed under the License is distributed on an "AS IS" BASIS,
//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
//     limitations under the License.
//
#ifndef __NUITKA_VARIABLES_TEMPORARY_H__
#define __NUITKA_VARIABLES_TEMPORARY_H__

// Wraps a "PyObject *" you received or acquired from another container to
// simplify refcount handling when you're not going to use the object beyond the
// local scope. It will hold a reference to the wrapped object as long as the
// PyObjectTemporary is alive, and will release the reference when the wrapper
// is destroyed: this eliminates the need for manual DECREF calls on Python
// objects before returning from a method call.
//
// In effect, wrapping an object inside a PyObjectTemporary is equivalent to a
// deferred Py_DECREF() call on the wrapped object.

class PyObjectTemporary
{
public:
    explicit PyObjectTemporary( PyObject *object )
    {
        assertObject( object );

        this->object = object;
    }

    ~PyObjectTemporary()
    {
        assertObject( this->object );

        Py_DECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        return INCREASE_REFCOUNT( this->object );
    }

    void assign0( PyObject *object )
    {
        assertObject( object );
        assertObject( this->object );

        PyObject *old = this->object;
        this->object = INCREASE_REFCOUNT( object );
        Py_DECREF( old );
    }

    void assign1( PyObject *object )
    {
        assertObject( object );
        assertObject( this->object );

        PyObject *old_object = this->object;
        this->object = object;
        Py_XDECREF( old_object );
    }

private:

    PyObjectTemporary( const PyObjectTemporary &object ) { assert( false ); }
    PyObjectTemporary() { assert( false ); };

    PyObject *object;
};

class PyObjectTemporaryWithDel
{
public:
    explicit PyObjectTemporaryWithDel( PyObject *object )
    {
        assertObject( object );

        this->object = object;
    }

    ~PyObjectTemporaryWithDel()
    {
        if ( this->object ) assertObject( this->object );

        Py_XDECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        return INCREASE_REFCOUNT( this->object );
    }

    void assign0( PyObject *object )
    {
        assertObject( object );
        if ( this->object ) assertObject( this->object );

        PyObject *old = this->object;
        this->object = INCREASE_REFCOUNT( object );
        Py_XDECREF( old );
    }

    void assign1( PyObject *object )
    {
        assertObject( object );
        if ( this->object ) assertObject( this->object );

        PyObject *old_object = this->object;
        this->object = object;
        Py_XDECREF( old_object );
    }

    // TODO: Tolerance must die, really and this method should be avoidable, as
    // it's only used to emulate block scopes.
    void del( bool tolerant )
    {
        assertObject( this->object );

        Py_XDECREF( this->object );
        this->object = NULL;
    }

private:

    PyObjectTemporaryWithDel( const PyObjectTemporary &object ) { assert( false ); }
    PyObjectTemporaryWithDel() { assert( false ); };

    PyObject *object;
};

class PyObjectTempVariable
{
public:
    explicit PyObjectTempVariable()
    {
        this->object = NULL;
    }

    ~PyObjectTempVariable()
    {
        if ( this->object ) assertObject( this->object );

        Py_XDECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    void assign1( PyObject *object )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        assertObject( object );

        this->object = object;
    }

    void assign0( PyObject *object )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        assertObject( object );

        this->object = INCREASE_REFCOUNT( object );
    }

    void del( bool tolerant )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        this->object = NULL;
    }

private:

    PyObjectTempVariable( const PyObjectTempVariable &object )
    {
        assert( false );
    }

    PyObject *object;
};

class PyObjectTempKeeper1
{
public:
    explicit PyObjectTempKeeper1()
    {
        this->object = NULL;
    }

    ~PyObjectTempKeeper1()
    {
        Py_XDECREF( this->object );
    }

    inline PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    inline PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    inline PyObject *assign( PyObject *value )
    {
        assertObject( value );

        this->object = value;
        return this->object;
    }

    bool isKeeping() const
    {
        return this->object != NULL;
    }

private:

    PyObjectTempKeeper1( const PyObjectTempKeeper1 &other ) { assert( false ); }

    PyObject *object;
};

class PyObjectTempKeeper0
{
public:
    explicit PyObjectTempKeeper0()
    {
        this->object = NULL;
    }

    ~PyObjectTempKeeper0()
    {}

    inline PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    inline PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    inline PyObject *assign( PyObject *value )
    {
        assertObject( value );

        this->object = value;
        return this->object;
    }

private:

    PyObjectTempKeeper0( const PyObjectTempKeeper0 &other ) { assert( false ); }

    PyObject *object;
};

#endif
<commit_msg>Fix, check in tolerant del was too strict for "--debug" mode.<commit_after>//     Copyright 2013, Kay Hayen, mailto:kay.hayen@gmail.com
//
//     Part of "Nuitka", an optimizing Python compiler that is compatible and
//     integrates with CPython, but also works on its own.
//
//     Licensed under the Apache License, Version 2.0 (the "License");
//     you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//     Unless required by applicable law or agreed to in writing, software
//     distributed under the License is distributed on an "AS IS" BASIS,
//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
//     limitations under the License.
//
#ifndef __NUITKA_VARIABLES_TEMPORARY_H__
#define __NUITKA_VARIABLES_TEMPORARY_H__

// Wraps a "PyObject *" you received or acquired from another container to
// simplify refcount handling when you're not going to use the object beyond the
// local scope. It will hold a reference to the wrapped object as long as the
// PyObjectTemporary is alive, and will release the reference when the wrapper
// is destroyed: this eliminates the need for manual DECREF calls on Python
// objects before returning from a method call.
//
// In effect, wrapping an object inside a PyObjectTemporary is equivalent to a
// deferred Py_DECREF() call on the wrapped object.

class PyObjectTemporary
{
public:
    explicit PyObjectTemporary( PyObject *object )
    {
        assertObject( object );

        this->object = object;
    }

    ~PyObjectTemporary()
    {
        assertObject( this->object );

        Py_DECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        return INCREASE_REFCOUNT( this->object );
    }

    void assign0( PyObject *object )
    {
        assertObject( object );
        assertObject( this->object );

        PyObject *old = this->object;
        this->object = INCREASE_REFCOUNT( object );
        Py_DECREF( old );
    }

    void assign1( PyObject *object )
    {
        assertObject( object );
        assertObject( this->object );

        PyObject *old_object = this->object;
        this->object = object;
        Py_XDECREF( old_object );
    }

private:

    PyObjectTemporary( const PyObjectTemporary &object ) { assert( false ); }
    PyObjectTemporary() { assert( false ); };

    PyObject *object;
};

class PyObjectTemporaryWithDel
{
public:
    explicit PyObjectTemporaryWithDel( PyObject *object )
    {
        assertObject( object );

        this->object = object;
    }

    ~PyObjectTemporaryWithDel()
    {
        if ( this->object ) assertObject( this->object );

        Py_XDECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        return INCREASE_REFCOUNT( this->object );
    }

    void assign0( PyObject *object )
    {
        assertObject( object );
        if ( this->object ) assertObject( this->object );

        PyObject *old = this->object;
        this->object = INCREASE_REFCOUNT( object );
        Py_XDECREF( old );
    }

    void assign1( PyObject *object )
    {
        assertObject( object );
        if ( this->object ) assertObject( this->object );

        PyObject *old_object = this->object;
        this->object = object;
        Py_XDECREF( old_object );
    }

    // TODO: Tolerance must die, really and this method should be avoidable, as
    // it's only used to emulate block scopes.
    void del( bool tolerant )
    {
        if ( this->object ) assertObject( this->object );

        Py_XDECREF( this->object );
        this->object = NULL;
    }

private:

    PyObjectTemporaryWithDel( const PyObjectTemporary &object ) { assert( false ); }
    PyObjectTemporaryWithDel() { assert( false ); };

    PyObject *object;
};

class PyObjectTempVariable
{
public:
    explicit PyObjectTempVariable()
    {
        this->object = NULL;
    }

    ~PyObjectTempVariable()
    {
        if ( this->object ) assertObject( this->object );

        Py_XDECREF( this->object );
    }

    PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    void assign1( PyObject *object )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        assertObject( object );

        this->object = object;
    }

    void assign0( PyObject *object )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        assertObject( object );

        this->object = INCREASE_REFCOUNT( object );
    }

    void del( bool tolerant )
    {
        if ( this->object ) assertObject( this->object );
        Py_XDECREF( this->object );

        this->object = NULL;
    }

private:

    PyObjectTempVariable( const PyObjectTempVariable &object )
    {
        assert( false );
    }

    PyObject *object;
};

class PyObjectTempKeeper1
{
public:
    explicit PyObjectTempKeeper1()
    {
        this->object = NULL;
    }

    ~PyObjectTempKeeper1()
    {
        Py_XDECREF( this->object );
    }

    inline PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    inline PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    inline PyObject *assign( PyObject *value )
    {
        assertObject( value );

        this->object = value;
        return this->object;
    }

    bool isKeeping() const
    {
        return this->object != NULL;
    }

private:

    PyObjectTempKeeper1( const PyObjectTempKeeper1 &other ) { assert( false ); }

    PyObject *object;
};

class PyObjectTempKeeper0
{
public:
    explicit PyObjectTempKeeper0()
    {
        this->object = NULL;
    }

    ~PyObjectTempKeeper0()
    {}

    inline PyObject *asObject0() const
    {
        assertObject( this->object );

        return this->object;
    }

    inline PyObject *asObject1() const
    {
        assertObject( this->object );

        return INCREASE_REFCOUNT( this->object );
    }

    inline PyObject *assign( PyObject *value )
    {
        assertObject( value );

        this->object = value;
        return this->object;
    }

private:

    PyObjectTempKeeper0( const PyObjectTempKeeper0 &other ) { assert( false ); }

    PyObject *object;
};

#endif
<|endoftext|>


<commit_before>#include "catch.hpp"
#include "LuaBinding.h"

using namespace ManualBind;

class Basic
{
};

// A very basic opaque pointer binding.
struct BasicPODbinding : public PODBinding<BasicPODbinding,Basic*>
{
    static constexpr const char* class_name = "Basic";

    static int create( lua_State* L )
    {
        return luaL_error( L, "Can not create an instance to opaque pointer" );
    }
};

TEST_CASE( "Basic POD binding retains identical pointer value." ) {

    lua_State* L = luaL_newstate();

    BasicPODbinding::register_class( L );

    Basic* bp = new Basic();

    // Give Lua a copy.
    BasicPODbinding::push( L, bp );
    lua_setglobal( L, "bp" );

    // Retrieve
    lua_getglobal( L, "bp" );
    Basic* fromLua = BasicPODbinding::fromStack( L, 1 );
    lua_pop( L, 1 );

    REQUIRE( bp == fromLua );

    lua_close( L );
}
<commit_msg>clean up after myself<commit_after>#include "catch.hpp"
#include "LuaBinding.h"

using namespace ManualBind;

class Basic
{
};

// A very basic opaque pointer binding.
struct BasicPODbinding : public PODBinding<BasicPODbinding,Basic*>
{
    static constexpr const char* class_name = "Basic";

    static int create( lua_State* L )
    {
        return luaL_error( L, "Can not create an instance to opaque pointer" );
    }
};

TEST_CASE( "Basic POD binding retains identical pointer value." ) {

    lua_State* L = luaL_newstate();

    BasicPODbinding::register_class( L );

    Basic* bp = new Basic();

    // Give Lua a copy.
    BasicPODbinding::push( L, bp );
    lua_setglobal( L, "bp" );

    // Retrieve
    lua_getglobal( L, "bp" );
    Basic* fromLua = BasicPODbinding::fromStack( L, 1 );
    lua_pop( L, 1 );

    REQUIRE( bp == fromLua );

    lua_close( L );

    delete bp;
}
<|endoftext|>