现在的位置: 首页 > 综合 > 正文

笔记9:GraphicsPath对象

2013年02月05日 ⁄ 综合 ⁄ 共 13677字 ⁄ 字号 评论关闭

01 GraphicsPath对象
   它由一系列相互连接的直线、曲线连接起来组成的开放(非闭合)图形。
   创建路径时就会隐式创建一个新图形(由上面的直线、曲线等组成)。也可以
                 显示地声明StartFigure。
          
   图形具有方向,其先后顺序加入的直线、曲线等就表明了次序。

   一般图形路径是开放的,由起点,到最后图形(终点)。也可以用ClosedFigure显式

   声明为闭合图形(比如填充和剪辑时要用)


'01.GraphicsPath图形路径,表示用一系列先后顺序的形状组成的图形
Imports System.Drawing
Imports System.Drawing.Drawing2D

Public Class Form1
    Dim gr As Graphics = Me.CreateGraphics
    Dim gp As New GraphicsPath
    Dim pn As New Pen(Color.Red, 2)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        gp.AddLine(New Point(0, 0), New Point(30, 20))
        gr.DrawPath(pn, gp)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        gp.AddEllipse(New Rectangle(20, 20, 20, 40))
        gr.DrawPath(pn, gp)
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        gp.AddBezier(New Point(30, 60), New Point(70, 60), New Point(50, 30), New Point(100, 10))
        gr.DrawPath(pn, gp)
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        gp.AddPie(New Rectangle(120, 0, 70, 70), 70, -90)
        gr.DrawPath(pn, gp)
    End Sub

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        Dim pts As Point() = {New Point(10, 100), New Point(75, 10), New Point(80, 160), _
                            New Point(100, 150), New Point(125, 80), New Point(175, 200), _
                            New Point(200, 80)} '7个点(两个Bezier相连,4个控制点)
        gp.AddBeziers(pts)
        gr.DrawPath(pn, gp)
    End Sub
End Class



02、路径

   GraphicsPath 允许将各种形状收集到一个单独的单元(如同集合一样)中。
   它用AddLine,AddCurve、AddClosedCurve、AddPie等来添加形状。

    而且路径还可添加到另一个路径中去,形成大型复杂路径。
           myGPath.AddPath(gp1,False)
   
    最后绘制路径:DrawPath(Pen,GP)


'02 路径
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim myPen As New Pen(Color.Blue, 2)

        Dim gp As New GraphicsPath
        Dim points As Point() = {New Point(15, 20), New Point(20, 40), New Point(50, 30)}
        Dim sf As New StringFormat

        gp.AddArc(New Rectangle(0, 0, 30, 20), -90, 180)
        gp.StartFigure() '不闭合当前图形即开始一个新图形。后面添加到该路径的所有点都被添加到此新图形中

        gp.AddCurve(points)
        gp.AddString("字串添加入路径Path", New FontFamily("宋体"), FontStyle.Bold, 14, New PointF(50, 20), sf)
        gp.AddPie(New Rectangle(230, 10, 40, 40), 40, 110)

        gr.DrawPath(myPen, gp)
    End Sub
End Class






'03 路径的开放与闭合
'StartFigure 不须闭合,开始新图
'CloseFigure 闭合当前图(可能是一个,也许是多个),开始新图。例子中闭合时机不同成图不同
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim myPath As New GraphicsPath

        ' First set of figures.
        myPath.StartFigure()
        myPath.AddArc(New Rectangle(10, 10, 50, 50), 0, 270)
        myPath.AddLine(New Point(50, 0), New Point(100, 50))
        myPath.AddArc(New Rectangle(50, 100, 75, 75), 0, 270)
        myPath.CloseFigure()
        myPath.StartFigure()
        myPath.AddArc(New Rectangle(100, 10, 50, 50), 0, 270)

        ' Second set of figures.
        myPath.StartFigure()
        myPath.AddArc(New Rectangle(10, 200, 50, 50), 0, 270)
        myPath.CloseFigure()
        myPath.StartFigure()
        myPath.AddLine(New Point(60, 200), New Point(110, 250))
        myPath.AddArc(New Rectangle(50, 300, 75, 75), 0, 270)
        myPath.CloseFigure()
        myPath.StartFigure()
        myPath.AddArc(New Rectangle(100, 200, 50, 50), 0, 270)

        ' Draw the path to the screen.
        gr.DrawPath(New Pen(Color.Black), myPath)
    End Sub
End Class





3、GraphicsPath方法
   ClearMarkers   清除路径的所有标记
   SetMarkers     在GraphicsPath上设置标记

   CloseFigure    闭合当前图形,开始新图
   CloseAllFigure 闭合所有开放图形,开始新图

   Flatten        将此路径中的各段曲线转换成相连的线段序列
   GetBounds      返回限定此GraphicsPath对象的矩形(外沿)

   InitializeLifetimeService  获取控制此实例的生存期策略的生存期服务对象。
   IsVisible      指示指定点是否此GraphicsPath对象内

   IsOutlineVisible  指示当使用指定Pen对象绘制此GraphicsPath对象时,指定点
                     是否包含在后者的轮廓内(下)
   Reset          清空PathPoints和PathTypes数组并将FillMode设置为Alernate
   Reverse        反转GraphicsPath对象PathPoints数组各点顺序

   Transform      将变形矩形应用到此GraphicsPath对象
   Warp           对此GraphicsPath对象应用由一个矩形和一个平等四边形定义的扭曲变形
   Widen          在用指定的画笔绘制此路径时,用包含所填充区域的曲线代替此路径


'04 Curve与ClosedCurve的对比
'弯曲程度(平滑与锐利的对比)

Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath

        Dim p1 As Point() = {New Point(20, 100), New Point(40, 150), New Point(60, 125), _
                           New Point(40, 100), New Point(60, 75), New Point(40, 50)}

        '下面对比封闭与开放
        gp.AddClosedCurve(p1, 0.5F) '1参:曲线上的点(Point数组),2参:曲线弯曲程序(0-1,1最平滑,0最锐利)
        gr.DrawPath(Pens.Red, gp)

        gp.Reset() '清空gp中图形基元(相当于清空集合中元素)
        gr.TranslateTransform(50, 0) '向右平移坐标
        gp.AddCurve(p1, 0.5F)
        gr.DrawPath(Pens.Red, gp)

        '下面对比一下弯曲的平滑程序
        gp.Reset()
        gr.TranslateTransform(50, 0) '在现有坐标上再右移50
        gp.AddCurve(p1, 0.1F)
        gr.DrawPath(Pens.Red, gp)

        gp.Reset()
        gr.TranslateTransform(50, 0)
        gp.AddCurve(p1, 1.0F)
        gr.DrawPath(Pens.Red, gp)
    End Sub
End Class




'05 SetMarkers与ClearMarkers
'   GP.AddPath(otherPath,Connect)加入另一路径
'   DrawPath与FillPath
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim gp2 As New GraphicsPath

        '人为创建标志,用于分隔各部分基元,可用NextMarker来循环访问。
        '相当于分成小组,两个标记间可含有多个子路径
        gp.AddEllipse(New Rectangle(10, 10, 60, 100))
        gp.SetMarkers()
        gp.AddLine(New Point(70, 50), New Point(100, 50))
        gp.AddRectangle(New Rectangle(100, 10, 60, 100))
        gp.SetMarkers()
        gp.AddLine(New Point(130, 110), New Point(130, 140))
        gp.SetMarkers()

        gp.ClearMarkers() '清除标记,小组解散。
        gr.DrawPath(Pens.Red, gp)


        Dim sf As New StringFormat
        gp2.AddString("只是文本轮廓", New FontFamily("楷体"), FontStyle.Italic, 20, New Point(33, 133), sf)

        gp.AddPath(gp2, True) '添加路径的第一个图形是否为该路径的最后图形的一部分

        'gr有两种画法:DrawPath(画轮廓)、FillPath(填充)。
        '下面用的是DrawPath,所以画出的文字是轮廓(空心);而FillPath是实心文字
        gr.DrawPath(Pens.Red, gp)
    End Sub
End Class




