Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 24-12-2010 05:18 » |
|
Имеется вот такая задача: определить направление (по ЧС или против ЧС), в котором были введены вершины полигона. Собственно, нужено чётко различить знак, а само понятие направления тут довольно условно. Вводится полигон так: мышью щёлкаем по окну, вводя последовательно точки-вершины. Я по своим догадкам попытался решить так (но, видимо, неправильно): беру первую вершину в качестве начала всех радиус-векторов, затем считаю сумму векторных произведений для всех смежных пар векторов по очереди. Каждый вектор суммы имеет знак в зависимости от направления вращения первого вектора ко второму, а чтобы не учитывалась длина исходных векторов, вектор-результат для каждой пары делится на произведение их модулей - как-будто полигон состоит из единичных векторов (хотя, не полностью уверен, что правильно так поступать). Все значения векторных произведений суммирую, получается итоговый "момент", по его знаку различаю направление ввода полигона алгоритм , похоже, неверный, так как правильно знак определяется через раз опять же, что делать с вершинами, совпавшими с первой. Сейчас я их просто игнорирую при суммировании вот код: //определить, по часовой стрелке направление или нет bool CGrafics::Poligon_GetDirIsClock(CPoint* points,int count)const { if(!points || count<3)return true;
//считаем первую точку началом радиус-вектора const LONG& x0=points[0].x; const LONG& y0=points[0].y;
//остальные вершины представляют собой концы радиус-вектора // для всех по очереди считаем векторное произведение // и суммируем со знаком double vecSumm=0;
LONG x1=points[1].x; LONG y1=points[1].y;
for(int i=2;i<count; i++) { LONG x2=points[i].x; LONG y2=points[i].y;
if(x1==x0 && y1==y0 || x2==x0 && y2==y0) { //одна из точек совпала с начальной точкой } else { //модуль вектора поворота надо будет разделить на произведения //модулей векторов, чтобы не учитывалась длина векторов LONG module1=sqrtl((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)); LONG module2=sqrtl((x2-x0)*(x2-x0)+(y2-y0)*(y2-y0));
if(module1 && module2) { vecSumm+=(x1*y2-y1*x2)*1.0/(module1*module2); } }
x1=x2; y1=y2; }
//знак суммы покажет направление вращения return vecSumm>0; }
Подскажите, кто знает, по какому алгоритму определить направление ввода полигона
|
|
« Последнее редактирование: 24-12-2010 05:20 от Алексей1153++ »
|
Записан
|
|
|
|
Dale
|
|
« Ответ #1 : 24-12-2010 06:44 » |
|
Есть такая книга "Математика и САПР", двухтомник, написали несколько французов.
Там есть формула для вычисления площади полигона по координатам вершин. В качестве побочного эффекта эта формула дает направление обхода контура - от него зависит знак результата.
Посмотреть смогу только дома, вряд ли она есть у меня на работе в виде скана.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 24-12-2010 07:27 » |
|
Dale, если не трудно, посмотри. Очень сильно нужно. Хотя бы странички с этим методом. Спасибо заранее )
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #3 : 24-12-2010 17:18 » |
|
"Математика и САПР", Москва, "Мир", 1988, стр. 15:
A = 1/2*S(xi*yi+1 - xi+1*yi) + xN*y1 - x1*yN
Знак S означает "сумма по i от 1 до N-1".
Знак площади зависит от направления обхода контура. В правой системе координат положительный знак указывает направление против часовой стрелки.
P.S. Я бы на всякий случай проверил эту формулу. Книгу читал давным-давно, выводил формулу сам, но уже не помню, совпала ли с книгой. Скопировал полностью, но интуиция подсказывает, что на 2 следует делить все выражение.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 24-12-2010 17:41 » |
|
Dale, Спасибо огромное Причём по правильности на правду больше похожа формула A = S(xi*yi+1 - xi+1*yi) + xN*y1 - x1*yN - ведь мне только знак нужен. Так что, всё-таки, деление на 2 - общее
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #5 : 24-12-2010 18:08 » |
|
Если нужен только знак, конечно, можно обойтись и без деления. Хоть и мизерная, но экономия.
Помнится, я еще при практической реализации дублировал первую точку, добавляя ее в конец списка. Тогда можно обойтись одним циклом, выкинув из формулы два последних слагаемых.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 24-12-2010 18:32 » |
|
Dale, а я после цикла сделал хвостик с i и 0 индексами. А можно наоборот - до цикла сделать
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #7 : 27-12-2010 01:59 » |
|
Алексей1153++, для ускорения, можно проанализировать знак только для первых 3 точек полигона, не лежащих на одной прямой( S > 0)..
|
|
« Последнее редактирование: 27-12-2010 02:05 от sss »
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #8 : 27-12-2010 07:00 » |
|
Три отдельно взятые точки ничего не говорят о направлении контура в целом.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #9 : 27-12-2010 08:33 » |
|
Dale, гм.. поспорим? Почему не значат... Первый же входящий треугольник имеет направление обхода.. Если у последующих треугольников направление измениться - значит нет однозначности в определении обхода всего полигона..
Да... И почему именно три отдельно взятые? Последовательные по порядку точки конечно же..
|
|
« Последнее редактирование: 27-12-2010 08:36 от sss »
|
Записан
|
while (8==8)
|
|
|
sss
Специалист
Offline
|
|
« Ответ #10 : 27-12-2010 08:46 » |
|
Решил все таки показать свой код.. #define EPSYLON ((real) 0.000000001)
typedef double real;
// Множество осей enum CoordsAxis { xAxis = 0, yAxis, zAxis};
// Направления обхода enum PolygonDetourMode{ dmAuto = 0, dmCW, dmCCW};
PolygonDetourMode CPolygon::DetectDetour( CoordsAxis a1, CoordsAxis a2) const throw ( EMathsssError*) { CVertexPair side; VERTEX Triangle[3]; real a1_d1, a1_d2, a2_d1, a2_d2, r, minL, t; bool bCW( false), bCCW( false);
for ( long lIdx = 0; lIdx < m_lCount; lIdx++) { for ( long i = 0; i < 3; i++) Triangle[i] = m_pVertexes[(lIdx + i) % m_lCount];
//Выяснение "масштаба нуля" side.V[0] = Triangle[0]; side.V[1] = Triangle[1]; minL = side.Length;
side.V[0] = Triangle[1]; side.V[1] = Triangle[2]; t = side.Length; if ( t < minL) minL = t;
side.V[0] = Triangle[2]; side.V[1] = Triangle[0]; t = side.Length; if ( t < minL) minL = t; minL *= EPSYLON;
a1_d1 = Triangle[1].Coords[a1] - Triangle[0].Coords[a1]; a2_d1 = Triangle[1].Coords[a2] - Triangle[0].Coords[a2];
a1_d2 = Triangle[2].Coords[a1] - Triangle[1].Coords[a1]; a2_d2 = Triangle[2].Coords[a2] - Triangle[1].Coords[a2]; r = (a1_d1 * a2_d2) - (a1_d2 * a2_d1);
if ( fabs( r) > fabs( minL)) //Засчитываем попытку { if ( r < 0) { if ( bCCW) { throw new __EMathsssError( ERROR_DETOUR_DETECT_FAILED); } bCW = true; } else { if ( bCW) throw new __EMathsssError( ERROR_DETOUR_DETECT_FAILED); bCCW = true; } } } if ( bCW) return dmCW; else if ( bCCW) return dmCCW; throw new __EMathsssError( ERROR_DETOUR_DETECT_FAILED); }
P.S.: Некоторые сложности с выяснением "масштаба нуля" возникают при реальных измерениях огромных полигонов..
|
|
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #11 : 27-12-2010 08:53 » |
|
Извольте. Вот три последовательные точки некоего полигона: Определите направление его обхода - по часовой стрелке либо же против.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #12 : 27-12-2010 08:55 » |
|
Не понял.. По часовой..
|
|
|
Записан
|
while (8==8)
|
|
|
yudjin
|
|
« Ответ #13 : 27-12-2010 09:00 » |
|
извините за вторжение - а так?
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #14 : 27-12-2010 09:01 » |
|
yudjin, у этого полигона неоднозначность.. Немного глубже провал - и даже общая площадь поменяет знак.. Или будет равна нулю..
И стоит ли тогда напрягать алгоритм???
|
|
« Последнее редактирование: 27-12-2010 09:04 от sss »
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #15 : 27-12-2010 09:03 » |
|
yudjin, абсолютно верно Именно это я и не успел нарисовать. sss, какая неоднозначность? Вы действительно не видите, что контур на самом деле обходится против часовой стрелки?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #16 : 27-12-2010 09:05 » |
|
Dale,мы говорим об методе, применимом только для выпуклых многоугольников. Хватит передергивать!!!
|
|
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #17 : 27-12-2010 09:07 » |
|
Dale,мы говорим об методе, применимом только для выпуклых многоугольников. Хватит передергивать!!! Давайте внимательно прочитаем постановку задачи от Алексей1153++ и поищем там слово выпуклый. Лично у меня не получилось. Может, вам больше повезет?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #18 : 27-12-2010 09:08 » |
|
-
|
|
« Последнее редактирование: 27-12-2010 09:13 от sss »
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #19 : 27-12-2010 09:10 » |
|
Dale, откуда вы взяли метод, подсказанный вами.. Может быть прочитаете? Пожалуйста: "Математика и САПР", Москва, "Мир", 1988, стр. 15.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #20 : 27-12-2010 09:13 » |
|
Ну и что.. Там не написано, что этот метод подходит только для выпуклых многоугольников?
|
|
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #21 : 27-12-2010 09:15 » |
|
Конечно, нет. Выпуклость здесь не играет никакой роли.
Добавлено через 1 минуту и 20 секунд: К тому же тогда понадобился бы алгоритм для предварительного определения выпуклости контура, чтобы исключить ошибочное применение данной формулы.
|
|
« Последнее редактирование: 27-12-2010 09:16 от Dale »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #22 : 27-12-2010 09:32 » |
|
Читаю.. И не понимаю как можно было предложить эту ссылку... Нахождение площади и все.. Понятие направления обхода для невыпуклых полигонов - нонсенс!
|
|
« Последнее редактирование: 27-12-2010 09:33 от sss »
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #23 : 27-12-2010 09:33 » |
|
Можно посмотреть ссылку, по которой читаете? У меня эта книга в бумажном варианте.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #24 : 27-12-2010 09:34 » |
|
|
|
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #25 : 27-12-2010 09:36 » |
|
Первая сноска внизу стр. 15.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #26 : 27-12-2010 09:38 » |
|
Вы подумайте - если первый треугольник введен по часовой стрелке, второй против - какой "общий" обход полигона и почему??
|
|
|
Записан
|
while (8==8)
|
|
|
Dale
|
|
« Ответ #27 : 27-12-2010 09:39 » |
|
Понятие направления обхода для невыпуклых полигонов - нонсенс! Отнюдь. Полигон имеет некоторую внутреннюю область. При обходе контура эта область постоянно находится либо только справа, либо только слева. Где именно - зависит от направления обхода. Выпуклость в данном случае не имеет никакого значения.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Kivals
|
|
« Ответ #28 : 27-12-2010 09:41 » |
|
... Понятие направления обхода для невыпуклых полигонов - нонсенс!
Не соглашусь. Нонсенсом было бы понятие обходя для многосвязных (вроде так называются?) полигонов. Возьмите класическую звездочку - это есть невыпуклый полигон, при этом направление определяется однозначно. Dale, +1
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #29 : 27-12-2010 09:42 » |
|
Dale, первый треугольник введен по часовой стрелке, второй против - какой "общий" обход.. Ответь пожалуйста? У кого площадь больше тот и победил?
|
|
|
Записан
|
while (8==8)
|
|
|
|