|
18 | 18 |
|
19 | 19 | // vtk |
20 | 20 | #include <vtkAppendPolyData.h> |
| 21 | +#include <vtkGradientFilter.h> |
21 | 22 | #include <vtkButterflySubdivisionFilter.h> |
22 | 23 | #include <vtkCenterOfMass.h> |
23 | 24 | #include <vtkCleanPolyData.h> |
@@ -863,6 +864,150 @@ Field Mesh::curvature(const CurvatureType type) const { |
863 | 864 | return curv; |
864 | 865 | } |
865 | 866 |
|
| 867 | + |
| 868 | +void computeGradient(vtkDataSet* inputDataSet, const char* scalarFieldName, const char* gradientFieldName) { |
| 869 | + vtkSmartPointer<vtkGradientFilter> gradientFilter = vtkSmartPointer<vtkGradientFilter>::New(); |
| 870 | + gradientFilter->SetInputData(inputDataSet); |
| 871 | + gradientFilter->SetInputScalars(vtkDataSet::FIELD_ASSOCIATION_POINTS, scalarFieldName); |
| 872 | + gradientFilter->SetResultArrayName(gradientFieldName); |
| 873 | + gradientFilter->Update(); |
| 874 | + /* |
| 875 | +
|
| 876 | + vtkSmartPointer<vtkDoubleArray> gradientData = vtkSmartPointer<vtkDoubleArray>::New(); |
| 877 | + gradientData->SetNumberOfComponents(3); |
| 878 | + gradientData->SetNumberOfTuples(inputDataSet->GetNumberOfPoints()); |
| 879 | + gradientData->SetName(gradientFieldName); |
| 880 | +*/ |
| 881 | + vtkDoubleArray* gradPointArray = vtkArrayDownCast<vtkDoubleArray>( |
| 882 | + vtkDataSet::SafeDownCast(gradientFilter->GetOutput())->GetPointData()->GetArray(gradientFieldName)); |
| 883 | + |
| 884 | + |
| 885 | +/* |
| 886 | + for (vtkIdType pointId = 0; pointId < inputDataSet->GetNumberOfPoints(); ++pointId) { |
| 887 | + double gradient[3]; |
| 888 | + gradientFilter->GetOutput()->GetPointData()->GetTuple(pointId, gradient); |
| 889 | + gradientData->SetTuple(pointId, gradient); |
| 890 | + } |
| 891 | +*/ |
| 892 | + |
| 893 | + // inputDataSet->GetPointData()->AddArray(gradientData); |
| 894 | + inputDataSet->GetPointData()->AddArray(gradPointArray); |
| 895 | +} |
| 896 | + |
| 897 | + |
| 898 | +void Mesh::computeFieldGradient(const std::string& field) const { |
| 899 | + computeGradient(poly_data_, field.c_str(), (std::string("gradient_") + field).c_str()); |
| 900 | + return; |
| 901 | + auto arr = poly_data_->GetPointData()->GetArray(field.c_str()); |
| 902 | + |
| 903 | + // for each vertex, compute the gradient of the field and store x,y,z |
| 904 | + // components in a vector |
| 905 | + auto gradient = vtkSmartPointer<vtkDoubleArray>::New(); |
| 906 | + gradient->SetNumberOfComponents(3); |
| 907 | + gradient->SetNumberOfTuples(numPoints()); |
| 908 | + gradient->SetName((std::string("gradient_") + field).c_str()); |
| 909 | + |
| 910 | + for (int i = 0; i < numPoints(); i++) { |
| 911 | + // get the field value at this vertex |
| 912 | + double value = arr->GetTuple1(i); |
| 913 | + |
| 914 | + // collect all neighboring vertices using vtk |
| 915 | + auto cell = vtkSmartPointer<vtkGenericCell>::New(); |
| 916 | + auto neighbors = vtkSmartPointer<vtkIdList>::New(); |
| 917 | + poly_data_->GetPointCells(i, neighbors); |
| 918 | + int num_neighbors = neighbors->GetNumberOfIds(); |
| 919 | + |
| 920 | + // for each neighbor vertex |
| 921 | + double x = 0.0; |
| 922 | + double y = 0.0; |
| 923 | + double z = 0.0; |
| 924 | + |
| 925 | + for (int j = 0; j < num_neighbors; j++) { |
| 926 | + // get the neighbor vertex id |
| 927 | + int neighbor_id = neighbors->GetId(j); |
| 928 | + |
| 929 | + // get the neighbor vertex |
| 930 | + auto neighbor = poly_data_->GetPoint(neighbor_id); |
| 931 | + |
| 932 | + // get the neighbor vertex value |
| 933 | + double neighbor_value = arr->GetTuple1(neighbor_id); |
| 934 | + |
| 935 | + // compute the gradient |
| 936 | + x += (neighbor[0] - getPoint(i)[0]) * (neighbor_value - value); |
| 937 | + y += (neighbor[1] - getPoint(i)[1]) * (neighbor_value - value); |
| 938 | + z += (neighbor[2] - getPoint(i)[2]) * (neighbor_value - value); |
| 939 | + } |
| 940 | + |
| 941 | + gradient->SetTuple3(i, x, y, z); |
| 942 | + } |
| 943 | + |
| 944 | + poly_data_->GetPointData()->AddArray(gradient); |
| 945 | +} |
| 946 | + |
| 947 | +Eigen::Vector3d Mesh::computeFieldGradientAtPoint(const std::string& field, const Point3& query) const { |
| 948 | + this->updateCellLocator(); |
| 949 | + |
| 950 | + // compute gradient if not already computed |
| 951 | + if (poly_data_->GetPointData()->GetArray((std::string("gradient_") + field).c_str()) == nullptr) { |
| 952 | + computeFieldGradient(field); |
| 953 | + } |
| 954 | + |
| 955 | + double closestPoint[3]; |
| 956 | + vtkIdType cellId; |
| 957 | + int subId; |
| 958 | + double dist; |
| 959 | + cellLocator->FindClosestPoint(query.data(), closestPoint, cellId, subId, dist); |
| 960 | + |
| 961 | + auto cell = poly_data_->GetCell(cellId); |
| 962 | + |
| 963 | + size_t v1 = cell->GetPointId(0); |
| 964 | + size_t v2 = cell->GetPointId(1); |
| 965 | + size_t v3 = cell->GetPointId(2); |
| 966 | + |
| 967 | + auto gradient = poly_data_->GetPointData()->GetArray((std::string("gradient_") + field).c_str()); |
| 968 | + |
| 969 | + Eigen::Vector3d grad1(gradient->GetTuple3(v1)[0], gradient->GetTuple3(v1)[1], gradient->GetTuple3(v1)[2]); |
| 970 | + Eigen::Vector3d grad2(gradient->GetTuple3(v2)[0], gradient->GetTuple3(v2)[1], gradient->GetTuple3(v2)[2]); |
| 971 | + Eigen::Vector3d grad3(gradient->GetTuple3(v3)[0], gradient->GetTuple3(v3)[1], gradient->GetTuple3(v3)[2]); |
| 972 | + |
| 973 | + // Compute barycentric distances |
| 974 | + Eigen::Vector3d cp(closestPoint[0], closestPoint[1], closestPoint[2]); |
| 975 | + Eigen::Vector3d bary = computeBarycentricCoordinates(cp, cellId); |
| 976 | + |
| 977 | + bary = bary / bary.sum(); |
| 978 | + |
| 979 | + Eigen::Vector3d result; |
| 980 | + result = bary[0] * grad1 + bary[1] * grad2 + bary[2] * grad3; |
| 981 | + return result; |
| 982 | +} |
| 983 | + |
| 984 | +double Mesh::interpolateFieldAtPoint(const std::string& field, const Point3& query) const { |
| 985 | + this->updateCellLocator(); |
| 986 | + |
| 987 | + double closestPoint[3]; |
| 988 | + vtkIdType cellId; |
| 989 | + int subId; |
| 990 | + double dist; |
| 991 | + this->cellLocator->FindClosestPoint(query.data(), closestPoint, cellId, subId, dist); |
| 992 | + |
| 993 | + auto cell = this->poly_data_->GetCell(cellId); |
| 994 | + |
| 995 | + size_t v1 = cell->GetPointId(0); |
| 996 | + size_t v2 = cell->GetPointId(1); |
| 997 | + size_t v3 = cell->GetPointId(2); |
| 998 | + |
| 999 | + // Compute barycentric distances |
| 1000 | + Eigen::Vector3d cp(closestPoint[0], closestPoint[1], closestPoint[2]); |
| 1001 | + Eigen::Vector3d bary = computeBarycentricCoordinates(cp, cellId); |
| 1002 | + |
| 1003 | + bary = bary / bary.sum(); |
| 1004 | + |
| 1005 | + Eigen::Vector3d values(this->getFieldValue(field, v1), this->getFieldValue(field, v2), |
| 1006 | + this->getFieldValue(field, v3)); |
| 1007 | + |
| 1008 | + return (bary * values.transpose()).mean(); |
| 1009 | +} |
| 1010 | + |
866 | 1011 | Mesh& Mesh::applySubdivisionFilter(const SubdivisionType type, int subdivision) { |
867 | 1012 | if (type == Mesh::SubdivisionType::Loop) { |
868 | 1013 | auto filter = vtkSmartPointer<vtkLoopSubdivisionFilter>::New(); |
@@ -1466,30 +1611,8 @@ Eigen::Vector3d Mesh::computeBarycentricCoordinates(const Eigen::Vector3d& pt, i |
1466 | 1611 | } |
1467 | 1612 |
|
1468 | 1613 | double Mesh::getFFCValue(Eigen::Vector3d query) const { |
1469 | | - this->updateCellLocator(); |
1470 | | - |
1471 | | - double closestPoint[3]; |
1472 | | - vtkIdType cellId; |
1473 | | - int subId; |
1474 | | - double dist; |
1475 | | - this->cellLocator->FindClosestPoint(query.data(), closestPoint, cellId, subId, dist); |
1476 | | - |
1477 | | - auto cell = this->poly_data_->GetCell(cellId); |
1478 | | - |
1479 | | - size_t v1 = cell->GetPointId(0); |
1480 | | - size_t v2 = cell->GetPointId(1); |
1481 | | - size_t v3 = cell->GetPointId(2); |
1482 | | - |
1483 | | - // Compute barycentric distances |
1484 | | - Eigen::Vector3d cp(closestPoint[0], closestPoint[1], closestPoint[2]); |
1485 | | - Eigen::Vector3d bary = computeBarycentricCoordinates(cp, cellId); |
1486 | | - |
1487 | | - bary = bary / bary.sum(); |
1488 | | - |
1489 | | - Eigen::Vector3d values(this->getFieldValue("value", v1), this->getFieldValue("value", v2), |
1490 | | - this->getFieldValue("value", v3)); |
1491 | | - |
1492 | | - return (bary * values.transpose()).mean(); |
| 1614 | + Point3 point(query.data()); |
| 1615 | + return interpolateFieldAtPoint("value", point); |
1493 | 1616 | } |
1494 | 1617 |
|
1495 | 1618 | Eigen::Vector3d Mesh::getFFCGradient(Eigen::Vector3d query) const { |
|
0 commit comments