How to Draw Thick 2D Lines in OpenGL

Background

In a recent project I needed to draw lines NSBezierPath style in OpenGL at different widths and which may be zoomed arbitrarily by the user. As OpenGL does not natively support rounded end caps on lines drawn with glVertex2f I employed the popular technique of drawing a GL_POINT at both ends of a line using the same vertices as the line itself.

This approach works to a point but, I discovered, not on every machine.

On my development iMac the OpenGL implementation handled this without complaint, but when testing it on a different machine (a Mac mini) I noticed an odd effect.  The points I was using to simulate end caps were gigantic in comparison to the lines themselves and it resembled a narrow bone with large joints on both ends.

I investigated the cause by querying the GL_SMOOTH_LINE_WIDTH_RANGE and GL_SMOOTH_POINT_SIZE_RANGE parameter values.  It seems the points could range from 1.0 – 64.0 in size but the lines only 1.0 – 7.0 on this test machine. What I needed was a width of 20.0.

At this point it was clear that I would need to replace my native OpenGL lines with quad based pseudo-lines. Searching online for an existing implementation yielded nothing that fit my needs so I ended up rolling my own, which I now offer for free to everybody via
my Github repository (JFOpenGLUtil.h, JFOpenGLUtil.m).


How It Works

The implementation is simple. A GL_QUAD is a 4-sided polygon consisting of 4 vertices and, if kept narrow, it can be made to resemble a line.  If we know the line width and the beginning and end points we’re ready. We only need to calculate one offset point from the beginning point.  This offset point is ½ the line width in a perpendicular angle from the line. Once this offset is determined it can be reused 4 times to render the quad.


How To Use It

Unlike glVertex2f, you’ll need to provide 2 points at once. This is because the angle (from the beginning to the end) is needed to determine the GL_QUAD vertices.  If you’re using a for loop to iterate over your points just skip the first point like this…

Point *previousPoint = nil;
for (Point *point in pointArray) {

	CGPoint endRenderPoint = [point renderPoint];

	if (previousPoint != nil) {
		CGPoint beginRenderPoint = [previousPoint renderPoint];

		[JFOpenGLUtil drawQuadLineWithWidth: lineWidth
					red: redColor
					green: greenColor
					blue: blueColor
					from: beginRenderPoint
					to: endRenderPoint];
	}
	previousPoint = point;
}

 

With this approach lines of virtually any width can be supported.  But don’t forget, anti-aliasing is needed to keep the quad line from looking jagged of course.  I hope this implementation helps you if OpenGL has been less than cooperative with your app’s line drawing.

Professional Layouts in OS X and iOS – Open Source View Position Utility

Introducing JFViewPositionUtil

I created JFViewPositionUtil for KEYBOX 2.0. I hand code my interfaces rather than use Interface Builder, and version 1.0 proved extremely difficult to lay out professionally while also balancing the consideration of localization.

Why would anybody in their right mind NOT use Interface Builder? Don’t get me wrong, it’s a fine tool but for the degree of customization I and many developers require it doesn’t quite cut it.

In the case of KEYBOX 1.0, a layout that would look good in English might make Japanese look awful. My initial approach to handle this was to adjust the font size on a per-language basis. It worked but was nowhere near optimal.

In version 2.0 I resolved to fix this and since its release I’ve used this class in all my products. It’s matured to the point where I believe it to be beneficial to others as well, and to this end I’ve decided to open source it.


Class Design

I designed this class to be goal oriented. That is, whatever your goal, you typically only need to invoke a single method offered by this class. It’s even a singleton so there is no need to instantiate it.

This utility class works with both OS X and iOS projects but it should be noted that it is designed to work in coordinate systems where the point of origin (0, 0) is the top left corner. In other words, you’ll want to flip your views in OS X projects when using this class.

Lazy-initialization of views

A quick note, since this utility class operates mainly on the notion of positioning views relative to others, it is beneficial to adopt a lazy-initialization approach to view creation. This way sibling views upon which your view depends will be initialized and positioned by the time you need to base your view’s position on them. All of the below examples in this post will use lazy-initialization of UIViews for iOS.


Common Layouts

