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

#include "gcs_fast_transfers.h"
#include <boost/program_options.hpp>
#include <fmt/format.h>
#include <google/cloud/storage/client.h>
#include <cstdint>
#include <cstdlib>
#include <future>
#include <iostream>
#include <numeric>
#include <string>
#include <thread>
// Posix headers last.
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

namespace {
namespace po = boost::program_options;
namespace gcs = google::cloud::storage;
po::variables_map parse_command_line(int argc, char* argv[]);
int check_system_call(std::string const& name, int result);

std::vector<std::int64_t> compute_slices(std::int64_t object_size,
                                         po::variables_map const& vm) {
  auto const minimum_slice_size = vm["minimum-slice-size"].as<std::int64_t>();
  auto const thread_count = vm["thread-count"].as<int>();

  std::vector<std::int64_t> result;
  auto const thread_slice = object_size / thread_count;
  if (thread_slice >= minimum_slice_size) {
    std::fill_n(std::back_inserter(result), thread_count, thread_slice);
    // If the object size is not a multiple of the thread count we may need
    // to spread any excess bytes across the slices.
    auto loc = result.rbegin();
    for (auto e = object_size % thread_count; e != 0; --e, ++loc) ++(*loc);
    return result;
  }
  for (; object_size > 0; object_size -= minimum_slice_size) {
    result.push_back(std::min(minimum_slice_size, object_size));
  }
  return result;
}

std::string task(std::int64_t offset, std::int64_t length,
                 std::string const& bucket, std::string const& object, int fd) {
  auto client = gcs::Client::CreateDefaultClient().value();
  auto is = client.ReadObject(bucket, object,
                              gcs::ReadRange(offset, offset + length));

  std::vector<char> buffer(1024 * 1024L);
  std::int64_t count = 0;
  std::int64_t write_offset = offset;
  do {
    is.read(buffer.data(), buffer.size());
    if (is.bad()) break;
    count += is.gcount();
    check_system_call("pwrite()",
                      ::pwrite(fd, buffer.data(), is.gcount(), write_offset));
    write_offset += is.gcount();
  } while (not is.eof());
  return fmt::format("Download range [{}, {}] got {}/{} bytes", offset,
                     offset + length, count, length);
}

using ::gcs_fast_transfers::file_info;
using ::gcs_fast_transfers::format_size;
using ::gcs_fast_transfers::kMiB;

}  // namespace

int main(int argc, char* argv[]) try {
  auto vm = parse_command_line(argc, argv);
  auto const bucket = vm["bucket"].as<std::string>();
  auto const object = vm["object"].as<std::string>();
  auto const destination = vm["destination"].as<std::string>();

  auto client = gcs::Client::CreateDefaultClient().value();
  auto metadata = client.GetObjectMetadata(bucket, object).value();

  auto slices = compute_slices(metadata.size(), vm);

  std::cout << "Downloading " << object << " from bucket " << bucket
            << " to file " << destination << "\n";
  std::cout << "This object size is approximately "
            << format_size(metadata.size()) << ". It will be downloaded in "
            << slices.size() << " slices." << std::endl;

  auto const start = std::chrono::steady_clock::now();
  auto constexpr kOpenFlags = O_CREAT | O_TRUNC | O_WRONLY;
  auto constexpr kOpenMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
  auto const fd = check_system_call(
      "open()", ::open(destination.c_str(), kOpenFlags, kOpenMode));

  std::vector<std::future<std::string>> tasks(slices.size());
  std::int64_t offset = 0;
  std::transform(slices.begin(), slices.end(), tasks.begin(), [&](auto length) {
    auto f = std::async(std::launch::async, task, offset, length, bucket,
                        object, fd);
    offset += length;
    return f;
  });

  for (auto& t : tasks) std::cout << t.get() << "\n";
  check_system_call("close(fd)", ::close(fd));

  auto const end = std::chrono::steady_clock::now();
  auto const elapsed_us =
      std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  auto const elapsed_ms =
      std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
  auto const effective_bandwidth_MiBs =
      (static_cast<double>(metadata.size()) / kMiB) /
      (elapsed_us.count() / 1'000'000.0);
  std::cout << "Download completed in " << elapsed_ms.count() << "ms\n"
            << "Effective bandwidth " << effective_bandwidth_MiBs << " MiB/s\n";

  auto [size, crc32c] = file_info(destination);
  if (size != metadata.size()) {
    std::cout << "Downloaded file size mismatch, expected=" << metadata.size()
              << ", got=" << size << std::endl;
    return 1;
  }

  if (crc32c != metadata.crc32c()) {
    std::cout << "Download file CRC32C mismatch, expected=" << metadata.crc32c()
              << ", got=" << crc32c << std::endl;
    return 1;
  }

  std::cout << "File size and CRC32C match expected values" << std::endl;

  return 0;
} catch (std::exception const& ex) {
  std::cerr << "Standard C++ exception thrown: " << ex.what() << std::endl;
  return 1;
} catch (...) {
  std::cerr << "Unknown C++ exception thrown" << std::endl;
  return 1;
}

namespace {
char const* kPositional[] = {"bucket", "object", "destination"};

[[noreturn]] void usage(std::string const& argv0,
                        po::options_description const& desc,
                        std::string const& message = {}) {
  auto exit_status = EXIT_SUCCESS;
  if (not message.empty()) {
    exit_status = EXIT_FAILURE;
    std::cout << "Error: " << message << "\n";
  }

  // format positional args
  auto const positional_names =
      std::accumulate(std::begin(kPositional), std::end(kPositional),
                      std::string{" [options]"}, [](auto a, auto const& b) {
                        a += ' ';
                        a += b;
                        return a;
                      });

  // print usage + options help, and exit normally
  std::cout << "usage: " << argv0 << positional_names << "\n\n" << desc << "\n";
  std::exit(exit_status);
}

po::variables_map parse_command_line(int argc, char* argv[]) {
  auto const default_minimum_slice_size = 64 * 1024 * 1024L;
  auto const default_thread_count = [] {
    auto constexpr kFallbackThreadCount = 2;
    auto constexpr kThreadsPerCore = 2;
    auto const count = std::thread::hardware_concurrency();
    if (count == 0) return kFallbackThreadCount;
    return static_cast<int>(count * kThreadsPerCore);
  }();

  po::positional_options_description positional;
  for (auto const* name : kPositional) positional.add(name, 1);
  po::options_description desc(
      "Download a single GCS object using multiple slices");
  desc.add_options()("help", "produce help message")
      //
      ("bucket", po::value<std::string>()->required(),
       "set the GCS bucket to download from")
      //
      ("object", po::value<std::string>()->required(),
       "set the GCS object to download")
      //
      ("destination", po::value<std::string>()->required(),
       "set the destination file to download into")
      //
      ("thread-count", po::value<int>()->default_value(default_thread_count),
       "number of parallel streams for the download")
      //
      ("minimum-slice-size",
       po::value<std::int64_t>()->default_value(default_minimum_slice_size),
       "minimum slice size");

  // parse the input into the map
  po::variables_map vm;

  // run notify() for all registered options in the map
  try {
    po::parsed_options parsed = po::command_line_parser(argc, argv)
                                    .options(desc)
                                    .positional(positional)
                                    .run();
    po::store(parsed, vm);
    po::notify(vm);
  } catch (std::exception const& ex) {
    // if required arguments are missing but help is desired, just print help
    if (vm.count("help") > 0 or argc == 1) usage(argv[0], desc);
    usage(argv[0], desc, ex.what());
  }

  if (vm.count("help") != 0) usage(argv[0], desc);

  for (std::string opt : kPositional) {
    if (not vm[opt].as<std::string>().empty()) continue;
    usage(argv[0], desc, fmt::format("the {} argument cannot be empty", opt));
  }

  if (vm["thread-count"].as<int>() == 0) {
    usage(argv[0], desc, "the --thread-count option cannot be zero");
  }
  if (vm["minimum-slice-size"].as<std::int64_t>() == 0) {
    usage(argv[0], desc, "the --minimum-slice-size option cannot be zero");
  }

  return vm;
}

int check_system_call(std::string const& name, int result) {
  if (result >= 0) return result;
  auto err = errno;
  throw std::runtime_error(
      fmt::format("Error in {}() - return value={}, error=[{}] {}", name,
                  result, err, strerror(err)));
}

}  // namespace
<commit_msg>cleanup: make the code easier to explain (#130)<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "gcs_fast_transfers.h"
#include <boost/program_options.hpp>
#include <fmt/format.h>
#include <google/cloud/storage/client.h>
#include <cstdint>
#include <cstdlib>
#include <future>
#include <iostream>
#include <numeric>
#include <string>
#include <thread>
// Posix headers last.
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

namespace {
namespace po = boost::program_options;
namespace gcs = google::cloud::storage;
po::variables_map parse_command_line(int argc, char* argv[]);
int check_system_call(std::string const& name, int result);

std::vector<std::int64_t> compute_slices(std::int64_t object_size,
                                         po::variables_map const& vm) {
  auto const minimum_slice_size = vm["minimum-slice-size"].as<std::int64_t>();
  auto const thread_count = vm["thread-count"].as<int>();

  std::vector<std::int64_t> result;
  auto const thread_slice = object_size / thread_count;
  if (thread_slice >= minimum_slice_size) {
    std::fill_n(std::back_inserter(result), thread_count, thread_slice);
    // If the object size is not a multiple of the thread count we may need
    // to add any excess bytes to the last slice.
    result.back() += object_size % thread_count;
    return result;
  }
  for (; object_size > 0; object_size -= minimum_slice_size) {
    result.push_back(std::min(minimum_slice_size, object_size));
  }
  return result;
}

std::string task(std::int64_t offset, std::int64_t length,
                 std::string const& bucket, std::string const& object, int fd) {
  auto client = gcs::Client::CreateDefaultClient().value();
  auto is = client.ReadObject(bucket, object,
                              gcs::ReadRange(offset, offset + length));

  std::vector<char> buffer(1024 * 1024L);
  std::int64_t count = 0;
  std::int64_t write_offset = offset;
  do {
    is.read(buffer.data(), buffer.size());
    if (is.bad()) break;
    count += is.gcount();
    check_system_call("pwrite()",
                      ::pwrite(fd, buffer.data(), is.gcount(), write_offset));
    write_offset += is.gcount();
  } while (not is.eof());
  return fmt::format("Download range [{}, {}] got {}/{} bytes", offset,
                     offset + length, count, length);
}

using ::gcs_fast_transfers::file_info;
using ::gcs_fast_transfers::format_size;
using ::gcs_fast_transfers::kMiB;

}  // namespace

int main(int argc, char* argv[]) try {
  auto vm = parse_command_line(argc, argv);
  auto const bucket = vm["bucket"].as<std::string>();
  auto const object = vm["object"].as<std::string>();
  auto const destination = vm["destination"].as<std::string>();

  auto client = gcs::Client::CreateDefaultClient().value();
  auto metadata = client.GetObjectMetadata(bucket, object).value();

  auto slices = compute_slices(metadata.size(), vm);

  std::cout << "Downloading " << object << " from bucket " << bucket
            << " to file " << destination << "\n";
  std::cout << "This object size is approximately "
            << format_size(metadata.size()) << ". It will be downloaded in "
            << slices.size() << " slices." << std::endl;

  auto const start = std::chrono::steady_clock::now();
  auto constexpr kOpenFlags = O_CREAT | O_TRUNC | O_WRONLY;
  auto constexpr kOpenMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
  auto const fd = check_system_call(
      "open()", ::open(destination.c_str(), kOpenFlags, kOpenMode));

  std::vector<std::future<std::string>> tasks(slices.size());
  std::int64_t offset = 0;
  std::transform(slices.begin(), slices.end(), tasks.begin(), [&](auto length) {
    auto f = std::async(std::launch::async, task, offset, length, bucket,
                        object, fd);
    offset += length;
    return f;
  });

  for (auto& t : tasks) std::cout << t.get() << "\n";
  check_system_call("close(fd)", ::close(fd));

  auto const end = std::chrono::steady_clock::now();
  auto const elapsed_us =
      std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  auto const elapsed_ms =
      std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
  auto const effective_bandwidth_MiBs =
      (static_cast<double>(metadata.size()) / kMiB) /
      (elapsed_us.count() / 1'000'000.0);
  std::cout << "Download completed in " << elapsed_ms.count() << "ms\n"
            << "Effective bandwidth " << effective_bandwidth_MiBs << " MiB/s\n";

  auto [size, crc32c] = file_info(destination);
  if (size != metadata.size()) {
    std::cout << "Downloaded file size mismatch, expected=" << metadata.size()
              << ", got=" << size << std::endl;
    return 1;
  }

  if (crc32c != metadata.crc32c()) {
    std::cout << "Download file CRC32C mismatch, expected=" << metadata.crc32c()
              << ", got=" << crc32c << std::endl;
    return 1;
  }

  std::cout << "File size and CRC32C match expected values" << std::endl;

  return 0;
} catch (std::exception const& ex) {
  std::cerr << "Standard C++ exception thrown: " << ex.what() << std::endl;
  return 1;
} catch (...) {
  std::cerr << "Unknown C++ exception thrown" << std::endl;
  return 1;
}

namespace {
char const* kPositional[] = {"bucket", "object", "destination"};

[[noreturn]] void usage(std::string const& argv0,
                        po::options_description const& desc,
                        std::string const& message = {}) {
  auto exit_status = EXIT_SUCCESS;
  if (not message.empty()) {
    exit_status = EXIT_FAILURE;
    std::cout << "Error: " << message << "\n";
  }

  // format positional args
  auto const positional_names =
      std::accumulate(std::begin(kPositional), std::end(kPositional),
                      std::string{" [options]"}, [](auto a, auto const& b) {
                        a += ' ';
                        a += b;
                        return a;
                      });

  // print usage + options help, and exit normally
  std::cout << "usage: " << argv0 << positional_names << "\n\n" << desc << "\n";
  std::exit(exit_status);
}

po::variables_map parse_command_line(int argc, char* argv[]) {
  auto const default_minimum_slice_size = 64 * 1024 * 1024L;
  auto const default_thread_count = [] {
    auto constexpr kFallbackThreadCount = 2;
    auto constexpr kThreadsPerCore = 2;
    auto const count = std::thread::hardware_concurrency();
    if (count == 0) return kFallbackThreadCount;
    return static_cast<int>(count * kThreadsPerCore);
  }();

  po::positional_options_description positional;
  for (auto const* name : kPositional) positional.add(name, 1);
  po::options_description desc(
      "Download a single GCS object using multiple slices");
  desc.add_options()("help", "produce help message")
      //
      ("bucket", po::value<std::string>()->required(),
       "set the GCS bucket to download from")
      //
      ("object", po::value<std::string>()->required(),
       "set the GCS object to download")
      //
      ("destination", po::value<std::string>()->required(),
       "set the destination file to download into")
      //
      ("thread-count", po::value<int>()->default_value(default_thread_count),
       "number of parallel streams for the download")
      //
      ("minimum-slice-size",
       po::value<std::int64_t>()->default_value(default_minimum_slice_size),
       "minimum slice size");

  // parse the input into the map
  po::variables_map vm;

  // run notify() for all registered options in the map
  try {
    po::parsed_options parsed = po::command_line_parser(argc, argv)
                                    .options(desc)
                                    .positional(positional)
                                    .run();
    po::store(parsed, vm);
    po::notify(vm);
  } catch (std::exception const& ex) {
    // if required arguments are missing but help is desired, just print help
    if (vm.count("help") > 0 or argc == 1) usage(argv[0], desc);
    usage(argv[0], desc, ex.what());
  }

  if (vm.count("help") != 0) usage(argv[0], desc);

  for (std::string opt : kPositional) {
    if (not vm[opt].as<std::string>().empty()) continue;
    usage(argv[0], desc, fmt::format("the {} argument cannot be empty", opt));
  }

  if (vm["thread-count"].as<int>() == 0) {
    usage(argv[0], desc, "the --thread-count option cannot be zero");
  }
  if (vm["minimum-slice-size"].as<std::int64_t>() == 0) {
    usage(argv[0], desc, "the --minimum-slice-size option cannot be zero");
  }

  return vm;
}

int check_system_call(std::string const& name, int result) {
  if (result >= 0) return result;
  auto err = errno;
  throw std::runtime_error(
      fmt::format("Error in {}() - return value={}, error=[{}] {}", name,
                  result, err, strerror(err)));
}

}  // namespace
<|endoftext|>


<commit_before><commit_msg>Bugfix: added missing `#include` line.<commit_after><|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TGeoBBox.h>

#include "AliEMCALGeometry.h"
#include "AliEveEMCALSModuleData.h"

class TClonesArray;
class TGeoNode;
class TGeoMatrix;
class TVector2;
class AliEveEventManager;

ClassImp(AliEveEMCALSModuleData)

Float_t AliEveEMCALSModuleData::fgSModuleBigBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleBigBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleBigBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleSmallBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleDCalBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleDCalBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleDCalBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox2 = 0.;

//Float_t AliEveEMCALSModuleData::fgSModuleCenter0 = 0.;
//Float_t AliEveEMCALSModuleData::fgSModuleCenter1 = 0.;
//Float_t AliEveEMCALSModuleData::fgSModuleCenter2 = 0.;

//
// Constructor
//
//______________________________________________________________________________
AliEveEMCALSModuleData::AliEveEMCALSModuleData(Int_t sm,AliEMCALGeometry* geom, TGeoNode* node, TGeoHMatrix* m) :
  TObject(),
  fGeom(geom),
  fNode(node),
  fSmId(sm),
  fNsm(0),
  fNDigits(0),
  fNClusters(0),
  fNHits(0),
  fPhiTileSize(0), fEtaTileSize(0),
  fHitArray(0),
  fDigitArray(0),
  fClusterArray(0),
  fMatrix(0),
  fHMatrix(m)
{
  Init(sm);
}

///
/// Copy constructor
///
//______________________________________________________________________________
  AliEveEMCALSModuleData::AliEveEMCALSModuleData(const AliEveEMCALSModuleData &esmdata) :
  TObject(),
  fGeom(esmdata.fGeom),
  fNode(esmdata.fNode),
  fSmId(esmdata.fSmId),
  fNsm(esmdata.fNsm),
  fNDigits(esmdata.fNDigits),
  fNClusters(esmdata.fNClusters),
  fNHits(esmdata.fNHits),
  fPhiTileSize(esmdata.fPhiTileSize), fEtaTileSize(esmdata.fEtaTileSize),
  fHitArray(esmdata.fHitArray),
  fDigitArray(esmdata.fDigitArray),
  fClusterArray(esmdata.fClusterArray),
  fMatrix(esmdata.fMatrix),
  fHMatrix(esmdata.fHMatrix)
{
  Init(esmdata.fNsm);
}

///
/// Destructor
///
//______________________________________________________________________________
AliEveEMCALSModuleData::~AliEveEMCALSModuleData()
{
  if(!fHitArray.empty())
    fHitArray.clear();

  if(!fDigitArray.empty())
    fDigitArray.clear();

  if(!fClusterArray.empty())
    fClusterArray.clear();
}

///
/// Release the SM data
///
//______________________________________________________________________________
void AliEveEMCALSModuleData::DropData()
{
  fNDigits   = 0;
  fNClusters = 0;
  fNHits     = 0;

  if(!fHitArray.empty())
    fHitArray.clear();

  if(!fDigitArray.empty())
    fDigitArray.clear();

  if(!fClusterArray.empty())
    fClusterArray.clear();

  return;
}

///
/// Initialize parameters
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::Init(Int_t sm)
{
  fNsm         = fGeom->GetNumberOfSuperModules();
  fPhiTileSize = fGeom->GetPhiTileSize();
  fEtaTileSize = fGeom->GetPhiTileSize();

  TGeoBBox* bbbox  = (TGeoBBox*) fNode->GetDaughter(0) ->GetVolume()->GetShape();
  TGeoBBox* sbbox  = (TGeoBBox*) fNode->GetDaughter(10)->GetVolume()->GetShape();
  TGeoBBox* dbbox  = (TGeoBBox*) fNode->GetDaughter(12)->GetVolume()->GetShape();
  TGeoBBox* dsbbox = (TGeoBBox*) fNode->GetDaughter(18)->GetVolume()->GetShape();

  fMatrix = (TGeoMatrix*) fNode->GetDaughter(sm)->GetMatrix();

  if(sm < 10)
  {
    fgSModuleBigBox0 = bbbox->GetDX();
    fgSModuleBigBox1 = bbbox->GetDY();
    fgSModuleBigBox2 = bbbox->GetDZ();
  }
  else if(sm < 12)
  {
    fgSModuleSmallBox0 = sbbox->GetDX();
    fgSModuleSmallBox1 = sbbox->GetDY();
    fgSModuleSmallBox2 = sbbox->GetDZ();
  }
  else if(sm < 18)
  {
    fgSModuleDCalBox0 = dbbox->GetDX();
    fgSModuleDCalBox1 = dbbox->GetDY();
    fgSModuleDCalBox2 = dbbox->GetDZ();
  }
  else if(sm < 20)
  {
    fgSModuleSmallDBox0 = dsbbox->GetDX();
    fgSModuleSmallDBox1 = dsbbox->GetDY();
    fgSModuleSmallDBox2 = dsbbox->GetDZ();
  }
}

///
/// Add a digit to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterDigit(Int_t AbsId, Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Double_t> bufDig(6);
  bufDig[0] = AbsId;
  bufDig[1] = isupMod;
  bufDig[2] = iamp;
  bufDig[3] = ix;
  bufDig[4] = iy;
  bufDig[5] = iz;

  fDigitArray.push_back(bufDig);

  fNDigits++;
}

