Archive > 2008

SOBezier – Getting started.

stompy » 30 July 2008 » In SOBezier » No Comments

The first part of this demonstration will create an application that draws a predefined curve in a window that is not re-sizeable. The idea is to get a simple working version up and running in the first place which can then be built upon.

Create the Project

In Xcode, create a new project of type “Cocoa Document-based application”. Save it wherever you like and call it SOBezier. The only project setting that needs to be set is to make sure that Garbage collection is turned on.

GC-on.png

MVC Classes

Cocoa makes extensive use of the Model-View-Controller (MVC) paradigm. Model objects are responsible for the data or state of the application. View objects are responsible for displaying the data and the Controller objects keep the two in sync. For this basic application, the model class is SOBezierCurve, a subclass of NSObject, which contains the points of the curve and also knows how to draw itself. The view class is SOBezierView, a subclass of NSView, in which the curve is drawn. These are co-ordinated by the MyDocument class, a subclass of NSDocument, which is the controller.

SOBezierCurve – the model

From the Xcode File menu, choose New File and then select a Cocoa Objective-C class. Call this SOBezier curve. This will create the header and the implementation files. Edit them to look like these code listings.

//  SOBezierCurve.h

#import <Cocoa/Cocoa.h>

@interface SOBezierCurve : NSObject {
    NSPoint pt1;
    NSPoint pt2;
    NSPoint ControlPt1;
    NSPoint ControlPt2;
}

@property (readwrite) NSPoint pt1;
@property (readwrite) NSPoint pt2;
@property (readwrite) NSPoint ControlPt1;
@property (readwrite) NSPoint ControlPt2;

- (id)initWithPt1:(NSPoint)point1
              Pt2:(NSPoint)point2
       ControlPt1:(NSPoint)cPoint1
       ControlPt2:(NSPoint)cPoint2;
- (void)drawCurve;

@end

Here, the four points that define the curve are declared and I am using the Objective-C 2.0 @property syntax to make these properties. Two methods are declared. First, an initialiser that creates the curve based on the four points being passed in, and a method that draws the curve.

The implementation is quite simple:

//  SOBezierCurve.m

#import "SOBezierCurve.h"

@implementation SOBezierCurve
@synthesize pt1, pt2, ControlPt1, ControlPt2;

- (id)initWithPt1:(NSPoint)point1
              Pt2:(NSPoint)point2
       ControlPt1:(NSPoint)cPoint1
       ControlPt2:(NSPoint)cPoint2
{
    // Designated initialiser.
    if (![super init]) {
        return nil;
    }
    pt1 = point1;
    pt2 = point2;
    ControlPt1 = cPoint1;
    ControlPt2 = cPoint2;
    
    return self;
}

- (void)drawCurve
{
    NSBezierPath *path = [NSBezierPath bezierPath];
    // Move to the first control point
    [path moveToPoint:ControlPt1];
    // Add a line from the control point to the first point of the curve
    [path lineToPoint:pt1];
    // Create the curve
    [path curveToPoint:pt2 controlPoint1:ControlPt1 controlPoint2:ControlPt2];
    // Draw a line from the end of the curve to the second control point
    [path lineToPoint:ControlPt2];
    
    // Now draw the curve
    [[NSColor blackColor] set];
    [path stroke];
}

@end

The initialiser just sets the points of the curve to the points that are passed in. the @sythesize directive lets Objective-C 2.0 create accessors for the properties that are Key Value Coding (KVC) compliant.

The DrawCurve: method is responsible for drawing the curve represented by these points. This is where the terminology becomes confusing with the term ‘bezier’ appearing everywhere. The NSBezierPath class is used extensively in Cocoa graphics, (which is why it is so easy to draw bezier curves), so to draw the curve a series of bezier paths are linked together as a single path and then drawn on the view by stroking this single path.

SOBezierView – the view

This class needs to be creates as we did with the SOBezierCurve class. From the Xcode File menu, choose New File and then select a Cocoa Objective-C NSView subclass. Call this file SOBezierView. This will create the header and the implementation files. Edit them to look like these code listings.

//  SOBezierView.h

#import <Cocoa/Cocoa.h>
@class MyDocument;

@interface SOBezierView : NSView {
    IBOutlet MyDocument *doc;
}

@end

This class doesn’t do much at the moment so it is quite small. The interface file just declares an outlet called doc to the controller, which is the MyDocument object in this case.

The implementation file only has two methods, both of which come from the superclass so they don’t need to be declared in the header file.

//  SOBezierView.m

#import "SOBezierView.h"
#import "MyDocument.h"
#import "SOBezierCurve.h"

@implementation SOBezierView

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

- (void)drawRect:(NSRect)rect {
    [[NSColor yellowColor] set];
    [NSBezierPath fillRect:[self bounds]];
    
    [[doc curve] drawCurve];
}

@end

The initWithFrame: method is where the initialisation code will go. But the important method is the drawRect: method which is invoked whenever the view needs to draw itself.

The first thing that the drawRect: method does is set the colour to be used and then calls the NSBezierPath fillRect: method to fill the entire view window with this colour. The rect paramater that is passed into the drawRect: method is the rectangle that is ‘dirty’ and needs to be redrawn, but to keep things simple, this implementation just fills in the whole view. If the view was drawing a number of curves, this dirty rectangle could be used to determine which curves are within this rectangle and the drawing code could be optimised to only draw those curves. The method then uses the outlet to the MyDocument object outlet doc to access curve object which is then asked to draw itself.

MyDocument – the controller

The MyDocument class was created by Xcode as part of the project.

Edit the header file so that it looks like this listing.

//  MyDocument.h
//  SOBezier

#import <Cocoa/Cocoa.h>
@class SOBezierCurve;                          // 1

@interface MyDocument : NSDocument
{
    SOBezierCurve *curve;                      // 2
}
@property (readwrite) SOBezierCurve *curve;    // 3
@end
  1. Here SOBezierCurve is declared to be a class.
  2. The curve attribute is declared as a pointer to an SOBezierCurve object.
  3. This attribute is declared as a property.

The MyDocument.m file contains a lot of generated code. For now the only changes need to be made to the beginning of the file. Edit the code so it looks like this listing.

//  MyDocument.m
//  SOBezier

#import "MyDocument.h"
#import "SOBezierCurve.h"                                   
// 1

@implementation MyDocument
@synthesize curve;                                          // 2

- (id)init                                                  // 3
{
    self = [super init];
    if (self) {
        NSPoint p1 = NSMakePoint(100, 150);
        NSPoint p2 = NSMakePoint(300, 150);
        NSPoint cP1 = NSMakePoint(100, 225);
        NSPoint cP2 = NSMakePoint(300, 75);
        
        curve = [[SOBezierCurve alloc] initWithPt1:p1
                                       Pt2:p2
                                ControlPt1:cP1
                                ControlPt2:cP2];
    
    }
    return self;
}

.
.
.

@end

  1. Import the header file for the SOBezierCurve class.
  2. This creates KVC compliant accessors for the curve attribute.
  3. The init method, called when the object is created, sets up the points to be used for the default curve and then creates an SOBezierCurve object with these points.

Create the User Interface

Here’s a short screencast of how the UI is created. (If a picture is worth a thousand words, how many more is a video worth?).

Once that is done, you can click build and go to see a simple bezier curve drawn on a yellow background. Not very interesting so far, but it’s a good starting point.

Next Steps

The next step will be to add handles to the points so they can be moved around the view causing the curve to change.

Finally, thanks for your attention and I’d appreciate any comments you have, particularly about things you don’t like, so that I can improve this demonstration.

Resources

You can get the source code up to this point from the project’s git repository here. A checkout of the Stage1_1 tag will get the code up to this point.

Alternatively, you can download a zip file of the completed version up to this point here: SOBezier_01.zip (60 kb)

Continue reading...

Tags: , , , , ,

SOBezier – A Cocoa Tutorial

stompy » 29 July 2008 » In SOBezier » No Comments

BasicApp.tiff

I am going to start a series of tutorials that will build a basic Mac application that draws and manipulates bezier curves. Following the example of the Hillegass book I am going to be building the application up bit by bit; adding functionality in stages. Although the sample code available on the Apple site and elsewhere on the net is quite detailed, it is sometimes hard to see how an application can be built up in small steps.

Because I am a fan of version control, and also because it can show the stages that the application is built up in, the git repository is available online, but if you don’t have (or want to use) git, I’ll also have zip files of the project as it goes along.

The screen shot looks a little dull right now, but I am planning to have support for preference panes, changing the curve, undo/redo, printing, archiving, and copying amongst other things.

Also, if there is enough support for it, I might screencast some of the stages.

I hope you’ll join me.

Continue reading...

Tags: , , , ,

Dunwich Dynamo 2008 – After

stompy » 23 July 2008 » In Cycling » 1 Comment

Bike on Beach 01

A much better ride than last year. It was dry, the weather was great, and I did it faster and felt better at the end of it. I’ve never ridden harder in my life and I was pleasantly surprised how far I was able to keep up the pace.

I was riding this as a sort of group ride with the LondonFGSS guys. Usually, our group rides have a “no man left behind” policy, and there are lots of stops to regroup and wait for slower riders to catch up. This was a little less formal than that.



img_0076.jpg
Originally uploaded by tommybrickell


We met at London Fields at around 1930 and left at 20:30. The later start meant that we weren’t riding with a big group of cyclists so we stayed in group until our first stop 12 miles in at a petrol station. Fortified myself with a Red Bull and a Mars bar. I also took the opportunity to readjust my saddle. Foolishly, I had changed the angle for the ride, and soon found the need to return it to the way it was before.

Maybe it was the sugar and caffeine, but I really picked up the speed after this point. I did a lot more drafting than usual, and it helped that I was riding with people I know as it was easier to get close to their back wheels, confident that they wouldn’t weave over the road, or change the speed much. It was a joy rolling along the smooth roads that were so much better in the dry. Just turning my cranks for mile after mile without stopping for lights or weaving around traffic. I felt discomfort in my thighs but I just kept going rather than wimping out early as I usually do. I got some good speed on the downhills that kept my momentum going for the uphills. Although the ride is flat there are some rolling sections that can catch you out. Last year I walked up some of the climbs, but I managed to ride up all of them this time.

Got to the feed stop at a quarter past two. There was a long line for food, but I was ready for this. I had a dehydrated ration pack and the line for hot water was a lot shorter. This gave me a hefty hot meal (beef and potato hot-pot). A cup of coffee and a handful of jelly babies and lots of water. We left the food stop at 0330. A little later than I wanted, but this is not supposed to be a race.

We rode in the pre-dawn light as a group for a bit and then I found that I couldn’t keep the speed up and dropped off the group. Caught up a couple of times, but I wasn’t able to stay with them. I really should have stopped and eaten the mars bar that I was carrying, but I was too tired to remember that I had it.

Saw some wildlife. Of course, there were a few bats, but also a hedgehog crossing the road and a hare bouncing around in one of the verges.

Some people waiting on a corner gave my encouragement “It’s only 7 miles now!” they said. I was in a weird fugue state – just turning my cranks and watching the road. I didn’t know what the time was and I think I was going quite slowly. Hippy flew by me with around 6 miles to go, and I woke myself up by standing on my pedals and getting my speed up to try and follow him. I didn’t keep up, but at least it got me going again. Those last few miles seemed to last forever. So close, but not there yet, and the legs burning and you pick up the speed to just get it over with. And then, almost like an anticlimax, there is a junction, a short road, and the beach is there right in front of you. I checked my mobile and was amazed to see it was 7.11 am. I thought it was more like 8. I don’t know where I made up the time because it felt like I was just grinding for the last few hours.

A big breakfast and then I thought I would have a sit on the beach. The pebbles were just warming up in the morning sun, and it was surprisingly comfortable to lie down on. I must have fallen asleep because it was an hour and a half later that I found the rest of the group a bit further down the beach.

Chilling 02

A little cider, a little mindless chat and then it was on the coach and another nap till we got to London. We were one of the last coaches back and there was a moment of fear searching for your bike amongst the hundred or so others stacked around Smithfields.

And that was it. I was home 22.5 hours after I left. Tired and groggy I don’t even remember what I had to eat that night.

Will I do it again – absolutely.



img_0100.jpg
Originally uploaded by tommybrickell

Continue reading...

Tags: , ,

Dunwich Dynamo 2008 – Before.

stompy » 18 July 2008 » In Cycling » 1 Comment

Photo © 2007 andy black used with permission.

The 2008 Dunwich Dynamo rolls out this Saturday night. A 120 mile overnight bike ride from London to Dunwich on the East coast. By tradition this is run on the weekend closest to the July full moon, and this will be the 16th run. It is an unsupported ride. There is no need to book, there’s nothing to pay. You just turn up at the start and ride out with everyone else. There’s no broom wagon at the back so if anything goes wrong, well, you’re on your own. Southwark Cyclists organises coaches back to London, with the bikes following on in a fleet of removal vans. At around half way, some kind people get a village hall and serve hot food. Of course, as they don’t know how many riders will be, there may not be anything left for the slower riders.

Last year’s ride was my first time I rode it; on a fixed wheel with a 48/17 gear ratio. It rained hard until dawn. But by the time I reached the beach at the end the sun was out and it was a glorious morning. All kinds of bikes and riders were out. Roadies on carbon speed machines, recumbents, commuters on hybrids or mountain bikes. Quite a few fixed wheels and single speeds as well. Old and young riders.

Strangely, trolling the web for memories of the ride, I found this picture from a fellow rider who I don’t even know. He blogged his ride here. It’s about 24 miles in and the worst of the rain was yet to come.

What I remember about the ride most is the sense of achievement. I was cold, wet and miserable for a lot of the time. But with so many bikes on the route – 400 cyclists riding out of London on a Saturday evening in a long stream before getting stretched out is a wondrous sight – you can always join a group and lift your spirits. It took me about 12 hours, but that includes stops for food and breaks.

I’m riding fixed again this year. I’m a better cyclist than I was then, so I’m planning on riding the whole way instead of walking up some of the hills. In a way I think it will be harder this year. Last time I just concentrated on turning the pedals, this time I know how far I have to go. There is some chance of rain this weekend, but it can’t be worst than last time, but the forecast is for strong wind, which isn’t pleasant when you’re on your own on a bike.

So, I’m hoping for clear skies and moonlight. I’ll clean my bike tomorrow and ride off away from the sunset and into the highlight of my cycling year.

Continue reading...

Tags: ,

MobileMe iDisk icon

stompy » 17 July 2008 » In Mac OS X » No Comments

iDisk_icon.png

I’ve just noticed the new iDisk icon on my desktop.

What’s the deal with the viiolet colour, and the nursery cloud? For a platform that rates aesthetics so highly this is like grit in the eye.

Ugh! I’m going to have to find a replacement for this.

Continue reading...

Tags: , , ,