Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.10.2022, 13:22   #1
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию Нарисовать Эллиптическую диаграмму.

Здравствуйте! Есть такая задача:
Цитата:
В центре окна нарисовать эллиптическую диаграмму. Диаграмму разбить на секторы 25, 65 и 10% красного, зелёного и голубого цветов и казать по центру дуги каждого сектора проценты. При всех изменениях размеров окна диаграмма должна быть отображена полностью.
Я так понимаю имеется ввиду не фигура эллипс? Тогда что, что то вроде синусоиды, я что-то подзавис на этом. Заранее извиняюсь за глупый вопрос.
apofioz вне форума Ответить с цитированием
Старый 09.10.2022, 13:26   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

См. функцию Arc или AngleArc
macomics вне форума Ответить с цитированием
Старый 10.10.2022, 09:57   #3
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
См. функцию Arc или AngleArc
А сегменты как рисовать, руками или есть уже написанные функции? Вообще ничего не получается, аргументы функций какие-то жёсткие, кроме левого верхнего и правого нижнего угла остальное понять сложно.
apofioz вне форума Ответить с цитированием
Старый 10.10.2022, 10:22   #4
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Код:
// Получение необходимой информации
BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &cr);

// Задание отступов от края окна
// RECT padding = Rect(0, 0, 0, 0);
// cr = Rect(cr.left + padding.left, cr.top + paddind.top, cr.right - parring.right, cr.bottom - padding.bottom);
// Предварительные вычисления
 // cen.x - относительное положение точки центра и одновременно радиус по x
 // cen.y - относительное положение точки центра и одновременно радиус по y
POINT cen = Point((cr.right - cr.left) / 2, (cr.bottom - cr.top) / 2);
// Угол в радианах сегмента pie
float arc0 = 0;
float arc1 = arc0 + 2 * 25 * M_PI / 100;
float arc2 = arc0 + 2 * 65 * M_PI / 100;
float arc3 = arc1 + 2 * 10 * M_PI / 100;
// Точки для дуги (абсолютные координаты)
POINT pnt0 = Point(cr.left + cen.x + cen.x * sin(arc0), cr.top + cen.y - cen.y * cos(arc0));
POINT pnt1 = Point(cr.left + cen.x + cen.x * sin(arc1), cr.top + cen.y - cen.y * cos(arc1));
POINT pnt2 = Point(cr.left + cen.x + cen.x * sin(arc2), cr.top + cen.y - cen.y * cos(arc2));
POINT pnt3 = Point(cr.left + cen.x + cen.x * sin(arc3), cr.top + cen.y - cen.y * cos(arc3));

// Отрисовка pie
MoveToEx(ps.hdc, pnt0.x, pnt0.y, NULL);
LineTo(ps.hdc, cr.left + cen.x, cr.top + cen.y);
LineTo(ps.hdc, pnt1.x, pnt1.y);
Arc(ps.hdc, cr.left, cr.top, cr.right, cr.bottom, pnt0.x, pnt0.y, pnt1.x, pnt1.y);

// Отрисовка pie (продолжение)
MoveToEx(ps.hdc, cr.left + cen.x, cr.top + cen.y, NULL);
LineTo(ps.hdc, pnt2.x, pnt2.y);
Arc(ps.hdc, cr.left, cr.top, cr.right, cr.bottom, pnt1.x, pnt1.y, pnt2.x, pnt2.y);

// Отрисовка pie (продолжение)
MoveToEx(ps.hdc, cr.left + cen.x, cr.top + cen.y, NULL);
LineTo(ps.hdc, pnt3.x, pnt3.y);
Arc(ps.hdc, cr.left, cr.top, cr.right, cr.bottom, pnt2.x, pnt2.y, pnt3.x, pnt3.y);
Если с углами вращения не ошибся, тогда так
Изображения
Тип файла: jpg arc.jpg (79.3 Кб, 7 просмотров)