///
/// Add a hit to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterHit(Int_t AbsId, Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Float_t> bufHit(6);
  bufHit[0] = AbsId;
  bufHit[1] = isupMod;
  bufHit[2] = iamp;
  bufHit[3] = ix;
  bufHit[4] = iy;
  bufHit[5] = iz;

  fHitArray.push_back(bufHit);

  fNHits++;
}

///
/// Add a cluster to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterCluster(Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Double_t> bufClu(5);
  bufClu[0] = isupMod;
  bufClu[1] = iamp;
  bufClu[2] = ix;
  bufClu[3] = iy;
  bufClu[4] = iz;

  fClusterArray.push_back(bufClu);

  fNClusters++;
}
<commit_msg>forgot ClassImp doxy condition<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TGeoBBox.h>

#include "AliEMCALGeometry.h"
#include "AliEveEMCALSModuleData.h"

class TClonesArray;
class TGeoNode;
class TGeoMatrix;
class TVector2;
class AliEveEventManager;

/// \cond CLASSIMP
ClassImp(AliEveEMCALSModuleData) ;
/// \endcond

Float_t AliEveEMCALSModuleData::fgSModuleBigBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleBigBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleBigBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleSmallBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleDCalBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleDCalBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleDCalBox2 = 0.;

Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox0 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox1 = 0.;
Float_t AliEveEMCALSModuleData::fgSModuleSmallDBox2 = 0.;

//Float_t AliEveEMCALSModuleData::fgSModuleCenter0 = 0.;
//Float_t AliEveEMCALSModuleData::fgSModuleCenter1 = 0.;
//Float_t AliEveEMCALSModuleData::fgSModuleCenter2 = 0.;

//
// Constructor
//
//______________________________________________________________________________
AliEveEMCALSModuleData::AliEveEMCALSModuleData(Int_t sm,AliEMCALGeometry* geom, TGeoNode* node, TGeoHMatrix* m) :
  TObject(),
  fGeom(geom),
  fNode(node),
  fSmId(sm),
  fNsm(0),
  fNDigits(0),
  fNClusters(0),
  fNHits(0),
  fPhiTileSize(0), fEtaTileSize(0),
  fHitArray(0),
  fDigitArray(0),
  fClusterArray(0),
  fMatrix(0),
  fHMatrix(m)
{
  Init(sm);
}

///
/// Copy constructor
///
//______________________________________________________________________________
  AliEveEMCALSModuleData::AliEveEMCALSModuleData(const AliEveEMCALSModuleData &esmdata) :
  TObject(),
  fGeom(esmdata.fGeom),
  fNode(esmdata.fNode),
  fSmId(esmdata.fSmId),
  fNsm(esmdata.fNsm),
  fNDigits(esmdata.fNDigits),
  fNClusters(esmdata.fNClusters),
  fNHits(esmdata.fNHits),
  fPhiTileSize(esmdata.fPhiTileSize), fEtaTileSize(esmdata.fEtaTileSize),
  fHitArray(esmdata.fHitArray),
  fDigitArray(esmdata.fDigitArray),
  fClusterArray(esmdata.fClusterArray),
  fMatrix(esmdata.fMatrix),
  fHMatrix(esmdata.fHMatrix)
{
  Init(esmdata.fNsm);
}

///
/// Destructor
///
//______________________________________________________________________________
AliEveEMCALSModuleData::~AliEveEMCALSModuleData()
{
  if(!fHitArray.empty())
    fHitArray.clear();

  if(!fDigitArray.empty())
    fDigitArray.clear();

  if(!fClusterArray.empty())
    fClusterArray.clear();
}

///
/// Release the SM data
///
//______________________________________________________________________________
void AliEveEMCALSModuleData::DropData()
{
  fNDigits   = 0;
  fNClusters = 0;
  fNHits     = 0;

  if(!fHitArray.empty())
    fHitArray.clear();

  if(!fDigitArray.empty())
    fDigitArray.clear();

  if(!fClusterArray.empty())
    fClusterArray.clear();

  return;
}

///
/// Initialize parameters
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::Init(Int_t sm)
{
  fNsm         = fGeom->GetNumberOfSuperModules();
  fPhiTileSize = fGeom->GetPhiTileSize();
  fEtaTileSize = fGeom->GetPhiTileSize();

  TGeoBBox* bbbox  = (TGeoBBox*) fNode->GetDaughter(0) ->GetVolume()->GetShape();
  TGeoBBox* sbbox  = (TGeoBBox*) fNode->GetDaughter(10)->GetVolume()->GetShape();
  TGeoBBox* dbbox  = (TGeoBBox*) fNode->GetDaughter(12)->GetVolume()->GetShape();
  TGeoBBox* dsbbox = (TGeoBBox*) fNode->GetDaughter(18)->GetVolume()->GetShape();

  fMatrix = (TGeoMatrix*) fNode->GetDaughter(sm)->GetMatrix();

  if(sm < 10)
  {
    fgSModuleBigBox0 = bbbox->GetDX();
    fgSModuleBigBox1 = bbbox->GetDY();
    fgSModuleBigBox2 = bbbox->GetDZ();
  }
  else if(sm < 12)
  {
    fgSModuleSmallBox0 = sbbox->GetDX();
    fgSModuleSmallBox1 = sbbox->GetDY();
    fgSModuleSmallBox2 = sbbox->GetDZ();
  }
  else if(sm < 18)
  {
    fgSModuleDCalBox0 = dbbox->GetDX();
    fgSModuleDCalBox1 = dbbox->GetDY();
    fgSModuleDCalBox2 = dbbox->GetDZ();
  }
  else if(sm < 20)
  {
    fgSModuleSmallDBox0 = dsbbox->GetDX();
    fgSModuleSmallDBox1 = dsbbox->GetDY();
    fgSModuleSmallDBox2 = dsbbox->GetDZ();
  }
}

///
/// Add a digit to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterDigit(Int_t AbsId, Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Double_t> bufDig(6);
  bufDig[0] = AbsId;
  bufDig[1] = isupMod;
  bufDig[2] = iamp;
  bufDig[3] = ix;
  bufDig[4] = iy;
  bufDig[5] = iz;

  fDigitArray.push_back(bufDig);

  fNDigits++;
}

///
/// Add a hit to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterHit(Int_t AbsId, Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Float_t> bufHit(6);
  bufHit[0] = AbsId;
  bufHit[1] = isupMod;
  bufHit[2] = iamp;
  bufHit[3] = ix;
  bufHit[4] = iy;
  bufHit[5] = iz;

  fHitArray.push_back(bufHit);

  fNHits++;
}

