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

#include "cli/CommandExecutor.hpp"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <string>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogDatabase.hpp"
#include "catalog/CatalogRelation.hpp"
#include "catalog/CatalogRelationSchema.hpp"
#include "cli/DropRelation.hpp"
#include "cli/PrintToScreen.hpp"
#include "parser/ParseStatement.hpp"
#include "parser/ParseString.hpp"
#include "parser/SqlParserWrapper.hpp"
#include "query_optimizer/QueryHandle.hpp"
#include "query_optimizer/QueryPlan.hpp"
#include "query_optimizer/QueryProcessor.hpp"
#include "storage/StorageBlock.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "storage/StorageManager.hpp"
#include "storage/TupleIdSequence.hpp"
#include "storage/TupleStorageSubBlock.hpp"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "utility/PtrVector.hpp"
#include "utility/SqlError.hpp"

#include "glog/logging.h"

#include "tmb/id_typedefs.h"

using std::fprintf;
using std::fputc;
using std::fputs;
using std::size_t;
using std::string;
using std::vector;

namespace tmb { class MessageBus; }

namespace quickstep {
namespace cli {
namespace {

namespace C = ::quickstep::cli;

void executeDescribeDatabase(
    const PtrVector<ParseString> *arguments,
    const CatalogDatabase &catalog_database,
    StorageManager *storage_manager,
    FILE *out) {
  // Column width initialized to 6 to take into account the header name
  // and the column value table
  int max_column_width = C::kInitMaxColumnWidth;
  vector<std::size_t> num_blocks;
  const CatalogRelation *relation = nullptr;
  if (arguments->size() == 0) {
    for (const CatalogRelation &rel : catalog_database) {
      max_column_width =
          std::max(static_cast<int>(rel.getName().length()), max_column_width);
      num_blocks.push_back(rel.size_blocks());
    }
  } else {
    const ParseString &table_name = arguments->front();
    const std::string &table_name_val = table_name.value();
    relation = catalog_database.getRelationByName(table_name_val);

    if (relation == nullptr) {
      THROW_SQL_ERROR_AT(&(arguments->front())) << " Unrecognized relation " << table_name_val;
    }
    max_column_width = std::max(static_cast<int>(relation->getName().length()),
                                    max_column_width);
    num_blocks.push_back(relation->size_blocks());
  }
  // Only if we have relations work on the printing logic.
  if (catalog_database.size() > 0) {
    const std::size_t max_num_blocks = *std::max_element(num_blocks.begin(), num_blocks.end());
    const int max_num_blocks_digits = std::max(PrintToScreen::GetNumberOfDigits(max_num_blocks),
                                      C::kInitMaxColumnWidth+2);
    vector<int> column_widths;
    column_widths.push_back(max_column_width +1);
    column_widths.push_back(C::kInitMaxColumnWidth + 1);
    column_widths.push_back(max_num_blocks_digits + 1);
    fputs("       List of relations\n\n", out);
    fprintf(out, "%-*s |", max_column_width+1, " Name");
    fprintf(out, "%-*s |", C::kInitMaxColumnWidth, " Type");
    fprintf(out, "%-*s\n", max_num_blocks_digits, " Blocks");
    PrintToScreen::printHBar(column_widths, out);
    //  If there are no argument print the entire list of tables
    //  else print the particular table only.
    vector<std::size_t>::const_iterator num_blocks_it = num_blocks.begin();
    if (arguments->size() == 0) {
      for (const CatalogRelation &rel : catalog_database) {
        fprintf(out, " %-*s |", max_column_width, rel.getName().c_str());
        fprintf(out, " %-*s |", C::kInitMaxColumnWidth - 1, "table");
        fprintf(out, " %-*lu\n", max_num_blocks_digits - 1, *num_blocks_it);
        ++num_blocks_it;
      }
    } else {
      fprintf(out, " %-*s |", max_column_width, relation->getName().c_str());
      fprintf(out, " %-*s |", C::kInitMaxColumnWidth -1, "table");
      fprintf(out, " %-*lu\n", max_num_blocks_digits - 1, *num_blocks_it);
      ++num_blocks_it;
    }
    fputc('\n', out);
  }
}

void executeDescribeTable(
    const PtrVector<ParseString> *arguments,
    const CatalogDatabase &catalog_database, FILE *out) {
  const ParseString &table_name = arguments->front();
  const std::string &table_name_val = table_name.value();
  const CatalogRelation *relation =
      catalog_database.getRelationByName(table_name_val);
  if (relation == nullptr) {
    THROW_SQL_ERROR_AT(&(arguments->front())) << " Unrecognized relation "  << table_name_val;
  }
  vector<int> column_widths;
  int max_attr_column_width = C::kInitMaxColumnWidth;
  int max_type_column_width = C::kInitMaxColumnWidth;

  for (const CatalogAttribute &attr : *relation) {
    // Printed column needs to be wide enough to print:
    //   1. The attribute name (in the printed "header").
    //   2. Any value of the attribute's Type.
    max_attr_column_width =
        std::max(max_attr_column_width,
            static_cast<int>(attr.getDisplayName().length()));
    max_type_column_width =
        std::max(max_type_column_width,
            static_cast<int>(attr.getType().getName().length()));
  }
  // Add room for one extra character to allow spacing between the column ending and the vertical bar
  column_widths.push_back(max_attr_column_width+1);
  column_widths.push_back(max_type_column_width+1);

  fprintf(out, "%*s \"%s\"\n", C::kInitMaxColumnWidth, "Table", table_name_val.c_str());
  fprintf(out, "%-*s |", max_attr_column_width+1, " Column");
  fprintf(out, "%-*s\n", max_type_column_width+1, " Type");
  PrintToScreen::printHBar(column_widths, out);
  for (const CatalogAttribute &attr : *relation) {
    fprintf(out, " %-*s |", max_attr_column_width,
            attr.getDisplayName().c_str());
    fprintf(out, " %-*s\n", max_type_column_width,
            attr.getType().getName().c_str());
  }
  // TODO(rogers): Add handlers for partitioning information.
  if (relation->hasIndexScheme()) {
    fprintf(out, "%*s\n", C::kInitMaxColumnWidth+2, " Indexes");
    const quickstep::IndexScheme &index_scheme = relation->getIndexScheme();
    for (auto index_it = index_scheme.begin(); index_it != index_scheme.end();
         ++index_it) {
      fprintf(out, "  \"%-*s\" %s", static_cast<int>(index_it->first.length()),
              index_it->first.c_str(),
              index_it->second.IndexSubBlockType_Name(
                  index_it->second.sub_block_type()).c_str());
      fputc(' ', out);
      fputc('(', out);
      fprintf(out, "%s", relation->getAttributeById(index_it->second.indexed_attribute_ids(0))
                             ->getDisplayName().c_str());
      for (std::size_t i = 1; i < static_cast<std::size_t>(index_it->second.indexed_attribute_ids_size()); ++i) {
        const char *attribute_display_name = relation->getAttributeById(
                                                 index_it->second.indexed_attribute_ids(i))
                                                     ->getDisplayName().c_str();
        fprintf(out, ", %s", attribute_display_name);
      }
      fputc(')', out);
      fputc('\n', out);
    }
  }
}

/**
 * @brief A helper function that executes a SQL query to obtain a scalar result.
 */
inline TypedValue executeQueryForSingleResult(
    const tmb::client_id main_thread_client_id,
    const tmb::client_id foreman_client_id,
    const std::string &query_string,
    tmb::MessageBus *bus,
    StorageManager *storage_manager,
    QueryProcessor *query_processor,
    SqlParserWrapper *parser_wrapper) {
  parser_wrapper->feedNextBuffer(new std::string(query_string));

  ParseResult result = parser_wrapper->getNextStatement();
  DCHECK(result.condition == ParseResult::kSuccess);

  const ParseStatement &statement = *result.parsed_statement;

  // Generate the query plan.
  std::unique_ptr<QueryHandle> query_handle(
      std::make_unique<QueryHandle>(query_processor->query_id(),
                                    main_thread_client_id,
                                    statement.getPriority()));
  query_processor->generateQueryHandle(statement, query_handle.get());
  DCHECK(query_handle->getQueryPlanMutable() != nullptr);

  // Use foreman to execute the query plan.
  QueryExecutionUtil::ConstructAndSendAdmitRequestMessage(
      main_thread_client_id, foreman_client_id, query_handle.get(), bus);

  QueryExecutionUtil::ReceiveQueryCompletionMessage(main_thread_client_id, bus);

  // Retrieve the scalar result from the result relation.
  const CatalogRelation *query_result_relation = query_handle->getQueryResultRelation();
  DCHECK(query_result_relation != nullptr);

  TypedValue value;
  {
    std::vector<block_id> blocks = query_result_relation->getBlocksSnapshot();
    DCHECK_EQ(1u, blocks.size());
    BlockReference block = storage_manager->getBlock(blocks[0], *query_result_relation);
    const TupleStorageSubBlock &tuple_store = block->getTupleStorageSubBlock();
    DCHECK_EQ(1, tuple_store.numTuples());
    DCHECK_EQ(1u, tuple_store.getRelation().size());

    if (tuple_store.isPacked()) {
      value = tuple_store.getAttributeValueTyped(0, 0);
    } else {
      std::unique_ptr<TupleIdSequence> existence_map(tuple_store.getExistenceMap());
      value = tuple_store.getAttributeValueTyped(*existence_map->begin(), 0);
    }
    value.ensureNotReference();
  }

  // Drop the result relation.
  DropRelation::Drop(*query_result_relation,
                     query_processor->getDefaultDatabase(),
                     query_processor->getStorageManager());

  return value;
}

void executeAnalyze(const tmb::client_id main_thread_client_id,
                    const tmb::client_id foreman_client_id,
                    MessageBus *bus,
                    QueryProcessor *query_processor,
                    FILE *out) {
  const CatalogDatabase &database = *query_processor->getDefaultDatabase();
  StorageManager *storage_manager = query_processor->getStorageManager();

  std::unique_ptr<SqlParserWrapper> parser_wrapper(new SqlParserWrapper());
  std::vector<std::reference_wrapper<const CatalogRelation>> relations(
      database.begin(), database.end());

  // Analyze each relation in the database.
  for (const CatalogRelation &relation : relations) {
    fprintf(out, "Analyzing %s ... ", relation.getName().c_str());
    fflush(out);

    CatalogRelation *mutable_relation =
        query_processor->getDefaultDatabase()->getRelationByIdMutable(relation.getID());

    // Get the number of distinct values for each column.
    for (const CatalogAttribute &attribute : relation) {
      std::string query_string = "SELECT COUNT(DISTINCT ";
      query_string.append(attribute.getName());
      query_string.append(") FROM ");
      query_string.append(relation.getName());
      query_string.append(";");

      TypedValue num_distinct_values =
          executeQueryForSingleResult(main_thread_client_id,
                                      foreman_client_id,
                                      query_string,
                                      bus,
                                      storage_manager,
                                      query_processor,
                                      parser_wrapper.get());

      DCHECK(num_distinct_values.getTypeID() == TypeID::kLong);
      mutable_relation->getStatisticsMutable()->setNumDistinctValues(
          attribute.getID(),
          num_distinct_values.getLiteral<std::int64_t>());
    }

    // Get the number of tuples for the relation.
    std::string query_string = "SELECT COUNT(*) FROM ";
    query_string.append(relation.getName());
    query_string.append(";");

    TypedValue num_tuples =
        executeQueryForSingleResult(main_thread_client_id,
                                    foreman_client_id,
                                    query_string,
                                    bus,
                                    storage_manager,
                                    query_processor,
                                    parser_wrapper.get());

    DCHECK(num_tuples.getTypeID() == TypeID::kLong);
    mutable_relation->getStatisticsMutable()->setNumTuples(
        num_tuples.getLiteral<std::int64_t>());

    fprintf(out, "done\n");
    fflush(out);
  }
  query_processor->markCatalogAltered();
  query_processor->saveCatalog();
}

}  // namespace

void executeCommand(const ParseStatement &statement,
                    const CatalogDatabase &catalog_database,
                    const tmb::client_id main_thread_client_id,
                    const tmb::client_id foreman_client_id,
                    MessageBus *bus,
                    StorageManager *storage_manager,
                    QueryProcessor *query_processor,
                    FILE *out) {
  const ParseCommand &command = static_cast<const ParseCommand &>(statement);
  const PtrVector<ParseString> *arguments = command.arguments();
  const std::string &command_str = command.command()->value();
  if (command_str == C::kDescribeDatabaseCommand) {
    executeDescribeDatabase(arguments, catalog_database, storage_manager, out);
  } else if (command_str == C::kDescribeTableCommand) {
    if (arguments->size() == 0) {
      executeDescribeDatabase(arguments, catalog_database, storage_manager, out);
    } else {
      executeDescribeTable(arguments, catalog_database, out);
    }
  } else if (command_str == C::kAnalyzeCommand) {
    executeAnalyze(
        main_thread_client_id, foreman_client_id, bus, query_processor, out);
  } else {
    THROW_SQL_ERROR_AT(command.command()) << "Invalid Command";
  }
}
}  // namespace cli
}  // namespace quickstep
<commit_msg>Enable \analyze command to be applied to specific tables<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#include "cli/CommandExecutor.hpp"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <string>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogDatabase.hpp"
#include "catalog/CatalogRelation.hpp"
#include "catalog/CatalogRelationSchema.hpp"
#include "cli/DropRelation.hpp"
#include "cli/PrintToScreen.hpp"
#include "parser/ParseStatement.hpp"
#include "parser/ParseString.hpp"
#include "parser/SqlParserWrapper.hpp"
#include "query_optimizer/QueryHandle.hpp"
#include "query_optimizer/QueryPlan.hpp"
#include "query_optimizer/QueryProcessor.hpp"
#include "storage/StorageBlock.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "storage/StorageManager.hpp"
#include "storage/TupleIdSequence.hpp"
#include "storage/TupleStorageSubBlock.hpp"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "utility/PtrVector.hpp"
#include "utility/SqlError.hpp"

