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?
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...
// 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
// 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>
// 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 {}
}