Recursively draw rectangles in WinForms - c#

I'm currently coding a Sierpinski Carpet. Now i have the problen, that it works per iteration only once and not at every square on my whole screen.
This is the code i use:
private void Carpet(Graphics g, SolidBrush brush, Single
x, Single y, Single width, Single height, int iteration)
{
if (iteration == 0) {}
else
{
for (int i = 0; i < iteration + 1; i++)
{
width = Convert.ToSingle(Width / Math.Pow(3,i-1));
height = Convert.ToSingle(Height / Math.Pow(3, i-1));
Single x1 = x + width/3;
Single x2 = x1 + width;
Single x3 = x2 + width;
Single y1 = y + height/3;
Single y2 = y1 + height;
Single y3 = y2 + height;
g.FillRectangle(brush, x1, y1, width / 3, height / 3);
g.FillRectangle(brush, x1, y2, width / 3, height / 3);
g.FillRectangle(brush, x1, y3, width / 3, height / 3);
g.FillRectangle(brush, x2, y1, width / 3, height / 3);
g.FillRectangle(brush, x2, y3, width / 3, height / 3);
g.FillRectangle(brush, x3, y1, width / 3, height / 3);
g.FillRectangle(brush, x3, y2, width / 3, height / 3);
g.FillRectangle(brush, x3, y3, width / 3, height / 3);
}
}
}
How can i enhance my code, so it recursively draws Rectangles everywhere and not just on the first part of my Screen.

You draw only the smallest rectangles and nothing else. But to find the position of all of them you have to have a recursive function. So, determine coordinates and call itself recursively in all iterations except the last one. If it's the last iteration then draw just one rectangle that fills the whole area given with (x, y, width, height).
Instead of the for loop you have to have eight recursive calls. And in case of the last iteration you call only one g.FillRectangle. But now the problem is how to determine which iteration is the last one? When you call Carpet recursively call it with iteration - 1, and the last iteration is then the one with value zero.

Related

Increasing the height of Panel according to wrapped string Label in Panel

i am trying to develop a win form for chatting purpose. I am developing Chat bubbles using pure inbuilt functions of .Net Framework, No fancy UI, No third party libraries.
Now let's have a look on how every thing is being done.
My following function is responsible for generating a Panel dynamically for each chat message received, the Pain event is used to draw rounded rectangle and color is transparent. A picture box is used to show static avatar.
private void SetRemoteMessage(string msg)
{
PictureBox pb = new PictureBox();
pb.Bounds = new Rectangle(0, 0, 72, 72);
pb.Image = Base64ToImage(avatar_his);
Panel p = new Panel();
Label lb = new Label();
lb.BackColor = Color.Transparent;
lb.ForeColor = Color.Blue;
lb.Text = msg;
lb.Font = new Font("Arial", 14, FontStyle.Bold, GraphicsUnit.Point);
p.Bounds = new Rectangle(rX, rY, (Width / 2) - 25, pb.Height);
p.BackColor = Color.Transparent;
lb.Size = new Size(p.Width - pb.Width, p.Height);
lb.Paint += _control_Paint;
lb.Location = new Point(pb.Width + 5, 0);
p.Controls.Add(pb);
p.Controls.Add(lb);
SetPanel(p);
rY += p.Height + 20;
mY += p.Height + 20;
}
following is the Paint event binded to the parent "Container" Panel so that a simple rounded rectangle is shown for each bubble
private void _control_Paint(object sender, PaintEventArgs e)
{
Control c = (Control)sender;
if(!c.Name.Equals("lb"))
{
Graphics v = e.Graphics;
DrawRoundRect(v, Pens.Blue, e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1, 10);
}
else
{
using (Font font1 = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point))
{
e.Graphics.DrawString(c.Text, font1, Brushes.Blue, c.Bounds);
}
}
base.OnPaint(e);
}
and the following function to actually generate rounded rectangles
private void DrawRoundRect(Graphics g, Pen p, float X, float Y, float width, float height, float radius)
{
GraphicsPath gp = new GraphicsPath();
gp.AddLine(X + radius, Y, X + width - (radius * 2), Y);
gp.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90);
gp.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2));
gp.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
gp.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height);
gp.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
gp.AddLine(X, Y + height - (radius * 2), X, Y + radius);
gp.AddArc(X, Y, radius * 2, radius * 2, 180, 90);
gp.CloseFigure();
g.DrawPath(p, gp);
}
The chat message is not wrapped automatically so to wrap it, the Pain method is used as it can be seen in Paint event . .the output is good as expected instead of one thing
The Problem can be seen easily the Panel height is not increasing according when a large message is given to display in bubble.
What i tried already is
Measuring string length with Graphics class, but i was not able to implement it with success
Enabling Scrollbars, Yes this approach worked but i am not interested to use this behavior
Counting string length and increasing height, This works but not efficient, specially when form is resized all calculations of measurement then become invalid.

How to multiple cut one picture in c#?

