<commit_before>// Copyright (c) 2015 Pierre Moulon.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/sfm_data_BA_ceres.hpp"

#include "ceres/rotation.h"

namespace openMVG {

/// Create the appropriate cost functor according the provided input camera intrinsic model
ceres::CostFunction * IntrinsicsToCostFunction(IntrinsicBase * intrinsic, const Vec2 & observation)
{
  switch(intrinsic->getType())
  {
    case PINHOLE_CAMERA:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic, 2, 3, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic(observation.data()));
    break;
    case PINHOLE_CAMERA_RADIAL1:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K1, 2, 4, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K1(observation.data()));
    break;
    case PINHOLE_CAMERA_RADIAL3:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K3, 2, 6, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K3(observation.data()));
    break;
    default:
      return NULL;
  }
}

Bundle_Adjustment_Ceres::BA_options::BA_options(const bool bVerbose, bool bmultithreaded)
  :_bVerbose(bVerbose)
{
  #ifdef OPENMVG_USE_OPENMP
    _nbThreads = omp_get_max_threads();
  #endif // OPENMVG_USE_OPENMP
  if (!bmultithreaded)
    _nbThreads = 1;

  _bCeres_Summary = false;

  _linear_solver_type = ceres::SPARSE_SCHUR;
  _preconditioner_type = ceres::JACOBI;
   if (ceres::IsSparseLinearAlgebraLibraryTypeAvailable(ceres::SUITE_SPARSE))
    _sparse_linear_algebra_library_type = ceres::SUITE_SPARSE;
  else
    if (ceres::IsSparseLinearAlgebraLibraryTypeAvailable(ceres::CX_SPARSE))
      _sparse_linear_algebra_library_type = ceres::CX_SPARSE;
}

Bundle_Adjustment_Ceres::Bundle_Adjustment_Ceres(
  Bundle_Adjustment_Ceres::BA_options options)
  : _openMVG_options(options)
{}

bool Bundle_Adjustment_Ceres::Adjust(
  SfM_Data & sfm_data,     // the SfM scene to refine
  bool bRefineRotations,   // tell if pose rotations will be refined
  bool bRefineTranslations,// tell if the pose translation will be refined
  bool bRefineIntrinsics,  // tell if the camera intrinsic will be refined
  bool bRefineStructure)   // tell if the structure will be refined
{
  //----------
  // Add camera parameters
  // - intrinsics
  // - poses [R|t]

  // Create residuals for each observation in the bundle adjustment problem. The
  // parameters for cameras and points are added automatically.
  //----------

  ceres::Problem problem;

  // Data wrapper for refinement:
  Hash_Map<IndexT, std::vector<double> > map_intrinsics;
  Hash_Map<IndexT, std::vector<double> > map_poses;

  // Setup Poses data & subparametrization
  for (Poses::const_iterator itPose = sfm_data.poses.begin(); itPose != sfm_data.poses.end(); ++itPose)
  {
    const IndexT indexPose = itPose->first;

    const Pose3 & pose = itPose->second;
    const Mat3 R = pose.rotation();
    const Vec3 t = pose.translation();

    double angleAxis[3];
    ceres::RotationMatrixToAngleAxis((const double*)R.data(), angleAxis);
    map_poses[indexPose].reserve(6); //angleAxis + translation
    map_poses[indexPose].push_back(angleAxis[0]);
    map_poses[indexPose].push_back(angleAxis[1]);
    map_poses[indexPose].push_back(angleAxis[2]);
    map_poses[indexPose].push_back(t(0));
    map_poses[indexPose].push_back(t(1));
    map_poses[indexPose].push_back(t(2));

    double * parameter_block = &map_poses[indexPose][0];
    problem.AddParameterBlock(parameter_block, 6);
    if (!bRefineTranslations && !bRefineIntrinsics)
    {
      //set the whole parameter block as constant for best performance.
      problem.SetParameterBlockConstant(parameter_block);
    }
    else  {
      // Subset parametrization
      std::vector<int> vec_constant_extrinsic;
      if(!bRefineRotations)
      {
        vec_constant_extrinsic.push_back(0);
        vec_constant_extrinsic.push_back(1);
        vec_constant_extrinsic.push_back(2);
      }
      if(!bRefineTranslations)
      {
        vec_constant_extrinsic.push_back(3);
        vec_constant_extrinsic.push_back(4);
        vec_constant_extrinsic.push_back(5);
      }
      if (!vec_constant_extrinsic.empty())
      {
        ceres::SubsetParameterization *subset_parameterization =
          new ceres::SubsetParameterization(6, vec_constant_extrinsic);
        problem.SetParameterization(parameter_block, subset_parameterization);
      }
    }
  }

  // Setup Intrinsics data & subparametrization
  for (Intrinsics::const_iterator itIntrinsic = sfm_data.intrinsics.begin();
    itIntrinsic != sfm_data.intrinsics.end(); ++itIntrinsic)
  {
    const IndexT indexCam = itIntrinsic->first;

    if (isValid(itIntrinsic->second->getType()))
    {
      map_intrinsics[indexCam] = itIntrinsic->second->getParams();

      double * parameter_block = &map_intrinsics[indexCam][0];
      problem.AddParameterBlock(parameter_block, map_intrinsics[indexCam].size());
      if (!bRefineIntrinsics)
      {
        //set the whole parameter block as constant for best performance.
        problem.SetParameterBlockConstant(parameter_block);
      }
    }
    else
    {
      std::cerr << "Unsupported camera type." << std::endl;
    }
  }

  // Set a LossFunction to be less penalized by false measurements
  //  - set it to NULL if you don't want use a lossFunction.
  ceres::LossFunction * p_LossFunction = new ceres::HuberLoss(Square(4.0));
  // TODO: make the LOSS function and the parameter an option

  // For all visibility add reprojections errors:
  for (Landmarks::iterator iterTracks = sfm_data.structure.begin();
    iterTracks!= sfm_data.structure.end(); ++iterTracks)
  {
    const Observations & obs = iterTracks->second.obs;

    for (Observations::const_iterator itObs = obs.begin();
      itObs != obs.end(); ++itObs)
    {
      // Build the residual block corresponding to the track observation:
      const View * view = sfm_data.views[itObs->first].get();

      // Each Residual block takes a point and a camera as input and outputs a 2
      // dimensional residual. Internally, the cost function stores the observed
      // image location and compares the reprojection against the observation.
      ceres::CostFunction* cost_function =
        IntrinsicsToCostFunction(sfm_data.intrinsics[view->id_intrinsic].get(), itObs->second.x);

      if (cost_function)
        problem.AddResidualBlock(cost_function,
          p_LossFunction,
          &map_intrinsics[view->id_intrinsic][0],
          &map_poses[view->id_pose][0],
          iterTracks->second.X.data()); //Do we need to copy 3D point to avoid false motion, if failure ?
    }
    if (!bRefineStructure)
      problem.SetParameterBlockConstant(iterTracks->second.X.data());
  }

  // Configure a BA engine and run it
  //  Make Ceres automatically detect the bundle structure.
  ceres::Solver::Options options;
  options.preconditioner_type = _openMVG_options._preconditioner_type;
  options.linear_solver_type = _openMVG_options._linear_solver_type;
  options.sparse_linear_algebra_library_type = _openMVG_options._sparse_linear_algebra_library_type;
  options.minimizer_progress_to_stdout = false;
  options.logging_type = ceres::SILENT;
  options.num_threads = _openMVG_options._nbThreads;
  options.num_linear_solver_threads = _openMVG_options._nbThreads;

  // Solve BA
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);
  if (_openMVG_options._bCeres_Summary)
    std::cout << summary.FullReport() << std::endl;

  // If no error, get back refined parameters
  if (!summary.IsSolutionUsable())
  {
    if (_openMVG_options._bVerbose)
      std::cout << "Bundle Adjustment failed." << std::endl;
    return false;
  }
  else // Solution is usable
  {
    if (_openMVG_options._bVerbose)
    {
      // Display statistics about the minimization
      std::cout << std::endl
        << "Bundle Adjustment statistics (approximated RMSE):\n"
        << " #views: " << sfm_data.views.size() << "\n"
        << " #poses: " << sfm_data.poses.size() << "\n"
        << " #intrinsics: " << sfm_data.intrinsics.size() << "\n"
        << " #tracks: " << sfm_data.structure.size() << "\n"
        << " #residuals: " << summary.num_residuals << "\n"
        << " Initial RMSE: " << std::sqrt( summary.initial_cost / summary.num_residuals) << "\n"
        << " Final RMSE: " << std::sqrt( summary.final_cost / summary.num_residuals) << "\n"
        << std::endl;
    }

    // Update camera poses with refined data
    for (Poses::iterator itPose = sfm_data.poses.begin();
      itPose != sfm_data.poses.end(); ++itPose)
    {
      const IndexT indexPose = itPose->first;

      Mat3 R_refined;
      ceres::AngleAxisToRotationMatrix(&map_poses[indexPose][0], R_refined.data());
      Vec3 t_refined(map_poses[indexPose][3], map_poses[indexPose][4], map_poses[indexPose][5]);
      // Update the pose
      Pose3 & pose = itPose->second;
      pose = Pose3(R_refined, -R_refined.transpose() * t_refined);
    }

    // Update camera intrinsics with refined data
    for (Intrinsics::iterator itIntrinsic = sfm_data.intrinsics.begin();
      itIntrinsic != sfm_data.intrinsics.end(); ++itIntrinsic)
    {
      const IndexT indexCam = itIntrinsic->first;

      const std::vector<double> & vec_params = map_intrinsics[indexCam];
      itIntrinsic->second.get()->updateFromParams(vec_params);
    }
    return true;
  }
}

} // namespace openMVG

<commit_msg>Fix wrong initialization in case of no OpenMP support. #293<commit_after>// Copyright (c) 2015 Pierre Moulon.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/sfm_data_BA_ceres.hpp"

#include "ceres/rotation.h"

