求绘制的图形可以像图片那样旋转
举报
能不能更新一版可旋转的绘制图形
举报
你可以把绘制图形绘制的对象设置为图片,然后可以直接旋转图片,再或者使用 正弦和余统函数来进行三角变换来旋转你的绘制图形:
例如下面的代码是一个基本的示例:
#include <graphics.h>
#include <math.h>
#include<stdio.h>
#define PI1 3.14159265358979323846
class vectorline
{
// 封装的内部变量。
private:
// 矢量直线是基于缓冲区绘图的。
DWORD* g_pBuf11 = GetImageBuffer();
// 矢量直线的透明度和线宽变量声明。
int alpha = 128, linesize1 = 1;
// 矢量直线要用到旋转。
double PI = 3.1415926535;
// 这一块属于是缓冲区画点里的变量。
int WIDTH = getwidth(), HEIGHT = getheight(), puti = 0;
int r1 = 0, g1 = 0, b1 = 0, r2 = 0, g2 = 0, b2 = 0;
COLORREF backdropcolor = 0, rgb_alpha = 0, color = WHITE;
// 这一块是绘图直线的变量,是属于矢量直线 line_ss 函数,这边负责,把直线矢量化的关键操作。
int dxss = 0, dyss = 0, stepsss = 0;
float xIncrementss = 0, yIncrementss = 0, xss = 0, yss = 0;
// 这一块是绘图直线的变量,是属于矢量直线 line_sss 函数,是负责分段绘图矢量直线,例如:上边和下边,同时也是控制矢量直线的粗细宽度。
int dxsss = 0, dx1sss = 0, dysss = 0, dy1sss = 0, dsss = 150, d1sss = 150, stepssss = 0, steps1sss = 0;
float xIncrementsss = 0,
xIncrement1sss = 0,
yIncrementsss = 0,
yIncrement1sss = 0,
xsss = 0, x111sss = 0,
ysss = 0, y111sss = 0;
// 计算待转换坐标 (x2, y2) 相对于确定坐标 (x1, y1) 的相对坐标
double relativeX = 0, relativeY = 0, radians = 0, degrees = 0;
double a = 0, a11 = 0, a1 = 0, a22 = 0;
int s = 0;
public:
// 设置矢量直线透明度函数。
void linealpha(int al) { alpha = al; }
// 设置矢量直线颜色函数。
void linecolor(COLORREF color1) { color = color1; setlinecolor(color1); }
// 设置矢量直线粗细大小。
void linesize(int size) { linesize1 = size / 3; }
// 快速缓冲区半透明画点函数 2
void putpixealpha(int x, int y)
{ // 把坐标转换为,缓冲区位数。
puti = y * WIDTH + x;
// 如果 puti 超出缓冲区范围,直接返回。
if (puti < 0 || puti >= (WIDTH * HEIGHT)) { return; }
// 读取屏幕所有绘图下方的颜色进行半透明混合。
backdropcolor = BGR(g_pBuf11[puti]);
// 在半透明计算前的颜色分配。
r1 = GetRValue(color), g1 = GetGValue(color), b1 = GetBValue(color),
r2 = GetRValue(backdropcolor), g2 = GetGValue(backdropcolor), b2 = GetBValue(backdropcolor);
// 进行半透明核心算法计算。
rgb_alpha = RGB((r1 * alpha + r2 * (256 - alpha)) >> 8, (g1 * alpha + g2 * (256 - alpha)) >> 8, (b1 * alpha + b2 * (256 - alpha)) >> 8);
// 把半透明混合计算后的结果写入缓冲区。
g_pBuf11[puti] = BGR(rgb_alpha);
}
// 普通半透明缓冲区直线(DDA 算法,效率虽低,但矢量化效果的最好),用于把一条直线矢量化的关键函数,只矢量化一条粗直线的边缘。
void line_ss(int x1, int y1, int x2, int y2)
{ // DDA 算法过程。
dxss = x2 - x1;
dyss = y2 - y1;
stepsss = abs(dxss) > abs(dyss) ? abs(dxss) : abs(dyss);
xIncrementss = dxss / (float)stepsss;
yIncrementss = dyss / (float)stepsss;
xss = x1;
yss = y1;
// 绘图矢量直线里的半透明画点。
for (int i = 0; i <= stepsss; i++)
{
putpixealpha((int)xss, (int)yss);
xss += xIncrementss;
yss += yIncrementss;
}
}
// 双层 DDA 直线,用于绘制矢量直线,x1, y1, 到 x2, y2,的长度里宽度里的直线内容,包括矢量化的边和,中间的填充直线。
void line_sss(int x1, int y1, int x2, int y2, int x11, int y11, int x22, int y22)
{
// 双层 DDA 直线算法,效率比 Bresenham 效果好,线条厚。
dxsss = x2 - x1, dx1sss = x22 - x11,
dysss = y2 - y1, dy1sss = y22 - y11,
stepssss = abs(dxsss) > abs(dysss) ? abs(dxsss) : abs(dysss),
steps1sss = abs(dx1sss) > abs(dy1sss) ? abs(dx1sss) : abs(dy1sss);
xIncrementsss = dxsss / (float)stepssss,
xIncrement1sss = dx1sss / (float)steps1sss,
yIncrementsss = dysss / (float)stepssss,
yIncrement1sss = dy1sss / (float)steps1sss,
xsss = x1, x111sss = x11,
ysss = y1, y111sss = y11;
// 如果小于 4 就把矢量线进一步细化,与普通直线大小差不多。
if (linesize1 < 4)stepssss = stepssss / 2;
// 核心程序,开始矢量化直线边缘和用直线填充矢量直线中间,并连接矢量直线宽度上的所有线。
for (int i = 0; i <= stepssss; i++)
{
// 绘制矢量直线中间空的线,因为矢量化是矢量直线的边缘。
if (i < stepssss - 3) { line((int)xsss, (int)ysss, (int)x111sss, (int)y111sss); }
if (i >= stepssss - 3)
{
// 控制细线矢量精度专用透明比例。
if (linesize1 < 4)
{
if (i == stepssss - 4) { linealpha(250); }
else if (i == stepssss - 3) { linealpha(120); }
else if (i == stepssss - 2) { linealpha(80); }
else if (i == stepssss - 1) { linealpha(40); }
else if (i == stepssss) { linealpha(20); }
}
else
{
// 控制粗线矢量精度专用透明比例。
if (i == stepssss - 4) { linealpha(180); }
else if (i == stepssss - 3) { linealpha(150); }
else if (i == stepssss - 2) { linealpha(120); }
else if (i == stepssss - 1) { linealpha(90); }
else if (i == stepssss) { linealpha(60); }
}
// 下面算法是把半透明直线,线相互交合起来,缺一不可,已经调教成最好配方了,是矢量化直线边缘核心函数,不参与矢量线中间段绘图。
line_ss((int)xsss, (int)ysss, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss + 1, (int)x111sss, (int)y111sss + 1);
line_ss((int)xsss, (int)ysss + 1, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss, (int)x111sss, (int)y111sss + 1);
line_ss((int)xsss, (int)ysss - 1, (int)x111sss, (int)y111sss - 1);
line_ss((int)xsss, (int)ysss - 1, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss, (int)x111sss, (int)y111sss - 1);
line_ss((int)xsss - 1, (int)ysss, (int)x111sss - 1, (int)y111sss);
line_ss((int)xsss - 1, (int)ysss, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss, (int)x111sss - 1, (int)y111sss);
line_ss((int)xsss + 1, (int)ysss, (int)x111sss + 1, (int)y111sss);
line_ss((int)xsss + 1, (int)ysss, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss, (int)x111sss + 1, (int)y111sss);
line_ss((int)xsss + 1, (int)ysss - 1, (int)x111sss + 1, (int)y111sss - 1);
line_ss((int)xsss + 1, (int)ysss - 1, (int)x111sss, (int)y111sss);
line_ss((int)xsss, (int)ysss, (int)x111sss + 1, (int)y111sss - 1);
}
xsss += xIncrementsss;
ysss += yIncrementsss;
x111sss += xIncrement1sss;
y111sss += yIncrement1sss;
}
}
// 绘图一条矢量直线,也是矢量系统的启动核心线函数。
void linev(int x1, int y1, int x2, int y2)
{
// 设置线条粗细为 2,对半透明直线无效,只对矢量中间普通画线生效。
setlinestyle(PS_SOLID, 2);
// 计算待转换坐标 (x2, y2) 相对于确定坐标 (x1, y1) 的相对坐标。
relativeX = x2 - x1;
relativeY = y2 - y1;
radians = atan2(relativeY, relativeX);
// 将弧度转换为角度。
degrees = radians * 180 / -PI;
// 将角度限制在 0 到 360 之间。
if (degrees < 0) { degrees += 360; }
// 角度给值,以经设定好了数值。
a = degrees,
a11 = degrees;
s = 0;
a = -a + 225,
a11 = -a11 + 225;
a1 = a + 180, a22 = a11 + 181;
// 在用鼠标控制矢量直线会随便鼠标移动,鼠标旋转,而端点也会随着旋转角度,保证矢量直线绘制的完成,不可缺少!
// 矢量线分两个线组成,例如:在水平线上,从直线中间开始,分别绘制上半段,与下半段,会随着角度的变化而变化,不固定。
line_sss
(
x1, y1,
(linesize1)*cos(a / 57.29) - linesize1 * sin(a / 57.29) + x1,
(linesize1)*sin(a / 57.29) + linesize1 * cos(a / 57.29) + y1,
x2, y2,
(linesize1)*cos(a11 / 57.29) - linesize1 * sin(a11 / 57.29) + x2,
(linesize1)*sin(a11 / 57.29) + linesize1 * cos(a11 / 57.29) + y2
);
// 在用鼠标控制矢量直线会随便鼠标移动,鼠标旋转,而端点会随着旋转角度,保证矢量直线绘制的完成,不可缺少!
// 矢量线分两个线组成,例如:在水平线上,从直线中间开始,分别绘制上半段,与下半段,会随着角度的变化而变化,不固定。
line_sss
(
x1, y1,
(linesize1)*cos(a1 / 57.29) - linesize1 * sin(a1 / 57.29) + x1,
(linesize1)*sin(a1 / 57.29) + linesize1 * cos(a1 / 57.29) + y1,
x2, y2,
(linesize1)*cos(a22 / 57.29) - linesize1 * sin(a22 / 57.29) + x2,
(linesize1)*sin(a22 / 57.29) + linesize1 * cos(a22 / 57.29) + y2
);
}
};
int main()
{
initgraph(640, 480);
vectorline v;
v.linecolor(RGB(176,8,76));
int xxx = 0;
BeginBatchDraw();
while(1)
{
// 定义正方体的 8 个顶点坐标
int x[8] = { -50, 50, 50, -50, -50, 50, 50, -50 };
int y[8] = { 50, 50, -50, -50, 50, 50, -50, -50 };
int z[8] = { 50, 50, 50, 50, -50, -50, -50, -50 };
bool a=true;
// 定义旋转角度和旋转中心坐标
double angle = 0;
int cx = 320;
int cy = 240;
while (a)
{
if(xxx==120)
{
xxx=0;
break;
}
xxx++;
// 清空屏幕
cleardevice();
// 绘制正方体
for (int i = 0; i < 4; i++)
{
v.linev(x[i] + cx, y[i] + cy, x[i + 4] + cx, y[i + 4] + cy);
v.linev(x[i] + cx, y[i] + cy, x[(i + 1) % 4] + cx, y[(i + 1) % 4] + cy);
v.linev(x[i + 4] + cx, y[i + 4] + cy, x[(i + 1) % 4 + 4] + cx, y[(i + 1) % 4 + 4] + cy);
}
// 计算旋转后的坐标
for (int i = 0; i < 8; i++)
{
int x1 = x[i];
int y1 = y[i] * cos(angle) + z[i] * sin(angle);
int z1 = -y[i] * sin(angle) + z[i] * cos(angle);
x[i] = x1 * cos(angle) - z1 * sin(angle);
y[i] = y1;
z[i] = x1 * sin(angle) + z1 * cos(angle);
}
// 更新旋转角度
angle += PI1 / 180;
// 延时一段时间
Sleep(50);
FlushBatchDraw();
}
}
EndBatchDraw();
closegraph();
return 0;
}