私はしばらくの間この問題に取り組んできましたが、これまでのところ良い解決策を思い付くことができませんでした。
問題:3つ(またはそれ以上)の2Dポイントの順序付きリストがあり、「見栄えがする」ように、3次ベジェ曲線でこれらをストロークしたいと思います。「見栄えが良い」部分は非常に単純です。2番目のポイントのウェッジを滑らかにしたいだけです(たとえば、カーブがそれ自体でダブルバックしないようにします)。したがって、3つのポイントが与えられた場合、曲線を描くときにトリプレットの2番目のポイントを囲む2つのコントロールポイントをどこに配置する必要があります。
これまでの私の解決策は次のとおりですが、不完全です。このアイデアは、私が求めている外観を伝えるのにも役立つかもしれません。
(x1、y1)、(x2、y2)、(x3、y3)の3つのポイントが与えられます。ポイントの各トリプレットによって内接する円を取ります(それらが同一線上にある場合は、それらの間に直線を引いて先に進みます)。点(x2、y2)でこの円に接する線を取ります-この接線上に(x2、y2)を囲む制御点を配置します。
それは私が立ち往生している最後の部分です。私が抱えている問題は、この接線上に2つの制御点を配置する方法を見つけることです。この線上の(x2、y2)からどれだけ離れているかについては、十分なヒューリスティックがありますが、もちろん、その距離にあるこの線上の2つのポイント。「間違った」方向のものを計算すると、曲線はそれ自体でループします。
3つのポイントで表される円の中心を見つけるには(いずれかのポイントのx値が同じ場合は、以下の計算でポイントを並べ替えるだけです)。
double ma = (point2.y - point1.y) / (point2.x - point1.x);
double mb = (point3.y - point2.y) / (point3.x - point2.x);
CGPoint c; // Center of a circle passing through all three points.
c.x = (((ma * mb * (point1.y - point3.y)) + (mb * (point1.x + point2.x)) - (ma * (point2.x + point3.x))) / (2 * (mb - ma)));
c.y = (((-1 / ma) * (c.x - ((point1.x + point2.x) / 2))) + ((point1.y + point2.y) / 2));
次に、接線上の点を見つけるために、この場合は、point2からpoint3に向かう曲線の制御点を見つけます。
double d = ...; // distance we want the point. Based on the distance between
// point2 and point3.
// mc: Slope of the line perpendicular to the line between
// point2 and c.
double mc = - (c.x - point2.x) / (c.y - point2.y);
CGPoint tp; // point on the tangent line
double c = point2.y - mc * point2.x; // c == y intercept
tp.x = ???; // can't figure this out, the question is whether it should be
// less than point2.x, or greater than?
tp.y = mc * tp.x + c;
// then, compute a point cp that is distance d from point2 going in the direction
// of tp.