SvgGraphicsShapes.vb
'''' This code is part of Document Solutions for Imaging demos.'' Copyright (c) MESCIUS inc. All rights reserved.''Imports SystemImports System.IOImports System.DrawingImports System.Collections.GenericImports System.LinqImports System.NumericsImports GrapeCity.Documents.DrawingImports GrapeCity.Documents.TextImports GrapeCity.Documents.SvgImports GCTEXT = GrapeCity.Documents.TextImports GCDRAW = GrapeCity.Documents.Drawing
'' This example shows how to use GcSvgGraphics for common graphics'' operations. It draws some geometric shapes on GcSvgGraphics,'' then converts that graphics to GcSvgDocument, which is saved'' to an SVG stream that is shown by this sample.'' Note that the code drawing shapes on GcSvgGraphics is identical'' to the code drawing shapes on GcBitmapGraphics in the Shapes sample.'' Compare this to the SvgShapes sample which creates SVG elements'' representing shapes, and draws them on the resulting raster GcBitmap.Public Class SvgGraphicsShapes Public ReadOnly Property DefaultMime As String Get Return Util.MimeTypes.SVG End Get End Property
'' Helper method to draw a polygon and a caption beneath it. '' Can also be used to just calculate the points without actual drawing. '' startAngle is for the first point, clockwise from (1,0). Private Function DrawPolygon(g As GcGraphics, center As PointF, r As Single, n As Integer, startAngle As Single, pen As GCDRAW.Pen, Optional caption As String = Nothing) As PointF() Dim pts(n - 1) As PointF For i = 0 To n - 1 pts(i) = New PointF(center.X + CSng(r * Math.Cos(startAngle + 2 * Math.PI * i / n)), center.Y + CSng(r * Math.Sin(startAngle + 2 * Math.PI * i / n))) Next If pen IsNot Nothing Then g.DrawPolygon(pts, pen) End If If Not String.IsNullOrEmpty(caption) Then DrawCaption(g, center, r, caption) End If Return pts End Function
'' Helper method to draw a caption beneath a shape: Private Sub DrawCaption(g As GcGraphics, center As PointF, r As Single, caption As String) g.DrawString(caption, New TextFormat() With { .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerif.ttf")), .FontSize = 12 }, New RectangleF(center.X - r, center.Y + r, r * 2, 24), TextAlignment.Center, ParagraphAlignment.Center, False) End Sub
'' Main entry point. Public Function GenerateImageStream(targetMime As String, pixelSize As Size, dpi As Single, opaque As Boolean, Optional sampleParams As String() = Nothing) As Stream If targetMime <> Util.MimeTypes.SVG Then Throw New Exception("This sample only supports SVG output format.") End If
Dim Inch = dpi Dim ms = New MemoryStream() Using g As New GcSvgGraphics(pixelSize.Width, pixelSize.Height) If opaque Then g.FillRectangle(New RectangleF(0, 0, g.Width, g.Height), Color.White) End If
'' Document header: g.DrawString("Shapes", New TextFormat() With { .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerifBold.ttf")), .FontBold = True, .FontSize = 14, .Underline = True }, New RectangleF(PointF.Empty, New SizeF(g.Width, 44)), TextAlignment.Center, ParagraphAlignment.Far)
'' Pen used to draw shapes: Dim pen = New GCDRAW.Pen(Color.Orange, 1) pen.LineJoin = PenLineJoin.Round Dim fill As Integer = 100 '' Surfaces fill alpha
'' Set up the helper layout grid: Dim grid = New With { .Cols = 3, .Rows = 5, .MarginX = Inch / 4, .MarginY = Inch / 3, .Radius = Inch * 0.7F, .StepX = (g.Width - Inch / 2) / 3, .StepY = (g.Height - Inch / 4) / 5.5F }
Dim startIp As New PointF(grid.MarginX + grid.StepX / 2, grid.MarginY + grid.StepY / 2 + 10) Dim ip As PointF = startIp
'' Circle: g.DrawEllipse(New RectangleF(ip.X - grid.Radius, ip.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), pen) DrawCaption(g, ip, grid.Radius, "Circle") ip.X += grid.StepX
'' Ellipse: g.DrawEllipse(New RectangleF(ip.X - grid.Radius * 1.4F, ip.Y - grid.Radius / 2, grid.Radius * 2 * 1.4F, grid.Radius), pen) DrawCaption(g, ip, grid.Radius, "Ellipse") ip.X += grid.StepX
'' Cylinder: Dim radX = grid.Radius / 1.4F Dim radY = grid.Radius / 6 Dim height = grid.Radius * 1.8F g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y - height / 2, radX * 2, radY * 2), pen) g.FillEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), Color.FromArgb(fill, pen.Color)) g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), pen) g.DrawLine(New PointF(ip.X - radX, ip.Y - height / 2 + radY), New PointF(ip.X - radX, ip.Y + height / 2 - radY), pen) g.DrawLine(New PointF(ip.X + radX, ip.Y - height / 2 + radY), New PointF(ip.X + radX, ip.Y + height / 2 - radY), pen) DrawCaption(g, ip, grid.Radius, "Cylinder") ip.X = startIp.X ip.Y += grid.StepY pen.Color = Color.Indigo
'' Square: DrawPolygon(g, ip, grid.Radius, 4, CSng(-Math.PI / 4), pen, "Square") ip.X += grid.StepX
'' Rectangle: Dim rectQx As Single = 1.4F Dim rectQy As Single = 0.6F Dim rect = New RectangleF(ip.X - grid.Radius * rectQx, ip.Y - grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy) g.DrawRectangle(rect, pen) DrawCaption(g, ip, grid.Radius, "Rectangle") ip.X += grid.StepX
'' Cube: Dim cubex As Single = 6 Dim cubePtsFar = DrawPolygon(g, New PointF(ip.X - cubex, ip.Y - cubex), grid.Radius, 4, CSng(-Math.PI / 4), pen) Dim cubePtsNear = DrawPolygon(g, New PointF(ip.X + cubex, ip.Y + cubex), grid.Radius, 4, CSng(-Math.PI / 4), pen) g.DrawLine(cubePtsFar(0), cubePtsNear(0), pen) g.DrawLine(cubePtsFar(1), cubePtsNear(1), pen) g.DrawLine(cubePtsFar(2), cubePtsNear(2), pen) g.DrawLine(cubePtsFar(3), cubePtsNear(3), pen) g.FillPolygon(New PointF() {cubePtsFar(1), cubePtsFar(2), cubePtsNear(2), cubePtsNear(1)}, Color.FromArgb(fill, pen.Color)) DrawCaption(g, ip, grid.Radius, "Cube") ip.X = startIp.X ip.Y += grid.StepY pen.Color = Color.DarkGreen
'' Pentagon: DrawPolygon(g, ip, grid.Radius, 5, CSng(-Math.PI / 2), pen, "Pentagon") ip.X += grid.StepX
'' Hexagon with transform: g.Transform = Matrix3x2.CreateScale(1.4F, 0.8F) * Matrix3x2.CreateTranslation(ip.X, ip.Y) DrawPolygon(g, PointF.Empty, grid.Radius, 6, 0, pen, Nothing) g.Transform = Matrix3x2.Identity DrawCaption(g, ip, grid.Radius, "Hexagon") ip.X += grid.StepX
'' Octagon: DrawPolygon(g, ip, grid.Radius, 8, CSng(-Math.PI / 8), pen, "Octagon") ip.X = startIp.X ip.Y += grid.StepY pen.Color = Color.DarkRed
'' Triangle: DrawPolygon(g, ip, grid.Radius, 3, CSng(-Math.PI / 2), pen, "Triangle") ip.X += grid.StepX
'' Filled pentagram: Dim pts = DrawPolygon(g, ip, grid.Radius, 5, CSng(-Math.PI / 2), pen, "Pentagram") pts = New PointF() {pts(0), pts(2), pts(4), pts(1), pts(3)} g.FillPolygon(pts, Color.FromArgb(fill, pen.Color)) g.DrawPolygon(pts, pen) ip.X += grid.StepX
'' Pyramid (oblique projection): Dim angle = Math.PI / 6 Dim s = CSng(Math.Sin(angle)) Dim c = CSng(Math.Cos(angle)) Dim project As Func(Of Single, Single, Single, PointF) = Function(x_, y_, z_) New PointF(x_ - c * y_ * 0.5F, -(z_ - s * y_ * 0.5F)) Dim p3d As Func(Of Vector3, PointF) = Function(v_) project(v_.X, v_.Y, v_.Z) Dim hedge = grid.Radius Dim pts3d = { New Vector3(-hedge, -hedge, 0), New Vector3(hedge, -hedge, 0), New Vector3(hedge, hedge, 0), New Vector3(-hedge, hedge, 0), New Vector3(0, 0, hedge * 2) } pts = pts3d.Select(Function(v_) p3d(v_)).ToArray() g.Transform = Matrix3x2.CreateTranslation(ip.X, ip.Y + hedge * 0.7F) g.DrawPolygon(New PointF() {pts(4), pts(1), pts(2), pts(3), pts(4), pts(2)}, pen) pen.Width /= 2 pen.Color = Color.FromArgb(fill, pen.Color) g.DrawLine(pts(0), pts(4), pen) g.DrawLine(pts(0), pts(1), pen) g.DrawLine(pts(0), pts(3), pen) g.FillPolygon(pts.Take(4).ToArray(), pen.Color) g.Transform = Matrix3x2.Identity DrawCaption(g, ip, grid.Radius, "Pyramid") ip.X = startIp.X ip.Y += grid.StepY pen.Width *= 2 pen.Color = Color.Green
'' Cone: Dim baseh = grid.Radius * 0.3F pts = DrawPolygon(g, ip, grid.Radius, 3, CSng(-Math.PI / 2), Nothing, "Cone") g.DrawLines(New PointF() {pts(2), pts(0), pts(1)}, pen) rect = New RectangleF(pts(2).X, pts(2).Y - baseh / 2, pts(1).X - pts(2).X, baseh) g.FillEllipse(rect, Color.FromArgb(fill, pen.Color)) g.DrawEllipse(rect, pen) ip.X += grid.StepX
'' Parallelogram (use skew transform on a rectangle): rect = New RectangleF(-grid.Radius * rectQx, -grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy) g.Transform = Matrix3x2.CreateSkew(CSng(Math.PI / 6), 0) * Matrix3x2.CreateTranslation(ip.X, ip.Y) g.DrawRectangle(rect, pen) g.Transform = Matrix3x2.Identity DrawCaption(g, ip, grid.Radius, "Parallelogram") ip.X += grid.StepX
'' Trapezoid (adjust points of a square): Dim dx As Single = 10 pts = DrawPolygon(g, ip, grid.Radius, 4, CSng(-Math.PI / 4), Nothing, "Trapezoid") pts(0).X -= dx pts(1).X += dx pts(2).X -= dx pts(3).X += dx g.DrawPolygon(pts, pen)
'' Done: Dim svg = g.ToSvgDocument() svg.Save(ms) ms.Seek(0, SeekOrigin.Begin) Return ms End Using End FunctionEnd Class