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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbMultivariateAlterationDetectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class MultivariateAlterationDetector: public Application
{
public:
  /** Standard class typedefs. */
  typedef MultivariateAlterationDetector          Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(MultivariateAlterationDetector, otb::Wrapper::Application);

private:
  MultivariateAlterationDetector()
  {
    SetName("MultivariateAlterationDetector");
    SetDescription("Multivariate Alteration Detector");

    // Documentation
    SetDocName("Multivariate alteration detector");
    SetDocLongDescription("This application detects change between two given images.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine MultivariateAlterationDetector ${OTB-BIN}/bin "
      "--in1 ${OTB-Data}/Input/Spot5-Gloucester-before.tif --in2 ${OTB-Data}/Input/Spot5-Gloucester-after.tif "
      "--out detectedChangeImage.tif ");
    AddDocTag(Tags::FeatureExtraction);
  }

  virtual ~MultivariateAlterationDetector()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in1", "Input Image 1");
    AddParameter(ParameterType_InputImage,  "in2", "Input Image 2");
    AddParameter(ParameterType_OutputImage, "out", "Change Map");
    SetParameterDescription("out","Image of detected changes.");
    AddParameter(ParameterType_RAM, "ram", "Available RAM");
    SetDefaultParameterInt("ram", 256);
    MandatoryOff("ram");
  }

  void DoUpdateParameters()
  {
  }

  void DoExecute()
  {
    typedef otb::MultivariateAlterationDetectorImageFilter<
        FloatVectorImageType,
        FloatVectorImageType> ChangeFilterType;

    ChangeFilterType::Pointer changeFilter = ChangeFilterType::New();

    changeFilter->SetInput1(GetParameterImage("in1"));
    changeFilter->SetInput2(GetParameterImage("in2"));

    m_Ref = changeFilter;

    SetParameterOutputImage("out", changeFilter->GetOutput());
  }

  itk::LightObject::Pointer m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::MultivariateAlterationDetector)
<commit_msg>ENH: update docexample to the new framework for ChangeDetection appli<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbMultivariateAlterationDetectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class MultivariateAlterationDetector: public Application
{
public:
  /** Standard class typedefs. */
  typedef MultivariateAlterationDetector          Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(MultivariateAlterationDetector, otb::Wrapper::Application);

private:
  MultivariateAlterationDetector()
  {
    SetName("MultivariateAlterationDetector");
    SetDescription("Multivariate Alteration Detector");

    // Documentation
    SetDocName("Multivariate alteration detector");
    SetDocLongDescription("This application detects change between two given images.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::FeatureExtraction);
  }

  virtual ~MultivariateAlterationDetector()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in1", "Input Image 1");
    AddParameter(ParameterType_InputImage,  "in2", "Input Image 2");
    AddParameter(ParameterType_OutputImage, "out", "Change Map");
    SetParameterDescription("out","Image of detected changes.");
    AddParameter(ParameterType_RAM, "ram", "Available RAM");
    SetDefaultParameterInt("ram", 256);
    MandatoryOff("ram");

    // Doc example parameter settings
    SetDocExampleParameterValue("in1", "Spot5-Gloucester-before.tif");
    SetDocExampleParameterValue("in2", "Spot5-Gloucester-after.tif");
    SetDocExampleParameterValue("out", "detectedChangeImage.tif");
  }

  void DoUpdateParameters()
  {
  }

  void DoExecute()
  {
    typedef otb::MultivariateAlterationDetectorImageFilter<
        FloatVectorImageType,
        FloatVectorImageType> ChangeFilterType;

    ChangeFilterType::Pointer changeFilter = ChangeFilterType::New();

    changeFilter->SetInput1(GetParameterImage("in1"));
    changeFilter->SetInput2(GetParameterImage("in2"));

    m_Ref = changeFilter;

    SetParameterOutputImage("out", changeFilter->GetOutput());
  }

  itk::LightObject::Pointer m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::MultivariateAlterationDetector)
<|endoftext|>


<commit_before>#include <thread>
#include <condition_variable>
#include <mutex>
#include <sstream>

#include <lcm/lcm-cpp.hpp>
#include <ConciseArgs>

#include <drc_utils/LcmWrapper.hpp>
#include <drc_utils/BotWrapper.hpp>

#include <bot_lcmgl_client/lcmgl.h>

#include <lcmtypes/drc/map_scans_t.hpp>
#include <lcmtypes/drc/affordance_collection_t.hpp>
#include <lcmtypes/drc/block_fit_request_t.hpp>

#include <maps/ScanBundleView.hpp>
#include <maps/LcmTranslator.hpp>

#include <pcl/common/io.h>
#include <pcl/common/transforms.h>

#include "BlockFitter.hpp"

struct State {
  drc::BotWrapper::Ptr mBotWrapper;
  drc::LcmWrapper::Ptr mLcmWrapper;
  bool mRunContinuously;
  bool mDoFilter;
  bool mRemoveGround;
  bool mGrabExactPoses;
  bool mDebug;
  Eigen::Vector3f mBlockSize;
  int mAlgorithm;
  bool mDoTrigger;
  std::string mNamePrefix;
  bool mTriggered;

  drc::map_scans_t mData;
  int64_t mLastDataTime;
  Eigen::Isometry3f mSensorPose;
  Eigen::Isometry3f mGroundPose;

  std::thread mWorkerThread;
  std::condition_variable mCondition;
  std::mutex mProcessMutex;
  std::mutex mDataMutex;

  State() {
    mRunContinuously = false;
    mDoFilter = true;
    mRemoveGround = true;
    mGrabExactPoses = false;
    mDebug = false;
    mAlgorithm = planeseg::BlockFitter::RectangleFitAlgorithm::MinimumArea;
    mBlockSize << 15+3/8.0, 15+5/8.0, 5+5/8.0;
    mBlockSize *=0.0254;
    mDoTrigger = false;
    mNamePrefix = "cinderblock";
    mTriggered = true;
  }

  void start() {
    mLastDataTime = 0;
    mData.utime = 0;
    mLcmWrapper->get()->subscribe("MAP_SCANS", &State::onScans, this);
    mWorkerThread = std::thread(std::ref(*this));
    mLcmWrapper->startHandleThread(true);
  }

  void stop() {
    mLcmWrapper->stopHandleThread();
    if (mWorkerThread.joinable()) mWorkerThread.join();
  }