The best way to demonstrate this class’ abilities is to simply show you. Since this class is goal oriented I’ll break things down by common layout goals.

■ Label to the right of an icon
This is a common layout pattern, and the code might look something like this…

Label right of icon

One variation of this is the case of a multiline label. You probably wouldn’t want to vertically center your label to the right of your icon. Instead, it might look more professional to snap the icon’s top right anchor point 5 points left of the label’s top left point. I’ll discuss this technique a bit later.

■ Center aligned titles/headers

Sounds simple enough right? The title is a label with a bold font. Here’s the code…
Centered Header

It’s generally a good idea to first call sizeToFit on labels prior to aligning them with JFViewPositionUtil, especially when you intend to center align them.

■ Text field under a label

Have a text field that should appear left aligned, say, 10 points under a label explaining its purpose? Here is how to accomplish this…

Left Aligned Textfield

And to right align it instead…
Right Aligned Textfield

This just touches upon some of the high-level functionality of this class.  Other useful methods exist, each aptly named for its purpose.

Going Beyond

If JFViewPositionUtil’s high levels actions don’t suffice its low-level anchoring system will. The code is based on anchoring points (shown below) at the cardinal points on a rectangle as well as a center point and allow for snapping of any anchor point of one view to any point of another while also allowing for offsets from this snap point for pixel-perfect precision.

Anchor Names

Earlier I mentioned aligning a multilined label’s top left corner 5 points to the right of an icon’s top right corner. Here is how to accomplish this…

Multilined Label

Notice that I’m aligning the label to the icon. You could just as easily do the reverse.


Going Even Further

JFViewPositionUtil’s high and low-level methods ought to satisfy all your view positioning needs, but if your app has some specialized effect that isn’t handled you might also find the pointForAnchorPoint:ofView: method useful. It retrieves the location (relative to the parent view) of any of the subview’s anchor points. Armed with this information you can create your own frames to position views just the way you want.

Grouped Layout Strategy

With this introduction to the class’ capabilities out of the way it’s now time to talk layout strategies.

While there is nothing wrong with laying out each control in relation to a sibling control it often makes sense to group controls within an otherwise invisible NSView/UIView and adjust the size of that parent view perfectly for the subviews it contains.

Why would you want to do this? This approach allows for a group view to be dynamically slid in between two others and to have them adjust their positions to accommodate it. Having to re-adjust dozens of controls in tandem is a lot harder than re-adjusting a single group view acting as the parent view for these controls.

JFViewPositionUtil offers the setHeightOfSuperview:toFitAllSubviewsWithMargin: method to help you in this regard. Think of this method as being like the UIView sizeToFit method except that it allows for an adjustable margin on the bottom of the lowest subview.

This method is also quite useful for adjusting the vertical height of UIScrollViews, even if you don’t plan to dynamically insert or remove group views within them. The logic has a special handler for UIScrollViews to set their content size in addition to their regular view size.

One last thing to note: The lazy-initialization approach I advocated earlier comes into play again here. Keep in mind that the group view needs to ensure that all its subviews are initialized and positioned prior to adjusting its own size to fit them. By going with lazy-initialization the group view doesn’t need to worry about the possibility of re-initializing its subviews.

Localization Concerns

As I mentioned earlier it was when I was localizing KEYBOX that I encountered difficulty with laying out my views. Japanese is a very compact language whereas French and Spanish are comparatively stretched out. English is somewhere in the middle.

The approach I took in version 2.0 was to use fixed size font, multilined labels to handle any text length and have any sibling controls appearing under them dynamically adjust their y positions to always be N points away. As long as the parent view had enough vertical room or was UIScrollView-based it worked like magic.


Animated Views

In case you were wondering, this class is also compatible with the animation systems of both OS X and iOS. Simply use JFViewPositionUtil to set the new position within an animation context and watch iOS do the rest for you.  For OS X you can use a view’s animator for the same effect or directly reset the view position at each progress step of an NSAnimation if need be.

Lastly, if you are developing an OS X project and use auto-resizing views (setAutoResizingMask:) you’ll be happy to know that they are completely supported as usual in much the same manner as animated views are.


In Closing