#include "glog/logging.h"

#include "tmb/id_typedefs.h"

using std::fprintf;
using std::fputc;
using std::fputs;
using std::size_t;
using std::string;
using std::vector;

namespace tmb { class MessageBus; }

namespace quickstep {
namespace cli {
namespace {

namespace C = ::quickstep::cli;

void executeDescribeDatabase(
    const PtrVector<ParseString> *arguments,
    const CatalogDatabase &catalog_database,
    StorageManager *storage_manager,
    FILE *out) {
  // Column width initialized to 6 to take into account the header name
  // and the column value table
  int max_column_width = C::kInitMaxColumnWidth;
  vector<std::size_t> num_blocks;
  const CatalogRelation *relation = nullptr;
  if (arguments->size() == 0) {
    for (const CatalogRelation &rel : catalog_database) {
      max_column_width =
          std::max(static_cast<int>(rel.getName().length()), max_column_width);
      num_blocks.push_back(rel.size_blocks());
    }
  } else {
    const ParseString &table_name = arguments->front();
    const std::string &table_name_val = table_name.value();
    relation = catalog_database.getRelationByName(table_name_val);

    if (relation == nullptr) {
      THROW_SQL_ERROR_AT(&(arguments->front())) << " Unrecognized relation " << table_name_val;
    }
    max_column_width = std::max(static_cast<int>(relation->getName().length()),
                                    max_column_width);
    num_blocks.push_back(relation->size_blocks());
  }
  // Only if we have relations work on the printing logic.
  if (catalog_database.size() > 0) {
    const std::size_t max_num_blocks = *std::max_element(num_blocks.begin(), num_blocks.end());
    const int max_num_blocks_digits = std::max(PrintToScreen::GetNumberOfDigits(max_num_blocks),
                                      C::kInitMaxColumnWidth+2);
    vector<int> column_widths;
    column_widths.push_back(max_column_width +1);
    column_widths.push_back(C::kInitMaxColumnWidth + 1);
    column_widths.push_back(max_num_blocks_digits + 1);
    fputs("       List of relations\n\n", out);
    fprintf(out, "%-*s |", max_column_width+1, " Name");
    fprintf(out, "%-*s |", C::kInitMaxColumnWidth, " Type");
    fprintf(out, "%-*s\n", max_num_blocks_digits, " Blocks");
    PrintToScreen::printHBar(column_widths, out);
    //  If there are no argument print the entire list of tables
    //  else print the particular table only.
    vector<std::size_t>::const_iterator num_blocks_it = num_blocks.begin();
    if (arguments->size() == 0) {
      for (const CatalogRelation &rel : catalog_database) {
        fprintf(out, " %-*s |", max_column_width, rel.getName().c_str());
        fprintf(out, " %-*s |", C::kInitMaxColumnWidth - 1, "table");
        fprintf(out, " %-*lu\n", max_num_blocks_digits - 1, *num_blocks_it);
        ++num_blocks_it;
      }
    } else {
      fprintf(out, " %-*s |", max_column_width, relation->getName().c_str());
      fprintf(out, " %-*s |", C::kInitMaxColumnWidth -1, "table");
      fprintf(out, " %-*lu\n", max_num_blocks_digits - 1, *num_blocks_it);
      ++num_blocks_it;
    }
    fputc('\n', out);
  }
}

void executeDescribeTable(
    const PtrVector<ParseString> *arguments,
    const CatalogDatabase &catalog_database, FILE *out) {
  const ParseString &table_name = arguments->front();
  const std::string &table_name_val = table_name.value();
  const CatalogRelation *relation =
      catalog_database.getRelationByName(table_name_val);
  if (relation == nullptr) {
    THROW_SQL_ERROR_AT(&(arguments->front())) << " Unrecognized relation "  << table_name_val;
  }
  vector<int> column_widths;
  int max_attr_column_width = C::kInitMaxColumnWidth;
  int max_type_column_width = C::kInitMaxColumnWidth;

  for (const CatalogAttribute &attr : *relation) {
    // Printed column needs to be wide enough to print:
    //   1. The attribute name (in the printed "header").
    //   2. Any value of the attribute's Type.
    max_attr_column_width =
        std::max(max_attr_column_width,
            static_cast<int>(attr.getDisplayName().length()));
    max_type_column_width =
        std::max(max_type_column_width,
            static_cast<int>(attr.getType().getName().length()));
  }
  // Add room for one extra character to allow spacing between the column ending and the vertical bar
  column_widths.push_back(max_attr_column_width+1);
  column_widths.push_back(max_type_column_width+1);

  fprintf(out, "%*s \"%s\"\n", C::kInitMaxColumnWidth, "Table", table_name_val.c_str());
  fprintf(out, "%-*s |", max_attr_column_width+1, " Column");
  fprintf(out, "%-*s\n", max_type_column_width+1, " Type");
  PrintToScreen::printHBar(column_widths, out);
  for (const CatalogAttribute &attr : *relation) {
    fprintf(out, " %-*s |", max_attr_column_width,
            attr.getDisplayName().c_str());
    fprintf(out, " %-*s\n", max_type_column_width,
            attr.getType().getName().c_str());
  }
  // TODO(rogers): Add handlers for partitioning information.
  if (relation->hasIndexScheme()) {
    fprintf(out, "%*s\n", C::kInitMaxColumnWidth+2, " Indexes");
    const quickstep::IndexScheme &index_scheme = relation->getIndexScheme();
    for (auto index_it = index_scheme.begin(); index_it != index_scheme.end();
         ++index_it) {
      fprintf(out, "  \"%-*s\" %s", static_cast<int>(index_it->first.length()),
              index_it->first.c_str(),
              index_it->second.IndexSubBlockType_Name(
                  index_it->second.sub_block_type()).c_str());
      fputc(' ', out);
      fputc('(', out);
      fprintf(out, "%s", relation->getAttributeById(index_it->second.indexed_attribute_ids(0))
                             ->getDisplayName().c_str());
      for (std::size_t i = 1; i < static_cast<std::size_t>(index_it->second.indexed_attribute_ids_size()); ++i) {
        const char *attribute_display_name = relation->getAttributeById(
                                                 index_it->second.indexed_attribute_ids(i))
                                                     ->getDisplayName().c_str();
        fprintf(out, ", %s", attribute_display_name);
      }
      fputc(')', out);
      fputc('\n', out);
    }
  }
}

/**
 * @brief A helper function that executes a SQL query to obtain a row of results.
 */
inline std::vector<TypedValue> executeQueryForSingleRow(
    const tmb::client_id main_thread_client_id,
    const tmb::client_id foreman_client_id,
    const std::string &query_string,
    tmb::MessageBus *bus,
    StorageManager *storage_manager,
    QueryProcessor *query_processor,
    SqlParserWrapper *parser_wrapper) {
  parser_wrapper->feedNextBuffer(new std::string(query_string));

  ParseResult result = parser_wrapper->getNextStatement();
  DCHECK(result.condition == ParseResult::kSuccess);

  const ParseStatement &statement = *result.parsed_statement;

  // Generate the query plan.
  std::unique_ptr<QueryHandle> query_handle(
      std::make_unique<QueryHandle>(query_processor->query_id(),
                                    main_thread_client_id,
                                    statement.getPriority()));
  query_processor->generateQueryHandle(statement, query_handle.get());
  DCHECK(query_handle->getQueryPlanMutable() != nullptr);

  // Use foreman to execute the query plan.
  QueryExecutionUtil::ConstructAndSendAdmitRequestMessage(
      main_thread_client_id, foreman_client_id, query_handle.get(), bus);

  QueryExecutionUtil::ReceiveQueryCompletionMessage(main_thread_client_id, bus);

  // Retrieve the scalar result from the result relation.
  const CatalogRelation *query_result_relation = query_handle->getQueryResultRelation();
  DCHECK(query_result_relation != nullptr);

  std::vector<TypedValue> values;
  {
    std::vector<block_id> blocks = query_result_relation->getBlocksSnapshot();
    DCHECK_EQ(1u, blocks.size());

    BlockReference block = storage_manager->getBlock(blocks[0], *query_result_relation);
    const TupleStorageSubBlock &tuple_store = block->getTupleStorageSubBlock();
    DCHECK_EQ(1, tuple_store.numTuples());

    const std::size_t num_columns = tuple_store.getRelation().size();
    if (tuple_store.isPacked()) {
      for (std::size_t i = 0; i < num_columns; ++i) {
        values.emplace_back(tuple_store.getAttributeValueTyped(0, i));
        values[i].ensureNotReference();
      }
    } else {
      std::unique_ptr<TupleIdSequence> existence_map(tuple_store.getExistenceMap());
      for (std::size_t i = 0; i < num_columns; ++i) {
        values.emplace_back(
            tuple_store.getAttributeValueTyped(*existence_map->begin(), i));
        values[i].ensureNotReference();
      }
    }
  }

  // Drop the result relation.
  DropRelation::Drop(*query_result_relation,
                     query_processor->getDefaultDatabase(),
                     query_processor->getStorageManager());

  return values;
}

/**
 * @brief A helper function that executes a SQL query to obtain a scalar result.
 */
inline TypedValue executeQueryForSingleResult(
    const tmb::client_id main_thread_client_id,
    const tmb::client_id foreman_client_id,
    const std::string &query_string,
    tmb::MessageBus *bus,
    StorageManager *storage_manager,
    QueryProcessor *query_processor,
    SqlParserWrapper *parser_wrapper) {
  std::vector<TypedValue> results =
      executeQueryForSingleRow(main_thread_client_id,
                               foreman_client_id,
                               query_string,
                               bus,
                               storage_manager,
                               query_processor,
                               parser_wrapper);
  DCHECK_EQ(1u, results.size());
  return results[0];
}

void executeAnalyze(const PtrVector<ParseString> *arguments,
                    const tmb::client_id main_thread_client_id,
                    const tmb::client_id foreman_client_id,
                    MessageBus *bus,
                    QueryProcessor *query_processor,
                    FILE *out) {
  const CatalogDatabase &database = *query_processor->getDefaultDatabase();
  StorageManager *storage_manager = query_processor->getStorageManager();

  std::unique_ptr<SqlParserWrapper> parser_wrapper(new SqlParserWrapper());
  std::vector<std::reference_wrapper<const CatalogRelation>> relations;
  if (arguments->size() == 0) {
    relations.insert(relations.begin(), database.begin(), database.end());
  } else {
    for (const auto &rel_name : *arguments) {
      const CatalogRelation *rel = database.getRelationByName(rel_name.value());
      if (rel == nullptr) {
        THROW_SQL_ERROR_AT(&rel_name) << "Table does not exist";
      } else {
        relations.emplace_back(*rel);
      }
    }
  }

  // Analyze each relation in the database.
  for (const CatalogRelation &relation : relations) {
    fprintf(out, "Analyzing %s ... ", relation.getName().c_str());
    fflush(out);

    CatalogRelation *mutable_relation =
        query_processor->getDefaultDatabase()->getRelationByIdMutable(relation.getID());

    // Get the number of distinct values for each column.
    for (const CatalogAttribute &attribute : relation) {
      std::string query_string = "SELECT COUNT(DISTINCT ";
      query_string.append(attribute.getName());
      query_string.append(") FROM ");
      query_string.append(relation.getName());
      query_string.append(";");

      std::vector<TypedValue> results =
          executeQueryForSingleRow(main_thread_client_id,
                                   foreman_client_id,
                                   query_string,
                                   bus,
                                   storage_manager,
                                   query_processor,
                                   parser_wrapper.get());

      auto *stat = mutable_relation->getStatisticsMutable();
      const attribute_id attr_id = attribute.getID();

      DCHECK(results[0].getTypeID() == TypeID::kLong);
      stat->setNumDistinctValues(attr_id,
                                 results[0].getLiteral<std::int64_t>());
    }

    // Get the number of tuples for the relation.
    std::string query_string = "SELECT COUNT(*) FROM ";
    query_string.append(relation.getName());
    query_string.append(";");

    TypedValue num_tuples =
        executeQueryForSingleResult(main_thread_client_id,
                                    foreman_client_id,
                                    query_string,
                                    bus,
                                    storage_manager,
                                    query_processor,
                                    parser_wrapper.get());

    DCHECK(num_tuples.getTypeID() == TypeID::kLong);
    mutable_relation->getStatisticsMutable()->setNumTuples(
        num_tuples.getLiteral<std::int64_t>());

    fprintf(out, "done\n");
    fflush(out);
  }
  query_processor->markCatalogAltered();
  query_processor->saveCatalog();
}

}  // namespace

void executeCommand(const ParseStatement &statement,
                    const CatalogDatabase &catalog_database,
                    const tmb::client_id main_thread_client_id,
                    const tmb::client_id foreman_client_id,
                    MessageBus *bus,
                    StorageManager *storage_manager,
                    QueryProcessor *query_processor,
                    FILE *out) {
  const ParseCommand &command = static_cast<const ParseCommand &>(statement);
  const PtrVector<ParseString> *arguments = command.arguments();
  const std::string &command_str = command.command()->value();
  if (command_str == C::kDescribeDatabaseCommand) {
    executeDescribeDatabase(arguments, catalog_database, storage_manager, out);
  } else if (command_str == C::kDescribeTableCommand) {
    if (arguments->size() == 0) {
      executeDescribeDatabase(arguments, catalog_database, storage_manager, out);
    } else {
      executeDescribeTable(arguments, catalog_database, out);
    }
  } else if (command_str == C::kAnalyzeCommand) {
    executeAnalyze(arguments,
                   main_thread_client_id,
                   foreman_client_id,
                   bus,
                   query_processor, out);
  } else {
    THROW_SQL_ERROR_AT(command.command()) << "Invalid Command";
  }
}
}  // namespace cli
}  // namespace quickstep
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "amr_forestclaw.H"

