text:
/**
 * spaintgui: Application.cpp
 * Copyright (c) Torr Vision Group, University of Oxford, 2015. All rights reserved.
 */

#include "Application.h"
using namespace tvginput;

#include <fstream>
#include <stdexcept>

#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/assign/list_of.hpp>
using boost::assign::map_list_of;

#include <ITMLib/Engines/Meshing/ITMMeshingEngineFactory.h>
#include <ITMLib/Objects/Camera/ITMCalibIO.h>
using namespace ITMLib;

#include <itmx/util/CameraPoseConverter.h>
using namespace itmx;

#include <oglx/WrappedGL.h>

#include <orx/persistence/ImagePersister.h>
#include <orx/persistence/PosePersister.h>
using namespace orx;

#include <rigging/MoveableCamera.h>
using namespace rigging;

#ifdef WITH_VICON
#include <spaint/fiducials/ViconFiducialDetector.h>
#endif
using namespace spaint;

#include <tvgutil/commands/NoOpCommand.h>
#include <tvgutil/filesystem/PathFinder.h>
#include <tvgutil/timing/TimeUtil.h>
using namespace tvgutil;

#include "renderers/HeadlessRenderer.h"
#ifdef WITH_OVR
#include "renderers/RiftRenderer.h"
#endif
#include "renderers/WindowedRenderer.h"

#include "commands/MarkVoxelsCommand.h"

//#################### CONSTRUCTORS ####################

Application::Application(const MultiScenePipeline_Ptr& pipeline, bool renderFiducials)
: m_activeSubwindowIndex(0),
  m_batchModeEnabled(false),
  m_commandManager(10),
  m_pauseBetweenFrames(true),
  m_paused(true),
  m_pipeline(pipeline),
  m_renderFiducials(renderFiducials),
  m_saveModelsOnExit(false),
  m_usePoseMirroring(true),
  m_voiceCommandStream("localhost", "23984")
{
  setup_labels();
  setup_meshing();

  Model_CPtr model = m_pipeline->get_model();
  const Settings_CPtr& settings = model->get_settings();

  if(settings->get_first_value<bool>("headless"))
  {
    m_renderer.reset(new HeadlessRenderer(model));
  }
  else
  {
    int subwindowConfigurationIndex = settings->get_first_value<int>("subwindowConfigurationIndex");
    switch_to_windowed_renderer(subwindowConfigurationIndex);
  }
}

//#################### PUBLIC MEMBER FUNCTIONS ####################

bool Application::run()
{
  for(;;)
  {
    // Check to see if the user wants to quit the application, and quit if necessary. Note that if we
    // are running in batch mode, we quit directly, rather than saving a mesh of the scene on exit.
    bool eventQuit = !process_events();
    bool escQuit = m_inputState.key_down(KEYCODE_ESCAPE);
    if(m_batchModeEnabled) { if(eventQuit) return false; }
    else                   { if(eventQuit || escQuit) break; }

    // If desired, save the memory usage for later analysis.
    if(m_memoryUsageOutputStream) save_current_memory_usage();

    // Take action as relevant based on the current input state.
    process_input();

    // If the application is unpaused, process a new frame.
    if(!m_paused)
    {
      // Run the main section of the pipeline.
      const std::set<std::string> scenesProcessed = m_pipeline->run_main_section();

      if(!scenesProcessed.empty())
      {
        // If a frame debug hook is active, call it.
        if(m_frameDebugHook) m_frameDebugHook(m_pipeline->get_model());

        // If we're currently recording the sequence, save the frame to disk.
        if(m_sequencePathGenerator) save_sequence_frame();
      }
      else if(m_batchModeEnabled)
      {
        // If we're running in batch mode and we reach the end of the sequence, quit.
        break;
      }
    }

    // Render the scene.
    m_renderer->render(m_fracWindowPos, m_renderFiducials);

    // If we're running a mapping server and we want to render any scene images requested by remote clients, do so.
    const Model_CPtr model = m_pipeline->get_model();
    if(model->get_mapping_server() && model->get_settings()->get_first_value<bool>("Application.renderClientImages", true))
    {
      m_renderer->render_client_images();
    }

    // If the application is unpaused, run the mode-specific section of the pipeline for the active scene.
    if(!m_paused) m_pipeline->run_mode_specific_section(get_active_scene_id(), get_monocular_render_state());

    // If we're currently recording a video, save the next frame of it to disk.
    if(m_videoPathGenerator) save_video_frame();

    // If desired, pause at the end of each frame for debugging purposes.
    if(m_pauseBetweenFrames) m_paused = true;
  }

  // If desired, save a mesh of the scene before the application terminates.
  if(m_saveMeshOnExit) save_mesh();

  // If desired, save a model of each scene before the application terminates.
  if(m_saveModelsOnExit) save_models();

  return true;
}

void Application::set_batch_mode_enabled(bool batchModeEnabled)
{
  m_batchModeEnabled = batchModeEnabled;
  m_paused = m_pauseBetweenFrames = !batchModeEnabled;
}

void Application::set_server_mode_enabled(bool serverModeEnabled)
{
  m_paused = m_pauseBetweenFrames = !serverModeEnabled;
}

void Application::set_frame_debug_hook(const FrameDebugHook& frameDebugHook)
{
  m_frameDebugHook = frameDebugHook;
}

void Application::set_save_memory_usage(bool saveMemoryUsage)
{
#ifdef WITH_CUDA
  // If we're trying to turn off memory usage saving, reset the output stream and early out.
  if(!saveMemoryUsage)
  {
    m_memoryUsageOutputStream.reset();
    return;
  }

  // Otherwise, prepare the output stream:

  // Step 1: Find the profiling subdirectory and make sure that it exists.
  const boost::filesystem::path profilingSubdir = find_subdir_from_executable("profiling");
  boost::filesystem::create_directories(profilingSubdir);

  // Step 2: Determine the name of the file to which to save the memory usage. We base this on the
  //         (global) experiment tag, if available, and the current timestamp if not.
  std::string profilingFileName = m_pipeline->get_model()->get_settings()->get_first_value<std::string>("experimentTag", "");
  if(profilingFileName == "") profilingFileName = "spaint-" + TimeUtil::get_iso_timestamp();
  profilingFileName += ".csv";

  // Step 3: Open the file and write a header row for the table. The table has three columns for each available GPU
  //         (denoting the free, used and total memory on that GPU in MB at each frame).
  const boost::filesystem::path profilingFile = profilingSubdir / profilingFileName;
  m_memoryUsageOutputStream.reset(new std::ofstream(profilingFile.string().c_str()));
  std::cout << "Saving memory usage information in: " << profilingFile << '\n';

  int gpuCount = 0;
  ORcudaSafeCall(cudaGetDeviceCount(&gpuCount));
  for(int i = 0; i < gpuCount; ++i)
  {
    cudaDeviceProp props;
    ORcudaSafeCall(cudaGetDeviceProperties(&props, i));

    *m_memoryUsageOutputStream << '(' << i << ')' << props.name << " - Free;" << '(' << i << ')' << props.name << " - Used;" << '(' << i << ')' << props.name << " - Total;";
  }

  *m_memoryUsageOutputStream << '\n';
#endif
}

void Application::set_save_mesh_on_exit(bool saveMeshOnExit)
{
  m_saveMeshOnExit = saveMeshOnExit;
}

void Application::set_save_models_on_exit(bool saveModelsOnExit)
{
  m_saveModelsOnExit = saveModelsOnExit;
}

//#################### PUBLIC STATIC MEMBER FUNCTIONS ####################

boost::filesystem::path Application::resources_dir()
{
  return find_subdir_from_executable("resources");
}

//#################### PRIVATE MEMBER FUNCTIONS ####################

const std::string& Application::get_active_scene_id() const
{
  return get_active_subwindow().get_scene_id();
}

Subwindow& Application::get_active_subwindow()
{
  return m_renderer->get_subwindow_configuration()->subwindow(m_activeSubwindowIndex);
}

const Subwindow& Application::get_active_subwindow() const
{
  return m_renderer->get_subwindow_configuration()->subwindow(m_activeSubwindowIndex);
}

VoxelRenderState_CPtr Application::get_monocular_render_state() const
{
  return m_renderer->get_monocular_render_state(m_activeSubwindowIndex);
}

SubwindowConfiguration_Ptr Application::get_subwindow_configuration(size_t i) const
{
  if(m_subwindowConfigurations.size() < i + 1)
  {
    m_subwindowConfigurations.resize(i + 1);
  }

  if(!m_subwindowConfigurations[i])
  {
    const Model_CPtr& model = m_pipeline->get_model();
    const Settings_CPtr& settings = model->get_settings();
    const SLAMState_CPtr slamState = model->get_slam_state(Model::get_world_scene_id());
    const Vector2i& rgbImageSize = slamState->get_rgb_image_size();

    const int subwindowImageWidth = settings->get_first_value<int>("Application.subwindowImageWidth", rgbImageSize.width);
    const int subwindowImageHeight = settings->get_first_value<int>("Application.subwindowImageHeight", rgbImageSize.height);
    const std::string collaborativeAgentPrefix = settings->get_first_value<std::string>("Application.collaborativeAgentPrefix", "Local");

    m_subwindowConfigurations[i] = SubwindowConfiguration::make_default(
      i, Vector2i(subwindowImageWidth, subwindowImageHeight), m_pipeline->get_type(), collaborativeAgentPrefix
    );
  }

  return m_subwindowConfigurations[i];
}

