How to calculate rect lines from N fields filling the length L with space S between them

This problem should have been solved a million times, but Google was not my friend.

I need to programmatically place a set of boxes to fill a certain length and be separated by a certain distance.

This is what I want:

alt text http://img257.imageshack.us/img257/3362/spacingiwant.png

Here is what I get:

alt text http://img194.imageshack.us/img194/3506/spacingiget.png

Since I work in Objective-C using Core Graphics, I need a series of Rects that I can draw or swing an image into. My naive attempt draws a set of boxes at a certain interval, but leaves space at the end.

Here is my code that is in the drawRect method: method

CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat barStartX = 96; CGFloat barStartY = 64.0; CGFloat barWidth = 16; CGFloat barHeight = 64; CGFloat barGutter = 8; int barSegments = 8; for (int segmentNumber = 0; segmentNumber <= (barSegments - 1); ++segmentNumber) { // get the box rect CGRect segment = CGRectMake(barStartX + (barWidth * segmentNumber), barStartY , barWidth - barGutter, barHeight); // plot box CGContextFillRect(context, segment); } 

Before creating an impenetrable monster of a one-time code that I don’t even understand in 6 months, I wonder if there is a general solution to this problem with an interval.

The answer does not have to be in Objective-C if it is somewhat similar to C. Readability takes precedence over performance considerations.

+4
source share
4 answers

I think that, despite your efforts, this question is a bit unclear. Here is my attempt.

The equation you describe in the title is as follows:

 N*x + (N-1)*S = L 

The solution, which for x gives us the width needed for each window:

 x = (L - (N-1)*S) / N 

This will cause the code to look something like this:

 CGContextRef context = UIGraphicsGetCurrentContext(); int barSegments = 8; CGFloat barStartX = 96; CGFloat barStartY = 64.0; CGFloat barTotalWidth = 196.0; CGFloat barHeight = 64; CGFloat barGutter = 8; CGFloat barWidth = (barTotalWidth - (barSegments-1)*barGutter) / barSegments; for (int segmentNumber = 0; segmentNumber < barSegments; ++segmentNumber) { // get the box rect CGRect segment = CGRectMake(barStartX + ((barWidth + barGutter) * segmentNumber), barStartY , barWidth, barHeight); // plot box CGContextFillRect(context, segment); } 
+4
source

Given n fields of width w and interval s, the total length will be:

l = n Γ— w + ( n -1) Γ— s

You know all the variables. The same formula can be used to place an arbitrary field. The diagram shows that the length coincides with the coordinate of the right edge of the final field. So you can just use n of 1 to find the right edge of all your boxes. Finding the left edge of this is trivial: subtract w, add 1 (as a field from 80 to 80 has a width of 1px).

Note that n is counted from 1, not 0. You can change the formula, of course, to count from 0.

+2
source

I would do something like this:

 CGFloat barStartX = 96; CGFloat barStartY = 64.0; CGFloat barWidth = 128; CGFloat barHeight = 64; ... int numSegments = 8; // number of segments CGFloat spacing = 8; // spacing between segments CGFloat segmentWidth = (barWidth - spacing*(numSegments - 1)) / numSegments; CGRect segmentRect = CGRectMake(barStartX, barStartY, segmentWidth, barHeight); for (int segmentNumber = 0; segmentNumber < numSegments; segmentNumber++) { segmentRect.origin.x = segmentNumber*(segmentWidth + spacing); CGContextFillRect(context, segmentRect); } 

I like to define the rectangle outside the loop, and then in the loop only update the properties of the rectangle, which actually change. In this case, only the x coordinate changes each time, so the cycle becomes quite simple.

+1
source

Draw the blue and pink rectangles separately and draw the last blue rectangle :) (or not draw the last pink)

0
source

All Articles