namespace openMVG {

/// Create the appropriate cost functor according the provided input camera intrinsic model
ceres::CostFunction * IntrinsicsToCostFunction(IntrinsicBase * intrinsic, const Vec2 & observation)
{
  switch(intrinsic->getType())
  {
    case PINHOLE_CAMERA:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic, 2, 3, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic(observation.data()));
    break;
    case PINHOLE_CAMERA_RADIAL1:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K1, 2, 4, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K1(observation.data()));
    break;
    case PINHOLE_CAMERA_RADIAL3:
      return new ceres::AutoDiffCostFunction<ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K3, 2, 6, 6, 3>(
        new ResidualErrorFunctor_Pinhole_Intrinsic_Radial_K3(observation.data()));
    break;
    default:
      return NULL;
  }
}

Bundle_Adjustment_Ceres::BA_options::BA_options(const bool bVerbose, bool bmultithreaded)
  :_bVerbose(bVerbose),
   _nbThreads(1)
{
  #ifdef OPENMVG_USE_OPENMP
    _nbThreads = omp_get_max_threads();
  #endif // OPENMVG_USE_OPENMP
  if (!bmultithreaded)
    _nbThreads = 1;

  _bCeres_Summary = false;

  _linear_solver_type = ceres::SPARSE_SCHUR;
  _preconditioner_type = ceres::JACOBI;
   if (ceres::IsSparseLinearAlgebraLibraryTypeAvailable(ceres::SUITE_SPARSE))
    _sparse_linear_algebra_library_type = ceres::SUITE_SPARSE;
  else
    if (ceres::IsSparseLinearAlgebraLibraryTypeAvailable(ceres::CX_SPARSE))
      _sparse_linear_algebra_library_type = ceres::CX_SPARSE;
}

Bundle_Adjustment_Ceres::Bundle_Adjustment_Ceres(
  Bundle_Adjustment_Ceres::BA_options options)
  : _openMVG_options(options)
{}

bool Bundle_Adjustment_Ceres::Adjust(
  SfM_Data & sfm_data,     // the SfM scene to refine
  bool bRefineRotations,   // tell if pose rotations will be refined
  bool bRefineTranslations,// tell if the pose translation will be refined
  bool bRefineIntrinsics,  // tell if the camera intrinsic will be refined
  bool bRefineStructure)   // tell if the structure will be refined
{
  //----------
  // Add camera parameters
  // - intrinsics
  // - poses [R|t]

  // Create residuals for each observation in the bundle adjustment problem. The
  // parameters for cameras and points are added automatically.
  //----------

  ceres::Problem problem;

  // Data wrapper for refinement:
  Hash_Map<IndexT, std::vector<double> > map_intrinsics;
  Hash_Map<IndexT, std::vector<double> > map_poses;

  // Setup Poses data & subparametrization
  for (Poses::const_iterator itPose = sfm_data.poses.begin(); itPose != sfm_data.poses.end(); ++itPose)
  {
    const IndexT indexPose = itPose->first;

    const Pose3 & pose = itPose->second;
    const Mat3 R = pose.rotation();
    const Vec3 t = pose.translation();

    double angleAxis[3];
    ceres::RotationMatrixToAngleAxis((const double*)R.data(), angleAxis);
    map_poses[indexPose].reserve(6); //angleAxis + translation
    map_poses[indexPose].push_back(angleAxis[0]);
    map_poses[indexPose].push_back(angleAxis[1]);
    map_poses[indexPose].push_back(angleAxis[2]);
    map_poses[indexPose].push_back(t(0));
    map_poses[indexPose].push_back(t(1));
    map_poses[indexPose].push_back(t(2));

    double * parameter_block = &map_poses[indexPose][0];
    problem.AddParameterBlock(parameter_block, 6);
    if (!bRefineTranslations && !bRefineIntrinsics)
    {
      //set the whole parameter block as constant for best performance.
      problem.SetParameterBlockConstant(parameter_block);
    }
    else  {
      // Subset parametrization
      std::vector<int> vec_constant_extrinsic;
      if(!bRefineRotations)
      {
        vec_constant_extrinsic.push_back(0);
        vec_constant_extrinsic.push_back(1);
        vec_constant_extrinsic.push_back(2);
      }
      if(!bRefineTranslations)
      {
        vec_constant_extrinsic.push_back(3);
        vec_constant_extrinsic.push_back(4);
        vec_constant_extrinsic.push_back(5);
      }
      if (!vec_constant_extrinsic.empty())
      {
        ceres::SubsetParameterization *subset_parameterization =
          new ceres::SubsetParameterization(6, vec_constant_extrinsic);
        problem.SetParameterization(parameter_block, subset_parameterization);
      }
    }
  }

  // Setup Intrinsics data & subparametrization
  for (Intrinsics::const_iterator itIntrinsic = sfm_data.intrinsics.begin();
    itIntrinsic != sfm_data.intrinsics.end(); ++itIntrinsic)
  {
    const IndexT indexCam = itIntrinsic->first;

    if (isValid(itIntrinsic->second->getType()))
    {
      map_intrinsics[indexCam] = itIntrinsic->second->getParams();

      double * parameter_block = &map_intrinsics[indexCam][0];
      problem.AddParameterBlock(parameter_block, map_intrinsics[indexCam].size());
      if (!bRefineIntrinsics)
      {
        //set the whole parameter block as constant for best performance.
        problem.SetParameterBlockConstant(parameter_block);
      }
    }
    else
    {
      std::cerr << "Unsupported camera type." << std::endl;
    }
  }

  // Set a LossFunction to be less penalized by false measurements
  //  - set it to NULL if you don't want use a lossFunction.
  ceres::LossFunction * p_LossFunction = new ceres::HuberLoss(Square(4.0));
  // TODO: make the LOSS function and the parameter an option

  // For all visibility add reprojections errors:
  for (Landmarks::iterator iterTracks = sfm_data.structure.begin();
    iterTracks!= sfm_data.structure.end(); ++iterTracks)
  {
    const Observations & obs = iterTracks->second.obs;

    for (Observations::const_iterator itObs = obs.begin();
      itObs != obs.end(); ++itObs)
    {
      // Build the residual block corresponding to the track observation:
      const View * view = sfm_data.views[itObs->first].get();

      // Each Residual block takes a point and a camera as input and outputs a 2
      // dimensional residual. Internally, the cost function stores the observed
      // image location and compares the reprojection against the observation.
      ceres::CostFunction* cost_function =
        IntrinsicsToCostFunction(sfm_data.intrinsics[view->id_intrinsic].get(), itObs->second.x);

      if (cost_function)
        problem.AddResidualBlock(cost_function,
          p_LossFunction,
          &map_intrinsics[view->id_intrinsic][0],
          &map_poses[view->id_pose][0],
          iterTracks->second.X.data()); //Do we need to copy 3D point to avoid false motion, if failure ?
    }
    if (!bRefineStructure)
      problem.SetParameterBlockConstant(iterTracks->second.X.data());
  }

  // Configure a BA engine and run it
  //  Make Ceres automatically detect the bundle structure.
  ceres::Solver::Options options;
  options.preconditioner_type = _openMVG_options._preconditioner_type;
  options.linear_solver_type = _openMVG_options._linear_solver_type;
  options.sparse_linear_algebra_library_type = _openMVG_options._sparse_linear_algebra_library_type;
  options.minimizer_progress_to_stdout = false;
  options.logging_type = ceres::SILENT;
  options.num_threads = _openMVG_options._nbThreads;
  options.num_linear_solver_threads = _openMVG_options._nbThreads;

  // Solve BA
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);
  if (_openMVG_options._bCeres_Summary)
    std::cout << summary.FullReport() << std::endl;

  // If no error, get back refined parameters
  if (!summary.IsSolutionUsable())
  {
    if (_openMVG_options._bVerbose)
      std::cout << "Bundle Adjustment failed." << std::endl;
    return false;
  }
  else // Solution is usable
  {
    if (_openMVG_options._bVerbose)
    {
      // Display statistics about the minimization
      std::cout << std::endl
        << "Bundle Adjustment statistics (approximated RMSE):\n"
        << " #views: " << sfm_data.views.size() << "\n"
        << " #poses: " << sfm_data.poses.size() << "\n"
        << " #intrinsics: " << sfm_data.intrinsics.size() << "\n"
        << " #tracks: " << sfm_data.structure.size() << "\n"
        << " #residuals: " << summary.num_residuals << "\n"
        << " Initial RMSE: " << std::sqrt( summary.initial_cost / summary.num_residuals) << "\n"
        << " Final RMSE: " << std::sqrt( summary.final_cost / summary.num_residuals) << "\n"
        << std::endl;
    }

    // Update camera poses with refined data
    for (Poses::iterator itPose = sfm_data.poses.begin();
      itPose != sfm_data.poses.end(); ++itPose)
    {
      const IndexT indexPose = itPose->first;

      Mat3 R_refined;
      ceres::AngleAxisToRotationMatrix(&map_poses[indexPose][0], R_refined.data());
      Vec3 t_refined(map_poses[indexPose][3], map_poses[indexPose][4], map_poses[indexPose][5]);
      // Update the pose
      Pose3 & pose = itPose->second;
      pose = Pose3(R_refined, -R_refined.transpose() * t_refined);
    }

    // Update camera intrinsics with refined data
    for (Intrinsics::iterator itIntrinsic = sfm_data.intrinsics.begin();
      itIntrinsic != sfm_data.intrinsics.end(); ++itIntrinsic)
    {
      const IndexT indexCam = itIntrinsic->first;

      const std::vector<double> & vec_params = map_intrinsics[indexCam];
      itIntrinsic->second.get()->updateFromParams(vec_params);
    }
    return true;
  }
}

} // namespace openMVG

<|endoftext|>


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2019 Daniel Baston <dbaston@gmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/operation/union/CoverageUnion.h>

#include <geos/geom/GeometryCollection.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/LineString.h>
#include <geos/geom/Polygon.h>
#include <geos/operation/polygonize/Polygonizer.h>
#include <geos/util/IllegalArgumentException.h>
#include <geos/util/TopologyException.h>

