23

How can I, given two different CGPoints, turn them into an CGRect?

Example:

CGPoint p1 = CGPointMake(0,10);
CGPoint p2 = CGPointMake(10,0);

How can I turn this into a CGRect?

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
christo16
  • 4,843
  • 5
  • 42
  • 53

7 Answers7

52

This will take two arbitrary points and give you the CGRect that has them as opposite corners.

CGRect r = CGRectMake(MIN(p1.x, p2.x), 
                      MIN(p1.y, p2.y), 
                      fabs(p1.x - p2.x), 
                      fabs(p1.y - p2.y));

The smaller x value paired with the smaller y value will always be the origin of the rect (first two arguments). The absolute value of the difference between x values will be the width, and between y values the height.

Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
  • Nice solution, I would change fabs to fabsf for more strict type matching. – nacross Oct 18 '13 at 07:28
  • 1
    @nacross: Good note, but do be aware that when compiling for 64 bit, `CGFloat`s are double size, not float size, so you'd lose information if you used `fabsf`. – Ben Zotto Oct 18 '13 at 22:24
  • `r` will not contain either of the points offered in the question. A`CGRect`'s `maxX` and `maxY` are *not* included in the rectangle, and points along those boundaries will fail `CGRectContainsPoint` – Christopher Swasey Apr 19 '16 at 16:27
  • @ChristopherSwasey: I've tweaked the answer to avoid misleading on this point (thanks) although note that this is not necessarily true: if one of the given points is the origin, it is "contained". This is a useful comment but only matters if you care about that (it seems unlikely that the OP did). – Ben Zotto Apr 21 '16 at 03:40
  • @BenZotto Indeed, if one of the points is the origin it will be contained, but any other corner will not—but neither of the points in the question were the origin. Where it will have a real effect is using this method as part of drawing code—that will result in a rectangle a point too small in at least one dimension. – Christopher Swasey Apr 25 '16 at 18:12
10

A slight modification of Ken's answer. Let CGGeometry "standardize" the rect for you.

CGRect rect = CGRectStandardize(CGRectMake(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y));

David H
  • 40,852
  • 12
  • 92
  • 138
colinta
  • 3,536
  • 1
  • 28
  • 18
6

Swift extension:

extension CGRect {
    init(p1: CGPoint, p2: CGPoint) {
        self.init(x: min(p1.x, p2.x),
                  y: min(p1.y, p2.y),
                  width: abs(p1.x - p2.x),
                  height: abs(p1.y - p2.y))
    }
}
kelin
  • 11,323
  • 6
  • 67
  • 104
4

This function takes any number of CGPoints and gives you the smallest CGRect back.

CGRect CGRectSmallestWithCGPoints(CGPoint pointsArray[], int numberOfPoints)
{
    CGFloat greatestXValue = pointsArray[0].x;
    CGFloat greatestYValue = pointsArray[0].y;
    CGFloat smallestXValue = pointsArray[0].x;
    CGFloat smallestYValue = pointsArray[0].y;

    for(int i = 1; i < numberOfPoints; i++)
    {
        CGPoint point = pointsArray[i];
        greatestXValue = MAX(greatestXValue, point.x);
        greatestYValue = MAX(greatestYValue, point.y);
        smallestXValue = MIN(smallestXValue, point.x);
        smallestYValue = MIN(smallestYValue, point.y);
    }

    CGRect rect;
    rect.origin = CGPointMake(smallestXValue, smallestYValue);
    rect.size.width = greatestXValue - smallestXValue;
    rect.size.height = greatestYValue - smallestYValue;

    return rect;
}
hfossli
  • 22,616
  • 10
  • 116
  • 130
4

Assuming p1 is the origin and the other point is the opposite corner of a rectangle, you could do this:

CGRect rect = CGRectMake(p1.x, p1.y,  fabs(p2.x-p1.x), fabs(p2.y-p1.y));
Ken Aspeslagh
  • 11,484
  • 2
  • 36
  • 42
  • If you already know that p1 is the origin (it's not in the OP's example), you don't need the `fabs`. But then you're kind of making the caller do the hard work in advance. – Ben Zotto Nov 11 '11 at 22:56
1
let r0 = CGRect(origin: p0, size: .zero)
let r1 = CGRect(origin: p1, size: .zero)
let rect = r0.union(r1).standardized
noppe
  • 65
  • 1
  • 7
  • Please add more information that may be useful for a future reader. – nurchi Nov 19 '21 at 16:11
  • `union` makes rectangle from two rects. So, make two zero size rect from point. `standardized ` is optional. This method convert rect to normal. – noppe Nov 21 '21 at 11:22
1

This will return a rect of width or height 0 if the two points are on a line

float x,y,h,w;
if (p1.x > p2.x) {
    x = p2.x;
    w = p1.x-p2.x;
} else {
    x = p1.x;
    w = p2.x-p1.x;
}
if (p1.y > p2.y) {
    y = p2.y;
    h = p1.y-p2.y;
} else {
    y = p1.y;
    h = p2.y-p1.y;
}

CGRect newRect = CGRectMake(x,y,w,h);
Jesse Black
  • 7,966
  • 3
  • 34
  • 45