// This needs to go away.  The p4est namespace should not be used directly.
#include <p4est.h>

int
main (int argc, char **argv)
{
  int			mpiret;
  int			lp;
  MPI_Comm		mpicomm;
  sc_options_t          *options;
  fclaw2d_domain_t	*domain;
  amr_options_t         *gparms;

  mpiret = MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = MPI_COMM_WORLD;
  lp = SC_LP_PRODUCTION;

  sc_init (mpicomm, 0, 0, NULL, lp);
  p4est_init (NULL, lp);

  /* propose option handling as present in p4est/libsc */
  /* the option values live in amr_options, see amr_options.h */
  options = sc_options_new (argv[0]);
  gparms = amr_options_new (options); // Sets default values
  amr_options_parse (options, gparms, argc, argv, lp);  // Reads options from a file

  /* -----------------------------------------------------------------*/
  /* Sample user defined options */
  /* -----------------------------------------------------------------*/

  domain = fclaw2d_domain_new_unitsquare (mpicomm, gparms->minlevel);

  fclaw2d_domain_list_levels(domain, lp);
  fclaw2d_domain_list_neighbors(domain, lp);

  amrinit(&domain, gparms);
  amrrun(&domain);
  amrreset(&domain);

  sc_options_destroy (options);         /* this could be moved up */
  amr_options_destroy (gparms);
  sc_finalize ();

  mpiret = MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
<commit_msg>Update swirl to compile<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "amr_forestclaw.H"

// This needs to go away.  The p4est namespace should not be used directly.
#include <p4est.h>

int
main (int argc, char **argv)
{
  int			mpiret;
  int			lp;
  MPI_Comm		mpicomm;
  sc_options_t          *options;
  fclaw2d_domain_t	*domain;
  amr_options_t         *gparms;

  mpiret = MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = MPI_COMM_WORLD;
  lp = SC_LP_PRODUCTION;

  sc_init (mpicomm, 0, 0, NULL, lp);
  p4est_init (NULL, lp);

  /* propose option handling as present in p4est/libsc */
  /* the option values live in amr_options, see amr_options.h */
  options = sc_options_new (argv[0]);
  gparms = amr_options_new (options); // Sets default values
  amr_options_parse (options, gparms, argc, argv, lp);  // Reads options from a file

  /* -----------------------------------------------------------------*/
  /* Sample user defined options */
  /* -----------------------------------------------------------------*/

  domain = fclaw2d_domain_new_unitsquare (mpicomm, gparms->minlevel);

  fclaw2d_domain_list_levels(domain, lp);
  fclaw2d_domain_list_neighbors(domain, lp);

  amrinit(&domain);
  amrrun(&domain);
  amrreset(&domain);

  sc_options_destroy (options);         /* this could be moved up */
  amr_options_destroy (gparms);
  sc_finalize ();

  mpiret = MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
<|endoftext|>


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

#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/features/organized_edge_detection.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <sensor_msgs/PointCloud2.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

float default_th_dd = 0.02;
int   default_max_search = 50;

typedef pcl::PointCloud<pcl::PointXYZRGBA> Cloud;
typedef Cloud::Ptr CloudPtr;
typedef Cloud::ConstPtr CloudConstPtr;

pcl::visualization::PCLVisualizer viewer ("3D Edge Viewer");

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -th_dd X       = the tolerance in meters for difference in depth values between neighboring points (The value is set for 1 meter and is adapted with respect to depth value linearly. (e.g. 2.0*th_dd in 2 meter depth)) (default: ");
  print_value ("%f", default_th_dd); print_info (")\n");
  print_info ("                     -max_search X  = the max search distance for deciding occluding and occluded edges (default: ");
  print_value ("%d", default_max_search); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), true); // Save as binary

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

void keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*)
{
  double opacity;
  if (event.keyUp())
  {
    switch (event.getKeyCode())
    {
      case '1':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "nan boundary edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "nan boundary edges");
        break;
      case '2':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "occluding edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "occluding edges");
        break;
      case '3':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "occluded edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "occluded edges");
        break;
      case '4':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "high curvature edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "high curvature edges");
        break;
      case '5':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "rgb edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "rgb edges");
        break;
    }
  }
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         float th_dd, int max_search)
{
  CloudPtr cloud (new Cloud);
  fromROSMsg (*input, *cloud);

  TicToc tt;
  tt.tic ();
  OrganizedEdgeDetection<PointXYZRGBA, Label> oed;
  oed.setInputCloud (cloud);
  oed.setDepthDisconThreshold (th_dd);
  oed.setMaxSearchNeighbors (max_search);
  //oed.setEdgeType (oed.EDGELABEL_OCCLUDING);
  //oed.setEdgeType (oed.EDGELABEL_HIGH_CURVATURE);
  //oed.setEdgeType (oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED);
  oed.setEdgeType (oed.EDGELABEL_NAN_BOUNDARY | oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED | oed.EDGELABEL_HIGH_CURVATURE | oed.EDGELABEL_RGB_CANNY);
  PointCloud<Label> labels;
  std::vector<PointIndices> label_indices;
  oed.compute (labels, label_indices);
  print_info ("Detecting all edges... [done, "); print_value ("%g", tt.toc ()); print_info (" ms]\n");

  // Make gray point clouds
  for (int idx = 0; idx < (int)cloud->points.size (); idx++)
  {
    uint8_t gray = (cloud->points[idx].r + cloud->points[idx].g + cloud->points[idx].b)/3;
    cloud->points[idx].r = cloud->points[idx].g = cloud->points[idx].b = gray;
  }

  // Display edges in PCLVisualizer
  viewer.setSize (640, 480);
  viewer.addCoordinateSystem (0.2f);
  viewer.addPointCloud (cloud, "original point cloud");
  viewer.registerKeyboardCallback(&keyboard_callback);

  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr occluding_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    occluded_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    nan_boundary_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    high_curvature_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    rgb_edges (new pcl::PointCloud<pcl::PointXYZRGBA>);

  for (int idx = 0; idx < (int)cloud->points.size (); idx++)
  {
    if (labels.points[idx].label & oed.EDGELABEL_NAN_BOUNDARY)
      nan_boundary_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_OCCLUDING)
      occluding_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_OCCLUDED)
      occluded_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_HIGH_CURVATURE)
      high_curvature_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_RGB_CANNY)
      rgb_edges->points.push_back (cloud->points[idx]);
  }

  const int point_size = 2;
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> nan_boundary_edges_color_handler (nan_boundary_edges, 0, 0, 255);
  viewer.addPointCloud<pcl::PointXYZRGBA> (nan_boundary_edges, nan_boundary_edges_color_handler, "nan boundary edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "nan boundary edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> occulding_edges_color_handler (occluding_edges, 0, 255, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (occluding_edges, occulding_edges_color_handler, "occluding edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "occluding edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> occluded_edges_color_handler (occluded_edges, 255, 0, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (occluded_edges, occluded_edges_color_handler, "occluded edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "occluded edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> high_curvature_edges_color_handler (high_curvature_edges, 255, 255, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (high_curvature_edges, high_curvature_edges_color_handler, "high curvature edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "high curvature edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> rgb_edges_color_handler (rgb_edges, 0, 255, 255);
  viewer.addPointCloud<pcl::PointXYZRGBA> (rgb_edges, rgb_edges_color_handler, "rgb edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "rgb edges");

  while (!viewer.wasStopped ())
  {
    viewer.spinOnce ();
    pcl_sleep(0.1);
  }

  // Combine point clouds and edge labels
  sensor_msgs::PointCloud2 output_edges;
  toROSMsg (labels, output_edges);
  concatenateFields (*input, output_edges, output);
}

int
main (int argc, char** argv)
{
  print_info ("Detect 3D edges from organized point cloud data. For more information, use: %s -h\n", argv[0]);
  bool help = false;
  parse_argument (argc, argv, "-h", help);
  if (argc < 3 || help)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  float th_dd = default_th_dd;
  int max_search = default_max_search;

  parse_argument (argc, argv, "-th_dd", th_dd);
  parse_argument (argc, argv, "-max_search", max_search);

  print_info ("th_dd: "); print_value ("%f\n", th_dd);
  print_info ("max_search: "); print_value ("%d\n", max_search);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;

  compute (cloud, output, th_dd, max_search);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

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

#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/features/organized_edge_detection.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <sensor_msgs/PointCloud2.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

float default_th_dd = 0.02f;
int   default_max_search = 50;

typedef pcl::PointCloud<pcl::PointXYZRGBA> Cloud;
typedef Cloud::Ptr CloudPtr;
typedef Cloud::ConstPtr CloudConstPtr;

pcl::visualization::PCLVisualizer viewer ("3D Edge Viewer");

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -th_dd X       = the tolerance in meters for difference in depth values between neighboring points (The value is set for 1 meter and is adapted with respect to depth value linearly. (e.g. 2.0*th_dd in 2 meter depth)) (default: ");
  print_value ("%f", default_th_dd); print_info (")\n");
  print_info ("                     -max_search X  = the max search distance for deciding occluding and occluded edges (default: ");
  print_value ("%d", default_max_search); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), true); // Save as binary

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

void keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*)
{
  double opacity;
  if (event.keyUp())
  {
    switch (event.getKeyCode())
    {
      case '1':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "nan boundary edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "nan boundary edges");
        break;
      case '2':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "occluding edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "occluding edges");
        break;
      case '3':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "occluded edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "occluded edges");
        break;
      case '4':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "high curvature edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "high curvature edges");
        break;
      case '5':
        viewer.getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, "rgb edges");
        viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1.0-opacity, "rgb edges");
        break;
    }
  }
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         float th_dd, int max_search)
{
  CloudPtr cloud (new Cloud);
  fromROSMsg (*input, *cloud);

  TicToc tt;
  tt.tic ();
  OrganizedEdgeDetection<PointXYZRGBA, Label> oed;
  oed.setInputCloud (cloud);
  oed.setDepthDisconThreshold (th_dd);
  oed.setMaxSearchNeighbors (max_search);
  //oed.setEdgeType (oed.EDGELABEL_OCCLUDING);
  //oed.setEdgeType (oed.EDGELABEL_HIGH_CURVATURE);
  //oed.setEdgeType (oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED);
  oed.setEdgeType (oed.EDGELABEL_NAN_BOUNDARY | oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED | oed.EDGELABEL_HIGH_CURVATURE | oed.EDGELABEL_RGB_CANNY);
  PointCloud<Label> labels;
  std::vector<PointIndices> label_indices;
  oed.compute (labels, label_indices);
  print_info ("Detecting all edges... [done, "); print_value ("%g", tt.toc ()); print_info (" ms]\n");

  // Make gray point clouds
  for (int idx = 0; idx < int (cloud->points.size ()); idx++)
  {
    uint8_t gray = uint8_t ((cloud->points[idx].r + cloud->points[idx].g + cloud->points[idx].b) / 3);
    cloud->points[idx].r = cloud->points[idx].g = cloud->points[idx].b = gray;
  }

  // Display edges in PCLVisualizer
  viewer.setSize (640, 480);
  viewer.addCoordinateSystem (0.2f);
  viewer.addPointCloud (cloud, "original point cloud");
  viewer.registerKeyboardCallback(&keyboard_callback);

  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr occluding_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    occluded_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    nan_boundary_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    high_curvature_edges (new pcl::PointCloud<pcl::PointXYZRGBA>),
    rgb_edges (new pcl::PointCloud<pcl::PointXYZRGBA>);

  for (int idx = 0; idx < int (cloud->points.size ()); idx++)
  {
    if (labels.points[idx].label & oed.EDGELABEL_NAN_BOUNDARY)
      nan_boundary_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_OCCLUDING)
      occluding_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_OCCLUDED)
      occluded_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_HIGH_CURVATURE)
      high_curvature_edges->points.push_back (cloud->points[idx]);
    if (labels.points[idx].label & oed.EDGELABEL_RGB_CANNY)
      rgb_edges->points.push_back (cloud->points[idx]);
  }

  const int point_size = 2;
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> nan_boundary_edges_color_handler (nan_boundary_edges, 0, 0, 255);
  viewer.addPointCloud<pcl::PointXYZRGBA> (nan_boundary_edges, nan_boundary_edges_color_handler, "nan boundary edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "nan boundary edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> occulding_edges_color_handler (occluding_edges, 0, 255, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (occluding_edges, occulding_edges_color_handler, "occluding edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "occluding edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> occluded_edges_color_handler (occluded_edges, 255, 0, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (occluded_edges, occluded_edges_color_handler, "occluded edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "occluded edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> high_curvature_edges_color_handler (high_curvature_edges, 255, 255, 0);
  viewer.addPointCloud<pcl::PointXYZRGBA> (high_curvature_edges, high_curvature_edges_color_handler, "high curvature edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "high curvature edges");

  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGBA> rgb_edges_color_handler (rgb_edges, 0, 255, 255);
  viewer.addPointCloud<pcl::PointXYZRGBA> (rgb_edges, rgb_edges_color_handler, "rgb edges");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, "rgb edges");

  while (!viewer.wasStopped ())
  {
    viewer.spinOnce ();
    boost::this_thread::sleep (boost::posix_time::microseconds (100));
  }

  // Combine point clouds and edge labels
  sensor_msgs::PointCloud2 output_edges;
  toROSMsg (labels, output_edges);
  concatenateFields (*input, output_edges, output);
}

int
main (int argc, char** argv)
{
  print_info ("Detect 3D edges from organized point cloud data. For more information, use: %s -h\n", argv[0]);
  bool help = false;
  parse_argument (argc, argv, "-h", help);
  if (argc < 3 || help)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  float th_dd = default_th_dd;
  int max_search = default_max_search;

  parse_argument (argc, argv, "-th_dd", th_dd);
  parse_argument (argc, argv, "-max_search", max_search);

  print_info ("th_dd: "); print_value ("%f\n", th_dd);
  print_info ("max_search: "); print_value ("%d\n", max_search);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;

  compute (cloud, output, th_dd, max_search);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

<|endoftext|>


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

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

All rights reserved.

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 "itkImage.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkImageFileWriter.h"

#include "../itkBlur3DImageFunction.h"

int itkBlur3DImageFunctionTest(int argc, char * argv[])
  {
  if(argc != 2)
    {
    std::cout <<
      "Usage: itkBlur3DImageFunctionTest <outputFilename>" << std::endl;
    return EXIT_FAILURE;
    }

  typedef itk::Image<float, 3>   ImageType;
  typedef ImageType::SizeType    ImageSizeType;
  typedef ImageType::SpacingType ImageSpacingType;

  ImageType::Pointer im = ImageType::New();
  ImageSizeType imSize;
  imSize[0] = 20;
  imSize[1] = 20;
  imSize[2] = 10;
  im->SetRegions(imSize);
  ImageSpacingType imSpacing;
  imSpacing[0] = 1;
  imSpacing[1] = 1;
  imSpacing[2] = 2;
  im->SetSpacing(imSpacing);

  im->Allocate();
  im->FillBuffer( 0 );

  ImageType::IndexType index;
  index[0] = 10;
  index[1] = 10;
  index[2] = 5;
  im->SetPixel(index, 100);

  typedef itk::Blur3DImageFunction<ImageType> ImageOpType;
  ImageOpType::Pointer imOp = ImageOpType::New();

  imOp->SetInputImage(im);
  imOp->SetScale(2);

  ImageType::Pointer imOut = ImageType::New();
  imOut->SetRegions(imSize);
  imOut->SetSpacing(imSpacing);
  imOut->Allocate();

  itk::ImageRegionIteratorWithIndex<ImageType> itOut(imOut,
    imOut->GetLargestPossibleRegion());
  ImageType::PointType pnt;
  unsigned int count = 0;
  itOut.GoToBegin();
  while(!itOut.IsAtEnd())
    {
    if( count/2.0 == count/2 )
      {
      itOut.Set( imOp->EvaluateAtIndex( itOut.GetIndex() ) );
      }
    else
      {
      imOut->TransformIndexToPhysicalPoint( itOut.GetIndex(), pnt );
      itOut.Set( imOp->Evaluate( pnt ) );
      }
    ++itOut;
    }

  typedef itk::ImageFileWriter<ImageType> ImageWriterType;
  ImageWriterType::Pointer imWriter = ImageWriterType::New();
  imWriter->SetFileName(argv[1]);
  imWriter->SetInput(imOut);
  imWriter->Update();

  return EXIT_SUCCESS;
  }

<commit_msg>ENH: Extended test to include non-zero index image<commit_after>/*=========================================================================

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

All rights reserved.

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 "itkImage.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkImageFileWriter.h"

#include "../itkBlur3DImageFunction.h"

int itkBlur3DImageFunctionTest( int argc, char * argv[] )
  {
  if( argc != 2 )
    {
    std::cout <<
      "Usage: itkBlur3DImageFunctionTest <outputFilename>" << std::endl;
    return EXIT_FAILURE;
    }

  typedef itk::Image<float, 3>   ImageType;
  typedef ImageType::SizeType    ImageSizeType;
  typedef ImageType::SpacingType ImageSpacingType;

  ImageType::Pointer im = ImageType::New( );

  ImageType::RegionType imRegion;

  ImageSizeType imSize;
  imSize[0] = 20;
  imSize[1] = 20;
  imSize[2] = 10;
  imRegion.SetSize( imSize );

  ImageType::IndexType index0;
  index0[0] = 10;
  index0[1] = 10;
  index0[2] = 10;
  imRegion.SetIndex( index0 );

  im->SetRegions( imRegion );

  ImageSpacingType imSpacing;
  imSpacing[0] = 1;
  imSpacing[1] = 1;
  imSpacing[2] = 2;
  im->SetSpacing( imSpacing );

  im->Allocate( );
  im->FillBuffer( 0 );

  ImageType::IndexType index;
  index[0] = 20;
  index[1] = 20;
  index[2] = 15;
  im->SetPixel( index, 100 );

  typedef itk::Blur3DImageFunction<ImageType> ImageOpType;
  ImageOpType::Pointer imOp = ImageOpType::New( );

  imOp->SetInputImage( im );
  imOp->SetScale( 2 );

  ImageType::Pointer imOut = ImageType::New( );
  imOut->SetRegions( imRegion );
  imOut->SetSpacing( imSpacing );
  imOut->Allocate( );

  itk::ImageRegionIteratorWithIndex<ImageType> itOut( imOut,
    imOut->GetLargestPossibleRegion( ) );
  ImageType::PointType pnt;
  unsigned int count = 0;
  itOut.GoToBegin( );
  while( !itOut.IsAtEnd( ) )
    {
    if( count/2.0 == count/2 )
      {
      itOut.Set( imOp->EvaluateAtIndex( itOut.GetIndex( ) ) );
      }
    else
      {
      imOut->TransformIndexToPhysicalPoint( itOut.GetIndex( ), pnt );
      itOut.Set( imOp->Evaluate( pnt ) );
      }
    ++itOut;
    }

  typedef itk::ImageFileWriter<ImageType> ImageWriterType;
  ImageWriterType::Pointer imWriter = ImageWriterType::New( );
  imWriter->SetFileName( argv[1] );
  imWriter->SetInput( imOut );
  imWriter->Update( );

  return EXIT_SUCCESS;
  }

<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2010 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Simple test of the Binary Coded GrayCode Phase Shift code
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "GrayCode.h"
#include <wcl/camera/CameraException.h>
#include <wcl/camera/CameraFactory.h>

#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define TIMER_VALUE 500
#define CROSS_DENSITY 100

using namespace std;
using namespace wcl;

GLvoid captureTimer(int value );

bool automated=false;
bool capturing=false;
unsigned image=0;
int window1, window2;
GrayCode g(IMAGE_WIDTH, IMAGE_HEIGHT);

// The in use camera
Camera *camera;

// Buffers for frame detection
unsigned char **buffers;

void init()
{
	buffers = new unsigned char *[g.getRequiredImageCount()];
	for( unsigned i = 0; i < g.getRequiredImageCount(); i++ )
	    buffers[i] = new unsigned char [IMAGE_WIDTH * IMAGE_HEIGHT];
}

GLvoid reshape(int width, int height)
{
	glViewport(0,0, (GLsizei)width, (GLsizei)height);
}

void keyboard(unsigned char key, int w, int h)
{
    if(key==27)
	exit(EXIT_SUCCESS);
    if(key==114 /* r */){
	g.reset();
	capturing=true;
	cout << "Reset" <<endl;;
    }
    if(key=='v'){
	cout << "Decoding GrayCode Ignoring Camera" << endl;
	g.decode((const unsigned char **)g.getCodedImages());
    }
    if(key==13){
	if( capturing == true ){
	    if(!g.next()){
		g.reset();
	    }
	}
	capturing=true;
    }
    if(key == 'a' ){
	automated=true;
	g.reset();
	image = 0;
	capturing=true;
	glutTimerFunc(TIMER_VALUE,captureTimer,0);
    }
}

void drawCross(const unsigned x, const unsigned y)
{
    glBegin(GL_LINE);
    glVertex3d(x>5?x-5:0,y,0);
    glVertex3d(x+5,y,0);
    glEnd();
    glBegin(GL_LINES);
    glVertex3d(x,y>5?y-5:0,0);
    glVertex3d(x,y+5,0);
    glEnd();
}

GLvoid displayProjector()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPixelZoom(1.0f, -1.0f);
	glRasterPos2i(-1, 1);

	if( capturing )
	    glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, g.generate());
	else {
	    glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, g.getDebugImage());

	    glOrtho(0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, -1.0, 1.0);

	    for(unsigned y=0; y < IMAGE_HEIGHT; y+=CROSS_DENSITY){
		for(unsigned x=0; x < IMAGE_WIDTH; x+=CROSS_DENSITY){
		    Vector v(2);
		    v[0]=x;
		    v[1]=y;
		    v = g.getRowCol(v);
		    glColor3f(0.3,0.0,0.0);
		    drawCross(x,y);
		    glColor3f(0.0,0.0,1.0);
		    drawCross(v[0],v[1]);
		}
	    }
	}

	glFlush();
	glutSwapBuffers();
}

GLvoid displayCamera()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPixelZoom(1.0f, -1.0f);
	glRasterPos2i(-1, 1);
	glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, camera->getFrame(Camera::RGB8));

	glFlush();
	glutSwapBuffers();
}

/**
 * Constantly fetch a new image from the camera to display
 */
GLvoid idle()
{
    glutSetWindow(window1);
    glutPostRedisplay();
    glutSetWindow(window2);
    glutPostRedisplay();
}

GLvoid captureTimer(int value )
{
    static bool display = true;
    static bool first=true;
    if(capturing)
    {
	if( display ) {
	    if( !first ){
		if(g.next() == false ){
		    capturing=false;
		    display=true;
		    first=true;
		    cout << "Decoding GrayCode" << endl;
		    g.decode((const unsigned char **)buffers);
		}
	    } else {
		first=false;
	    }
	    glutSetWindow(window1);
	    glutPostRedisplay();
	    glutSetWindow(window2);
	    glutPostRedisplay();
	    display=false;
	} else {
	    cout << "Capturing Image" << image << endl;
	    memcpy(buffers[image],camera->getFrame(Camera::MONO8),IMAGE_WIDTH * IMAGE_HEIGHT);
	    image++;
	    display=true;
	}
	if( automated ){
	    glutTimerFunc(TIMER_VALUE,captureTimer,0);
	}
    }

}

int main(int argc, char** argv)
{
    try {
	if(argc < 2 ){
	    Camera::Configuration config;
	    config.width=IMAGE_WIDTH;
	    config.height=IMAGE_HEIGHT;
	    camera = CameraFactory::findCamera(config);
	} else {
	    camera = CameraFactory::getCamera(argv[1]);
	    Camera::Configuration config = camera->getActiveConfiguration();
	    config.width=IMAGE_WIDTH;
	    config.height=IMAGE_HEIGHT;
	    camera->setConfiguration(config);
	}
    } catch(CameraException &e)
    {
	cout << "CameraException:" << e.what() << endl;
	exit(0);
    }

    if ( camera == NULL ){
	cout << "Camera Not Found" << endl;
	exit(0);
    }

    //Set power frequency compensation to 50 Hz
    //this is noncritical so don't stop the program if it fails
    try {
	camera->setControlValue(Camera::POWER_FREQUENCY, 1);
    }catch(CameraException &e){}

    init();
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(IMAGE_WIDTH, IMAGE_HEIGHT);
    glutInitWindowPosition(100,100);
    window1 = glutCreateWindow(argv[0]);
    glutDisplayFunc(displayProjector);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);

    glutInitWindowPosition(100+IMAGE_WIDTH,100);
    window2 = glutCreateWindow(argv[0]);
    glutDisplayFunc(displayCamera);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glutMainLoop();
}
<commit_msg>Clean up reset to reset the stage and also the image counter<commit_after>/*-
 * Copyright (c) 2010 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Simple test of the Binary Coded GrayCode Phase Shift code
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "GrayCode.h"
#include <wcl/camera/CameraException.h>
#include <wcl/camera/CameraFactory.h>

#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define TIMER_VALUE 500
#define CROSS_DENSITY 100

using namespace std;
using namespace wcl;

GLvoid captureTimer(int value );

bool automated=false;
bool capturing=false;
unsigned image=0;
int window1, window2;
GrayCode g(IMAGE_WIDTH, IMAGE_HEIGHT);

// The in use camera
Camera *camera;

// Buffers for frame detection
unsigned char **buffers;

void init()
{
	buffers = new unsigned char *[g.getRequiredImageCount()];
	for( unsigned i = 0; i < g.getRequiredImageCount(); i++ )
	    buffers[i] = new unsigned char [IMAGE_WIDTH * IMAGE_HEIGHT];
}

GLvoid reshape(int width, int height)
{
	glViewport(0,0, (GLsizei)width, (GLsizei)height);
}

void keyboard(unsigned char key, int w, int h)
{
    if(key==27)
	exit(EXIT_SUCCESS);
    if(key=='r'){
	g.reset();
	image=0;
	capturing=false;
	cout << "Reset" <<endl;;
    }
    if(key=='v'){
	cout << "Decoding GrayCode Ignoring Camera" << endl;
	g.decode((const unsigned char **)g.getCodedImages());
    }
    if(key==13){
	if( capturing == true ){
	    if(!g.next()){
		g.reset();
	    }
	}
	capturing=true;
    }
    if(key == 'a' ){
	automated=true;
	g.reset();
	image = 0;
	capturing=true;
	glutTimerFunc(TIMER_VALUE,captureTimer,0);
    }
}

void drawCross(const unsigned x, const unsigned y)
{
    glBegin(GL_LINE);
    glVertex3d(x>5?x-5:0,y,0);
    glVertex3d(x+5,y,0);
    glEnd();
    glBegin(GL_LINES);
    glVertex3d(x,y>5?y-5:0,0);
    glVertex3d(x,y+5,0);
    glEnd();
}

GLvoid displayProjector()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPixelZoom(1.0f, -1.0f);
	glRasterPos2i(-1, 1);

	if( capturing )
	    glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, g.generate());
	else {
	    glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, g.getDebugImage());

	    glOrtho(0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, -1.0, 1.0);

	    for(unsigned y=0; y < IMAGE_HEIGHT; y+=CROSS_DENSITY){
		for(unsigned x=0; x < IMAGE_WIDTH; x+=CROSS_DENSITY){
		    Vector v(2);
		    v[0]=x;
		    v[1]=y;
		    v = g.getRowCol(v);
		    glColor3f(0.3,0.0,0.0);
		    drawCross(x,y);
		    glColor3f(0.0,0.0,1.0);
		    drawCross(v[0],v[1]);
		}
	    }
	}

	glFlush();
	glutSwapBuffers();
}

GLvoid displayCamera()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPixelZoom(1.0f, -1.0f);
	glRasterPos2i(-1, 1);
	glDrawPixels( IMAGE_WIDTH, IMAGE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, camera->getFrame(Camera::RGB8));

	glFlush();
	glutSwapBuffers();
}

/**
 * Constantly fetch a new image from the camera to display
 */
