Tuesday, June 19, 2018

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 ;)





Saturday, April 7, 2018

Free Hand Drawing on Apple Maps

This is kinda a note based on the learning I've had working with the Free Hand Drawing(FHD in short) on all the major Maps(Google, Mapbox & Apple Maps) on the market.

So, If you'd like to have an in-depth technical understanding, please refer this post which was my first experience with FHD on Google Maps that delves deep into the Google Maps SDK explaining the FHD functionality & its implementation.
And to get a context on the Mapbox based FHD solution, please do refer this blog.

What I learned with Apple Maps:
Apple Maps iOS SDK doesn't differ much from Mapbox iOS SDK, most of the API's has almost the same signatures/pattern, it almost looks like a copy-paste from a developer(API User)'s perspective, Not sure if Apple Copied from Mapbox or vice-versa(I pick this), but the mapping system works totally different internally especially w.r.t the FHD features like polylines, polygons etc. The FHD works smoother on Apple Maps and there are some major differences specifically while drawing a polygon on Apple Maps & Mapbox.


Here's the gist of it:

I tried drawing the polygon(Nearly the same) on both the maps and here's result on the Apple Maps:


And this is the result of the Mapbox:







































Are you seeing the difference?

When you get the Polygon object from the Mapbox, it gives you all the intersecting & overlapping polygons altogether, so it is your job to decide on which one you want & omit others, which is unnecessary work in most of the use cases, where you'd end up wasting your valuable time re-inventing the wheel by writing a lot of algorithms just to get rid of those intersecting/overlapping areas in the polygon drawn.

However, the Apple Maps polygon does all those tedious work for you and gives you the polygon by omitting those intersecting/overlapping polygon and also does a pretty good job of displaying the same on the Map View as well.

Google Maps also behaves similar to the Apple Maps in most of the FHD use cases.


For some reason, If you're stuck/planning to use Mapbox, then stay tuned for more updates in my next blog as I've done some good amount of work in that area of deciphering the polygon coordinates to phase out those intersecting/overlapping polygons.

Here's the open-source sample code that does all those amazing stuff.

Share it across, if you've found it useful, let the needy rejoice.

Have Fun!



What I Learned While Building my Noisli Clone Musicly in React Native and Expo

