diff --git a/Base/Core/imstkAPIUtilities.h b/Base/Core/imstkAPIUtilities.h new file mode 100644 index 0000000000000000000000000000000000000000..dee524ceb8e5f9a210adeb85c138b9d62dcb8984 --- /dev/null +++ b/Base/Core/imstkAPIUtilities.h @@ -0,0 +1,219 @@ +/*========================================================================= + +Library: iMSTK + +Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, +& Imaging in Medicine, Rensselaer Polytechnic Institute. + +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.txt + +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. + +=========================================================================*/ + +#ifndef imstkAPIUtilities_h +#define imstkAPIUtilities_h + +// Objects +#include "imstkFEMDeformableBodyModel.h" +#include "imstkSceneObject.h" + +// Solvers +#include "imstkNonlinearSystem.h" + +// Geometry +#include "imstkPlane.h" +#include "imstkSphere.h" +#include "imstkCube.h" +#include "imstkSurfaceMesh.h" +#include "imstkMeshIO.h" + +// logger +#include "g3log/g3log.hpp" + +namespace imstk +{ + +namespace apiutils +{ + +/// +/// \brief Create a analytical visual scene object that and add it to the scene +/// +std::shared_ptr<imstk::VisualObject> +createVisualAnalyticalSceneObject(imstk::Geometry::Type type, + std::shared_ptr<imstk::Scene> scene, + const std::string objName, + const double scale = 1., + const imstk::Vec3d t = imstk::Vec3d(0., 0., 0.)) +{ + if (!scene) + { + LOG(WARNING) << "createVisualAnalyticalSceneObject: Scene is not valid!"; + return nullptr; + } + + if (objName.empty()) + { + LOG(WARNING) << "createVisualAnalyticalSceneObject: Name is empty!"; + return nullptr; + } + + std::shared_ptr<imstk::Geometry> geom; + switch (type) + { + case imstk::Geometry::Type::Sphere: + geom = std::make_shared<imstk::Sphere>(); + break; + + case imstk::Geometry::Type::Plane: + geom = std::make_shared<imstk::Plane>(); + break; + + case imstk::Geometry::Type::Cube: + geom = std::make_shared<imstk::Cube>(); + break; + + default: + LOG(WARNING) << "createVisualgAnalyticalSceneObject: Scene object geometry type is not analytical!"; + return nullptr; + } + + geom->scale(scale); + geom->translate(t); + + auto sceneObj = std::make_shared<imstk::VisualObject>(objName); + sceneObj->setVisualGeometry(geom); + scene->addSceneObject(sceneObj); + + return sceneObj; +}; + +/// +/// \brief Create a analytical colliding scene object that and add it to the scene +/// +std::shared_ptr<imstk::CollidingObject> +createCollidingAnalyticalSceneObject(imstk::Geometry::Type type, + std::shared_ptr<imstk::Scene> scene, + const std::string objName, + const double scale = 1., + const imstk::Vec3d t = imstk::Vec3d(0., 0., 0.)) +{ + if (!scene) + { + LOG(WARNING) << "createCollidingSphereSceneObject: Scene is not valid!"; + return nullptr; + } + + if (objName.empty()) + { + LOG(WARNING) << "createCollidingAnalyticalSceneObject: Name is empty!"; + return nullptr; + } + + std::shared_ptr<imstk::Geometry> geom; + switch (type) + { + case imstk::Geometry::Type::Sphere: + geom = std::make_shared<imstk::Sphere>(); + break; + + case imstk::Geometry::Type::Plane: + geom = std::make_shared<imstk::Plane>(); + break; + + case imstk::Geometry::Type::Cube: + geom = std::make_shared<imstk::Cube>(); + break; + + default: + LOG(WARNING) << "createCollidingAnalyticalSceneObject: Scene object geometry type is not analytical!"; + return nullptr; + } + + geom->scale(scale); + geom->translate(t); + + auto sceneObj = std::make_shared<imstk::CollidingObject>(objName); + sceneObj->setVisualGeometry(geom); + sceneObj->setCollidingGeometry(geom); + scene->addSceneObject(sceneObj); + + return sceneObj; +}; + +/// +/// \brief Read a mesh, create a visual scene object and add to the scene +/// +std::shared_ptr<imstk::SceneObject> +createAndAddVisualSceneObject(std::shared_ptr<imstk::Scene> scene, + const std::string fileName, + const std::string objectName) +{ + if (!scene) + { + LOG(WARNING) << "createAndAddVisualSceneObject: Scene is not valid!"; + return nullptr; + } + + if (fileName.empty()) + { + LOG(WARNING) << "createAndAddVisualSceneObject: File name is empty!"; + return nullptr; + } + + auto mesh = imstk::MeshIO::read(fileName); + auto SurfaceMesh = std::dynamic_pointer_cast<imstk::SurfaceMesh>(mesh); + + // Create object and add to scene + auto meshSceneObject = std::make_shared<imstk::VisualObject>("meshObject"); + meshSceneObject->setVisualGeometry(SurfaceMesh); + meshSceneObject->setName(objectName); + scene->addSceneObject(meshSceneObject); + + return meshSceneObject; +}; + +/// +/// \brief Create a non-linear system using FEM dynamic model +/// +std::shared_ptr<imstk::NonLinearSystem> +createNonLinearSystem(std::shared_ptr<imstk::FEMDeformableBodyModel> dynaModel) +{ + + if (!dynaModel) + { + LOG(WARNING) << "createNonLinearSystem: Dynamic model is not valid!"; + return nullptr; + } + + auto nlSystem = std::make_shared<imstk::NonLinearSystem>( + dynaModel->getFunction(), + dynaModel->getFunctionGradient()); + + std::vector<LinearProjectionConstraint> linProj; + for (auto i : dynaModel->getFixNodeIds()) + { + linProj.push_back(LinearProjectionConstraint(i, true)); + } + nlSystem->setLinearProjectors(linProj); + nlSystem->setUnknownVector(dynaModel->getUnknownVec()); + nlSystem->setUpdateFunction(dynaModel->getUpdateFunction()); + nlSystem->setUpdatePreviousStatesFunction(dynaModel->getUpdatePrevStateFunction()); + + return nlSystem; +}; + +} //apiutils + +} // imstk + +#endif // imstkAPIUtilities_h \ No newline at end of file diff --git a/Base/Core/imstkUtils.h b/Base/Core/imstkPlotterUtils.h similarity index 97% rename from Base/Core/imstkUtils.h rename to Base/Core/imstkPlotterUtils.h index 9bf4555ddd986d7a8202903fc19b1044fdee09dd..9e0df9350cb12459eb1f0f5954ec06670305a700 100644 --- a/Base/Core/imstkUtils.h +++ b/Base/Core/imstkPlotterUtils.h @@ -19,8 +19,8 @@ limitations under the License. =========================================================================*/ -#ifndef imstkUtils_h -#define imstkUtils_h +#ifndef imstkPlotterUtils_h +#define imstkPlotterUtils_h // STL includes #include <iostream> @@ -33,7 +33,7 @@ limitations under the License. namespace imstk { -namespace plotters +namespace plotterutils { /// @@ -187,4 +187,4 @@ static void writePlotterVecVsVecMatPlotlib(Vectord& x, Vectord& y, const char* f } // imstk -#endif // ifndef imstkUtils_h +#endif // ifndef imstkPlotterUtils_h diff --git a/Examples/Sandbox/main.cpp b/Examples/Sandbox/main.cpp index f384ac5da52d1c70fa479f88f223aee6aa44a1aa..41ab8c0cfc8606eb6938868440946ea54c917157 100644 --- a/Examples/Sandbox/main.cpp +++ b/Examples/Sandbox/main.cpp @@ -53,7 +53,10 @@ // logger #include "g3log/g3log.hpp" -#include "imstkUtils.h" + +// imstk utilities +#include "imstkPlotterUtils.h" +#include "imstkAPIUtilities.h" #include "imstkVirtualCouplingPBDObject.h" #include "imstkPbdObject.h" @@ -172,7 +175,6 @@ int main() void testLapToolController() { - #ifdef iMSTK_USE_OPENHAPTICS // SDK and Scene auto sdk = std::make_shared<imstk::SimulationManager>(); @@ -187,39 +189,19 @@ void testLapToolController() sdk->addModule(server); // Plane - auto planeGeom = std::make_shared<imstk::Plane>(); - planeGeom->scale(100); - planeGeom->translate(Vec3d(0., -20., 0.)); - auto planeObj = std::make_shared<imstk::VisualObject>("VisualPlane"); - planeObj->setVisualGeometry(planeGeom); - scene->addSceneObject(planeObj); - - auto createAndAddVisualSceneObject = - [](std::shared_ptr<imstk::Scene> scene, - const std::string& fileName, - const std::string& objectName) -> - std::shared_ptr<imstk::SceneObject> - { - auto mesh = imstk::MeshIO::read(fileName); - auto SurfaceMesh = std::dynamic_pointer_cast<imstk::SurfaceMesh>(mesh); - - // Create object and add to scene - auto meshObject = std::make_shared<imstk::VisualObject>("meshObject"); - meshObject->setVisualGeometry(SurfaceMesh); - meshObject->setName(objectName); - scene->addSceneObject(meshObject); - return meshObject; - }; + auto planeObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Plane, scene, "VisualPlane", 100., imstk::Vec3d(0., -20., 0.)); // laparoscopic tool - auto pivot = createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/pivot.obj", "pivot"); - auto upperJaw = createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/upper.obj", "upperJaw"); - auto lowerJaw = createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/lower.obj", "lowerJaw"); + auto pivot = apiutils::createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/pivot.obj", "pivot"); + auto upperJaw = apiutils::createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/upper.obj", "upperJaw"); + auto lowerJaw = apiutils::createAndAddVisualSceneObject(scene, iMSTK_DATA_ROOT"/laptool/lower.obj", "lowerJaw"); auto trackingCtrl = std::make_shared<imstk::DeviceTracker>(client0); trackingCtrl->setTranslationScaling(0.5); auto lapToolController = std::make_shared<imstk::LaparoscopicToolController>(pivot, upperJaw, lowerJaw, trackingCtrl); lapToolController->setJawRotationAxis(imstk::Vec3d(1.0, 0, 0)); + lapToolController->setJawAngleChange(0.1); scene->addObjectController(lapToolController); // Set Camera @@ -261,7 +243,7 @@ void testMshAndVegaIO() std::string ofile = iMSTK_DATA_ROOT"/liver/liver.veg"; auto writeStatus = imstk::MeshIO::write(volMeshA, ofile); std::cout << "------------------------------Summary----------------------------------------------------\n"; - std::cout << "Following file converion: " << ((writeStatus) ? "Success \n" : "Failure \n"); + std::cout << "Following file conversion: " << ((writeStatus) ? "Success \n" : "Failure \n"); std::cout << "\n Input mesh file : \n" << ifile << std::endl; std::cout << "\n Output mesh file: \n" << ofile << std::endl; @@ -290,7 +272,6 @@ void testMshAndVegaIO() // Run sdk->setCurrentScene(scene); sdk->startSimulation(true); - } void testVTKTexture() @@ -497,21 +478,11 @@ void testPenaltyRigidCollision() sdk->addModule(client1); // Plane - auto planeGeom = std::make_shared<Plane>(); - planeGeom->scale(10); - auto planeObj = std::make_shared<CollidingObject>("Plane"); - planeObj->setVisualGeometry(planeGeom); - planeObj->setCollidingGeometry(planeGeom); - scene->addSceneObject(planeObj); + auto planeObj = apiutils::createCollidingAnalyticalSceneObject(imstk::Geometry::Type::Plane, scene, "plane", 10); // Sphere0 - auto sphere0Geom = std::make_shared<Sphere>(); - sphere0Geom->scale(0.5); - sphere0Geom->translate(Vec3d(1, 0.5, 0)); - auto sphere0Obj = std::make_shared<imstk::CollidingObject>("Sphere0"); - sphere0Obj->setVisualGeometry(sphere0Geom); - sphere0Obj->setCollidingGeometry(sphere0Geom); - scene->addSceneObject(sphere0Obj); + auto sphere0Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere0", 0.5, Vec3d(1, 0.5, 0)); auto trackCtrl0 = std::make_shared<imstk::DeviceTracker>(client0); trackCtrl0->setTranslationScaling(40); @@ -519,13 +490,8 @@ void testPenaltyRigidCollision() scene->addObjectController(sphere0Controller); // Sphere1 - auto sphere1Geom = std::make_shared<Sphere>(); - sphere1Geom->scale(0.5); - sphere1Geom->translate(Vec3d(-1, 0.5, 0)); - auto sphere1Obj = std::make_shared<imstk::CollidingObject>("Sphere1"); - sphere1Obj->setVisualGeometry(sphere1Geom); - sphere1Obj->setCollidingGeometry(sphere1Geom); - scene->addSceneObject(sphere1Obj); + auto sphere1Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere1", 0.5, Vec3d(-1., 0.5, 0.)); auto trackCtrl1 = std::make_shared<imstk::DeviceTracker>(client1); trackCtrl1->setTranslationScaling(40); @@ -576,21 +542,12 @@ void testTwoFalcons() sdk->addModule(hdk); // Plane - auto planeGeom = std::make_shared<imstk::Plane>(); - planeGeom->scale(50); - planeGeom->translate(imstk::FORWARD_VECTOR * 15); - auto planeObj = std::make_shared<imstk::VisualObject>("VisualPlane"); - planeObj->setVisualGeometry(planeGeom); - scene->addSceneObject(planeObj); + auto planeObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Plane, scene, "VisualPlane", 50, imstk::FORWARD_VECTOR * 15); // Sphere0 - auto sphere0Geom = std::make_shared<imstk::Sphere>(); - sphere0Geom->setPosition(imstk::Vec3d(16, 4.5, 0)); - sphere0Geom->scale(1); - auto sphere0Obj = std::make_shared<imstk::CollidingObject>("Sphere0"); - sphere0Obj->setVisualGeometry(sphere0Geom); - sphere0Obj->setCollidingGeometry(sphere0Geom); - scene->addSceneObject(sphere0Obj); + auto sphere0Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere0", 1., Vec3d(16, 4.5, 0)); auto trackCtrl0 = std::make_shared<imstk::DeviceTracker>(falcon0); trackCtrl0->setTranslationScaling(30); @@ -598,13 +555,8 @@ void testTwoFalcons() scene->addObjectController(controller0); // Sphere1 - auto sphere1Geom = std::make_shared<imstk::Sphere>(); - sphere1Geom->setPosition(imstk::Vec3d(-16, 4.5, 0)); - sphere1Geom->scale(1); - auto sphere1Obj = std::make_shared<imstk::CollidingObject>("Sphere1"); - sphere1Obj->setVisualGeometry(sphere1Geom); - sphere1Obj->setCollidingGeometry(sphere1Geom); - scene->addSceneObject(sphere1Obj); + auto sphere1Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere1", 1., Vec3d(-16, 4.5, 0)); auto trackCtrl1 = std::make_shared<imstk::DeviceTracker>(falcon1); trackCtrl1->setTranslationScaling(30); @@ -642,22 +594,12 @@ void testTwoOmnis() sdk->addModule(server); // Plane - auto planeGeom = std::make_shared<imstk::Plane>(); - planeGeom->scale(50); - planeGeom->translate(imstk::FORWARD_VECTOR * 15); - auto planeObj = std::make_shared<imstk::VisualObject>("VisualPlane"); - planeObj->setVisualGeometry(planeGeom); - scene->addSceneObject(planeObj); + auto planeObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Plane, scene, "VisualPlane", 50., imstk::FORWARD_VECTOR * 15); // Sphere0 - auto sphere0Geom = std::make_shared<imstk::Sphere>(); - sphere0Geom->setPosition(imstk::Vec3d(2, 2.5, 0)); - sphere0Geom->scale(1); - - auto sphere0Obj = std::make_shared<imstk::CollidingObject>("Sphere0"); - sphere0Obj->setVisualGeometry(sphere0Geom); - sphere0Obj->setCollidingGeometry(sphere0Geom); - scene->addSceneObject(sphere0Obj); + auto sphere0Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere0", 1., Vec3d(2, 2.5, 0)); auto trackCtrl0 = std::make_shared<imstk::DeviceTracker>(client0); trackCtrl0->setTranslationScaling(0.05); @@ -665,14 +607,8 @@ void testTwoOmnis() scene->addObjectController(controller0); // Sphere1 - auto sphere1Geom = std::make_shared<imstk::Sphere>(); - sphere1Geom->setPosition(imstk::Vec3d(-2, 2.5, 0)); - sphere1Geom->scale(1); - - auto sphere1Obj = std::make_shared<imstk::CollidingObject>("Sphere1"); - sphere1Obj->setVisualGeometry(sphere1Geom); - sphere1Obj->setCollidingGeometry(sphere1Geom); - scene->addSceneObject(sphere1Obj); + auto sphere1Obj = apiutils::createCollidingAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "Sphere1", 1., Vec3d(-2, 2.5, 0)); auto trackCtrl1 = std::make_shared<imstk::DeviceTracker>(client1); trackCtrl1->setTranslationScaling(0.05); @@ -682,6 +618,7 @@ void testTwoOmnis() // Update Camera position auto cam = scene->getCamera(); cam->setPosition(imstk::Vec3d(0, 0, 10)); + auto sphere0Geom = sphere0Obj->getVisualGeometry(); cam->setFocalPoint(sphere0Geom->getPosition()); // Run @@ -746,7 +683,7 @@ void testCameraController() server->addDeviceClient(client); sdk->addModule(server); #else - LOG(WARNING) << "Phantom device option not enabled during build!"; + LOG(WARNING) << "Phantom device option not enabled during build!"; #endif @@ -814,26 +751,18 @@ void testViewer() auto sceneTest = sdk->createNewScene("SceneTest"); // Plane - auto planeGeom = std::make_shared<imstk::Plane>(); - planeGeom->scale(10); - auto planeObj = std::make_shared<imstk::VisualObject>("VisualPlane"); - planeObj->setVisualGeometry(planeGeom); + auto planeObj = apiutils::createVisualAnalyticalSceneObject(imstk::Geometry::Type::Plane, sceneTest, "VisualPlane", 10); // Cube - auto cubeGeom = std::make_shared<imstk::Cube>(); - cubeGeom->scale(0.5); + auto cubeObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Cube, sceneTest, "VisualCube", 0.5, Vec3d(1.0, -1.0, 0.5)); + auto cubeGeom = cubeObj->getVisualGeometry(); cubeGeom->rotate(imstk::UP_VECTOR, imstk::PI_4); cubeGeom->rotate(imstk::RIGHT_VECTOR, imstk::PI_4); - cubeGeom->translate(1.0, -1.0, 0.5); - auto cubeObj = std::make_shared<imstk::VisualObject>("VisualCube"); - cubeObj->setVisualGeometry(cubeGeom); // Sphere - auto sphereGeom = std::make_shared<imstk::Sphere>(); - sphereGeom->scale(0.3); - sphereGeom->translate(0, 2, 0); - auto sphereObj = std::make_shared<imstk::VisualObject>("VisualSphere"); - sphereObj->setVisualGeometry(sphereGeom); + auto sphereObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, sceneTest, "VisualSphere", 0.3, Vec3d(0, 2., 0)); // Light (white) auto whiteLight = std::make_shared<imstk::Light>("whiteLight"); @@ -1333,11 +1262,11 @@ void testVectorPlotters() b.resize(100); b.setConstant(2.0); - plotters::writePlotterVectorMatlab(a, "plotX.m"); - plotters::writePlotterVecVsVecMatlab(a, b, "plotXvsY.m"); + plotterutils::writePlotterVectorMatlab(a, "plotX.m"); + plotterutils::writePlotterVecVsVecMatlab(a, b, "plotXvsY.m"); - plotters::writePlotterVectorMatPlotlib(a, "plotX.py"); - plotters::writePlotterVecVsVecMatPlotlib(a, b, "plotXvsY.py"); + plotterutils::writePlotterVectorMatPlotlib(a, "plotX.py"); + plotterutils::writePlotterVecVsVecMatPlotlib(a, b, "plotXvsY.py"); getchar(); }