Amazon.com Widgets Final Answer to Exercise 8.7
Welcome, Guest. Please login or register.
Did you miss your activation email?
June 19, 2013, 05:58:54 PM
Home Help Search chat Login Register   
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+  Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+  Programming in Objective-C, 4th edition
| |-+  Exercises
| | |-+  Chapter 8
| | | |-+  Final Answer to Exercise 8.7
Pages: [1]   Go Down
Print
Author Topic: Final Answer to Exercise 8.7  (Read 439 times)
rue
Jr. Member
**
Posts: 53






« on: April 29, 2012, 06:08:40 PM »

Basically, I used the method I created in exercise 8.6

1. First determine if the two rectangles intersect each other.
I did this by comparing the 4 points (corners) of the rectangle and checked each corner to see if they're located inside the other rectangle. If a point (i.e. corner of a rectangle) is inside the other rectangle, then we know the 2 rectangles intersect.
There is a special case where a rectangle may be completely inside the other rectangle, so I had to do these tests eight times... 4 corners of each rectangle for the (2) rectangles.

2. If the two rectangles intersect each other, then we can easily determine the region where they intersect.  

My main program.

Code: (Objective-C)
#import <Foundation/Foundation.h>
#import "GraphicObject.h"
#import "Rectangle.h"
#import "Circle.h"
#import "Triangle.h"


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

    @autoreleasepool {
        
        XYPoint *rectOrigin;      
        Rectangle *myRect1,*myRect2,*myRectIntersect;
        BOOL    rectangleIntersect;
        
        rectOrigin = [XYPoint new];
        myRect1 = [Rectangle new];
        myRect2 = [Rectangle new];
        myRectIntersect = [Rectangle new];
        
        [rectOrigin setX:200 andY:420];
        [myRect1 setOrigin:rectOrigin];
        [myRect1 setWidth:250 andHeight:75];
        
        [rectOrigin setX:400 andY:300];
        [myRect2 setOrigin:rectOrigin];
        [myRect2 setWidth:100 andHeight:180];
        
        rectangleIntersect = [myRect1 isIntersect:myRect2];
        
        myRectIntersect = [myRect1 rectIntersection:myRect2];
        
        
        NSLog(@"The Rectangle2 (%g,%g,%g,%g) is %@ Rectangle1 (%g,%g,%g,%g)",myRect2.origin.x,myRect2.origin.y,myRect2.origin.x+myRect2.width, myRect2.origin.y+myRect2.height,rectangleIntersect==YES?@"INTERSECTING":@"DOES NOT INTERSECT",myRect1.origin.x,myRect1.origin.y,myRect1.origin.x+myRect1.width, myRect1.origin.y+myRect1.height);
        
        NSLog(@"The intersection rectangle is located at (%g,%g,%g,%g) ",myRectIntersect.origin.x,myRectIntersect.origin.y,myRectIntersect.origin.x+myRectIntersect.width, myRectIntersect.origin.y+myRectIntersect.height);
        NSLog(@"The intersection rectangle properties are height = %g, width= %g", myRectIntersect.height, myRectIntersect.width);
          
    }
    return 0;
}

My Rectangle headers and methods.
Code: (Objective-C)
#import <Foundation/Foundation.h>
#import "GraphicObject.h"
#import "XYPoint.h"

@interface Rectangle : GraphicObject
{
    double width;
    double height;
    XYPoint *origin;
}

@property double width, height;

-(XYPoint *) origin;
-(void)     setOrigin: (XYPoint*) pt;
-(void)     setWidth:(double)w andHeight: (double)h;
-(double)   area;
-(double)   perimeter;
-(BOOL) containsPoint: (XYPoint*) aPoint;
-(BOOL) isIntersect: (Rectangle*) aRect;
-(Rectangle *) rectIntersection: (Rectangle*) aRect;
@end

Code: (Objective-C)
#import "Rectangle.h"

@implementation Rectangle
@synthesize width, height;

-(void) setWidth:(double)w andHeight:(double)h
{
    width = w;
    height = h;
}

-(void) setOrigin:(XYPoint *)pt
{
    if (!origin)
        origin = [XYPoint new];
    
    origin.x = pt.x;
    origin.y = pt.y;
}

-(double) area
{
    return width * height;
}

