人机交互技术复习提纲(17-21)


#1
请定义一个类,存储指定文件夹下的所有文件名(含各级子文件夹),并写出该类的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Public Class clsDirectory
Public Files As List(Of String)
Public Directories As List(Of clsDirectory)

Public Sub New(PathName As String)
Create(PathName)
End Sub

Private Sub Create(PathName As String)
Files = Directory.GetFiles(PathName).ToList
directories = New List(Of clsDirectory)
Dim foldes() As String = Directory.GetDirectories(PathName)
For i = 0 To foldes.Count - 1
Directories.Add(New clsDirectory(foldes(i)))
Next
End Sub
End Class

#2
请编写函数,将指定的Tuple类型数据(例如:(“dad”, ”son”))插入到TreeView控件中。

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
知识点:Tuple(Of String, String):二元组类型。主要成员:Item1,Item2
Public Tuples As List(Of Tuple(Of String, String)) //树形结构中的二元关系集合
-----------------------------------------------------------------------------------------------------------------
Public Sub Append(tuple As Tuple(Of String, String))
If AppendNode(tuple) = True Then
//树中添加了节点,二元关系集合才能添加二元关系
Tuples.Add(tuple)
End If
End Sub

Private Function AppendNode(tuple As Tuple(Of String, String)) As Boolean
Dim parentnode As TreeNode = SearchNode(Root, tuple.Item1)
If parentnode Is Nothing Then Return False
parentnode.Nodes.Add(tuple.Item2)
Return True
End Function

//在node所表示的属性结构中,查找关键值为key的节点
Private Function SearchNode(node As TreeNode, key As String) As TreeNode
If node.Text = key Then Return node
For i = 0 To node.Nodes.Count - 1
Dim node1 As TreeNode = SearchNode(node.Nodes(i), key)
If node1 IsNot Nothing Then Return node1
Next
Return Nothing
End Function

#3
请编写函数,在TreeView控件中,删除text等于指定字符串的结点及其子树。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Public Sub Remove(key As String)
If RemoveNode(key) = False Then Return
For i = Tuples.Count - 1 To 0 Step -1
If Tuples(i).Item1 = key Or Tuples(i).Item2 = key Then
Tuples.RemoveAt(i)
End If
Next
End Sub

Private Function RemoveNode(key As String) As Boolean
Dim node As TreeNode = SearchNode(Root, key)
If node Is Nothing Then Return False
Dim parentnode As TreeNode = node.Parent()
If parentnode Is Nothing Then Return False //企图删除根节点
parentnode.Nodes.Remove(node)
Return True
End Function

#4
请编写函数,创建一列n个按钮控件,并指定每个按钮的Click事件。

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
Public Class clsButtonRow
Private Buttons As List(Of Button)
Private Width As Integer // 方形按钮的宽度
Private XGap As Integer //X方向按钮的间距
Private Start As Point //按钮集合的排列起点(左上角)

Public Sub New(frm As frmTest, Start As Point, ButtonN As Integer)
Me.Width = 25 : Me.XGap = 1
Me.Start = Start
// 创建按钮集合
CreateButtons(ButtonN)
//将按钮集合加入frm中
For i = 0 To ButtonN - 1
frm.Controls.Add(Buttons(i))
Next
frm.ResumeLayout(False)
//恢复正常的布局逻辑,可以选择强制对挂起的布局请求立即进行布局。
frm.PerformLayout()
//强制控件将布局逻辑应用于其所有子控件。
End Sub

Public Sub CreateButtons(ButtonN As Integer)
Buttons = New List(Of Button)
For i = 0 To ButtonN - 1
Buttons.Add(New Button)
With Buttons(i)
.Name = "btn" & i
.Text = ""
.TabIndex = i
.UseVisualStyleBackColor = True
.Size = New System.Drawing.Size(Width, Width)
.Location = New System.Drawing.Point(Start.X + i * (Width + XGap), Start.Y)
End With
AddHandler Buttons(i).Click, AddressOf Button_Click
Next
End Sub

Private Sub Button_Click(sender As Object, e As EventArgs)
MsgBox("Hello " & sender.name)
End Sub

End Class

#5
请举例说明Delegate类型的作用。

  • 可交互的后台任务类
    1 学习委托类型。其本质是指向函数的指针类型。委托对象是具体某个函数的地址。
    2 在跨线程操作的流程中,委托对象使得一个线程可以通知另一个线程,执行指定的操作。

界面窗体的引用:

1
2
3
4
Private frmOut As frmTest       //拥有控件的窗体,有权改写控件
Public Sub New(para As WorkerPara, frmOut As frmTest)
Me.frmOut = frmOut
End Sub

委托类型的定义:

1
Delegate Sub AppendMessage(id As Integer, msg As String) //函数类型

委托对象的定义、创建、使用

1
2
Private ReportProgress As AppendMessage  
'函数对象,向界面报告计算的进度

1
Me.ReportProgress = New AppendMessage(AddressOf frmOut.AppendMessage)
1
2
//在拥有控件的窗口线程上,用指定的参数列表执行指定委托函数。
frmOut.Invoke(ReportProgress, para.id, sum.ToString)

#6
请举例说明自定义事件的使用方法。

#7
请举例说明BackgroundWorker的使用方法。

  • BackgroundWorker是•net里用来执行多线程任务的控件
  • BackgroundWorker类(在单独的线程上执行操作)。
  • RunWorkerAsync方法:开始执行后台操作;
  • CancelAsync方法:请求取消挂起的后台操作。
  • 在程序中调用BackgroundWorker控件的RunWorkerAsync方法则会启动DoWork事件的事件处理,当DoWork事件处理完成时,则会触发RunWorkerCompleted事件。
    1
    2
    3
    例子:2开发环境->5多线程技术->2单个后台线程的运行过程
    附加:发射小球(多线程)
    功能:利用BackgroundWorker类的对象,在后台线程上,进行大计算,界面无停滞感觉。
  • (1)在frmTest窗口设计中,从工具箱拖拉一个BackgroundWorker控件至窗口下方,重命名为bkWork。
  • (2)在开始按钮的Click事件btnStart_Click中,开始执行后台操作:
    Me.bkWork.RunWorkerAsync(para),其中para是包装后的参数
  • (3)在bkWork_DoWork事件中,处理大计算操作。
  • (4)在bkWork_RunWorkerCompleted事件中,在文本框中显示大计算的结果:txtResult.Text = e.Result
  • (5)在取消按钮的Click事件btnCancel_Click中,请求取消挂起的后台操作: Me.bkWork.CancelAsync()

#8
请举例说明Parallel.For的使用方法。

#9
在智能输入中,用户在文本框中按键后,会显示输入提示,文本框将显示用户所确定的选项。请写出程序操作流程。

1
2
参考程序:3开发项目->1键盘操作->1智能输入->2词库类
功能:在文本框中输入字符,弹出单词选择窗口,用户可以输入字符,也可选择单词。
  • (1)frmListBox_Load事件中:读文件,初始化词库
  • (2)txtContent_KeyPress事件中:获取当前用户在文本框中输入字符串
    frm_WordSelected,frm_CharPress事件,GetLastChars()函数
    
  • (3)WordListInit(LastChars As String)中:显示最接近的单词集
    LastChars是指主窗口中正在输入的单词,已经输入的部分。
    
  • (4)lstWords_KeyPress事件中:接受输入的字符,将其传入主窗口的文本框中,同时调整当前选项的位置;
  • (5)lstWords_KeyPress事件中:接受空格字符,表示选定当前选项,并将选定单词传入主窗口的文本框中;

#10
在文本编辑中,常常有对命令序列的管理要求。请写出基本操作的类型定义,及命令序列的存储结构。

1
参考程序:3开发项目->1键盘操作->1智能输入->4操作历史->2回退&前进

##基本操作的类型定义:

###(1)操作虚类

1
2
3
4
5
Public MustInherit Class clsOp
Public MustOverride Sub DoWork(txtContent As TextBox)
Public MustOverride Sub UnDo(txtContent As TextBox)
End Class
无子过程

###(2)插入类,继承于操作虚类

