[ MilosDj @ 11.12.2016. 16:44 ] @
Poceo sam da ucim C# pre 2 meseca. Imao bih par pitanja i svaki validan C# savet je dobrodosao 1. Ovo sam iskoristio za grupisanje imena i funkcija. Jel ima neki bolji nacin? Code: private Dictionary<string, Ord> combo_functions = new Dictionary<string, Ord> { {"pixels_white", new Ord("pixels_", "Pixels White", new object[]{0xFF000000, 0xFFFFFFFF, 10000})}, ... 2. Koristim initComboBoxPixels() da popunim comboBox. Moze li se direktno popuniti combo_functions? 3. init_pixel_bounce() ima bug. Zasto uzastipno kliktanje na start ubrzava bouncing pixel. 4. U button_start_Click koristim animate_f. Nesto nisam zadovoljan s tim. Ima li direktan nacin da se pozove e handler, ili da napravim jedan eHandler pa da mu predam potrebne parametre ili nesto bolje/vise C#? Kako se dinamicki menjaju event handleri u C#? Jel to uopste dobar pravac razmisljanja za C#? 5. Zeza me image. Bouncing pixel ide iza imgWidth. Namerno sam stavio window width na 820. Ako je width = 800, image bude veca od prozora. Zasto??? 6. clearAnimation() treba da obrise sve event handlers. Kako se to radi u ovom slucaju? 7. DispatcherTimer je proradio za wpf. Ima li nesto bolje u ovom slucaju? Ako ikome zatreba ceo kod. To manje vise radi. Baguje ta veca slika, wbmpex ima bug za Rect, cudno se ponasa bounce... Code: // MainWindow.xaml.cs using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Reflection; using wbmp.pack; using System.Windows.Threading; namespace wbmp1 { public class Ord { public string fname; public string title; public object[] ar; public Ord (string n, string t, object[] a) { fname = n; title = t; ar = a; } } public partial class MainWindow : Window { private Wbmp w; private Random rnd = new Random(); private string toCall = ""; private bool animation = false; DispatcherTimer dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal); private wbmp.pack.Point p_bounce; private wbmp.pack.Point p_move; private Dictionary<string, string> combo_dict = new Dictionary<string, string>(); // fname, title, ar{bg, col, count} private Dictionary<string, Ord> combo_functions = new Dictionary<string, Ord> { {"pixels_white", new Ord("pixels_", "Pixels White", new object[]{0xFF000000, 0xFFFFFFFF, 10000})}, {"pixels_black", new Ord("pixels_", "Pixels Black", new object[]{0xFFFFFFFF, 0xFF000000, 10000})}, {"pixels_green", new Ord("pixels_", "Pixels Green", new object[]{0xFFFFFFFF, 0xFF00FF00, 10000})}, {"pixels_random", new Ord("pixels_random", "Pixels Random", new object[]{10000})}, {"pixels_quad", new Ord("piels_quad", "Pixels Quad", new object[] {0xFFFFFFFF})}, {"p_bounce_black", new Ord("init_pixel_bounce", "P Bounce Black", new object[] {0xFFFFFFFF, 0xFF000000})}, {"p_bounce_white", new Ord("init_pixel_bounce", "P Bounce White", new object[] {0xFF000000, 0xFFFFFFFF})}, {"pixels_bounce_", new Ord("pixels_bounce_", "Pixels Bounce", new object[] {0xFFFFFFFF, 0xFF000000, 1000})}, {"lines_white", new Ord("lines_", "Lines White", new object[]{0xFF000000, 0xFFFFFFFF, 1000})}, {"lines_black", new Ord("lines_", "Lines Black", new object[]{0xFFFFFFFF, 0xFF000000, 1000})}, {"lines_random", new Ord("lines_random", "Lines Random", new object[]{10000})}, {"triangles_white", new Ord("triangles_", "Triangles White", new object[]{0xFF000000, 0xFFFFFFFF, 25})}, {"triangles_black", new Ord("triangles_", "Triangles Black", new object[]{0xFFFFFFFF, 0xFF000000, 25})}, {"triangles_random", new Ord("triangles_random", "Triangles Random", new object[]{25})}, {"triangles_bound_white", new Ord("triangles_bound_", "Triangles Bound White", new object[]{0xFF000000, 0xFFFFFFFF, 50})}, {"triangles_bound_black", new Ord("triangles_bound_", "Triangles Bound Black", new object[]{0xFFFFFFFF, 0xFF000000, 50})}, {"triangles_bound_random", new Ord("triangles_bound_random", "Triangles Bound Random", new object[]{50})}, {"rect_white", new Ord("rect_", "Rect White", new object[]{0xFF000000, 0xFFFFFFFF, 50})}, {"rect_black", new Ord("rect_", "Rect Black", new object[]{0xFFFFFFFF, 0xFF000000, 50})}, {"rect_random", new Ord("rect_random", "Rect Random", new object[]{50})}, {"quad_white", new Ord("quad_", "Quad White", new object[]{0xFF000000, 0xFFFFFFFF, 50})}, {"quad_black", new Ord("quad_", "Quad Black", new object[]{0xFFFFFFFF, 0xFF000000, 50})}, {"quad_random", new Ord("quad_random", "Quad Random", new object[]{50})}, {"ellipse_white", new Ord("ellipse_", "Ellipse White", new object[]{0xFF000000, 0xFFFFFFFF, 50})}, {"ellipse_black", new Ord("ellipse_", "Ellipse Black", new object[]{0xFFFFFFFF, 0xFF000000, 50})}, {"ellipse_random", new Ord("ellipse_random", "Ellipse Random", new object[]{50})}, {"poly_white", new Ord("poly_", "Poly White", new object[]{0xFF000000, 0xFFFFFFFF, 20})}, {"poly_black", new Ord("poly_", "Poly Black", new object[]{0xFFFFFFFF, 0xFF000000, 20})}, {"poly_random", new Ord("poly_random", "Poly Random", new object[]{20})}, }; public MainWindow () { InitializeComponent(); w = new Wbmp(800, 600); image.Source = w.WB; initComboBoxPixels(); pixels_(); } public void invoke (string fstr, object[] p=null) { //using System.Reflection; try { Type ot = this.GetType(); MethodInfo mi = ot.GetMethod(fstr); if (null == mi) return; mi.Invoke(this, p); // null or [] params } catch (AmbiguousMatchException) { // manu same name methods txt_ekran.Text = "Same method names"; } catch (Exception e) { txt_ekran.Text = e.ToString(); } } private void initComboBoxPixels () { var ci = new ComboBoxItem(); foreach (KeyValuePair<string, Ord> o in combo_functions) { combo_dict.Add(o.Key, o.Value.title); } comboBoxShapes.ItemsSource = combo_dict; comboBoxShapes.DisplayMemberPath = "Value"; // "Key" } /// <summary> /// pixels_ /// </summary> /// <param name="bg_col">uint background color</param> /// <param name="color">uint line color</param> /// <param name="count">int count</param> public void pixels_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000, int count = 1000) { w.Clear(bg_col); int x,y; for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); w.Pixel(x, y, color); } w.Refresh(); } /// <summary> /// random color pizels /// </summary> /// <param name="count">int number of pixels on screen</param> public void pixels_random (int count=1000) { w.Clear(); ColorUint c = new ColorUint(); int x,y; for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); c.B = (byte)rnd.Next(128, 256); c.G = (byte)rnd.Next(128, 256); c.R = (byte)rnd.Next(128, 256); w.Pixel(x, y, c); } w.Refresh(); } public void init_pixel_bounce (uint bg_col=0xFFFFFFFF, uint color=0xFF000000) { animation = true; cb_anim.IsChecked = false; dispatcherTimer.Tick += new EventHandler(pixel_bounce); // remove? dispatcherTimer.Interval = new TimeSpan(0,0,0,0,16); dispatcherTimer.Start(); p_bounce = new wbmp.pack.Point(); p_bounce.X = rnd.Next(w.ImgWidth); p_bounce.Y = rnd.Next(w.ImgHeight); p_bounce.C = color; p_move.X = (float)rnd.NextDouble(); p_move.Y = (float)rnd.NextDouble(); // how to set bg_col p_move.C = bg_col; } public void pixel_bounce (object source, EventArgs e) { w.Clear(p_move.C); int mw = w.ImgWidth - 1; int mh = w.ImgHeight - 1; //p_bounce + p_move p_bounce.X += p_move.X; p_bounce.Y += p_move.Y; if (p_bounce.X <= 0) { p_move.X = -p_move.X; p_bounce.X = 0; } else if (p_bounce.X >= mw) { p_move.X = -p_move.X; p_bounce.X = mw; } if (p_bounce.Y <= 0) { p_move.Y = -p_move.Y; p_bounce.Y = 0; } else if (p_bounce.Y >= mh) { p_move.Y = -p_move.Y; p_bounce.Y = mh; } w.Pixel(p_bounce); w.Refresh(); } /// <summary> /// Draw lines on screen /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void lines_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000, int count = 1000) { w.Clear(bg_col); for (var i=0; i < count; ++i) { w.Line1(rnd.Next(w.ImgWidth), rnd.Next(w.ImgHeight), rnd.Next(w.ImgWidth), rnd.Next(w.ImgHeight), color); } w.Refresh(); } /// <summary> /// Draw random color lines /// </summary> /// <param name="count"></param> public void lines_random (int count=1000) { ColorUint c = new ColorUint(); w.Clear(0xFFFFFFFF); for (var i=0; i < count; ++i) { w.Line1(rnd.Next(w.ImgWidth), rnd.Next(w.ImgHeight), rnd.Next(w.ImgWidth), rnd.Next(w.ImgHeight), c.Random()); } w.Refresh(); } /// <summary> /// Draw triangles /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void triangles_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000, int count=100) { int wpx, hpx; wpx = w.ImgWidth; hpx = w.ImgHeight; w.Clear(bg_col); wbmp.pack.Point a = new wbmp.pack.Point(), b = new wbmp.pack.Point(), c = new wbmp.pack.Point(); for (var i=0; i < count; ++i) { a.X = rnd.Next(wpx); a.Y = rnd.Next(hpx); b.X = rnd.Next(wpx); b.Y = rnd.Next(hpx); c.X = rnd.Next(wpx); c.Y = rnd.Next(hpx); w.Triangle(a, b, c, color); } w.Refresh(); } /// <summary> /// Draw random color triangles /// </summary> /// <param name="count"></param> public void triangles_random (int count=100) { ColorUint col = new ColorUint(); int wpx, hpx; wpx = w.ImgWidth; hpx = w.ImgHeight; w.Clear(0xFFFFFFFF); wbmp.pack.Point a = new wbmp.pack.Point(), b = new wbmp.pack.Point(), c = new wbmp.pack.Point(); for (var i=0; i < count; ++i) { a.X = rnd.Next(wpx); a.Y = rnd.Next(hpx); b.X = rnd.Next(wpx); b.Y = rnd.Next(hpx); c.X = rnd.Next(wpx); c.Y = rnd.Next(hpx); w.Triangle(a, b, c, col.Random()); } w.Refresh(); } /// <summary> /// Draw triangles /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void triangles_bound_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000, int count=100) { int wpx, hpx; wpx = w.ImgWidth; hpx = w.ImgHeight; w.Clear(bg_col); wbmp.pack.Point a = new wbmp.pack.Point(), b = new wbmp.pack.Point(), c = new wbmp.pack.Point(); for (var i=0; i < count; ++i) { a.X = rnd.Next(wpx); a.Y = rnd.Next(hpx); b.X = range((int)a.X, 0, wpx, 100); b.Y = range((int)a.Y, 0, hpx, 100); c.X = range((int)a.X, 0, wpx, 100); c.Y = range((int)a.Y, 0, hpx, 100); w.Triangle(a, b, c, color); } w.Refresh(); } /// <summary> /// Draw random color bounded triangles /// </summary> /// <param name="count"></param> public void triangles_bound_random (int count = 100) { ColorUint col = new ColorUint(); int wpx, hpx; wpx = w.ImgWidth; hpx = w.ImgHeight; w.Clear(0xFFFFFFFF); wbmp.pack.Point a = new wbmp.pack.Point(), b = new wbmp.pack.Point(), c = new wbmp.pack.Point(); for (var i=0; i < count; ++i) { a.X = rnd.Next(wpx); a.Y = rnd.Next(hpx); b.X = range((int)a.X, 0, wpx, 100); b.Y = range((int)a.Y, 0, hpx, 100); c.X = range((int)a.X, 0, wpx, 100); c.Y = range((int)a.Y, 0, hpx, 100); w.Triangle(a, b, c, col.Random()); } w.Refresh(); } /// <summary> /// Draw ellipse /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void ellipse_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000 , int count = 100) { ColorUint col = new ColorUint(); int x,y,r1,r2; w.Clear(bg_col); for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); r1 = rnd.Next(0, 100); r2 = rnd.Next(0, 100); w.Ellipse(x,y,r1,r2, color); } w.Refresh(); } /// <summary> /// Draw random color ellipse /// </summary> /// <param name="count"></param> public void ellipse_random (int count = 100) { ColorUint col = new ColorUint(); int x,y,r1,r2; w.Clear(0xFFFFFFFF); for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); r1 = rnd.Next(0, 100); r2 = rnd.Next(0, 100); w.Ellipse(x,y,r1,r2, col.Random()); } w.Refresh(); } /// <summary> /// Draw Rect /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void rect_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000 , int count = 100) { ColorUint col = new ColorUint(); int x,y,r1,r2; w.Clear(bg_col); for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); r1 = x + rnd.Next(0, 100); r2 = y + rnd.Next(0, 100); w.Rect(x,y,r1,r2, color); } w.Refresh(); } /// <summary> /// Draw random color Rect /// </summary> /// <param name="count"></param> public void rect_random (int count = 100) { ColorUint col = new ColorUint(); int x,y,r1,r2; w.Clear(0xFFFFFFFF); for (var i=0; i < count; ++i) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); r1 = x + rnd.Next(0, 100); r2 = y + rnd.Next(0, 100); w.Rect(x,y,r1,r2, col.Random()); } w.Refresh(); } // ? public void quad_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000 , int count = 100) { ColorUint col = new ColorUint(); int x1,y1, x2,y2,x3,y3, x4,y4; w.Clear(bg_col); for (var i=0; i < count; ++i) { x1 = rnd.Next(w.ImgWidth); y1 = rnd.Next(w.ImgHeight); x2 = x1 + range(x1); y2 = y1 + range(y1); x3 = x1 + range(x1); y3 = y1 + range(y1); x4 = x1 + range(x1); y4 = y1 + range(y1); w.Quad(x1, y1,x2, y2, x3,y3, x4,y4, color); } w.Refresh(); } // ? public void quad_random (int count = 100) { ColorUint col = new ColorUint(); int x1,y1, x2,y2,x3,y3, x4,y4; w.Clear(0xFFFFFFFF); for (var i=0; i < count; ++i) { x1 = rnd.Next(w.ImgWidth); y1 = rnd.Next(w.ImgHeight); x2 = x1 + range(x1, 0, w.ImgWidth, 50); y2 = y1 + range(y1, 0, w.ImgHeight, 50); x3 = x1 + range(x1, 0, w.ImgWidth, 50); y3 = y1 + range(y1, 0, w.ImgHeight, 50); x4 = x1 + range(x1, 0, w.ImgWidth, 50); y4 = y1 + range(y1, 0, w.ImgHeight, 50); w.Quad(x1, y1,x2, y2, x3,y3, x4,y4, col.Random()); } w.Refresh(); } /// <summary> /// Draw Polyline /// </summary> /// <param name="bg_col"></param> /// <param name="color"></param> /// <param name="count"></param> public void poly_ (uint bg_col=0xFFFFFFFF, uint color=0xFF000000 , int count = 100) { int i, j, len, x,y; w.Clear(bg_col); for (j = 0; j < count; ++j) { len = rnd.Next(3,10) * 2; int[] points = new int[len]; for (i = 0; i < len; i += 2) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); points[i] = x; points[i+1] = y; } w.Polyline(points, color); } w.Refresh(); } /// <summary> /// Draw random color Rect /// </summary> /// <param name="count"></param> public void poly_random (int count = 100) { int i, j, len, x,y; ColorUint col = new ColorUint(); w.Clear(0xFFFFFFFF); int[][] points_ar = new int[count][]; for (j = 0; j < count; ++j) { len = rnd.Next(3,10) * 2; points_ar[j] = new int[len]; for (i = 0; i < len; i += 2) { x = rnd.Next(w.ImgWidth); y = rnd.Next(w.ImgHeight); points_ar[j][i] = x; points_ar[j][i+1] = y; } } for (j = 0; j < count; ++j) { w.Polyline(points_ar[j], col.Random()); } w.Refresh(); } public int range (int x, int start=0, int end=800, int pm=50) { int a, b; a = x - pm; a = a < start ? start : a; b = x + pm; b = b > end ? end : b; return rnd.Next(a, b); } private void comboBoxShapes_GotFocus (object sender, RoutedEventArgs e) { int index = comboBoxShapes.SelectedIndex; if (index < 0) return; KeyValuePair<string, string> si = (KeyValuePair<string, string>) comboBoxShapes.SelectedItem; txt_ekran.Text = si.Value; toCall = si.Key; } private void comboBoxShapes_SelectionChanged (object sender, SelectionChangedEventArgs e) { int index = comboBoxShapes.SelectedIndex; if (index < 0) return; KeyValuePair<string, string> si = (KeyValuePair<string, string>) comboBoxShapes.SelectedItem; txt_ekran.Text = si.Value; toCall = si.Key; } private void button_start_Click (object sender, RoutedEventArgs e) { if (String.IsNullOrWhiteSpace(toCall)) return; clearAnimation(); if (combo_functions.ContainsKey(toCall)) { Ord obj = combo_functions[toCall]; if (cb_anim.IsChecked ?? false) { if (animation) return; else animation = true; txt_ekran.Text += " animation"; dispatcherTimer.Tick += new EventHandler(animate_f); dispatcherTimer.Interval = new TimeSpan(0,0,0,0,16); dispatcherTimer.Start(); } else { // no anim checked invoke(obj.fname, obj.ar); } } }// end button start click() private void button_stop_Click (object sender, RoutedEventArgs e) { clearAnimation(); // toCall = ""; txt_ekran.Text = toCall; w.Clear(0xFFFFFFFF); w.Refresh(); } private void clearAnimation () { if (!animation) return; dispatcherTimer.Stop(); animation = false; } private void animate_f (object source, EventArgs e) { Ord obj = combo_functions[toCall]; invoke(obj.fname, obj.ar); } // // }// end class }// end namespace Code: // MainWindow.xaml.cs <Window x:Class="wbmp1.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:wbmp1" mc:Ignorable="d" Title="Draw" Height="702" Width="820" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Background="Red"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="600"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Image x:Name="image" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" SnapsToDevicePixels="True" Stretch="None" ScrollViewer.VerticalScrollBarVisibility="Disabled" Margin="1" ClipToBounds="True" IsEnabled="False" IsHitTestVisible="False"/> <Canvas Grid.Row="1"> <Canvas.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="Black" Offset="0"/> <GradientStop Color="White" Offset="1"/> <GradientStop Color="#FFDFDFDF" Offset="1"/> <GradientStop Color="#FF212121"/> </LinearGradientBrush> </Canvas.Background> <ComboBox x:Name="comboBoxShapes" Canvas.Left="10" Canvas.Top="10" Width="120" GotFocus="comboBoxShapes_GotFocus" SelectionChanged="comboBoxShapes_SelectionChanged"/> <Button x:Name="button_stop" Content="Stop" Width="75" Height="20" HorizontalAlignment="Right" VerticalAlignment="Center" Click="button_stop_Click" Canvas.Left="90" Canvas.Top="41"/> <Button x:Name="button_start" Content="Start" Canvas.Left="10" Canvas.Top="41" Width="75" Click="button_start_Click"/> <TextBox x:Name="txt_ekran" Canvas.Left="384" Width="400" FontFamily="Verdana" FontSize="12" Height="61" TextWrapping="Wrap" Background="#FFE1E1E4" IsReadOnly="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/> <CheckBox x:Name="cb_anim" Content="Animation" Canvas.Left="135" Canvas.Top="10"/> </Canvas> </Grid> </Window> Code: // Wbmp.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace wbmp.pack { #region Color Point /// <summary> /// 0xAARRGGBB uint color /// </summary> public class ColorUint { // 0xaarrggbb; private uint c; // inverted on PC private Random rnd = new Random(); /// <summary> /// set uint color by 4 bytes argb /// </summary> /// <param name="r">byte red</param> /// <param name="g">byte green</param> /// <param name="b">byte blue</param> /// <param name="a">byte alpha</param> public ColorUint (byte r=255, byte g=255, byte b=255, byte a=255) { /*uint gg = (uint) g << 8, rr = (uint) r << 16, aa = (uint) a << 24; c = aa | rr | gg | b; */ c = (uint) a << 24 | (uint) r << 16 | (uint) g << 8 | b; } /// <summary> /// set uint color by uint /// </summary> /// <param name="color">uint color</param> public ColorUint (uint color) { c = color; } /// <summary> /// set uint color by int /// </summary> /// <param name="color"></param> public ColorUint (int color) { c = unchecked( (uint)color); } /// <summary> /// return uint color /// </summary> public uint C { get {return c; } } /// <summary> /// set Alpha /// </summary> public byte A { set { c = (c & 0x00FFFFFF) | (uint)value << 24;} } /// <summary> /// set Red /// </summary> public byte R { set { c = (c & 0xFF00FFFF) | (uint)value << 16;} } /// <summary> /// set Green /// </summary> public byte G { set { c = c & 0xFFFF00FF | (uint)value << 8;} } /// <summary> /// set Blue /// </summary> public byte B { set { c = c & 0xFFFFFF00 | (uint)value;} } public uint? Cnull { get {return null;} } public uint Random(int low=0, int high=256) { R = (byte)rnd.Next(low, high); G = (byte)rnd.Next(low, high); B = (byte)rnd.Next(low, high); return C; } } // end ColorUint /// <summary> /// float x,y,z c uint color /// </summary> public struct Point { public float X, Y, Z; public uint C; } #endregion /// <summary> /// /// </summary> class Wbmp { private int imgWidth, imgHeight, imgBuffLen; private uint[] imgBuffer; private Int32Rect imgRect; private WriteableBitmap wb; /// <summary> /// create Wbmp object /// </summary> /// <param name="w">img width</param> /// <param name="h">img height</param> /// <param name="dpix">dpi</param> /// <param name="dpiy">dpi</param> /// <param name="pf">Pixelformat fastest Pbgra32 | Bgr32</param> /// <param name="bp">for custom palete or null</param> public Wbmp (int w=800, int h=600, int dpix=96, int dpiy=96, PixelFormat? pf = null, BitmapPalette bp=null) { imgWidth = w; imgHeight = h; imgBuffer = new uint[imgWidth * imgHeight]; imgBuffLen = imgBuffer.Length; imgRect = new Int32Rect(0,0,imgWidth,imgHeight); pf = pf == null ? PixelFormats.Pbgra32 : pf; wb = new WriteableBitmap(imgWidth, imgHeight, dpix, dpiy, (PixelFormat)pf, bp); } #region Properties /// <summary> /// return writable bitmap /// </summary> public WriteableBitmap WB { get {return wb;} // set {};all internal vars } /// <summary> /// return int imgWidth /// </summary> public int ImgWidth { get {return imgWidth;} } /// <summary> /// return int imgHeight /// </summary> public int ImgHeight { get {return imgHeight;} } #endregion /// <summary> /// clear buffer with specific color /// </summary> /// <param name="c">arbg uint</param> public void Clear(uint color=0xFFFFFFFF) { for (var i = 0; i < imgBuffLen; ++i) { imgBuffer[i] = color; } } /// <summary> /// clear imgBuffer with ColorUint c /// </summary> /// <param name="c">ColorUint color</param> public void Clear(ColorUint color) { for (var i = 0; i < imgBuffLen; ++i) { imgBuffer[i] = color.C; } } /// <summary> /// refresh image /// </summary> public void Refresh () { wb.WritePixels(imgRect, imgBuffer, imgWidth*4, 0, 0); } /// <summary> /// put uint color pixel on x,y imgBuffer /// </summary> /// <param name="x">int x</param> /// <param name="y">int y</param> /// <param name="c">uint color</param> public void Pixel(int x, int y, uint c) { int i = y * imgWidth + x; if (0 <= i && i < imgBuffLen) imgBuffer[i] = c; } /// <summary> /// put int color pixel on x,y imgBuffer /// </summary> /// <param name="x">int x</param> /// <param name="y">int y</param> /// <param name="c">uint color</param> public void Pixel(int x, int y, int c) { int i = y * imgWidth + x; if (0 <= i && i < imgBuffLen) imgBuffer[i] = unchecked ( (uint)c); } /// <summary> /// put ColorUint pixel on x,y imgBuffer /// </summary> /// <param name="x">int x</param> /// <param name="y">int y</param> /// <param name="c">ColorUint color</param> public void Pixel(int x, int y, ColorUint c) { int i = y * imgWidth + x; if (0 <= i && i < imgBuffLen) imgBuffer[i] = c.C; } /// <summary> /// put Point pixel on imgBuffer /// </summary> /// <param name="p">Point p</param> public void Pixel(Point p) { int i = (int)p.Y * imgWidth + (int)p.X; if (0 <= i && i < imgBuffLen) imgBuffer[i] = p.C; } /// <summary> /// Draw color line by two points DDA algorithm (Digital Differential Analyzer) /// </summary> /// <param name="a">PointF a</param> /// <param name="b">PointF b</param> /// <param name="c">ColorUint c </param> public void Line1 (Point a, Point b, ColorUint c) { Line1(a.X, a.Y, b.X, b.Y, c.C); } /// <summary> /// Draw color line by two points DDA algorithm (Digital Differential Analyzer) /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="c"></param> public void Line1 (float x1, float y1, float x2, float y2, uint c) { // Distance start and end point float dx = x2 - x1; float dy = y2 - y1; // Determine slope (absoulte value) float len = dy >= 0 ? dy : -dy; float lenx = dx >= 0 ? dx : -dx; len = lenx > len ? lenx : len; // Prevent divison by zero if (0 == len) return; // Init steps and start float incx = dx / len; float incy = dy / len; float x = (float)x1; float y = (float)y1; // Walk line! int i; for (int line = 0; line < len; ++line) { i = (int)y * imgWidth + (int)x; if (0 <= i && i < imgBuffLen) imgBuffer[i] = c; x += incx; y += incy; } } // end line() /// <summary> /// Draws a colored line by connecting two points using an optimized DDA. /// Uses pixels array and width directly for best performance. /// </summary> /// <param name="x1">x1 start point</param> /// <param name="y1">y1 start point</param> /// <param name="x2">x2 end point</param> /// <param name="y2">y2 end point</param> /// <param name="color">uint color</param> public void Line (int x1, int y1, int x2, int y2, uint c) { // Distance start and end point int dx = x2 - x1; int dy = y2 - y1; const int PRECISION_SHIFT = 8; // Determine slope (absoulte value) int lenX, lenY; lenY = dy >= 0 ? dy : -dy; lenX = dx >= 0 ? dx : -dx; if (lenX > lenY) { // x increases by +/- 1 if (dx < 0) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } // Init steps and start int incy = (dy << PRECISION_SHIFT) / dx; int y1s = y1 << PRECISION_SHIFT; int y2s = y2 << PRECISION_SHIFT; int hs = imgHeight << PRECISION_SHIFT; if (y1 < y2) { if (y1 >= imgHeight || y2 < 0) return; if (y1s < 0) { if (incy == 0) return; int oldy1s = y1s; // Find lowest y1s that is greater or equal than 0. y1s = incy - 1 + ((y1s + 1) % incy); x1 += (y1s - oldy1s) / incy; } if (y2s >= hs) { if (incy != 0) { // Find highest y2s that is less or equal than ws - 1. // y2s = y1s + n * incy. Find n. y2s = hs - 1 - (hs - 1 - y1s) % incy; x2 = x1 + (y2s - y1s) / incy; } } } else { // y1 > y2 if (y2 >= imgHeight || y1 < 0) return; if (y1s >= hs) { if (incy == 0) return; int oldy1s = y1s; // Find highest y1s that is less or equal than ws - 1. // y1s = oldy1s + n * incy. Find n. y1s = hs - 1 + (incy - (hs - 1 - oldy1s) % incy); x1 += (y1s - oldy1s) / incy; } if (y2s < 0) { if (incy != 0) { // Find lowest y2s that is greater or equal than 0. // y2s = y1s + n * incy. Find n. y2s = y1s % incy; x2 = x1 + (y2s - y1s) / incy; } } } // end else y1 > y2 if (x1 < 0) { y1s -= incy * x1; x1 = 0; } if (x2 >= imgWidth) { x2 = imgWidth - 1; } int ys = y1s; // Walk line! int y = ys >> PRECISION_SHIFT; int previousY = y; int index = x1 + y * imgWidth; int k = incy < 0 ? 1 - imgWidth : 1 + imgWidth; for (int x = x1; x <= x2; ++x) { imgBuffer[index] = c; ys += incy; y = ys >> PRECISION_SHIFT; if (y != previousY) { previousY = y; index += k; } else { ++index; } } } else { // big lenX < lenY // Prevent divison by zero if (lenY == 0) return; if (dy < 0) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } // Init steps and start int x1s = x1 << PRECISION_SHIFT; int x2s = x2 << PRECISION_SHIFT; int ws = imgWidth << PRECISION_SHIFT; int incx = (dx << PRECISION_SHIFT) / dy; if (x1 < x2) { if (x1 >= imgWidth || x2 < 0) return; if (x1s < 0) { if (incx == 0) return; int oldx1s = x1s; // Find lowest x1s that is greater or equal than 0. x1s = incx - 1 + ((x1s + 1) % incx); y1 += (x1s - oldx1s) / incx; } if (x2s >= ws) { if (incx != 0) { // Find highest x2s that is less or equal than ws - 1. // x2s = x1s + n * incx. Find n. x2s = ws - 1 - (ws - 1 - x1s) % incx; y2 = y1 + (x2s - x1s) / incx; } } } else { if (x2 >= imgWidth || x1 < 0) return; if (x1s >= ws) { if (incx == 0) return; int oldx1s = x1s; // Find highest x1s that is less or equal than ws - 1. // x1s = oldx1s + n * incx. Find n. x1s = ws - 1 + (incx - (ws - 1 - oldx1s) % incx); y1 += (x1s - oldx1s) / incx; } if (x2s < 0) { if (incx != 0) { // Find lowest x2s that is greater or equal than 0. // x2s = x1s + n * incx. Find n. x2s = x1s % incx; y2 = y1 + (x2s - x1s) / incx; } } } if (y1 < 0) { x1s -= incx * y1; y1 = 0; } if (y2 >= imgHeight) { y2 = imgHeight - 1; } int index = x1s + ((y1 * imgWidth) << PRECISION_SHIFT); // Walk line! var inc = (imgWidth << PRECISION_SHIFT) + incx; for (int y = y1; y <= y2; ++y) { //imgBuffer[index >> PRECISION_SHIFT] = color; imgBuffer[index >> PRECISION_SHIFT] = c; index += inc; } } // end big else } // end draw line() public void Line (Point a, Point b, uint c=0xFFFFFFFF) { Line((int)a.X, (int)a.Y, (int)b.X, (int)b.Y, c); } /// <summary> /// draw triangle /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="x3"></param> /// <param name="y3"></param> /// <param name="c">uint color</param> public void Triangle (int x1, int y1, int x2, int y2, int x3, int y3, uint c=0xFFFFFFFF) { Line(x1, y1, x2, y2, c); Line(x2, y2, x3, y3, c); Line(x3, y3, x1, y1, c); } /// <summary> /// draw triangle /// </summary> /// <param name="a">Point a</param> /// <param name="b">Point b</param> /// <param name="c">Point c</param> /// <param name="col">uint color</param> public void Triangle (Point a, Point b, Point c, uint col=0xFFFFFFFF) { Line(a, b, col); Line(a, c, col); Line(b, c, col); } /// <summary> /// Draw rect by int /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="color">uint color</param> public void Rect (int x1, int y1, int x2, int y2, uint color) { // Check boundaries if ((x1 < 0 && x2 < 0) || (y1 < 0 && y2 < 0) || (x1 >= imgWidth && x2 >= imgWidth) || (y1 >= imgHeight && y2 >= imgHeight)) return; // Clamp boundaries if (x1 < 0) { x1 = 0; } if (y1 < 0) { y1 = 0; } if (x2 < 0) { x2 = 0; } if (y2 < 0) { y2 = 0; } if (x1 > imgWidth) { x1 = imgWidth; } // ? if (y1 > imgHeight) { y1 = imgHeight; } if (x2 > imgWidth) { x2 = imgWidth; } if (y2 > imgHeight) { y2 = imgHeight; } var startY = y1 * imgWidth; var endY = y2 * imgWidth; var offset2 = (endY - imgWidth) + x1; var endOffset = startY + x2; var startYPlusX1 = startY + x1; // top and bottom horizontal scanlines for (var x = startYPlusX1; x < endOffset; x++) { if (x >= 0 && x < imgBuffLen) imgBuffer[x] = color; // top horizontal line if (offset2 >= 0 && offset2 < imgBuffLen) imgBuffer[offset2] = color; // bottom horizontal line offset2++; } // offset2 == endY + x2 // vertical scanlines endOffset = startYPlusX1 + imgWidth; offset2 -= imgWidth; for (var y = startY + x2 - 1 + imgWidth; y < offset2; y += imgWidth) { if (y >= 0 && y < imgBuffLen) imgBuffer[y] = color; // right vertical line if (endOffset >= 0 && endOffset < imgBuffLen) imgBuffer[endOffset] = color; // left vertical line endOffset += imgWidth; } } // end Rect /// <summary> /// Draw Rect by Point and uint /// </summary> /// <param name="a">Point</param> /// <param name="b">Point</param> /// <param name="color">uint</param> public void Rect (Point a, Point b, uint color) { Rect((int)a.X, (int)a.Y, (int)b.X, (int)b.Y, color); } /// <summary> /// Draw rect by Point and ColorUint /// </summary> /// <param name="a">Point a</param> /// <param name="b">Point b</param> /// <param name="color">ColorUint</param> public void Rect (Point a, Point b, ColorUint color) { Rect((int)a.X, (int)a.Y, (int)b.X, (int)b.Y, color.C); } /// <summary> /// Draw Quad /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="x3"></param> /// <param name="y3"></param> /// <param name="x4"></param> /// <param name="y4"></param> /// <param name="color">uint</param> public void Quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, uint color) { Line(x1, y1, x2, y2, color); Line(x2, y2, x3, y3, color); Line(x3, y3, x4, y4, color); Line(x4, y4, x1, y1, color); } /// <summary> /// Draw Quad by 4 Points /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> /// <param name="d"></param> /// <param name="color">uint</param> public void Quad (Point a, Point b, Point c, Point d, uint color) { Line((int)a.X, (int)a.Y, (int)b.X, (int)b.Y, color); Line((int)b.X, (int)b.Y, (int)c.X, (int)c.Y, color); Line((int)c.X, (int)c.Y, (int)d.X, (int)d.Y, color); Line((int)d.X, (int)d.Y, (int)a.X, (int)a.Y, color); } /// <summary> /// Draw Quad by 4 Points and ColorUint /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> /// <param name="d"></param> /// <param name="color">ColorUint</param> public void Quad (Point a, Point b, Point c, Point d, ColorUint color) { Line((int)a.X, (int)a.Y, (int)b.X, (int)b.Y, color.C); Line((int)b.X, (int)b.Y, (int)c.X, (int)c.Y, color.C); Line((int)c.X, (int)c.Y, (int)d.X, (int)d.Y, color.C); Line((int)d.X, (int)d.Y, (int)a.X, (int)a.Y, color.C); } /// <summary> /// Draws a polyline. Add first point also at end of array if line should be closed. /// </summary> /// <param name="points">The points of polyline in x and y pairs, therefore array is interpreted as (x1, y1, x2, y2, ..., xn, yn).</param> /// <param name="color">The color for line.</param> public void Polyline(int[] points, uint color) { var w = imgWidth; var h = imgHeight; var x1 = points[0]; var y1 = points[1]; // Clamp boundaries if (x1 < 0) { x1 = 0; } if (y1 < 0) { y1 = 0; } if (x1 > w) { x1 = w; } if (y1 > h) { y1 = h; } for (var i = 2; i < points.Length; i += 2) { var x2 = points[i]; var y2 = points[i + 1]; // Clamp boundaries if (x2 < 0) { x2 = 0; } if (y2 < 0) { y2 = 0; } if (x2 > w) { x2 = w; } if (y2 > h) { y2 = h; } Line(x1, y1, x2, y2, color); x1 = x2; y1 = y2; } } /// <summary> /// List of Point /// </summary> /// <param name="points">Point list</param> /// <param name="color">uint</param> public void Polyline(List<Point> points, uint color) { Point p1, p2; p1 = points.ElementAt<Point>(0); // Clamp boundaries if (p1.X < 0) { p1.X = 0; } if (p1.Y < 0) { p1.Y = 0; } if (p1.X > imgWidth) { p1.X = imgWidth; } if (p1.Y > imgHeight) { p1.Y = ImgHeight; } int len = points.Count; for (var i = 2; i < len; i += 2) { p2 = points.ElementAt<Point>(i); // Clamp boundaries if (p2.X < 0) { p2.X = 0; } if (p2.Y < 0) { p2.Y = 0; } if (p2.X > imgWidth) { p2.X = imgWidth; } if (p2.Y > imgHeight) { p2.Y = imgHeight; } Line(p1, p2, color); p1 = p2; } } /// <summary> /// A Fast Bresenham Type Algorithm For Drawing Ellipses http://homepage.smc.edu/kennedy_john/belipse.pdf /// Uses a different parameter representation than DrawEllipse(). /// </summary> /// <param name="xc">x-coordinate of ellipses center.</param> /// <param name="yc">y-coordinate of ellipses center.</param> /// <param name="xr">radius of ellipse in x-direction.</param> /// <param name="yr">radius of ellipse in y-direction.</param> /// <param name="color">color for line.</param> public void Ellipse (int xc, int yc, int xr, int yr, uint color) { var w = imgWidth; var h = imgHeight; // Avoid endless loop if (xr < 1 || yr < 1) return; // Init vars int uh, lh, uy, ly, lx, rx; int x = xr; int y = 0; int xrSqTwo = (xr * xr) << 1; int yrSqTwo = (yr * yr) << 1; int xChg = yr * yr * (1 - (xr << 1)); int yChg = xr * xr; int err = 0; int xStopping = yrSqTwo * xr; int yStopping = 0; // Draw first set of points counter clockwise where tangent line slope > -1. while (xStopping >= yStopping) { // Draw 4 quadrant points at once uy = yc + y; // Upper half ly = yc - y; // Lower half if (uy < 0) uy = 0; // Clip if (uy >= h) uy = h - 1; // ... if (ly < 0) ly = 0; if (ly >= h) ly = h - 1; uh = uy * w; // Upper half lh = ly * w; // Lower half rx = xc + x; lx = xc - x; if (rx < 0) rx = 0; // Clip if (rx >= w) rx = w - 1; // ... if (lx < 0) lx = 0; if (lx >= w) lx = w - 1; imgBuffer[rx + uh] = color; // Quadrant I (Actually an octant) imgBuffer[lx + uh] = color; // Quadrant II imgBuffer[lx + lh] = color; // Quadrant III imgBuffer[rx + lh] = color; // Quadrant IV y++; yStopping += xrSqTwo; err += yChg; yChg += xrSqTwo; if ((xChg + (err << 1)) > 0) { x--; xStopping -= yrSqTwo; err += xChg; xChg += yrSqTwo; } } // ReInit vars x = 0; y = yr; uy = yc + y; // Upper half ly = yc - y; // Lower half if (uy < 0) uy = 0; // Clip if (uy >= h) uy = h - 1; // ... if (ly < 0) ly = 0; if (ly >= h) ly = h - 1; uh = uy * w; // Upper half lh = ly * w; // Lower half xChg = yr * yr; yChg = xr * xr * (1 - (yr << 1)); err = 0; xStopping = 0; yStopping = xrSqTwo * yr; // Draw second set of points clockwise where tangent line slope < -1. while (xStopping <= yStopping) { // Draw 4 quadrant points at once rx = xc + x; lx = xc - x; if (rx < 0) rx = 0; // Clip if (rx >= w) rx = w - 1; // ... if (lx < 0) lx = 0; if (lx >= w) lx = w - 1; imgBuffer[rx + uh] = color; // Quadrant I (Actually an octant) imgBuffer[lx + uh] = color; // Quadrant II imgBuffer[lx + lh] = color; // Quadrant III imgBuffer[rx + lh] = color; // Quadrant IV x++; xStopping += yrSqTwo; err += xChg; xChg += yrSqTwo; if ((yChg + (err << 1)) > 0) { y--; uy = yc + y; // Upper half ly = yc - y; // Lower half if (uy < 0) uy = 0; // Clip if (uy >= h) uy = h - 1; // ... if (ly < 0) ly = 0; if (ly >= h) ly = h - 1; uh = uy * w; // Upper half lh = ly * w; // Lower half yStopping -= xrSqTwo; err += yChg; yChg += xrSqTwo; } } }// end elipse /* // DrawPixel method updates WriteableBitmap by using // unsafe code to write a pixel into back buffer. static void DrawPixel(MouseEventArgs e) { int column = (int)e.GetPosition(i).X; int row = (int)e.GetPosition(i).Y; // Reserve back buffer for updates. writeableBitmap.Lock(); unsafe { // Get a pointer to back buffer. int pBackBuffer = (int)writeableBitmap.BackBuffer; // Find address of pixel to draw. pBackBuffer += row * writeableBitmap.BackBufferStride; pBackBuffer += column * 4; // Compute pixel's color. int color_data = 255 << 16; // R color_data |= 128 << 8; // G color_data |= 255 << 0; // B // Assign color data to pixel. *((int*) pBackBuffer) = color_data; } // Specify area of bitmap that changed. writeableBitmap.AddDirtyRect(new Int32Rect(column, row, 1, 1)); // Release back buffer and make it available for display. writeableBitmap.Unlock(); } */ } // end Wmpp {} } |