« ここを見た? | トップページ | 「C4D XPresso」で検索してここに来た方、ここを見た? »

XPressoでZを無視(2D:XY)した「直線の交点」のC.O.F.F.E.E.ノード

直線の交点を求めてみよう。
とは、言っても3D空間で直線が交わる事はかなり少ない。
3D空間で2直線が交わる事ができるのは、2直線が同一平面上に在る場合のみ。
今回は、Z値を無視したXY平面に平行投影した交点を求めてみよう。

簡単に言えば、C4Dでのビューの前面もしくは後面の見た目の交点と言う事です。

この場合だと、同一平面でなくても、直線が平行でなければ交点ができます。

中学数学で学習した y = ax + b の連立方程式を解けばいいのだ。
で、どうするだ?

C4Dには無限の直線オブジェクトはないので、2点を通過する直線と言うことにしよう。
この直線を2個(直線A、直線B)使って、交点を取得しヌルオブジェクトを配置します。
ビューを「前面」にしてください。

その前に、画面上分かりやすく、操作性を良くするために、下準備をします。
必要のない方は読み飛ばしてください。

シーンにテキストスプラインを4個追加します。適当に配置してください。
名前は次のように変更し、テキストスプラインのテキストも名前と同じものにしてください。

Crosspoint_01 Crosspoint_02

説明しなくても分かるとは思いますが、
As : 直線Aの開始点
Ae : 直線Aの終了点
Bs : 直線Bの開始点
Be : 直線Bの終了点
開始点/終了点と言うとなんだか線分のように思うかもしれませんが、今回はこの2点を通過する直線です。

更にポイント数が2個の線形スプラインを2個追加してください。
ポイントの位置は適当でいいです。
スプラインの表示色も設定しました。

Crosspoint_03_2Crosspoint_04

では、4個のテキストスプラインを移動すると、スプラインのポイントが追従するようにXPressoを作成します。

XPressoに4個(As/Ae/Bs/Be)のテキストスプラインをドロップし出力端子に「絶対位置」を追加。
新規ノード/XPresso/一般/「ポイント」を4個追加し入力端子に「ポイントの位置」を追加。
2個のスプライン(直線A/直線B)をドロップし出力端子に「オブジェクト」を追加。
下記のように連結します。

Crosspoint_05_2

一目で分かるようにポイント番号に新規ノード/XPresso/一般/「定数」ノードを使ってポイント番号(0/1)を指定しましたが、「ポイント」ノードの属性でポイント番号に直接入力してもかまいません。
「ポイント」ノードのマトリクスモードは「グローバル」であることを確認してください。

これでテキストスプラインを移動すると、スプラインのポイントが追従します。

Crosspoint_06

後は、交点用のヌルオブジェクトを追加して置いてください。
分かりやすくするのに、色と表示を変更してください。

Crosspoint_09

では、交点を求めるXPressoを作成しましょう。

y = ax + b は、覚えているだろうか?
a は、x の増量1.0に対してyの増減量。中学の時には(傾き)と言っていたっけ…
b は、x が0.0の時のyの初期値。

Crosspoint_07

こんなグラフだね。
では直線Aを
y = Aa・x + Ab …分かりづらいだろうか?

直線Bは
y = Ba・x + Bb …まぁいいかぁ。

では直線Aを完成させよう。
テキストスプライン(As/Ae)のグローバル座標を使ってAaを求めよう。
Aa = (Ae.y - As.y) / (Ae.x - As.x)…xの増量でyの増量を割るとx1.0の増量分のyの増量が求められるね。
Ab = y - Aa・x…だから、Ab = As.y - Aa・As.xだね。

直線Bも同じようにすると、
Ba = (Be.y - Bs.y) / (Be.x - Bs.x)
Bb = Bs.y - Ba・Bs.x

交点は…
Aa・x + Ab = Ba・x + Bb
(Aa - Ba)x = Bb - Ab
x = (Bb - Ab)/(Aa - Ba)
と、なるわけだ。
後は、y=Aa・x+Abに代入すると交点のyが求められるわけだ。