This is only a note on the Blog post I wrote on Medium (that's getting garnered with a huge view counts & some claps, which I see it as a gratitude from the community) on the stuff I learned while developing the Noisli clone app in React Native.
I think there's no such tutorial/blog that explains the Pros & Cons and the different ways of developing the React Native apps, hence I think the blog post serves several kinds of people starting from a Fresher to even an Experienced developer who hasn't developed/tried all the approaches. I consider this article as a unique one as some of the people have conveyed/thanked me personally the same way that I had thought of and wrote it initially.

I always feel it's better to have multiple touch points to some great posts/articles, hence adding a note here as well for those who haven't seen & would be interested to take a look at.

Enjoy!


Sunday, March 25, 2018

iOS: Playing with Static Libs, Fat Frameworks, Static/Dynamic Frameworks with Swift & Objective-C classes mixed up

Recently, I got to know few facts on how exactly Static Library(SL), Fat Frameworks(FF), Static/Dynamic Frameworks(SDF) actually works while I was working on a legacy code base which had a ton of all of the above stuff working altogether.

This article is to log the few notes on the struggles we faced with having all these above things mixed up altogether with both Swift & Objective-C mixed up.


Static Library(SL):
Static Libraries was the initial(Way too Older now) way of code distribution where any project integrating the library would include .a file(Which contains the implementation classes) and all the header '.h' files separately along with the .a file in order for them to work in conjunction.


Fat Frameworks(FF):
Fat Frameworks are nothing but just the Static Library compressed as a framework, which was a means of distributing the code before Xcode6 when Apple introduced Static/Dynamic Frameworks(SDF).


Static/Dynamic Frameworks(SDF):

In Frameworks world, Umbrella Header file serves 2 purposes:
It acts as the Bridging header between Swift & Objective-C.
It acts as the interface between the Framework itself & other modules/projects.

In order to create a SDF, you simply expose all the header files in the Framework's Umbrella Header file and Integrate the Framework into the other projects/modules and start using/accessing the Framework classes/files.

But, in order to integrate non-modular frameworks(SL or FF) with both Swift & Objective-C files in it, you need to have a custom .modulemap file where you should explicitly expose all the headers that you're willing to expose to the user of the Framework. These changes applies with recent Xcode9+ updates.

And there is a caveat even with this approach when you're dealing with SL or FF.
We've seen it working very well when you have to deal with just one level deeper encapsulation like this:
Project --> FF 

But, when you're in a situation such as below:
Project --> FF --> SL
or
Project --> FF --> FF --> SL
or
any other combinations of deeper layer that goes with SL or FF, then it becomes so much complicated and you'd have to do a lot unneccesary hard work to make them work altogether.

At any bigger cost, it is always better to get out of that older techniques(SL or FF), since they're kinda becoming a burden to maintain the legacy code bases because it literally costs you more energy/time/money to have SL or FF going forward rather than switching to the SDF.
Thus, going with the new SDF way is the wise advise to make the code bases less vulnerable, easily scalable and futuristic.

Hope it helps someone struggling in that way. Cheers!


Friday, March 9, 2018

Free Hand Drawing on Maps with MapBox SDK

Recently, I got to work on the MapBox SDK for iOS. So, this is a short journal of my experience with it.

Basically, it's a MapBox SDK based freehand drawing article.
For those who are here for Google Maps based solution, then please refer this blog which is again based on this lib.

This is not a Google Maps Vs MapBox debate as well, please make up your mind before starting up.
[Note: Am not aware of the updates to the Google Maps SDK since 2015]

So, let's start with what I've got to say.

I've already created a Freehand Drawing(FHD, in short) tool, implemented way back in 2015, which was based on the Google Maps SDK, hence for MapBox based FHD solution, I was already 50% done.
In the existing implementation, I have the touch detection and coordinates collection, polyline drawing & polygon drawing logics already implemented and in place, but all of them were using the GoogleMaps API's.
So, the 2 main parts/API's that I'll need to look in MapBox SDK were:
1.) Polyline
2.) Polygon

But, it was not straight-forward though, since the way Google Maps Polyline/Polygon API's designed were just around adding them directly as annotation/kinda directly on the map,
For Ex:
You just have to reference your map object to the polyline object like this:
    "polyline.map = mapView"
So, the hierarchy kinda looks like this:
MapView --> Polyline

but with MapBox, there are a few encapsulated layer which allows you to do multiple layers of customization. For example, in order to add a polyline, you can add directly as an annotation just like you do with the Google Maps API (As mentioned above)
Or
You can create a style layer(MGLLineStyleLayer) by assigning an MGLPolylineSource object to which the polyline(MGLPolylineFeature) object is added/referred.
So, here the hierarchy looks something like this:
MapView --> StyleLayer --> Polyline

And, the same goes with respect to the Polygon(MGLPolygon) as well.

So, with MapBox, I can add the polyline/polygon in 2 different ways (As far as I've explored)

Hence, it was quite simple to replace the GMSPolyline API's with respective MapBox polyline API's in the same Objective-C project simply by removing the Google Maps SDK, but I faced an issue, with the implementation, where the Polygon was not getting displayed for dynamically calculated coordinates but was working very well for static coordinates.
I raised an issue on their Github page and got a reply asking me to raise it to their support team, which I didn't expect, and when I emailed to their support team, I got a response back after a day saying that they won't be able to help me debug the issue and suggested to raise it on StackOverflow, so they are basically relying on the community out there for issues, probably since they have a very small team.
But, they pointed me in the code where I was also skeptical about. It was around the CLLocationCoordinates2D array, where the issue might be, but I didn't mind to even fix that because I decided to re-write the whole implementation in Swift by then and thankfully the issue was resolved when I finished writting it up completely in Swift.

So, finally, SARMapDrawView was re-implemented/written in Swift and is open-sourced now as SARMapBoxDrawView.


Am still looking out for the solution of these 2 major issues with MapBox:

1.) Encrypted Path String:
Google Maps SDK has one fantastic API(GMSPath) where they'd just give us the path in a string format (around 10chars, I think). So, basically they have an algorithm working behind the scenes that generates this string based upon the given coordinates of the Polygon(GMSPolygon) object, which is very much helpful when there is a huge coordinates list and any user of the SDK can simply use this encrypted string instead of handling those huge arrays of coordinates, just in case the user is not really cared about the coordinates data but just expects a simple polygon handling mechanism. It works really well and is a very efficient polygon handling approach.

2.) Overlapping/Crossing Polygons:
In FHD, when a user draws multiple overlapping or crossing or inner-circling polygon, then Google Maps polygon(GMSPolygon) simply creates a polygon object by marking with just outer coordinates of all the drawn polygons and it looks like a whole single region drawn, whereas, in MapBox, the Polygon object is not manipulated or moderated but simply drawn on lines of wherever the user drew or wherever the polylines were drawn, it simply looks like a polyline drawn on user's touch path(which we already do), not like a real polygon like in Google Maps - GMSPolygon.


I hope you found this as an Interesting read. Please lemme know in the comments below for anything.

Thanks for your time!

Saturday, February 24, 2018

Learning/Notes on Deploying a NodeJS app on Heroku, Amazon-AWS and Docker

Note/Warning: Am not going to go deeper/step-by-step into the deployment process and I'm not going to go deeper into the Pros & Cons by comparing them against each other, as well. 
I just wanted to share my learnings/difficulties faced in the process of deploying my server app to Heroku, Amazon-AWS & Docker-Cloud.

Heroku:
This is very straight-forward where you have different options:

Deploying with Git:
Just like how you use Git to push code to your Git repo, you can push your Heroku app onto their server using the very similar commands. This is easiest/simplest way to deploy apps on Heroku.

GitHub Integration:
If your repo is hosted on GitHub, then this is like a piece of cake, you can simply automate your whole deployment process.

Dropbox Sync:
If you're not hosting your repo for any reason and just saving them into your Dropbox folder, then also you're covered with the Heroku's easiest Deployment process. You can simply connect your Heroku account to the source in your Dropbox folder and it will take care of the deployment for you.

And there are also several other options as well, but these are the very simplest ones that I found while creating quick prototypes during Hackathons and for other purposes.
Like Steve Jobs says: "It just works!"

But, there are several debates as to why most of the big-shot guys/companies don't prefer to use it, so probably this might not be the best solution when it comes to deploying your production apps that have the potentiality to take over the world.


Docker Cloud & AWS:
There are several great tuts on Youtube to guide you on how to deploy your Node/React JS app onto AWS and also there are some good ones to deploy on Docker.

Deploying on Docker:
Docker is basically a container that's OS independent, which means it runs on any given platform. So, presume that your app will work on any given platform.
Just like the Heroku's Git command lines, Docker also provides a similar CLI which is very straight-forward to push your Docker images to the Docker Cloud.
There is something called as 'Swarm mode', where the Docker cloud will take care of creating instances/clusters for your server, but for some reason it was not working for me(Maybe it had some issues, since I'm using it in its Beta mode), so I turned off the Swarm mode and connected my AWS account using ARN ID(that acts as the API key b/w Docker cloud & AWS) in the Service providers section of the portal and after starting up the EC2 Instance on AWS, the docker image was hosted on the cloud.

AWS:
After launching the AWS Instance, I was just so much puzzled on how & where to access my app hosted onto it.
In the EC2 Instances summary page, you will be presented with a Public DNS address, which looks something like this: "ec2-18-221-199-55.us-east-2.compute.amazonaws.com", this is where your hosted app can be accessed.


And, Amazon has this process of network filtering, so you basically have the option to filter out or restrict the request from a certain set of IP addresses or you've to add your IP address from which you're trying to access this URL to connect with your app.


Conclusion:
This post might look absurd with much lesser information here & there, but I still think that this will help someone who gets started up and just wanted to have a summary and the few tidbits on the difficulties I faced would certainly help someone person like me to get beyond it.

That's all I had to say. Hope you've got something out of it.
Thanks for your time!

Monday, July 17, 2017

What’s New in Swift

This article is just a short overview of this WWDC session.


Here are the few things that were discussed as part of the session:


1.) Private variables are now accessible to all the extensions of the class in the same file.


