Pointers, Invalid Operands to Binary, and Noobs
[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
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 if
s, 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 XYPoint
s are equal.
精彩评论