Skip to content

Commit

Permalink
Merged pull request #16 from trajectoryjp/feature/issue#15
Browse files Browse the repository at this point in the history
Make GetSpatialIdsWithinRadiusOfLine() return expected result when radius==0
  • Loading branch information
HarutakaMatsumoto committed Apr 22, 2024
2 parents 364edd1 + 7cab703 commit 1773946
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 27 deletions.
5 changes: 3 additions & 2 deletions operated/shifting_spatial_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ func Get26spatialIdsAroundVoxel(spatialID string) []string {
// error: エラー
func GetNspatialIdsAroundVoxcels(spatialIDs []string, hLayers, vLayers int64) ([]string, error) {

if hLayers < 1 || vLayers < 1 {
return nil, fmt.Errorf("both hLayers and vLayers parameters must be >= 1")
// invalid input validation (both parameters must be non-negative)
if hLayers < 0 || vLayers < 0 {
return nil, fmt.Errorf("both hLayers and vLayers parameters must be >= 0")
}

hExpandParam := hLayers * 2
Expand Down
65 changes: 65 additions & 0 deletions operated/shifting_spatial_id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ func TestGetShiftingSpatialID07(t *testing.T) {
t.Log("テスト終了")
}

// TestGetNspatialIdsAroundVoxcels01 tests hLayers=1 and vLayers=1 around two spatial IDs
// Expected value should return the same result as the combined, unique result of Get26spatialIdsAroundVoxel() for each of the two "ids"
func TestGetNspatialIdsAroundVoxcels01(t *testing.T) {

ids := []string{"10/10/10/10/10", "10/11/11/10/10"}
Expand Down Expand Up @@ -271,6 +273,8 @@ func TestGetNspatialIdsAroundVoxcels01(t *testing.T) {

}

// TestGetNspatialIdsAroundVoxcels02 tests hLayers=1 and vLayers=1
// Expected value should be the same result as Get26spatialIdsAroundVoxel()
func TestGetNspatialIdsAroundVoxcels02(t *testing.T) {

ids := []string{"10/10/10/10/10"}
Expand Down Expand Up @@ -299,6 +303,67 @@ func TestGetNspatialIdsAroundVoxcels02(t *testing.T) {

}

// TestGetNspatialIdsAroundVoxcels03 tests hLayers=0 and vLayers=0
// Expected value should be 0 Extended Spatial IDs, or an empty string []string{}
func TestGetNspatialIdsAroundVoxcels03(t *testing.T) {

ids := []string{"10/10/10/10/10"}
expectVal := []string{}

nLayer := 0

resultVal, error := GetNspatialIdsAroundVoxcels(ids, int64(nLayer), int64(nLayer))
if error != nil {
t.Error(error)
}

// using maps will allow comparison with deepEqual if order is different
map1, map2 := make(map[string]string), make(map[string]string)
for _, value := range expectVal {
map1[value] = value
}
for _, value := range resultVal {
map2[value] = value
}
if !reflect.DeepEqual(map1, map2) {
// 戻り値の空間IDが期待値と異なる場合Errorをログに出力
t.Errorf("空間ID - 期待値:%v, \n取得値: %v", map1, map2)
}
t.Log("テスト終了")

}

// TestGetNspatialIdsAroundVoxcels04 tests hLayers=0 and vLayers=1
// Expected value should be 1 Extended Spatial ID above and 1 Extended Spatial ID below "id"
func TestGetNspatialIdsAroundVoxcels04(t *testing.T) {

ids := []string{"10/10/10/10/10"}
expectVal := []string{"10/10/10/10/9", "10/10/10/10/11"}

resultVal, error := GetNspatialIdsAroundVoxcels(
ids,
0,
1)
if error != nil {
t.Error(error)
}

// using maps will allow comparison with deepEqual if order is different
map1, map2 := make(map[string]string), make(map[string]string)
for _, value := range expectVal {
map1[value] = value
}
for _, value := range resultVal {
map2[value] = value
}
if !reflect.DeepEqual(map1, map2) {
// 戻り値の空間IDが期待値と異なる場合Errorをログに出力
t.Errorf("空間ID - 期待値:%v, \n取得値: %v", map1, map2)
}
t.Log("テスト終了")

}

// stringスライスの中に指定文字列を含むか判定する
//
// 引数:
Expand Down
41 changes: 18 additions & 23 deletions transform/voxel_around_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,17 @@ func GetExtendedSpatialIdsWithinRadiusOfLine(startPoint *object.Point, endPoint
if error != nil {
return nil, error
}

// 2. Find the Spatial Ids that are not on the line but within the radius distance of the line

// Variable Setup

// the closest.measure object to determine IDs not on the path line but within the criterion distance
var measure1 = closest.Measure{}
// the distances from each SpatialID in uniqueMegaBoxIDs to the route path line
var measureDistances1 []float64
// the slice of Spatial IDs created by combining the result of all adjacent 26 SpatialIDs from all spatialIDs on the route line
var megaBoxIds []string
// the slice of unique Spatial IDs (non-duplicates) from megaBoxIDs
var uniqueMegaBoxIds []string
// the Spatial IDs in uniqueMegaBoxIds with the IDs on the route path line removed
var noLinePathMegaBoxIds []string
// the slice of Spatial Ids from noLinePathMegaBoxIds found within the radius but not on the route line
// the slice of ExtendedSpatialIDs around the Ids on the route line. (returned result already cleaned for duplicates).
var idsAroundVoxcels []string
// the Extended Spatial IDs with the IDs on the route path line removed
var idsAroundLine []string // fix this
// the slice of Extended Spatial Ids from noLinePathIdsAroundLine found within the radius but not on the route line
var idsToAdd []string
// points is the [2]slice / list of startPoint and endPoint in geodesic format (lat/lon)
var points = []*object.Point{startPoint, endPoint}
Expand Down Expand Up @@ -97,20 +92,18 @@ func GetExtendedSpatialIdsWithinRadiusOfLine(startPoint *object.Point, endPoint
}

// Return the SpatialIDs within the box created by hLayers and vLayers
megaBoxIds, error = operated.GetNspatialIdsAroundVoxcels(idsOnLine, hLayers, vLayers)
idsAroundVoxcels, error = operated.GetNspatialIdsAroundVoxcels(idsOnLine, hLayers, vLayers)
if error != nil {
return nil, error
}

// Make unique list of spatial ids
uniqueMegaBoxIds = common.Unique(megaBoxIds)

// Subtract the spatial ids in the line
noLinePathMegaBoxIds = common.Difference(uniqueMegaBoxIds, idsOnLine)
// Remove the spatial ids in the line from the ids around the line so that only the ids around the line remain
idsAroundLine = common.Difference(idsAroundVoxcels, idsOnLine)

// if skipsMeasurement=true, measure the distance between the route line and each id in idsAroundLine
if !skipsMeasurement {

for _, id := range noLinePathMegaBoxIds {
for _, id := range idsAroundLine {

// Get 8 vertexes of the SpatialID
IdVertexes, error := shape.GetPointOnExtendedSpatialId(id, enum.Vertex)
Expand Down Expand Up @@ -144,8 +137,6 @@ func GetExtendedSpatialIdsWithinRadiusOfLine(startPoint *object.Point, endPoint
// dist is the closest distance between the line (ConvexHull[0]) and the vertexes of Spatial ID[i]
var dist = measure1.Distance

measureDistances1 = append(measureDistances1, dist)

// Since MeasureNonnegativeDistance() was used the distance value in dist
// will always be non-zero. If dist < radius, add the spatialID to idsToAdd
if dist < (radius) {
Expand All @@ -158,7 +149,8 @@ func GetExtendedSpatialIdsWithinRadiusOfLine(startPoint *object.Point, endPoint
idsWithinCriterion = common.Unique(common.Union(idsToAdd, idsOnLine))

} else {
idsWithinCriterion = megaBoxIds
// if skipsMeasurement=false, return all ids in noLinePathIdsAroundLine and combine with idsOnLine
idsWithinCriterion = common.Unique(common.Union(idsAroundLine, idsOnLine))
}

return idsWithinCriterion, nil
Expand All @@ -180,7 +172,10 @@ func GetExtendedSpatialIdsWithinRadiusOfLine(startPoint *object.Point, endPoint
// error: エラー
func FitClearanceAroundExtendedSpatialID(spatialID string, clearance float64) (horizontalLayer int64, verticalLayer int64, error error) {

// validate clearance
// validate clearance: There are two special cases:
// 1. The clearance must be non-negative (clearance must be >= 0)
// 2. If the clearance is exactly 0, return 0 for both the horizontalLayer and verticalLayer. This is because
// if clearance is 0, the only Spatial IDs that are on the route line should be used -- no surrounding Spatial IDs
if clearance < 0 {
return 0, 0, fmt.Errorf("\ninvalid clearance value. Clearance must be >= 0")
}
Expand All @@ -200,8 +195,8 @@ func FitClearanceAroundExtendedSpatialID(spatialID string, clearance float64) (h
// vLayyer is the number of vertical spatialID distances required to fit the clearance
var vLayer int64

var hUnits int64 = 2
var vUnits int64 = 2
var hUnits int64 = 1
var vUnits int64 = 1

// Begin horizonal fitting loop (determine hLayer)
for {
Expand Down
105 changes: 103 additions & 2 deletions transform/voxel_around_line_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,83 @@ import (
"github.com/trajectoryjp/spatial_id_go/v3/shape"
)

// TestGetExtendedSpatialIdsWithinRadiusOfLine01 tests when skipsMeasurement=true and radius =0
// Expected value should return the exact same voxels as GetExtendedSpatialIdsOnLine
func TestGetExtendedSpatialIdsWithinRadiusOfLine01(t *testing.T) {

var radius float64 = 0
var hZoom int64 = 25
var vZoom int64 = 25

startPoint, error := object.NewPoint(139.788452, 35.67093015, 0)
if error != nil {
t.Error(error)
}
endPoint, error := object.NewPoint(139.788452, 35.670840, 0)
if error != nil {
t.Error(error)
}

idsOnLine, error := shape.GetExtendedSpatialIdsOnLine(startPoint, endPoint, hZoom, vZoom)
if error != nil {
t.Error(error)
}
idsWithinRadiusOfLine, error := GetExtendedSpatialIdsWithinRadiusOfLine(startPoint, endPoint, radius, hZoom, vZoom, true)
if error != nil {
t.Error(error)
}

map1, map2 := make(map[string]string), make(map[string]string)
for _, value := range idsOnLine {
map1[value] = value
}
for _, value := range idsWithinRadiusOfLine {
map2[value] = value
}
if !reflect.DeepEqual(map1, map2) {
t.Errorf("期待値: %v 取得値: %v", idsOnLine, idsWithinRadiusOfLine)
}
t.Log("テスト終了")

}

// TestGetSpatialIdsWithinRadiusOfLine02 tests when skipsMeasurement=true and radius > 0 but radius is
// less than than the length of a voxcel.
// Expected value should return 54 voxcels:
// - GetExtendedSpatialIdsOnLine: 4 ids
// - FitClearanceAroundSpatialId: hlayer=1, vlayer=1
// - GetNspatialIdsAroundVoxcels: (count excludes ids on line) 50
// - GetSpatialIdsWithinRadiusOfLine: (count includes ids on line) 9 ids per layer * 6 layers = 54 ids expected
func TestGetExtendedSpatialIdsWithinRadiusOfLine02(t *testing.T) {

var radius float64 = 0.1
var hZoom int64 = 23
var vZoom int64 = 23

startPoint, error := object.NewPoint(139.788452, 35.67093015, 0)
if error != nil {
t.Error(error)
}
endPoint, error := object.NewPoint(139.788452, 35.670840, 0)
if error != nil {
t.Error(error)
}

idsOnLine, error := shape.GetExtendedSpatialIdsOnLine(startPoint, endPoint, hZoom, vZoom)
if error != nil {
t.Error(error)
}
idsWithinRadiusOfLine, error := GetExtendedSpatialIdsWithinRadiusOfLine(startPoint, endPoint, radius, hZoom, vZoom, true)
if error != nil {
t.Error(error)
}

if len(idsOnLine) != 4 || len(idsWithinRadiusOfLine) != 54 {
t.Fatalf("Expected values not returned. \nExpected Number of Extended Spatial Ids on Line: 4; returned: %v\nExpected number of extended Spatial Ids within radius of line: 54; returned: %v", len(idsOnLine), len(idsWithinRadiusOfLine))
}

}

func TestGetExtendedSpatialIdsWithinRadiusOfLine10m_r0_horizontal(t *testing.T) {

var radius float64 = 0
Expand Down Expand Up @@ -68,8 +145,8 @@ func TestGetExtendedSpatialIdsWithinRadiusOfLine10m_r0_horizontal(t *testing.T)
func TestFitClearanceAroundExtendedSpatialID01(t *testing.T) {

var clearance float64 = 0
var expectedHLayer int64 = 1
var expectedVLayer int64 = 1
var expectedHLayer int64 = 0
var expectedVLayer int64 = 0

point, error := object.NewPoint(139.788081, 35.672680, 100)
if error != nil {
Expand Down Expand Up @@ -161,6 +238,30 @@ func TestFitClearanceAroundExtendedSpatialID04(t *testing.T) {

}

func TestFitClearanceAroundExtendedSpatialID05(t *testing.T) {

var clearance float64 = 0.01
var expectedHLayer int64 = 1
var expectedVLayer int64 = 1

point, error := object.NewPoint(139.788081, 35.672680, 100)
if error != nil {
t.Error(error)
}
hLayer, vLayer, error := testFitClearanceAroundSpatialID(t, point, clearance, 21, 21)
if error != nil {
t.Error(error)
}

if hLayer != expectedHLayer {
t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectedHLayer, hLayer)
}
if vLayer != expectedVLayer {
t.Errorf("空間ID - 期待値:%v, 取得値:%v", expectedVLayer, vLayer)
}

}

func testFitClearanceAroundSpatialID(t *testing.T, point *object.Point, clearance float64, hZoom int64, vZoom int64) (hLayer int64, vlayer int64, error error) {

points := []*object.Point{point}
Expand Down

0 comments on commit 1773946

Please sign in to comment.