home processing download documents tutorial python tutorial gallery source about
 チュートリアル (トピック一覧へ戻る)

曲面上の線

     曲面上の格子点

ファイルからNURBS曲面を読み込み、グリッドに沿って点を配置します。 ファイルの読み込みの手順に関しては、ファイル入出力のチュートリアルを参照してください。 以下のコードで使用されているファイルは以下のリンクから参照してください。 以下のスケッチにおいて、シーン内の全てのNURBS曲面を参照するために 拡張For文("for (ISurface surf: surfs) {...}") が用いられています。 拡張For文は指定の配列から全ての要素を順に参照します。 拡張For文は、カウンター変数が役割を持たず、配列の全ての要素が参照される際に用いられます。

以下のコードでは、ijを用いた2次元Forループによって、 格子上の点が曲面上にサンプルされます。 サンプルされる数はunum, vnumで指定されます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;

  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt = surf.pt( i*uinc, j*vinc );
      new IPoint(pt).clr( i*uinc, j*vinc, 0);
    }
  }

}

上記スケッチで用いられているsurf.pt( i*uinc, j*vinc )は曲面上の点をサンプルする基本的な方法です。

生成したまたは存在している幾何学オブジェクトを消去するには、そのオブジェクトのdel()メソッドを用います。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt = surf.pt( i*uinc, j*vinc );
      new IPoint(pt).clr( i*uinc, j*vinc, 0);
    }
  }
  surf.del();

}


     曲面上の格子線

以下のスケッチは曲面のU方向に沿って線を生成します。 For文の条件式がi < unumでありi <= unumでないことに注意してください。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      IVec pt2 = surf.pt((i+1)*uinc, j*vinc);
      new ICurve(pt1, pt2).clr(0);
    }
  }
  surf.del();
}

同様に、ijの操作を入れ替えて、曲線を曲面のV方向に沿って生成することも可能です。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i <= unum; i++){
    for(int j=0; j < vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      IVec pt2 = surf.pt(i*uinc, (j+1)*vinc);
      new ICurve(pt1, pt2).clr(1.0);
    }
  }
  surf.del();
}

線を曲面のU方向とV方向の両方に生成することも可能です。 その場合、For文にIf文を加えてijが範囲の外に出ないようにします。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      if(i < unum){
        IVec pt2u = surf.pt((i+1)*uinc, j*vinc);
        new ICurve(pt1, pt2u).clr(0);
      }
      if(j < vnum){
        IVec pt2v = surf.pt(i*uinc, (j+1)*vinc);
        new ICurve(pt1, pt2v).clr(1.0);
      }
    }
  }
  surf.del();
}

上記のスケッチにおけるカウンター変数 ij、点間距離uincvincの関係を図で確認します。

For文がカウンター変数 ijの値を増加させながら反復する際、それぞれの点が生成される座標も移動していきます。

ij にある値を加えたり引いたりして座標の計算を変更することで、 上記の変数に相対的な距離・方向をもつ座標を生成できます。


     曲面上の斜線

上記のスケッチにおいて斜線を引くには、ij に基づく座標を線で繋ぎます。 上記の図のように、それらの点はグリッドの対角の点に位置するためです。 ここではpt( i*uinc, j*vinc )pt( (i+1)*uinc, (j+1)*vinc )の二点を選びます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j < vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      IVec pt2 = surf.pt((i+1)*uinc, (j+1)*vinc);
      new ICurve(pt1, pt2).clr(0,1.,1.);
    }
  }
  surf.del();
}

斜線の向きは上記の繋ぐ点の組み合わせによって変えることができます。 ここでは pt( i*uinc, (j+1)*vinc )pt( (i+1)*uinc, j*vinc ) の二点を選びます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j < vnum; j++){
      IVec pt1 = surf.pt(i*uinc, (j+1)*vinc);
      IVec pt2 = surf.pt((i+1)*uinc, j*vinc);
      new ICurve(pt1, pt2).clr(0,0,1.);
    }
  }
  surf.del();
}

以下のスケッチは斜線と格子線を両方曲面上に表示します。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      if(i < unum){
        IVec pt2u = surf.pt((i+1)*uinc, j*vinc);
        new ICurve(pt1, pt2u).clr(0);
      }
      if(j < vnum){
        IVec pt2v = surf.pt(i*uinc, (j+1)*vinc);
        new ICurve(pt1, pt2v).clr(1.0);
      }
      if(i < unum && j < vnum){
        IVec pt2uv = surf.pt((i+1)*uinc, (j+1)*vinc);
        new ICurve(pt1, pt2uv).clr(0,1.,1.);
      }
    }
  }
  surf.del();
}


     曲面上の斜め格子線

以下のコードにおいて、ij の値の和が偶数であるとき if( (i+j)%2 == 0 )のみ、 あるいは奇数であるときのみ線を生成することで、斜め格子線が表現されます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j <= vnum; j++){
      if( (i+j)%2 == 0 ){
        IVec pt1 = surf.pt(i*uinc, j*vinc);
        if( j > 0){
          IVec pt2 = surf.pt((i+1)*uinc, (j-1)*vinc);
          new ICurve(pt1, pt2).clr(0);
        }
        if( j < vnum ){
          IVec pt3 = surf.pt((i+1)*uinc, (j+1)*vinc);
          new ICurve(pt1, pt3).clr(0,0,1.);
        }
      }
    }
  }
  surf.del();
}

ij の値の和が偶数であるとき生成される点の座標を図で確認します。

このとき 点pt1(座標 i*uinc, j*vinc)、 点pt2(座標 (i+1)*uinc, (j-1)*vinc)、 点pt3(座標 (i+1)*uinc, (j+1)*vinc)、 は「く」の字に繋がれています。

この「く」の字の線が反復されることで、斜め格子線が形成されます。


ij の値の和が奇数であるとき if( (i+j)%2 == 1 のみ線を生成するようスケッチを書き換えることで、格子線が反転されます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j <= vnum; j++){
      if( (i+j)%2 == 1 ){
        IVec pt1 = surf.pt(i*uinc, j*vinc);
        if( j > 0){
          IVec pt2 = surf.pt((i+1)*uinc, (j-1)*vinc);
          new ICurve(pt1, pt2).clr(0);
        }
        if( j < vnum ){
          IVec pt3 = surf.pt((i+1)*uinc, (j+1)*vinc);
          new ICurve(pt1, pt3).clr(0,0,1.);
        }
      }
    }
  }
  surf.del();
}


     可変間隔の斜め格子線

このコードでは、反復ごとにvnumの値を1ずつ増加させていくことで、格子線のV軸上の幅が徐々に縮小されます。 この場合、次回の反復において生成される点の位置が先行して必要になります。そのため、vnum + 1で次回の vnumの値を取得し、それを用いて次回のvincvinc2として取得し、更にそれを用いて次回の点の位置を取得しています。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 4;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    vnum++;
    vinc = 1.0/vnum;
    for(int j=0; j <= vnum; j++){
      double vinc2 = 1.0/(vnum+1);
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      IVec pt2 = surf.pt((i+1)*uinc, j*vinc2);
      IVec pt3 = surf.pt((i+1)*uinc, (j+1)*vinc2);
      new ICurve(pt1, pt2).clr(1.,0,0);
      new ICurve(pt1, pt3).clr(.5,0,1);
    }
  }
  surf.del();
}


     曲面上の六角格子線

斜め格子線のコードをを修正することで、六角形の格子を形成することができます。 以下のスケッチにおいて、新しいdouble型変数 r は斜め線の角度を指定します。 r=0.0 の際、斜め格子と同様の形状が形成されます。 0 < r < 0.5の際、六角格子線が形成されます。 0.5 < rの際、リボン状の格子線が形成されます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 20, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  double r = 0.3;
  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      if( (i+j)%2 == 0 ){
        IVec pt1 = surf.pt(i*uinc, (j-r)*vinc);
        IVec pt2 = surf.pt(i*uinc, (j+r)*vinc);
        new ICurve(pt1, pt2).clr(1.,0,1.);
        if( i < unum ){
          if( j > 0){
            IVec pt3 = surf.pt((i+1)*uinc, (j-1+r)*vinc);
            new ICurve(pt1, pt3).clr(0);
          }
          if( j < vnum ){
            IVec pt4 = surf.pt((i+1)*uinc, (j+1-r)*vinc);
            new ICurve(pt2, pt4).clr(0,0,1.);
          }
        }
      }
    }
  }
  surf.del();
}


     曲面上の六角格子線その2

