I'm trying to write a program that paints a polygon onto a PictureBox. I want the user to enter values such as the center's X and Y point, length, angle, number of edges to textboxes. Then I want to use the values in textboxes as parameters.
The problem is that the program throws different types of exceptions as soon as I launch it without letting me enter any values into the textboxes. I guess it takes the TextBox.Text as a null value or an empty string so other parts of my code fail.
How do I get TextBox.Text?
Also, if you have any suggestions about calculating the vertex points of a polygon please share it with 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 ConsoleApp1;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public int CenterX, CenterY, Length, Angle;
public int Edges;
private void button1_Click(object sender, EventArgs e)
{
CenterX = int.Parse(textBox1.Text);
CenterY = int.Parse(textBox2.Text);
Length = int.Parse(textBox3.Text);
Angle = int.Parse(textBox4.Text);
Edges = int.Parse(textBox5.Text);
pictureBox1.Invalidate();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox5_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
/////////////////////////////////////////////////////////////////////////////
pictureBox1.CreateGraphics();
/////////////////////////////////////////////////////////////////////////////
int width = pictureBox1.ClientSize.Width;
int height = pictureBox1.ClientSize.Height;
int newWidth = width / 2;
int newHeight = height / 2;
e.Graphics.TranslateTransform((float)newWidth, (float)newHeight);
/////////////////////////////////////////////////////////////////////////////
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
/////////////////////////////////////////////////////////////////////////////
Pen pen = new Pen(Color.Black, 5);
/////////////////////////////////////////////////////////////////////////////
Polygon polygon = new Polygon(CenterX, CenterY);
polygon.LENGTH = Length;
polygon.ROTATIONANGLE = Angle;
polygon.NUMBER_OF_EDGES = Edges;
polygon.calculateEdgeCoordinates();
polygon.rotatePolygon();
/////////////////////////////////////////////////////////////////////////////
PointF[] points = new PointF[polygon.rotatedPoints.Count];
for (int i = 0; i < polygon.rotatedPoints.Count; i++)
{
points[i] = polygon.rotatedPoints[i];
}
e.Graphics.DrawPolygon(pen, points);
e.Dispose();
}
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
}
public class Polygon
{
Point2D center = new Point2D();
public List<Point2D> edgePoints = new List<Point2D>();
public List<PointF> rotatedPoints = new List<PointF>();
private double radius, angle, length, rotationAngle; private int numberOfEdges;
public double RADIUS { get => radius; set => radius = value; }
public double LENGTH { get => length; set => length = value; }
public double ROTATIONANGLE { get => rotationAngle; set => rotationAngle = value; }
public int NUMBER_OF_EDGES { get => numberOfEdges; set => numberOfEdges = value; }
public Polygon()
{
Point2D polarCoords = center.calculatePolarCoordinates();
polarCoords.X = length;
angle = polarCoords.Y;
}
public Polygon(double x, double y)
{
center.X = x;
center.Y = y;
Point2D polarCoords = center.calculatePolarCoordinates();
polarCoords.X = length;
angle = polarCoords.Y;
}
public void calculateEdgeCoordinates()
{
double interiorAngle = 360 / numberOfEdges;
for (int i=0; i < numberOfEdges; i++)
{
if (i == 0)
{
Point2D point = new Point2D(length, angle);
edgePoints.Add(point);
}
else
{
Point2D point = new Point2D(length, angle+interiorAngle);
edgePoints.Add(point);
}
}
}
public void rotatePolygon()
{
for (int i=0; i < edgePoints.Count; i++)
{
edgePoints[i].Y += rotationAngle;
edgePoints[i].calculateCartesianCoordinates();
PointF point = new PointF((float)(edgePoints[i].X), (float)(edgePoints[i].Y));
rotatedPoints.Add(point);
}
}
}
}
This is necessary to start off with
private void button1_Click(object sender, EventArgs e)
{
if (!int.TryParse(textBox1.Text, out CenterX))
CenterX = 0;
if (!int.TryParse(textBox2.Text, out CenterY))
CenterY = 0;
if (!int.TryParse(textBox3.Text, out Length))
Length = 0;
if (!int.TryParse(textBox4.Text, out Angle))
Angle = 0;
if (!int.TryParse(textBox5.Text, out Edges))
Edges = 0;
pictureBox1.Invalidate();
}
Then also use this: (here's your 0 division if numberOfEdges = 0)
double interiorAngle = 360;
if (numberOfEdges != 0)
interiorAngle = 360 / numberOfEdges;
Related
The method genereer ("generate") draws a Bitmap image of a Mandelbrot. It has a variable schaal ("scale") which makes the Bitmap zoom in on the image with a certain factor. The standard value for this is 0.01, as declared above in the partial class Form1.
I have a textBox3 in the GUI, and I want to be able to type a new value in this textBox3, click on the button and draw a new image based on the scale.
I've written a method called Lees ("read"), which parses a double from textBox3. I've put this method in the Button1_MouseClick method, as well as the genereer method to draw a new image upon button click. I've also put the genereer method in the Form1_Shown method.
However, this doesn't seem to be working. When I click on the button, no matter what the value is, I get a white dot in the middle of the screen.
public partial class Form1 : Form
{
public double waardeX, waardeY, schaal = 0.01;
public int maxIteraties;
public Form1()
{
InitializeComponent();
}
private void Form1_Shown(object sender, EventArgs e)
{
Genereer();
}
public void Lees()
{
schaal = double.Parse(textBox3.Text);
}
private void Genereer()
{
double max = 100;
Bitmap bitmap = new Bitmap(Figuur.Width, Figuur.Height);
for (int x = 0; x < Figuur.Width; x++)
{
for (int y = 0; y < Figuur.Height; y++)
{
//double a = (double)(x - (Figuur.Width / 2)) / (double)(Figuur.Width / 4);
//double b = (double)(y - (Figuur.Height / 2)) / (double)(Figuur.Height / 4);
double a = (double)(x - (Figuur.Width / 2)) * (double)(schaal);
double b = (double)(y - (Figuur.Height /2)) * (double)(schaal);
Mandelgetal getal = new Mandelgetal(a, b);
Mandelgetal waarde = new Mandelgetal(0, 0);
int i = 0;
while (i < max)
{
//i++; //v1
waarde.Vermenigvuldig();
waarde.Toevoegen(getal);
if (waarde.Wortel() > 2.0)
{
break;
}
else
{
if (i % 2.0 == 0.0)
{
bitmap.SetPixel(x, y, Color.White);
i++; //v2
}
else
{
bitmap.SetPixel(x, y, Color.Black);
i++; //v2
}
}
}
if((a*a + b*b) > 4)
{
bitmap.SetPixel(x, y, Color.Black);
}
Figuur.Image = bitmap;
}
}
}
private void Button1_MouseClick(object sender, MouseEventArgs e)
{
Lees();
Genereer();
this.Invalidate();
}
}
}
I need to move a point along a rectangle path at the command of a button. I want it to start at the upper right corner of the rectangle path, but I am not sure how to get it to go all the way around the path and stop at the original point. The screen refreshes at the speed provided by the user in an input box. Thank you in advance!
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.Timers;
namespace Assignment_2
{
public partial class Form1 : Form
{
private const int formwidth = 1280;
private const int formheight = 720;
private const int ball_a_radius = 10;
private const int horizontaladjustment = 8;
private const double ball_a_distance_moved_per_refresh = 1.6;
private double ball_a_real_coord_x = 515;
private double ball_a_real_coord_y = 40;
private int ball_a_int_coord_x;
private int ball_a_int_coord_y;
private const double graphicrefreshrate = 30.0;
private static System.Timers.Timer graphic_area_refresh_clock = new System.Timers.Timer();
private static System.Timers.Timer ball_a_control_clock = new System.Timers.Timer();
private bool ball_a_clock_active = false;
public double speed = 0;
public Form1()
{
InitializeComponent();
ball_a_int_coord_x = (int)(ball_a_real_coord_x);
ball_a_int_coord_y = (int)(ball_a_real_coord_y);
System.Console.WriteLine("Initial coordinates: ball_a_int_coord_x = {0}. ball_a_int_coord_y = {1}.",
ball_a_int_coord_x, ball_a_int_coord_y);
graphic_area_refresh_clock.Enabled = false;
graphic_area_refresh_clock.Elapsed += new ElapsedEventHandler(Updatedisplay);
ball_a_control_clock.Enabled = false;
ball_a_control_clock.Elapsed += new ElapsedEventHandler(Updateballa);
Startgraphicclock(graphicrefreshrate);
Startballaclock(speed);
}
public class NumericTextBox : TextBox
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
}
private void panel2_Paint_1(object sender, PaintEventArgs e)
{
//Create pen
Pen blackPen = new Pen(Color.Black, 1);
//Create rectangle
Rectangle rect = new Rectangle(125, 50, 400, 400);
//Draw rectangle to screen
e.Graphics.DrawRectangle(blackPen, rect);
Graphics graph = e.Graphics;
graph.FillEllipse(Brushes.Green, ball_a_int_coord_x, ball_a_int_coord_y, 2 * ball_a_radius, 2 * ball_a_radius);
base.OnPaint(e);
}
public void button7_Click(object sender, EventArgs e)
{
speed = Convert.ToInt32(textBox3.Text);
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
protected void Startgraphicclock(double refreshrate)
{
double elapsedtimebetweentics;
if (refreshrate < 1.0) refreshrate = 1.0;
elapsedtimebetweentics = 1000.0 / refreshrate;
graphic_area_refresh_clock.Interval = (int)System.Math.Round(elapsedtimebetweentics);
graphic_area_refresh_clock.Enabled = true;
}
protected void Startballaclock(double updaterate)
{
double elapsedtimebetweenballmoves;
if (updaterate < 1.0) updaterate = 1.0;
elapsedtimebetweenballmoves = 1000.0 / updaterate;
ball_a_control_clock.Interval = (int)System.Math.Round(elapsedtimebetweenballmoves);
ball_a_control_clock.Enabled = true;
ball_a_clock_active = true;
}
protected void Updatedisplay(System.Object sender, ElapsedEventArgs evt)
{
Invalidate();
if (!(ball_a_clock_active))
{
graphic_area_refresh_clock.Enabled = false;
System.Console.WriteLine("The graphical area is no longer refreshing. You may close the window.");
}
}
protected void Updateballa(System.Object sender, ElapsedEventArgs evt)
{
ball_a_real_coord_x = ball_a_real_coord_x - 5;
ball_a_real_coord_y = ball_a_real_coord_y - 5;
ball_a_int_coord_x = (int)System.Math.Round(ball_a_real_coord_x);
ball_a_int_coord_y = (int)System.Math.Round(ball_a_real_coord_y);
if (ball_a_int_coord_x >= formwidth || ball_a_int_coord_y + 2 * ball_a_radius <= 0 || ball_a_int_coord_y >= formheight)
{
ball_a_clock_active = false;
ball_a_control_clock.Enabled = false;
System.Console.WriteLine("The clock controlling ball a has stopped.");
}
}
private void button4_Click(object sender, EventArgs e)
{
ball_a_control_clock.Enabled = true;
}
}
}
I have a more straightforward way to move a circle. Your code is too long for me to read. See if you like this!
If I were you, I would use a PictureBox. I first create an image of a circle, and then put that image in the PictureBox. Then you can just use a timer to change the position of the PictureBox.
You should set the Interval of the timer to 33 ms, which is roughly 30 fps. This is how you would programme the timer:
Keep a counter to indicate how many pixels the circle has moved. Let's say you want it to move in a 100px x 50px rectangular path.
For every 33ms,
If the counter is less than 100,
increase the X position and the counter by 1,
if the counter is between 101 and 150,
increase the Y position and the counter by 1,
if the counter is between 151 and 250,
decrease the X position by 1 and increment the counter
if the counter is between 251 and 300,
decrease the Y position by 1 and increment the counter
if the counter is greater than 300,
stop the timer
I really don't like drawing stuff on the screen with the OnPaint event. I mean, you are moving a ball! People think of this as changing the x and y positions of a ball, not as deleting the ball at the previous position and drawing it in the new position. Changing the position of the picture box just makes LOTS more sense, don't you think so?
I am using Windows Form application and using one button to generate random number and draw on form. when button is clicked, It is adding a random number using Graphics.Drawing method. Problem is when I hit the button first time it works fine and add a random number i.e 11111. When I hit button again it will add a new random number (on next position) but it will also change previous numbers to new generated random number.
Updated: (Added Complete Code)
Edit: I have moved Random outside of scoop so now it does not generate same number but still its changing old random numbers to other ones.
Main Class:
using System;
using System.Collections;
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;
namespace DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseMovePosition = e.Location;
if (e.Button == MouseButtons.Left)
mousePressdDown = 1;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
mouseDownPosition = e.Location;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition);
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a.old, a.cur);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, Point mold, Point mcur)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
string header2 = rnd.Next().ToString();
RectangleF header2Rect = new RectangleF();
int moldX = mold.X - 5;
int moldY = mold.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(header2, useFont, Brushes.Black, header2Rect);
}
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
Drawing Data Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace DrawingText
{
[Serializable]
class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
}
public DrawingData(Point old, Point cur)
{
mold = old;
mcur = cur;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
}
}
3 times button clicked and it replaced old value with new one:
You need to store the random value with the point values in the DrawingData class, like this:
Main Class:
namespace DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition, rnd.Next().ToString());
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, DrawingData a)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
RectangleF header2Rect = new RectangleF();
int moldX = a.old.X - 5;
int moldY = a.old.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(a.Rand, useFont, Brushes.Black, header2Rect);
}
}
}
}
Drawing Data Class:
namespace DrawingText
{
[Serializable]
public class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
private string randValue; // random data value
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
randValue = String.Empty;
}
public DrawingData(Point old, Point cur, string rand)
{
mold = old;
mcur = cur;
randValue = rand;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
public sting Rand
{
get
{
return randValue;
}
set
{
randValue = value;
}
}
}
You are recreating your random each time in the loop which will cause it to have the same seed, and the same first number. That's why all your numbers are the same. You should.
Move your random outside of the method and loop, and use it instead. Change the line Random rnd = new Random() to rnd = new Random(). You already have a variable in the class to hold the random.
If you want the previous random numbers to remain the same as the last time, you need to store them in a list somewhere and draw them on paint. You are currently creating a new set of random numbers each time.
This is made on the fly using graphics path:
GraphicsPath gp;
int moldX = 10;
int moldY = 10;
public Form1()
{
InitializeComponent();
gp = new GraphicsPath();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.FillPath(Brushes.Black, gp);
// if you want the numbers outlined do e.Graphics.DrawPath
}
private void button1_Click(object sender, EventArgs e)
{
AddToPath();
Invalidate();
}
private void AddToPath()
{
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
Random rnd = new Random();
string header2 = rnd.Next().ToString();
int strsize = TextRenderer.MeasureText(header2, useFont).Height;
StringFormat format = StringFormat.GenericDefault;
gp.AddString(header2, useFont.FontFamily, 1, 28, new Point(moldX, moldY), format);
moldX += 5;
moldY += strsize;
}
}
I am working on an application for WP8, in my code I want to assign indexes to buttons like in arrays. Reason is that I want to operate buttons with buttons (i.e one button that is pressed activate other buttons)
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;
namespace test2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class LEDButton : Button
{
public const int LEDWidth = 50;
public const int LEDHeight = 30;
public LEDButton()
{
BackColor = Color.Tan;//inner color
//BackColor = Color.FromArgb(0, 64, 0);
ForeColor = Color.Yellow;//outline
FlatStyle = FlatStyle.Popup;//Button style
Size = new Size(LEDWidth, LEDHeight);
UseVisualStyleBackColor = false;
}
}
private void button1_Click(object sender, EventArgs e)
{
LEDButton[,] b = new LEDButton[4, 4];
for (int y = 0; y < b.GetUpperBound(0); y++)
{
for (int x = 0; x < b.GetUpperBound(1); x++)
{
b[y, x] = new LEDButton()
{
//put button properties here
Name = "button" + y.ToString() + x.ToString(),//String.Format("Button{0}{1}", y, x),
TabIndex = 10 * y + x,
Text = y.ToString() + x.ToString(),
Location = new Point(LEDButton.LEDWidth * x + 20, LEDButton.LEDHeight * y + 20)
};
// b[y, x].Click += button_Click;
}
}
// add buttons to controls
for (int y = 0; y < b.GetUpperBound(0); y++)
for (int x = 0; x < b.GetUpperBound(1); x++)
this.Controls.Add(b[y, x]);
}
}
}
If I have understood your question properly, you should rely on an array of delegates. Here you have a correction of your code assigning dynamically 4 different methods to 4 different buttons:
namespace test2
{
public partial class Form1 : Form
{
public delegate void button_click(object sender, EventArgs e);
public static button_click[] clickMethods = new button_click[4];
public Form1()
{
InitializeComponent();
}
public class LEDButton : Button
{
public const int LEDWidth = 50;
public const int LEDHeight = 30;
public LEDButton()
{
BackColor = Color.Tan;//inner color
//BackColor = Color.FromArgb(0, 64, 0);
ForeColor = Color.Yellow;//outline
FlatStyle = FlatStyle.Popup;//Button style
Size = new Size(LEDWidth, LEDHeight);
UseVisualStyleBackColor = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
clickMethods[0] = buttonGeneric_Click_1;
clickMethods[1] = buttonGeneric_Click_2;
clickMethods[2] = buttonGeneric_Click_3;
clickMethods[3] = buttonGeneric_Click_4;
}
private void buttonGeneric_Click_1(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_2(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_3(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_4(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
LEDButton[,] b = new LEDButton[4, 4];
for (int y = 0; y < b.GetUpperBound(0); y++)
{
for (int x = 0; x < b.GetUpperBound(1); x++)
{
b[y, x] = new LEDButton()
{
//put button properties here
Name = "button" + y.ToString() + x.ToString(),//String.Format("Button{0}{1}", y, x),
TabIndex = 10 * y + x,
Text = y.ToString() + x.ToString(),
Location = new Point(LEDButton.LEDWidth * x + 20, LEDButton.LEDHeight * y + 20)
};
if (y <= 3)
{
b[y, x].Click += new System.EventHandler(clickMethods[y]);
}
}
}
// add buttons to controls
for (int y = 0; y < b.GetUpperBound(0); y++)
for (int x = 0; x < b.GetUpperBound(1); x++)
this.Controls.Add(b[y, x]);
}
}
}
--- loop ---
Button abc = new Button();
abc.Name = loopCounter.ToString();
--- loop ---
This will help you to assigning indexes,
Don't use array of Button, it is useless!
Greetings
I genereated a terrain with this equation:
H(x,y) = (abs(sin(x * y)) + abs(sin(0,2 * x) + sin(0,4 * y)) + abs(cos(0,12 * x) + cos(0,47 * y))) * e^(0.005*(x+y))
Now, this gives me a mix of featuresize, and a nice slope. This works fine, when I plot it using scilab.
I tried to import this in a c# application.
The terrain is created in this code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Collections.Generic;
namespace Kamera_eins
{
public partial class Terrain : Form
{
public double[,] DTM;
string response ;
public Terrain()
{
InitializeComponent();
response = "";
DTM = new double[2048/4,2048/4];
}
public void BoxTheSky()
{
}
public void BoxTheLand()
{
mesh();
surf();
}
public void begin()
{
}
public void mesh()
{
response = "";
int i = new int();
int j = new int();
i = 0;
j = 0;
for (i=0;i<2048/4 ;i++ ) {
for (j=0;j<2048/4 ;j++ ) {
DTM[i,j] = Math.Abs (Math.Sin (j*i)) + Math.Abs(Math.Sin(0.2*i) * Math.Sin(0.4*j) ) + Math.Abs(Math.Cos(0.12* i) * Math.Cos(0.47*j));
DTM[i,j] = Math.Pow(Math.E, (0.012* (i + j)));
}
}
response = "DTM mesh ready";
}
public void surf()
{
}
}
}
This is kept in a file called terrain.cs, and i make this a winform, because i plan to add a simple textbox, where i can later make some sort of realtime log of the process.
Now, there is another file, and in that file, intend to display this terrain. this second file goes as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
namespace Kamera_eins
{
public class viewport : Form
{
public Microsoft.DirectX.Direct3D.Device device = null;
public PresentParameters presentparameter = new PresentParameters();
public bool device_exists;
public bool show;
public int HEIGHT;
public int WIDTH;
public string paintDesc;
private float angle ;
private CustomVertex.PositionColored[] vertices;
public double[,] heightData;
private int[] indices;
private IndexBuffer ib;
private VertexBuffer vb;
private Microsoft.DirectX.DirectInput.Device keyb;
//public
public viewport()
{
this.ClientSize = new System.Drawing.Size(600, 600);
this.Text = "Terrain viewport";
WIDTH = 2048 / 4;
HEIGHT = 2048 / 4;
heightData = new double[HEIGHT,WIDTH];
keyb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
presentparameter.Windowed = true;
presentparameter.SwapEffect = SwapEffect.Discard;
presentparameter.AutoDepthStencilFormat = DepthFormat.D16;
presentparameter.EnableAutoDepthStencil = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
try {
device = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparameter);
device.DeviceLost += new EventHandler(this.InvalidateDeviceObjects);
device.DeviceReset += new EventHandler(this.RestoreDeviceObjects);
device.Disposing += new EventHandler(this.DeleteDeviceObjects);
device.DeviceResizing += new CancelEventHandler(this.EnvironmentResizing);
device_exists = true;
} catch (Exception DirectException) {
device_exists = false;
}
}
private void setcamera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.View = Matrix.LookAtLH (new Vector3(0, 0, 100), new Vector3(0, 0, 0) , new Vector3(0,0,1) );
device.RenderState.Lighting = false;
device.RenderState.FillMode = FillMode.WireFrame;
device.RenderState.CullMode = Cull.None;
}
public void declareVertex()
{
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), HEIGHT*WIDTH, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[HEIGHT*WIDTH];
for (int x=0;x< WIDTH;x++) {
for (int y=0; y< HEIGHT;y++) {
vertices[x + y * WIDTH].Position = new Vector3(x, y, (float)heightData[x,y]);
int r = Convert.ToInt32(205 * heightData[x,y] / 200 );
if(r>254)
r = 254;
vertices[x + y * WIDTH].Color = Color.FromArgb( r , 120 , 120).ToArgb();
}
}
vb.SetData(vertices, 0, LockFlags.None);
}
public void declareIndex()
{
ib = new IndexBuffer(typeof(int), (WIDTH-1)*(HEIGHT-1)*6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(WIDTH-1)*(HEIGHT-1)*6];
for (int x=0;x< WIDTH-1;x++) {
for (int y=0; y< HEIGHT-1;y++) {
indices[(x+y*(WIDTH-1))*6] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+1] = (x+1)+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+2] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+3] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+4] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+5] = x+(y+1)*WIDTH;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
MessageBox.Show("");
}
protected virtual void InvalidateDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void RestoreDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void DeleteDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void EnvironmentResizing(object sender, CancelEventArgs e)
{
}
public void run()
{
while(this.Created)
{
render();
setcamera();
// optional: loading the height using functional call:
// loadheight();
Application.DoEvents();
}
}
public void render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
//display terrain
device.VertexFormat = CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.Transform.World = Matrix.Translation(-HEIGHT/2, -WIDTH/2, 0)*Matrix.RotationZ(angle) ;
device.DrawIndexedPrimitives(PrimitiveType.TriangleFan, 0, 0, WIDTH*HEIGHT, 0, indices.Length/3);
//turn off lights now
device.EndScene();
device.Present();
this.Invalidate();
readkeyboard();
}
}
void readkeyboard()
{
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.Delete])
{
angle+=0.03f;
}
if (keys[Key.Next])
{
angle-=0.03f;
}
}
public void openport()
{
}
protected override void OnPaint(PaintEventArgs e)
{
render();
setcamera();
}
}
}
Now, yet a third file calls the world creation and display:
void MainFormLoad(object sender, EventArgs e)
{
world = new World();
world.setterrain();
}
the surf and box-somthing functions do not yet do anything.
All what i get now, is just a black window (the device.clear(... ) part) - i tried to adjust the camera .. no success
please help, i want to show the terrain in the window ....