  void operator()() {
    while (true) {
      // wait for data
      std::unique_lock<std::mutex> lock(mProcessMutex);
      mCondition.wait_for(lock, std::chrono::milliseconds(100));

      // grab data
      drc::map_scans_t data;
      Eigen::Isometry3f sensorPose;
      Eigen::Isometry3f groundPose;
      {
        std::unique_lock<std::mutex> dataLock(mDataMutex);
        if (mData.utime == mLastDataTime) continue;
        data = mData;
        sensorPose = mSensorPose;
        groundPose = mGroundPose;
        mLastDataTime = mData.utime;
      }

      // convert scans to point cloud
      maps::ScanBundleView view;
      maps::LcmTranslator::fromLcm(data, view);
      maps::PointCloud rawCloud, curCloud;
      std::vector<float> allDeltas;
      for (const auto& scan : view.getScans()) {

        // compute range deltas
        int numRanges = scan->getNumRanges();
        std::vector<float> deltas;
        const auto& ranges = scan->getRanges();
        float prevRange = -1;
        int curIndex = 0;
        for (int i = 0; i < numRanges; ++i, ++curIndex) {
          if (ranges[i] <= 0) continue;
          prevRange = ranges[i];
          deltas.push_back(0);
          break;
        }
        for (int i = curIndex+1; i < numRanges; ++i) {
          float range = ranges[i];
          if (range <= 0) continue;
          deltas.push_back(range-prevRange);
          prevRange = range;
        }

        // add this scan to cloud
        scan->get(curCloud, true);
        rawCloud += curCloud;
        allDeltas.insert(allDeltas.end(), deltas.begin(), deltas.end());
      }
      pcl::transformPointCloud
        (rawCloud, rawCloud,
         Eigen::Affine3f(view.getTransform().matrix()).inverse());
      planeseg::LabeledCloud::Ptr cloud(new planeseg::LabeledCloud());
      pcl::copyPointCloud(rawCloud, *cloud);
      /* TODO: change point type
      for (int i = 0; i < (int)cloud->size(); ++i) {
        cloud->points[i].label = 1000*allDeltas[i];
      }
      */

      // remove points outside max radius
      const float kValidRadius = 5;  // meters; TODO: could make this a param
      const float kValidRadius2 = kValidRadius*kValidRadius;
      planeseg::LabeledCloud::Ptr tempCloud(new planeseg::LabeledCloud());
      for (int i = 0; i < (int)cloud->size(); ++i) {
        Eigen::Vector3f p = cloud->points[i].getVector3fMap();
        float dist2 = (p-sensorPose.translation()).squaredNorm();
        if (dist2 > kValidRadius2) continue;
        tempCloud->push_back(cloud->points[i]);
      }
      std::swap(cloud, tempCloud);

      // process
      planeseg::BlockFitter fitter;
      fitter.setSensorPose(sensorPose.translation(),
                           sensorPose.rotation().col(2));
      fitter.setGroundBand(groundPose.translation()[2]-1.0,
                           groundPose.translation()[2]+0.5);
      if (mDoFilter) fitter.setAreaThresholds(0.8, 1.2);
      else fitter.setAreaThresholds(0, 1000);
      fitter.setBlockDimensions(mBlockSize);
      fitter.setRemoveGround(mRemoveGround);
      fitter.setRectangleFitAlgorithm
        ((planeseg::BlockFitter::RectangleFitAlgorithm)mAlgorithm);
      fitter.setDebug(mDebug);
      fitter.setCloud(cloud);
      auto result = fitter.go();
      if (!result.mSuccess) {
        std::cout << "error: could not detect blocks" << std::endl;
        continue;
      }

      //
      // construct json string
      //

      // header
      std::string json;
      json += "{\n";
      json += "  \"command\": \"echo_response\",\n";
      json += "  \"descriptions\": {\n";
      std::string timeString = std::to_string(mBotWrapper->getCurrentTime());

      // blocks
      for (int i = 0; i < (int)result.mBlocks.size(); ++i) {
        const auto& block = result.mBlocks[i];
        std::string dimensionsString, positionString, quaternionString;
        {
          std::ostringstream oss;
          Eigen::Vector3f size = block.mSize;
          oss << size[0] << ", " << size[1] << ", " << size[2];
          dimensionsString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Vector3f p = block.mPose.translation();
          oss << p[0] << ", " << p[1] << ", " << p[2];
          positionString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Quaternionf q(block.mPose.rotation());
          oss << q.w() << ", " << q.x() << ", " << q.y() << ", " << q.z();
          quaternionString = oss.str();
        }
        std::string uuid = timeString + "_" + std::to_string(i+1);

        json += "    \"" + uuid + "\": {\n";
        json += "      \"classname\": \"BoxAffordanceItem\",\n";
        json += "      \"pose\": [[" + positionString + "], [" +
          quaternionString + "]],\n";
        json += "      \"uuid\": \"" + uuid + "\",\n";
        json += "      \"Dimensions\": [" + dimensionsString + "],\n";
        json += "      \"Name\": \"" + mNamePrefix + " " +
          std::to_string(i) + "\"\n";
        json += "    },\n";
      }

      // ground
      {
        std::string positionString, quaternionString;
        Eigen::Vector3f groundNormal = result.mGroundPlane.head<3>();
        {
          std::ostringstream oss;
          Eigen::Vector3f p = groundPose.translation();
          p -= (groundNormal.dot(p)+result.mGroundPlane[3])*groundNormal;
          oss << p[0] << ", " << p[1] << ", " << p[2];
          positionString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Matrix3f rot = Eigen::Matrix3f::Identity();
          rot.col(2) = groundNormal.normalized();
          rot.col(1) = rot.col(2).cross(Eigen::Vector3f::UnitX()).normalized();
          rot.col(0) = rot.col(1).cross(rot.col(2)).normalized();
          Eigen::Quaternionf q(rot);
          oss << q.w() << ", " << q.x() << ", " << q.y() << ", " << q.z();
          quaternionString = oss.str();
        }

        json += "    \"ground affordance\": {\n";
        json += "      \"classname\": \"BoxAffordanceItem\",\n";
        json += "      \"pose\": [[" + positionString + "], [" +
          quaternionString + "]],\n";
        json += "      \"uuid\": \"ground affordance\",\n";
        json += "      \"Dimensions\": [15, 15, 0.01],\n";
        json += "      \"Name\": \"ground affordance\",\n";
        json += "      \"Visible\": 0\n";
        json += "    }\n";
      }

      // footer
      json += "  },\n";
      json += "  \"commandId\": \"" + timeString + "\",\n";
      json += "  \"collectionId\": \"block-fitter\"\n";
      json += "}\n";

      // publish result
      drc::affordance_collection_t msg;
      msg.utime = data.utime;
      msg.name = json;
      msg.naffs = 0;
      mLcmWrapper->get()->publish("AFFORDANCE_COLLECTION_COMMAND", &msg);
      std::cout << "Published affordance collection" << std::endl;

      // publish lcmgl
      if (mDebug) {
        bot_lcmgl_t* lcmgl;
        lcmgl = bot_lcmgl_init(mLcmWrapper->get()->getUnderlyingLCM(),
                              "block-fitter");
        for (const auto& block : result.mBlocks) {
          bot_lcmgl_color3f(lcmgl, 1, 0, 0);
          bot_lcmgl_line_width(lcmgl, 4);
          bot_lcmgl_begin(lcmgl, LCMGL_LINE_LOOP);
          for (const auto& pt : block.mHull) {
            bot_lcmgl_vertex3f(lcmgl, pt[0], pt[1], pt[2]);
          }
          bot_lcmgl_end(lcmgl);
        }

        bot_lcmgl_color3f(lcmgl, 0, 1, 0);
        bot_lcmgl_begin(lcmgl, LCMGL_LINE_LOOP);
        for (const auto& pt : result.mGroundPolygon) {
          bot_lcmgl_vertex3f(lcmgl, pt[0], pt[1], pt[2]);
        }
        bot_lcmgl_end(lcmgl);

        bot_lcmgl_switch_buffer(lcmgl);
        bot_lcmgl_destroy(lcmgl);
      }

      if (!mRunContinuously) break;
    }
    mLcmWrapper->stopHandleThread();
  }

  void onScans(const lcm::ReceiveBuffer* iBuf,
               const std::string& iChannel,
               const drc::map_scans_t* iMessage) {
    std::unique_lock<std::mutex> lock(mDataMutex);
    if (!mTriggered) return;
    mData = *iMessage;
    int64_t scanTime = iMessage->utime;
    int64_t headPoseTime = mBotWrapper->getLatestTime("head", "local");
    int64_t groundPoseTime = mBotWrapper->getLatestTime("ground", "local");
    if ((groundPoseTime == 0) || (headPoseTime == 0) ||
        (mGrabExactPoses && ((std::abs(headPoseTime-scanTime) > 1e6) ||
                             (std::abs(groundPoseTime-scanTime) > 1e6)))) {
      std::cout << "warning: got scans but no valid pose found" << std::endl;
      return;
    }
    mBotWrapper->getTransform("head", "local", mSensorPose, iMessage->utime);
    mBotWrapper->getTransform("ground", "local", mGroundPose, iMessage->utime);
    mCondition.notify_one();
    if (mDoTrigger) mTriggered = false;
  }

  void onTrigger(const lcm::ReceiveBuffer* iBuf, const std::string& iChannel,
                 const drc::block_fit_request_t* iMessage) {
    mNamePrefix = iMessage->name_prefix;
    mBlockSize << iMessage->dimensions[0], iMessage->dimensions[1],
      iMessage->dimensions[2];
    mAlgorithm = iMessage->algorithm;
    mTriggered = true;
    std::cout << "received trigger" << std::endl;
  }
};

int main(const int iArgc, const char** iArgv) {

  std::string sizeString("");
  std::string triggerChannel;
  State state;

  ConciseArgs opt(iArgc, (char**)iArgv);
  opt.add(state.mRunContinuously, "c", "continuous", "run continuously");
  opt.add(state.mDoFilter, "f", "filter", "filter blocks based on size");
  opt.add(sizeString, "s", "blocksize", "prior size for blocks \"x y z\"");
  opt.add(state.mRemoveGround, "g", "remove-ground",
          "whether to remove ground before processing");
  opt.add(state.mAlgorithm, "a", "algorithm",
          "0=min_area, 1=closest_size, 2=closest_hull");
  opt.add(state.mGrabExactPoses, "p", "exact-poses",
          "wait for synchronized poses");
  opt.add(triggerChannel, "t", "trigger-channel",
          "perform block fit only when trigger is received");
  opt.add(state.mDebug, "d", "debug", "debug flag");
  opt.parse();

  if (sizeString.length() > 0) {
    std::istringstream iss(sizeString);
    float x, y, z;
    if (iss >> x) {
      if (iss >> y) {
        if (iss >> z) {
          state.mBlockSize << x,y,z;
          std::cout << "using block size " << state.mBlockSize.transpose() <<
            std::endl;
        }
      }
    }
  }

  state.mBotWrapper.reset(new drc::BotWrapper());
  state.mLcmWrapper.reset(new drc::LcmWrapper(state.mBotWrapper->getLcm()));

  if (triggerChannel.length() > 0) {
    state.mDoTrigger = true;
    state.mTriggered = false;
    state.mLcmWrapper->get()->subscribe(triggerChannel,
                                        &State::onTrigger, &state);
  }

  state.start();
  state.stop();

  return 1;
}
<commit_msg>always do processing upon new trigger<commit_after>#include <thread>
#include <condition_variable>
#include <mutex>
#include <sstream>

#include <lcm/lcm-cpp.hpp>
#include <ConciseArgs>

#include <drc_utils/LcmWrapper.hpp>
#include <drc_utils/BotWrapper.hpp>

#include <bot_lcmgl_client/lcmgl.h>

