1

[Edit: Rectangle definition added at bottom.] [Edit2: XYPoint interface added at bottom.]

I'm working on a method that checks if two rectangles overlap. (Yeah, I'm in Kochan's Programming in Objective-C, doing the exercises, and I am painfully new at this.) When I compile this, the error message is: "Invalid operands to binary +". I get it on the first if statement and on the if-else that follows it.

I think I have an issue with pointers, but Kochan doesn't talk about this much.

And, if I take out these lines, the rest of the method works just fine. And the relevant variables are all floating type.

Help?

Also, any other thoughts on the method would be totally welcome. (Like, how do I make lines of code not go out so long. Like I said, painfully new at this.)

-(void) overlap: (Rectangle *)r2
{

overlapRectangle = [[Rectangle alloc] init];
leftRectangle = [[Rectangle alloc] init];
rightRectangle = [[Rectangle alloc] init];
lowerRectangle = [[Rectangle alloc] init];
upperRectangle = [[Rectangle alloc] init];

BOOL xIntersect = NO;
BOOL yIntersect = NO;


//  Test to see if the Rectangle contains, or is equal to, Rectangle b

if (origin.x <= r2.origin.x && origin.y <= r2.origin.y && (origin.x + width) >= (r2.origin + r2.width) && (origin.y + height) >= (r2.origin.y + r2.height) ) 
{
    overlapRectangle = r2;
}

//  Test to see if Retangle b contains, or is equal to, the Rectangle

else if (origin.x >= r2.origin.x && origin.y >= r2.origin.y && origin.x + width <= r2.origin + r2.width && origin.y + height <= r2.origin.y + r2.height ) 
{
    overlapRectangle = self;
}

//  I should add tests for triangles overlapping on three 
//  sides or overlapping  on two sides, but I'm not going 
//  to right now. Just learning objects and methods.


//  Test to see if rectangles overlap on the x-axis 
//  Current is an if, because I wanted to run the code below
//  to see if it worked, and it did. 

if (origin.x <= r2.origin.x)
{
    leftRectangle = self;
    rightRectangle = r2;
}
else 
{
    rightRectangle = self;
    leftRectangle = r2;
}

if (rightRectangle.origin.x + rightRectangle.width > leftRectangle.origin.x) 
{
    xIntersect = YES;
}



//  Test to see if rectangles overlap on the y-axis

if (origin.y <= r2.origin.y)
{
    lowerRectangle = self;
    upperRectangle = r2;
}
else 
{
    lowerRectangle = self;
    upperRectangle = r2;
}

if (lowerRectangle.origin.y + lowerRectangle.height > upperRectangle.origin.y) 
{
    yIntersect = YES;
}



//  If retangles overlap on both the x-axis and y-axis, 
//  determination of overlapping rectangle's origin, height, and width
//  and display same.

if (xIntersect == YES && yIntersect == YES) 
{
    overlapRectangle.origin.y = upperRectangle.origin.y;
    overlapRectangle.origin.x = rightRectangle.origin.x;
    overlapRectangle.height = lowerRectangle.height - (upperRectangle.origin.y - lowerRectangle.origin.y);
    overlapRectangle.width = leftRectangle.width - (rightRectangle.origin.x - leftRectangle.origin.x);


    NSLog (@"Your rectangles overlap.");
    NSLog (@"Rectangle: w = %g, h = %g", overlapRectangle.width, overlapRectangle.height);
    NSLog (@"Area = %g, Perimeter = %g", [overlapRectangle area], [overlapRectangle perimeter]);
    NSLog (@"Origin at (%g, %g)", overlapRectangle.origin.x, overlapRectangle.origin.y);
}

else 
{
    NSLog (@"Your rectangles do not overlap.");
}



[overlapRectangle autorelease];
[leftRectangle autorelease];
[rightRectangle autorelease];
[lowerRectangle autorelease];
[upperRectangle autorelease];

}

Rectangle Definition:

// Interface, Rectangle Class

@interface Rectangle : NSObject

{
    float width;
    float height;
    XYPoint *origin;

    // For overlapping calculations

    Rectangle *overlapRectangle;
    Rectangle *leftRectangle; 
    Rectangle *rightRectangle; 
    Rectangle *lowerRectangle; 
    Rectangle *upperRectangle; 
}

@property float width, height;

-(XYPoint *) origin;
-(void) setOrigin: (XYPoint *) pt;
-(void) setWidth: (float) w andHeight: (float) h;
-(float) area;        
-(float) perimeter;   
-(void) print;
-(void) translate;
-(void) overlap: (Rectangle *)r2;
-(void) draw;


@end

XYPoint interface:

#import <Foundation/Foundation.h>

@interface XYPoint : NSObject
{
    float x;
    float y;
}

@property float x, y;

-(void) setX: (float) xVal andY: (float) yVal;