void Application::handle_key_down(const SDL_Keysym& keysym)
{
  m_inputState.press_key(static_cast<Keycode>(keysym.sym));

  // If the P key is pressed, toggle pose mirroring.
  if(keysym.sym == KEYCODE_p)
  {
    m_usePoseMirroring = !m_usePoseMirroring;
  }

  // If the semi-colon key is pressed, toggle whether or not median filtering is used when rendering the scene raycast.
  if(keysym.sym == KEYCODE_SEMICOLON)
  {
    m_renderer->set_median_filtering_enabled(!m_renderer->get_median_filtering_enabled());
  }

  // If the quote key is pressed:
  if(keysym.sym == KEYCODE_QUOTE)
  {
    // Toggle whether or not supersampling is used when rendering the scene raycast.
    m_renderer->set_supersampling_enabled(!m_renderer->get_supersampling_enabled());

    // Let the pipeline know that the raycast result size may have changed.
    const Vector2i& imgSize = get_active_subwindow().get_image()->noDims;
    m_pipeline->update_raycast_result_size(imgSize.x * imgSize.y);
  }

  // If / is pressed on its own, save a screenshot. If left shift + / is pressed, toggle sequence recording.
  // If right shift + / is pressed, toggle video recording.
  if(keysym.sym == SDLK_SLASH)
  {
    if(m_inputState.key_down(KEYCODE_LSHIFT)) toggle_recording("sequence", m_sequencePathGenerator);
    else if(m_inputState.key_down(KEYCODE_RSHIFT)) toggle_recording("video", m_videoPathGenerator);
    else save_screenshot();
  }

  // If we're running in batch mode, ignore all other keypresses.
  if(m_batchModeEnabled) return;

  // If the B key is pressed, arrange for all subsequent frames to be processed without pausing.
  if(keysym.sym == KEYCODE_b)
  {
    m_pauseBetweenFrames = false;
    m_paused = false;
  }

  // If the F key is pressed, toggle whether or not fusion is run for the active scene.
  if(keysym.sym == KEYCODE_f)
  {
    const std::string& sceneID = get_active_scene_id();
    m_pipeline->set_fusion_enabled(sceneID, !m_pipeline->get_fusion_enabled(sceneID));
  }

  // If the N key is pressed, arrange for just the next frame to be processed and enable pausing between frames.
  if(keysym.sym == KEYCODE_n)
  {
    m_pauseBetweenFrames = true;
    m_paused = false;
  }

  // If the O key is pressed, toggle segmentation output.
  if(keysym.sym == KEYCODE_o)
  {
    m_pipeline->toggle_segmentation_output();
  }

  // If left control + R is pressed, reset the active scene.
  if(keysym.sym == KEYCODE_r && m_inputState.key_down(KEYCODE_LCTRL))
  {
    m_pipeline->reset_scene(get_active_scene_id());
  }

  if(keysym.sym == KEYCODE_BACKSPACE)
  {
    const Model_Ptr& model = m_pipeline->get_model();
    const std::string& sceneID = get_active_scene_id();
    if(m_inputState.key_down(KEYCODE_RCTRL) && m_inputState.key_down(KEYCODE_RSHIFT))
    {
      // If right control + right shift + backspace is pressed, clear the semantic labels of all the voxels in the active scene, and reset the random forest and command manager.
      model->clear_labels(sceneID, ClearingSettings(CLEAR_ALL, 0, 0));
      m_pipeline->reset_forest(sceneID);
      m_commandManager.reset();
    }
    else if(m_inputState.key_down(KEYCODE_RCTRL))
    {
      // If right control + backspace is pressed, clear the labels of all voxels with the current semantic label, and reset the command manager.
      model->clear_labels(sceneID, ClearingSettings(CLEAR_EQ_LABEL, 0, model->get_semantic_label()));
      m_commandManager.reset();
    }
    else if(m_inputState.key_down(KEYCODE_RSHIFT))
    {
      // If right shift + backspace is pressed, clear the semantic labels of all the voxels in the active scene that were not labelled by the user.
      model->clear_labels(sceneID, ClearingSettings(CLEAR_NEQ_GROUP, SpaintVoxel::LG_USER, 0));
    }
    else
    {
      // If backspace is pressed on its own, clear the labels of all voxels with the current semantic label that were not labelled by the user.
      model->clear_labels(sceneID, ClearingSettings(CLEAR_EQ_LABEL_NEQ_GROUP, SpaintVoxel::LG_USER, model->get_semantic_label()));
    }
  }

  // If the H key is pressed, print out a list of controls.
  if(keysym.sym == KEYCODE_h)
  {
    std::cout << "\nKeyboard Controls:\n\n"
              << "W = Forwards\n"
              << "S = Backwards\n"
              << "A = Strafe Left\n"
              << "D = Strafe Right\n"
              << "Q = Move Up\n"
              << "E = Move Down\n"
              << "Shift + Q = Rotate Left\n"
              << "Shift + E = Rotate Right\n"
              << "F = Toggle Fusion\n"
              << "G = Set Up Vector For Active Subwindow\n"
              << "O = Toggle Segmentation Output\n"
              << "P = Toggle Pose Mirroring\n"
              << "Up = Look Down\n"
              << "Down = Look Up\n"
              << "Left = Turn Left\n"
              << "Right = Turn Right\n"
              << "C + 1 = To Semantic Lambertian Raycast\n"
              << "C + 2 = To Semantic Phong Raycast\n"
              << "C + 3 = To Semantic Colour Raycast\n"
              << "C + 4 = To Semantic Flat Raycast\n"
              << "C + 5 = To Colour Raycast\n"
              << "C + 6 = To Normal Raycast\n"
              << "C + 7 = To Depth Raycast\n"
              << "C + 8 = To Confidence Raycast\n"
              << "C + 9 = To Colour Input\n"
              << "C + 0 = To Depth Input\n"
              << "I + 1 = To Null Selector\n"
              << "I + 2 = To Picking Selector\n"
              << "I + 3 = To Leap Selector\n"
              << "I + 4 = To Touch Selector\n"
              << "L = Label With Leap Selector (Whilst Held)\n"
              << "M + 1 = To Normal Mode\n"
              << "M + 2 = To Propagation Mode\n"
              << "M + 3 = To Training Mode\n"
              << "M + 4 = To Prediction Mode\n"
              << "M + 5 = To Correction Mode\n"
              << "M + 6 = To Smoothing Mode\n"
              << "M + 7 = To Feature Inspection Mode\n"
              << "K + 1 = Disable Fiducials\n"
              << "K + 2 = Only Detect Fiducials\n"
              << "K + 3 = Only Render Fiducials\n"
              << "K + 4 = Detect and Render Fiducials\n"
              << "R + # = To Windowed Renderer (Specified Subwindow Configuration)\n"
              << "RShift + R + 1 = To Rift Renderer (Windowed)\n"
              << "RShift + R + 2 = To Rift Renderer (Fullscreen)\n"
              << "V + 1 = To Follow Camera Mode\n"
              << "V + 2 = To Free Camera Mode\n"
              << "B = Process All Frames\n"
              << "N = Process Next Frame\n"
              << "LCtrl + R = Reset Scene\n"
              << "[ = Decrease Picking Selection Radius\n"
              << "] = Increase Picking Selection Radius\n"
              << "RShift + [ = To Previous Semantic Label\n"
              << "RShift + ] = To Next Semantic Label\n"
              << "Backspace = Clear Current Label Propagation\n"
              << "RShift + Backspace = Clear All Label Propagations\n"
              << "RCtrl + Backspace = Clear Current Label\n"
              << "RCtrl + RShift + Backspace = Reset Classifier (Clear Labels and Forest)\n"
              << "; = Toggle Median Filtering\n"
              << "' = Toggle Supersampling\n"
              << "/ = Save Screenshot\n"
              << "LShift + / = Toggle Sequence Recording\n"
              << "RShift + / = Toggle Video Recording\n"
              << '\n'
              << "Joystick Controls:\n\n"
              << "Left Analog Stick = Move Camera\n"
              << "Right Analog Stick = Look Up/Down/Left/Right\n"
              << "L1 = Move Up\n"
              << "R1 = Move Down\n"
              << "L2 = Rotate Left\n"
              << "R2 = Rotate Right\n"
              << "Triangle = Set Up Vector For Active Subwindow\n";
  }
}

void Application::handle_key_up(const SDL_Keysym& keysym)
{
  m_inputState.release_key(static_cast<Keycode>(keysym.sym));
}

void Application::handle_mousebutton_down(const SDL_MouseButtonEvent& e)
{
  m_fracWindowPos = m_renderer->compute_fractional_window_position(e.x, e.y);
  SubwindowConfiguration_CPtr config = m_renderer->get_subwindow_configuration();
  boost::optional<std::pair<size_t,Vector2f> > fracSubwindowPos = config->compute_fractional_subwindow_position(m_fracWindowPos);
  if(!fracSubwindowPos) return;

  switch(e.button)
  {
    case SDL_BUTTON_LEFT:
      m_inputState.press_mouse_button(MOUSE_BUTTON_LEFT, fracSubwindowPos->second.x, fracSubwindowPos->second.y);
      break;
    case SDL_BUTTON_MIDDLE:
      m_inputState.press_mouse_button(MOUSE_BUTTON_MIDDLE, fracSubwindowPos->second.x, fracSubwindowPos->second.y);
      break;
    case SDL_BUTTON_RIGHT:
      m_inputState.press_mouse_button(MOUSE_BUTTON_RIGHT, fracSubwindowPos->second.x, fracSubwindowPos->second.y);
      break;
    default:
      break;
  }
}

void Application::handle_mousebutton_up(const SDL_MouseButtonEvent& e)
{
  switch(e.button)
  {
    case SDL_BUTTON_LEFT:
      m_inputState.release_mouse_button(MOUSE_BUTTON_LEFT);
      break;
    case SDL_BUTTON_MIDDLE:
      m_inputState.release_mouse_button(MOUSE_BUTTON_MIDDLE);
      break;
    case SDL_BUTTON_RIGHT:
      m_inputState.release_mouse_button(MOUSE_BUTTON_RIGHT);
      break;
    default:
      break;
  }
}

