home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH9 / SRC / OBJPLINE.CLS < prev    next >
Encoding:
Text File  |  1996-05-04  |  8.0 KB  |  309 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjPolyline"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' Point3D and Segment3D are defined in module M3OPS.BAS as:
  11. '    Type Point3D
  12. '        coord(1 To 4) As Single
  13. '        trans(1 To 4) As Single
  14. '    End Type
  15. '
  16. '    Type Segment3D
  17. '        pt1 As Integer
  18. '        pt2 As Integer
  19. '    End Type
  20.  
  21. Private NumPoints As Integer ' Number of points.
  22. Private Points() As Point3D  ' Data points.
  23.  
  24. Private NumSegs As Integer   ' Number of segments.
  25. Private Segs() As Segment3D  ' The segments.
  26.  
  27. ' ***********************************************
  28. ' Create a pyramid with height L and base given
  29. ' by the points in the coord array. Add the
  30. ' segments that make up the pyramid to this
  31. ' polyline.
  32. ' ***********************************************
  33. Sub Stellate(L As Single, ParamArray coord() As Variant)
  34. Dim x0 As Single
  35. Dim y0 As Single
  36. Dim z0 As Single
  37. Dim x1 As Single
  38. Dim y1 As Single
  39. Dim z1 As Single
  40. Dim x2 As Single
  41. Dim y2 As Single
  42. Dim z2 As Single
  43. Dim x3 As Single
  44. Dim y3 As Single
  45. Dim z3 As Single
  46. Dim Ax As Single
  47. Dim Ay As Single
  48. Dim Az As Single
  49. Dim Bx As Single
  50. Dim By As Single
  51. Dim Bz As Single
  52. Dim Nx As Single
  53. Dim Ny As Single
  54. Dim Nz As Single
  55. Dim num As Integer
  56. Dim i As Integer
  57. Dim pt As Integer
  58.  
  59.     num = (UBound(coord) + 1) \ 3
  60.     If num < 3 Then
  61.         Beep
  62.         MsgBox "Must have at least 3 points to stellate.", , vbExclamation
  63.         Exit Sub
  64.     End If
  65.     
  66.     ' (x0, y0, z0) is the center of the polygon.
  67.     x0 = 0
  68.     y0 = 0
  69.     z0 = 0
  70.     pt = 0
  71.     For i = 1 To num
  72.         x0 = x0 + coord(pt)
  73.         y0 = y0 + coord(pt + 1)
  74.         z0 = z0 + coord(pt + 2)
  75.         pt = pt + 3
  76.     Next i
  77.     x0 = x0 / num
  78.     y0 = y0 / num
  79.     z0 = z0 / num
  80.     
  81.     ' Find the normal.
  82.     x1 = coord(0)
  83.     y1 = coord(1)
  84.     z1 = coord(2)
  85.     x2 = coord(3)
  86.     y2 = coord(4)
  87.     z2 = coord(5)
  88.     x3 = coord(6)
  89.     y3 = coord(7)
  90.     z3 = coord(8)
  91.     Ax = x2 - x1
  92.     Ay = y2 - y1
  93.     Az = z2 - z1
  94.     Bx = x3 - x2
  95.     By = y3 - y2
  96.     Bz = z3 - z2
  97.     m3Cross Nx, Ny, Nz, Ax, Ay, Az, Bx, By, Bz
  98.     
  99.     ' Give the normal length L.
  100.     m3SizeVector L, Nx, Ny, Nz
  101.     
  102.     ' The normal + <x0, y0, z0> gives the point.
  103.     x0 = x0 + Nx
  104.     y0 = y0 + Ny
  105.     z0 = z0 + Nz
  106.  
  107.     ' Build the segments that make up the object.
  108.     x1 = coord(3 * num - 3)
  109.     y1 = coord(3 * num - 2)
  110.     z1 = coord(3 * num - 1)
  111.     pt = 0
  112.     For i = 1 To num
  113.         x2 = coord(pt)
  114.         y2 = coord(pt + 1)
  115.         z2 = coord(pt + 2)
  116.         AddSegment x1, y1, z1, x2, y2, z2, x0, y0, z0
  117.         x1 = x2
  118.         y1 = y2
  119.         z1 = z2
  120.         pt = pt + 3
  121.     Next i
  122. End Sub
  123.  
  124.  
  125.  
  126.  
  127. ' ***********************************************
  128. ' Return a string indicating the object type.
  129. ' ***********************************************
  130. Property Get ObjectType() As String
  131.     ObjectType = "POLYLINE"
  132. End Property
  133.  
  134. ' ************************************************
  135. ' Add one or more line segments to the polyline.
  136. ' ************************************************
  137. Public Sub AddSegment(ParamArray coord() As Variant)
  138. Dim num_segs As Integer
  139. Dim i As Integer
  140. Dim last As Integer
  141. Dim pt As Integer
  142.  
  143.     num_segs = (UBound(coord) + 1) \ 3 - 1
  144.     ReDim Preserve Segs(1 To NumSegs + num_segs)
  145.  
  146.     last = AddPoint((coord(0)), (coord(1)), (coord(2)))
  147.     pt = 0
  148.     For i = 1 To num_segs
  149.         Segs(NumSegs + i).pt1 = last
  150.         pt = pt + 3
  151.         last = AddPoint((coord(pt)), (coord(pt + 1)), (coord(pt + 2)))
  152.         Segs(NumSegs + i).pt2 = last
  153.     Next i
  154.  
  155.     NumSegs = NumSegs + num_segs
  156. End Sub
  157.  
  158. ' ************************************************
  159. ' Add a point to the polyline or reuse a point.
  160. ' Return the point's index.
  161. ' ************************************************
  162. Private Function AddPoint(x As Single, y As Single, z As Single) As Integer
  163. Dim i As Integer
  164.  
  165.     ' See if the point is already here.
  166.     For i = 1 To NumPoints
  167.         If x = Points(i).coord(1) And _
  168.            y = Points(i).coord(2) And _
  169.            z = Points(i).coord(3) Then _
  170.                 Exit For
  171.     Next i
  172.     AddPoint = i
  173.     
  174.     ' If so, we're done.
  175.     If i <= NumPoints Then Exit Function
  176.     
  177.     ' Otherwise create the new point.
  178.     NumPoints = NumPoints + 1
  179.     ReDim Preserve Points(1 To NumPoints)
  180.     Points(i).coord(1) = x
  181.     Points(i).coord(2) = y
  182.     Points(i).coord(3) = z
  183.     Points(i).coord(4) = 1#
  184. End Function
  185.  
  186.  
  187. ' ***********************************************
  188. ' Fix the data coordinates at their transformed
  189. ' values.
  190. ' ***********************************************
  191. Public Sub FixPoints()
  192. Dim i As Integer
  193. Dim j As Integer
  194.  
  195.     For i = 1 To NumPoints
  196.         For j = 1 To 3
  197.             Points(i).coord(j) = Points(i).trans(j)
  198.         Next j
  199.     Next i
  200. End Sub
  201.  
  202. ' ************************************************
  203. ' Apply a transformation matrix which may not
  204. ' contain 0, 0, 0, 1 in the last column to the
  205. ' object.
  206. ' ************************************************
  207. Public Sub ApplyFull(M() As Single)
  208. Dim i As Integer
  209.  
  210.     For i = 1 To NumPoints
  211.         m3ApplyFull Points(i).coord, M, Points(i).trans
  212.     Next i
  213. End Sub
  214.  
  215. ' ************************************************
  216. ' Apply a transformation matrix to the object.
  217. ' ************************************************
  218. Public Sub Apply(M() As Single)
  219. Dim i As Integer
  220.  
  221.     For i = 1 To NumPoints
  222.         m3Apply Points(i).coord, M, Points(i).trans
  223.     Next i
  224. End Sub
  225.  
  226.  
  227. ' ************************************************
  228. ' Apply a nonlinear transformation.
  229. ' ************************************************
  230. Public Sub Distort(D As Object)
  231. Dim i As Integer
  232.  
  233.     For i = 1 To NumPoints
  234.         D.Distort Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  235.     Next i
  236. End Sub
  237.  
  238. ' ************************************************
  239. ' Write a polyline to a file using Write.
  240. ' Begin with "POLYLINE" to identify this object.
  241. ' ************************************************
  242. Public Sub FileWrite(filenum As Integer)
  243. Dim i As Integer
  244.  
  245.     Write #filenum, "POLYLINE", NumPoints, NumSegs
  246.     
  247.     ' Write the points.
  248.     For i = 1 To NumPoints
  249.         Write #filenum, Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  250.     Next i
  251.  
  252.     ' Write the segments.
  253.     For i = 1 To NumSegs
  254.         Write #filenum, Segs(i).pt1, Segs(i).pt2
  255.     Next i
  256. End Sub
  257.  
  258. ' ************************************************
  259. ' Draw the transformed points on a Form, Printer,
  260. ' or PictureBox.
  261. ' ************************************************
  262. Public Sub Draw(canvas As Object, Optional R As Variant)
  263. Dim seg As Integer
  264. Dim pt1 As Integer
  265. Dim pt2 As Integer
  266. Dim dist As Single
  267.  
  268.     On Error Resume Next
  269.     If IsMissing(R) Then R = INFINITY
  270.     dist = R
  271.     For seg = 1 To NumSegs
  272.         pt1 = Segs(seg).pt1
  273.         pt2 = Segs(seg).pt2
  274.         ' Don't draw if either point is farther
  275.         ' from the focus point than the center of
  276.         ' projection (which is distance dist away).
  277.         If Points(pt1).trans(3) < R And Points(pt2).trans(3) < R Then _
  278.             canvas.Line _
  279.                 (Points(pt1).trans(1), Points(pt1).trans(2))- _
  280.                 (Points(pt2).trans(1), Points(pt2).trans(2))
  281.     Next seg
  282. End Sub
  283.  
  284. ' ************************************************
  285. ' Read a polyline from a file using Input.
  286. ' Assume the "POLYLINE" label has already been
  287. ' read.
  288. ' ************************************************
  289. Public Sub FileInput(filenum As Integer)
  290. Dim i As Integer
  291.  
  292.     Input #filenum, NumPoints, NumSegs
  293.     
  294.     ' Allocate and read the points.
  295.     ReDim Points(1 To NumPoints)
  296.     For i = 1 To NumPoints
  297.         Input #filenum, Points(i).coord(1), Points(i).coord(2), Points(i).coord(3)
  298.         Points(i).coord(4) = 1
  299.     Next i
  300.     
  301.     ' Allocate and read the segments.
  302.     ReDim Segs(1 To NumSegs)
  303.     For i = 1 To NumSegs
  304.         Input #filenum, Segs(i).pt1, Segs(i).pt2
  305.     Next i
  306. End Sub
  307.  
  308.  
  309.