///
/// Add a cluster to this SM
///
// ______________________________________________________________________________
void AliEveEMCALSModuleData::RegisterCluster(Int_t isupMod, Double_t iamp, Double_t ix, Double_t iy, Double_t iz)
{
  std::vector<Double_t> bufClu(5);
  bufClu[0] = isupMod;
  bufClu[1] = iamp;
  bufClu[2] = ix;
  bufClu[3] = iy;
  bufClu[4] = iz;

  fClusterArray.push_back(bufClu);

  fNClusters++;
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(k)

class Solution {
public:
    string removeDuplicateLetters(string s) {
        unordered_map<char, int> cnts;
        for (const auto& c : s) {
            ++cnts[c];
        }

        string res;
        unordered_set<char> visited;
        stack<char> stk;
        for (int i = 0; i < s.size(); --cnts[s[i]], ++i) {
            if (!visited.count(s[i]) && (stk.empty() || stk.top() != s[i])) {
                while (!stk.empty() && stk.top() >= s[i] && cnts[stk.top()] > 0) {
                    visited.erase(stk.top());
                    stk.pop();
                }
                stk.emplace(s[i]);
                visited.emplace(s[i]);
            }
        }
        while (!stk.empty()) {
            res.push_back(stk.top());
            stk.pop();
        }
        reverse(res.begin(), res.end());
        return res;
    }
};
<commit_msg>Update remove-duplicate-letters.cpp<commit_after>// Time:  O(n)
// Space: O(k), k is size of the alphabet

class Solution {
public:
    string removeDuplicateLetters(string s) {
        unordered_map<char, int> cnts;
        for (const auto& c : s) {
            ++cnts[c];
        }

        string res;
        unordered_set<char> visited;
        stack<char> stk;
        for (int i = 0; i < s.size(); --cnts[s[i]], ++i) {
            if (!visited.count(s[i]) && (stk.empty() || stk.top() != s[i])) {
                while (!stk.empty() && stk.top() >= s[i] && cnts[stk.top()] > 0) {
                    visited.erase(stk.top());
                    stk.pop();
                }
                stk.emplace(s[i]);
                visited.emplace(s[i]);
            }
        }
        while (!stk.empty()) {
            res.push_back(stk.top());
            stk.pop();
        }
        reverse(res.begin(), res.end());
        return res;
    }
};
<|endoftext|>


<commit_before>//
//  HiveMindi.cpp
//
//  OpenFrameworks code for the Hive Mind neuro art performance
//
//  Created by Sean Montgomery on 10/06/17.
//
//  This work is licensed under the MIT License
//

#include "HiveMind.h"

HiveMind::HiveMind(int tcpPort)
{
	_openBci.setTcpPort(tcpPort);
	//_openBci.enableDataLogging(ofToDataPath(ofGetTimestampString("%Y-%m-%d-%H-%M-%S") + ".log"));

	_nHeadsets = 2;

	_eegChannels = {	// Headset x Channels
		{4},
		{4}
	};

	_eegBands = {		// Bands x Frequencies
		{4, 7},
		{8, 15},
		{16, 31}
	};

	_eegData.resize(_nHeadsets);
	_eegBandData.resize(_nHeadsets);
	_eegBaselineBandData.resize(_nHeadsets);
	for (int h = 0; h < _nHeadsets; h++)
	{
		_eegBandData.at(h).resize(_eegChannels.at(h).size());
		_eegBaselineBandData.at(h).resize(_eegChannels.at(h).size());
		for (int ch = 0; ch < _eegChannels.at(h).size(); ch++)
		{
			_eegBandData.at(h).at(ch).resize(_eegBands.size());
			_eegBaselineBandData.at(h).at(ch).resize(_eegBands.size());
		}
	}

	_maxNormBandValue.resize(_nHeadsets);

	_dominantBand1 = -1;
	_dominantBand2 = -1;

	_dataReset = false;
	_dataIsReset = false;

	_smoothingWeight = 0.052f;	//1- 10^(log10(0.2) / (2*15))
	_baselineWeight = 0.0026f;	//1- 10^(log10(0.2) / (2*60*5))

	_fftDelay.resize(_nHeadsets);
	for (int h = 0; h < _nHeadsets; h++)
	{
		_lastFftMillis.push_back(ofGetElapsedTimeMillis());
		_fftDelay.at(h) = -1;
	}
}

HiveMind::~HiveMind() {
	// Stop the thread if it's still running
	waitForThread(true);
}

void HiveMind::setEegChannels(int headset, vector<int> channels)
{
	if (headset < _nHeadsets)
	{
		_eegChannels.at(headset) = channels;
	}
}

void HiveMind::setEegBands(vector<vector<float>> eegBands)
{
	_eegBands = eegBands;
}

void HiveMind::threadedFunction()
{
	while (isThreadRunning()) {

		_openBci.update();

		lock();
		vector<string> ipAddresses = _openBci.getHeadsetIpAddresses();
		for (int h = 0; h < ipAddresses.size() && h < _nHeadsets; h++)
		{
			//cout << _openBci.getStringData(ipAddresses.at(h));
			// ToDo: buffer _eegData
			//_eegData.at(h) = _openBci.getData(ipAddresses.at(h));
			vector<vector<float>> tempData = _openBci.getData(ipAddresses.at(h));
			if (_eegData.at(h).size() < tempData.size())
			{
				_eegData.at(h).resize(tempData.size());
			}
			for (int ch = 0; ch < tempData.size(); ch++)
			{
				for (int n = 0; n < tempData.at(ch).size(); n++)
				{
					// ToDo: Make this less horribly inefficient
					_eegData.at(h).at(ch).push_back(tempData.at(ch).at(n));
				}
			}

			vector<vector<float>> tempFftData;
			vector<int> tempDominantBand;
			tempDominantBand.resize(_nHeadsets);
			if (_openBci.isFftNew(ipAddresses.at(h)))
			{
				tempFftData = _openBci.getLatestFft(ipAddresses.at(h));

				_maxNormBandValue.at(h) = -1;
				tempDominantBand.at(h) = -1;
				if (_dataReset)
				{
					_dataIsReset = true;
				}
				for (int b = 0; b < _eegBands.size(); b++)
				{
					for (int ch = 0; ch < _eegChannels.at(h).size(); ch++)
					{
						int f1 = _openBci.getFftBinFromFrequency(_eegBands.at(b).at(0));
						int f2 = _openBci.getFftBinFromFrequency(_eegBands.at(b).at(1));

						float sum = 0;
						for (int f = f1; f <= f2; f++)
						{
							sum = sum + tempFftData.at(ch).at(f);
						}
						float avg = sum / (1.f + f2 - f1);

						// ToDo: Deal with averaging across channels
						if (_dataReset)
						{
							_eegBandData.at(h).at(ch).at(b) = avg;
							_eegBaselineBandData.at(h).at(ch).at(b) = avg;
						}
						else
						{
							_eegBandData.at(h).at(ch).at(b) =
								ofxOpenBciWifi::smooth(avg, _eegBandData.at(h).at(ch).at(b), _smoothingWeight);
							_eegBaselineBandData.at(h).at(ch).at(b) =
								ofxOpenBciWifi::smooth(avg, _eegBaselineBandData.at(h).at(ch).at(b), _baselineWeight);
						}
						float normalizedData = _eegBandData.at(h).at(ch).at(b) / _eegBaselineBandData.at(h).at(ch).at(b);
						if (normalizedData > _maxNormBandValue.at(h))
						{
							_maxNormBandValue.at(h) = normalizedData;
							tempDominantBand.at(h) = b;
						}
					}
				}

				if (h == 0)
				{
					_dominantBand1 = tempDominantBand.at(h);
				}
				if (h == 1)
				{
					_dominantBand2 = tempDominantBand.at(h);
				}

				_fftDelay.at(h) = ofGetElapsedTimeMillis() - _lastFftMillis.at(h);
				_lastFftMillis.at(h) = ofGetElapsedTimeMillis();
				if (_fftDelay.size() > 1)
				{
					_fftDelay1 = _fftDelay.at(0);
					_fftDelay2 = _fftDelay.at(1);
				}
			}
		}

		if (_dataIsReset)
		{
			_dataReset = false;
		}

		unlock();
		sleep(1);
	}
}

float HiveMind::getFftDelay(int headset)
{
	if (headset == 0)
	{
		return _fftDelay1;
	}
	if (headset == 1)
	{
		return _fftDelay2;
	}
	return -1;
}

int HiveMind::getDominantBand(int headset)
{
	if (headset == 0)
	{
		return _dominantBand1;
	}
	if (headset == 1)
	{
		return _dominantBand2;
	}
	return -1;
}

int HiveMind::getFrameCount(int headset, int frameRate)
{
	if (frameRate == 60)
	{
		if (getDominantBand(headset) == 0)	return 4; // Theta
		if (getDominantBand(headset) == 1)	return 2; // Alpha
		if (getDominantBand(headset) == 2)	return 1; // Beta
	}
}

vector<float> HiveMind::getEegBandData(int headset)
{
	lock();
	vector<float> temp = _eegBandData.at(headset).at(0);
	unlock();
	return temp;
}

vector<float> HiveMind::getEegBaselineBandData(int headset)
{
	lock();
	vector<float> temp = _eegBaselineBandData.at(headset).at(0);
	unlock();
	return temp;
}

void HiveMind::resetBandData()
{
	_dataReset = true;
	_dataIsReset = false;
}

vector<vector<float>> HiveMind::getData(int headset)
{
	// ToDo: clear _eegData buffer
	vector<vector<float>> returnData;
	lock();
	returnData = _eegData.at(headset);
	_eegData.at(headset).clear();
	unlock();
	return returnData;
}

vector<vector<float>> HiveMind::getData(string ipAddress)
{
	// ToDo: clear _eegData buffer
	vector<vector<float>> returnData;
	lock();
	vector<string> ipAddresses = _openBci.getHeadsetIpAddresses();
	for (int h = 0; h < ipAddresses.size(); h++)
	{
		if (ipAddress.compare(ipAddresses.at(h)) == 0)
		{
			returnData = _eegData.at(h);
			_eegData.at(h).clear();
		}
	}
	unlock();
	return returnData;
}

void HiveMind::setTcpPort(int port)
{
	_openBci.setTcpPort(port);
}

//vector<vector<int>> goodEegChannels;
//
//void threadedFunction();
//
//public:
//
//	HiveMind();
//	~HiveMind();
//
//	int getDominantBand(int headset);<commit_msg>Added LP filter enabled<commit_after>//
//  HiveMindi.cpp
//
//  OpenFrameworks code for the Hive Mind neuro art performance
//
//  Created by Sean Montgomery on 10/06/17.
//
//  This work is licensed under the MIT License
//

#include "HiveMind.h"

HiveMind::HiveMind(int tcpPort)
{
	_openBci.setTcpPort(tcpPort);
	//_openBci.enableDataLogging(ofToDataPath(ofGetTimestampString("%Y-%m-%d-%H-%M-%S") + ".log"));

	_openBci.enableLPFilter(30);

	_nHeadsets = 2;

	_eegChannels = {	// Headset x Channels
		{4},
		{4}
	};

	_eegBands = {		// Bands x Frequencies
		{4, 7},
		{8, 15},
		{16, 31}
	};

	_eegData.resize(_nHeadsets);
	_eegBandData.resize(_nHeadsets);
	_eegBaselineBandData.resize(_nHeadsets);
	for (int h = 0; h < _nHeadsets; h++)
	{
		_eegBandData.at(h).resize(_eegChannels.at(h).size());
		_eegBaselineBandData.at(h).resize(_eegChannels.at(h).size());
		for (int ch = 0; ch < _eegChannels.at(h).size(); ch++)
		{
			_eegBandData.at(h).at(ch).resize(_eegBands.size());
			_eegBaselineBandData.at(h).at(ch).resize(_eegBands.size());
		}
	}

	_maxNormBandValue.resize(_nHeadsets);

	_dominantBand1 = -1;
	_dominantBand2 = -1;

	_dataReset = false;
	_dataIsReset = false;

	_smoothingWeight = 0.052f;	//1- 10^(log10(0.2) / (2*15))
	_baselineWeight = 0.0026f;	//1- 10^(log10(0.2) / (2*60*5))

	_fftDelay.resize(_nHeadsets);
	for (int h = 0; h < _nHeadsets; h++)
	{
		_lastFftMillis.push_back(ofGetElapsedTimeMillis());
		_fftDelay.at(h) = -1;
	}
}

HiveMind::~HiveMind() {
	// Stop the thread if it's still running
	waitForThread(true);
}

void HiveMind::setEegChannels(int headset, vector<int> channels)
{
	if (headset < _nHeadsets)
	{
		_eegChannels.at(headset) = channels;
	}
}

void HiveMind::setEegBands(vector<vector<float>> eegBands)
{
	_eegBands = eegBands;
}

void HiveMind::threadedFunction()
{
	while (isThreadRunning()) {

		_openBci.update();

		lock();
		vector<string> ipAddresses = _openBci.getHeadsetIpAddresses();
		for (int h = 0; h < ipAddresses.size() && h < _nHeadsets; h++)
		{
			//cout << _openBci.getStringData(ipAddresses.at(h));
			// ToDo: buffer _eegData
			//_eegData.at(h) = _openBci.getData(ipAddresses.at(h));
			vector<vector<float>> tempData = _openBci.getData(ipAddresses.at(h));
			if (_eegData.at(h).size() < tempData.size())
			{
				_eegData.at(h).resize(tempData.size());
			}
			for (int ch = 0; ch < tempData.size(); ch++)
			{
				for (int n = 0; n < tempData.at(ch).size(); n++)
				{
					// ToDo: Make this less horribly inefficient
					_eegData.at(h).at(ch).push_back(tempData.at(ch).at(n));
				}
			}

			vector<vector<float>> tempFftData;
			vector<int> tempDominantBand;
			tempDominantBand.resize(_nHeadsets);
			if (_openBci.isFftNew(ipAddresses.at(h)))
			{
				tempFftData = _openBci.getLatestFft(ipAddresses.at(h));

				_maxNormBandValue.at(h) = -1;
				tempDominantBand.at(h) = -1;
				if (_dataReset)
				{
					_dataIsReset = true;
				}
				for (int b = 0; b < _eegBands.size(); b++)
				{
					for (int ch = 0; ch < _eegChannels.at(h).size(); ch++)
					{
						int f1 = _openBci.getFftBinFromFrequency(_eegBands.at(b).at(0));
						int f2 = _openBci.getFftBinFromFrequency(_eegBands.at(b).at(1));

						float sum = 0;
						for (int f = f1; f <= f2; f++)
						{
							sum = sum + tempFftData.at(ch).at(f);
						}
						float avg = sum / (1.f + f2 - f1);

						// ToDo: Deal with averaging across channels
						if (_dataReset)
						{
							_eegBandData.at(h).at(ch).at(b) = avg;
							_eegBaselineBandData.at(h).at(ch).at(b) = avg;
						}
						else
						{
							_eegBandData.at(h).at(ch).at(b) =
								ofxOpenBciWifi::smooth(avg, _eegBandData.at(h).at(ch).at(b), _smoothingWeight);
							_eegBaselineBandData.at(h).at(ch).at(b) =
								ofxOpenBciWifi::smooth(avg, _eegBaselineBandData.at(h).at(ch).at(b), _baselineWeight);
						}
						float normalizedData = _eegBandData.at(h).at(ch).at(b) / _eegBaselineBandData.at(h).at(ch).at(b);
						if (normalizedData > _maxNormBandValue.at(h))
						{
							_maxNormBandValue.at(h) = normalizedData;
							tempDominantBand.at(h) = b;
						}
					}
				}

				if (h == 0)
				{
					_dominantBand1 = tempDominantBand.at(h);
				}
				if (h == 1)
				{
					_dominantBand2 = tempDominantBand.at(h);
				}

				_fftDelay.at(h) = ofGetElapsedTimeMillis() - _lastFftMillis.at(h);
				_lastFftMillis.at(h) = ofGetElapsedTimeMillis();
				if (_fftDelay.size() > 1)
				{
					_fftDelay1 = _fftDelay.at(0);
					_fftDelay2 = _fftDelay.at(1);
				}
			}
		}

		if (_dataIsReset)
		{
			_dataReset = false;
		}

		unlock();
		sleep(1);
	}
}

float HiveMind::getFftDelay(int headset)
{
	if (headset == 0)
	{
		return _fftDelay1;
	}
	if (headset == 1)
	{
		return _fftDelay2;
	}
	return -1;
}

int HiveMind::getDominantBand(int headset)
{
	if (headset == 0)
	{
		return _dominantBand1;
	}
	if (headset == 1)
	{
		return _dominantBand2;
	}
	return -1;
}

int HiveMind::getFrameCount(int headset, int frameRate)
{
	if (frameRate == 60)
	{
		if (getDominantBand(headset) == 0)	return 4; // Theta
		if (getDominantBand(headset) == 1)	return 2; // Alpha
		if (getDominantBand(headset) == 2)	return 1; // Beta
	}
}

vector<float> HiveMind::getEegBandData(int headset)
{
	lock();
	vector<float> temp = _eegBandData.at(headset).at(0);
	unlock();
	return temp;
}

vector<float> HiveMind::getEegBaselineBandData(int headset)
{
	lock();
	vector<float> temp = _eegBaselineBandData.at(headset).at(0);
	unlock();
	return temp;
}

void HiveMind::resetBandData()
{
	_dataReset = true;
	_dataIsReset = false;
}

vector<vector<float>> HiveMind::getData(int headset)
{
	// ToDo: clear _eegData buffer
	vector<vector<float>> returnData;
	lock();
	returnData = _eegData.at(headset);
	_eegData.at(headset).clear();
	unlock();
	return returnData;
}

vector<vector<float>> HiveMind::getData(string ipAddress)
{
	// ToDo: clear _eegData buffer
	vector<vector<float>> returnData;
	lock();
	vector<string> ipAddresses = _openBci.getHeadsetIpAddresses();
	for (int h = 0; h < ipAddresses.size(); h++)
	{
		if (ipAddress.compare(ipAddresses.at(h)) == 0)
		{
			returnData = _eegData.at(h);
			_eegData.at(h).clear();
		}
	}
	unlock();
	return returnData;
}

void HiveMind::setTcpPort(int port)
{
	_openBci.setTcpPort(port);
}

//vector<vector<int>> goodEegChannels;
//
//void threadedFunction();
//
//public:
//
//	HiveMind();
//	~HiveMind();
//
//	int getDominantBand(int headset);<|endoftext|>


<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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {qb_RoadExtract.tif}
//    OUTPUTS: {ExtractRoadOutput.png}
//    337 557 432 859 1.0 0.00005 1.0 0.39269 1.0 10.0 25.
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// The easiest way to use the road extraction filter provided by OTB is to use the composite
// filter. If a modification in the pipeline is required to adapt to a particular situation,
// the step by step example, described in the next section can be adapted.
//
// This example demonstrates the use of the \doxygen{otb}{RoadExtractionFilter}.
// This filter is a composite filter achieving road extraction according to the algorithm
// adapted by E. Christophe and J. Inglada \cite{Christophe2007} from an original method
// proposed in \cite{Lacroix1998}.
//
// The first step toward the use of this filter is the inclusion of the proper header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

#include "otbPolyLineParametricPathWithValue.h"
#include "otbRoadExtractionFilter.h"
#include "otbDrawPathListFilter.h"

// Software Guide : EndCodeSnippet

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbMath.h"

#include "itkInvertIntensityImageFilter.h"
#include "itkGrayscaleDilateImageFilter.h"
#include "itkBinaryBallStructuringElement.h"

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

  if(argc != 14)
    {
      std::cerr << "Usage: "<< argv[0];
      std:: cerr <<" inputFileName outputFileName firstPixelComponent secondPixelComponent ";
      std::cerr <<"thirdPixelComponent fourthPixelComponent amplitudeThrehsold tolerance ";
      std::cerr <<"angularThreshold firstMeanDistanceThreshold secondMeanDistanceThreshold ";
      std::cerr<<"distanceThreshold"<<std::endl;
      return EXIT_FAILURE;
    }

   const unsigned int Dimension = 2;
   // Software Guide : BeginLatex
   //
   // Then we must decide what pixel type to use for the image. We choose to do
   // all the computation in floating point precision and rescale the results
   // between 0 and 255 in order to export PNG images.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef double        InputPixelType;
   typedef unsigned char OutputPixelType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   //  The images are defined using the pixel type and the dimension. Please note that
   //  the doxygen{otb}{RoadExtractionFilter} needs an \doxygen{otb}{VectorImage} as input
   //  to handle multispectral images.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::VectorImage<InputPixelType,Dimension> InputVectorImageType;
   typedef otb::Image<InputPixelType,Dimension> InputImageType;
   typedef otb::Image<OutputPixelType,Dimension> OutputImageType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   // We define the type of the polyline that the filter produces. We use the
   // \doxygen{otb}{PolyLineParametricPathWithValue}, which allows the filter to produce
   // a likehood value along with each polyline. The filter is able to produce
   // \doxygen{itk}{PolyLineParametricPath} as well.
   //
   //  Software Guide : EndLatex

   //  Software Guide : BeginCodeSnippet

   typedef otb::PolyLineParametricPathWithValue<InputPixelType,Dimension> PathType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // Now we can define the \doxygen{otb}{RoadExtractionFilter} that takes a multi-spectral
   // image as input and produces a list of polylines.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::RoadExtractionFilter<InputVectorImageType,
                                     PathType> RoadExtractionFilterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // We also define an \doxygen{otb}{DrawPathListFilter} to draw the output
   // polylines on an image, taking their likehood values into account.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::DrawPathListFilter<InputImageType, PathType,
                                   InputImageType> DrawPathFilterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The intensity rescaling of the results will be carried out by the
   // \code{itk::RescaleIntensityImageFilter} which is templated by the
   // input and output image types.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef itk::RescaleIntensityImageFilter<InputImageType,
                                            OutputImageType> RescalerType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   //  An \doxygen{otb::ImageFileReader} class is also instantiated in order to read
   //  image data from a file.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::ImageFileReader<InputVectorImageType> ReaderType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   // An \doxygen{otb::ImageFileWriter} is instantiated in order to write the
   // output image to a file.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::ImageFileWriter<OutputImageType> WriterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The different filters composing our pipeline are created by invoking their
   // \code{New()} methods, assigning the results to smart pointers.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   ReaderType::Pointer reader = ReaderType::New();
   RoadExtractionFilterType::Pointer roadExtractionFilter
     = RoadExtractionFilterType::New();
   DrawPathFilterType::Pointer drawingFilter = DrawPathFilterType::New();
   RescalerType::Pointer rescaleFilter = RescalerType::New();
   WriterType::Pointer writer = WriterType::New();

   // Software Guide : EndCodeSnippet

   reader->SetFileName(argv[1]);

   // Software Guide : BeginLatex
   //
   // The \doxygen{otb::RoadExtractionFilter} needs to have a reference pixel
   // corresponding to the spectral content likely to represent a road. This is done
   // by passing a pixel to the filter. Here we suppose that the input image
   // has four spectral bands.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   InputVectorImageType::PixelType ReferencePixel;
   ReferencePixel.SetSize(4);
   ReferencePixel.SetElement(0,::atof(argv[3]));
   ReferencePixel.SetElement(1,::atof(argv[4]));
   ReferencePixel.SetElement(2,::atof(argv[5]));
   ReferencePixel.SetElement(3,::atof(argv[6]));
   roadExtractionFilter->SetReferencePixel(ReferencePixel);

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // We must also set the  alpha parameter of the filter which allows us to tune the width of the roads
   // we want to extract. Typical value is $1.0$ and should be working in most situations.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetAlpha(atof(argv[7]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // All other parameter should not influence the results too much in most situation and can
   // be kept at the default value.
   //
   // The amplitude threshold parameter tunes the sensitivity of the vectorization step. A typical
   // value is $5 \cdot 10^{-5}$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetAmplitudeThreshold(atof(argv[8]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The tolerance threshold tunes the sensitivity of the path simplification step.
   // Typical value is $1.0$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetTolerance(atof(argv[9]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // Roads are not likely to have sharp turns. Therefore we set the max angle parameter,
   // as well as the link angular threshold. The value is typicaly $\frac{\pi}{8}$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

    roadExtractionFilter->SetMaxAngle(atof(argv[10]));
    roadExtractionFilter->SetAngularThreshold(atof(argv[10]));

    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The \doxygen{otb::RoadExtractionFilter} performs two odd path removing operations at different stage of
    // its execution. The first mean distance threshold and the second mean distance threshold set their criterion
    // for removal. Path are removed if their mean distance between nodes is to small, since such path coming
    // from previous filters are likely to be tortuous. The first removal operation as a typical mean distance
    // threshold parameter of $1.0$, and the second of $10.0$.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

    roadExtractionFilter->SetFirstMeanDistanceThreshold(atof(argv[11]));
    roadExtractionFilter->SetSecondMeanDistanceThreshold(atof(argv[12]));

    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The \doxygen{otb::RoadExtractionFilter} is able to link path whose ends are near
    // according to an euclidean distance criterion. The threshold for this distance
    // to link a path is the distance threshold parameter. A typical value is $25$.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

     roadExtractionFilter->SetDistanceThreshold(atof(argv[13]));

     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // We will now create a black background image to draw the resulting polyline on.
     // To achieve this we need to know the size of our input image. Therefore we trigger the
     // \code{GenerateOutputInformation()} of the reader.
     //
     // Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet

     reader->GenerateOutputInformation();
     InputImageType::Pointer blackBackground = InputImageType::New();
     blackBackground->SetRegions(reader->GetOutput()->GetLargestPossibleRegion());
     blackBackground->Allocate();
     blackBackground->FillBuffer(0);

     // Software Guide : EndCodeSnippet

     // Software Guide  : BeginLatex
     //
     // We tell the \doxygen{otb::DrawPathListFilter} to try to use the likehood value
     // embedded within the polyline as a value for drawing this polyline if possible.
     //
     // Software Guide : EndLatex

     // Software Guide  : BeginCodeSnippet

     drawingFilter->UseInternalPathValueOn();

     // Software Guide  : EndCodeSnippet

     //  Software Guide : BeginLatex
     //
     //  The \code{itk::RescaleIntensityImageFilter} needs to know which
     //  is the minimum and maximum values of the output generated
     //  image. Those can be chosen in a generic way by using the
     //  \code{NumericTraits} functions, since they are templated over
     //  the pixel type.
     //
     //  Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet
     rescaleFilter->SetOutputMinimum(itk::NumericTraits< OutputPixelType >::min());
     rescaleFilter->SetOutputMaximum(itk::NumericTraits< OutputPixelType >::max());
     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // Now it is time for some pipeline wiring.
     //
     // Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet

     roadExtractionFilter->SetInput(reader->GetOutput());
     drawingFilter->SetInput(blackBackground);
     drawingFilter->SetInputPath(roadExtractionFilter->GetOutput());
     rescaleFilter->SetInput(drawingFilter->GetOutput());

     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // The update of the pipeline is triggered by the \code{Update()} method
     // of the rescale intensity filter.
     //
     // Software Guide : EndLatex

     //  Software Guide : BeginCodeSnippet

     rescaleFilter->Update();

     // Software Guide : EndCodeSnippet

     // output image enhancement
     typedef itk::BinaryBallStructuringElement<OutputPixelType,Dimension> StructuringElementType;
     typedef itk::GrayscaleDilateImageFilter<OutputImageType,OutputImageType,StructuringElementType> DilateFilterType;
     typedef itk::InvertIntensityImageFilter<OutputImageType,OutputImageType> InvertFilterType;

     StructuringElementType se;
     se.SetRadius(1);
     se.CreateStructuringElement();

     DilateFilterType::Pointer dilater = DilateFilterType::New();

     dilater->SetInput(rescaleFilter->GetOutput());
     dilater->SetKernel(se);

     InvertFilterType::Pointer invertFilter = InvertFilterType::New();
     invertFilter->SetInput(dilater->GetOutput());

     writer->SetFileName(argv[2]);
     writer->SetInput(invertFilter->GetOutput());
     writer->Update();

     // Software Guide : BeginLatex
     //
     // Figure~\ref{fig:ROADEXTRACTION_FILTER} shows the result of applying
     // the road extraction filter to a fusionned Quickbird image.
     // \begin{figure}
     // \center
     // \includegraphics[width=0.44\textwidth]{qb_ExtractRoad_pretty.eps}
     // \includegraphics[width=0.44\textwidth]{ExtractRoadOutput.eps}
     // \itkcaption[Road extraction filter application]{Result of applying
     // the \doxygen{otb}{RoadExtractionFilter} to a fusionned Quickbird
     // image. From left to right : original image, extracted road with their
     // likehood values.}
     // \label{fig:ROADEXTRACTION_FILTER}
     // \end{figure}
     //
     // Software Guide : EndLatex

     return EXIT_SUCCESS;
}

<commit_msg>correction liens doxygen<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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {qb_RoadExtract.tif}
//    OUTPUTS: {ExtractRoadOutput.png}
//    337 557 432 859 1.0 0.00005 1.0 0.39269 1.0 10.0 25.
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// The easiest way to use the road extraction filter provided by OTB is to use the composite
// filter. If a modification in the pipeline is required to adapt to a particular situation,
// the step by step example, described in the next section can be adapted.
//
// This example demonstrates the use of the \doxygen{otb}{RoadExtractionFilter}.
// This filter is a composite filter achieving road extraction according to the algorithm
// adapted by E. Christophe and J. Inglada \cite{Christophe2007} from an original method
// proposed in \cite{Lacroix1998}.
//
// The first step toward the use of this filter is the inclusion of the proper header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

#include "otbPolyLineParametricPathWithValue.h"
#include "otbRoadExtractionFilter.h"
#include "otbDrawPathListFilter.h"

// Software Guide : EndCodeSnippet

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbMath.h"

#include "itkInvertIntensityImageFilter.h"
#include "itkGrayscaleDilateImageFilter.h"
#include "itkBinaryBallStructuringElement.h"

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

  if(argc != 14)
    {
      std::cerr << "Usage: "<< argv[0];
      std:: cerr <<" inputFileName outputFileName firstPixelComponent secondPixelComponent ";
      std::cerr <<"thirdPixelComponent fourthPixelComponent amplitudeThrehsold tolerance ";
      std::cerr <<"angularThreshold firstMeanDistanceThreshold secondMeanDistanceThreshold ";
      std::cerr<<"distanceThreshold"<<std::endl;
      return EXIT_FAILURE;
    }

   const unsigned int Dimension = 2;
   // Software Guide : BeginLatex
   //
   // Then we must decide what pixel type to use for the image. We choose to do
   // all the computation in floating point precision and rescale the results
   // between 0 and 255 in order to export PNG images.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef double        InputPixelType;
   typedef unsigned char OutputPixelType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   //  The images are defined using the pixel type and the dimension. Please note that
   //  the doxygen{otb}{RoadExtractionFilter} needs an \doxygen{otb}{VectorImage} as input
   //  to handle multispectral images.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::VectorImage<InputPixelType,Dimension> InputVectorImageType;
   typedef otb::Image<InputPixelType,Dimension> InputImageType;
   typedef otb::Image<OutputPixelType,Dimension> OutputImageType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   // We define the type of the polyline that the filter produces. We use the
   // \doxygen{otb}{PolyLineParametricPathWithValue}, which allows the filter to produce
   // a likehood value along with each polyline. The filter is able to produce
   // \doxygen{itk}{PolyLineParametricPath} as well.
   //
   //  Software Guide : EndLatex

   //  Software Guide : BeginCodeSnippet

   typedef otb::PolyLineParametricPathWithValue<InputPixelType,Dimension> PathType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // Now we can define the \doxygen{otb}{RoadExtractionFilter} that takes a multi-spectral
   // image as input and produces a list of polylines.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::RoadExtractionFilter<InputVectorImageType,
                                     PathType> RoadExtractionFilterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // We also define an \doxygen{otb}{DrawPathListFilter} to draw the output
   // polylines on an image, taking their likehood values into account.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::DrawPathListFilter<InputImageType, PathType,
                                   InputImageType> DrawPathFilterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The intensity rescaling of the results will be carried out by the
   // \doxygen{itk}{RescaleIntensityImageFilter} which is templated by the
   // input and output image types.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef itk::RescaleIntensityImageFilter<InputImageType,
                                            OutputImageType> RescalerType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   //  An \doxygen{otb}{ImageFileReader} class is also instantiated in order to read
   //  image data from a file.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::ImageFileReader<InputVectorImageType> ReaderType;

   // Software Guide : EndCodeSnippet

   //  Software Guide : BeginLatex
   //
   // An \doxygen{otb}{ImageFileWriter} is instantiated in order to write the
   // output image to a file.
   //
   //  Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   typedef otb::ImageFileWriter<OutputImageType> WriterType;

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The different filters composing our pipeline are created by invoking their
   // \code{New()} methods, assigning the results to smart pointers.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   ReaderType::Pointer reader = ReaderType::New();
   RoadExtractionFilterType::Pointer roadExtractionFilter
     = RoadExtractionFilterType::New();
   DrawPathFilterType::Pointer drawingFilter = DrawPathFilterType::New();
   RescalerType::Pointer rescaleFilter = RescalerType::New();
   WriterType::Pointer writer = WriterType::New();

   // Software Guide : EndCodeSnippet

   reader->SetFileName(argv[1]);

   // Software Guide : BeginLatex
   //
   // The \doxygen{otb}{RoadExtractionFilter} needs to have a reference pixel
   // corresponding to the spectral content likely to represent a road. This is done
   // by passing a pixel to the filter. Here we suppose that the input image
   // has four spectral bands.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   InputVectorImageType::PixelType ReferencePixel;
   ReferencePixel.SetSize(4);
   ReferencePixel.SetElement(0,::atof(argv[3]));
   ReferencePixel.SetElement(1,::atof(argv[4]));
   ReferencePixel.SetElement(2,::atof(argv[5]));
   ReferencePixel.SetElement(3,::atof(argv[6]));
   roadExtractionFilter->SetReferencePixel(ReferencePixel);

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // We must also set the  alpha parameter of the filter which allows us to tune the width of the roads
   // we want to extract. Typical value is $1.0$ and should be working in most situations.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetAlpha(atof(argv[7]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // All other parameter should not influence the results too much in most situation and can
   // be kept at the default value.
   //
   // The amplitude threshold parameter tunes the sensitivity of the vectorization step. A typical
   // value is $5 \cdot 10^{-5}$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetAmplitudeThreshold(atof(argv[8]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // The tolerance threshold tunes the sensitivity of the path simplification step.
   // Typical value is $1.0$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

   roadExtractionFilter->SetTolerance(atof(argv[9]));

   // Software Guide : EndCodeSnippet

   // Software Guide : BeginLatex
   //
   // Roads are not likely to have sharp turns. Therefore we set the max angle parameter,
   // as well as the link angular threshold. The value is typicaly $\frac{\pi}{8}$.
   //
   // Software Guide : EndLatex

   // Software Guide : BeginCodeSnippet

    roadExtractionFilter->SetMaxAngle(atof(argv[10]));
    roadExtractionFilter->SetAngularThreshold(atof(argv[10]));

    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The \doxygen{otb}{RoadExtractionFilter} performs two odd path removing operations at different stage of
    // its execution. The first mean distance threshold and the second mean distance threshold set their criterion
    // for removal. Path are removed if their mean distance between nodes is to small, since such path coming
    // from previous filters are likely to be tortuous. The first removal operation as a typical mean distance
    // threshold parameter of $1.0$, and the second of $10.0$.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

    roadExtractionFilter->SetFirstMeanDistanceThreshold(atof(argv[11]));
    roadExtractionFilter->SetSecondMeanDistanceThreshold(atof(argv[12]));

    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The \doxygen{otb}{RoadExtractionFilter} is able to link path whose ends are near
    // according to an euclidean distance criterion. The threshold for this distance
    // to link a path is the distance threshold parameter. A typical value is $25$.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

     roadExtractionFilter->SetDistanceThreshold(atof(argv[13]));

     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // We will now create a black background image to draw the resulting polyline on.
     // To achieve this we need to know the size of our input image. Therefore we trigger the
     // \code{GenerateOutputInformation()} of the reader.
     //
     // Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet

     reader->GenerateOutputInformation();
     InputImageType::Pointer blackBackground = InputImageType::New();
     blackBackground->SetRegions(reader->GetOutput()->GetLargestPossibleRegion());
     blackBackground->Allocate();
     blackBackground->FillBuffer(0);

     // Software Guide : EndCodeSnippet

     // Software Guide  : BeginLatex
     //
     // We tell the \doxygen{otb}{DrawPathListFilter} to try to use the likehood value
     // embedded within the polyline as a value for drawing this polyline if possible.
     //
     // Software Guide : EndLatex

     // Software Guide  : BeginCodeSnippet

     drawingFilter->UseInternalPathValueOn();

     // Software Guide  : EndCodeSnippet

     //  Software Guide : BeginLatex
     //
     //  The \code{itk::RescaleIntensityImageFilter} needs to know which
     //  is the minimum and maximum values of the output generated
     //  image. Those can be chosen in a generic way by using the
     //  \code{NumericTraits} functions, since they are templated over
     //  the pixel type.
     //
     //  Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet
     rescaleFilter->SetOutputMinimum(itk::NumericTraits< OutputPixelType >::min());
     rescaleFilter->SetOutputMaximum(itk::NumericTraits< OutputPixelType >::max());
     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // Now it is time for some pipeline wiring.
     //
     // Software Guide : EndLatex

     // Software Guide : BeginCodeSnippet

     roadExtractionFilter->SetInput(reader->GetOutput());
     drawingFilter->SetInput(blackBackground);
     drawingFilter->SetInputPath(roadExtractionFilter->GetOutput());
     rescaleFilter->SetInput(drawingFilter->GetOutput());

     // Software Guide : EndCodeSnippet

     // Software Guide : BeginLatex
     //
     // The update of the pipeline is triggered by the \code{Update()} method
     // of the rescale intensity filter.
     //
     // Software Guide : EndLatex

     //  Software Guide : BeginCodeSnippet

     rescaleFilter->Update();

     // Software Guide : EndCodeSnippet

     // output image enhancement
     typedef itk::BinaryBallStructuringElement<OutputPixelType,Dimension> StructuringElementType;
     typedef itk::GrayscaleDilateImageFilter<OutputImageType,OutputImageType,StructuringElementType> DilateFilterType;
     typedef itk::InvertIntensityImageFilter<OutputImageType,OutputImageType> InvertFilterType;

     StructuringElementType se;
     se.SetRadius(1);
     se.CreateStructuringElement();

     DilateFilterType::Pointer dilater = DilateFilterType::New();

     dilater->SetInput(rescaleFilter->GetOutput());
     dilater->SetKernel(se);

     InvertFilterType::Pointer invertFilter = InvertFilterType::New();
     invertFilter->SetInput(dilater->GetOutput());

     writer->SetFileName(argv[2]);
     writer->SetInput(invertFilter->GetOutput());
     writer->Update();

     // Software Guide : BeginLatex
     //
     // Figure~\ref{fig:ROADEXTRACTION_FILTER} shows the result of applying
     // the road extraction filter to a fusionned Quickbird image.
     // \begin{figure}
     // \center
     // \includegraphics[width=0.44\textwidth]{qb_ExtractRoad_pretty.eps}
     // \includegraphics[width=0.44\textwidth]{ExtractRoadOutput.eps}
     // \itkcaption[Road extraction filter application]{Result of applying
     // the \doxygen{otb}{RoadExtractionFilter} to a fusionned Quickbird
     // image. From left to right : original image, extracted road with their
     // likehood values.}
     // \label{fig:ROADEXTRACTION_FILTER}
     // \end{figure}
     //
     // Software Guide : EndLatex

     return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>//===------------------------ strstream.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "strstream"