void Application::process_camera_input()
{
  // Allow the user to change the camera mode of the active sub-window.
  Subwindow& activeSubwindow = get_active_subwindow();
  if(m_inputState.key_down(KEYCODE_v))
  {
    if(m_inputState.key_down(KEYCODE_1)) activeSubwindow.set_camera_mode(Subwindow::CM_FOLLOW);
    else if(m_inputState.key_down(KEYCODE_2)) activeSubwindow.set_camera_mode(Subwindow::CM_FREE);
  }

  // If the active sub-window is in free camera mode, allow the user to move its camera around.
  const SubwindowConfiguration_Ptr& subwindowConfiguration = m_renderer->get_subwindow_configuration();
  if(activeSubwindow.get_camera_mode() == Subwindow::CM_FREE)
  {
    // Compute the linear and angular speeds to use, based on the time elapsed since we last processed camera input.
    static boost::chrono::microseconds prevTime = TimeUtil::get_time_since_epoch<boost::chrono::microseconds>();
    boost::chrono::microseconds curTime = TimeUtil::get_time_since_epoch<boost::chrono::microseconds>();

    const int canonicalFrameTimeMs = 16;
    const float scalingFactor = (curTime.count() - prevTime.count()) / (canonicalFrameTimeMs * 1000.0f);
    const float speed = 0.1f * scalingFactor;
    const float angularSpeed = 0.05f * scalingFactor;

    prevTime = curTime;

    // If the G key (or the triangle button on a connected PS3 controller) is pressed, set the
    // up vector for the active subwindow based on the current orientation of the camera.
    MoveableCamera_Ptr camera = activeSubwindow.get_camera();
    if(m_inputState.key_down(KEYCODE_g) || m_inputState.joystick_button_down(PS3_BUTTON_TRIANGLE))
    {
        activeSubwindow.set_camera_up_vector(camera->v());
    }

    // Get the up vector for the active subwindow.
    const Eigen::Vector3f& up = activeSubwindow.get_camera_up_vector();

    // Allow the user to move the camera around using the keyboard.
    if(m_inputState.key_down(KEYCODE_w)) camera->move_n(speed);
    if(m_inputState.key_down(KEYCODE_s)) camera->move_n(-speed);
    if(m_inputState.key_down(KEYCODE_d)) camera->move_u(-speed);
    if(m_inputState.key_down(KEYCODE_a)) camera->move_u(speed);
    if(m_inputState.key_down(KEYCODE_q) && !m_inputState.key_down(KEYCODE_LSHIFT)) camera->move(up, speed);
    if(m_inputState.key_down(KEYCODE_e) && !m_inputState.key_down(KEYCODE_LSHIFT)) camera->move(up, -speed);

    if(m_inputState.key_down(KEYCODE_RIGHT)) camera->rotate(up, -angularSpeed);
    if(m_inputState.key_down(KEYCODE_LEFT)) camera->rotate(up, angularSpeed);
    if(m_inputState.key_down(KEYCODE_UP)) camera->rotate(camera->u(), angularSpeed);
    if(m_inputState.key_down(KEYCODE_DOWN)) camera->rotate(camera->u(), -angularSpeed);
    if(m_inputState.key_down(KEYCODE_q) && m_inputState.key_down(KEYCODE_LSHIFT)) camera->rotate(camera->n(), -angularSpeed);
    if(m_inputState.key_down(KEYCODE_e) && m_inputState.key_down(KEYCODE_LSHIFT)) camera->rotate(camera->n(), angularSpeed);

    // Allow the user to move the camera around using a connected PS3 controller.
    const float JOYSTICK_THRESHOLD = 0.1f; // to avoid analog jitter

    const float translationX = InputState::normalise_joystick_axis_state_signed(m_inputState.joystick_axis_state(PS3_AXIS_ANALOG_LEFT_X));
    const float translationY = InputState::normalise_joystick_axis_state_signed(m_inputState.joystick_axis_state(PS3_AXIS_ANALOG_LEFT_Y));
    const float moveUp = InputState::normalise_joystick_axis_state(m_inputState.joystick_axis_state(PS3_AXIS_TRIGGER_L1));
    const float moveDown = InputState::normalise_joystick_axis_state(m_inputState.joystick_axis_state(PS3_AXIS_TRIGGER_R1));
    if(std::abs(translationX) > JOYSTICK_THRESHOLD) camera->move_u(-translationX * speed);
    if(std::abs(translationY) > JOYSTICK_THRESHOLD) camera->move_n(-translationY * speed);
    if(moveUp > JOYSTICK_THRESHOLD) camera->move(up, moveUp * speed);
    if(moveDown > JOYSTICK_THRESHOLD) camera->move(up, -moveDown * speed);

    const float rotationX = InputState::normalise_joystick_axis_state_signed(m_inputState.joystick_axis_state(PS3_AXIS_ANALOG_RIGHT_X));
    const float rotationY = InputState::normalise_joystick_axis_state_signed(m_inputState.joystick_axis_state(PS3_AXIS_ANALOG_RIGHT_Y));
    const float rotationZ_Left = InputState::normalise_joystick_axis_state(m_inputState.joystick_axis_state(PS3_AXIS_TRIGGER_L2));
    const float rotationZ_Right = InputState::normalise_joystick_axis_state(m_inputState.joystick_axis_state(PS3_AXIS_TRIGGER_R2));
    if(std::abs(rotationX) > JOYSTICK_THRESHOLD) camera->rotate(up, -rotationX * angularSpeed);
    if(std::abs(rotationY) > JOYSTICK_THRESHOLD) camera->rotate(camera->u(), rotationY * angularSpeed);
    if(rotationZ_Left > JOYSTICK_THRESHOLD) camera->rotate(camera->n(), -rotationZ_Left * angularSpeed);
    if(rotationZ_Right > JOYSTICK_THRESHOLD) camera->rotate(camera->n(), rotationZ_Right * angularSpeed);

    // If pose mirroring is enabled, set the cameras of all other sub-windows that show the same scene
    // and are in free camera mode to have the same pose as this one.
    if(m_usePoseMirroring)
    {
      for(size_t i = 0, subwindowCount = subwindowConfiguration->subwindow_count(); i < subwindowCount; ++i)
      {
        Subwindow& subwindow = subwindowConfiguration->subwindow(i);
        if(subwindow.get_scene_id() == get_active_scene_id() && subwindow.get_camera_mode() == Subwindow::CM_FREE)
        {
          subwindow.get_camera()->set_from(*camera);
        }
      }
    }
  }

  // If one of the sub-windows has its remote flag set and a mapping client is active for its scene, send a rendering request to the mapping server.
  for(size_t i = 0, subwindowCount = subwindowConfiguration->subwindow_count(); i < subwindowCount; ++i)
  {
    const Subwindow& subwindow = subwindowConfiguration->subwindow(i);
    const MappingClient_Ptr& mappingClient = m_pipeline->get_model()->get_mapping_client(subwindow.get_scene_id());
    if(mappingClient && subwindow.get_remote_flag())
    {
      mappingClient->update_rendering_request(subwindow.get_image()->noDims, CameraPoseConverter::camera_to_pose(*subwindow.get_camera()), subwindow.get_type());
    }
  }
}

void Application::process_command_input()
{
  static bool blockUndo = false;
  if(m_inputState.key_down(KEYCODE_LCTRL) && m_inputState.key_down(KEYCODE_z))
  {
    if(!blockUndo && m_commandManager.can_undo())
    {
      m_commandManager.undo();
      blockUndo = true;
    }
  }
  else blockUndo = false;

  static bool blockRedo = false;
  if(m_inputState.key_down(KEYCODE_LCTRL) && m_inputState.key_down(KEYCODE_y))
  {
    if(!blockRedo && m_commandManager.can_redo())
    {
      m_commandManager.redo();
      blockRedo = true;
    }
  }
  else blockRedo = false;
}

bool Application::process_events()
{
  SDL_Event event;
  while(SDL_PollEvent(&event))
  {
    switch(event.type)
    {
      case SDL_KEYDOWN:
        handle_key_down(event.key.keysym);
        break;
      case SDL_KEYUP:
        handle_key_up(event.key.keysym);
        break;
      case SDL_MOUSEBUTTONDOWN:
        handle_mousebutton_down(event.button);
        break;
      case SDL_MOUSEBUTTONUP:
        handle_mousebutton_up(event.button);
        break;
      case SDL_MOUSEMOTION:
      {
        m_fracWindowPos = m_renderer->compute_fractional_window_position(event.motion.x, event.motion.y);
        SubwindowConfiguration_CPtr config = m_renderer->get_subwindow_configuration();
        boost::optional<std::pair<size_t,Vector2f> > fracSubwindowPos = config->compute_fractional_subwindow_position(m_fracWindowPos);
        if(fracSubwindowPos)
        {
          m_activeSubwindowIndex = fracSubwindowPos->first;
          m_inputState.set_mouse_position(fracSubwindowPos->second.x, fracSubwindowPos->second.y);
        }
        break;
      }
      case SDL_JOYAXISMOTION:
        m_inputState.set_joystick_axis_state(static_cast<JoystickAxis>(event.jaxis.axis), event.jaxis.value);
        break;
      case SDL_JOYBUTTONDOWN:
        m_inputState.press_joystick_button(static_cast<JoystickButton>(event.jbutton.button));
        break;
      case SDL_JOYBUTTONUP:
        m_inputState.release_joystick_button(static_cast<JoystickButton>(event.jbutton.button));
        break;
      case SDL_QUIT:
        return false;
      default:
        break;
    }
  }

  return true;
}

void Application::process_fiducial_input()
{
  if(m_inputState.key_down(KEYCODE_k))
  {
    bool k1 = m_inputState.key_down(KEYCODE_1),
         k2 = m_inputState.key_down(KEYCODE_2),
         k3 = m_inputState.key_down(KEYCODE_3),
         k4 = m_inputState.key_down(KEYCODE_4);

    if(k1 || k2 || k3 || k4)
    {
      const std::string& sceneID = get_active_scene_id();
      m_pipeline->set_detect_fiducials(sceneID, k2 || k4);
      m_renderFiducials = k3 || k4;
    }
  }
}

void Application::process_input()
{
  process_camera_input();
  process_renderer_input();

  // If we are running in batch mode, suppress all non-essential input.
  if(m_batchModeEnabled) return;

  process_command_input();
  process_fiducial_input();
  process_labelling_input();
  process_mode_input();
  process_voice_input();
}

void Application::process_labelling_input()
{
  // Allow the user to change the current semantic label.
  static bool canChangeLabel = true;
  const Model_Ptr& model = m_pipeline->get_model();
  LabelManager_CPtr labelManager = model->get_label_manager();
  SpaintVoxel::Label semanticLabel = model->get_semantic_label();

  if(m_inputState.key_down(KEYCODE_RSHIFT) && m_inputState.key_down(KEYCODE_RIGHTBRACKET))
  {
    if(canChangeLabel) semanticLabel = labelManager->get_next_label(semanticLabel);
    canChangeLabel = false;
  }
  else if(m_inputState.key_down(KEYCODE_RSHIFT) && m_inputState.key_down(KEYCODE_LEFTBRACKET))
  {
    if(canChangeLabel) semanticLabel = labelManager->get_previous_label(semanticLabel);
    canChangeLabel = false;
  }
  else canChangeLabel = true;

  model->set_semantic_label(semanticLabel);

  // Update the current selector.
  model->update_selector(m_inputState, model->get_slam_state(get_active_scene_id()), get_monocular_render_state(), m_renderer->is_mono());

  // Record whether or not we're in the middle of marking some voxels (this allows us to make voxel marking atomic for undo/redo purposes).
  static bool currentlyMarking = false;

  // Specify the precursors map for compressible commands.
  static const std::string beginMarkVoxelsDesc = "Begin Mark Voxels";
  static const std::string markVoxelsDesc = MarkVoxelsCommand::get_static_description();
  static std::map<std::string,std::string> precursors = map_list_of(beginMarkVoxelsDesc,markVoxelsDesc)(markVoxelsDesc,markVoxelsDesc);

  // If the current selector is active:
  if(model->get_selector()->is_active())
  {
    // Get the voxels selected by the user (if any).
    Selector::Selection_CPtr selection = model->get_selection();

    // If there are selected voxels, mark the voxels with the current semantic label.
    if(selection)
    {
      const SpaintVoxel::PackedLabel packedLabel(semanticLabel, SpaintVoxel::LG_USER);
      const bool useUndo = true;
      if(useUndo)
      {
        if(!currentlyMarking)
        {
          m_commandManager.execute_command(Command_CPtr(new NoOpCommand(beginMarkVoxelsDesc)));
          currentlyMarking = true;
        }
        m_commandManager.execute_compressible_command(Command_CPtr(new MarkVoxelsCommand(get_active_scene_id(), selection, packedLabel, model)), precursors);
      }
      else model->mark_voxels(get_active_scene_id(), selection, packedLabel, NORMAL_MARKING);
    }
  }
  else if(currentlyMarking)
  {
    m_commandManager.execute_compressible_command(Command_CPtr(new NoOpCommand("End Mark Voxels")), precursors);
    currentlyMarking = false;
  }
}

