Packages
dynamic_rtree
0.1.0
Distributed Dynamic R-tree (DDRT) implementation for Elixir. It's mainly a R-tree. Why dynamic? Because it's optimized to do fast updates at the tree leafs spatial index. Why distributed? Well.. you can run the DDRT on different nodes and they will have the same r-tree data.
Current section
Files
Jump to
Current section
Files
lib/elixir_rtree/utils.ex
defmodule ElixirRtree.Utils do
@moduledoc false
def format_bbox([{min_x,max_x} = x,{min_y,max_y} = y])do
%{
x: x,
y: y,
xm: min_x,
xM: max_x,
ym: min_y,
yM: max_y
}
end
def ets_value([raw],atom)do
case atom do
:bbox -> raw |> elem(1)
:type -> raw |> elem(2)
end
end
def ets_index(atom)do
case atom do
:bbox -> 2
:type -> 3
end
end
# Combine two bounding boxes into one
def combine(box1,box2)do
a = box1 |> format_bbox
b = box2 |> format_bbox
xm = Kernel.min(a.xm,b.xm)
xM = Kernel.max(a.xM,b.xM)
ym = Kernel.min(a.ym,b.ym)
yM = Kernel.max(a.yM,b.yM)
result = [{xm,xM},{ym,yM}]
result = if area(box1) === 0, do: box2, else: result
if area(box2) === 0, do: box1, else: result
end
#Combine multiple bbox
def combine_multiple(list)when length(list) > 1 do
real_list = list |> Enum.filter(fn x -> area(x) > 0 end)
tl(real_list) |> Enum.reduce(hd(real_list),fn [{a,b},{c,d}] = _e, [{x,y},{z,w}] = _acc ->
[{Kernel.min(a,x),Kernel.max(b,y)},{Kernel.min(c,z),Kernel.max(d,w)}]
end)
end
def combine_multiple(list)do
hd(list)
end
# Returns de percent of the overlap area (of the box1) between box1 and box2
def overlap_area(box1,box2)do
a = box1 |> format_bbox
b = box2 |> format_bbox
x_overlap = Kernel.max(0,Kernel.min(a.xM,b.xM) - Kernel.max(a.xm,b.xm))
y_overlap = Kernel.max(0,Kernel.min(a.yM,b.yM) - Kernel.max(a.ym,b.ym))
((x_overlap * y_overlap)/area(box1)) * 100
end
# Return if those 2 boxes are overlapping
def overlap?(box1,box2)do
if overlap_area(box1,box2) > 0, do: true, else: false
end
# Return if box 1 contains box 2
def contained?(box1,box2)do
a = box1 |> format_bbox
b = box2 |> format_bbox
a.xm <= b.xm and a.xM >= b.xM and a.ym <= b.ym and a.yM >= b.yM
end
# Enlargement area after adding new box
def enlargement_area(box,new_box)do
a1 = area(box)
a2 = combine_multiple([box,new_box]) |> area
a2 - a1
end
# Checks if box is at some border of parent_box
def in_border?(parent_box,box)do
p = parent_box |> format_bbox
b = box |> format_bbox
p.xm == b.xm or p.xM == b.xM or p.ym == b.ym or p.yM == b.yM
end
# Return the area of a bounding box
def area([{a,b},{c,d}]) when ((b - a) * (d - c) != 0) do
(b - a) * (d - c)
end
def area([{_a,_b},{_c,_d}])do
-1
end
# Return de the middle bounding box value
def middle_value([{a,b},{c,d}])do
(a + b + c + d) / 2
end
def get_posxy([{a,b},{c,d}])do
%{x: (b + a) / 2, y: (c + d) / 2 }
end
def box_move([{a,b},{c,d}],move)do
x = move[:x]
y = move[:y]
[{a+x,b+x},{c+y,d+y}]
end
end