Visibility of Platonic solids - c#

I'm doing what will draw platonic solids with visibility and constant shading. I have to do it without opengl or directX. I'm solving now the visibility. I could be probably solved by painters alghoritm but I don't know how to implement it in my code. There is how I draw it.
So I'm asking for advice how to implement the painters alghoritm in my code. I allready know something about this alghoritm - teoreticaly. And it will be probably enought just do the step with sorting of faces by the z - coordinate.
For projection I use class projection matrix and I have arrays vertexBuffer and indexBuffer like in OpenGL.
I do all in Visual studio 2010 in C#.
ProjectionMatrix
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace KPG3D
{
/// <summary>
/// Structure of 3D point
/// </summary>
public struct Point3D
{
public float X;
public float Y;
public float Z;
public Point3D(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
public class ProjectionMatrix
{
public float[,] projectionMatrix = new float[4, 4]; //projection matrix
/// <summary>
/// Konstructor of projection matrix
/// </summary>
public ProjectionMatrix()
{
setIdentity();
}
/// <summary>
/// Konstructor of projection matrix
/// </summary>
public ProjectionMatrix(float zNear, float zFar, float viewportWidth, float viewportHeight)
{
setIdentity();
float Q = zFar / (zFar - zNear);
float w = 2 * zNear / viewportWidth;
float h = 2 * zNear / viewportHeight;
projectionMatrix[0, 0] = w;
projectionMatrix[1, 1] = h;
projectionMatrix[2, 2] = Q;
projectionMatrix[3, 2] = 1;
projectionMatrix[2, 3] = -Q * zNear;
}
/// <summary>
/// Konstructor of projection matrix
/// </summary>
public ProjectionMatrix(float d, float z)
{
setIdentity();//set identity matrix
projectionMatrix[0, 0] = d / (d - z);
projectionMatrix[1, 1] = d / (d - z);
projectionMatrix[2, 2] = 0;
}
/// <summary>
/// Set the matrix to identity
/// </summary>
public void setIdentity()
{
projectionMatrix[0, 0] = 1;
projectionMatrix[0, 1] = 0;
projectionMatrix[0, 2] = 0;
projectionMatrix[0, 3] = 0;
projectionMatrix[1, 0] = 0;
projectionMatrix[1, 1] = 1;
projectionMatrix[1, 2] = 0;
projectionMatrix[1, 3] = 0;
projectionMatrix[2, 0] = 0;
projectionMatrix[2, 1] = 0;
projectionMatrix[2, 2] = 1;
projectionMatrix[2, 3] = 0;
projectionMatrix[3, 0] = 0;
projectionMatrix[3, 1] = 0;
projectionMatrix[3, 2] = 0;
projectionMatrix[3, 3] = 1;
}
/// <summary>
/// Aplicate projection on set point
/// </summary>
/// <param name="p">Point want to transformate</param>
/// <returns>Transformated point</returns>
public Point3D multiply(Point3D p)
{
Point3D result;
float tmp = projectionMatrix[3, 0] * p.X + projectionMatrix[3, 1] * p.Y + projectionMatrix[3, 2] * p.Z + projectionMatrix[3, 3] * 1;
result.X = (projectionMatrix[0, 0] * p.X + projectionMatrix[0, 1] * p.Y + projectionMatrix[0, 2] * p.Z + projectionMatrix[0, 3] * 1) / tmp;
result.Y = (projectionMatrix[1, 0] * p.X + projectionMatrix[1, 1] * p.Y + projectionMatrix[1, 2] * p.Z + projectionMatrix[1, 3] * 1) / tmp;
result.Z = (projectionMatrix[2, 0] * p.X + projectionMatrix[2, 1] * p.Y + projectionMatrix[2, 2] * p.Z + projectionMatrix[2, 3] * 1) / tmp;
return result;
}
}
}
Form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace KPG3D
{
public partial class Form1 : Form
{
private Bitmap canvasBitmap; //bitmap of drawing area
private Graphics g; //access to graffics
private List<Point3D> vertexBuffer = new List<Point3D>(); //list of all vertices
private List<int> indexBuffer = new List<int>();//list of all indices
private Point3D centroid = new Point3D(0, 0, 0);// center of object
private ProjectionMatrix projection = null; //projection matrix
private bool rotation = false;
private int objectID = 0;
public Form1()
{
InitializeComponent();
//create bitmap and set to canvas
canvasBitmap = new Bitmap(canvas.Width, canvas.Height);
canvas.Image = canvasBitmap;
//prepare grafics
g = Graphics.FromImage(canvasBitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Matrix origin = new Matrix();
origin.Translate(canvas.Width / 2, canvas.Height / 2);
g.Transform = origin;
}
/// <summary>
/// Reaction on click on start button
/// </summary>
private void buttonStart_Click(object sender, EventArgs e)
{
if (projection == null)
{
projection = new ProjectionMatrix(1, 100, 1, 1);
//createBox();
//createTetrahedron();
createChosenObject();
}
Timer t = new Timer();
t.Tick += new EventHandler(timerDrawing);//set tick method
t.Interval = 30; //every 30 ms
t.Enabled = true;
t.Start();
}
/// <summary>
/// Create tetrahedron
/// </summary>
private void createTetrahedron()
{
Point3D a = new Point3D(-3,-3, 7);//h
Point3D b = new Point3D( 3,-3,13);//c
Point3D c = new Point3D( 3, 3, 7);//a
Point3D d = new Point3D(-3, 3,13);//f
vertexBuffer.Add(a);
vertexBuffer.Add(b);
vertexBuffer.Add(c);
vertexBuffer.Add(d);
//acb
indexBuffer.Add(0);
indexBuffer.Add(2);
indexBuffer.Add(1);
//adc
indexBuffer.Add(0);
indexBuffer.Add(3);
indexBuffer.Add(2);
//cdb
indexBuffer.Add(2);
indexBuffer.Add(3);
indexBuffer.Add(1);
//adb
indexBuffer.Add(0);
indexBuffer.Add(3);
indexBuffer.Add(1);
centroid = new Point3D(0, 0, 10);
}
/// <summary>
/// Create chosen object
/// </summary>
private void createChosenObject() {
switch (objectID) {
case 1:
createTetrahedron();
break;
case 2:
createHexahedron();
break;
case 3:
createOctahedron();
break;
case 4:
createDodecahedron();
break;
case 5:
createIcosahedron();
break;
default:
//do nothing
break;
}
}
/// <summary>
/// Rotate direcion vector by the specified angle
/// </summary>
/// <param name="vector">Direction vector</param>
/// <param name="angle">Angle of rotation</param>
/// <returns></returns>
private Point3D rotateVector(Point3D vector, Point3D centroid, double angle)
{
vector.X -= centroid.X;
vector.Y -= centroid.Y;
vector.Z -= centroid.Z;
Point3D result;
result.X = vector.X * (float)Math.Cos(angle) - vector.Z * (float)Math.Sin(angle);
result.Z = vector.X * (float)Math.Sin(angle) + vector.Z * (float)Math.Cos(angle);
result.Y = vector.Y;
result.X += centroid.X;
result.Y += centroid.Y;
result.Z += centroid.Z;
return result;
}
/// <summary>
/// Reaction on timer
/// </summary>
private void timerDrawing(Object obj, EventArgs ea)
{
//rotation of object
if (rotation == true)
{
for (int i = 0; i < vertexBuffer.Count; i++)
{
vertexBuffer[i] = rotateVector(vertexBuffer[i], centroid, 0.02);
}
}
//drawing of object
draw(vertexBuffer, indexBuffer);
//refresh what is on canvas
canvas.Invalidate();
}
/// <summary>
///Draw point and triangles
/// </summary>
/// <param name="vert"></param>
/// <param name="ind"></param>
private void draw(List<Point3D> vert, List<int> ind)
{
//clear drawing area
g.Clear(Color.Maroon);
//prepare pen and brush
Pen pen = new Pen(Color.Black, 1);
SolidBrush brush = new SolidBrush(Color.Black);
SolidBrush faceBrush = new SolidBrush(Color.FromArgb(75, Color.Green));
//draw edges
for (int i = 0; i < ind.Count / 3; i++)
{
Point3D A = projection.multiply(vert[ind[3 * i + 0]]);
Point3D B = projection.multiply(vert[ind[3 * i + 1]]);
Point3D C = projection.multiply(vert[ind[3 * i + 2]]);
//count to 2D
PointF a = new PointF(A.X * 200, -A.Y * 200);
PointF b = new PointF(B.X * 200, -B.Y * 200);
PointF c = new PointF(C.X * 200, -C.Y * 200);
g.FillPolygon(faceBrush, new PointF[] { a, b, c });
//draw triangle
g.DrawLine(pen, a, b);
g.DrawLine(pen, b, c);
g.DrawLine(pen, c, a);
}
//draw element
for (int i = 0; i < vert.Count; i++)
{
Point3D p = projection.multiply(vert[i]); //projection from 3D to 2D
g.FillRectangle(brush, p.X * 200 - 2, -p.Y * 200 - 2, 4, 4);
}
}
/// <summary>
/// Printscreen to file
/// </summary>
private void buttonPrintScreen_Click(object sender, EventArgs e)
{
canvas.Image.Save("out.png");
}
private void checkBoxRotate_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxRotate.Checked) rotation = true;
else rotation = false;
}
private void objectChooser_SelectedIndexChanged(object sender, EventArgs e)
{
//set ide of chosen object
if(objectChooser.SelectedItem.Equals("Tetrahedron")) objectID = 1;
else if (objectChooser.SelectedItem.Equals("Box")) objectID = 2;
else if (objectChooser.SelectedItem.Equals("Octahedron")) objectID = 3;
else if(objectChooser.SelectedItem.Equals("Dodecahedron")) objectID = 4;
else if (objectChooser.SelectedItem.Equals("Icosahedron")) objectID = 5;
}
}
}

If you have to account for intersecting triangles (see image), I think the easiest solution will involve a z-buffer (they are pretty easy to create and use). If you do not have to render intersecting triangles, your proposed solution of z sorting will be simpler and will work just fine.

Related

How can i display in a middle of a progressBar some text?

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
What i want to do is to show in the middle of the progressBar a text in red and that the text will blink until the progressBar operation end getting to 100%.
The text to display is: Processing Please Wait
In the end in the background completed event just to stop the blinking and display instead: Processing Please Wait to display: Operation Ended or something like that maybe: Process Ended or Finished.
I forgot to mention that my progressBar1 i'm using is a costum UserControl i did and not the regular progressBar for example after dragging this to my form1 designer this progressBar dosen't have the Increment property.
using System;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace VistaStyleProgressBar
{
/// <summary>
/// A replacement for the default ProgressBar control.
/// </summary>
[DefaultEvent("ValueChanged")]
public class ProgressBar : System.Windows.Forms.UserControl
{
#region - Designer -
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Create the control and initialize it.
/// </summary>
public ProgressBar()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.BackColor = Color.Transparent;
if (!InDesignMode())
{
mGlowAnimation.Tick += new EventHandler(mGlowAnimation_Tick);
mGlowAnimation.Interval = 15;
if (Value < MaxValue) { mGlowAnimation.Start(); }
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region - Component Designer -
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// ProgressBar
//
this.Name = "ProgressBar";
this.Size = new System.Drawing.Size(264, 32);
this.Paint += new PaintEventHandler(ProgressBar_Paint);
}
#endregion
#endregion
#region - Properties -
private int mGlowPosition = -325;
private Timer mGlowAnimation = new Timer();
#region - Value -
private int mValue = 0;
/// <summary>
/// The value that is displayed on the progress bar.
/// </summary>
[Category("Value"),
DefaultValue(0),
Description("The value that is displayed on the progress bar.")]
public int Value
{
get { return mValue; }
set
{
if (value > MaxValue || value < MinValue) { return; }
mValue = value;
if (value < MaxValue) { mGlowAnimation.Start(); }
if (value == MaxValue) { mGlowAnimation.Stop(); }
ValueChangedHandler vc = ValueChanged;
if (vc != null) { vc(this, new System.EventArgs()); }
this.Invalidate();
}
}
private int mMaxValue = 100;
/// <summary>
/// The maximum value for the Value property.
/// </summary>
[Category("Value"),
DefaultValue(100),
Description("The maximum value for the Value property.")]
public int MaxValue
{
get { return mMaxValue; }
set
{
mMaxValue = value;
if (value > MaxValue) { Value = MaxValue; }
if (Value < MaxValue) { mGlowAnimation.Start(); }
MaxChangedHandler mc = MaxChanged;
if (mc != null) { mc(this, new System.EventArgs()); }
this.Invalidate();
}
}
private int mMinValue = 0;
/// <summary>
/// The minimum value for the Value property.
/// </summary>
[Category("Value"),
DefaultValue(0),
Description("The minimum value for the Value property.")]
public int MinValue
{
get { return mMinValue; }
set
{
mMinValue = value;
if (value < MinValue) { Value = MinValue; }
MinChangedHandler mc = MinChanged;
if (mc != null) { mc(this, new System.EventArgs()); }
this.Invalidate();
}
}
#endregion
#region - Bar -
private Color mStartColor = Color.FromArgb(0, 211, 40);
/// <summary>
/// The start color for the progress bar.
/// 210, 000, 000 = Red
/// 210, 202, 000 = Yellow
/// 000, 163, 211 = Blue
/// 000, 211, 040 = Green
/// </summary>
[Category("Bar"),
DefaultValue(typeof(Color), "210, 0, 0"),
Description("The start color for the progress bar." +
"210, 000, 000 = Red\n" +
"210, 202, 000 = Yellow\n" +
"000, 163, 211 = Blue\n" +
"000, 211, 040 = Green\n")]
public Color StartColor
{
get { return mStartColor; }
set { mStartColor = value; this.Invalidate(); }
}
private Color mEndColor = Color.FromArgb(0, 211, 40);
/// <summary>
/// The end color for the progress bar.
/// 210, 000, 000 = Red
/// 210, 202, 000 = Yellow
/// 000, 163, 211 = Blue
/// 000, 211, 040 = Green
/// </summary>
[Category("Bar"),
DefaultValue(typeof(Color), "0, 211, 40"),
Description("The end color for the progress bar." +
"210, 000, 000 = Red\n" +
"210, 202, 000 = Yellow\n" +
"000, 163, 211 = Blue\n" +
"000, 211, 040 = Green\n")]
public Color EndColor
{
get { return mEndColor; }
set { mEndColor = value; this.Invalidate(); }
}
#endregion
#region - Highlights and Glows -
private Color mHighlightColor = Color.White;
/// <summary>
/// The color of the highlights.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "White"),
Description("The color of the highlights.")]
public Color HighlightColor
{
get { return mHighlightColor; }
set { mHighlightColor = value; this.Invalidate(); }
}
private Color mBackgroundColor = Color.FromArgb(201, 201, 201);
/// <summary>
/// The color of the background.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "201,201,201"),
Description("The color of the background.")]
public Color BackgroundColor
{
get { return mBackgroundColor; }
set { mBackgroundColor = value; this.Invalidate(); }
}
private bool mAnimate = true;
/// <summary>
/// Whether the glow is animated.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(bool), "true"),
Description("Whether the glow is animated or not.")]
public bool Animate
{
get { return mAnimate; }
set
{
mAnimate = value;
if (value) { mGlowAnimation.Start(); } else { mGlowAnimation.Stop(); }
this.Invalidate();
}
}
private Color mGlowColor = Color.FromArgb(150, 255, 255, 255);
/// <summary>
/// The color of the glow.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "150, 255, 255, 255"),
Description("The color of the glow.")]
public Color GlowColor
{
get { return mGlowColor; }
set { mGlowColor = value; this.Invalidate(); }
}
#endregion
#endregion
#region - Drawing -
private void DrawBackground(Graphics g)
{
Rectangle r = this.ClientRectangle; r.Width--; r.Height--;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.FillPath(new SolidBrush(this.BackgroundColor), rr);
}
private void DrawBackgroundShadows(Graphics g)
{
Rectangle lr = new Rectangle(2, 2, 10, this.Height - 5);
LinearGradientBrush lg = new LinearGradientBrush(lr, Color.FromArgb(30, 0, 0, 0),
Color.Transparent,
LinearGradientMode.Horizontal);
lr.X--;
g.FillRectangle(lg, lr);
Rectangle rr = new Rectangle(this.Width - 12, 2, 10, this.Height - 5);
LinearGradientBrush rg = new LinearGradientBrush(rr, Color.Transparent,
Color.FromArgb(20, 0, 0, 0),
LinearGradientMode.Horizontal);
g.FillRectangle(rg, rr);
}
private void DrawBar(Graphics g)
{
Rectangle r = new Rectangle(1, 2, this.Width - 3, this.Height - 3);
r.Width = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width);
g.FillRectangle(new SolidBrush(GetIntermediateColor()), r);
}
private void DrawBarShadows(Graphics g)
{
Rectangle lr = new Rectangle(1, 2, 15, this.Height - 3);
LinearGradientBrush lg = new LinearGradientBrush(lr, Color.White, Color.White,
LinearGradientMode.Horizontal);
ColorBlend lc = new ColorBlend(3);
lc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
lc.Positions = new float[] { 0.0F, 0.2F, 1.0F };
lg.InterpolationColors = lc;
lr.X--;
g.FillRectangle(lg, lr);
Rectangle rr = new Rectangle(this.Width - 3, 2, 15, this.Height - 3);
rr.X = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width) - 14;
LinearGradientBrush rg = new LinearGradientBrush(rr, Color.Black, Color.Black,
LinearGradientMode.Horizontal);
ColorBlend rc = new ColorBlend(3);
rc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
rc.Positions = new float[] { 0.0F, 0.8F, 1.0F };
rg.InterpolationColors = rc;
g.FillRectangle(rg, rr);
}
private void DrawHighlight(Graphics g)
{
Rectangle tr = new Rectangle(1, 1, this.Width - 1, 6);
GraphicsPath tp = RoundRect(tr, 2, 2, 0, 0);
g.SetClip(tp);
LinearGradientBrush tg = new LinearGradientBrush(tr, Color.White,
Color.FromArgb(128, Color.White),
LinearGradientMode.Vertical);
g.FillPath(tg, tp);
g.ResetClip();
Rectangle br = new Rectangle(1, this.Height - 8, this.Width - 1, 6);
GraphicsPath bp = RoundRect(br, 0, 0, 2, 2);
g.SetClip(bp);
LinearGradientBrush bg = new LinearGradientBrush(br, Color.Transparent,
Color.FromArgb(100, this.HighlightColor),
LinearGradientMode.Vertical);
g.FillPath(bg, bp);
g.ResetClip();
}
private void DrawInnerStroke(Graphics g)
{
Rectangle r = this.ClientRectangle;
r.X++; r.Y++; r.Width -= 3; r.Height -= 3;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.DrawPath(new Pen(Color.FromArgb(100, Color.White)), rr);
}
private void DrawGlow(Graphics g)
{
Rectangle r = new Rectangle(mGlowPosition, 0, 60, this.Height);
LinearGradientBrush lgb = new LinearGradientBrush(r, Color.White, Color.White,
LinearGradientMode.Horizontal);
ColorBlend cb = new ColorBlend(4);
cb.Colors = new Color[] { Color.Transparent, this.GlowColor, this.GlowColor, Color.Transparent };
cb.Positions = new float[] { 0.0F, 0.5F, 0.6F, 1.0F };
lgb.InterpolationColors = cb;
Rectangle clip = new Rectangle(1, 2, this.Width - 3, this.Height - 3);
clip.Width = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width);
g.SetClip(clip);
g.FillRectangle(lgb, r);
g.ResetClip();
}
private void DrawOuterStroke(Graphics g)
{
Rectangle r = this.ClientRectangle; r.Width--; r.Height--;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.DrawPath(new Pen(Color.FromArgb(178, 178, 178)), rr);
}
#endregion
#region - Functions -
private GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
{
float x = r.X, y = r.Y, w = r.Width, h = r.Height;
GraphicsPath rr = new GraphicsPath();
rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
rr.AddLine(x + r1, y, x + w - r2, y);
rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
rr.AddLine(x + w, y + r2, x + w, y + h - r3);
rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
rr.AddLine(x + w - r3, y + h, x + r4, y + h);
rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
rr.AddLine(x, y + h - r4, x, y + r1);
return rr;
}
private bool InDesignMode()
{
return (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}
private Color GetIntermediateColor()
{
Color c = this.StartColor;
Color c2 = this.EndColor;
float pc = this.Value * 1.0F / (this.MaxValue - this.MinValue);
int ca = c.A, cr = c.R, cg = c.G, cb = c.B;
int c2a = c2.A, c2r = c2.R, c2g = c2.G, c2b = c2.B;
int a = (int)Math.Abs(ca + (ca - c2a) * pc);
int r = (int)Math.Abs(cr - ((cr - c2r) * pc));
int g = (int)Math.Abs(cg - ((cg - c2g) * pc));
int b = (int)Math.Abs(cb - ((cb - c2b) * pc));
if (a > 255) { a = 255; }
if (r > 255) { r = 255; }
if (g > 255) { g = 255; }
if (b > 255) { b = 255; }
return (Color.FromArgb(a, r, g, b));
}
#endregion
#region - Other -
private void ProgressBar_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
DrawBackground(e.Graphics);
DrawBackgroundShadows(e.Graphics);
DrawBar(e.Graphics);
DrawBarShadows(e.Graphics);
DrawHighlight(e.Graphics);
DrawInnerStroke(e.Graphics);
DrawGlow(e.Graphics);
DrawOuterStroke(e.Graphics);
}
private void mGlowAnimation_Tick(object sender, EventArgs e)
{
if (this.Animate)
{
mGlowPosition += 4;
if (mGlowPosition > this.Width)
{
mGlowPosition = -300;
}
this.Invalidate();
}
else
{
mGlowAnimation.Stop();
mGlowPosition = -320;
}
}
#endregion
#region - Events -
/// <summary>
/// When the Value property is changed.
/// </summary>
public delegate void ValueChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the Value property is changed.
/// </summary>
public event ValueChangedHandler ValueChanged;
/// <summary>
/// When the MinValue property is changed.
/// </summary>
public delegate void MinChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the MinValue property is changed.
/// </summary>
public event MinChangedHandler MinChanged;
/// <summary>
/// When the MaxValue property is changed.
/// </summary>
public delegate void MaxChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the MaxValue property is changed.
/// </summary>
public event MaxChangedHandler MaxChanged;
#endregion
}
}
I tried this case the Increment property not exist so it's a problem.
private void timer2_Tick(object sender, EventArgs e)
{
progressBar1.Increment(+1);
int percent = progressBar1.Value;
progressBar1
.CreateGraphics()
.DrawString(
percent.ToString() + "%",
new Font("Arial", (float)8.25, FontStyle.Regular),
Brushes.Black,
new PointF(progressBar1.Width / 2 - 10,
progressBar1.Height / 2 - 7)
);
if (progressBar1.Value >= 99)
{
timer2.Stop();
this.Close();
}
}
What I would do is make a label with the desired text and then add to the background worker:
if ( progressBar1.Value == 100% )
{
label1.Text = "Process finished";
}
If you cant see the label and it is hidden behind the processBar change the location of the label to front
Hope I could help!
Edit: This link should explain the blinking event How to implement a blinking label on a form
Have wrote no blinking/flickering TextProgressBar
You can find source code here: https://github.com/ukushu/TextProgressBar
Sample:

Mandelbrot Conversion [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm receiving no errors but when I'm running it I'm also unable to see the Mandelbrot it just displays the grey box, I'm currently stuck at this one point thanks for any help, if you see any other parts of my code which contains grammar or coding errors it would be much appreciated if you told me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace SE_Fractal_Assignment
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public struct HSBColor
{
float h;
float s;
float b;
int a;
public HSBColor(float h, float s, float b)
{
this.a = 0xff;
this.h = Math.Min(Math.Max(h, 0), 255);
this.s = Math.Min(Math.Max(h, 0), 255);
this.b = Math.Min(Math.Max(h, 0), 255);
}
public float H
{
get { return h; }
}
public float S
{
get { return s; }
}
public float B
{
get { return b; }
}
public int A
{
get { return a; }
}
public Color Color
{
get
{
return FromHSB(this);
}
}
public static Color FromHSB(HSBColor hsbColor)
{
float r = hsbColor.b;
float g = hsbColor.b;
float b = hsbColor.b;
if (hsbColor.s != 0)
{
float max = hsbColor.b;
float dif = hsbColor.b * hsbColor.s / 255f;
float min = hsbColor.b - dif;
float h = hsbColor.h * 360f / 255f;
if (h < 60f)
{
r = max;
g = h * dif / 60f + min;
b = min;
}
else if (h < 120f)
{
r = -(h - 120f) * dif / 60f + min;
g = max;
b = min;
}
else if (h < 180f)
{
r = min;
g = max;
b = -(h - 120f) * dif / 60f + min;
}
else if (h < 240f)
{
r = min;
g = -(h - 240f) * dif / 60f + min;
b = max;
}
else if (h < 300f)
{
r = -(h - 240f) * dif / 60f + min;
g = min;
b = max;
}
else if (h <= 360f)
{
r = max;
g = min;
b = -(h - 360f) * dif / 60f + min;
}
else
{
r = 0;
g = 0;
b = 0;
}
}
return Color.FromArgb
(
hsbColor.a,
(int)Math.Round(Math.Min(Math.Max(r, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(g, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(b, 0), 255))
);
}
}
private const int MAX = 256; // max iterations
private const double SX = -2.025; // start value goal
private const double SY = -1.125; // start value imaginary
private const double EX = 0.6; // end value real
private const double EY = 1.125; // end value imaginary
private static int x1, y1, xs, ys, xe, ye;
private static double xstart, ystart, xende, yende, xzoom, yzoom;
private static bool action, rectangle, finished;
private static float xy;
//private Image picture1;
private System.Drawing.Bitmap bitmap;
private Graphics g1;
private Cursor c1, c2;
private HSBColor HSBcol = new HSBColor();
// private HSB HSBcol = new HSB();
private void Form1_Paint(object sender, PaintEventArgs e)
{
g1 = e.Graphics;
g1.DrawImage(bitmap, 0, 0, x1, y1);
g1.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
init();
start();
}
public void init()
{
//HSBcol = new HSB();
finished = false;
c1 = Cursors.WaitCursor;
c2 = Cursors.Cross;
x1 = 640;
y1 = 480;
xy = (float)x1 / (float)y1;
bitmap.SetPixel(x1, y1, Color.Blue);
g1 = Graphics.FromImage(bitmap);
finished = true;
// xy = (float)x1 / (float)y1;
//picture = createImage(x1, y1);
//g1 = picture.getGraphics();
}
public void destroy() // delete all instances
{
if (finished)
{
//removeMouseListener(this);
//removeMouseMotionListener(this);
//bitmap = null;
g1 = null;
c1 = null;
c2 = null;
//System.gc(); // garbage collection
GC.Collect();
}
}
public void start()
{
action = false;
rectangle = false;
initvalues();
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
mandelbrot();
}
public void stop()
{
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
/* Pen myPen = new Pen(Color.White);
g.DrawImage(bitmap, 0, 0);
if (rectangle)
{
if (xs < xe)
{
if (ys < ye)
{
g.DrawRectangle(myPen, xs, ys, (xe - xs), (ye - ys));
}
}
else
{
g.DrawRectangle(myPen, xs, ys, (xe - xs), (ye - ys));
}
myPen.Dispose();
}*/
}
private void mandelbrot() // calculate all points
{
int x, y;
float h, b, alt = 0.0f;
action = false;
for (x = 0; x < x1; x += 2)
for (y = 0; y < y1; y++)
{
h = pointcolour(xstart + xzoom * (double)x, ystart + yzoom * (double)y);
// color value
if (h != alt)
{
b = 1.0f - h * h; // brightnes
///djm added
///HSBcol.fromHSB(h,0.8f,b);
///
//convert hsb to rgb then make a Java Color
Color color = HSBColor.FromHSB(new HSBColor(h * 255, 0.8f * 255, b * 255));
///g1.setColor(col);
//djm end
//djm added to convert to RGB from HSB
//g1.setColor(Color.getHSBColor(h, 0.8f, b));
//djm test
// Color col = Color.FromArgb(0, 0, 0, 0);
//red = Color.Red;
// green = Color.Green;
// blue = Color.Blue;
//djm
alt = h;
}
Pen pen = new Pen(Color.Aqua);
g1.DrawLine(pen, x, y, x + 1, y);
}
//showStatus("Mandelbrot-Set ready - please select zoom area with pressed mouse.");
//setCursor(c2);
action = true;
}
private float pointcolour(double xwert, double ywert)
// color value from 0.0 to 1.0 by iterations
{
double r = 0.0, i = 0.0, m = 0.0;
int j = 0;
while ((j < MAX) && (m < 4.0))
{
j++;
m = r * r - i * i;
i = 2.0 * r * i + ywert;
r = m + xwert;
}
return (float)j / (float)MAX;
}
private void initvalues() // reset start values
{
xstart = SX;
ystart = SY;
xende = EX;
yende = EY;
if ((float)((xende - xstart) / (yende - ystart)) != xy)
xstart = xende - (yende - ystart) * (double)xy;
}
private void Form1_paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g1 = g;
action = false;
rectangle = false;
initvalues();
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
//picture = g.DrawImage;
//g.DrawImage(picture,0,0);
update(g);
mandelbrot();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (action)
{
xs = e.X;
ys = e.Y;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
// e.consume();
if (action)
{
xe = e.X;
ye = e.Y;
rectangle = true;
//repaint();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
rectangle = false;
}
private void Form1_Click(object sender, MouseEventArgs e)
{
}
public String getAppletInfo()
{
return "fractal.class - Mandelbrot Set a Java Applet by Eckhard Roessel 2000-2001";
}
}
}
Honestly, the code is so cluttered and disorganized, it's hard to know all of what might be wrong with it. Sorry to be so blunt.
That said, a couple of obvious problems I see involving your "g1" Graphics instance member.
First, you are using the same field for two purposes: when computing the original image, you expect this to be a Graphics instance you can use to draw into your bitmap. But in the Paint event, you set it to the Graphics instance for the window, into which the painting should be done.
Second, in that Paint event, you dispose the Graphics instance before you return. But the instance you're disposing isn't yours. It belongs to the Forms system, and the only thing you should be doing with it is drawing into it.
There actually appear to be two different Paint event handlers and it's not clear which one you're using. You only dispose the Graphics instance in one of those places, so that may or may not be the real problem.
Personally, I would break the problem down into different elements. For a relative novice, it can be hard enough just to correctly draw a bitmap. It can also be difficult to really grasp how Paint event handling should be done. And of course, there's the Mandelbrot computations themselves. Trying to implement all three things (and more) at the same time can be overwhelming, and will take a lot longer assuming you can figure it out at all.
I would start by writing a simple program that just has a single PictureBox, which when you click a button, your program creates a new Bitmap object, into which you draw something simple (say, a rectangle, circle, or maybe just some text) and then assigns that Bitmap object to the PictureBox.Image property.
Once you have that working, then you can change the drawing part of the code to draw a Mandelbrot image instead.
Finally, once you have that working, then you can work on using the Paint event to draw the bitmap into your window directly instead of using the PictureBox control (the main reason for wanting to do this would presumably be that you eventually want to update the image as it's being drawn...if you only want to show it at the very end, then IMHO the PictureBox is a better approach).

How to scale and draw a plot in C#

I am trying to use the CSV below for drawing a plot:
2.364258,3.005366
2.723633,3.009784
3.083008,3.012145
3.442383,3.012705
3.801758,3.010412
4.160156,3.010703
4.518555,3.011985
4.876953,3.012547
5.235352,3.009941
5.592773,3.011252
5.951172,3.010596
6.30957,3.011951
6.667969,3.010613
7.026367,3.008634
7.384766,3.009744
7.743164,3.01062
8.101563,3.00942
8.459961,3.009438
8.818359,3.009478
9.177734,3.010827
What I did so far is that I tried to make a Class to do this! this is the part when I try to draw the curve:
class Plotter
{
#region Fields and variables
private Bitmap plot;
private Graphics g;
public string PlotType {get; set;}
private int iWidth; //Width of the box
private int iHeight; //
private float xMax; //maximum range on X axis
private float yMax; //maximum range on Y axis
private PointF[] points;
#endregion
#region Constructors
/// <summary>
/// Constructor of class
/// </summary>
/// <param name="iWidth">Width of image in pixels</param>
/// <param name="iHeight">Height of image in pixels</param>
/// <param name="xMax">Maximum value of the values on X</param>
/// <param name="yMax">Maximum value of the values on Y</param>
/// <param name="pairs">Pairs of data in an array of PointF[] this is raw data!!</param>
public Plotter(int iWidth, int iHeight, float xMax, float yMax, PointF[] points)
{
this.iWidth = iWidth;
this.iHeight = iHeight;
this.xMax = xMax;
this.yMax = yMax;
this.points = points;
plot = new Bitmap(iWidth, iHeight);
}
public Bitmap DrawPlot()
{
Pen blackPen = new Pen(Color.Black, 1);
g = Graphics.FromImage(plot);
PointF[] p = new PointF[points.GetLength(0)];
//Try to scale input data to pixel coordinates
foreach (PointF point in points)
{
int i = 0;
p[i].X = point.X * iWidth;
p[1].X = point.Y * iHeight;
}
g.DrawCurve(blackPen, p, 0);
return plot;
}
What I get at the end is jsut a stright line! that I think has been drawn on X{0,0} and Y{0,0} to X{0, 400} and Y{0,0}
Can you help me correct the mistakes please?
P.S: http://itools.subhashbose.com/grapher/index.php this site can draw the plot I need pretty good from the CSV data I have (if you need to check).
Thanks!
This seems to be your problem:
foreach (PointF point in points)
{
int i = 0;
p[i].X = point.X * iWidth;
p[1].X = point.Y * iHeight;
}
i is always zero and you are never assigning Y. The "second" assignment isn't even using i, but the 1 index.
Quick fix without error checking:
int i = 0;
foreach (PointF point in points)
{
p[i].X = point.X * iWidth;
p[i].Y = point.Y * iHeight;
i++;
}
Your assigning the x both times.
p[i].X = point.X * iWidth;
p[1].X = point.Y * iHeight;
And as #LarsTech points out you need to fix the counter

Are there mesh building helper classes in WPF or .NET 4.0?

The mechanisms for building a mesh in WPF are quite low-level. For example you have to supply the vertexes and the indexes. Are there helpers in the WPF or anywhere in the .NET 4.0 framework I can use? Or do I have to resort to third party libraries?
Here's an older chunk of XNA 3.1 code I wrote to build a Sphere. I apply a transformation matrix in my rendering loop that allows me to stretch and orient it. Computing the vertices is fairly straightforward... computing the indices are what I find more difficult. This should hopefully give you an idea, though. The other primitives (e.g. cone, cylinder, cube...) are much simpler to compute.
The m_iSegments paremeter just allows me to define how many slices I want to divide the sphere into... the more segments, the more vertices, the smoother the sphere.
The m_Appearance parameter is my wrapper for the shader.
/// <summary>
/// This method constructs ellipsoid vertices, indices, and normals.
/// Equations are performed using the parameterized equations:
///
/// x = a cos(B)cos(L)
/// y = b cos(B)sin(L)
/// z = c sin(B)
///
/// Where:
///
/// B = latitude and,
/// L = longitude
///
/// </summary>
/// <seealso cref="http://en.wikipedia.org/wiki/Ellipsoid">Wikipedia - Ellipsoid</seealso>
public override void BuildVertices()
{
#region Declarations
int iIndex = 0; // Stores the index of the vertex array.
int iBeta = 0; // Stores the beta increment.
int iLambda = 0; // Stores the lambda increment.
float Beta = 0.0f; // Beta0 - Stores the latitude.
float Lambda = 0.0f; // Lambda0 - Stores the longitude.
float BetaStep = MathHelper.Pi / m_iSegments; // Latitude Segements, in degrees.
float LambdaStep = MathHelper.TwoPi / m_iSegments; // Longitude Segments, in degrees.
Vector3 vectPos = Vector3.Zero; // Vertex Position Vector
Vector3 vectNor = Vector3.Zero; // Vertex Normal Vector
Vector2 vectTex = Vector2.Zero; // Vertex Texture Coordinate
#endregion
#region Build the vertices.
int[] iIndices = new int[6 * m_iSegments * m_iSegments];
Vector3[] vVertices = new Vector3[(m_iSegments + 1) * (m_iSegments + 1)];
Vector2[] vTexCrds = new Vector2[vVertices.Length];
iIndex = 0;
for (iBeta = 0; iBeta <= m_iSegments; iBeta++)
{
// Compute the latitude.
Beta = MathHelper.Clamp((-MathHelper.PiOver2) + (iBeta * BetaStep), -MathHelper.PiOver2, MathHelper.PiOver2);
for (iLambda = 0; iLambda <= m_iSegments; iLambda++)
{
// Compute the current longitude.
Lambda = MathHelper.Clamp((-MathHelper.Pi) + (iLambda * LambdaStep), -MathHelper.Pi, MathHelper.Pi);
// Compute the current vertex.
vVertices[iIndex] = new Vector3((float)(Math.Cos(Beta) * Math.Sin(Lambda)),
(float)(Math.Sin(Beta)),
(float)(Math.Cos(Beta) * Math.Cos(Lambda)));
// Compute the triangle indices.
if (iBeta < m_iSegments &&
iLambda < m_iSegments)
{
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 0] = iIndex;
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 1] = iIndex + m_iSegments + 1;
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 2] = iIndex + m_iSegments + 2;
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 3] = iIndex;
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 4] = iIndex + m_iSegments + 2;
iIndices[iIndex + (iIndex * 5) - (iBeta * 6) + 5] = iIndex + 1;
}
// Compute the texture coordinates.
vTexCrds[iIndex] = new Vector2((float)iLambda / (float)m_iSegments, 1.0f - (float)iBeta / (float)m_iSegments);
iIndex++;
}
}
# endregion
#region Build the normals.
Vector3[] vNormals = new Vector3[vVertices.Length];
for (iIndex = 0; iIndex < vVertices.Length; iIndex++)
{
vNormals[iIndex] = vVertices[iIndex] - this.AbsolutePosition;
vNormals[iIndex].Normalize();
}
#endregion
#region Build the buffers.
VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[vVertices.Length];
for (iIndex = 0; iIndex < vVertices.Length; iIndex++)
vertices[iIndex] = new VertexPositionNormalTexture(vVertices[iIndex], vNormals[iIndex], vTexCrds[iIndex]);
m_pAppearance.SetBuffers(vertices, iIndices);
#endregion
}