#include "algorithm"
#include "climits"
#include "cstring"

_LIBCPP_BEGIN_NAMESPACE_STD

strstreambuf::strstreambuf(streamsize __alsize)
    : __strmode_(__dynamic),
      __alsize_(__alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
}

strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
    : __strmode_(__dynamic),
      __alsize_(__default_alsize),
      __palloc_(__palloc),
      __pfree_(__pfree)
{
}

void
strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
{
    if (__n == 0)
        __n = strlen(__gnext);
    else if (__n < 0)
        __n = INT_MAX;
    if (__pbeg == nullptr)
        setg(__gnext, __gnext, __gnext + __n);
    else
    {
        setg(__gnext, __gnext, __pbeg);
        setp(__pbeg, __pbeg + __n);
    }
}

strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init(__gnext, __n, __pbeg);
}

strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, (char*)__pbeg);
}

strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, (char*)__pbeg);
}

strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES

strstreambuf::strstreambuf(strstreambuf&& __rhs)
    : streambuf(__rhs),
      __strmode_(__rhs.__strmode_),
      __alsize_(__rhs.__alsize_),
      __palloc_(__rhs.__palloc_),
      __pfree_(__rhs.__pfree_)
{
    __rhs.setg(nullptr, nullptr, nullptr);
    __rhs.setp(nullptr, nullptr);
}

strstreambuf&
strstreambuf::operator=(strstreambuf&& __rhs)
{
    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
    {
        if (__pfree_)
            __pfree_(eback());
        else
            delete [] eback();
    }
    streambuf::operator=(__rhs);
    __strmode_ = __rhs.__strmode_;
    __alsize_ = __rhs.__alsize_;
    __palloc_ = __rhs.__palloc_;
    __pfree_ = __rhs.__pfree_;
    __rhs.setg(nullptr, nullptr, nullptr);
    __rhs.setp(nullptr, nullptr);
}

#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES

strstreambuf::~strstreambuf()
{
    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
    {
        if (__pfree_)
            __pfree_(eback());
        else
            delete [] eback();
    }
}

void
strstreambuf::swap(strstreambuf& __rhs)
{
    streambuf::swap(__rhs);
    _STD::swap(__strmode_, __rhs.__strmode_);
    _STD::swap(__alsize_, __rhs.__alsize_);
    _STD::swap(__palloc_, __rhs.__palloc_);
    _STD::swap(__pfree_, __rhs.__pfree_);
}

void
strstreambuf::freeze(bool __freezefl)
{
    if (__strmode_ & __dynamic)
    {
        if (__freezefl)
            __strmode_ |= __frozen;
        else
            __strmode_ &= ~__frozen;
    }
}

char*
strstreambuf::str()
{
    if (__strmode_ & __dynamic)
        __strmode_ |= __frozen;
    return eback();
}

int
strstreambuf::pcount() const
{
    return static_cast<int>(pptr() - pbase());
}

strstreambuf::int_type
strstreambuf::overflow(int_type __c)
{
    if (__c == EOF)
        return int_type(0);
    if (pptr() == epptr())
    {
        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
            return int_type(EOF);
        streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
        streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
        char* buf = nullptr;
        if (__palloc_)
            buf = static_cast<char*>(__palloc_(new_size));
        else
            buf = new char[new_size];
        if (buf == nullptr)
            return int_type(EOF);
        memcpy(buf, eback(), old_size);
        ptrdiff_t ninp = gptr()  - eback();
        ptrdiff_t einp = egptr() - eback();
        ptrdiff_t nout = pptr()  - pbase();
        ptrdiff_t eout = epptr() - pbase();
        if (__strmode_ & __allocated)
        {
            if (__pfree_)
                __pfree_(eback());
            else
                delete [] eback();
        }
        setg(buf, buf + ninp, buf + einp);
        setp(buf + einp, buf + einp + eout);
        pbump(nout);
        __strmode_ |= __allocated;
    }
    *pptr() = static_cast<char>(__c);
    pbump(1);
    return int_type((unsigned char)__c);
}