void Application::process_mode_input()
{
  MultiScenePipeline::Mode mode = m_pipeline->get_mode();
  if(m_inputState.key_down(KEYCODE_m))
  {
    if(m_inputState.key_down(KEYCODE_1))      mode = MultiScenePipeline::MODE_NORMAL;
    else if(m_inputState.key_down(KEYCODE_2)) mode = MultiScenePipeline::MODE_PROPAGATION;
    else if(m_inputState.key_down(KEYCODE_3)) mode = MultiScenePipeline::MODE_TRAINING;
    else if(m_inputState.key_down(KEYCODE_4)) mode = MultiScenePipeline::MODE_PREDICTION;
    else if(m_inputState.key_down(KEYCODE_5)) mode = MultiScenePipeline::MODE_TRAIN_AND_PREDICT;
    else if(m_inputState.key_down(KEYCODE_6)) mode = MultiScenePipeline::MODE_SMOOTHING;
    else if(m_inputState.key_down(KEYCODE_7)) mode = MultiScenePipeline::MODE_FEATURE_INSPECTION;
    else if(m_inputState.key_down(KEYCODE_8)) mode = MultiScenePipeline::MODE_SEGMENTATION_TRAINING;
    else if(m_inputState.key_down(KEYCODE_9)) mode = MultiScenePipeline::MODE_SEGMENTATION;
  }
  m_pipeline->set_mode(mode);
}

void Application::process_renderer_input()
{
  // Allow the user to switch renderers.
  static int framesTillSwitchAllowed = 0;
  const int SWITCH_DELAY = 20;
  if(framesTillSwitchAllowed == 0)
  {
    if(m_inputState.key_down(KEYCODE_r))
    {
      if(m_inputState.key_down(KEYCODE_LSHIFT))
      {
#ifdef WITH_OVR
        if(m_inputState.key_down(KEYCODE_1) || m_inputState.key_down(KEYCODE_2))
        {
          try
          {
            switch_to_rift_renderer(m_inputState.key_down(KEYCODE_1) ? RiftRenderer::WINDOWED_MODE : RiftRenderer::FULLSCREEN_MODE);
            framesTillSwitchAllowed = SWITCH_DELAY;
          }
          catch(std::runtime_error& e)
          {
            std::cerr << e.what() << '\n';
          }
        }
#endif
      }
      else
      {
        for(size_t subwindowConfigurationIndex = 0; subwindowConfigurationIndex <= 9; ++subwindowConfigurationIndex)
        {
          if(m_inputState.key_down(static_cast<Keycode>(KEYCODE_0 + subwindowConfigurationIndex)))
          {
            switch_to_windowed_renderer(subwindowConfigurationIndex);
            framesTillSwitchAllowed = SWITCH_DELAY;
            break;
          }
        }
      }
    }
  }
  else --framesTillSwitchAllowed;

  // Allow the user to change the visualisation type of the active sub-window.
  if(m_inputState.key_down(KEYCODE_c))
  {
    Subwindow& subwindow = get_active_subwindow();
    boost::optional<VisualisationGenerator::VisualisationType> type;

    if(!m_inputState.key_down(KEYCODE_LALT))
    {
      type =
        m_inputState.key_down(KEYCODE_1) ? VisualisationGenerator::VT_SCENE_SEMANTICLAMBERTIAN :
        m_inputState.key_down(KEYCODE_2) ? VisualisationGenerator::VT_SCENE_SEMANTICPHONG :
        m_inputState.key_down(KEYCODE_3) ? VisualisationGenerator::VT_SCENE_SEMANTICCOLOUR :
        m_inputState.key_down(KEYCODE_4) ? VisualisationGenerator::VT_SCENE_SEMANTICFLAT :
        m_inputState.key_down(KEYCODE_5) ? VisualisationGenerator::VT_SCENE_COLOUR :
        m_inputState.key_down(KEYCODE_6) ? VisualisationGenerator::VT_SCENE_NORMAL :
        m_inputState.key_down(KEYCODE_7) ? VisualisationGenerator::VT_SCENE_CONFIDENCE :
        m_inputState.key_down(KEYCODE_8) ? VisualisationGenerator::VT_SCENE_DEPTH :
        m_inputState.key_down(KEYCODE_9) ? VisualisationGenerator::VT_INPUT_COLOUR :
        m_inputState.key_down(KEYCODE_0) ? boost::optional<VisualisationGenerator::VisualisationType>(VisualisationGenerator::VT_INPUT_DEPTH) :
        boost::none;

      if(type)
      {
        subwindow.set_surfel_flag(m_inputState.key_down(KEYCODE_LSHIFT));
        subwindow.set_remote_flag(m_inputState.key_down(KEYCODE_LCTRL));
      }
    }
    else
    {
      type =
        m_inputState.key_down(KEYCODE_1) ? VisualisationGenerator::VT_RELOCALISER_LEAVES :
        m_inputState.key_down(KEYCODE_2) ? VisualisationGenerator::VT_RELOCALISER_POINTS :
        m_inputState.key_down(KEYCODE_3) ? boost::optional<VisualisationGenerator::VisualisationType>(VisualisationGenerator::VT_RELOCALISER_GTPOINTS) :
        boost::none;
    }

    if(type) subwindow.set_type(*type);
  }
}

void Application::process_voice_input()
{
  // If we are not connected to a voice command server, early out.
  if(!m_voiceCommandStream) return;

  size_t availableBytes;
  while((availableBytes = m_voiceCommandStream.rdbuf()->available()) > 0)
  {
    // If there is a voice command available, get it from the stream and trim it to remove any trailing carriage return.
    std::string command;
    std::getline(m_voiceCommandStream, command);
    boost::trim(command);

    // Output the voice command for debugging purposes.
    std::cout << "Voice Command: " << command << '\n';

    // Process any requests to change label.
    const LabelManager_Ptr& labelManager = m_pipeline->get_model()->get_label_manager();
    for(size_t i = 0, labelCount = labelManager->get_label_count(); i < labelCount; ++i)
    {
      SpaintVoxel::Label label = static_cast<SpaintVoxel::Label>(i);
      std::string changeLabelCommand = "label " + labelManager->get_label_name(label);
      if(command == changeLabelCommand) m_pipeline->get_model()->set_semantic_label(label);
    }

    // Process any requests to disable/enable fusion for the active scene.
    if(command == "disable fusion") m_pipeline->set_fusion_enabled(get_active_scene_id(), false);
    if(command == "enable fusion") m_pipeline->set_fusion_enabled(get_active_scene_id(), true);

    // Process any requests to change pipeline mode.
    if(command == "switch to normal mode") m_pipeline->set_mode(MultiScenePipeline::MODE_NORMAL);
    if(command == "switch to propagation mode") m_pipeline->set_mode(MultiScenePipeline::MODE_PROPAGATION);
    if(command == "switch to training mode") m_pipeline->set_mode(MultiScenePipeline::MODE_TRAINING);
    if(command == "switch to prediction mode") m_pipeline->set_mode(MultiScenePipeline::MODE_PREDICTION);
    if(command == "switch to correction mode") m_pipeline->set_mode(MultiScenePipeline::MODE_TRAIN_AND_PREDICT);
    if(command == "switch to smoothing mode") m_pipeline->set_mode(MultiScenePipeline::MODE_SMOOTHING);
  }
}

void Application::save_current_memory_usage()
{
#ifdef WITH_CUDA
  // Make sure that the memory usage output stream has been initialised, and throw if not.
  if(!m_memoryUsageOutputStream)
  {
    throw std::runtime_error("Error: Memory usage output stream has not been initialised");
  }

  // Find how many GPUs are available.
  int gpuCount = 0;
  ORcudaSafeCall(cudaGetDeviceCount(&gpuCount));

  // Save the currently active GPU (we have to change the active GPU to query the memory usage
  // of the other GPUs, and we want to restore the original GPU once we're done).
  int originalGpu = -1;
  ORcudaSafeCall(cudaGetDevice(&originalGpu));

  // For each available GPU:
  for(int i = 0; i < gpuCount; ++i)
  {
    // Set the GPU as active.
    ORcudaSafeCall(cudaSetDevice(i));

    // Look up its memory usage.
    size_t freeMemory, totalMemory;
    ORcudaSafeCall(cudaMemGetInfo(&freeMemory, &totalMemory));

    // Convert the memory usage to MB.
    const size_t bytesPerMb = 1024 * 1024;
    const size_t freeMb = freeMemory / bytesPerMb;
    const size_t usedMb = (totalMemory - freeMemory) / bytesPerMb;
    const size_t totalMb = totalMemory / bytesPerMb;

    // Save the memory usage to the output stream.
    *m_memoryUsageOutputStream << freeMb << ";" << usedMb << ";" << totalMb << ";";
  }

  *m_memoryUsageOutputStream << '\n';

  // Restore the GPU that was originally active.
  ORcudaSafeCall(cudaSetDevice(originalGpu));
#endif
}

