home *** CD-ROM | disk | FTP | other *** search
- VERSION 1.0 CLASS
- BEGIN
- MultiUse = -1 'True
- END
- Attribute VB_Name = "ObjBSpline"
- Attribute VB_Creatable = False
- Attribute VB_Exposed = False
- Option Explicit
-
- Private DegreeU As Integer ' Degree in U direction.
- Private DegreeV As Integer ' Degree in V direction.
- Private MaxU As Integer ' Dimensions of control grid.
- Private MaxV As Integer
- Private Points() As Point3D ' Control points.
-
- ' grid holds a refined grid to display the surface.
- Private grid As ObjPicture
-
- ' u and v increment parameters.
- Private GapU As Single
- Private GapV As Single
- Private Du As Single
- Private Dv As Single
-
- ' Display flags.
- Private ShowControls As Boolean ' Draw control points?
- Private ShowGrid As Boolean ' Draw control grid?
-
- Function Factorial(ByVal n As Single) As Single
- Dim i As Integer
- Dim tot As Single
-
- tot = 1
- For i = 2 To n
- tot = tot * i
- Next i
- Factorial = tot
- End Function
-
- ' ************************************************
- ' Create the refined grid to display the surface.
- ' ************************************************
- Public Sub InitializeGrid(degu As Integer, degv As Integer, gap_u As Single, gap_v As Single, d_u As Single, d_v As Single)
- Dim u As Single
- Dim v As Single
- Dim stopu As Single
- Dim stopv As Single
- Dim x As Single
- Dim y As Single
- Dim z As Single
- Dim x1 As Single
- Dim y1 As Single
- Dim z1 As Single
- Dim pline As ObjPolyline
-
- DegreeU = degu
- DegreeV = degv
- GapU = gap_u
- GapV = gap_v
- Du = d_u
- Dv = d_v
-
- Set grid = New ObjPicture
-
- ' Create curves with constant u.
- stopu = MaxU - DegreeU + 2 + GapU / 10
- stopv = MaxV - DegreeV + 2 + Dv / 10
- For u = 0 To stopu Step GapU
- Set pline = New ObjPolyline
- grid.objects.Add pline
-
- SurfaceValue u, 0, x1, y1, z1
-
- For v = Dv To stopv Step Dv
- SurfaceValue u, v, x, y, z
- pline.AddSegment x1, y1, z1, x, y, z
- x1 = x
- y1 = y
- z1 = z
- Next v
- Next u
-
- ' Create curves with constant v.
- stopv = MaxV - DegreeV + 2 + GapV / 10
- stopu = MaxU - DegreeU + 2 + Du / 10
- For v = 0 To stopv Step GapV
- Set pline = New ObjPolyline
- grid.objects.Add pline
-
- SurfaceValue 0, v, x1, y1, z1
- For u = Du To stopu Step Du
- SurfaceValue u, v, x, y, z
- pline.AddSegment x1, y1, z1, x, y, z
- x1 = x
- y1 = y
- z1 = z
- Next u
- Next v
- End Sub
- ' ************************************************
- ' Apply a transformation matrix which may not
- ' contain 0, 0, 0, 1 in the last column to the
- ' object.
- ' ************************************************
- Public Sub ApplyFull(M() As Single)
- Dim i As Integer
- Dim j As Integer
-
- ' Apply the matrix to the grid if it exists.
- If Not grid Is Nothing Then grid.ApplyFull M
-
- ' Apply the matrix to the control points.
- For i = 0 To MaxU
- For j = 0 To MaxV
- m3ApplyFull Points(i, j).coord, M, Points(i, j).trans
- Next j
- Next i
- End Sub
- ' ************************************************
- ' Apply a nonlinear transformation.
- ' ************************************************
- Public Sub Distort(D As Object)
- Dim i As Integer
- Dim j As Integer
-
- ' Distort the grid if it exists.
- If Not grid Is Nothing Then grid.Distort D
-
- ' Distort the sparse data.
- For i = 0 To MaxU
- For j = 0 To MaxV
- D.Distort Points(i, j).coord(1), Points(i, j).coord(2), Points(i, j).coord(3)
- Next j
- Next i
- End Sub
- ' ************************************************
- ' Draw the transformed object on a Form, Printer,
- ' or PictureBox.
- ' ************************************************
- Public Sub Draw(canvas As Object, Optional r As Variant)
- Dim i As Integer
- Dim j As Integer
-
- ' Draw the grid if it exists.
- If Not grid Is Nothing Then grid.Draw canvas, r
-
- ' Draw the control points if desired.
- If ShowControls Then
- On Error Resume Next
- For i = 0 To MaxU
- For j = 0 To MaxV
- canvas.Line (Points(i, j).trans(1) - 2, Points(i, j).trans(2) - 2)-Step(4, 4), , BF
- Next j
- Next i
- End If
-
- ' Draw the control grid if desired.
- If ShowGrid Then
- On Error Resume Next
- For i = 0 To MaxU
- canvas.CurrentX = Points(i, 0).trans(1)
- canvas.CurrentY = Points(i, 0).trans(2)
- For j = 1 To MaxV
- canvas.Line -(Points(i, j).trans(1), Points(i, j).trans(2))
- Next j
- Next i
- For j = 0 To MaxV
- canvas.CurrentX = Points(0, j).trans(1)
- canvas.CurrentY = Points(0, j).trans(2)
- For i = 1 To MaxU
- canvas.Line -(Points(i, j).trans(1), Points(i, j).trans(2))
- Next i
- Next j
- End If
- End Sub
-
- ' ************************************************
- ' Read a B-Spline surface from a file using Input.
- ' Assume the "BSPLINE" label has already been
- ' read.
- ' ************************************************
- Public Sub FileInput(filenum As Integer)
- Dim i As Integer
- Dim j As Integer
-
- ' Get the basic information.
- Input #filenum, _
- DegreeU, DegreeV, MaxU, MaxV, GapU, GapV, _
- Du, Dv
-
- ' Allocate the Data array.
- SetBounds MaxU + 1, MaxV + 1
-
- ' Read the control points.
- For i = 0 To MaxU
- For j = 0 To MaxV
- Input #filenum, _
- Points(i, j).coord(1), _
- Points(i, j).coord(2), _
- Points(i, j).coord(3)
- Points(i, j).coord(4) = 1
- Next j
- Next i
-
- ' Initialize the grid data.
- If Du = 0 Then
- Set grid = Nothing
- Else
- InitializeGrid DegreeU, DegreeV, _
- GapU, GapV, Du, Dv
- End If
- End Sub
-
-
-
-
- ' ************************************************
- ' Write a B-Spline surface to a file using Write.
- ' Begin with "BSPLINE" to identify this object.
- ' ************************************************
- Public Sub FileWrite(filenum As Integer)
- Dim i As Integer
- Dim j As Integer
-
- ' Write basic information.
- Write #filenum, "BSPLINE", _
- DegreeU, DegreeV, MaxU, MaxV, GapU, GapV, _
- Du, Dv
-
- ' Write the data.
- For i = 0 To MaxU
- For j = 0 To MaxV
- Write #filenum, _
- Points(i, j).coord(1), _
- Points(i, j).coord(2), _
- Points(i, j).coord(3)
- Next j
- Next i
- End Sub
- ' ************************************************
- ' Write the B-Spline curve's grid object to a file
- ' using Write. The data can later be loaded into
- ' an ObjPicture object but not an ObjBSpline
- ' object.
- ' ************************************************
- Public Sub FileWriteGrid(filenum As Integer)
- If Not grid Is Nothing Then grid.FileWrite filenum
- End Sub
-
- ' ***********************************************
- ' Fix the data coordinates at their transformed
- ' values.
- ' ***********************************************
- Public Sub FixPoints()
- Dim i As Integer
- Dim j As Integer
- Dim k As Integer
-
- ' Fix the grid points if the grid exists.
- If Not grid Is Nothing Then grid.FixPoints
-
- ' Fix the controls points.
- For i = 0 To MaxU
- For j = 0 To MaxV
- For k = 1 To 3
- Points(i, j).coord(k) = _
- Points(i, j).trans(k)
- Next k
- Next j
- Next i
- End Sub
-
- ' ************************************************
- ' Return the knot value.
- ' ************************************************
- Private Function Knot(i As Integer, max As Integer, degree As Integer) As Integer
- If i < degree Then
- Knot = 0
- ElseIf i <= max Then
- Knot = i - degree + 1
- Else
- Knot = max - degree + 2
- End If
- End Function
-
-
- ' ************************************************
- ' Return the value of the blending function Ni,k.
- ' ************************************************
- Private Function NValue(i As Integer, max As Integer, degree As Integer, max_degree As Integer, u As Single) As Single
- Dim denom As Single
- Dim v1 As Single
- Dim v2 As Single
-
- If degree = 1 Then
- If Knot(i, max, max_degree) <= u And _
- u < Knot(i + 1, max, max_degree) Then
- NValue = 1
- Else
- NValue = 0
- End If
-
- ' Recall that:
- ' Ni,1(u) = 0 if ti <= u < ti+1
- ' 1 otherwise
- ' The following test handles u = tmax.
- If i = max And _
- Knot(i, max, max_degree) <= u And _
- u <= Knot(i + 1, max, max_degree) + 0.001 Then
- NValue = 1
- End If
- Exit Function
- End If
-
- denom = Knot(i + degree - 1, max, max_degree) - _
- Knot(i, max, max_degree)
- If denom = 0 Then
- v1 = 0
- Else
- v1 = (u - Knot(i, max, max_degree)) * _
- NValue(i, max, degree - 1, max_degree, u) / _
- denom
- End If
-
- denom = Knot(i + degree, max, max_degree) - _
- Knot(i + 1, max, max_degree)
- If denom = 0 Then
- v2 = 0
- Else
- v2 = (Knot(i + degree, max, max_degree) - u) * _
- NValue(i + 1, max, degree - 1, max_degree, u) / _
- denom
- End If
-
- NValue = v1 + v2
- End Function
-
- ' ***********************************************
- ' Return a string indicating the object type.
- ' ***********************************************
- Property Get ObjectType() As String
- ObjectType = "BSPLINE"
- End Property
- ' ************************************************
- ' Let the user know if we are drawing the control
- ' grid.
- ' ************************************************
- Property Get DrawGrid() As Boolean
- DrawGrid = ShowGrid
- End Property
-
- ' ************************************************
- ' Let the user know if we are drawing the control
- ' points.
- ' ************************************************
- Property Get DrawControls() As Boolean
- DrawControls = ShowControls
- End Property
-
-
- ' ************************************************
- ' Let the user decide whether we should draw the
- ' control grid.
- ' ************************************************
- Property Let DrawGrid(value As Boolean)
- ShowGrid = value
- End Property
- ' ************************************************
- ' Let the user decide whether we should draw the
- ' control points.
- ' ************************************************
- Property Let DrawControls(value As Boolean)
- ShowControls = value
- End Property
-
-
-
-
- ' ************************************************
- ' Apply a transformation matrix to the object.
- ' ************************************************
- Public Sub Apply(M() As Single)
- Dim i As Integer
- Dim j As Integer
-
- ' Apply the matrix to the grid if it exists.
- If Not grid Is Nothing Then grid.Apply M
-
- ' Apply the matrix to the control points.
- For i = 0 To MaxU
- For j = 0 To MaxV
- m3Apply Points(i, j).coord, M, Points(i, j).trans
- Next j
- Next i
- End Sub
-
-
-
-
-
- ' ************************************************
- ' Set MaxU and MaxV ans allocate room for the
- ' control points.
- ' ************************************************
- Public Sub SetBounds(NumX As Integer, NumZ As Integer)
- MaxU = NumX - 1
- MaxV = NumZ - 1
- ReDim Points(0 To NumX, 0 To NumZ)
- End Sub
-
- ' ************************************************
- ' Set the value for a control point.
- ' ************************************************
- Public Sub SetControlPoint(i As Integer, j As Integer, x As Single, y As Single, z As Single)
- Points(i - 1, j - 1).coord(1) = x
- Points(i - 1, j - 1).coord(2) = y
- Points(i - 1, j - 1).coord(3) = z
- Points(i - 1, j - 1).coord(4) = 1
- End Sub
- ' ************************************************
- ' Return the value of the B-Spline surface at this
- ' position.
- ' ************************************************
- Private Sub SurfaceValue(u As Single, v As Single, x As Single, y As Single, z As Single)
- Dim p As Integer
- Dim i As Integer
- Dim j As Integer
- Dim pt As Point3D
- Dim Ni As Single
- Dim Nj As Single
-
- For i = 0 To MaxU
- ' Compute Ni.
- Ni = NValue(i, MaxU, DegreeU, DegreeU, u)
-
- For j = 0 To MaxV
- ' Compute Nj.
- Nj = NValue(j, MaxV, DegreeV, DegreeV, v)
-
- ' Add to the coordinates.
- For p = 1 To 3
- pt.coord(p) = pt.coord(p) + _
- Points(i, j).coord(p) * _
- Ni * Nj
- Next p
- Next j
- Next i
-
- ' Prepare the output.
- x = pt.coord(1)
- y = pt.coord(2)
- z = pt.coord(3)
- End Sub
-