-(double) perimeter
{
    return (width + height) * 2 ;
}

-(XYPoint*) origin
{
    return origin;
}

-(BOOL) containsPoint: (XYPoint*) aPoint
{
    // returns TRUE if aPoint is inside this Rectangle
    if ((aPoint.x >= self.origin.x) && (aPoint.x <= self.origin.x + self.width) &&
        (aPoint.y >= self.origin.y) && (aPoint.y <= self.origin.y + self.height))
        return YES;
    else
        return NO;
}

-(BOOL) isIntersect: (Rectangle*) aRect;
{
    // Returns YES if ANY (i.e. one or more) points of aRect is inside Rectangle.self
    // check each corner of aRect if inside Rectangle.self, start at x,y and go counterclockwise
    
    XYPoint *tempPoint;
    tempPoint = [XYPoint new];
    
    // lower left corner
    tempPoint.x = aRect.origin.x;
    tempPoint.y = aRect.origin.y;
    if ([self containsPoint:tempPoint])
        return YES;

    // lower right corner
    tempPoint.x = aRect.origin.x + aRect.width;
    tempPoint.y = aRect.origin.y;
    if ([self containsPoint:tempPoint])
        return YES;
    
    // upper right corner
    tempPoint.x = aRect.origin.x + aRect.width;
    tempPoint.y = aRect.origin.y + aRect.height;
    if ([self containsPoint:tempPoint])
        return YES;
    
    // upper left corner
    tempPoint.x = aRect.origin.x;
    tempPoint.y = aRect.origin.y + aRect.height;
    if ([self containsPoint:tempPoint])
        return YES;
    
    
    // NOW check from the point of view of the other rectangle
    // for cases where the rectangle is inside the other rectangle,
    // or at least 2 points of one rectangle are inside the other rectangle.
    
    // lower left corner
    tempPoint.x = self.origin.x;
    tempPoint.y = self.origin.y;
    if ([aRect containsPoint:tempPoint])
        return YES;
    
    // lower right corner
    tempPoint.x = self.origin.x + self.width;
    tempPoint.y = self.origin.y;
    if ([aRect containsPoint:tempPoint])
        return YES;
    
    // upper right corner
    tempPoint.x = self.origin.x + self.width;
    tempPoint.y = self.origin.y + self.height;
    if ([aRect containsPoint:tempPoint])
        return YES;
    
    // upper left corner
    tempPoint.x = self.origin.x;
    tempPoint.y = self.origin.y + self.height;
    if ([aRect containsPoint:tempPoint])
        return YES;
    

    // the two rectangles don't intersect
    return NO;  
    
}


-(Rectangle *) rectIntersection: (Rectangle*) aRect;
{
    // Returns YES if ANY (i.e. one or more) points of aRect is inside Rectangle.self
    // check each corner of aRect if inside Rectangle.self, start at x,y and go counterclockwise
    
    XYPoint *lowerLeftCorner,*upperRightCorner;
    Rectangle *rectIntersect;

    lowerLeftCorner = [XYPoint new];
    upperRightCorner = [XYPoint new];
    
    if (!rectIntersect)
        rectIntersect = [Rectangle new];

    if ([self isIntersect: aRect])
    {
        [lowerLeftCorner setX: MAX(self.origin.x, aRect.origin.x) andY:MAX(self.origin.y, aRect.origin.y)];
        [upperRightCorner setX:MIN(self.origin.x+self.width, aRect.origin.x+aRect.width) andY:MIN(self.origin.y+self.height, aRect.origin.y+aRect.height)];
        [rectIntersect setOrigin:lowerLeftCorner];
        [rectIntersect setWidth:upperRightCorner.x - lowerLeftCorner.x];
        [rectIntersect setHeight:upperRightCorner.y - lowerLeftCorner.y];
        return rectIntersect;
    }
    
    // the two rectangles don't intersect
    return rectIntersect;
    
}

@end

The methods isIntersect and rectIntersection are the key to solving this problem.

I've tested the program with various scenarios and it seems to be returning the correct answer, regardless of which rectangle is set as Rect1 or Rect2. So I think the program is correct.

** the only scenario which I haven't tested are rectangles that have been rotated. This algorithm will not work in those cases.

SAMPLE RUN:

2012-04-29 20:02:07.129 Chap8.Ex6[21736:403] The Rectangle2 (400,300,500,480) is INTERSECTING Rectangle1 (200,420,450,495)
2012-04-29 20:02:07.131 Chap8.Ex6[21736:403] The intersection rectangle is located at (400,420,450,480)
2012-04-29 20:02:07.131 Chap8.Ex6[21736:403] The intersection rectangle properties are height = 60, width= 50
« Last Edit: April 29, 2012, 06:20:38 PM by rue » Logged
eagle74
Newbie
*
Posts: 24


www.cucinareblog.it


WWW Email




« Reply #1 on: May 06, 2012, 10:00:20 AM »

my compliments rue, our algorithms seem similar  Grin
here is my version(my comments are written in italian, but if someone would like to understand them I'll translate!!):

My main program.
Code: (Objective-C)

#import <Foundation/Foundation.h>
#import "Rectangles.h"
#import "Squares.h"
#import "XYPoint.h"
#import "Triangle.h"
#import "Circle.h"



int main(int argc, const char * argv[])
{
   
    @autoreleasepool
    {
       
       
        Rectangles *R =[[Rectangles alloc]init];
        Rectangles *R1 =[[Rectangles alloc]init];
       
        XYPoint    *XY =[[XYPoint alloc]init];
        XYPoint    *XY1=[[XYPoint alloc]init];
       
        //setto  origine , base e altezza           
        [XY setX: 100 setY: 50];
        [R setWidth: 80 andHeight: 50];
       
        [XY1 setX: 140 setY: 20];
        [R1 setWidth:60 andHeight: 50];
       
        R.origin= XY;//qui sto richiamando il set, è come se scrivessi[R1 setOrigin:XY]
        R1.origin=XY1;
       
        [R intersect: R1];
       
    }

}

rectangles.h
Code: (Objective-C)
#import <Foundation/Foundation.h>
#import "XYPoint.h"
#import "GraphicObject.h"

@interface Rectangles : GraphicObject

@property int width, height;


-(XYPoint*) origin;
-(void) setOrigin: (XYPoint*) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
-(int) perimeter;
-(XYPoint *) coordinate: (int) t;
-(BOOL) containsPoint: (XYPoint *) aPoint;
-(Rectangles *) intersect: (Rectangles *) intersector;
@end


rectangles.m
Code: (Objective-C)
#import "Rectangles.h"
@implementation Rectangles
{
   
    XYPoint *origin;
    XYPoint *point;

    XYPoint *originNew;
    Rectangles *newRect;
    Rectangles *newR2;
}


@synthesize width, height;


-(void) setOrigin: (XYPoint *) pt
{

   if ( ! origin )//è lo stesso che scrivere if origin==0
   {
        origin = [[XYPoint alloc]init];
   }
       origin.x=pt.x;
    origin.y=pt.y;
   
}


-(XYPoint*) origin
{
    return origin;
}


-(void) setWidth: (int) w andHeight: (int) h
{
    width=w;
    height=h;
}

-(int) area
{
    return width*height;
}
-(int) perimeter
{
    return 2*(width+height);
}

//calcolo le coordinate del nuovo rettangolo passandolo in input e specificando nel tipo quale tipo di coordinata voglio in output

-(XYPoint *) coordinate: (int) t
{
   
    int h = self.height; 
    int w = self.width;
   
   
  //1=origine
  //2=basso a dx
  //3=alto a sx
  //4=alto a dx
   
    point = [[XYPoint alloc]init];
    switch(t)
       {
            case 1:
               point.x=self.origin.x;
               point.y=self.origin.y;
               //NSLog(@"L'origine ha coordinate:(%i;%i)",point.x,point.y);
               return point;
               break;

           
           
            case 2:
               point.x=self.origin.x+w;
               point.y=self.origin.y;
               //NSLog(@"Il punto in basso a dx ha coordinate:(%i;%i)",point.x,point.y);
               return point;
               break;
           
            case 3:
               point.x=self.origin.x+w;
               point.y=self.origin.y+h;
               //NSLog(@"Il punto in alto a dx ha coordinate:(%i;%i)",point.x,point.y);
               return point;
               break;

                       
            case 4:
               point.x=self.origin.x;
               point.y=self.origin.y+h;
               //NSLog(@"Il punto in alto a sx ha coordinate:(%i;%i)",point.x,point.y);
               return point;
               break; 

                                     
        default:
            NSLog(@"tipo di coordinata non esistente");
            break;
            }
    return 0;
}

//vedo se il punto in input è all'interno del rettangolo
-(BOOL) containsPoint: (XYPoint *) aPoint
{
      if (self.origin.x  <= aPoint.x &&  (self.origin.x + self.width)  >= aPoint.x
          &&
          self.origin.y   <= aPoint.y &&  (self.origin.y + self.height) >= aPoint.y)
          return YES;
    else
        return NO;
}


//a seconda del punto che sta all'interno del rettangolo calcolo la nuova origine e area
-(Rectangles *) intersect: (Rectangles *) intersector
{   
    newRect= [[Rectangles alloc]init];
   
    if ([self containsPoint:[intersector coordinate: 1]] &&
        [self containsPoint:[intersector coordinate: 2]] &&
        [self containsPoint:[intersector coordinate: 3]] &&
        [self containsPoint:[intersector coordinate: 4]] )//tutto interno
    {
        newRect.width=intersector.width;
        newRect.height=intersector.height;
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }

   
    if ([self containsPoint:[intersector coordinate: 2]] &&
        [self containsPoint:[intersector coordinate: 3]])//ad e bd
    {
        newRect.width=intersector.origin.x+intersector.width-self.origin.x;
        newRect.height=intersector.height;
        originNew=[[XYPoint alloc] init];
        originNew.x=self.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }

   
    if ([self containsPoint:[intersector coordinate: 1]] &&
        [self containsPoint:[intersector coordinate: 2]])//or e bd
    {
        newRect.width=intersector.width;
        newRect.height=self.origin.y+self.height-intersector.origin.y;
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }

   
    if ([self containsPoint:[intersector coordinate: 1]] &&
        [self containsPoint:[intersector coordinate: 4]])//or e as
    {
        newRect.width=self.origin.x+self.width-intersector.origin.x;
        newRect.height=intersector.height;
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }

    if ([self containsPoint:[intersector coordinate: 3]] &&
        [self containsPoint:[intersector coordinate: 4]])//as e ad
    {
        newRect.width=intersector.width;
        newRect.height=intersector.origin.y+intersector.height-self.origin.y;
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=self.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }

    if ([self containsPoint:[intersector coordinate: 1]])//origine
    {
        newRect.width=self.origin.x+self.width-intersector.origin.x;
        newRect.height=self.origin.y+self.height-intersector.origin.y;
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }
       else if ([self containsPoint:[intersector coordinate: 2]])//basso destra
    {
        newRect.width=intersector.origin.x+intersector.width-self.origin.x;
        newRect.height=self.origin.y+self.height-intersector.origin.y;
        originNew=[[XYPoint alloc] init];
        originNew.x=self.origin.x;
        originNew.y=intersector.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }
   

    else if ([self containsPoint:[intersector coordinate: 3]])//alto destra
    {
        newRect.width=intersector.origin.x+intersector.width-self.origin.x;
        newRect.height=intersector.origin.y+intersector.height-self.origin.y;
        originNew=[[XYPoint alloc] init];
        originNew.x=self.origin.x;
        originNew.y=self.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
       
    }

   
    else if ([self containsPoint:[intersector coordinate: 4]])//alto sinistra
    {
        newRect.width=(self.origin.x+self.width-intersector.origin.x);
        newRect.height=(intersector.origin.y+intersector.height-self.origin.y);
        originNew=[[XYPoint alloc] init];
        originNew.x=intersector.origin.x;
        originNew.y=self.origin.y;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }
   
    else
    {
        newRect.width=0;
        newRect.height=0;
        originNew=[[XYPoint alloc] init];
        originNew.x=0;
        originNew.y=0;
        [newRect setOrigin: originNew];
        NSLog(@"La nuova origine è  %i:%i",newRect.origin.x,newRect.origin.y);
        NSLog(@"La nuova area è:%ix%i = %i",newRect.width, newRect.height,newRect.width*newRect.height);
        return(newRect);
    }   
   
}

@end

Logged

"The more i know people the more i love dogs."Socrate
Pages: [1]   Go Up
Print
Jump to:  



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.