void Application::save_mesh() const
{
  // If meshing is disabled, early out.
  if(!m_meshingEngine) return;

  // Look up the IDs of all of the scenes we are reconstructing.
  Model_CPtr model = m_pipeline->get_model();
  const Settings_CPtr& settings = model->get_settings();
  const std::vector<std::string> sceneIDs = model->get_scene_ids();

  // Determine the (base) filename to use for the mesh, based on either the experiment tag (if specified) or the current timestamp (otherwise).
  std::string meshBaseName = settings->get_first_value<std::string>("experimentTag", "spaint-" + TimeUtil::get_iso_timestamp());

  // Determine the directory into which to save the meshes, and make sure that it exists.
  boost::filesystem::path dir = find_subdir_from_executable("meshes");
  if(sceneIDs.size() > 1) dir = dir / meshBaseName;
  boost::filesystem::create_directories(dir);

  // Mesh each scene independently.
  for(size_t sceneIdx = 0; sceneIdx < sceneIDs.size(); ++sceneIdx)
  {
    const std::string& sceneID = sceneIDs[sceneIdx];
    std::cout << "Meshing " << sceneID << " scene.\n";
    SpaintVoxelScene_CPtr scene = model->get_slam_state(sceneID)->get_voxel_scene();

    // Construct the mesh (specifying a maximum number of triangles to avoid running out of memory on less powerful GPUs, e.g. the Titan Black).
    Mesh_Ptr mesh(new ITMMesh(settings->GetMemoryType(), 1 << 24));
    m_meshingEngine->MeshScene(mesh.get(), scene.get());

    // Determine the relative transform (if any) to apply to the mesh prior to saving it.
    boost::optional<Matrix4f> relativeTransform;

#ifdef WITH_VICON
    ViconInterface_CPtr vicon = model->get_vicon();
    if(vicon)
    {
      // If we're using the Vicon system, try to get the relative transform from this scene's coordinate system to Vicon space, and use that.
      relativeTransform = vicon->get_world_to_vicon_transform(sceneID);
    }
    else
#endif
    {
      // Otherwise, if there's a pose optimiser, try to get the relative transform from this scene's coordinate system to the World scene's coordinate system.
      if(model->get_collaborative_pose_optimiser() && sceneID != Model::get_world_scene_id())
      {
        boost::optional<std::pair<ORUtils::SE3Pose,size_t> > result = model->get_collaborative_pose_optimiser()->try_get_relative_transform(Model::get_world_scene_id(), sceneID);
        relativeTransform = result ? boost::optional<Matrix4f>(result->first.GetM()) : boost::none;
      }
    }

    // If a relative transform is being used, we need to update every triangle in the mesh. We do this on the CPU, since this is not currently
    // a time-sensitive operation. (We might want to use a proper CUDA kernel in the future.)
    if(relativeTransform)
    {
      // First of all, allocate a memory block on the CPU to hold a copy of the mesh triangles, and copy them into it. Note that this copy could have
      // been avoided if the mesh was already allocated on the CPU, but that would have made the meshing itself slower.
      typedef ITMMesh::Triangle Triangle;
      typedef ORUtils::MemoryBlock<Triangle> TriangleBlock;
      boost::shared_ptr<TriangleBlock> triangles(new TriangleBlock(mesh->noMaxTriangles, MEMORYDEVICE_CPU));
      triangles->SetFrom(mesh->triangles, mesh->memoryType == MEMORYDEVICE_CUDA ? TriangleBlock::CUDA_TO_CPU : TriangleBlock::CPU_TO_CPU);

      // Next, transform each triangle using the relative transform determined above.
      const Matrix4f transform = *relativeTransform;
      Triangle *trianglesData = triangles->GetData(MEMORYDEVICE_CPU);
      for(size_t triangleIdx = 0; triangleIdx < mesh->noTotalTriangles; ++triangleIdx)
      {
        trianglesData[triangleIdx].p0  = transform * trianglesData[triangleIdx].p0;
        trianglesData[triangleIdx].p1  = transform * trianglesData[triangleIdx].p1;
        trianglesData[triangleIdx].p2  = transform * trianglesData[triangleIdx].p2;
      }

      // Finally, copy the updated triangles back into the mesh.
      mesh->triangles->SetFrom(triangles.get(), mesh->memoryType == MEMORYDEVICE_CUDA ? TriangleBlock::CPU_TO_CUDA : TriangleBlock::CPU_TO_CPU);
    }

    // Save the mesh to disk.
    const boost::filesystem::path meshPath = dir / (meshBaseName + "_" + sceneID + ".ply");
    std::cout << "Saving mesh to: " << meshPath << '\n';
    mesh->WritePLY(meshPath.string().c_str());
  }
}

void Application::save_models() const
{
  // Find the models directory and make sure it exists.
  boost::filesystem::path modelsSubdir = find_subdir_from_executable("models");
  boost::filesystem::create_directories(modelsSubdir);

  // Determine the directory to use for saving the models, based on either the experiment tag (if specified) or the current timestamp (otherwise).
  const Settings_CPtr& settings = m_pipeline->get_model()->get_settings();
  std::string modelName = settings->get_first_value<std::string>("experimentTag", TimeUtil::get_iso_timestamp());
  boost::filesystem::path outputDir = modelsSubdir / modelName;

  // Save the models to disk.
  m_pipeline->save_models(outputDir);
}

void Application::save_screenshot() const
{
  boost::filesystem::path p = find_subdir_from_executable("screenshots") / ("spaint-" + TimeUtil::get_iso_timestamp() + ".png");
  boost::filesystem::create_directories(p.parent_path());
  std::cout << "[spaint] Saving screenshot to " << p << "...\n";
  ImagePersister::save_image_on_thread(m_renderer->capture_screenshot(), p);
}

void Application::save_sequence_frame()
{
  const Subwindow& mainSubwindow = m_renderer->get_subwindow_configuration()->subwindow(0);
  const std::string& sceneID = mainSubwindow.get_scene_id();

  // If the RGBD calibration hasn't already been saved, save it now.
  SLAMState_CPtr slamState = m_pipeline->get_model()->get_slam_state(sceneID);
  boost::filesystem::path calibrationFile = m_sequencePathGenerator->get_base_dir() / "calib.txt";
  if(!boost::filesystem::exists(calibrationFile))
  {
    writeRGBDCalib(calibrationFile.string().c_str(), slamState->get_view()->calib);
  }

  // Save the current input images.
  ImagePersister::save_image_on_thread(slamState->get_input_raw_depth_image_copy(), m_sequencePathGenerator->make_path("frame-%06i.depth.png"));
  ImagePersister::save_image_on_thread(slamState->get_input_rgb_image_copy(), m_sequencePathGenerator->make_path("frame-%06i.color.png"));

  // Save the inverse pose (i.e. the camera -> world transformation).
  PosePersister::save_pose_on_thread(slamState->get_pose().GetInvM(), m_sequencePathGenerator->make_path("frame-%06i.pose.txt"));

  m_sequencePathGenerator->increment_index();
}

void Application::save_video_frame()
{
  m_videoPathGenerator->increment_index();
  ImagePersister::save_image_on_thread(m_renderer->capture_screenshot(), m_videoPathGenerator->make_path("%06i.png"));
}

void Application::setup_labels()
{
  const LabelManager_Ptr& labelManager = m_pipeline->get_model()->get_label_manager();
  std::ifstream fs((resources_dir() / "Labels.txt").c_str());
  if(fs)
  {
    // If a labels file is present, load the labels from it.
    std::cout << "[spaint] Loading labels...\n";

    std::string label;
    while(std::getline(fs, label))
    {
      boost::trim(label);
      if(label != "") labelManager->add_label(label);
    }

    // Add additional dummy labels up to the maximum number of labels we are allowed.
    for(size_t i = labelManager->get_label_count(), count = labelManager->get_max_label_count(); i < count; ++i)
    {
      labelManager->add_label(boost::lexical_cast<std::string>(i));
    }
  }
  else
  {
    // Otherwise, use a set of dummy labels.
    std::cout << "[spaint] Failed to load labels, reverting to a set of dummy labels...\n";

    labelManager->add_label("background");
    for(size_t i = 1, count = labelManager->get_max_label_count(); i < count; ++i)
    {
      labelManager->add_label(boost::lexical_cast<std::string>(i));
    }
  }

  // Set the initial semantic label to use for painting.
  m_pipeline->get_model()->set_semantic_label(1);
}

void Application::setup_meshing()
{
  const Settings_CPtr& settings = m_pipeline->get_model()->get_settings();
  if(settings->createMeshingEngine || m_saveMeshOnExit)
  {
    m_meshingEngine.reset(ITMMeshingEngineFactory::MakeMeshingEngine<SpaintVoxel,ITMVoxelBlockHash>(settings->deviceType));
  }
}

#ifdef WITH_OVR
void Application::switch_to_rift_renderer(RiftRenderer::RiftRenderingMode mode)
{
  const size_t riftSubwindowConfigurationIndex = 1;
  SubwindowConfiguration_Ptr subwindowConfiguration = get_subwindow_configuration(riftSubwindowConfigurationIndex);
  if(!subwindowConfiguration) return;

  m_renderer.reset(new RiftRenderer("Semantic Paint", m_pipeline->get_model(), subwindowConfiguration, mode));
}
#endif

void Application::switch_to_windowed_renderer(size_t subwindowConfigurationIndex)
{
  SubwindowConfiguration_Ptr subwindowConfiguration = get_subwindow_configuration(subwindowConfigurationIndex);
  if(!subwindowConfiguration) return;

  const Settings_CPtr& settings = m_pipeline->get_model()->get_settings();
  const int mainViewportWidth = settings->get_first_value<int>("Application.mainViewportWidth", 640);
  const int mainViewportHeight = settings->get_first_value<int>("Application.mainViewportHeight", 480);
  const Subwindow& mainSubwindow = subwindowConfiguration->subwindow(0);
  const Vector2i windowViewportSize((int)ROUND(mainViewportWidth / mainSubwindow.width()), (int)ROUND(mainViewportHeight / mainSubwindow.height()));

  const std::string title = m_pipeline->get_model()->get_mapping_server() ? "SemanticPaint - Server" : "SemanticPaint";
  m_renderer.reset(new WindowedRenderer(title, m_pipeline->get_model(), subwindowConfiguration, windowViewportSize));
}

void Application::toggle_recording(const std::string& type, boost::optional<tvgutil::SequentialPathGenerator>& pathGenerator)
{
  if(pathGenerator)
  {
    pathGenerator.reset();
    std::cout << "[spaint] Stopped saving " << type << ".\n";
  }
  else
  {
    pathGenerator.reset(SequentialPathGenerator(find_subdir_from_executable(type + "s") / TimeUtil::get_iso_timestamp()));
    boost::filesystem::create_directories(pathGenerator->get_base_dir());
    std::cout << "[spaint] Started saving " << type << " to " << pathGenerator->get_base_dir() << "...\n";
  }
}

ext: cpp

max_stars_repo_name: torrvision/spaint

max_issues_repo_name: torrvision/spaint

max_forks_repo_name: torrvision/spaint


text:
/* ----------------------------------------------------------------------------

 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 * Atlanta, Georgia 30332-0415
 * All Rights Reserved
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)

 * See LICENSE for the license information

 * -------------------------------------------------------------------------- */

/**
 *  @file  testTOAFactor.cpp
 *  @brief Unit tests for "Time of Arrival" factor
 *  @author Frank Dellaert
 *  @author Jay Chakravarty
 *  @date December 2014
 */

#include <gtsam_unstable/geometry/Event.h>
#include <gtsam/nonlinear/ExpressionFactorGraph.h>
#include <gtsam/nonlinear/expressions.h>
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/base/numericalDerivative.h>

#include <CppUnitLite/TestHarness.h>
#include <boost/format.hpp>
#include <boost/bind.hpp>

using namespace std;
using namespace gtsam;

// typedefs
typedef Expression<Point3> Point3_;
typedef Expression<Event> Event_;

