円のリストを取得し、完全に重なっている円のリストのみを返す関数を実行しようとしています (別の円の内側)。問題は、アルゴリズムが少なくともO(n²)であることです。これは、getConcentricCircles 関数のネストされた for と、大規模なデータセットの時間がかかるためです。それを最適化する方法はありますか?
編集:これが役立つかどうかはわかりませんが、アルゴリズムを使用して、虹彩と瞳孔の検出で誤検知を検出します。円が完全に別の円の内側にある場合、それが瞳孔で、外側が虹彩である可能性があります。それらは同心である必要があり、非常に単純化されますが、人間の目の瞳孔は虹彩の中心に正確にないことがあります。これが私がこれを行う理由です。
編集 2: isCircleInCircle を Peter Lawrey のソリューションに置き換えました。一部のケースでは正しくありませんでした
円が円の内側にあるかどうかをチェックする関数:
private static boolean isCircleInCircle(Circle a, Circle b) {
// the circle is inside if the distance between the centre is less than the difference in the radius
double dx = a.getX() - b.getX();
double dy = a.getY() - b.getY();
double radiusDifference = a.getRadius() - b.getRadius();
double centreDistanceSquared = dx*dx + dy*dy; // edited
return radiusDifference * radiusDifference > centreDistanceSquared;
}
次に、リストのすべての要素を相互にチェックし、重なっている円 (および重なっている円) のみを保存します。
public HashSet<Circle> getConcentricCircles(List<Circle> circleList) {
HashSet<Circle> toReturn = new HashSet<Circle>();
for (Circle circle : circleList) {
for (Circle toCheck : circleList) {
// if the circles are not the same and one is inside another,
if (!toCheck.equals(circle) && isCircleInCircle(circle, toCheck)) {
// add both to the hashset
toReturn.add(circle);
toReturn.add(toCheck);
}
}
}
return toReturn;
}