GLvoid idle()
{
    glutSetWindow(window1);
    glutPostRedisplay();
    glutSetWindow(window2);
    glutPostRedisplay();
}

GLvoid captureTimer(int value )
{
    static bool display = true;
    static bool first=true;
    if(capturing)
    {
	if( display ) {
	    if( !first ){
		if(g.next() == false ){
		    capturing=false;
		    display=true;
		    first=true;
		    cout << "Decoding GrayCode" << endl;
		    g.decode((const unsigned char **)buffers);
		}
	    } else {
		first=false;
	    }
	    glutSetWindow(window1);
	    glutPostRedisplay();
	    glutSetWindow(window2);
	    glutPostRedisplay();
	    display=false;
	} else {
	    cout << "Capturing Image" << image << endl;
	    memcpy(buffers[image],camera->getFrame(Camera::MONO8),IMAGE_WIDTH * IMAGE_HEIGHT);
	    image++;
	    display=true;
	}
	if( automated ){
	    glutTimerFunc(TIMER_VALUE,captureTimer,0);
	}
    }

}

int main(int argc, char** argv)
{
    try {
	if(argc < 2 ){
	    Camera::Configuration config;
	    config.width=IMAGE_WIDTH;
	    config.height=IMAGE_HEIGHT;
	    camera = CameraFactory::findCamera(config);
	} else {
	    camera = CameraFactory::getCamera(argv[1]);
	    Camera::Configuration config = camera->getActiveConfiguration();
	    config.width=IMAGE_WIDTH;
	    config.height=IMAGE_HEIGHT;
	    camera->setConfiguration(config);
	}
    } catch(CameraException &e)
    {
	cout << "CameraException:" << e.what() << endl;
	exit(0);
    }

    if ( camera == NULL ){
	cout << "Camera Not Found" << endl;
	exit(0);
    }

    //Set power frequency compensation to 50 Hz
    //this is noncritical so don't stop the program if it fails
    try {
	camera->setControlValue(Camera::POWER_FREQUENCY, 1);
    }catch(CameraException &e){}

    init();
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(IMAGE_WIDTH, IMAGE_HEIGHT);
    glutInitWindowPosition(100,100);
    window1 = glutCreateWindow(argv[0]);
    glutDisplayFunc(displayProjector);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);

    glutInitWindowPosition(100+IMAGE_WIDTH,100);
    window2 = glutCreateWindow(argv[0]);
    glutDisplayFunc(displayCamera);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glutMainLoop();
}
<|endoftext|>