// units
static const double ms = 1e-3;
static const double cm = 1e-2;

// Create a noise model for the TOA error
static SharedNoiseModel model(noiseModel::Isotropic::Sigma(1, 0.5 * ms));

static const double timeOfEvent = 25;
static const Event exampleEvent(timeOfEvent, 1, 0, 0);
static const Point3 microphoneAt0(0,0,0);

//*****************************************************************************
TEST( TOAFactor, NewWay ) {
  Key key = 12;
  Event_ eventExpression(key);
  Point3_ microphoneConstant(microphoneAt0); // constant expression
  double measurement = 7;
  Double_ expression(&Event::toa, eventExpression, microphoneConstant);
  ExpressionFactor<double> factor(model, measurement, expression);
}

//*****************************************************************************
TEST( TOAFactor, WholeEnchilada ) {

  static const bool verbose = false;

  // Create microphones
  const double height = 0.5;
  vector<Point3> microphones;
  microphones.push_back(Point3(0, 0, height));
  microphones.push_back(Point3(403 * cm, 0, height));
  microphones.push_back(Point3(403 * cm, 403 * cm, height));
  microphones.push_back(Point3(0, 403 * cm, 2 * height));
  EXPECT_LONGS_EQUAL(4, microphones.size());
//  microphones.push_back(Point3(200 * cm, 200 * cm, height));

  // Create a ground truth point
  const double timeOfEvent = 0;
  Event groundTruthEvent(timeOfEvent, 245 * cm, 201.5 * cm, (212 - 45) * cm);

  // Simulate simulatedTOA
  size_t K = microphones.size();
  vector<double> simulatedTOA(K);
  for (size_t i = 0; i < K; i++) {
    simulatedTOA[i] = groundTruthEvent.toa(microphones[i]);
    if (verbose) {
      cout << "mic" << i << " = " << microphones[i] << endl;
      cout << "z" << i << " = " << simulatedTOA[i] / ms << endl;
    }
  }

  // Now, estimate using non-linear optimization
  ExpressionFactorGraph graph;
  Key key = 12;
  Event_ eventExpression(key);
  for (size_t i = 0; i < K; i++) {
    Point3_ microphone_i(microphones[i]); // constant expression
    Double_ predictTOA(&Event::toa, eventExpression, microphone_i);
    graph.addExpressionFactor(predictTOA, simulatedTOA[i], model);
  }

  /// Print the graph
  if (verbose)
    GTSAM_PRINT(graph);

  // Create initial estimate
  Values initialEstimate;
  //Event estimatedEvent(timeOfEvent -10, 200 * cm, 150 * cm, 350 * cm);
  Vector4 delta;
  delta << 0.1, 0.1, -0.1, 0.1;
  Event estimatedEvent = groundTruthEvent.retract(delta);
  initialEstimate.insert(key, estimatedEvent);

  // Print
  if (verbose)
    initialEstimate.print("Initial Estimate:\n");

  // Optimize using Levenberg-Marquardt optimization.
  LevenbergMarquardtParams params;
  params.setAbsoluteErrorTol(1e-10);
  if (verbose)
    params.setVerbosity("ERROR");
  LevenbergMarquardtOptimizer optimizer(graph, initialEstimate, params);
  Values result = optimizer.optimize();
  if (verbose)
    result.print("Final Result:\n");

  EXPECT(assert_equal(groundTruthEvent, result.at<Event>(key), 1e-6));
}
//*****************************************************************************
int main() {
  TestResult tr;
  return TestRegistry::runAllTests(tr);
}
//*****************************************************************************

max_stars_repo_name: DEVESHTARASIA/gtsam

max_issues_repo_name: DEVESHTARASIA/gtsam

max_forks_repo_name: DEVESHTARASIA/gtsam


text:
#pragma once

// Classes in this file:
//     shared_object
//     application_component
//     application

#include "cool/common.hpp"
#include "cool/enum_traits.hpp"

#include <unordered_map>

#include <boost/thread.hpp>
#include <boost/cast.hpp>

/// shared data object base
class shared_object : public ref_counter<shared_object> {
public:
	virtual ~shared_object() {}
};

typedef boost::intrusive_ptr<shared_object> shared_object_ptr;

DEFINE_ENUM_CLASS(
	update_order, uint32_t,
	earliest,
	pre_update,
	update,
	post_update,
	pre_draw,
	draw,
	post_draw,
	latest
)

/// application component
class application_component : public ref_counter<application_component> {
public:
	application_component(update_order order) : _order(order) {}
	virtual ~application_component() {}

	update_order get_update_order() const { return _order; }

	virtual void initialize() = 0;
	virtual void update() = 0;

private:
	update_order _order;
};

typedef boost::intrusive_ptr<application_component> application_component_ptr;

DEFINE_ENUM_CLASS(
	touch, uint32_t,
	begin,
	end,
	move,
	cancel
)

/// application base class
class application : public ref_counter<application> {
public:
	application(void* context);

	virtual ~application();

	static application* get_instance() { return _instance; }

	void* get_context() const { return _context; }

	shared_object* add_shared_object(const char* name, shared_object* data);
	shared_object* get_shared_object(const char* name) const;
	shared_object_ptr remove_shared_object(const char* name);

	template <typename T>
	T* add_shared_object(const char* name, shared_object* data) {
		return static_cast<T*>(add_shared_object(name, data));
	}

	template <typename T>
	T* get_shared_object(const char* name) const {
		return boost::polymorphic_downcast<T*>(get_shared_object(name));
	}

	application_component* add_component(application_component* component);
	void remove_component(application_component* component);

	// lifecycle callbacks

	virtual void on_save_state() {}
	virtual void on_create() {}
	virtual void on_gain_focus() {}
	virtual void on_lost_focus() {}
	virtual void on_terminate() {}

	// loop callbacks

	virtual void on_update();
	virtual void on_render(int /*width*/, int /*height*/) {}

	// input callbacks

	virtual void on_touch(touch /*action*/, int /*x*/, int /*y*/) {}

protected:
	void update_components();

private:
	static application* _instance;

	void* _context;

	typedef std::unordered_map<std::string, shared_object_ptr> SharedObjects;
	SharedObjects _shared_objects;

	mutable boost::mutex _mutex;

	typedef std::vector<application_component_ptr> Components;
	Components _components;

private:
	DISALLOW_COPY_AND_ASSIGN(application)
};

typedef boost::intrusive_ptr<application> application_ptr;

extern application* create_application(void* context);

ext: hpp

max_stars_repo_name: mzhirnov/cool

max_issues_repo_name: mzhirnov/cool

max_forks_repo_name: mzhirnov/cool


text:
#ifndef BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED
#define BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED

// Copyright Aleksey Gurtovoy 2000-2004
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Id: max_element.hpp 49267 2008-10-11 06:19:02Z agurtovoy $
// $Date: 2008-10-10 23:19:02 -0700 (Fri, 10 Oct 2008) $
// $Revision: 49267 $

#include <boost/mpl/less.hpp>
#include <boost/mpl/iter_fold.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/aux_/common_name_wknd.hpp>
#include <boost/mpl/aux_/na_spec.hpp>

namespace boost { namespace mpl {

BOOST_MPL_AUX_COMMON_NAME_WKND(max_element)

namespace aux {

template< typename Predicate >
struct select_max
{
    template< typename OldIterator, typename Iterator >
    struct apply
    {
        typedef typename apply2<
              Predicate
            , typename deref<OldIterator>::type
            , typename deref<Iterator>::type
            >::type condition_;

        typedef typename if_<
              condition_
            , Iterator
            , OldIterator
            >::type type;
    };
};

} // namespace aux

template<
      typename BOOST_MPL_AUX_NA_PARAM(Sequence)
    , typename Predicate = less<_,_>
    >
struct max_element
    : iter_fold<
          Sequence
        , typename begin<Sequence>::type
        , protect< aux::select_max<Predicate> >
        >
{
};

BOOST_MPL_AUX_NA_SPEC(1, max_element)

}}

#endif // BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED

max_stars_repo_name: PXLVision/opengv

max_issues_repo_name: isuhao/klib

max_forks_repo_name: isuhao/klib


text:
/* Copyright (c) 2018 vargaconsulting, Toronto,ON Canada
 * Author: Varga, Steven <steven@vargaconsulting.ca>
 */

#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <Eigen/Dense> // must include Eigen before <h5cpp/core>

#include <cstdint>
#include "struct.h"
#include <h5cpp/core>
	// generated file must be sandwiched between core and io
	// to satisfy template dependencies in <h5cpp/io>
	#include "generated.h"
#include <h5cpp/io>
#include "utils.hpp"

template<class T> using Matrix   = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;

int main(){

	h5::fd_t fd = h5::create("example.h5",H5F_ACC_TRUNC);

	// SCALAR: integral
	try { // centrally used error handling
		std::vector<int> stream(83);
		std::iota(std::begin(stream), std::end(stream), 1);
		// the leading dimension is extended once chunk is full, chunk is filled in row major order
		// zero copy writes directly to chunk buffer then pushed through filter chain if specified
		// works up to H5CPP_MAX_RANK default to 7
		// last chunk if partial filled with h5::fill_value<T>( some_value )
		h5::pt_t pt = h5::create<int>(fd, "stream of integral",
				 h5::max_dims{H5S_UNLIMITED,3,5}, h5::chunk{2,3,5} | h5::gzip{9} | h5::fill_value<int>(3) );
		for( auto record : stream )
			h5::append(pt, record);
		//auto M = h5::read<arma::mat>(fd,"stream of integral" );
	} catch ( const h5::error::any& e ){
		std::cerr << "ERROR:" << e.what();
	}

	// SCALAR: pod
	try { // centrally used error handling
		std::vector<sn::example::Record> stream = h5::utils::get_test_data<sn::example::Record>(127);

		// implicit conversion from h5::ds_t to h5::pt_t makes it a breeze to create
		// packet_table from h5::open | h5::create calls,
		// The newly created h5::pt_t  stateful container caches the incoming data until
		// bucket filled. IO operations are at h5::chunk boundaries
		// or when resource is released. Last partial chunk handled as expected.
		//
		// compiler assisted introspection generates boilerplate, developer
		// can focus on the idea, leaving boring details to machines
		//h5::pt_t pt = h5::create<sn::example::Record>(fd, "stream of struct",
		h5::pt_t pt = h5::create<sn::example::Record>(fd, "stream of struct",
				 h5::max_dims{H5S_UNLIMITED,7}, h5::chunk{4,7} | h5::gzip{9} );
		for( auto record : stream )
			h5::append(pt, record);
	} catch ( const h5::error::any& e ){
		std::cerr << "ERROR:" << e.what();
	}

	// CONTAINERS : WORK IN PROGRESS!!!
	{ 	// packet table for a collection of matrices modelling a HD resolution of gray scale images
		// c++ objects may be factored into:
		// 1. information available compile time: underlying type or element_type, ...
		// 2. runtime information: actual place and size in memory
		// because of the latter, there is no 'type' safe way to declare a packet table but agree upon that
		// the slowest growing dimension -- the left most in current_dims{ index, rows,cols }
		// is the object index, the rest : [rows*cols] is the data content of the object being indexed

		// creates and transfers ownership to pt
		//size_t nrows = 1280, ncols=720, nframes=25*60*1;
		size_t nrows = 3, ncols=13, nframes=7;
		h5::pt_t pt = h5::create<double>(fd, "stream of matrices", // 1280 x 720
				h5::max_dims{H5S_UNLIMITED,nrows,ncols},
				// currently chunk dimensions must match object size
				h5::chunk{1,nrows,ncols} ); // chunk size controls h5::append internal cache size
		Matrix<double> M(nrows,ncols);
		// paint matrix with a sequence -- arma::mat doesn't know iterators
		int k=0;
	   	for( int i=0; i<nrows; i++)
			for(int j=0; j<ncols; j++) M(i,j) = ++k;
		// actual performance: create 'movie' frame by frame
		for( int i = 1; i < nframes; i++) 	//
			h5::append( pt, M);  			// save it into file
	}

	{
		h5::pt_t pt = h5::create<double>(fd, "stream of vectors",
				h5::max_dims{H5S_UNLIMITED,5}, h5::chunk{1,5} );

		arma::vec V(5); for(int i=0; i<5; i++) V(i) = i;

		for( int i = 0; i < 7; i++)
			V[0] = i, h5::append( pt, V);  			// save it into file
	}

	return 0;
}


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include <algorithm>
#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <boost/optional/optional.hpp>
#include <glog/logging.h>
#include <gtest/gtest.h>

