Working out Concave/Convex Hull

This post is nearly like a continuation of my previous post. But not necessarily need to be followed.


This post itself is a note on my learnings with finding out a concave hull solution for a project that I worked on recently.

Requirements:
We had a requirement where the user would simply freehand draw (FHD) on a map view and we should be able to fetch the list of users located/contained in that region.

Our Tools:
We used MongoDB as the backend, which provides us with beautiful queries/API's fast enough to search the list of users(we have in our DB) within a given polygon (Polygon = Freehand drawing enclosed with the starting & ending points, hence forming a region).
The only issue with MongoDB search is that it expects a perfect polygon with no intersection at all. If a single point in the polygon intersects then it'll simply throw out an error. Not sure if MongoDB guys did this intentionally, but it leaves its users with a huge burden/workaround to handle & implement their own solution for it.

Our Story:
So, to solve this particular issue, we started looking around for the concave hull solutions.
When we came across this hull library, we felt that EUREKA moment, and eventually tried its Swift counterpart. But only after trying it out, we saw that it didn't work for us as we expected it to be.
Definitely, the hull lib is fantastically done and works very well for convex hull by adjusting the 'concavity' parameter to adjust it based upon your need/requirement/satisfaction but certainly doesn't generate a perfect Concave hull, actually not even close to what we wanted, so we literally wasted/invested days to even try it out.

But, later we decided to move on.
To be noted here that we didn't have the resources to implement our own Concave hull solution.
We even looked around btw and met JTS, which had its Swift Counterpart, which again didn't have the concave hull solution, only after this we decided that the Concave hull was a much bigger problem set that was even tried & failed by masters/giants in the industry.
So after a very long time, we decided to go with our own custom/hybrid implementation, which seemed as the only feasible option for us at this stage.



This was the final solution that we ended up doing:


When the user draws FHD on the map view, we'd create an imaginary(In the background) convex hull polygon, which is a valid region that our MongoDB server would accept to search for the users contained in that particular region and after the results are fetched, at the client end, we would loop through every result/user from the results list and check whether the user is contained within the user's drawn FHD region (which can be easily done with API's provided by Apple Maps framework or MapKit framework or even using the GEOSwift API's) and ignore any user that doesn't contain within the user's FHD region.
The major Caveat here is that the solution is not a scalable one, as it has to loop through every user to see if they fall into the region or not and hence has the performance of O(n), which is not ideal in case of scalable systems.
But, unfortunately, we're stuck with this solution for now with this problem set.
But, there are other ways to handle it like Uber's approach of categorizing users with country/city wise, which seems to be a good one and have also been looking out for other approaches that we'll be tackling in the near future.

So, if there's any betterment that can be done/applied here, please don't hesitate to comment it out as it might be of a great help to us and If you find this information helpful, please do share the same across and please show some gratitude in the comments below ;)





Comments

Popular posts from this blog

Free Hand Drawing on Google's Map View

Android from iOS Guy's Perspective

Free Hand Drawing on Maps with MapBox SDK