j_hindsight
j_hindsight

Reputation: 27

method to return the intersection of 2 rectangles

I'm new to programming and objective-c (so i could be way off here) and i'm working my way through programming in objective c 4th edition text book and have become stuck on one of the exercises.

Can anyone tell what's wrong with the method below? In my program there is a rectangle class which has methods to set it's width, height and it's origin (from a class called XYPoint).

The containsPoint method checks to see if a rectangle's origin is within another rectangle. When i test this method it always returns 'No' even when the rectangle does contain the point.

The intersects method takes a rectangle as an argument (aRect) and uses the containsPoint method in an if statement to check if it intersects with the reciever and if it does, return a rectangle with an origin at the intersect and the correct width and height.

-(BOOL) containsPoint:(XYPoint *) aPoint
{
//create two variables to be used within the method 
float upperX, upperY;

//assign them values, add the height and width to the origin values to range which the XYPoint must fall into 
upperX = origin.x + height;
upperY = origin.y + width;    

//if the value of aPoint's x and y points fall between the object's origin and the upperX or upperY values then the rectangle must contain the XYPoint and a message is sent to NSLog

if ((aPoint.x >= origin.x) && (aPoint.x <= upperX) && (aPoint.y >= origin.y) && (aPoint.y <= upperY) ) 
{
    NSLog(@"Contains point");
    return YES;

}

else
{
    NSLog(@"Does not contain point");
    return NO;

}


}


-(Rectangle *) intersects: (Rectangle *) aRect
{
//create new  variables, Rectangle and XYPoint objects to use within the method
Rectangle *intersectRect = [[Rectangle alloc] init];
XYPoint *aRectOrigin = [[XYPoint alloc] init];
float wi, he;   //create some variables

if ([self containsPoint:aRect.origin]) {     //send the containsPoint method to self to test if the intersect
    [aRectOrigin setX:aRect.origin.x andY:origin.y];   //set the origin for the new intersecting rectangle
    [intersectRect setOrigin:aRectOrigin];
    wi = (origin.x + width) - aRect.origin.x;   //determine the width of the intersecting rectangle
    he = (origin.y + height) - aRect.origin.y;  //determine the height of the intersecting rectangle
    [intersectRect setWidth:wi andHeight:he];   //set the rectangle's width and height

    NSLog(@"The shapes intersect");
    return intersectRect;
}

//if the test returned NO then send back these values
else {
    [intersectRect setWidth:0. andHeight:0.];
    [aRectOrigin setX:0. andY:0.];
    [intersectRect setOrigin:aRectOrigin];

    NSLog(@"The shapes do not intersect");
    return intersectRect;
}
}

when i test with the following code

    int main (int argc, char * argv [])
{
    @autoreleasepool {

        Rectangle *aRectangle = [[Rectangle alloc] init];
        Rectangle *bRectangle = [[Rectangle alloc] init];
        Rectangle *intersectRectangle = [[Rectangle alloc] init];
        XYPoint *aPoint = [[XYPoint alloc] init];
        XYPoint *bPoint = [[XYPoint alloc] init];

        [aPoint setX:200.0 andY:420.00];
        [bPoint setX:400.0 andY:300.0];

        [aRectangle setWidth:250.00 andHeight:75.00];
        [aRectangle setOrigin:aPoint];

        [bRectangle setWidth:100.00 andHeight:180.00];
        [bRectangle setOrigin:bPoint];    

        printf("Are the points within the rectangle's borders?  ");  
        [aRectangle containsPoint: bPoint] ? printf("YES\n") : printf("NO\n");  
        intersectRectangle = [aRectangle intersects:bRectangle];

}
    return 0;   
}

i get the following output

Contains point  
The origin is at 0.000000,0.000000, the width is 250.000000 and the height is 75.000000  

Upvotes: 0

Views: 2771

Answers (4)

Eman Shedeed
Eman Shedeed

