The Making of Loose Leaf’s Killer Feature: Scissors

I easily spent the most time during development on the scissors tool, which might be surprising given how simple it is to use. You can see a quick example below. Just like real scissors, you can easily slice your pictures into any shape.

It seems simple enough right, so what makes this so tough? The next example shows just how robust the scissors are. For a dramatically bizarre shape, they still cut it into pieces just as you’d expect, and quickly at that. And it even supports cutting holes into scraps too.  

We’re getting closer to seeing why this is so tough: it’s cutting arbitrary shapes with an arbitrary path into an arbitrary number of sub-shapes or holes, and doing this quickly enough on a relatively small mobile processor.

First: The Model

Before we can dive into how the slice happens, we have to understand how the data is modeled.

Each scrap is at least is a closed (looped) outer Bézier path with potentially many inner paths. Each of those Bézier paths is actually made up of many segments, each of which is a single cubic Bézier curve. Following along these path elements shows up the direction of that path. The enclosed subpaths are always in the reverse direction of the outer shape path.

You can see an arbitrary shape here, along with its numbered segments and path direction. Next to it is a simple 3 segment scissor cut.

numbered-shapenumbered-scissors

With only these two paths, we can determine how to cut the original shape into its smaller pieces.

Second: The Algorithm

In the picture above, it’s obvious to us humans where the new scraps would be, but for a computer to calculate the new shapes, it has to detect where the shape’s path and the scissor’s path intersect. This gives us the key pieces that show which segments of the scissor’s line will be edges of new subshapes, and which pieces we can safely ignore.

Once we find these intersection points, we can throw away all pieces of the scissors that aren’t inside of the shape. Next we compile a list of all segments of the shape, their direction, and the intersecting segments of the scissors, and their direction. The scissors’ segments are special, and we duplicate these, one for each direction.

intersectionspath-with-direction-2

After all of this path processing, we’re finally ready to calculate the paths of our new sliced shape!

Now we follow these simple rules:

  1. each of the shape’s segments can be used only once
  2. pick any of the scissor segments of either direction
  3. follow it along its direction to the next intersection
  4. follow the arrows, turning left at each intersection, until you reach the original segment again
  5. continue until you run out of segments to use

Third: The Output

Tracing along the edges in this way, and you’ll easily compile up a list of the new shapes.

Fourth: Debugging

The real difficulty of this process came from a number of reasons:

  1. The UIBezierPath class for iOS is extremely lacking, especially when compared to NSBeizerPath in OS X
  2. There are no built in methods to find intersection points or splitting of Bezier paths or curves
  3. By default, accessing any element of a UIBezierPath requires looping through the entire path, making most any algorithm performance terrible

All of that means that I needed to write lots of Bezier specific code, which generally means lots of bugs too.

I used unit tests to verify as much of my code as I could, but it was very had to catch every edge case – especially when the scissors and shape would be at tangents. To help find these edge cases, I also write a small iOS app that’d let me draw any shape and then cut it with any scissor path. This let me try new shapes and cuts extremely quickly – I even gave the app to my 5yo daughter and asked her to try and break it.

Anytime the app threw an exception or otherwise had a problem – it would email me the paths of the shape and scissors for me to debug and add to my unit tests. In this way, I slowly built up a library of unit tests as I worked toward a robust solution.

Fifth: References

For anyone looking to write code for Bezier paths, I highly suggest the following reading and resources:

  1. A Primer on Bézier Curves – http://pomax.github.io/bezierinfo/
  2. KevinLinDev Geometry Tutorial – http://www.kevlindev.com/gui/math/polynomial/
  3. DrawKit – http://apptree.net/drawkit.htm

Opening Up Loose Leaf Development

You wouldn’t know it, but I had to solve some difficult and interesting problems to get Loose Leaf shipped. You wouldn’t know because I never told anyone. I never described how I built Loose Leaf’s list view before UICollectionView, or how hard it was to get the pen ink to “stick” to scraps efficiently, or what went into creating the scissors tool. I spent 2 years working without sharing anything, and it took me that long to see the missed opportunity of coding silently.

Ideas Aren’t Valuable, Sharing Them Is

I’ve made this mistake with almost everything I’ve built. I already knew that ideas are worthless, but I still held my feature ideas for Loose Leaf Leaf too close. The thought “I can’t tell anyone, they’ll steal my idea” just evolved over the years into “I can’t show this, it’s not ready yet.” A different excuse for the same behavior. Two summers ago, I even gave a talk at OwlSpark about this very topic- should’ve listened to myself!

The Cost of Closed

Over these two years, I’ve missed out on a lot.

I missed out on user feedback. I only found out that Loose Leaf has trouble on boarding new users after I’d launched. If I’d been more open, I would’ve seen that problem before launch.

I missed out on learning. Loose Leaf was my first OpenGL experience, and to say it was a struggle is an understatement. Just being open and asking about my questions and troubles could have sped up that portion of development, among others.

I missed out on teaching. Loose Leaf does more with UIBezierPath than I’ve heard about in almost any project. I’ve spent an incredible amount of time optimizing drawing and calculating with Bézier paths. I’ve learned a lot that I should’ve been giving back much sooner.

I missed out on giving. Sure, I shouldn’t give the farm away, but there’s no excuse for not open sourcing pieces of Loose Leaf’s codebase for the greater good. The Bézier example above is a prime candidate.

The Value of Open

You’ve only really learned something when it changes your behavior, so how has mine changed?

I’m being proactive about user feedback. I’ve started building up a focus group of active users (join here!) and’ve just finished up its first survey. I’ve prioritized version 1.1 development on specific user feedback.

I’m asking more questions. I’m on IRC at #iphonedev, #macdev, #cocoa-init, and #OpenGL, and I’ll be posting questions to StackOverflow more often. I’m also attending startup and iOS meetups consistently to meet and ask other developers.

I’m answering more questions – both on the IRC above and on SO. I’ve setup RSS using fetchrss.com for specific SO keywords to funnel specific questions into feedbin. I’m also active in /r/iOSProgramming answering questions when I can. I’m also sharing as much as possible on this blog – everything from how I made the promo, or app preview, or or even recorded the UITouches for demo videos, and I have many more blog posts in the queue.

I’m giving away as much as I can – most recently with the code to show all UITouch locations and sharing what I’ve learned creating an App Preview. I’m working on upgrading those dots to hand shadows and will open source that when I’ve finished (I’m even livestreaming the shadow dev every Monday). I have a list of more features in Loose Leaf that I’ll be streaming and cleaning up for open source as well.

Open Inspiration

Some people who’ve really inspired me with their open development: John Saddington who is open and encouraging about his work on Desk.pm. Notch, who released Minecraft before it even hit alpha. Shaun Inman who consistently blogged about making The Last RocketAsher Vollmer who’s live tweeting his development of CloseCastles.

Anatomy of an App Launch: Success and Failure of Loose Leaf’s First Day

You only get one chance at a first impression – and your app’s first impression is almost entirely dependent on what you do before your launch day even arrives. I first launched Loose Leaf on Nov 18th with only mild success, and I’ve learned an incredible amount since then. I want to use this post to share what I did right with Loose Leaf’s launch, and where I went wrong, and hopefully you can avoid some of the mistakes I made.

Phase 1: Leading up to App Launch

Your app’s marketing needs to start long before your app launches – even when the app is still in development. By the time the app launch day nears, you’ll already want to have reviewers lined up ready to write and a following of interested customers chomping at the bit to get your app. But how do you get from there to here without even an app to show anyone?

What I did right

I knew from previous apps that the most important thing I could do would be to start building an email list as soon as possible. I setup a teaser website for Loose Leaf and tied a signup form into Mad Mimi so that interested people could be notified when I launch. I also setup a @getlooseleaf Twitter account for the app to provide a face to the app’s development.

What I did wrong

Up until launch day, I was spending 100% of my time on development and QA – I wasn’t spending any purposeful time into marketing. So while I had a website, I wasn’t actively pushing much traffic to it. I also wasn’t actively posting and following folks on Twitter, so my reach there was limited. I’ll make another post later about better strategies for social media, but my pre-launch strategy was closer to sit-and-wait-for-people-to-talk-to than it was to reach-out-to-others-and-join-the-conversation.

By the time launch day rolled around, I only had about 100 people signed up on my list, and only 1 or 2 daily visitors to the site. Contrast that with Here, File File!, an app I launched many years ago, and I could see the writing on the wall. HFF launched with close to 5000 people on our email list; the list I had for Loose Leaf was barely 2% of that.

Where I placed all my hope

I ignored the problems I had with email and traffic because of one thing: WWDC. I didn’t have a ticket last year, but I did go to AltConf and met a number of press/bloggers throughout the week. My demo went well and I made some great connections, and I left believing I’d secured reviews on 5 high traffic blogs and Mac sites. In the next section I’ll describe where I went wrong and why these weren’t as secure as I’d thought.

Phase 2: Two Weeks Before App Launch

By this point, you should already have your app uploaded to iTunes Connect and passed through review. Don’t leave it up to chance! You never know what the reviewer might find. You want to leave plenty of time for your app to be rejected and re-reviewed before your target date. This is also the perfect time to start reaching out to bloggers and press about your app.

What I did right

I followed up with the press I’d met from AltConf, and I also researched nearly 30 more bloggers and press who’d written about similar apps in the past. I kept my email pitch short, included screenshots and links to the app promo video. I certainly didn’t expect all 30 to write, but I was hoping for a handful added to the 5 I thought I had.

What I did wrong

Up until two weeks before launch, I didn’t reach back out to the press from AltConf, and I didn’t make any effort to reach out to or find additional bloggers or press until now. I had put my full faith into only those original press, and I should’ve spent more time growing the email list and reaching out to additional customers and press.

Phase 3: Launch Day

The night before launch day I could barely sleep. No matter what happened, I was and am extremely proud of the 2 years I poured into Loose Leaf and what I was able to build. When launch day hit, I had just 1 large review that sent a fair bit of traffic into the App Store, but by the end of the day I’d barely earned over $500. That… is not what I’d expected.

Remember those press and bloggers I’d met during AltConf? Welp, AltConf was in June, and I launched in late November – that means I’d been nose in the grindstone for nearly 6 months and hadn’t reached back out. Those hot leads had turned stone cold, and it’s my own fault for not keeping connected. I’d be lucky if they remembered anything about Loose Leaf, let alone cared enough to write about it.

Phase 4: Post Launch

Here’s where the real marathon begins. I’m barely a month after launch, and instead of being focused 100% on product development like before launch, I’ve learned my lesson: I’m now 100% focused on marketing and sales. I’m definitely playing catch up, but the difference between then and now is that I actually have a strategy. I’ve started working with Madalyn Sklar on a proper marketing plan, and it’s already helping focus our efforts considerably.

The Plan

Step 1) Proper social media strategy. I’m reworking how and why I use the Loose Leaf twitter account and Facebook page. In addition to being there to respond to customers, I’m actively joining the conversation instead of just passively listening in. Madalyn has been a huge help teaching me how to use social more effectively.

Step 2) Proper marketing assets. Loose Leaf is an app about gestures – it’s the app that epitomizes “show don’t tell,” but at launch I barely had 2 videos showing the app in action. It’s a month later and now I have nearly 15. This ties back into the social step 1 as well, all of the marketing assets that I’m building for ads / tutorials / website we can also share on twitter/fb/instagram/etc.

Step 3) Advertising. I’m working on Facebook, Twitter, and Google Ads, and my priority here is optimizing those ads and also optimizing the sales pitch on the website. This step is essential, because it’s forcing me not only to very narrowly define a target audience for each ad, but also to define how Loose Leaf solves a specific problem for that audience.

Step 4) Opening up. Pre-launch I was buried alone in my codebase working furiously to ship, and my hermit-ness cost me on launch day. My new goal is to be open about my process on this blog, and even open up pieces of the codebase as I did late last month.

The Takeaway

Your app launch is only as good as your pre-launch. Make sure to put as much time and attention into your marketing that you do in your code and QA. I didn’t spend near enough time pre-launch on marketing that I should have, and now I have a lot of catch up to do. Focus on your email list – get people excited and keep them excited all the way into launch day. Bring your own army of customers to your launch, don’t hope and wait for others to do it for you.

Google Author link
Page 1 of 4412345...102030...Last »