#include "kudu/common/column_predicate.h"
#include "kudu/common/common.pb.h"
#include "kudu/common/iterator.h"
#include "kudu/common/partial_row.h"
#include "kudu/common/scan_spec.h"
#include "kudu/common/schema.h"
#include "kudu/gutil/port.h"
#include "kudu/gutil/stringprintf.h"
#include "kudu/tablet/local_tablet_writer.h"
#include "kudu/tablet/tablet-test-util.h"
#include "kudu/tablet/tablet.h"
#include "kudu/util/memory/arena.h"
#include "kudu/util/slice.h"
#include "kudu/util/status.h"
#include "kudu/util/stopwatch.h"
#include "kudu/util/test_macros.h"

using std::string;
using std::unique_ptr;
using std::vector;

namespace kudu {
namespace tablet {

const char* const kTestHostnames[] = { "foo", "foobar", "baz", nullptr };

class CompositePushdownTest : public KuduTabletTest {
 public:
  CompositePushdownTest()
      : KuduTabletTest(Schema({ ColumnSchema("year", INT16),
                                ColumnSchema("month", INT8),
                                ColumnSchema("day", INT8),
                                ColumnSchema("hostname", STRING),
                                ColumnSchema("data", STRING) },
                              4)) {
  }

  virtual void SetUp() OVERRIDE {
    KuduTabletTest::SetUp();

    FillTestTablet();
  }

  void FillTestTablet() {
    uint32_t nrows = 10 * 12 * 28;
    int i = 0;

    LocalTabletWriter writer(tablet().get(), &client_schema_);
    KuduPartialRow row(&client_schema_);
    for (int16_t year = 2000; year <= 2010; year++) {
      for (int8_t month = 1; month <= 12; month++) {
        for (int8_t day = 1; day <= 28; day++) {
          for (int host_idx = 0; kTestHostnames[host_idx] != nullptr; host_idx++) {
            CHECK_OK(row.SetInt16(0, year));
            CHECK_OK(row.SetInt8(1, month));
            CHECK_OK(row.SetInt8(2, day));
            CHECK_OK(row.SetStringCopy(3, kTestHostnames[host_idx]));
            CHECK_OK(row.SetStringCopy(4, StringPrintf("%d/%02d/%02d-%s", year, month, day,
                                                       kTestHostnames[host_idx])));
            ASSERT_OK_FAST(writer.Insert(row));

            if (i == nrows * 9 / 10) {
              ASSERT_OK(tablet()->Flush());
            }
            ++i;
          }
        }
      }
    }
  }

  // Helper function for sorting returned results by the 'data' field.
  // This is needed as "2" is lexicographically greater than "12" which means
  // that, e.g., comparing "(int16 year=2001, int8 month=2, int8 day=7, string
  // data=2001/02/07)" to "(int16 year=2001, int8 month=12, int8
  // day=7, string data=2001/12/07)" would be semantically incorrect if
  // the comparison was on the whole string vs the last portion of the
  // string ("2001/02/01" vs. "2001/12/01")
  struct SuffixComparator {
    bool operator()(const string &a, const string &b) {
      string s_a = a.substr(a.find("data="));
      string s_b = b.substr(b.find("data="));
      return s_a < s_b;
    }
  };

  void ScanTablet(ScanSpec *spec, vector<string> *results, const char *descr) {
    SCOPED_TRACE(descr);

    unique_ptr<RowwiseIterator> iter;
    ASSERT_OK(tablet()->NewRowIterator(client_schema_, &iter));
    ASSERT_OK(iter->Init(spec));
    ASSERT_TRUE(spec->predicates().empty()) << "Should have accepted all predicates";
    LOG_TIMING(INFO, descr) {
      ASSERT_OK(IterateToStringList(iter.get(), results));
    }
    std::sort(results->begin(), results->end(), SuffixComparator());
    for (const string &str : *results) {
      VLOG(1) << str;
    }
  }
};

TEST_F(CompositePushdownTest, TestPushDownExactEquality) {
  ScanSpec spec;
  int16_t year = 2001;
  int8_t month = 9;
  int8_t day = 7;
  Slice host(kTestHostnames[0]);
  auto pred_year = ColumnPredicate::Equality(schema_.column(0), &year);
  auto pred_month = ColumnPredicate::Equality(schema_.column(1), &month);
  auto pred_day = ColumnPredicate::Equality(schema_.column(2), &day);
  auto pred_host = ColumnPredicate::Equality(schema_.column(3), &host);
  spec.AddPredicate(pred_year);
  spec.AddPredicate(pred_month);
  spec.AddPredicate(pred_day);
  spec.AddPredicate(pred_host);
  vector<string> results;

  NO_FATALS(ScanTablet(&spec, &results, "Exact match using compound key"));
  ASSERT_EQ(1, results.size());
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="foo", string data="2001/09/07-foo"))",
            results.front());
}

// Test for "host <= 'foo'" which should reject 'foobaz'.
// Regression test for a bug in an earlier implementation of predicate pushdown.
TEST_F(CompositePushdownTest, TestPushDownStringInequality) {
  Arena arena(256);
  ScanSpec spec;
  int16_t year = 2001;
  int8_t month = 9;
  int8_t day = 7;
  Slice host("foo");
  auto pred_year = ColumnPredicate::Equality(schema_.column(0), &year);
  auto pred_month = ColumnPredicate::Equality(schema_.column(1), &month);
  auto pred_day = ColumnPredicate::Equality(schema_.column(2), &day);
  auto pred_host = ColumnPredicate::InclusiveRange(schema_.column(3), nullptr, &host, &arena);
  spec.AddPredicate(pred_year);
  spec.AddPredicate(pred_month);
  spec.AddPredicate(pred_day);
  spec.AddPredicate(*pred_host);
  vector<string> results;

  NO_FATALS(ScanTablet(&spec, &results, "Exact match using compound key"));
  ASSERT_EQ(2, results.size());
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="baz", string data="2001/09/07-baz"))",
            results.front());
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="foo", string data="2001/09/07-foo"))",
            results.back());
}

TEST_F(CompositePushdownTest, TestPushDownDateEquality) {
  ScanSpec spec;
  int16_t year = 2001;
  int8_t month = 9;
  int8_t day = 7;
  auto pred_year = ColumnPredicate::Equality(schema_.column(0), &year);
  auto pred_month = ColumnPredicate::Equality(schema_.column(1), &month);
  auto pred_day = ColumnPredicate::Equality(schema_.column(2), &day);
  spec.AddPredicate(pred_year);
  spec.AddPredicate(pred_month);
  spec.AddPredicate(pred_day);
  vector<string> results;

  NO_FATALS(ScanTablet(&spec, &results, "Exact match using compound key"));
  ASSERT_EQ(3, results.size());
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="baz", string data="2001/09/07-baz"))",
            results[0]);
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="foo", string data="2001/09/07-foo"))",
            results[1]);
  EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=7, "
            R"(string hostname="foobar", string data="2001/09/07-foobar"))",
            results[2]);
}

TEST_F(CompositePushdownTest, TestPushDownPrefixEquality) {
  int16_t year = 2001;
  int8_t month = 9;
  ColumnPredicate pred_year = ColumnPredicate::Equality(schema_.column(0), &year);
  ColumnPredicate pred_month = ColumnPredicate::Equality(schema_.column(1), &month);

  {
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results,
                         "Prefix match using 2/3 of a compound key"));
    ASSERT_EQ(28 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=1, "
              R"(string hostname="baz", string data="2001/09/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=28, "
              R"(string hostname="foobar", string data="2001/09/28-foobar"))",
              results.back());
  }

  {
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results,
                         "Prefix match using 1/3 of a compound key"));
    ASSERT_EQ(28 * 12 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=1, int8 day=1, "
              R"(string hostname="baz", string data="2001/01/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=2, int8 day=1, "
              R"(string hostname="baz", string data="2001/02/01-baz"))",
              results[28 * 3]);
    EXPECT_EQ("(int16 year=2001, int8 month=12, int8 day=28, "
              R"(string hostname="foobar", string data="2001/12/28-foobar"))",
              results.back());
  }
}

TEST_F(CompositePushdownTest, TestPushDownPrefixEqualitySuffixInequality) {
  int16_t year = 2001;
  int8_t month_l = 9;
  int8_t month_u = 12;
  int8_t day_l = 1;
  int8_t day_u = 16;

  auto pred_year = ColumnPredicate::Equality(schema_.column(0), &year);

  auto pred_month_eq = ColumnPredicate::Equality(schema_.column(1), &month_l);
  auto pred_month_ge_lt = ColumnPredicate::Range(schema_.column(1), &month_l, &month_u);
  auto pred_month_lt = ColumnPredicate::Range(schema_.column(1), nullptr, &month_l);

  auto pred_day_ge_lt = ColumnPredicate::Range(schema_.column(2), &day_l, &day_u);
  auto pred_day_ge = ColumnPredicate::Range(schema_.column(2), &day_l, nullptr);
  auto pred_day_lt = ColumnPredicate::Range(schema_.column(2), nullptr, &day_u);

  {
    // year=2001, month=9, day >= 1 && day < 16
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month_eq);
    spec.AddPredicate(pred_day_ge_lt);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix equality, suffix inequality"));
    ASSERT_EQ(15 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=1, "
              R"(string hostname="baz", string data="2001/09/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=15, "
              R"(string hostname="foobar", string data="2001/09/15-foobar"))",
              results.back());
  }

  {
    // year=2001, month=9, day >= 1
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month_eq);
    spec.AddPredicate(pred_day_ge);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix equality, suffix inequality"));
    ASSERT_EQ(28 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=1, "
              R"(string hostname="baz", string data="2001/09/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=28, "
              R"(string hostname="foobar", string data="2001/09/28-foobar"))",
              results.back());
  }

  {
    // year=2001, month=9, day < 16
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month_eq);
    spec.AddPredicate(pred_day_lt);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix equality, suffix inequality"));
    ASSERT_EQ(15 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=1, "
              R"(string hostname="baz", string data="2001/09/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=15, "
              R"(string hostname="foobar", string data="2001/09/15-foobar"))",
              results.back());
  }

  {
    // year=2001, month >= 9 && month < 12
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month_ge_lt);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix equality, suffix inequality"));
    ASSERT_EQ(3 * 28 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=9, int8 day=1, "
              R"(string hostname="baz", string data="2001/09/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=11, int8 day=28, "
              R"(string hostname="foobar", string data="2001/11/28-foobar"))",
              results.back());
  }

  {
    // year=2001, month < 9
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    spec.AddPredicate(pred_month_lt);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix equality, suffix inequality"));
    ASSERT_EQ(8 * 28 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=1, int8 day=1, "
              R"(string hostname="baz", string data="2001/01/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2001, int8 month=8, int8 day=28, "
              R"(string hostname="foobar", string data="2001/08/28-foobar"))",
              results.back());
  }
}

TEST_F(CompositePushdownTest, TestPushdownPrefixInequality) {

  int16_t year_2001 = 2001;
  int16_t year_2004 = 2004;
  {
    // year >= 2001 && year < 2004
    auto pred_year = ColumnPredicate::Range(schema_.column(0), &year_2001, &year_2004);
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix inequality"));
    ASSERT_EQ(3 * 12 * 28 * 3, results.size());
    EXPECT_EQ("(int16 year=2001, int8 month=1, int8 day=1, "
              R"(string hostname="baz", string data="2001/01/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2003, int8 month=12, int8 day=28, "
              R"(string hostname="foobar", string data="2003/12/28-foobar"))",
              results.back());
  }

  {
    // year >= 2001
    auto pred_year = ColumnPredicate::Range(schema_.column(0), &year_2001, nullptr);
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix inequality"));
    ASSERT_EQ(10 * 12 * 28 * 3, results.size());
    // Needed because results from memrowset are returned first and memrowset begins
    // with last 10% of the keys (e.g., last few years)
    EXPECT_EQ("(int16 year=2001, int8 month=1, int8 day=1, "
              R"(string hostname="baz", string data="2001/01/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2010, int8 month=12, int8 day=28, "
              R"(string hostname="foobar", string data="2010/12/28-foobar"))",
              results.back());
  }

  {
    // year < 2004
    auto pred_year = ColumnPredicate::Range(schema_.column(0), nullptr, &year_2004);
    ScanSpec spec;
    spec.AddPredicate(pred_year);
    vector<string> results;
    NO_FATALS(ScanTablet(&spec, &results, "Prefix inequality"));
    ASSERT_EQ(4 * 12 * 28 * 3, results.size());
    EXPECT_EQ("(int16 year=2000, int8 month=1, int8 day=1, "
              R"(string hostname="baz", string data="2000/01/01-baz"))",
              results.front());
    EXPECT_EQ("(int16 year=2003, int8 month=12, int8 day=28, "
              R"(string hostname="foobar", string data="2003/12/28-foobar"))",
              results.back());
  }
}
} // namespace tablet
} // namespace kudu

ext: cc

max_stars_repo_name: attilabukor/kudu

max_issues_repo_name: attilabukor/kudu

max_forks_repo_name: attilabukor/kudu


text:
#ifndef SNOWSIM_PLANE_COLLISIONOBJECT_H
#define SNOWSIM_PLANE_COLLISIONOBJECT_H

#include <Eigen/Dense>

#include "collisionObject.hpp"

using namespace Eigen;

namespace SnowSimulator {

class Plane : public CollisionObject {
public:
  Plane(const Vector3f &point, const Vector3f &normal, double friction,
        bool sticky)
      : m_point(point), m_normal(normal.normalized()), m_friction(friction),
        m_sticky(sticky) {
    m_velocity.setZero();
  }

  double phi(const Eigen::Vector3f &x) { return m_normal.dot(x - m_point); }

  Vector3f normal(const Eigen::Vector3f &x) { return m_normal; }

  Vector3f velocity() { return m_velocity; }

  double friction() { return m_friction; }

  bool sticky() { return m_sticky; }

protected:
  Vector3f m_point;
  Vector3f m_normal;

  Vector3f m_velocity;
  double m_friction;

  bool m_sticky;
};

} // namespace SnowSimulator

#endif // SNOWSIM_PLANE_COLLISIONOBJECT_H

max_stars_repo_name: kvchen/snowsim

max_issues_repo_name: kvchen/snowsim

max_forks_repo_name: kvchen/snowsim


text:
// Created by Ryan Elliott on 7/30/20.
//

#ifndef LUDERE_PORTFOLIO_HPP
#define LUDERE_PORTFOLIO_HPP

#include <unordered_map>

#include <boost/function.hpp>

#include <ludere/brokerage_fees.hpp>
#include <ludere/exchange.hpp>
#include <ludere/order_event.hpp>
#include <ludere/filled_order.hpp>
#include <ludere/data_event_subscribable.hpp>
#include <ludere/order.hpp>
#include <ludere/position.hpp>
#include <ludere/uuid.hpp>

namespace lud {

class portfolio : public data_event_subscribable
{
public:
    portfolio(exchange &exchange_, float cash_);

    __attribute__((always_inline))
    void set_brokerage_fees(brokerage_fees brokerage_fees_)
    {
        m_brokerage_fees = brokerage_fees_;
    }

    void handle_buy_order_event_concluded(const std::shared_ptr<order> &order_,
                                          std::shared_ptr<filled_order> &filled_order_);
    void handle_sell_order_event_concluded(const std::shared_ptr<order> &order_,
                                           std::shared_ptr<filled_order> &filled_order_);
    void place_order(std::shared_ptr<order> order_);

    /// Verify a Portfolio has enough capital to perform a trade.
    [[nodiscard]] bool verify_capital(const std::shared_ptr<order> &order_, const float security_price_) const;

    /// Ensures the Portfolio has at least num_shares_ for security_.
    [[nodiscard]] bool verify_num_shares(int num_shares_, const std::string &security_) const;

    /// Ensures the Portfolio is liquid enough for a given cost. Does not natively incorporate brokerage fees.
    [[nodiscard]] bool soft_verify_capital(const float cost_) const
    { return m_liquid_cash >= cost_; }

    [[nodiscard]] bool soft_verify_shares(const std::string &ticker_, const float num_shares_) const
    { return m_holdings.find(ticker_) != m_holdings.end() && m_holdings.at(ticker_).m_num_shares >= num_shares_; }

    void handle_market_data(const lud::candlestick_data_aggregate &data_) override;

    /// Update the Portfolio's balance against the current positions and current market data
    void update_historic(const candlestick_data_aggregate &data_);

    [[nodiscard]] __attribute__((always_inline))
    float net_value() const
    { return m_portfolio_value + m_liquid_cash; }

    void summary() const;

private:
    exchange &m_exchange;
    const float m_starting_capital;
    float m_portfolio_value;
    float m_liquid_cash;
    int m_num_trades;

    brokerage_fees m_brokerage_fees;

    std::unordered_map<std::string, holding> m_holdings;
    std::unordered_map<uuid_hash, strategy_callback_def> m_order_callbacks;
    std::unordered_map<uuid_hash, std::shared_ptr<order>> m_all_orders; // All orders, even cancelled and failures
    std::unordered_map<uuid_hash, std::shared_ptr<filled_order>> m_all_filled_orders;

private:
    void
    handle_order_event_concluded(const std::shared_ptr<order> &order_, std::shared_ptr<filled_order> &filled_order_);
    void add_position(std::shared_ptr<order> order_, std::shared_ptr<filled_order> filled_order_);
};

}

#endif //LUDERE_PORTFOLIO_HPP


text:
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/graph_archetypes.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/concept/assert.hpp>

int main(int,char*[])
{
  using namespace boost;
  // Check adjacency_list with properties
  {
    typedef adjacency_list<vecS, vecS, directedS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      ReadablePropertyGraphConcept<Graph, Vertex, vertex_index_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  {
    typedef adjacency_list<vecS, vecS, bidirectionalS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      ReadablePropertyGraphConcept<Graph, Vertex, vertex_index_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  {
    typedef adjacency_list< listS, listS, directedS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  {
    typedef adjacency_list< listS, listS, undirectedS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  // Checking adjacency_list with EdgeList=setS
  {
    typedef adjacency_list<setS, vecS, bidirectionalS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      ReadablePropertyGraphConcept<Graph, Vertex, vertex_index_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  {
    typedef adjacency_list< setS, listS, directedS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  {
    typedef adjacency_list< setS, listS, undirectedS,
      property<vertex_color_t, int>,
      property<edge_weight_t, int>
    > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Vertex, vertex_color_t> ));
    BOOST_CONCEPT_ASSERT((
      LvaluePropertyGraphConcept<Graph, Edge, edge_weight_t> ));
  }
  // Check adjacency_list without any properties
  {
    typedef adjacency_list<vecS, vecS, directedS > Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      ReadablePropertyGraphConcept<Graph, Vertex, vertex_index_t> ));
  }
  {
    typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT((
      ReadablePropertyGraphConcept<Graph, Vertex, vertex_index_t> ));
  }
  {
    typedef adjacency_list< listS, listS, directedS> Graph;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
  }
  {
    typedef adjacency_list< listS, listS, undirectedS> Graph;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
  }
  // Checking EdgeList=setS with no properties
  {
    typedef adjacency_list<setS, vecS, bidirectionalS> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept<Graph,
      Vertex, vertex_index_t> ));
  }
  {
    typedef adjacency_list< setS, listS, directedS> Graph;
    BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
  }
  {
    typedef adjacency_list< setS, listS, undirectedS> Graph;
    BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept<Graph> ));
    BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept<Graph> ));
  }
  return 0;
}