sub_set01へ戻る

名称 ・・・・・・・

x,y,zいずれかの座標値からtパラメータを計算

ルーチン名 ・・・・・・・

XyzToT

スクリプトNo ・・・・・・・ sub_set01- 004
file名 ・・・・・・・ ScriptSet01.lzh
sub_set01のページからセットごとダウンロードしてください。
概略 ・・・・・・・

xyzいずれか一つの座標値を指定してできる面と曲線との交点のtパラメータを計算する。

使用前提 ・・・・・・・

線形状(べジェ曲線)を選択して適切な引数を指定してから実行する。
引数に渡す Vec3,PtNo,Dat,direction を前もって用意しておく。

依存関係 ・・・・・・・

GetnVec
kaisa
Formula1D
Formula2D
Cardano

ベジエ制御点P0〜P3の座標値の取得---sub_set01-012
階差の計算(ベジエ制御点Pから階差を計算)---sub_set01-016
1次式の解法---sub_set01-013
2次式の解法(解の公式)---sub_set01-014
3次式の解法(カルダノ方式)---sub_set01-015

引数説明 ・・・・・・・

PtNo:
Vec3:
Dat :
direction :

(in)PtNo番目〜PtNo+1番目のアンカーポイントまで計算される。
(in)線型状の座標データ【3次元配列】が格納されている。
(in)指定した方向の座標値
(in)指定する方向(x:0 , y:1 , z:2)

戻り値説明 ・・・・・・・

ベジェ曲線と交差する交点(解の数は1〜3個)のtパラメータ
t(0)は判定用に使う、t(1)以降がtパラメータ
uboundを使ってtパラメータの数を確認する。

変数説明 ・・・・・・・

XYZ0(2)〜XYZ3(2)
P
a,b,c
tt
tt2()
nd
nd2

階差
ベジエ制御点P0〜P3の座標値
カルダノ法用パラメータ(3次式の項の係数)
tパラメータ(データは複数(1〜3)の場合もある) 配列かbool値
範囲内のtパラメータ
返されるtパラメータの数
範囲内の解(tパラメータ)の数

注意点 ・・・・・・・

戻り値の扱いに注意が必要。
tt(0)は判定用に使用されるので、戻り値を受け取るときにIsArrayがtrueならばデータが存在するのでuboundを使って配列数を調べ処理する。 falseならば処理を中断するなどの切り分けが必要。

 
スクリプト
'-----------XYZのうち一つの値を渡し、ベジェ曲線と交差する交点のtパラメータを計算する(誤差あり)
Function XyzToT(PtNo,Vec3,Dat,direction)
'戻値---tパラメータ
'引数---
' PtNo:(in)PtNo番目のアンカーポイント〜PtNo+1番目のアンカーポイントまでが計算の対象となる。
' Vec3:(in)対象となる線形状の座標データ(3次元配列)
' Dat :(in)次のjで指定した座標軸方向の数値(XYZのうち一つの値)
' direction:(in)指定する座標軸方向(0:x , 1:y , 2:z)
  Dim XYZ0(2),XYZ1(2),XYZ2(2),XYZ3(2)  '階差
  Dim P                  'ベジエ制御点P0〜P3の座標値
  Dim a,b,c              'カルダノ法用パラメータ(3次式の項の係数)
  Dim tt                 'tパラメータ(データは複数(1〜3)の場合もある)
  Dim tt2()              '範囲内のtパラメータ
  Dim nd                 '返されるtパラメータの数
  Dim nd2                '範囲内の解(tパラメータ)の数
  Dim i

  nd2=0
  redim tt2(nd2)

  P=GetnVec(Vec3,PtNo)  'ベジエ制御点P0〜P3の座標値を取り出す

  Call kaisa(P,XYZ0,XYZ1,XYZ2,XYZ3)  '1〜3段階差を求る

  if XYZ3(direction)<>0 then           '各次元の係数で処理を振り分ける。
    a=3*XYZ2(direction)/XYZ3(direction)
    b=3*XYZ1(direction)/XYZ3(direction)
    c=(XYZ0(direction)-Dat)/XYZ3(direction)
    tt=Cardano(a,b,c)          '3次式の解を求める
  elseif XYZ2(direction)<>0 then
   a=3*XYZ2(direction)
    b=3*XYZ1(direction)
    c=(XYZ0(direction)-Dat)
    tt=Formula2D(a,b,c)        '2次式の解を求める
  elseif XYZ1(direction)<>0 then
    a=3*XYZ1(direction)
    b=(XYZ0(direction)-Dat)
    tt=Formula1D(a,b)          '1次式の解を求める
  else
    XShade.message"この方向には変化量がありません"
    tt2(0)=false
    exit function
  end if

  nd=Ubound(tt,1)
  if tt(0)=false then
    XShade.message"交差ポイントはありません"
    tt2(0)=false
    exit function
  end if

  '範囲(0〜1)外の解を排除
  tt2(0)=true
  for i=1 to nd
    if tt(i)>=0 and tt(i)<=1 then 
      nd2=nd2+1
      redim preserve tt2(nd2)
      tt2(nd2)=tt(i)
    end if
  next
  if nd2=0 then         '解が0の場合はfalseを返す。
    tt2(0)=false
    exit function
  end if

  XyzToT=tt2
end Function
使用例
  Dim NA,Vec3,PtNo
  Dim DatXYZ,Direction
  
  'アンカーポイントの数を取得
  NA=XShade.NumberOfAnchorPoints()
  'アンカーポイントの座標値を取得
  Vec3=GetVec3(NA)
  
'-------------------xyzいずれかを指定しベジェ曲線上でどのtを取るか計算
'    (アンカーポイント番号PtNo〜PtNo+1の部分が対象)
  PtNo=0: DatXYZ=300: Direction=0
  tt=XyzToT(PtNo,Vec3,DatXYZ,Direction)
  if tt(0)<>false then                                 'tt(0)には処理結果(true,false)が格納されている。
    nd=ubound(tt,1)
    XShade.Message"解の数は"&nd&"個です。"
    for i=1 to nd
      XShade.Message"解("&i&")は"&round(tt(i)*100000)/100000
    next
  end if

sub_set01へ戻る