'06.CloseFigure与CloseAllFigure对比
'   StartFigure不闭合开始新图
'   CloseFigure闭合前面图(起点和终点封闭),再开始新图
Imports System.Drawing.Drawing2D
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim p As Point() = {New Point(120, 120), New Point(160, 128), _
                          New Point(160, 148), New Point(120, 160)}

        gp.StartFigure() '不闭合,开始新图
        gp.AddLine(New Point(10, 10), New Point(150, 10))
        gp.AddLine(New Point(150, 10), New Point(10, 150))

        gp.StartFigure()
        gp.AddArc(New Rectangle(70, 1, 100, 100), 0, 90)

        gp.StartFigure()
        gp.AddCurve(p)

        gr.DrawPath(Pens.Blue, gp)

        '下面对比:闭合当前图形
        gr.TranslateTransform(190, 0)
        gp.CloseFigure() '闭合当前图形
        gr.DrawPath(Pens.Red, gp)

        '下面对比:闭合所有图形
        gr.TranslateTransform(190, 0)
        gp.CloseAllFigures() '闭合所有图形
        gr.DrawPath(Pens.Black, gp)
    End Sub
End Class






'07.Flatten把曲线平展成多个连续的线段
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath

        Dim p As Point() = {New Point(20, 100), New Point(70, 10), _
                          New Point(130, 200), New Point(180, 100)}
        Dim Matr As New Matrix

        gp.AddCurve(p)
        gr.DrawPath(Pens.Black, gp)

        '当前matr向下平移10
        Matr.Translate(0, 10)
        '指定曲线和其展平的近似直线之间的最大允许误差。值 0.25 是默认值。
        '降低该展平值将增加近似直线中线段的数目。(越小越接近曲线)
        gp.Flatten(Matr, 10.0F)
        gr.DrawPath(Pens.Red, gp)

        '当前matr向下平移10
        Matr.Translate(0, 10)
        gp.Flatten(Matr, 1.0F)
        gr.DrawPath(Pens.Blue, gp)

        '当前matr向下平移10
        Matr.Translate(0, 10)
        gp.Flatten(Matr, 200.0F)
        gr.DrawPath(Pens.Red, gp)
    End Sub
End Class





'08 GP.GetBounds 取得GP的边界(矩形区域,例:红色框中区域)
Imports System.Drawing.Drawing2D
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim p As Point() = {New Point(120, 120), New Point(160, 128), _
                          New Point(160, 148), New Point(120, 160)}

        gp.StartFigure() '不闭合,开始新图
        gp.AddLine(New Point(10, 10), New Point(150, 10))
        gp.AddLine(New Point(150, 10), New Point(10, 150))

        gp.StartFigure()
        gp.AddArc(New Rectangle(70, 1, 100, 100), 0, 90)

        gp.StartFigure()
        gp.AddCurve(p)

        gr.DrawPath(Pens.Blue, gp)
        gr.DrawRectangle(Pens.Red, gp.GetBounds.Left, gp.GetBounds.Top, gp.GetBounds.Width, gp.GetBounds.Height)
    End Sub
End Class





'09 PathPoints、GetLastPoint 
'   Pointcount 路径中点数
'IsOutlineVisible 测试某点是否在图形的轮廓线内(上),是:True,否False
'IsVisible  是否在GP对象内,与上面不同:上面是轮廓线上,这个是轮廓线所包围区域(不含轮廓线)
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath

        gp.AddLine(New Point(10, 10), New Point(60, 60))
        MessageBox.Show(gp.GetLastPoint.X & "," & gp.GetLastPoint.Y) '60,40
        gp.AddEllipse(New Rectangle(0, 0, 100, 150))
        MessageBox.Show(gp.GetLastPoint.X & "," & gp.GetLastPoint.Y) '100,75

        Dim a() As PointF = gp.PathPoints '路径中的点
        MessageBox.Show(a.GetUpperBound(0)) '14  (0-14)
        MessageBox.Show(gp.PointCount) '15

        gr.DrawPath(Pens.Red, gp)
        MessageBox.Show(gp.IsOutlineVisible(New Point(50, 40), Pens.Black, gr)) 'False

        gr.FillPath(Brushes.Blue, gp)
        MessageBox.Show(gp.IsOutlineVisible(New Point(50, 40), Pens.Black, gr)) 'False
        MessageBox.Show(gp.IsVisible(New Point(9, 9), gr))
    End Sub
End Class







'10.Transform 对GraphicsPaht对象进行变形(缩放、转换、旋转、扭曲)
'复合变换的顺序非常重要。一般说来,先旋转、再缩放、然后平移,
'与先缩放、再旋转、然后平移是不同的.
'所以这个顺序要注意
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim matr As New Matrix

        gp.AddRectangle(New Rectangle(10, 10, 100, 40))
        gr.DrawPath(Pens.Red, gp)

        '由于Matrix是矩阵,变形就靠它,因矩阵太不利于直接操作,故Matrix提供了几个方法:
        'Matrix.Rotate(int32)   旋转
        'Matrix.Scale(1,2)    X,Y上的缩放
        'Matrix.Translate(x,y) 平移
        'Matrix.Shear(x,y)     x,y上的切变因子

        '平移后旋转
        matr.Translate(130, 0)
        matr.Rotate(30)

        gp.Transform(matr)
        gr.DrawPath(Pens.Black, gp)

        '现有基础上,平移、再放大X轴=================
        matr.Translate(-250, 50)
        matr.Scale(2, 1)

        gp.Transform(matr)
        gr.DrawPath(Pens.Black, gp)
    End Sub
End Class





'11.Warp 与前面Transform一样,进行变形
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim matr As New Matrix

        Dim srcRect As New Rectangle(30, 10, 50, 100)
        '目标平行四边行,可为三点(第四点由前面三点自动计算得出)
        Dim destPoints As PointF() = {New Point(120, 10), New Point(220, 35), New Point(130, 110)}

        gp.AddRectangle(srcRect)
        gr.DrawPath(Pens.Black, gp) '画出原图

        '下面变换
        matr.Translate(10, 0) '平移
        gp.Warp(destPoints, srcRect, matr, WarpMode.Perspective, 0.5F)
        gr.DrawPath(Pens.Red, gp)
    End Sub
End Class




'12 Widen缩放原GP上的轮廓粗细
' widen(pen,matrix,flatness)
' matrix用于变形
'flatness 曲线展平程序
'如果希望填充线条之间的空间,必须使用FillPath,而不是DrawPath
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath
        Dim matr As New Matrix

        gp.AddEllipse(0, 0, 100, 100)
        gp.AddEllipse(100, 0, 100, 100)
        gr.DrawPath(Pens.Black, gp)

        Dim widenPen As New Pen(Color.Blue, 10) '此笔主要取宽度(轮廓加粗),颜色没用
        matr.Translate(50, 50) '平移
        gp.Widen(widenPen, matr, 1.0F) '开始变形
        gr.DrawPath(Pens.Red, gp)  '画出轮廓(注意:只有轮廓)

        '清除,看FillPath效果
        gp.Reset()
        gp.AddEllipse(0, 0, 100, 100)
        gp.AddEllipse(100, 0, 100, 100)
        matr.Translate(-30, 50) '平移
        gp.Widen(widenPen, matr, 1.0F)
        gr.FillPath(Brushes.Red, gp) '填充轮廓(实心)

        '再变换一次
        matr.Translate(250, -120) '平移
        gp.Widen(widenPen, matr, 1.0F) '开始变形
        gr.DrawPath(Pens.Red, gp)  '画出轮廓(注意:只有轮廓)
    End Sub
End Class




4、轨迹梯度刷
   GraphicsPath按先后(轨迹)次序维护一系列线条和曲线。
   PathGradientBrush路径渐变刷,在中心点可定义颜色,边沿还可按轨迹分别指定颜色。