Reputation: 114

 //intersect function
 -(Rectangle *)intersect:(Rectangle *)secondRec
 {
 int intersectRectWidth;
 int intersectRectHeight;
 int intersectRectOriginX;
 int intersectRectOriginY;
 Rectangle * intersectRec =[[Rectangle alloc]init];
 intersectRectOriginX = MAX(self.origin.x,secondRec.origin.x);

 intersectRectOriginY = MAX((self.origin.y) , (secondRec.origin.y));
int myWidth=self.width+self.origin.x;
int secondRecWidth=secondRec.width+secondRec.origin.x;
int tempWidth=secondRecWidth - myWidth;
if (tempWidth > 0) {
    intersectRectWidth=secondRec.width - tempWidth;
}
else
{
    tempWidth=abs(tempWidth);
    intersectRectWidth = self.width - tempWidth;
}

//height
int myHeight=self.height+self.origin.y;
int secondRecHeight=secondRec.height +secondRec.origin.y;
int tempHeight=secondRecHeight - myHeight;
if (tempHeight > 0) {
    intersectRectHeight=secondRec.height - tempHeight;
}
else
{
    tempHeight=abs(tempHeight);
    intersectRectHeight = self.height - tempHeight;
}
intersectRec.width=intersectRectWidth;
intersectRec.height=intersectRectHeight;
XYPoint * intersectOrigin =[[XYPoint alloc]init];
[intersectOrigin setX:intersectRectOriginX andY:intersectRectOriginY];
[intersectRec setOrigin:intersectOrigin];
return intersectRec;

}

    //main
    XYPoint * org1=[[XYPoint alloc]init];
    XYPoint * org2=[[XYPoint alloc]init];
    Rectangle * firstRec=[[Rectangle alloc]init];
    Rectangle * secondRec=[[Rectangle alloc]init];
    Rectangle * intersectRec=[[Rectangle alloc]init];
    [org1 setX:400 andY:300];
    [org2 setX:200 andY:420];
    [firstRec setOrigin:org1];
    [secondRec setOrigin:org2];
    [firstRec setWidth:100 andHeight:180];
    [secondRec setWidth:250 andHeight:75];
    intersectRec=[firstRec intersect:secondRec];
    NSLog(@"intersect rectangle origin.x= %i origin.y=%i width=%i height=%i",intersectRec.origin.x,intersectRec.origin.y,intersectRec.width,intersectRec.height);

Upvotes: 0

Aaron Lelevier
Aaron Lelevier

Reputation: 20780

Here is the code (I'm currently using "Programming in Objective-C 5th edition by Stephen Kochan) and judging by your variables and syntax, it looks like you are too.

    // Use Floats for XYPoint and Rectangular exercise 8.4 on pg. 166

import "Rectangle.h"

import "XYPoint.h"

int main(int argc, const char * argv[]) {

@autoreleasepool {
    Rectangle *myRect = [[Rectangle alloc] init];
    Rectangle *yourRect = [[Rectangle alloc] init];
    XYPoint   *myPoint = [[XYPoint alloc] init];
    XYPoint   *yourPoint = [[XYPoint alloc] init];

    // For first Rectangle set w, h, origin
    [myRect setWidth:250 andHeight:75];
    [myPoint setX:200 andY:420];
    myRect.origin = myPoint;

    // Second Rectangle
    [yourRect setWidth:100 andHeight:180];
    [yourPoint setX:400 andY:300];
    yourRect.origin = yourPoint;

    // Find Points of intersection
    float x1, x2, y1, y2;
    x1 = MAX(myRect.origin.x, yourRect.origin.x);
    x2 = MIN(myRect.origin.x + myRect.width, yourRect.origin.x + yourRect.width);
    y1 = MAX(myRect.origin.y, yourRect.origin.y);
    y2 = MIN(myRect.origin.y + myRect.height, yourRect.origin.y + yourRect.height);

    // Make Intersecting Rectangle
    Rectangle *intrRect = [[Rectangle alloc] init];
    [intrRect setWidth: abs(x2 - x1) andHeight: abs(y2 - y1)];

    // Print Intersecting Rectangle's infor for a check
    NSLog(@"Width = %g, Height = %g, Bottom point = (%g, %g), Top point = (%g, %g)", intrRect.width, intrRect.height, x1, y1, x2, y2);

}
return 0;

}

Upvotes: 3

CRD
CRD

Reputation: 53000

You have made a number of errors, both in geometry and Objective-C, but this is how you learn!

  1. Geometry: for two rectangles to intersect the origin of one does not need to be within the area of the other. Your two rectangles intersect but the intersection does not contain either origin. So your containsPoint: will return NO.
  2. You only allocate objects if you create them, not if code which you call creates and returns them. So your allocation in Rectangle *intersectRectangle = [[Rectangle alloc] init]; creates an object which is then discarded by your assignment intersectRectangle = [aRectangle intersects:bRectangle];
  3. For simple classes such as these it is usual to create init methods which set the properties, as creating an object without setting the properties is not useful. E.g. for your XYPoint class you would normally have an initialisation method - (id) initWithX:(float)x andY:(float)y;. You then use [[XYPoint alloc] initWithX:200.0 andY:420.0]] to create and initialise in one go.
  4. As you are experimenting this is not important, but in real code for very simple and small classes which have value semantics - which means they behave much like integers and floats - it is common to use structures (struct) and functions and not objects and methods. Look up the definitions of NSRect and NSPoint as examples.

HTH

Upvotes: 0

isaac
isaac

Reputation: 4897

Why not just use the included functions for determining intersection and/or containment:

if (CGRectContainsPoint(CGRect rect, CGPoint point))
{
    // Contains point...
}

or

if (CGRectIntersectsRect(CGRect rectOne, CGRect rectTwo))
{
    // Rects intersect...
}

or

if (CGRectContainsRect(CGRect rectOne, CGRect rectTwo))
{
    // RectOne contains rectTwo...
}

Upvotes: 2

Related Questions