Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to specify a certain point of the equation bounding box as a reference point? #27

Closed
sadqiang opened this issue Jan 1, 2019 · 5 comments
Labels
Resolution/Answered The provided question has been answered. Type/Question

Comments

@sadqiang
Copy link
Contributor

sadqiang commented Jan 1, 2019

I am making a crazy analog clock as follows.

clock

The problem is that I have not control to specify a certain point on the equation bounding box as a reference point at which I position the equation with DrawOneLine method.

Here is my code:

using SkiaSharp;
using SkiaSharp.Views.Forms;
using CSharpMath.SkiaSharp;

using System;
using Xamarin.Forms;
using static System.Math;

namespace Clock
{
    public partial class MainPage : ContentPage
    {
        readonly SKPaint blackFillPaint = new SKPaint
        {
            Style = SKPaintStyle.Fill,
            Color = SKColors.Black
        };

        readonly SKPaint whiteFillPaint = new SKPaint
        {
            Style = SKPaintStyle.Fill,
            Color = SKColors.White
        };

        readonly SKPaint whiteStrokePaint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.White,
            StrokeCap = SKStrokeCap.Round,
            IsAntialias = true
        };

        readonly SKPaint redStrokePaint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.Red,
            StrokeCap = SKStrokeCap.Round,
            IsAntialias = true
        };

        readonly string[] labels =
            {
                @"$\frac{44+4}{4}$",
                @"$\frac{44}{44}$",
                @"$\frac{4}{4}+\frac{4}{4}$",
                @"$\frac{4+4+4}{4}$",
                @"$4+\frac{4-4}{4}$",
                @"$4+4^{4-4}$",
                @"$4+\frac{4+4}{4}$",
                @"$\frac{44}{4}-4$",
                @"$4\times4-4-4$",
                @"$4+4+\frac{4}{4}$",
                @"$\frac{44-4}{4}$",
                @"$\frac{4!}{\sqrt4}-\frac{4}{4}$"
            };

        public MainPage()
        {
            InitializeComponent();
            Device.StartTimer(TimeSpan.FromSeconds(1), () =>
               {
                   canvasView.InvalidateSurface();
                   return true;
               });
        }

        private void CanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            SKCanvas canvas = e.Surface.Canvas;
            canvas.Clear(SKColors.CornflowerBlue);

            int width = e.Info.Width;
            int height = e.Info.Height;

            canvas.Translate(width / 2, height / 2);
            canvas.Scale(width / 210f);


            canvas.DrawCircle(0, 0, 100, blackFillPaint);


            var painter = new TextPainter
            {
                FontSize = 8,
                TextColor = SKColors.White
            };

            for (int i = 0; i < 60; i++)
            {
                canvas.Save();
                canvas.RotateDegrees(6 * i);
                canvas.DrawCircle(0, -90, i % 5 == 0 ? 4 : 2, whiteFillPaint);
                canvas.Restore();

                if (i % 5 == 0)
                {
                    painter.Text = labels[i / 5];
                    painter.DrawOneLine(canvas, (float)(80 * Cos((90 - 6 * i) / 180f * PI)), (float)(-80 * Sin((90 - 6 * i) / 180f * PI)));
                }
            }


            DateTime dateTime = DateTime.Now;

            // H
            canvas.Save();
            canvas.RotateDegrees(30 * dateTime.Hour + dateTime.Minute / 2f);
            whiteStrokePaint.StrokeWidth = 12;
            canvas.DrawLine(0, 0, 0, -50, whiteStrokePaint);
            canvas.Restore();

            // M
            canvas.Save();
            canvas.RotateDegrees(6 * dateTime.Minute + dateTime.Second / 10f);
            whiteStrokePaint.StrokeWidth = 6;
            canvas.DrawLine(0, 0, 0, -65, whiteStrokePaint);
            canvas.Restore();


            // S
            canvas.Save();
            float seconds = dateTime.Second;// + dateTime.Millisecond / 1000f;
            canvas.RotateDegrees(6f * seconds);
            redStrokePaint.StrokeWidth = 2;
            canvas.DrawLine(0, 0, 0, -75, redStrokePaint);
            canvas.Restore();


        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Clock"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="Clock.MainPage">

    <skia:SKCanvasView x:Name="canvasView" PaintSurface="CanvasView_PaintSurface"/>

</ContentPage>
@charlesroddie
Copy link
Collaborator

Use the Measure property of a MathPainter or TextPainter.

@Happypig375
Copy link
Collaborator

Change these two lines to make the displayed formulae shorter,

-                @"$4\times4-4-4$",
-                @"$4+4+\frac{4}{4}$",
+                @"$\sqrt{4}\times4$",
+                @"$\:\:(4-\frac{4}{4})^{\sqrt{4}}$",

and change these lines to draw the formulae at the centre. (DrawOneLine's coordinates are at the baseline - like in penmanship, while Draw's coordinates are at the corner)

-                    painter.DrawOneLine(canvas, (float)(80 * Cos((90 - 6 * i) / 180f * PI)), (float)(-80 * Sin((90 - 6 * i) / 180f * PI)));
+                    var measure = painter.Measure(width).Value;
+                    var θ = (90 - 6 * i) / 180f * PI;
+                    var sinθ = (float)Sin(θ);
+                    var cosθ = (float)Cos(θ);
+                    painter.Draw(canvas, new System.Drawing.PointF((75) * cosθ - measure.Width / 2, (-75) * sinθ - measure.Height / 2), float.PositiveInfinity);

image
I'll include this in the example app if you don't mind.

@Happypig375 Happypig375 added the Resolution/Answered The provided question has been answered. label Jan 2, 2019
@Happypig375
Copy link
Collaborator

P.S. Use ```cs instead of ``` to start a C# code block since it will also provide syntax highlighting. I fixed it for you.

@charlesroddie
Copy link
Collaborator

For a MathPainter (which is better to use here) the height adjustment would be - (measure.Bottom + measure.Top) / 2.

@sadqiang
Copy link
Contributor Author

sadqiang commented Jan 2, 2019

Thank you very much for answering. No problem for reusing this code. By the way, the code was "retyped" (but not exactly the same) from Charles Petzold's webinar about SkiaSharp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution/Answered The provided question has been answered. Type/Question
Projects
None yet
Development

No branches or pull requests

3 participants