LockBits image rotation method not working?

Hey all. I resorted to using LockBits for 2d bitmap image rotation after getting fed up with the slow performance and wacky behavior of both Get/Set Pixel, and RotateTransfom. So here is the code I've come up with, and by my reckoning, it should work perfectly. It doesn't.
private static void InternalRotateImage(Bitmap originalBitmap, Bitmap rotatedBitmap, PointF centerPoint, float theta)
{
BitmapData originalData = originalBitmap.LockBits(
new Rectangle(0, 0, originalBitmap.Width, originalBitmap.Height),
ImageLockMode.ReadOnly,
originalBitmap.PixelFormat);
BitmapData rotatedData = rotatedBitmap.LockBits(
new Rectangle(0, 0, rotatedBitmap.Width, rotatedBitmap.Height),
ImageLockMode.WriteOnly,
rotatedBitmap.PixelFormat);
unsafe
{
byte[,] A = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] R = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] G = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] B = new byte[originalData.Height * 2, originalBitmap.Width * 2];
for (int y = 0; y < originalData.Height; y++)
{
byte* row = (byte*)originalData.Scan0 + (y * originalData.Stride);
for (int x = 0; x < originalData.Width; x++)
{
B[y, x] = row[x * 4];
G[y, x] = row[x * 4 + 1];
R[y, x] = row[x * 4 + 2];
A[y, x] = row[x * 4 + 3];
}
}
for (int y = 0; y < rotatedData.Height; y++)
{
byte* row = (byte*)rotatedData.Scan0 + (y * rotatedData.Stride);
for (int x = 0; x < rotatedData.Width; x++)
{
int newy = (int)Math.Abs((Math.Cos(theta) * (x - centerPoint.X) - Math.Sin(theta) * (y - centerPoint.Y) + centerPoint.X));
int newx = (int)Math.Abs((Math.Sin(theta) * (x - centerPoint.X) + Math.Cos(theta) * (y - centerPoint.Y) + centerPoint.Y));
row[x * 4] = B[newy, newx];
row[x * 4 + 1] = G[newy, newx];
row[x * 4 + 2] = R[newy, newx];
row[x * 4 + 3] = A[newy, newx];
}
}
}
originalBitmap.UnlockBits(originalData);
rotatedBitmap.UnlockBits(rotatedData);
}
Anybody got any ideas? I'm fresh out. Thanks in advance!
EDIT:
This is what I ended up using (many thanks to Hans Passant):
private Image RotateImage(Image img, float rotationAngle)
{
Image image = new Bitmap(img.Width * 2, img.Height * 2);
Graphics gfx = Graphics.FromImage(image);
int center = (int)Math.Sqrt(img.Width * img.Width + img.Height * img.Height) / 2;
gfx.TranslateTransform(center, center);
gfx.RotateTransform(rotationAngle);
gfx.DrawImage(img, -img.Width / 2, -img.Height / 2);
return image;
}
It's the same thing as his, just on a per image basis, as opposed to a form.
You are digging yourself a deeper hole. This goes wrong early, the size of the rotated bitmap is not Width x Height. It is also very inefficient. You need to get RotateTransform going, it is important to also use TranslateTransform and pick the correct image drawing location.
Here's a sample Windows Forms app that rotates a bitmap around its center point, offset just enough to touch the inner edge of the form when it rotates. Drop a Timer on the form and add an image resource with Project + Properties, Resource tab. Name it SampleImage, it doesn't have to be square. Make the code look like this:
public partial class Form1 : Form {
private float mDegrees;
private Image mBmp;
public Form1() {
InitializeComponent();
mBmp = Properties.Resources.SampleImage;
timer1.Enabled = true;
timer1.Interval = 50;
timer1.Tick += new System.EventHandler(this.timer1_Tick);
this.DoubleBuffered = true;
}
private void timer1_Tick(object sender, EventArgs e) {
mDegrees += 3.0F;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
int center = (int)Math.Sqrt(mBmp.Width * mBmp.Width + mBmp.Height * mBmp.Height) / 2;
e.Graphics.TranslateTransform(center, center);
e.Graphics.RotateTransform(mDegrees);
e.Graphics.DrawImage(mBmp, -mBmp.Width/2, -mBmp.Height/2);
}
}
You can make draw a lot faster by creating a bitmap in the 32bppPArgb format, I skipped that step.

Categories