Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Площадь области, заданной граничными точками, Если область невыпуклая 
:(
    Опции темы
Governor
Дата 5.4.2013, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Есть массив граничных точек (заданных декартовыми координатами), ограничивающих некоторую область. Задача - подсчитать её площадь.

Задача осложняется тем, что внутри области могут иметься "дырки" - участки не принадлежащие области, но находящиеся внутри её внешних границ, и часть граничных точек принадлежит границе в такими "дырками", так что подсчёт методом треугольников не подходит.

Может кто-то решал уже такую задачу и есть готовое решение? Я был бы очень благодарен. 

Если кому надо - код на Delphi для решения этой задачи для выпуклых множеств методом треугольников:

Код

type bpoint = record // точка
                 angle, x,y : real;
              end;
     bounds =  array[1..10000] of bpoint;  // массив границ


var    bnds:  bounds;
       bndb: word; // число граничных точек
     
function square:double; //подсчёт площади
var
s: double; i,j:word; xmax, xmin, ymax, ymin, xx,yy, r1, r2, dr:double;
  buf:bpoint;
begin

 // поиск внутренней точки
 xmin:=1e10; ymin:=1e10; xmax:=0; ymax:=0;
 for i:=1 to bndb do
 begin
  if bnds[i].x>xmax then xmax:=bnds[i].x;
  if bnds[i].x<xmin then xmin:=bnds[i].x;
  if bnds[i].y>ymax then ymax:=bnds[i].y;
  if bnds[i].y<ymin then ymin:=bnds[i].y;
 end;
 xx:=(xmax+xmin)/2;
 yy:=(ymax+ymin)/2;


// расчёт углов к внутренней точке 
 for i:=1 to bndb do
 begin
   if bnds[i].x<>xx then
     bnds[i].angle:=2*pi*ord(bnds[i].x<xx)*ord(bnds[i].y>yy)+pi*ord(bnds[i].x>xx)+arctan((bnds[i].y-yy)/(bnds[i].x-xx))

     else if bnds[i].y>yy then bnds[i].angle:=pi/2 else bnds[i].angle:=-pi/2;
 end;


// сортировка пузырьком граничных точек по углу к внутренней точке множества
  for i:=1 to bndb-1 do
  for j:=i+1 to bndb do
   if bnds[i].angle>bnds[j].Angle then
    begin
      buf:=bnds[i];
      bnds[i]:=bnds[j];
      bnds[j]:=buf;
    end;

// подсчёт площади
 s:=0;
 for i:=2 to bndb do
 begin
  r1:=sqrt(sqr(bnds[i-1].x-xx)+sqr(bnds[i-1].y-yy));
  r2:=sqrt(sqr(bnds[i].x-xx)+sqr(bnds[i].y-yy));
  dr:=sqrt(sqr(bnds[i-1].x-bnds[i].x)+sqr(bnds[i-1].y-bnds[i].y));
  if (1>=sqr((sqr(r1)+sqr(r2)-sqr(dr))/(2*r1*r2)))  then
  s:=s+r1*r2/2*sqrt(1-sqr((sqr(r1)+sqr(r2)-sqr(dr))/(2*r1*r2)));
 end;
// замыкающий треугольник между начальной и конечной точками
 r1:=sqrt(sqr(bnds[bndb].x-xx)+sqr(bnds[bndb].y-yy));
 r2:=sqrt(sqr(bnds[1].x-xx)+sqr(bnds[1].y-yy));
 dr:=sqrt(sqr(bnds[1].x-bnds[bndb].x)+sqr(bnds[1].y-bnds[bndb].y));
 if 1>sqr((sqr(r1)+sqr(r2)-sqr(dr))/(2*r1*r2))   then
 s:=s+r1*r2/2*sqrt(1-sqr((sqr(r1)+sqr(r2)-sqr(dr))/(2*r1*r2)));
 square:=s;
end;

PM MAIL ICQ   Вверх
Akina
Дата 5.4.2013, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Точно так же решается методом треугольников. С одной разницей - перед расчётом площади начального (первого) треугольника следует убедиться, что он лежит внутри фигуры, а после расчёта его площади - вырезаешь его из фигуры, и оставшуюся фигуру обсчитываешь с самого начала.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 5.4.2013, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Akina, тогда не попадут области, принадлежащие множеству, но попадающие в те треугольники, на которые попадают "дырки" (за дырками).
PM MAIL ICQ   Вверх
Фантом
Дата 5.4.2013, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Цитата(Governor @  5.4.2013,  11:41 Найти цитируемый пост)

Задача осложняется тем, что внутри области могут иметься "дырки" - участки не принадлежащие области, но находящиеся внутри её внешних границ, и часть граничных точек принадлежит границе в такими "дырками", так что подсчёт методом треугольников не подходит.


В такой постановке Ваша задача не имеет однозначного решения. Необходима какая-то дополнительная информация. Например,  данные о том, какие подмножества точек формируют границы каких "дырок" (в предположении, что каждая дырка является выпуклой) или ограничение снизу на величину угла области или еще что-нибудь. В общем, надо брать "источник" задачи и формулировать дополнительные критерии, позволяющие сузить множество возможных решений.
PM   Вверх
Akina
Дата 5.4.2013, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Governor @  5.4.2013,  12:18 Найти цитируемый пост)
тогда не попадут области, принадлежащие множеству, но попадающие в те треугольники, на которые попадают "дырки" (за дырками). 

Этой гениальной фразы я не понял... поясни с рисунком.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 5.4.2013, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Akina

Присоединённый файл ( Кол-во скачиваний: 21 )
Присоединённый файл  дырка.JPG 14,61 Kb
PM MAIL ICQ   Вверх
Akina
Дата 5.4.2013, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Ааа... тогда у тебя не один массив граничных точек, а несколько. Кажды из них описывает свою область, один - внешний контур, остальные - внутренние.

Однако это вовсе не является проблемой. И есть даже два разных решения.

Первое. Если в случае без дырок каждый раз выбирался для обработки треугольник из трёх последовательных по контуру точек, то в случае с дырами допустимы как такой треугольник, так и треугольник с двумя соседними точками на одном контуре и одной точкой на другом контуре. При этом одиночная точка дублируется (их станет две), а контуры объединяются.

Второе. По вышеописанному алгоритму считается площадь дырки. С минусом. Дырка выбрасывается. Далее минусуется площадь второй дырки... третьей... когда все дырки посчитаны. полученная (отрицательная) площадь используется в качестве начального значения при расчёте площади внешнего контура. Дырки при этом уже не учитываются.

Само собой предполагается, что дырки не пересекаются ни друг с другом, ни с внешним контуром.

Добавлено через 6 минут и 55 секунд
Да. Дополнение к первому алгоритму.
Если было определено, что очередной построенный треугольник - внешний, то можно либо искать другой треугольник, который будет внутренним (как минимум два таких всегда есть), либо просто считать его плошадь отрицательной. Думаю, второе проще.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 5.4.2013, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Akina
Фантом

Цитата

В общем, надо брать "источник" задачи и формулировать дополнительные критерии, 


Исходная задача такая:

1. Есть карта Москвы (или любого другого города) и массив граничных точек города.
2. Есть набор конусов вращения, заданных радиусами и высотами, а также центрами оснований (несколько десятков).
3. Эти конусы как-то пересекаются друг с другом и с границами города, причём высоты и радиусы каждый час меняются. 

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

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

Добавлено через 6 минут и 1 секунду
Цитата

Само собой предполагается, что дырки не пересекаются ни друг с другом, ни с внешним контуром.


Увы, могут.
PM MAIL ICQ   Вверх
Akina
Дата 5.4.2013, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Governor @  5.4.2013,  14:43 Найти цитируемый пост)
Увы, могут. 

В таком случае сначала необходимо провести подготовку, и объединить все пересекающиеся контуры. Две дырки - в одну неправильно формы. Дырку и основной контур - в новый основной контур, с вырезом.

Да, а какая нужна точность подсчёта? а то может просто взять квадрат (прямоугольник) приличного размера (скажем 10к пикселей по каждой координате), покрасить белым, потом на него нанести в масштабе контуры города (чёрным), поверх него все твои конусы (белым), и, наконец, тупо посчитать количество оставшихся чёрных пикселей...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 5.4.2013, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Akina

Подсчёт разноцветных пикселов, конечно, интересный метод, но мне не подойдёт, хотелось бы не закрашивать области.

Добавлено через 12 минут и 39 секунд
Впрочем, вы меня натолкнули на интересную мысль, может просто разбить область на квадраты и, определив принадлежность каждого квадрата к области, суммировать их площади?
PM MAIL ICQ   Вверх
Akina
Дата 5.4.2013, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Governor @  5.4.2013,  15:24 Найти цитируемый пост)
 хотелось бы не закрашивать области.

Так не на экране же... берёшь скрытый контрол или прямо полотно - и на нём рисуешь. тебе ж не отображать, верно? ты все свои массивы, коллекции да рекордсеты ж на экране не рисуешь.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 12.4.2013, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



C "дырками" я научился бороться: 
1. При формировании массива граничных точек запоминаю к какой именно соседней областью данная  точка граничит
2. Прохожу по всем точкам, граничащим с одной и той же областью, нахожу центральную точку (полусумма минимальных и максимальных координат), упорядочиваю все эти точки по углу к центральной, и считаю максимальное расстояние между соседними точками упорядоченными таким образом. После последней точки идет первая.
3. Если максимальное расстояние между соседями меньше "эпсилон" (погрешности), то контур замкнут и мы имеем "дырку". В этом случае считаем её площадь методом треугольников, а при расчёте площади всей области этот контур не учитываем, а из общей площади вычитаем площадь дырки.

Всё хорошо работает, пока контур замкнут. Но если он хотя бы немного не замкнут, то это уже не срабатывает, а сильная невыпуклость области вызывает сильную ошибку в методе треугольников. 

Придётся, наверное, всё-таки считать пикселы.
PM MAIL ICQ   Вверх
Akina
Дата 12.4.2013, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Governor @  12.4.2013,  15:10 Найти цитируемый пост)
если он хотя бы немного не замкнут

Нельзя быть немножко беременной.

Цитата(Governor @  5.4.2013,  11:41 Найти цитируемый пост)
Задача - подсчитать её площадь.

Площадь бывает только у замкнутой фигуры. И неважно, с дырками или без.

Цитата(Governor @  12.4.2013,  15:10 Найти цитируемый пост)
нахожу центральную точку (полусумма минимальных и максимальных координат), 

Это центр масс. И в твоём случае он не имееет ровным счётом никакого смысла, ни физического, ни математического.

Цитата(Governor @  12.4.2013,  15:10 Найти цитируемый пост)
упорядочиваю все эти точки по углу к центральной, и считаю максимальное расстояние между соседними точками упорядоченными таким образом.

А в чём смысл? Порядок точек в контуре не имеет ничего общего с полученным после сортировки порядком.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Governor
Дата 16.5.2013, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.4.2005
Где: Москва

Репутация: нет
Всего: нет



Akina

Цитата

Площадь бывает только у замкнутой фигуры. И неважно, с дырками или без.


Разумеется, речь идёт о контуре "дырки". Внутри замкнутого контура может быть "дырка" незамкнутого контура. Общий контур при этом будет замкнутым и будет иметь площадь.

Вот, сделал подсчёт пикселей, как вы предлагали:

Код

var bounds:array[byte] of TPoint;

procedure TForm1.Button1Click(Sender: TObject);
var i,n:byte; maxx,minx,maxy,miny,x0,y0:word;  maxx_y:word;
    ii,jj:word;   nnn:longint;  Rect:TRect;
begin

// очистка холста

  Rect.Left:=0;   Rect.Top:=0;
  Rect.Right:=Image1.width;
  Rect.bottom:=Image1.Height;
  image1.Canvas.Brush.Color:=clwhite;
  Image1.Canvas.FillRect(Rect);


// считывание данных

 n:=0;
 for i:=1 to StringGrid1.RowCount-1 do
 if StringGrid1.cells[0,i]<>'' then
 begin
  bounds[i].x:=Strtoint(StringGrid1.cells[0,i]);
  bounds[i].y:=Strtoint(StringGrid1.cells[1,i]);
  inc(n);
 end
 else break;

// прорисовка контура

 image1.canvas.MoveTo(bounds[1].x, bounds[1].y);
 for i:=2 to n do
  image1.canvas.LineTo(bounds[i].x, bounds[i].y);

 image1.canvas.LineTo(bounds[1].x, bounds[1].y);

// поиск внутренней точки и описанного прямоугольника 

 maxx:=0; maxy:=0; minx:=image1.width; miny:=image1.height;

 for i:=1 to n do
  begin
   if bounds[i].x>maxx then maxx:=bounds[i].x;
   if bounds[i].y>maxy then maxy:=bounds[i].y;
   if bounds[i].x<minx then minx:=bounds[i].x;
   if bounds[i].y<miny then miny:=bounds[i].y;
  end;

 for ii:=minx to maxx do
 if image1.Canvas.Pixels[ii, (miny+maxy)div 2] = clblack then
  begin
   x0:=ii+2;
   y0:=(miny+maxy)div 2;
   break
  end;



// заливка площади, ограниченной чёрным контуром

 image1.Canvas.Brush.Color:=clgreen;
 image1.Canvas.FloodFill(X0, Y0, clblack, fsBorder);


// подсчёт окрашенных пикселей
 nnn:=0;
 for ii:=minx to maxx do
  for jj:=miny to maxy do
   if  image1.Canvas.Pixels[ii, jj] = clGreen then
    inc(nnn);

// вывод результата

 label2.Caption:=inttostr(nnn);

end;


Тонкий момент - поиск внутренней точки. Предполагает, что область связная.

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

Это сообщение отредактировал(а) Governor - 16.5.2013, 14:05
PM MAIL ICQ   Вверх
Akina
Дата 16.5.2013, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Governor @  16.5.2013,  15:01 Найти цитируемый пост)
Внутри замкнутого контура может быть "дырка" незамкнутого контура.

Ты думай, что говоришь-то... или хотя бы попробуй нарисовать... если это дырка - она замкнута, а если незамкнута - это просто полилиния, площадь которой нулевая.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0968 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.