1
2
3
4
//在position之前插入newchars 
Public Class clsInsertOp
Inherits clsOp
Private position As Integer, newchars As String

###(3)更新类,继承于操作虚类

1
2
3
4
5
6
7
Public Class clsUpdateOp
Inherits clsOp
Private position As Integer, length As Integer
Private oldchars As String, newchars As String
// 替换前的旧文本, 替换后的新文本
包含的子过程:
New(position As Integer, length As Integer, oldchars As String, newchars As String)(其他同上)

###(4)删除类,继承于操作虚类

1
2
3
4
5
6
7
8
9
//从position开始删除长度为length的字符串
Public Class clsDeleteOp
Inherits clsOp
Private position As Integer, length As Integer
Private deletetxt As String
// 删除的文本
包含的子过程:
New(position As Integer, length As Integer, deletetxt As String)
(其他同上)

##命令序列的存储结构:

###(5)操作集合类

1
2
3
Public Class clsOps
Private Ops As List(Of clsOp), ith As Integer
End Class

#11
在图像处理中,位图的数据类型是什么?举例说明如何读写像素?

1
参考程序:3开发项目->2图像处理->1图像读写与分析->1图像文件及像素RGB的读写

位图的数据类型:Bitmap
Bitmap类:用于处理由像素数据定义的图像的对象。
读写像素举例:

##(1)在picturebox picCanvas中打开显示图像:

1
2
3
4
5
6
7
Fname = "Tulips.jpg"
Source = New Bitmap(Fname) //在图像计算中,用作数据源
Target = New Bitmap(Source) // 用于显示
picCanvas.Image = Target
// Bitmap是Image(虚类)的子类
picCanvas.Width = Target.Width
picCanvas.Height = Target.Height

##(2)保存图像:

1
2
Dim Fname1 As String = "Tulips1.jpg"
Target.Save(Fname1)

##(3)图像的操作(修改像素):

1
2
3
4
    // GetPixel、SetPixel
Dim oldcolor As Color = Source.GetPixel(i, j)
newcolor = Color.FromArgb(oldcolor.R, 0, 0)
Target.SetPixel(i, j, newcolor)

注:FromArgb(R,G,B)从指定的8位颜色值(红绿蓝)创建system.drawing.color结构。

#12
在播放幻灯片时,有许多图像切换特效。请举例说明其实现方法。

通过文件名获得source原图片,并设置target图片的宽和高,设置picturebox控件中的图片为target暂时为空,并设置picturebox的宽和高为target的 宽和高
百叶窗效果:
①//自定义一个timer控件

1
2
3
4
5
Private WithEvents Timer1 As System.Windows.Forms.Timer 
并设置这个控件的属性(在btnOpen_Click()事件中添加)
Timer1 = New System.Windows.Forms.Timer //创建一个类的对象
Timer1.Interval = 50 //设置tick时间发生的时间间隔为50ms
Timer1.Enabled = True //使timer控件中的timer事件有效

②添加Timer 的tick事件,每经过Interval属性指定的时间间隔时发生一次
根据单选按钮Radio的check值选择执行DisplayVertical函数还是DisplayHorizontal函数

1
2
3
4
5
6
Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles Timer1.Tick
Const dx As Integer = 5, dy As Integer = 5
If RadioVertical.Checked = True Then DisplayVertical(dx)
If RadioHorizontal.Checked = True Then DisplayHorizontal(dy)
picCanvas.Refresh()
End Sub

③添加 DisplayVertical (dx As Integer)函数 垂直百叶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Private Sub DisplayVertical(dx As Integer)
Static xStart As Integer = 0
If xStart >= Source.Width Then
xStart = 0 : Timer1.Enabled = False
End If
For x = xStart To xStart + dx - 1
If x >= Source.Width Then Exit For //如果像素点横坐标超过图片宽度则退出循环
For y = 0 To Source.Height - 1
Dim c As Color = Source.GetPixel(x, y)
Target.SetPixel(x, y, c)
Next
Next
xStart += dx
End Sub

#13
区域选择是图像处理中的基本操作,请说明区域选择的方法,区域的数据结构,及可能的操作。

##区域的数据结构:
01.png-40.3kB
02.png-24kB

##区域选择的方法:

  • 首先创建BitmapModifier对象,在创建的过程中通过new函数将SourceBuff中符合条件的像素值,改为Mark色,写入TargetBuff
  • 然后通过GetRegions函数根据Mark色识别、创建区域,保存到区域集合对象中
1
2
3
4
5
6
7
8
9
//构造函数
Public Sub New(fname As String, red As Tuple(Of Integer, Integer), green As Tuple(Of Integer, Integer), blue As Tuple(Of Integer, Integer), Mark As Color)

//GetRegions函数 通过像素点的颜色值来选择的,RGB的颜色值在上面范围呢,就选中
//在TargetBuff中,根据Mark识别、创建区域,保存到区域集合对象中
Function GetRegions() As clsRegions

//bfs函数
Private Function Bfs(Buff As Bitmap, sp As Point, flagMatrix(,) As Boolean) As List(Of Point)

##可能的操作

  • 定义了red,green,blue三个二元组。
  • 当点击form上的open按钮获得图片,此时同时设置这三个二元组(这个作为区域内点的颜色范围),
  • 创建BitmapModifier对象根据区域内点的颜色范围为source图片标记mark色(在构造函数里)。
  • 当点击GetRegions函数时,调用BitmapModifier类的GetRegions函数和Regions的FillList函数

#14
绘图软件中,图形对象的管理是如何实现的?请写出图元类的结构定义。

##图形对象的管理

  • 定义抽象基类clsElem,类clsLine、clsRectangle等图形类继承它
  • 定义类clsElems作为图形元素的集合类,其数据成员是List类型存放clasElem对象。
  • 绘图时,创建一个clsElems的对象Elems作为存储图形元素的对象,
  • 当鼠标按下并抬起后创建直线或矩形等图形对象,并将其添加到Elems中。

##图元类的结构定义

###抽象类:clsElem

1
2
3
Public MustInherit Class clsElem
Public MustOverride Sub Draw(ByVal g As Graphics)
End Class

###子类1直线类:clsElem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Class clsLine
Inherits clsElem

Private sp, ep As PointF

Public Sub New(ByVal sp As PointF, ByVal ep As PointF)
Me.sp = sp : Me.ep = ep
End Sub

Public Overrides Sub Draw(g As Graphics)
Dim myPen As New Pen(Color.Red, 1)
g.DrawLine(myPen, sp, ep)
End Sub
Public Overrides Function ToString() As String
Dim s As String = "Line "
s = s & ": " & sp.ToString & "," & ep.ToString
Return s
End Function

End Class

###类clsElems:

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
Public Class clsElems
Public elems As List(Of clsElem)
Event Redraw()

Public Sub New()
elems = New List(Of clsElem)
End Sub
Public Sub Append(e As clsElem)
elems.Add(e)
RaiseEvent Redraw()
End Sub

Public Sub Draw(ByVal g As Graphics)
For i = 0 To elems.Count - 1
elems(i).Draw(g)
Next
End Sub

Public Function Count() As Integer
Return elems.Count
End Function
Public Function GetElem(index As Integer) As clsElem
Return elems(index)
End Function
End Class

#15
绘图软件中,用户应能设定作图的范围,并在该范围内利用鼠标绘图。请写出实现方法。

##变换矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Class clsMatrix3
Private M11, M12, M13 As Single
Private M21, M22, M23 As Single
Private M31, M32, M33 As Single

Public Sub New()
M11 = 1 : M12 = 0 : M13 = 0
M21 = 0 : M22 = 1 : M23 = 0
M31 = 0 : M32 = 0 : M33 = 1
End Sub
Sub New(a As Single, b As Single, c As Single, d As Single)
M11 = a : M12 = 0 : M13 = 0
M21 = 0 : M22 = c : M23 = 0
M31 = b : M32 = d : M33 = 1
End Sub

Function Tranform(p As PointF) As PointF
Dim newp As PointF
newp.X = p.X * M11 + p.Y * M21 + M31
newp.Y = p.X * M12 + p.Y * M22 + M32
Return newp
End Function

End Class

##转换公式

