Beispiel #1
0
void MSubLine::getGradShapeFunctions(double u, double v, double w, double s[][3], int order) const
{
  if(!_orig)
    return;

  if (_orig->getDim()==getDim())
    return _orig->getGradShapeFunctions(u, v, w, s, order);

  int nsf = _orig->getNumShapeFunctions();
  double gradsuvw[1256][3];
  _orig->getGradShapeFunctions(u, v, w, gradsuvw, order);

  double jac[3][3];
  double invjac[3][3];
  _orig->getJacobian(u, v, w, jac);
  inv3x3(jac, invjac);
  MEdge edge = getBaseElement()->getEdge(0);
  SVector3 tang = edge.tangent();

  double gradxyz[3];
  double projgradxyz[3];
  for (int i=0; i<nsf; ++i)
  {
    // (i) get the cartesian coordinates of the gradient
    gradxyz[0] = invjac[0][0] * gradsuvw[i][0] + invjac[0][1] * gradsuvw[i][1] + invjac[0][2] * gradsuvw[i][2];
    gradxyz[1] = invjac[1][0] * gradsuvw[i][0] + invjac[1][1] * gradsuvw[i][1] + invjac[1][2] * gradsuvw[i][2];
    gradxyz[2] = invjac[2][0] * gradsuvw[i][0] + invjac[2][1] * gradsuvw[i][1] + invjac[2][2] * gradsuvw[i][2];

    // (ii) projection of the gradient on edges in the cartesian space
    SVector3 grad(&gradxyz[0]);
    double prodscal = dot(tang,grad);
    projgradxyz[0] = prodscal * tang.x();
    projgradxyz[1] = prodscal * tang.y();
    projgradxyz[2] = prodscal * tang.z();

    // (iii) get the parametric coordinates of the projection in the parametric space of the parent element
    s[i][0] = jac[0][0] * projgradxyz[0] + jac[0][1] * projgradxyz[1] + jac[0][2] * projgradxyz[2];
    s[i][1] = jac[1][0] * projgradxyz[0] + jac[1][1] * projgradxyz[1] + jac[1][2] * projgradxyz[2];
    s[i][2] = jac[2][0] * projgradxyz[0] + jac[2][1] * projgradxyz[1] + jac[2][2] * projgradxyz[2];
  }
}
Beispiel #2
0
static void drawBarycentricDual(std::vector<T*> &elements)
{
  glColor4ubv((GLubyte *) & CTX::instance()->color.fg);
  glEnable(GL_LINE_STIPPLE);
  glLineStipple(1, 0x0F0F);
  gl2psEnable(GL2PS_LINE_STIPPLE);
  glBegin(GL_LINES);
  for(unsigned int i = 0; i < elements.size(); i++){
    MElement *ele = elements[i];
    if(!isElementVisible(ele)) continue;
    SPoint3 pc = ele->barycenter();
    if(ele->getDim() == 2){
      for(int j = 0; j < ele->getNumEdges(); j++){
        MEdge e = ele->getEdge(j);
        SPoint3 p = e.barycenter();
        glVertex3d(pc.x(), pc.y(), pc.z());
        glVertex3d(p.x(), p.y(), p.z());
      }
    }
    else if(ele->getDim() == 3){
      for(int j = 0; j < ele->getNumFaces(); j++){
        MFace f = ele->getFace(j);
        SPoint3 p = f.barycenter();
        glVertex3d(pc.x(), pc.y(), pc.z());
        glVertex3d(p.x(), p.y(), p.z());
        for(int k = 0; k < f.getNumVertices(); k++){
          MEdge e(f.getVertex(k), (k == f.getNumVertices() - 1) ?
                  f.getVertex(0) : f.getVertex(k + 1));
          SPoint3 pe = e.barycenter();
          glVertex3d(p.x(), p.y(), p.z());
          glVertex3d(pe.x(), pe.y(), pe.z());
        }
      }
    }
  }
  glEnd();
  glDisable(GL_LINE_STIPPLE);
  gl2psDisable(GL2PS_LINE_STIPPLE);
}
Beispiel #3
0
void updateBoVec<2, MEdge>(
  const int normalSource, const MVertex *const vertex, const int zoneIndex,
  const int vertIndex,
  const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB>
    &faces,
  ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem)
{
  GEntity *ent;
  if(normalSource == NormalSourceElement) goto getNormalFromElements;
  ent = vertex->onWhat();
  if(ent == 0) {
    goto getNormalFromElements;
    // No entity: try to find a normal from the faces
  }
  else {
    switch(ent->dim()) {
    case 0:

      /*--------------------------------------------------------------------*
       * In this case, there are possibly two GEdges from this zone
       * connected to the vertex.  If the angle between the two edges is
       * significant, the BC patch will be split and this vertex will be
       * written in both patches with different normals.  If the angle is
       * small, or only one GEdge belongs to this zone, then the vertex will
       * only be written to one patch.
       *--------------------------------------------------------------------*/

      {
        // Find edge entities that are connected to elements in the zone
        std::vector<std::pair<GEdge *, int> > useGEdge;
        const int nFace = faces.size();
        for(int iFace = 0; iFace != nFace; ++iFace) {
          if(zoneIndex == faces[iFace].zoneIndex) {
            MEdge mEdge =
              faces[iFace].parentElement->getEdge(faces[iFace].parentFace);
            // Get the other vertex on the mesh edge.
            MVertex *vertex2 = mEdge.getMinVertex();
            if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex();
            // Check if the entity associated with vertex2 is a line and
            // is also connected to vertex.  If so, add it to the container of
            // edge entities that will be used to determine the normal
            GEntity *const ent2 = vertex2->onWhat();
            if(ent2->dim() == 1) {
              useGEdge.push_back(
                std::pair<GEdge *, int>(static_cast<GEdge *>(ent2), iFace));
            }
          }
        }

        //--'useGEdge' now contains the edge entities that will be used to
        // determine
        //--the normals

        switch(useGEdge.size()) {
        case 0:
          //           goto getNormalFromElements;
          // We probably don't want BC data if none of the faces attatched to
          // this vertex and in this zone are on the boundary.
          break;

        case 1: {
          const GEdge *const gEdge =
            static_cast<const GEdge *>(useGEdge[0].first);
          SVector3 boNormal;
          if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal))
            goto getNormalFromElements;
          zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(), boNormal,
                                             const_cast<MVertex *>(vertex),
                                             vertIndex));
          patch.add(gEdge->tag());
        } break;

        case 2: {
          // Get the first normal
          const GEdge *const gEdge1 =
            static_cast<const GEdge *>(useGEdge[0].first);
          SVector3 boNormal1;
          if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1,
                         useGEdge[0].second))
            goto getNormalFromElements;

          // Get the second normal
          const GEdge *const gEdge2 =
            static_cast<const GEdge *>(useGEdge[1].first);
          SVector3 boNormal2;
          if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2,
                         useGEdge[1].second))
            goto getNormalFromElements;

          if(dot(boNormal1, boNormal2) < 0.98) {
            //--Write 2 separate patches

            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.add(gEdge1->tag());
            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge2->tag(), boNormal2,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.add(gEdge2->tag());
          }
          else {
            //--Write one patch

            boNormal1 += boNormal2;
            boNormal1 *= 0.5;
            zoneBoVec.push_back(
              VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1,
                             const_cast<MVertex *>(vertex), vertIndex));
            patch.addPair(gEdge1->tag(), gEdge2->tag());
          }
        } break;

        default:
          Msg::Error("Internal error based on 2-D boundary assumptions (file "
                     "\'MZoneBoundary.cpp').  Boundary vertices may be "
                     "incorrect");
          break;
        }
      }
      break;
    case 1:

      /*--------------------------------------------------------------------*
       * The vertex exists on an edge and belongs to only 1 BC patch.
       *--------------------------------------------------------------------*/

      {
        SVector3 boNormal;
        if(edge_normal(vertex, zoneIndex, static_cast<const GEdge *>(ent),
                       faces, boNormal))
          goto getNormalFromElements;
        zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal,
                                           const_cast<MVertex *>(vertex),
                                           vertIndex));
        patch.add(ent->tag());
      }
      break;

    default: goto getNormalFromElements;
    }
  }
  return;

getNormalFromElements:;

  /*--------------------------------------------------------------------*
   * Geometry information cannot be used - generate normals from the
   * elements
   *--------------------------------------------------------------------*/

  {
    if(warnNormFromElem && normalSource == 1) {
      Msg::Warning("Some or all boundary normals were determined from mesh "
                   "elements instead of from the geometry");
      warnNormFromElem = false;
    }
    // The mesh plane normal is computed from all elements attached to the
    // vertex
    SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the
                                  // plane of the mesh
    const int nFace = faces.size();
    for(int iFace = 0; iFace != nFace; ++iFace) {
      if(faces[iFace].zoneIndex == zoneIndex) {
        // Make sure all the planes go in the same direction
        //**Required?
        SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
        if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
        meshPlaneNormal += mpnt;
      }
    }
    // Sum the normals from each element.  The tangent is computed from all
    // faces in the zone attached to the vertex and is weighted by the length of
    // the edge.  Each tangent has to be converted independently into an
    // inwards-pointing normal.
    SVector3 boNormal(0.);
    for(int iFace = 0; iFace != nFace; ++iFace) {
      if(faces[iFace].zoneIndex == zoneIndex) {
        const SVector3 tangent =
          faces[iFace]
            .parentElement->getEdge(faces[iFace].parentFace)
            .tangent();
        // Normal to the boundary (unknown direction)
        SVector3 bnt = crossprod(tangent, meshPlaneNormal);
        // Inwards normal
        const SVector3 inwards(vertex->point(),
                               faces[iFace].parentElement->barycenter());
        if(dot(bnt, inwards) < 0.) bnt.negate();
        boNormal += bnt;
      }
    }
    boNormal.normalize();
    zoneBoVec.push_back(VertexBoundary(
      zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex));
    patch.add(0);
  }
}
Beispiel #4
0
bool Centerline::cutByDisk(SVector3 &PT, SVector3 &NORM, double &maxRad)
{
  double a = NORM.x();
  double b = NORM.y();
  double c = NORM.z();
  double d = -a * PT.x() - b * PT.y() - c * PT.z();

  int maxStep = 20;
  const double EPS = 0.007;

  //std::set<MEdge,Less_Edge> allEdges;
  std::vector<MEdge> allEdges;
  for(unsigned int i = 0; i < triangles.size(); i++){
    for ( unsigned int j= 0; j <  3; j++){
      allEdges.push_back(triangles[i]->getEdge(j));
      //allEdges.insert(triangles[i]->getEdge(j));
    }
  }
  std::unique(allEdges.begin(), allEdges.end());

  bool closedCut = false;
  int step = 0;
  while (!closedCut && step < maxStep){
    double rad = 1.1*maxRad+0.05*step*maxRad;
    std::map<MEdge,MVertex*,Less_Edge> cutEdges;
    std::vector<MVertex*> cutVertices;
    std::vector<MTriangle*> newTris;
    std::set<MEdge,Less_Edge> newCut;
    cutEdges.clear();
    cutVertices.clear();
    newTris.clear();
    newCut.clear();
    // for (std::set<MEdge,Less_Edge>::iterator it = allEdges.begin();
    // 	 it != allEdges.end() ; ++it){
    // MEdge me = *it;
    for (unsigned int j = 0; j < allEdges.size(); j++){
      MEdge me = allEdges[j];
      SVector3 P1(me.getVertex(0)->x(),me.getVertex(0)->y(), me.getVertex(0)->z());
      SVector3 P2(me.getVertex(1)->x(),me.getVertex(1)->y(), me.getVertex(1)->z());
      double V1 = a * P1.x() + b * P1.y() + c * P1.z() + d;
      double V2 = a * P2.x() + b * P2.y() + c * P2.z() + d;
      bool inters = (V1*V2<=0.0) ? true: false;
      bool inDisk = ((norm(P1-PT) < rad ) || (norm(P2-PT) < rad)) ? true : false;
      double rdist = -V1/(V2-V1);
      if (inters && rdist > EPS && rdist < 1.-EPS){
	SVector3 PZ = P1+rdist*(P2-P1);
	if (inDisk){
          MVertex *newv = new MVertex (PZ.x(), PZ.y(), PZ.z());
          cutEdges.insert(std::make_pair(me,newv));
        }
      }
      else if (inters && rdist <= EPS && inDisk )
	cutVertices.push_back(me.getVertex(0));
      else if (inters && rdist >= 1.-EPS && inDisk)
	cutVertices.push_back(me.getVertex(1));
    }
    for(unsigned int i = 0; i < triangles.size(); i++){
      cutTriangle(triangles[i], cutEdges,cutVertices, newTris, newCut);
    }
    if (isClosed(newCut)) {
      triangles.clear();
      triangles = newTris;
      theCut.insert(newCut.begin(),newCut.end());
      break;
    }
    else {
      step++;
      //if (step == maxStep) {printf("no closed cut %d \n", (int)newCut.size()); };
      // // triangles = newTris;
      // // theCut.insert(newCut.begin(),newCut.end());
      // char name[256];
      // sprintf(name, "myCUT-%d.pos", step);
      // FILE * f2 = Fopen(name,"w");
      // fprintf(f2, "View \"\"{\n");
      // std::set<MEdge,Less_Edge>::iterator itp =  newCut.begin();
      // while (itp != newCut.end()){
      // 	MEdge l = *itp;
      // 	fprintf(f2, "SL(%g,%g,%g,%g,%g,%g){%g,%g};\n",
      // 		  l.getVertex(0)->x(), l.getVertex(0)->y(), l.getVertex(0)->z(),
      // 		  l.getVertex(1)->x(), l.getVertex(1)->y(), l.getVertex(1)->z(),
      // 		  1.0,1.0);
      // 	  itp++;
      // 	}
      // 	fprintf(f2,"};\n");
      // 	fclose(f2);
    }
  }


  if (step < maxStep){
    //printf("cutByDisk OK step =%d  \n", step);
    return true;
  }
  else {
    //printf("cutByDisk not succeeded \n");
    return false;
  }

}
static int getAspectRatio(std::vector<MElement *> &elements,
                          std::vector<std::vector<MEdge> > &boundaries)
{

  double area3D = 0.0;
  for(unsigned int i = 0; i <elements.size(); ++i){
    MElement *t = elements[i];
    std::vector<MVertex *> v(3);
    for(int k = 0; k < 3; k++) v[k] = t->getVertex(k);
    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 a_3D = fabs(triangle_area(p0, p1, p2));
    area3D += a_3D;
  }

  double tot_length = 0.0;
  for(unsigned int i = 0; i <boundaries.size(); ++i){
    std::vector<MEdge> iBound = boundaries[i];
    double iLength = 0.0;
    for( unsigned int j = 0; j <iBound.size(); ++j){
      MVertex *v0 = iBound[j].getVertex(0);
      MVertex *v1 = iBound[j].getVertex(1);
      const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) +
                                 (v0->y() - v1->y()) * (v0->y() - v1->y()) +
                                 (v0->z() - v1->z()) * (v0->z() - v1->z()));
      iLength += length;
    }
    tot_length += iLength;
  }
  int AR = 1;
  if (boundaries.size() > 0){
    tot_length /= boundaries.size();
    AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length));
  }

  //compute AR also with Bounding box
  std::set<MVertex*> vs;
  for(unsigned int i = 0; i < elements.size(); i++){
    MElement *e = elements[i];
    for(int j = 0; j < e->getNumVertices(); j++){
      vs.insert(e->getVertex(j));
    }
  }
  SBoundingBox3d bb;
  std::vector<SPoint3> vertices;
  for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){
    SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
    vertices.push_back(pt);
    bb += pt;
  }
  double H = norm(SVector3(bb.max(), bb.min()));

  //SOrientedBoundingBox obbox =  SOrientedBoundingBox::buildOBB(vertices);
  //double H = obbox.getMaxSize();

  double D = H;
  if (boundaries.size()  > 0 ) D = 10e4;
  for (unsigned int i = 0; i < boundaries.size(); i++){
    std::set<MVertex*> vb;
    std::vector<MEdge> iBound = boundaries[i];
    for (unsigned int j = 0; j < iBound.size(); j++){
      MEdge e = iBound[j];
      vb.insert(e.getVertex(0));
      vb.insert(e.getVertex(1));
    }
    std::vector<SPoint3> vBounds;
    SBoundingBox3d bb;
    for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){
      SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
      vBounds.push_back(pt);
      bb +=pt;
    }
    double iD = norm(SVector3(bb.max(), bb.min()));
    D = std::min(D, iD);

    //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds);
    //D = std::max(D, obboxD.getMaxSize());
  }
  int AR2 = (int)ceil(H/D);

  return std::max(AR, AR2);
}