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