From f5d66a4e29014ac0d038e050ceffd9cf497a5000 Mon Sep 17 00:00:00 2001 From: epernod Date: Sun, 6 Oct 2024 01:05:38 +0200 Subject: [PATCH 1/2] [src] Add new component (wip) --- CMakeLists.txt | 2 + .../MeshTools/GridBarycentersPositions.cpp | 204 ++++++++++++++++++ .../MeshTools/GridBarycentersPositions.h | 88 ++++++++ 3 files changed, 294 insertions(+) create mode 100644 src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp create mode 100644 src/InfinyToolkit/MeshTools/GridBarycentersPositions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bd9716..82f6c8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(HEADER_FILES ## Mesh tools sections ${INFINYTOOLKIT_SRC_DIR}/MeshTools/NearestTexcoordsMap.h + ${INFINYTOOLKIT_SRC_DIR}/MeshTools/GridBarycentersPositions.h ${INFINYTOOLKIT_SRC_DIR}/BruteForceFeedback.h ) @@ -71,6 +72,7 @@ set(SOURCE_FILES ## Mesh tools sections ${INFINYTOOLKIT_SRC_DIR}/MeshTools/NearestTexcoordsMap.cpp + ${INFINYTOOLKIT_SRC_DIR}/MeshTools/GridBarycentersPositions.cpp ${INFINYTOOLKIT_SRC_DIR}/BruteForceFeedback.cpp ) diff --git a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp new file mode 100644 index 0000000..f1b5a37 --- /dev/null +++ b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp @@ -0,0 +1,204 @@ +/***************************************************************************** + * - Copyright (C) - 2020 - InfinyTech3D - * + * * + * This file is part of the InfinyToolkit plugin for the SOFA framework * + * * + * Commercial License Usage: * + * Licensees holding valid commercial license from InfinyTech3D may use this * + * file in accordance with the commercial license agreement provided with * + * the Software or, alternatively, in accordance with the terms contained in * + * a written agreement between you and InfinyTech3D. For further information * + * on the licensing terms and conditions, contact: contact@infinytech3d.com * + * * + * GNU General Public License Usage: * + * Alternatively, this file may be used under the terms of the GNU General * + * Public License version 3. The licenses are as published by the Free * + * Software Foundation and appearing in the file LICENSE.GPL3 included in * + * the packaging of this file. Please review the following information to * + * ensure the GNU General Public License requirements will be met: * + * https://www.gnu.org/licenses/gpl-3.0.html. * + * * + * Authors: see Authors.txt * + * Further information: https://infinytech3d.com * + ****************************************************************************/ + +#define SOFA_COMPONENT_GRIDBARYCENTERPOSITIONS_CPP +#include +#include +#include + +#include +#include + +namespace sofa::infinytoolkit +{ + +using namespace sofa::defaulttype; +using namespace sofa::helper; + +SOFA_DECL_CLASS(GridBaryCentersPositions) + +const int GridBaryCentersPositionsClass = core::RegisterObject("GridBaryCentersPositions test.") + .add< GridBaryCentersPositions >() +; + +GridBaryCentersPositions::GridBaryCentersPositions() + : d_inputPositions(initData(&d_inputPositions, "positions", "Indices of the points on the first model")) + , d_tetrahedra(initData(&d_tetrahedra, "tetrahedra", "Indices of input tetrahedra")) + , d_n(initData(&d_n, type::Vec3i(2, 2, 2), "n", "grid resolution")) + , d_useInterpolation(initData(&d_useInterpolation, false, "useInterpolation", "Radius to search corresponding fixed point")) + , d_drawInterpolation(initData(&d_drawInterpolation, false, "drawInterpolation", "Radius to search corresponding fixed point")) + , d_outputPositions(initData(&d_outputPositions, "outputPositions", "Radius to search corresponding fixed point")) + , d_outputGrid(initData(&d_outputGrid, "outputGrid", "Radius to search corresponding fixed point")) +{ + +} + +GridBaryCentersPositions::~GridBaryCentersPositions() +{ +} + + +void GridBaryCentersPositions::init() +{ + addInput(&d_inputPositions); + addInput(&d_tetrahedra); + addInput(&d_n); + + addOutput(&d_outputPositions); + addOutput(&d_outputGrid); + + type::Vec3i grid = d_n.getValue(); + + if (grid[0] < 2) grid[0] = 2; + if (grid[1] < 2) grid[1] = 2; + if (grid[2] < 2) grid[2] = 2; + + d_n.setValue(grid); +} + + +void GridBaryCentersPositions::doUpdate() +{ + sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; + computeSurfaceMeshGrid(); + + /* if (d_useInterpolation.getValue()) + computeTriangulationMapping(); + else + computeNearestPointMapping(); + + m_mapColors.resize(fullPositions.size()); + for (unsigned int i = 0; i < m_mapColors.size(); ++i) + { + m_mapColors[i] = sofa::type::RGBAColor(SReal(rand()) / RAND_MAX, SReal(rand()) / RAND_MAX, SReal(rand()) / RAND_MAX, 1._sreal); + }*/ +} + + +void GridBaryCentersPositions::computeSurfaceMeshGrid() +{ + sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; + m_fullMin = { std::numeric_limits::max() , std::numeric_limits::max() , std::numeric_limits::max() }; + m_fullMax = { std::numeric_limits::min() , std::numeric_limits::min() , std::numeric_limits::min() }; + + for (auto pos : fullPositions) + { + for (int i = 0; i < 3; i++) + { + if (pos[i] < m_fullMin[i]) + m_fullMin[i] = pos[i]; + + if (pos[i] > m_fullMax[i]) + m_fullMax[i] = pos[i]; + } + } + std::cout << "m_fullMin: " << m_fullMin << " | m_fullMax: " << m_fullMax << std::endl; + sofa::type::Vec3i grid = d_n.getValue(); + + sofa::type::Vec3 steps; + for (int i = 0; i < 3; i++) + { + steps[i] = (m_fullMax[i] - m_fullMin[i]) / grid[i]; + std::cout << "length: " << (m_fullMax[i] - m_fullMin[i]) << " | " << steps[i] << std::endl; + } + + + for (int i = 0; i < grid[0]; i++) + { + SReal xmin = m_fullMin[0] + steps[0] * i; + SReal xmax = m_fullMin[0] + steps[0] * (i + 1); + std::cout << "xmin: " << xmin << " | xmax: " << xmax << std::endl; + for (int j = 0; j < grid[1]; j++) + { + SReal ymin = m_fullMin[1] + steps[1] * j; + SReal ymax = m_fullMin[1] + steps[1] * (j + 1); + for (int k = 0; k < grid[2]; k++) + { + SReal zmin = m_fullMin[2] + steps[2] * k; + SReal zmax = m_fullMin[2] + steps[2] * (k + 1); + m_minBBoxes.push_back(Vec3(xmin, ymin, zmin)); + m_maxBBoxes.push_back(Vec3(xmax, ymax, zmax)); + } + } + } + + std::cout << "m_minBBoxes: " << m_minBBoxes.size() << std::endl; +} + + +void GridBaryCentersPositions::computeOutputPositions() +{ + +} + + +void GridBaryCentersPositions::draw(const core::visual::VisualParams* vparams) +{ + /*if (m_mapPositionIds.empty() || d_drawInterpolation.getValue() == false) + return;*/ + + const auto stateLifeCycle = vparams->drawTool()->makeStateLifeCycle(); + vparams->drawTool()->setLightingEnabled(false); + + vparams->drawTool()->drawBoundingBox(m_fullMin, m_fullMax); + + type::RGBAColor red = type::RGBAColor::red(); + vparams->drawTool()->setMaterial(red); + for (int i = 0; i < m_minBBoxes.size(); i++) + { + vparams->drawTool()->drawBoundingBox(m_minBBoxes[i], m_maxBBoxes[i], 0.1); + } + //sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; + //sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > mapPositions = d_mapPositions; + + //std::vector vertices; + //std::vector colors; + + //if (m_mapPositionIds.size() == fullPositions.size()) + //{ + // for (unsigned int i = 0; i < fullPositions.size(); ++i) + // { + // vertices.emplace_back(fullPositions[i]); + // vertices.emplace_back(mapPositions[m_mapPositionIds[i]]); + // colors.emplace_back(m_mapColors[i]); + // } + //} + //else + //{ + // for (unsigned int i = 0; i < fullPositions.size(); ++i) + // { + // for (unsigned int j = 0; j < 3; ++j) + // { + // vertices.emplace_back(fullPositions[i]); + // vertices.emplace_back(mapPositions[m_mapPositionIds[i * 3 + j]]); + // colors.emplace_back(m_mapColors[i]); + // } + // } + //} + + //vparams->drawTool()->drawLines(vertices, 1, colors); +} + + +} //namespace sofa::infinytoolkit diff --git a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h new file mode 100644 index 0000000..545a1a7 --- /dev/null +++ b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h @@ -0,0 +1,88 @@ +/***************************************************************************** + * - Copyright (C) - 2020 - InfinyTech3D - * + * * + * This file is part of the InfinyToolkit plugin for the SOFA framework * + * * + * Commercial License Usage: * + * Licensees holding valid commercial license from InfinyTech3D may use this * + * file in accordance with the commercial license agreement provided with * + * the Software or, alternatively, in accordance with the terms contained in * + * a written agreement between you and InfinyTech3D. For further information * + * on the licensing terms and conditions, contact: contact@infinytech3d.com * + * * + * GNU General Public License Usage: * + * Alternatively, this file may be used under the terms of the GNU General * + * Public License version 3. The licenses are as published by the Free * + * Software Foundation and appearing in the file LICENSE.GPL3 included in * + * the packaging of this file. Please review the following information to * + * ensure the GNU General Public License requirements will be met: * + * https://www.gnu.org/licenses/gpl-3.0.html. * + * * + * Authors: see Authors.txt * + * Further information: https://infinytech3d.com * + ****************************************************************************/ +#pragma once + +#include +#include +#include +#include + +namespace sofa::infinytoolkit +{ + +using sofa::type::Vec3; + +/** Attach given pair of particles, projecting the positions of the second particles to the first ones. +*/ +class SOFA_INFINYTOOLKIT_API GridBaryCentersPositions : public sofa::core::DataEngine +{ +public: + SOFA_CLASS(GridBaryCentersPositions, core::DataEngine); + + typedef typename core::topology::BaseMeshTopology::SeqTetrahedra SeqTetrahedra; + typedef typename core::topology::BaseMeshTopology::SeqHexahedra SeqHexahedra; + + GridBaryCentersPositions(); + ~GridBaryCentersPositions() override; + + void init() override; + void doUpdate() override; + + void draw(const core::visual::VisualParams* vparams) override; + +protected: + /** + * + **/ + void computeSurfaceMeshGrid(); + + /** + * + */ + void computeOutputPositions(); + +public: + /// Inputs Data + Data< type::vector< Vec3 > > d_inputPositions; ///< Full mesh position + Data< SeqTetrahedra > d_tetrahedra; ///< Tetrahedra of mesh subset + //Data< type::vector< Vec3 > > d_mapPositions; ///< Surface mesh position + //Data< type::vector > d_mapTexCoords; ///< Surface mesh texcoords + //Data d_radius; ///< Radius to search corresponding fixed point if no indices are given + Data< sofa::type::Vec< 3, int > > d_n; + /// Outputs Data + Data< type::vector< Vec3 > > d_outputPositions; ///< Full mesh texcoords + Data< SeqHexahedra > d_outputGrid; ///< Hexahedra of mesh subset + + /// Parameters Data + Data d_useInterpolation; ///< Bool option to choose between nearest point or interpolation method + Data d_drawInterpolation; ///< Boop optio to draw the mapping computed between inputPosition and mapPosition + +private: + sofa::type::vector m_minBBoxes; + sofa::type::vector m_maxBBoxes; + //sofa::type::fixed_array + Vec3 m_fullMin, m_fullMax; +}; + +} //namespace sofa::component::engine From 1433f9efc87d720ad6d891b1e765b9d0f6b79cf8 Mon Sep 17 00:00:00 2001 From: epernod Date: Sun, 6 Oct 2024 23:19:33 +0200 Subject: [PATCH 2/2] Update grid creation and barycenters computations --- .../MeshTools/GridBarycentersPositions.cpp | 91 +++++++++---------- .../MeshTools/GridBarycentersPositions.h | 8 +- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp index f1b5a37..60c7293 100644 --- a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp +++ b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.cpp @@ -46,8 +46,7 @@ GridBaryCentersPositions::GridBaryCentersPositions() : d_inputPositions(initData(&d_inputPositions, "positions", "Indices of the points on the first model")) , d_tetrahedra(initData(&d_tetrahedra, "tetrahedra", "Indices of input tetrahedra")) , d_n(initData(&d_n, type::Vec3i(2, 2, 2), "n", "grid resolution")) - , d_useInterpolation(initData(&d_useInterpolation, false, "useInterpolation", "Radius to search corresponding fixed point")) - , d_drawInterpolation(initData(&d_drawInterpolation, false, "drawInterpolation", "Radius to search corresponding fixed point")) + , d_drawGrid(initData(&d_drawGrid, false, "drawGrid", "Debug draw of the grid and barycenters points")) , d_outputPositions(initData(&d_outputPositions, "outputPositions", "Radius to search corresponding fixed point")) , d_outputGrid(initData(&d_outputGrid, "outputGrid", "Radius to search corresponding fixed point")) { @@ -82,17 +81,6 @@ void GridBaryCentersPositions::doUpdate() { sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; computeSurfaceMeshGrid(); - - /* if (d_useInterpolation.getValue()) - computeTriangulationMapping(); - else - computeNearestPointMapping(); - - m_mapColors.resize(fullPositions.size()); - for (unsigned int i = 0; i < m_mapColors.size(); ++i) - { - m_mapColors[i] = sofa::type::RGBAColor(SReal(rand()) / RAND_MAX, SReal(rand()) / RAND_MAX, SReal(rand()) / RAND_MAX, 1._sreal); - }*/ } @@ -100,7 +88,7 @@ void GridBaryCentersPositions::computeSurfaceMeshGrid() { sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; m_fullMin = { std::numeric_limits::max() , std::numeric_limits::max() , std::numeric_limits::max() }; - m_fullMax = { std::numeric_limits::min() , std::numeric_limits::min() , std::numeric_limits::min() }; + m_fullMax = { -std::numeric_limits::max() , -std::numeric_limits::max() , -std::numeric_limits::max() }; for (auto pos : fullPositions) { @@ -113,14 +101,14 @@ void GridBaryCentersPositions::computeSurfaceMeshGrid() m_fullMax[i] = pos[i]; } } - std::cout << "m_fullMin: " << m_fullMin << " | m_fullMax: " << m_fullMax << std::endl; - sofa::type::Vec3i grid = d_n.getValue(); + + const sofa::type::Vec3i& grid = d_n.getValue(); sofa::type::Vec3 steps; for (int i = 0; i < 3; i++) { steps[i] = (m_fullMax[i] - m_fullMin[i]) / grid[i]; - std::cout << "length: " << (m_fullMax[i] - m_fullMin[i]) << " | " << steps[i] << std::endl; + //std::cout << "length: " << (m_fullMax[i] - m_fullMin[i]) << " | " << steps[i] << std::endl; } @@ -128,7 +116,6 @@ void GridBaryCentersPositions::computeSurfaceMeshGrid() { SReal xmin = m_fullMin[0] + steps[0] * i; SReal xmax = m_fullMin[0] + steps[0] * (i + 1); - std::cout << "xmin: " << xmin << " | xmax: " << xmax << std::endl; for (int j = 0; j < grid[1]; j++) { SReal ymin = m_fullMin[1] + steps[1] * j; @@ -143,7 +130,39 @@ void GridBaryCentersPositions::computeSurfaceMeshGrid() } } - std::cout << "m_minBBoxes: " << m_minBBoxes.size() << std::endl; + m_indicesPerCell.resize(m_minBBoxes.size()); + + for (int i = 0; i < fullPositions.size(); i++) + { + sofa::type::Vec< 3, int > gridPos; + for (int j = 0; j < 3; ++j) + { + SReal localCoord = fullPositions[i][j] - m_fullMin[j]; + gridPos[j] = int(localCoord / steps[j]); + } + + int vecPosition = gridPos[2] + gridPos[1] * grid[2] + gridPos[0] * grid[2] * grid[1]; + std::cout << "pos: " << fullPositions[i] << " | " << gridPos << " | " << vecPosition << std::endl; + m_indicesPerCell[vecPosition].push_back(i); + } + + sofa::helper::WriteAccessor< Data< type::vector< Vec3 > > > outputPositions = d_outputPositions; + for (int i = 0; i < m_indicesPerCell.size(); i++) + { + sofa::type::vector& indices = m_indicesPerCell[i]; + + if (indices.empty()) + continue; + + Vec3 bary = Vec3(0.0, 0.0, 0.0); + for (int id : indices) + { + bary += fullPositions[id]; + } + bary /= indices.size(); + + outputPositions.push_back(bary); + } } @@ -155,8 +174,8 @@ void GridBaryCentersPositions::computeOutputPositions() void GridBaryCentersPositions::draw(const core::visual::VisualParams* vparams) { - /*if (m_mapPositionIds.empty() || d_drawInterpolation.getValue() == false) - return;*/ + if (d_drawGrid.getValue() == false) + return; const auto stateLifeCycle = vparams->drawTool()->makeStateLifeCycle(); vparams->drawTool()->setLightingEnabled(false); @@ -169,35 +188,13 @@ void GridBaryCentersPositions::draw(const core::visual::VisualParams* vparams) { vparams->drawTool()->drawBoundingBox(m_minBBoxes[i], m_maxBBoxes[i], 0.1); } - //sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > fullPositions = d_inputPositions; - //sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > mapPositions = d_mapPositions; //std::vector vertices; //std::vector colors; - - //if (m_mapPositionIds.size() == fullPositions.size()) - //{ - // for (unsigned int i = 0; i < fullPositions.size(); ++i) - // { - // vertices.emplace_back(fullPositions[i]); - // vertices.emplace_back(mapPositions[m_mapPositionIds[i]]); - // colors.emplace_back(m_mapColors[i]); - // } - //} - //else - //{ - // for (unsigned int i = 0; i < fullPositions.size(); ++i) - // { - // for (unsigned int j = 0; j < 3; ++j) - // { - // vertices.emplace_back(fullPositions[i]); - // vertices.emplace_back(mapPositions[m_mapPositionIds[i * 3 + j]]); - // colors.emplace_back(m_mapColors[i]); - // } - // } - //} - - //vparams->drawTool()->drawLines(vertices, 1, colors); + type::RGBAColor green = type::RGBAColor::green(); + sofa::helper::ReadAccessor< Data< type::vector< Vec3 > > > outPositions = d_outputPositions; + vparams->drawTool()->drawSpheres(outPositions, 0.1, green); + } diff --git a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h index 545a1a7..d408636 100644 --- a/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h +++ b/src/InfinyToolkit/MeshTools/GridBarycentersPositions.h @@ -66,21 +66,19 @@ class SOFA_INFINYTOOLKIT_API GridBaryCentersPositions : public sofa::core::DataE /// Inputs Data Data< type::vector< Vec3 > > d_inputPositions; ///< Full mesh position Data< SeqTetrahedra > d_tetrahedra; ///< Tetrahedra of mesh subset - //Data< type::vector< Vec3 > > d_mapPositions; ///< Surface mesh position - //Data< type::vector > d_mapTexCoords; ///< Surface mesh texcoords - //Data d_radius; ///< Radius to search corresponding fixed point if no indices are given Data< sofa::type::Vec< 3, int > > d_n; /// Outputs Data Data< type::vector< Vec3 > > d_outputPositions; ///< Full mesh texcoords Data< SeqHexahedra > d_outputGrid; ///< Hexahedra of mesh subset /// Parameters Data - Data d_useInterpolation; ///< Bool option to choose between nearest point or interpolation method - Data d_drawInterpolation; ///< Boop optio to draw the mapping computed between inputPosition and mapPosition + Data d_drawGrid; ///< Boop optio to draw the mapping computed between inputPosition and mapPosition private: sofa::type::vector m_minBBoxes; sofa::type::vector m_maxBBoxes; + sofa::type::vector > m_indicesPerCell; + //sofa::type::fixed_array Vec3 m_fullMin, m_fullMax; };