Последний раз редактировалось macomics; 10.10.2022 в 11:19.
macomics вне форума Ответить с цитированием
Старый 10.10.2022, 10:55   #5
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Если с углами вращения не ошибся, тогда так
За код, спасибо, но я не его просил, да и толку то, если не понятно из чего берутся данные-координаты(
apofioz вне форума Ответить с цитированием
Старый 10.10.2022, 11:22   #6
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Я приложил скриншот. В коде все данные получены и расчеты приводятся.
macomics вне форума Ответить с цитированием
Старый 10.10.2022, 13:53   #7
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Я приложил скриншот. В коде все данные получены и расчеты приводятся.
Эллипс не просили рисовать, только, диаграмму, зачем тогда вообще использовать arc, если можно воспользоваться безгемморойной функцией. А как, и возможно ли, закрасить те сегменты, что нарисовали? CreateBrush() я правильно понимаю?

n * 2 * PI / 100 - это перевод в радианы, если я ничего не путаю. А как дальнейшее вычисление координат идёт я пока что вспомнить не могу.
apofioz вне форума Ответить с цитированием
Старый 10.10.2022, 14:10   #8
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Angle = n * 2 * PI / 100; // Перевод % в радианы
offX = RadiusX * sin(Angle); // Вычисление точки на окружности (координата X, относительно cen)
offY = RadiusY * cos(Angle); // Вычисление точки на окружности (координата Y, относительно cen)
pnt = Point((cr.left + cen.x) + offX, (cr.top + cen.y) - offY); // Вычисление координат точки в окне

Эллипс получается из-за приведенных вами данных: 25 + 65 + 10 = 100

Используйте FloodFill, но надо вычислить точку X = ((cr.left + cen.x) + pos0.x + pos1.x) / 3 и Y = ((cr.top + cen.y) + pos0.y + pos1.y) / 3, которая будет всегда внутри фигуры (3 - это количество точек в частном). Хотя наверное лучше будет просто убрать из расчетов центральную точку, но это уже вы поэкспериментируйте.

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

Последний раз редактировалось macomics; 10.10.2022 в 14:30.
macomics вне форума Ответить с цитированием
Старый 11.10.2022, 05:12   #9
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Я несколько другими формулами пользовался:
x = pCenter.x + 0.5 * cxEllipse * cos(2 * PI * Angle);
y = pCenter.y - 0.5 * cyEllipse * sin(2 * PI * Angle);

pCenter - координаты центра эллипса.
cxEllipse - ширина эллипса
cyEllipse - высота эллипса
Angle - 0.1, 0.65, 0.25

Но вывод получается некрасивый, если уж на то пошло, то я понимаю, как вычислять координаты и в тоже время не понимаю, значит всё же не до конца понимаю. Короче говоря мой код такой:
Код:
case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);

		hPen[0] = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
		hPen[1] = (HPEN)SelectObject(hdc, hPen[0]);
		RECT rcArc;
		int cxHalfClient = (cxClient >> 1);
		int cyHalfClient = (cyClient >> 1);

		int cxHalfEllipse = (cxEllipse >> 1);
		SetRect(&rcArc, cxHalfClient - cxHalfEllipse,
			cyHalfClient - 100,
			cxHalfClient + cxHalfEllipse,
			cyHalfClient + 100);
		cyEllipse = rcArc.bottom - rcArc.top;

		POINT pCenter = { ((rcArc.left + rcArc.right) >> 1),
						 ((rcArc.top + rcArc.bottom) >> 1)
		};
		int x0 = (int)(pCenter.x + 0.5 * (cxEllipse));
		int y0 = pCenter.y;
		int x = (int)(pCenter.x + 0.5 * (cxEllipse) * cos(PI * 0.1));
		int y = (int)(pCenter.y - 0.5 * (cyEllipse) * sin(PI * 0.1));
		

		//SetTextAlign(hdc, TA_CENTER);


		MoveToEx(hdc, x, pCenter.y, NULL);
		LineTo(hdc, x0, y0);

		Arc(hdc, rcArc.left, rcArc.top,
			rcArc.right, rcArc.bottom,
			x0, y0, x, y);

		x0 = x;
		y0 = y;
		x = (int)(pCenter.x + 0.5 * cxEllipse * cos(PI * 0.05));
		y = (int)(pCenter.y - 0.6 * cyEllipse * sin(PI * 0.05));

		//SetTextAlign(hdc, TA_TOP | TA_BASELINE);
		TextOut(hdc, x, y, TEXT("10 %"), 4);

		MoveToEx(hdc, x0, pCenter.y, NULL);
		LineTo(hdc, x0, y0);

		hPen[0] = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
		SelectObject(hdc, hPen[0]);
		//---------------------- Вторая часть эллипса -----------------
		x = (int)(pCenter.x + 0.5 * (cxEllipse) * cos(PI * 0.65));
		y = (int)(pCenter.y - 0.5 * (cyEllipse) * sin(PI * 0.65));

		Arc(hdc, rcArc.left, rcArc.top, rcArc.right, rcArc.bottom, x0, y0, x, y);

		MoveToEx(hdc, x0, pCenter.y, NULL);
		LineTo(hdc, x, pCenter.y);

		x0 = x;
		y0 = y;
		x = (int)(pCenter.x + 0.5 * cxEllipse * cos(PI * 0.425));
		y = (int)(pCenter.y - 0.6 * cyEllipse * sin(PI * 0.425));

		TextOut(hdc, x, y, TEXT("65 %"), 4);
		MoveToEx(hdc, x0, y0, NULL);
		LineTo(hdc, x0, pCenter.y);
		//----------------------- Третья часть эллипса ----------------------

		hPen[0] = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
		SelectObject(hdc, hPen[0]);
		

		x = (int)(pCenter.x + 0.5 * cxEllipse * cos(PI));
		y = (int)(pCenter.y - 0.5 * cyEllipse * sin(PI));

		Arc(hdc, rcArc.left, rcArc.top, rcArc.right, rcArc.bottom, x0, y0, x, y);

		MoveToEx(hdc, x, y, NULL);
		LineTo(hdc, x0, pCenter.y);

		x = (int)(pCenter.x + 0.6 * cxEllipse * cos(PI*0.75));
		y = (int)(pCenter.y - 0.5 * cyEllipse * sin(PI*0.75));

		TextOut(hdc, x, y, TEXT("25 %"), 4);

		
		SelectObject(hdc, hPen[1]);
		DeleteObject(hPen[0]);
		EndPaint(hwnd, &ps);
		return 0;
	}