これをXPressoのC.O.F.F.E.E.ノードにしてみよう。
入力端子に4個のベクトル(As/Ae/Bs/Be)
出力端子に1個のベクトル(cross)

/*
XYでの交点を求める。
2009.3.5
*/


main()
{
  var Aa , Ab , Ba , Bb , cx , cy;

  Aa = (Ae.y - As.y) / (Ae.x - As.x);
  Ab = As.y - Aa * As.x;

  Ba = (Be.y - Bs.y) / (Be.x - Bs.x);
  Bb = Bs.y - Ba * Bs.x;

  cx = (Bb - Ab)/(Aa - Ba);
  cy = Aa * cx + Ab;
  cross = vector(cx , cy , 0.0);
}

こんなに短いのね…

それでは、このC.O.F.F.E.E.ノードに連結します。
テキストスプライン(As/Ae/Bs/Be)の絶対位置をつなぎ、最後に追加した交点用のヌルオブジェクトの絶対位置をcrossにつなぎます。交点用のヌルオブジェクトを追加し忘れた人はシーンに追加しXPressoにドロップしてください。

Crosspoint_08

Crosspoint_10

テキストスプライン(As/Ae/Bs/Be)を移動してみよう。
交点用のヌルオブジェクトは動作しているね。

でもこれは、大きな穴があるね。
0割が生じてC.O.F.F.E.E.エラーが起こります。

交点がない場合の処理。

直線Aや直線Bが直線でない場合の処理。
AsとAeが同じだったりBsとBeが同じだった場合、交点の計算をしない。

直線Aと直線Bが平行の場合の処理。
AaとBaが同じ場合交点の計算をしない。

直線Aや直線Bが垂直の場合。

直線Aが垂直の場合、Aaを計算しない。
cx = As.x;
cy = Ba * cx + Bb;

直線Bが垂直の場合、Baを計算しない。
cx = Bs.x;
cy = Aa * cx + Ab;

このC.O.F.F.E.E.ノードに交点の存在判定「exist」ブールを出力端子に追加します。

/*
XYでの交点を求める。
2009.3.5
*/


main()
{

  if(Ae == As || Be == Bs){//直線Aや直線Bが直線でない場合
    exist = FALSE;
    return;
  }


  var Aa , Ab , Ba , Bb , cx , cy;


  //a,bの計算
  if(Ae.x != As.x){//直線Aが垂直でない場合
    Aa = (Ae.y - As.y) / (Ae.x - As.x);
    Ab = As.y - Aa * As.x;
  }


  if(Be.x != Bs.x){//直線Bが垂直でない場合
    Ba = (Be.y - Bs.y) / (Be.x - Bs.x);
    Bb = Bs.y - Ba * Bs.x;
  }


  if(Aa == Ba){//直線Aと直線Bが平行の場合
    exist = FALSE;
    return;
  }



  //交点の計算
  if(Ae.x != As.x && Be.x != Bs.x){//直線A、直線Bが共に垂直でない場合
    cx = (Bb - Ab)/(Aa - Ba);
    cy = Aa * cx + Ab;
  }


  if(Ae.x == As.x){//直線Aが垂直の場合
    cx = As.x;
    cy = Ba * cx + Bb;
  }


  if(Be.x == Bs.x){//直線Bが垂直の場合
    cx = Bs.x;
    cy = Aa * cx + Ab;
  }


  cross = vector(cx , cy , 0.0);
  exist = TRUE;
}

交点の存在判定の「exist」を交点用のヌルオブジェクトの入力端子「ON」を追加し、接続します。
「exist」は交点が存在する場合のみTRUEを返します。

Crosspoint_11

これで垂直でも並行でも問題はないだろう…

Crosspoint_12

今回のC4DファイルR9.5は、「cross.ZIP」です。

今回のネタも無意味か…

|

« ここを見た? | トップページ | 「C4D XPresso」で検索してここに来た方、ここを見た? »