Turn two CGPoints into a CGRect
Asked Answered
Z

7

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?

Zeralda answered 11/11, 2011 at 22:41 Comment(0)
C
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.

Conqueror answered 11/11, 2011 at 22:48 Comment(5)
Nice solution, I would change fabs to fabsf for more strict type matching.Antistrophe
@nacross: Good note, but do be aware that when compiling for 64 bit, CGFloats are double size, not float size, so you'd lose information if you used fabsf.Conqueror
r will not contain either of the points offered in the question. ACGRect's maxX and maxY are not included in the rectangle, and points along those boundaries will fail CGRectContainsPointResinoid
@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).Conqueror
@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.Resinoid
M
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));

Microsporangium answered 8/11, 2012 at 22:15 Comment(0)
W
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))
    }
}
Williamsen answered 8/4, 2019 at 15:3 Comment(0)
W
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));
Wondawonder answered 11/11, 2011 at 22:46 Comment(1)
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.Conqueror
B
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;
}
Balsaminaceous answered 12/12, 2012 at 13:30 Comment(0)
M
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);
Monophonic answered 11/11, 2011 at 22:48 Comment(0)
Y
1
let r0 = CGRect(origin: p0, size: .zero)
let r1 = CGRect(origin: p1, size: .zero)
let rect = r0.union(r1).standardized
Ygerne answered 18/11, 2021 at 17:21 Comment(2)
Please add more information that may be useful for a future reader.Amari
union makes rectangle from two rects. So, make two zero size rect from point. standardized is optional. This method convert rect to normal.Ygerne

© 2022 - 2024 — McMap. All rights reserved.