JFViewPositionUtil is the result of my own frustrations with dynamic, hand-coded views.  If you are equally frustrated with the difficulties of having to code your UI by hand but simply cannot rely on Interface Builder to meet your exacting needs JFViewPositionUtil might be the sweet spot for you. I invite you to give it a try and find out for yourself!

If you have any questions or comments please contact me at jay [AT] this domain.

Open Source Code for Developing Sudoku for iPhone and OS X

My Love For Sudoku

I’m a Sudoku addict. My love for Sudoku has most certainly surpassed unhealthy levels.  Naturally, being a developer I at one point had an interest in developing my own Sudoku game just to see what it entails.

The concept of Sudoku is a very ancient one but the game’s recent popularity is attributed to the company NIKOLI which owns the copyright to the word “Sudoku” and the Japanese “数独” (lit: “number alone”) within Japan.

Game concepts, in and of themselves, cannot be copyrighted and to get around any copyright disputes I considered calling my game “9 Lives” and varying the gameplay enough by employing a strict rule of allowing up to 9 mistakes before the player loses. Essentially I was interested in making a Sudoku game for pros (no hints or anything).

However, I later learned through the Quinn/Tetris debacle that even though game concepts cannot be copyrighted, the owners of such games still show their legal fangs if you encroach on their territory and considering that my presence here in Japan is also where NIKOLI is based I reconsidered developing my own game.

That was 5 years ago, when I was just beginning to learn Objective C and OS X development. While cleaning some things up on my Mac I recently rediscovered my old Sudoku board generator code and it feels like a waste to just let it sit there unused.  Instead I decided to rewrite it (the original code is too embarassing to release) and donate it to others interested in making their own Sudoku games.

Most of the Sudoku games I have played only offer pregenerated boards. My code creates random ones each and every time. As such it depends on a random number generator, in this case my JFRandom utility class which is available on github.

If you are outside Japan and interested in making your own sudoku game check out my Sudoku Board Generator.

 

How To Use It

This one line is all you need to generate a random Sudoku board…

SudokuBoard *board = [SudokuBoardGenerator generate];

Outputting the resulting Sudoku board with NSLog will show the board in full like below…

7 1 8 5 4 3 6 2 9 

6 9 3 2 1 8 5 7 4 

5 4 2 9 7 6 3 1 8 

4 3 5 7 9 1 8 6 2 

1 6 7 8 3 2 4 9 5 

2 8 9 4 6 5 7 3 1 

8 5 1 6 2 7 9 4 3 

9 2 6 3 5 4 1 8 7 

3 7 4 1 8 9 2 5 6 


The board exposes 9 sectors (3×3 grid) and the numbers contained within for you to display in your game.  That’s all there is to it.  The details are all abstracted away from you.  If you have any questions please don’t hesitate to contact me at jay [AT] this domain.

Generating Random Numbers, Strings and Data in Objective C

Today I’m open sourcing JFRandom, a powerful utility class for creating random numbers, arrays of these as well as random strings and data.  It’s available for free download over at github.

I’ve been using this class in my KEYBOX product for nearly a year now and I can attest to its robustness.  JFRandom works in both ARC and non-ARC projects for both iOS and OS X.

Whether you need random data for encryption purposes, video game AI, shuffled music playback or just lucky lotto ticket numbers, JFRandom has you covered.

 

How to Use JFRandom

JFRandom is very simple so I’ll just illustrate one-liner examples of the main functionality below.

 

For single random numbers…

NSInteger number = 0;
BOOL worked = [JFRandom generateNumberBetweenLow: 0 andHigh: 100 intoReceiver: &number];

 

For arrays of random numbers…

NSInteger sequence[100];
BOOL worked = [JFRandom generateNumberSequenceOfLength: 100 into: sequence betweenLow: -1000 andHigh: 1000 withOnlyUniqueValues: NO];

 

If you need each number in the array to also be unique do this…

NSInteger sequence[100];
BOOL worked = [JFRandom generateNumberSequenceOfLength: 100 into: sequence betweenLow: -1000 andHigh: 1000 withOnlyUniqueValues: YES];

Note that creating unique number arrays can cause performance issues as the existing selection must be first examined for instances of the next random number to place within.

 

JFRandom also generates random NSData instances…

NSData *data = [JFRandom generateRandomDataOfLength: 16];

 

If you need the bytes to be signed rather than unsigned…

NSData *data = [JFRandom generateRandomSignedDataOfLength: 16];

 

And of course if you need a string full of random characters it’s this easy…

NSString *text = [JFRandom generateRandomStringOfLength: 64];

 

These are the basic capabilities of JFRandom.  There are a few more methods that allow for randomly picking of numbers within a pre-determined array etc…  Check out JFRandom now and save yourself the trouble of coding and testing this yourself!

Update to JFUrlUtil

Just a small update regarding the JFUrlUtil URL encoder for Objective C I introduced recently:  I recently encountered URLs in the wild containing the “@” character and accordingly have now added support for encoding it.

The updated JFUrlUtil is available here.

If you find any URLs that don’t encode properly please inform me (jay@jayfuerstenberg.com) and I’ll improve this utility.

Singleton Pattern in Objective C

Objective C unfortunately does not support the singleton pattern with which Java developers are familiar.  The reason stems from the fact that there are no private methods in Objective C to prevent the init constructor method from being invoked.

There is however a simple hack that can provide the benefits of the singleton pattern in Objective C.  Singleton classes tend to be managers of data so let’s go with the class name JFDataManager in this example.

 

Going Global

Since Objective C doesn’t support the singleton pattern we have to resort to using a global variable the way C does.

A global variable can be referenced from anywhere in the application and since we want to discourage the direct manipulation of this global variable we need to hide it.  The best place to hide it is the one place nobody will look, in definition file for that class, JFDataManager.m.

Doing so will render it unlikely of being referenced since we’re never supposed to #import or #include *.m files.  Note that I said unlikely.  Technically any inquisitive developer can find and reference it.

The declaration might look something like this…

JFDataManager *__JFDataManager_sharedInstance__ = nil;

Since the class name was previously declared in JFDataManager.h this instance is completely legal.  Now since we’re dealing with global variables there is the risk of name collision so it’s good practice to go with an instance name that includes the class name as I’ve done above.

 

Exposing It The Recommended Way

The convention for telling developers that they should access the singleton instance and not instantiate their own is to offer a class method beginning with the word “shared”.  You may have noticed a sharedApplication method exposed by the NSApplication and UIApplication classes.  You’ll want to follow this approach.

JFDataManager will expose the below method…

+ (JFDataManager *) sharedManager;

The implementation of this method will return the shared instance and if necessary lazy-initialize it like this…

+ (JFDataManager *) sharedManager {
	if (__JFDataManager_sharedInstance__ == nil) {
		__JFDataManager_sharedInstance__ = [[JFDataManager alloc] init];
	}
	return __JFDataManager_sharedInstance__;
}

 

Getting the shared instance is as simple as invoking the sharedManager method.  That’s really all there is to using the singleton pattern in Objective C.  It involves a bit of trickery but Objective C developers using your class will enjoy the same benefits Java developers already do.

 

URL Encoding In Objective C

A new project I’m working on uses NSURL to a great extent and as useful as that class is, it has one sour point.  It is unforgiving of improperly encoded strings when instantiating an NSURL via the URLWithString convenience constructor.

Naturally I needed an encoder that would escape the unsafe characters.  There is a decent selection online but they each lacked a few properties I need in my project.

  1. The domain + path portion needs to be left alone (no conversion of slashes etc…).
  2. Any previously escaped sequences (like %20) need to be left alone and not have the percent escaped again (like %2520).

I’ve given up looking for an existing solution and rolled my own, which I now share with you!

My implementation is called JFUrlUtil (Download) and is open sourced under the Apache license.

 

How it works

JFUrlUtil features a single public method called encodeUrl.  The approach it takes is basically to iterate over each character in the URL string you provide and escape where appropriate.  It is quite performant as it avoids invoking NSString’s stringByReplacingOccurrencesOfString:withString: method for each unsafe character.

Compatibility

I’ve tested this implementation against tens of thousands of URLs and have yet to find any encoded URL capable of causing NSURL to frown.  If you can find one I didn’t anticipate please let me know (jay@jayfuerstenberg.com) and I’ll gladly update my implementation.