I want to multiple cut one picture in c# code.the following image is my c # forum and I can select an area and cut it.
I want to multiple cut one picture in c# code
I want to repeat this process
private void btnKes_Click(object sender, EventArgs e)
{
int tiklanma = 0;
if (true)
{
tiklanma++;
}
pictureBox2.Refresh();
pictureBox2.Refresh();
Bitmap sourceBitmap = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Graphics g = pictureBox2.CreateGraphics();
int x1, x2, y1, y2;
Int32.TryParse(txtX1.Text, out x1);
Int32.TryParse(txtX2.Text, out x2);
Int32.TryParse(txtY1.Text, out y1);
Int32.TryParse(txtY2.Text, out y2);
if ((x1 < x2 && y1 < y2))
{
rectCropArea = new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
else if (x2 < x1 && y2 > y1)
{
rectCropArea = new Rectangle(x2, y1, x1 - x2, y2 - y1);
}
else if (x2 > x1 && y2 < y1)
{
rectCropArea = new Rectangle(x1, y2, x2 - x1, y1 - y2);
}
else
{
rectCropArea = new Rectangle(x2, y2, x1 - x2, y1 - y2);
}
pictureBox1.Refresh(); // This repositions the dashed box to new location as per coordinates entered.
int sayac = 40;
for (int i = 0; i < tiklanma; i++)
{
PictureBox pcBx = new PictureBox();
Size size = new Size(100, 100);
pcBx.Location();
pcBx.Size = size;
g.DrawImage(sourceBitmap, new Rectangle(0, 0, rectCropArea.Width, rectCropArea.Height), rectCropArea, GraphicsUnit.Pixel);
}
sourceBitmap.Dispose();
}
I want to select the fields more than once in the second picture and save the fields. How can I do this?
Use a FlowLayoutPanel, and every time you draw a new segment on the main image add a new PictureBox control to the layout panel.
Eventually you'll want to do other things with these picture segments, and so I also recommend immediately going a for a custom/user control here that includes a PictureBox as one part. That will make it much easier later to use buttons or context with each picture.
The specifics for all of this are out of scope for this type of question. We'd need to see more of your code to be able to use appropriate context with our answer, and the results are more than can fit well in the simple Q&A format. So go, try what you can, and then come back and ask new questions when you run into more specific problems.

Panel Round Edge

public void DrawRoundRect(Graphics g, Pen p, float X, float Y, float width, float height, float radius)
{
GraphicsPath gp = new GraphicsPath();
gp.AddLine(X + radius, Y, X + width - (radius * 2), Y);
gp.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90);
gp.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2));
gp.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
gp.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height);
gp.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
gp.AddLine(X, Y + height - (radius * 2), X, Y + radius);
gp.AddArc(X, Y, radius * 2, radius * 2, 180, 90);
gp.CloseFigure();
g.DrawPath(p, gp);
}
private void _pnlLogIn_Paint(object sender, PaintEventArgs e)
{
Graphics v = e.Graphics;
DrawRoundRect(v, Pens.Blue, e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1, 10);
//Without rounded corners
//e.Graphics.DrawRectangle(Pens.Blue, e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
base.OnPaint(e);
}
Hello, What is wrong with my code. My panel has already a round edge but the border of the rectangular panel remains. What code should i add or revise? thank you..
Image
Set your panel region to Graphics path.
In your code posted, do it after you call DrawPath in DrawRoundRect method.
Something like this:
_pnlLogIn.Region = new System.Drawing.Region(gp);
After I do above code change, I see my window as shown below.
I tried with bit bigger radius (40)..

Zooming in on quadratic curve line in c#

