Esempio n. 1
0
void MeshBuilder::AddFacet (const MeshGeomFacet& facet, bool takeFlag, bool takeProperty)
{
    unsigned char flag = 0;
    unsigned long prop = 0;
    if (takeFlag)
        flag = facet._ucFlag;
    if (takeProperty)
        prop = facet._ulProp;

    AddFacet(facet._aclPoints[0], facet._aclPoints[1], facet._aclPoints[2], facet.GetNormal(), flag, prop);
}
Esempio n. 2
0
bool MeshEvalDentsOnSurface::Evaluate()
{
    this->indices.clear();
    MeshRefPointToFacets  clPt2Facets(_rclMesh);
    const MeshPointArray& rPntAry = _rclMesh.GetPoints();
    MeshFacetArray::_TConstIterator f_beg = _rclMesh.GetFacets().begin();

    MeshGeomFacet rTriangle;
    Base::Vector3f tmp;
    unsigned long ctPoints = _rclMesh.CountPoints();
    for (unsigned long index=0; index < ctPoints; index++) {
        std::vector<unsigned long> point;
        point.push_back(index);

        // get the local neighbourhood of the point
        std::set<unsigned long> nb = clPt2Facets.NeighbourPoints(point,1);
        const std::set<unsigned long>& faces = clPt2Facets[index];

        for (std::set<unsigned long>::iterator pt = nb.begin(); pt != nb.end(); ++pt) {
            const MeshPoint& mp = rPntAry[*pt];
            for (std::set<unsigned long>::const_iterator
                ft = faces.begin(); ft != faces.end(); ++ft) {
                    // the point must not be part of the facet we test
                    if (f_beg[*ft]._aulPoints[0] == *pt)
                        continue;
                    if (f_beg[*ft]._aulPoints[1] == *pt)
                        continue;
                    if (f_beg[*ft]._aulPoints[2] == *pt)
                        continue;
                    // is the point projectable onto the facet?
                    rTriangle = _rclMesh.GetFacet(f_beg[*ft]);
                    if (rTriangle.IntersectWithLine(mp,rTriangle.GetNormal(),tmp)) {
                        const std::set<unsigned long>& f = clPt2Facets[*pt];
                        this->indices.insert(this->indices.end(), f.begin(), f.end());
                        break;
                    }
            }
        }
    }

    // remove duplicates
    std::sort(this->indices.begin(), this->indices.end());
    this->indices.erase(std::unique(this->indices.begin(),
                        this->indices.end()), this->indices.end());

    return this->indices.empty();
}
Esempio n. 3
0
void MeshKernel::AddFacet(const MeshGeomFacet &rclSFacet)
{
    unsigned long i;
    MeshFacet clFacet;

    // set corner points
    for (i = 0; i < 3; i++) {
        _clBoundBox.Add(rclSFacet._aclPoints[i]);
        clFacet._aulPoints[i] = _aclPointArray.GetOrAddIndex(rclSFacet._aclPoints[i]);
    }

    // adjust orientation to normal
    AdjustNormal(clFacet, rclSFacet.GetNormal());

    unsigned long ulCt = _aclFacetArray.size();

    // set neighbourhood
    unsigned long ulP0 = clFacet._aulPoints[0];
    unsigned long ulP1 = clFacet._aulPoints[1];
    unsigned long ulP2 = clFacet._aulPoints[2];
    unsigned long ulCC = 0;
    for (TMeshFacetArray::iterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); ++pF, ulCC++) {
        for (int i=0; i<3;i++) {
            unsigned long ulP = pF->_aulPoints[i];
            unsigned long ulQ = pF->_aulPoints[(i+1)%3];
            if (ulQ == ulP0 && ulP == ulP1) {
                clFacet._aulNeighbours[0] = ulCC;
                pF->_aulNeighbours[i] = ulCt;
            }
            else if (ulQ == ulP1 && ulP == ulP2) {
                clFacet._aulNeighbours[1] = ulCC;
                pF->_aulNeighbours[i] = ulCt;
            }
            else if (ulQ == ulP2 && ulP == ulP0) {
                clFacet._aulNeighbours[2] = ulCC;
                pF->_aulNeighbours[i] = ulCt;
            }
        }
    }

    // insert facet into array
    _aclFacetArray.push_back(clFacet);
}
Esempio n. 4
0
bool MeshTrimming::CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints, std::vector<MeshGeomFacet>& aclNewFacets)
{
    MeshGeomFacet clFac;

    // no valid triangulation possible
    if (iSide == -1)
        return false;

    // two points found
    if (raclPoints.size() == 2) {
        MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
        AdjustFacet(facet, iSide);
        Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]);
    
        if (iSide == 1) {
            // swap P1 and P2
            clP1 = raclPoints[1];
            clP2 = raclPoints[0];
        }

        // check which facets can be inserted
        int iCtPts=0;
        Base::Vector3f clFacPnt;
        Base::Vector2D clProjPnt;
        for (int i=0; i<3; i++) {
            clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
            clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
            if (myPoly.Contains(clProjPnt) == myInner)
                ++iCtPts;
        }

        if (iCtPts == 2) {
            // erstes Dreieck
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
        }
        else if (iCtPts == 1) {
            // erstes Dreieck
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
            clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
            // zweites Dreieck
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
            clFac._aclPoints[1] = clP1;
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
        }
        else
            return false;
    }
    // four points found
    else if (raclPoints.size() == 4) {
        MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
        AdjustFacet(facet, iSide);

        MeshFacet clOrg(myMesh._aclFacetArray[ulFacetPos]);
        clFac = myMesh.GetFacet(ulFacetPos);
        // intersection points
        Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]), clP3(raclPoints[2]), clP4(raclPoints[3]);

        // check which facets can be inserted
        int iCtPts=0;
        Base::Vector3f clFacPnt;
        Base::Vector2D clProjPnt;
        for (int i=0; i<3; i++) {
            clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
            clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
            if (myPoly.Contains(clProjPnt) == myInner)
                ++iCtPts;
        }

        // sort the intersection points in a certain order
        if (iCtPts == 0 || iCtPts == 3) {
            if (iSide == 1) {
                // swap the points
                clP1 = clP2;
                clP2 = raclPoints[0];
                clP3 = clP4;
                clP4 = raclPoints[2];
            }

            if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
                // swap P1 and P3
                Base::Vector3f tmp(clP1);
                clP1 = clP3;
                clP3 = tmp;
            }
            if ((clP2-clFac._aclPoints[0]).Length() > (clP4-clFac._aclPoints[0]).Length()) {
                // swap P2 and P4
                Base::Vector3f tmp(clP2);
                clP2 = clP4;
                clP4 = tmp;
            }
        }
        else {
            if (iSide == 0) {
                Base::Vector3f clNormal(clFac.GetNormal());
                MeshGeomFacet clTmpFac; clTmpFac._aclPoints[0] = clFac._aclPoints[1];
                clTmpFac._aclPoints[1] = clP2; clTmpFac._aclPoints[2] = clP1;
                if (clTmpFac.GetNormal() * clNormal > 0) {
                    Base::Vector3f tmp(clP1); 
                    clP1 = clP2; 
                    clP2 = tmp;
                }
                else {
                    Base::Vector3f tmp(clP1); 
                    clP1 = clP4; 
                    clP4 = clP2; 
                    clP2 = clP3; 
                    clP3 = tmp;
                }
            }
            else if (iSide == 1) {
                if ((clP2-clFac._aclPoints[1]).Length() > (clP4-clFac._aclPoints[1]).Length()) {
                    Base::Vector3f tmp(clP1); 
                    clP1 = clP4; 
                    clP4 = tmp;
                    tmp = clP2;          
                    clP2 = clP3; 
                    clP3 = tmp;
                }
                else {
                    Base::Vector3f tmp(clP1); 
                    clP1 = clP2; 
                    clP2 = tmp;
                    tmp = clP3;          
                    clP3 = clP4; 
                    clP4 = tmp;
                }
            }
            else {
                if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
                    Base::Vector3f tmp(clP1); 
                    clP1 = clP3; 
                    clP3 = tmp;
                    tmp = clP2;          
                    clP2 = clP4; 
                    clP4 = tmp;
                }
            }
        }
  
        // now create the new facets
        if (iCtPts == 0) {
            // insert first facet
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
            clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
            clFac._aclPoints[2] = clP1;
            aclNewFacets.push_back(clFac);
            // insert second facet
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
            clFac._aclPoints[1] = clP1;
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
            // finally insert third facet
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
            clFac._aclPoints[1] = clP4;
            clFac._aclPoints[2] = clP3;
            aclNewFacets.push_back(clFac);
        }
        else if (iCtPts == 1) {
            // insert first facet
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = clP2;
            clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[1]];
            aclNewFacets.push_back(clFac);
            // finally insert second facet
            clFac._aclPoints[0] = clP4;
            clFac._aclPoints[1] = clP3;
            clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[2]];
            aclNewFacets.push_back(clFac);
        }
        else if (iCtPts == 2) {
            // insert first facet
            clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
            clFac._aclPoints[1] = clP2;
            clFac._aclPoints[2] = clP4;
            aclNewFacets.push_back(clFac);
            // insert second facet
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = clP4;
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
            // finally insert third facet
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = clP3;
            clFac._aclPoints[2] = clP4;
            aclNewFacets.push_back(clFac);
        }
        else {
            // insert first facet
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = clP3;
            clFac._aclPoints[2] = clP4;
            aclNewFacets.push_back(clFac);
            // finally insert second facet
            clFac._aclPoints[0] = clP1;
            clFac._aclPoints[1] = clP4;
            clFac._aclPoints[2] = clP2;
            aclNewFacets.push_back(clFac);
        }
    }
    else
        return false;

    return true;
}
//static int matchCounter = 0;
bool SetOperations::CollectFacetVisitor::AllowVisit (const MeshFacet& rclFacet, const MeshFacet& rclFrom, unsigned long ulFInd, unsigned long ulLevel, unsigned short neighbourIndex)
{
  if (rclFacet.IsFlag(MeshFacet::MARKED) && rclFrom.IsFlag(MeshFacet::MARKED))
  { // facet connected to an edge
    unsigned long pt0 = rclFrom._aulPoints[neighbourIndex], pt1 = rclFrom._aulPoints[(neighbourIndex+1)%3];
    Edge edge(_mesh.GetPoint(pt0), _mesh.GetPoint(pt1));

    std::map<Edge, EdgeInfo>::iterator it = _edges.find(edge);

    if (it != _edges.end())
    {
      if (_addFacets == -1)
      { // detemine if the facets shoud add or not only once
        MeshGeomFacet facet = _mesh.GetFacet(rclFrom); // triangulated facet
        MeshGeomFacet facetOther = it->second.facets[1-_side][0]; // triangulated facet from same edge and other mesh
        Vector3f normalOther = facetOther.GetNormal();
        //Vector3f normal = facet.GetNormal();

        Vector3f edgeDir = it->first.pt1 - it->first.pt2;
        Vector3f ocDir = (edgeDir % (facet.GetGravityPoint() - it->first.pt1)) % edgeDir;
        ocDir.Normalize();
        Vector3f ocDirOther = (edgeDir % (facetOther.GetGravityPoint() - it->first.pt1)) % edgeDir;
        ocDirOther.Normalize();

        //Vector3f dir = ocDir % normal;
        //Vector3f dirOther = ocDirOther % normalOther;

        bool match = ((ocDir * normalOther) * _mult) < 0.0f;

        //if (matchCounter == 1)
        //{
        //  // _builder.addSingleArrow(it->second.pt1, it->second.pt1 + edgeDir, 3, 0.0, 1.0, 0.0);

        //  _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], facet._aclPoints[2], true, 3.0, 1.0, 0.0, 0.0);
        //  // _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + ocDir, 3, 1.0, 0.0, 0.0);
        //  _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + normal, 3, 1.0, 0.5, 0.0);
        //  // _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + dir, 3, 1.0, 1.0, 0.0);

        //  _builder.addSingleTriangle(facetOther._aclPoints[0], facetOther._aclPoints[1], facetOther._aclPoints[2], true, 3.0, 0.0, 0.0, 1.0);
        //  // _builder.addSingleArrow(facetOther.GetGravityPoint(), facetOther.GetGravityPoint() + ocDirOther, 3, 0.0, 0.0, 1.0);
        //  _builder.addSingleArrow(facetOther.GetGravityPoint(), facetOther.GetGravityPoint() + normalOther, 3, 0.0, 0.5, 1.0);
        //  // _builder.addSingleArrow(facetOther.GetGravityPoint(), facetOther.GetGravityPoint() + dirOther, 3, 0.0, 1.0, 1.0);

        //}

       // float scalar = dir * dirOther * _mult;
       // bool match = scalar > 0.0f;


        //MeshPoint pt0 = it->first.pt1;
        //MeshPoint pt1 = it->first.pt2;

        //int i, n0 = -1, n1 = -1, m0 = -1, m1 = -1;
        //for (i = 0; i < 3; i++)
        //{
        //  if ((n0 == -1) && (facet._aclPoints[i] == pt0))
        //    n0 = i;
        //  if ((n1 == -1) && (facet._aclPoints[i] == pt1))
        //    n1 = i;
        //  if ((m0 == -1) && (facetOther._aclPoints[i] == pt0))
        //    m0 = i;
        //  if ((m1 == -1) && (facetOther._aclPoints[i] == pt1))
        //    m1 = i;
        //}

        //if ((n0 != -1) && (n1 != -1) && (m0 != -1) && (m1 != -1))
        //{
        //  bool orient_n = n1 > n0;
        //  bool orient_m = m1 > m0;

        //  Vector3f dirN = facet._aclPoints[n1] - facet._aclPoints[n0];
        //  Vector3f dirM = facetOther._aclPoints[m1] - facetOther._aclPoints[m0];

        //  if (matchCounter == 1)
        //  {
        //    _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + dirN, 3, 1.0, 1.0, 0.0);
        //    _builder.addSingleArrow(facetOther.GetGravityPoint(), facetOther.GetGravityPoint() + dirM, 3, 0.0, 1.0, 1.0);
        //  }

        //  if (_mult > 0.0)
        //    match = orient_n == orient_m;
        //  else
        //    match = orient_n != orient_m;
        //}
  
        if (match)
          _addFacets = 0;
        else
          _addFacets = 1;

        //matchCounter++;
      }

      return false;
    }    
  }

  return true;
}
void SetOperations::TriangulateMesh (const MeshKernel &cutMesh, int side)
{
  // Triangulate Mesh 
  std::map<unsigned long, std::list<std::set<MeshPoint>::iterator> >::iterator it1;
  for (it1 = _facet2points[side].begin(); it1 != _facet2points[side].end(); it1++)
  {
    std::vector<Vector3f> points;
    std::set<MeshPoint>   pointsSet;

    unsigned long fidx = it1->first;
    MeshGeomFacet f = cutMesh.GetFacet(fidx);

    //if (side == 1)
    //    _builder.addSingleTriangle(f._aclPoints[0], f._aclPoints[1], f._aclPoints[2], 3, 0, 1, 1);

     // facet corner points
    //const MeshFacet& mf = cutMesh._aclFacetArray[fidx];
    int i;
    for (i = 0; i < 3; i++)
    {
      pointsSet.insert(f._aclPoints[i]);
      points.push_back(f._aclPoints[i]);
    }
    
    // triangulated facets
    std::list<std::set<MeshPoint>::iterator>::iterator it2;
    for (it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
    {
      if (pointsSet.find(*(*it2)) == pointsSet.end())
      {
        pointsSet.insert(*(*it2));
        points.push_back(*(*it2));
      }

    }

    Vector3f normal = f.GetNormal();
    Vector3f base = points[0];
    Vector3f dirX = points[1] - points[0];
    dirX.Normalize();
    Vector3f dirY = dirX % normal;

    // project points to 2D plane
    i = 0;
    std::vector<Vector3f>::iterator it;
    std::vector<Vector3f> vertices;
    for (it = points.begin(); it != points.end(); it++)
    {
      Vector3f pv = *it;
      pv.TransformToCoordinateSystem(base, dirX, dirY);
      vertices.push_back(pv);
    }

    DelaunayTriangulator tria;
    tria.SetPolygon(vertices);
    tria.TriangulatePolygon();

    std::vector<MeshFacet> facets = tria.GetFacets();
    for (std::vector<MeshFacet>::iterator it = facets.begin(); it != facets.end(); ++it)
    {
      if ((it->_aulPoints[0] == it->_aulPoints[1]) ||
          (it->_aulPoints[1] == it->_aulPoints[2]) ||
          (it->_aulPoints[2] == it->_aulPoints[0]))
      { // two same triangle corner points
        continue;
      }
  
      MeshGeomFacet facet(points[it->_aulPoints[0]],
                          points[it->_aulPoints[1]],
                          points[it->_aulPoints[2]]);

      //if (side == 1)
      // _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], facet._aclPoints[2], true, 3, 0, 1, 1);

      //if (facet.Area() < 0.0001f)
      //{ // too small facet
      //  continue;
      //}

      float dist0 = facet._aclPoints[0].DistanceToLine
          (facet._aclPoints[1],facet._aclPoints[1] - facet._aclPoints[2]);
      float dist1 = facet._aclPoints[1].DistanceToLine
          (facet._aclPoints[0],facet._aclPoints[0] - facet._aclPoints[2]);
      float dist2 = facet._aclPoints[2].DistanceToLine
          (facet._aclPoints[0],facet._aclPoints[0] - facet._aclPoints[1]);

      if ((dist0 < _minDistanceToPoint) ||
          (dist1 < _minDistanceToPoint) ||
          (dist2 < _minDistanceToPoint))
      {
        continue;
      }

      //dist0 = (facet._aclPoints[0] - facet._aclPoints[1]).Length();
      //dist1 = (facet._aclPoints[1] - facet._aclPoints[2]).Length();
      //dist2 = (facet._aclPoints[2] - facet._aclPoints[3]).Length();

      //if ((dist0 < _minDistanceToPoint) || (dist1 < _minDistanceToPoint) || (dist2 < _minDistanceToPoint))
      //{
      //  continue;
      //}

      facet.CalcNormal();
      if ((facet.GetNormal() * f.GetNormal()) < 0.0f)
      { // adjust normal
         std::swap(facet._aclPoints[0], facet._aclPoints[1]);
         facet.CalcNormal();
      }


      int j;
      for (j = 0; j < 3; j++)
      {
        std::map<Edge, EdgeInfo>::iterator eit = _edges.find(Edge(facet._aclPoints[j], facet._aclPoints[(j+1)%3]));

        if (eit != _edges.end())
        {

          if (eit->second.fcounter[side] < 2)
          {
            //if (side == 0)
            //   _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], facet._aclPoints[2], true, 3, 0, 1, 1);

            eit->second.facet[side] = fidx;
            eit->second.facets[side][eit->second.fcounter[side]] = facet;
            eit->second.fcounter[side]++;
            facet.SetFlag(MeshFacet::MARKED); // set all facets connected to an edge: MARKED

          }
        }
      }

      _newMeshFacets[side].push_back(facet);

    } // for (i = 0; i < (out->numberoftriangles * 3); i += 3)
  } // for (it1 = _facet2points[side].begin(); it1 != _facet2points[side].end(); it1++)
}
Esempio n. 7
0
CurvatureInfo FacetCurvature::Compute(unsigned long index) const
{
    Base::Vector3f rkDir0, rkDir1, rkPnt;
    Base::Vector3f rkNormal;

    MeshGeomFacet face = myKernel.GetFacet(index);
    Base::Vector3f face_gravity = face.GetGravityPoint();
    Base::Vector3f face_normal = face.GetNormal();
    std::set<unsigned long> point_indices;
    FitPointCollector collect(point_indices);

    float searchDist = myRadius;
    int attempts=0;
    do {
        mySearch.Neighbours(index, searchDist, collect);
        if (point_indices.empty())
            break;
        float min_points = myMinPoints;
        float use_points = point_indices.size();
        searchDist = searchDist * sqrt(min_points/use_points);
    }
    while((point_indices.size() < myMinPoints) && (attempts++ < 3));

    std::vector<Base::Vector3f> fitPoints;
    const MeshPointArray& verts = myKernel.GetPoints();
    fitPoints.reserve(point_indices.size());
    for (std::set<unsigned long>::iterator it = point_indices.begin(); it != point_indices.end(); ++it) {
        fitPoints.push_back(verts[*it] - face_gravity);
    }

    float fMin, fMax;
    if (fitPoints.size() >= myMinPoints) {
        SurfaceFit surf_fit;
        surf_fit.AddPoints(fitPoints);
        surf_fit.Fit();
        rkNormal = surf_fit.GetNormal();
        double dMin, dMax, dDistance;
        if (surf_fit.GetCurvatureInfo(0.0, 0.0, 0.0, dMin, dMax, rkDir1, rkDir0, dDistance)) {
            fMin = (float)dMin;
            fMax = (float)dMax;
        }
        else {
            fMin = FLT_MAX;
            fMax = FLT_MAX;
        }
    }
    else {
        // too few points => cannot calc any properties
        fMin = FLT_MAX;
        fMax = FLT_MAX;
    }

    CurvatureInfo info;
    if (fMin < fMax) {
        info.fMaxCurvature = fMax;
        info.fMinCurvature = fMin;
        info.cMaxCurvDir = rkDir1;
        info.cMinCurvDir = rkDir0;
    }
    else {
        info.fMaxCurvature = fMin;
        info.fMinCurvature = fMax;
        info.cMaxCurvDir = rkDir0;
        info.cMinCurvDir = rkDir1;
    }

    // Reverse the direction of the normal vector if required
    // (Z component of "local" normal vectors should be opposite in sign to the "local" view vector)
    if (rkNormal * face_normal < 0.0) {
        // Note: Changing the normal directions is similar to flipping over the object.
        // In this case we must adjust the curvature information as well.
        std::swap(info.cMaxCurvDir,info.cMinCurvDir);
        std::swap(info.fMaxCurvature,info.fMinCurvature);
        info.fMaxCurvature *= (-1.0);
        info.fMinCurvature *= (-1.0);
    }

    return info;
}
void CurveProjectorShape::projectCurve( const TopoDS_Edge& aEdge,
                                        std::vector<FaceSplitEdge> &vSplitEdges)
{
  Standard_Real fFirst, fLast;
  Handle(Geom_Curve) hCurve = BRep_Tool::Curve( aEdge,fFirst,fLast );
  
  // getting start point
  gp_Pnt gpPt = hCurve->Value(fFirst);

  // projection of the first point 
  Base::Vector3f cStartPoint = Base::Vector3f((float)gpPt.X(),
                                              (float)gpPt.Y(),
                                              (float)gpPt.Z());
  Base::Vector3f cResultPoint, cSplitPoint, cPlanePnt, cPlaneNormal;
  unsigned long uStartFacetIdx,uCurFacetIdx;
  unsigned long uLastFacetIdx=ULONG_MAX-1; // use another value as ULONG_MAX
  unsigned long auNeighboursIdx[3];
  bool GoOn;
  
  if( !findStartPoint(_Mesh,cStartPoint,cResultPoint,uStartFacetIdx) )
    return;

  uCurFacetIdx = uStartFacetIdx;
  do{
    MeshGeomFacet cCurFacet= _Mesh.GetFacet(uCurFacetIdx);
    _Mesh.GetFacetNeighbours ( uCurFacetIdx, auNeighboursIdx[0], auNeighboursIdx[1], auNeighboursIdx[2]);
    Base::Vector3f PointOnEdge[3];

    GoOn = false;
    int NbrOfHits = 0,HitIdx=0;
    
    for(int i=0; i<3; i++)
    {
      // ignore last visited facet
      if ( auNeighboursIdx[i] == uLastFacetIdx ) 
        continue;

      // get points of the edge i
      const Base::Vector3f& cP0 = cCurFacet._aclPoints[i];
      const Base::Vector3f& cP1 = cCurFacet._aclPoints[(i+1)%3];

      if ( auNeighboursIdx[i] != ULONG_MAX )
      {
        // calculate the normal by the edge vector and the middle between the two face normals
        MeshGeomFacet N = _Mesh.GetFacet( auNeighboursIdx[i] );
        cPlaneNormal = ( N.GetNormal() + cCurFacet.GetNormal() ) % ( cP1 - cP0 );
        cPlanePnt    = cP0;
      }else{
        // with no neighbours the face normal is used
        cPlaneNormal = cCurFacet.GetNormal() % ( cP1 - cP0 );
        cPlanePnt    = cP0;
      }

      Handle(Geom_Plane) hPlane = new Geom_Plane(gp_Pln(gp_Pnt(cPlanePnt.x,cPlanePnt.y,cPlanePnt.z), 
                                                        gp_Dir(cPlaneNormal.x,cPlaneNormal.y,cPlaneNormal.z)));
 
      GeomAPI_IntCS Alg(hCurve,hPlane); 

      if ( Alg.IsDone() )
      {
        // deciding by the number of result points (intersections)
        if( Alg.NbPoints() == 1)
        {
          gp_Pnt P = Alg.Point(1);
          float l = ((Base::Vector3f((float)P.X(),(float)P.Y(),(float)P.Z()) - cP0)
                  * (cP1 - cP0) ) / ((cP1 - cP0) * (cP1 - cP0));
          // is the Point on the Edge of the facet?
          if(l<0.0 || l>1.0)
            PointOnEdge[i] = Base::Vector3f(FLOAT_MAX,0,0);
          else{
            cSplitPoint = (1-l) * cP0 + l * cP1;
            PointOnEdge[i] = (1-l)*cP0 + l * cP1;
            NbrOfHits ++;
            HitIdx = i;
          }
        // no intersection
        }else if(Alg.NbPoints() == 0){
          PointOnEdge[i] = Base::Vector3f(FLOAT_MAX,0,0);
        // more the one intersection (@ToDo)
        }else if(Alg.NbPoints() > 1){
          PointOnEdge[i] = Base::Vector3f(FLOAT_MAX,0,0);
          Base::Console().Log("MeshAlgos::projectCurve(): More then one intersection in Facet %lu, Edge %d\n",uCurFacetIdx,i);
        }
      }
    }

    uLastFacetIdx = uCurFacetIdx;

    if(NbrOfHits == 1)
    {
      uCurFacetIdx = auNeighboursIdx[HitIdx];
      FaceSplitEdge splitEdge;
      splitEdge.ulFaceIndex = uCurFacetIdx;
      splitEdge.p1 = cResultPoint;
      splitEdge.p2 = cSplitPoint;
      vSplitEdges.push_back( splitEdge );
      cResultPoint = cSplitPoint;
      GoOn = true;
    }else{
      Base::Console().Log("MeshAlgos::projectCurve(): Possible reentry in Facet %lu\n", uCurFacetIdx);
    }

    if( uCurFacetIdx == uStartFacetIdx )
      GoOn = false;

  }while(GoOn);

}