Мне не нравится моё решение, но пока не пойму, как вычислять координаты, ничего исправить не смогу.


Цитата:
Сообщение от macomics Посмотреть сообщение
cen - вычисляется относительно левого верхнего угла белого прямоугольника, а значит в ней записаны относительные координаты центра этого прямоугольника и одновременно радиусы эллипса.
Белого прямоугольника? может рабочей области окна? Или я что-то не так понял...
apofioz вне форума Ответить с цитированием
Старый 11.10.2022, 08:34   #10
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Цитата:
Сообщение от apofioz Посмотреть сообщение
Код:
x = (int)(pCenter.x + 0.5 * (cxEllipse) * cos(PI * 0.65));
		y = (int)(pCenter.y - 0.5 * (cyEllipse) * sin(PI * 0.65));
А ничего что новую область диаграммы надо откладывать от правой границы старой. т.е. первый сегмент 10%, тогда второй сегмент будет 10 + 65 = 75%

sin и cos не отсчитывается по вашему желанию относительно какой-то оси. Они всегда привязаны к координатным осям. Поэтому управлять этими функциями вы можете только задавая углы относительно осей координат.

Последний раз редактировалось macomics; 11.10.2022 в 09:51.
macomics вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нарисовать круговую диаграмму Proskurina Паскаль, Turbo Pascal, PascalABC.NET 2 08.11.2012 08:50
Нарисовать столбиковую диаграмму по результатам сдачи экзамена по матану Proskurina Паскаль, Turbo Pascal, PascalABC.NET 8 07.11.2012 23:14
Нарисовать столбиковую диаграмму Proskurina Помощь студентам 2 24.10.2012 13:40
Нарисовать диаграмму сравнения методов Gebbellz Помощь студентам 0 15.12.2010 17:52
нарисовать круговую диаграмму в паскале vbchristy46 Помощь студентам 2 28.06.2010 20:33