1
2
3
4
5
6
7
8
9
10
11
12
13
通过Lp2Dp函数可以将逻辑坐标转为设备坐标
Public Function Lp2Dp(Lp As PointF) As Point
Dim p As PointF = M_Lp2Dp.Tranform(Lp)
Dim newp As Point
newp.X = p.X : newp.Y = p.Y
Return newp
End Function

通过Dp2Lp函数可以将设备坐标转为逻辑坐标
Public Function Dp2Lp(Dp As Point) As PointF
Return M_Dp2Lp.Tranform(Dp)
End Function
End Function

定义两个数据成员:

1
2
Private CS As clsCS  //picCanvas中的坐标系
Dim DBox, LBox As clsBox //设备坐标、逻辑坐标的范围

窗口在初始化时设置设备坐标,逻辑坐标,坐标系的值,其中逻辑坐标范围是由用户设定的,根据DBox和LBox设置picCanvas中的坐标系

1
2
3
4
5
6
7
8
Private Sub frmTest_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DBox = New clsBox(0, picCanvas.Width, picCanvas.Height, 0)
LBox = New clsBox(txtXmin.Text, txtXmax.Text, txtYmin.Text, txtYmax.Text)
CS = New clsCS(DBox, LBox)
Lines = New clsLines : Polygon = Nothing
Flag = OpFlag.Create : tvPoints.Nodes.Add(Lines.Node)
Redraw()
End Sub

当设置作图范围的按钮按下时,逻辑坐标的范围将重置并重新设定作图范围

1
2
3
4
5
Private Sub btnSetup_Click(sender As System.Object, e As System.EventArgs) Handles btnSetup.Click
LBox = New clsBox(txtXmin.Text, txtXmax.Text, txtYmin.Text, txtYmax.Text)
CS = New clsCS(DBox, LBox)
Redraw()
End Sub

重新设定作图范围,首先将整个绘图界面清除并填充为白色,通过调用CS的Draw函数为作图区域作坐标系

1
2
3
4
5
6
7
Private Sub Redraw()
Dim g As Graphics = picCanvas.CreateGraphics
g.Clear(Color.White)
CS.Draw(g)
If Flag = OpFlag.Create Then Lines.Draw(g, CS)
If Flag = OpFlag.Modify Then Polygon.Draw(g, CS)
End Sub

CS的Draw函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Public Sub Draw(g As Graphics)
//通过Lp2Dp()函数和sp,ep的横坐标画出坐标系的横坐标
Dim myPen = New Pen(Color.Blue, 1)
Dim sp, ep As PointF
sp.X = LBox.xmin : sp.Y = 0
ep.X = LBox.xmax : ep.Y = 0
Dim sp1 As Point = Lp2Dp(sp)
Dim ep1 As Point = Lp2Dp(ep)
g.DrawLine(myPen, sp1, ep1)

//通过Lp2Dp()函数和sp,ep的纵坐标画出坐标系的横坐标
sp.X = 0 : sp.Y = LBox.ymin
ep.X = 0 : ep.Y = LBox.ymax
Dim sp2 As Point = Lp2Dp(sp)
Dim ep2 As Point = Lp2Dp(ep)
g.DrawLine(myPen, sp2, ep2)
End Sub

#16
绘图软件中,创建图形对象中的橡皮筋技术、图形变换中的拖动技术,极大的改善了绘图界面,请说明其中的事件流程。

##橡皮筋技术

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
55
56
57
58
59
class CEx1View : public CView
{
protected:
CPoint m_prev, m_ep;
void CEx1View::OnLButtonDown(UINT nFlags, CPoint point)
{
CView::OnLButtonDown(nFlags, point);
m_prev=point; m_ep=point;
CDC *pDC=GetDC();
pDC->SetROP2(R2_NOTXORPEN);
if(m_tool==1)
{ CLine oldline(m_prev,m_ep );
oldline.SetColor(m_color); oldline.Draw(pDC);
}
if(m_tool==2)
{ double oldr=…………;
CCircle oldcircle(m_prev,oldr);
oldcircle.SetColor(m_color); oldcircle.Draw(pDC);
}
SetCapture();
}
void CEx1View::OnMouseMove(UINT nFlags, CPoint point)
{
if(nFlags!=MK_LBUTTON) return;
CDC *pDC=GetDC();
pDC->SetROP2(R2_NOTXORPEN);
if(m_tool==1)
{ CLine oldline(m_prev,m_ep );
oldline.SetColor(m_color); oldline.Draw(pDC);
CLine newline(m_prev,point);
newline.SetColor(m_color); newline.Draw(pDC);
}
if(m_tool==2)
{ double oldr=…………;
CCircle oldcircle(m_prev,oldr);
oldcircle.SetColor(m_color); oldcircle.Draw(pDC);
double newr=…………;
CCircle newcircle(m_prev,newr);
newcircle.SetColor(m_color); newcircle.Draw(pDC);
}
m_ep=point;
CView::OnMouseMove(nFlags, point);
}
void CEx1View::OnLButtonUp(UINT nFlags, CPoint point)
{ ……………………
CEx1Doc* pDoc = GetDocument();
………
pDoc->AddElem(pline);
ReleaseCapture();
Invalidate(true);
}
void CEx1View::OnDraw(CDC* pDC)
{
pDC->SetROP2(R2_COPYPEN);
for(int i=0; i<pDoc->GetElemCount(); i++)
{ CElem *pelem=pDoc->GetElem(i);
pelem->Draw(pDC);
}
}

##拖动技术

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
class CEx1View : public CView
{ ……………
CLine *m_pLine;
CCircle *m_pCircle;
CPoint m_prev, m_ep;
void CEx1View::OnMouseMove(UINT nFlags, CPoint point)
{
if(nFlags!=MK_LBUTTON) return;
CDC *pDC=GetDC();
pDC->SetROP2(R2_NOTXORPEN);
if(m_tool==1)
{ CLine oldline(*m_pLine);
oldline.Pan(m_ep-m_prev); oldline.Draw(pDC);
CLine newline(*m_pLine);
newline.Pan(point-m_prev);newline.Draw(pDC);
}
if(m_tool==2)
{ CCircle oldcircle(*m_pCircle);
oldcircle.Pan(m_ep-m_prev); oldcircle.Draw(pDC);
CCircle newcircle(*m_pCircle);
newcircle.Pan(point-m_prev);newcircle.Draw(pDC);
}
m_ep=point;
CView::OnMouseMove(nFlags, point);
}
void CEx1View::OnLButtonUp(UINT nFlags, CPoint point)
{
CView::OnLButtonUp(nFlags, point);
if(m_tool==1) m_pLine->Pan(point-m_prev);
if(m_tool==2) m_pCircle->Pan(point-m_prev);
ReleaseCapture();
Invalidate(true);
}

#17

绘图软件中,图形对象的点选择,是如何实现的?请写出相关的类中的方法接口。

1
项目存在于:0000讲义\09 二维图形项目\3 图形对象的选择技术\1 点选择图形

下面是经过我筛选的代码图
1.png-49.9kB

经过代码分析,关系图如上所示,结论如下:

