Esempio n. 1
0
void PartialAction :: relaxEdge (WingedMesh& mesh, WingedEdge& edge, AffectedFaces& affectedFaces) {
  if (relaxableEdge (edge)) {
    affectedFaces.insert (edge.leftFaceRef  ());
    affectedFaces.insert (edge.rightFaceRef ());
    PartialAction::flipEdge (mesh, edge);
  }
}
Esempio n. 2
0
void PartialAction :: deleteEdgeFace ( WingedMesh& mesh, WingedEdge& edge
                                     , AffectedFaces& affectedFaces) 
{
#ifndef NDEBUG
  const unsigned int numEdgesLeft  = edge.leftFaceRef  ().numEdges ();
  const unsigned int numEdgesRight = edge.rightFaceRef ().numEdges ();
#endif
  assert (numEdgesLeft  >= 2);
  assert (numEdgesRight >= 2);

  WingedFace& faceToDelete  = edge.rightFaceRef ();
  WingedFace& remainingFace = edge.leftFaceRef ();

  assert (faceToDelete != remainingFace);

  affectedFaces.remove (faceToDelete);
  affectedFaces.insert (remainingFace);

  dissolveEdgeFace (edge);

  mesh.deleteEdge (edge);
  mesh.deleteFace (faceToDelete); 

  assert (remainingFace.numEdges () >= 3);
  assert (remainingFace.numEdges () == numEdgesLeft + numEdgesRight - 2);
}
Esempio n. 3
0
void WingedUtil :: printStatistics (const WingedEdge& e) {
  auto maybeEdgeIndex = [] (WingedEdge* edge) {
    return bool (edge) ? std::to_string (edge->index ())
                       : std::string ("NULL");
  };
  auto maybeFaceIndex = [] (WingedFace* face) {
    return bool (face) ? std::to_string (face->index ())
                       : std::string ("NULL");
  };
  auto maybeVertexIndex = [] (WingedVertex* vertex) {
    return bool (vertex) ? std::to_string (vertex->index ())
                         : std::string ("NULL");
  };

  std::cout << "edge " << e.index () 
    << "\n\tvertex 1:\t\t"        << maybeVertexIndex (e.vertex1          ())
    <<   "\tvertex 2:\t\t"        << maybeVertexIndex (e.vertex2          ())
    << "\n\tleft face:\t\t"       << maybeFaceIndex   (e.leftFace         ())
    <<   "\tright face:\t\t"      << maybeFaceIndex   (e.rightFace        ())
    << "\n\tleft predecessor:\t"  << maybeEdgeIndex   (e.leftPredecessor  ())
    <<   "\tleft successor:\t\t"  << maybeEdgeIndex   (e.leftSuccessor    ())
    << "\n\tright predecessor:\t" << maybeEdgeIndex   (e.rightPredecessor ())
    <<   "\tright successor:\t"   << maybeEdgeIndex   (e.rightSuccessor   ())
    << std::endl;
}
Esempio n. 4
0
void FEdgeXDetector::processShapes(WingedEdge& we) {
    bool progressBarDisplay = false;
    Vec3r Min, Max;
    vector<WShape*> wshapes = we.getWShapes();
    WXShape * wxs;

    if(_pProgressBar != NULL) {
        _pProgressBar->reset();
        _pProgressBar->setLabelText("Detecting feature lines");
        _pProgressBar->setTotalSteps(wshapes.size() * 3);
        _pProgressBar->setProgress(0);
        progressBarDisplay = true;
    }

    for(vector<WShape*>::const_iterator it = wshapes.begin();
        it != wshapes.end();
        it++){
        wxs = dynamic_cast<WXShape*>(*it);
        //printf("\n\nmesh silhouette = %d\n\n",wxs->MeshSilhouettes());
        wxs->bbox(Min, Max);
        _bbox_diagonal = (Max-Min).norm();
        if(_changes){
            vector<WFace*>& wfaces = wxs->GetFaceList();
            for(vector<WFace*>::iterator wf=wfaces.begin(), wfend=wfaces.end();
                wf!=wfend;
                ++wf){
                WXFace* wxf = dynamic_cast<WXFace*>(*wf);
                wxf->Clear();
            }
            _computeViewIndependant = true;
        } else if (!(wxs)->getComputeViewIndependantFlag()) {
            wxs->Reset();
            _computeViewIndependant = false;
        } else {
            _computeViewIndependant = true;
        }
        preProcessShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
        processBorderShape(wxs);

        // skipping crease detection:
        //    processCreaseShape(wxs);

        if(_computeRidgesAndValleys)
            processRidgesAndValleysShape(wxs);
        if(_computeSuggestiveContours)
            processSuggestiveContourShape(wxs);
        processSilhouetteShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);

        // build smooth edges:
        buildSmoothEdges(wxs);

        // Post processing for suggestive contours
        if(_computeSuggestiveContours)
            postProcessSuggestiveContourShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);

        wxs->setComputeViewIndependantFlag(false);
        _computeViewIndependant = false;
        _changes = false;

        // reset user data
        (*it)->ResetUserData();
    }
}
Esempio n. 5
0
    // Subdivides only the edges on the boundary.
    WingedEdge WingedEdge::BoundaryTrianglularSubdivide(float min_len)
    {
        
        WingedEdge mesh;// = *this;

        
        for (auto face_iter = faceList.begin(); face_iter != faceList.end(); ++face_iter)
        {
            const Face face = face_iter -> first;
            
            
            /* massive assumption that there is 3 edges in our face */
            Edge e1 = face.E1();
            Edge e2 = face.E2();
            Edge e3 = face.E3();
            
            // Compute the vertices opposite the cooresponding indiced edges.
            bool success = true;
            Vertex v1 = GetAdjacentVertex(face, e1, success);
            Vertex v2 = GetAdjacentVertex(face, e2, success);
            Vertex v3 = GetAdjacentVertex(face, e3, success);
            
            if(!success)
            {
                throw new RuntimeError("Error : Winged Edge topology is malformed!");
            }
            
            // -- Compute boundary predicates that answer whether or not an edge should be divided.
            bool b1, b2, b3;
            b1 = getNumAdjacentFaces(e1) == 1;
            b2 = getNumAdjacentFaces(e2) == 1;
            b3 = getNumAdjacentFaces(e3) == 1;
            
            // Non Boundary --> do not subdivide the face.
            if(!(b1 || b2 || b3))
            {
                
                e1 = mesh.AddEdge(e1);
                e2 = mesh.AddEdge(e2);
                e2 = mesh.AddEdge(e2);
                
                mesh.AddFace(e1, e2, e3);
                
                continue;
            }
            
            
            // FIXME : Only compute butterfly midpoints, if the original predicate is true.
            
            // Compute interpolated midpoints.
            Vertex mid_b1, mid_b2, mid_b3;
            mid_b1 = SubdivideEdge(face, e1, v1, false);
            mid_b2 = SubdivideEdge(face, e2, v2, false);
            mid_b3 = SubdivideEdge(face, e3, v3, false);
            
            
            // Bound the change in midpoint.
            if(min_len > 0)
            {
                // Compute linear mid points.
                Vertex mid_l1, mid_l2, mid_l3;
                mid_l1 = SubdivideEdge(face, e1, v1, true);
                mid_l2 = SubdivideEdge(face, e2, v2, true);
                mid_l3 = SubdivideEdge(face, e3, v3, true);
                
                float sqr_len_min = min_len > 1 ? min_len*min_len : min_len;
                
                b1 = b1 && computeSqrOffset(mid_b1, mid_l1) > sqr_len_min;
                b2 = b2 && computeSqrOffset(mid_b2, mid_l2) > sqr_len_min;
                b3 = b3 && computeSqrOffset(mid_b3, mid_l3) > sqr_len_min;
            }
            
            
            
            // -- Count the number of edges that are on the boundary.
            int boundary_count = 0;
            boundary_count = b1 ? boundary_count + 1 : boundary_count;
            boundary_count = b2 ? boundary_count + 1 : boundary_count;
            boundary_count = b3 ? boundary_count + 1 : boundary_count;
     
            // Non Boundary --> do not subdivide the face.
            if(boundary_count == 0)
            {
                e1 = mesh.AddEdge(e1);
                e2 = mesh.AddEdge(e2);
                e2 = mesh.AddEdge(e2);
                
                mesh.AddFace(e1, e2, e3);
                continue;
            }
            
            
            // 1 boundary --> subdivide into 2 vertices.
            if(boundary_count == 1)
            {
                
                Vertex v_new, v_old1, v_old2, v_old3;
                
                if(b1)
                {
                    v_new = mid_b1;
                    v_old1 = v1;
                    v_old2 = v2;
                    v_old3 = v3;
                }
                else if(b2)
                {
                    v_new = mid_b2;
                    v_old1 = v2;
                    v_old2 = v3;
                    v_old3 = v1;
                }
                else
                {
                    v_new = mid_b3;
                    v_old1 = v3;
                    v_old2 = v1;
                    v_old3 = v2;
                }
                
                // face1
                e1 = mesh.AddEdge(v_new, v_old1);
                e2 = mesh.AddEdge(v_new, v_old2);
                e3 = mesh.AddEdge(v_old1, v_old2);
                mesh.AddFace(e1, e2, e3);
                
                // Face 2.
                e2 = mesh.AddEdge(v_new, v_old3);
                e3 = mesh.AddEdge(v_old1, v_old3);
                mesh.AddFace(e1, e2, e3);
                
                continue;
            }
            
            // 2 - 3 boundaries. Perform the full 4 face triangulation.
            
            if(boundary_count == 3)
            {
                performTriangulation(mesh,
                                     v1, v2, v3,
                                     mid_b1, mid_b2, mid_b3);
                
                continue;
            }
            
            if(boundary_count > 3)
            {
                throw new RuntimeError("Face has more than 3 edges. This is not a triangle!");
            }
            
            // -- 2 boundary case. Subdivide into 3 triangles.
            Vertex v_new1, v_new2, v_old1, v_old2, v_old3;
            
            if(!b1)
            {
                v_old1 = v1;
                v_old2 = v2;
                v_old3 = v3;
                v_new1 = mid_b2;
                v_new2 = mid_b3;
            }
            else if(!b2)
            {
                v_old1 = v2;
                v_old2 = v3;
                v_old3 = v1;
                v_new1 = mid_b3;
                v_new2 = mid_b1;
            }
            else
            {
                v_old1 = v3;
                v_old2 = v1;
                v_old3 = v2;
                v_new1 = mid_b1;
                v_new2 = mid_b2;
            }

            
            // Boundary triangles.
            e1 = mesh.AddEdge(v_old1, v_new1);
            e2 = mesh.AddEdge(v_old1, v_new2);
            e3 = mesh.AddEdge(v_new1, v_new2);
            mesh.AddFace(e1, e2, e3);
            
            
            e1 = mesh.AddEdge(v_old3, v_new1);
            e2 = mesh.AddEdge(v_old3, v_new2);
            e3 = mesh.AddEdge(v_new1, v_new2);
            mesh.AddFace(e1, e2, e3);
            
            // Constant edge triangle.
            e1 = mesh.AddEdge(v_old2, v_new2);
            e2 = mesh.AddEdge(v_old3, v_new2);
            e3 = mesh.AddEdge(v_old3, v_old2);
            mesh.AddFace(e1, e2, e3);
            
        }
       
        return mesh;
    }