namespace geos {
namespace operation {
namespace geounion {

using geos::geom::Geometry;
using geos::geom::LineSegment;
using geos::geom::LineString;
using geos::geom::Polygon;
using geos::geom::GeometryCollection;
using geos::geom::GeometryFactory;
using geos::operation::polygonize::Polygonizer;

void CoverageUnion::extractSegments(const Geometry* geom) {
    const Polygon* p = dynamic_cast<const Polygon*>(geom);
    if (p != nullptr) {
        extractSegments(p);
    } else {
        auto gc = dynamic_cast<const GeometryCollection*>(geom);
        if (gc == nullptr) {
            throw geos::util::IllegalArgumentException("Unhandled geometry type in CoverageUnion.");
        }

        for (std::size_t i = 0; i < gc->getNumGeometries(); i++) {
            extractSegments(gc->getGeometryN(i));
        }
    }
}

void CoverageUnion::extractSegments(const Polygon* p) {
    const LineString* ring = p->getExteriorRing();

    extractSegments(ring);
    for (std::size_t i = 0; i < p->getNumInteriorRing(); i++) {
        extractSegments(p->getInteriorRingN(i));
    }
}

void CoverageUnion::extractSegments(const LineString* ls) {
    auto coords = ls->getCoordinatesRO();

    if (coords->isEmpty())
        return;

    for (std::size_t i = 1; i < coords->size(); i++) {
        LineSegment segment{coords->getAt(i), coords->getAt(i-1)};
        segment.normalize();

       if (!segments.erase(segment)) {
           segments.emplace(std::move(segment));
       }
    }
}

std::unique_ptr<Geometry> CoverageUnion::polygonize(const GeometryFactory* gf) {
    Polygonizer p{true};

    // Create a vector to manage the lifecycle of a geometry corresponding to each line segment.
    // Polygonizer needs these to stay alive until it does its work.
    std::vector<std::unique_ptr<Geometry>> segment_geoms;
    segment_geoms.reserve(segments.size());

    for (const LineSegment& segment : segments) {
        auto seg_geom = segment.toGeometry(*gf);
        p.add(static_cast<Geometry*>(seg_geom.get()));
        segment_geoms.emplace_back(std::move(seg_geom));
    }

    if (!p.allInputsFormPolygons()) {
        throw geos::util::TopologyException("CoverageUnion cannot process incorrectly noded inputs.");
    }

    auto polygons = p.getPolygons();
    segment_geoms.clear();

    if (polygons.size() == 1) {
        return std::move(polygons[0]);
    }

    return gf->createMultiPolygon(std::move(polygons));
}

std::unique_ptr<geom::Geometry> CoverageUnion::Union(const geom::Geometry* geom) {
    CoverageUnion cu;
    cu.extractSegments(geom);

    double area_in = geom->getArea();

    auto ret = cu.polygonize(geom->getFactory());

    double area_out = ret->getArea();

    if (std::abs((area_out - area_in)/area_in) > AREA_PCT_DIFF_TOL) {
        throw geos::util::TopologyException("CoverageUnion cannot process overlapping inputs.");
    }

    return ret;
}

}
}
}
<commit_msg>Remove unneeded explicit .clear()<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2019 Daniel Baston <dbaston@gmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/operation/union/CoverageUnion.h>

#include <geos/geom/GeometryCollection.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/LineString.h>
#include <geos/geom/Polygon.h>
#include <geos/operation/polygonize/Polygonizer.h>
#include <geos/util/IllegalArgumentException.h>
#include <geos/util/TopologyException.h>

namespace geos {
namespace operation {
namespace geounion {

using geos::geom::Geometry;
using geos::geom::LineSegment;
using geos::geom::LineString;
using geos::geom::Polygon;
using geos::geom::GeometryCollection;
using geos::geom::GeometryFactory;
using geos::operation::polygonize::Polygonizer;

void CoverageUnion::extractSegments(const Geometry* geom) {
    const Polygon* p = dynamic_cast<const Polygon*>(geom);
    if (p != nullptr) {
        extractSegments(p);
    } else {
        auto gc = dynamic_cast<const GeometryCollection*>(geom);
        if (gc == nullptr) {
            throw geos::util::IllegalArgumentException("Unhandled geometry type in CoverageUnion.");
        }

        for (std::size_t i = 0; i < gc->getNumGeometries(); i++) {
            extractSegments(gc->getGeometryN(i));
        }
    }
}

void CoverageUnion::extractSegments(const Polygon* p) {
    const LineString* ring = p->getExteriorRing();

    extractSegments(ring);
    for (std::size_t i = 0; i < p->getNumInteriorRing(); i++) {
        extractSegments(p->getInteriorRingN(i));
    }
}

void CoverageUnion::extractSegments(const LineString* ls) {
    auto coords = ls->getCoordinatesRO();

    if (coords->isEmpty())
        return;

    for (std::size_t i = 1; i < coords->size(); i++) {
        LineSegment segment{coords->getAt(i), coords->getAt(i-1)};
        segment.normalize();

       if (!segments.erase(segment)) {
           segments.emplace(std::move(segment));
       }
    }
}

std::unique_ptr<Geometry> CoverageUnion::polygonize(const GeometryFactory* gf) {
    Polygonizer p{true};

    // Create a vector to manage the lifecycle of a geometry corresponding to each line segment.
    // Polygonizer needs these to stay alive until it does its work.
    std::vector<std::unique_ptr<Geometry>> segment_geoms;
    segment_geoms.reserve(segments.size());

    for (const LineSegment& segment : segments) {
        auto seg_geom = segment.toGeometry(*gf);
        p.add(static_cast<Geometry*>(seg_geom.get()));
        segment_geoms.emplace_back(std::move(seg_geom));
    }

    if (!p.allInputsFormPolygons()) {
        throw geos::util::TopologyException("CoverageUnion cannot process incorrectly noded inputs.");
    }

    auto polygons = p.getPolygons();
    if (polygons.size() == 1) {
        return std::move(polygons[0]);
    }

    return gf->createMultiPolygon(std::move(polygons));
}

std::unique_ptr<geom::Geometry> CoverageUnion::Union(const geom::Geometry* geom) {
    CoverageUnion cu;
    cu.extractSegments(geom);

    double area_in = geom->getArea();

    auto ret = cu.polygonize(geom->getFactory());

    double area_out = ret->getArea();

    if (std::abs((area_out - area_in)/area_in) > AREA_PCT_DIFF_TOL) {
        throw geos::util::TopologyException("CoverageUnion cannot process overlapping inputs.");
    }

    return ret;
}

}
}
}
<|endoftext|>


<commit_before>#include "voyager/http/http_server.h"
#include "voyager/http/http_parser.h"
#include "voyager/http/http_response.h"
#include "voyager/core/tcp_connection.h"

namespace voyager {

HttpServer::HttpServer(EventLoop* ev,
                       const SockAddr& addr,
                       const std::string& name,
                       int thread_size)
    : server_(ev, addr, name, thread_size) {
  server_.SetConnectionCallback(std::bind(&HttpServer::NewConnection,
                                          this,
                                          std::placeholders::_1));
  server_.SetCloseCallback(std::bind(&HttpServer::HandleClose,
                                     this,
                                     std::placeholders::_1));
  server_.SetMessageCallback(std::bind(&HttpServer::HandleMessage,
                                       this,
                                       std::placeholders::_1,
                                       std::placeholders::_2));
}

void HttpServer::Start() {
  server_.Start();
}

void HttpServer::NewConnection(const TcpConnectionPtr& ptr) {
  ptr->SetUserData(new HttpParser());
}

void HttpServer::HandleClose(const TcpConnectionPtr& ptr) {
  HttpParser* parser = reinterpret_cast<HttpParser*>(ptr->UserData());
  delete parser;
}

void HttpServer::HandleMessage(const TcpConnectionPtr& ptr, Buffer* buf) {
  HttpParser* parser = reinterpret_cast<HttpParser*>(ptr->UserData());
  bool ok = parser->ParseBuffer(buf);
  if (!ok) {
    ptr->SendMessage(std::string("HTTP/1.1 400 Bad Request\r\n\r\n"));
    ptr->ShutDown();
  }

  if (parser->FinishParse()) {
    HttpRequestPtr request(parser->GetRequest());
    parser->Reset();
    HttpResponse response;

    std::string s(request->Value(HttpMessage::kConnection));

    if (strcasecmp(&*s.begin(), "close") == 0 ||
        (strcasecmp(&*s.begin(), "keep-alive") != 0 &&
        (request->Version() == HttpMessage::kHttp10))) {
      response.SetCloseState(true);
    }
    if (http_cb_) {
      http_cb_(request, &response);
    }

    ptr->SendMessage(&response.ResponseMessage());
    if (response.CloseState()) {
      ptr->ShutDown();
    }
  }
}

}  // namespace voyager
<commit_msg>fix bug<commit_after>#include "voyager/http/http_server.h"
#include "voyager/http/http_parser.h"
#include "voyager/http/http_response.h"
#include "voyager/core/tcp_connection.h"

