From 0677e91d0aeda408583ca2005607a1f65a484a78 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Fri, 12 Jul 2024 19:31:55 +0900 Subject: [PATCH 01/18] added multidimensional radix tree into CheckSpatialIdsOverlap --- integrate/check_spatial_id_overlap.go | 107 ++++++++++++--------- integrate/check_spatial_id_overlap_test.go | 8 +- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/integrate/check_spatial_id_overlap.go b/integrate/check_spatial_id_overlap.go index 73ca713..07bad85 100644 --- a/integrate/check_spatial_id_overlap.go +++ b/integrate/check_spatial_id_overlap.go @@ -2,6 +2,9 @@ package integrate import ( "fmt" + "github.com/trajectoryjp/multidimensional-radix-tree/tree" + "github.com/trajectoryjp/spatial_id_go/v4/common/consts" + "github.com/trajectoryjp/spatial_id_go/v4/common/errors" "strconv" "strings" ) @@ -27,36 +30,9 @@ import ( // 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) { - // ズームレベルの取り出し - arr1 := strings.Split(spatialId1, "/") - arr2 := strings.Split(spatialId2, "/") - if len(arr1) != 4 || len(arr2) != 4 { - // 不正形式 - return false, fmt.Errorf("invalid format. spatialId1: %v, spatialId2: %v", spatialId1, spatialId2) - } - zoom1, _ := strconv.Atoi(arr1[0]) - zoom2, _ := strconv.Atoi(arr2[0]) - - // zoomレベルで場合分け - // zoomレベルが等しいとき、変換なし - if zoom1 > zoom2 { - // spatialId2のzoomレベルをzoom1に合わせるよう変換 - convertedSpatialId, err := ChangeSpatialIdsZoom([]string{spatialId1}, int64(zoom2)) - if err != nil { - return false, err - } - spatialId1 = convertedSpatialId[0] - } else if zoom1 < zoom2 { - // spatialId1のzoomレベルをzoom2に合わせるよう変換 - convertedSpatialId, err := ChangeSpatialIdsZoom([]string{spatialId2}, int64(zoom1)) - if err != nil { - return false, err - } - spatialId2 = convertedSpatialId[0] - } - - return spatialId1 == spatialId2, nil - + ids1 := []string{spatialId1} + ids2 := []string{spatialId2} + return CheckSpatialIdsArrayOverlap(ids1, ids2) } // CheckSpatialIdsArrayOverlap 2つの空間ID重複の判定関数 @@ -80,26 +56,69 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bool, error) { - // spatialIds1から各要素の取り出し - for _, spatialId1 := range spatialIds1 { - // spatialIds2から各要素の取り出し - for _, spatialId2 := range spatialIds2 { - // 取り出した要素の比較 - result, err := CheckSpatialIdsOverlap(spatialId1, spatialId2) - if err != nil { - // エラー発生時、falseとerrorを返却 - return false, err - } - if result { - // 重複判定時、trueとnilを返却 - return result, nil - } + tr := tree.CreateTree(tree.Create2DTable()) + // spatialIds1から各要素をradix treeに格納 + for indexSpatialId1, spatialId1 := range spatialIds1 { + zoom1, x1, y1, err := getSpatialIdAttrs(spatialId1) + if err != nil { + return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) + } + index1 := tree.Indexs{int64(x1), int64(y1)} + tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + } + // spatialIds2から各要素の取り出し + for indexSpatialId2, spatialId2 := range spatialIds2 { + zoom2, x2, y2, err := getSpatialIdAttrs(spatialId2) + if err != nil { + return false, fmt.Errorf("%w @spatialId2[%v]", err, indexSpatialId2) + } + index2 := tree.Indexs{int64(x2), int64(y2)} + // 取り出した要素の比較 + result := tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + if result { + // 重複判定時、trueとnilを返却 + return result, nil } } return false, nil } +// getSpatialIdAttrs 空間IDフォーマットチェック関数 +// +// 入力された空間IDの各成分を格納した配列を返却する。 +// 以下の条件に当てはまる場合はフォーマット違反となりエラーインスタンスが返却される。 +// +// ・空間IDの各成分に数値が入力されていない場合 +// ・区切り文字の数が3つで無い場合 +// +// 引数: +// +// spatialId:空間ID +// +// 戻り値: +// +// 空間IDに含まれる精度(ズームレベル)、X, Y成分を格納した以下のtuple +// (精度(ズームレベル), X成分, Y成分) +// 入力された拡張空間IDのフォーマットが不正な場合、戻り値を0にしエラーインスタンスを返却。 +func getSpatialIdAttrs(spatialId string) (int, int, int, error) { + // 分割 + spatialIdAttributes := strings.Split(spatialId, consts.SpatialIDDelimiter) + if len(spatialIdAttributes) != 4 { + // 不正形式(要素数) + return 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) + } + var errNumberConversion error + zoom, errNumberConversion := strconv.Atoi(spatialIdAttributes[0]) + x, errNumberConversion := strconv.Atoi(spatialIdAttributes[2]) + y, errNumberConversion := strconv.Atoi(spatialIdAttributes[3]) + // 不正形式(数値) + if errNumberConversion != nil { + return 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) + } + return zoom, x, y, nil +} + // CheckExtendedSpatialIdsOverlap 2つの拡張空間IDの重複の判定関数 // // 比較対象として入力された2つの拡張空間IDのズームレベルを変換して揃え、重複の判定を行う。 diff --git a/integrate/check_spatial_id_overlap_test.go b/integrate/check_spatial_id_overlap_test.go index dd5b6f4..8391674 100644 --- a/integrate/check_spatial_id_overlap_test.go +++ b/integrate/check_spatial_id_overlap_test.go @@ -77,7 +77,7 @@ func TestCheckSpatialIdsOverlap03(t *testing.T) { // 期待値 expectValue := false - expectError := "invalid format. spatialId1: , spatialId2: 16/0/58198/25804" + expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" if !reflect.DeepEqual(resultValue, expectValue) { t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) @@ -107,7 +107,7 @@ func TestCheckSpatialIdsOverlap04(t *testing.T) { // 期待値 expectValue := false - expectError := "invalid format. spatialId1: 25/0/29803148/13212522/777, spatialId2: 16/0/58198/25804" + expectError := "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]" if !reflect.DeepEqual(resultValue, expectValue) { t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) @@ -192,7 +192,7 @@ func TestCheckSpatialIdsArrayOverlap03(t *testing.T) { // 期待値 expectValue := false - expectError := "invalid format. spatialId1: , spatialId2: 16/0/58198/25803" + expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" if !reflect.DeepEqual(resultValue, expectValue) { t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) @@ -222,7 +222,7 @@ func TestCheckSpatialIdsArrayOverlap04(t *testing.T) { // 期待値 expectValue := false - expectError := "invalid format. spatialId1: 25/0/29803148/13212522/777, spatialId2: 16/0/58198/25803" + expectError := "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]" if !reflect.DeepEqual(resultValue, expectValue) { t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) From 19f539757b8f55cf315a9116e32e3e39773ebef7 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Tue, 16 Jul 2024 19:55:00 +0900 Subject: [PATCH 02/18] added handling f-index in CheckSpatialIdsOverlap --- integrate/check_spatial_id_overlap.go | 41 +++++--- integrate/check_spatial_id_overlap_test.go | 112 +++++++++++++++++++++ 2 files changed, 140 insertions(+), 13 deletions(-) diff --git a/integrate/check_spatial_id_overlap.go b/integrate/check_spatial_id_overlap.go index 07bad85..12be71f 100644 --- a/integrate/check_spatial_id_overlap.go +++ b/integrate/check_spatial_id_overlap.go @@ -56,25 +56,39 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bool, error) { - tr := tree.CreateTree(tree.Create2DTable()) + tr := tree.CreateTree(tree.Create3DTable()) + trMinus := tree.CreateTree(tree.Create3DTable()) // spatialIds1から各要素をradix treeに格納 for indexSpatialId1, spatialId1 := range spatialIds1 { - zoom1, x1, y1, err := getSpatialIdAttrs(spatialId1) + zoom1, f1, x1, y1, err := getSpatialIdAttrs(spatialId1) if err != nil { return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) } - index1 := tree.Indexs{int64(x1), int64(y1)} - tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + index1 := tree.Indexs{int64(f1), int64(x1), int64(y1)} + switch f1 < 0 { + case true: + //index1[0] *= -1 + trMinus.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + case false: + tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + } } // spatialIds2から各要素の取り出し for indexSpatialId2, spatialId2 := range spatialIds2 { - zoom2, x2, y2, err := getSpatialIdAttrs(spatialId2) + zoom2, f2, x2, y2, err := getSpatialIdAttrs(spatialId2) if err != nil { return false, fmt.Errorf("%w @spatialId2[%v]", err, indexSpatialId2) } - index2 := tree.Indexs{int64(x2), int64(y2)} + index2 := tree.Indexs{int64(f2), int64(x2), int64(y2)} // 取り出した要素の比較 - result := tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + result := false + switch f2 < 0 { + case true: + //index2[0] *= -1 + result = trMinus.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + case false: + result = tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + } if result { // 重複判定時、trueとnilを返却 return result, nil @@ -98,25 +112,26 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo // // 戻り値: // -// 空間IDに含まれる精度(ズームレベル)、X, Y成分を格納した以下のtuple -// (精度(ズームレベル), X成分, Y成分) +// 空間IDに含まれる精度(ズームレベル), F, X, Y成分を格納した以下のtuple +// (精度(ズームレベル), F成分, X成分, Y成分) // 入力された拡張空間IDのフォーマットが不正な場合、戻り値を0にしエラーインスタンスを返却。 -func getSpatialIdAttrs(spatialId string) (int, int, int, error) { +func getSpatialIdAttrs(spatialId string) (int, int, int, int, error) { // 分割 spatialIdAttributes := strings.Split(spatialId, consts.SpatialIDDelimiter) if len(spatialIdAttributes) != 4 { // 不正形式(要素数) - return 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) + return 0, 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) } var errNumberConversion error zoom, errNumberConversion := strconv.Atoi(spatialIdAttributes[0]) + f, errNumberConversion := strconv.Atoi(spatialIdAttributes[1]) x, errNumberConversion := strconv.Atoi(spatialIdAttributes[2]) y, errNumberConversion := strconv.Atoi(spatialIdAttributes[3]) // 不正形式(数値) if errNumberConversion != nil { - return 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) + return 0, 0, 0, 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("spatialId: %v", spatialId)) } - return zoom, x, y, nil + return zoom, f, x, y, nil } // CheckExtendedSpatialIdsOverlap 2つの拡張空間IDの重複の判定関数 diff --git a/integrate/check_spatial_id_overlap_test.go b/integrate/check_spatial_id_overlap_test.go index 8391674..807570f 100644 --- a/integrate/check_spatial_id_overlap_test.go +++ b/integrate/check_spatial_id_overlap_test.go @@ -120,6 +120,118 @@ func TestCheckSpatialIdsOverlap04(t *testing.T) { t.Log("テスト終了") } +// TestCheckSpatialIdsOverlap05 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/8/58198/25804"} +// +// + 確認内容 +// - fインデックスの包含関係があることを確認できること +func TestCheckSpatialIdsOverlap05(t *testing.T) { + // 入力値 + spatialId1 := "13/1/7274/3225" + spatialId2 := "16/8/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap06 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/17/58198/25804"} +// +// + 確認内容 +// - fインデックスの包含関係がないことを確認できること +func TestCheckSpatialIdsOverlap06(t *testing.T) { + // 入力値 + spatialId1 := "13/1/7274/3225" + spatialId2 := "16/17/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap07 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-8/58198/25804"} +// +// + 確認内容 +// - fインデックスが負数の場合においても入力値から包含関係があることを確認できること +func TestCheckSpatialIdsOverlap07(t *testing.T) { + // 入力値 + spatialId1 := "13/-1/7274/3225" + spatialId2 := "16/-8/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap08 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-10/58198/25804"} +// +// + 確認内容 +// - fインデックスに関する包含関係がないことを確認できること +func TestCheckSpatialIdsOverlap08(t *testing.T) { + // 入力値 + spatialId1 := "13/-1/7274/3225" + spatialId2 := "16/-10/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + // TestCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 正常系動作確認 // // + 試験データ From a15052fb77110920d0bf79cd6acd8be30475617e Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Fri, 19 Jul 2024 13:41:59 +0900 Subject: [PATCH 03/18] fixed handling minus f-index in CheckSpatialIdsArrayOverlap by using altitude index conversion To avoid cycle import between `integrate` and `transform`, check_spatial_id_overlap.go moved to new package --- .../check_spatial_id_overlap.go | 48 +- .../check_spatial_id_overlap_test.go | 2 +- transform/convert_quadkey_and_Vertical_id.go | 39 +- .../convert_quadkey_and_Vertical_id_test.go | 2512 ++++++++--------- 4 files changed, 1328 insertions(+), 1273 deletions(-) rename {integrate => detector}/check_spatial_id_overlap.go (82%) rename {integrate => detector}/check_spatial_id_overlap_test.go (99%) diff --git a/integrate/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go similarity index 82% rename from integrate/check_spatial_id_overlap.go rename to detector/check_spatial_id_overlap.go index 12be71f..3afea5c 100644 --- a/integrate/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -1,10 +1,12 @@ -package integrate +package detector import ( "fmt" "github.com/trajectoryjp/multidimensional-radix-tree/tree" "github.com/trajectoryjp/spatial_id_go/v4/common/consts" "github.com/trajectoryjp/spatial_id_go/v4/common/errors" + "github.com/trajectoryjp/spatial_id_go/v4/integrate" + "github.com/trajectoryjp/spatial_id_go/v4/transform" "strconv" "strings" ) @@ -56,7 +58,9 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bool, error) { + // f,x,yで3次元分の2分木 tr := tree.CreateTree(tree.Create3DTable()) + // 負数fインデックスを持つ空間IDは高度変換して別の3次元2分木に保存 trMinus := tree.CreateTree(tree.Create3DTable()) // spatialIds1から各要素をradix treeに格納 for indexSpatialId1, spatialId1 := range spatialIds1 { @@ -64,12 +68,23 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo if err != nil { return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) } - index1 := tree.Indexs{int64(f1), int64(x1), int64(y1)} switch f1 < 0 { case true: - //index1[0] *= -1 - trMinus.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + convertedFIndices1, errAltConversion := transform.ConvertZToAltitudekey( + int64(f1), + int64(zoom1), + int64(zoom1), + 25, // 空間ID高さが1mになるズームレベル + 16777216, // 元の最大高さを保ったまま正方向と負方向でfインデックスを半数ずつ導入 + ) + if errAltConversion != nil { + return false, fmt.Errorf("%w @spatialId1[%v]", errAltConversion, indexSpatialId1) + } + for _, index := range convertedFIndices1 { + trMinus.Append(tree.Indexs{index, int64(x1), int64(y1)}, tree.ZoomSetLevel(zoom1), spatialId1) + } case false: + index1 := tree.Indexs{int64(f1), int64(x1), int64(y1)} tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) } } @@ -79,14 +94,29 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo if err != nil { return false, fmt.Errorf("%w @spatialId2[%v]", err, indexSpatialId2) } - index2 := tree.Indexs{int64(f2), int64(x2), int64(y2)} // 取り出した要素の比較 result := false switch f2 < 0 { case true: - //index2[0] *= -1 - result = trMinus.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + convertedFIndices2, errAltConversion := transform.ConvertZToAltitudekey( + int64(f2), + int64(zoom2), + int64(zoom2), + 25, // 空間ID高さが1mになるズームレベル + 16777216, // 元の最大高さ(33,554,432m)を保ったまま正方向と負方向でfインデックスを半数ずつ導入 + ) + if errAltConversion != nil { + return false, fmt.Errorf("%w @spatialId2[%v]", errAltConversion, indexSpatialId2) + } + for _, index := range convertedFIndices2 { + result = trMinus.IsOverlap(tree.Indexs{index, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) + if result { + // 重複判定時、trueとnilを返却 + return result, nil + } + } case false: + index2 := tree.Indexs{int64(f2), int64(x2), int64(y2)} result = tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) } if result { @@ -182,12 +212,12 @@ func CheckExtendedSpatialIdsOverlap(extendedSpatialId1 string, extendedSpatialId } // 変換後のZoomレベルを指定して変換 - extendedSpatialIds1, err := ChangeExtendedSpatialIdsZoom([]string{extendedSpatialId1}, int64(targetHorizontalZoom), int64(targetVerticalZoom)) + extendedSpatialIds1, err := integrate.ChangeExtendedSpatialIdsZoom([]string{extendedSpatialId1}, int64(targetHorizontalZoom), int64(targetVerticalZoom)) if err != nil { // 変換エラー return false, err } - extendedSpatialIds2, err := ChangeExtendedSpatialIdsZoom([]string{extendedSpatialId2}, int64(targetHorizontalZoom), int64(targetVerticalZoom)) + extendedSpatialIds2, err := integrate.ChangeExtendedSpatialIdsZoom([]string{extendedSpatialId2}, int64(targetHorizontalZoom), int64(targetVerticalZoom)) if err != nil { // 変換エラー return false, err diff --git a/integrate/check_spatial_id_overlap_test.go b/detector/check_spatial_id_overlap_test.go similarity index 99% rename from integrate/check_spatial_id_overlap_test.go rename to detector/check_spatial_id_overlap_test.go index 807570f..45d6dd3 100644 --- a/integrate/check_spatial_id_overlap_test.go +++ b/detector/check_spatial_id_overlap_test.go @@ -1,4 +1,4 @@ -package integrate +package detector import ( "reflect" diff --git a/transform/convert_quadkey_and_Vertical_id.go b/transform/convert_quadkey_and_Vertical_id.go index 81c7269..7723d53 100644 --- a/transform/convert_quadkey_and_Vertical_id.go +++ b/transform/convert_quadkey_and_Vertical_id.go @@ -383,9 +383,9 @@ func ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys(extendedSpatialIDs []str var altitudeKeys []int64 quadkeys := []int64{} - currentID, error := object.NewExtendedSpatialID(idString) - if error != nil { - return nil, error + currentID, err := object.NewExtendedSpatialID(idString) + if err != nil { + return nil, err } // check zoom of currentID @@ -401,9 +401,9 @@ func ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys(extendedSpatialIDs []str } // B. convert vertical IDs to fit Output Vertical Zoom Level - altitudeKeys, error = convertZToAltitudekey(currentID.Z(), currentID.VZoom(), outputAltitudekeyZoom, zBaseExponent, zBaseOffset) - if error != nil { - return nil, error + altitudeKeys, err = ConvertZToAltitudekey(currentID.Z(), currentID.VZoom(), outputAltitudekeyZoom, zBaseExponent, zBaseOffset) + if err != nil { + return nil, err } // 水平方向と垂直方向の組み合わせを作成する @@ -672,7 +672,32 @@ func convertVerticallIDToBit(vZoom int64, vIndex int64, outputZoom int64, maxHei } -func convertZToAltitudekey(inputIndex int64, inputZoom int64, outputZoom int64, zBaseExponent int64, zBaseOffset int64) ([]int64, error) { +// ConvertZToAltitudekey (拡張)空間IDのz成分をaltitudekeyに高度変換する。 +// +// 変換前と変換後の精度差によって出力されるaltitudekeyの個数は増減する。 +// +// 引数 : +// +// inputIndex : 変換対象の(拡張)空間IDのz成分(fインデックス) +// +// inputZoom : 変換対象の(拡張)空間IDのズームレベル(zインデックス) +// +// outputZoom : 変換後のaltitudekeyの精度指定 +// +// zBaseExponent : 変換後のaltitudekeyの高さが1mとなるズームレベル +// +// zBaseOffset : ズームレベルがzBaseExponentのとき、高度0mにおけるaltitudekeyのインデックス値 +// +// 戻り値 : +// +// 変換後のaltitudekeyのスライス +// +// 戻り値(エラー) : +// +// 以下の条件に当てはまる場合、エラーインスタンスが返却される。 +// 入力インデックス不正 :inputIndexにそのズームレベル(inputZoom)で存在しないインデックス値が入力されていた場合。 +// 出力インデックス不正 :出力altitudekeyが出力ズームレベル(outputZoom)で存在しないインデックス値になった場合。 +func ConvertZToAltitudekey(inputIndex int64, inputZoom int64, outputZoom int64, zBaseExponent int64, zBaseOffset int64) ([]int64, error) { var ( outputIndexes []int64 diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index d655697..c813c53 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -1,1256 +1,1256 @@ -// 空間IDパッケージ -package transform - -import ( - "reflect" - "sort" - "strconv" - "testing" - - "github.com/trajectoryjp/spatial_id_go/v4/common/errors" - "github.com/trajectoryjp/spatial_id_go/v4/common/object" -) - -func TestConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(t *testing.T) { - // データの作成 - quadkeyAndVerticalIDList := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalID := object.NewQuadkeyAndVerticalID(6, 2914, 7, 74, 500, 0) // 231202 6/24/53/5/0 - quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) - newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, 0, 0) // 231002 "7/48/58/2/0","7/49/58/2/0","7/48/59/2/0","7/49/59/2/0" - quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDList2 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(9, 451739, 25, 0, 0, 0) // 123210212 "9/338/229/2/0" - quadkeyAndVerticalIDList2 = append(quadkeyAndVerticalIDList2, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDListE := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE := object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, -500, 0) // 231002 - quadkeyAndVerticalIDListE = append(quadkeyAndVerticalIDListE, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE2 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(6, 2882, 2, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE2 = append(quadkeyAndVerticalIDListE2, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE3 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(32, 2882, 2, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE3 = append(quadkeyAndVerticalIDListE3, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE4 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 2882, 36, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE4 = append(quadkeyAndVerticalIDListE4, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE5 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 4611686018427388065, 25, 0, 500, 0) // 231002 - quadkeyAndVerticalIDListE5 = append(quadkeyAndVerticalIDListE5, newQuadkeyAndVerticalIDE) - - datas := []struct { - quadkeyAndVerticalIDs []*object.QuadkeyAndVerticalID - ToHZoom int64 - ToVZoom int64 - result []string - pattern int64 - e error - }{ - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 6, ToVZoom: 20, pattern: 0, result: []string{"6/24/53/20/9", "6/24/49/20/0"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 7, ToVZoom: 2, pattern: 0, result: []string{"7/48/107/2/0", "7/49/107/2/0", "7/48/98/2/0", "7/49/98/2/0", "7/48/99/2/0", "7/49/99/2/0", "7/48/106/2/0", "7/49/106/2/0"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 5, ToVZoom: 8, pattern: 0, result: []string{"5/12/26/8/0", "5/12/24/8/0"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList2, ToHZoom: 9, ToVZoom: 2, pattern: 0, result: []string{"9/338/229/2/0"}}, - // 異常系(精度エラー) - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToHZoom: 0, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToHZoom: 5, ToVZoom: 36, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE2, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE3, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE4, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE5, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - } - - for _, p := range datas { - result, e := ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom) - sort.Strings(result) - sort.Strings(p.result) - if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d,%d) == %s, result: %s", p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom, p.result, result) - return - } - if p.pattern == 1 && e != p.e { - t.Log(t.Name()) - t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d,%d) == %+v, result: %+v", p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom, e, p.e) - } - } - -} - -func TestConvertQuadkeysAndVerticalIDsToSpatialIDs(t *testing.T) { - // データの作成 - quadkeyAndVerticalIDList := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalID := object.NewQuadkeyAndVerticalID(6, 2914, 7, 74, 500, 0) // 231202 6/24/53/5/0 - quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) - newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, 0, 0) // 231002 "7/48/58/2/0","7/49/58/2/0","7/48/59/2/0","7/49/59/2/0" - quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDList2 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(9, 451739, 25, 0, 0, 0) // 123210212 "9/338/229/2/0" - quadkeyAndVerticalIDList2 = append(quadkeyAndVerticalIDList2, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDListE := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE := object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, -500, 0) // 231002 - quadkeyAndVerticalIDListE = append(quadkeyAndVerticalIDListE, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE2 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(6, 2882, 2, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE2 = append(quadkeyAndVerticalIDListE2, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE3 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(32, 2882, 2, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE3 = append(quadkeyAndVerticalIDListE3, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE4 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 2882, 36, 10, 500, 0) // 231002 - quadkeyAndVerticalIDListE4 = append(quadkeyAndVerticalIDListE4, newQuadkeyAndVerticalIDE) - - quadkeyAndVerticalIDListE5 := []*object.QuadkeyAndVerticalID{} - newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 4611686018427388065, 25, 0, 500, 0) // 231002 - quadkeyAndVerticalIDListE5 = append(quadkeyAndVerticalIDListE5, newQuadkeyAndVerticalIDE) - - datas := []struct { - quadkeyAndVerticalIDs []*object.QuadkeyAndVerticalID - ToZoom int64 - result []string - pattern int64 - e error - }{ - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 6, pattern: 0, result: []string{"6/0/24/53", "6/0/24/49"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 7, pattern: 0, result: []string{"7/0/48/107", "7/0/49/107", "7/0/48/98", "7/0/49/98", "7/0/48/99", "7/0/49/99", "7/0/48/106", "7/0/49/106"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 5, pattern: 0, result: []string{"5/0/12/26", "5/0/12/24"}}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList2, ToZoom: 9, pattern: 0, result: []string{"9/0/338/229"}}, - // 異常系(精度エラー) - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToZoom: 0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE2, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE3, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE4, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE5, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - } - - for _, p := range datas { - result, e := ConvertQuadkeysAndVerticalIDsToSpatialIDs(p.quadkeyAndVerticalIDs, p.ToZoom) - sort.Strings(result) - sort.Strings(p.result) - if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("ConvertQuadkeysAndVerticalIDsToSpatialIDs(%+v,%d) == %s, result: %s", p.quadkeyAndVerticalIDs, p.ToZoom, p.result, result) - return - } - if p.pattern == 1 && e != p.e { - t.Log(t.Name()) - t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d) == %+v, result: %+v", p.quadkeyAndVerticalIDs, p.ToZoom, e, p.e) - } - } - -} - -func TestConvertExtendedSpatialIdsToQuadkeysAndVerticalIDs(t *testing.T) { - // 結果確認用の構造体を作成する - //"20/85263/65423"→ 00012322332320003333 →7432012031 21:29728048124,29728048125,29728048126,29728048127, - //horizontalID: "20/45621/43566", result: 3448507833}, //"00003031203000312321" - //horizontalID: "26/4562451/2343566", result: 26508024119725}, //"00012001233201113020012231" - //horizontalID: "26/1/2", result: 9}, //"00000000000000000000000021" - //horizontalID: "26/2/1", result: 6}, //"00000000000000000000000012" - //horizontalID: "5/4562451/2343566", result: 429}, //"12231" - - quadkeyAndVerticalIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID := object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 58}, {29728048124, 57}, {29728048125, 58}, {29728048125, 57}, {29728048126, 58}, {29728048126, 57}, {29728048127, 58}, {29728048127, 57}}, 10, 500, 0) - quadkeyAndVerticalIDs = append(quadkeyAndVerticalIDs, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsSpatialIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 56}}, 26, 0, 0) - quadkeyAndVerticalIDsSpatialIDs = append(quadkeyAndVerticalIDsSpatialIDs, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsHBorders1 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(1, [][2]int64{{0, 56}}, 26, 0, 0) - quadkeyAndVerticalIDsHBorders1 = append(quadkeyAndVerticalIDsHBorders1, newQuadkeyAndVerticalID) - quadkeyAndVerticalIDsHBorders31 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) - quadkeyAndVerticalIDsHBorders31 = append(quadkeyAndVerticalIDsHBorders31, newQuadkeyAndVerticalID) - - // quadkeyAndVerticalIDsValueE := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - // newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) - // quadkeyAndVerticalIDsValueE = append(quadkeyAndVerticalIDsValueE, newQuadkeyAndVerticalID) - - _, err := strconv.ParseInt("test", 10, 64) - datas := []struct { - spatialIds []string - ToHZoom int64 - ToVZoom int64 - maxHeight float64 - minHeight float64 - result []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID - resultLength int - pattern int64 // 0:正常 1:異常 2:個数(水平) 3:個数(垂直) - e error - }{ - // 正常 - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 21, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, pattern: 0}, - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 19, ToVZoom: 26, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDs, pattern: 0}, - - // 水平精度個数確認 低精度は1、高精度は精度差^4 - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 24, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 512, pattern: 2}, - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 2, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 2, pattern: 2}, - // 水平精度境界値 - {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders1, resultLength: 2, pattern: 2}, - {spatialIds: []string{"35/85263/65423/26/0"}, ToHZoom: 31, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders31, pattern: 0}, - - // 垂直精度境界値 - {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 21, ToVZoom: 0, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, - {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 21, ToVZoom: 1, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, - - // 異常系(精度エラー) - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 0, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 20, ToVZoom: -1, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"35/85263/65423/26/56"}, ToHZoom: 32, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"20/85263/65423/35/56"}, ToHZoom: 20, ToVZoom: 36, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"36/85263/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"20/85263/65423/36/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - - // 異常系(高度エラー) - {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: -500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - // 異常系(入力エラー) - {spatialIds: []string{"20/test/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, err.Error())}, - } - for _, p := range datas { - - result, e := ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight) - if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, p.result[0], result[0]) - } - if p.pattern == 1 && e != p.e { - t.Log(t.Name()) - t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, e, p.e) - } - if p.pattern == 2 && p.resultLength != len(result[0].InnerIDList()) { - t.Log(t.Name()) - t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) - } - if p.pattern == 3 && p.resultLength != len(result[0].InnerIDList()) { - t.Log(t.Name()) - t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) - } - - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_1(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 56}}, - 26, - 25, - 0, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/26/56"}, - 20, - 26, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_2(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 21, - [][2]int64{{29728048124, 56}, {29728048125, 56}, {29728048126, 56}, {29728048127, 56}}, - 26, - 25, - 0, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/26/56"}, - 21, - 26, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_3(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 7}}, - 12, - 14, // 2^14 - 0, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/26/56"}, - 20, - 12, - 14, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_4(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 54}}, - 12, - 14, - 188, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/26/56"}, - 20, - 12, - 14, - 188, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_5(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 21, - [][2]int64{{29728048124, 12}, {29728048124, 13}, {29728048125, 12}, {29728048125, 13}, {29728048126, 12}, {29728048126, 13}, {29728048127, 12}, {29728048127, 13}}, - 15, - 14, - -50, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/56"}, - 21, - 15, - 14, - -50, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example1(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 3}}, - 3, - 3, - 2, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/1"}, - 20, - 3, - 3, - 2, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example2(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 2}}, - 2, - 3, - 2, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/3"}, - 20, - 2, - 3, - 2, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example3(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 2}, {7432012031, 3}}, - 3, - 3, - 2, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/24/0"}, - 20, - 3, - 3, - 2, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example4(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 0}, {7432012031, 1}, {7432012031, 2}, {7432012031, 3}}, - 25, - 23, - -1, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/1"}, - 20, - 25, - 23, - -1, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example5(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( - 20, - [][2]int64{{7432012031, 0}}, - 23, - 25, - -1, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/1"}, - 20, - 23, - 25, - -1, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example6(t *testing.T) { - expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ - object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( // 例6 - 20, - [][2]int64{{7432012031, 0}}, - 23, - 25, - -1, - ), - } - - result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( - []string{"20/85263/65423/25/4"}, - 20, - 23, - 25, - -1, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertSpatialIdsToQuadkeysAndVerticalIDs(t *testing.T) { - quadkeyAndVerticalIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID := object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 1023}, {29728048125, 1023}, {29728048126, 1023}, {29728048127, 1023}}, 10, 500, 0) - quadkeyAndVerticalIDs = append(quadkeyAndVerticalIDs, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsUpup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 2047}, {29728048125, 2047}, {29728048126, 2047}, {29728048127, 2047}}, 11, 500, 0) - quadkeyAndVerticalIDsUpup = append(quadkeyAndVerticalIDsUpup, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsDwdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 511}}, 9, 500, 0) - quadkeyAndVerticalIDsDwdw = append(quadkeyAndVerticalIDsDwdw, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsDwup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 2047}}, 11, 500, 0) - quadkeyAndVerticalIDsDwup = append(quadkeyAndVerticalIDsDwup, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsSpatialIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 112}, {29728048124, 113}, {29728048125, 112}, {29728048125, 113}, {29728048126, 112}, {29728048126, 113}, {29728048127, 112}, {29728048127, 113}}, 21, 0, 0) - quadkeyAndVerticalIDsSpatialIDs = append(quadkeyAndVerticalIDsSpatialIDs, newQuadkeyAndVerticalID) - quadkeyAndVerticalIDsSpatialIDsUpdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 28}, {29728048125, 28}, {29728048126, 28}, {29728048127, 28}}, 19, 0, 0) - quadkeyAndVerticalIDsSpatialIDsUpdw = append(quadkeyAndVerticalIDsSpatialIDsUpdw, newQuadkeyAndVerticalID) - quadkeyAndVerticalIDsSpatialIDsDwup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 112}, {1858003007, 113}}, 21, 0, 0) - quadkeyAndVerticalIDsSpatialIDsDwup = append(quadkeyAndVerticalIDsSpatialIDsDwup, newQuadkeyAndVerticalID) - quadkeyAndVerticalIDsSpatialIDsDwdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 28}}, 19, 0, 0) - quadkeyAndVerticalIDsSpatialIDsDwdw = append(quadkeyAndVerticalIDsSpatialIDsDwdw, newQuadkeyAndVerticalID) - - quadkeyAndVerticalIDsHBorders1 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(1, [][2]int64{{0, 56}}, 26, 0, 0) - quadkeyAndVerticalIDsHBorders1 = append(quadkeyAndVerticalIDsHBorders1, newQuadkeyAndVerticalID) - quadkeyAndVerticalIDsHBorders31 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 0}}, 10, 500, 0) - quadkeyAndVerticalIDsHBorders31 = append(quadkeyAndVerticalIDsHBorders31, newQuadkeyAndVerticalID) - - // quadkeyAndVerticalIDsValueE := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} - // newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) - // quadkeyAndVerticalIDsValueE = append(quadkeyAndVerticalIDsValueE, newQuadkeyAndVerticalID) - - _, err := strconv.ParseInt("test", 10, 64) - datas := []struct { - spatialIds []string - ToHZoom int64 - ToVZoom int64 - maxHeight float64 - minHeight float64 - result []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID - resultLength int - pattern int64 // 0:正常 1:異常 2:個数(水平) 3:個数(垂直) - e error - }{ - // 正常 - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, pattern: 0}, //all1 - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 11, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsUpup, pattern: 0}, //all1 - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 9, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsDwdw, pattern: 0}, //all1 - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 11, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsDwup, pattern: 0}, //all1 - - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 21, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDs, pattern: 0}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 19, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsUpdw, pattern: 0}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 21, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsDwup, pattern: 0}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 19, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsDwdw, pattern: 0}, - - // 水平精度個数確認 低精度は1、高精度は精度差^4 - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 24, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 256, pattern: 2}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 2, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 1, pattern: 2}, - // 水平精度境界値 - {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders1, resultLength: 66, pattern: 2}, - {spatialIds: []string{"35/0/85263/65423"}, ToHZoom: 31, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders31, pattern: 0}, - - // 垂直精度境界値 - {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 21, ToVZoom: 0, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, - {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 21, ToVZoom: 1, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, - - // 異常系(精度エラー) - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 0, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 20, ToVZoom: -1, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"35/56/85263/65423"}, ToHZoom: 32, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 20, ToVZoom: 36, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - {spatialIds: []string{"36/56/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - - // 異常系(高度エラー) - {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: -500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, - // 異常系(入力エラー) - {spatialIds: []string{"20/56/test/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, err.Error())}, - } - for _, p := range datas { - result, e := ConvertSpatialIDsToQuadkeysAndVerticalIDs(p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight) - if p.pattern == 0 && !SortCheck(result, p.result) { - t.Log(t.Name()) - t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, p.result[0], result[0]) - } - if p.pattern == 1 && e != p.e { - t.Log(t.Name()) - t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, e, p.e) - } - - if p.pattern == 2 && p.resultLength != len(result[0].InnerIDList()) { - t.Log(t.Name()) - t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) - } - if p.pattern == 3 && p.resultLength != len(result[0].InnerIDList()) { - t.Log(t.Name()) - t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) - } - - } -} - -func SortCheck(r []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID, rt []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID) bool { - // 実行結果とテスト値が一致しない場合、false。それ以外の場合、true - for index, rTmp := range r { - rtTmp := rt[index] - if rtTmp.QuadkeyZoom() != rTmp.QuadkeyZoom() { - return false - } - if rtTmp.VerticalZoom() != rTmp.VerticalZoom() { - return false - } - if rtTmp.MaxHeight() != rTmp.MaxHeight() { - return false - } - if rtTmp.MinHeight() != rTmp.MinHeight() { - return false - } - for _, li := range rTmp.InnerIDList() { - b := false - for _, li2 := range rtTmp.InnerIDList() { - if li2 == li { - b = true - } - } - // テスト値の内部形式IDが関数の実行結果に存在しない場合、false - if !b { - return b - } - } - } - // 最後に到達した場合はTrue - return true -} - -func TestDeleteDuplicationList(t *testing.T) { - datas := []struct { - duplicationList []string - result []string - }{ - {duplicationList: []string{"20/562356/78451/23/956", "20/562356/78451/23/957", "20/562356/78451/23/956", "20/562356/78451/23/957"}, result: []string{"20/562356/78451/23/956", "20/562356/78451/23/957"}}, - } - for _, p := range datas { - result := deleteDuplicationList(p.duplicationList) - sort.Strings(result) - sort.Strings(p.result) - if !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("deleteDuplicationList(%s) == %s, result: %s", p.duplicationList, p.result, result) - } - - } -} - -func TestConvertHorizontalIDToQuadkey(t *testing.T) { - datas := []struct { - horizontalID string - result int64 - }{ - {horizontalID: "20/45621/43566", result: 3448507833}, //"00003031203000312321" - {horizontalID: "26/4562451/2343566", result: 26508024119725}, //"00012001233201113020012231" - {horizontalID: "26/1/2", result: 9}, //"00000000000000000000000021" - {horizontalID: "26/2/1", result: 6}, //"00000000000000000000000012" - {horizontalID: "5/4562451/2343566", result: 429}, //"12231" - ///{horizontalID: "31/2147483647/2147483647", result: 5}, - } - for _, p := range datas { - result := convertHorizontalIDToQuadkey(p.horizontalID) - if result != p.result { - t.Log(t.Name()) - t.Errorf("convertHorizontalIDToQuadkey(%s) == %d, result: %d", p.horizontalID, p.result, result) - } - } -} -func TestConvertQuadkeyToHorizontalID(t *testing.T) { - datas := []struct { - quadkey int64 - zoom int64 - resultX int64 - resultY int64 - }{ - {quadkey: 2914, zoom: 6, resultX: 24, resultY: 53}, //2914-""231202"" - {quadkey: 438, zoom: 6, resultX: 22, resultY: 13}, //438-"012312" - {quadkey: 14628, zoom: 7, resultX: 82, resultY: 100}, //14628-"3210210" - } - for _, p := range datas { - resultX, resultY := convertQuadkeyToHorizontalID(p.quadkey, p.zoom) - if resultX != p.resultX && resultY != p.resultY { - t.Log(t.Name()) - t.Errorf("convertQuadkeyToHorizontalID(%d,%d) == %d,%d, resultX: %d,resultY: %d,", p.quadkey, p.zoom, p.resultX, p.resultY, resultX, resultY) - } - - } -} -func TestConvertVerticallIDToBit(t *testing.T) { - datas := []struct { - vZoom int64 - vIndex int64 - outputZoom int64 - maxHeight float64 - minHeight float64 - result []int64 - }{ - // 正常系 1111−0000すべて - {vZoom: 16, vIndex: 0, outputZoom: 4, maxHeight: 500.0, minHeight: 0.0, result: []int64{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}, - // 正常系 bit形式の枠外(正方向) - {vZoom: 13, vIndex: 6, outputZoom: 5, maxHeight: 0.0, minHeight: -500.0, result: []int64{31}}, - // 正常系 bit形式の枠外(負方向) - {vZoom: 13, vIndex: -6, outputZoom: 5, maxHeight: 500.0, minHeight: 0.0, result: []int64{0}}, - {vZoom: 20, vIndex: 0, outputZoom: 8, maxHeight: 500.0, minHeight: -500.0, result: []int64{136, 128, 129, 130, 131, 132, 133, 134, 135}}, - //{vZoom: 35, vIndex: 0, outputZoom: 35, maxHeight: 1.0, minHeight: 0.0, result: []int64{136, 128, 129, 130, 131, 132, 133, 134, 135}}, - } - for _, p := range datas { - result := convertVerticallIDToBit(p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight) - if !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("convertVerticallIDToBit(%d,%d, %d,%f,%f) == %d, result: %d", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) - } - - } -} - -func TestCalcBitIndex(t *testing.T) { - datas := []struct { - altitude float64 - outputZoom int64 - maxHeight float64 - minHeight float64 - pattern int64 - result int64 - }{ - // 正常(地表) - {altitude: 256.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 524}, - // 正常(桁数補正) - {altitude: 0.0, outputZoom: 10, maxHeight: 256.0, minHeight: -256.0, pattern: 0, result: 512}, - // 正常(地中) - {altitude: -200.0, outputZoom: 10, maxHeight: 0.0, minHeight: -500.0, pattern: 0, result: 614}, - // 正常 All1 - {altitude: 2560.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 1023}, - // 正常 All0 - {altitude: -256.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 0}, - // 正常 0 - {altitude: -256.0, outputZoom: 1, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 0}, - // 正常 1 - {altitude: 512.0, outputZoom: 1, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 1}, - } - for _, p := range datas { - result := calcBitIndex(p.altitude, p.outputZoom, p.maxHeight, p.minHeight) - if result != p.result { - t.Log(t.Name()) - t.Errorf("calcBitIndex(%f, %d,%f,%f) == %d, result: %d", p.altitude, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) - } - } -} - -func TestConvertBitToVerticalID(t *testing.T) { - datas := []struct { - vZoom int64 - vIndex int64 - outputZoom int64 - maxHeight float64 - minHeight float64 - pattern int64 - result []string - }{ - // 正常系 - // 01010101010101010101010101→5592405 - {vZoom: 26, vIndex: 5592405, outputZoom: 26, maxHeight: 500, minHeight: 0, pattern: 0, result: []string{"26/83", "26/83"}}, - {vZoom: 2, vIndex: 4, outputZoom: 25, maxHeight: 500, minHeight: 0, pattern: 1, result: []string{"126", "500", "375"}}, - {vZoom: 26, vIndex: 5592405, outputZoom: 25, maxHeight: 0, minHeight: -500, pattern: 0, result: []string{"25/-459", "25/-459"}}, - // インデックスの補完 - {vZoom: 8, vIndex: 85, outputZoom: 26, maxHeight: 1000, minHeight: 0, pattern: 0, result: []string{"26/671", "26/664", "26/665", "26/666", "26/667", "26/668", "26/669", "26/670"}}, - } - for _, p := range datas { - result := convertBitToVerticalID(p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight) - if p.pattern == 0 { - if !reflect.DeepEqual(result, p.result) { - t.Log(t.Name()) - t.Errorf("convertBitToVerticalID(%d,%d, %d,%f,%f) == %s, result: %s", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) - } - } else { - // スライスの長さ,桁数 - length, _ := strconv.Atoi(p.result[0]) - if len(result) != length { - t.Log(t.Name()) - t.Errorf("convertBitToVerticalID(%d,%d, %d,%f,%f) == %s, result: %s", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result[0], result) - } - } - } - -} - -func TestQuadkeyCheckZoom(t *testing.T) { - // テストデータのテーブルを定義 - datas := []struct { - HZoom int64 - VZoom int64 - result bool - }{ - {HZoom: 1, VZoom: 12, result: true}, - {HZoom: 2, VZoom: 12, result: true}, - {HZoom: 31, VZoom: 12, result: true}, - {HZoom: 12, VZoom: 0, result: true}, - {HZoom: 12, VZoom: 1, result: true}, - {HZoom: 12, VZoom: 35, result: true}, - {HZoom: 0, VZoom: 12, result: false}, - {HZoom: 32, VZoom: 12, result: false}, - {HZoom: 12, VZoom: -1, result: false}, - {HZoom: 12, VZoom: 36, result: false}, - } - - for _, p := range datas { - result := quadkeyCheckZoom(p.HZoom, p.VZoom) - if result != p.result { - t.Log(t.Name()) - t.Errorf("quadkeyCheckZoom(%d, %d) == %s, result: %s", p.HZoom, p.VZoom, strconv.FormatBool(p.result), strconv.FormatBool(result)) - } - } -} - -func TestSpatialIDCheckZoom(t *testing.T) { - // テストデータのテーブルを定義 - datas := []struct { - HZoom int64 - VZoom int64 - result bool - }{ - {HZoom: 0, VZoom: 12, result: true}, - {HZoom: 1, VZoom: 12, result: true}, - {HZoom: 35, VZoom: 12, result: true}, - {HZoom: 12, VZoom: 0, result: true}, - {HZoom: 12, VZoom: 1, result: true}, - {HZoom: 12, VZoom: 35, result: true}, - {HZoom: -1, VZoom: 12, result: false}, - {HZoom: 36, VZoom: 12, result: false}, - {HZoom: 12, VZoom: -1, result: false}, - {HZoom: 12, VZoom: 36, result: false}, - } - - for _, p := range datas { - result := extendedSpatialIDCheckZoom(p.HZoom, p.VZoom) - if result != p.result { - t.Log(t.Name()) - t.Errorf("extendedSpatialIDCheckZoom(%d, %d) == %s, result: %s", p.HZoom, p.VZoom, strconv.FormatBool(p.result), strconv.FormatBool(result)) - } - } - -} - -func TestConvertZToAltitudekey_1(t *testing.T) { - expected := []int64{400, 401, 402, 403} - - result, error := convertZToAltitudekey( - 100, - 25, - 27, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_2(t *testing.T) { - expected := []int64{50} - - result, error := convertZToAltitudekey( - 100, - 25, - 24, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_3(t *testing.T) { - expected := []int64{100} - - result, error := convertZToAltitudekey( - 100, - 25, - 25, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_4(t *testing.T) { - expected := []int64{53} - - result, error := convertZToAltitudekey( - 100, - 25, - 25, - 25, - -47, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_5(t *testing.T) { - expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") - - result, error := convertZToAltitudekey( - 100, - 25, - 21, - 25, - -272, - ) - if error != expectedError { - t.Fatal(result, error) - } -} - -func TestConvertZToAltitudekey_6(t *testing.T) { - expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") - - result, error := convertZToAltitudekey( - 100, - 25, - 25, - 25, - -512, - ) - if error != expectedError { - t.Fatal(result, error) - } -} - -func TestConvertZToAltitudekey_7(t *testing.T) { - expected := []int64{1000} - - result, error := convertZToAltitudekey( - 28, - 25, - 14, - 25, - 2048000, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_8(t *testing.T) { - expected := []int64{100} - - result, error := convertZToAltitudekey( - 100, - 25, - 24, - 24, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToAltitudekey_9(t *testing.T) { - expected := []int64{800, 801, 802, 803, 804, 805, 806, 807} - - result, error := convertZToAltitudekey( - 100, - 25, - 27, - 24, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if !reflect.DeepEqual(result, expected) { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_1(t *testing.T) { - expected := int64(47) - - result, error := convertZToMinAltitudekey( - 0, - 25, - 25, - 25, - 47, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_2(t *testing.T) { - expected := int64(0) - - result, error := convertZToMinAltitudekey( - 0, - 25, - 25, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_3(t *testing.T) { - expected := int64(0) - - result, error := convertZToMinAltitudekey( - 0, - 25, - 27, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_4(t *testing.T) { - expected := int64(4) - - result, error := convertZToMinAltitudekey( - 1, - 25, - 27, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_5(t *testing.T) { - expected := int64(3276800) - - result, error := convertZToMinAltitudekey( - 100, - 10, - 25, - 25, - 0, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_6(t *testing.T) { - expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") - - result, error := convertZToMinAltitudekey( - 100, - 10, - 25, - 25, - -3276801, - ) - if error != expectedError { - t.Fatal(result, error) - } -} - -func TestConvertZToMinAltitudekey_7(t *testing.T) { - expected := int64(24) - - result, error := convertZToMinAltitudekey( - 47, - 25, - 24, - 25, - 2, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_8(t *testing.T) { - expected := int64(2) - - result, error := convertZToMinAltitudekey( - 47, - 25, - 20, - 25, - 32, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_9(t *testing.T) { - expected := int64(12) - - result, error := convertZToMinAltitudekey( - 47, - 25, - 12, - 14, - 4, - ) - if error != nil { - t.Fatal(error) - } - - if result != expected { - t.Fatal(result) - } -} - -func TestConvertZToMinAltitudekey_10(t *testing.T) { - expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") - - result, error := convertZToMinAltitudekey( - -1, - 25, - 25, - 25, - 0, - ) - if error != expectedError { - t.Fatal(result, error) - } -} - -func TestConvertZToMinAltitudekey_11(t *testing.T) { - expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") - - result, error := convertZToMinAltitudekey( - -100, - 25, - 26, - 24, - 51, - ) - if error != expectedError { - t.Fatal(result, error) - } -} +// 空間IDパッケージ +package transform + +import ( + "reflect" + "sort" + "strconv" + "testing" + + "github.com/trajectoryjp/spatial_id_go/v4/common/errors" + "github.com/trajectoryjp/spatial_id_go/v4/common/object" +) + +func TestConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(t *testing.T) { + // データの作成 + quadkeyAndVerticalIDList := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalID := object.NewQuadkeyAndVerticalID(6, 2914, 7, 74, 500, 0) // 231202 6/24/53/5/0 + quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) + newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, 0, 0) // 231002 "7/48/58/2/0","7/49/58/2/0","7/48/59/2/0","7/49/59/2/0" + quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDList2 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(9, 451739, 25, 0, 0, 0) // 123210212 "9/338/229/2/0" + quadkeyAndVerticalIDList2 = append(quadkeyAndVerticalIDList2, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDListE := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE := object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, -500, 0) // 231002 + quadkeyAndVerticalIDListE = append(quadkeyAndVerticalIDListE, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE2 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(6, 2882, 2, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE2 = append(quadkeyAndVerticalIDListE2, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE3 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(32, 2882, 2, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE3 = append(quadkeyAndVerticalIDListE3, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE4 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 2882, 36, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE4 = append(quadkeyAndVerticalIDListE4, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE5 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 4611686018427388065, 25, 0, 500, 0) // 231002 + quadkeyAndVerticalIDListE5 = append(quadkeyAndVerticalIDListE5, newQuadkeyAndVerticalIDE) + + datas := []struct { + quadkeyAndVerticalIDs []*object.QuadkeyAndVerticalID + ToHZoom int64 + ToVZoom int64 + result []string + pattern int64 + e error + }{ + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 6, ToVZoom: 20, pattern: 0, result: []string{"6/24/53/20/9", "6/24/49/20/0"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 7, ToVZoom: 2, pattern: 0, result: []string{"7/48/107/2/0", "7/49/107/2/0", "7/48/98/2/0", "7/49/98/2/0", "7/48/99/2/0", "7/49/99/2/0", "7/48/106/2/0", "7/49/106/2/0"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToHZoom: 5, ToVZoom: 8, pattern: 0, result: []string{"5/12/26/8/0", "5/12/24/8/0"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList2, ToHZoom: 9, ToVZoom: 2, pattern: 0, result: []string{"9/338/229/2/0"}}, + // 異常系(精度エラー) + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToHZoom: 0, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToHZoom: 5, ToVZoom: 36, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE2, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE3, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE4, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE5, ToHZoom: 5, ToVZoom: 35, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + } + + for _, p := range datas { + result, e := ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom) + sort.Strings(result) + sort.Strings(p.result) + if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d,%d) == %s, result: %s", p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom, p.result, result) + return + } + if p.pattern == 1 && e != p.e { + t.Log(t.Name()) + t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d,%d) == %+v, result: %+v", p.quadkeyAndVerticalIDs, p.ToHZoom, p.ToVZoom, e, p.e) + } + } + +} + +func TestConvertQuadkeysAndVerticalIDsToSpatialIDs(t *testing.T) { + // データの作成 + quadkeyAndVerticalIDList := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalID := object.NewQuadkeyAndVerticalID(6, 2914, 7, 74, 500, 0) // 231202 6/24/53/5/0 + quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) + newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, 0, 0) // 231002 "7/48/58/2/0","7/49/58/2/0","7/48/59/2/0","7/49/59/2/0" + quadkeyAndVerticalIDList = append(quadkeyAndVerticalIDList, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDList2 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewQuadkeyAndVerticalID(9, 451739, 25, 0, 0, 0) // 123210212 "9/338/229/2/0" + quadkeyAndVerticalIDList2 = append(quadkeyAndVerticalIDList2, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDListE := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE := object.NewQuadkeyAndVerticalID(6, 2882, 25, 0, -500, 0) // 231002 + quadkeyAndVerticalIDListE = append(quadkeyAndVerticalIDListE, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE2 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(6, 2882, 2, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE2 = append(quadkeyAndVerticalIDListE2, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE3 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(32, 2882, 2, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE3 = append(quadkeyAndVerticalIDListE3, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE4 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 2882, 36, 10, 500, 0) // 231002 + quadkeyAndVerticalIDListE4 = append(quadkeyAndVerticalIDListE4, newQuadkeyAndVerticalIDE) + + quadkeyAndVerticalIDListE5 := []*object.QuadkeyAndVerticalID{} + newQuadkeyAndVerticalIDE = object.NewQuadkeyAndVerticalID(31, 4611686018427388065, 25, 0, 500, 0) // 231002 + quadkeyAndVerticalIDListE5 = append(quadkeyAndVerticalIDListE5, newQuadkeyAndVerticalIDE) + + datas := []struct { + quadkeyAndVerticalIDs []*object.QuadkeyAndVerticalID + ToZoom int64 + result []string + pattern int64 + e error + }{ + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 6, pattern: 0, result: []string{"6/0/24/53", "6/0/24/49"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 7, pattern: 0, result: []string{"7/0/48/107", "7/0/49/107", "7/0/48/98", "7/0/49/98", "7/0/48/99", "7/0/49/99", "7/0/48/106", "7/0/49/106"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList, ToZoom: 5, pattern: 0, result: []string{"5/0/12/26", "5/0/12/24"}}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDList2, ToZoom: 9, pattern: 0, result: []string{"9/0/338/229"}}, + // 異常系(精度エラー) + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToZoom: 0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE2, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE3, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE4, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {quadkeyAndVerticalIDs: quadkeyAndVerticalIDListE5, ToZoom: 5, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + } + + for _, p := range datas { + result, e := ConvertQuadkeysAndVerticalIDsToSpatialIDs(p.quadkeyAndVerticalIDs, p.ToZoom) + sort.Strings(result) + sort.Strings(p.result) + if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("ConvertQuadkeysAndVerticalIDsToSpatialIDs(%+v,%d) == %s, result: %s", p.quadkeyAndVerticalIDs, p.ToZoom, p.result, result) + return + } + if p.pattern == 1 && e != p.e { + t.Log(t.Name()) + t.Errorf("ConvertQuadkeysAndVerticalIDsToExtendedSpatialIDs(%+v,%d) == %+v, result: %+v", p.quadkeyAndVerticalIDs, p.ToZoom, e, p.e) + } + } + +} + +func TestConvertExtendedSpatialIdsToQuadkeysAndVerticalIDs(t *testing.T) { + // 結果確認用の構造体を作成する + //"20/85263/65423"→ 00012322332320003333 →7432012031 21:29728048124,29728048125,29728048126,29728048127, + //horizontalID: "20/45621/43566", result: 3448507833}, //"00003031203000312321" + //horizontalID: "26/4562451/2343566", result: 26508024119725}, //"00012001233201113020012231" + //horizontalID: "26/1/2", result: 9}, //"00000000000000000000000021" + //horizontalID: "26/2/1", result: 6}, //"00000000000000000000000012" + //horizontalID: "5/4562451/2343566", result: 429}, //"12231" + + quadkeyAndVerticalIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID := object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 58}, {29728048124, 57}, {29728048125, 58}, {29728048125, 57}, {29728048126, 58}, {29728048126, 57}, {29728048127, 58}, {29728048127, 57}}, 10, 500, 0) + quadkeyAndVerticalIDs = append(quadkeyAndVerticalIDs, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsSpatialIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 56}}, 26, 0, 0) + quadkeyAndVerticalIDsSpatialIDs = append(quadkeyAndVerticalIDsSpatialIDs, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsHBorders1 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(1, [][2]int64{{0, 56}}, 26, 0, 0) + quadkeyAndVerticalIDsHBorders1 = append(quadkeyAndVerticalIDsHBorders1, newQuadkeyAndVerticalID) + quadkeyAndVerticalIDsHBorders31 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) + quadkeyAndVerticalIDsHBorders31 = append(quadkeyAndVerticalIDsHBorders31, newQuadkeyAndVerticalID) + + // quadkeyAndVerticalIDsValueE := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + // newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) + // quadkeyAndVerticalIDsValueE = append(quadkeyAndVerticalIDsValueE, newQuadkeyAndVerticalID) + + _, err := strconv.ParseInt("test", 10, 64) + datas := []struct { + spatialIds []string + ToHZoom int64 + ToVZoom int64 + maxHeight float64 + minHeight float64 + result []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID + resultLength int + pattern int64 // 0:正常 1:異常 2:個数(水平) 3:個数(垂直) + e error + }{ + // 正常 + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 21, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, pattern: 0}, + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 19, ToVZoom: 26, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDs, pattern: 0}, + + // 水平精度個数確認 低精度は1、高精度は精度差^4 + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 24, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 512, pattern: 2}, + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 2, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 2, pattern: 2}, + // 水平精度境界値 + {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders1, resultLength: 2, pattern: 2}, + {spatialIds: []string{"35/85263/65423/26/0"}, ToHZoom: 31, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders31, pattern: 0}, + + // 垂直精度境界値 + {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 21, ToVZoom: 0, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, + {spatialIds: []string{"20/85263/65423/26/0"}, ToHZoom: 21, ToVZoom: 1, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, + + // 異常系(精度エラー) + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 0, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 20, ToVZoom: -1, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"35/85263/65423/26/56"}, ToHZoom: 32, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"20/85263/65423/35/56"}, ToHZoom: 20, ToVZoom: 36, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"36/85263/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"20/85263/65423/36/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + + // 異常系(高度エラー) + {spatialIds: []string{"20/85263/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: -500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + // 異常系(入力エラー) + {spatialIds: []string{"20/test/65423/26/56"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, err.Error())}, + } + for _, p := range datas { + + result, e := ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight) + if p.pattern == 0 && !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, p.result[0], result[0]) + } + if p.pattern == 1 && e != p.e { + t.Log(t.Name()) + t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, e, p.e) + } + if p.pattern == 2 && p.resultLength != len(result[0].InnerIDList()) { + t.Log(t.Name()) + t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) + } + if p.pattern == 3 && p.resultLength != len(result[0].InnerIDList()) { + t.Log(t.Name()) + t.Errorf("ConvertExtendedSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) + } + + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_1(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 56}}, + 26, + 25, + 0, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/26/56"}, + 20, + 26, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_2(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 21, + [][2]int64{{29728048124, 56}, {29728048125, 56}, {29728048126, 56}, {29728048127, 56}}, + 26, + 25, + 0, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/26/56"}, + 21, + 26, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_3(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 7}}, + 12, + 14, // 2^14 + 0, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/26/56"}, + 20, + 12, + 14, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_4(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 54}}, + 12, + 14, + 188, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/26/56"}, + 20, + 12, + 14, + 188, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_5(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 21, + [][2]int64{{29728048124, 12}, {29728048124, 13}, {29728048125, 12}, {29728048125, 13}, {29728048126, 12}, {29728048126, 13}, {29728048127, 12}, {29728048127, 13}}, + 15, + 14, + -50, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/56"}, + 21, + 15, + 14, + -50, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example1(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 3}}, + 3, + 3, + 2, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/1"}, + 20, + 3, + 3, + 2, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example2(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 2}}, + 2, + 3, + 2, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/3"}, + 20, + 2, + 3, + 2, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example3(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 2}, {7432012031, 3}}, + 3, + 3, + 2, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/24/0"}, + 20, + 3, + 3, + 2, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example4(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 0}, {7432012031, 1}, {7432012031, 2}, {7432012031, 3}}, + 25, + 23, + -1, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/1"}, + 20, + 25, + 23, + -1, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example5(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( + 20, + [][2]int64{{7432012031, 0}}, + 23, + 25, + -1, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/1"}, + 20, + 23, + 25, + -1, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys_Example6(t *testing.T) { + expected := []*object.FromExtendedSpatialIDToQuadkeyAndAltitudekey{ + object.NewFromExtendedSpatialIDToQuadkeyAndAltitudekey( // 例6 + 20, + [][2]int64{{7432012031, 0}}, + 23, + 25, + -1, + ), + } + + result, error := ConvertExtendedSpatialIDsToQuadkeysAndAltitudekeys( + []string{"20/85263/65423/25/4"}, + 20, + 23, + 25, + -1, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertSpatialIdsToQuadkeysAndVerticalIDs(t *testing.T) { + quadkeyAndVerticalIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID := object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 1023}, {29728048125, 1023}, {29728048126, 1023}, {29728048127, 1023}}, 10, 500, 0) + quadkeyAndVerticalIDs = append(quadkeyAndVerticalIDs, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsUpup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 2047}, {29728048125, 2047}, {29728048126, 2047}, {29728048127, 2047}}, 11, 500, 0) + quadkeyAndVerticalIDsUpup = append(quadkeyAndVerticalIDsUpup, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsDwdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 511}}, 9, 500, 0) + quadkeyAndVerticalIDsDwdw = append(quadkeyAndVerticalIDsDwdw, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsDwup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 2047}}, 11, 500, 0) + quadkeyAndVerticalIDsDwup = append(quadkeyAndVerticalIDsDwup, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsSpatialIDs := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 112}, {29728048124, 113}, {29728048125, 112}, {29728048125, 113}, {29728048126, 112}, {29728048126, 113}, {29728048127, 112}, {29728048127, 113}}, 21, 0, 0) + quadkeyAndVerticalIDsSpatialIDs = append(quadkeyAndVerticalIDsSpatialIDs, newQuadkeyAndVerticalID) + quadkeyAndVerticalIDsSpatialIDsUpdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(21, [][2]int64{{29728048124, 28}, {29728048125, 28}, {29728048126, 28}, {29728048127, 28}}, 19, 0, 0) + quadkeyAndVerticalIDsSpatialIDsUpdw = append(quadkeyAndVerticalIDsSpatialIDsUpdw, newQuadkeyAndVerticalID) + quadkeyAndVerticalIDsSpatialIDsDwup := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 112}, {1858003007, 113}}, 21, 0, 0) + quadkeyAndVerticalIDsSpatialIDsDwup = append(quadkeyAndVerticalIDsSpatialIDsDwup, newQuadkeyAndVerticalID) + quadkeyAndVerticalIDsSpatialIDsDwdw := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(19, [][2]int64{{1858003007, 28}}, 19, 0, 0) + quadkeyAndVerticalIDsSpatialIDsDwdw = append(quadkeyAndVerticalIDsSpatialIDsDwdw, newQuadkeyAndVerticalID) + + quadkeyAndVerticalIDsHBorders1 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(1, [][2]int64{{0, 56}}, 26, 0, 0) + quadkeyAndVerticalIDsHBorders1 = append(quadkeyAndVerticalIDsHBorders1, newQuadkeyAndVerticalID) + quadkeyAndVerticalIDsHBorders31 := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 0}}, 10, 500, 0) + quadkeyAndVerticalIDsHBorders31 = append(quadkeyAndVerticalIDsHBorders31, newQuadkeyAndVerticalID) + + // quadkeyAndVerticalIDsValueE := []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID{} + // newQuadkeyAndVerticalID = object.NewFromExtendedSpatialIDToQuadkeyAndVerticalID(31, [][2]int64{{29031296, 1}, {29031296, 0}}, 10, 500, 0) + // quadkeyAndVerticalIDsValueE = append(quadkeyAndVerticalIDsValueE, newQuadkeyAndVerticalID) + + _, err := strconv.ParseInt("test", 10, 64) + datas := []struct { + spatialIds []string + ToHZoom int64 + ToVZoom int64 + maxHeight float64 + minHeight float64 + result []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID + resultLength int + pattern int64 // 0:正常 1:異常 2:個数(水平) 3:個数(垂直) + e error + }{ + // 正常 + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, pattern: 0}, //all1 + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 11, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsUpup, pattern: 0}, //all1 + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 9, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsDwdw, pattern: 0}, //all1 + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 11, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsDwup, pattern: 0}, //all1 + + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 21, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDs, pattern: 0}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 21, ToVZoom: 19, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsUpdw, pattern: 0}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 21, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsDwup, pattern: 0}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 19, ToVZoom: 19, maxHeight: 0, minHeight: 0.0, result: quadkeyAndVerticalIDsSpatialIDsDwdw, pattern: 0}, + + // 水平精度個数確認 低精度は1、高精度は精度差^4 + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 24, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 256, pattern: 2}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 2, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 1, pattern: 2}, + // 水平精度境界値 + {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders1, resultLength: 66, pattern: 2}, + {spatialIds: []string{"35/0/85263/65423"}, ToHZoom: 31, ToVZoom: 10, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDsHBorders31, pattern: 0}, + + // 垂直精度境界値 + {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 21, ToVZoom: 0, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, + {spatialIds: []string{"20/0/85263/65423"}, ToHZoom: 21, ToVZoom: 1, maxHeight: 500, minHeight: 0.0, result: quadkeyAndVerticalIDs, resultLength: 4, pattern: 3}, + + // 異常系(精度エラー) + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 0, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 20, ToVZoom: -1, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"35/56/85263/65423"}, ToHZoom: 32, ToVZoom: 10, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 20, ToVZoom: 36, maxHeight: 0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + {spatialIds: []string{"36/56/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + + // 異常系(高度エラー) + {spatialIds: []string{"20/56/85263/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: -500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, "")}, + // 異常系(入力エラー) + {spatialIds: []string{"20/56/test/65423"}, ToHZoom: 1, ToVZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 1, e: errors.NewSpatialIdError(errors.InputValueErrorCode, err.Error())}, + } + for _, p := range datas { + result, e := ConvertSpatialIDsToQuadkeysAndVerticalIDs(p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight) + if p.pattern == 0 && !SortCheck(result, p.result) { + t.Log(t.Name()) + t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, p.result[0], result[0]) + } + if p.pattern == 1 && e != p.e { + t.Log(t.Name()) + t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, e, p.e) + } + + if p.pattern == 2 && p.resultLength != len(result[0].InnerIDList()) { + t.Log(t.Name()) + t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) + } + if p.pattern == 3 && p.resultLength != len(result[0].InnerIDList()) { + t.Log(t.Name()) + t.Errorf("ConvertSpatialIDsToQuadkeysAndVerticalIDs(%s,%d,%d,%f,%f) == %+v, result: %+v", p.spatialIds, p.ToHZoom, p.ToVZoom, p.maxHeight, p.minHeight, len(result[0].InnerIDList()), p.resultLength) + } + + } +} + +func SortCheck(r []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID, rt []*object.FromExtendedSpatialIDToQuadkeyAndVerticalID) bool { + // 実行結果とテスト値が一致しない場合、false。それ以外の場合、true + for index, rTmp := range r { + rtTmp := rt[index] + if rtTmp.QuadkeyZoom() != rTmp.QuadkeyZoom() { + return false + } + if rtTmp.VerticalZoom() != rTmp.VerticalZoom() { + return false + } + if rtTmp.MaxHeight() != rTmp.MaxHeight() { + return false + } + if rtTmp.MinHeight() != rTmp.MinHeight() { + return false + } + for _, li := range rTmp.InnerIDList() { + b := false + for _, li2 := range rtTmp.InnerIDList() { + if li2 == li { + b = true + } + } + // テスト値の内部形式IDが関数の実行結果に存在しない場合、false + if !b { + return b + } + } + } + // 最後に到達した場合はTrue + return true +} + +func TestDeleteDuplicationList(t *testing.T) { + datas := []struct { + duplicationList []string + result []string + }{ + {duplicationList: []string{"20/562356/78451/23/956", "20/562356/78451/23/957", "20/562356/78451/23/956", "20/562356/78451/23/957"}, result: []string{"20/562356/78451/23/956", "20/562356/78451/23/957"}}, + } + for _, p := range datas { + result := deleteDuplicationList(p.duplicationList) + sort.Strings(result) + sort.Strings(p.result) + if !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("deleteDuplicationList(%s) == %s, result: %s", p.duplicationList, p.result, result) + } + + } +} + +func TestConvertHorizontalIDToQuadkey(t *testing.T) { + datas := []struct { + horizontalID string + result int64 + }{ + {horizontalID: "20/45621/43566", result: 3448507833}, //"00003031203000312321" + {horizontalID: "26/4562451/2343566", result: 26508024119725}, //"00012001233201113020012231" + {horizontalID: "26/1/2", result: 9}, //"00000000000000000000000021" + {horizontalID: "26/2/1", result: 6}, //"00000000000000000000000012" + {horizontalID: "5/4562451/2343566", result: 429}, //"12231" + ///{horizontalID: "31/2147483647/2147483647", result: 5}, + } + for _, p := range datas { + result := convertHorizontalIDToQuadkey(p.horizontalID) + if result != p.result { + t.Log(t.Name()) + t.Errorf("convertHorizontalIDToQuadkey(%s) == %d, result: %d", p.horizontalID, p.result, result) + } + } +} +func TestConvertQuadkeyToHorizontalID(t *testing.T) { + datas := []struct { + quadkey int64 + zoom int64 + resultX int64 + resultY int64 + }{ + {quadkey: 2914, zoom: 6, resultX: 24, resultY: 53}, //2914-""231202"" + {quadkey: 438, zoom: 6, resultX: 22, resultY: 13}, //438-"012312" + {quadkey: 14628, zoom: 7, resultX: 82, resultY: 100}, //14628-"3210210" + } + for _, p := range datas { + resultX, resultY := convertQuadkeyToHorizontalID(p.quadkey, p.zoom) + if resultX != p.resultX && resultY != p.resultY { + t.Log(t.Name()) + t.Errorf("convertQuadkeyToHorizontalID(%d,%d) == %d,%d, resultX: %d,resultY: %d,", p.quadkey, p.zoom, p.resultX, p.resultY, resultX, resultY) + } + + } +} +func TestConvertVerticallIDToBit(t *testing.T) { + datas := []struct { + vZoom int64 + vIndex int64 + outputZoom int64 + maxHeight float64 + minHeight float64 + result []int64 + }{ + // 正常系 1111−0000すべて + {vZoom: 16, vIndex: 0, outputZoom: 4, maxHeight: 500.0, minHeight: 0.0, result: []int64{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}, + // 正常系 bit形式の枠外(正方向) + {vZoom: 13, vIndex: 6, outputZoom: 5, maxHeight: 0.0, minHeight: -500.0, result: []int64{31}}, + // 正常系 bit形式の枠外(負方向) + {vZoom: 13, vIndex: -6, outputZoom: 5, maxHeight: 500.0, minHeight: 0.0, result: []int64{0}}, + {vZoom: 20, vIndex: 0, outputZoom: 8, maxHeight: 500.0, minHeight: -500.0, result: []int64{136, 128, 129, 130, 131, 132, 133, 134, 135}}, + //{vZoom: 35, vIndex: 0, outputZoom: 35, maxHeight: 1.0, minHeight: 0.0, result: []int64{136, 128, 129, 130, 131, 132, 133, 134, 135}}, + } + for _, p := range datas { + result := convertVerticallIDToBit(p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight) + if !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("convertVerticallIDToBit(%d,%d, %d,%f,%f) == %d, result: %d", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) + } + + } +} + +func TestCalcBitIndex(t *testing.T) { + datas := []struct { + altitude float64 + outputZoom int64 + maxHeight float64 + minHeight float64 + pattern int64 + result int64 + }{ + // 正常(地表) + {altitude: 256.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 524}, + // 正常(桁数補正) + {altitude: 0.0, outputZoom: 10, maxHeight: 256.0, minHeight: -256.0, pattern: 0, result: 512}, + // 正常(地中) + {altitude: -200.0, outputZoom: 10, maxHeight: 0.0, minHeight: -500.0, pattern: 0, result: 614}, + // 正常 All1 + {altitude: 2560.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 1023}, + // 正常 All0 + {altitude: -256.0, outputZoom: 10, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 0}, + // 正常 0 + {altitude: -256.0, outputZoom: 1, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 0}, + // 正常 1 + {altitude: 512.0, outputZoom: 1, maxHeight: 500.0, minHeight: 0.0, pattern: 0, result: 1}, + } + for _, p := range datas { + result := calcBitIndex(p.altitude, p.outputZoom, p.maxHeight, p.minHeight) + if result != p.result { + t.Log(t.Name()) + t.Errorf("calcBitIndex(%f, %d,%f,%f) == %d, result: %d", p.altitude, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) + } + } +} + +func TestConvertBitToVerticalID(t *testing.T) { + datas := []struct { + vZoom int64 + vIndex int64 + outputZoom int64 + maxHeight float64 + minHeight float64 + pattern int64 + result []string + }{ + // 正常系 + // 01010101010101010101010101→5592405 + {vZoom: 26, vIndex: 5592405, outputZoom: 26, maxHeight: 500, minHeight: 0, pattern: 0, result: []string{"26/83", "26/83"}}, + {vZoom: 2, vIndex: 4, outputZoom: 25, maxHeight: 500, minHeight: 0, pattern: 1, result: []string{"126", "500", "375"}}, + {vZoom: 26, vIndex: 5592405, outputZoom: 25, maxHeight: 0, minHeight: -500, pattern: 0, result: []string{"25/-459", "25/-459"}}, + // インデックスの補完 + {vZoom: 8, vIndex: 85, outputZoom: 26, maxHeight: 1000, minHeight: 0, pattern: 0, result: []string{"26/671", "26/664", "26/665", "26/666", "26/667", "26/668", "26/669", "26/670"}}, + } + for _, p := range datas { + result := convertBitToVerticalID(p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight) + if p.pattern == 0 { + if !reflect.DeepEqual(result, p.result) { + t.Log(t.Name()) + t.Errorf("convertBitToVerticalID(%d,%d, %d,%f,%f) == %s, result: %s", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result, result) + } + } else { + // スライスの長さ,桁数 + length, _ := strconv.Atoi(p.result[0]) + if len(result) != length { + t.Log(t.Name()) + t.Errorf("convertBitToVerticalID(%d,%d, %d,%f,%f) == %s, result: %s", p.vZoom, p.vIndex, p.outputZoom, p.maxHeight, p.minHeight, p.result[0], result) + } + } + } + +} + +func TestQuadkeyCheckZoom(t *testing.T) { + // テストデータのテーブルを定義 + datas := []struct { + HZoom int64 + VZoom int64 + result bool + }{ + {HZoom: 1, VZoom: 12, result: true}, + {HZoom: 2, VZoom: 12, result: true}, + {HZoom: 31, VZoom: 12, result: true}, + {HZoom: 12, VZoom: 0, result: true}, + {HZoom: 12, VZoom: 1, result: true}, + {HZoom: 12, VZoom: 35, result: true}, + {HZoom: 0, VZoom: 12, result: false}, + {HZoom: 32, VZoom: 12, result: false}, + {HZoom: 12, VZoom: -1, result: false}, + {HZoom: 12, VZoom: 36, result: false}, + } + + for _, p := range datas { + result := quadkeyCheckZoom(p.HZoom, p.VZoom) + if result != p.result { + t.Log(t.Name()) + t.Errorf("quadkeyCheckZoom(%d, %d) == %s, result: %s", p.HZoom, p.VZoom, strconv.FormatBool(p.result), strconv.FormatBool(result)) + } + } +} + +func TestSpatialIDCheckZoom(t *testing.T) { + // テストデータのテーブルを定義 + datas := []struct { + HZoom int64 + VZoom int64 + result bool + }{ + {HZoom: 0, VZoom: 12, result: true}, + {HZoom: 1, VZoom: 12, result: true}, + {HZoom: 35, VZoom: 12, result: true}, + {HZoom: 12, VZoom: 0, result: true}, + {HZoom: 12, VZoom: 1, result: true}, + {HZoom: 12, VZoom: 35, result: true}, + {HZoom: -1, VZoom: 12, result: false}, + {HZoom: 36, VZoom: 12, result: false}, + {HZoom: 12, VZoom: -1, result: false}, + {HZoom: 12, VZoom: 36, result: false}, + } + + for _, p := range datas { + result := extendedSpatialIDCheckZoom(p.HZoom, p.VZoom) + if result != p.result { + t.Log(t.Name()) + t.Errorf("extendedSpatialIDCheckZoom(%d, %d) == %s, result: %s", p.HZoom, p.VZoom, strconv.FormatBool(p.result), strconv.FormatBool(result)) + } + } + +} + +func TestConvertZToAltitudekey_1(t *testing.T) { + expected := []int64{400, 401, 402, 403} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 27, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_2(t *testing.T) { + expected := []int64{50} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 24, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_3(t *testing.T) { + expected := []int64{100} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 25, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_4(t *testing.T) { + expected := []int64{53} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 25, + 25, + -47, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_5(t *testing.T) { + expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") + + result, error := ConvertZToAltitudekey( + 100, + 25, + 21, + 25, + -272, + ) + if error != expectedError { + t.Fatal(result, error) + } +} + +func TestConvertZToAltitudekey_6(t *testing.T) { + expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") + + result, error := ConvertZToAltitudekey( + 100, + 25, + 25, + 25, + -512, + ) + if error != expectedError { + t.Fatal(result, error) + } +} + +func TestConvertZToAltitudekey_7(t *testing.T) { + expected := []int64{1000} + + result, error := ConvertZToAltitudekey( + 28, + 25, + 14, + 25, + 2048000, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_8(t *testing.T) { + expected := []int64{100} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 24, + 24, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToAltitudekey_9(t *testing.T) { + expected := []int64{800, 801, 802, 803, 804, 805, 806, 807} + + result, error := ConvertZToAltitudekey( + 100, + 25, + 27, + 24, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_1(t *testing.T) { + expected := int64(47) + + result, error := convertZToMinAltitudekey( + 0, + 25, + 25, + 25, + 47, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_2(t *testing.T) { + expected := int64(0) + + result, error := convertZToMinAltitudekey( + 0, + 25, + 25, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_3(t *testing.T) { + expected := int64(0) + + result, error := convertZToMinAltitudekey( + 0, + 25, + 27, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_4(t *testing.T) { + expected := int64(4) + + result, error := convertZToMinAltitudekey( + 1, + 25, + 27, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_5(t *testing.T) { + expected := int64(3276800) + + result, error := convertZToMinAltitudekey( + 100, + 10, + 25, + 25, + 0, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_6(t *testing.T) { + expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") + + result, error := convertZToMinAltitudekey( + 100, + 10, + 25, + 25, + -3276801, + ) + if error != expectedError { + t.Fatal(result, error) + } +} + +func TestConvertZToMinAltitudekey_7(t *testing.T) { + expected := int64(24) + + result, error := convertZToMinAltitudekey( + 47, + 25, + 24, + 25, + 2, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_8(t *testing.T) { + expected := int64(2) + + result, error := convertZToMinAltitudekey( + 47, + 25, + 20, + 25, + 32, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_9(t *testing.T) { + expected := int64(12) + + result, error := convertZToMinAltitudekey( + 47, + 25, + 12, + 14, + 4, + ) + if error != nil { + t.Fatal(error) + } + + if result != expected { + t.Fatal(result) + } +} + +func TestConvertZToMinAltitudekey_10(t *testing.T) { + expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") + + result, error := convertZToMinAltitudekey( + -1, + 25, + 25, + 25, + 0, + ) + if error != expectedError { + t.Fatal(result, error) + } +} + +func TestConvertZToMinAltitudekey_11(t *testing.T) { + expectedError := errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") + + result, error := convertZToMinAltitudekey( + -100, + 25, + 26, + 24, + 51, + ) + if error != expectedError { + t.Fatal(result, error) + } +} From 7c8a6d68aa7ca4b5896d210978372e10852862fb Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 25 Jul 2024 17:30:14 +0900 Subject: [PATCH 04/18] optimization of altitude conversion at same zoom level refactored convertZToMinAltitudekey to reuse index boundary check --- common/consts/consts.go | 7 ++ transform/convert_quadkey_and_Vertical_id.go | 99 ++++++++++++++++--- .../convert_quadkey_and_Vertical_id_test.go | 57 +++++++++++ 3 files changed, 151 insertions(+), 12 deletions(-) diff --git a/common/consts/consts.go b/common/consts/consts.go index 61f564c..1d799c4 100644 --- a/common/consts/consts.go +++ b/common/consts/consts.go @@ -6,3 +6,10 @@ const OrthCrs = 3857 // OrthCrs 直交座標系のEPSGコード const SpatialIDDelimiter = "/" // SpatialIDDelimiter 空間IDの区切り文字 const Minima = 1e-10 // Minima 浮動小数点誤差 + +const ZBaseExponent = 25 // ZBaseExponent 空間IDにおけるボクセルの高さが1mとなるズームレベル + +// ZBaseOffsetForNegativeFIndex +// +// 元の最大高さを保ったまま正方向と負方向でfインデックスを半数ずつ導入するためのzBaseOffset +const ZBaseOffsetForNegativeFIndex = 1 << (ZBaseExponent - 1) diff --git a/transform/convert_quadkey_and_Vertical_id.go b/transform/convert_quadkey_and_Vertical_id.go index 7723d53..ba8d87c 100644 --- a/transform/convert_quadkey_and_Vertical_id.go +++ b/transform/convert_quadkey_and_Vertical_id.go @@ -2,6 +2,8 @@ package transform import ( + "fmt" + "github.com/trajectoryjp/spatial_id_go/v4/common/consts" "math" "strconv" "strings" @@ -733,13 +735,9 @@ func ConvertZToAltitudekey(inputIndex int64, inputZoom int64, outputZoom int64, func convertZToMinAltitudekey(inputIndex int64, inputZoom int64, outputZoom int64, zBaseExponent int64, zBaseOffset int64) (int64, error) { // 1. check that the input index exists in the input system - inputResolution := common.CalculateArithmeticShift(1, inputZoom) - - maxInputIndex := inputResolution - 1 - minInputIndex := -inputResolution - - if inputIndex > maxInputIndex || inputIndex < minInputIndex { - return 0, errors.NewSpatialIdError(errors.InputValueErrorCode, "input index does not exist") + err, ok := validateIndexExists(inputIndex, inputZoom, true) + if !ok { + return 0, err } // 2. Calculate outputIndex @@ -748,12 +746,9 @@ func convertZToMinAltitudekey(inputIndex int64, inputZoom int64, outputZoom int6 outputIndex = common.CalculateArithmeticShift(outputIndex, (outputZoom - zBaseExponent)) // 3. Check to make sure outputIndex exists in the output system - outputResolution := common.CalculateArithmeticShift(1, outputZoom) - - maxOutputIndex := outputResolution - 1 - minOutputIndex := int64(0) + _, ok = validateIndexExists(outputIndex, outputZoom, false) - if outputIndex > maxOutputIndex || outputIndex < minOutputIndex { + if !ok { return 0, errors.NewSpatialIdError(errors.InputValueErrorCode, "output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset") } @@ -761,6 +756,86 @@ func convertZToMinAltitudekey(inputIndex int64, inputZoom int64, outputZoom int6 } +// validateIndexExists 指定した(拡張)空間IDインデックスが指定ズームレベルにおいて存在するか確認する +// +// 引数 : +// +// inputIndex : 確認対象の(拡張)空間IDのインデックス +// +// inputZoom : 変換対象の(拡張)空間IDのズームレベル(zインデックス) +// +// minValueIsNegative : 最小インデックス範囲が0未満である(fインデックス)場合true, そうでない(x,yインデックス)場合false +// +// trueの場合最大インデックス値を符号反転したものを最小インデックス範囲として扱う +// +// falseの場合最小インデックス範囲を0として扱う +// +// 戻り値 : +// +// インデックスが存在すればtrue,しなければfalse +// +// 戻り値(エラー) : +// +// 戻り値がfalseの場合、同時に以下の内容のエラーインスタンスが返却される。 +// 入力インデックス不正 :inputIndexにそのズームレベル(inputZoom)で存在しないインデックス値が入力されていた場合。 +// 出力インデックス不正 :変換後のインデックスが入力ズームレベル(inputZoom)で存在しないインデックス値になった場合。 +func validateIndexExists(inputIndex int64, inputZoom int64, minValueIsNegative bool) (error, bool) { + inputResolution := common.CalculateArithmeticShift(1, inputZoom) + + maxInputIndex := inputResolution - 1 + var minInputIndex int64 + if minValueIsNegative { + minInputIndex = -inputResolution + } else { + minInputIndex = 0 + } + + if inputIndex > maxInputIndex || inputIndex < minInputIndex { + return errors.NewSpatialIdError(errors.InputValueErrorCode, "input index does not exist"), false + } + return nil, true +} + +// AddZBaseOffsetToZ (拡張)空間IDz成分(fインデックス)にオフセット加算する +// ConvertZToAltitudekey()でズームレベル変換を行わずオフセット変換のみ指定したもの +// +// したがって ConvertZToAltitudekey(f, z, z, consts.ZBaseExponent, zBaseOffset)と等価 +// +// 引数 : +// +// fIndex : (拡張)空間ID高さインデックス(f) +// +// zoomLevel : (拡張)空間IDのズームレベル(z) +// +// ここで指定するズームレベルはconsts.ZBaseExponent以下の値でなければならない +// +// offsetZoom : オフセット変換量。正のoffsetで上方向, 負のoffsetで下方向に変換される +// +// offsetZoomは2**(consts.ZBaseExponent - zoomLevel)より大きくするべき(除算時に切り捨てられるため) +// +// 戻り値 : +// +// オフセット変換後のfインデックス +// +// 戻り値(エラー) : +// +// 以下の条件に当てはまる場合、エラーインスタンスが返却される。 +// 入力ズームレベル不正 :zoomLevelが最大ズームレベルを超える場合(consts.zBaseExponent より上のズームレベルはサポートしない)。 +// 出力インデックス不正 :変換後のインデックスが入力ズームレベル(inputZoom)で存在しないインデックス値になった場合。 +func AddZBaseOffsetToZ(fIndex int64, zoomLevel uint8, zBaseOffset int64) (int64, error) { + if zoomLevel > consts.ZBaseExponent { + return 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("zoom level %v must be less than %v", zoomLevel, consts.ZBaseExponent)) + } + // zBaseOffset * (2**(zoomLevel-ZBaseExponent)) + offset := zBaseOffset >> (consts.ZBaseExponent - zoomLevel) + outputIndex := offset + fIndex + _, ok := validateIndexExists(outputIndex, int64(zoomLevel), true) + if !ok { + return 0, errors.NewSpatialIdError(errors.ValueConvertErrorCode, fmt.Sprintf("output index (%v) does not exist with given zoomLevel (%v)", outputIndex, zoomLevel)) + } + return outputIndex, nil +} + // 高さのbit形式のインデックスを計算する。 // // 引数 : diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index c813c53..913400b 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -2,6 +2,7 @@ package transform import ( + "github.com/trajectoryjp/spatial_id_go/v4/common/consts" "reflect" "sort" "strconv" @@ -1058,6 +1059,62 @@ func TestConvertZToAltitudekey_9(t *testing.T) { } } +func TestAddZBaseOffsetToZ(t *testing.T) { + testCases := []struct { + fIndex int64 + zoomLevel uint8 + offset int64 + expected int64 + expectErr bool + }{ + { // "16/-10/58198/25804" (z=16,f=-10のみ使用) + -10, + 16, + consts.ZBaseOffsetForNegativeFIndex, + (1 << (16 - 1)) - 10, // 32758 + false, + }, + { + 1 - (1 << consts.ZBaseExponent), // -33554431 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + -16777215, + false, + }, + { + 1 - (1 << consts.ZBaseExponent), // -33554431 + consts.ZBaseExponent, + -consts.ZBaseOffsetForNegativeFIndex, + 0, + true, + }, + { + (1 << consts.ZBaseExponent) - 1, // 33554431 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + 0, + true, + }, + { + -10, + consts.ZBaseExponent + 1, + consts.ZBaseOffsetForNegativeFIndex, + 0, + true, + }, + } + + for _, testCase := range testCases { + result, err := AddZBaseOffsetToZ(testCase.fIndex, testCase.zoomLevel, testCase.offset) + if testCase.expectErr == (err == nil) { + t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) expected error existence: %v, result: %v", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expectErr, err) + } + if result != testCase.expected { + t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) == %d, result: %d", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expected, result) + } + } +} + func TestConvertZToMinAltitudekey_1(t *testing.T) { expected := int64(47) From 1eed9786c2a56cfbc62bdc4783188283761bc61d Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 25 Jul 2024 17:30:59 +0900 Subject: [PATCH 05/18] optimization of altitude conversion in CheckSpatialIdsArrayOverlap --- detector/check_spatial_id_overlap.go | 43 +++++++++------------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index 3afea5c..24b168f 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -49,6 +49,8 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // // spatialIds1, spatialIds2: 重複判定対象の空間ID列。ズームレベルが異なっている入力も許容。 // +// ただし高度は16,777,216 〜 -16,777,216mに制限される(この範囲で高度変換を行う) +// // 戻り値: // // bool: @@ -57,6 +59,7 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // error: // 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 +// 空間ID高度変換失敗:高度範囲外の空間IDが入力されていた場合。 func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bool, error) { // f,x,yで3次元分の2分木 tr := tree.CreateTree(tree.Create3DTable()) @@ -68,22 +71,14 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo if err != nil { return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) } - switch f1 < 0 { - case true: - convertedFIndices1, errAltConversion := transform.ConvertZToAltitudekey( - int64(f1), - int64(zoom1), - int64(zoom1), - 25, // 空間ID高さが1mになるズームレベル - 16777216, // 元の最大高さを保ったまま正方向と負方向でfインデックスを半数ずつ導入 - ) + if f1 < 0 { + // 高度インデックスをオフセット変換のみ実行して自然数にする + convertedFIndex, errAltConversion := transform.AddZBaseOffsetToZ(int64(f1), uint8(zoom1), consts.ZBaseOffsetForNegativeFIndex) if errAltConversion != nil { return false, fmt.Errorf("%w @spatialId1[%v]", errAltConversion, indexSpatialId1) } - for _, index := range convertedFIndices1 { - trMinus.Append(tree.Indexs{index, int64(x1), int64(y1)}, tree.ZoomSetLevel(zoom1), spatialId1) - } - case false: + trMinus.Append(tree.Indexs{convertedFIndex, int64(x1), int64(y1)}, tree.ZoomSetLevel(zoom1), spatialId1) + } else { index1 := tree.Indexs{int64(f1), int64(x1), int64(y1)} tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) } @@ -96,26 +91,14 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo } // 取り出した要素の比較 result := false - switch f2 < 0 { - case true: - convertedFIndices2, errAltConversion := transform.ConvertZToAltitudekey( - int64(f2), - int64(zoom2), - int64(zoom2), - 25, // 空間ID高さが1mになるズームレベル - 16777216, // 元の最大高さ(33,554,432m)を保ったまま正方向と負方向でfインデックスを半数ずつ導入 - ) + if f2 < 0 { + // 高度インデックスをオフセット変換のみ実行して自然数にする + convertedFIndex2, errAltConversion := transform.AddZBaseOffsetToZ(int64(f2), uint8(zoom2), consts.ZBaseOffsetForNegativeFIndex) if errAltConversion != nil { return false, fmt.Errorf("%w @spatialId2[%v]", errAltConversion, indexSpatialId2) } - for _, index := range convertedFIndices2 { - result = trMinus.IsOverlap(tree.Indexs{index, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) - if result { - // 重複判定時、trueとnilを返却 - return result, nil - } - } - case false: + result = trMinus.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) + } else { index2 := tree.Indexs{int64(f2), int64(x2), int64(y2)} result = tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) } From 0da2345b3fcf3cb3107f1e9e4773b55d55a780e8 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Tue, 23 Jul 2024 12:38:56 +0900 Subject: [PATCH 06/18] added fuzzing tests AddZBaseOffsetToZ at z=18 --- transform/convert_quadkey_and_Vertical_id_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index 913400b..0f1f953 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -1115,6 +1115,19 @@ func TestAddZBaseOffsetToZ(t *testing.T) { } } +func FuzzAddZBaseOffsetToZAt18(f *testing.F) { + conditions := []int64{-131072, 131072} // (1 << 24) >> (abs(18-25)) + for _, cond := range conditions { + f.Add(cond) + } + f.Fuzz(func(t *testing.T, cond int64) { + _, err := AddZBaseOffsetToZ(cond, 18, consts.ZBaseOffsetForNegativeFIndex) + if err != nil && cond > conditions[0] && cond < conditions[1] { + t.Error(err) + } + }) +} + func TestConvertZToMinAltitudekey_1(t *testing.T) { expected := int64(47) From e2883c0f63b7066dd113a834c8360a213c708189 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Tue, 23 Jul 2024 12:40:16 +0900 Subject: [PATCH 07/18] added benchmark test for CheckSpatialIdsOverlap, CheckExtendedSpatialIdsOverlap --- detector/check_spatial_id_overlap_test.go | 276 ++++++++++++++++++++-- 1 file changed, 261 insertions(+), 15 deletions(-) diff --git a/detector/check_spatial_id_overlap_test.go b/detector/check_spatial_id_overlap_test.go index 45d6dd3..04a960d 100644 --- a/detector/check_spatial_id_overlap_test.go +++ b/detector/check_spatial_id_overlap_test.go @@ -96,25 +96,45 @@ func TestCheckSpatialIdsOverlap03(t *testing.T) { // + 試験データ // - パターン1: // 比較対象の空間ID:{"25/0/29803148/13212522/777"},{"16/0/58198/25804"} +// - パターン2: +// 比較対象の空間ID:{"25/0/29803148/13212522"},{"16/0/58198/25804/777"} // // + 確認内容 // - 入力値から入力チェックエラーを取得できること func TestCheckSpatialIdsOverlap04(t *testing.T) { - //入力値 - spatialId1 := "25/0/29803148/13212522/777" - spatialId2 := "16/0/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]" - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + testCases := []struct { + spatialId1 string + spatialId2 string + expectValue bool + expectError string + }{ + { + //入力値 + spatialId1: "25/0/29803148/13212522/777", + spatialId2: "16/0/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]", + }, + { + //入力値 + spatialId1: "25/0/29803148/13212522", + spatialId2: "16/0/58198/25804/777", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,spatialId: 16/0/58198/25804/777 @spatialId2[0]", + }, + } + for _, testCase := range testCases { + resultValue, resultErr := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) + + if !reflect.DeepEqual(resultValue, testCase.expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) + } + if resultErr.Error() != testCase.expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr.Error()) + } } t.Log("テスト終了") @@ -232,6 +252,140 @@ func TestCheckSpatialIdsOverlap08(t *testing.T) { t.Log("テスト終了") } +// TestCheckSpatialIdsOverlap09 空間IDの重複確認関数 空間ID高度変換失敗 +// +// 試験詳細: +// + 試験データ +// - パターン1(ズームレベル超過エラー): +// 比較対象の空間ID:{"26/-1/7274/3225"},{"16/8/58198/25804"} +// - パターン2(ズームレベル超過エラー): +// 比較対象の空間ID:{"13/1/7274/3225"},{"26/-8/58198/25804"} +// - パターン3(高度範囲外エラー): +// 比較対象の空間ID:{"25/16777216/0/3225"},{"18/1/58198/25804"} +// - パターン4(高度範囲外エラー): +// 比較対象の空間ID:{"18/1/58198/25804"},{"25/16777216/0/3225"} +// - パターン5(高度範囲外エラー): +// 比較対象の空間ID:{"25/-16777217/0/3225"},{"16/8/58198/25804"} +// - パターン6(高度範囲外エラー): +// 比較対象の空間ID:{"18/1/58198/25804"},{"25/-16777217/0/3225"} +// +// + 確認内容 +// - 入力値から指定した入力チェックエラー、変換エラーを取得できること +func TestCheckSpatialIdsOverlap09(t *testing.T) { + testCases := []struct { + spatialId1 string + spatialId2 string + expectValue bool + expectError string + }{ + { + //入力値 + spatialId1: "26/-1/7274/3225", + spatialId2: "16/8/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId1[0] = 26/-1/7274/3225", + }, + { + //入力値 + spatialId1: "13/1/7274/3225", + spatialId2: "26/-8/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId2[0] = 26/-8/58198/25804", + }, + { + //入力値 + spatialId1: "25/16777216/0/3225", + spatialId2: "18/1/58198/25804", + // 期待値 + expectValue: false, + expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId1[0] = 25/16777216/0/3225", + }, + { + //入力値 + spatialId1: "18/1/58198/25804", + spatialId2: "25/16777216/0/3225", + // 期待値 + expectValue: false, + expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId2[0] = 25/16777216/0/3225", + }, + { + //入力値 + spatialId1: "25/-16777217/0/3225", + spatialId2: "18/1/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId1[0] = 25/-16777217/0/3225", + }, + { + //入力値 + spatialId1: "18/1/58198/25804", + spatialId2: "25/-16777217/0/3225", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId2[0] = 25/-16777217/0/3225", + }, + } + for _, testCase := range testCases { + resultValue, err := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) + var resultErr string + if err != nil { + resultErr = err.Error() + } + + if !reflect.DeepEqual(resultValue, testCase.expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) + } + if resultErr != testCase.expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr) + } + } + + t.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsOverlap01 空間IDの重複確認関数 包含関係あり +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7274/3225"}, {"16/0/58198/25804"}(包含関係あり) +// +// + 確認内容 +// - 入力値の先頭に包含関係があった場合の処理速度 +func BenchmarkCheckSpatialIdsOverlap01(b *testing.B) { + // 入力値 + spatialId1 := "13/0/7274/3225" + spatialId2 := "16/0/58198/25804" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsOverlap02 空間IDの重複確認関数 包含関係なし +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7275/3226"}, {"16/0/58198/25804"}(包含関係なし) +// +// + 確認内容 +// - 入力値に包含関係がなかった場合の処理速度 +func BenchmarkCheckSpatialIdsOverlap02(b *testing.B) { + // 入力値 + spatialId1 := "13/0/7275/3226" + spatialId2 := "16/0/58198/25804" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + // TestCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 正常系動作確認 // // + 試験データ @@ -347,6 +501,54 @@ func TestCheckSpatialIdsArrayOverlap04(t *testing.T) { t.Log("テスト終了") } +// BenchmarkCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係あり) +// +// + 試験データ +// - パターン1(包含関係あり): +// 比較対象の空間ID列:[100]{"13/0/7274/3225"}, [100]{"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckSpatialIdsArrayOverlap01(b *testing.B) { + // 入力値 + spatialIds1 := []string{} + spatialIds2 := []string{} + for i := 0; i < 100; i++ { + spatialIds1 = append(spatialIds1, "13/0/7274/3225") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsArrayOverlap02 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係なし) +// +// + 試験データ +// - パターン1(包含関係なし): +// 比較対象の空間ID列:[100]{"13/0/7275/3226"}, [100]{"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値に包含関係がない場合の処理速度 +func BenchmarkCheckSpatialIdsArrayOverlap02(b *testing.B) { + // 入力値 + spatialIds1 := []string{} + spatialIds2 := []string{} + for i := 0; i < 100; i++ { + spatialIds1 = append(spatialIds1, "13/0/7275/3226") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} + // TestCheckExtendedSpatialIdsOverlap01 拡張空間IDの重複確認関数 正常系動作確認 // // 試験詳細: @@ -469,6 +671,26 @@ func TestCheckExtendedSpatialIdsOverlap04(t *testing.T) { t.Log("テスト終了") } +// BenchmarkCheckExtendedSpatialIdsOverlap01 空間IDの重複確認関数 自然数fインデックスベンチマーク +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"16/58206/25805/16/1"}, {"15/29104/12902/15/0"}(包含関係あり) +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckExtendedSpatialIdsOverlap01(b *testing.B) { + // 入力値 + spatialId1 := "16/58209/25805/16/1" + spatialId2 := "15/29104/12902/15/0" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + // TestCheckExtendedSpatialIdsArrayOverlap01 拡張空間IDの重複確認関数 正常系動作確認 // // 試験詳細: @@ -590,3 +812,27 @@ func TestCheckExtendedSpatialIdsArrayOverlap04(t *testing.T) { t.Log("テスト終了") } + +// BenchmarkCheckExtendedSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク +// +// + 試験データ +// - パターン1(包含関係あり): +// 比較対象の空間ID列:[10]{"16/58206/25805/16/1"}, [10]{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckExtendedSpatialIdsArrayOverlap01(b *testing.B) { + // 入力値 + spatialIds1 := []string{"16/58206/25805/16/1"} + spatialIds2 := []string{"15/29104/12902/15/0"} + for i := 0; i < 9; i++ { + spatialIds1 = append(spatialIds1, "16/58206/25805/16/1") + spatialIds2 = append(spatialIds2, "15/29104/12902/15/0") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} From 0d39eb989d3825cf24e32495b9eac9442fd400fc Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 25 Jul 2024 13:51:14 +0900 Subject: [PATCH 08/18] fix altitude range specification for CheckSpatialIdsOverlap --- detector/check_spatial_id_overlap.go | 45 ++++++++----------- .../convert_quadkey_and_Vertical_id_test.go | 28 ++++++++++++ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index 24b168f..675d9b6 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -49,7 +49,7 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // // spatialIds1, spatialIds2: 重複判定対象の空間ID列。ズームレベルが異なっている入力も許容。 // -// ただし高度は16,777,216 〜 -16,777,216mに制限される(この範囲で高度変換を行う) +// ただし高度は16,777,216未満 〜 -16,777,216m以上に制限される(この範囲で高度変換を行う) // // 戻り値: // @@ -57,31 +57,27 @@ func CheckSpatialIdsOverlap(spatialId1 string, spatialId2 string) (bool, error) // 重複の有無が返却される。true: 重複あり false: 重複なし // // error: -// 以下の条件に当てはまる場合、エラーインスタンスが返却される。ただしこのときbool値にfalseが返却される。 +// 以下の条件に当てはまる場合、エラーインスタンスが返却される。このときbool値はfalseで返却される。 // 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 -// 空間ID高度変換失敗:高度範囲外の空間IDが入力されていた場合。 +// 空間ID高度範囲外:高度範囲外の空間IDが入力されていた場合。 func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bool, error) { // f,x,yで3次元分の2分木 tr := tree.CreateTree(tree.Create3DTable()) - // 負数fインデックスを持つ空間IDは高度変換して別の3次元2分木に保存 - trMinus := tree.CreateTree(tree.Create3DTable()) // spatialIds1から各要素をradix treeに格納 for indexSpatialId1, spatialId1 := range spatialIds1 { zoom1, f1, x1, y1, err := getSpatialIdAttrs(spatialId1) if err != nil { return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) } - if f1 < 0 { - // 高度インデックスをオフセット変換のみ実行して自然数にする - convertedFIndex, errAltConversion := transform.AddZBaseOffsetToZ(int64(f1), uint8(zoom1), consts.ZBaseOffsetForNegativeFIndex) - if errAltConversion != nil { - return false, fmt.Errorf("%w @spatialId1[%v]", errAltConversion, indexSpatialId1) - } - trMinus.Append(tree.Indexs{convertedFIndex, int64(x1), int64(y1)}, tree.ZoomSetLevel(zoom1), spatialId1) - } else { - index1 := tree.Indexs{int64(f1), int64(x1), int64(y1)} - tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) + convertedFIndex, errAltConversion := transform.AddZBaseOffsetToZ(int64(f1), uint8(zoom1), consts.ZBaseOffsetForNegativeFIndex) + if convertedFIndex < 0 { + return false, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("input f-index %v is out of altitude range @spatialId1[%v] = %v", f1, indexSpatialId1, spatialId1)) + } + if errAltConversion != nil { + return false, fmt.Errorf("%w @spatialId1[%v] = %v", errAltConversion, indexSpatialId1, spatialId1) } + index1 := tree.Indexs{convertedFIndex, int64(x1), int64(y1)} + tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) } // spatialIds2から各要素の取り出し for indexSpatialId2, spatialId2 := range spatialIds2 { @@ -90,18 +86,15 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo return false, fmt.Errorf("%w @spatialId2[%v]", err, indexSpatialId2) } // 取り出した要素の比較 - result := false - if f2 < 0 { - // 高度インデックスをオフセット変換のみ実行して自然数にする - convertedFIndex2, errAltConversion := transform.AddZBaseOffsetToZ(int64(f2), uint8(zoom2), consts.ZBaseOffsetForNegativeFIndex) - if errAltConversion != nil { - return false, fmt.Errorf("%w @spatialId2[%v]", errAltConversion, indexSpatialId2) - } - result = trMinus.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) - } else { - index2 := tree.Indexs{int64(f2), int64(x2), int64(y2)} - result = tr.IsOverlap(index2, tree.ZoomSetLevel(zoom2)) + // 高度インデックスをオフセット変換のみ実行して自然数にする + convertedFIndex2, errAltConversion := transform.AddZBaseOffsetToZ(int64(f2), uint8(zoom2), consts.ZBaseOffsetForNegativeFIndex) + if convertedFIndex2 < 0 { + return false, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("input f-index %v is out of altitude range @spatialId2[%v] = %v", f2, indexSpatialId2, spatialId2)) + } + if errAltConversion != nil { + return false, fmt.Errorf("%w @spatialId2[%v] = %v", errAltConversion, indexSpatialId2, spatialId2) } + result := tr.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) if result { // 重複判定時、trueとnilを返却 return result, nil diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index 0f1f953..0c65e1a 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -1081,6 +1081,34 @@ func TestAddZBaseOffsetToZ(t *testing.T) { -16777215, false, }, + { + (1 << (consts.ZBaseExponent - 1)) - 1, // 16777215 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + 33554431, + false, + }, + { + -(1 << (consts.ZBaseExponent - 1)), // -16777216 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + 0, + false, + }, + { + -1 - (1 << (consts.ZBaseExponent - 1)), // -16777217 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + -1, + false, + }, + { + 1 << (consts.ZBaseExponent - 1), // 16777216 + consts.ZBaseExponent, + consts.ZBaseOffsetForNegativeFIndex, + 0, + true, + }, { 1 - (1 << consts.ZBaseExponent), // -33554431 consts.ZBaseExponent, From 75095803e502ec72d1a83ce3fb5415cc9ea99200 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Tue, 13 Aug 2024 16:51:32 +0900 Subject: [PATCH 09/18] fixed dependency multi-dimensional-radix-tree --- detector/check_spatial_id_overlap.go | 2 +- go.mod | 5 ++++- go.sum | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index 675d9b6..aeac981 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -2,7 +2,7 @@ package detector import ( "fmt" - "github.com/trajectoryjp/multidimensional-radix-tree/tree" + "github.com/trajectoryjp/multidimensional-radix-tree/src/tree" "github.com/trajectoryjp/spatial_id_go/v4/common/consts" "github.com/trajectoryjp/spatial_id_go/v4/common/errors" "github.com/trajectoryjp/spatial_id_go/v4/integrate" diff --git a/go.mod b/go.mod index 9b54e31..2acfcb5 100644 --- a/go.mod +++ b/go.mod @@ -11,4 +11,7 @@ require ( require golang.org/x/image v0.7.0 // indirect -require github.com/trajectoryjp/closest_go v1.0.1 +require ( + github.com/trajectoryjp/closest_go v1.0.1 + github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d +) diff --git a/go.sum b/go.sum index 331219d..3818e5e 100644 --- a/go.sum +++ b/go.sum @@ -4,13 +4,19 @@ github.com/trajectoryjp/closest_go v1.0.1 h1:dvshtZzPDwhGDhzn5SVZxlgNnqr/gLp4uIp github.com/trajectoryjp/closest_go v1.0.1/go.mod h1:+iTxW7/pOi0dIqo2/GcqGqWh/fAj2gMjDIiZ+BFDXIc= github.com/trajectoryjp/geodesy_go v1.0.1 h1:FvvnA3kPcPoXOjn6cS27R9aiCLyszOarFuZRVlQRG2s= github.com/trajectoryjp/geodesy_go v1.0.1/go.mod h1:eJuX+ds+t3MKxHG9dhobqNjUbUsYlpTT9XDO0mbc0LU= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240723082158-f3916a674d95 h1:M+XVwjY8llZ0bRaGHI3V0GKktgehxZI/GxoZ91f1qhA= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240723082158-f3916a674d95/go.mod h1:dDSriNaS7E5bvwmmXxF62rqb1FfgzgB7IDdMEsm8O9A= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d h1:K2EBr4rnKcca/DjrMI779x2nJ1U3UuFyZsFPh/uR52I= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d/go.mod h1:dDSriNaS7E5bvwmmXxF62rqb1FfgzgB7IDdMEsm8O9A= github.com/wroge/wgs84 v1.1.7 h1:8WVUUrpjysYxrn0ssWX7z90SOUKCuHt9NQ5tg9ovjIY= github.com/wroge/wgs84 v1.1.7/go.mod h1:mc1F8ubW03DO4zaf/006cmhaiMlfvbKmqVAcPuAtsNA= github.com/xieyuschen/deepcopy v1.0.1 h1:nTCnKprCOdibz8WXWlMZzULIlpzZX0ZzKjz8HlGd/Nk= +github.com/xieyuschen/deepcopy v1.0.1/go.mod h1:smzaXhQZuuehOzevwMMLzvM7gBslB4VPdgJbwdyIDSA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw= golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg= From 26f3757c3fe91c89b30781a459709682cdf9388e Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Tue, 13 Aug 2024 16:58:43 +0900 Subject: [PATCH 10/18] created example program for benchmark graph --- test/detect_overlap/.gitignore | 1 + test/detect_overlap/go.mod | 15 ++++++++++ test/detect_overlap/go.sum | 52 ++++++++++++++++++++++++++++++++++ test/detect_overlap/main.go | 51 +++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 test/detect_overlap/.gitignore create mode 100644 test/detect_overlap/go.mod create mode 100644 test/detect_overlap/go.sum create mode 100644 test/detect_overlap/main.go diff --git a/test/detect_overlap/.gitignore b/test/detect_overlap/.gitignore new file mode 100644 index 0000000..c627000 --- /dev/null +++ b/test/detect_overlap/.gitignore @@ -0,0 +1 @@ +*.prof diff --git a/test/detect_overlap/go.mod b/test/detect_overlap/go.mod new file mode 100644 index 0000000..b6b1fd6 --- /dev/null +++ b/test/detect_overlap/go.mod @@ -0,0 +1,15 @@ +module github.com/trajectoryjp/spatial_id_go/v4/testoverlap + +go 1.22.5 + +require github.com/trajectoryjp/spatial_id_go/v4 v4.0.0-20240813075132-0b8c6d4fdae5 + +require ( + github.com/go-gl/mathgl v1.1.0 // indirect + github.com/trajectoryjp/closest_go v1.0.1 // indirect + github.com/trajectoryjp/geodesy_go v1.0.1 // indirect + github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d // indirect + github.com/wroge/wgs84 v1.1.7 // indirect + golang.org/x/image v0.7.0 // indirect + gonum.org/v1/gonum v0.13.0 // indirect +) diff --git a/test/detect_overlap/go.sum b/test/detect_overlap/go.sum new file mode 100644 index 0000000..1fbf175 --- /dev/null +++ b/test/detect_overlap/go.sum @@ -0,0 +1,52 @@ +github.com/go-gl/mathgl v1.1.0 h1:0lzZ+rntPX3/oGrDzYGdowSLC2ky8Osirvf5uAwfIEA= +github.com/go-gl/mathgl v1.1.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= +github.com/trajectoryjp/closest_go v1.0.1 h1:dvshtZzPDwhGDhzn5SVZxlgNnqr/gLp4uIpGDIEOHaU= +github.com/trajectoryjp/closest_go v1.0.1/go.mod h1:+iTxW7/pOi0dIqo2/GcqGqWh/fAj2gMjDIiZ+BFDXIc= +github.com/trajectoryjp/geodesy_go v1.0.1 h1:FvvnA3kPcPoXOjn6cS27R9aiCLyszOarFuZRVlQRG2s= +github.com/trajectoryjp/geodesy_go v1.0.1/go.mod h1:eJuX+ds+t3MKxHG9dhobqNjUbUsYlpTT9XDO0mbc0LU= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d h1:K2EBr4rnKcca/DjrMI779x2nJ1U3UuFyZsFPh/uR52I= +github.com/trajectoryjp/multidimensional-radix-tree/src v0.0.0-20240725143308-c304415df20d/go.mod h1:dDSriNaS7E5bvwmmXxF62rqb1FfgzgB7IDdMEsm8O9A= +github.com/trajectoryjp/spatial_id_go/v4 v4.0.0-20240813075132-0b8c6d4fdae5 h1:MkiRbXMpb8DY4jdBk8PK8mlI9nTM8dItFRYjqDkbR0M= +github.com/trajectoryjp/spatial_id_go/v4 v4.0.0-20240813075132-0b8c6d4fdae5/go.mod h1:zpAxqh+UyVGxJbqF3R9QCW9SnZ7/GJnJ1T9kiQ4jA2E= +github.com/wroge/wgs84 v1.1.7 h1:8WVUUrpjysYxrn0ssWX7z90SOUKCuHt9NQ5tg9ovjIY= +github.com/wroge/wgs84 v1.1.7/go.mod h1:mc1F8ubW03DO4zaf/006cmhaiMlfvbKmqVAcPuAtsNA= +github.com/xieyuschen/deepcopy v1.0.1 h1:nTCnKprCOdibz8WXWlMZzULIlpzZX0ZzKjz8HlGd/Nk= +github.com/xieyuschen/deepcopy v1.0.1/go.mod h1:smzaXhQZuuehOzevwMMLzvM7gBslB4VPdgJbwdyIDSA= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw= +golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= +gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU= diff --git a/test/detect_overlap/main.go b/test/detect_overlap/main.go new file mode 100644 index 0000000..6b3259d --- /dev/null +++ b/test/detect_overlap/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "github.com/trajectoryjp/spatial_id_go/v4/detector" + _ "net/http/pprof" + "os" + "runtime/pprof" + "time" +) + +const maxCases = 10 + +func main() { + // profile + f, err := os.Create("cpu.prof") + if err != nil { + panic(err) + } + defer func(f *os.File) { + _ = f.Close() + }(f) + // 入力値 + spatialIdCount := maxCases + fmt.Println("inputCount,id1Len,id2Len,truePoint,duration(ns),detection result") + _ = pprof.StartCPUProfile(f) + // caseCount < spatialIdCountまで: caseCountで重複する配列データ生成 + // caseCount => spatialIdCount: 重複なしデータ生成 + for caseCount := 0; caseCount < spatialIdCount+1; caseCount++ { + spatialIds1, spatialIds2 := makeTargets(caseCount, spatialIdCount, []string{}, []string{}) + start := time.Now() + result, _ := detector.CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + end := time.Now() + duration := end.Sub(start) + fmt.Printf("%v,%v,%v,%v,%v,%v\n", spatialIdCount, len(spatialIds1), len(spatialIds2), caseCount, duration.Nanoseconds(), result) + } + pprof.StopCPUProfile() +} + +func makeTargets(truePoint int, spatialIdCount int, spatialIds1 []string, spatialIds2 []string) ([]string, []string) { + for i := 0; i < spatialIdCount; i++ { + if i == truePoint { + spatialIds1 = append(spatialIds1, "13/0/7274/3225") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } else { + spatialIds1 = append(spatialIds1, "13/0/7275/3226") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } + } + return spatialIds1, spatialIds2 +} From de00e69fe4b652cc63d348eb272c4563e781b829 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Wed, 21 Aug 2024 16:36:25 +0900 Subject: [PATCH 11/18] added DetectOverlap for radix-tree caching --- detector/check_spatial_id_overlap.go | 32 ++++++++++++++++++++++- detector/check_spatial_id_overlap_test.go | 31 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index aeac981..17fea32 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -79,6 +79,36 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo index1 := tree.Indexs{convertedFIndex, int64(x1), int64(y1)} tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) } + return CheckSpatialIdsArrayOverlapWithCache(tr, spatialIds2) +} + +// CheckSpatialIdsArrayOverlapWithCache 2つの空間ID重複の判定関数 キャッシュ利用版 +// +// CheckSpatialIdsArrayOverlap と同様に、比較対象として入力された2つの空間ID列の重複の判定を行う。 +// ただし比較元の空間ID(spatialIds1)は3次元バイナリツリーに格納した形式を用いる。 +// +// 入力するバイナリツリーは必ず3次元形式(`Create3DTable`を利用した形式)でなければならない。 +// それ以外の場合にはpanicが発生する。 +// +// 引数: +// +// spatialIds1, spatialIds2: 重複判定対象の空間ID列。ズームレベルが異なっている入力も許容。 +// +// ただし高度は16,777,216未満 〜 -16,777,216m以上に制限される(この範囲で高度変換を行う) +// +// 戻り値: +// +// bool: +// 重複の有無が返却される。true: 重複あり false: 重複なし +// +// error: +// 以下の条件に当てはまる場合、エラーインスタンスが返却される。このときbool値はfalseで返却される。 +// 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 +// 空間ID高度範囲外:高度範囲外の空間IDが入力されていた場合。 +// panic: +// 以下の条件に当てはまる場合、panicが発生する。 +// バイナリツリー次元数不正:次元数がマッチしないバイナリツリーが入力されていた場合。 +func CheckSpatialIdsArrayOverlapWithCache(spatialIds1 tree.TreeInterface, spatialIds2 []string) (bool, error) { // spatialIds2から各要素の取り出し for indexSpatialId2, spatialId2 := range spatialIds2 { zoom2, f2, x2, y2, err := getSpatialIdAttrs(spatialId2) @@ -94,7 +124,7 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo if errAltConversion != nil { return false, fmt.Errorf("%w @spatialId2[%v] = %v", errAltConversion, indexSpatialId2, spatialId2) } - result := tr.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) + result := spatialIds1.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) if result { // 重複判定時、trueとnilを返却 return result, nil diff --git a/detector/check_spatial_id_overlap_test.go b/detector/check_spatial_id_overlap_test.go index 04a960d..c13b1a2 100644 --- a/detector/check_spatial_id_overlap_test.go +++ b/detector/check_spatial_id_overlap_test.go @@ -1,6 +1,7 @@ package detector import ( + "github.com/trajectoryjp/multidimensional-radix-tree/src/tree" "reflect" "testing" ) @@ -501,6 +502,36 @@ func TestCheckSpatialIdsArrayOverlap04(t *testing.T) { t.Log("テスト終了") } +// TestPanicCheckSpatialIdsArrayOverlapWithCache 空間ID列の重複確認関数 バイナリツリー次元不正 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の空間ID列:2DTable(){"13/7274/3225"}, {"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値からpanic発生を取得できること +func TestPanicCheckSpatialIdsArrayOverlapWithCache(t *testing.T) { + defer func() { + // panicが発生しなかった場合Errorをログに出力 + if err := recover(); err == nil { + t.Errorf("error - 期待値:(panic()), 取得値:nil\n") + } else { + t.Logf("success paniced: %v", err) + } + }() + //入力値 + spatialIds1 := tree.CreateTree(tree.Create2DTable()) + // "13/7274/3225" (Appendでpanicしないよう、2Dデータを作成) + spatialIds1.Append(tree.Indexs{0, 7274, 3225}, tree.ZoomSetLevel(13), "2d value") + spatialIds2 := []string{"16/0/58198/25803"} + + // panic生成 + _, _ = CheckSpatialIdsArrayOverlapWithCache(spatialIds1, spatialIds2) + + t.Log("テスト終了") +} + // BenchmarkCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係あり) // // + 試験データ From 16f4cef92bb381f6ff6cd93c844607d8a7ea5ef9 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 3 Oct 2024 16:40:14 +0900 Subject: [PATCH 12/18] Revert "added DetectOverlap for radix-tree caching" It needs receiver if implementing tree cache; ``` type detector struct { tr tree.TreeInterface } func CheckSpatialIdsArrayOverlapWithCache(spatialIds1 tree.TreeInterface, spatialIds2 []string) (bool, error){ // ... } ``` This reverts commit de00e69f --- detector/check_spatial_id_overlap.go | 32 +- detector/check_spatial_id_overlap_test.go | 1708 ++++++++++----------- 2 files changed, 839 insertions(+), 901 deletions(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index 17fea32..aeac981 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -79,36 +79,6 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo index1 := tree.Indexs{convertedFIndex, int64(x1), int64(y1)} tr.Append(index1, tree.ZoomSetLevel(zoom1), spatialId1) } - return CheckSpatialIdsArrayOverlapWithCache(tr, spatialIds2) -} - -// CheckSpatialIdsArrayOverlapWithCache 2つの空間ID重複の判定関数 キャッシュ利用版 -// -// CheckSpatialIdsArrayOverlap と同様に、比較対象として入力された2つの空間ID列の重複の判定を行う。 -// ただし比較元の空間ID(spatialIds1)は3次元バイナリツリーに格納した形式を用いる。 -// -// 入力するバイナリツリーは必ず3次元形式(`Create3DTable`を利用した形式)でなければならない。 -// それ以外の場合にはpanicが発生する。 -// -// 引数: -// -// spatialIds1, spatialIds2: 重複判定対象の空間ID列。ズームレベルが異なっている入力も許容。 -// -// ただし高度は16,777,216未満 〜 -16,777,216m以上に制限される(この範囲で高度変換を行う) -// -// 戻り値: -// -// bool: -// 重複の有無が返却される。true: 重複あり false: 重複なし -// -// error: -// 以下の条件に当てはまる場合、エラーインスタンスが返却される。このときbool値はfalseで返却される。 -// 空間IDフォーマット不正:空間IDのフォーマットに違反する値が"重複判定対象空間ID"に入力されていた場合。 -// 空間ID高度範囲外:高度範囲外の空間IDが入力されていた場合。 -// panic: -// 以下の条件に当てはまる場合、panicが発生する。 -// バイナリツリー次元数不正:次元数がマッチしないバイナリツリーが入力されていた場合。 -func CheckSpatialIdsArrayOverlapWithCache(spatialIds1 tree.TreeInterface, spatialIds2 []string) (bool, error) { // spatialIds2から各要素の取り出し for indexSpatialId2, spatialId2 := range spatialIds2 { zoom2, f2, x2, y2, err := getSpatialIdAttrs(spatialId2) @@ -124,7 +94,7 @@ func CheckSpatialIdsArrayOverlapWithCache(spatialIds1 tree.TreeInterface, spatia if errAltConversion != nil { return false, fmt.Errorf("%w @spatialId2[%v] = %v", errAltConversion, indexSpatialId2, spatialId2) } - result := spatialIds1.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) + result := tr.IsOverlap(tree.Indexs{convertedFIndex2, int64(x2), int64(y2)}, tree.ZoomSetLevel(zoom2)) if result { // 重複判定時、trueとnilを返却 return result, nil diff --git a/detector/check_spatial_id_overlap_test.go b/detector/check_spatial_id_overlap_test.go index 39a2f6c..04a960d 100644 --- a/detector/check_spatial_id_overlap_test.go +++ b/detector/check_spatial_id_overlap_test.go @@ -1,870 +1,838 @@ -package detector - -import ( - "reflect" - "testing" - - "github.com/trajectoryjp/multidimensional-radix-tree/src/tree" -) - -// TestCheckSpatialIdsOverlap01 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/0/7274/3225"}, {"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値から包含関係があることを確認できること -func TestCheckSpatialIdsOverlap01(t *testing.T) { - // 入力値 - spatialId1 := "13/0/7274/3225" - spatialId2 := "16/0/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := true - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap02 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/0/7275/3226"}, {"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値から包含関係がないことを確認できること -func TestCheckSpatialIdsOverlap02(t *testing.T) { - // 入力値 - spatialId1 := "13/0/7275/3226" - spatialId2 := "16/0/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap03 空間IDの重複確認関数 空入力時動作確認 -// -// 試験詳細: -// - パターン1: -// 比較対象の空間ID:空 -// -// + 確認内容 -// - エラーを取得できること -func TestCheckSpatialIdsOverlap03(t *testing.T) { - // 入力値 - spatialId1 := "" - spatialId2 := "16/0/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap04 空間IDの重複確認関数 空間IDフォーマット不正 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"25/0/29803148/13212522/777"},{"16/0/58198/25804"} -// - パターン2: -// 比較対象の空間ID:{"25/0/29803148/13212522"},{"16/0/58198/25804/777"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckSpatialIdsOverlap04(t *testing.T) { - testCases := []struct { - spatialId1 string - spatialId2 string - expectValue bool - expectError string - }{ - { - //入力値 - spatialId1: "25/0/29803148/13212522/777", - spatialId2: "16/0/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]", - }, - { - //入力値 - spatialId1: "25/0/29803148/13212522", - spatialId2: "16/0/58198/25804/777", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,spatialId: 16/0/58198/25804/777 @spatialId2[0]", - }, - } - for _, testCase := range testCases { - resultValue, resultErr := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) - - if !reflect.DeepEqual(resultValue, testCase.expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) - } - if resultErr.Error() != testCase.expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr.Error()) - } - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap05 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/8/58198/25804"} -// -// + 確認内容 -// - fインデックスの包含関係があることを確認できること -func TestCheckSpatialIdsOverlap05(t *testing.T) { - // 入力値 - spatialId1 := "13/1/7274/3225" - spatialId2 := "16/8/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := true - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap06 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/17/58198/25804"} -// -// + 確認内容 -// - fインデックスの包含関係がないことを確認できること -func TestCheckSpatialIdsOverlap06(t *testing.T) { - // 入力値 - spatialId1 := "13/1/7274/3225" - spatialId2 := "16/17/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap07 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-8/58198/25804"} -// -// + 確認内容 -// - fインデックスが負数の場合においても入力値から包含関係があることを確認できること -func TestCheckSpatialIdsOverlap07(t *testing.T) { - // 入力値 - spatialId1 := "13/-1/7274/3225" - spatialId2 := "16/-8/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := true - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap08 空間IDの重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-10/58198/25804"} -// -// + 確認内容 -// - fインデックスに関する包含関係がないことを確認できること -func TestCheckSpatialIdsOverlap08(t *testing.T) { - // 入力値 - spatialId1 := "13/-1/7274/3225" - spatialId2 := "16/-10/58198/25804" - resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsOverlap09 空間IDの重複確認関数 空間ID高度変換失敗 -// -// 試験詳細: -// + 試験データ -// - パターン1(ズームレベル超過エラー): -// 比較対象の空間ID:{"26/-1/7274/3225"},{"16/8/58198/25804"} -// - パターン2(ズームレベル超過エラー): -// 比較対象の空間ID:{"13/1/7274/3225"},{"26/-8/58198/25804"} -// - パターン3(高度範囲外エラー): -// 比較対象の空間ID:{"25/16777216/0/3225"},{"18/1/58198/25804"} -// - パターン4(高度範囲外エラー): -// 比較対象の空間ID:{"18/1/58198/25804"},{"25/16777216/0/3225"} -// - パターン5(高度範囲外エラー): -// 比較対象の空間ID:{"25/-16777217/0/3225"},{"16/8/58198/25804"} -// - パターン6(高度範囲外エラー): -// 比較対象の空間ID:{"18/1/58198/25804"},{"25/-16777217/0/3225"} -// -// + 確認内容 -// - 入力値から指定した入力チェックエラー、変換エラーを取得できること -func TestCheckSpatialIdsOverlap09(t *testing.T) { - testCases := []struct { - spatialId1 string - spatialId2 string - expectValue bool - expectError string - }{ - { - //入力値 - spatialId1: "26/-1/7274/3225", - spatialId2: "16/8/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId1[0] = 26/-1/7274/3225", - }, - { - //入力値 - spatialId1: "13/1/7274/3225", - spatialId2: "26/-8/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId2[0] = 26/-8/58198/25804", - }, - { - //入力値 - spatialId1: "25/16777216/0/3225", - spatialId2: "18/1/58198/25804", - // 期待値 - expectValue: false, - expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId1[0] = 25/16777216/0/3225", - }, - { - //入力値 - spatialId1: "18/1/58198/25804", - spatialId2: "25/16777216/0/3225", - // 期待値 - expectValue: false, - expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId2[0] = 25/16777216/0/3225", - }, - { - //入力値 - spatialId1: "25/-16777217/0/3225", - spatialId2: "18/1/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId1[0] = 25/-16777217/0/3225", - }, - { - //入力値 - spatialId1: "18/1/58198/25804", - spatialId2: "25/-16777217/0/3225", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId2[0] = 25/-16777217/0/3225", - }, - } - for _, testCase := range testCases { - resultValue, err := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) - var resultErr string - if err != nil { - resultErr = err.Error() - } - - if !reflect.DeepEqual(resultValue, testCase.expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) - } - if resultErr != testCase.expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr) - } - } - - t.Log("テスト終了") -} - -// BenchmarkCheckSpatialIdsOverlap01 空間IDの重複確認関数 包含関係あり -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/0/7274/3225"}, {"16/0/58198/25804"}(包含関係あり) -// -// + 確認内容 -// - 入力値の先頭に包含関係があった場合の処理速度 -func BenchmarkCheckSpatialIdsOverlap01(b *testing.B) { - // 入力値 - spatialId1 := "13/0/7274/3225" - spatialId2 := "16/0/58198/25804" - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) - } - b.StopTimer() - b.Log("テスト終了") -} - -// BenchmarkCheckSpatialIdsOverlap02 空間IDの重複確認関数 包含関係なし -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"13/0/7275/3226"}, {"16/0/58198/25804"}(包含関係なし) -// -// + 確認内容 -// - 入力値に包含関係がなかった場合の処理速度 -func BenchmarkCheckSpatialIdsOverlap02(b *testing.B) { - // 入力値 - spatialId1 := "13/0/7275/3226" - spatialId2 := "16/0/58198/25804" - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) - } - b.StopTimer() - b.Log("テスト終了") -} - -// TestCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID列:{"13/0/7274/3225"}, {"16/0/58198/25800", "16/0/58198/25804"} -// -// + 確認内容 -// - 入力値から包含関係があることを確認できること -func TestCheckSpatialIdsArrayOverlap01(t *testing.T) { - // 入力値 - spatialIds1 := []string{"13/0/7274/3225"} - spatialIds2 := []string{"16/0/58198/25800", "16/0/58198/25804"} - resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := true - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsArrayOverlap02 空間ID列の重複確認関数 正常系動作確認 -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID列:{"13/0/7275/3226"}, {"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値から包含関係がないことを確認できること -func TestCheckSpatialIdsArrayOverlap02(t *testing.T) { - // 入力値 - spatialIds1 := []string{"13/0/7275/3226"} - spatialIds2 := []string{"16/0/58198/25804", "16/0/58198/25805"} - resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsArrayOverlap03 空間ID列の重複確認関数 空入力時動作確認 -// -// 試験詳細: -// - パターン1: -// 比較対象の空間ID列:空 -// -// + 確認内容 -// - エラーを取得できること -func TestCheckSpatialIdsArrayOverlap03(t *testing.T) { - // 入力値 - spatialIds1 := []string{""} - spatialIds2 := []string{"16/0/58198/25803", "16/0/58198/25804"} - resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// TestCheckSpatialIdsArrayOverlap04 空間ID列の重複確認関数 空間IDフォーマット不正 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の空間ID列:{"25/0/29803148/13212522/777"},{"16/0/58198/25803", "16/0/58198/25804"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckSpatialIdsArrayOverlap04(t *testing.T) { - //入力値 - spatialIds1 := []string{"25/0/29803148/13212522/777"} - spatialIds2 := []string{"16/0/58198/25803", "16/0/58198/25804"} - resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]" - - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// TestPanicCheckSpatialIdsArrayOverlapWithCache 空間ID列の重複確認関数 バイナリツリー次元不正 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の空間ID列:2DTable(){"13/7274/3225"}, {"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値からpanic発生を取得できること -func TestPanicCheckSpatialIdsArrayOverlapWithCache(t *testing.T) { - defer func() { - // panicが発生しなかった場合Errorをログに出力 - if err := recover(); err == nil { - t.Errorf("error - 期待値:(panic()), 取得値:nil\n") - } else { - t.Logf("success paniced: %v", err) - } - }() - //入力値 - spatialIds1 := tree.CreateTree(tree.Create2DTable()) - // "13/7274/3225" (Appendでpanicしないよう、2Dデータを作成) - spatialIds1.Append(tree.Indexs{0, 7274, 3225}, tree.ZoomSetLevel(13), "2d value") - spatialIds2 := []string{"16/0/58198/25803"} - - // panic生成 - _, _ = CheckSpatialIdsArrayOverlapWithCache(spatialIds1, spatialIds2) - - t.Log("テスト終了") -} - -// BenchmarkCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係あり) -// -// + 試験データ -// - パターン1(包含関係あり): -// 比較対象の空間ID列:[100]{"13/0/7274/3225"}, [100]{"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値に包含関係があった場合の処理速度 -func BenchmarkCheckSpatialIdsArrayOverlap01(b *testing.B) { - // 入力値 - spatialIds1 := []string{} - spatialIds2 := []string{} - for i := 0; i < 100; i++ { - spatialIds1 = append(spatialIds1, "13/0/7274/3225") - spatialIds2 = append(spatialIds2, "16/0/58198/25804") - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - } - b.StopTimer() - b.Log("テスト終了") -} - -// BenchmarkCheckSpatialIdsArrayOverlap02 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係なし) -// -// + 試験データ -// - パターン1(包含関係なし): -// 比較対象の空間ID列:[100]{"13/0/7275/3226"}, [100]{"16/0/58198/25804"} -// -// + 確認内容 -// - 入力値に包含関係がない場合の処理速度 -func BenchmarkCheckSpatialIdsArrayOverlap02(b *testing.B) { - // 入力値 - spatialIds1 := []string{} - spatialIds2 := []string{} - for i := 0; i < 100; i++ { - spatialIds1 = append(spatialIds1, "13/0/7275/3226") - spatialIds2 = append(spatialIds2, "16/0/58198/25804") - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - } - b.StopTimer() - b.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsOverlap01 拡張空間IDの重複確認関数 正常系動作確認 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58209/25805/16/1"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から包含関係があることを確認できること -func TestCheckExtendedSpatialIdsOverlap01(t *testing.T) { - //入力値 - spatialId1 := "16/58209/25805/16/1" - spatialId2 := "15/29104/12902/15/0" - resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := true - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsOverlap02 拡張空間IDの重複確認関数 正常系動作確認 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58210/25805/16/2"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から包含関係がないことを確認できること -func TestCheckExtendedSpatialIdsOverlap02(t *testing.T) { - //入力値 - spatialId1 := "16/58210/25806/16/2" - spatialId2 := "15/29104/12902/15/0" - resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsOverlap03 拡張空間IDの重複確認関数 区切り文字数がフォーマットに従っていない場合 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58210/25805/16"},{"15/29104/12902/15"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckExtendedSpatialIdsOverlap03(t *testing.T) { - //入力値 - spatialId1 := "16/58209/25805/16" - spatialId2 := "15/29104/12902/15" - resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - expectError := "invalid format. extendedSpatialId1: 16/58209/25805/16, extendedSpatialId2: 15/29104/12902/15" - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsOverlap04 拡張空間IDの重複確認関数 int64変換時にエラーが発生した場合 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58209A/25805/16/1"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckExtendedSpatialIdsOverlap04(t *testing.T) { - //入力値 - spatialId1 := "16/58209A/25805/16/1" - spatialId2 := "15/29104/12902/15/0" - resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー" - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// BenchmarkCheckExtendedSpatialIdsOverlap01 空間IDの重複確認関数 自然数fインデックスベンチマーク -// -// + 試験データ -// - パターン1: -// 比較対象の空間ID:{"16/58206/25805/16/1"}, {"15/29104/12902/15/0"}(包含関係あり) -// -// + 確認内容 -// - 入力値に包含関係があった場合の処理速度 -func BenchmarkCheckExtendedSpatialIdsOverlap01(b *testing.B) { - // 入力値 - spatialId1 := "16/58209/25805/16/1" - spatialId2 := "15/29104/12902/15/0" - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) - } - b.StopTimer() - b.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsArrayOverlap01 拡張空間IDの重複確認関数 正常系動作確認 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58209/25805/16/1"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から包含関係があることを確認できること -func TestCheckExtendedSpatialIdsArrayOverlap01(t *testing.T) { - //入力値 - spatialIds1 := []string{"16/58206/25805/16/1", "16/58209/25805/16/1"} - spatialIds2 := []string{"15/29104/12902/15/0"} - resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := true - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsArrayOverlap02 拡張空間IDの重複確認関数 正常系動作確認 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58210/25805/16/2"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から包含関係がないことを確認できること -func TestCheckExtendedSpatialIdsArrayOverlap02(t *testing.T) { - //入力値 - spatialIds1 := []string{"16/58210/25806/16/2", "16/58211/25806/16/2"} - spatialIds2 := []string{"15/29104/12902/15/0"} - resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr != nil { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsArrayOverlap03 拡張空間IDの重複確認関数 区切り文字数がフォーマットに従っていない場合 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58210/25805/16"},{"15/29104/12902/15"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckExtendedSpatialIdsArrayOverlap03(t *testing.T) { - //入力値 - spatialIds1 := []string{"16/58209/25805/16"} - spatialIds2 := []string{"15/29104/12902/15"} - resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - expectError := "invalid format. extendedSpatialId1: 16/58209/25805/16, extendedSpatialId2: 15/29104/12902/15" - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// TestCheckExtendedSpatialIdsArrayOverlap04 拡張空間IDの重複確認関数 int64変換時にエラーが発生した場合 -// -// 試験詳細: -// + 試験データ -// - パターン1: -// 比較対象の拡張空間ID:{"16/58209A/25805/16/1"},{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値から入力チェックエラーを取得できること -func TestCheckExtendedSpatialIdsArrayOverlap04(t *testing.T) { - //入力値 - spatialIds1 := []string{"16/58209A/25805/16/1"} - spatialIds2 := []string{"15/29104/12902/15/0"} - resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - - // 期待値 - expectValue := false - expectError := "InputValueError,入力チェックエラー" - - // 空間IDと期待値の比較 - if !reflect.DeepEqual(resultValue, expectValue) { - t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) - } - if resultErr.Error() != expectError { - // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 - t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) - } - - t.Log("テスト終了") -} - -// BenchmarkCheckExtendedSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク -// -// + 試験データ -// - パターン1(包含関係あり): -// 比較対象の空間ID列:[10]{"16/58206/25805/16/1"}, [10]{"15/29104/12902/15/0"} -// -// + 確認内容 -// - 入力値に包含関係があった場合の処理速度 -func BenchmarkCheckExtendedSpatialIdsArrayOverlap01(b *testing.B) { - // 入力値 - spatialIds1 := []string{"16/58206/25805/16/1"} - spatialIds2 := []string{"15/29104/12902/15/0"} - for i := 0; i < 9; i++ { - spatialIds1 = append(spatialIds1, "16/58206/25805/16/1") - spatialIds2 = append(spatialIds2, "15/29104/12902/15/0") - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) - } - b.StopTimer() - b.Log("テスト終了") -} +package detector + +import ( + "reflect" + "testing" +) + +// TestCheckSpatialIdsOverlap01 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7274/3225"}, {"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値から包含関係があることを確認できること +func TestCheckSpatialIdsOverlap01(t *testing.T) { + // 入力値 + spatialId1 := "13/0/7274/3225" + spatialId2 := "16/0/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap02 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7275/3226"}, {"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値から包含関係がないことを確認できること +func TestCheckSpatialIdsOverlap02(t *testing.T) { + // 入力値 + spatialId1 := "13/0/7275/3226" + spatialId2 := "16/0/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap03 空間IDの重複確認関数 空入力時動作確認 +// +// 試験詳細: +// - パターン1: +// 比較対象の空間ID:空 +// +// + 確認内容 +// - エラーを取得できること +func TestCheckSpatialIdsOverlap03(t *testing.T) { + // 入力値 + spatialId1 := "" + spatialId2 := "16/0/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap04 空間IDの重複確認関数 空間IDフォーマット不正 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"25/0/29803148/13212522/777"},{"16/0/58198/25804"} +// - パターン2: +// 比較対象の空間ID:{"25/0/29803148/13212522"},{"16/0/58198/25804/777"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckSpatialIdsOverlap04(t *testing.T) { + testCases := []struct { + spatialId1 string + spatialId2 string + expectValue bool + expectError string + }{ + { + //入力値 + spatialId1: "25/0/29803148/13212522/777", + spatialId2: "16/0/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]", + }, + { + //入力値 + spatialId1: "25/0/29803148/13212522", + spatialId2: "16/0/58198/25804/777", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,spatialId: 16/0/58198/25804/777 @spatialId2[0]", + }, + } + for _, testCase := range testCases { + resultValue, resultErr := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) + + if !reflect.DeepEqual(resultValue, testCase.expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) + } + if resultErr.Error() != testCase.expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr.Error()) + } + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap05 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/8/58198/25804"} +// +// + 確認内容 +// - fインデックスの包含関係があることを確認できること +func TestCheckSpatialIdsOverlap05(t *testing.T) { + // 入力値 + spatialId1 := "13/1/7274/3225" + spatialId2 := "16/8/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap06 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/1/7274/3225"}, {"16/17/58198/25804"} +// +// + 確認内容 +// - fインデックスの包含関係がないことを確認できること +func TestCheckSpatialIdsOverlap06(t *testing.T) { + // 入力値 + spatialId1 := "13/1/7274/3225" + spatialId2 := "16/17/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap07 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-8/58198/25804"} +// +// + 確認内容 +// - fインデックスが負数の場合においても入力値から包含関係があることを確認できること +func TestCheckSpatialIdsOverlap07(t *testing.T) { + // 入力値 + spatialId1 := "13/-1/7274/3225" + spatialId2 := "16/-8/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap08 空間IDの重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/-1/7274/3225"}, {"16/-10/58198/25804"} +// +// + 確認内容 +// - fインデックスに関する包含関係がないことを確認できること +func TestCheckSpatialIdsOverlap08(t *testing.T) { + // 入力値 + spatialId1 := "13/-1/7274/3225" + spatialId2 := "16/-10/58198/25804" + resultValue, resultErr := CheckSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsOverlap09 空間IDの重複確認関数 空間ID高度変換失敗 +// +// 試験詳細: +// + 試験データ +// - パターン1(ズームレベル超過エラー): +// 比較対象の空間ID:{"26/-1/7274/3225"},{"16/8/58198/25804"} +// - パターン2(ズームレベル超過エラー): +// 比較対象の空間ID:{"13/1/7274/3225"},{"26/-8/58198/25804"} +// - パターン3(高度範囲外エラー): +// 比較対象の空間ID:{"25/16777216/0/3225"},{"18/1/58198/25804"} +// - パターン4(高度範囲外エラー): +// 比較対象の空間ID:{"18/1/58198/25804"},{"25/16777216/0/3225"} +// - パターン5(高度範囲外エラー): +// 比較対象の空間ID:{"25/-16777217/0/3225"},{"16/8/58198/25804"} +// - パターン6(高度範囲外エラー): +// 比較対象の空間ID:{"18/1/58198/25804"},{"25/-16777217/0/3225"} +// +// + 確認内容 +// - 入力値から指定した入力チェックエラー、変換エラーを取得できること +func TestCheckSpatialIdsOverlap09(t *testing.T) { + testCases := []struct { + spatialId1 string + spatialId2 string + expectValue bool + expectError string + }{ + { + //入力値 + spatialId1: "26/-1/7274/3225", + spatialId2: "16/8/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId1[0] = 26/-1/7274/3225", + }, + { + //入力値 + spatialId1: "13/1/7274/3225", + spatialId2: "26/-8/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId2[0] = 26/-8/58198/25804", + }, + { + //入力値 + spatialId1: "25/16777216/0/3225", + spatialId2: "18/1/58198/25804", + // 期待値 + expectValue: false, + expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId1[0] = 25/16777216/0/3225", + }, + { + //入力値 + spatialId1: "18/1/58198/25804", + spatialId2: "25/16777216/0/3225", + // 期待値 + expectValue: false, + expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId2[0] = 25/16777216/0/3225", + }, + { + //入力値 + spatialId1: "25/-16777217/0/3225", + spatialId2: "18/1/58198/25804", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId1[0] = 25/-16777217/0/3225", + }, + { + //入力値 + spatialId1: "18/1/58198/25804", + spatialId2: "25/-16777217/0/3225", + // 期待値 + expectValue: false, + expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId2[0] = 25/-16777217/0/3225", + }, + } + for _, testCase := range testCases { + resultValue, err := CheckSpatialIdsOverlap(testCase.spatialId1, testCase.spatialId2) + var resultErr string + if err != nil { + resultErr = err.Error() + } + + if !reflect.DeepEqual(resultValue, testCase.expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", testCase.expectValue, resultValue) + } + if resultErr != testCase.expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", testCase.expectError, resultErr) + } + } + + t.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsOverlap01 空間IDの重複確認関数 包含関係あり +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7274/3225"}, {"16/0/58198/25804"}(包含関係あり) +// +// + 確認内容 +// - 入力値の先頭に包含関係があった場合の処理速度 +func BenchmarkCheckSpatialIdsOverlap01(b *testing.B) { + // 入力値 + spatialId1 := "13/0/7274/3225" + spatialId2 := "16/0/58198/25804" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsOverlap02 空間IDの重複確認関数 包含関係なし +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"13/0/7275/3226"}, {"16/0/58198/25804"}(包含関係なし) +// +// + 確認内容 +// - 入力値に包含関係がなかった場合の処理速度 +func BenchmarkCheckSpatialIdsOverlap02(b *testing.B) { + // 入力値 + spatialId1 := "13/0/7275/3226" + spatialId2 := "16/0/58198/25804" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// TestCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID列:{"13/0/7274/3225"}, {"16/0/58198/25800", "16/0/58198/25804"} +// +// + 確認内容 +// - 入力値から包含関係があることを確認できること +func TestCheckSpatialIdsArrayOverlap01(t *testing.T) { + // 入力値 + spatialIds1 := []string{"13/0/7274/3225"} + spatialIds2 := []string{"16/0/58198/25800", "16/0/58198/25804"} + resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := true + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsArrayOverlap02 空間ID列の重複確認関数 正常系動作確認 +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID列:{"13/0/7275/3226"}, {"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値から包含関係がないことを確認できること +func TestCheckSpatialIdsArrayOverlap02(t *testing.T) { + // 入力値 + spatialIds1 := []string{"13/0/7275/3226"} + spatialIds2 := []string{"16/0/58198/25804", "16/0/58198/25805"} + resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsArrayOverlap03 空間ID列の重複確認関数 空入力時動作確認 +// +// 試験詳細: +// - パターン1: +// 比較対象の空間ID列:空 +// +// + 確認内容 +// - エラーを取得できること +func TestCheckSpatialIdsArrayOverlap03(t *testing.T) { + // 入力値 + spatialIds1 := []string{""} + spatialIds2 := []string{"16/0/58198/25803", "16/0/58198/25804"} + resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + expectError := "InputValueError,入力チェックエラー,spatialId: @spatialId1[0]" + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// TestCheckSpatialIdsArrayOverlap04 空間ID列の重複確認関数 空間IDフォーマット不正 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の空間ID列:{"25/0/29803148/13212522/777"},{"16/0/58198/25803", "16/0/58198/25804"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckSpatialIdsArrayOverlap04(t *testing.T) { + //入力値 + spatialIds1 := []string{"25/0/29803148/13212522/777"} + spatialIds2 := []string{"16/0/58198/25803", "16/0/58198/25804"} + resultValue, resultErr := CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + expectError := "InputValueError,入力チェックエラー,spatialId: 25/0/29803148/13212522/777 @spatialId1[0]" + + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係あり) +// +// + 試験データ +// - パターン1(包含関係あり): +// 比較対象の空間ID列:[100]{"13/0/7274/3225"}, [100]{"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckSpatialIdsArrayOverlap01(b *testing.B) { + // 入力値 + spatialIds1 := []string{} + spatialIds2 := []string{} + for i := 0; i < 100; i++ { + spatialIds1 = append(spatialIds1, "13/0/7274/3225") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// BenchmarkCheckSpatialIdsArrayOverlap02 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク(包含関係なし) +// +// + 試験データ +// - パターン1(包含関係なし): +// 比較対象の空間ID列:[100]{"13/0/7275/3226"}, [100]{"16/0/58198/25804"} +// +// + 確認内容 +// - 入力値に包含関係がない場合の処理速度 +func BenchmarkCheckSpatialIdsArrayOverlap02(b *testing.B) { + // 入力値 + spatialIds1 := []string{} + spatialIds2 := []string{} + for i := 0; i < 100; i++ { + spatialIds1 = append(spatialIds1, "13/0/7275/3226") + spatialIds2 = append(spatialIds2, "16/0/58198/25804") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsOverlap01 拡張空間IDの重複確認関数 正常系動作確認 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58209/25805/16/1"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から包含関係があることを確認できること +func TestCheckExtendedSpatialIdsOverlap01(t *testing.T) { + //入力値 + spatialId1 := "16/58209/25805/16/1" + spatialId2 := "15/29104/12902/15/0" + resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := true + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsOverlap02 拡張空間IDの重複確認関数 正常系動作確認 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58210/25805/16/2"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から包含関係がないことを確認できること +func TestCheckExtendedSpatialIdsOverlap02(t *testing.T) { + //入力値 + spatialId1 := "16/58210/25806/16/2" + spatialId2 := "15/29104/12902/15/0" + resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsOverlap03 拡張空間IDの重複確認関数 区切り文字数がフォーマットに従っていない場合 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58210/25805/16"},{"15/29104/12902/15"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckExtendedSpatialIdsOverlap03(t *testing.T) { + //入力値 + spatialId1 := "16/58209/25805/16" + spatialId2 := "15/29104/12902/15" + resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + expectError := "invalid format. extendedSpatialId1: 16/58209/25805/16, extendedSpatialId2: 15/29104/12902/15" + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsOverlap04 拡張空間IDの重複確認関数 int64変換時にエラーが発生した場合 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58209A/25805/16/1"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckExtendedSpatialIdsOverlap04(t *testing.T) { + //入力値 + spatialId1 := "16/58209A/25805/16/1" + spatialId2 := "15/29104/12902/15/0" + resultValue, resultErr := CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + + // 期待値 + expectValue := false + expectError := "InputValueError,入力チェックエラー" + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// BenchmarkCheckExtendedSpatialIdsOverlap01 空間IDの重複確認関数 自然数fインデックスベンチマーク +// +// + 試験データ +// - パターン1: +// 比較対象の空間ID:{"16/58206/25805/16/1"}, {"15/29104/12902/15/0"}(包含関係あり) +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckExtendedSpatialIdsOverlap01(b *testing.B) { + // 入力値 + spatialId1 := "16/58209/25805/16/1" + spatialId2 := "15/29104/12902/15/0" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckExtendedSpatialIdsOverlap(spatialId1, spatialId2) + } + b.StopTimer() + b.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsArrayOverlap01 拡張空間IDの重複確認関数 正常系動作確認 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58209/25805/16/1"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から包含関係があることを確認できること +func TestCheckExtendedSpatialIdsArrayOverlap01(t *testing.T) { + //入力値 + spatialIds1 := []string{"16/58206/25805/16/1", "16/58209/25805/16/1"} + spatialIds2 := []string{"15/29104/12902/15/0"} + resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := true + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsArrayOverlap02 拡張空間IDの重複確認関数 正常系動作確認 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58210/25805/16/2"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から包含関係がないことを確認できること +func TestCheckExtendedSpatialIdsArrayOverlap02(t *testing.T) { + //入力値 + spatialIds1 := []string{"16/58210/25806/16/2", "16/58211/25806/16/2"} + spatialIds2 := []string{"15/29104/12902/15/0"} + resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr != nil { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:nil, 取得値:%s", resultErr) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsArrayOverlap03 拡張空間IDの重複確認関数 区切り文字数がフォーマットに従っていない場合 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58210/25805/16"},{"15/29104/12902/15"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckExtendedSpatialIdsArrayOverlap03(t *testing.T) { + //入力値 + spatialIds1 := []string{"16/58209/25805/16"} + spatialIds2 := []string{"15/29104/12902/15"} + resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + expectError := "invalid format. extendedSpatialId1: 16/58209/25805/16, extendedSpatialId2: 15/29104/12902/15" + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// TestCheckExtendedSpatialIdsArrayOverlap04 拡張空間IDの重複確認関数 int64変換時にエラーが発生した場合 +// +// 試験詳細: +// + 試験データ +// - パターン1: +// 比較対象の拡張空間ID:{"16/58209A/25805/16/1"},{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値から入力チェックエラーを取得できること +func TestCheckExtendedSpatialIdsArrayOverlap04(t *testing.T) { + //入力値 + spatialIds1 := []string{"16/58209A/25805/16/1"} + spatialIds2 := []string{"15/29104/12902/15/0"} + resultValue, resultErr := CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + + // 期待値 + expectValue := false + expectError := "InputValueError,入力チェックエラー" + + // 空間IDと期待値の比較 + if !reflect.DeepEqual(resultValue, expectValue) { + t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectValue, resultValue) + } + if resultErr.Error() != expectError { + // 戻り値のエラーインスタンスが期待値と異なる場合Errorをログに出力 + t.Errorf("error - 期待値:%s, 取得値:%s\n", expectError, resultErr.Error()) + } + + t.Log("テスト終了") +} + +// BenchmarkCheckExtendedSpatialIdsArrayOverlap01 空間ID列の重複確認関数 空間IDの重複確認関数 配列ベンチマーク +// +// + 試験データ +// - パターン1(包含関係あり): +// 比較対象の空間ID列:[10]{"16/58206/25805/16/1"}, [10]{"15/29104/12902/15/0"} +// +// + 確認内容 +// - 入力値に包含関係があった場合の処理速度 +func BenchmarkCheckExtendedSpatialIdsArrayOverlap01(b *testing.B) { + // 入力値 + spatialIds1 := []string{"16/58206/25805/16/1"} + spatialIds2 := []string{"15/29104/12902/15/0"} + for i := 0; i < 9; i++ { + spatialIds1 = append(spatialIds1, "16/58206/25805/16/1") + spatialIds2 = append(spatialIds2, "15/29104/12902/15/0") + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = CheckExtendedSpatialIdsArrayOverlap(spatialIds1, spatialIds2) + } + b.StopTimer() + b.Log("テスト終了") +} From 9bca547cc3460242fff83367413c6612bc0f563e Mon Sep 17 00:00:00 2001 From: "Harutaka Obara(Matsumoto)" Date: Wed, 16 Oct 2024 17:59:18 +0900 Subject: [PATCH 13/18] Appended comparison tests --- .../convert_quadkey_and_Vertical_id_test.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index 7e045c8..974d99f 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" "testing" + "time" "github.com/trajectoryjp/spatial_id_go/v4/common/consts" @@ -1757,14 +1758,26 @@ func TestAddZBaseOffsetToZ(t *testing.T) { }, } - for _, testCase := range testCases { + for i, testCase := range testCases { + t.Logf("test case %d", i) + + startTime := time.Now() result, err := AddZBaseOffsetToZ(testCase.fIndex, testCase.zoomLevel, testCase.offset) + t.Log("elapsed time: ", time.Since(startTime)) if testCase.expectErr == (err == nil) { t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) expected error existence: %v, result: %v", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expectErr, err) - } - if result != testCase.expected { + } else if result != testCase.expected { t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) == %d, result: %d", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expected, result) } + + startTime = time.Now() + result, err = convertZToMinAltitudekey(testCase.fIndex, int64(testCase.zoomLevel), int64(testCase.zoomLevel), consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex) + t.Log("elapsed time: ", time.Since(startTime)) + if testCase.expectErr == (err == nil) { + t.Errorf("convertZToMinAltitudekey(%d, %d, %d) expected error existence: %v, result: %v", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expectErr, err) + } else if result != testCase.expected { + t.Errorf("convertZToMinAltitudekey(%d, %d, %d) == %d, result: %d", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expected, result) + } } } From b090a2f696c8864384f06a50dc8989f7bb890576 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 17 Oct 2024 12:05:51 +0900 Subject: [PATCH 14/18] fixed comparison tests between `AddZBaseOffsetToZ` and `convertZToMinAltitudekey` --- transform/convert_quadkey_and_Vertical_id.go | 4 +-- .../convert_quadkey_and_Vertical_id_test.go | 27 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/transform/convert_quadkey_and_Vertical_id.go b/transform/convert_quadkey_and_Vertical_id.go index c9b4ea5..5b9fc92 100644 --- a/transform/convert_quadkey_and_Vertical_id.go +++ b/transform/convert_quadkey_and_Vertical_id.go @@ -1136,7 +1136,7 @@ func validateIndexExists(inputIndex int64, inputZoom int64, minValueIsNegative b // // 以下の条件に当てはまる場合、エラーインスタンスが返却される。 // 入力ズームレベル不正 :zoomLevelが最大ズームレベルを超える場合(consts.zBaseExponent より上のズームレベルはサポートしない)。 -// 出力インデックス不正 :変換後のインデックスが入力ズームレベル(inputZoom)で存在しないインデックス値になった場合。 +// 出力インデックス不正 :変換後のインデックスが入力ズームレベル(inputZoom)で存在しないインデックス値になった場合。 なお出力が負数インデックスになる場合もサポートしないためこのエラーになる。 func AddZBaseOffsetToZ(fIndex int64, zoomLevel uint8, zBaseOffset int64) (int64, error) { if zoomLevel > consts.ZOriginValue { return 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("zoom level %v must be less than %v", zoomLevel, consts.ZOriginValue)) @@ -1144,7 +1144,7 @@ func AddZBaseOffsetToZ(fIndex int64, zoomLevel uint8, zBaseOffset int64) (int64, // zBaseOffset * (2**(zoomLevel-ZOriginValue)) offset := zBaseOffset >> (consts.ZOriginValue - zoomLevel) outputIndex := offset + fIndex - _, ok := validateIndexExists(outputIndex, int64(zoomLevel), true) + _, ok := validateIndexExists(outputIndex, int64(zoomLevel), false) if !ok { return 0, errors.NewSpatialIdError(errors.ValueConvertErrorCode, fmt.Sprintf("output index (%v) does not exist with given zoomLevel (%v)", outputIndex, zoomLevel)) } diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index 974d99f..a3e1f87 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -1704,8 +1704,10 @@ func TestAddZBaseOffsetToZ(t *testing.T) { 1 - (1 << consts.ZOriginValue), // -33554431 consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex, - -16777215, - false, + // 負数非許容 + //-16777215, + 0, + true, }, { (1 << (consts.ZOriginValue - 1)) - 1, // 16777215 @@ -1725,8 +1727,10 @@ func TestAddZBaseOffsetToZ(t *testing.T) { -1 - (1 << (consts.ZOriginValue - 1)), // -16777217 consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex, - -1, - false, + // 負数非許容 + //-1, + 0, + true, }, { 1 << (consts.ZOriginValue - 1), // 16777216 @@ -1749,13 +1753,14 @@ func TestAddZBaseOffsetToZ(t *testing.T) { 0, true, }, - { - -10, - consts.ZOriginValue + 1, - consts.ZBaseOffsetForNegativeFIndex, - 0, - true, - }, + // convertZToMinAltitudekey はz>25も扱えるが AddZBaseOffsetToZ ではそうでないため比較できない + //{ + // -10, + // consts.ZOriginValue + 1, + // consts.ZBaseOffsetForNegativeFIndex, + // 33554422, + // false, + //}, } for i, testCase := range testCases { From d1587dd2528c7f5feb363c4ed47689c61b998f94 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Wed, 16 Oct 2024 18:14:44 +0900 Subject: [PATCH 15/18] moved example benchmark of checkSpatialIdsArrayOverlap --- {test => examples}/detect_overlap/.gitignore | 0 {test => examples}/detect_overlap/go.mod | 0 {test => examples}/detect_overlap/go.sum | 0 {test => examples}/detect_overlap/main.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {test => examples}/detect_overlap/.gitignore (100%) rename {test => examples}/detect_overlap/go.mod (100%) rename {test => examples}/detect_overlap/go.sum (100%) rename {test => examples}/detect_overlap/main.go (100%) diff --git a/test/detect_overlap/.gitignore b/examples/detect_overlap/.gitignore similarity index 100% rename from test/detect_overlap/.gitignore rename to examples/detect_overlap/.gitignore diff --git a/test/detect_overlap/go.mod b/examples/detect_overlap/go.mod similarity index 100% rename from test/detect_overlap/go.mod rename to examples/detect_overlap/go.mod diff --git a/test/detect_overlap/go.sum b/examples/detect_overlap/go.sum similarity index 100% rename from test/detect_overlap/go.sum rename to examples/detect_overlap/go.sum diff --git a/test/detect_overlap/main.go b/examples/detect_overlap/main.go similarity index 100% rename from test/detect_overlap/main.go rename to examples/detect_overlap/main.go From 056776c4a44c233e34b83ca4fb0b0a52e472801d Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 17 Oct 2024 14:24:34 +0900 Subject: [PATCH 16/18] use `ConvertZToMinMaxAltitudekey` instead of `AddZBaseOffsetToZ` for `CheckSpatialIdsArrayOverlap` --- detector/check_spatial_id_overlap.go | 7 ++-- detector/check_spatial_id_overlap_test.go | 42 ++++++++--------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/detector/check_spatial_id_overlap.go b/detector/check_spatial_id_overlap.go index aeac981..c6b1d69 100644 --- a/detector/check_spatial_id_overlap.go +++ b/detector/check_spatial_id_overlap.go @@ -69,7 +69,9 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo if err != nil { return false, fmt.Errorf("%w @spatialId1[%v]", err, indexSpatialId1) } - convertedFIndex, errAltConversion := transform.AddZBaseOffsetToZ(int64(f1), uint8(zoom1), consts.ZBaseOffsetForNegativeFIndex) + // 高度インデックスをオフセット変換のみ実行して自然数にする + // minAltitudeKey == maxAltitudeKeyになるため結果は片方のみ利用する + convertedFIndex, _, errAltConversion := transform.ConvertZToMinMaxAltitudekey(int64(f1), int64(zoom1), int64(zoom1), consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex) if convertedFIndex < 0 { return false, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("input f-index %v is out of altitude range @spatialId1[%v] = %v", f1, indexSpatialId1, spatialId1)) } @@ -87,7 +89,8 @@ func CheckSpatialIdsArrayOverlap(spatialIds1 []string, spatialIds2 []string) (bo } // 取り出した要素の比較 // 高度インデックスをオフセット変換のみ実行して自然数にする - convertedFIndex2, errAltConversion := transform.AddZBaseOffsetToZ(int64(f2), uint8(zoom2), consts.ZBaseOffsetForNegativeFIndex) + // minAltitudeKey == maxAltitudeKeyになるため結果は片方のみ利用する + convertedFIndex2, _, errAltConversion := transform.ConvertZToMinMaxAltitudekey(int64(f2), int64(zoom2), int64(zoom2), consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex) if convertedFIndex2 < 0 { return false, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("input f-index %v is out of altitude range @spatialId2[%v] = %v", f2, indexSpatialId2, spatialId2)) } diff --git a/detector/check_spatial_id_overlap_test.go b/detector/check_spatial_id_overlap_test.go index 04a960d..f37d46c 100644 --- a/detector/check_spatial_id_overlap_test.go +++ b/detector/check_spatial_id_overlap_test.go @@ -256,17 +256,13 @@ func TestCheckSpatialIdsOverlap08(t *testing.T) { // // 試験詳細: // + 試験データ -// - パターン1(ズームレベル超過エラー): -// 比較対象の空間ID:{"26/-1/7274/3225"},{"16/8/58198/25804"} -// - パターン2(ズームレベル超過エラー): -// 比較対象の空間ID:{"13/1/7274/3225"},{"26/-8/58198/25804"} -// - パターン3(高度範囲外エラー): +// - パターン1(入力高度範囲外エラー): // 比較対象の空間ID:{"25/16777216/0/3225"},{"18/1/58198/25804"} -// - パターン4(高度範囲外エラー): +// - パターン2(入力高度範囲外エラー): // 比較対象の空間ID:{"18/1/58198/25804"},{"25/16777216/0/3225"} -// - パターン5(高度範囲外エラー): +// - パターン3(入力高度範囲外エラー): // 比較対象の空間ID:{"25/-16777217/0/3225"},{"16/8/58198/25804"} -// - パターン6(高度範囲外エラー): +// - パターン4(入力高度範囲外エラー): // 比較対象の空間ID:{"18/1/58198/25804"},{"25/-16777217/0/3225"} // // + 確認内容 @@ -279,52 +275,42 @@ func TestCheckSpatialIdsOverlap09(t *testing.T) { expectError string }{ { - //入力値 - spatialId1: "26/-1/7274/3225", - spatialId2: "16/8/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId1[0] = 26/-1/7274/3225", - }, - { - //入力値 - spatialId1: "13/1/7274/3225", - spatialId2: "26/-8/58198/25804", - // 期待値 - expectValue: false, - expectError: "InputValueError,入力チェックエラー,zoom level 26 must be less than 25 @spatialId2[0] = 26/-8/58198/25804", - }, - { + // 入力空間IDのfインデックスが不正 //入力値 spatialId1: "25/16777216/0/3225", spatialId2: "18/1/58198/25804", // 期待値 expectValue: false, - expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId1[0] = 25/16777216/0/3225", + expectError: "InputValueError,入力チェックエラー,output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset @spatialId1[0] = 25/16777216/0/3225", }, { + // 入力空間IDのfインデックスが不正 //入力値 spatialId1: "18/1/58198/25804", spatialId2: "25/16777216/0/3225", // 期待値 expectValue: false, - expectError: "ValueConvertError,値の変換エラー,output index (33554432) does not exist with given zoomLevel (25) @spatialId2[0] = 25/16777216/0/3225", + expectError: "InputValueError,入力チェックエラー,output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset @spatialId2[0] = 25/16777216/0/3225", }, { + // 入力可能な高度インデックス範囲を超えている(下限より小さい) //入力値 spatialId1: "25/-16777217/0/3225", spatialId2: "18/1/58198/25804", // 期待値 expectValue: false, - expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId1[0] = 25/-16777217/0/3225", + // 高度変換が負数を許容しないため高度変換エラーになる + expectError: "InputValueError,入力チェックエラー,output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset @spatialId1[0] = 25/-16777217/0/3225", }, { + // 入力可能な高度インデックス範囲を超えている(下限より小さい) //入力値 spatialId1: "18/1/58198/25804", spatialId2: "25/-16777217/0/3225", // 期待値 expectValue: false, - expectError: "InputValueError,入力チェックエラー,input f-index -16777217 is out of altitude range @spatialId2[0] = 25/-16777217/0/3225", + // 高度変換が負数を許容しないため高度変換エラーになる + expectError: "InputValueError,入力チェックエラー,output index does not exist with given outputZoom, zBaseExponent, and zBaseOffset @spatialId2[0] = 25/-16777217/0/3225", }, } for _, testCase := range testCases { From a0e744016df071d6e4b05c6e5ade5dcc47a9f70c Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 17 Oct 2024 14:38:49 +0900 Subject: [PATCH 17/18] remove `AddZBaseOffsetToZ` it found that `AddZBaseOffsetToZ` is not useful since it is slower than `ConvertZToMinMaxAltitudekey`, and this function existence only matters when `AddZBaseOffsetToZ` is faster than `ConvertZToMinAltitudekey`. --- transform/convert_quadkey_and_Vertical_id.go | 40 ------ .../convert_quadkey_and_Vertical_id_test.go | 115 ------------------ 2 files changed, 155 deletions(-) diff --git a/transform/convert_quadkey_and_Vertical_id.go b/transform/convert_quadkey_and_Vertical_id.go index 5b9fc92..5700c07 100644 --- a/transform/convert_quadkey_and_Vertical_id.go +++ b/transform/convert_quadkey_and_Vertical_id.go @@ -1111,46 +1111,6 @@ func validateIndexExists(inputIndex int64, inputZoom int64, minValueIsNegative b return nil, true } -// AddZBaseOffsetToZ (拡張)空間IDz成分(fインデックス)にオフセット加算する -// ConvertZToAltitudekey()でズームレベル変換を行わずオフセット変換のみ指定したもの -// -// したがって ConvertZToAltitudekey(f, z, z, consts.ZBaseExponent, zBaseOffset)と等価 -// -// 引数 : -// -// fIndex : (拡張)空間ID高さインデックス(f) -// -// zoomLevel : (拡張)空間IDのズームレベル(z) -// -// ここで指定するズームレベルはconsts.ZBaseExponent以下の値でなければならない -// -// offsetZoom : オフセット変換量。正のoffsetで上方向, 負のoffsetで下方向に変換される -// -// offsetZoomは2**(consts.ZBaseExponent - zoomLevel)より大きくするべき(除算時に切り捨てられるため) -// -// 戻り値 : -// -// オフセット変換後のfインデックス -// -// 戻り値(エラー) : -// -// 以下の条件に当てはまる場合、エラーインスタンスが返却される。 -// 入力ズームレベル不正 :zoomLevelが最大ズームレベルを超える場合(consts.zBaseExponent より上のズームレベルはサポートしない)。 -// 出力インデックス不正 :変換後のインデックスが入力ズームレベル(inputZoom)で存在しないインデックス値になった場合。 なお出力が負数インデックスになる場合もサポートしないためこのエラーになる。 -func AddZBaseOffsetToZ(fIndex int64, zoomLevel uint8, zBaseOffset int64) (int64, error) { - if zoomLevel > consts.ZOriginValue { - return 0, errors.NewSpatialIdError(errors.InputValueErrorCode, fmt.Sprintf("zoom level %v must be less than %v", zoomLevel, consts.ZOriginValue)) - } - // zBaseOffset * (2**(zoomLevel-ZOriginValue)) - offset := zBaseOffset >> (consts.ZOriginValue - zoomLevel) - outputIndex := offset + fIndex - _, ok := validateIndexExists(outputIndex, int64(zoomLevel), false) - if !ok { - return 0, errors.NewSpatialIdError(errors.ValueConvertErrorCode, fmt.Sprintf("output index (%v) does not exist with given zoomLevel (%v)", outputIndex, zoomLevel)) - } - return outputIndex, nil -} - // 高さのbit形式のインデックスを計算する。 // // 引数 : diff --git a/transform/convert_quadkey_and_Vertical_id_test.go b/transform/convert_quadkey_and_Vertical_id_test.go index a3e1f87..c2d9181 100755 --- a/transform/convert_quadkey_and_Vertical_id_test.go +++ b/transform/convert_quadkey_and_Vertical_id_test.go @@ -8,7 +8,6 @@ import ( "strconv" "strings" "testing" - "time" "github.com/trajectoryjp/spatial_id_go/v4/common/consts" @@ -1685,120 +1684,6 @@ func TestConvertZToMinMaxAltitudekey_9(t *testing.T) { assertConvertZToMinMaxAltitudekey(t, expectedMin, expectedMax, args) } -func TestAddZBaseOffsetToZ(t *testing.T) { - testCases := []struct { - fIndex int64 - zoomLevel uint8 - offset int64 - expected int64 - expectErr bool - }{ - { // "16/-10/58198/25804" (z=16,f=-10のみ使用) - -10, - 16, - consts.ZBaseOffsetForNegativeFIndex, - (1 << (16 - 1)) - 10, // 32758 - false, - }, - { - 1 - (1 << consts.ZOriginValue), // -33554431 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - // 負数非許容 - //-16777215, - 0, - true, - }, - { - (1 << (consts.ZOriginValue - 1)) - 1, // 16777215 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - 33554431, - false, - }, - { - -(1 << (consts.ZOriginValue - 1)), // -16777216 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - 0, - false, - }, - { - -1 - (1 << (consts.ZOriginValue - 1)), // -16777217 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - // 負数非許容 - //-1, - 0, - true, - }, - { - 1 << (consts.ZOriginValue - 1), // 16777216 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - 0, - true, - }, - { - 1 - (1 << consts.ZOriginValue), // -33554431 - consts.ZOriginValue, - -consts.ZBaseOffsetForNegativeFIndex, - 0, - true, - }, - { - (1 << consts.ZOriginValue) - 1, // 33554431 - consts.ZOriginValue, - consts.ZBaseOffsetForNegativeFIndex, - 0, - true, - }, - // convertZToMinAltitudekey はz>25も扱えるが AddZBaseOffsetToZ ではそうでないため比較できない - //{ - // -10, - // consts.ZOriginValue + 1, - // consts.ZBaseOffsetForNegativeFIndex, - // 33554422, - // false, - //}, - } - - for i, testCase := range testCases { - t.Logf("test case %d", i) - - startTime := time.Now() - result, err := AddZBaseOffsetToZ(testCase.fIndex, testCase.zoomLevel, testCase.offset) - t.Log("elapsed time: ", time.Since(startTime)) - if testCase.expectErr == (err == nil) { - t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) expected error existence: %v, result: %v", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expectErr, err) - } else if result != testCase.expected { - t.Errorf("CalcAddZBaseOffsetToZ(%d, %d, %d) == %d, result: %d", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expected, result) - } - - startTime = time.Now() - result, err = convertZToMinAltitudekey(testCase.fIndex, int64(testCase.zoomLevel), int64(testCase.zoomLevel), consts.ZOriginValue, consts.ZBaseOffsetForNegativeFIndex) - t.Log("elapsed time: ", time.Since(startTime)) - if testCase.expectErr == (err == nil) { - t.Errorf("convertZToMinAltitudekey(%d, %d, %d) expected error existence: %v, result: %v", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expectErr, err) - } else if result != testCase.expected { - t.Errorf("convertZToMinAltitudekey(%d, %d, %d) == %d, result: %d", testCase.fIndex, testCase.zoomLevel, testCase.offset, testCase.expected, result) - } - } -} - -func FuzzAddZBaseOffsetToZAt18(f *testing.F) { - conditions := []int64{-131072, 131072} // (1 << 24) >> (abs(18-25)) - for _, cond := range conditions { - f.Add(cond) - } - f.Fuzz(func(t *testing.T, cond int64) { - _, err := AddZBaseOffsetToZ(cond, 18, consts.ZBaseOffsetForNegativeFIndex) - if err != nil && cond > conditions[0] && cond < conditions[1] { - t.Error(err) - } - }) -} - func TestConvertZToMinAltitudekey_1(t *testing.T) { expected := int64(47) From e6054ccc06ea26cc8f98b05b6c44befc53c1fd92 Mon Sep 17 00:00:00 2001 From: Mandai Yusuke Date: Thu, 17 Oct 2024 14:41:39 +0900 Subject: [PATCH 18/18] renamed example detect overlap directory --- examples/{detect_overlap => detectOverlap}/.gitignore | 0 examples/{detect_overlap => detectOverlap}/go.mod | 0 examples/{detect_overlap => detectOverlap}/go.sum | 0 examples/{detect_overlap => detectOverlap}/main.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename examples/{detect_overlap => detectOverlap}/.gitignore (100%) rename examples/{detect_overlap => detectOverlap}/go.mod (100%) rename examples/{detect_overlap => detectOverlap}/go.sum (100%) rename examples/{detect_overlap => detectOverlap}/main.go (100%) diff --git a/examples/detect_overlap/.gitignore b/examples/detectOverlap/.gitignore similarity index 100% rename from examples/detect_overlap/.gitignore rename to examples/detectOverlap/.gitignore diff --git a/examples/detect_overlap/go.mod b/examples/detectOverlap/go.mod similarity index 100% rename from examples/detect_overlap/go.mod rename to examples/detectOverlap/go.mod diff --git a/examples/detect_overlap/go.sum b/examples/detectOverlap/go.sum similarity index 100% rename from examples/detect_overlap/go.sum rename to examples/detectOverlap/go.sum diff --git a/examples/detect_overlap/main.go b/examples/detectOverlap/main.go similarity index 100% rename from examples/detect_overlap/main.go rename to examples/detectOverlap/main.go