ぬの部屋(仮)
nu-no-he-ya
  •      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 Library

    1.ダウンロード

    以下の、Clone or downloadからVCG Libraryをダウンロードする。

    https://github.com/cnr-isti-vclab/vcglib/

    2.Includeする

    //基本的なデータタイプ
    #include <vcg/complex/complex.h>
    // PLYファイルの入出力
    #include <wrap/io_trimesh/import_ply.h>
    #include <wrap/io_trimesh/export_ply.h>
    

    3.基本的なデータ型を作成

    vcg::Vertex,vcg::Faceなどの既存型があるが、それらを継承した型を使うのが方針らしい。

    class MyFace;
    class MyVertex;
    class MyEdge;
    
    struct MyUsedTypes : public vcg::UsedTypes<
       vcg::Use<MyVertex>::AsVertexType,
       vcg::Use<MyFace>::AsFaceType,
       vcg::Use<MyEdge>::AsEdgeType> {};
    
    //頂点型
    class MyVertex : public vcg::Vertex< 
    	MyUsedTypes, 
    	vcg::vertex::Coord3f, 
    	vcg::vertex::Color4b, 
    	vcg::vertex::Normal3f, 
    	vcg::vertex::VFAdj, 
    	vcg::vertex::VEAdj, 
    	vcg::vertex::Qualityf, 
    	vcg::vertex::BitFlags, 
    	vcg::vertex::Mark> {
    //ここにメンバ変数を追加できる
    };
    //面型
    class MyFace : public vcg::Face  < 
    	MyUsedTypes, 
    	vcg::face::VertexRef, 
    	vcg::face::Normal3f, 
    	vcg::face::FFAdj, 
    	vcg::face::EFAdj, 
    	vcg::face::Mark, 
    	vcg::face::VFAdj, 
    	vcg::face::BitFlags > {
    };
    //エッジ型
    class MyEdge : public vcg::Edge< 
    	MyUsedTypes, 
    	vcg::edge::VertexRef, 
    	vcg::edge::BitFlags, 
    	vcg::edge::EVAdj, 
    	vcg::edge::EFAdj> {
    };
    //3Dモデル型
    class MyMesh : public vcg::tri::TriMesh< 
    	std::vector<MyVertex>, 
    	std::vector<MyFace>, 
    	std::vector<MyEdge> > {
    };
    

    4.PLYファイルを読み込む例

    エッジ情報などはデフォルトでは計算してくれないので、UpdateTopologyのAllocateEdgeなどで作成する

    //メッシュデータオブジェクト
    MyMesh mesh;
    int main(int argc, char **argv)
    {
    
      //plyファイル読み込み
      vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, "data.ply");
    
      //面法線計算
      vcg::tri::UpdateNormal<MyMesh>::PerFace(mesh);
    
      //Triangleのエッジ情報を作成
      vcg::tri::UpdateTopology<MyMesh>::AllocateEdge(mesh);
    
      //縮尺
     // meshオブジェクトがbboxメンバ(Bounding Box)を持っているので、
      // モデルの最大・最小の座標がわかる
      double scalex = 1.0 / (mesh.bbox.max.X() - mesh.bbox.min.X());
      double scaley = 1.0 / (mesh.bbox.max.Y() - mesh.bbox.min.Y());
      double scalez = 1.0 / (mesh.bbox.max.Z() - mesh.bbox.min.Z());
    
      double scale = (std::min)((std::min)(scalex, scaley), scalez);
    
      //センタリング
      double offsx = mesh.bbox.min.X() + (mesh.bbox.max.X() - mesh.bbox.min.X()) / 2;
      double offsy = mesh.bbox.min.Y() + (mesh.bbox.max.Y() - mesh.bbox.min.Y()) / 2;
      double offsz = mesh.bbox.min.Z() + (mesh.bbox.max.Z() - mesh.bbox.min.Z()) / 2;
    

    5.表示

    全ての三角形はmeshオブジェクト内のface配列に格納されている。

    //三角形で表示
    void disp_triangles() {
    
      //マテリアルの設定
      glMaterialfv(GL_FRONT, GL_AMBIENT, material_ambient);
      glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular);
    
      glEnable(GL_LIGHTING);
    
      glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse_w);
      //描画処理本体
      // mesh.face[0].N で面法線
      // mesh.face[0].V(0)->C.X() で三角形の第一頂点のR
      // mesh.face[0].V(0)->P().X() で三角形の第一頂点のx座標
     // * cがついているのはconstの意味
      glBegin(GL_TRIANGLES);
      for (const auto& f : mesh.face) {
        glNormal3d(f.cN().X(), f.cN().Y(), f.cN().Z());
        for (size_t i = 0; i < 3; i++) {
          glColor3ub(f.cV(i)->cC().X(), f.cV(i)->cC().Y(), f.cV(i)->cC().Z());
          glVertex3d(f.cV(i)->cP().X(), f.cV(i)->cP().Y(), f.cV(i)->cP().Z());
        }
    
      }
      glEnd();
    }
    //三角形のエッジを表示
    void disp_edge() {
    
      glDisable(GL_LIGHTING);
    
      glColor3d(1, 0, 0);
      glBegin(GL_LINES);
      for (const auto& e : mesh.edge) {
        glVertex3d(e.cV(0)->cP().X(), e.cV(0)->cP().Y(), e.cV(0)->cP().Z());
        glVertex3d(e.cV(1)->cP().X(), e.cV(1)->cP().Y(), e.cV(1)->cP().Z());
      }
      glEnd();
    }
    

    VCG Library メッシュからfaceのみを削除する

    VCG LibraryのBall Pivotingでメッシュ生成

    VCG LibraryでkdTree

    VCG Library でスムージング

    VCG Library ターゲットの周辺のオブジェクトを取得

    VCG LibraryでMeshに三角形を登録する方法

    VCG Library でポリゴンファイル保存

    VCG Libraryで色のついたポリゴンの読み込み・表示

    VCG LibのFace-FaceやEdge-Faceなどの関連付け

    VCG Library

    vray for blender で Sun(Direct) Decayの変化

    Vray for Blender、Sun(Direct)のDecayの変化を一括して動画にしました。

    Decayは減衰を表します。ライトの距離を離していくと、以下のように違いが現れます。

    必要な関数やクラスを.libファイルの中から探す

    経緯

    Point Cloud Library (PCL) と言うのを使っているのですが、その中でstlの入出力をしたくなりました。

    #include <pcl/io/vtk_lib_io.h>

    をしてから

    pcl::io::loadPolygonFileSTL ()

    を使ってみましたが、リンクエラーでvtkDebugLeaksManagerが見つからないといわれます。

    答えを言うとvtkCommonCore-8.0.lib をリンクすればいいのですが、調べてみてもCMakeすればいいよみたいな情報しかなくて結構困りました。

     

    vtkとついているんだからvtkのlibディレクトリを探せばいいことまではわかっています。ある程度目星がついているのに他を探し回るのは嫌だし、だからと言って200個あるlibを一つ一つリンクしてみるのも自分がかわいそうになるので、もう少しましな方法を考えます。

    結論

    以下のようなBATファイルを作成しました(linksearch.bat)

    set LIBFILEPATH=%1
    set SEARCHWORD=%2
    set OUTPUTFILE=flistresult.txt
    @echo on
    type nul > %OUTPUTFILE%
    @for %%i in (%LIBFILEPATH%) do (
      @echo on
      @echo %%i
      @echo off
      echo %%i >> %OUTPUTFILE%
      dumpbin /LINKERMEMBER “%%i” | findstr /C:”%SEARCHWORD%” >> %OUTPUTFILE%
    )
    notepad %OUTPUTFILE%

     

    使い方は、第一引数にライブラリディレクトリのパス、第二引数に検索したいシンボルを指定します。

    linksearch “C:\Program Files\PCL 1.8.1\3rdParty\VTK\lib\*” vtkDebugLeaksManager@@QEAA@XZ

     

    この出力結果(flistresult.txt)は、このようになります。

     
    .\libx\vtkalglib-8.0-gd.lib
    .\libx\vtkalglib-8.0.lib
    .\libx\vtkChartsCore-8.0-gd.lib
    .\libx\vtkChartsCore-8.0.lib
    .\libx\vtkCommonColor-8.0-gd.lib
    .\libx\vtkCommonColor-8.0.lib
    .\libx\vtkCommonComputationalGeometry-8.0-gd.lib
    .\libx\vtkCommonComputationalGeometry-8.0.lib
    .\libx\vtkCommonCore-8.0-gd.lib
         33737C6 ??0vtkDebugLeaksManager@@QEAA@XZ
         33737C6 ??1vtkDebugLeaksManager@@QEAA@XZ
         69 ??0vtkDebugLeaksManager@@QEAA@XZ
         69 ??1vtkDebugLeaksManager@@QEAA@XZ
    .\libx\vtkCommonCore-8.0.lib
         D16866 ??0vtkDebugLeaksManager@@QEAA@XZ
         D16866 ??1vtkDebugLeaksManager@@QEAA@XZ
         69 ??0vtkDebugLeaksManager@@QEAA@XZ
         69 ??1vtkDebugLeaksManager@@QEAA@XZ
    .\libx\vtkCommonDataModel-8.0-gd.lib
    .\libx\vtkCommonDataModel-8.0.lib
    .\libx\vtkCommonExecutionModel-8.0-gd.lib
    .\libx\vtkCommonExecutionModel-8.0.lib
    .\libx\vtkCommonMath-8.0-gd.lib
    .\libx\vtkCommonMath-8.0.lib
    .\libx\vtkCommonMisc-8.0-gd.lib
    .\libx\vtkCommonMisc-8.0.lib
    .\libx\vtkCommonSystem-8.0-gd.lib

    … (以下略)

    ※行が長くなるので中身を.\libx\に移しています

     

    検索対象のvtkDebugLeaksManagerが表れているなら、その上のlib名で定義されています

    本当は、必要なファイルだけを表示するなどしたかったのですが、Windowsのbatがよくわからずに断念しました。

     

    解説

    Microsoft COFF Binary File Dumper (DUMPBIN.EXE) は、COFF (Common Object File Format) 形式のバイナリ ファイルに関する情報を出力します。 DUMPBIN を使うと、COFF オブジェクト ファイル、COFF オブジェクトの標準ライブラリ、実行可能ファイル、およびダイナミック リンク ライブラリ (DLL) の内容を確認できます。

    DUMPBIN リファレンス

    ということで、dumpbinはexe,dll,libの内容を確認するためのツールです。

    dumpbinはVisual Studioに入っています。Visual Studioのコマンドプロンプト、例えば「VS 2017用 x64 Native Tools コマンドプロンプト」から起動します。

    vs2017console

     

    そして、/LINKERMEMBER オプションをつけます。

    このオプションは、ライブラリで定義されているパブリック シンボルを出力します。

      — /LINKERMEMBER

    > dumpbin /LINKERMEMBER ファイル名

     

    ただしこれだけだと、必要のない情報も全部出力されてしまいます。テキストエディタの検索機能を使ってもいいのですが、せっかくなのでfindstrへパイプします。

    findstr /C:”検索したい文字列”

    ファイルの中からテキスト文字列を検索する。検索対象のパス指定が無ければ、プロンプトで入力されたテキストまたは別のコマンドからパイプ処理で渡されたテキストを検索する。正規表現の使用ができる。

     — コマンドプロンプト findstr

     

    即ち、目星のついているライブラリに対して、以下のように実行して、標準出力があればよいという事になります。

     

    dumpbin /LINKERMEMBER “vtkCommonCore-8.0.lib” | findstr /C:”vtkDebugLeaksManager@@QEAA@XZ”

     

    注意として、findstrに渡すシンボル名は大抵の場合、(C++でコンパイルされているなら)C++の命名規則で渡した方が確実のようです。@@とかついたものです。これはリンクエラーに書いてあるものをそのままコピペすればよいという意味です。


    あとはこの内容をbatで適切に変えていけば良いと言うことになります。

    Windowsのbatは(本当に)よくわからないので、解説出来ません。

     

     

     

    vray for blender で Sun(Direct)

     

    Direct Light Parameters (Google翻訳)

    Direct – a simple directional light

    直接 – 単純な指向性のある光

    ということで、Directは太陽光というよりも指向性のライトという扱いです。

    light_direct

     

    各パラメータの変更による結果の変化

    ①Intensity

    とどのつまりはライトの強さです。

    ②Radius

    ライトの径です

    ③Hotspot

    Radius=10の時のhotspotの変化。

    半径内の最も光の強い領域のサイズです

    ④Decay

    別ページで掲載

     

     

    WordPressのファイルの最大アップロードサイズを変更する

    記事に画像などをアップロード出来ないことがあります。Wordpressの管理画面の「メディア」→「新規追加」の「最大アップロードサイズ」を上回るファイルはアップロード出来ません。

    これが初期状態では2M等小さい値になっています。上限を上げる方法です。

    php.iniか.htaccessを変更します。巷ではphp.iniのほうが多いですがそれでは効かない場合があります。やってみて動かなかったら.htaccessを編集しましょう。

    ちなみに私はさくらレンタルサーバーを使っていますがphp.iniが効きませんでした。

     

    次のいずれかを行います。

    php.ini

    wordpress-file-size-phpini

    追加内容:

    memory_limit=50M
    post_max_size=40M
    upload_max_filesize=30M

     

    .htaccess

    wordpress-file-size-htaccess

    追加内容:

    php_value memory_limit 100M
    php_value post_max_size 40M
    php_value upload_max_filesize 30M

     

    functions.php

    wordpress-file-size-functionsphp

    追加内容:

    @ini_set( ‘memory_limit’, ’50M’ );
    @ini_set( ‘post_max_size’, ’40M’);
    @ini_set( ‘upload_max_size’, ’30M’ );

     

    functions.phpの場合、ini_set関数を使います。

    ini_setはphp.iniの設定を変える関数です。

    @はエラーを出力しないためにつけます。

    http://php.net/manual/ja/function.ini-set.php

     

     

    意味と注意

    意味は、

    • memory_limit               …  スクリプトが確保できる最大メモリ
    • post_max_size              …  データに許可される最大サイズ
    • upload_max_filesize   …  アップロードできるファイルの最大サイズ

    で、設定するサイズは以下の関係である必要があります。

    upload_max_filesize < post_max_size < memory_limit

     

    C言語で、ある三次元ベクトルに垂直なベクトルを求める

    C/C++で、ある三次元ベクトルに垂直なベクトルを求めます。

    内積・外積を使うので、それらも定義する必要があります。

     

    三次元ベクトルの外積

    外積を求める式は、このようになります。

      outer3

    //! @brief 三次元ベクトルの外積を求める
    //! @param [out] dvec 求めたベクトル
    //! @param [in] svec1 一つ目の三次元ベクトル
    //! @param [in] svec2 二つ目の三次元ベクトル
    //! @return なし
    void outer(double * const dvec, double const * const svec1, double const * const svec2) {
    
      const double& xa = svec1[0];
      const double& ya = svec1[1];
      const double& za = svec1[2];
      const double& xb = svec2[0];
      const double& yb = svec2[1];
      const double& zb = svec2[2];
    
      dvec[0] = ya * zb - za * yb;
      dvec[1] = za * xb - xa * zb;
      dvec[2] = xa * yb - ya * xb;
    }
    

     


    三次元ベクトルの内積

    内積を求める式は、このようになります。

    inner2

    //! @brief ベクトルの内積を求める
    //! @param [in] vec1 一つ目の三次元ベクトル
    //! @param [in] vec2 二つ目の三次元ベクトル
    //! @return 内積
    double inner(double const * const vec1, double const * const vec2) {
      const double& xa = vec1[0];
      const double& ya = vec1[1];
      const double& za = vec1[2];
      const double& xb = vec2[0];
      const double& yb = vec2[1];
      const double& zb = vec2[2];
    
      return (xa*xb + ya*yb + za*zb);
    }
    

    三次元ベクトルの長さ

    vlen2

    //! @brief ベクトルの長さを求める関数
    //! @param [in] vec 三次元ベクトル
    //! @return 長さ
    double vlen(double const * const vec) {
      const double& x = vec[0];
      const double& y = vec[1];
      const double& z = vec[2];
    
      return sqrt(x * x + y * y + z * z);
    }
    

    二つの三次元ベクトルがなす角度(ラジアン)

    angle

    //! @brief 二つのベクトルの角度をラジアンで求める関数
    //! @param [in] vec1 一つ目の三次元ベクトル
    //! @param [in] vec2 二つ目の三次元ベクトル
    //! @return 二つのベクトルのなす角(ラジアン)
    double vangle(double const * const vec1, double const * const vec2) {
      return acos(inner(vec1, vec2) / (vlen(vec1) * vlen(vec2)));
    }
    

    上記コードでは省いていますが、acosの引数の範囲は-1~1なので、この範囲を超えると定義域エラーとなります。実用する場合は何らかのエラー処理が必要になります。


    ある三次元ベクトルに垂直なベクトルを求める

    //! @brief ある三次元ベクトルに垂直な三次元ベクトルを求める
    //! @param [out] dst3 結果の格納先
    //! @param [in] src3 三次元ベクトル
    void rightvec(double* dst3, double* src3) {
    
      double tmp[3] = { 1,0,0 };
    
      //tmpとsrc3の角度0またはそれに近いなら、別なベクトルを用意
      if (vangle(tmp, src3) < 0.00174533) { //0.00174533rad=1degree
        tmp[0] = 0;
        tmp[1] = 1;
        tmp[2] = 0;
      }
      //外積を求める
      outer(dst3, tmp, src3);
    }
    

    ベクトルa,bの外積は、必ずa,b両方に対して垂直になります。

    従って、あるベクトルuと、何でも良いからuとは違うベクトルvを用意し、その二つの外積wを求めると、必ずu⊥wとなります。計算が終わったらvは捨てて構いません。

    ただし、u≠vでなければなりません。そこで上記プログラムでは、まずv(1,0,0)を用意します。もしuとvの角度が極めて0に近ければ、同じベクトルと考え、vを(0,1,0)に変更した後、外積を求めます

     

     

    以下動作テスト

    #include <Windows.h>
    #include <gl/GL.h>
    #include <gl/freeglut.h>
    #include <math.h>
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"freeglut.lib")
    

     

    void display(void)
    {
      glClear(GL_COLOR_BUFFER_BIT);
    
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
    
      glTranslated(0.0, 0.0, -5.0);
    
      glPushMatrix();
      static double deg = 0;
      deg = deg + 1;
      glRotated(deg, 0, 1, 0);
    
      glColor3d(1, 0, 0);
      //一本目のベクトルを表示
      double src3[3] = { 2,-3,4 };
      glBegin(GL_LINES);
      glVertex3d(0, 0, 0);
      glVertex3dv(src3);
      glEnd();
    
      glColor3d(0, 1, 0);
      double dst3[3];
      rightvec(dst3, src3);
      //二本目のベクトルを表示
      glBegin(GL_LINES);
      glVertex3d(0, 0, 0);
      glVertex3dv(dst3);
      glEnd();
    
    
      glPopMatrix();
    
    
      glFlush();
    }
    void timer(int value) {
      glutPostRedisplay();
      glutTimerFunc(50, timer, 0);
    }
    void init(void)
    {
      glClearColor(0.0, 0.0, 1.0, 1.0);
    }
    void resize(int w, int h)
    {
      glViewport(0, 0, w, h);
    
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
    }
    int main(int argc, char *argv[])
    {
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_RGBA);
      glutCreateWindow(argv[0]);
      glutDisplayFunc(display);
      glutReshapeFunc(resize);
      glutTimerFunc(100, timer, 0);
      init();
      glutMainLoop();
      return 0;
    }
    

     

     

     

    C++のunordered_mapで自作クラスを使う (主にハッシュ値生成について)

    概要

    C++11以降、ハッシュマップ(hash map)の機能が追加されました。

    しかしhash mapの名前の既存ライブラリがたくさんあったので、衝突しないようにunordered_mapという名前にしました。

     

    で、このunorderd_mapは基本型ならそのまま使えるんですが、自作型の場合にはクラスのインスタンスからハッシュ値を作る機能も作ってやる必要があります。

    サンプルコード

    #include <string>
    #include <unordered_map>
    #include <iostream>
    
    ////////////////////////////////////////////////////////////////
    //ハッシュ値を統合する ( 汎用的に使用できる関数 )
    // seed  in:既存のハッシュ値  out:元のseedとvから作成したハッシュ値を統合した値
    // v     新たにハッシュ値を作成する値
    template<typename T>
    void hash_combine(size_t & seed, T const& v) {
      //基本型に関するハッシュ生成は標準ライブラリが提供している
      std::hash<T> primitive_type_hash;
    
      //生成したハッシュを合成する。このコードはboostものを使用する
      seed ^= primitive_type_hash(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
    
    ////////////////////////////////////////////////////////////////
    // 自作データ
    class MyData {
    public:
      std::string m_v_str;
      int m_v_int;
      double m_v_double;
    };
    ////////////////////////////////////////////////////////////////
    // 自作データの比較演算子
    bool operator==(const MyData& v1, const MyData& v2) {
    
      return
        v1.m_v_str == v2.m_v_str &&
        v1.m_v_int == v2.m_v_int &&
        v1.m_v_double == v2.m_v_double;//本当はdoubleを==比較してはいけません
    }
    
    ////////////////////////////////////////////////////////////////
    //自作データのハッシュを作成
    namespace std {
    
      // 標準ライブラリは struct hash<>というデータをハッシュ化する関数オブジェクトのテンプレートを提供している
      // これは最初から基本型に対しては特殊化されているのでそのまま使える(上記hash_combine内で使用)
      // 自作クラスの場合は自分で特殊化し、operator()を定義してやる。
    
      template<>
      struct hash<MyData> {
      public:
        size_t operator()(const MyData& data)const {
    
          //クラスのメンバの値それぞれについてハッシュ生成して、それらを結合して一つのハッシュ値にする
          std::size_t seed = 0;
          hash_combine(seed, data.m_v_str);
          hash_combine(seed, data.m_v_int);
          hash_combine(seed, data.m_v_double);
    
          return seed;
    
        }
      };
    }
    
    ////////////////////////////////////////////////////////////////
    // エントリポイント
    int main()
    {
      std::unordered_map<MyData, int> map;
    
      map[ { "hello"   , 111 , 6.0e3 } ] = 0;
      map[ { "goodbye" , 111 , 6.0e3 } ] = 0;
      map[ { "hello"   , 222 , 6.0e3 } ] = 0;
      map[ { "goodbye" , 222 , 6.0e3 } ] = 0;
      map[ { "hello"   , 222 , 2.0e4 } ] = 0;
      map[ { "goodbye" , 222 , 3.0e4 } ] = 0;
    
      for (int i = 0; i < 3; i++) {
        map[{"hello"  , 111, 6.0e3 }]++;
        map[{"goodbye", 111, 6.0e3 }]++;
      }
    
      using namespace std;
    
      //結果出力
      for (auto& data : map) {
        cout 
          << "( " 
          << data.first.m_v_str << " , " 
          << data.first.m_v_int << " , " 
          << data.first.m_v_double << " ) = " 
          << data.second 
          << std::endl;
      }
    
      int i;
      cin >> i;
    
      return 0;
    }
    

     

    実行結果

    ( goodbye , 222 , 6000 ) = 0
    ( hello , 111 , 6000 ) = 3
    ( goodbye , 111 , 6000 ) = 3
    ( hello , 222 , 6000 ) = 0
    ( hello , 222 , 20000 ) = 0
    ( goodbye , 222 , 30000 ) = 0

     

    要点

    unorderd_mapのキーとなる値が

    • 基本型やstd::string型の時   …   何も考えずそのまま使える
    • 基本型でないとき … 基本型のハッシュ値をhash_combineで結合し一つのハッシュ値としてから使用する

     

    std::hash

    std::hash – cppreference.com

    std::hashはハッシュを生成するクラス(コード上はstruct)のテンプレートです。

    これはintやfloat等の基本型や、std::stringやstd::shared_ptr型等の(標準)ライブラリ型に対して特殊化がされており、それらの型のハッシュ値を作成できます。

     

    hash_combine

    boost Reference l- 1.55.0 Header <boost/functional/hash.hpp>

    これはboostにあった関数です。この関数は、与えられたハッシュ値と、与えられたデータから作成した別のハッシュ値の二つを統合し、一つのハッシュ値を作成します。boostではハッシュ生成にboost::hash_valueという関数が使われています。自前実装するときはstd::hashで作成します。

     

     

     

    Blender bpy でvertexとfaceとedgeを追加

    vertexを定義してfaceを追加

    import bpy
    
    
    #頂点定義
    verts = []
    verts.append( [0.2,1.5,1.5] )
    verts.append( [1.5,1.5,1.5] )
    verts.append( [1.5,0.2,0.2] )
    
    
    #面を、それを構成する頂点番号で定義
    faces =[]
    faces.append( [0,1,2] )
    
    
    #頂点と頂点番号からメッシュを作成
    mymesh = bpy.data.meshes.new("mymesh")
    mymesh.from_pydata(verts,[],faces) #作成部分
    mymesh.update()
    
    
    #オブジェクトを作成し、メッシュを登録
    obj = bpy.data.objects.new("My_Object", mymesh)
    
    
    #オブジェクトのマテリアルを作成
    mat = bpy.data.materials.new("Mat1")
    mat.diffuse_color = (0.3,0.7,0.5)
    obj.active_material = mat
    
    
    #オブジェクトを登録
    scene = bpy.context.scene
    scene.objects.link(obj)
    

     

    makeface

    #作成部分を以下のように変更すると、頂点の登録のみになります。

    mymesh.from_pydata(verts,[],[])
    

     

    エッジ用の頂点リストを作成したうえで、#作成部分を以下のように変更すると、エッジの登録のみになります。

    edges = []
    edges.append( [0,2] ) # エッジをなす二点の頂点番号
    
    mymesh = bpy.data.meshes.new("mymesh")
    mymesh.from_pydata(verts,edges,[])
    mymesh.update()
    

     

     

     

     

    WordPressのカスタムフィールド追加(後編 データの保存)

    6.コード

    <?php
    ///////////////////////////////////////////////////////////////
    //カスタムフィールドの入力欄の中のデータをデータベースへ保存する
    function hook_func_for_save_customfield( $post_id )
    {
      $areaname = "field_1";
      $key = "_key_for_field_1";
      
      ///// 正しい手段で送信されたデータであることを確認 ////
      //① nonceがセットされていなければ不正
      if ( ! isset( $_POST[ 'nonce_for_field_1' ] ) )  
        return $post_id;
      
      
      //② nonceがセットされていても、自分で作成した値でないなら不正
      if ( ! wp_verify_nonce( $_POST['nonce_for_field_1'] , 'send_field1' )) 
        return $post_id;
      
      if ( ! current_user_can( 'edit_post', $post_id ) ) // ③ 書き込み権限がなければ不正
        return $post_id;
        
      ///// カスタムフィールドの値を更新 ///
      
      $data = $_POST[$areaname];
      
      if(get_post_meta($post_id, $key) == ""){
        //新しいデータならデータを作成
        add_post_meta($post_id, $key, $data, true);
      }
      elseif($data != get_post_meta($post_id, $key, true)){
        //既存にあるデータで内容が異なるなら更新
        update_post_meta($post_id, $key, $data);
      }elseif($data == ""){
        //入力内容が空ならデータの削除
        delete_post_meta($post_id, $key, get_post_meta($post_id, $key, true));
      }
      
      return $post_id;
    }
               
    add_action( 'save_post', 'hook_func_for_save_customfield' );
    ?>
    

    7.動作

    1. save_postアクションフックにより、更新ボタンが押されたときにhook_func_for_save_customfield関数が実行されます。
    2. hook_func_for_save_customfield関数では、
      ①nonceがPOSTされ、
      ②かつその内容が発行した物と一致し、
      ③さらに書き込み権限があるときにのみ、次の処理を行います。
    3. 送信された値を元に、カスタムフィールドの値を、
      ・まだ値がなければ作成 … add_post_meta関数で新規作成
      ・値はあるが内容が異なる … update_post_metaで更新
      ・入力内容が空 … delete_post_metaでデータから削除
      を行います。

     


    save_postアクションフック

    save_post は投稿や固定ページが作成または更新されたとき実行されるアクションです。インポート、投稿や固定ページの編集画面、XMLRPC、メールによる投稿などがきっかけになります。投稿データは投稿の編集方法に応じて $_POST, $_GET またはグローバルの $post_data に保存されます。例えばクイック編集は $_POST を使います。

    —  プラグイン API/アクションフック一覧/save post

    8.正しい点順で送信されたデータであることを確認

    isset( $_POST[ ‘nonce_for_field_1’ ]

    これはWordpressではなくPHPの世界の話です。

    <input type="hidden" id="nonce_for_field_1" name="nonce_for_field_1" value="81b29b57b2" />
    

    というフィールドをPOSTした場合、PHP側では

    isset( $_POST[ ‘nonce_for_field_1’ ]

    として受け取ります。issetは’nonce_for_field_1’という変数が送信されてきたかを確認します。nonceが正しいかを調べる前に、そもそも送られてきているかを調べるわけです。

    変数がセットされており、それが NULL でないことを調べます。

    PHP マニュアル

     

    wp_verify_nonce関数

    wp_nonce_fieldあるいはwp_create_nonceで生成したnonceと、送られてきたnonceが等しいかを検証する関数です。

    nonce が正しいもので有効期限が切れていないことを、指定されたアクションとの関係も含めて確かめます。

    wp_verify_nonce(
        $nonce, //送られてきたnonce
        $action //生成時に指定したアクション
    );

    似た関数にcheck_admin_refereがありますが、現在は非推奨です。

    バージョン 2.0.1 以降、リファラーがチェックされるのは $action 引数を省略(またはデフォルトの -1 をセット)したときだけですが、これは nonce を使わない後方互換性のためです。

    関数リファレンス/check admin referer

    つまりリファラーをチェックするときはnonceがチェックされず、nonceがチェックされるときはリファラーがチェックされない・・・ということでしょうか

     


    まとめると、wp_verify_noceとwp_nonce_fieldは、以下のように対応しています。

     

    <?php
    //送信時
    wp_nonce_field( 'send_field1' , 'nonce_for_field_1' );
    ?>
    
    

    <?php
    //受信時 
    wp_verify_nonce( $_POST['nonce_for_field_1'] , 'send_field1' )
    ?>
    

     

    current_user_can関数

    ユーザーが権限を所有しているかどうかを調べます。

    ページの編集の権利を持っているかどうかを調べるときは、’edit_pages’を指定します。

     

    権限の一覧はこちらが詳しいです:

    WordPress私的マニュアル current_user_can

    9.カスタムフィールドの値を更新

    get_post_meta関数で該当する価を取得します。get_post_meta関数の第三引数がfalseまたは省略した場合、カスタムフィールドの配列が返ります。trueを指定した場合は、配列の内容が全て一つの文字列となって返ります。

    その結果に応じて、次の各関数を呼び出し追加・削除・更新を行います。


    add_post_meta ($post_id, $key, $data, true);

    add_post_meta() は、指定した投稿や固定ページへカスタムフィールド(「メタデータ」とも呼ばれます)を追加します。どんな投稿タイプの投稿でも構いません。ひとつのカスタムフィールドは、実際にはキーと値の組です。

    関数リファレンス/add post meta

    update_post_meta($post_id, $key, $data);

    update_post_meta() は、指定した投稿に存在するカスタムフィールドの値を更新します。add_post_meta() の代わりとしても使うことができます。この関数はまず、$post_id で ID を指定した投稿に $meta_key を持つカスタムフィールドが存在することを確認します。もし存在しなければ代わりに add_post_meta( $post_id, $meta_key, $meta_value ) を実行し、その結果を返します。

    関数リファレンス/update post meta

     

    delete_post_meta($post_id, $key, get_post_meta($post_id, $key, true));

    この関数は、投稿から指定したキー(もしくはキーと値)を持つカスタムフィールドをすべて削除します。update_post_meta()get_post_meta()add_post_meta() も見てください。

    関数リファレンス/delete post meta

     

     

     

    WordPressのカスタムフィールド追加(前編 メタボックス表示)

    1.全貌

    自分でカスタムフィールドを作成する場合、大きく分けて

    • メタボックスを表示するコードの記述
    • 値の読み込み/書き込みするコードの記述

    の二つが必要になります。

    まず、メタボックスを表示します。functions.phpに以下を記述します。

     

    <?php
    ////////////////////////////////////////////////////////////////////
    //カスタムフィールドの見た目(入力欄等)を追加する
    function hook_func_for_metabox(){
      // ① メタボックスの特性を定義する
      add_meta_box( 
        'metabox_div_id',//メタボックスのdivに指定されるID
        'メタボックス1', //タイトル
        'html_for_metabox_1_func', //表示用のHTMLを出力するphp関数(下で定義)
        'post', //どのタイプの記事入力画面で表示するか
        'normal',
        'high'
      );
    }
    // ② メタボックスの中身を実装する
    function html_for_metabox_1_func($post){
      $areaname = "field_1";
      $key = "_key_for_field_1";
      
        echo '<textarea name="' . $areaname . '" rows="8" cols="60">' . get_post_meta($post->ID,$key,true) . '</textarea>';
      
      // ③ nonceを作成し、hiddenフィールドとして書き込む
      wp_nonce_field( 'send_field1' , 'nonce_for_field_1' );
    }
    // ④ カスタムフィールド用のメタボックスを追加する
    add_action('admin_menu', 'hook_func_for_metabox');
    ?>
    

     

    動作としては、

    1.admin_menuアクションフックにより、管理画面が表示されたときにhook_func_for_metaboxが実行されます。

    2.hook_func_for_metaboxの中で、メタボックスを追加するadd_meta_box関数が呼び出されます。そしてこの関数から、メタボックスの中身を描画するhtml_for_metabox_1_func関数が呼び出されます。

    3.html_for_metabox_1_func関数内で、<textarea></textare>タグをechoし、入力欄を表示します。

    これにより、投稿画面に「メタボックス1」というタイトルの、テキスト入力フィールドを一つ持つ領域(通称メタボックス)が作成されます。

    customfield1_metabox1

     

    2.admin_menuアクションフック

    admin_menuアクションフックは、

    管理画面メニューの基本構造が配置された後に実行する。

    プラグイン API/アクションフック一覧

    とのことです。

    ちなみに、

    admin_menu

    という説明もあります。。。
    いずれにせよ、
    add_action(‘admin_menu’, ‘hook_func_for_metabox’);

    この一行により、管理画面メニューが配置された後に、hook_func_for_metaboxが実行されるようになります。

    ちなみに、add_meta_boxesアクションフックというのもあり、

    add_action(‘add_meta_boxes’, ‘hook_func_for_metabox’);

    こちらでもメタボックスを追加出来ます。この場合、下記add_meta_boxの$screenが’dashboard’など、引数によってはメタボックスが追加出来なくなります。

     

    3.add_meta_boxによるメタボックスの定義

    add_meta_boxはメタボックスを追加する関数です。

    関数リファレンス/add meta box

     

    引数名 今回の例 意味
    $id metabox_div_id

    例えばこのように出力されます:

    <div id="metabox_div_id">
    ...
    </div>
    $title メタボックス1

    タイトルです

    customfield1_metabox1

    $callback html_for_metabox_1_func このメタボックスの中身を表示するための関数を指定します(後述)
    $screen post
    • ‘post’
      投稿ページ編集画面
    • ‘page’
      固定ページ編集画面
    • ‘dashboard’
      ダッシュボード
      customfield1_metabox2_dashboard
    • ‘link’
      ※不明。廃止されたリンク集機能のことか?
    • ‘attachment’
      「メディアを編集」ページ
      メディアを追加し、リンク先を「添付ファイルのページ」に設定したときメディアをクリックして行く添付ファイルページから「メディアを編集」をクリックして表示されるページ
      customfield1_metabox3_attachment
    • ‘custom_post_type’
      カスタム投稿タイプのslugを指定するという意味
    • ‘comment’
      customfield1_metabox5_comment

     

    $context normal

    メタボックスの表示位置を指定します。

    • normal
      customfield1_metabox7_normal
    • advanced
      customfield1_metabox8_advanced
    • side
      customfield1_metabox6_side
    $priority high (※)
    $callback_args    

     

    (※) 表示順と思われます。

    <?php
    function hook_func_for_metabox(){
        //メタボックスの特性を定義する
      add_meta_box( 
        'metabox_div_id',
        'カスタムフィールド1',
        'html_for_field1_func',
        'post',
        'advanced',
        'low'
      );
      add_meta_box( 
        'metabox_div_id_dummy',
        'テストダミーボックス2',
        'html_for_field1_func',
        'post',
        'advanced',
        'high'
      );
      add_meta_box( 
        'metabox_div_id_dummy2',
        'てすとのぼっくす3',
        'html_for_field1_func',
        'post',
        'advanced',
        'high'
      );
    }
    ?>
    
    customfield1_metabox9_lhh

    <?php
    function hook_func_for_metabox(){
        //メタボックスの特性を定義する
      add_meta_box( 
        'metabox_div_id',
        'カスタムフィールド1',
        'html_for_field1_func',
        'post',
        'advanced',
        'high'
      );
      add_meta_box( 
        'metabox_div_id_dummy',
        'テストダミーボックス2',
        'html_for_field1_func',
        'post',
        'advanced',
        'low'
      );
      add_meta_box( 
        'metabox_div_id_dummy2',
        'てすとのぼっくす3',
        'html_for_field1_func',
        'post',
        'advanced',
        'high'
      );
    }
    ?>
    
     customfield1_metabox9_hlh

     

    4.メタボックスの中身の描画

    html_for_metabox_1_funcの中ではHTMLをechoしているだけですが、重要な点がいくつかあります。

    <?php
    //メタボックスの中身を実装する
    function html_for_field1_func($post){
      $areaname = "field_1";
      $key = "_key_for_field_1";
      
      echo '<textarea name="' . $areaname . '" rows="3" cols="40">' . get_post_meta($post->ID,$key,true) . '</textarea>';
      
      //nonceを作成し、hiddenフィールドとして書き込む
      wp_nonce_field( 'send_field1' , 'nonce_for_field_1' );
    }
    ?>
    

     

    最も重要なのは_key_for_field_1という値で、これがいわゆる、カスタムフィールドの値が保存されている変数名です。

    html_for_field1_funcでは<textarea>…</textarea>を表示しますが、その際に既に値が設定されていた場合はその値を表示したいので、get_post_meta関数で、現在のpostの_key_for_field_1の項目を取得して表示しています。

    生成されるHTMLの例:

    <textarea name="field_1" rows="3" cols="40"> この記事のカスタムフィールドの内容 </textarea>
    

     

    注意として、_key_for_field_1のように、キー名は_ (アンダースコア)から始めた方が格好良いです。必須ではないですが、_から始まるキー名でないと、自分で追加したメタボックスの中だけでなく、投稿編集ページに最初からある「カスタムフィールド」の領域にもこのキーのカスタムフィールドの編集欄が出来てしまいます。害はないですが同じ物が二つあるのは気持ちが悪いので避けた方が良いでしょう。

    customfield1_metabox10_double

     

    参考  Codex 関数リファレンス/add post meta 見えない カスタムフィールドを作る


    最後にwp_noce_fieldとwp_create_nonceですが、これらはセキュリティ的に必要なのでカスタムフィールドの書き込みと読み出しには直接関係はありません。従って省略可能ですが、普通セキュリティ対策は必須なので書きます

    5.wp_nonce_field

    nonce(ノンス)は、ある種の誤使用や悪意のある操作から URL やフォームを守るための「一度だけ使われる数値」です。

    https://wpdocs.osdn.jp/WordPress_Nonce

     

    私はセキュリティの専門家ではないのですが、もの凄くざっくりとした説明をすると以下のようになります。

    成功した場合。

    WordPress自分が発行したnonceと、「送信」ボタンが押されたときのnonceを比較し、その二つが等しければ

    「この通信は、確かに自分が作成した送信フォームから送られた」

    と結論します。

    nonce1

    失敗する場合。

    何らかの理由により偽フォームに飛んでしまったような場合、そのフォームは自分のWordpressが作成したページではないので、発行したnonceも記載されていません。このフォームから送信した場合、送信されてくるnonce(あれば)と先ほど自分が発行したnonceが異なるので、

    「この通信は、偽フォームから送られた」

    と考えます。

    nonce2

     

    wp_nonce_fieldは、内部で wp_create_nonce 関数を呼び出しています。

     

    wp_create_nonce

    nonce を生成して返します。nonce は現在の時刻$action 引数現在のユーザー ID に基づいて生成されます。

    関数リファレンス/wp create nonce

     

    つまり時間やユーザーや引数を元に、81b29b57b2のような文字列を作成します。そしてHTMLのhiddenフィールドとして出力します。

    表記

    wp_nonce_field( ‘send_field1’ , ‘nonce_for_field_1‘ );

     

    出力

    <input type="hidden" id="nonce_for_field_1" name="nonce_for_field_1" value="81b29b57b2" />
    

     

    ここで、HTMLのformからPOSTでSubmitした場合、PHP側では

    <?php
    if(isset($_POST[‘nonce_for_field_1’])){
      $nonce = $_POST[‘nonce_for_field_1’];
      echo $comment; //この結果は81b29b57b2
    }
    ?>
    

    と、$_POSTを使って受け取ることができます。

     

    これで表示が終わったので、次回にはこのカスタムフィールドの値が「投稿」ボタンや「下書き」ボタンが押されたときにデータベースに保存するコードを記述します。