1)掌握3*3矩阵乘法运算的编程实现
2)掌握平移,比例,旋转三种基本二维几何变换矩阵生成
3)掌握相对于任意参考点的二维复合变换矩阵生成
1)设计实现二维图形变换类,具有平移、比例、旋转二维几何变换功能,以及相对于任意参考点的二维复合变换功能;
2)将2.2节直线类所绘制的如图2-3所示的菱形线框,绕最上端A点匀速旋转,并要求相对于A点来回缩放。
3) 使用双缓冲机制进行图形绘制,避免运动闪烁,所有图形先绘制到用户自定的DC,绘制完成后再统一拷贝到屏幕DC。
本次实是对上一次直线扫描转换的代码进行增改,无需新建工程。
代码实现:
#pragma once
class CP2
{
public:
CP2();
virtual~CP2();
CP2(double, double);
public:
double x;
double y;
double w;
};
class CLine
{
public:
CLine();
virtual~CLine();
void SetLineColor(COLORREF);
void MoveTo(CP2);
void MoveTo(double, double);
void LineTo(CP2, CDC*);
void LineTo(double, double, CDC*);
public:
CP2 P0;
CP2 P1;
COLORREF clr;
};
#include"pch.h"
#include"Line.h"
#include"math.h"
#define Round(d) int(floor(d+0.5))
CP2::CP2()
{
x = 0.0;
y = 0.0;
w = 1.0;
};
CP2::~CP2()
{}
CP2::CP2(double x, double y)
{
this->x = x;
this->y = y;
this->w = 1;
};
CLine::CLine()
{}
CLine::~CLine()
{}
void CLine::SetLineColor(COLORREF color)
{
clr = color;
}
void CLine::MoveTo(CP2 p0)
{
P0 = p0;
}
void CLine::MoveTo(double x, double y)
{
P0.x = x;
P0.y = y;
}
void CLine::LineTo(double x, double y, CDC* pDC)
{
CP2 p;
p.x = x;
p.y = y;
LineTo(p, pDC);
}
void CLine::LineTo(CP2 p1, CDC* pDC)
{
P1 = p1;
CP2 p, t;
if (fabs(P0.x - P1.x) < 1e-6)
{
if (P0.y > P1.y)
{
t = P0; P0 = P1; P1 = t;
}
for (p = P0; p.y < P1.y; p.y++)
{
pDC->SetPixelV(Round(p.x), Round(p.y), clr);
}
}
else
{
double k, d;
k = (P1.y - P0.y) / (P1.x - P0.x);
if (k > 1.0)
{
if (P0.y > P1.y)
{
t = P0; P0 = P1; P1 = t;
}
d = 1 - 0.5 * k;
for (p = P0; p.y < P1.y; p.y++)
{
pDC->SetPixelV(Round(p.x), Round(p.y), clr);
if (d >= 0)
{
p.x++;
d += 1 - k;
}
else
d += 1;
}
}
if (0.0 <= k && k <= 1.0)
{
if (P0.x > P1.x)
{
t = P0; P0 = P1; P1 = t;
}
d = 0.5 - k;
for (p = P0; p.x < P1.x; p.x++)
{
pDC->SetPixelV(Round(p.x), Round(p.y), clr);
if (d < 0)
{
p.y++;
d += 1 - k;
}
else
d -= k;
}
}
if (k >= -1.0 && k < 0.0)
{
if (P0.x > P1.x)
{
t = P0; P0 = P1; P1 = t;
}
d = -0.5 - k;
for (p = P0; p.x < P1.x; p.x++)
{
pDC->SetPixelV(Round(p.x), Round(p.y), clr);
if (d > 0)
{
p.y--;
d -= 1 + k;
}
else
d -= k;
}
}
if (k < -1.0)
{
if (P0.y > P1.y)
{
t = P0; P0 = P1; P1 = t;
}
d = -1 - 0.5 * k;
for (p = P0; p.y > P1.y; p.y--)
{
pDC->SetPixelV(Round(p.x), Round(p.y), clr);
if (d < 0)
{
p.x++;
d -= 1 + k;
}
else
d -= 1;
}
}
}
P0 = p1;
}
#pragma once
#include "Line.h"
class CTrans2D // 二维几何转换
{
public:
CTrans2D();
virtual~CTrans2D();
void SetPoints(CP2*, int);
void Identity();
void Translate(double, double); // 平移变换矩阵
void Rotate(double); // 旋转变换矩阵
void Scale(double, double); // 比例变换矩阵
void RotatePoint(double, CP2); // 相对于任意点的旋转变换矩阵
void ScalePoint(double, double, CP2); // 相对于任意点的比例变换矩阵
protected:
void MultiMatrix(); // 矩阵相乘
public:
double m_aT[3][3];
CP2* m_pPoints;
int m_iNum;
};
#include "pch.h"
#include"CTrans2D.h"
#include"math.h"
#define PI 3.14159
CTrans2D::CTrans2D()
{}
CTrans2D::~CTrans2D()
{}
void CTrans2D::SetPoints(CP2 *p, int n) {
m_pPoints = p;
m_iNum = n;
}
void CTrans2D::Identity()//单位矩阵
{
m_aT[0][0] = 1.0; m_aT[0][1] = 0.0; m_aT[0][2] = 0.0;
m_aT[1][0] = 0.0; m_aT[1][1] = 1.0; m_aT[1][2] = 0.0;
m_aT[2][0] = 0.0; m_aT[2][1] = 0.0; m_aT[2][2] = 1.0;
}
void CTrans2D::Translate(double tx, double ty)//平移变换矩阵
{
Identity();
m_aT[2][0] = tx;
m_aT[2][1] = ty;
MultiMatrix();
}
void CTrans2D::Rotate(double beta)//旋转变换矩阵
{
Identity();
double rad = beta*PI/180;
m_aT[0][0] = cos(rad); m_aT[0][1] = sin(rad);
m_aT[1][0] = -sin(rad); m_aT[1][1] = cos(rad);
MultiMatrix();
}
void CTrans2D::Scale(double sx, double sy)//比例变换矩阵
{
Identity();
m_aT[0][0] = sx;
m_aT[1][1] = sy;
MultiMatrix();
}
void CTrans2D::RotatePoint(double beta, CP2 p)//相对于任意点的旋转变换矩阵
{
Translate(-p.x, -p.y);
Rotate(beta);
Translate(p.x, p.y);
}
void CTrans2D::ScalePoint(double sx, double sy, CP2 p)//相对于任意点的整体比例变换矩阵
{
Translate(-p.x, -p.y);
Scale(sx, sy);
Translate(p.x, p.y);
//baotu
}
void CTrans2D::MultiMatrix()//矩阵相乘
{
CP2 * PNew = new CP2[m_iNum];
for (int i = 0; i < m_iNum; i++) {
PNew[i] = m_pPoints[i];
}
for (int j = 0; j < m_iNum; j++)
{
m_pPoints[j].x = PNew[j].x*m_aT[0][0] + PNew[j].y*m_aT[1][0] + PNew[j].w*m_aT[2][0];
m_pPoints[j].y = PNew[j].x*m_aT[0][1] + PNew[j].y*m_aT[1][1] + PNew[j].w*m_aT[2][1];
m_pPoints[j].w = PNew[j].x*m_aT[0][2] + PNew[j].y*m_aT[1][2] + PNew[j].w*m_aT[2][2];
}
delete []PNew;
}
只对TestView.cpp中的绘制函数进行修改,其他代码不变
需要导入头文件
#include "CTrans2D.h"
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CRect rect;
GetClientRect(&rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(rect.Width(), rect.Height());
pDC->SetViewportExt(rect.Width(), -rect.Height());
pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
/*rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);*/
CDC MemDC; // 内存DC
CBitmap NewBitmap, * pOldBitmap; // 内存中承载的临时位图
MemDC.CreateCompatibleDC(pDC); // 建立与屏幕pDC兼容的MemDC
NewBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); // 创建兼容位图
pOldBitmap = MemDC.SelectObject(&NewBitmap); // 将兼容位图选入MemDC
MemDC.FillSolidRect(rect, pDC->GetBkColor()); // 按原来背景填充客户区,否则未黑色
MemDC.SetMapMode(MM_ANISOTROPIC); // MemDC自定义坐标系与pDC相同
MemDC.SetWindowExt(rect.Width(), rect.Height());
MemDC.SetViewportExt(rect.Width(), -rect.Height());
MemDC.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
CLine* line = new CLine;
line->SetLineColor(RGB(0, 0, 0));
line->MoveTo(CP2(-rect.Width() / 2, 0));
line->LineTo(CP2(rect.Width() / 2, 0), &MemDC);
line->MoveTo(CP2(0, -rect.Height() / 2));
line->LineTo(CP2(0, rect.Height() / 2), &MemDC);
//绘制动态旋转
int a = 200;
CP2 points[4];
points[0].x = 0, points[0].y = a;
points[1].x = a, points[1].y = 0;
points[2].x = 0, points[2].y = -a;
points[3].x = -a, points[3].y = 0;
//===================================================
CP2 A(0, a);
CTrans2D tans;
tans.SetPoints(points, 4);
static float s = 1.0;
static float step = 0.01;
if (s >= 2.0 || s <= 0.5)
step = -step;
s += step;
tans.ScalePoint(s, s, A);
//匀速逆时针旋转
static float theta = 0.0;
theta += 1.0;
if (theta >= 360.0)
theta = 0.0;
tans.RotatePoint(theta, A);
//====================================================
//CP2 B(a, 0);
//CP2 C(0, -a);
//CP2 D(-a, 0);
line->SetLineColor(RGB(255, 0, 0));//红色
line->MoveTo(points[0]);
line->LineTo(points[1], &MemDC);
line->SetLineColor(RGB(0, 255, 0));//绿色
line->LineTo(points[2], &MemDC);
line->SetLineColor(RGB(0, 0, 255));//蓝色
line->LineTo(points[3], &MemDC);
line->SetLineColor(RGB(255, 255, 0));//黄色
line->LineTo(points[0], &MemDC);
delete line;
//====================================================
pDC->BitBlt(-rect.Width() / 2, -rect.Height() / 2, rect.Width(), rect.Height(), &MemDC, -rect.Width() / 2, -rect.Height() / 2, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
NewBitmap.DeleteObject();
Invalidate(FALSE);
}
实验结果:

这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in
给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at
我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[
Ruby中如何“一般地”计算以下格式(有根、无根)的JSON对象的数量?一般来说,我的意思是元素可能不同(例如“标题”被称为其他东西)。没有根:{[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]}根包裹:{"posts":[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]} 最佳答案 首先,withoutroot代码不是有效的json格式。它将没有包
目标我正在尝试计算自给定日期以来周的距离,而无需跳过任何步骤。我更喜欢用普通的Ruby来做,但ActiveSupport无疑是一个可以接受的选择。我的代码我写了以下内容,这似乎可行,但对我来说似乎还有很长的路要走。require'date'DAYS_IN_WEEK=7.0defweeks_sincedate_stringdate=Date.parsedate_stringdays=Date.today-dateweeks=days/DAYS_IN_WEEKweeks.round2endweeks_since'2015-06-15'#=>32.57ActiveSupport的#weeks