バーチカル曲線の描画

平面上の3点のガイドカーブからバーチカル曲線を描画する。ここではXY平面で計算する。

計算の詳細については以下のページへ
バーチカル曲線

//
// ガイドポリラインをバーチカル曲線に変換する
// Run Over: Primitives
//

//
// 直線の交点を求める関数
//
vector CrossPointXY(vector p0; vector p1; vector p2; vector p3)
{
    // 線分が交差していた場合、直線の交点座標を計算する
    float a1 = p0.y - p1.y;
    float b1 = p1.x - p0.x;
    float c1 = (p1.x - p0.x) * p0.y - (p1.y - p0.y) * p0.x;
     
    float a2 = p2.y - p3.y;
    float b2 = p3.x - p2.x;
    float c2 = (p3.x - p2.x) * p2.y - (p3.y - p2.y) * p2.x;
     
    float x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1);
    float y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1);

    return set(x, y, 0);
}

//
// y = (i1-i2) / (2 * L) * x^2
//

// 水平長(バーチカル曲線の最大距離)
float L = 100;

int pts[] = primpoints(0, @primnum);

vector p0 = point(0, "P", pts[0]);
vector p1 = point(0, "P", pts[1]);
vector p2 = point(0, "P", pts[2]);

// 傾き
float i1 = (p1.y - p0.y) / (p1.x - p0.x);
float i2 = (p2.y - p1.y) / (p2.x - p1.x);

// バーチカル曲線の水平長より辺が短かったらバーチカル曲線の長さを短縮する
float length0 = sqrt(pow((p1-p0).x,2) + pow((p1-p0).y,2))*2;
float length1 = sqrt(pow((p2-p1).x,2) + pow((p2-p1).y,2))*2;

L = min(length1, min(length0, L));

// バーチカル曲線の始点の座標を求める
float x = p1.x - L/2;
vector cross = CrossPointXY(p0, p1, set(x, -1000, 0), set(x, 1000, 0));

vector curvePos[];  // バーチカル曲線の座標リスト
int num = 100;
float dist = L / float(num-1);

for(int i = 0; i < num; i++)
{
    x = dist * i;
    float y  = i1 * x - (i1-i2) / (2 * L) * pow(x,2);
    curvePos[i] = cross + set(x, y, 0);
}

// ポリライン(始点からの直線)の生成
int prim = addprim(0, "polyline");
int pt = addpoint(0, pts[0]);
addvertex(0, prim, pt);
pt = addpoint(0, curvePos[0]);
addvertex(0, prim, pt);

// ポリライン(バーチカル曲線部分)の生成
prim = addprim(0, "polyline");

// 谷か山かを判別する
vector left = cross(set(0,0,1), p1-p0);
float d = dot(left, p2-p1);

vector slopeColor = set(1, 0.5, 0);   // 山
if(d > 0) slopeColor = set(0, 0.5, 1.0);   // 谷
    
for(int i = 0; i < len(curvePos); i++)
{
    int pt2 = addpoint(0, curvePos[i]);
    addvertex(0, prim, pt2);
    
    setpointattrib(0, "Cd", pt2, slopeColor);
}

// ポリライン(終点までの曲線)の生成
prim = addprim(0, "polyline");
pt = addpoint(0, curvePos[-1]);
addvertex(0, prim, pt);
pt = addpoint(0, pts[2]);
addvertex(0, prim, pt);

// 元のポリラインを削除
removeprim(0, @primnum, 1);

直線と放物線で構成されたポリラインが出来上がる。

タイトルとURLをコピーしました