'13.轨迹渐变 笔刷
'   笔刷不会超出指定的区域(例中指定的区域为红色矩形)

Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath

        gp.AddEllipse(10, 10, 140, 70)
        Dim pb As New Drawing2D.PathGradientBrush(gp)

        '中心色及边沿色
        Dim colors As Color() = {Color.FromArgb(255, 255, 255, 255)}
        pb.CenterColor = Color.FromArgb(255, 0, 0, 255)
        pb.SurroundColors = colors

        gr.FillEllipse(pb, 10, 10, 140, 70)

        '坐标平衡后,对指定区域的填充
        gr.TranslateTransform(170, 0)
        gr.FillRectangle(pb, 10, 10, 200, 40)
        gr.DrawRectangle(Pens.Red, 10, 10, 200, 40) '就是这个区域
    End Sub
End Class





'14 轨迹渐变刷的中心
'   中心点颜色及位置的设置
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim gp As New GraphicsPath

        gp.AddEllipse(30, 10, 140, 70)
        Dim pb As New PathGradientBrush(gp)

        Dim colors As Color() = {Color.FromArgb(255, 0, 255, 255)}
        pb.CenterPoint = New Point(150, 40) '中心点
        pb.SurroundColors = colors          '四边颜色

        gr.FillEllipse(pb, 30, 10, 140, 70)

        '平移坐标后看中心颜色效果
        gr.TranslateTransform(170, 0)
        pb.CenterColor = Color.FromArgb(255, 0, 0, 255)
        gr.FillEllipse(pb, 30, 10, 140, 70)
    End Sub
End Class





'15.复习:不需要GraphicsPath,直接构造PathGradientBrush

Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim gr As Graphics = Me.CreateGraphics
        Dim points As Point() = {New Point(100, 0), New Point(200, 200), New Point(0, 200)}
        Dim colors As Color() = {Color.FromArgb(255, 0, 128, 0), Color.FromArgb(255, 255, 255, 255), _
                               Color.FromArgb(255, 0, 0, 255)}
        Dim pos As Single() = {0.0F, 0.4F, 1.0F}


        Dim pb As New PathGradientBrush(points)
        Dim cb As New ColorBlend '颜色混合,用于颜色与位置的插值
        cb.Colors = colors
        '值数组,指定沿渐变线距离的百分比
        '该数组的元素指定沿渐变线距离的百分比。例如,元素值 0.2f 指定该点距离起始点为总距离的 20%。
        '该数组中的元素由介于 0.0f 和 1.0f 之间的浮点值表示,并且数组的第一个元素必须是 0.0f,而最后一个元素必须是 1.0f。
        cb.Positions = pos
        pb.InterpolationColors = cb

        gr.FillRectangle(pb, 0, 0, 200, 200) '此区域刚好容纳一个笔刷印,所以看上去只有一个三角形
        gr.DrawRectangle(Pens.Black, 0, 0, 200, 200)
    End Sub
End Class





'16.开放与闭合图形填充时,效果一样。
'   尽管开放图形没有闭合,但填充时却把它当作是闭合图形进行填充
Imports System.Drawing.Drawing2D
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' Create a GraphicsPath object.
        Dim myPath As New GraphicsPath
        Dim gr As Graphics = Me.CreateGraphics
        ' First set of figures.
        myPath.StartFigure()
        myPath.AddArc(10, 10, 50, 50, 0, 270)
        myPath.AddLine(New Point(50, 0), New Point(100, 50))
        myPath.AddArc(50, 100, 75, 75, 0, 270)
        myPath.CloseFigure()
        myPath.StartFigure()
        myPath.AddArc(100, 10, 50, 50, 0, 270)
        gr.DrawPath(New Pen(Color.Black), myPath)

        '注释其中一句闭合,可以看到开放图形
        myPath.Reset()
        myPath.StartFigure()
        myPath.AddArc(10, 10, 50, 50, 0, 270)
        myPath.AddLine(New Point(50, 0), New Point(100, 50))
        myPath.AddArc(50, 100, 75, 75, 0, 270)
        'myPath.CloseFigure()
        myPath.StartFigure()
        myPath.AddArc(100, 10, 50, 50, 0, 270)
        gr.TranslateTransform(150, 0)
        gr.DrawPath(New Pen(Color.Black), myPath)

        '填充开放图形
        gr.TranslateTransform(-150, 180)
        gr.FillPath(Brushes.Brown, myPath) '尽管是开放轮廓,但填充时却看着是闭合的
    End Sub
End Class


抱歉!评论已关闭.