Shapes.vb
  1. ''
  2. '' This code is part of Document Solutions for PDF demos.
  3. '' Copyright (c) MESCIUS inc. All rights reserved.
  4. ''
  5. Imports System.IO
  6. Imports System.Drawing
  7. Imports System.Numerics
  8. Imports System.Linq
  9. Imports GrapeCity.Documents.Pdf
  10. Imports GrapeCity.Documents.Text
  11. Imports GrapeCity.Documents.Drawing
  12. Imports GCTEXT = GrapeCity.Documents.Text
  13. Imports GCDRAW = GrapeCity.Documents.Drawing
  14.  
  15. '' Demonstrates how various shapes can be drawn in DsPdf.
  16. '' Shows how simple shapes can be combined to produce more complex shapes.
  17. '' Simple graphics transformations are used to draw some shapes.
  18. Public Class Shapes
  19.  
  20. '' Helper method to draw a polygon and a caption beneath it.
  21. '' Can also be used to just calculate the points without actual drawing.
  22. '' startAngle is for the first point, clockwise from (1,0).
  23. Private Function DrawPolygon(
  24. ByVal g As GcGraphics,
  25. ByVal center As PointF,
  26. ByVal r As Single,
  27. ByVal n As Integer,
  28. ByVal startAngle As Single,
  29. ByVal pn As GCDRAW.Pen,
  30. Optional ByVal caption As String = Nothing) As PointF()
  31. Dim pts(n - 1) As PointF
  32. For i = 0 To n - 1
  33. pts(i) = New PointF(center.X + (r * Math.Cos(startAngle + 2 * Math.PI * i / n)), center.Y + (r * Math.Sin(startAngle + 2 * Math.PI * i / n)))
  34. Next
  35.  
  36. If pn IsNot Nothing Then
  37. g.DrawPolygon(pts, pn)
  38. End If
  39. If Not String.IsNullOrEmpty(caption) Then
  40. DrawCaption(g, center, r, caption)
  41. End If
  42. Return pts
  43. End Function
  44.  
  45. '' Helper method to draw a caption beneath a shape:
  46. Private Sub DrawCaption(ByVal g As GcGraphics, ByVal center As PointF, ByVal r As Single, ByVal caption As String)
  47. g.DrawString(
  48. caption,
  49. New TextFormat() With {.Font = StandardFonts.Times, .FontSize = 10},
  50. New RectangleF(center.X - r, center.Y + r, r * 2, 24),
  51. TextAlignment.Center, ParagraphAlignment.Center, False)
  52. End Sub
  53.  
  54. '' Main entry point.
  55. Function CreatePDF(ByVal stream As Stream) As Integer
  56. Dim doc = New GcPdfDocument()
  57. Dim page = doc.Pages.Add()
  58. Dim g = page.Graphics
  59. '' Document header:
  60. g.DrawString("Shapes",
  61. New TextFormat() With {.Font = StandardFonts.TimesBold, .FontSize = 14, .Underline = True},
  62. New RectangleF(PointF.Empty, New SizeF(page.Size.Width, 44)),
  63. TextAlignment.Center, ParagraphAlignment.Far)
  64. '' Pen used to draw shapes:
  65. Dim pen = New GCDRAW.Pen(Color.Orange, 1)
  66. pen.LineJoin = PenLineJoin.Round
  67. Dim fill = 100 '' Surfaces fill alpha
  68.  
  69. '' Set up the helper layout grid:
  70. Dim grid = New With {
  71. .Cols = 3,
  72. .Rows = 5,
  73. .MarginX = 72,
  74. .MarginY = 36,
  75. .Radius = 36,
  76. .StepX = (page.Size.Width - 144) / 3,
  77. .StepY = (page.Size.Height - 72) / 5
  78. }
  79.  
  80. '' Insertion point of the next figure's center:
  81. Dim startIp = New PointF(grid.MarginX + grid.StepX / 2, grid.MarginY + grid.StepY / 2 + 10)
  82. Dim ip = startIp
  83. #If False Then
  84. '' Debug code to show the layout grid:
  85. Dim ipp = ip
  86. For i = 1 To grid.Cols
  87. ipp.Y = ip.Y
  88. For j = 1 To grid.Rows
  89. g.DrawRectangle(New RectangleF(ipp.X - grid.Radius, ipp.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), Color.LightGreen, 0.5F)
  90. ipp.Y += grid.StepY
  91. Next
  92. ipp.X += grid.StepX
  93. Next
  94. #End If
  95. '' Circle:
  96. g.DrawEllipse(New RectangleF(ip.X - grid.Radius, ip.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), pen)
  97. DrawCaption(g, ip, grid.Radius, "Circle")
  98. ip.X += grid.StepX
  99.  
  100. '' Ellipse:
  101. g.DrawEllipse(New RectangleF(ip.X - grid.Radius * 1.4F, ip.Y - grid.Radius / 2, grid.Radius * 2 * 1.4F, grid.Radius), pen)
  102. DrawCaption(g, ip, grid.Radius, "Ellipse")
  103. ip.X += grid.StepX
  104.  
  105. '' Cylinder:
  106. Dim radX = grid.Radius / 1.4F
  107. Dim radY = grid.Radius / 6
  108. Dim height = grid.Radius * 1.8F
  109. g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y - height / 2, radX * 2, radY * 2), pen)
  110. g.FillEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), Color.FromArgb(fill, pen.Color))
  111. g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), pen)
  112. g.DrawLine(New PointF(ip.X - radX, ip.Y - height / 2 + radY), New PointF(ip.X - radX, ip.Y + height / 2 - radY), pen)
  113. g.DrawLine(New PointF(ip.X + radX, ip.Y - height / 2 + radY), New PointF(ip.X + radX, ip.Y + height / 2 - radY), pen)
  114. DrawCaption(g, ip, grid.Radius, "Cylinder")
  115. ip.X = startIp.X
  116. ip.Y += grid.StepY
  117. pen.Color = Color.Indigo
  118.  
  119. '' Square:
  120. DrawPolygon(g, ip, grid.Radius, 4, -Math.PI / 4, pen, "Square")
  121. ip.X += grid.StepX
  122.  
  123. '' Rectangle:
  124. Dim rectQx = 1.4F
  125. Dim rectQy = 0.6F
  126. Dim rect = New RectangleF(ip.X - grid.Radius * rectQx, ip.Y - grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy)
  127. g.DrawRectangle(rect, pen)
  128. DrawCaption(g, ip, grid.Radius, "Rectangle")
  129. ip.X += grid.StepX
  130.  
  131. '' Cube:
  132. Dim cubex = 6
  133. Dim cubePtsFar = DrawPolygon(g, New PointF(ip.X - cubex, ip.Y - cubex), grid.Radius, 4, -Math.PI / 4, pen)
  134. Dim cubePtsNear = DrawPolygon(g, New PointF(ip.X + cubex, ip.Y + cubex), grid.Radius, 4, -Math.PI / 4, pen)
  135. g.DrawLine(cubePtsFar(0), cubePtsNear(0), pen)
  136. g.DrawLine(cubePtsFar(1), cubePtsNear(1), pen)
  137. g.DrawLine(cubePtsFar(2), cubePtsNear(2), pen)
  138. g.DrawLine(cubePtsFar(3), cubePtsNear(3), pen)
  139. g.FillPolygon(New PointF() {cubePtsFar(1), cubePtsFar(2), cubePtsNear(2), cubePtsNear(1)}, Color.FromArgb(fill, pen.Color))
  140. DrawCaption(g, ip, grid.Radius, "Cube")
  141. ip.X = startIp.X
  142. ip.Y += grid.StepY
  143. pen.Color = Color.DarkGreen
  144.  
  145. '' Pentagon:
  146. DrawPolygon(g, ip, grid.Radius, 5, -Math.PI / 2, pen, "Pentagon")
  147. ip.X += grid.StepX
  148.  
  149. '' Hexagon:
  150. '' For sample sake, we apply a transform to make the hexagon wider and shorter:
  151. g.Transform = Matrix3x2.CreateScale(1.4F, 0.8F) * Matrix3x2.CreateTranslation(ip.X, ip.Y)
  152. DrawPolygon(g, PointF.Empty, grid.Radius, 6, 0, pen, Nothing)
  153. g.Transform = Matrix3x2.Identity
  154. DrawCaption(g, ip, grid.Radius, "Hexagon")
  155. ip.X += grid.StepX
  156.  
  157. '' Octagon:
  158. DrawPolygon(g, ip, grid.Radius, 8, -Math.PI / 8, pen, "Octagon")
  159. ip.X = startIp.X
  160. ip.Y += grid.StepY
  161. pen.Color = Color.DarkRed
  162.  
  163. '' Triangle:
  164. DrawPolygon(g, ip, grid.Radius, 3, -Math.PI / 2, pen, "Triangle")
  165. ip.X += grid.StepX
  166.  
  167. '' Filled pentagram:
  168. Dim pts = DrawPolygon(g, ip, grid.Radius, 5, -Math.PI / 2, pen, "Pentagram")
  169. pts = New PointF() {pts(0), pts(2), pts(4), pts(1), pts(3)}
  170. g.FillPolygon(pts, Color.FromArgb(fill, pen.Color))
  171. g.DrawPolygon(pts, pen)
  172. ip.X += grid.StepX
  173.  
  174. '' Set up a simple kind of oblique projection to draw a pyramid:
  175. Dim angle = Math.PI / 6
  176. Dim s = Math.Sin(angle)
  177. Dim c = Math.Cos(angle)
  178.  
  179. Dim project As Func(Of Single, Single, Single, PointF) =
  180. Function(ByVal x_, ByVal y_, ByVal z_)
  181. Return New PointF(x_ - c * y_ * 0.5F, -(z_ - s * y_ * 0.5F))
  182. End Function
  183.  
  184. Dim p3d As Func(Of Vector3, PointF) =
  185. Function(ByVal v_)
  186. Return project(v_.X, v_.Y, v_.Z)
  187. End Function
  188.  
  189. Dim hedge = grid.Radius '' 1/2 edge
  190. '' Debug - draw the 3 axis:
  191. '' g.DrawLine(project(0, 0, 0), project(100, 0, 0), Color.Red)
  192. '' g.DrawLine(project(0, 0, 0), project(0, 100, 0), Color.Green)
  193. '' g.DrawLine(project(0, 0, 0), project(0, 0, 100), Color.Blue)
  194.  
  195. '' 3d points forming a square pyramid:
  196. Dim pts3d As Vector3() =
  197. {
  198. New Vector3(-hedge, -hedge, 0),
  199. New Vector3(hedge, -hedge, 0),
  200. New Vector3(hedge, hedge, 0),
  201. New Vector3(-hedge, hedge, 0),
  202. New Vector3(0, 0, hedge * 2)
  203. }
  204. '' Project the points to draw the pyramid:
  205. pts = pts3d.Select(Function(v_) p3d(v_)).ToArray()
  206. g.Transform = Matrix3x2.CreateTranslation(ip.X, ip.Y + hedge * 0.7F)
  207. '' Visible edges:
  208. g.DrawPolygon(New PointF() {pts(4), pts(1), pts(2), pts(3), pts(4), pts(2)}, pen)
  209. '' Invisible edges:
  210. pen.Width /= 2
  211. pen.Color = Color.FromArgb(fill, pen.Color)
  212. g.DrawLine(pts(0), pts(4), pen)
  213. g.DrawLine(pts(0), pts(1), pen)
  214. g.DrawLine(pts(0), pts(3), pen)
  215. g.FillPolygon(pts.Take(4).ToArray(), pen.Color)
  216. ''
  217. g.Transform = Matrix3x2.Identity
  218. DrawCaption(g, ip, grid.Radius, "Pyramid")
  219. ip.X = startIp.X
  220. ip.Y += grid.StepY
  221. pen.Width *= 2
  222. pen.Color = Color.Green
  223.  
  224. '' Cone:
  225. Dim baseh = grid.Radius * 0.3F
  226. pts = DrawPolygon(g, ip, grid.Radius, 3, -Math.PI / 2, Nothing, "Cone")
  227. g.DrawLines(New PointF() {pts(2), pts(0), pts(1)}, pen)
  228. rect = New RectangleF(pts(2).X, pts(2).Y - baseh / 2, pts(1).X - pts(2).X, baseh)
  229. g.FillEllipse(rect, Color.FromArgb(fill, pen.Color))
  230. g.DrawEllipse(rect, pen)
  231. ip.X += grid.StepX
  232.  
  233. '' Parallelogram (use graphics.Transform on a rectangle):
  234. rect = New RectangleF(-grid.Radius * rectQx, -grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy)
  235. g.Transform = Matrix3x2.CreateSkew(Math.PI / 6, 0) * Matrix3x2.CreateTranslation(ip.X, ip.Y)
  236. g.DrawRectangle(rect, pen)
  237. g.Transform = Matrix3x2.Identity
  238. DrawCaption(g, ip, grid.Radius, "Parallelogram")
  239. ip.X += grid.StepX
  240.  
  241. '' Trapezoid (use DrawPolygon to just get the points of the square):
  242. Dim dx = 10
  243. pts = DrawPolygon(g, ip, grid.Radius, 4, -Math.PI / 4, Nothing, "Trapezoid")
  244. pts(0).X -= dx
  245. pts(1).X += dx
  246. pts(2).X -= dx
  247. pts(3).X += dx
  248. g.DrawPolygon(pts, pen)
  249. ''
  250. '' Done:
  251. doc.Save(stream)
  252. Return doc.Pages.Count
  253. End Function
  254. End Class
  255.