<commit_before>// mixing different itertools, there is nothing called iter::mixed()

#include "itertools.hpp"

#include "catch.hpp"

#include <iostream>
#include <vector>

class MyUnMovable {
    int val;
public:
    constexpr MyUnMovable(int val)
        : val{val}
    { }

    MyUnMovable(const MyUnMovable&) = delete;
    MyUnMovable& operator=(const MyUnMovable&) = delete;

    MyUnMovable(MyUnMovable&& other)
        : val{other.val}
    { }

    constexpr int get_val() const {
        return val;
    }
    void set_val(int val) {
        this->val = val;
    }

    bool operator==(const MyUnMovable& other) const {
        return this->val == other.val;
    }

    bool operator!=(const MyUnMovable& other) const {
        return !(*this == other);
    }
};

namespace {
    auto inc_ten = [](MyUnMovable& el) -> MyUnMovable& {
        int va = el.get_val();
        el.set_val(va + 10);
        return el;
    };
    auto dec_ten = [](MyUnMovable& el) -> MyUnMovable& {
        int va = el.get_val();
        el.set_val(va - 10);
        return el;
    };
}

TEST_CASE("filtering doesn't dereference multiple times", "[imap][filter]") {
    using iter::filter;
    using iter::imap;

    // source data
    std::array<MyUnMovable, 3> arr = {{{41}, {42}, {43}}};

    auto transformed1 = imap(inc_ten, arr);
    auto filtered = filter([](const MyUnMovable& el) {
        return 52 != el.get_val();
    }, transformed1);
    auto transformed2 = imap(dec_ten, filtered);

    std::vector<int> v;
    for (auto&& el : transformed2) {
        // I would use imap again instead of the loop if this wasn't an imap
        // test
        v.push_back(el.get_val());
    }

    std::vector<int> vc = {41, 43};

    REQUIRE( v == vc);

    constexpr std::array<MyUnMovable, 3> arrc = {{{41}, {52}, {43}}};
    REQUIRE( arr == arrc );
}

