Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#include "heatmethodfield.h"
#include <iostream>
using namespace std;
using namespace Eigen;
heatMethodField::heatMethodField(QMeshPatch* inputMesh)
{
surfaceMesh = inputMesh;
//genus = detectGenus();
genus = 0;
}
heatMethodField::~heatMethodField(){}
////////////////////////////////
/* Heat method basic function */
void heatMethodField::compBoundaryHeatKernel() {
_initBoundaryHeatKernel();
runHeatMethod();
/*After compute, install the geo-Field to boundary field*/
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode* Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
Node->boundaryValue = Node->geoFieldValue;
}
//printf("--> Compute Boundary HEAT Field Finish\n");
}
//void heatMethodField::inputStressFieldValue() {
//
// FILE* fp = fopen("../Model/Surface_Mesh/1700field.txt", "r");
// if (!fp) {
// printf("Can not open the data file - OFF File Import!\n"); return;
// }
//
// Eigen::VectorXd fieldValue = Eigen::VectorXd::Zero(surfaceMesh->GetNodeNumber());
// char linebuf[256];
// int i = 0;
// while (true) {
// fgets(linebuf, 255, fp);
// if (feof(fp)) break;
// fieldValue(i) = atof(linebuf);
// i++;
// }
// fclose(fp);
//
// int index = 0;
// for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// QMeshNode* Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// Node->zigzagValue = fieldValue(index); index++;
// }
//
// printf("-- (heatMethodField) Finish input the stress field value !\n\n");
//}
void heatMethodField::_initBoundaryHeatKernel() {
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode* Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
Node->selected = false; Node->geoFieldValue = 0;
}
//set boundary point as heat source
for (GLKPOSITION Pos = surfaceMesh->GetEdgeList().GetHeadPosition(); Pos;) {
QMeshEdge* edge = (QMeshEdge*)surfaceMesh->GetEdgeList().GetNext(Pos);
if (edge->IsBoundaryEdge() == true) {
edge->GetStartPoint()->geoFieldValue = 1; edge->GetEndPoint()->geoFieldValue = 1;
edge->GetStartPoint()->selected = true; edge->GetEndPoint()->selected = true;
}
}
}
void heatMethodField::runHeatMethod(){
initialMeshIndex();
VectorXd u(surfaceMesh->GetNodeNumber());
u.setZero();
int index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
u(index) = Node->geoFieldValue;
index++;
}
heatMethodPreProcess();
heatMethodCompwithConstrain(u);
}
void heatMethodField::initialMeshIndex()
{
int index = 0; int hIndex = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
Node->SetIndexNo(index); index++;
if (Node->selected) Node->heatmethodIndex = -1;
else {
Node->heatmethodIndex = hIndex; hIndex++;
}
}
index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetEdgeList().GetHeadPosition(); Pos;) {
QMeshEdge *Edge = (QMeshEdge*)surfaceMesh->GetEdgeList().GetNext(Pos);
Edge->SetIndexNo(index);
index++;
}
index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetFaceList().GetHeadPosition(); Pos;) {
QMeshFace *Face = (QMeshFace*)surfaceMesh->GetFaceList().GetNext(Pos);
Face->SetIndexNo(index);
index++;
}
}
void heatMethodField::heatMethodPreProcess(){
int v = surfaceMesh->GetNodeNumber();
// build Laplacian Matrix
Eigen::SparseMatrix<double> L(v, v);
buildLaplacian(L,false);
poissonSolver.compute(L);
// build Area Matrix
Eigen::SparseMatrix<double> A(v, v);
buildAreaMatrix(A);
double mean_edge_length = meanEdgeLength();
t = 100* mean_edge_length * mean_edge_length;
F = A - t * L;
heatSolver.compute(F);
}
void heatMethodField::heatMethodCompwithConstrain(Eigen::VectorXd& u) {
u = heatSolver.solve(u);
// compute unit vector field X and divergence ∇.X
Eigen::MatrixXd gradients(surfaceMesh->GetFaceNumber(), 3);
computeVectorField(gradients, u);
//cout << gradients << endl;
Eigen::VectorXd integratedDivs(surfaceMesh->GetNodeNumber());
computeIntegratedDivergence(integratedDivs, gradients);
//cout << integratedDivs << endl;
/*build the equation with constrain*/
int vc = surfaceMesh->GetNodeNumber(); //constrained node number
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
if (Node->selected) vc--;
}
Eigen::VectorXd integratedDivs_constrain(vc);
int Cindex = 0;
int index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
if (Node->selected) index++;
else {
integratedDivs_constrain(Cindex) = integratedDivs(index);
Cindex++;
index++;
}
}
Eigen::SparseMatrix<double> L(vc, vc);
buildLaplacian(L, true);
index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
if (Node->selected) continue;
double sumCoefficients = 0.0;
for (GLKPOSITION Pos1 = Node->GetEdgeList().GetHeadPosition(); Pos1;) {
QMeshEdge *connectEdge = (QMeshEdge*)Node->GetEdgeList().GetNext(Pos1);
double coefficient = computeEdgeAngle(Node, connectEdge);
sumCoefficients += coefficient;
QMeshNode* Node1 = connectEdge->GetEndPoint();
if (Node == Node1) Node1 = connectEdge->GetStartPoint();
if (Node1->selected)
integratedDivs_constrain(index) -= Node1->geoFieldValue * coefficient;
}
index++;
}
poissonSolver.compute(L);
// compute max and min phis
Eigen::VectorXd phi = poissonSolver.solve(integratedDivs_constrain);
Eigen::VectorXd phiAll(surfaceMesh->GetNodeNumber());
// set phi to each vertex
index = 0; Cindex = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
if (Node->selected) phiAll(index) = Node->geoFieldValue;
else { phiAll(index) = phi(Cindex); Cindex++; }
index++;
}
subtractMinimumDistance(phiAll); index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
Node->geoFieldValue = phiAll(index);
index++;
}
}
//////////////////////////////
/* Mesh processing function */
//int heatMethodField::detectGenus() {
// int meshgenus = 0;
// int bNodeinprocessed = 0;
//
// //get boundary node and install
// for (GLKPOSITION Pos = surfaceMesh->GetEdgeList().GetHeadPosition(); Pos;) {
// QMeshEdge *Edge = (QMeshEdge*)surfaceMesh->GetEdgeList().GetNext(Pos);
// if (Edge->IsBoundaryEdge()) {
// Edge->GetStartPoint()->isBoundaryNode = true;
// Edge->GetEndPoint()->isBoundaryNode = true;
// }
// }
// for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// if (Node->isBoundaryNode)
// {
// bNodeinprocessed++; Node->processed = false;
// }
// }
//
// //cout<<"boundary node num = "<<bNodeinprocessed<<endl;
//
// if (bNodeinprocessed == 0) {
// std::cout << "This is a closed mesh! cannot used to generate tool path!" << std::endl;
// return 0;
// }
//
// while (bNodeinprocessed != 0) {
// QMeshNode* startNode; //find the start node, should always be found
// for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// startNode = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// if (startNode->isBoundaryNode && startNode->processed == false) break;
// }
// startNode->processed = true;
// bNodeinprocessed--;
//
// QMeshNode* nextNode; bool nNodeDetected;
// do {
// nNodeDetected = false;
// //Notice that, node->getnodelist won't return anything since we didn't install the information!
// for (GLKPOSITION Pos = startNode->GetEdgeList().GetHeadPosition(); Pos;) {
// QMeshEdge* connectEdge = (QMeshEdge*)startNode->GetEdgeList().GetNext(Pos);
// if (!connectEdge->IsBoundaryEdge()) continue;
//
// nextNode = connectEdge->GetEndPoint();
// if (nextNode == startNode) nextNode = connectEdge->GetStartPoint();
//
// if (nextNode->processed == false) {
// bNodeinprocessed--;
// nNodeDetected = true;
// nextNode->processed = true;
// startNode = nextNode;
// break;
// }
// }
// } while (nNodeDetected == true);
// meshgenus++;
// }
//
// //std::cout<< "The boundary ring of this mesh is "<< meshgenus << std::endl <<std::endl;
// return meshgenus;
//}
/*we can input a plane equation to cut the given mesh for this function -- zty can be used later*/
//void heatMethodField::planeCutSelection(double norm[]) {
//
// Vector3d centroid; centroid << 0, 0, 0;
//
// ////compute the center of mesh as the plane cut position
// //for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// // QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// // double pp[3]; Node->GetCoord3D(pp);
// // for (int i = 0; i < 3; i++) centroid(i) += pp[i];
// //}
// //for (int i = 0; i < 3; i++) centroid(i) /= surfaceMesh->GetNodeNumber();
//
// // std::cout << "Center point = " << std::endl << centroid << std::endl;
// // //Vector3d PCAdir; PCAdir << 1.0, 3.0, 0.0;
// Vector3d PCAdir; PCAdir << 1.0, 0.0, 0.0;
// PCAdir = PCAdir.normalized();
//
// //compute tht PCA direction for the given mesh
// Eigen::MatrixXd points(surfaceMesh->GetNodeNumber(), 3);
// int index = 0;
// for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// Node->GetCoord3D(points(index, 0), points(index, 1), points(index, 2));
// index++;
// }
//
// Eigen::Vector3d means = points.colwise().mean();
//
// centroid = means;
// //std::cout << "Center point = " << std::endl << centroid << std::endl;
//
// // Subtract mean image from the data set to get mean centered data vector
// Eigen::MatrixXd U = points.rowwise() - means.transpose();
//
// // Covariance matrix from the mean centered data matrix
// Eigen::MatrixXd covariance = (U.transpose() * U) / (double)(points.rows());
//
// // Calculate eigenvectors
// Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigenSolver(covariance, Eigen::ComputeEigenvectors);
// Eigen::Matrix3d eigenvectorsMatrix = eigenSolver.eigenvectors();
// Eigen::Vector3d eigenvalue = eigenSolver.eigenvalues();
//
// //std::cout << "eigenvalue = " << std::endl << eigenvalue << std::endl;
// //std::cout << "eigenvectorsMatrix = " << std::endl << eigenvectorsMatrix << std::endl;
//
// std::ptrdiff_t Maxindex;
// //eigenvalue.maxCoeff(&index); //Max principle stress
// (eigenvalue.cwiseAbs()).maxCoeff(&Maxindex); //Max principle stress (ABS)
//
// PCAdir = eigenvectorsMatrix.col(Maxindex);
//
// PCAdir << 1.0, 0.0, 0.0;
// if (norm != NULL) {
// for (int i = 0; i < 3; i++) PCAdir(i) = norm[i];
// }
// PCAdir.normalize();
//
// /*Plane equation: Ax+By+Cz+D = 0, detect the intersect triangle*/
// double D = 0.0;
// for (int i = 0; i < 3; i++) D -= centroid(i) * PCAdir(i);
// for (GLKPOSITION Pos = surfaceMesh->GetFaceList().GetHeadPosition(); Pos;) {
// QMeshFace *Face = (QMeshFace*)surfaceMesh->GetFaceList().GetNext(Pos);
// Face->isIntersetwithPlane = false;
// int side = 0;
// for (int i = 0; i < 3; i++) {
// double pp[3];
// Face->GetNodeRecordPtr(i)->GetCoord3D(pp[0], pp[1], pp[2]);
// double planeDetect = PCAdir(0) * pp[0] + PCAdir(1) * pp[1] + PCAdir(2) * pp[2] + D;
// if (abs(planeDetect) < 0.00000001) std::cout << "special case!!!" << std::endl;
// if (planeDetect > 0) side++;
// }
// if (side == 1 || side == 2) {
// Face->isIntersetwithPlane = true;
// //std::cout << "Plane selected !" << std::endl;
// }
// }
//
// /*set Initial Seed Point Value with their distance to the interset edge*/
// for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// Node->geoFieldValue = 0.0;
// Node->selected = false;
// }
//
// for (GLKPOSITION Pos = surfaceMesh->GetFaceList().GetHeadPosition(); Pos;) {
// QMeshFace *Face = (QMeshFace*)surfaceMesh->GetFaceList().GetNext(Pos);
// if (Face->isIntersetwithPlane) {
// for (int i = 0; i < 3; i++) {
// double pp[3];
// Face->GetNodeRecordPtr(i)->GetCoord3D(pp[0], pp[1], pp[2]);
// double planeDetect = PCAdir(0) * pp[0] + PCAdir(1) * pp[1] + PCAdir(2) * pp[2] + D;
// Face->GetNodeRecordPtr(i)->geoFieldValue = planeDetect;
// Face->GetNodeRecordPtr(i)->selected = true;
// }
// }
// }
//
//}
//////////////////////////////////////////////////////
/* Below are the function for heat method computing */
void heatMethodField::buildLaplacian(Eigen::SparseMatrix<double> &L,bool constrain) const {
std::vector<Eigen::Triplet<double>> LTriplet;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
if (constrain && Node->heatmethodIndex<0) continue;
double sumCoefficients = 0.0;
for (GLKPOSITION Pos1 = Node->GetEdgeList().GetHeadPosition(); Pos1;) {
QMeshEdge *connectEdge = (QMeshEdge*)Node->GetEdgeList().GetNext(Pos1);
double coefficient = computeEdgeAngle(Node, connectEdge);
sumCoefficients += coefficient;
QMeshNode* Node1 = connectEdge->GetEndPoint(); if (Node == Node1) Node1 = connectEdge->GetStartPoint();
if(!constrain) LTriplet.push_back(Eigen::Triplet<double>(Node->GetIndexNo(), Node1->GetIndexNo(), coefficient));
else {
if (Node1->heatmethodIndex < 0) continue;
else LTriplet.push_back(Eigen::Triplet<double>(Node->heatmethodIndex, Node1->heatmethodIndex, coefficient));
}
}
if (!constrain)
LTriplet.push_back(Eigen::Triplet<double>(Node->GetIndexNo(), Node->GetIndexNo(), -sumCoefficients));
else
LTriplet.push_back(Eigen::Triplet<double>(Node->heatmethodIndex, Node->heatmethodIndex, -sumCoefficients));
}
L.setFromTriplets(LTriplet.begin(), LTriplet.end());
}
void heatMethodField::buildAreaMatrix
(Eigen::SparseMatrix<double> &A) const {
std::vector<Eigen::Triplet<double>> ATriplet;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
ATriplet.push_back(Eigen::Triplet<double>(Node->GetIndexNo(), Node->GetIndexNo(), Node->dualArea()));
}
A.setFromTriplets(ATriplet.begin(), ATriplet.end());
}
double heatMethodField::computeEdgeAngle
(QMeshNode* Node, QMeshEdge* connectEdge) const {
Eigen::Vector3d p0, p1, p2, v1, v2;
double cotA, cotB;
QMeshNode* Node1 = connectEdge->GetEndPoint(); if (Node == Node1) Node1 = connectEdge->GetStartPoint();
if (connectEdge->GetLeftFace() != nullptr) {
QMeshFace* LeftFace = connectEdge->GetLeftFace();
QMeshNode* LFNode = LeftFace->GetNodeRecordPtr(0);
if (LFNode == Node1 || LFNode == Node) LFNode = LeftFace->GetNodeRecordPtr(1);
if (LFNode == Node1 || LFNode == Node) LFNode = LeftFace->GetNodeRecordPtr(2);
if (Node->GetIndexNo() == Node1->GetIndexNo() || Node->GetIndexNo() == LFNode->GetIndexNo() || Node1->GetIndexNo() == LFNode->GetIndexNo())
cout << "Left face is in a mess!" << endl;
Node->GetCoord3D(p0(0), p0(1), p0(2));
Node1->GetCoord3D(p1(0), p1(1), p1(2));
LFNode->GetCoord3D(p2(0), p2(1), p2(2));
v1 = p2 - p1;
v2 = p2 - p0;
cotA = v1.dot(v2) / v1.cross(v2).norm();
}
else cotA = 0;
if (connectEdge->GetRightFace() != nullptr) {
QMeshFace* RightFace = connectEdge->GetRightFace();
QMeshNode* RFNode = RightFace->GetNodeRecordPtr(0);
if (RFNode == Node1 || RFNode == Node) RFNode = RightFace->GetNodeRecordPtr(1);
if (RFNode == Node1 || RFNode == Node) RFNode = RightFace->GetNodeRecordPtr(2);
if (Node->GetIndexNo() == Node1->GetIndexNo() || Node->GetIndexNo() == RFNode->GetIndexNo() || Node1->GetIndexNo() == RFNode->GetIndexNo())
cout << "Right face is in a mess!" << endl;
Node->GetCoord3D(p0(0), p0(1), p0(2));
Node1->GetCoord3D(p1(0), p1(1), p1(2));
RFNode->GetCoord3D(p2(0), p2(1), p2(2));
v1 = p2 - p1;
v2 = p2 - p0;
cotB = v1.dot(v2) / v1.cross(v2).norm();
}
else cotB = 0;
//cout << "cotA = " << cotA << ", cotB = " << cotB << endl;
return(0.5*(cotA + cotB));
}
void heatMethodField::computeVectorField
(Eigen::MatrixXd &gradients, const Eigen::VectorXd &u) const {
gradients.setZero();
for (GLKPOSITION Pos = surfaceMesh->GetFaceList().GetHeadPosition(); Pos;) {
QMeshFace *Face = (QMeshFace*)surfaceMesh->GetFaceList().GetNext(Pos);
if (Face->isBoundaryFace() == false) {
Eigen::Vector3d gradient, normal;
gradient.setZero();
Face->CalPlaneEquation();
Face->GetNormal(normal(0), normal(1), normal(2));
normal.normalize();
for (int i = 0; i < 3; i++) {
QMeshNode* Node = Face->GetNodeRecordPtr(i % 3);
QMeshNode* Node1 = Face->GetNodeRecordPtr((i + 1) % 3);
QMeshNode* Node2 = Face->GetNodeRecordPtr((i + 2) % 3);
double ui = u(Node->GetIndexNo());
double pp1[3], pp2[3];
Node1->GetCoord3D(pp1[0], pp1[1], pp1[2]);
Node2->GetCoord3D(pp2[0], pp2[1], pp2[2]);
Eigen::Vector3d ei = Eigen::Vector3d(pp2[0] - pp1[0], pp2[1] - pp1[1], pp2[2] - pp1[2]);
gradient += ui * normal.cross(ei);
}
gradient /= (2.0 * Face->CalArea());
gradient.normalize();
//cout << gradient << endl;
for (int i = 0; i < 3; i++) {
gradients(Face->GetIndexNo(), i) = -gradient(i);
}
}
}
}
void heatMethodField::computeIntegratedDivergence
(Eigen::VectorXd &integratedDivs,const Eigen::MatrixXd &gradients) const {
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
double integratedDiv = 0.0;
Eigen::Vector3d p; Node->GetCoord3D(p(0), p(1), p(2));
for (GLKPOSITION Pos1 = Node->GetFaceList().GetHeadPosition(); Pos1;) {
QMeshFace *connectFace = (QMeshFace*)Node->GetFaceList().GetNext(Pos1);
Eigen::Vector3d gradient = gradients.row(connectFace->GetIndexNo());
int index = connectFace->getNodePtrNumber(Node);
if (index == -1) cout << "faild to detect the index for this face!";
QMeshNode* Node1 = connectFace->GetNodeRecordPtr((index + 1) % 3);
QMeshNode* Node2 = connectFace->GetNodeRecordPtr((index + 2) % 3);
Vector3d p1, p2;
Node1->GetCoord3D(p1(0), p1(1), p1(2));
Node2->GetCoord3D(p2(0), p2(1), p2(2));
Eigen::Vector3d e1 = p1 - p;
Eigen::Vector3d e2 = p2 - p;
Eigen::Vector3d ei = p2 - p1;
double theta1 = acos((-e2).dot(-ei) / (e2.norm() * ei.norm()));
double cot1 = 1.0 / tan(theta1);
double theta2 = acos((-e1).dot(ei) / (e1.norm() * ei.norm()));
double cot2 = 1.0 / tan(theta2);
integratedDiv += e1.dot(gradient) * cot1 + e2.dot(gradient) * cot2;
}
integratedDivs[Node->GetIndexNo()] = 0.5 * integratedDiv;
}
}
double heatMethodField::subtractMinimumDistance
(Eigen::VectorXd &phi) const {
// compute max and min phis
double minPhi = INFINITY;
double maxPhi = -INFINITY;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode *Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
int thisIndex = Node->GetIndexNo();
if (minPhi > phi(thisIndex)) minPhi = phi(thisIndex);
if (maxPhi < phi(thisIndex)) maxPhi = phi(thisIndex);
}
double range = maxPhi - minPhi;
for (int i = 0; i<phi.size(); ++i)
phi(i) = 1 - (phi(i) - minPhi) / range;
return range;
}
double heatMethodField::meanEdgeLength() const
{
double avgLength = 0.0;
for (GLKPOSITION Pos = surfaceMesh->GetEdgeList().GetHeadPosition(); Pos;) {
QMeshEdge *Edge = (QMeshEdge*)surfaceMesh->GetEdgeList().GetNext(Pos);
avgLength += Edge->CalLength();
}
avgLength /= (double)surfaceMesh->GetEdgeNumber();
return avgLength;
}
void heatMethodField::meshRefinement() {
int nodeNum = surfaceMesh->GetNodeNumber() + surfaceMesh->GetEdgeNumber();
int faceNum = surfaceMesh->GetFaceNumber() * 4;
//Eigen::VectorXd scalarField = Eigen::VectorXd::Zero(nodeNum);
// build nodeNum and nodeTable - refinement
float* nodeTable;
nodeTable = (float*)malloc(sizeof(float) * nodeNum * 3);
int index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
QMeshNode* Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
double pp[3]; Node->GetCoord3D(pp[0],pp[1],pp[2]); Node->SetIndexNo(index); //scalarField(index) = Node->zigzagValue;
for (int i = 0; i < 3; i++) nodeTable[index * 3 + i] = (float)pp[i];
index++;
}
index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetEdgeList().GetHeadPosition(); Pos;) {
QMeshEdge* Edge = (QMeshEdge*)surfaceMesh->GetEdgeList().GetNext(Pos);
double p1[3], p2[3];
Edge->GetStartPoint()->GetCoord3D(p1[0],p1[1],p1[2]); Edge->GetEndPoint()->GetCoord3D(p2[0], p2[1], p2[2]);
//scalarField(index + surfaceMesh->GetNodeNumber()) = (Edge->GetStartPoint()->zigzagValue + Edge->GetEndPoint()->zigzagValue) / 2;
for (int i = 0; i < 3; i++) nodeTable[(index + surfaceMesh->GetNodeNumber()) * 3 + i] = (float)((p1[i] + p2[i]) / 2);
Edge->refineNodeIndex = index; index++;
}
// build faceNum and faceTable - refinement
unsigned int* faceTable;
faceTable = (unsigned int*)malloc(sizeof(unsigned int) * faceNum * 3);
index = 0;
for (GLKPOSITION Pos = surfaceMesh->GetFaceList().GetHeadPosition(); Pos;) {
QMeshFace* face = (QMeshFace*)surfaceMesh->GetFaceList().GetNext(Pos);
int nodeIndex[6];
for (int i = 0; i < 3; i++) {
nodeIndex[i] = face->GetNodeRecordPtr(i)->GetIndexNo();
nodeIndex[3 + i] = face->GetEdgeRecordPtr(i+1)->refineNodeIndex + surfaceMesh->GetNodeNumber();
}
int faceNodeIndex[12] = { 1,4,6,4,2,5,4,5,6,6,5,3 };
for (int i = 0; i < 12; i++)
faceTable[index * 12 + i] = nodeIndex[faceNodeIndex[i] - 1];
index++;
}
// reconstruct the mesh
surfaceMesh->ClearAll();
surfaceMesh->constructionFromVerFaceTable(nodeNum, nodeTable, faceNum, faceTable);
//protect the stress field value
//index = 0;
//for (GLKPOSITION Pos = surfaceMesh->GetNodeList().GetHeadPosition(); Pos;) {
// QMeshNode* Node = (QMeshNode*)surfaceMesh->GetNodeList().GetNext(Pos);
// Node->zigzagValue = scalarField(index); index++;
//}
//std::cout << surfaceMesh->GetNodeNumber() << std::endl;
free(nodeTable);
free(faceTable);
//std::cout << "--> Refine Mesh Finish (one time)" << std::endl;
}ac2468ac8This file is pinned to the selected release. Download the original to open it in your design tool.