このような単純な状況では、次の 3 つの手順を実行できます: 形状の重心を見つける、x 軸と現在の点と重心によって形成される線との間の角度に基づいて対象の点を並べ替える、並べ替えられた点をウォークスルーする.
状況を考えると、重心の x 座標は、関心のある各ポイントの x 座標の合計を、関心のあるポイントの総数で割ったものです (それぞれ、重心の y 座標)。角度を計算するには、ほぼすべての言語で使用できる atan2 を使用するだけです。あなたの関心のあるポイントは、1 または 5 として提示されているポイントです。それ以外の場合はコーナーではありません (入力に基づく)。
Hough があなたの質問を解決すると騙されないでください。費用もかかる方法です。また、マトリックスが与えられた場合、他の方法に勝るものがないほど完全な情報が既にあります(もちろん、問題は、提示したような良い結果を繰り返すことです-そのような場合、ハフが役立つかもしれません)。
私の Ruby は非常に悪いので、次のコードを問題のガイドラインとして使用してください。
include Math
data = ["0000000000000000",
"0000053335000000",
"0000030003000000",
"0000030003000000",
"0000020002000000",
"0533210001233500",
"0300000000000300",
"0300000000000300",
"0300000000000300",
"0533210001233500",
"0000020002000000",
"0000030003000000",
"0000030003000000",
"0000053335000000",
"0000000000000000",
"0000000000000000"]
corner_x = []
corner_y = []
data.each_with_index{|line, i|
line.split(//).each_with_index{|col, j|
if col == "1" || col == "5"
# Cartesian coords.
corner_x.push(j + 1)
corner_y.push(data.length - i)
end
}
}
centroid_y = corner_y.reduce(:+)/corner_y.length.to_f
centroid_x = corner_x.reduce(:+)/corner_x.length.to_f
corner = []
corner_x.zip(corner_y).each{|c|
dy = c[1] - centroid_y
dx = c[0] - centroid_x
theta = Math.atan2(dy, dx)
corner.push([theta, c])
}
corner.sort!
corner.each_cons(2) {|c|
puts "%s->%s" % [c[0][1].inspect, c[1][1].inspect]
}
これにより、次の結果が得られます。
[2, 7]->[6, 7]
[6, 7]->[6, 3]
[6, 3]->[10, 3]
[10, 3]->[10, 7]
[10, 7]->[14, 7]
[14, 7]->[14, 11]
[14, 11]->[10, 11]
[10, 11]->[10, 15]
[10, 15]->[6, 15]
[6, 15]->[6, 11]
[6, 11]->[2, 11]
左下の点から始まる反時計回りの頂点はどれですか(左下の位置で(1、1)から始まるデカルト座標)。