TEST_CASE("dropwhile doesn't dereference multiple times", "[imap][dropwhile]"){
    using iter::imap;
    using iter::dropwhile;
    // source data
    std::array<MyUnMovable, 3> arr = {{{41}, {42}, {43}}};

    auto transformed1 = imap(inc_ten, arr);
    auto filtered = dropwhile([](const MyUnMovable& el) {
        return 52 != el.get_val();
    }, transformed1);
    auto transformed2 = imap(dec_ten, filtered);

    std::vector<int> v;
    for (auto&& el : transformed2) {
        v.push_back(el.get_val());
    }

    std::vector<int> vc = {42, 43};

    std::vector<int> vsc = {51, 42, 43};
    auto get_vals = imap([](const MyUnMovable& mv){return mv.get_val();}, arr);
    std::vector<int> vs(std::begin(get_vals), std::end(get_vals));
    REQUIRE( vs == vsc );
}
<commit_msg>tests takewhile for double-deref<commit_after>// mixing different itertools, there is nothing called iter::mixed()

#include "itertools.hpp"

#include "catch.hpp"

#include <iostream>
#include <vector>

class MyUnMovable {
    int val;
public:
    constexpr MyUnMovable(int val)
        : val{val}
    { }

    MyUnMovable(const MyUnMovable&) = delete;
    MyUnMovable& operator=(const MyUnMovable&) = delete;

    MyUnMovable(MyUnMovable&& other)
        : val{other.val}
    { }

    constexpr int get_val() const {
        return val;
    }
    void set_val(int val) {
        this->val = val;
    }

    bool operator==(const MyUnMovable& other) const {
        return this->val == other.val;
    }

    bool operator!=(const MyUnMovable& other) const {
        return !(*this == other);
    }
};

namespace {
    auto inc_ten = [](MyUnMovable& el) -> MyUnMovable& {
        int va = el.get_val();
        el.set_val(va + 10);
        return el;
    };
    auto dec_ten = [](MyUnMovable& el) -> MyUnMovable& {
        int va = el.get_val();
        el.set_val(va - 10);
        return el;
    };
}

TEST_CASE("filtering doesn't dereference multiple times", "[imap][filter]") {
    using iter::filter;
    using iter::imap;

    // source data
    std::array<MyUnMovable, 3> arr = {{{41}, {42}, {43}}};

    auto transformed1 = imap(inc_ten, arr);
    auto filtered = filter([](const MyUnMovable& el) {
        return 52 != el.get_val();
    }, transformed1);
    auto transformed2 = imap(dec_ten, filtered);

    std::vector<int> v;
    for (auto&& el : transformed2) {
        // I would use imap again instead of the loop if this wasn't an imap
        // test
        v.push_back(el.get_val());
    }

    std::vector<int> vc = {41, 43};

    REQUIRE( v == vc);

    constexpr std::array<MyUnMovable, 3> arrc = {{{41}, {52}, {43}}};
    REQUIRE( arr == arrc );
}

