Skip to content
Snippets Groups Projects
MElement.cpp 6.18 KiB
Newer Older
#include <math.h>
#include "MElement.h"
#include "GEntity.h"
#include "Numeric.h"

int MElement::_globalNum = 0;

static double dist(MVertex *v1, MVertex *v2)
{
  double dx = v1->x() - v2->x();
  double dy = v1->y() - v2->y();
  double dz = v1->z() - v2->z();
  return sqrt(dx * dx + dy * dy + dz * dz);
}

double MElement::minEdge()
{
  double m = 1.e25;
  MVertex *v[2];
  for(int i = 0; i < getNumEdges(); i++){
    getEdge(i, v);
    m = std::min(m, dist(v[0], v[1]));
  }
  return m;
}

double MElement::maxEdge()
{
  double m = 0.;
  MVertex *v[2];
  for(int i = 0; i < getNumEdges(); i++){
    getEdge(i, v);
    m = std::max(m, dist(v[0], v[1]));
  }
  return m;
}

double MElement::rhoShapeMeasure()
{
  double min = minEdge();
  double max = maxEdge();
  if(max)
    return min / max;
  else
    return 0.;
}

double MTetrahedron::gammaShapeMeasure()
{
  double p0[3] = { _v[0]->x(), _v[0]->y(), _v[0]->z() };
  double p1[3] = { _v[1]->x(), _v[1]->y(), _v[1]->z() };
  double p2[3] = { _v[2]->x(), _v[2]->y(), _v[2]->z() };
  double p3[3] = { _v[3]->x(), _v[3]->y(), _v[3]->z() };
  double s1 = fabs(triangle_area(p0, p1, p2));
  double s2 = fabs(triangle_area(p0, p2, p3));
  double s3 = fabs(triangle_area(p0, p1, p3));
  double s4 = fabs(triangle_area(p1, p2, p3));
  double rhoin = 3. * fabs(getVolume()) / (s1 + s2 + s3 + s4);
  return 12. * rhoin / (sqrt(6.) * maxEdge());
}

double MTetrahedron::etaShapeMeasure()
{
  double lij2 = 0.;
  for(int i = 0; i <= 3; i++) {
    for(int j = i + 1; j <= 3; j++) {
      double lij = dist(_v[i], _v[j]);
      lij2 += lij * lij;
    }
  }
  double v = fabs(getVolume());
  return 12. * pow(0.9 * v * v, 1./3.) / lij2;
}

void MElement::cog(double &x, double &y, double &z)
{
  x = y = z = 0.;
  int n = getNumVertices();
  for(int i = 0; i < n; i++) {
    MVertex *v = getVertex(i);
    x += v->x();
    y += v->y();
    z += v->z();
  }
  x /= (double)n;
  y /= (double)n;
  z /= (double)n;
}

void MElement::writeMSH(FILE *fp, double version, int num, int elementary, 
			int physical)
{
  // if necessary, change the ordering of the vertices to get positive
  // volume
  setVolumePositive();

  int n = getNumVertices();
  int type = getTypeForMSH();

  fprintf(fp, "%d %d", num ? num : _num, type);
  if(version < 2.0)
    fprintf(fp, " %d %d %d", physical, elementary, n);
  else
    fprintf(fp, " 3 %d %d %d", physical, elementary, _partition);
  
  if(physical >= 0){
    for(int i = 0; i < n; i++)
      fprintf(fp, " %d", getVertex(i)->getNum());
  }
  else{
    int nn = n - getNumEdgeVertices() - getNumFaceVertices() - getNumVolumeVertices();
    for(int i = 0; i < nn; i++)
      fprintf(fp, " %d", getVertex(nn - i - 1)->getNum());
    int ne = getNumEdgeVertices();
    for(int i = 0; i < ne; i++)
      fprintf(fp, " %d", getVertex(nn + ne - i - 1)->getNum());
    int nf = getNumFaceVertices();
    for(int i = 0; i < nf; i++)
      fprintf(fp, " %d", getVertex(nn + ne + nf - i - 1)->getNum());
    int nv = getNumVolumeVertices();
    for(int i = 0; i < nv; i++)
      fprintf(fp, " %d", getVertex(n - i - 1)->getNum());
  fprintf(fp, "\n");
void MElement::writePOS(FILE *fp, double scalingFactor, int elementary)
{
  int n = getNumVertices();
  double gamma = gammaShapeMeasure();
  double eta = etaShapeMeasure();
  double rho = rhoShapeMeasure();

  fprintf(fp, "%s(", getStringForPOS());
  for(int i = 0; i < n; i++){
    if(i) fprintf(fp, ",");
    fprintf(fp, "%g,%g,%g", getVertex(i)->x() * scalingFactor, 
	    getVertex(i)->y() * scalingFactor, getVertex(i)->z() * scalingFactor);
  }
  fprintf(fp, "){");
  for(int i = 0; i < n; i++)
    fprintf(fp, "%d,", elementary);
  for(int i = 0; i < n; i++)
    fprintf(fp, "%d,", getNum());
  for(int i = 0; i < n; i++)
    fprintf(fp, "%g,", gamma);
  for(int i = 0; i < n; i++)
    fprintf(fp, "%g,", eta);
  for(int i = 0; i < n; i++){
    if(i == n - 1)
      fprintf(fp, "%g", rho);
    else
      fprintf(fp, "%g,", rho);
  }
  fprintf(fp, "};\n");
}

void MElement::writeSTL(FILE *fp, double scalingFactor)
{
  int n = getNumVertices();
  if(n < 3 || n > 4) return;

  MVertex *v0 = getVertex(0);
  MVertex *v1 = getVertex(1);
  MVertex *v2 = getVertex(2);
  double N[3];
  normal3points(v0->x(), v0->y(), v0->z(), 
		v1->x(), v1->y(), v1->z(), 
		v2->x(), v2->y(), v2->z(), N);
  fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]);
  fprintf(fp, "  outer loop\n");
  fprintf(fp, "    vertex %g %g %g\n", v0->x() * scalingFactor, 
	  v0->y() * scalingFactor, v0->z() * scalingFactor);
  fprintf(fp, "    vertex %g %g %g\n", v1->x() * scalingFactor, 
	  v1->y() * scalingFactor, v1->z() * scalingFactor);
  fprintf(fp, "    vertex %g %g %g\n", v2->x() * scalingFactor, 
	  v2->y() * scalingFactor, v2->z() * scalingFactor);
  fprintf(fp, "  endloop\n");
  fprintf(fp, "endfacet\n");
  if(n == 4){
    MVertex *v3 = getVertex(3);
    fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]);
    fprintf(fp, "  outer loop\n");
    fprintf(fp, "    vertex %g %g %g\n", v0->x() * scalingFactor, 
	    v0->y() * scalingFactor, v0->z() * scalingFactor);
    fprintf(fp, "    vertex %g %g %g\n", v2->x() * scalingFactor, 
	    v2->y() * scalingFactor, v2->z() * scalingFactor);
    fprintf(fp, "    vertex %g %g %g\n", v3->x() * scalingFactor, 
	    v3->y() * scalingFactor, v3->z() * scalingFactor);
    fprintf(fp, "  endloop\n");
    fprintf(fp, "endfacet\n");
  }
}

void MElement::writeVRML(FILE *fp)
{
  for(int i = 0; i < getNumVertices(); i++)
    fprintf(fp, "%d,", getVertex(i)->getNum() - 1);
  fprintf(fp, "-1,\n");
}

void MElement::writeUNV(FILE *fp, int elementary)
{
  // if necessary, change the ordering of the vertices to get positive
  // volume
  setVolumePositive();

  int n = getNumVertices();
  int type = getTypeForUNV();

  fprintf(fp, "%10d%10d%10d%10d%10d%10d\n",
	  _num, type, elementary, elementary, 7, n);
  if(type == 21 || type == 24) // BEAM or BEAM2
    fprintf(fp, "%10d%10d%10d\n", 0, 0, 0);
  for(int k = 0; k < n; k++) {
    fprintf(fp, "%10d", getVertex(k)->getNum());
    if(k % 8 == 7)
      fprintf(fp, "\n");
  }
  if(n - 1 % 8 != 7)
    fprintf(fp, "\n");
}

void MElement::writeMESH(FILE *fp, int elementary)
{
  for(int i = 0; i < getNumVertices(); i++)
    fprintf(fp, " %d", getVertex(i)->getNum());
  fprintf(fp, " %d\n", elementary);
}