namespace voyager {

HttpServer::HttpServer(EventLoop* ev,
                       const SockAddr& addr,
                       const std::string& name,
                       int thread_size)
    : server_(ev, addr, name, thread_size) {
  server_.SetConnectionCallback(std::bind(&HttpServer::NewConnection,
                                          this,
                                          std::placeholders::_1));
  server_.SetCloseCallback(std::bind(&HttpServer::HandleClose,
                                     this,
                                     std::placeholders::_1));
  server_.SetMessageCallback(std::bind(&HttpServer::HandleMessage,
                                       this,
                                       std::placeholders::_1,
                                       std::placeholders::_2));
}

void HttpServer::Start() {
  server_.Start();
}

void HttpServer::NewConnection(const TcpConnectionPtr& ptr) {
  ptr->SetUserData(new HttpParser());
}

void HttpServer::HandleClose(const TcpConnectionPtr& ptr) {
  HttpParser* parser = reinterpret_cast<HttpParser*>(ptr->UserData());
  delete parser;
}

void HttpServer::HandleMessage(const TcpConnectionPtr& ptr, Buffer* buf) {
  HttpParser* parser = reinterpret_cast<HttpParser*>(ptr->UserData());
  bool ok = parser->ParseBuffer(buf);
  if (!ok) {
    ptr->SendMessage(std::string("HTTP/1.1 400 Bad Request\r\n\r\n"));
    ptr->ShutDown();
  }

  if (parser->FinishParse()) {
    HttpRequestPtr request(parser->GetRequest());
    HttpResponse response;

    std::string s(request->Value(HttpMessage::kConnection));

    if (strcasecmp(&*s.begin(), "close") == 0 ||
        (strcasecmp(&*s.begin(), "keep-alive") != 0 &&
        (request->Version() == HttpMessage::kHttp10))) {
      response.SetCloseState(true);
    } else {
      parser->Reset();
    }

    if (http_cb_) {
      http_cb_(request, &response);
    }

    ptr->SendMessage(&response.ResponseMessage());
    if (response.CloseState()) {
      ptr->ShutDown();
    }
  }
}

}  // namespace voyager
<|endoftext|>


<commit_before>// $RCSfile: $
// $Revision: $ $Date: $
// Auth: Samson Bonfante (bonfante@steptools.com)
//
// Copyright (c) 1991-2016 by STEP Tools Inc.
//
// 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 "nodeMachineState.h"
#include "nodeUtils.h"
#include <stp_schema.h>
#include <future>
#include <thread>

StixSimGeomType GeomTypeFromString(char* typ)
{
    if (!strcmp(typ, "MESH"))
    {
	return STIXSIM_GT_MESH;
    }
    if (!strcmp(typ, "POLYLINE"))
    {
	return STIXSIM_GT_POLYLINE;
    }
    else
    {
	return STIXSIM_GT_NULL;
    }
}

typedef struct {
    /*SECRETLY A Nan::Global<v8::Promise::Resolver>* */
    void* pmise;
    double rtn;
} waitstruct;
std::vector<waitstruct> promisepool;
std::mutex pp_mutex;
void messager(uv_async_t *hanlde) {

    pp_mutex.lock();
    v8::HandleScope handle(v8::Isolate::GetCurrent());
    for(auto v:promisepool){
	auto ppmise = (Nan::Global<v8::Promise::Resolver>*)v.pmise;
	v8::Local<v8::Number> rtn = Nan::New(v.rtn);
	v8::Local<v8::Promise::Resolver> pmise = Nan::New(*(ppmise));
	pmise->Resolve(rtn);
	delete v.pmise;
    }
    promisepool.clear();
    pp_mutex.unlock();
}
void __waiterFunction(void* arg) {
    machineState * ms = static_cast<machineState*>(arg);
    ms->Wait();
}
void machineState::Wait() {
    bool wait = true;
    double rtn = 0;
    while (wait) {
	void * vpmise;
	wait = _ms->WaitForStateUpdate(vpmise, rtn);
	waitstruct waiter;
	waiter.pmise = vpmise;
	waiter.rtn = rtn;
	pp_mutex.lock();
	promisepool.push_back(waiter);
	pp_mutex.unlock();
	uv_async_send(&async);
	if (!wait) return;
    }
}

NAN_METHOD(machineState::New)
{

    if (info.IsConstructCall()){
    	if (info.Length() == 0){
    	    return;
    	}
        else if(info.Length() == 1 || (info.Length() == 2 && info[1]->BooleanValue() == false)){
        	char * b;
        	v8StringToChar(info[0], b);
        	machineState * ms = new machineState();
        	ms->_ms = MachineState::InitializeState(b);
        	delete[] b;
        	ms->Wrap(info.This());
        	info.GetReturnValue().Set(info.This());
        }
        else if(info.Length() == 2){
            char * b;
            v8StringToChar(info[0], b);
            bool c = info[1]->BooleanValue();
            machineState * ms = new machineState();
            ms->_ms = MachineState::InitializeState(b, c);
            delete[] b;
	    uv_async_init(uv_default_loop(), &ms->async, messager);
	    uv_thread_create(&ms->waitqueue, __waiterFunction, (void*)ms);

	    ms->Wrap(info.This());
            info.GetReturnValue().Set(info.This());
        }
        else{
            return;
        }
    }
    else{
	   return;
    }
}

NAN_METHOD(machineState::AdvanceState)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    ms->_ms->AdvanceState(&pmise);
    info.GetReturnValue().Set(pmise);
}

NAN_METHOD(machineState::GetGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    //This function has a 2 argument and a no argument version.
    if (info.Length() == 0)
    {
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn);
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	return;
    }
    else
    {
	if (info.Length() != 2) return; // invalid number of arguments
	if (info[0]->IsUndefined()) return; //No Given ID
	if (info[1]->IsUndefined()) return; //No Given Typ
	if (!info[0]->IsString()) return; //ID is not valid
	if (!info[1]->IsString()) return; //Typ is not valid
	char * id;
	v8StringToChar(info[0], id);
	RoseObject * obj = ms->_ms->FindObjectByID(id);
	if (!obj)
	{
	    delete[] id;
	    return; //No Object Associated with given ID
	}
	char * typ;
	v8StringToChar(info[1], typ);
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn, id, obj, GeomTypeFromString(typ));
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	delete[] id;
	delete[] typ;
	return;
    }
}

NAN_METHOD(machineState::GetDeltaGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
	return;
    if (!info[0]->IsNumber()) { // argument of wrong type
	return;
    }
    int in = Nan::To<int32_t>(info[0]).FromJust();
    RoseStringObject rtn;
    ms->_ms->GetDynamicGeometryJSON(rtn, in);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::ResetDeltaGeometry)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->ResetDynamicGeometry();
    return;
}

NAN_METHOD(machineState::GetDeltaStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,false);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetKeyStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,true);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GoToWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    RoseObject * obj = ms->_ms->design()->findByEntityId(Nan::To<int32_t>(info[0]).FromJust());
    if (!obj)
    return;
    stp_machining_workingstep * ws = ROSE_CAST(stp_machining_workingstep, obj);
    if(!ws)
    return;
    int rtnval = ms->_ms->GoToWS(ws);
    info.GetReturnValue().Set(rtnval);
    return;
}

NAN_METHOD(machineState::GetEIDfromUUID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    if(!info[0]->IsString())
    return;
    char * uuid = 0;
    v8StringToChar(info[0], uuid);
    RoseObject * obj = ms->_ms->FindObjectByID(uuid);
    if (!obj)
    return;
    int rtnval = obj->entity_id();
    info.GetReturnValue().Set(Nan::New(rtnval));
    return;
}

NAN_METHOD(machineState::LoadMachine)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info[0]->IsUndefined()) return;
    char * b;
    v8StringToChar(info[0], b);
    bool success = ms->_ms->SetMachine(b);
    info.GetReturnValue().Set(success);
    delete[] b;

    return;
}

NAN_METHOD(machineState::NextWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToNextWS();
    return;
}

NAN_METHOD(machineState::PrevWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToPrevWS();
    return;
}

NAN_METHOD(machineState::GetPrevWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetPrevWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetNextWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetNextWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetCurrentFeedrate)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double feed = ms->_ms->GetCurrentFeedrate();
    info.GetReturnValue().Set(feed);
    return;
}

NAN_METHOD(machineState::GetCurrentSpindleSpeed)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double speed = ms->_ms->GetCurrentSpindleSpeed();
    info.GetReturnValue().Set(speed);
    return;
}

NAN_METHOD(machineState::SetToolPosition)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 6) return;    // bad input

    double xyz[3];
    double ijk[3];

    for (int i=0; i<3; i++) {
	if (info[i]->IsUndefined()) return; // throw ex
	if (!info[i]->IsNumber()) return; // needs to be a number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	xyz[i] = num.FromJust();
    }

    for (int i=3; i<6; i++) {
	if (info[i]->IsUndefined()) return; // bad input
	if (!info[i]->IsNumber()) return; // check for number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	ijk[i - 3] = num.FromJust();
    }

    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    auto pased = new Nan::Global<v8::Promise::Resolver>(pmise);
    pased->Reset(pmise);
    ms->_ms->SetToolPosition(xyz, ijk,(pased));
    info.GetReturnValue().Set(pmise);
    return;
}

NAN_MODULE_INIT(machineState::Init)
{
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New("machineState").ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    Nan::SetPrototypeMethod(tpl, "AdvanceState", AdvanceState);
    Nan::SetPrototypeMethod(tpl, "GetGeometryJSON", GetGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaGeometryJSON", GetDeltaGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaStateJSON", GetDeltaStateJSON);
    Nan::SetPrototypeMethod(tpl, "GetKeyStateJSON", GetKeyStateJSON);
    Nan::SetPrototypeMethod(tpl, "GoToWS", GoToWS);
    Nan::SetPrototypeMethod(tpl, "GetEIDfromUUID", GetEIDfromUUID);
    Nan::SetPrototypeMethod(tpl, "LoadMachine", LoadMachine);
    Nan::SetPrototypeMethod(tpl, "NextWS", NextWS);
    Nan::SetPrototypeMethod(tpl, "PrevWS", PrevWS);
    Nan::SetPrototypeMethod(tpl, "GetPrevWSID", GetPrevWSID);
    Nan::SetPrototypeMethod(tpl, "GetWSID", GetWSID);
    Nan::SetPrototypeMethod(tpl, "GetNextWSID", GetNextWSID);
    Nan::SetPrototypeMethod(tpl, "GetCurrentFeedrate", GetCurrentFeedrate);
    Nan::SetPrototypeMethod(tpl, "GetCurrentSpindleSpeed", GetCurrentSpindleSpeed);
    Nan::SetPrototypeMethod(tpl, "SetToolPosition", SetToolPosition);
    Nan::SetPrototypeMethod(tpl, "ResetDeltaGeometry", ResetDeltaGeometry);
    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
    Nan::Set(target, Nan::New("machineState").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());

    MachineState::init();
}
<commit_msg>mutex from std::future switch to libuv for consistency.<commit_after>// $RCSfile: $
// $Revision: $ $Date: $
// Auth: Samson Bonfante (bonfante@steptools.com)
//
// Copyright (c) 1991-2016 by STEP Tools Inc.
//
// 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 "nodeMachineState.h"
#include "nodeUtils.h"
#include <stp_schema.h>
#include <thread>

