xoolive / quadtree

Quadtrees – iterate on pairs of neighbours
MIT License
8 stars 3 forks source link

Improve precision near borders by using double precision #12

Closed cglacet closed 6 years ago

cglacet commented 6 years ago

After changing float to double the precision roughly went from 10^(-3) to 10^(-12) (meaning that all elements that lies inside the mask at a distance greater than 10^(-12) from the mask-borders are correctly retrieved when requesting .elements(), elements that are closer to the border may not be part of elements() iterator)

I used a test where I drop a single point px,py and move the mask area around it using a fixed delta dx, dy (distance to this point) and a variable error error_test that goes smaller and smaller for each iteration. I also test limits for px,py being inside and outside the mask.

from smartquadtree import Quadtree

quad_tree = Quadtree(0, 0, 180, 90)
px,py = 40,20
quad_tree.insert((px,py))
dx, dy = 0.1,0.1
for inside in [1, -1]:
    if inside == 1:
        print("Testing locations barely inside: ")
    if inside == -1:
        print("Testing locations barely outside: ")
    total_nb_tests = 100
    nb_test_passed = 0
    failed = False
    for i in range(total_nb_tests):
        try:
            error_test = 10**(-i)*min(dx,dy)
            x,y = px+dx-(error_test*inside),py+dy-(error_test*inside)
            sw = (x-dx, y-dy)
            nw = (x-dx, y+dy)
            ne = (x+dx, y+dy)
            se = (x+dx, y-dy)
            quad_tree.set_mask([sw,nw,ne,se])
            nb_elements_captured = len(list(quad_tree.elements()))
            inside_test_success = (nb_elements_captured == 1 and inside == 1)
            outside_test_success = (nb_elements_captured == 0 and inside == -1)

            if inside_test_success or outside_test_success:
                nb_test_passed += 1
            else:
                failed = True
        except Exception as e:
            failed = True

        if failed:
            failed = False

    print("\t Success up to a precision of 10^(-{})".format(nb_test_passed))

Before changing floats to doubles:

Testing locations barely inside:
     Success up to a precision of 10^(-3)
Testing locations barely outside:
     Success up to a precision of 10^(-100)

After the change:

Testing locations barely inside:
     Success up to a precision of 10^(-12)
Testing locations barely outside:
     Success up to a precision of 10^(-100)
xoolive commented 6 years ago

Thank you! I hope the corrected version of the tool will serve you well...