2
\$\begingroup\$

This started simple, as most things do. I just wanted a little structure to hold polar coordinates for a totally minor class. But starting with this answer and borrowing from existing Objective-C concepts like CGPoint and CGSize, the simple struct quickly morphed into a more complete solution.

I have this all in a _polar.h file that I have included in my files and I was wondering what other things should be included and/or other criticism of my technique. Am I approaching this thing correctly?

(Note: startPoint and endPoint are part of the structure to help solve other problems in my class and are not necessarily "normal" parts of a polar structure.)

#ifndef Polar__polar_h
#define Polar__polar_h

struct _Polar {
    CGFloat angle;
    CGFloat r;
    CGPoint startPoint;
    CGPoint endPoint;
};
typedef struct _Polar Polar;

static inline Polar
PolarMakeFromPoints(CGPoint startPoint, CGPoint endPoint) {
    Polar polar;
    polar.startPoint =startPoint;
    polar.endPoint =endPoint;
    polar.angle =atan2f(endPoint.y -startPoint.y, endPoint.x -startPoint.x);
    polar.r =sqrtf(powf(endPoint.x -startPoint.x, 2.0) + pow(endPoint.y -startPoint.y, 2.0));
    return polar;
}
static inline Polar
PolarMake(CGFloat angle, CGFloat r) {
    Polar polar;
    polar.angle =angle;
    polar.r =r;
    polar.startPoint =CGPointZero;
    polar.endPoint =CGPointMake((cos(angle) *r), (sin(angle) *r));
    return polar;
}
static inline bool
PolarEqualToPolar(Polar polar1, Polar polar2) {
    return polar1.angle ==polar2.angle && polar1.r ==polar2.r;
}
static inline bool
PolarIdenticalToPolar(Polar polar1, Polar polar2) {
    return CGPointEqualToPoint(polar1.startPoint, polar2.startPoint)
        && CGPointEqualToPoint(polar1.endPoint, polar2.endPoint);
}

static inline Polar
_PolarZero() {
    Polar polar;
    polar.angle =0.0;
    polar.r =0.0;
    polar.startPoint =CGPointZero;
    polar.endPoint =CGPointZero;
    return polar;
}
#define PolarZero _PolarZero()

static inline NSString
*NSStringFromPolar(Polar polar) {
    return [NSString stringWithFormat:@"a=%f r=%f", polar.angle, polar.r];
}


// Extend NSValue to work with Polar
@interface NSValue (Polar)
+(id)valueWithPolar:(Polar)polar;
-(Polar)polarValue;
@end
@implementation NSValue (Polar)
+(id)valueWithPolar:(Polar)polar {
    return [NSValue value:&polar withObjCType:@encode(Polar)];
}
-(Polar)polarValue {
    Polar polar;
    [self getValue:&polar];
    return polar;
}
@end


@interface NSString (Polar)
@end
@implementation NSString (Polar)

@end

#endif
\$\endgroup\$
2
\$\begingroup\$
  • Why the #ifdef guard? It’s not needed in Objective-C since we have the #import directive instead of #include.

  • Why have the whole thing in the header? The usual solution is to put the function declarations into the header and the implementations into the implementation file.

  • The difference between PolarEqualToPolar and PolarIdenticalToPolar is not clear to me. I mean, I could assert something from the implementation, but that’s not a good API if I have to.

  • Related to the previous point, do you realize you’re skating on thin ice when comparing the float components using plain equality (==)? The same disclaimer applies here as for any floating-point comparison, there are nasty suprises caused by precision issues. (See the classical article about What Every Computer Scientist Should Know About Floating-Point Arithmetic.) This is not necessarily a fault of your API or code, it’s just good to be aware of.

  • Do you really need the performance gains to write this in C instead of Objective-C? Always use high-level code unless the profiler tells you otherwise. Granted, polar coordinates are somewhat on the performant side, but then the modern hardware is so fast you could write the code in high-level Objective-C and still get very usable performance for many use cases.

\$\endgroup\$
  • \$\begingroup\$ +1, but note that this was tagged with ios, so unless this person's app is only targeting new iPhones (e.g. 5) and iPads, the modern hardware is still a pretty small computer. I've run into performance problems with mapping code before. \$\endgroup\$ – Nate Apr 20 '13 at 10:14
  • \$\begingroup\$ I have some experience developing games for the iPhone and I was surprised how fast the machines are; I seldom needed to drop into C for performance reasons. But you’re right, C is a reasonable default in this case. \$\endgroup\$ – zoul Apr 20 '13 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.