I am relatively new to c# and i am trying to draw the quadratic curve with an X and Y graph to scale with. The i drew curve although appears at the upper left corner of the screen which is very small and barely noticeable. Is there possible way to enlarge my curve line and align it to the middle so it can be shown properly?
protected override void OnPaint(PaintEventArgs e)
{
float a = 1, b = -3, c = -4;
double x1, x2, x3, y1, y2, y3, delta;
delta = (b * b) - (4 * a * c);
x1 = ((b * (-1)) + Math.Sqrt(delta)) / (2 * a);
y1 = a * (x1 * x1) + b * (x1) + c;
x2 = x1 + 1;
y2 = a * (x2 * x2) + b * (x2) + c;
x3 = x1 - 3;
y3 = a * (x3 * x3) + b * (x3) + c;
int cx1 = Convert.ToInt32(x1);
int cx2 = Convert.ToInt32(x2);
int cx3 = Convert.ToInt32(x3);
int cy1 = Convert.ToInt32(y1);
int cy2 = Convert.ToInt32(y2);
int cy3 = Convert.ToInt32(y3);
Graphics g = e.Graphics;
Pen aPen = new Pen(Color.Blue, 1);
Point point1 = new Point(cx1, cy1);
Point point2 = new Point(cx2, cy2);
Point point3 = new Point(cx3, cy3);
Point[] Points = { point1, point2, point3 };
g.DrawCurve(aPen, Points);
Yes it is possible and even rather simple to both move (Translate) and enlarge (Scale) the Graphics results by using Graphics.TranslateTransform and Matrix and Graphics.MultiplyTransform:
using System.Drawing.Drawing2D;
//..
int deltaX = 100;
int deltaY = 100;
g.TranslateTransform(deltaX, deltaY);
float factor = 2.5f;
Matrix m = new Matrix();
m.Scale(factor, factor);
g.MultiplyTransform(m);
Note that the scaling works like a lens and will enlarge the pixels. So you may want to scale down the Pen.Width when you scale up the Graphics..
Using one before..
g.DrawEllipse(Pens.Blue, 11, 11, 55, 55);
..and two after the transformations..
g.DrawEllipse(Pens.Red, 11, 11, 55, 55);
using (Pen pen = new Pen(Color.Green, 1/factor))
g.DrawEllipse(pen, 11, 11, 44, 44);
..these calls result in this image:
(I have changed the green circle's radius to avoid complete overlaying..)
It will be up to you to find the desired numbers for the moving and scaling; this will probably involve finding the minimum and maximum values for points involved..
I would suggest that you look into Microsoft Chart controls, it has a lots of interesting features regarding how to do this kind of curves with the ability to parameterize them.
A link to a more recent version of it: here

Blending/smooth-shading material

I'm creating and drawing a triangle mesh in wpf c# using GeometryModel3D. I've been trying to figure out how to create a smooth shading over the triangles, like the classic openGL smooth shaded triangle.
I would like to define a colour for each vertex, and then having the colours interpolated over the face, like this, assuming the three colour where red, green and blue.
I assumed I would need to use a brush, but I haven't been able to figure out how.
So any help would be appreciated, or any pointer to a guide that shows me how to achieve this.
EDIT:
I've looked at Triangular Gradient in WPF3D, which seems to answer the question partly, just using xaml.
Unfortunatly it seems like it need equilateral triangles.
2nd EDIT
The answer above, uses the RadialGradientBrush. Is the RadiusXand RadiusY used to make it elliptic instead of circular?
3rd EDIT
Okay, I'm fairly sure I can use the RadialGradientBrush. What I think I can do is, find the center of the circumcircle of the triangles, and create a RadialGradientBrush with RadiusX and RadiusY equal to the radius if the circumcircle. I would then move the focal point of the RadialGradientBrush to the vertices with GradientOrigin.
GradientOrigin takes two doubles X,Y as the center, with both of them being in the interval [0,1]. From what I can read is X = 0.0 is the left side and X = 1.0 is the right side and Y = 0.0 is the top and Y = 1.0 is the bottom. What I can't figure out, is this mapping [0,1]x[0,1] to a circle, or is it a square? The mapping from the vertices of the triangle to [0,1]x[0,1], depends on what shape this interval represents.
Have you heard of Helix 3D Toolkit for WPF ?
I didn't go as far as you'd like but I guess it is possible by looking at the Surface Demo example :
There are surely libraries for that, but to give some simple way, searching through some google,http://www.geeksforgeeks.org/check-whether-a-given-point-lies-inside-a-triangle-or-not/
computing the distance from corners, gives info about the smooth color. Checking if point is in triangle.
float area(int x1, int y1, int x2, int y2, int x3, int y3)
{
return (float)Math.Abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0);
}
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{
/* Calculate area of triangle ABC */
float A = area(x1, y1, x2, y2, x3, y3);
/* Calculate area of triangle PBC */
float A1 = area(x, y, x2, y2, x3, y3);
/* Calculate area of triangle PAC */
float A2 = area(x1, y1, x, y, x3, y3);
/* Calculate area of triangle PAB */
float A3 = area(x1, y1, x2, y2, x, y);
/* Check if sum of A1, A2 and A3 is same as A */
return (A == A1 + A2 + A3);
}
for (int ii = 5; ii < 100; ii++)
{
for (int jj = 5; jj < 100; jj++)
{
int distanceRed =0, distanceGreen =0,distanceBlue =0;
if (isInside(30, 50, 30, 90, 20, 70, ii, jj))
{
distanceRed = (int)Math.Sqrt(((ii - 30) * (ii - 30) + (jj - 50) * (jj - 50)));
distanceGreen = (int)Math.Sqrt(((ii - 30) * (ii - 30) + (jj - 90) * (jj - 90)));
distanceBlue = (int)Math.Sqrt(((ii - 20) * (ii - 20) + (jj - 70) * (jj - 70)));
}
else
{
distanceRed = 0; distanceGreen = 0; distanceBlue = 0;
}
ptr[(((int)jj) * 3) + ((int)ii) * stride] = (byte)(distanceRed % 256);
ptr[(((int)jj) * 3) + ((int)ii) * stride + 1] = (byte)(distanceGreen % 256);
ptr[(((int)jj) * 3) + ((int)ii) * stride + 2] = (byte)(distanceBlue % 256);
}
}
gives the result:
Couldnt fit the red. Maybe the modulo is wrong here.
Also the sqrt is inefficient.

Categories