@end
ctaggart
  • 166
  • 1
  • 10
  • 3
    On what line is the error reported? Can you post your definition of Rectangle? Any particular reason not to use CGRect and CGRectIntersectsRect(CGRect rect1, CGRect rect2) from CGGeometry? – highlycaffeinated May 28 '11 at 03:59
  • The errors show up on the first *if* line and on the first *if-else* line. I'll grab the Rectangle definition. – ctaggart May 28 '11 at 04:07
  • 1
    The type of your `width`, `height`, and origin coordinates is a basic type, like `float`? Or an object? EDIT: Oh, you're going to post the header. That will answer my question. Great! – jscs May 28 '11 at 04:11
  • You asked: "Any particular reason not to use CGRect and CGRectIntersectsRect(CGRect rect1, CGRect rect2) from CGGeometry?" Ummm... because I didn't know it existed. I am 100% brand new at this. – ctaggart May 28 '11 at 04:12
  • 1
    Okay, now what's the interface for `XYPoint`? :) – jscs May 28 '11 at 04:13
  • I'll grab that XYPoint interface. BRB. (And thanks for the help.) – ctaggart May 28 '11 at 04:13
  • 1
    Re: `CGRectIntersectsRect` -- It's a good question, but those functions only work with Apple's `CGRect` structs. They can't be used with your custom classes here. – jscs May 28 '11 at 04:14
  • 1
    Okay, I think I know what's wrong. Working on an answer... – jscs May 28 '11 at 04:27
  • If you need anything else, just ask. I'm check in. – ctaggart May 28 '11 at 04:29
  • Answer posted. Ask for clarification if you need to. BTW, I assume it's you voting up my comments. I appreciate it, but it's unnecessary. There's no reputation attached to comments, so you only need to vote on them if the comment is really insightful or important. Hint: this one isn't ;) – jscs May 28 '11 at 04:43
  • Ha! I thought it would help reputation. Maybe then they are gratitude points. (It's taking everything I have not to up your last comment.) Thanks again. – ctaggart May 28 '11 at 04:53

1 Answers1

3

You've just got what is probably a typo:

// Test to see if the Rectangle contains, or is equal to, 
// Rectangle b

if (origin.x <= r2.origin.x && origin.y <= r2.origin.y && 
   (origin.x + width) >= (r2.origin + r2.width) && 
                         //^^^This is trying to add an XYPoint,
                         // which is an object, to a float.
   (origin.y + height) >= (r2.origin.y + r2.height) ) 
{
   overlapRectangle = r2;
}

// Test to see if Rectangle b contains, or is equal to, 
// the Rectangle
else if (origin.x >= r2.origin.x && origin.y >= r2.origin.y && 
         origin.x + width <= r2.origin + r2.width && 
                            //^^^Same thing.
         origin.y + height <= r2.origin.y + r2.height ) 
{
...

The compiler should have told you what the types were that you were asking to be added:

error: invalid operands to binary + (have 'struct XYPoint *' and 'float')

that's the key. You just need to change the r2.origin to r2.origin.x so that you're adding two floats.

As for the length of the lines, there's two things you can do. You can move each segment of the conditions to different lines as I've done, but it would probably be best to create a couple of methods for Rectangle that will do the tests for you. This will make the code more readable, so when you come back to it in six months and the line reads:

if( [self containsRectangle:r2] || [self isEqualToRectangle:r2] ){

you'll know what's going on right away. Here's some suggestions for that:

- (BOOL)containsRectangle:(Rectangle *)otherRect {
    BOOL originBelow = ((origin.x <= otherRect.origin.x) && 
                        (origin.y <= otherRect.origin.y));
    float maxX = origin.x + width;
    float otherMaxX = otherRect.origin.x + otherRect.width;
    BOOL maxXGreater = maxX >= otherMaxX;
    Bfloat maxY = origin.y + height;
    float otherMaxY = otherRect.origin.y + otherRect.height;
    BOOL maxYGreater = maxY >= otherMaxY;
    return originBelow && maxXGreater && maxYGreater;
}

- (BOOL)isEqualToRectangle:(Rectangle *)otherRect {
    BOOL sizeEqual = ((width == otherRect.width) && 
                      (height == otherRect.height));
    return sizeEqual && [origin isEqualToXYPoint:otherRect.origin];

}

Note: I didn't test these, just pasted them together from the conditions of your ifs, so double-check them before you use them. I did fix the typo, though.

Notice that I also made up a method on XYPoint here, isEqualToXYPoint:; you can implement that as well, to return a BOOL if the x and y of both XYPoints are equal.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Josh, It worked. Sorry for all that hassle over a typo. I should have caught that. The rest of what you suggested also makes perfect sense. And if I knew anything about NSXMLParser error codes, I'd try to help with your questions, but I think that might be a while. Thanks again! – ctaggart May 28 '11 at 04:50
  • No need to apologize; I was happy to help! Good luck! (One thing you could remember from this is that when your lines of code are long and complex like that, it's hard to catch typos -- try to break things down to make it easier to read.) – jscs May 28 '11 at 04:53