ある直線 ax + by + c = 0; との交点が得られても、 その交点が2点の間にあるかを知るのは面倒なのではないかと思った。
考えてみて、このような方法を思いついた。
点A を原点とし、 点B に向かう直線を x軸としたローカル座標系を考える。
この座標系で、ベジエ曲線の y座標の式は、直線との距離を意味し、 x座標の式は、最も近い直線上の位置を意味する。
yの式が 0 で、 x の式が 0以上 、 AB の長さ以下なら、 交点が直線の上にあることになる。
まず、ローカル座標の x軸方向・y軸方向の単位ベクトルを作る
次に、ベジエ曲線の点を、ローカル座標に直す
小さい点は内積の意味。 2つのベクトルの x1 * x2 + y1 * y2 を計算する。
変換したローカル座標を元に、ベジエ曲線の式を作り、解く。->3次方程式を解く
これで、2点を結ぶ直線上に交点があることや、 直線上のどこに交点があるかを知ることが出来そう。
あと、ベジェ曲線の次数を減らせば線分同士の交点も求められる。
[試しに書いてみたソース]
public float[] intersection_line(PointF pa, PointF pb) { Vec2D vpta = new Vec2D(pa); Vec2D vptb = new Vec2D(pb); Vec2D vAB = new Vec2D(pa, pb); Vec2D Ix = vAB / vAB.length; Vec2D Iy = new Vec2D(-Ix.y, Ix.x); Vec2D[] p2 = new Vec2D[4]; for (int cnt = 0; cnt < 4; cnt++) { Vec2D AP = new Vec2D(pa, pts[cnt]); p2[cnt] = new Vec2D( Vec2D.inproduct(AP, Ix), Vec2D.inproduct(AP, Iy)); } Complex[] res = MyMath.cubiceq(-p2[0].y + p2[1].y*3 - p2[2].y*3 + p2[3].y, 3 * p2[0].y - 2 * p2[1].y*3 + p2[2].y*3, -3 * p2[0].y + p2[1].y*3, p2[0].y); List res2 = new List(); foreach (Complex v in res) { if (v.imag < 0.0000001) { double xval = (-p2[0].x + p2[1].x * 3 - p2[2].x * 3 + p2[3].x) * Math.Pow(v.real, 3) + (3 * p2[0].x - 2 * p2[1].x * 3 + p2[2].x * 3) * Math.Pow(v.real, 2) + (-3 * p2[0].x + p2[1].x * 3) * v.real + p2[0].x; if (xval >= 0 && xval <= vAB.length && 0 <= v.real && v.real <= 1) //追記 res2.Add(v.real); } } float[] result = new float[res2.Count]; for (int cnt = 0; cnt < res2.Count; cnt++) { result[cnt] = (float)res2[cnt]; } return result; }
[Vec2D クラス] 適当に作ったベクトルクラス
struct Vec2D { public double x; public double y; public Vec2D(double x, double y) //constructor { this.x = x; this.y = y; } public Vec2D(PointF pt) //constructor { this.x = pt.X; this.y = pt.Y; } public Vec2D(PointF pa, PointF pb) { this.x = pb.X - pa.X; this.y = pb.Y - pa.Y; } //演算子 public static Vec2D operator +(Vec2D c1, Vec2D c2) { return new Vec2D(c1.x + c2.x, c1.y + c2.y); } public static Vec2D operator -(Vec2D c1, Vec2D c2) { return new Vec2D(c1.x - c2.x, c1.y - c2.y); } public static Vec2D operator -(Vec2D c1) { return new Vec2D(-c1.x, -c1.y); } public static Vec2D operator *(double c1, Vec2D c2) { return new Vec2D(c1 * c2.x, c1 * c2.y); } public static Vec2D operator /(Vec2D c1, double c2) { return new Vec2D(c1.x / c2, c1.y / c2); } public static double inproduct(Vec2D c1, Vec2D c2) { return c1.x * c2.x + c1.y * c2.y; } public double length { get{ return Math.Sqrt( x * x + y * y ); } } }