#include <lcmtypes/drc/map_scans_t.hpp>
#include <lcmtypes/drc/affordance_collection_t.hpp>
#include <lcmtypes/drc/block_fit_request_t.hpp>

#include <maps/ScanBundleView.hpp>
#include <maps/LcmTranslator.hpp>

#include <pcl/common/io.h>
#include <pcl/common/transforms.h>

#include "BlockFitter.hpp"

struct State {
  drc::BotWrapper::Ptr mBotWrapper;
  drc::LcmWrapper::Ptr mLcmWrapper;
  bool mRunContinuously;
  bool mDoFilter;
  bool mRemoveGround;
  bool mGrabExactPoses;
  bool mDebug;
  Eigen::Vector3f mBlockSize;
  int mAlgorithm;
  bool mDoTrigger;
  std::string mNamePrefix;
  bool mTriggered;

  drc::map_scans_t mData;
  int64_t mLastDataTime;
  Eigen::Isometry3f mSensorPose;
  Eigen::Isometry3f mGroundPose;

  std::thread mWorkerThread;
  std::condition_variable mCondition;
  std::mutex mProcessMutex;
  std::mutex mDataMutex;

  State() {
    mRunContinuously = false;
    mDoFilter = true;
    mRemoveGround = true;
    mGrabExactPoses = false;
    mDebug = false;
    mAlgorithm = planeseg::BlockFitter::RectangleFitAlgorithm::MinimumArea;
    mBlockSize << 15+3/8.0, 15+5/8.0, 5+5/8.0;
    mBlockSize *=0.0254;
    mDoTrigger = false;
    mNamePrefix = "cinderblock";
    mTriggered = true;
  }

  void start() {
    mLastDataTime = 0;
    mData.utime = 0;
    mLcmWrapper->get()->subscribe("MAP_SCANS", &State::onScans, this);
    mWorkerThread = std::thread(std::ref(*this));
    mLcmWrapper->startHandleThread(true);
  }

  void stop() {
    mLcmWrapper->stopHandleThread();
    if (mWorkerThread.joinable()) mWorkerThread.join();
  }

  void operator()() {
    while (true) {
      // wait for data
      std::unique_lock<std::mutex> lock(mProcessMutex);
      mCondition.wait_for(lock, std::chrono::milliseconds(100));

      // grab data
      drc::map_scans_t data;
      Eigen::Isometry3f sensorPose;
      Eigen::Isometry3f groundPose;
      {
        std::unique_lock<std::mutex> dataLock(mDataMutex);
        if (mData.utime == mLastDataTime) continue;
        data = mData;
        sensorPose = mSensorPose;
        groundPose = mGroundPose;
        mLastDataTime = mData.utime;
      }

      // convert scans to point cloud
      maps::ScanBundleView view;
      maps::LcmTranslator::fromLcm(data, view);
      maps::PointCloud rawCloud, curCloud;
      std::vector<float> allDeltas;
      for (const auto& scan : view.getScans()) {

        // compute range deltas
        int numRanges = scan->getNumRanges();
        std::vector<float> deltas;
        const auto& ranges = scan->getRanges();
        float prevRange = -1;
        int curIndex = 0;
        for (int i = 0; i < numRanges; ++i, ++curIndex) {
          if (ranges[i] <= 0) continue;
          prevRange = ranges[i];
          deltas.push_back(0);
          break;
        }
        for (int i = curIndex+1; i < numRanges; ++i) {
          float range = ranges[i];
          if (range <= 0) continue;
          deltas.push_back(range-prevRange);
          prevRange = range;
        }

        // add this scan to cloud
        scan->get(curCloud, true);
        rawCloud += curCloud;
        allDeltas.insert(allDeltas.end(), deltas.begin(), deltas.end());
      }
      pcl::transformPointCloud
        (rawCloud, rawCloud,
         Eigen::Affine3f(view.getTransform().matrix()).inverse());
      planeseg::LabeledCloud::Ptr cloud(new planeseg::LabeledCloud());
      pcl::copyPointCloud(rawCloud, *cloud);
      /* TODO: change point type
      for (int i = 0; i < (int)cloud->size(); ++i) {
        cloud->points[i].label = 1000*allDeltas[i];
      }
      */

      // remove points outside max radius
      const float kValidRadius = 5;  // meters; TODO: could make this a param
      const float kValidRadius2 = kValidRadius*kValidRadius;
      planeseg::LabeledCloud::Ptr tempCloud(new planeseg::LabeledCloud());
      for (int i = 0; i < (int)cloud->size(); ++i) {
        Eigen::Vector3f p = cloud->points[i].getVector3fMap();
        float dist2 = (p-sensorPose.translation()).squaredNorm();
        if (dist2 > kValidRadius2) continue;
        tempCloud->push_back(cloud->points[i]);
      }
      std::swap(cloud, tempCloud);

      // process
      planeseg::BlockFitter fitter;
      fitter.setSensorPose(sensorPose.translation(),
                           sensorPose.rotation().col(2));
      fitter.setGroundBand(groundPose.translation()[2]-1.0,
                           groundPose.translation()[2]+0.5);
      if (mDoFilter) fitter.setAreaThresholds(0.8, 1.2);
      else fitter.setAreaThresholds(0, 1000);
      fitter.setBlockDimensions(mBlockSize);
      fitter.setRemoveGround(mRemoveGround);
      fitter.setRectangleFitAlgorithm
        ((planeseg::BlockFitter::RectangleFitAlgorithm)mAlgorithm);
      fitter.setDebug(mDebug);
      fitter.setCloud(cloud);
      auto result = fitter.go();
      if (!result.mSuccess) {
        std::cout << "error: could not detect blocks" << std::endl;
        continue;
      }

      //
      // construct json string
      //

      // header
      std::string json;
      json += "{\n";
      json += "  \"command\": \"echo_response\",\n";
      json += "  \"descriptions\": {\n";
      std::string timeString = std::to_string(mBotWrapper->getCurrentTime());

      // blocks
      for (int i = 0; i < (int)result.mBlocks.size(); ++i) {
        const auto& block = result.mBlocks[i];
        std::string dimensionsString, positionString, quaternionString;
        {
          std::ostringstream oss;
          Eigen::Vector3f size = block.mSize;
          oss << size[0] << ", " << size[1] << ", " << size[2];
          dimensionsString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Vector3f p = block.mPose.translation();
          oss << p[0] << ", " << p[1] << ", " << p[2];
          positionString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Quaternionf q(block.mPose.rotation());
          oss << q.w() << ", " << q.x() << ", " << q.y() << ", " << q.z();
          quaternionString = oss.str();
        }
        std::string uuid = timeString + "_" + std::to_string(i+1);

        json += "    \"" + uuid + "\": {\n";
        json += "      \"classname\": \"BoxAffordanceItem\",\n";
        json += "      \"pose\": [[" + positionString + "], [" +
          quaternionString + "]],\n";
        json += "      \"uuid\": \"" + uuid + "\",\n";
        json += "      \"Dimensions\": [" + dimensionsString + "],\n";
        json += "      \"Name\": \"" + mNamePrefix + " " +
          std::to_string(i) + "\"\n";
        json += "    },\n";
      }

      // ground
      {
        std::string positionString, quaternionString;
        Eigen::Vector3f groundNormal = result.mGroundPlane.head<3>();
        {
          std::ostringstream oss;
          Eigen::Vector3f p = groundPose.translation();
          p -= (groundNormal.dot(p)+result.mGroundPlane[3])*groundNormal;
          oss << p[0] << ", " << p[1] << ", " << p[2];
          positionString = oss.str();
        }
        {
          std::ostringstream oss;
          Eigen::Matrix3f rot = Eigen::Matrix3f::Identity();
          rot.col(2) = groundNormal.normalized();
          rot.col(1) = rot.col(2).cross(Eigen::Vector3f::UnitX()).normalized();
          rot.col(0) = rot.col(1).cross(rot.col(2)).normalized();
          Eigen::Quaternionf q(rot);
          oss << q.w() << ", " << q.x() << ", " << q.y() << ", " << q.z();
          quaternionString = oss.str();
        }

        json += "    \"ground affordance\": {\n";
        json += "      \"classname\": \"BoxAffordanceItem\",\n";
        json += "      \"pose\": [[" + positionString + "], [" +
          quaternionString + "]],\n";
        json += "      \"uuid\": \"ground affordance\",\n";
        json += "      \"Dimensions\": [15, 15, 0.01],\n";
        json += "      \"Name\": \"ground affordance\",\n";
        json += "      \"Visible\": 0\n";
        json += "    }\n";
      }

      // footer
      json += "  },\n";
      json += "  \"commandId\": \"" + timeString + "\",\n";
      json += "  \"collectionId\": \"block-fitter\"\n";
      json += "}\n";

      // publish result
      drc::affordance_collection_t msg;
      msg.utime = data.utime;
      msg.name = json;
      msg.naffs = 0;
      mLcmWrapper->get()->publish("AFFORDANCE_COLLECTION_COMMAND", &msg);
      std::cout << "Published affordance collection" << std::endl;

      // publish lcmgl
      if (mDebug) {
        bot_lcmgl_t* lcmgl;
        lcmgl = bot_lcmgl_init(mLcmWrapper->get()->getUnderlyingLCM(),
                              "block-fitter");
        for (const auto& block : result.mBlocks) {
          bot_lcmgl_color3f(lcmgl, 1, 0, 0);
          bot_lcmgl_line_width(lcmgl, 4);
          bot_lcmgl_begin(lcmgl, LCMGL_LINE_LOOP);
          for (const auto& pt : block.mHull) {
            bot_lcmgl_vertex3f(lcmgl, pt[0], pt[1], pt[2]);
          }
          bot_lcmgl_end(lcmgl);
        }

        bot_lcmgl_color3f(lcmgl, 0, 1, 0);
        bot_lcmgl_begin(lcmgl, LCMGL_LINE_LOOP);
        for (const auto& pt : result.mGroundPolygon) {
          bot_lcmgl_vertex3f(lcmgl, pt[0], pt[1], pt[2]);
        }
        bot_lcmgl_end(lcmgl);

        bot_lcmgl_switch_buffer(lcmgl);
        bot_lcmgl_destroy(lcmgl);
      }

      if (!mRunContinuously) break;
    }
    mLcmWrapper->stopHandleThread();
  }

