Как вычислить Rect ряда из N блоков, заполняющих длину L с интервалом S между ними - PullRequest
4 голосов
/ 18 июля 2009

Эта проблема должна быть решена миллион раз, но Google не был моим другом.

Мне нужно программно разделить набор полей, чтобы заполнить определенную длину и быть разделенными определенным расстоянием.

Вот что я хочу:

альтернативный текст http://img257.imageshack.us/img257/3362/spacingiwant.png

Вот что я получаю:

альтернативный текст http://img194.imageshack.us/img194/3506/spacingiget.png

Поскольку я работаю в Objective-C с использованием Core Graphics, мне нужна серия Rects, в которые я могу нарисовать или перетащить изображение. Моя наивная попытка нарисовать набор ящиков с определенным интервалом, но в конце оставить пробел.

Вот мой код, который находится в drawRect: метод

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);
}

Прежде чем я создам непроницаемую монструозность одноразового кода, которую даже через 6 месяцев я не пойму, мне интересно, есть ли общее решение этой проблемы пробелов.

Ответ не обязательно должен быть в Objective-C, если он в некоторой степени похож на C. Читабельность имеет приоритет перед соображениями производительности.

Ответы [ 4 ]

4 голосов
/ 18 июля 2009

Я думаю, что, несмотря на ваши усилия, этот вопрос немного неясен. Вот моя попытка.

Уравнение, которое вы описываете в заголовке:

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

Решение этого для x дает нам ширину, необходимую для каждой коробки:

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

Это приведет к тому, что код будет примерно таким:

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);
}
2 голосов
/ 18 июля 2009

Учитывая n коробки шириной w и расстоянием s , общая длина будет:

l = n × w + ( n -1) × s

Вы знаете все переменные. Эту же формулу можно использовать для размещения произвольного поля. Из вашей диаграммы мы видим, что длина совпадает с координатой правого края последнего блока. Таким образом, вы можете просто использовать n от 1 до любого, чтобы найти правый край всех ваших ящиков. Найти левый край из этого тривиально: вычтите w , добавьте 1 (поскольку поле от 80 до 80 имеет ширину 1px).

Обратите внимание, что n считается от 1, а не от 0. Вы можете изменить формулу, конечно, чтобы считать от 0.

1 голос
/ 18 июля 2009

Я бы сделал что-то вроде этого:

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);
}

Мне нравится определять прямоугольник вне цикла, а затем в цикле обновлять только те свойства прямоугольника, которые действительно меняются. В этом случае только координата x меняется каждый раз, поэтому цикл становится довольно простым.

0 голосов
/ 18 июля 2009

Нарисуйте синий и розовый прямоугольники отдельно и нарисуйте последний синий прямоугольник :) (или не рисуйте последний розовый)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...