I am trying to draw a network topology consists of many nodes to be like a 3D nodes using the idea of projection, but when I click the button that should implement the code nothing appears!!!! the following is the main code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Windows.Forms;
using AUV_Topology.AUV_Topology;
using AUV_Topology;
namespace AUV_Topology
{
public partial class Form2 : Form
{
private int iSetupDisplay = -1; // used for making drawing on the graphics
static int NodeNum = 0; // an int number is given for each node
static bool deploymentButtonWasClicked = false; // flag to check if button "Deploy" is clicked
static Sink sink; // sink object from sink class
static SensorNode[] SNs; // array of SNs
static int[,] SNsLocation; // to store SN locations
static int[,] SNsNighbors; // to store each SN nighbors
static int[] SinkNighbors; // to store each SN nighbors
static int transmissionRange; // the transmission range for each sensor node
static double sensorNodeIntialEnergy; // in order to store the energy filled in the text box in the GUI
System.IO.StreamWriter writer; // declare a writer object from the straem writer class
static Random r = new Random(); // in order to generate a random number
static AUV[] auv; // array of AUVs objects from AUV class
static int rows, columns; // to get the number of rows and columns from the text boxes in the GUI
static int[,] cellsCenters; // an array to store the indexes (col & row) for each center for each cell in the grid topology
static int[] columnsXs; // the index of each X cordinates in each column
static int[] rowsYs; // the index of each Y cordinates
static int numOfCells; // compute the number of cells by multpling the rows with columns
static int cellSide; // to compute the length of each side for each cell
public Form2()
{
InitializeComponent();
// Create a file for output named TraceFile.txt.
Stream myFile = File.Create("C:/Users/AMCT/Desktop/TraceFile2.txt");
TextWriterTraceListener myTextListener = new TextWriterTraceListener(myFile);
Trace.Listeners.Add(myTextListener);
}
private void Form2_Load(object sender, EventArgs e)
{
}
public delegate void UpdateControlsDelegate();
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct Point3D
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public Point3D(int x, int y, int z) : this()
{
this.X = x;
this.Y = y;
this.Z = z;
}
}
public static SoundPlayer player = new SoundPlayer("C:/Users/AMCT/Desktop/project/C#-Code-VisualStudio-2010/GAAPS/Sonar_pings.wav");
public static int tr;
//***Deployment***//
#region nodesDeployment
private void nodesDeployment_Click_1(object sender, EventArgs e)
{
//chromosome size
rows = 10;
columns = 10;
int numOfGridCells = rows * columns; // Calculate the total number of the cells for the grid topology
tr = Convert.ToInt32(TransRange.Text);
calculateCellsCenters(200, 200, 700, 700, numOfGridCells, 500, 500); // Compute all the center points (Xc,Yc) for all cells of the partitioned region (grid)
if (NumSN.Text != string.Empty) // to check that the user has entered the number of nodes for this topology
{
topology2.Visible = true;
NodeNum = Convert.ToInt32(NumSN.Text); // get the number from the text box
sensorNodeIntialEnergy = Convert.ToDouble(SNEnergy.Text);
Point3D[] auvLocation2D = new Point3D[4];
for (int i = 0; i < 4; i++)
auvLocation2D[i] = new Point3D(cellsCenters[0, 0], cellsCenters[1, 8], 700 - i * 100);
Point3D p3d = new Point3D(542, 600, 210);
PointF point2Dsink = Project(p3d);
sink = new Sink("Sink", 1, point2Dsink.X, point2Dsink.Y, 100);
auv = new AUV[4];
for (int i = 0; i < 4; i++)
{
PointF point2D = Project(auvLocation2D[i]);
int d = 700 - i * 100;
auv[i] = new AUV(point2D.X, point2D.Y, d, sink, i);
}
SNs = new SensorNode[NodeNum];
for (int i = 0; i < NodeNum; i++)
SNs[i] = new SensorNode(i, "SN" + i, r.Next(355, 750) % (topology2.Width), sensorNodeIntialEnergy, sink, auv[0], 0);
nodesCoordinations(); // choose XY coordinates for each sensor node
generateRoutingTable(); // build the routing table for each sensor node
deploymentButtonWasClicked = true;
}
makeDrawing(); // Draw
}
#endregion
//***Nodes Coordinates***//
#region Nodes Coordinates ( used by deployment process )
public void nodesCoordinations()
{
SNsLocation = new int[2, NodeNum]; // build an array of size n which is equal to the number of nodes that was chosen by the user to store all SNs locations
# region SNs Locations
for (int i = 0; i < NodeNum; i++)
if (NodeNum != 0)
{
SNsLocation[0, i] = r.Next(300, 800) % (topology2.Width); // choose random X coordinate between 300 & 800 pixel
SNsLocation[1, i] = r.Next(260, 725) % (topology2.Width); // choose random Y coordinate between 260 & 725 pixel
}
}
# endregion
public void generateRoutingTable()
{
/// Size of SNsNighbors Array = [node #, Nighbors #]
double D; // Euclidean distance
SNsNighbors = new int[NodeNum, NodeNum];
SinkNighbors = new int[NodeNum];
transmissionRange = Convert.ToInt32(TransRange.Text);
/// This Method estimate the Euclidean distance between SNs = (D)
/// Suppose that the transmission rane for all nodes = 150
/// if d <= Transmission Rang of SNi, SNi can communicate with SNj
for (int i = 0; i < NodeNum; i++) // For all SNs
for (int j = 0; j < NodeNum; j++) // For all SNs
{
if (i != j)
{
double Xn = SNsLocation[0, i]; // 0 for x - axis
double Yn = SNsLocation[1, i]; // 1 for y - axis
double Xs = SNsLocation[0, j]; // 0 for x - axis
double Ys = SNsLocation[1, j]; // 1 for y - axis
D = Math.Pow((Math.Pow(Xn - Xs, 2) + Math.Pow(Yn - Ys, 2)), 0.5);
// the transmission range is 150
if (D <= transmissionRange)
SNsNighbors[i, j] = 1; // SNj is nighbore for SNi
else
SNsNighbors[i, j] = 0; // SNj is NOT nighbore for SNi
}
else
SNsNighbors[i, j] = 0; // SNj is NOT nighbore for SNi
}
}
#endregion nodesDeployment
//***Paint Handlers***//
#region Paint handlers
private void topology_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Font font = new Font("Times New Roman", 7.0f); // choose the type of font and its size
StringFormat format = new StringFormat(); // declare string format
format.Alignment = StringAlignment.Center; // declare string alignment
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; // declare the quality for the drawings
Pen transmissionRangeColor = Pens.LightCyan; // the color used to draw the ellipse which repesents the transmission range for each node
Pen nodeNieghbors = Pens.LightSeaGreen; // the color used to draw the green lines between sensor nodes which indicates direct connection between nodes
Pen sinkNieghbors = Pens.Azure;
Brush nodeName = Brushes.White; // the color used for strings used to name the nodes
Brush auvSendMsg = Brushes.Red; // the color used for strings used to name the nodes
#region Display Sink
if (deploymentButtonWasClicked) // chech if the "Deploy" button was clicked
{
DrawImage("C:/Users/AMCT/Desktop/project/C#-Code-VisualStudio-2010/GAAPS/Sink.png", e.Graphics, sink.sinkX, sink.sinkY, 35, 45);
DrawString("Sink", e.Graphics, font, nodeName, new Point3D(600, 600 + 34, 233), 5);// Display the sink name
#region Draw Grid
topology2.Invalidate();
DrawGrid(numOfCells, cellSide, 800, e.Graphics);
DrawGrid(numOfCells, cellSide, 700, e.Graphics);
DrawGrid(numOfCells, cellSide, 600, e.Graphics);
DrawGrid(numOfCells, cellSide, 500, e.Graphics);
DrawGrid(numOfCells, cellSide, 400, e.Graphics);
for (int j = 0; j < rows; j++)
for (int i = 0; i < columns; i++)
{
DrawRectangle(e.Graphics, Brushes.SteelBlue, new Point3D(cellsCenters[0, i], cellsCenters[1, j], 800));
DrawRectangle(e.Graphics, Brushes.SteelBlue, new Point3D(cellsCenters[0, i], cellsCenters[1, j], 700));
DrawRectangle(e.Graphics, Brushes.SteelBlue, new Point3D(cellsCenters[0, i], cellsCenters[1, j], 600));
DrawRectangle(e.Graphics, Brushes.SteelBlue, new Point3D(cellsCenters[0, i], cellsCenters[1, j], 500));
DrawRectangle(e.Graphics, Brushes.SteelBlue, new Point3D(cellsCenters[0, i], cellsCenters[1, j], 400));
}
base.OnPaint(e);
#endregion
#region Display Sensor Nodes
/// node[0,i] means >> x-axis
/// node [1,i] means >> y-axis
for (int n = 0; n < NodeNum; n++)
{
DrawSensor(new Point3D(SNsLocation[0, n], SNsLocation[1, n], 760), new Point3D(SNsLocation[0, n], SNsLocation[1, n], SNs[n].snDepth), e.Graphics);
//DrawTransmissionRange(e.Graphics, transmissionRangeColor, new Point3D(SNsLocation[0, n],SNsLocation[1, n],SNs[n].snDepth), transmissionRange);
DrawString("SN" + (n + 1), e.Graphics, font, nodeName, new Point3D(SNsLocation[0, n] - 30, SNsLocation[1, n] - 10, SNs[n].snDepth), 12); // display node name
/*for (int i = 0; i < NodeNum - 1; i++)
{
if (SNsNighbors[n, i] == 1) // Green line between nieghbors
DrawLine(e.Graphics, nodeNieghbors, new Point3D(SNsLocation[0, n] + 5, SNsLocation[1, n] + 5, SNs[n].snDepth), new Point3D(SNsLocation[0, i] + 5, SNsLocation[1, i] + 5,SNs[i].snDepth));
}*/
}
#endregion
#region AUV-Animation
for (int i = 0; i < 4; i++)
{
DrawImage("C:/Users/AMCT/Desktop/project/C#-Code-VisualStudio-2010/GAAPS/AUVs-Icon.png", e.Graphics, auv[i].auvX, auv[i].auvY, 45, 20);
base.OnPaint(e);
}
}
#endregion
# endregion
// finish painting
}
/// <summary>
/// Draws a sensor at the specified position(s)
/// </summary>
private void DrawSensor(Point3D from, Point3D to, Graphics gr)
{
DrawLine(gr, Pens.Maroon, from, to);
DrawSphere(gr, Pens.Black, Brushes.Gold, to, 6);
}
/// <summary>
/// Draws a sensor at the specified position(s)
/// </summary>
private void DrawSendingSensor(Point3D from, Point3D to, Graphics gr)
{
DrawLine(gr, Pens.Maroon, from, to);
DrawSphere(gr, Pens.Black, Brushes.Black, to, 6);
}
/// <summary>
/// Draws a sphere as a Circle at the specified position
/// </summary>
private void DrawSphere(Graphics gr, Pen outline, Brush fill, Point3D center, float radius)
{
PointF center2D = Project(center);
gr.FillEllipse(fill, center2D.X - radius, center2D.Y - radius, radius * 2, radius * 2);
gr.DrawEllipse(outline, center2D.X - radius, center2D.Y - radius, radius * 2, radius * 2);
}
/// <summary>
/// Draws the grid at the specified depth
/// </summary>
private void DrawGrid(int numOfCells, int cellSize, int depth, Graphics gr)
{
Pen p = Pens.SteelBlue;
for (int i = 0; i < Math.Sqrt(numOfCells) + 1; i++)
{
// Vertical
DrawLine(gr, p, new Point3D(i * cellSize + 200, 200, depth), new Point3D(i * cellSize + 200, 700, depth));
// Horizontal
DrawLine(gr, p, new Point3D(200, i * cellSize + 200, depth), new Point3D(700, i * cellSize + 200, depth));
}
}
/// <summary>
/// Draws a line from one 3DPoint to another
/// </summary>
private void DrawLine(Graphics graphics, Pen pen, Point3D p1, Point3D p2)
{
PointF pointFrom = Project(p1);
PointF pointTo = Project(p2);
graphics.DrawLine(pen, pointFrom, pointTo);
}
/// <summary>
/// Draws a small Rectangle to represent the center point for each cell in the grid
/// </summary>
private void DrawRectangle(Graphics graphics, Brush brush, Point3D center)
{
PointF center2D = Project(center);
graphics.FillRectangle(brush, center2D.X, center2D.Y, 2, 2);
}
/// <summary>
/// Projects a Point3D to a PointF
/// </summary>
///
/// <summary>
/// Draws a string at the specified position
/// </summary>
private void DrawString(String s, Graphics gr, Font f, Brush fill, Point3D center, float radius)
{
PointF center2D = Project(center);
gr.DrawString(s, f, fill, center2D.X - radius, center2D.Y - radius);
}
/// <summary>
/// Draws a string at the specified position
/// </summary>
private void DrawImage(String path, Graphics gr, float x, float y, int rectX, int rectY)
{
gr.DrawImage(new Bitmap(path), new Rectangle((int)x, (int)y, rectX, rectY)); // draw AUV
}
/// <summary>
/// Draws a transmission range for each node at the specified position
/// </summary>
private void DrawTransmissionRange(Graphics gr, Pen color, Point3D center, int tRange)
{
PointF center2D = Project(center);
gr.DrawEllipse(color, center2D.X - (tRange / 2) + 5, center2D.Y - (tRange / 2) + 5, tRange, tRange); // draw the tranmission range of node
}
/// <summary>
/// Converts from 3D point to 2D point
/// </summary>
private PointF Project(Point3D p)
{
Perspective per = new Perspective();
return per.Project(p);
}
#endregion
#region Cells Center Points
public void calculateCellsCenters(int intialPointX, int intialPointY, int lastPointX, int lastPointY, int cells, int squareGridX, int squareGridY)
{
double diagonalLengthEachCell;
numOfCells = cells;
int netArea = squareGridX * squareGridY;
double cellArea = netArea / numOfCells;
FileStream fs = new FileStream("C:/Users/AMCT/Desktop/testPositions.txt", FileMode.Append, FileAccess.Write);
cellSide = (int)Math.Sqrt(cellArea);
int centerPointEachCell;
columnsXs = new int[columns + 1];
cellsCenters = new int[2, rows]; // 0 for the point on the x axis and 1 for the point on the y axis so this is why the first element of size 2
rowsYs = new int[rows + 1];
diagonalLengthEachCell = cellSide * Math.Sqrt(2);
centerPointEachCell = (int)diagonalLengthEachCell / 3;
columnsXs[0] = intialPointX; // to let the first point for the first column equal to 300 later on
//Calculate The Columns Points
for (int k = 1; k < (columns + 1); k++)
columnsXs[k] = columnsXs[k - 1] + cellSide;
rowsYs[0] = intialPointY; // its equal to 175 in our case to let the first pint for the first column equal to 200 later on
//Calculate The Rows Points
for (int s = 1; s < (rows + 1); s++)
rowsYs[s] = rowsYs[s - 1] + cellSide;
/***calculate-centers***/
using (StreamWriter sw = new StreamWriter(fs))
{
for (int i = 0; i < rows; i++)
{
cellsCenters[1, i] = rowsYs[i] + centerPointEachCell;
for (int j = 0; j < columns; j++)
{
cellsCenters[0, j] = columnsXs[j] + centerPointEachCell;
sw.Write("({0},{1}) ", cellsCenters[0, j], cellsCenters[1, i]);
}
sw.WriteLine();
}
}
}
#endregion
public void makeDrawing()
{
iSetupDisplay = 0;
if (iSetupDisplay != -1)
{
iSetupDisplay += 10;
if (iSetupDisplay >= topology2.Width)
iSetupDisplay = -1;
topology2.Refresh();
}
}
}
}
I used this method in the previous code to enable the drawing:
public void makeDrawing()
{
iSetupDisplay = 0;
if (iSetupDisplay != -1)
{
iSetupDisplay += 10;
if (iSetupDisplay >= topology2.Width)
iSetupDisplay = -1;
topology2.Refresh();
}
}
But I can't get the things painted on the picture box as I want! The following code is the code I use to make the projection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using AUVtopology;
namespace AUV_Topology
{
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Perspective
{
public float X_shift { get; set; }
public float Y_shift { get; set; }
public float X_x { get; set; }
public float X_y { get; set; }
public float X_z { get; set; }
public float Y_x { get; set; }
public float Y_y { get; set; }
public float Y_z { get; set; }
public Perspective()
{
this.X_shift = 420;
this.Y_shift = -400;
this.X_x = -0.4f;
this.X_y = 1.0f;
this.X_z = 0.0f;
this.Y_x = 0.4f;
this.Y_y = 0.0f;
this.Y_z = 1.0f;
}
public PointF Project(Form1.Point3D p)
{
return new PointF(X_shift + X_x * p.X + X_y * p.Y + X_z * p.Z, Y_shift + Y_x * p.X + Y_y * p.Y + Y_z * p.Z);
}
public PointF Project(Form2.Point3D p)
{
return new PointF(X_shift + X_x * p.X + X_y * p.Y + X_z * p.Z, Y_shift + Y_x * p.X + Y_y * p.Y + Y_z * p.Z);
}
}
public class PerspectiveGrid : Control
{
private Perspective _perspective;
public Perspective Perspective
{
get { return _perspective; }
set
{
_perspective = value;
Invalidate();
}
}
public PerspectiveGrid()
{
Perspective = new Perspective
{
X_shift = 420,
Y_shift = -400,
X_x = -0.4f,
X_y = 1.0f,
X_z = 0.0f,
Y_x = 0.4f,
Y_y = 0.0f,
Y_z = 1.0f,
};
}
}
}
Is the problem in the method that I use to enable drawing or something else?!
It's easy. You just need to get graphics context of the image box.
Graphics g = Graphics.FromImage(this.pictureBox1.Image);
After you do that, you use the "g" in my example to do any line drawing, etc that you want to do. Not that this will still require you to invalidate the picture box after drawing to it, but you don't have to have your drawing code in
Form_Paint, and you don't need to mess with buffering settings. Personally i prefer this method to drawing in the Form_paint since it is persistent and doesn't have to be redrawn every frame (manually).
To prove it works:
I need to fill a rectangle with a black to white (transparent) gradient. However, I could only find a GradientBrush class and all examples I found showed smooth transition and I want sharp bars. That's what I need:
You need to average the colors between your start color and your end color. Here is a routine that does all that, using an averaging formula found here: Generate Color Gradient in C#
private void PaintGradientBars(Graphics g, Rectangle r,
Color startColor, Color endColor, int numBars) {
int rMin = startColor.R;
int gMin = startColor.G;
int bMin = startColor.B;
int rMax = endColor.R;
int gMax = endColor.G;
int bMax = endColor.B;
int left = 0;
for (int i = 0; i < numBars; i++) {
int rAvg = rMin + (int)((rMax - rMin) * i / numBars);
int gAvg = gMin + (int)((gMax - gMin) * i / numBars);
int bAvg = bMin + (int)((bMax - bMin) * i / numBars);
Color useColor = Color.FromArgb(rAvg, gAvg, bAvg);
int width = (r.Width - left) / (numBars - i);
using (SolidBrush br = new SolidBrush(useColor)) {
g.FillRectangle(br, new Rectangle(left, 0, width, r.Height));
}
left += width;
}
}
Then you make a simple call:
private void panel1_Paint(object sender, PaintEventArgs e) {
PaintGradientBars(e.Graphics, panel1.ClientRectangle,
Color.Blue, Color.Green, 5);
}
Resulting in:
in this code i use picturebox, play with 'k' and 'i'
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
int k = 20;
Color mycolor = new Color();
for (int i = 0; i < 10; i++)
{
mycolor = Color.FromArgb(i * k, i * k, i * k);
SolidBrush mybrash = new SolidBrush(mycolor);
e.Graphics.FillRectangle((Brush)mybrash, 0 + i * k, 0, k, k);
}
}
Good luck!