2.) Composing a class with any number of protocols.

Example : 
protocol Shakeable {
    func shake()
}
extension UIButtonShakeable {}
extension UISliderShakeable {}
func shakeControls(controls: [UIControl & Shakeable]) {
    for control in controls where control.state.isEnabled {
        control.shake()
    }
}

3.) Swift Versions:

Swift 4 is source-compatible with Swift3.
Swift3.2 introduced that contains most of the Swift4 syntax changes.
So, there will be 2 Swift versions in Xcode9: Swift3.2  & Swift4.

The end result is: If you open a Swift 3 project in Xcode9 and build the project with Swift3.2, it should work as it is, i.e., without any code changes.
This is mainly to give the developers time to adopt to the new Swift changes, so that the project dependencies can migrate asynchronously.

4.) New faster Build system:

Includes these:
(i) The pre-compiled header is the default option for compatibility between Obj-C & Swift classes.
The Bridging headers are build each time when a build is run, whereas the Xcode9’s default ‘Pre-Compiled header’ is build only once, which improves the build time for projects that contains huge amount of Legacy Objective-C classes.

(ii) Code Coverage: Xcode8 runs a separate build, where Xcode 9 will use the same last build when you run a test with Code Coverage, which eventually reduces the test execution time.

(iii) Indexing is not a separate background process now, it is done along with the build process that has a small overhead to the build, of course.

(iv) No unused code is build, the compiler just omits it. (It doesn’t mean that we should have unused code in our projects ;) )


5.) Strings:
(i) String collections can be directly manipulated without using the internal ‘characters’ collection.

Example:
let values = "one, two, three…"

//To get index after the ‘,’ char from the ‘values’ string
Swift 3:
while let comma = values[i..<values.endIndex].index(of: ",") {
    let index = values.index(after: comma)
}

Swift4:
while let comma = values[i..<values.endIndex].index(of: ",") {
    let index1 = values.characters.index(after: comma)
}

(ii) String ‘characters’ collection iteration can be iterated without using ‘values.endIndex’ in the below example.

Swift 3:
var i = values.startIndex
while let comma = values[i..<values.endIndex].index(of: ",") {
}

Swift 4:
var i = values.startIndex
while let comma = values[i...].index(of: ",") {
}

(iii) Substring cannot be used as it is from Swift 4. It needs to be copied before using it further, this is to overcome an issue of memory leak with Substring before Swift4.

Example:
let big = downloadHugeString()
let small = extractTinyString(from: big)

Swift 3:

myLabel.text = small // This leads to the memory leak, since the 'big' text is being holded by the internal String classes that does the process of extracting the substring from the given 'big' string.
Swift 4:

myLabel.text = String(small)//Hence, this is the recommended/only way to use the substring going forward.
This mainly affects huge string operation. Doesn’t majorly have any great effect on the small string manipulations.



(iv) Multi line strings literals are easier to write now.

Swift 3:

let longString = "Q1: Why does \(name) have \(n\(characters)'s in their name?\nA: I don't know.Q2: H r u?\nA: I am \(name)"
Swift 4:
let longString = """
                Q1: Why does \(name) have \(n) \(characters)'s in their name?
                A: I don't know.
                Q2: H r u?
                A: I am \(name)
                """