Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
ac2468ac8This file is pinned to the selected release. Download the original to open it in your design tool.
#include "StdAfx.h"
#include "QMeshTetra.h"
#include "QMeshFace.h"
#include "QMeshEdge.h"
#include "QMeshNode.h"
#include "../GLKLib/GLKGeometry.h"
#include <math.h>
QMeshTetra::QMeshTetra(void)
{
//type = 4;
meshSurface=NULL;
indexno=0;
selected=false; inner=true;
m_nIdentifiedPatchIndex = -1;
for (int i=0; i<4; i++) faces[i]=NULL;
//for(int i=0;i<8;i++) flags[i]=FALSE;
attachedList.RemoveAll();
Pos=NULL;
}
QMeshTetra::~QMeshTetra(void)
{
}
int QMeshTetra::GetIndexNo(){
return indexno;
}
void QMeshTetra::SetIndexNo( const int _index ){
indexno = _index;
}
void QMeshTetra::SetMeshSurfacePtr(QMeshPatch* _mesh){
meshSurface=_mesh;
}
QMeshPatch* QMeshTetra::GetMeshSurfacePtr(){
return meshSurface;
}
QMeshFace * QMeshTetra::GetFaceRecordPtr( const int whichFace ){
return faces[whichFace-1];
}
void QMeshTetra::SetFaceRecordPtr( const int whichFace, QMeshFace * _face ){
faces[whichFace-1] = _face;
}
QMeshEdge * QMeshTetra::GetEdgeRecordPtr( const int whichEdge ){
switch (whichEdge){
case 1: case 2: case 3:
return faces[0]->GetEdgeRecordPtr(whichEdge);
case 4: case 5: case 6:
{
QMeshNode *n1 = this->GetNodeRecordPtr(whichEdge-3);
QMeshNode *n4 = this->GetNodeRecordPtr(4);
for (int k=1; k<=3; k++)
for (int i=1; i<=3; i++){
QMeshEdge *edge = faces[k]->GetEdgeRecordPtr(i);
if ((edge->GetStartPoint()==n1 && edge->GetEndPoint()==n4) || (edge->GetStartPoint()==n4 && edge->GetEndPoint()==n1))
return edge;
}
}
default:
return NULL;
}
}
int QMeshTetra::GetFaceIndex(QMeshFace* face){
for (int i=1; i<=4; i++)
if (GetFaceRecordPtr(i)==face) return i;
return -1;
}
int QMeshTetra::GetEdgeIndex(QMeshEdge* edge){
for (int i=1; i<=6; i++)
if (GetEdgeRecordPtr(i)==edge) return i;
return -1;
}
bool QMeshTetra::IsFixed()
{
if (GetNodeRecordPtr(1)->GetIndexNo() > -1 ||
GetNodeRecordPtr(2)->GetIndexNo() > -1 ||
GetNodeRecordPtr(3)->GetIndexNo() > -1 ||
GetNodeRecordPtr(4)->GetIndexNo() > -1) return false;
else return true;
}
bool QMeshTetra::IsInner()
{
bool a = true;
/*for (int i = 0; i < 6; i++) {
if (GetEdgeRecordPtr(i + 1)->IsBoundaryEdge() == true) {
a = false; break;
}
}*/
for (int i = 0; i < 4; i++) {
if (GetFaceRecordPtr(i + 1)->GetLeftTetra() == false ||
GetFaceRecordPtr(i + 1)->GetRightTetra() == false) {
a = false; break;
}
}
return a;
}
//These are all computing with single Tetra
bool QMeshTetra::IsNormalDirection( const int whichFace )
{
//ASSERT( (whichEdge==1) || (whichEdge==2) || (whichEdge==3) );
int bitNumber = whichFace - 1;
return isNormal[bitNumber];
}
void QMeshTetra::SetDirectionFlag( const int whichEdge, const int toBe )
{
//ASSERT( (whichEdge==1) || (whichEdge==2) || (whichEdge==3) );
int bitNumber = whichEdge - 1;
isNormal[bitNumber]=toBe;
}
//BOOL QMeshTetra::GetAttribFlag( const int whichBit )
//{
// return flags[whichBit];
//}
//
//void QMeshTetra::SetAttribFlag( const int whichBit, const BOOL toBe )
//{
// flags[whichBit] = toBe;
//}
void QMeshTetra::CalCenterPos(double &xx, double &yy, double &zz)
{
double pp[3];
xx = 0.0; yy = 0.0; zz = 0.0;
for (int i=0;i<4;i++) {
GetNodePos(i+1,pp[0],pp[1],pp[2]);
xx=xx+pp[0]; yy=yy+pp[1]; zz=zz+pp[2];
}
xx=xx/(double)4; yy=yy/(double)4; zz=zz/(double)4;
}
double QMeshTetra::CalVolume(double t[4][3]){
double a[3], b[3], c[3];
for (int i=0; i<3; i++){
a[i] = t[1][i]-t[0][i];
b[i] = t[2][i]-t[0][i];
c[i] = t[3][i]-t[0][i];
}
double area[3];
CROSS(area, c, b);
volume = DOT(a,area);
if (volume<0){
int x=0;
volume = -volume;
}
return volume;
}
double QMeshTetra::CalVolume(){
double t[4][3];
for (int i=0; i<4; i++)
GetNodePos(i+1, t[i][0], t[i][1], t[i][2]);
return CalVolume(t);
}
double QMeshTetra::CalVolume_Last() {
double t[4][3];
for (int i = 0; i < 4; i++) {
QMeshNode *Node = GetNodeRecordPtr(i+1);
Node->GetCoord3D_last(t[i][0], t[i][1], t[i][2]);
}
return CalVolume(t);
}
double QMeshTetra::GetVolume(){
return volume;
}
double QMeshTetra::CalSolidAngle(int whichNode){
if (whichNode<=0 || whichNode>4) {printf("index range from 1 to 4!\n"); return -1;}
double p[3][3];
double pp[3];
GetNodePos(whichNode, pp[0], pp[1], pp[2]);
for (int i=1, j=0; i<=4; i++){
if (i==whichNode) continue;
GetNodePos(i, p[j][0], p[j][1], p[j][2]);
j++;
}
return CalSolidAngle(p, pp);
}
double QMeshTetra::CalSolidAngle(double p[3][3], double pp[3]){
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
p[i][j]-=pp[j];
double length[3]={0,0,0};
for (int i=0; i<3; i++){
length[i] = p[i][0]*p[i][0]+p[i][1]*p[i][1]+p[i][2]*p[i][2];
length[i] = sqrt(length[i]);
}
//L'Huilier's theorem
//double thetaA = acos(abs(DOT(p[0], p[1])/(length[0]*length[1])));
//double thetaB = acos(abs(DOT(p[0], p[2])/(length[0]*length[2])));
//double thetaC = acos(abs(DOT(p[2], p[1])/(length[2]*length[1])));
//double thetaS = (thetaA+thetaB+thetaC)/2.0;
//double O4 = sqrt(tan(thetaS/2.0)*tan((thetaS-thetaA)/2.0)*tan((thetaS-thetaB)/2.0)*tan((thetaS-thetaC)/2.0));
//double Omega = 4.0*atan(O4);
/////////////////////////////////////////////////////////////////////////////////////////////
double dest[3];
CROSS(dest, p[1], p[2]);
double det = fabs(DOT(p[0], dest));
double div = length[0]*length[1]*length[2] + DOT(p[0], p[1])*length[2] + DOT(p[0], p[2])*length[1] + DOT(p[1], p[2])*length[0];
double at = atan2(det, div);
if (at<0) at += PI;
double Omega = 2*at;
//if (omega!=Omega){
// printf("omega!=Omega %.17f %.17f\n", omega, Omega);
//}
/////////////////////////////////////////////////////////////////////////////////////////////
if (Omega>2*PI)
printf("ERROR: Omega=%.17f\n", Omega);
return Omega;
}
bool QMeshTetra::CalTetraBarycentry(double p[3], double &_p, double &_q, double &_r, double &_s){
double t[4][3];
for (int i=0; i<4; i++)
GetNodePos(i+1, t[i][0], t[i][1], t[i][2]);
return CalTetraBarycentry(p, t, _p, _q, _r, _s);
}
bool QMeshTetra::CalTetraBarycentry(double p[3], double t[4][3], double &_p, double &_q, double &_r, double &_s){
GLKGeometry geo;
int index[5][4]={
{1,3,2,4}, {1,3,2,4}, {1,4,3,2}, {1,2,4,3}, {2,3,4,1}
};
double d[5];
for (int i=0; i<5; i++){
double a[16];
for (int m=0; m<4; m++){
for (int n=0; n<3; n++)
a[m*4+n]=t[index[i][m]-1][n];
a[m*4+3]=1;
}
if (i>0){
for (int n=0; n<3; n++)
a[12+n]=p[n];
}
d[i]=geo.Determinant4(a);
}
if (d[0]==0) {
return false;
}
for (int i=1; i<=4; i++){
d[i]/=d[0];
}
_p = d[4]; _q = d[2]; _r = d[3]; _s = 1.0-_p-_q-_r;
for (int i=1; i<=4; i++){
if (d[i]<0){
if (fabs(d[i])<1e-5) continue;
return false;
}
if (d[i]>1+1e-5) return false;
}
if (_p>1) _p=1;
if (_p<0) _p=0;
if (_q>1) _q=1;
if (_q<0) _q=0;
if (_r>1) _r=1;
if (_r<0) _r=0;
_s = 1.0-_p-_q-_r;
return true;
}
void QMeshTetra::BarycentryToPosition(double _p, double _q, double _r, double _s, double t[4][3], double p[3]){
for (int i=0; i<3; i++)
p[i] = _p * t[0][i] + _q * t[1][i] + _r * t[2][i] + _s * t[3][i];
}
void QMeshTetra::BarycentryToPosition(double _p, double _q, double _r, double _s, double p[3]){
double t[4][3];
for (int i=0; i<4; i++)
GetNodePos(i+1, t[i][0], t[i][1], t[i][2]);
BarycentryToPosition(_p, _q, _r, _s, t, p);
}
//These are all relationship between Tetra and Node
//void QMeshTetra::AddNode(QMeshNode *_node) {
// nodeList.AddTail(_node);
//}
//int QMeshTetra::GetNodeNumber()
//{
// return nodeList.GetCount();
//}
//QMeshNode* QMeshTetra::GetNodeRecordPtr(int No) //from 1 to n
//{
// return meshSurface->GetNodeRecordPtr(tet_node_index[No - 1] + 1);
// /*if ((No < 1) || (No > nodeList.GetCount())) return nullptr;
// return (QMeshNode *)nodeList.GetAt(nodeList.FindIndex(No - 1));*/
//}
//index start from 1
QMeshNode * QMeshTetra::GetNodeRecordPtr(int whichNode) {
switch (whichNode) {
case 1: case 2: case 3:
if (!isNormal[0]) whichNode = 4 - whichNode;
return faces[0]->GetNodeRecordPtr(whichNode-1);
case 4:
for (int i = 1; i <= 3; i++) {
bool exist = false;
for (int j = 1; j <= 3; j++)
if (faces[1]->GetNodeRecordPtr(i-1) == this->GetNodeRecordPtr(j))
exist = true;
if (!exist) return faces[1]->GetNodeRecordPtr(i-1);
}
default:
printf("QMeshTetra::GetNodeRecordPtr( UINT whichNode ) ERROR: node not found %d\n", whichNode);
return NULL;
}
}
void QMeshTetra::GetNodePos(const int whichNode, double &xx, double &yy, double &zz) {
this->GetNodeRecordPtr(whichNode)->GetCoord3D(xx, yy, zz);
}
int QMeshTetra::GetNodeIndex(QMeshNode* node) {
for (int i = 1; i <= 4; i++)
if (GetNodeRecordPtr(i) == node) return i;
return -1;
}