ぬの部屋(仮)
nu-no-he-ya
  •      12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • VCG LibでOpenEdgeのループを検出する

    MyMesh

    #pragma once
    
    // vcg コア
    #include <vcg/complex/complex.h>
    
    // vcg input output
    #include <wrap/io_trimesh/import_ply.h>
    #include <wrap/io_trimesh/export_ply.h>
    #include <wrap/io_trimesh/import_stl.h>
    
    
    using namespace vcg;
    using namespace std;
    
    /////////////////////////////////////////////////
    /////////////////////////////////////////////////
    // メッシュデータ型
    /////////////////////////////////////////////////
    /////////////////////////////////////////////////
    class MyFace;
    class MyVertex;
    class MyEdge;
    
    struct MyUsedTypes : public
      UsedTypes<
      Use<MyVertex>::AsVertexType,
      Use<MyFace>::AsFaceType,
      Use<MyEdge>::AsEdgeType
    
      >
    {};
    
    class MyVertex :
      public Vertex<
      MyUsedTypes,
      vertex::Coord3f,
      vertex::Color4b,
      vertex::Normal3f,
      vertex::BitFlags,
      vertex::VEAdj,// needed
      vertex::Mark>
    {
    public:
      bool m_loopchecked;
      MyVertex() {
        m_loopchecked = false;
      }
    
    };
    
    class MyEdge : public vcg::Edge<
      MyUsedTypes,
      vcg::edge::VertexRef,
      vcg::edge::VEAdj,// needed
      vcg::edge::BitFlags> {
    
    public:
      MyEdge() {
      }
    };
    
    class MyFace :
      public Face  <
      MyUsedTypes,
      face::VertexRef,
      face::Normal3f,
      face::FFAdj,// needed
      face::BitFlags >
    {};
    
    
    class MyMesh :
      public vcg::tri::TriMesh<
      vector<MyVertex>,
      vector<MyFace>,
      vector<MyEdge>
      >
    {};
    

    実装

    #pragma once
    #include <windows.h>
    #include <GL/gl.h>
    #include <GL/freeglut.h>
    #include "nurotate.h"
    
    
    #include "MyMesh.h"
    
    //! @brief 穴構成頂点の配列をhole_tとする。
    using hole_t = std::vector<int>;
    
    //! @brief 穴の配列
    std::vector<hole_t> holes;

    //! @brief 穴を検出する関数 //! @param [in] mesh メッシュデータ //! @param [out] hole 穴構成頂点の格納先 //! @param [in] vid 検索開始地点の頂点ID //! @retval false 穴が見つからなかった //! @retval true 穴が見つかった bool search_near_edge(MyMesh& mesh, hole_t& hole,int vid) { vcg::edge::VEIterator<MyEdge> vfe(&mesh.vert[vid]); for (; !vfe.End(); ++vfe) { MyEdge* e = vfe.E(); // OpenEdge以外は読み飛ばす if (e->IsB() == false) { continue; } //現在検索中の頂点ともう一方に分ける int from, to; if (vcg::tri::Index(mesh, e->cV(0)) == vid) { from = vid; to = vcg::tri::Index(mesh, e->cV(1)); } else { from = vid; to = vcg::tri::Index(mesh, e->cV(0)); } if (hole.size() != 0) { if (hole[0] == to) { hole.push_back(from); return true; } } if (mesh.vert[to].m_loopchecked == true) continue; mesh.vert[from].m_loopchecked = true; hole.push_back(from); if (search_near_edge(mesh, hole, to) == true) { return true; } } return false; }
    MyMesh m; int width, height; //回転オブジェクト定義 nu::mrotate camr; //! @brief 表示関数 //! @return なし void disp(void) { glClearColor(0.3, 0.3, 0.3, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,width / (double)height, 0.1, 5); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); GLfloat lpos[4] = { 0,1,1,1 }; GLfloat ambw[4] = { 0.5,0.5,0.5,1 }; GLfloat color[4] = { 1,1,1,1 }; GLfloat lspec[4] = { 1,1,1,1 }; GLfloat mspec[4] = { 0.5,0.5,0.5,1 }; ///////////////////////////////////////////// glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, ambw); glLightfv(GL_LIGHT0, GL_SPECULAR, lspec); glLightfv(GL_LIGHT0, GL_POSITION, lpos); ///////////////////////////////////////////// glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mspec); glPushMatrix(); //原点を視線方向に0.5ずらす glTranslated(0, 0, -2); //回転行列を適用 double mat[16]; glMultMatrixd(camr.getmatrix(mat));
    glPushMatrix(); glScaled(2.0 / m.bbox.Diag(), 2.0 / m.bbox.Diag(), 2.0 / m.bbox.Diag()); { //全ての面を表示 glBegin(GL_TRIANGLES); for (auto& f : m.face) { glNormal3f(f.cN().X(), f.cN().Y(), f.cN().Z()); glVertex3d(f.cV(0)->cP().X(), f.cV(0)->cP().Y(), f.cV(0)->cP().Z()); glVertex3d(f.cV(1)->cP().X(), f.cV(1)->cP().Y(), f.cV(1)->cP().Z()); glVertex3d(f.cV(2)->cP().X(), f.cV(2)->cP().Y(), f.cV(2)->cP().Z()); } glEnd(); } { //全てのエッジを表示 glDisable(GL_LIGHTING); glLineWidth(1); glColor3d(0, 0, 0); for (auto& f : m.face) { glBegin(GL_LINE_LOOP); glVertex3d(f.cV(0)->cP().X(), f.cV(0)->cP().Y(), f.cV(0)->cP().Z()); glVertex3d(f.cV(1)->cP().X(), f.cV(1)->cP().Y(), f.cV(1)->cP().Z()); glVertex3d(f.cV(2)->cP().X(), f.cV(2)->cP().Y(), f.cV(2)->cP().Z()); glEnd(); } } { //見つかった穴だけを表示 glDisable(GL_LIGHTING); glLineWidth(3); glColor3d(0, 0, 1); for (auto& hole : holes) { glBegin(GL_LINE_STRIP); for (auto& v : hole) { glVertex3d( m.vert[v].cP().X(), m.vert[v].cP().Y(), m.vert[v].cP().Z() ); } glEnd(); } } glPopMatrix();

    glPopMatrix(); glFlush(); } void reshape(int w, int h) { width = w; height = h; //クライアント領域のサイズを指定 //Win32APIの場合はGetClientRectで求めたrightとbottomだがglutではwとh camr.setWindowSize(width, height); //クライアント領域のどこの範囲に描画しているかを指定。 //glViewportで一画面丸々描画しているので、クライアント領域の(0,0)-(width,height)に書いていることになる camr.setRenderRect(0, 0, width, height); disp(); } //マウスクリック時のイベント void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { camr.dragstart(x, y);//最初の回転軸を決定 } else if (state == GLUT_UP) { camr.dragend();//ドラッグ終了 } glutPostRedisplay(); } //ドラッグ時のイベント void motion(int x, int y) { camr.dragto(x, y);//移動中の回転軸を更新 disp(); } //エントリポイント int main(int argc, char ** argv) { glutInit(&argc, argv); glutInitWindowPosition(100, 50); glutInitWindowSize(400, 300); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutCreateWindow("MouseRotateSample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMotionFunc(motion);
    vcg::tri::io::ImporterPLY<MyMesh>::Open(m, "sample.ply"); vcg::tri::Clean<MyMesh>::RemoveDuplicateVertex(m); vcg::tri::UpdateBounding<MyMesh>::Box(m); vcg::tri::UpdateNormal<MyMesh>::PerFace(m); vcg::tri::UpdateTopology<MyMesh>::FaceFace(m); vcg::tri::UpdateTopology<MyMesh>::AllocateEdge(m); vcg::tri::UpdateTopology<MyMesh>::VertexEdge(m); vcg::tri::UpdateFlags<MyMesh>::VertexBorderFromFaceAdj(m);
     
    ///////////////////////////////// // 穴検出 /////////////////////// bool ret; for (size_t i = 0; i < m.vert.size(); i++) { //OpenEdgeのフラグが立っていないなら何もしない if (m.vert[i].IsB() == false) continue; //すでにループかどうかの評価をしたフラグが立っていれば何もしない if (m.vert[i].m_loopchecked) continue; m.vert[i].m_loopchecked = true; hole_t hole; ret = search_near_edge(m, hole,i);//未チェックのOpenEdge構成頂点を渡して穴かどうかの評価 if (ret == true) { holes.push_back(hole);//穴一覧を更新 } }
     
    glutMainLoop(); return 0; }

    回転について

    以下を参照

    実行結果