  void onScans(const lcm::ReceiveBuffer* iBuf,
               const std::string& iChannel,
               const drc::map_scans_t* iMessage) {
    std::unique_lock<std::mutex> lock(mDataMutex);
    if (!mTriggered) return;
    mData = *iMessage;
    int64_t scanTime = iMessage->utime;
    int64_t headPoseTime = mBotWrapper->getLatestTime("head", "local");
    int64_t groundPoseTime = mBotWrapper->getLatestTime("ground", "local");
    if ((groundPoseTime == 0) || (headPoseTime == 0) ||
        (mGrabExactPoses && ((std::abs(headPoseTime-scanTime) > 1e6) ||
                             (std::abs(groundPoseTime-scanTime) > 1e6)))) {
      std::cout << "warning: got scans but no valid pose found" << std::endl;
      return;
    }
    mBotWrapper->getTransform("head", "local", mSensorPose, iMessage->utime);
    mBotWrapper->getTransform("ground", "local", mGroundPose, iMessage->utime);
    mCondition.notify_one();
    if (mDoTrigger) mTriggered = false;
  }

  void onTrigger(const lcm::ReceiveBuffer* iBuf, const std::string& iChannel,
                 const drc::block_fit_request_t* iMessage) {
    mNamePrefix = iMessage->name_prefix;
    mBlockSize << iMessage->dimensions[0], iMessage->dimensions[1],
      iMessage->dimensions[2];
    mAlgorithm = iMessage->algorithm;
    mLastDataTime = 0;  // force processing of new data
    mTriggered = true;
    std::cout << "received trigger" << std::endl;
  }
};

int main(const int iArgc, const char** iArgv) {

  std::string sizeString("");
  std::string triggerChannel;
  State state;

  ConciseArgs opt(iArgc, (char**)iArgv);
  opt.add(state.mRunContinuously, "c", "continuous", "run continuously");
  opt.add(state.mDoFilter, "f", "filter", "filter blocks based on size");
  opt.add(sizeString, "s", "blocksize", "prior size for blocks \"x y z\"");
  opt.add(state.mRemoveGround, "g", "remove-ground",
          "whether to remove ground before processing");
  opt.add(state.mAlgorithm, "a", "algorithm",
          "0=min_area, 1=closest_size, 2=closest_hull");
  opt.add(state.mGrabExactPoses, "p", "exact-poses",
          "wait for synchronized poses");
  opt.add(triggerChannel, "t", "trigger-channel",
          "perform block fit only when trigger is received");
  opt.add(state.mDebug, "d", "debug", "debug flag");
  opt.parse();

  if (sizeString.length() > 0) {
    std::istringstream iss(sizeString);
    float x, y, z;
    if (iss >> x) {
      if (iss >> y) {
        if (iss >> z) {
          state.mBlockSize << x,y,z;
          std::cout << "using block size " << state.mBlockSize.transpose() <<
            std::endl;
        }
      }
    }
  }

  state.mBotWrapper.reset(new drc::BotWrapper());
  state.mLcmWrapper.reset(new drc::LcmWrapper(state.mBotWrapper->getLcm()));

  if (triggerChannel.length() > 0) {
    state.mDoTrigger = true;
    state.mTriggered = false;
    state.mLcmWrapper->get()->subscribe(triggerChannel,
                                        &State::onTrigger, &state);
  }

  state.start();
  state.stop();

  return 1;
}
<|endoftext|>


<commit_before>/*
 * GLRenderSystem_Buffers.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "GLRenderSystem.h"
#include "../CheckedCast.h"
#include "../../Core/Helper.h"
#include "GLTypes.h"
#include "Buffer/GLVertexBuffer.h"
#include "Buffer/GLIndexBuffer.h"
#include "Buffer/GLVertexBufferArray.h"

namespace LLGL
{

/* ----- Buffers ------ */

