Memention Blog

Wheels are turning - Trust your data


iphone image

Once in a while one came across some neat programming trick that makes one smile.

A few weeks back I bought a used Smart car, you know the tiny one. Well, as it’s getting colder here in Sweden and I didn’t get any winter tires with the car I started to look for some on the net. The whole point of buying this Smart was to have a cheap transport back and forth to my current work place, so I was also looking for ways to buy some cheap, or rather inexpensive, tires. The Smart has some pretty small tires so they are also somewhat difficult to find. So, how about using some other tire dimensions? Well, there are rules how far from the original dimensions one can go, here in Sweden this is ± 5 % speedometer error. Most online tire sellers seemed to have tire calculators just for this purpose. Idea! Make an iPhone app! Well, remember always to check if others already have done it and of-course there already where two tire calculators on the app store. But, I though they looked rather dull so I decided to create the app anyway - in 3D as this is more my specialty.

The app is very simple and I decided to put the tire size number on top of the screen in three blue squares. First the tire tread width, second the height profile and last the tire inner diameter. As they are basically identical in the user interface functionality, a blue square that can be dragged up/down to set value its value, I thought a little How can I make this neat. Well, pretty quickly I came up with a trick to use three variables that are set when a drag/set movement is begun and a very simple handling when changed. At this point I had already working methods for easily setting the wheel dimensions with real life values like ‘205/55 R16’.

[self setWheelWidth:205 profile:55 diameter:16];

// But actual call is used with variables
[self setWheelWidth:width profile:profile diameter:diameter];

The tread widths always where specified starting from 125 increasing with ten until reaching 335. The height profile from 20 up to 80 in steps of 5. The diameter from 12 to 26 in steps of 1.

I defined these value lists as three arrays.

float widthValues[] = { 125, 135, 145, ... , 315, 325, 335 };

float profileValues[] = { 20, 25, 30, ... , 70, 75, 80 };

float diameterValues[] = { 12, 13, 14, ... , 24, 25, 26 };

So, how to easily change one of three variables width, profile, diameter and select a valid value?

The trick is to keep a pointer to the variable that is currently activly changing. To handle the valid values these are also pointed to with another pointer variable.

float *activeVariable;
float *activeValidValues;
int   numValidValues;

When the finger touches inside any of the blue squares initializing of these variables are done.

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch *touch = [touches anyObject];

    activeVariable = nil; // Make sure no old value is active

    if ([widthSquare pointInside:[touch locationInView:widthSquare] 
                       withEvent:nil]) { 

        activeVariable = &width;
        activeValidValues = widthValues;
        numValidValues = sizeof(widthValues)/sizeof(float);

    }
    if ([profileSquare pointInside:[touch locationInView:profileSquare] 
                         withEvent:nil]) { 

        activeVariable = &profile;
        activeValidValues = profileValues;
        numValidValues = sizeof(profileValues)/sizeof(float);

    }
    if ([diameterSquare pointInside:[touch locationInView:diameterSquare] 
                          withEvent:nil]) { 

        activeVariable = &diameter;
        activeValidValues = diameterValues;
        numValidValues = sizeof(diameterValues)/sizeof(float);

    }
}

Now to the beauty of the trick. The change handling. At this point we have a pointer to the variable that is going to be changed, a list of valid values and the number of valid values, so basically all we have to do now is to get an index into the valid values list from the touch Y coordinate, get the value and set the variable pointed to by activeVariable.

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];

    if (activeVariable) {

        // The two final lines of this trick
        int idx = (int)(numValidValues * (p.y-20)/440.0) % numValidValues;
        *activeVariable = activeValidValues[idx];
        
        // The right variable has been changed, update 3D wheel
        [self setWheelWidth:width profile:profile diameter:diameter];
    }
}

This trick is quite dependent on trusting the pointers in the handling part. I often see programmers that write code in a very defensive manor that would never do things like this. I do not recommend this trick either. I’m just sharing this solution that made me smile and worked great for this little iPhone app. I’m also not sure what to call it either, ”Modifing by pointers”?, but basically it’s a simple decoupling, but working on plain float variables instead of some abstract class objects.

Hope it made you smile too…

The app is available in iTunes here.

By Edward Patel, 19 Sep 2009




Show comments

Archive

Getting there13 Mar 2014
Throwing pebbles12 Jul 2013
Provision this!30 Aug 2012
Break what?18 Aug 2011
That old thing04 May 2011
Removing a Step15 May 2010
Make It Work22 Feb 2010
KISS server31 Jan 2010
tig on Mac12 Dec 2009
The XML Runner31 Oct 2009
Get some software from Memention
Powered by Jekyll and Disqus.
Copyright © 2010-2013 Memention AB