Esempio n. 6
0
 // Private work function.
 WingedEdge WingedEdge::Subdivide(bool linear, bool pascal, std::map<Vertex, std::vector<Vertex> > &derivations)
 {
     WingedEdge mesh;
     std::set<Edge> edges;
     
     for (auto face = faceList.begin(); face != faceList.end(); ++face)
     {
         
         /* massive assumption that there is 3 edges in our face */
         Edge e1 = face -> first.E1();
         Edge e2 = face -> first.E2();
         Edge e3 = face -> first.E3();
         
         /* might need to verify this doesn't pick duplicates */
         Vertex v1 = e1.V1();
         Vertex v2 = e1.V2();
         Vertex v3 = (e2.V1() == v1 || e2.V1() == v2) ? e2.V2() : e2.V1();
         
         /* guarantee we know what e2 is */
         if (v1 == e3.V1() || v1 == e3.V2())
         {
             Edge tmp = e3;
             e3 = e2;
             e2 = tmp;
         }
         
         int f1, f2, f3;
         f1 = getNumAdjacentFaces(e1);
         f2 = getNumAdjacentFaces(e2);
         f3 = getNumAdjacentFaces(e3);
         
         // Do not subdivide and do not incorporate non boundary faces.
         // This is the part the creates the pascal behavior,
         if(pascal && f1 == 2 && f2 == 2 && f3 == 2)
         {
             continue;
         }
         
         bool success = true;
         Vertex v4 = SubdivideEdge(face->first, e1, GetAdjacentVertex(face->first, e1, success), linear, derivations);
         Vertex v5 = SubdivideEdge(face->first, e2, GetAdjacentVertex(face->first, e2, success), linear, derivations);
         Vertex v6 = SubdivideEdge(face->first, e3, GetAdjacentVertex(face->first, e3, success), linear, derivations);
         
         // A half hearted success check.
         if(!success)
         {
             throw RuntimeError("WindgedEdge Error: Something is wrong with the mesh to be subdivided.");
         }
         
         {
             e1 = mesh.AddEdge(v1, v4);
             e2 = mesh.AddEdge(v1, v5);
             e3 = mesh.AddEdge(v5, v4);
             mesh.AddFace(e1, e2, e3);
         }
         
         {
             e1 = mesh.AddEdge(v4, v2);
             e2 = mesh.AddEdge(v4, v6);
             e3 = mesh.AddEdge(v6, v2);
             mesh.AddFace(e1, e2, e3);
         }
         
         {
             e1 = mesh.AddEdge(v5, v6);
             e2 = mesh.AddEdge(v5, v3);
             e3 = mesh.AddEdge(v3, v6);
             mesh.AddFace(e1, e2, e3);
         }
         
         {
             e1 = mesh.AddEdge(v6, v5);
             e2 = mesh.AddEdge(v6, v4);
             e3 = mesh.AddEdge(v4, v5);
             mesh.AddFace(e1, e2, e3);
         }
         
     }
     
     /*
      std::cout << "Subdivide info: " << std::endl;
      std::cout << "VertexList: " << mesh.NumVertices() << std::endl;
      std::cout << "EdgeList: " << mesh.NumEdges() << std::endl;
      std::cout << "FaceList: " << mesh.NumFaces() << std::endl;
      */
     
     return mesh;
 }
