Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: вращение композиции из примитивов, builder  (Прочитано 27104 раз)
0 Пользователей и 1 Гость смотрят эту тему.
rukia
Интересующийся

ru
Offline Offline

« : 27-10-2008 11:49 » 

здравствуйте) у меня есть композиция из 5 графических примитивов.вот:
Код:
int x=250;int y=150;// коорд-ы центра вращения
  //а это параматр, который передается в функцию.
 Image1->Canvas-> Pen->Color = clRed;
 Image1->Canvas->MoveTo(x,y);
 Image1->Canvas->Rectangle(x-2*a,y-2*a,x+2*a,y+2*a);
 Image1->Canvas-> Arc(x+3*a,y-a,x+a,y+a,x+2*a,y+a,x+2*a,y-a);
 Image1->Canvas-> Arc (x-a,y-3*a,x+a,y-a,x+a,y-2*a,x-a,y-2*a);
 Image1->Canvas-> Arc (x-3*a,y-a,x-a,y+a,x-2*a,y-a,x-2*a,y+a);
 Image1->Canvas->Arc(x-a,y+3*a,x+a,y+a,x-a,y+2*a,x+a,y+2*a);
это выглядит как квадрат стороной в 4а с 4 "ушами" радиуса а. нужно,в том числе, чтобы вся эта штука врщалась вокруг центра квадрата... с использованием ,видимо, таймера. тоесть поворачивать на елементарный угол за каждый его "тик". но писать это вращение для каждого примитива же было бы странно  Скромно так...
Можно как-то вращать это как единую систему? подскажите пожалуйста, как это можно сделать!
простите за глупый вопрс, просто первая работа с графикой.. Краснею
« Последнее редактирование: 28-10-2008 12:37 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 27-10-2008 11:59 » 

rukia, а здесь дело не в графике, а в алгебре и аналитической геометрии.

Нужно ввести мировую систему координат - двумерное пространство, описать в нём взаимное расположение и пропорции фигур, а потом задать оператор вращения вокруг некой точки над этим пространством.

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

Затем останется только перевести мировую систему координат в экранную (обычно это перенос центра координат из левого верхнего угла в середину canvas, и зеркальное отражение по Y, чтобы ось была направлена вверх (хотя не обязательно)).

И так на каждом тике таймера.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #2 : 28-10-2008 11:36 » 

dimka, суров, отче Улыбаюсь

как справедливо подозревает автор, всё это уже написано, в т.ч. в виндовом GDI, и ничего никуда вводить не надо. надо юзать SetWorldTransform, (которая, собственно, и сделает маппинг мировых координат в экранные, вкупе со структурой XForm, позволяющей задавать четыре типа операций: вращение, масштабирование, сдвиг и зеркальное отображение.

в принципе, можно попробовать вывести всё это на отдельный канвас, вытащить текущую матрицу трансформирования через GetWorldTransform, расставить синусы и косинусы в структуре XForm (для вращения), и сказать канвасу ModifyWorldTransform.


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

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 28-10-2008 12:08 » 

Игорь, это поможет только в том случае, если канва единственное, что нужно вращать.

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

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #4 : 28-10-2008 12:20 » 

Джон, зачем? выведи их на отдельную канву, отрисуй, а потом - CopyRect или вообще BitBlt на исходную.
Записан

x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #5 : 28-10-2008 14:12 » 

Цитата
писать это вращение для каждого примитива же было бы странно


кстати, вот с етим я не совсем несогласное Улыбаюсь наоборот логично было бы написать функцию, возвращающую TPoint, повернутый относительно заданого центра координат на заданный угол. и не напрямую указывать (X,Y), а через эту функцию. и безо всяких танцев с бубном спокойно крутить любую арку и вообще любую фигуру, получаемую стандартными функциями GDI. функция преобразования - тривиальная:

Код:
|x' y'| == |x y| * | cos A   sin A|  
                   |-sin A   cos A| 
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 28-10-2008 14:16 » 

А ты можешь сделать прозрачную канву? (кстати я есть бильдеръ плохо понимайт, исхожу из того что канва есть тоже что и DC - device context в API),

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


зы Я кстати так в gdi+ и трансофрмирую всё, но только ВСЁ сразу.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #7 : 28-10-2008 14:22 » 

Джон, канва в билдере или дельфи - это не совсем DC, это обёртка вокруг DC, включающая в себя, помимо прочего, и дескриптор контекста (hDC). прозрачность же канвы - это вопрос её отображения, а не хранения. при копировании одной канвы на другую для всех пикселей можно указывать битовые операции. например, ты можешь её "заXORить", тупо скопировать один в один, скопировать по маске, инвертировать, etc. при выводе канвы в битмап для самого битмапа можно указать прозрачный цвет. ну и так далее. а на уровне АПИ прозрачности, как таковой не существует. даже если залить её цветом clNone, это всё равно какой-то цвет Улыбаюсь вопрос в том, кто и как этот цвет будет интерпретировать уже на стадии отоюражения.
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #8 : 28-10-2008 14:30 » 

а на уровне АПИ прозрачности, как таковой не существует.

Именно это я и имел ввиду. В конечном итоге этот "прозрачный" цвет является определяющим для ROP кода.  Те в самом общем случае придётся ещё и маску делать для всех контуров примитивов.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #9 : 28-10-2008 14:33 » 

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

по-моему, ничего там сложного нет Улыбаюсь
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #10 : 28-10-2008 14:38 » 

Наверное нет.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
rukia
Интересующийся

ru
Offline Offline

« Ответ #11 : 28-10-2008 15:15 » 

ойой) я погуглю про то, о чем вы говорите, спасибо за советы  Улыбаюсь
а вот если не преобразовывать экранные координаты( то есть оставить те, у которых начало в верхнем левом углу Image1), а написать так:
Код:
  // int a и float dang передаются в ф-ю; х, у коорд-ы центра вращения 
   Image1->Canvas-> Pen->Color = clRed;
   Image1->Canvas->MoveTo(x,y);
   Image1->Canvas->Rectangle(x+2*sqrt(2)*a*cos(3.14/4+ang+dang),
 y-2*sqrt(2)*a*sin(3.14/4+ang+dang),
 x+2*a*sqrt(2)*cos(-3*3.14/4+ang+dang),
 y+2*a*sqrt(2)*sin(-3*3.14/4+ang+dang));
 ang+=dang;
    //нарисовать белый квадрат 6а*6а;
то есть воспользоваться полярными координатами. 2*a*sqrt(2) это радиус окружности, описываемой даанной точкой.(написано только для квадрата, задаю вращения правого верхнего и левого нижнего углов)
это будет работать? или я танцую с бубном, изобретая еще и прии этом велосипед?
!!!
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 28-10-2008 15:21 » 

rukia, а до формул ты не можешь абстрагироватьс? Чесслово, глазки разбегаются от такого количества букафф.

зы А формулу х77 ты уже попробовал? Не работает?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #13 : 28-10-2008 15:24 » 

rukia, работать будет, но совсем не так, как ты хочешь. Rectangle всегда нарисует квадрат. со сторонами, параллельными сторонам монитора Улыбаюсь ты сдвинул точки, но прямоугольник всё равно останется прямоугольников, под наклоном GDI ректанглы выводить не умеет Улыбаюсь

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

плюсы:

1) каждый созданный регион имеет свой hRGN, дескриптор. т.е. по сути ты получишь набор векторных примитивов, которые можно отрисовать на любом канвасе.
2) регионы можно выводить любым цветом и стилем, вплоть до заливки произвольным битмапом.
3) регионы удобно сохранять на диск (в т.ч. в БД)

почитать можно у нас же на сайте: Работа с регионами
Записан

zubr
Гость
« Ответ #14 : 28-10-2008 15:56 » 

Хмм.. У борланда в классе TCanvas есть метод void __fastcall Polygon(const TPoint * Points, const int Points_Size); с помощью которого по точкам можно строить любую фигуру, в том числе и повернутый прямоугольник. Также для данной задачи можно посмотреть в сторону метафайлов.
Записан
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #15 : 28-10-2008 16:06 » 

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

просто задача, на мой взгляд, лучше решается именно в векторном, а не растровом виде.
Записан

rukia
Интересующийся

ru
Offline Offline

« Ответ #16 : 28-10-2008 16:19 » 

под наклоном GDI ректанглы выводить не умеет Улыбаюсь
вот это удар)))) а я-то думаю, ну чего он не вращается) а дуги, по идее будут таким методом вращаться? и еще вопрос- а та формула с 2х2 матрицей преоброзования, она сойдет и для экранных координат, или она только в мировых с центром в центре квадрата?
Записан
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #17 : 28-10-2008 16:27 » 

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

матрица там общая, подразумевает центр мировых координат. чтобы из этих координат получить экранные, тебе нужно сдвинуть центр по оси X и инвертировать по оси Y.
Записан

x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #18 : 28-10-2008 16:35 » 

кстати, чем ещё хороши регионы, при ExtCreateRegion матрицу трансформации (XFORM) можно задавать изначально. т.е. берём регион любой сложности (прямоугольник, элипс, ломанную - неважно), вытаскиваем из неё данные (GetRegionData) и эти данные засовываем в ExtCreateRegion вместе с настроенной XFORM. в результате имеем новый регион, повёрнутый на заданный угол (причём, кроме поворота можно отработать масштабирование (scale) и сдвиг (shear). просто и красиво (к вопросу Джона о прозрачных битмапах - можно вообще не юзать битмап, а юзать дескриптор логического объекта GDI и прямо в памяти творить с этим объектом всё, что угодно). а когда эту штуку надо где-то отрисовать - просто дёргаем FrameRgn.
Записан

zubr
Гость
« Ответ #19 : 28-10-2008 17:29 » 

x77, по поводу Polygon не согласен - что это растровая функция. Борландский Poligon - это оболочка для виндовой GDI-функции Poligon, отрисовывающей примитив, аналогично Rectangle, LineTo, curves и т. п.
Вот цитата из MSDN:
Цитата
2-D vector graphics
Vector graphics involves drawing primitives (such as lines, curves, and figures) that are specified by sets of points on a coordinate system. For example, a straight line can be specified by its two endpoints, and a rectangle can be specified by a point giving the location of its upper-left corner and a pair of numbers giving its width and height. A simple path can be specified by an array of points to be connected by straight lines. A Bézier spline is a sophisticated curve specified by four control points.

GDI+ provides classes that store information about the primitives themselves, classes that store information about how the primitives are to be drawn, and classes that actually do the drawing. For example, the Rect class stores the location and size of a rectangle; the Pen class stores information about line color, line width, and line style; and the Graphics class has methods for drawing lines, rectangles, paths, and other figures. There are also several Brush classes that store information about how closed figures and paths are to be filled with colors or patterns.
Насчет регионов не спорю, возможно это и удобнее.
Записан
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #20 : 28-10-2008 18:20 » 

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

простой пример. ты вывел на канвас прямоугольник. как этот прямоугольник сдвинуть на 10 пикселей влево? задача борлее чем нетривиальная. а с регионом - ты сказал ему OffsetRgn и отрисовал по новой, при работе с регионами у тебя не пикселы в канвасе, а дескриптор логического объекта GDI. которым можно рулить непосредственно в памяти. вот в этом смысле (возможно, не совсем корректном с точки зрения терминов) я регионы отношу к векторной графике, а функции канваса - к растровой. эти функции "не помнят", что они же рисовали.
« Последнее редактирование: 28-10-2008 18:24 от x77 » Записан

rukia
Интересующийся

ru
Offline Offline

« Ответ #21 : 28-10-2008 18:27 » 

спасиво еще раз) тоесть, что бы повернуть, например, квадрат тот же самый, надо создать массив типа TPoint , передать его полигону, затем(если без перехода к мировым координатам)повернуть каждую из четырех точек-элементов массива таким образом:
Код:
x1 =    x * cos(ugl) + y * sin(ugl) + x0;
      y1 =  - x * sin(ugl) + y * cos(ugl) + y0;
, где
Код:
x0 = img->Width/2;
y0 = img->Height/2;
и по совместительству коорд. центра вращения.
после чего циклом присвоить эти новые точки тмассиву с именнем как у перого, и тогда в следующий вызов  полигона ему передадуться повернутые точки под именем перврго массива.да? или я ошиблась в чем-то?(а наверно так и есть  Скромно так... )а в чем?)))
Записан
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #22 : 28-10-2008 18:31 » 

rukia, думать лень Улыбаюсь дайте конечный кусок кода, чтобы можно было скопипастить и посмотреть, как он работает.
Записан

rukia
Интересующийся

ru
Offline Offline

« Ответ #23 : 28-10-2008 18:40 » 

эх..я не могу, он нечаянно удалился, а это было по памяти. я завтра или послезавтра точно напишу) спасибо за советы! ничего про графику не было на семинарах и лекциях... зато теперь я знаю, про что читать ))))
Записан
x77
Команда клуба

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #24 : 28-10-2008 19:01 » 

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

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 29-10-2008 21:38 » 

Цитата: rukia
Код:
x1 =    x * cos(ugl) + y * sin(ugl) + x0;
      y1 =  - x * sin(ugl) + y * cos(ugl) + y0;
, где
Код:
x0 = img->Width/2;
        y0 = img->Height/2;
 и по совместительству коорд. центра вращения.
после чего циклом присвоить эти новые точки тмассиву с именнем как у перого, и тогда в следующий вызов  полигона ему передадуться повернутые точки под именем перврго массива.да? или я ошиблась в чем-то?(а наверно так и есть  Скромно так... )а в чем?)))
Это близко к истине, но не помню точно, все ли плюсы в первых формулах при применении оператора вращения. А соображать сейчас не могу - от другого голова пухнет Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
rukia
Интересующийся

ru
Offline Offline

« Ответ #26 : 30-10-2008 21:06 » 

привет))
если сделать так хотя бы для квадратика, то он несомненно вращается!но.. не так=(
если отбросить классы и затирание на каждом тике, то вот:
Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{  int a=30;
   float x0 = Image1->Width/2.0;
   float y0 =Image1->Height/2.0;
   TPoint p[4];
  p[0].x = (x0+2*a)*cos(ugl)+(y0-2*a)*sin(ugl)+x0;
p[0].y = -(x0+2*a)* sin(ugl) +(y0-2*a)*cos(ugl)+y0;
p[1].x = (x0+2*a)*cos(ugl)+(y0+2*a)*sin(ugl)+x0;
p[1].y = -(x0+2*a)* sin(ugl) +(y0+2*a)*cos(ugl)+y0;
p[2].x = (x0-2*a)*cos(ugl)+(y0+2*a)*sin(ugl)+x0;
p[2].y = -(x0-2*a)* sin(ugl) +(y0+2*a)*cos(ugl)+y0;
p[3].x = (x0-2*a)*cos(ugl)+(y0-2*a)*sin(ugl)+x0;;
p[3].y = -(x0-2*a)* sin(ugl) +(y0-2*a)*cos(ugl)+y0;

Image1->Canvas->Pen->Color = clRed;
Image1->Canvas->Polygon(p,3);
ugl+=0.1;
//Image1->Canvas->Brush->Color = clWhite;
//Image1-> Canvas->Rectangle(x0+4*a,y0-4*a,x0-4*a,y0+4*a);
}
Записан
rukia
Интересующийся

ru
Offline Offline

« Ответ #27 : 30-10-2008 21:16 » 

а если менять знаки разными способами, то получаются очень интересные эффекты) даже трехмерно вращающийся треугольник..
а тут я написала сейчас все в куче, чтоб удобнее сделать копипаст. только объявить еще float ugl=0.0; и сделать кнопку для включения таймера))) и можно лицезреть э т о..
Записан
rukia
Интересующийся

ru
Offline Offline

« Ответ #28 : 30-10-2008 22:07 » 

опс! смотрите как странно:
Код:
 TPoint p[4]; // ?????? ???????
 p[0].x = (y0/1000+2*a)*cos(ugl)+(x0/1000-2*a)*sin(ugl)+x0;
p[0].y = -(y0/1000+2*a)* sin(ugl) +(x0/1000-2*a)*cos(ugl)+y0;
p[1].x = (y0/1000+2*a)*cos(ugl)+(x0/1000+2*a)*sin(ugl)+x0;
p[1].y = -(y0/1000+2*a)* sin(ugl) +(x0/1000+2*a)*cos(ugl)+y0;
p[2].x = (y0/1000-2*a)*cos(ugl)+(x0/1000+2*a)*sin(ugl)+x0;
p[2].y = -(y0/1000-2*a)* sin(ugl) +(x0/1000+2*a)*cos(ugl)+y0;
p[3].x = (y0/1000-2*a)*cos(ugl)+(x0/1000-2*a)*sin(ugl)+x0;;
p[3].y = -(y0/1000-2*a)* sin(ugl) +(x0/1000-2*a)*cos(ugl)+y0;
Image1->Canvas->Polygon(p,3);
ugl+=0.1;
а это работает!! почему?
зы-- причем чем больше делитель, тем больше точность вращения.(проверено экспериментально)
Записан
rukia
Интересующийся

ru
Offline Offline

« Ответ #29 : 31-10-2008 08:27 » new

уже работает нормально=)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines