Первый мой опыт попытки вращения отрезка пал на вращение относительно его начала.
Вообще в интернете описаны матрицы-шматрицы и написано: "используйте их, и будет вам счастье в компьютерной графике". Но такие, как я, не обладают математическим знанием, поэтому использование матриц вызывает определенные затруднения. Кроме того, даже глядя на формулу поворота, мне не удавалось её подставить в код должным образом. Попытки найти пример не увенчались успехом. Но сила моя как раз в том, что ищу я упорно и чаще нахожу то, что ищу (хотя не всегда получается). Вот и попалась мне формула:
X = x1+(x2-x1)*cos(A)-(y2-y1)*sin(A)
Y = y1+(x2-x1)*sin(A)+(y2-y1)*cos(A)
(где X и Y новые координаты того конца, который вращаем)
Вот это было как раз тем, что было так нужно.
Код 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 |
#include <iostream.h> #include <graphics.h> #include <math.h> struct MyPoint {float x,y;} O,A; //Определим свой тип данных float R=100; //Длина отрезка. /*ФУНКЦИЯ ВВОДА ПАРАМЕТРОВ*/ void input() { O.x=getmaxx()/2; //Начало отрезка в центр экрана O.y=getmaxy()/2; //Начало отрезка в центр экрана A.x=O.x+R; //Конец отрезка A.y=A.x*sin(70); //Конец отрезка кладем на окружность circle(O.x,O.y,R); //Это я для себя проводил } int main() { int gd=DETECT,gm; initgraph(&gd,&gm,""); input(); //Ввод параметров cin.get(); closegraph(); return; } |
Итак. Это в принципе простой код, но некоторым понадобятся пояснения. Выполняется только одна функция, в которой одна точка отрезка размещается в центр экрана, вторая точка определяется согласно длины отрезка. Так как вращение отрезка будет вокруг его начала, то значит это самое начало является центром окружности. Сам отрезок получается радиусом окружности и чтобы определить координаты его конца, нужно точку конца отрезка положить на окружность. Если координата х или y известны, то положить точку на окружность не составляет труда. В моем случае я клал по известному x. Не имеет разницы то, как строится отрезок. Если длина его неизвестна, то значит ее придется посчитать по теореме Пифагора.
Код 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 |
#include <iostream.h> #include <graphics.h> #include <math.h> struct MyPoint {float x,y;} O,A; //Наш тип данных float R=100; //Длина отрезка /*Функция поворота отрезка*/ void rotate(float x1,float y1,float &x2,float &y2, float angle) { float dx=x2; //Запоминаем для следующих вычислений float dy=y2; //Запоминаем для следующих вычислений x2=x1+(dx-x1)*cos(angle*M_PI/180)-(dy-y1)*sin(angle*M_PI/180); //Поворот на angle градусов y2=y1+(dx-x1)*sin(angle*M_PI/180)+(dy-y1)*cos(angle*M_PI/180); //Поворот на angle градусов circle(x1,y1,R); //Это я для себя делал line(x1,y1,x2,y2); //Выводим повернутую линию } /*Функция ввода параметров*/ void input() { O.x=getmaxx()/2; O.y=getmaxy()/2; A.x=O.x+R*cos(90); A.y=O.y+R*sin(90); line(O.x,O.y,A.x,A.y); //Переместил сюда setcolor(3); //Для себя } void main() { int gd=DETECT,gm; initgraph(&gd,&gm,""); input(); //Вводим параметры float angle=90; //Задаем угол rotate(O.x,O.y,A.x,A.y,angle); //Поворачиваем точку А отрезка ОА на angle градусов cin.get(); closegraph(); return; } |
Вот можно сравнить по первому коду и увидеть некоторые изменения. В функцию поворота нужно передавать координаты двух точек (концы отрезка) и угол, на который нужно сделать поворот. Так как координаты одного конца должны менять значение, то в принимаемых параметрах внутри функции указываем их как ссылки. Обратите внимание на запоминание параметров (указанных как ссылки) во временные переменные.
Это формула, которую я отыскал. Грамотно пояснить не смогу, но скажу не очень грамотно.
Чтобы повернуть точку на произвольный угол, нужно определить позицию этой точки и только после этого поворачивать. Вот такой расчет и поворот и происходит в формуле.
Теперь не должно составлять труда поворачивать отрезок вокруг своего начала на произвольно заданный угол. Я думаю дописывать это не обязательно и вы замечательно доделаете это на ваш вкус.
====================
Вроде задача решена и больше ничего не нужно. Но это не совсем так. Мне, например, всегда было интересно как программировать аналоговые часы. Программировать я их тут не буду, но если присмотреться, то поворот отрезка очень напоминает стрелку с часов. Значит можно реализовать поворот стрелки. Для этого нужно использовать цикл. Я склонен считать, что этот самый цикл может вызывать затруднения, поэтому
Код С++ Поворот отрезка Аналоговые Часы Стрелка
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 47 48 49 50 51 52 53 54 |
#include <iostream.h> #include <graphics.h> #include <math.h> #include <dos.h> //Добавилась директива для задержки struct MyPoint {float x,y;} O,A; //Наш тип данных float R=100; //Длина отрезка /*Функция поворота отрезка*/ void rotate(float x1,float y1,float &x2,float &y2, float angle) { float dx=x2; //Запоминаем для вычислений float dy=y2; //Запоминаем для вычислений x2=x1+(dx-x1)*cos(angle*M_PI/180)-(dy-y1)*sin(angle*M_PI/180); //Получили первую координату y2=y1+(dx-x1)*sin(angle*M_PI/180)+(dy-y1)*cos(angle*M_PI/180); //Получили вторую координату circle(x1,y1,R); //Циферблат line(x1,y1,x2,y2); //Стрелка } /*ФУНКЦИЯ ВВОДА ПАРАМЕТРОВ*/ void input() { O.x=getmaxx()/2; O.y=getmaxy()/2; A.x=O.x+R*cos(90); A.y=O.y+R*sin(90); line(O.x,O.y,A.x,A.y); //Начальное положение стрелки setcolor(3); } void main() { int gd=DETECT,gm; initgraph(&gd,&gm,""); input(); //Ввод параметров float angle=360/60; //Узнаем угол для одной секунды float step=360/angle-1; //Количество повторений для цикла /*ЦИКЛ ПЕРЕРИСОВЫВАЕТ СЕКУНДНУЮ СТРЕЛКУ*/ for (int i=0;i<step;i++) { cleardevice(); //Очистка экрана rotate(O.x,O.y,A.x,A.y,angle); //Поворот отрезка sleep(1); //Задержка одна секунда } cin.get(); closegraph(); return; } |
Я рисовал стрелку расположенную фиг знает где. Если надо расположить в начальном положении, то
A.x=O.x;
A.y=O.y-R;
Добавить одну задержку в секунду после вывода первой линии в конец input().
Если нужно зациклить часы до нажатия какой-либо клавиши, то использовать вместо for
1 2 3 4 5 6 |
#include <conio.h> while (!kbhit()) { тело цикла } |
и добавить первую прорисовку циферблата (я ее не делал). Там же где прорисовка первой стрелки
======================================
Если вы усвоите этот материал, то без труда сможете реализовать свои первые часики))
Конечно могут возникнуть вопросы, так как я, пытаясь сжать информацию, пропускал разные моменты, но если хотите спросить, на то что смогу — на то отвечу.
😥
Огромное спасибо! Очень помогло
Блин, чувак, КРЕПКО ЖМУ ТЕБЕ РУКУ!!!
Хотел бы обратиться по имени, но не знаю как тебя звать )
В общем, я премного благодарен, очень выручил )
Моя задача заключается в том, что нужно поворачивать отрезок относительно центра, но глядя на твой код я решу эту задачу без проблем )
В моем случае середина отрезка это точка начала, а поворачивать буду как бы сразу 2 отрезка (концы) на один и тот же угол ))
Огромное спасибо! Выручил.