2021.03.10
最も近い座標を探す
1番近い座標は?
以下の図は、そのイメージです。
1番近い座標を探す方法
具体的には以下のようなプログラムになります。
①基準の座標を決めます。(ox,oy)
Javaソースコード
ClosestCoordinates1.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078
public class ClosestCoordinates1 { // 最も近い座標の配列の添え字を戻すメソッド // (ox,oy)が基準座標 // (x[],y[])が探索座標 static int closest_coordinates( double ox, double oy, double[] x, double[] y ) { // 引数に不備がある場合、-1を戻す if ( null == x ) return -1; if ( null == y ) return -1; if ( 1 > x.length ) return -1; if ( 1 > y.length ) return -1; if ( x.length != y.length ) return -1; // 調べる座標数 int crdnum = x.length; // 調べる座標が1つの場合、0を戻す。 if ( 1 == crdnum ) return 0; // 距離の最小値を格納する変数 // 初期値 : doubleの最大 double dist2_min = Double.MAX_VALUE; // 距離の最小値が格納される配列の添え字を格納する変数 // 初期値 : -1 int crd_min = -1; // 最も近い座標を求める for ( int i = 0; i < crdnum; i++ ) { // 距離の2乗を計算 double dx = x[ i ] - ox; double dy = y[ i ] - oy; double dist2 = dx * dx + dy * dy; // 距離の最小値の比較 if ( dist2 < dist2_min ) { // 距離の最小値を配列の添え字の更新 dist2_min = dist2; crd_min = i; } } // 距離の最小値が格納される配列の添え字を戻す return crd_min; } // メイン public static void main(String[] args) { // 調べる座標を配列に格納 // x,yは0.0以上~1000.0の乱数で作成 double[] x = new double[ 10 ]; double[] y = new double[ 10 ]; for ( int i = 0; i < x.length; i++ ) { x[ i ] = Math.random() * 1000.0; y[ i ] = Math.random() * 1000.0; } // 基準の座標を設定 double ox = 500.0; double oy = 500.0; int ans = closest_coordinates( ox, oy, x, y ); if ( 0 > ans ) { System.out.println( "配列番号の取得に失敗しました!" ); } // 結果を出力 System.out.println( "最も近い座標の配列番号 : " + ans ); System.out.println( "最も近い座標 : " + x[ ans ] + " " + y[ ans ] ); System.out.println(); // 調べた座標を出力 for ( int i = 0; i < x.length; i++ ) { System.out.println( i + " " + x[ i ] + " " + y[ i ] ); } } }
コンパイル ソースコードが「ANSI」の場合
C:\talavax\javasample>javac -encoding sjis ClosestCoordinates1.java
コンパイル ソースコードが「UTF-8」の場合
C:\talavax\javasample>javac ClosestCoordinates1.java
実行
C:\talavax\javasample>java ClosestCoordinates1
出力結果
最も近い座標の配列番号 : 5 最も近い座標 : 522.6032407893074 529.1182157580057 0 877.7147009243795 718.844711996419 1 526.6243989932896 972.9817185296182 2 918.0303176324935 178.36544193189474 3 327.8529222496893 98.33227058715333 4 864.9148502306463 293.97241655453996 5 522.6032407893074 529.1182157580057 6 556.547189361226 99.08534083354937 7 507.57394473692665 420.918431684552 8 478.02958653506147 933.9869793183221 9 334.80064599857684 252.08397376586979
Javaソースコードの解説
001
public class ClosestCoordinates1 {
クラス名を、ClosestCoordinates1としています。
002 003 004 005
// 最も近い座標の配列の添え字を戻すメソッド // (ox,oy)が基準座標 // (x[],y[])が探索座標 static int closest_coordinates( double ox, double oy, double[] x, double[] y )
007 008 009 010 011 012
// 引数に不備がある場合、-1を戻す
if ( null == x ) return -1;
if ( null == y ) return -1;
if ( 1 > x.length ) return -1;
if ( 1 > y.length ) return -1;
if ( x.length != y.length ) return -1;
014 015
// 調べる座標数 int crdnum = x.length;
017 018
// 調べる座標が1つの場合、0を戻す。
if ( 1 == crdnum ) return 0;
探索する座標の個数crdnumが1の場合、return文で0を戻してメソッドを抜けています。この0は配列の添え字番号のことでx[0],y[0]が最も近い座標ということです。個数が1の場合、その1つが1番近い座標です。
020 021 022
// 距離の最小値を格納する変数 // 初期値 : doubleの最大 double dist2_min = Double.MAX_VALUE;
024 025 026
// 距離の最小値が格納される配列の添え字を格納する変数 // 初期値 : -1 int crd_min = -1;
028 029
// 最も近い座標を求める for ( int i = 0; i < crdnum; i++ ) {
030 031 032 033
// 距離の2乗を計算 double dx = x[ i ] - ox; double dy = y[ i ] - oy; double dist2 = dx * dx + dy * dy;
このプログラムは一番近い座標を探すものなので、直線距離の2乗でも比較することができます。もちろん直線距離で比較することもできますが、直線距離を求めるには平方根を計算する必要があり余分な処理時間がかかります。
直線距離の計算は、以下の図を参考にしてください。
035 036 037 038 039 040
// 距離の最小値の比較 if ( dist2 < dist2_min ) { // 距離の最小値を配列の添え字の更新 dist2_min = dist2; crd_min = i; }
計算で得られた距離の2乗の値dist2と現在の距離の最小値を格納した変数dist2_minを比較して、変数dist2の値が小さければ、変数dist2_minにdist2の値を代入します。さらに配列の添え字crd_minに変数iの値を代入します。
043 044
// 距離の最小値が格納される配列の添え字を戻す return crd_min;
048 049
// メイン public static void main(String[] args) {
このmainメソッドからプログラムを実行します。
050 051 052 053 054 055 056 057 058
// 調べる座標を配列に格納 // x,yは0.0以上~1000.0の乱数で作成 double[] x = new double[ 10 ]; double[] y = new double[ 10 ]; for ( int i = 0; i < x.length; i++ ) { x[ i ] = Math.random() * 1000.0; y[ i ] = Math.random() * 1000.0; }
Math.randomメソッド
public static double Math.random()
・乱数を返します。 パラメータ なし 戻り値 0.0以上、1.0未満の乱数
060 061 062 063 064 065 066
// 基準の座標を設定 double ox = 500.0; double oy = 500.0; int ans = closest_coordinates( ox, oy, x, y ); if ( 0 > ans ) { System.out.println( "配列番号の取得に失敗しました!" ); }
変数ansの値が0未満の場合、エラーで結果が得られなかったことを意味しています。
068 069 070 071 072 073 074 075 076
// 結果を出力 System.out.println( "最も近い座標の配列番号 : " + ans ); System.out.println( "最も近い座標 : " + x[ ans ] + " " + y[ ans ] ); System.out.println(); // 調べた座標を出力 for ( int i = 0; i < x.length; i++ ) { System.out.println( i + " " + x[ i ] + " " + y[ i ] ); }
結果をprintlnで出力しています。
以上です。