私は2D点の集合を持っています。私は、すべての点を囲む最小面積の楕円を見つける必要があります。誰かがどのように問題に取り組まなければならないかという考えを伝えることができますか?サークルのためには簡単でした。中心とポイントの間の最大距離。しかし、楕円については、それは私が知らない非常に複雑です。私はこれをC++で実装する必要があります。 Find C++の点集合を囲む楕円の最小部分
答えて
私がそれを証明できるかどうかはわかりませんが、最適解は(少なくとも)3点の接線で表され、他のすべての点は楕円の中にあります!)。だから何もしなければ、〜n^3点の3つの点をすべてチェックし、それらが解を定義しているかどうかを調べることで、それを強制することができます。周囲の楕円の中に厳密に含まれていなければならないすべての点を削除することでそれを改善することが可能であるべきですが、どうすればそれができるかわかりません。たぶんxとyの座標でポイントを並べ替えると、何か派手なやり方で。
完全な解決策ではありませんが、それはスタートです。
EDIT: 残念ながら、3点では楕円を定義するには不十分です。しかし、おそらくあなたが3点を接する最小面積の楕円に制限したら?
Rory Daultonは、解の制約を明確に指定する必要があると示唆しています。手始めに、今はこれを前提としています
- それは2D問題
- 楕円を軸
- センターは、私はこのような標準のgenereを攻撃する代わりに
(0,0)
の任意で整列されているとテストapproximation search(バイナリ検索とリニア検索のハイブリッド)の問題でスピードアップできます(ただし、最初からブルートフォースを試すこともできますそれが動作する場合)。ソリューション
の
計算制約を使用すると、楕円のおおよその配置位置とサイズを見つける必要があり、検索を制限します。そのためにはあなたのポイントにアウトスクライブサークルを使用することができます。楕円領域は円以下であり、配置は近くになることは明らかです。
- 円がそのバウンディングボックスにセンタリングさせて、半径が最大なるポイント
- のバウンディングボックスを見つける:円は私たちは、これは例えば使用することができ、必ずしも可能な最小1である必要はありません。その中心から任意の点までの距離。
これは
O(n)
の複雑さです(n
はあなたのポイントの番号です)。検索「すべて」の可能な楕円と最善の解決策
を覚えているので、我々は
area = M_PI*rx*ry
が最小であるrx,ry
ながら、楕円の中心(x0,y0)
と半車軸を見つける必要があります。近似探索では、各変数はO(log(m))
の係数を持ち、各反復はO(n)
という妥当性をテストする必要があるため、最終的な複雑度はO(n.log^4(m))
となります。ここで、m
は各検索パラメータの可能なバリエーションの平均数です(精度と検索の制約に依存します)。単純なブルート検索ではO(n.m^4)
となります。特に浮動小数点の場合は、実際には恐ろしいです。m
が本当に大きくなる可能性があります。これをスピードアップするために、楕円の面積は見つかった円の面積以下であるため、すべてのより大きい楕円を無視することができます。
rx,ry
の制約は、境界ボックス+/-一部の予備の縦横比から導き出すことができます。//--------------------------------------------------------------------------- // input points const int n=15; // number of random points to test float pnt[n][2]; // debug bounding box float box_x0,box_y0,box_x1,box_y1; // debug outscribed circle float circle_x,circle_y,circle_r; // solution ellipse float ellipse_x,ellipse_y,ellipse_rx,ellipse_ry; //--------------------------------------------------------------------------- void compute(float x0,float y0,float x1,float y1) // cal with bounding box where you want your points will be generated { int i; float x,y; // generate n random 2D points inside defined area Randomize(); for (i=0;i<n;i++) { pnt[i][0]=x0+(x1-x0)*Random(); pnt[i][1]=y0+(y1-y0)*Random(); } // compute bounding box x0=pnt[0][0]; x1=x0; y0=pnt[0][1]; y1=y0; for (i=0;i<n;i++) { x=pnt[i][0]; if (x0>x) x0=x; if (x1<x) x1=x; y=pnt[i][1]; if (y0>y) y0=y; if (y1<y) y1=y; } box_x0=x0; box_x1=x1; box_y0=y0; box_y1=y1; // "outscribed" circle circle_x=0.5*(x0+x1); circle_y=0.5*(y0+y1); circle_r=0.0; for (i=0;i<n;i++) { x=pnt[i][0]-circle_x; x*=x; y=pnt[i][1]-circle_y; y*=y; x+=y; if (circle_r<x) circle_r=x; } circle_r=sqrt(circle_r); // smallest area ellipse int N; double m,e,step,area; approx ax,ay,aa,ab; N=3; // number of recursions each one improves accuracy with factor 10 area=circle_r*circle_r; // solution will not be bigger that this step=((x1-x0)+(y1-y0))*0.05; // initial position/size step for the search as 1/10 of avg bounding box size for (ax.init( x0, x1,step,N,&e);!ax.done;ax.step()) // search x0 for (ay.init( y0, y1,step,N,&e);!ay.done;ay.step()) // search y0 for (aa.init(0.5*(x1-x0),2.0*circle_r,step,N,&e);!aa.done;aa.step()) // search rx for (ab.init(0.5*(y1-y0),2.0*circle_r,step,N,&e);!ab.done;ab.step()) // search ry { e=aa.a*ab.a; // is ellipse outscribed? if (aa.a>=ab.a) { m=aa.a/ab.a; // convert to circle of radius rx for (i=0;i<n;i++) { x=(pnt[i][0]-ax.a); x*=x; y=(pnt[i][1]-ay.a)*m; y*=y; // throw away this ellipse if not if (x+y>aa.a*aa.a) { e=2.0*area; break; } } } else{ m=ab.a/aa.a; // convert to circle of radius ry for (i=0;i<n;i++) { x=(pnt[i][0]-ax.a)*m; x*=x; y=(pnt[i][1]-ay.a); y*=y; // throw away this ellipse if not if (x+y>ab.a*ab.a) { e=2.0*area; break; } } } } ellipse_x =ax.aa; ellipse_y =ay.aa; ellipse_rx=aa.aa; ellipse_ry=ab.aa; } //---------------------------------------------------------------------------
のみ15ポイントでさえ、この単純な例で計算するのに約2秒を要した:上記のリンクから
approx
クラスがいることを利用し
ここでは、単純な小さなC++例。 circle_r^2
などのテスト専用領域のようなヒューリスティックを追加するか、数学のルールでソリューション領域を選択することで、パフォーマンスを向上させることができます。近似探索の代わりにブルートフォースを使用すると、計算時間がほんの数分になることが予想されるので、O(scary)
...
この例は、ポイントのアスペクト比については、 rx,ry
〜2.0*circle_r
これでは不十分かもしれません。代わりに、rx*ry<=circle_r^2
...
がCCD(環状下降座標)の一例のバリエーションのための他の(「高速」)方法を使用することができるにも存在することアスペクト点の比およびまたは状態から上限を計算することができます。 。しかし、このような方法は、通常、最適な解決策がまったく見つからないか、または任意のされることを保証することはできません...出力例のここ
は概要:
ドットは、pnt[n]
から灰色の個々の点です破線のものはバウンディングボックスであり、アウトスクライブサークルを使用しています。緑色の楕円が解です。
- 1. plot楕円の点の割合を囲む
- 2. はここで最小の部分集合の集合
- 3. SAGEの楕円点
- 4. 楕円曲線点
- 5. 2D点の集合を囲む外接円を見つけるアルゴリズム
- 6. 中心楕円の起点
- 7. 2つの楕円(楕円)の交点の面積ですか?
- 8. 楕円のリンクリストをc#
- 9. 楕円上の点を計算する
- 10. C++の楕円へのパラメータ
- 11. C#WPF楕円スライダー
- 12. セージの楕円曲線上のデカルト点
- 13. 複数のバウンディングボックスを含む最小円
- 14. 与えられたポイントの割合を含む楕円R
- 15. 円で点集合をクラスタリングする
- 16. 高速楕円体交点アルゴリズム
- 17. 部分集合全体の集合R
- 18. 楕円のラスタライズ
- 19. 楕円の同心円リング
- 20. 円と楕円のラスタライゼーションアルゴリズム
- 21. 楕円体のプロット
- 22. 私は楕円体に合わせて、次のMATLABスクリプトを使用したい楕円
- 23. Bowyer-Watsonアルゴリズムの点の集合をスーパー三角形で囲む方法は?
- 24. 3Dの楕円軌道上の点を計算する
- 25. Cで楕円を描く方法は?
- 26. C/C++の部分最小二乗実装ですか?
- 27. 与えられた値より小さい最大部分集合sum
- 28. 配列の最大部分集合の和を求める
- 29. 楕円弧の点を計算する方法
- 30. 3点を通る楕円の方程式は?
この問題のクローズフォームの解決策がない場合は、ある種のヒューリスティック検索手法にかなり慣れやすいようです。 – templatetypedef
楕円を原点の中央に配置する必要がありますか?楕円の軸は座標軸に平行でなければなりませんか? –
質問を再タグ付けしました(C++が必要だと明言したときにJAVAにタグを付けるのはなぜですか?) – Spektre