  • 基类clsElem里面定义了必须重写的纯需函数SelectBypoint();
  • clsElems类是面向窗体,管理所有元素的类,其中的SelectBypoint()调用元素的函数:elems(i).SelectByPoint(p),只要有一个为真,判断终止,返回元素编号,否则返回-1
  • clsLine继承clsElem,重写了SelectBypoint,并设有同名的共享函数,用于计算是否选中(判断过程是,看选中点是否在起点到终点的直线段上,运行存在delta的误差),同时也方便其他类的调用
  • clsRectangle继承clsElem,重写了SelectBypoint方法,在其中构造4组起点终点,调用clsLine中的共享函数,只要有一组为真,就被选中
  • clsPolygon继承clsElem,重写了SelectBypoint,从它的KeyPoints数组中,依次抽出两点,判断并迭代更新,只要有一个为真,就被选中
1
2
类接口:
SelectBypoint();

#18
绘图软件和图像处理中,都存在线性变换,请写出平移、变比、旋转的变换矩阵。

平移:相对坐标原点平移$(Tx,Ty)$
\begin{equation}
T_t=
\left[
\begin{array}{ccc}
1 & 0 & 0 \
0 & 1 & 0 \
Tx & Ty & 1
\end{array}
\right]
\end{equation}

变比:相对坐标原点,沿x方向缩放Sx倍,沿y方向缩放Sy倍:
\begin{equation}
T_s=
\left[
\begin{array}{ccc}
Sx & 0 & 0 \
0 & Sy & 0 \
0 & 0 & 1
\end{array}
\right]
\end{equation}

旋转:转过$θ$角

\begin{equation}
T_r=
\left[
\begin{array}{ccc}
cosθ & sinθ & 0 \
-sinθ & cosθ & 0 \
0 & 0 & 1
\end{array}
\right]
\end{equation}


#19
良好的绘图软件,应该支持层次化的图形对象结构。请写出自定义块类和块插入对象的类定义。

1
项目存在于:0000讲义\二位图形项目1-5\5 层次化的对象结构\2 自定义块的管理

自定义块类
03.png-24.2kB

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

Public Class clsBlock
Private Elems As List(Of clsElem)
Private BasePoint As PointF
Public Sub New(ByVal Elems As clsSelection, ByVal BasePoint As PointF)
Public Function Count() As Integer
Public Function Item(ByVal index As Integer) As clsElem
Public Function GetBasePoint() As PointF
End Class
```
>+ 属性:
> 1. **Elems**
存储当前被选中的元素集合,来源于clsSelection.clone()
> 2. **BasePoint**
基点(0,0) 可以是其他点
>+ 函数
>1. **New(ByVal Elems As clsSelection, ByVal BasePoint As PointF)**
构造函数
>2. **Count()**
返回块对象中基本元素个数
>3. **Item(ByVal index As Integer)**
返回块对象中第index个个基本元素的引用
>4. **GetBasePoint()**
返回基点位置


**块插入对象的类定义**
![04.png-41.8kB][5]

Public Class clsBlockInsert
Inherits clsElem
Private Block As clsBlock
Private M As clsMatrix3 对Block中所有图形对象的变换矩阵
Public Sub New(ByVal Block As clsBlock, ByVal InsertPoint As PointF, ByVal scaleX As Single, ByVal scaleY As Single, ByVal angle As Single)
Public Sub New(ByVal Block As clsBlock, ByVal M As clsMatrix3)
Public Overrides Function Clone() As clsElem
Public Overrides Function ToString() As String
Public Overrides Sub Transform(ByVal m As clsMatrix3)
End Class

`

这个类本身继承与clsElem,所以可以被当成基本元素操作

  • 属性:
  1. Block
    被定义的块
  2. M
    对Block中所有图形对象的变换矩阵
  • 函数
  1. New(ByVal Block As clsBlock, ByVal InsertPoint As PointF, ByVal scaleX As Single, ByVal scaleY As Single, ByVal angle As Single)
    构造函数,根据参数构造变换矩阵
  2. New(ByVal Block As clsBlock, ByVal M As clsMatrix3)
    构造函数,直接配置矩阵
  3. Clone()
    构造一个对象返回,值相同
  4. ToString()
    ToString表明位置
  5. Transform(ByVal m As clsMatrix3)
    根据矩阵变换

#20
在绘图软件中,图形对象的属性包括什么?如何实现属性的共性、个性管理?
???


#21
在本学期的学习中,你了解了不少软件项目,请写出10个名称及简单功能。

  • 1 资源管理器:用控件显示文件资源,并有简单的操作
  • 2 扫雷软件:扫雷游戏,创建button,并集成用户控件
  • 3 表达式计算器:输入表达式,按步骤求结果
  • 4 多线程,并行计算填图:利用多线程技术,进行并行运算
  • 5 智能输入:利用键树,达到智能提示的效果
  • 6 绘图软件:绘制图形,选中,变换图形
  • 7 积木摆放:较好的摆放积木块,三维
  • 8 朗读文章:可以朗读英文单词
  • 9 图像变化:可以做到图像的效果变换
  • 10 图像拟合图形:可以提取边界,进行边界重组等