Esempio n. 7
0
 // Adds 4 sub triangles based on three original vertices and 3 new vertices to the given mesh.
 // FIXME : Add better documentation and understanding to this function.
 void WingedEdge::performTriangulation(WingedEdge &mesh,
                                       Vertex &v1, Vertex &v2, Vertex &v3,
                                       Vertex &v4, Vertex &v5, Vertex &v6)
 {
     Edge e1, e2, e3;
     
     
     // Face 1.
     e1 = mesh.AddEdge(v1, v5);
     e2 = mesh.AddEdge(v1, v6);
     e3 = mesh.AddEdge(v5, v6);
     mesh.AddFace(e1, e2, e3);
     
     
     // Face 2.
     e1 = mesh.AddEdge(v2, v4);
     e2 = mesh.AddEdge(v2, v6);
     e3 = mesh.AddEdge(v4, v6);
     mesh.AddFace(e1, e2, e3);
     //
     
     // Face 3.
     e1 = mesh.AddEdge(v3, v4);
     e2 = mesh.AddEdge(v3, v5);
     e3 = mesh.AddEdge(v4, v5);
     mesh.AddFace(e1, e2, e3);
     
     
     // Face 4.
     e1 = mesh.AddEdge(v4, v5);
     e2 = mesh.AddEdge(v4, v6);
     e3 = mesh.AddEdge(v5, v6);
     mesh.AddFace(e1, e2, e3);
     
 }