StixSimGeomType GeomTypeFromString(char* typ)
{
    if (!strcmp(typ, "MESH"))
    {
	return STIXSIM_GT_MESH;
    }
    if (!strcmp(typ, "POLYLINE"))
    {
	return STIXSIM_GT_POLYLINE;
    }
    else
    {
	return STIXSIM_GT_NULL;
    }
}

typedef struct {
    /*SECRETLY A Nan::Global<v8::Promise::Resolver>* */
    void* pmise;
    double rtn;
} waitstruct;
std::vector<waitstruct> promisepool;
uv_mutex_t pp_mutex;
void messager(uv_async_t *hanlde) {

    uv_mutex_lock(&pp_mutex);
    v8::HandleScope handle(v8::Isolate::GetCurrent());
    for(auto v:promisepool){
	auto ppmise = (Nan::Global<v8::Promise::Resolver>*)v.pmise;
	v8::Local<v8::Number> rtn = Nan::New(v.rtn);
	v8::Local<v8::Promise::Resolver> pmise = Nan::New(*(ppmise));
	pmise->Resolve(rtn);
	delete v.pmise;
    }
    promisepool.clear();
    uv_mutex_unlock(&pp_mutex);
}
void __waiterFunction(void* arg) {
    machineState * ms = static_cast<machineState*>(arg);
    ms->Wait();
}
void machineState::Wait() {
    bool wait = true;
    double rtn = 0;
    while (wait) {
	void * vpmise;
	wait = _ms->WaitForStateUpdate(vpmise, rtn);
	waitstruct waiter;
	waiter.pmise = vpmise;
	waiter.rtn = rtn;
	uv_mutex_lock(&pp_mutex);
	promisepool.push_back(waiter);
	uv_mutex_unlock(&pp_mutex);
	uv_async_send(&async);
	if (!wait) return;
    }
}

NAN_METHOD(machineState::New)
{

    if (info.IsConstructCall()){
    	if (info.Length() == 0){
    	    return;
    	}
        else if(info.Length() == 1 || (info.Length() == 2 && info[1]->BooleanValue() == false)){
        	char * b;
        	v8StringToChar(info[0], b);
        	machineState * ms = new machineState();
        	ms->_ms = MachineState::InitializeState(b);
        	delete[] b;
        	ms->Wrap(info.This());
        	info.GetReturnValue().Set(info.This());
        }
        else if(info.Length() == 2){
            char * b;
            v8StringToChar(info[0], b);
            bool c = info[1]->BooleanValue();
            machineState * ms = new machineState();
            ms->_ms = MachineState::InitializeState(b, c);
            delete[] b;
	    uv_async_init(uv_default_loop(), &ms->async, messager);
	    uv_thread_create(&ms->waitqueue, __waiterFunction, (void*)ms);
	    uv_mutex_init(&pp_mutex);
	    ms->Wrap(info.This());
            info.GetReturnValue().Set(info.This());
        }
        else{
            return;
        }
    }
    else{
	   return;
    }
}

NAN_METHOD(machineState::AdvanceState)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    ms->_ms->AdvanceState(&pmise);
    info.GetReturnValue().Set(pmise);
}

NAN_METHOD(machineState::GetGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    //This function has a 2 argument and a no argument version.
    if (info.Length() == 0)
    {
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn);
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	return;
    }
    else
    {
	if (info.Length() != 2) return; // invalid number of arguments
	if (info[0]->IsUndefined()) return; //No Given ID
	if (info[1]->IsUndefined()) return; //No Given Typ
	if (!info[0]->IsString()) return; //ID is not valid
	if (!info[1]->IsString()) return; //Typ is not valid
	char * id;
	v8StringToChar(info[0], id);
	RoseObject * obj = ms->_ms->FindObjectByID(id);
	if (!obj)
	{
	    delete[] id;
	    return; //No Object Associated with given ID
	}
	char * typ;
	v8StringToChar(info[1], typ);
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn, id, obj, GeomTypeFromString(typ));
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	delete[] id;
	delete[] typ;
	return;
    }
}

NAN_METHOD(machineState::GetDeltaGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
	return;
    if (!info[0]->IsNumber()) { // argument of wrong type
	return;
    }
    int in = Nan::To<int32_t>(info[0]).FromJust();
    RoseStringObject rtn;
    ms->_ms->GetDynamicGeometryJSON(rtn, in);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::ResetDeltaGeometry)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->ResetDynamicGeometry();
    return;
}

NAN_METHOD(machineState::GetDeltaStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,false);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetKeyStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,true);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GoToWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    RoseObject * obj = ms->_ms->design()->findByEntityId(Nan::To<int32_t>(info[0]).FromJust());
    if (!obj)
    return;
    stp_machining_workingstep * ws = ROSE_CAST(stp_machining_workingstep, obj);
    if(!ws)
    return;
    int rtnval = ms->_ms->GoToWS(ws);
    info.GetReturnValue().Set(rtnval);
    return;
}

NAN_METHOD(machineState::GetEIDfromUUID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    if(!info[0]->IsString())
    return;
    char * uuid = 0;
    v8StringToChar(info[0], uuid);
    RoseObject * obj = ms->_ms->FindObjectByID(uuid);
    if (!obj)
    return;
    int rtnval = obj->entity_id();
    info.GetReturnValue().Set(Nan::New(rtnval));
    return;
}

NAN_METHOD(machineState::LoadMachine)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info[0]->IsUndefined()) return;
    char * b;
    v8StringToChar(info[0], b);
    bool success = ms->_ms->SetMachine(b);
    info.GetReturnValue().Set(success);
    delete[] b;

    return;
}

NAN_METHOD(machineState::NextWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToNextWS();
    return;
}

NAN_METHOD(machineState::PrevWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToPrevWS();
    return;
}

NAN_METHOD(machineState::GetPrevWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetPrevWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetNextWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetNextWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetCurrentFeedrate)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double feed = ms->_ms->GetCurrentFeedrate();
    info.GetReturnValue().Set(feed);
    return;
}

NAN_METHOD(machineState::GetCurrentSpindleSpeed)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double speed = ms->_ms->GetCurrentSpindleSpeed();
    info.GetReturnValue().Set(speed);
    return;
}

NAN_METHOD(machineState::SetToolPosition)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 6) return;    // bad input

    double xyz[3];
    double ijk[3];

    for (int i=0; i<3; i++) {
	if (info[i]->IsUndefined()) return; // throw ex
	if (!info[i]->IsNumber()) return; // needs to be a number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	xyz[i] = num.FromJust();
    }

    for (int i=3; i<6; i++) {
	if (info[i]->IsUndefined()) return; // bad input
	if (!info[i]->IsNumber()) return; // check for number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	ijk[i - 3] = num.FromJust();
    }

    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    auto pased = new Nan::Global<v8::Promise::Resolver>(pmise);
    pased->Reset(pmise);
    ms->_ms->SetToolPosition(xyz, ijk,(pased));
    info.GetReturnValue().Set(pmise);
    return;
}

NAN_MODULE_INIT(machineState::Init)
{
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New("machineState").ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    Nan::SetPrototypeMethod(tpl, "AdvanceState", AdvanceState);
    Nan::SetPrototypeMethod(tpl, "GetGeometryJSON", GetGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaGeometryJSON", GetDeltaGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaStateJSON", GetDeltaStateJSON);
    Nan::SetPrototypeMethod(tpl, "GetKeyStateJSON", GetKeyStateJSON);
    Nan::SetPrototypeMethod(tpl, "GoToWS", GoToWS);
    Nan::SetPrototypeMethod(tpl, "GetEIDfromUUID", GetEIDfromUUID);
    Nan::SetPrototypeMethod(tpl, "LoadMachine", LoadMachine);
    Nan::SetPrototypeMethod(tpl, "NextWS", NextWS);
    Nan::SetPrototypeMethod(tpl, "PrevWS", PrevWS);
    Nan::SetPrototypeMethod(tpl, "GetPrevWSID", GetPrevWSID);
    Nan::SetPrototypeMethod(tpl, "GetWSID", GetWSID);
    Nan::SetPrototypeMethod(tpl, "GetNextWSID", GetNextWSID);
    Nan::SetPrototypeMethod(tpl, "GetCurrentFeedrate", GetCurrentFeedrate);
    Nan::SetPrototypeMethod(tpl, "GetCurrentSpindleSpeed", GetCurrentSpindleSpeed);
    Nan::SetPrototypeMethod(tpl, "SetToolPosition", SetToolPosition);
    Nan::SetPrototypeMethod(tpl, "ResetDeltaGeometry", ResetDeltaGeometry);
    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
    Nan::Set(target, Nan::New("machineState").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());

    MachineState::init();
}
<|endoftext|>


<commit_before>// $RCSfile: $
// $Revision: $ $Date: $
// Auth: Samson Bonfante (bonfante@steptools.com)
//
// Copyright (c) 1991-2016 by STEP Tools Inc.
//
// 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 "nodeMachineState.h"
#include "nodeUtils.h"
#include <stp_schema.h>
#include <future>
#include <thread>

StixSimGeomType GeomTypeFromString(char* typ)
{
    if (!strcmp(typ, "MESH"))
    {
	return STIXSIM_GT_MESH;
    }
    if (!strcmp(typ, "POLYLINE"))
    {
	return STIXSIM_GT_POLYLINE;
    }
    else
    {
	return STIXSIM_GT_NULL;
    }
}

