見原文,轉自http://longriver.me/?p=355算法
圖1,將一個地域劃分爲網格,並給每一個網格惟一idide
圖2,AOI:圓明園,天安門,森林公園flex
假設一種空間檢索的應用場景,如今有一堆面狀的區域,咱們知道這些面狀區域(AOI area of interest)的輪廓如圖2,咱們有一些座標點,那麼如何判斷這些座標點是否落在aoi裏,落到了哪一個區域裏呢?ui
完成這項工做,須要三步:this
1
2
3
4
5
6
7
8
9
10
11
|
int
aoi_util
::
build_gridindex
(
)
{
// build index for each aoi
for
(
size_t
j
=
0
;
j
<
aois
.
size
(
)
;
++
j
)
{
aoi_index
idx
;
idx
=
j
;
AOI
*
aoi_ptr
=
&aois
[
j
]
;
build_gridindex
(
aoi_ptr
,
idx
)
;
}
return
0
;
}
|
Mesh_size 能夠根據一共檢索區域的大小來進行設定,在咱們的應用場景下設爲1000,指每一個網格的大小爲1000m。spa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
int
aoi_util
::
build_gridindex
(
AOI *
aoi_ptr
,
aoi_index
idx
)
{
ll_t
min_x
,
min_y
,
max_x
,
max_y
;
//get every aoi's leftmost rightmost ,ceiling,bottom
min_x
=
aoi_ptr
->
min_boundx
(
)
;
min_y
=
aoi_ptr
->
min_boundy
(
)
;
max_x
=
aoi_ptr
->
max_boundx
(
)
;
max_y
=
aoi_ptr
->
max_boundy
(
)
;
// get every grid id
typedef
grid_index
::
iterator
grid_map_it
;
for
(
size_t
a
=
size_t
(
min_x
/
mesh_size
)
;
a
<=
size_t
(
max_x
/
mesh_size
)
;
a
++
)
{
for
(
size_t
b
=
size_t
(
min_y
/
mesh_size
)
;
b
<=
size_t
(
max_y
/
mesh_size
)
;
b
++
)
{
uint32_t
id
=
get_id_by_grid
(
a
,
b
)
;
grid_map_it
it
=
grid2index
.
find
(
id
)
;
if
(
it
==
grid2index
.
end
(
)
)
{
index_value
idx_vl
;
idx_vl
.
push_back
(
idx
)
;
// each grid may have more than one aoi
grid2index
.
insert
(
std
::
pair
<
uint32_t
,
index_value
>
(
id
,
idx_vl
)
)
;
}
else
{
it
->
second
.
push_back
(
idx
)
;
}
}
}
return
0
;
}
|
2,爲每一個檢索點找到所在的mesh 和每一個mesh中的aoi
rest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
AOI
*
aoi_util
::
get_aoi_for_point
(
ll_t
x
,
ll_t
y
)
{
uint32_t
mesh_id
=
get_id_by_xy
(
x
,
y
)
;
typedef
grid_index
::
const_iterator
grid_map_it
;
typedef
index_value
::
iterator
index_value_it
;
index_value
idx_list
;
grid_map_it
it
=
grid2index
.
find
(
mesh_id
)
;
if
(
it
!=
grid2index
.
end
(
)
)
{
idx_list
=
it
->
second
;
for
(
index_value_it
iv_it
=
idx_list
.
begin
(
)
;
iv_it
!=
idx_list
.
end
(
)
;
++
iv_it
)
{
aoi_index
idx
=
*
iv_it
;
AOI
*
aoi_i
=
&
(
aois
[
idx
]
)
;
// determine if poinxy in this aoi
if
(
aoi_i
->
is_point_inside
(
x
,
y
)
)
{
return
aoi_i
;
}
}
}
return
NULL
;
}
|
3,判斷一個point 是否在aoi裏面,一個aoi其本質上是一個多邊形,由頂點描述,所以如今有不少現成的算法講如何判斷一個點是否落在多邊形中,參照這邊博文http://alienryderflex.com/polygon/講的很是詳細,代碼實現以下,具體原理,請閱讀博文。code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
bool
AOI
::
is_point_inside
(
ll_t
x
,
ll_t
y
)
{
typedef
vertexes_t
::
iterator
v_iterator
;
v_iterator
it
,
pre_it
;
bool
oddNodes
=
0
;
// vertexes are polygon’s vertexes vector
it
=
pre_it
=
vertexes
.
begin
(
)
;
for
(
;
it
!=
vertexes
.
end
(
)
;
++
it
)
{
if
(
(
it
->
second
<
y
&&
pre_it
->
second
>=
y
)
||
(
pre_it
->
second
<
y
&&
it
->
second
>=
y
)
&&
(
it
->
first
<=
x
||
it
->
second
<=
x
)
)
{
oddNodes
^=
(
it
->
first
+
(
y
-
it
->
second
)
/
(
pre_it
->
second
-
it
->
second
)
\
*
(
pre_it
->
first
-
it
->
first
)
<
x
)
;
}
pre_it
=
it
;
}
return
oddNodes
;
}
|
4,剩餘的一些代碼,如如何對grid去hash值,能夠本身去實現,貼上咱們的實現,僅做參考:htm
1
2
3
4
|
uint32_t
aoi_util
::
get_id_by_grid
(
uint32_t
a
,
uint32_t
b
)
{
return
(
(
a
&
0xffff
)
<<
16
)
|
(
b
&
0xffff
)
;
}
|