-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix width and height usage #57
Conversation
This looks good so far! I’ll give it a closer review soon. |
@crhallberg This addresses all the Once those were fixed all of the corresponding tests that used the logic of With these changes it should make it possible to implement the k-nearest-neighbours which I'll have a go at next. 👍🏻 |
Ah, just seen there's still an update for the intersects. Working on that now. |
OK, done now. Should have everything covered I think. 👍🏻 |
I'm going to make another update to change the way the contains is used for querying. |
@crhallberg I've now added a new Also added two new tests that highlight the issue. |
I was thinking maybe |
I'm not sure I understand the difference between the comparisons. I thought the point was that if we consistently use EDIT: If we have differing cases for placing and querying, I feel like we're going to get inconsistent results. A point on the edge will not be placed inside but will be searched for inside that region? My opinion is that we shouldn't change the name of |
Well the difference is in why it is used. In the insert code you have this at the end...
The check for adding any point should only allow one of these inserts to work. With the old logic, if a point was on the border of northeast and northwest (or worse, the point where all four meet) then it would get added to multiple child regions. So, we need to make sure that when adding a point it can only ever be added to a single child region. However, when querying, we no longer have this restriction. And in fact shouldn't want it. When running a query we're not passing in a child region to ask if it should contain a point or not. We're asking if an arbitrary region encompasses that point. For example. If we had a quad tree like When adding the point (25, 50) during a subdivision. We want it to always go into the northeast region (and never the northwest region). However, if we run a query of the region Whilst it may at first appear that the two are the same check, they actually are subtly different. Luckily, the two cases are completely distinct and so using different names would be ok. For example, you would never be adding a node to a region that is a circle. You would only ever be querying the quad tree with a circle. Hope that makes sense. |
That does make sense! Thank you for the explanation! How would you feel about the names |
Those are perfect yes. I'll make that change. Thanks 👍🏻 |
Your explanation also reveals why the check is inclusive on the right and bottom: it escapes on the OR. return false || 0 || 7 || 8; // 7
return alwaysFalse() || alwaysTrue() || veryExpensiveTrue(); // veryExpensiveTrue was never run OR statements stop evaluating once they get a true. return northeast.insert || northwest.insert || southeast.insert || southwest.insert A point on the border between NE and NW will be grabbed by NE because it checks first and Knowing this, I think I'd rather keep the one inclusive |
Ah yeah, good shout. I'd completely skipped over that. However, if I go ahead with the "remove named children" I think the update may be required. 😄 I'll go back to the single |
Yes, I'm kind of amazed. When you work through the logic of the subdivision and look at the region covered by it you find out it's very different from what it should be. With the original logic a region (black) and it's sub divisions (red) would look something like this... |
I think a combination of the inconsistencies came together to account for the errors in each other and cancel out (to a certain extent). But if we want to update to use k-nearest-neighbours then we need to make sure that everything is working as it should. |
In fact, yeah, looking back at the old So, contains would return true for the green point in the NW region. Even though it wasn't actually contained in the NW region. And any testing on this would look fine. However, contains would also return true for the blue point in the NW region. And I can only imagine that there wasn't a test written for this as it would be an odd thing to test... but also a difficult scenario to set up. |
I've finally found the time to go step-by-step through the old code and I think your drawings are correct:
All in all, great work so far! I think you've caught all the instances that I can see. I have some nitpicks about the tests but they are outside the scope here. |
Cool, thanks for the update and summary. I refactored the subdivide as it is done in two places. Once in the actual subdivide and once in the JSON decoding function. Happy to put that back though if you would prefer. And yes, I agree with the test. I'll add another one in 👍🏻 |
You're right. Excellent! What's left that I can dig into?
|
@crhallberg I updated that test and added an additional test to test points on the boundary. |
Seems ready to go! Are you ready? |
@crhallberg yeah, I don't think there are any more updates for this PR from me 👍🏻 |
@crhallberg I'm not able to merge it. I think you will have to merge the PR yourself. 👍🏻 |
Thanks so much! |
Awesome thanks! I'll get on to looking at the k-nearest-neighbours now. See if we can get something interesting working with that. 👍🏻 |
Updating the width/height issues.
Currently width and height are used to mean one of two things...
The second use is more consistent with how "width" and "height" are used as general concepts so I am opting to use this as the new single definition.
Another small fix I will apply is the comparison check to determine if a point is "in" a node. Currently, a point can belong to multiple sibling nodes (i.e. nodes on the same level). I will update so that each point can only belong to a single node.