NAN_METHOD(machineState::New)
{

    if (info.IsConstructCall()){
    	if (info.Length() == 0){
    	    return;
    	}
        else if(info.Length() == 1 || (info.Length() == 2 && info[1]->BooleanValue() == false)){
        	char * b;
        	v8StringToChar(info[0], b);
        	machineState * ms = new machineState();
        	ms->_ms = MachineState::InitializeState(b);
        	delete[] b;
        	ms->Wrap(info.This());
        	info.GetReturnValue().Set(info.This());
        }
        else if(info.Length() == 2){
            char * b;
            v8StringToChar(info[0], b);
            bool c = info[1]->BooleanValue();
            machineState * ms = new machineState();
            ms->_ms = MachineState::InitializeState(b, c);
            delete[] b;
	    std::thread([ms]() {
		bool wait = true;
		double rtn = 0;
		while (wait) {
		    void * vpmise;
		    wait = ms->_ms->WaitForStateUpdate(vpmise, rtn);
		    printf("got Joe ptr %p\n", vpmise);
		    auto ppmise = (Nan::Global<v8::Promise::Resolver>*)vpmise;
		    v8::Local<v8::Promise::Resolver> pmise = Nan::New(*ppmise);
		    if (!wait) return;
		    pmise->Resolve(Nan::New(rtn));
		    delete ppmise;
		}
	    }).detach();
            ms->Wrap(info.This());
            info.GetReturnValue().Set(info.This());
        }
        else{
            return;
        }
    }
    else{
	   return;
    }
}

NAN_METHOD(machineState::AdvanceState)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    ms->_ms->AdvanceState(&pmise);
    info.GetReturnValue().Set(pmise);
}

NAN_METHOD(machineState::GetGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    //This function has a 2 argument and a no argument version.
    if (info.Length() == 0)
    {
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn);
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	return;
    }
    else
    {
	if (info.Length() != 2) return; // invalid number of arguments
	if (info[0]->IsUndefined()) return; //No Given ID
	if (info[1]->IsUndefined()) return; //No Given Typ
	if (!info[0]->IsString()) return; //ID is not valid
	if (!info[1]->IsString()) return; //Typ is not valid
	char * id;
	v8StringToChar(info[0], id);
	RoseObject * obj = ms->_ms->FindObjectByID(id);
	if (!obj)
	{
	    delete[] id;
	    return; //No Object Associated with given ID
	}
	char * typ;
	v8StringToChar(info[1], typ);
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn, id, obj, GeomTypeFromString(typ));
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	delete[] id;
	delete[] typ;
	return;
    }
}

NAN_METHOD(machineState::GetDeltaGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
	return;
    if (!info[0]->IsNumber()) { // argument of wrong type
	return;
    }
    RoseStringObject rtn;
    ms->_ms->GetDynamicGeometryJSON(rtn,Nan::To<int32_t>(info[0]).FromJust());
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetDeltaStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,false);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetKeyStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,true);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GoToWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    RoseObject * obj = ms->_ms->design()->findByEntityId(Nan::To<int32_t>(info[0]).FromJust());
    if (!obj)
    return;
    stp_machining_workingstep * ws = ROSE_CAST(stp_machining_workingstep, obj);
    if(!ws)
    return;
    int rtnval = ms->_ms->GoToWS(ws);
    info.GetReturnValue().Set(rtnval);
    return;
}

NAN_METHOD(machineState::GetEIDfromUUID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    if(!info[0]->IsString())
    return;
    char * uuid = 0;
    v8StringToChar(info[0], uuid);
    RoseObject * obj = ms->_ms->FindObjectByID(uuid);
    if (!obj)
    return;
    int rtnval = obj->entity_id();
    info.GetReturnValue().Set(Nan::New(rtnval));
    return;
}

NAN_METHOD(machineState::LoadMachine)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info[0]->IsUndefined()) return;
    char * b;
    v8StringToChar(info[0], b);
    bool success = ms->_ms->SetMachine(b);
    info.GetReturnValue().Set(success);
    delete[] b;

    return;
}

NAN_METHOD(machineState::NextWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToNextWS();
    return;
}

NAN_METHOD(machineState::PrevWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToPrevWS();
    return;
}

NAN_METHOD(machineState::GetPrevWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetPrevWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetNextWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetNextWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetCurrentFeedrate)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double feed = ms->_ms->GetCurrentFeedrate();
    info.GetReturnValue().Set(feed);
    return;
}

NAN_METHOD(machineState::GetCurrentSpindleSpeed)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double speed = ms->_ms->GetCurrentSpindleSpeed();
    info.GetReturnValue().Set(speed);
    return;
}

NAN_METHOD(machineState::SetToolPosition)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 6) return;    // bad input

    double xyz[3];
    double ijk[3];

    for (int i=0; i<3; i++) {
	if (info[i]->IsUndefined()) return; // throw ex
	if (!info[i]->IsNumber()) return; // needs to be a number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	xyz[i] = num.FromJust();
    }

    for (int i=3; i<6; i++) {
	if (info[i]->IsUndefined()) return; // bad input
	if (!info[i]->IsNumber()) return; // check for number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	ijk[i - 3] = num.FromJust();
    }

    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    auto pased = new Nan::Global<v8::Promise::Resolver>(pmise);
    pased->Reset(pmise);
    printf("giving Joe ptr %p\n", pased);
    ms->_ms->SetToolPosition(xyz, ijk,(pased));
    info.GetReturnValue().Set(pmise);
    return;
}

NAN_MODULE_INIT(machineState::Init)
{
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New("machineState").ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    Nan::SetPrototypeMethod(tpl, "AdvanceState", AdvanceState);
    Nan::SetPrototypeMethod(tpl, "GetGeometryJSON", GetGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaGeometryJSON", GetDeltaGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaStateJSON", GetDeltaStateJSON);
    Nan::SetPrototypeMethod(tpl, "GetKeyStateJSON", GetKeyStateJSON);
    Nan::SetPrototypeMethod(tpl, "GoToWS", GoToWS);
    Nan::SetPrototypeMethod(tpl, "GetEIDfromUUID", GetEIDfromUUID);
    Nan::SetPrototypeMethod(tpl, "LoadMachine", LoadMachine);
    Nan::SetPrototypeMethod(tpl, "NextWS", NextWS);
    Nan::SetPrototypeMethod(tpl, "PrevWS", PrevWS);
    Nan::SetPrototypeMethod(tpl, "GetPrevWSID", GetPrevWSID);
    Nan::SetPrototypeMethod(tpl, "GetWSID", GetWSID);
    Nan::SetPrototypeMethod(tpl, "GetNextWSID", GetNextWSID);
    Nan::SetPrototypeMethod(tpl, "GetCurrentFeedrate", GetCurrentFeedrate);
    Nan::SetPrototypeMethod(tpl, "GetCurrentSpindleSpeed", GetCurrentSpindleSpeed);
    Nan::SetPrototypeMethod(tpl, "SetToolPosition", SetToolPosition);
    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
    Nan::Set(target, Nan::New("machineState").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());

    MachineState::init();
}
<commit_msg>Fixed some isolate idiocy<commit_after>// $RCSfile: $
// $Revision: $ $Date: $
// Auth: Samson Bonfante (bonfante@steptools.com)
//
// Copyright (c) 1991-2016 by STEP Tools Inc.
//
// 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 "nodeMachineState.h"
#include "nodeUtils.h"
#include <stp_schema.h>
#include <future>
#include <thread>

StixSimGeomType GeomTypeFromString(char* typ)
{
    if (!strcmp(typ, "MESH"))
    {
	return STIXSIM_GT_MESH;
    }
    if (!strcmp(typ, "POLYLINE"))
    {
	return STIXSIM_GT_POLYLINE;
    }
    else
    {
	return STIXSIM_GT_NULL;
    }
}

NAN_METHOD(machineState::New)
{

    if (info.IsConstructCall()){
    	if (info.Length() == 0){
    	    return;
    	}
        else if(info.Length() == 1 || (info.Length() == 2 && info[1]->BooleanValue() == false)){
        	char * b;
        	v8StringToChar(info[0], b);
        	machineState * ms = new machineState();
        	ms->_ms = MachineState::InitializeState(b);
        	delete[] b;
        	ms->Wrap(info.This());
        	info.GetReturnValue().Set(info.This());
        }
        else if(info.Length() == 2){
            char * b;
            v8StringToChar(info[0], b);
            bool c = info[1]->BooleanValue();
            machineState * ms = new machineState();
            ms->_ms = MachineState::InitializeState(b, c);
            delete[] b;
	    v8::Isolate* iso = Nan::GetCurrentContext()->GetIsolate();
	    std::thread([ms,iso]() {
		bool wait = true;
		double rtn = 0;
		while (wait) {
		    void * vpmise;
		    wait = ms->_ms->WaitForStateUpdate(vpmise, rtn);
		    printf("got Joe ptr %p\n", vpmise);
		    auto ppmise = (Nan::Global<v8::Promise::Resolver>*)vpmise;
		    v8::Local<v8::Promise::Resolver> pmise = v8::Local<v8::Promise::Resolver>::New(iso,*ppmise);
		    if (!wait) return;
		    pmise->Resolve(v8::Number::New(iso,rtn));
		    delete ppmise;
		}
	    }).detach();
            ms->Wrap(info.This());
            info.GetReturnValue().Set(info.This());
        }
        else{
            return;
        }
    }
    else{
	   return;
    }
}

NAN_METHOD(machineState::AdvanceState)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    ms->_ms->AdvanceState(&pmise);
    info.GetReturnValue().Set(pmise);
}

NAN_METHOD(machineState::GetGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    //This function has a 2 argument and a no argument version.
    if (info.Length() == 0)
    {
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn);
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	return;
    }
    else
    {
	if (info.Length() != 2) return; // invalid number of arguments
	if (info[0]->IsUndefined()) return; //No Given ID
	if (info[1]->IsUndefined()) return; //No Given Typ
	if (!info[0]->IsString()) return; //ID is not valid
	if (!info[1]->IsString()) return; //Typ is not valid
	char * id;
	v8StringToChar(info[0], id);
	RoseObject * obj = ms->_ms->FindObjectByID(id);
	if (!obj)
	{
	    delete[] id;
	    return; //No Object Associated with given ID
	}
	char * typ;
	v8StringToChar(info[1], typ);
	RoseStringObject rtn;
	ms->_ms->GetGeometryJSON(rtn, id, obj, GeomTypeFromString(typ));
	info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
	delete[] id;
	delete[] typ;
	return;
    }
}

NAN_METHOD(machineState::GetDeltaGeometryJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
	return;
    if (!info[0]->IsNumber()) { // argument of wrong type
	return;
    }
    RoseStringObject rtn;
    ms->_ms->GetDynamicGeometryJSON(rtn,Nan::To<int32_t>(info[0]).FromJust());
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetDeltaStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,false);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GetKeyStateJSON)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    RoseStringObject rtn;
    ms->_ms->GetStateJSON(rtn,true);
    info.GetReturnValue().Set(CharTov8String(rtn.as_const()));
    return;
}

NAN_METHOD(machineState::GoToWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    RoseObject * obj = ms->_ms->design()->findByEntityId(Nan::To<int32_t>(info[0]).FromJust());
    if (!obj)
    return;
    stp_machining_workingstep * ws = ROSE_CAST(stp_machining_workingstep, obj);
    if(!ws)
    return;
    int rtnval = ms->_ms->GoToWS(ws);
    info.GetReturnValue().Set(rtnval);
    return;
}

NAN_METHOD(machineState::GetEIDfromUUID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 1) //Function takes one argument
    return;
    if(!info[0]->IsString())
    return;
    char * uuid = 0;
    v8StringToChar(info[0], uuid);
    RoseObject * obj = ms->_ms->FindObjectByID(uuid);
    if (!obj)
    return;
    int rtnval = obj->entity_id();
    info.GetReturnValue().Set(Nan::New(rtnval));
    return;
}

NAN_METHOD(machineState::LoadMachine)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info[0]->IsUndefined()) return;
    char * b;
    v8StringToChar(info[0], b);
    bool success = ms->_ms->SetMachine(b);
    info.GetReturnValue().Set(success);
    delete[] b;

    return;
}

NAN_METHOD(machineState::NextWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToNextWS();
    return;
}

NAN_METHOD(machineState::PrevWS)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    ms->_ms->GoToPrevWS();
    return;
}

NAN_METHOD(machineState::GetPrevWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetPrevWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetNextWSID)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    int id = ms->_ms->GetNextWSID();
    info.GetReturnValue().Set(id);
    return;
}

NAN_METHOD(machineState::GetCurrentFeedrate)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double feed = ms->_ms->GetCurrentFeedrate();
    info.GetReturnValue().Set(feed);
    return;
}

NAN_METHOD(machineState::GetCurrentSpindleSpeed)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (!info[0]->IsUndefined()) return; //This function takes no arguments.
    double speed = ms->_ms->GetCurrentSpindleSpeed();
    info.GetReturnValue().Set(speed);
    return;
}

NAN_METHOD(machineState::SetToolPosition)
{
    machineState * ms = Nan::ObjectWrap::Unwrap<machineState>(info.This());
    if (!ms || !(ms->_ms)) return;
    if (info.Length() != 6) return;    // bad input

    double xyz[3];
    double ijk[3];

    for (int i=0; i<3; i++) {
	if (info[i]->IsUndefined()) return; // throw ex
	if (!info[i]->IsNumber()) return; // needs to be a number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	xyz[i] = num.FromJust();
    }

    for (int i=3; i<6; i++) {
	if (info[i]->IsUndefined()) return; // bad input
	if (!info[i]->IsNumber()) return; // check for number

	Nan::Maybe<double> num = Nan::To<double>(info[i]);

	ijk[i - 3] = num.FromJust();
    }

    v8::Local<v8::Promise::Resolver> pmise = v8::Promise::Resolver::New(info.GetIsolate());
    auto pased = new Nan::Global<v8::Promise::Resolver>(pmise);
    pased->Reset(pmise);
    printf("giving Joe ptr %p\n", pased);
    ms->_ms->SetToolPosition(xyz, ijk,(pased));
    info.GetReturnValue().Set(pmise);
    return;
}

NAN_MODULE_INIT(machineState::Init)
{
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New("machineState").ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    Nan::SetPrototypeMethod(tpl, "AdvanceState", AdvanceState);
    Nan::SetPrototypeMethod(tpl, "GetGeometryJSON", GetGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaGeometryJSON", GetDeltaGeometryJSON);
    Nan::SetPrototypeMethod(tpl, "GetDeltaStateJSON", GetDeltaStateJSON);
    Nan::SetPrototypeMethod(tpl, "GetKeyStateJSON", GetKeyStateJSON);
    Nan::SetPrototypeMethod(tpl, "GoToWS", GoToWS);
    Nan::SetPrototypeMethod(tpl, "GetEIDfromUUID", GetEIDfromUUID);
    Nan::SetPrototypeMethod(tpl, "LoadMachine", LoadMachine);
    Nan::SetPrototypeMethod(tpl, "NextWS", NextWS);
    Nan::SetPrototypeMethod(tpl, "PrevWS", PrevWS);
    Nan::SetPrototypeMethod(tpl, "GetPrevWSID", GetPrevWSID);
    Nan::SetPrototypeMethod(tpl, "GetWSID", GetWSID);
    Nan::SetPrototypeMethod(tpl, "GetNextWSID", GetNextWSID);
    Nan::SetPrototypeMethod(tpl, "GetCurrentFeedrate", GetCurrentFeedrate);
    Nan::SetPrototypeMethod(tpl, "GetCurrentSpindleSpeed", GetCurrentSpindleSpeed);
    Nan::SetPrototypeMethod(tpl, "SetToolPosition", SetToolPosition);
    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
    Nan::Set(target, Nan::New("machineState").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());

    MachineState::init();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 - 2014 Jolla Ltd.
** Contact: http://jolla.com/
**
** This file is part of Qt Creator.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Digia.
**
****************************************************************************/

#include "merdeployconfigurationfactory.h"

#include "merconstants.h"
#include "merdeployconfiguration.h"
#include "merdeploysteps.h"
#include "merdevicefactory.h"
#include "merrpmpackagingstep.h"
#include "meruploadandinstallrpmsteps.h"

#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <remotelinux/genericdirectuploadstep.h>
#include <utils/qtcassert.h>

using namespace ProjectExplorer;

namespace Mer {
namespace Internal {

MerDeployConfigurationFactory::MerDeployConfigurationFactory(QObject *parent)
    : DeployConfigurationFactory(parent)
{
}

QList<Core::Id> MerDeployConfigurationFactory::availableCreationIds(Target *parent) const
{
    QList<Core::Id> ids;
    //TODO: canHandle(parent)
    Core::Id type = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(parent->kit());
    if (type == Constants::MER_DEVICE_TYPE) {
        ids << MerMb2RpmBuildConfiguration::configurationId()
            << MerRsyncDeployConfiguration::configurationId()
            << MerRpmDeployConfiguration::configurationId();
            //<< MerRpmBuildDeployConfiguration::configurationId();
    }

    return ids;
}

QString MerDeployConfigurationFactory::displayNameForId(const Core::Id id) const
{
    if (id == MerRsyncDeployConfiguration::configurationId())
        return MerRsyncDeployConfiguration::displayName();
    else if (id == MerRpmDeployConfiguration::configurationId())
        return MerRpmDeployConfiguration::displayName();
    else if (id == MerMb2RpmBuildConfiguration::configurationId())
        return MerMb2RpmBuildConfiguration::displayName();
    else if (id == MerRpmBuildDeployConfiguration::configurationId())
        return MerRpmBuildDeployConfiguration::displayName();

    return QString();
}

bool MerDeployConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
{
    if (canHandle(parent) && availableCreationIds(parent).contains(id))
        return true;

    return false;
}

DeployConfiguration *MerDeployConfigurationFactory::create(Target *parent, const Core::Id id)
{
    QTC_ASSERT(canCreate(parent, id), return 0);

    ProjectExplorer::DeployConfiguration *dc = 0;

     if (id == MerRpmDeployConfiguration::configurationId()) {
         dc = new MerRpmDeployConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerMb2RpmDeployStep(dc->stepList()));
     } else if (id == MerRsyncDeployConfiguration::configurationId()) {
         dc = new MerRsyncDeployConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerMb2RsyncDeployStep(dc->stepList()));
     } else if (id == MerMb2RpmBuildConfiguration::configurationId()) {
         dc = new MerMb2RpmBuildConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerMb2RpmBuildStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerRpmValidationStep(dc->stepList()));
         //dc->stepList()->insertStep(2, new MerUploadAndInstallRpmStep(dc->stepList()));
     } else if (id == MerRpmBuildDeployConfiguration::configurationId()) {
         dc = new MerRpmBuildDeployConfiguration(parent, id);
         dc->stepList()->insertStep(1, new MerRpmPackagingStep(dc->stepList()));
         dc->stepList()->insertStep(2, new MerUploadAndInstallRpmStep(dc->stepList()));
     }

    return dc;
}

bool MerDeployConfigurationFactory::canRestore(ProjectExplorer::Target *parent,
                                               const QVariantMap &map) const
{
    return canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::DeployConfiguration *MerDeployConfigurationFactory::restore(
        ProjectExplorer::Target *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;

    Core::Id id = ProjectExplorer::idFromMap(map);

    MerDeployConfiguration * const dc = qobject_cast<MerDeployConfiguration *>(create(parent, id));
    QTC_ASSERT(dc, return 0);
    if (!dc->fromMap(map)) {
        delete dc;
        return 0;
    }

    if (!dc->stepList()->contains(MerPrepareTargetStep::stepId()))
        dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));

    return dc;
}