二種類の直交する線と斜め線によって、異なる種類の六角格子線を形成することができます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 12, vnum = 12;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      if( (i+j)%3 == 0 ){
        if( i < unum ){
          IVec pt2 = surf.pt((i+1)*uinc, j*vinc);
          new ICurve(pt1, pt2).clr(0); // orthogonal line
        }
        if( j < vnum ){
          IVec pt3 = surf.pt(i*uinc, (j+1)*vinc);
          new ICurve(pt1, pt3).clr(0.5); // orthogonal line
        }
      }
      if( (i+j)%3 == 1 ){
        if( i < unum && j < vnum ){
          IVec pt4 = surf.pt((i+1)*uinc, (j+1)*vinc);
          new ICurve(pt1, pt4).clr(1.,0,0); // diagonal line
        }
      }
    }
  }
  surf.del();
}


     線分からの円柱の生成

ICylinderクラスを用いることで、 上記スケッチの格子線を円柱として形成することができます。 ICylinderクラスは開始点、終了点、半径を引数に生成されます。 以下のスケッチでは上記スケッチの線を円柱として形成します。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 8, vnum = 8;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  for(int i=0; i < unum; i++){
    for(int j=0; j <= vnum; j++){
      if( (i+j)%2 == 0 ){
        IVec pt1 = surf.pt(i*uinc, j*vinc);
        if( j > 0){
          IVec pt2 = surf.pt((i+1)*uinc, (j-1)*vinc);
          new ICylinder(pt1, pt2, 0.5);
        }
        if( j < vnum ){
          IVec pt3 = surf.pt((i+1)*uinc, (j+1)*vinc);
          new ICylinder(pt1, pt3, 0.5);
        }
      }
    }
  }
  surf.del();
}


     線分からの垂直面の生成

double型変数depthによって、入力曲面からオフセットされた点をサンプルし、 ISurfaceクラスを用いることで、 垂直に押し出した面として生成することができます。

import processing.opengl.*;
import igeo.*;

size( 480, 360, IG.GL );

//IG.open("surface1.3dm");  //input geometry from 3dm file
IG.open("surface1.obj"); ///input geometry from OBJ file

ISurface[] surfs = IG.surfaces();

for( ISurface surf : surfs ){

  int unum = 12, vnum = 12;
  double uinc = 1.0/unum, vinc = 1.0/vnum;
  double depth = 3.0;

  for(int i=0; i <= unum; i++){
    for(int j=0; j <= vnum; j++){
      IVec pt1 = surf.pt(i*uinc, j*vinc);
      IVec pt1d = surf.pt(i*uinc, j*vinc, depth);
      if( (i+j)%3 == 0 ){
        if( i < unum ){
          IVec pt2 = surf.pt((i+1)*uinc, j*vinc);
          IVec pt2d = surf.pt((i+1)*uinc, j*vinc, depth);
          new ISurface(pt1, pt2, pt2d, pt1d).clr(0);
        }
        if( j < vnum ){
          IVec pt3 = surf.pt(i*uinc, (j+1)*vinc);
          IVec pt3d = surf.pt(i*uinc, (j+1)*vinc, depth);
          new ISurface(pt1, pt3, pt3d, pt1d).clr(0.5);
        }
      }
      if( (i+j)%3 == 1 ){
        if( i < unum && j < vnum ){
          IVec pt4 = surf.pt((i+1)*uinc, (j+1)*vinc);
          IVec pt4d = surf.pt((i+1)*uinc, (j+1)*vinc, depth);
          new ISurface(pt1, pt4, pt4d, pt1d).clr(1.,0,0);
        }
      }
    }
  }
  surf.del();
}


(トピック一覧へ戻る)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT