0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2D CGライブラリSkiaSharp「マンデルブロート集合」

Posted at
  • 下記サイトにあるWinForms+GDI版マンデルブロート集合をWPF+SkiaSharpに移植しました。作者許諾済み。


  • マウスの左で拡大します。右で縮小です。表示には5秒程掛かります。
  • ウィンドウのリサイズは可能ですがかなり動作が遅いです。
  • 移植が不完全なのか拡大時に違う所を拡大してしまう事があります。
  • 結構古く、DOSの時代に既にありました。

・うまくクリックすると多様な模様が出る(自己相似性)
1 - コピー (4).jpg

1 - コピー (7).jpg

1 - コピー (6).jpg

WPF C#

////////////////////////////////////////////////////////
// WPF+SkiaSharp  マンデルブロ集合
// 移植元 https://lets-csharp.com/drow-mandelbrot-set/
/////////////////////////////////////////////////////////

using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System.Numerics;
using System.Windows;
using System.Windows.Input;

namespace SkiaSharpSample {

    public partial class MainWindow : Window	{
    
        double ParDot = 0.005;
        double CenterX = -0.5;
        double CenterY = 0;

        int R,G,B;
        int NumberOfTrials = 40;

		public MainWindow()		{
			InitializeComponent();
        }

        static int SK_X,SK_Y;

        double RealMin{
            get { return CenterX - ParDot * SK_X / 2; }
        }
 
        double ImaginarylMin{
            get { return CenterY - ParDot * SK_Y / 2; }
        }

		void PaintSurface(object sender, SKPaintSurfaceEventArgs args){
            
           // SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;

            SK_X=args.Info.Width;
            SK_Y=args.Info.Height;

            canvas.Clear(SKColors.White);
            
            SKPaint skPaint = new SKPaint{
	            Style = SKPaintStyle.Stroke,
	            IsAntialias = true,
                Color=new SKColor(0,0,0),
	            StrokeWidth = 1               
            };
    
            for (int x = 0; x < SK_X; x++){
                for (int y = 0; y < SK_Y; y++)            {
 
                    Complex c = new Complex(RealMin + x * ParDot,ImaginarylMin + y * ParDot);

                    int count = 0;
                    if (IsMandelbrotSet(c,ref count)){
                        skPaint.Color=new SKColor(255,255,255);
                        canvas.DrawPoint(x, y, skPaint);
                    }
                    else{
                        CreateColorFromInt(count);
                        skPaint.Color=new SKColor((byte)R,(byte)G,(byte)B);
                        canvas.DrawPoint(x, y, skPaint);
                    }
                }
            }
        }

        bool IsMandelbrotSet(Complex c,ref int count){

            int numberOfTrials = 384;
            Complex z = Complex.Zero;
            for (int i = 0; i < numberOfTrials; i++){
                z = z * z + c;
                if (z.Magnitude > 2){
                    count = i;
                    return false;
                }
            }
            count = -1;
            return true;
        }

        private void Window_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {

            System.Windows.Point point = e.GetPosition(this);
            int MY=(int)point.Y;
            int MX=(int)point.X;
                      
            CenterX = MX*  ParDot + RealMin;
            CenterY = (SK_Y - MY) * ParDot + ImaginarylMin;
            
            if (e.LeftButton == MouseButtonState.Pressed){
                 ParDot *= 0.5;
            }

            if (e.RightButton == MouseButtonState.Pressed){
                 ParDot /= 0.5;
            }
           
            skiaCanvas.InvalidateVisual(); 
        }

        private void skiaCanvas_PreviewMouseMove(object sender, MouseEventArgs e) {
            var x2=e.GetPosition(this).X;
            var y2=e.GetPosition(this).Y;
            
            double x = RealMin - x2 * ParDot;
            double y = ImaginarylMin + (SK_Y - y2) * ParDot;
       
            Title ="X=" + x.ToString()+" Y="+y.ToString() +" ParDot="+ParDot.ToString();        
        }

        void  CreateColorFromInt(int i){
            if (i < 128) {
                R=(i * 2);
                G= i * 2;
                B= 255 - i * 2;
                
            }
            else if (i < 256){
                R=255;
                G=255 - (i - 128) * 2;
                B=0;
            }
            else if (i < 384){
                R=255;
                G=(i - 256) * 2;
                B=(i - 256) * 2;
            }
            else{
                R=0;
                G=0;
                B=0;
            }
        }
    }
}

WPF XAML

<Window x:Class="SkiaSharpSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SkiaSharpSample" xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" 
        xmlns:wpf="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" mc:Ignorable="d"
        Title="SkiaSharp" Height="480" Width="640"  MouseDown="Window_MouseDown"  >

    <Grid  >
        <wpf:SKElement x:Name="skiaCanvas" PaintSurface="PaintSurface"  PreviewMouseMove="skiaCanvas_PreviewMouseMove"  />
    </Grid>
</Window>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?