strstreambuf::int_type
strstreambuf::pbackfail(int_type __c)
{
    if (eback() == gptr())
        return EOF;
    if (__c == EOF)
    {
        gbump(-1);
        return int_type(0);
    }
    if (__strmode_ & __constant)
    {
        if (gptr()[-1] == static_cast<char>(__c))
        {
            gbump(-1);
            return __c;
        }
        return EOF;
    }
    gbump(-1);
    *gptr() = static_cast<char>(__c);
    return __c;
}

strstreambuf::int_type
strstreambuf::underflow()
{
    if (gptr() == egptr())
    {
        if (egptr() >= pptr())
            return EOF;
        setg(eback(), gptr(), pptr());
    }
    return int_type((unsigned char)*gptr());
}

strstreambuf::pos_type
strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
{
    off_type __p(-1);
    bool pos_in = __which & ios::in;
    bool pos_out = __which & ios::out;
    bool legal = false;
    switch (__way)
    {
    case ios::beg:
    case ios::end:
        if (pos_in || pos_out)
            legal = true;
        break;
    case ios::cur:
        if (pos_in != pos_out)
            legal = true;
        break;
    }
    if (pos_in && gptr() == nullptr)
        legal = false;
    if (pos_out && pptr() == nullptr)
        legal = false;
    if (legal)
    {
        off_type newoff;
        char* seekhigh = epptr() ? epptr() : egptr();
        switch (__way)
        {
        case ios::beg:
            newoff = 0;
            break;
        case ios::cur:
            newoff = (pos_in ? gptr() : pptr()) - eback();
            break;
        case ios::end:
            newoff = seekhigh - eback();
            break;
        }
        newoff += __off;
        if (0 <= newoff && newoff <= seekhigh - eback())
        {
            char* newpos = eback() + newoff;
            if (pos_in)
                setg(eback(), newpos, max(newpos, egptr()));
            if (pos_out)
            {
                // min(pbase, newpos), newpos, epptr()
                __off = epptr() - newpos;
                setp(min(pbase(), newpos), epptr());
                pbump(static_cast<int>((epptr() - pbase()) - __off));
            }
            __p = newoff;
        }
    }
    return pos_type(__p);
}

strstreambuf::pos_type
strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
{
    off_type __p(-1);
    bool pos_in = __which & ios::in;
    bool pos_out = __which & ios::out;
    if (pos_in || pos_out)
    {
        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
        {
            off_type newoff = __sp;
            char* seekhigh = epptr() ? epptr() : egptr();
            if (0 <= newoff && newoff <= seekhigh - eback())
            {
                char* newpos = eback() + newoff;
                if (pos_in)
                    setg(eback(), newpos, max(newpos, egptr()));
                if (pos_out)
                {
                    // min(pbase, newpos), newpos, epptr()
                    off_type temp = epptr() - newpos;
                    setp(min(pbase(), newpos), epptr());
                    pbump(static_cast<int>((epptr() - pbase()) - temp));
                }
                __p = newoff;
            }
        }
    }
    return pos_type(__p);
}

istrstream::~istrstream()
{
}

ostrstream::~ostrstream()
{
}

strstream::~strstream()
{
}

_LIBCPP_END_NAMESPACE_STD
<commit_msg>clang found a missing return statement.<commit_after>//===------------------------ strstream.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "strstream"
#include "algorithm"
#include "climits"
#include "cstring"

_LIBCPP_BEGIN_NAMESPACE_STD

strstreambuf::strstreambuf(streamsize __alsize)
    : __strmode_(__dynamic),
      __alsize_(__alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
}

strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
    : __strmode_(__dynamic),
      __alsize_(__default_alsize),
      __palloc_(__palloc),
      __pfree_(__pfree)
{
}

void
strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
{
    if (__n == 0)
        __n = strlen(__gnext);
    else if (__n < 0)
        __n = INT_MAX;
    if (__pbeg == nullptr)
        setg(__gnext, __gnext, __gnext + __n);
    else
    {
        setg(__gnext, __gnext, __pbeg);
        setp(__pbeg, __pbeg + __n);
    }
}

strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init(__gnext, __n, __pbeg);
}

strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, (char*)__pbeg);
}

strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
    : __strmode_(),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, (char*)__pbeg);
}

strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
    : __strmode_(__constant),
      __alsize_(__default_alsize),
      __palloc_(nullptr),
      __pfree_(nullptr)
{
    __init((char*)__gnext, __n, nullptr);
}

#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES

strstreambuf::strstreambuf(strstreambuf&& __rhs)
    : streambuf(__rhs),
      __strmode_(__rhs.__strmode_),
      __alsize_(__rhs.__alsize_),
      __palloc_(__rhs.__palloc_),
      __pfree_(__rhs.__pfree_)
{
    __rhs.setg(nullptr, nullptr, nullptr);
    __rhs.setp(nullptr, nullptr);
}

strstreambuf&
strstreambuf::operator=(strstreambuf&& __rhs)
{
    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
    {
        if (__pfree_)
            __pfree_(eback());
        else
            delete [] eback();
    }
    streambuf::operator=(__rhs);
    __strmode_ = __rhs.__strmode_;
    __alsize_ = __rhs.__alsize_;
    __palloc_ = __rhs.__palloc_;
    __pfree_ = __rhs.__pfree_;
    __rhs.setg(nullptr, nullptr, nullptr);
    __rhs.setp(nullptr, nullptr);
    return *this;
}

#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES

strstreambuf::~strstreambuf()
{
    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
    {
        if (__pfree_)
            __pfree_(eback());
        else
            delete [] eback();
    }
}

void
strstreambuf::swap(strstreambuf& __rhs)
{
    streambuf::swap(__rhs);
    _STD::swap(__strmode_, __rhs.__strmode_);
    _STD::swap(__alsize_, __rhs.__alsize_);
    _STD::swap(__palloc_, __rhs.__palloc_);
    _STD::swap(__pfree_, __rhs.__pfree_);
}

void
strstreambuf::freeze(bool __freezefl)
{
    if (__strmode_ & __dynamic)
    {
        if (__freezefl)
            __strmode_ |= __frozen;
        else
            __strmode_ &= ~__frozen;
    }
}

char*
strstreambuf::str()
{
    if (__strmode_ & __dynamic)
        __strmode_ |= __frozen;
    return eback();
}

int
strstreambuf::pcount() const
{
    return static_cast<int>(pptr() - pbase());
}

strstreambuf::int_type
strstreambuf::overflow(int_type __c)
{
    if (__c == EOF)
        return int_type(0);
    if (pptr() == epptr())
    {
        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
            return int_type(EOF);
        streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
        streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
        char* buf = nullptr;
        if (__palloc_)
            buf = static_cast<char*>(__palloc_(new_size));
        else
            buf = new char[new_size];
        if (buf == nullptr)
            return int_type(EOF);
        memcpy(buf, eback(), old_size);
        ptrdiff_t ninp = gptr()  - eback();
        ptrdiff_t einp = egptr() - eback();
        ptrdiff_t nout = pptr()  - pbase();
        ptrdiff_t eout = epptr() - pbase();
        if (__strmode_ & __allocated)
        {
            if (__pfree_)
                __pfree_(eback());
            else
                delete [] eback();
        }
        setg(buf, buf + ninp, buf + einp);
        setp(buf + einp, buf + einp + eout);
        pbump(nout);
        __strmode_ |= __allocated;
    }
    *pptr() = static_cast<char>(__c);
    pbump(1);
    return int_type((unsigned char)__c);
}

strstreambuf::int_type
strstreambuf::pbackfail(int_type __c)
{
    if (eback() == gptr())
        return EOF;
    if (__c == EOF)
    {
        gbump(-1);
        return int_type(0);
    }
    if (__strmode_ & __constant)
    {
        if (gptr()[-1] == static_cast<char>(__c))
        {
            gbump(-1);
            return __c;
        }
        return EOF;
    }
    gbump(-1);
    *gptr() = static_cast<char>(__c);
    return __c;
}

strstreambuf::int_type
strstreambuf::underflow()
{
    if (gptr() == egptr())
    {
        if (egptr() >= pptr())
            return EOF;
        setg(eback(), gptr(), pptr());
    }
    return int_type((unsigned char)*gptr());
}

strstreambuf::pos_type
strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
{
    off_type __p(-1);
    bool pos_in = __which & ios::in;
    bool pos_out = __which & ios::out;
    bool legal = false;
    switch (__way)
    {
    case ios::beg:
    case ios::end:
        if (pos_in || pos_out)
            legal = true;
        break;
    case ios::cur:
        if (pos_in != pos_out)
            legal = true;
        break;
    }
    if (pos_in && gptr() == nullptr)
        legal = false;
    if (pos_out && pptr() == nullptr)
        legal = false;
    if (legal)
    {
        off_type newoff;
        char* seekhigh = epptr() ? epptr() : egptr();
        switch (__way)
        {
        case ios::beg:
            newoff = 0;
            break;
        case ios::cur:
            newoff = (pos_in ? gptr() : pptr()) - eback();
            break;
        case ios::end:
            newoff = seekhigh - eback();
            break;
        }
        newoff += __off;
        if (0 <= newoff && newoff <= seekhigh - eback())
        {
            char* newpos = eback() + newoff;
            if (pos_in)
                setg(eback(), newpos, max(newpos, egptr()));
            if (pos_out)
            {
                // min(pbase, newpos), newpos, epptr()
                __off = epptr() - newpos;
                setp(min(pbase(), newpos), epptr());
                pbump(static_cast<int>((epptr() - pbase()) - __off));
            }
            __p = newoff;
        }
    }
    return pos_type(__p);
}

strstreambuf::pos_type
strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
{
    off_type __p(-1);
    bool pos_in = __which & ios::in;
    bool pos_out = __which & ios::out;
    if (pos_in || pos_out)
    {
        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
        {
            off_type newoff = __sp;
            char* seekhigh = epptr() ? epptr() : egptr();
            if (0 <= newoff && newoff <= seekhigh - eback())
            {
                char* newpos = eback() + newoff;
                if (pos_in)
                    setg(eback(), newpos, max(newpos, egptr()));
                if (pos_out)
                {
                    // min(pbase, newpos), newpos, epptr()
                    off_type temp = epptr() - newpos;
                    setp(min(pbase(), newpos), epptr());
                    pbump(static_cast<int>((epptr() - pbase()) - temp));
                }
                __p = newoff;
            }
        }
    }
    return pos_type(__p);
}

istrstream::~istrstream()
{
}

ostrstream::~ostrstream()
{
}

strstream::~strstream()
{
}

_LIBCPP_END_NAMESPACE_STD
<|endoftext|>