Помощь - Поиск - Пользователи - Календарь
Полная версия: Нарисовать калейдоскоп
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Relrin
Сейчас стараюсь решить задачку в графике, однако возникло масса проблем с кодингом.
Условие следующее:
Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла

Я представил эту ситуацию так:
Нажмите для просмотра прикрепленного файла
Каждая сторона имеет свой номер(чтобы было проще соориентироваться, при отрисовке линий).
Проблемы которые возникли:
1) Отрисовка этих линий в одном треугольнике (начинаем с треугольника FOA)
2) "Отзеркаливание" этих линий, вместо того, чтобы рисовать их с нуля. (в нашем примере, нарисовав линии в треугольнике FOA, рисуем зеркально линии в OAB, относительно OA; после этого, опять зеркально рисуем для треугольника BOC, относительно BO).

Для отрисовки линий, пока трудно представляю как выбрать некоторые "случайные" координаты для первой точки линии на одной стороне, а после, взять другие "случайные" на одной из двух других. Пока что пришло на ум, через case как-то выделять эти стороны, обращение к ним, если одна из них выбрана.
С отзеркаливанием линий, это по-мойму самая сложная часть, поскольку возникают вопросы:
а) как указать программе, какую взяли линии за "ось симметрии"
б) рисовать относительно нее линии

Исходный код, того, чего я смог пока сделать (Показать/Скрыть)
volvo
Ты пошел сложным путем. Я бы сделал по-другому... Пока только идея, попробуй реализовать сам, не получится - я набросаю код...

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

2. Разбиение треугольника линиями. Развиваем мысль относительно ПСК, каждая линия - это еще одна дистанция (если конец отрезка лежит на радиальной стороне) или еще один радиус + дистанция (если не на радиальной). Генерируешь случайным образом несколько пар чисел, и по ним рисуешь линии.

3. А теперь - самое интересное: как зеркально отразить линии от какой-то оси? А просто... smile.gif С одной стороны (общая радиальная сторона двух треугольников) вообще ничего делать не надо правда? А для точек, лежащих на другой стороне, что надо сделать? Изменить угол (если у тебя 6-ти угольник, то каждый центральный угол = 360/6 = 60 градусов, то есть, тебе достаточно уменьшить/увеличить угол на 120 градусов, смотря в какую сторону ты идешь). Всё. Расстояние от центра останется тем же, больше делать не надо ничего. Если точка лежит на НЕрадиальной стороне - то что? Правильно, надо опять изменить угол. Дистанция останется той же. Вот и всё, нарисуй картинку на бумаге, прими центр за начало ПСК, поставь несколько точек на любую сторону, и посмотри, насколько просто их зеркально отобразить... Потом просто соединяешь точки в том же порядке, что и в самом первом треугольнике, и у тебя есть отображение.

Все детали дорабатываются непосредственно перед началом программирования. А это так, черновой набросок... Так что попробуй, только сразу не откидывай идею... smile.gif
Relrin
Цитата(volvo @ 18.03.2011 0:12) *

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

2. Разбиение треугольника линиями. Развиваем мысль относительно ПСК, каждая линия - это еще одна дистанция (если конец отрезка лежит на радиальной стороне) или еще один радиус + дистанция (если не на радиальной). Генерируешь случайным образом несколько пар чисел, и по ним рисуешь линии.

3. А теперь - самое интересное: как зеркально отразить линии от какой-то оси? А просто... smile.gif С одной стороны (общая радиальная сторона двух треугольников) вообще ничего делать не надо правда? А для точек, лежащих на другой стороне, что надо сделать? Изменить угол (если у тебя 6-ти угольник, то каждый центральный угол = 360/6 = 60 градусов, то есть, тебе достаточно уменьшить/увеличить угол на 120 градусов, смотря в какую сторону ты идешь). Всё. Расстояние от центра останется тем же, больше делать не надо ничего. Если точка лежит на НЕрадиальной стороне - то что? Правильно, надо опять изменить угол. Дистанция останется той же. Вот и всё, нарисуй картинку на бумаге, прими центр за начало ПСК, поставь несколько точек на любую сторону, и посмотри, насколько просто их зеркально отобразить... Потом просто соединяешь точки в том же порядке, что и в самом первом треугольнике, и у тебя есть отображение.

Идея интересна, немного на бумаге набросал, покрутил - получается красиво. Однако, не сложнее ли будет такое программировать(особенно если учитывать, что с таким... "полярным" программированием встречаюсь впервые, сколько пробую кодить)? Пока все же попробую еще что-нибудь придумать с декартовой системой... wacko.gif
volvo
Цитата
не сложнее ли будет такое программировать(особенно если учитывать, что с таким... "полярным" программированием встречаюсь впервые, сколько пробую кодить)?
Я не думаю, что это будет сложнее, чем в декартовых координатах. Понимаешь, в чем дело... Логика решения этой задачи подразумевает повороты. А повороты проще делать именно в полярной СК.

Что касается отображения: отображать линии надо и там и там, только в твоем случае у тебя есть готовая процедура Line, а в моем варианте подразумевается написать свою процедуру, PolarLine. Кстати, на самом деле писать ее даже не придется, достаточно посмотреть в поиске, я уже выкладывал где-то решения в ПСК, там есть и конвертер координат из одной системы в другую, и отрисовка в полярной СК основных графических примитивов (точка и линия - 100% есть).

Ну, решать-то тебе, делай по-своему, если тебе будет проще...
Relrin
Относительно отзеркаливания, пришла в голову идея, что, после того, как в одном треугольнике нарисуем все нужные линии, запишем в массивы их координаты (начало и конец соответственно), после чего нужно будет только изменить их координаты, путем поворота на 60 градусов по часовой/против часовой стрелки. Еще, не знаю, возможно, что через линейное преобразование можно сделать, но не уверен в результате...

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

Исходный код:

{Поиск начальной координаты линии}
Procedure FindXYStart;
Var
buf: integer;
Begin
side:=random(3)+1;
case side of
1: begin
buf:=top[1].X-center.X;
x1:=top[1].X-random(buf)+1;
buf:=center.Y-top[1].Y;
y1:=center.Y-random(buf)+1;
end;
2: begin
buf:=abs(top[1].X-top[2].X);
x1:=top[1].X-random(buf)+1;
buf:=abs(top[1].Y);
y1:=buf;
end;
3: begin
buf:=center.X-top[2].X;
x1:=center.X-random(buf)+1;
buf:=center.Y-top[2].Y;
y1:=center.Y-random(buf)+1;
end;
end;
End;

{Поиск конечной координаты линии}
Procedure FindXYEnd;
Var
asd: word;
buf: integer;
Begin
case side of
1: begin
repeat
asd:=random(3)+1;
until asd<>side;
case asd of
2: begin
buf:=abs(top[1].X-top[2].X);
x2:=top[1].X-random(buf)+1;
buf:=abs(top[1].Y);
y2:=buf;
end;
3: begin
buf:=abs(center.X-top[2].X);
x2:=center.X-random(buf)+1;
buf:=abs(center.Y-top[2].Y);
y2:=center.Y-random(buf)+1;
end;
end;
end;

2: begin
repeat
asd:=random(3)+1;
until asd<>side;
case asd of
1: begin
buf:=abs(top[1].X-center.X);
x2:=top[1].X-random(buf)+1;
buf:=abs(center.Y-top[1].Y);
y2:=center.Y-random(buf)+1;
end;
3: begin
buf:=abs(center.X-top[2].X);
x2:=center.X-random(buf)+1;
buf:=abs(center.Y-top[2].Y);
y2:=center.Y-random(buf)+1;
end;
end;
end;

3: begin
repeat
asd:=random(3)+1;
until asd<>side;
case asd of
1: begin
buf:=abs(top[1].X-center.X);
x2:=top[1].X-random(buf)+1;
buf:=abs(center.Y-top[1].Y);
y2:=center.Y-random(buf)+1;
end;
2: begin
buf:=abs(top[1].X-top[2].X);
x2:=top[1].X-random(buf)+1;
buf:=abs(top[1].Y);
y2:=buf;
end;
end;
end;
end;
End;

volvo
Цитата
после чего нужно будет только изменить их координаты, путем поворота на 60 градусов по часовой/против часовой стрелки.
То есть, ты пришел к тому же, о чем я написал тебе во втором посте, но делаешь это пока сложным методом... Ничего, через пару дней тебе в голову придет идея, что можно не хранить координаты X, Y для начала/конца отрезка, а сделать что-то вроде:

type
Position_Type =
(Radial_Edge_Left, Radial_Edge_Right, Non_Radial_Edge);
Polar_Point =
record
Position : Position_Type;
Phi, R : Integer;
end;

procedure Generate_Point(var Pnt : Polar_Point);
begin
Pnt.Position := Position_Type (Random (Ord (Non_Radial_Edge)));
case Pnt.Position of
Radial_Edge_Left : // Сгенерировать точку на "левой" радиальной стороне треугольника
begin
Pnt.Phi := 0;
// Я принял отсчет угла от "левой" стороны, которая проходится
// первой при обходе по часовой стрелке...
Pnt.R := Random (Radius);
end;

Radial_Edge_Right : // Сгенерировать точку на "правой" радиальной стороне
begin
Pnt.Phi := Angle; // 360 / количество сторон многоугольника
Pnt.R := Random (Radius);
end;

Non_Radial_Edge : // Сгенерировать точку на НЕрадиальной стороне
begin
Pnt.Phi := Random (Angle);
Pnt.R := Trunc (Radius * Cos (To_Radians (Pnt.Phi)));
end;
end;
end;

Тут же можно генерировать и вторую точку отрезка, только надо следить, чтобы их поля Position не были равны, иначе линия отрезок сольется с одной из сторон треугольника... Видишь, насколько все проще? Если подумать - то не надо будет даже ничего добавлять ни к чему для отзеркаливания: допустим, ты пронумеровал все треугольники от 1 до N, и сгенерировал несколько отрезков для треугольника №1. Тогда во все нечетные можно просто отображать те же отрезки, а в четные - поменяв Position с REL на RER, а для NRE - изменив угол с Phi на Angle - Phi... И всё, можно сразу всё отрисовать, буквально за 1 проход...
Relrin
Тогда как будет выглядеть в целом программа, если это будет в ПСК?
volvo
Чуть позже, хорошо? Часа через 3-4 я освобожусь и сделаю каркас...
Relrin
Цитата(volvo @ 18.03.2011 20:39) *

Чуть позже, хорошо? Часа через 3-4 я освобожусь и сделаю каркас...

Ок. Мне к спеху smile.gif
Lapp
Цитата(Relrin @ 18.03.2011 19:46) *
Ок. Мне к спеху smile.gif

К спеху или НЕ к спеху? ))

Хм. Полярные координаты тут действительно могут облегчить жизнь в некоторых аспектах, но не во всех. При закрашивании "стеклышек" (термин из реальных калейдоскопов)) все равно придется работать в Декартовой СК. И, если уж так, то по крайней мере _я_ не вижу, почему бы не сделать простую процедурку для отражения в ДСК, и не мешать в одну кучу разные координаты..

И вообще, я не вижу проблемы в рисовании, проведении прямых и отражении - это все мелочи. Мне кажется, реальную головную боль вызовет программирование закрашивания стеклышек.. Кстати, забавно будет, если еще наложить условие, что красок только 4 smile.gif.
Relrin
Цитата(Lapp @ 18.03.2011 22:45) *

К спеху или НЕ к спеху? ))

Хм. Полярные координаты тут действительно могут облегчить жизнь в некоторых аспектах, но не во всех. При закрашивании "стеклышек" (термин из реальных калейдоскопов)) все равно придется работать в Декартовой СК. И, если уж так, то по крайней мере _я_ не вижу, почему бы не сделать простую процедурку для отражения в ДСК, и не мешать в одну кучу разные координаты..

И вообще, я не вижу проблемы в рисовании, проведении прямых и отражении - это все мелочи. Мне кажется, реальную головную боль вызовет программирование закрашивания стеклышек.. Кстати, забавно будет, если еще наложить условие, что красок только 4 smile.gif.

Не к спеху, немного описался smile.gif

Исходя из условия задачи, оба варианта имею права на жизнь, у обеих свои плюсы и минусы. Например, треугольники рисовать проще в ДСК, в то время как рисовать линии и отражения на других - в ПСК
Relrin
volvo, можешь скинуть код решения задачи в ПСК?
Relrin
Возник вопрос, относительно старой темы - калейдоскопа.
Как зарисовать каждую область, которую поделила линия. Т.е. допустим линия поделила треугольник пополам, и каждую половинку мы закрашиваем, при этом, цвета должны быть такие же в других треугольниках (т.е. симметрично)? dry.gif
Lapp
Цитата(Relrin @ 4.05.2011 17:04) *
Возник вопрос, относительно старой темы - калейдоскопа.
Как зарисовать каждую область, которую поделила линия. Т.е. допустим линия поделила треугольник пополам, и каждую половинку мы закрашиваем, при этом, цвета должны быть такие же в других треугольниках (т.е. симметрично)? dry.gif

Наконец, разговор коснулся сути smile.gif (см. мой пост выше).
В твоем вопросе звучит, что ты озадачился алгоритмом заполнения. Но еще по твоему вопросу понятно, что ты еще очень слабо вник в проблему.

Советую тебе попытаться полностью, с начала до конца, промоделировать этот процессс на бумаге. Сначала ограничься рисованием одного сектора (об отражениях подумаешь потом). Ты - компьютер. Берешь лист - это твой экрвн. Ты можешь:
- ставить точки в определенные места;
- проводить отрезки, указывая их концы;
- закрашивать области, ограниченные точками одного цвета, начиная с данной точки (FloodFill).
Ставь точки, проводи отрезки (всякий раз думая, как задать их координаты). Закрашивай области (продумывай, как задать координаты начальной точки). Попробуй выработать алгоритм и записать его на бумаге.

Вот когда это все сделаешь - тогда принимайся за прогу. А до того - и не пытайся )).
Показывай свое словесное описание алгоритмя тут. Будем разбираться.
IUnknown
Цитата
Возник вопрос, относительно старой темы - калейдоскопа.
У меня тоже возник вопрос: основная твоя задача - "нарисовать калейдоскоп", или все-таки "нарисовать калейдоскоп буква в букву так, как написано в задании"? Если второе - то можешь дальше не читать.

Если все-таки, задача _красиво нарисовать_ (Показать/Скрыть)


Выбирай...
hydroxychloroquine for rheumatoi
cialis ventajas y desventajas
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.