bool MerDeployConfigurationFactory::canClone(ProjectExplorer::Target *parent,
                                             ProjectExplorer::DeployConfiguration *source) const
{
    return canCreate(parent, source->id());
}

ProjectExplorer::DeployConfiguration *MerDeployConfigurationFactory::clone(
        ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source)
{
    if (!canClone(parent, source))
        return 0;
    if (source->id() == MerRpmDeployConfiguration::configurationId()) {
        return new MerRpmDeployConfiguration(parent, qobject_cast<MerRpmDeployConfiguration *>(source));
    } else if(source->id() == MerRsyncDeployConfiguration::configurationId()){
        return new MerRsyncDeployConfiguration(parent, qobject_cast<MerRsyncDeployConfiguration *>(source));
    }else if(source->id() == MerMb2RpmBuildConfiguration::configurationId()){
        return new MerMb2RpmBuildConfiguration(parent, qobject_cast<MerMb2RpmBuildConfiguration *>(source));
    } else if(source->id() == MerRpmBuildDeployConfiguration::configurationId()){
        return new MerRpmBuildDeployConfiguration(parent, qobject_cast<MerRpmBuildDeployConfiguration *>(source));
    }

    return 0;
}

bool MerDeployConfigurationFactory::canHandle(ProjectExplorer::Target *t) const
{
    return MerDeviceFactory::canCreate(ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(t->kit()));
}

} // Internal
} // Mer
<commit_msg>Mer: Omit MerPrepareTargetStep for MerMb2RpmBuildConfiguration<commit_after>/****************************************************************************
**
** Copyright (C) 2012 - 2014 Jolla Ltd.
** Contact: http://jolla.com/
**
** This file is part of Qt Creator.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Digia.
**
****************************************************************************/

#include "merdeployconfigurationfactory.h"

#include "merconstants.h"
#include "merdeployconfiguration.h"
#include "merdeploysteps.h"
#include "merdevicefactory.h"
#include "merrpmpackagingstep.h"
#include "meruploadandinstallrpmsteps.h"

#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <remotelinux/genericdirectuploadstep.h>
#include <utils/qtcassert.h>

using namespace ProjectExplorer;

namespace Mer {
namespace Internal {

MerDeployConfigurationFactory::MerDeployConfigurationFactory(QObject *parent)
    : DeployConfigurationFactory(parent)
{
}

QList<Core::Id> MerDeployConfigurationFactory::availableCreationIds(Target *parent) const
{
    QList<Core::Id> ids;
    //TODO: canHandle(parent)
    Core::Id type = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(parent->kit());
    if (type == Constants::MER_DEVICE_TYPE) {
        ids << MerMb2RpmBuildConfiguration::configurationId()
            << MerRsyncDeployConfiguration::configurationId()
            << MerRpmDeployConfiguration::configurationId();
            //<< MerRpmBuildDeployConfiguration::configurationId();
    }

    return ids;
}

QString MerDeployConfigurationFactory::displayNameForId(const Core::Id id) const
{
    if (id == MerRsyncDeployConfiguration::configurationId())
        return MerRsyncDeployConfiguration::displayName();
    else if (id == MerRpmDeployConfiguration::configurationId())
        return MerRpmDeployConfiguration::displayName();
    else if (id == MerMb2RpmBuildConfiguration::configurationId())
        return MerMb2RpmBuildConfiguration::displayName();
    else if (id == MerRpmBuildDeployConfiguration::configurationId())
        return MerRpmBuildDeployConfiguration::displayName();

    return QString();
}

bool MerDeployConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
{
    if (canHandle(parent) && availableCreationIds(parent).contains(id))
        return true;

    return false;
}

DeployConfiguration *MerDeployConfigurationFactory::create(Target *parent, const Core::Id id)
{
    QTC_ASSERT(canCreate(parent, id), return 0);

    ProjectExplorer::DeployConfiguration *dc = 0;

     if (id == MerRpmDeployConfiguration::configurationId()) {
         dc = new MerRpmDeployConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerMb2RpmDeployStep(dc->stepList()));
     } else if (id == MerRsyncDeployConfiguration::configurationId()) {
         dc = new MerRsyncDeployConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerMb2RsyncDeployStep(dc->stepList()));
     } else if (id == MerMb2RpmBuildConfiguration::configurationId()) {
         dc = new MerMb2RpmBuildConfiguration(parent, id);
         dc->stepList()->insertStep(0, new MerMb2RpmBuildStep(dc->stepList()));
         dc->stepList()->insertStep(1, new MerRpmValidationStep(dc->stepList()));
         //dc->stepList()->insertStep(2, new MerUploadAndInstallRpmStep(dc->stepList()));
     } else if (id == MerRpmBuildDeployConfiguration::configurationId()) {
         dc = new MerRpmBuildDeployConfiguration(parent, id);
         dc->stepList()->insertStep(1, new MerRpmPackagingStep(dc->stepList()));
         dc->stepList()->insertStep(2, new MerUploadAndInstallRpmStep(dc->stepList()));
     }

    return dc;
}

bool MerDeployConfigurationFactory::canRestore(ProjectExplorer::Target *parent,
                                               const QVariantMap &map) const
{
    return canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::DeployConfiguration *MerDeployConfigurationFactory::restore(
        ProjectExplorer::Target *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;

    Core::Id id = ProjectExplorer::idFromMap(map);

    MerDeployConfiguration * const dc = qobject_cast<MerDeployConfiguration *>(create(parent, id));
    QTC_ASSERT(dc, return 0);
    if (!dc->fromMap(map)) {
        delete dc;
        return 0;
    }

    if (!dc->stepList()->contains(MerPrepareTargetStep::stepId())
            && id != MerMb2RpmBuildConfiguration::configurationId()) {
        dc->stepList()->insertStep(0, new MerPrepareTargetStep(dc->stepList()));
    }

    return dc;
}

bool MerDeployConfigurationFactory::canClone(ProjectExplorer::Target *parent,
                                             ProjectExplorer::DeployConfiguration *source) const
{
    return canCreate(parent, source->id());
}

ProjectExplorer::DeployConfiguration *MerDeployConfigurationFactory::clone(
        ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source)
{
    if (!canClone(parent, source))
        return 0;
    if (source->id() == MerRpmDeployConfiguration::configurationId()) {
        return new MerRpmDeployConfiguration(parent, qobject_cast<MerRpmDeployConfiguration *>(source));
    } else if(source->id() == MerRsyncDeployConfiguration::configurationId()){
        return new MerRsyncDeployConfiguration(parent, qobject_cast<MerRsyncDeployConfiguration *>(source));
    }else if(source->id() == MerMb2RpmBuildConfiguration::configurationId()){
        return new MerMb2RpmBuildConfiguration(parent, qobject_cast<MerMb2RpmBuildConfiguration *>(source));
    } else if(source->id() == MerRpmBuildDeployConfiguration::configurationId()){
        return new MerRpmBuildDeployConfiguration(parent, qobject_cast<MerRpmBuildDeployConfiguration *>(source));
    }

    return 0;
}

bool MerDeployConfigurationFactory::canHandle(ProjectExplorer::Target *t) const
{
    return MerDeviceFactory::canCreate(ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(t->kit()));
}

} // Internal
} // Mer
<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <cstring>

class Solution {
public:
    using vector = std::vector<int>;

    int strStr(char* T, char* P) {
        if (T[0] == '\0' || P[0] == '\0') {
            if (P[0] == '\0') {
                return 0;
            }

            return -1;
        }

        vector overlap;
        buildOverlapTable(P, overlap);

        const auto length = strlen(T), end = overlap.size() - 1;

        for (int m{}, i{}; m + i < length;) {
            if (P[i] == T[m + i]) {
                if (i == end) {
                    return m;
                }
                ++i;
            } else {
                if (overlap[i] > -1) {
                    m += i - overlap[i];
                    i = overlap[i];
                } else {
                    i = 0;
                    ++m;
                }
            }
        }

        return -1;
    }

private:
    void buildOverlapTable(char* needle, vector& table) {
        table.clear();

        if (needle[0] == '\0') {
            return;
        }

        table.push_back(-1);

        if (needle[1] == '\0') {
            return;
        }

        table.push_back(0);

        // Table constructing magic
        {
            int cnd{};

            for (char* str = needle + 2; *str != '\0';) {
                if (str[-1] == needle[cnd]) {
                    ++cnd;
                    table.push_back(cnd);
                    ++str;
                } else if (cnd > 0) {
                    cnd = table[cnd];
                } else {
                    table.push_back(0);
                    ++str;
                }
            }
        }
    }
};
<commit_msg>changed var names to something a little more helpful<commit_after>#pragma once

#include <vector>
#include <cstring>

class Solution {
public:
    using vector = std::vector<int>;

    int strStr(char* haystack, char* needle
    ) {
        if (haystack[0] == '\0' || needle[0] == '\0') {
            if (needle[0] == '\0') {
                return 0;
            }

            return -1;
        }

        vector overlap;
        buildOverlapTable(needle, overlap);

        const auto length = strlen(haystack), end = overlap.size() - 1;

        for (int m{}, i{}; m + i < length;) {
            if (needle[i] == haystack[m + i]) {
                if (i == end) {
                    return m;
                }
                ++i;
            } else {
                if (overlap[i] > -1) {
                    m += i - overlap[i];
                    i = overlap[i];
                } else {
                    i = 0;
                    ++m;
                }
            }
        }

        return -1;
    }

private:
    void buildOverlapTable(char* needle, vector& table) {
        table.clear();

        if (needle[0] == '\0') {
            return;
        }

        table.push_back(-1);

        if (needle[1] == '\0') {
            return;
        }

        table.push_back(0);

        // Table constructing magic
        {
            int cnd{};

            for (char* str = needle + 2; *str != '\0';) {
                if (str[-1] == needle[cnd]) {
                    ++cnd;
                    table.push_back(cnd);
                    ++str;
                } else if (cnd > 0) {
                    cnd = table[cnd];
                } else {
                    table.push_back(0);
                    ++str;
                }
            }
        }
    }
};
<|endoftext|>