text: //=========================================================================
  //  Copyright (c) Kitware, Inc.
  //  All rights reserved.
  //  See LICENSE.txt for details.
  //
  //  This software is distributed WITHOUT ANY WARRANTY; without even
  //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  //  PURPOSE.  See the above copyright notice for more information.
  //=========================================================================
  #include "smtk/bridge/cgm/operators/Sweep.h"
  
  #include "smtk/bridge/cgm/Session.h"
  #include "smtk/bridge/cgm/CAUUID.h"
  #include "smtk/bridge/cgm/Engines.h"
  #include "smtk/bridge/cgm/TDUUID.h"
  
  #include "smtk/io/Logger.h"
  
  #include "smtk/model/CellEntity.h"
  #include "smtk/model/Manager.h"
  #include "smtk/model/Model.h"
  
  #include "smtk/attribute/Attribute.h"
  #include "smtk/attribute/DoubleItem.h"
  #include "smtk/attribute/IntItem.h"
  #include "smtk/attribute/ModelEntityItem.h"
  #include "smtk/attribute/StringItem.h"
  
  #include "CGMApp.hpp"
  #include "DagType.hpp"
  #include "CubitAttribManager.hpp"
  #include "CubitCompat.hpp"
  #include "CubitDefines.h"
  #include "DLIList.hpp"
  #include "InitCGMA.hpp"
  #include "GeometryModifyTool.hpp"
  #include "GeometryQueryEngine.hpp"
  #include "GeometryQueryTool.hpp"
  #include "RefEdge.hpp"
  #include "RefEntity.hpp"
  #include "RefEntityFactory.hpp"
  #include "RefGroup.hpp"
  #include "Body.hpp"
  
  #include "smtk/bridge/cgm/Sweep_xml.h"
  
  using namespace smtk::model;
  using smtk::attribute::ModelEntityItemPtr;
  
  namespace smtk {
    namespace bridge {
      namespace cgm {
  
  smtk::model::OperatorResult Sweep::operateInternal()
  {
    // 0 = extrude, 1 = revolve, 2 = helix, 3 = sweep along curve:
    int sweepOp = this->findInt("construction method")->value();
    int keepInputs = this->findInt("keep inputs")->value();
    smtk::model::EntityRefArray expunged;
    DLIList<RefEntity*> cgmThingsToSweep;
    DLIList<RefEdge*> cgmSweepPath;
    bool ok = true;
    ok &= this->cgmEntities(*this->specification()->associations().get(), cgmThingsToSweep, keepInputs, expunged);
    if (sweepOp == 3) // sweep along curve
      ok &= this->cgmEntities(*this->findModelEntity("sweep path").get(), cgmSweepPath, keepInputs, expunged);
  
    if (!ok)
      return this->createResult(smtk::model::OPERATION_FAILED);
  
    DLIList<Body*> cgmResults;
    CubitStatus s;
    switch (sweepOp)
      {
    case 0: // extrude
        {
        s = CUBIT_FAILURE;
        smtk::attribute::DoubleItemPtr sweepDistItem = this->findDouble("sweep distance");
        double sweepDist = sweepDistItem->isEnabled() ? sweepDistItem->value() : 0.0;
        smtk::attribute::DoubleItemPtr extrudeDirItem = this->findDouble("extrusion direction");
        double draftAngle = this->findDouble("draft angle")->value();
        int draftType = this->findInt("draft type")->value();
        // Sweep along a direction (if given)
        if (extrudeDirItem->isEnabled())
          {
          std::vector<double> sweepDir(extrudeDirItem->begin(), extrudeDirItem->end());
          double sweepDirMag2 = 0.;
          for (int i = 0; i < 3; ++i)
            sweepDirMag2 += sweepDir[i] * sweepDir[i];
          if (sweepDirMag2 != 0.)
            {
            // Scale the sweep direction to match the distance specified:
            if (sweepDistItem->isEnabled() && sweepDist != 0.0)
              {
              double scaleFactor = sweepDist / sqrt(sweepDirMag2);
              for (int i = 0; i < 3; ++i)
                sweepDir[i] *= scaleFactor;
              }
            // Perform a sweep along a specified direction
            s = GeometryModifyTool::instance()->sweep_translational(
              cgmThingsToSweep,
              CubitVector(&sweepDir[0]),
              draftAngle,
              draftType,
              /* switch_side, unused */ CUBIT_FALSE,
              /* rigid, unused */ CUBIT_FALSE,
              /* anchor_entity */ CUBIT_FALSE,
              keepInputs,
              cgmResults
            );
            }
          }
        // Sweep direction unspecified. Try a perpendicular sweep.
        if (
          s == CUBIT_FAILURE &&
          !extrudeDirItem->isEnabled() &&
          sweepDistItem->isEnabled() &&
          sweepDist != 0.0)
          {
          s = GeometryModifyTool::instance()->sweep_perpendicular(
            cgmThingsToSweep,
            sweepDist,
            draftAngle,
            draftType,
            /* switch_side, unused */ CUBIT_FALSE,
            /* rigid, unused */ CUBIT_FALSE,
            /* anchor_entity */ CUBIT_FALSE,
            keepInputs,
            cgmResults
          );
          }
        if (s == CUBIT_FAILURE)
          {
          smtkInfoMacro(log(),
            "At least one of the \"extrusion direction\" and \"sweep distance\" "
            "items must be enabled and set to a non-zero value.");
          }
        }
      break;
    case 1: // revolve
        {
        double sweepAngle = this->findDouble("sweep angle")->value();
        smtk::attribute::DoubleItemPtr sweepBaseItem = this->findDouble("axis base point");
        smtk::attribute::DoubleItemPtr sweepAxisItem = this->findDouble("axis of revolution");
        std::vector<double> sweepBase(sweepBaseItem->begin(), sweepBaseItem->end());
        std::vector<double> sweepAxis(sweepAxisItem->begin(), sweepAxisItem->end());
        s = GeometryModifyTool::instance()->sweep_rotational(
          cgmThingsToSweep,
          CubitVector(&sweepBase[0]), CubitVector(&sweepAxis[0]), sweepAngle,
          cgmResults,
          /* anchor_entity, unused */ false,
          keepInputs
        );
        }
      break;
    case 2: // helix
        {
        double helixAngle = this->findDouble("helix angle")->value();
        double pitch = this->findDouble("pitch")->value();
        bool righthanded = this->findInt("handedness")->value() ? true : false;
        smtk::attribute::DoubleItemPtr sweepBaseItem = this->findDouble("axis base point");
        smtk::attribute::DoubleItemPtr sweepAxisItem = this->findDouble("axis of revolution");
        std::vector<double> sweepBase(sweepBaseItem->begin(), sweepBaseItem->end());
        std::vector<double> sweepAxis(sweepAxisItem->begin(), sweepAxisItem->end());
        CubitVector cbtSweepBase(&sweepBase[0]);
        CubitVector cbtSweepAxis(&sweepAxis[0]);
        s = GeometryModifyTool::instance()->sweep_helical(
          cgmThingsToSweep,
          cbtSweepBase,
          cbtSweepAxis,
          pitch,
          helixAngle,
          righthanded,
          /* anchor_entity, unused */ CUBIT_FALSE,
          keepInputs,
          cgmResults
        );
        }
      break;
    case 3: // sweep along path
        {
        s = GeometryModifyTool::instance()->sweep_along_curve(
          cgmThingsToSweep,
          cgmSweepPath,
          cgmResults,
          /* anchor_entity, unused */ CUBIT_FALSE,
          keepInputs,
          /* draft_angle, unused */ 0.0,
          /* draft_type, unused */ 0,
          /* rigid, unused */ CUBIT_FALSE
          );
        }
      break;
    default:
      smtkInfoMacro(log(),
        "Unexpected sweep construction method " << sweepOp << ".");
      s = CUBIT_FAILURE;
      break;
      }
  
    if (s != CUBIT_SUCCESS)
      {
      smtkInfoMacro(log(), "Failed to perform sweep (status " << s << ").");
      return this->createResult(smtk::model::OPERATION_FAILED);
      }
  
    smtk::model::OperatorResult result = this->createResult(
      smtk::model::OPERATION_SUCCEEDED);
  
    this->addEntitiesToResult(cgmResults, result, CREATED);
    result->findModelEntity("expunged")->setValues(expunged.begin(), expunged.end());
  
    return result;
  }
  
      } // namespace cgm
    } //namespace bridge
  } // namespace smtk
  
  smtkImplementsModelOperator(
    SMTKCGMSESSION_EXPORT,
    smtk::bridge::cgm::Sweep,
    cgm_sweep,
    "sweep",
    Sweep_xml,
    smtk::bridge::cgm::Session);
  