TEST_CASE("dropwhile doesn't dereference multiple times", "[imap][dropwhile]"){
    using iter::imap;
    using iter::dropwhile;

    std::array<MyUnMovable, 3> arr = {{{41}, {42}, {43}}};

    auto transformed1 = imap(inc_ten, arr);
    auto filtered = dropwhile([](const MyUnMovable& el) {
        return 52 != el.get_val();
    }, transformed1);
    auto transformed2 = imap(dec_ten, filtered);

    std::vector<int> v;
    for (auto&& el : transformed2) {
        v.push_back(el.get_val());
    }

    std::vector<int> vc = {42, 43};

    std::vector<int> vsc = {51, 42, 43};
    auto get_vals = imap([](const MyUnMovable& mv){return mv.get_val();}, arr);
    std::vector<int> vs(std::begin(get_vals), std::end(get_vals));
    REQUIRE( vs == vsc );
}

TEST_CASE("takewhile doesn't dereference multiple times", "[imap][takewhile]"){
    using iter::imap;
    using iter::takewhile;

    std::array<MyUnMovable, 3> arr = {{{41}, {42}, {43}}};

    auto transformed1 = imap(inc_ten, arr);
    auto filtered = takewhile([](const MyUnMovable& el) {
        return 53 != el.get_val();
    }, transformed1);
    auto transformed2 = imap(dec_ten, filtered);

    std::vector<int> v;
    for (auto&& el : transformed2) {
        v.push_back(el.get_val());
    }

    std::vector<int> vc = {41, 42};

    std::vector<int> vsc = {41, 42, 53};
    auto get_vals = imap([](const MyUnMovable& mv){return mv.get_val();}, arr);
    std::vector<int> vs(std::begin(get_vals), std::end(get_vals));
    REQUIRE( vs == vsc );
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include <stdint.h>
#include "epackettype.h"
#include "crosepacket.h"
#include "cloginserver.h"
#include "ccharisc.h"
#include "mock/mock_cloginclient.h"
#include "mock/mock_cloginisc.h"

using namespace RoseCommon;

TEST(TestLoginServer, TestClientPacketPath) {
  CLoginServer network;
  CLoginISC* iscServ = new CLoginISC();
  CLoginClient_Mock netConnect;
  EXPECT_EQ(true, network.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(network.Listen());

  iscServ->SetId(0);
  iscServ->SetType(1);
  CLoginServer::GetISCList().push_front(iscServ);

  std::this_thread::sleep_for(std::chrono::milliseconds(500));
  EXPECT_EQ(true, netConnect.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(netConnect.Connect());

  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  CRosePacket* pak = new CRosePacket(ePacketType::PAKCS_ACCEPT_REQ);
  netConnect.Send(pak);

  CRosePacket* pak4 = new CRosePacket(ePacketType::PAKCS_LOGIN_REQ);
  pak4->AddString("cc03e747a6afbbcbf8be7668acfebee5", false);
  pak4->AddString("test", false);
  netConnect.Send(pak4);

  CRosePacket* pak2 = new CRosePacket(ePacketType::PAKCS_CHANNEL_LIST_REQ);
  pak2->pChannelListReq.lServerID = 1;
  netConnect.Send(pak2);

  CRosePacket* pak5 = new CRosePacket(ePacketType::PAKCS_SRV_SELECT_REQ);
  pak5->Add<uint32_t>(0);
  pak5->Add<uint8_t>(0);
  netConnect.Send(pak5);

  CRosePacket* pak3 = new CRosePacket(ePacketType::PAKCS_ALIVE);
  netConnect.Send(pak3);

  std::this_thread::sleep_for(
      std::chrono::milliseconds(500));  // Change this to condition variables
  // EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
  EXPECT_NO_FATAL_FAILURE(netConnect.Shutdown());
  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  EXPECT_NO_FATAL_FAILURE(network.Shutdown());
}

TEST(TestLoginServer, TestISCRosePacketPath) {
  //	CLogConsole::SetDisplayOmittable( true );

/*  CLoginServer network(true);
  CCharISC netConnect;
  EXPECT_EQ(true, network.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(network.Listen());

  //std::this_thread::sleep_for(std::chrono::milliseconds(500));
  EXPECT_EQ(true, netConnect.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(netConnect.Connect());

  //std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
  CRosePacket* pak = new CRosePacket( ePacketType::ISC_ALIVE );
  netConnect.Send( pak );
  {
    uint8_t serverCount = 0;
    std::lock_guard<std::mutex> lock(CLoginServer::GetISCListMutex());
    for (auto& server : CLoginServer::GetISCList()) {
      if (server->GetType() == 1) serverCount++;
    }

    EXPECT_EQ(1, serverCount);
  }

  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  //        CRosePacket* pak = new CRosePacket( ePacketType::ISC_ALIVE );
  //        netConnect.Send( pak );

  std::this_thread::sleep_for(
      std::chrono::milliseconds(500));  // Change this to condition variables
  EXPECT_NO_FATAL_FAILURE(netConnect.Disconnect());
  EXPECT_NO_FATAL_FAILURE(netConnect.Shutdown());

  EXPECT_NO_FATAL_FAILURE(network.Shutdown());
*/
  //	CLogConsole::SetDisplayOmittable( false );
}
<commit_msg>Removed useless code<commit_after>#include "gtest/gtest.h"

#include <stdint.h>
#include "epackettype.h"
#include "crosepacket.h"
#include "cloginserver.h"
#include "ccharisc.h"
#include "mock/mock_cloginclient.h"
#include "mock/mock_cloginisc.h"

using namespace RoseCommon;

TEST(TestLoginServer, TestClientPacketPath) {
  CLoginServer network;
//  CLoginISC* iscServ = new CLoginISC();
  CLoginClient_Mock netConnect;
  EXPECT_EQ(true, network.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(network.Listen());

//  iscServ->SetId(0);
//  iscServ->SetType(1);
//  CLoginServer::GetISCList().push_front(iscServ);

  std::this_thread::sleep_for(std::chrono::milliseconds(500));
  EXPECT_EQ(true, netConnect.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(netConnect.Connect());

  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  CRosePacket* pak = new CRosePacket(ePacketType::PAKCS_ACCEPT_REQ);
  netConnect.Send(pak);

  CRosePacket* pak4 = new CRosePacket(ePacketType::PAKCS_LOGIN_REQ);
  pak4->AddString("cc03e747a6afbbcbf8be7668acfebee5", false);
  pak4->AddString("test", false);
  netConnect.Send(pak4);

  CRosePacket* pak2 = new CRosePacket(ePacketType::PAKCS_CHANNEL_LIST_REQ);
  pak2->pChannelListReq.lServerID = 1;
  netConnect.Send(pak2);

  CRosePacket* pak5 = new CRosePacket(ePacketType::PAKCS_SRV_SELECT_REQ);
  pak5->Add<uint32_t>(0);
  pak5->Add<uint8_t>(0);
  netConnect.Send(pak5);

  CRosePacket* pak3 = new CRosePacket(ePacketType::PAKCS_ALIVE);
  netConnect.Send(pak3);

  std::this_thread::sleep_for(
      std::chrono::milliseconds(500));  // Change this to condition variables
  // EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
  EXPECT_NO_FATAL_FAILURE(netConnect.Shutdown());
  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  EXPECT_NO_FATAL_FAILURE(network.Shutdown());
}

TEST(TestLoginServer, TestISCRosePacketPath) {
  //	CLogConsole::SetDisplayOmittable( true );

/*  CLoginServer network(true);
  CCharISC netConnect;
  EXPECT_EQ(true, network.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(network.Listen());

  //std::this_thread::sleep_for(std::chrono::milliseconds(500));
  EXPECT_EQ(true, netConnect.Init("127.0.0.1", 29110));
  EXPECT_NO_FATAL_FAILURE(netConnect.Connect());

  //std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
  CRosePacket* pak = new CRosePacket( ePacketType::ISC_ALIVE );
  netConnect.Send( pak );
  {
    uint8_t serverCount = 0;
    std::lock_guard<std::mutex> lock(CLoginServer::GetISCListMutex());
    for (auto& server : CLoginServer::GetISCList()) {
      if (server->GetType() == 1) serverCount++;
    }

    EXPECT_EQ(1, serverCount);
  }

  // std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
  //        CRosePacket* pak = new CRosePacket( ePacketType::ISC_ALIVE );
  //        netConnect.Send( pak );

  std::this_thread::sleep_for(
      std::chrono::milliseconds(500));  // Change this to condition variables
  EXPECT_NO_FATAL_FAILURE(netConnect.Disconnect());
  EXPECT_NO_FATAL_FAILURE(netConnect.Shutdown());

  EXPECT_NO_FATAL_FAILURE(network.Shutdown());
*/
  //	CLogConsole::SetDisplayOmittable( false );
}
<|endoftext|>