static GLenum GetGLBufferUsage(long flags)
{
    return ((flags & BufferFlags::DynamicUsage) != 0 ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
}

Buffer* GLRenderSystem::CreateBuffer(const BufferDescriptor& desc, const void* initialData)
{
    /* Create either base of sub-class GLBuffer object */
    switch (desc.type)
    {
        case BufferType::Vertex:
        {
            /* Create vertex buffer and build vertex array */
            auto bufferGL = MakeUnique<GLVertexBuffer>();
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
                bufferGL->BuildVertexArray(desc.vertexBuffer.format);
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
        break;

        case BufferType::Index:
        {
            /* Create index buffer and store index format */
            auto bufferGL = MakeUnique<GLIndexBuffer>(desc.indexBuffer.format);
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
        break;

        default:
        {
            /* Create generic buffer */
            auto bufferGL = MakeUnique<GLBuffer>(desc.type);
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
    }
}

BufferArray* GLRenderSystem::CreateBufferArray(unsigned int numBuffers, Buffer* const * bufferArray)
{
    AssertCreateBufferArray(numBuffers, bufferArray);
    auto type = (*bufferArray)->GetType();

    if (type == BufferType::Vertex)
    {
        /* Create vertex buffer array and build VAO */
        auto vertexBufferArray = MakeUnique<GLVertexBufferArray>();
        vertexBufferArray->BuildVertexArray(numBuffers, bufferArray);
        return TakeOwnership(bufferArrays_, std::move(vertexBufferArray));
    }

    return TakeOwnership(bufferArrays_, MakeUnique<GLBufferArray>(type, numBuffers, bufferArray));
}

void GLRenderSystem::Release(Buffer& buffer)
{
    RemoveFromUniqueSet(buffers_, &buffer);
}

void GLRenderSystem::Release(BufferArray& bufferArray)
{
    RemoveFromUniqueSet(bufferArrays_, &bufferArray);
}

void GLRenderSystem::WriteBuffer(Buffer& buffer, const void* data, std::size_t dataSize, std::size_t offset)
{
    /* Bind and update buffer sub-data */
    auto& bufferGL = LLGL_CAST(GLBuffer&, buffer);
    GLStateManager::active->BindBuffer(bufferGL);
    bufferGL.BufferSubData(data, dataSize, static_cast<GLintptr>(offset));
}

void* GLRenderSystem::MapBuffer(Buffer& buffer, const BufferCPUAccess access)
{
    /* Get, bind, and map buffer */
    auto& bufferGL = LLGL_CAST(GLBuffer&, buffer);
    GLStateManager::active->BindBuffer(bufferGL);
    return bufferGL.MapBuffer(GLTypes::Map(access));
}

void GLRenderSystem::UnmapBuffer(Buffer& buffer)
{
    /* Get, bind, and unmap buffer */
    auto& bufferGL = LLGL_CAST(GLBuffer&, buffer);
    GLStateManager::active->BindBuffer(bufferGL);
    bufferGL.UnmapBuffer();
}

} // /namespace LLGL

// ================================================================================
<commit_msg>Simplified "Write/Map/UnmapBuffer" functions in GL renderer.<commit_after>/*
 * GLRenderSystem_Buffers.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "GLRenderSystem.h"
#include "../CheckedCast.h"
#include "../../Core/Helper.h"
#include "GLTypes.h"
#include "Buffer/GLVertexBuffer.h"
#include "Buffer/GLIndexBuffer.h"
#include "Buffer/GLVertexBufferArray.h"

namespace LLGL
{

/* ----- Buffers ------ */

static GLenum GetGLBufferUsage(long flags)
{
    return ((flags & BufferFlags::DynamicUsage) != 0 ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
}

Buffer* GLRenderSystem::CreateBuffer(const BufferDescriptor& desc, const void* initialData)
{
    /* Create either base of sub-class GLBuffer object */
    switch (desc.type)
    {
        case BufferType::Vertex:
        {
            /* Create vertex buffer and build vertex array */
            auto bufferGL = MakeUnique<GLVertexBuffer>();
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
                bufferGL->BuildVertexArray(desc.vertexBuffer.format);
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
        break;

        case BufferType::Index:
        {
            /* Create index buffer and store index format */
            auto bufferGL = MakeUnique<GLIndexBuffer>(desc.indexBuffer.format);
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
        break;

        default:
        {
            /* Create generic buffer */
            auto bufferGL = MakeUnique<GLBuffer>(desc.type);
            {
                GLStateManager::active->BindBuffer(*bufferGL);
                bufferGL->BufferData(initialData, desc.size, GetGLBufferUsage(desc.flags));
            }
            return TakeOwnership(buffers_, std::move(bufferGL));
        }
    }
}

BufferArray* GLRenderSystem::CreateBufferArray(unsigned int numBuffers, Buffer* const * bufferArray)
{
    AssertCreateBufferArray(numBuffers, bufferArray);
    auto type = (*bufferArray)->GetType();

    if (type == BufferType::Vertex)
    {
        /* Create vertex buffer array and build VAO */
        auto vertexBufferArray = MakeUnique<GLVertexBufferArray>();
        vertexBufferArray->BuildVertexArray(numBuffers, bufferArray);
        return TakeOwnership(bufferArrays_, std::move(vertexBufferArray));
    }

    return TakeOwnership(bufferArrays_, MakeUnique<GLBufferArray>(type, numBuffers, bufferArray));
}

void GLRenderSystem::Release(Buffer& buffer)
{
    RemoveFromUniqueSet(buffers_, &buffer);
}

void GLRenderSystem::Release(BufferArray& bufferArray)
{
    RemoveFromUniqueSet(bufferArrays_, &bufferArray);
}

static GLBuffer& BindAndGetGLBuffer(Buffer& buffer)
{
    auto& bufferGL = LLGL_CAST(GLBuffer&, buffer);
    GLStateManager::active->BindBuffer(bufferGL);
    return bufferGL;
}

void GLRenderSystem::WriteBuffer(Buffer& buffer, const void* data, std::size_t dataSize, std::size_t offset)
{
    /* Bind and update buffer sub-data */
    BindAndGetGLBuffer(buffer).BufferSubData(data, dataSize, static_cast<GLintptr>(offset));
}

void* GLRenderSystem::MapBuffer(Buffer& buffer, const BufferCPUAccess access)
{
    /* Bind and map buffer */
    return BindAndGetGLBuffer(buffer).MapBuffer(GLTypes::Map(access));
}

void GLRenderSystem::UnmapBuffer(Buffer& buffer)
{
    /* Bind and unmap buffer */
    BindAndGetGLBuffer(buffer).UnmapBuffer();
}

} // /namespace LLGL

// ================================================================================
<|endoftext|>


<commit_before>// g++ j.cc -o j -L/usr/local/lib -lroaring
#include <vector>
#include <string>
#include <array>
#include <map>
#include "roaring.hh"

enum FieldType {
  TIMESTAMP,
  DIMENSION,
  BOOL,
  METRIC_INT,
  METRIC_FLOAT
};

class FieldBase {};

template <FieldType, typename T>
class Field : FieldBase {
 private:
  std::string name;
  std::vector<T> vals;
  std::vector< std::vector<T> > mvals;
  std::map<T, Roaring *> dict_;
  Roaring *roar_;
  int count_;
  FieldType type_;
 public:
  Field(std::string name);
  void insert(T &val);
  std::map<std::string, Roaring *> &dict();
  Roaring *roar() {
    return roar_;
  }
};

template <FieldType type, typename T>
Field<type, T>::Field(std::string name):
    type_(type), name(name) {
  switch (type) {
    case METRIC_INT:
    case METRIC_FLOAT: {
    } break;
    default:
      throw std::runtime_error("invalid field type for Field<>");
  }
}

template <>
Field<DIMENSION, std::string>::Field(std::string name):
    type_(DIMENSION), name(name) {
  // switch (type) {
  //   case DIMENSION: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for string");
  // }
}

template <>
Field<TIMESTAMP, int64_t>::Field(std::string name):
    type_(TIMESTAMP), name(name) {
  // switch (type) {
  //   case TIMESTAMP: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for int64");
  // }
}

template <>
Field<BOOL, bool>::Field(std::string name):
    type_(BOOL), name(name) {
  roar_ = new Roaring();
  // switch (type) {
  //   case BOOL: {
  //     roar_ = new Roaring();
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for bool");
  // }
}

template <FieldType type, typename T>
void Field<type, T>::insert(T &val) {
  switch (type_) {
    case TIMESTAMP:
    case METRIC_INT:
    case METRIC_FLOAT: {
      vals.push_back(val);
    } break;
    case DIMENSION: {
      Roaring *roar;
      if (dict_.count(val) > 0) {
        roar = dict_[val];
      } else {
        roar = new Roaring();
        dict_[val] = roar;
      }
      roar->add(count_);
    } break;
    default:
      throw std::runtime_error("can not insert val to field with unknown type");
  }

  count_++;
}

template<>
std::map<std::string, Roaring *> &Field<DIMENSION, std::string>::dict() {
  return dict_;
}

class DimensionField {
 public:
  Field<DIMENSION, std::string> *strdim;
  Field<BOOL, bool> *booldim;
  bool isBoolDim;
  DimensionField(Field<DIMENSION, std::string> *strdim_): strdim(strdim_), isBoolDim(false) {}
  DimensionField(Field<BOOL, bool> *booldim_): booldim(booldim_), isBoolDim(true) {}
};

class Query {
 private:
 public:
  Query();
  ~Query();
};

struct GroupByResult {
  std::vector<std::string> key;
  Roaring roaring;
};

static void genGroups(std::vector<GroupByResult> &groups, std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields, std::vector<std::string> currKey, int index) {
  bool genGroup = index == (groupByKeys.size() - 1);
  std::string key = groupByKeys[index];
  FieldBase *fieldRef = fields[key];
  Field<DIMENSION, std::string> *field = (Field<DIMENSION, std::string> *)fieldRef;
  std::map<std::string, Roaring *> &dict = field->dict();
  for (std::map<std::string, Roaring *>::iterator it = dict.begin(); it != dict.end(); it++) {
    std::vector<std::string> groupKey = currKey;
    groupKey.push_back(it->first);

    if (genGroup) {
      GroupByResult gres;
      gres.key = groupKey;
      groups.push_back(gres);
    } else {
      genGroups(groups, groupByKeys, fields, groupKey, index + 1);
    }
  }
}

std::vector<GroupByResult> genGroupByResult(std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields) {
  std::vector<GroupByResult> groups;
  genGroups(groups, groupByKeys, fields, std::vector<std::string>(), 0);
  return groups;
}

int main(int argc, char *argv[]) {
  Field<TIMESTAMP, int64_t> *timestamp = new Field<TIMESTAMP, int64_t>("timestamp");
  Field<DIMENSION, std::string> *publisher = new Field<DIMENSION, std::string>("publisher");
  Field<DIMENSION, std::string> *advertiser = new Field<DIMENSION, std::string>("advertiser");
  Field<DIMENSION, std::string> *gender = new Field<DIMENSION, std::string>("gender");
  Field<DIMENSION, std::string> *country = new Field<DIMENSION, std::string>("country");
  Field<BOOL, bool> *click = new Field<BOOL, bool>("click");
  Field<METRIC_FLOAT, float> *price = new Field<METRIC_FLOAT, float>("price");
  std::map<std::string, FieldBase*> fields;

  fields["timestamp"] = (FieldBase*)timestamp;
  fields["publisher"] = (FieldBase*)publisher;
  fields["advertiser"] = (FieldBase*)advertiser;
  fields["gender"] = (FieldBase*)gender;
  fields["country"] = (FieldBase*)country;
  fields["click"] = (FieldBase*)click;
  fields["price"] = (FieldBase*)price;

  // select count(*) from logs where click = 1 group by country,gender
  {
    // generate new bitmap of all elements. so we need segment wide count variable
    int count = 3;
    Roaring roar(roaring_bitmap_from_range(0, count, 1));

    //////////////////////////////////////////////////////////////////////
    /////////// FILTERING STATE //////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // do bitwise AND with click = 1
    // roar.printf();
    roar &= click->roar();
    // roar.printf();

    //////////////////////////////////////////////////////////////////////
    /////////// GROUPING STATE ///////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // generate groups for every group by term
    std::vector< GroupByResult > groups;
    std::vector<std::string> groupByKeys;
    groupByKeys.push_back("advertiser");
    groupByKeys.push_back("gender");
    groupByKeys.push_back("country");
  }

  return 0;
}

<commit_msg>log group by keys<commit_after>// g++ j.cc -o j -L/usr/local/lib -lroaring
#include <iostream>
#include <vector>
#include <string>
#include <array>
#include <map>
#include "roaring.hh"

enum FieldType {
  TIMESTAMP,
  DIMENSION,
  BOOL,
  METRIC_INT,
  METRIC_FLOAT
};

class FieldBase {};

template <FieldType, typename T>
class Field : FieldBase {
 private:
  std::string name;
  std::vector<T> vals;
  std::vector< std::vector<T> > mvals;
  std::map<T, Roaring *> dict_;
  Roaring *roar_;
  int count_;
  FieldType type_;
 public:
  Field(std::string name);
  void insert(T &val);
  std::map<std::string, Roaring *> &dict();
  Roaring *roar() {
    return roar_;
  }
};

template <FieldType type, typename T>
Field<type, T>::Field(std::string name):
    type_(type), name(name) {
  switch (type) {
    case METRIC_INT:
    case METRIC_FLOAT: {
    } break;
    default:
      throw std::runtime_error("invalid field type for Field<>");
  }
}

template <>
Field<DIMENSION, std::string>::Field(std::string name):
    type_(DIMENSION), name(name) {
  // switch (type) {
  //   case DIMENSION: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for string");
  // }
}

template <>
Field<TIMESTAMP, int64_t>::Field(std::string name):
    type_(TIMESTAMP), name(name) {
  // switch (type) {
  //   case TIMESTAMP: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for int64");
  // }
}

template <>
Field<BOOL, bool>::Field(std::string name):
    type_(BOOL), name(name) {
  roar_ = new Roaring();
  // switch (type) {
  //   case BOOL: {
  //     roar_ = new Roaring();
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for bool");
  // }
}

template <FieldType type, typename T>
void Field<type, T>::insert(T &val) {
  switch (type_) {
    case TIMESTAMP:
    case METRIC_INT:
    case METRIC_FLOAT: {
      vals.push_back(val);
    } break;
    case DIMENSION: {
      Roaring *roar;
      if (dict_.count(val) > 0) {
        roar = dict_[val];
      } else {
        roar = new Roaring();
        dict_[val] = roar;
      }
      roar->add(count_);
    } break;
    default:
      throw std::runtime_error("can not insert val to field with unknown type");
  }

  count_++;
}

template<>
std::map<std::string, Roaring *> &Field<DIMENSION, std::string>::dict() {
  return dict_;
}

class DimensionField {
 public:
  Field<DIMENSION, std::string> *strdim;
  Field<BOOL, bool> *booldim;
  bool isBoolDim;
  DimensionField(Field<DIMENSION, std::string> *strdim_): strdim(strdim_), isBoolDim(false) {}
  DimensionField(Field<BOOL, bool> *booldim_): booldim(booldim_), isBoolDim(true) {}
};

class Query {
 private:
 public:
  Query();
  ~Query();
};

struct GroupByResult {
  std::vector<std::string> key;
  Roaring roaring;
};

static void genGroups(std::vector<GroupByResult> &groups, std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields, std::vector<std::string> currKey, int index) {
  bool genGroup = index == (groupByKeys.size() - 1);
  std::string key = groupByKeys[index];
  FieldBase *fieldRef = fields[key];
  Field<DIMENSION, std::string> *field = (Field<DIMENSION, std::string> *)fieldRef;
  std::map<std::string, Roaring *> &dict = field->dict();
  for (std::map<std::string, Roaring *>::iterator it = dict.begin(); it != dict.end(); it++) {
    std::vector<std::string> groupKey = currKey;
    groupKey.push_back(it->first);

    if (genGroup) {
      GroupByResult gres;
      gres.key = groupKey;
      groups.push_back(gres);
    } else {
      genGroups(groups, groupByKeys, fields, groupKey, index + 1);
    }
  }
}

std::vector<GroupByResult> genGroupByResult(std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields) {
  std::vector<GroupByResult> groups;
  genGroups(groups, groupByKeys, fields, std::vector<std::string>(), 0);
  return groups;
}

int main(int argc, char *argv[]) {
  Field<TIMESTAMP, int64_t> *timestamp = new Field<TIMESTAMP, int64_t>("timestamp");
  Field<DIMENSION, std::string> *publisher = new Field<DIMENSION, std::string>("publisher");
  Field<DIMENSION, std::string> *advertiser = new Field<DIMENSION, std::string>("advertiser");
  Field<DIMENSION, std::string> *gender = new Field<DIMENSION, std::string>("gender");
  Field<DIMENSION, std::string> *country = new Field<DIMENSION, std::string>("country");
  Field<BOOL, bool> *click = new Field<BOOL, bool>("click");
  Field<METRIC_FLOAT, float> *price = new Field<METRIC_FLOAT, float>("price");
  std::map<std::string, FieldBase*> fields;

  fields["timestamp"] = (FieldBase*)timestamp;
  fields["publisher"] = (FieldBase*)publisher;
  fields["advertiser"] = (FieldBase*)advertiser;
  fields["gender"] = (FieldBase*)gender;
  fields["country"] = (FieldBase*)country;
  fields["click"] = (FieldBase*)click;
  fields["price"] = (FieldBase*)price;

  // select count(*) from logs where click = 1 group by country,gender
  {
    // generate new bitmap of all elements. so we need segment wide count variable
    int count = 3;
    Roaring roar(roaring_bitmap_from_range(0, count, 1));

    //////////////////////////////////////////////////////////////////////
    /////////// FILTERING STATE //////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // do bitwise AND with click = 1
    // roar.printf();
    roar &= click->roar();
    // roar.printf();

    //////////////////////////////////////////////////////////////////////
    /////////// GROUPING STATE ///////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // generate groups for every group by term
    std::vector< GroupByResult > groups;
    std::vector<std::string> groupByKeys;
    groupByKeys.push_back("advertiser");
    groupByKeys.push_back("gender");
    groupByKeys.push_back("country");

    groups = genGroupByResult(groupByKeys, fields);

    for (std::vector< GroupByResult >::iterator it = groups.begin(); it != groups.end(); it++) {
      const GroupByResult &gres = *it;
      std::vector<std::string> key = gres.key;
      for (std::vector<std::string>::iterator it2 = key.begin(); it2 != key.end(); it2++) {
        std::cout << *it2;
        if (it2 != key.end()) {
          std::cout << ", ";
        }
      }
      std::cout << std::endl;
    }
  }

  return 0;
}

<|endoftext|>


<commit_before>#include <iostream>

using namespace std;

int main()
{
	int numEntries = 0;
	cin >> numEntries;
	cin.ignore();

	while (numEntries--)
	{
	}
	return 0;
}
<commit_msg>Shit be broke, yo<commit_after>#include <iostream>
#include <list>

using namespace std;

struct word
{
	int x;
	int y;
	int length;
	string word;

	list<word*> conflicts;
};

int main()
{
	int numEntries = 0;
	cin >> numEntries;
	cin.ignore();

	while (numEntries--)
	{
		int H, V;
		cin >> H >> V;

		map<int, word> horizontal;
		map<int, word> vertical;

		for (int i = 0; i < H; i++)
		{
			int x, y;
			cin >> x >> y;
			horizontal[y].x = x;
			horizontal[y].y = y;
			cin >> horizontal[y].word;
			horizontal[y].length = horizontal[y].word.size();
		}

		for (int i = 0; i < V; i++)
		{
			int x, y;
			cin >> x >> y;
			vertical[x].x = x;
			vertical[x].y = y;
			cin >> vertical[x].word;
			vertical[x].length = vertical[x].word.size();

			for (int y = y; y < vertical[x].y + vertical[x].length; y++)
			{
				if (horizontal.count(y))
				{

				}
			}
		}
	}
	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlTable.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2007-08-03 09:58:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"

#ifndef RPT_XMLTABLE_HXX
#include "xmlTable.hxx"
#endif
#ifndef RPT_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif
#ifndef _REPORT_RPTUIDEF_HXX
#include "RptDef.hxx"
#endif
#ifndef RPT_XMLHELPER_HXX
#include "xmlHelper.hxx"
#endif
#ifndef RPT_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef RPT_XMLCOLUMN_HXX
#include "xmlColumn.hxx"
#endif
#ifndef _COM_SUN_STAR_REPORT_FORCENEWPAGE_HPP_
#include <com/sun/star/report/ForceNewPage.hpp>
#endif
#ifndef RPT_XMLCONDPRTEXPR_HXX
#include "xmlCondPrtExpr.hxx"
#endif
#ifndef RPT_XMLSTYLEIMPORT_HXX
#include "xmlStyleImport.hxx"
#endif
#include "xmlstrings.hrc"
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef REPORTDESIGN_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif
#include <com/sun/star/report/XShape.hpp>
#include <com/sun/star/report/XFixedLine.hpp>

namespace rptxml
{
    using namespace ::rtl;
    using namespace ::xmloff;
    using namespace ::com::sun::star;
    using ::com::sun::star::uno::Reference;
    using namespace ::com::sun::star::xml::sax;
    using ::com::sun::star::xml::sax::XAttributeList;

    sal_uInt16 lcl_getForceNewPageOption(const ::rtl::OUString& _sValue)
    {
        sal_uInt16 nRet = report::ForceNewPage::NONE;
        const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
        SvXMLUnitConverter::convertEnum( nRet,_sValue,aXML_EnumMap );
        return nRet;
    }
DBG_NAME( rpt_OXMLTable )

OXMLTable::OXMLTable( ORptFilter& rImport
                ,sal_uInt16 nPrfx
                ,const OUString& _sLocalName
                ,const Reference< XAttributeList > & _xAttrList
                ,const uno::Reference< report::XSection >& _xSection
                )
:SvXMLImportContext( rImport, nPrfx, _sLocalName )
,m_xSection(_xSection)
,m_nColSpan(1)
,m_nRowSpan(0)
,m_nRowIndex(0)
,m_nColumnIndex(0)
{
    DBG_CTOR( rpt_OXMLTable,NULL);
    OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
    const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
    const SvXMLTokenMap& rTokenMap = rImport.GetSectionElemTokenMap();

    const sal_Int16 nLength = (m_xSection.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
    static const ::rtl::OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
    try
    {
        for(sal_Int16 i = 0; i < nLength; ++i)
        {
            rtl::OUString sLocalName;
            const rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
            const sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
            rtl::OUString sValue = _xAttrList->getValueByIndex( i );

            switch( rTokenMap.Get( nPrefix, sLocalName ) )
            {
                case XML_TOK_VISIBLE:
                    m_xSection->setVisible(sValue == s_sTRUE);
                    break;
                case XML_TOK_FORCE_NEW_PAGE:
                    m_xSection->setForceNewPage(lcl_getForceNewPageOption(sValue));
                    break;
                case XML_TOK_FORCE_NEW_COLUMN:
                    m_xSection->setNewRowOrCol(lcl_getForceNewPageOption(sValue));
                    break;
                case XML_TOK_KEEP_TOGETHER:
                    m_xSection->setKeepTogether(sValue == s_sTRUE);
                    break;

                case XML_TOK_SECTION_NAME:
                    m_xSection->setName(sValue);
                    break;
                case XML_TOK_SECT_STYLE_NAME:
                    m_sStyleName = sValue;
                    break;
                default:
                    break;
            }
        }
    }
    catch(Exception&)
    {
        OSL_ENSURE(0,"Exception catched while filling the section props");
    }
}
// -----------------------------------------------------------------------------
OXMLTable::~OXMLTable()
{
    DBG_DTOR( rpt_OXMLTable,NULL);
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLTable::CreateChildContext(
        sal_uInt16 _nPrefix,
        const OUString& _rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    ORptFilter& rImport = GetOwnImport();
    const SvXMLTokenMap&    rTokenMap   = rImport.GetColumnTokenMap();
    Reference<XMultiServiceFactory> xFactor = rImport.getServiceFactory();

    switch( rTokenMap.Get( _nPrefix, _rLocalName ) )
    {
        case XML_TOK_TABLE_COLUMNS:
        case XML_TOK_TABLE_ROWS:
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList ,this);
            break;
        case XML_TOK_ROW:
            incrementRowIndex();
            rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
            break;
        case XML_TOK_COLUMN:
            rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
            break;
        default:
                break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( rImport, _nPrefix, _rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ORptFilter& OXMLTable::GetOwnImport()
{
    return static_cast<ORptFilter&>(GetImport());
}
// -----------------------------------------------------------------------------
void OXMLTable::EndElement()
{
    try
    {
        if ( m_xSection.is() )
        {
            if ( m_sStyleName.getLength() )
            {
                const SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
                if ( pAutoStyles )
                {
                    XMLPropStyleContext* pAutoStyle = PTR_CAST(XMLPropStyleContext,pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_TABLE,m_sStyleName));
                    if ( pAutoStyle )
                    {
                        pAutoStyle->FillPropertySet(m_xSection.get());
                    }
                }
            } // if ( m_sStyleName.getLength() )
            // set height
            ::std::vector<sal_Int32>::iterator aIter = m_aHeight.begin();
            ::std::vector<sal_Int32>::iterator aEnd = m_aHeight.end();
            sal_Int32 nHeight = 0;
            for (; aIter != aEnd; ++aIter)
                nHeight += *aIter;
            m_xSection->setHeight( nHeight );
            // set positions, widths, and heights
            sal_Int32 nLeftMargin = rptui::getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
            sal_Int32 nPosY = 0;
            ::std::vector< ::std::vector<TCell> >::iterator aRowIter = m_aGrid.begin();
            ::std::vector< ::std::vector<TCell> >::iterator aRowEnd = m_aGrid.end();
            for (sal_Int32 i = 0; aRowIter != aRowEnd; ++aRowIter,++i)
            {
                sal_Int32 nPosX = nLeftMargin;
                ::std::vector<TCell>::iterator aColIter = (*aRowIter).begin();
                ::std::vector<TCell>::iterator aColEnd = (*aRowIter).end();
                for (sal_Int32 j = 0; aColIter != aColEnd; ++aColIter,++j)
                {
                    TCell& rCell = *aColIter;
                    if ( !rCell.xElements.empty())
                    {
                        ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellIter = rCell.xElements.begin();
                        const ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellEnd = rCell.xElements.end();
                        for (;aCellIter != aCellEnd ; ++aCellIter)
                        {
                            uno::Reference<report::XShape> xShape(*aCellIter,uno::UNO_QUERY);
                            if ( xShape.is() )
                            {
                                xShape->setPositionX(xShape->getPositionX() + nLeftMargin);
                            }
                            else
                            {
                                sal_Int32 nWidth = rCell.nWidth;
                                sal_Int32 nColSpan = rCell.nColSpan;
                                if ( nColSpan > 1 )
                                {
                                    ::std::vector<TCell>::iterator aWidthIter = aColIter + 1;
                                    while ( nColSpan > 1 )
                                    {
                                        nWidth += (aWidthIter++)->nWidth;
                                        --nColSpan;
                                    }
                                }
                                nHeight = rCell.nHeight;
                                sal_Int32 nRowSpan = rCell.nRowSpan;
                                if ( nRowSpan > 1 )
                                {
                                    ::std::vector< ::std::vector<TCell> >::iterator aHeightIter = aRowIter + 1;
                                    while( nRowSpan > 1)
                                    {
                                        nHeight += (*aHeightIter)[j].nHeight;
                                        ++aHeightIter;
                                        --nRowSpan;
                                    }
                                }
                                Reference<XFixedLine> xFixedLine(*aCellIter,uno::UNO_QUERY);
                                if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
                                {
                                    OSL_ENSURE(static_cast<sal_uInt32>(j+1) < m_aWidth.size(),"Illegal pos of col iter. There should be an empty cell for the next line part.");
                                    nWidth += m_aWidth[j+1];

                                }
                                try
                                {
                                    (*aCellIter)->setSize(awt::Size(nWidth,nHeight));
                                    (*aCellIter)->setPosition(awt::Point(nPosX,nPosY));
                                }
                                catch(beans::PropertyVetoException)
                                {
                                    OSL_ENSURE(0,"Could set the correct positions!");
                                }
                            }
                        }
                    }
                    nPosX += m_aWidth[j];
                }
                nPosY += m_aHeight[i];
            }
        } // if ( m_xComponent.is() )
    }
    catch(Exception&)
    {
        OSL_ENSURE(0,"OXMLTable::EndElement -> exception catched");
    }
}
// -----------------------------------------------------------------------------
void OXMLTable::addCell(const Reference<XReportComponent>& _xElement)
{
    uno::Reference<report::XShape> xShape(_xElement,uno::UNO_QUERY);
    OSL_ENSURE(static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size(),
        "OXMLTable::addCell: Invalid column and row index");
    if ( static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size() )
    {
        TCell& rCell = m_aGrid[m_nRowIndex-1][m_nColumnIndex-1];
        if ( _xElement.is() )
            rCell.xElements.push_back( _xElement );
        if ( !xShape.is() )
        {
            rCell.nWidth   = m_aWidth[m_nColumnIndex-1];
            rCell.nHeight  = m_aHeight[m_nRowIndex-1];
            rCell.nColSpan = m_nColSpan;
            rCell.nRowSpan = m_nRowSpan;
        }
    }

    if ( !xShape.is() )
        m_nColSpan = m_nRowSpan = 1;
}
// -----------------------------------------------------------------------------
void OXMLTable::incrementRowIndex()
{
    ++m_nRowIndex;
    m_nColumnIndex = 0;
    m_aGrid.push_back(::std::vector<TCell>(m_aWidth.size()));
}
//----------------------------------------------------------------------------
} // namespace rptxml
// -----------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS dba24a (1.2.10); FILE MERGED 2007/08/13 05:36:13 oj 1.2.10.2: RESYNC: (1.2-1.3); FILE MERGED 2007/08/08 11:24:56 oj 1.2.10.1: #i80308# remove using rtl<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlTable.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-26 14:24:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"

#ifndef RPT_XMLTABLE_HXX
#include "xmlTable.hxx"
#endif
#ifndef RPT_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif
#ifndef _REPORT_RPTUIDEF_HXX
#include "RptDef.hxx"
#endif
#ifndef RPT_XMLHELPER_HXX
#include "xmlHelper.hxx"
#endif
#ifndef RPT_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef RPT_XMLCOLUMN_HXX
#include "xmlColumn.hxx"
#endif
#ifndef _COM_SUN_STAR_REPORT_FORCENEWPAGE_HPP_
#include <com/sun/star/report/ForceNewPage.hpp>
#endif
#ifndef RPT_XMLCONDPRTEXPR_HXX
#include "xmlCondPrtExpr.hxx"
#endif
#ifndef RPT_XMLSTYLEIMPORT_HXX
#include "xmlStyleImport.hxx"
#endif
#include "xmlstrings.hrc"
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef REPORTDESIGN_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif
#include <com/sun/star/report/XShape.hpp>
#include <com/sun/star/report/XFixedLine.hpp>

namespace rptxml
{
    using namespace ::xmloff;
    using namespace ::com::sun::star;
    using ::com::sun::star::uno::Reference;
    using namespace ::com::sun::star::xml::sax;
    using ::com::sun::star::xml::sax::XAttributeList;

    sal_uInt16 lcl_getForceNewPageOption(const ::rtl::OUString& _sValue)
    {
        sal_uInt16 nRet = report::ForceNewPage::NONE;
        const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
        SvXMLUnitConverter::convertEnum( nRet,_sValue,aXML_EnumMap );
        return nRet;
    }
DBG_NAME( rpt_OXMLTable )

OXMLTable::OXMLTable( ORptFilter& rImport
                ,sal_uInt16 nPrfx
                ,const ::rtl::OUString& _sLocalName
                ,const Reference< XAttributeList > & _xAttrList
                ,const uno::Reference< report::XSection >& _xSection
                )
:SvXMLImportContext( rImport, nPrfx, _sLocalName )
,m_xSection(_xSection)
,m_nColSpan(1)
,m_nRowSpan(0)
,m_nRowIndex(0)
,m_nColumnIndex(0)
{
    DBG_CTOR( rpt_OXMLTable,NULL);
    OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
    const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
    const SvXMLTokenMap& rTokenMap = rImport.GetSectionElemTokenMap();

    const sal_Int16 nLength = (m_xSection.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
    static const ::rtl::OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
    try
    {
        for(sal_Int16 i = 0; i < nLength; ++i)
        {
            rtl::OUString sLocalName;
            const rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
            const sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
            rtl::OUString sValue = _xAttrList->getValueByIndex( i );

            switch( rTokenMap.Get( nPrefix, sLocalName ) )
            {
                case XML_TOK_VISIBLE:
                    m_xSection->setVisible(sValue == s_sTRUE);
                    break;
                case XML_TOK_FORCE_NEW_PAGE:
                    m_xSection->setForceNewPage(lcl_getForceNewPageOption(sValue));
                    break;
                case XML_TOK_FORCE_NEW_COLUMN:
                    m_xSection->setNewRowOrCol(lcl_getForceNewPageOption(sValue));
                    break;
                case XML_TOK_KEEP_TOGETHER:
                    m_xSection->setKeepTogether(sValue == s_sTRUE);
                    break;

                case XML_TOK_SECTION_NAME:
                    m_xSection->setName(sValue);
                    break;
                case XML_TOK_SECT_STYLE_NAME:
                    m_sStyleName = sValue;
                    break;
                default:
                    break;
            }
        }
    }
    catch(Exception&)
    {
        OSL_ENSURE(0,"Exception catched while filling the section props");
    }
}
// -----------------------------------------------------------------------------
OXMLTable::~OXMLTable()
{
    DBG_DTOR( rpt_OXMLTable,NULL);
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLTable::CreateChildContext(
        sal_uInt16 _nPrefix,
        const ::rtl::OUString& _rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    ORptFilter& rImport = GetOwnImport();
    const SvXMLTokenMap&    rTokenMap   = rImport.GetColumnTokenMap();
    Reference<XMultiServiceFactory> xFactor = rImport.getServiceFactory();

    switch( rTokenMap.Get( _nPrefix, _rLocalName ) )
    {
        case XML_TOK_TABLE_COLUMNS:
        case XML_TOK_TABLE_ROWS:
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList ,this);
            break;
        case XML_TOK_ROW:
            incrementRowIndex();
            rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
            break;
        case XML_TOK_COLUMN:
            rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
            break;
        default:
                break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( rImport, _nPrefix, _rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ORptFilter& OXMLTable::GetOwnImport()
{
    return static_cast<ORptFilter&>(GetImport());
}
// -----------------------------------------------------------------------------
void OXMLTable::EndElement()
{
    try
    {
        if ( m_xSection.is() )
        {
            if ( m_sStyleName.getLength() )
            {
                const SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
                if ( pAutoStyles )
                {
                    XMLPropStyleContext* pAutoStyle = PTR_CAST(XMLPropStyleContext,pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_TABLE,m_sStyleName));
                    if ( pAutoStyle )
                    {
                        pAutoStyle->FillPropertySet(m_xSection.get());
                    }
                }
            } // if ( m_sStyleName.getLength() )
            // set height
            ::std::vector<sal_Int32>::iterator aIter = m_aHeight.begin();
            ::std::vector<sal_Int32>::iterator aEnd = m_aHeight.end();
            sal_Int32 nHeight = 0;
            for (; aIter != aEnd; ++aIter)
                nHeight += *aIter;
            m_xSection->setHeight( nHeight );
            // set positions, widths, and heights
            sal_Int32 nLeftMargin = rptui::getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
            sal_Int32 nPosY = 0;
            ::std::vector< ::std::vector<TCell> >::iterator aRowIter = m_aGrid.begin();
            ::std::vector< ::std::vector<TCell> >::iterator aRowEnd = m_aGrid.end();
            for (sal_Int32 i = 0; aRowIter != aRowEnd; ++aRowIter,++i)
            {
                sal_Int32 nPosX = nLeftMargin;
                ::std::vector<TCell>::iterator aColIter = (*aRowIter).begin();
                ::std::vector<TCell>::iterator aColEnd = (*aRowIter).end();
                for (sal_Int32 j = 0; aColIter != aColEnd; ++aColIter,++j)
                {
                    TCell& rCell = *aColIter;
                    if ( !rCell.xElements.empty())
                    {
                        ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellIter = rCell.xElements.begin();
                        const ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellEnd = rCell.xElements.end();
                        for (;aCellIter != aCellEnd ; ++aCellIter)
                        {
                            uno::Reference<report::XShape> xShape(*aCellIter,uno::UNO_QUERY);
                            if ( xShape.is() )
                            {
                                xShape->setPositionX(xShape->getPositionX() + nLeftMargin);
                            }
                            else
                            {
                                sal_Int32 nWidth = rCell.nWidth;
                                sal_Int32 nColSpan = rCell.nColSpan;
                                if ( nColSpan > 1 )
                                {
                                    ::std::vector<TCell>::iterator aWidthIter = aColIter + 1;
                                    while ( nColSpan > 1 )
                                    {
                                        nWidth += (aWidthIter++)->nWidth;
                                        --nColSpan;
                                    }
                                }
                                nHeight = rCell.nHeight;
                                sal_Int32 nRowSpan = rCell.nRowSpan;
                                if ( nRowSpan > 1 )
                                {
                                    ::std::vector< ::std::vector<TCell> >::iterator aHeightIter = aRowIter + 1;
                                    while( nRowSpan > 1)
                                    {
                                        nHeight += (*aHeightIter)[j].nHeight;
                                        ++aHeightIter;
                                        --nRowSpan;
                                    }
                                }
                                Reference<XFixedLine> xFixedLine(*aCellIter,uno::UNO_QUERY);
                                if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
                                {
                                    OSL_ENSURE(static_cast<sal_uInt32>(j+1) < m_aWidth.size(),"Illegal pos of col iter. There should be an empty cell for the next line part.");
                                    nWidth += m_aWidth[j+1];

                                }
                                try
                                {
                                    (*aCellIter)->setSize(awt::Size(nWidth,nHeight));
                                    (*aCellIter)->setPosition(awt::Point(nPosX,nPosY));
                                }
                                catch(beans::PropertyVetoException)
                                {
                                    OSL_ENSURE(0,"Could set the correct positions!");
                                }
                            }
                        }
                    }
                    nPosX += m_aWidth[j];
                }
                nPosY += m_aHeight[i];
            }
        } // if ( m_xComponent.is() )
    }
    catch(Exception&)
    {
        OSL_ENSURE(0,"OXMLTable::EndElement -> exception catched");
    }
}
// -----------------------------------------------------------------------------
void OXMLTable::addCell(const Reference<XReportComponent>& _xElement)
{
    uno::Reference<report::XShape> xShape(_xElement,uno::UNO_QUERY);
    OSL_ENSURE(static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size(),
        "OXMLTable::addCell: Invalid column and row index");
    if ( static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size() )
    {
        TCell& rCell = m_aGrid[m_nRowIndex-1][m_nColumnIndex-1];
        if ( _xElement.is() )
            rCell.xElements.push_back( _xElement );
        if ( !xShape.is() )
        {
            rCell.nWidth   = m_aWidth[m_nColumnIndex-1];
            rCell.nHeight  = m_aHeight[m_nRowIndex-1];
            rCell.nColSpan = m_nColSpan;
            rCell.nRowSpan = m_nRowSpan;
        }
    }

    if ( !xShape.is() )
        m_nColSpan = m_nRowSpan = 1;
}
// -----------------------------------------------------------------------------
void OXMLTable::incrementRowIndex()
{
    ++m_nRowIndex;
    m_nColumnIndex = 0;
    m_aGrid.push_back(::std::vector<TCell>(m_aWidth.size()));
}
//----------------------------------------------------------------------------
} // namespace rptxml
// -----------------------------------------------------------------------------
<|endoftext|>