标题: 第六回:寻找交点,离胜利就剩一步 之 纽带
- floodpeak 2008-05-07 12:30 阅读:1329
- 评论:10 查看评论 | 添加评论
[图片]
[图片]

    终于,我们进入了算法的核心地带。
    在《第二回:漫谈新思路,是我们自己干的时候了》中我们说到整个算法的处理过程包括三个大块:寻找辅助线、寻找交点、寻找三角形。交点的寻找及其结果的组织,是能否找到三角形的关键,因而本回会用较长的篇幅把这个过程阐述清楚,为后文打下坚实的基础。
    由于内容实在过多,为了避免冗长造成的疲倦,我将本回分成两个部分。本文的主题是介绍寻找交点和寻找三角形两个大块的纽带——二维表Point2Table,还记得《第二回:漫谈新思路,是我们自己干的时候了》“二、寻找相交点”小节中提到的二维表吗,没错,就是它!

一、 类图和代码

[图片]
    这里是整个类的代码,行数逾百,后面会进行逐段的分析。
 
[图片][图片]Point2Table
  1[图片][图片]Public Class Point2TableClass Point2Table
  2[图片]
  3[图片][图片]    Private Class PointIndexWithTClass PointIndexWithT
  4[图片]            Implements IComparable
  5[图片]
  6[图片]        Private _index As Integer '在VertexBuffer中的索引
  7[图片]        Private t As Decimal
  8[图片]
  9[图片][图片]      Public Sub New()Sub New(ByVal ind As Integer, ByVal t As Decimal)
 10[图片]            Me._index = ind
 11[图片]            Me.t = t
 12[图片]        End Sub
 13[图片]
 14[图片][图片]      Public ReadOnly Property Index()Property Index() As Integer
 15[图片]            Get
 16[图片]                Return Me._index
 17[图片]            End Get
 18[图片]        End Property
 19[图片]
 20[图片][图片]      Public Function CompareTo()Function CompareTo(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
 21[图片]            If Not (TypeOf obj Is PointIndexWithT) Then
 22[图片]                MsgBox("PointWithU中传入参数有误")
 23[图片]                Return 0
 24[图片]            End If
 25[图片]            Dim pwu As PointIndexWithT = CType(obj, PointIndexWithT)
 26[图片]            Return Me.t.CompareTo(pwu.t)
 27[图片]        End Function
 28[图片]    End Class
 29[图片]
 30[图片]    Private rowsForSort As New List(Of List(Of PointIndexWithT))
 31[图片]    Private rows As New List(Of List(Of Integer))
 32[图片]    Private vb As New VertexBuffer
 33[图片]    Private ib As IndexBuffer = Nothing
 34[图片]
 35[图片][图片]  Public ReadOnly Property IndexBuffer()Property IndexBuffer() As IndexBuffer
 36[图片]        Get
 37[图片]            If (ib Is Nothing) Then
 38[图片]                ib = New IndexBuffer
 39[图片]                Dim qs As New QuadrangleSeeker(Me)
 40[图片]                Dim quadrangles As List(Of Integer) = Nothing
 41[图片]                Me.Sort() '对表进行排序
 42[图片]                quadrangles = qs.getQuadrangles()
 43[图片]                For i As Integer = 0 To quadrangles.Count - 1 Step 4
 44[图片]                    If (quadrangles(i + 2) <> quadrangles(i + 3)) Then
 45[图片]                        ib.add(quadrangles(i))
 46[图片]                        ib.add(quadrangles(i + 2))
 47[图片]                        ib.add(quadrangles(i + 3))
 48[图片]                    End If
 49[图片]                    If (quadrangles(i) <> quadrangles(i + 1)) Then
 50[图片]                        ib.add(quadrangles(i + 3))
 51[图片]                        ib.add(quadrangles(i + 1))
 52[图片]                        ib.add(quadrangles(i))
 53[图片]                    End If
 54[图片]                Next
 55[图片]            End If
 56[图片]            Return Me.ib
 57[图片]        End Get
 58[图片]    End Property
 59[图片]
 60[图片][图片]  Public ReadOnly Property VertexBuffer()Property VertexBuffer() As VertexBuffer
 61[图片]        Get
 62[图片]            Return Me.vb
 63[图片]        End Get
 64[图片]    End Property
 65[图片]
 66[图片][图片]  Default Public ReadOnly Property Item()Property Item(ByVal i As Integer) As List(Of Integer)
 67[图片]        Get
 68[图片]            If (i < rowsForSort.Count AndAlso i >= 0) Then
 69[图片]                Return rows(i)
 70[图片]            Else
 71[图片]                MsgBox("数组越界")
 72[图片]                Return Nothing
 73[图片]            End If
 74[图片]        End Get
 75[图片]    End Property
 76[图片]
 77[图片][图片]  Public ReadOnly Property Count()Property Count() As Integer
 78[图片]        Get
 79[图片]            Return Me.rowsForSort.Count
 80[图片]        End Get
 81[图片]    End Property
 82[图片]
 83[图片][图片]  Public Sub addRow()Sub addRow()
 84[图片]        rowsForSort.Add(New List(Of PointIndexWithT))
 85[图片]    End Sub
 86[图片]
 87[图片][图片]  Public Sub addPoint()Sub addPoint(ByVal point As Point2, ByVal t As Decimal, ByVal u As Decimal)
 88[图片]        If (u < 0 OrElse u > 1) Then    '没有和线段相交
 89[图片]            Return
 90[图片]        End If
 91[图片]        Dim index As Integer = Me.vb.add(point)
 92[图片]        rowsForSort(rowsForSort.Count - 1).Add(New PointIndexWithT(index, t))
 93[图片]    End Sub
 94[图片]
 95[图片][图片]  Public Sub removePoint()Sub removePoint(ByVal rowIndex As Integer, ByVal columnIndex As Integer)
 96[图片]        Me.rowsForSort(rowIndex).RemoveAt(columnIndex)
 97[图片]    End Sub
 98[图片]
 99[图片][图片]  Public Sub Sort()Sub Sort()
100[图片]        Me.rows = New List(Of List(Of Integer))
101[图片]        For Each row As List(Of PointIndexWithT) In rowsForSort
102[图片]            row.Sort()      '按照t进行排序
103[图片]            Dim list As New List(Of Integer)        '实例化一行
104[图片]            For Each piwt As PointIndexWithT In row '遍历行中每一个带T的点索引
105[图片]                list.Add(piwt.Index)                '将索引值添加到列表中
106[图片]            Next
107[图片]            Me.rows.Add(list)   '将列表添加进行中
108[图片]        Next
109[图片]    End Sub
110[图片]End Class
111[图片]

二、 两个缓冲的宿主
    容易看出属性中的IndexBuffer和VertexBuffer正是上篇文章中设计的数据结构,客户代码可以直接调用这两个只读属性获得处理完毕的两个缓冲,进而加以利用,所以说Point2Table除了是寻找交点和寻找三角形的纽带外,还有另一重身份,那就是整个算法和客户代码的纽带,这里是算法的出口。在调用IndexBuffer属性时,程序会去调用寻找三角形的逻辑,这部分内容我们将在下一回中详细介绍。在调用VertexBuffer属性时,程序直接返回顶点缓冲vb,这个缓冲是用户在寻找交点的过程中填充的,这部分内容我们将在本回的下一部分中详细介绍。

三、嵌套类PointIndexWithT
    在上面的类图中,有一个可爱的棒糖,棒糖下面是一个名字古怪的私有嵌套类PointIndexWithT,翻译过来就是带着T的点索引,索引就是上文VertexBuffer中的索引,T就是《第四回:掌握数学工具,没个好帮手怎么行》“三、用向量描述直线”小节中提到的T。下图可以直观的看出Index和T的含义:
 

[图片]

    该类的引入只有一个目的,将某条扫描线上的所有交点从左至右进行排序,注意一点,这里参与排序的是T,而排序的实体(我们要的结果)是点的索引。
 
1[图片][图片] Public Function CompareTo()Function CompareTo(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
2[图片]        If Not (TypeOf obj Is PointIndexWithT) Then
3[图片]            MsgBox("PointWithU中传入参数有误")
4[图片]            Return 0
5[图片]        End If
6[图片]        Dim pwu As PointIndexWithT = CType(obj, PointIndexWithT)
7[图片]        Return Me.t.CompareTo(pwu.t)
8[图片]    End Function

    上面的这段代码实现了IComparable接口的CompateTo方法,目的是让PointIndexWithT的数组可以使用框架提供的Sort函数。代码很简单,只是简单的比较了一下T,我们已经说过了,T就是为了排序而生。如果你还不是太清楚,没关系,下面我就用一个例子来说明。

四、例说排序
    下图是三角剖分一个凹多边形的过程,图中的VB代表VertexBuffer,也就是顶点缓冲。每一行后面会有几个矩形框,每个矩形框代表一个加入到Point2Table的点,框中上面一个值代表Index,下面的值为该点的T。

[图片][图片]

    上图中的T只是一个示意值,请不要用尺子丈量。

五、排序的实现
    有了上面直观的了解,相信下面的内容很容易理解。

    Private rowsForSort As New List(Of List(Of PointIndexWithT))
    Private rows As New List(Of List(Of Integer))
 1[图片][图片]Public Sub Sort()Sub Sort()
 2[图片]        Me.rows = New List(Of List(Of Integer))
 3[图片]        For Each row As List(Of PointIndexWithT) In rowsForSort
 4[图片]            row.Sort()      '按照t进行排序
 5[图片]            Dim list As New List(Of Integer)        '实例化一行
 6[图片]            For Each piwt As PointIndexWithT In row '遍历行中每一个带T的点索引
 7[图片]                list.Add(piwt.Index)                '将索引值添加到列表中
 8[图片]            Next
 9查看评论 | 添加评论
返回顶部 | 返回首页