Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/18: Рейтинг темы: голосов - 18, средняя оценка - 4.78
2 / 2 / 2
Регистрация: 21.07.2015
Сообщений: 36
1

Сумма площадей прямоугольников с учетом их пересечения

19.09.2015, 01:23. Показов 3525. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть плоскость (поле) 1000х1000. В нем задаются N прямоугольников (каждый 4-мя точками). Необходимо рассчитать суммарную площадь всех прямоугольников с учетом их пересечений. При чем в одной области могут пересекаться несколько прямоугольников.

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

Помогите придумать алгоритм, поиск ничего подобного не выдал.

П.с. Все прямоугольники параллельны осям координат.

Добавлено через 2 часа 41 минуту
Очевидно, речь о использовании формулы включений-исключений, но только как это все формализовать?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.09.2015, 01:23
Ответы с готовыми решениями:

Нахождение площадей пересечения случайных прямоугольников
Предположим у меня есть некоторое количество прямоугольников (точек x;y которые образуют...

Нахождения площадей всех прямоугольников с заданным полупериметром P
составить программу на С++ нахождения площадей всех прямоугольников с заданным полупериметром...

Посчитать сумму площадей двух прямоугольников, стороны которых заданы
Надо посчитать суму площадей двух прямоугольников, стороны которых заданы. Но посчитать надо...

Написать функции для вычисления площадей кругов, прямоугольников и треугольников
Написать функции для вычисления площадей кругов, прямоугольников и треугольников.

11
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
19.09.2015, 08:48 2
Лучше сказать "найти площадь покрываемую всеми пр-ками". Простое решение: берем пр-к, добавляем его плошадь и от нее отнимаем площади пересечений со всеми предыдущими пр-ками. Это квадратичный перебор, т.е. плохая скорость.

Более сложное (но и более скоростное) решение: на исходное поле наложить сетку, напр 10x10. Идти по всем пр-кам, искать какие клетки они пересекают и подсчитывать покрываемые площади в каждой клетке. Если оказалось что клетка полностью покрыта - дальнейшие проверки для нее опускаем.
0
Модератор
Эксперт функциональных языков программирования
3051 / 2193 / 459
Регистрация: 26.03.2015
Сообщений: 8,472
19.09.2015, 14:53 3
Цитата Сообщение от Igor3D Посмотреть сообщение
и от нее отнимаем площади пересечений со всеми предыдущими пр-ками
как её искать?
ведь это, практически, исходная задача

Добавлено через 42 минуты
Пока мне приходит в голову только замена прямоугольников на набор непересекающихся прямоугольников.
Нужно аккуратно выписать все виды пересечения и для каждого задать набор результирующих прямоугольников (от 1 до 3, вроде бы).

Добавлено через 25 минут
Цитата Сообщение от NikBond Посмотреть сообщение
Координаты точек прямоугольников могут быть десятичными дробями, поэтому просто выразить поле через матрицу, по видимому, не выйдет.
У Вас есть набор координат x и набор координат y. Нанесите их на поле - и получите "матрицу". Возможно, это самый быстрый способ.
0
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
20.09.2015, 09:44 4
Цитата Сообщение от Shamil1 Посмотреть сообщение
как её искать?
ведь это, практически, исходная задача
Да, верно. Это для 2 все просто, а для большего числа отнимаемое значение могло быть уже отнято предыдущим (только "дошло" ).

Цитата Сообщение от Shamil1 Посмотреть сообщение
У Вас есть набор координат x и набор координат y. Нанесите их на поле - и получите "матрицу". Возможно, это самый быстрый способ.
Ну и что дальше делать с этой матрицей?

Наверное так: каждая строка и каждый столбец хранят список своих пр-ков. Смысл в том что элемент матрицы (образованный текущими строкой и столбцом) или полностью покрывается или полностью нет. Проверяем все пр-ки принадлежащие текущей строке и столбцу + следующей строке и столбцу. Если эл-т никем не покрыт - добавляем его площадь в рез-т

Добавлено через 1 час 45 минут
Точнее так: каждая строка/столбец хранят список всех пр-ков покрывающих хотя бы часть данной строки/столбца. Тогда эл-т матрицы покрыт если найдется хотя бы 1 пр-к покрывающий и строку и столбец.
0
Модератор
Эксперт функциональных языков программирования
3051 / 2193 / 459
Регистрация: 26.03.2015
Сообщений: 8,472
20.09.2015, 11:59 5
Цитата Сообщение от Igor3D Посмотреть сообщение
Ну и что дальше делать с этой матрицей?
1. У нас есть два отсортированных массива с границами (по одному для каждой координаты).
2. Для каждого прямоугольника "закрашиваем" клетки матрицы, которые лежат внутри него.
3. Суммируем площади закрашенных клеток.

Примерно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
double CalcSquare(List<Rect> rects)
{
    // 1. У нас есть два отсортированных массива с границами (по одному для каждой координаты).
    double[] xlimits = rects.Select(p => p.TopLeft.X).Concat(rects.Select(p => p.BottomRight.X)).Distinct().OrderBy(x => x).ToArray();
    double[] ylimits = rects.Select(p => p.TopLeft.Y).Concat(rects.Select(p => p.BottomRight.Y)).Distinct().OrderBy(x => x).ToArray();
    
    // 2. Для каждого прямоугольника "закрашиваем" клетки матрицы, которые лежат внутри него.
    bool[,] matrix = new bool[xlimits.Length - 1, ylimits.Length - 1];
    foreach(Rect rect in rects)
    {
        int imin = Array.BinarySearch(xlimits, rect.TopLeft.X);
        int imax = Array.BinarySearch(xlimits, rect.BottomRight.X);
        int jmin = Array.BinarySearch(ylimits, rect.TopLeft.Y);
        int jmax = Array.BinarySearch(ylimits, rect.BottomRight.Y);
        
        for(int i = imin; i < imax; i++)
            for(int j = jmin; j < jmax; j++)
                matrix[i, j] = true;
    }
    
    // 3. Суммируем площади закрашенных клеток.
    double square = 0;
    for(int i = 0; i < xlimits.Length - 1; i++)
    {
        double width = xlimits[i+1] - xlimits[i];
        double height = 0;
        for(int j = 0; j < ylimits.Length - 1; j++)
            if(matrix[i,j])
                height += ylimits[j+1] - ylimits[j];
        square += width * height;
    }
    return square;
}
 
 
public struct Rect
{
    public Point TopLeft;
    public Point BottomRight;
}
 
public struct Point
{
    public double X;
    public double Y;
}
Добавлено через 23 минуты
Массивы границ можно вычислить примерно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Tuple<double[], double[]> GetLimits(List<Rect> rects)
{
    double[] xlimits = new double[rects.Count * 2];
    double[] ylimits = new double[rects.Count * 2];
    
    int i = 0;
    foreach(Rect rect in rects)
    {
        xlimits[i] = rect.TopLeft.X;
        ylimits[i++] = rect.TopLeft.Y;
        xlimits[i] = rect.BottomRight.X;
        ylimits[i++] = rect.BottomRight.Y;
    }
    Array.Sort(xlimits);
    Array.Sort(ylimits);
    
    int i1 = 1, j1 = 1;
    for(int k = 1; k < xlimits.Length; k++)
    {
        if(xlimits[k] != xlimits[k-1])
            xlimits[i1++] = xlimits[k];
        if(ylimits[k] != ylimits[k-1])
            ylimits[j1++] = ylimits[k];
    }
    Array.Resize(ref xlimits, i1);
    Array.Resize(ref ylimits, j1);
 
    return Tuple.Create(xlimits, ylimits);
}
p.s. Код я не запускал, так что возможны опечатки.
0
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
20.09.2015, 13:15 6
Может чуть техничнее обойтись без binary_search (напр сохранить индексы в самих пр-ках).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
struct Rect {
 float x0, y0, x1, y1;
 int index_x0, index_y0, index_x1, index_y1;
};
 
struct RVal {
 RVal( float _val, int * _index) : val(_val), index(_index) {}
 bool operator < ( const RVal & sec ) const { return val < sec.val; }
 
 float val;
 int * index;
};
 
typedef std::vector <Rect> TRectVec;
typedef std::vector <RVal> TRValVec;
 
void BuildRanges( TRectVec & rect, TRValVec & rx, TRValVec & ry )
{
 for (size_t i = 0; i < rect.size(); ++i) {
  Rect r = rect[i];
  rx.push_back(RVal(r.x0, &r.index_x0); 
  rx.push_back(RVal(r.x1, &r.index_x1); 
 
  ry.push_back(RVal(r.y0, &r.index_y0); 
  ry.push_back(RVal(r.y1, &r.index_y1); 
 }
 
// sort
 std::sort(rx.begin(), rx.end());
 std::sort(ry.begin(), ry.end());
 
// pack 
 for (int i = 0; i < 2; ++i) {
  TRValVec & dst = i ? ry : rx;
  size_t place = 0;
  for (size_t i = 0; i < dst.size(); ++i) {
   *dst[i].index = place;
   if (dst[i].val == dst[place].val) continue;
   ++place;
   if (i != place) dst[place] = dst[i];
   *dst[place].index = place;
  }  
  dst.resize(place);
 }
}
0
Модератор
Эксперт функциональных языков программирования
3051 / 2193 / 459
Регистрация: 26.03.2015
Сообщений: 8,472
20.09.2015, 14:51 7
Цитата Сообщение от Igor3D Посмотреть сообщение
Может чуть техничнее обойтись без binary_search (напр сохранить индексы в самих пр-ках).
Не понял, как можно хранить индексы в прямоугольниках. И смысла приведённого кода тоже не понял.

Без BinarySearch обойтись можно. Например, поместить границы в словарь (хеш-таблицу).
C#
1
Dictionary<double,int> xdict = xlimits.Select((x,i) => new {x,i}).ToDictionary(p => p.x, p => p.i);
0
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
20.09.2015, 15:33 8
Цитата Сообщение от Shamil1 Посмотреть сообщение
Не понял, как можно хранить индексы в прямоугольниках. И смысла приведённого кода тоже не понял.
Эл-т массива/контейнера границ xранит указатель на то "из чего он был создан" (мин x, и.т.д). Когда индекс границы уже определен, он вписывается по этому указателю. А сами значения (на которые указывают указатели) сидят в пр-ках
0
Модератор
Эксперт функциональных языков программирования
3051 / 2193 / 459
Регистрация: 26.03.2015
Сообщений: 8,472
20.09.2015, 18:54 9
Igor3D,
Пусть у Вас есть два прямоугольника с одинаковыми x0. Если я правильно понимаю, index_x0 в них имеют разные адреса. На который из них будет ссылаться index в элементе массива границ (RVal), val которого равен этим x0?
0
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
21.09.2015, 08:12 10
Цитата Сообщение от Shamil1 Посмотреть сообщение
Пусть у Вас есть два прямоугольника с одинаковыми x0. Если я правильно понимаю, index_x0 в них имеют разные адреса. На который из них будет ссылаться index в элементе массива границ (RVal), val которого равен этим x0?
В готовом массиве границ указывает на index_x0 одного из пр-ков (какого - зависит от сортировки). Но это неважно, когда массив готов, то указатели уже не нужны, пр-ки имеют готовые индексы.

При создании RVal(ы) указывают на поля index_x0 каждый в своем пр-ке (из которого этот RVal создан). Когда массив RVal пакуется в оба пр-ка запишется одинаковое значение index_x0.

Не по теме:


Наверное работаете на языках без указателей :)

0
Модератор
Эксперт функциональных языков программирования
3051 / 2193 / 459
Регистрация: 26.03.2015
Сообщений: 8,472
21.09.2015, 17:01 11
Да, нет. Просто у Вас логика запутана. Вы сначала задаёте индекс (в большинстве случаев - неправильно), а потом проверяете, правильно ли Вы его задали. Если неправильно, то, не доделав одну задачу ("задать индекс"), переходите к другой ("сдвинуть элемент"). Причём, не ясно, зачем сдвигать элементы в массиве, если в дальнейшем Вы не собираетесь использовать этот массив. И только после этого Вы устанавливаете правильное значение (обращаясь к элементу по новому индексу в массиве).
0
1824 / 732 / 99
Регистрация: 01.10.2012
Сообщений: 3,749
21.09.2015, 18:03 12
Цитата Сообщение от Shamil1 Посмотреть сообщение
Да, нет. Просто у Вас логика запутана. Вы сначала задаёте индекс (в большинстве случаев - неправильно), а потом проверяете, правильно ли Вы его задали. Если неправильно, то, не доделав одну задачу ("задать индекс"), переходите к другой ("сдвинуть элемент"). Причём, не ясно, зачем сдвигать элементы в массиве, если в дальнейшем Вы не собираетесь использовать этот массив. И только после этого Вы устанавливаете правильное значение (обращаясь к элементу по новому индексу в массиве).
Как же не собираюсь? rx(y) - это то же что у Вас x(y)limits, они нужны для подсчета площадей. А вот здесь ошибка
C++
1
dst.resize(place);  // правильно place + 1
1
21.09.2015, 18:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.09.2015, 18:03
Помогаю со студенческими работами здесь

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

Площадь пересечения прямоугольников
Прямоугольники на плоскости заданы координатами противоположных вершин. Необходимо рассчитать...

Площадь пересечения прямоугольников
Здравствуйте. Мне нужно найти площадь пересечения двух прямоугольников, если известны координаты...

Определить точки пересечения прямоугольников
Добрый день. Допустим имеем два прямоугольника, нужно определить их касание ( имея координаты их...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru