what i got when i run it
here's my code i take input from user to draw line using brenesham but it just draw horizontal line even when i tried with many values i have same issue so i want it to draw line with angel as i saw in my tutorials where they implement it with angles not just horizontal angel
private void button2_Click(object sender, EventArgs e)
{
int x1 = Convert.ToInt32(textBox5.Text);
int y1 = Convert.ToInt32(textBox6.Text);
int x2 = Convert.ToInt32(textBox7.Text);
int y2 = Convert.ToInt32(textBox8.Text);
Point p1 = new Point(x1, y1);
Point p2 = new Point(x2, y2);
Bresenham_Line(p1, p2);
}
private void Bresenham_Line(Point p1, Point p2)
{
double x, y, x2, y2;
Bitmap pp = new Bitmap(this.Width, this.Height);
double dx = p2.X - p1.X;
double dy = p2.Y - p2.Y;
double p = 2 * (dy - dx);
double c1 = 2 * dy;
double c2 = 2 * (dy - dx);
x = p1.X; y = p1.Y;
pp.SetPixel((int)x, (int)y, Color.Blue);
x2 = p2.X; y2 = p2.Y;
while (x < x2)
{
if (p < 0)
{
p += c1;
}
else
{
p += c2;
y += 1;
}
x++;
pp.SetPixel((int)x, (int)y, Color.Black);
}
pictureBox1.Image = pp;
}
i added photo from what i get when i run it
I am using the following code to calculate points for a circle arc drawn with a Line Renderer.
for (int i = 0; i <= pts; i++)
{
float x = center.x + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
float y = center.y + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
arcLine.positionCount = i + 1;
arcLine.SetPosition(i, new Vector2(x, y));
ang += (float)totalAngle / pts;
}
How can I change the angle ang to create a reflected arc along the line P1P2 as in the image below?
Please note that totalAngle represents the portion of the circle that is to be drawn between 0 and 360.
I'm not entirely sure that's possible, but I've come up with another way that works like this:
First, a helper function:
Vector2 GetPosition (float radius, float angle)
{
angle *= Mathf.Deg2Rad;
return new Vector2
{
x = radius * Mathf.Cos(angle),
y = radius * Mathf.Sin(angle)
};
}
Then, compute positions p1 and p2:
var p1 = GetPosition(radius, ang);
var p2 = GetPosition(radius, totalAngle);
To derive the mid-point p3:
var p3 = (p1 + p2) * 0.5f;
And finally rotate the original point about p3 to obtain the reflected point:
var pos = p3 * 2f - GetPosition(radius, ang);
And that's it! Your code should look something like this:
void Draw ()
{
var p1 = GetPosition(radius, ang);
var p2 = GetPosition(radius, totalAngle);
var p3 = (p1 + p2) * 0.5f;
for (int i = 0; i <= pts; i++)
{
var pos = p3 * 2f - GetPosition(radius, ang);
arcLine.positionCount = i + 1;
arcLine.SetPosition(i, center + pos);
ang += totalAngle / pts;
}
}
Vector2 GetPosition (float radius, float angle)
{
angle *= Mathf.Deg2Rad;
return new Vector2
{
x = radius * Mathf.Cos(angle),
y = radius * Mathf.Sin(angle)
};
}
Here's it in action:
I have a C# bitmap object, and i am able to draw a line from point A to point B.
I have the 2 points on the edges of the diagram, and I would like to draw an ellipse from A to B. The basic g.DrawEllipse() only draws ellipses either perfectly horizontally or vertically, however I need the ellipse to be kind of diagonal from the one end of the image to the other.
My bitmap: 200 tall by 500 wide
Point A: Column 0, Row 20 (0,20)
Point B: Column 499, Row 60 (499, 60)
Widest Point: 30 - Narrow Radius of the ellipse
Here is what I have so far, the draw ellipse doesnt have the overload I need, so help there please:
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawLine(pen, new Point(20,0), new Point(499,60));
g.DrawEllipse(pen, 20, 0, someWidth, someHeight);
}
Here is how to use the DrawEllipse method from a rotation, the minor axis and two vertices.
First we calculate the Size of the bounding Rectangle:
Given the Points A and B sitting on the short sides of length smallSize we get the long side with a little Pythagoras:
int longSide = (int)(Math.Sqrt((A.Y - B.Y) * (A.Y - B.Y) + (B.X - A.X) * (B.X - A.X)));
So :
Size size = new System.Drawing.Size(longSide, smallSize);
Next we need the rotation angle:
float angle = -(float)(Math.Atan2(A.Y - B.Y, B.X - A.X) * 180f / Math.PI);
And it will make things easier to also get the center Point C:
Point C = new Point((A.X + B.X)/ 2, (A.Y + B.Y)/ 2);
The last thing we want is a routine that draws an ellipse of a given Size, rotated around C at an angle:
void DrawEllipse(Graphics G, Pen pen, Point center, Size size, float angle)
{
int h2 = size.Height / 2;
int w2 = size.Width / 2;
Rectangle rect = new Rectangle( new Point(center.X - w2, center.Y - h2), size );
G.TranslateTransform(center.X, center.Y);
G.RotateTransform(angle);
G.TranslateTransform(-center.X, -center.Y);
G.DrawEllipse(pen, rect);
G.ResetTransform();
}
Here is a little testbed that brings it all together:
Point A = new Point(200, 200); // *
Point B = new Point(500, 250);
int smallSize = 50;
void doTheDraw(PictureBox pb)
{
Bitmap bmp = new Bitmap(pb.Width, pb.Height);
float angle = -(float)(Math.Atan2(A.Y - B.Y, B.X - A.X) * 180f / Math.PI);
int longSide = (int)(Math.Sqrt((A.Y - B.Y) * (A.Y - B.Y) + (B.X - A.X) * (B.X - A.X)));
Point C = new Point((A.X + B.X) / 2, (A.Y + B.Y) / 2);
Size size = new System.Drawing.Size((int)longSide, smallSize);
using (Pen pen = new Pen(Color.Orange, 3f))
using (Graphics g = Graphics.FromImage(bmp))
{
// a nice background grid (optional):
DrawGrid(g, 0, 0, 100, 50, 10,
Color.LightSlateGray, Color.DarkGray, Color.Gainsboro);
// show the points we use (optional):
g.FillEllipse(Brushes.Red, A.X - 4, A.Y - 4, 8, 8);
g.FillRectangle(Brushes.Red, B.X - 3, B.Y - 3, 7, 7);
g.FillEllipse(Brushes.Red, C.X - 5, C.Y - 5, 11, 11);
// show the connection line (optional):
g.DrawLine(Pens.Orange, A, B);
// here comes the ellipse:
DrawEllipse(g, pen, C, size, angle);
}
pb.Image = bmp;
}
The grid is a nice helper:
void DrawGrid(Graphics G, int ox, int oy,
int major, int medium, int minor, Color c1, Color c2, Color c3)
{
using (Pen pen1 = new Pen(c1, 1f))
using (Pen pen2 = new Pen(c2, 1f))
using (Pen pen3 = new Pen(c3, 1f))
{
pen2.DashStyle = DashStyle.Dash;
pen3.DashStyle = DashStyle.Dot;
for (int x = ox; x < G.VisibleClipBounds.Width; x += major)
G.DrawLine(pen1, x, 0, x, G.VisibleClipBounds.Height);
for (int y = oy; y < G.VisibleClipBounds.Height; y += major)
G.DrawLine(pen1, 0, y, G.VisibleClipBounds.Width, y);
for (int x = ox; x < G.VisibleClipBounds.Width; x += medium)
G.DrawLine(pen2, x, 0, x, G.VisibleClipBounds.Height);
for (int y = oy; y < G.VisibleClipBounds.Height; y += medium)
G.DrawLine(pen2, 0, y, G.VisibleClipBounds.Width, y);
for (int x = ox; x < G.VisibleClipBounds.Width; x += minor)
G.DrawLine(pen3, x, 0, x, G.VisibleClipBounds.Height);
for (int y = oy; y < G.VisibleClipBounds.Height; y += minor)
G.DrawLine(pen3, 0, y, G.VisibleClipBounds.Width, y);
}
}
Note that I made A, B, smallSide class level variables so I can modify them during my tests, (and I did *)..
As you can see I have added a TrackBar to make the smallside dynamic; for even more fun I have added this MouseClick event:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button.HasFlag(MouseButtons.Left)) A = e.Location;
else B = e.Location;
doTheDraw(pictureBox1);
}
Note that I didn't care for disposing of the old Bitmap; you should, of course..!
If you wish to use Graphics to create a diagonal ellipse, perhaps you can use DrawBezier() method.
Here is some code that does it:
// Draws an ellipse using 2 beziers.
private void DrawEllipse(Graphics g, PointF center, float width, float height, double rotation)
{
// Unrotated ellipse frame
float left = center.X - width / 2;
float right = center.X + width / 2;
float top = center.Y - height / 2;
float bottom = center.Y + height / 2;
PointF p1 = new PointF(left, center.Y);
PointF p2 = new PointF(left, top);
PointF p3 = new PointF(right, top);
PointF p4 = new PointF(right, center.Y);
PointF p5 = new PointF(right, bottom);
PointF p6 = new PointF(left, bottom);
// Draw ellipse with rotated points.
g.DrawBezier(Pens.Black, Rotate(p1, center, rotation), Rotate(p2, center, rotation), Rotate(p3, center, rotation), Rotate(p4, center, rotation));
g.DrawBezier(Pens.Black, Rotate(p4, center, rotation), Rotate(p5, center, rotation), Rotate(p6, center, rotation), Rotate(p1, center, rotation));
}
// Rotating a given point by given angel around a given pivot.
private PointF Rotate(PointF point, PointF pivot, double angle)
{
float x = point.X - pivot.X;
float y = point.Y - pivot.Y;
double a = Math.Atan(y / x);
if (x < 0)
{
a += Math.PI;
}
float size = (float)Math.Sqrt(x * x + y * y);
double newAngel = a + angle;
float newX = ((float)Math.Cos(newAngel) * size);
float newY = ((float)Math.Sin(newAngel) * size);
return pivot + new SizeF(newX, newY);
}
The above code computes the frame of the ellipse (proir to the rotation) at points p1, p2, ..., p6. And then, draws the ellipse as 2 beziers with the ellipse frame rotated points.
Imagagine I have a polygon like the following:
I am looking for a C# algorithm with whom I can find a point (could be the middlepoint or also a random point) inside any polygon.
For finding the center of mass I used the following algorithm:
private Point3d GetPolyLineCentroid(DBObject pObject, double pImageWidth, double pImageHeight)
{
Point2d[] pointArray = GetPointArrayOfRoomPolygon(pObject);
double centroidX = 0.0;
double centroidY = 0.0;
double signedArea = 0.0;
double x0 = 0.0; // Current vertex X
double y0 = 0.0; // Current vertex Y
double x1 = 0.0; // Next vertex X
double y1 = 0.0; // Next vertex Y
double a = 0.0; // Partial signed area
int i = 0;
for (i = 0; i < pointArray.Length - 1; ++i)
{
x0 = pointArray[i].X;
y0 = pointArray[i].Y;
x1 = pointArray[i + 1].X;
y1 = pointArray[i + 1].Y;
a = x0 * y1 - x1 * y0;
signedArea += a;
centroidX += (x0 + x1) * a;
centroidY += (y0 + y1) * a;
}
x0 = pointArray[i].X;
y0 = pointArray[i].Y;
x1 = pointArray[0].X;
y1 = pointArray[0].Y;
a = x0 * y1 - x1 * y0;
signedArea += a;
centroidX += (x0 + x1) * a;
centroidY += (y0 + y1) * a;
signedArea *= 0.5;
centroidX /= (6.0 * signedArea);
centroidY /= (6.0 * signedArea);
Point3d centroid = new Point3d(centroidX, centroidY, 0);
return centroid;
}
This works good with polygones like this:
But if my polygon has the form of a C or something like that this algorithmn does not work because the center off mass is outside the polygon.
Does anyone has an idea how to get always points inside any polygon?
You can use polygon triangulation to break your polygon apart into triangles.
One such algorithm is demonstrated using c# in this CodeProject article.
Once you have triangles, finding arbitrary points that lie within the triangle is easy. Any barycentric coordinate with a sum of 1.0 multiplied by the vertices of the triangle will give you a point inside the triangle.
The center can be derived using the barycentric coordinate [0.333333, 0.333333, 0.333333] :
float centerX = A.x * 0.333333 + B.x * 0.333333 + C.x * 0.3333333;
float centerY = A.y * 0.333333 + B.y * 0.333333 + C.y * 0.3333333;
or more simply:
float centerX = (A.x + B.x + C.x) / 3f;
float centerY = (A.y + B.y + C.y) / 3f;
Use This:
private Point getCentroid(pointArray)
{
double centroidX = 0.0;
double centroidY = 0.0;
for (int i = 0; i < pointArray.Length; i++)
{
centroidX += pointArray[i].X;
centroidY += pointArray[i].Y;`
}
centroidX /= pointArray.Length;
centroidY /= pointArray.Length;
return(new Point(centroidX ,centroidY));
}
this code is just to find Center of Mass of Polygon. To check whether a point is inside or outside polygon check this link http://bbs.dartmouth.edu/~fangq/MATH/download/source/Determining%20if%20a%20point%20lies%20on%20the%20interior%20of%20a%20polygon.htm
I'm trying to generate a set of points (represented by a Vector struct) that roughly models a spiral galaxy.
The C# code I've been playing with is below; but I can only seem to get it to generate a single 'arm' of the galaxy.
public Vector3[] GenerateArm(int numOfStars, int numOfArms, float rotation)
{
Vector3[] result = new Vector3[numOfStars];
Random r = new Random();
float fArmAngle = (float)((360 / numOfArms) % 360);
float fAngularSpread = 180 / (numOfArms * 2);
for (int i = 0; i < numOfStars; i++)
{
float fR = (float)r.NextDouble() * 64.0f;
float fQ = ((float)r.NextDouble() * fAngularSpread) * 1;
float fK = 1;
float fA = ((float)r.NextDouble() % numOfArms) * fArmAngle;
float fX = fR * (float)Math.Cos((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
float fY = fR * (float)Math.Sin((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
float resultX = (float)(fX * Math.Cos(rotation) - fY * Math.Sin(rotation));
float resultY = (float)(fY * Math.Cos(rotation) - fX * Math.Sin(rotation));
result[i] = new Vector3(resultX, resultY, 1.0f);
}
return result;
}
Check this. It's a simulation of galaxy using density wave theory. Code is available.
http://beltoforion.de/galaxy/galaxy_en.html
I liked this idea so much i had to play around with it on my own and here is my result.
Note that i used PointF instead of Vector3, but you should be able to search and replace and add , 0) in a few places.
PointF[] points;
private void Render(Graphics g, int width, int height)
{
using (Brush brush = new SolidBrush(Color.FromArgb(20, 150, 200, 255)))
{
g.Clear(Color.Black);
foreach (PointF point in points)
{
Point screenPoint = new Point((int)(point.X * (float)width), (int)(point.Y * (float)height));
screenPoint.Offset(new Point(-2, -2));
g.FillRectangle(brush, new Rectangle(screenPoint, new Size(4, 4)));
}
g.Flush();
}
}
public PointF[] GenerateGalaxy(int numOfStars, int numOfArms, float spin, double armSpread, double starsAtCenterRatio)
{
List<PointF> result = new List<PointF>(numOfStars);
for (int i = 0; i < numOfArms; i++)
{
result.AddRange(GenerateArm(numOfStars / numOfArms, (float)i / (float)numOfArms, spin, armSpread, starsAtCenterRatio));
}
return result.ToArray();
}
public PointF[] GenerateArm(int numOfStars, float rotation, float spin, double armSpread, double starsAtCenterRatio)
{
PointF[] result = new PointF[numOfStars];
Random r = new Random();
for (int i = 0; i < numOfStars; i++)
{
double part = (double)i / (double)numOfStars;
part = Math.Pow(part, starsAtCenterRatio);
float distanceFromCenter = (float)part;
double position = (part * spin + rotation) * Math.PI * 2;
double xFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
double yFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
float resultX = (float)Math.Cos(position) * distanceFromCenter / 2 + 0.5f + (float)xFluctuation;
float resultY = (float)Math.Sin(position) * distanceFromCenter / 2 + 0.5f + (float)yFluctuation;
result[i] = new PointF(resultX, resultY);
}
return result;
}
public static double Pow3Constrained(double x)
{
double value = Math.Pow(x - 0.5, 3) * 4 + 0.5d;
return Math.Max(Math.Min(1, value), 0);
}
Example:
points = GenerateGalaxy(80000, 2, 3f, 0.1d, 3);
Result:
I would abstract that function out into a createArm function.
Then you can store each arm as its own galaxy (temporarily).
So if you want 2 arms, do 2 galaxies of 5000. Then, rotate one of them 0 degrees around the origin (so doesn't move) and the other 180 degrees around the origin.
With this you can do an arbitrary number of arms by using different rotation amounts. You could even add some "naturalization" to it by making the rotation distance more random, like with a range instead of straight (360 / n). For example, 5 arms would be 0, 72, 144, 216, 288. But with some randomization you could make it 0, 70, 146, 225, 301.
Edit:
Some quick google-fu tells me (source)
q = initial angle, f = angle of rotation.
x = r cos q
y = r sin q
x' = r cos ( q + f ) = r cos q cos f - r sin q sin f
y' = r sin ( q + w ) = r sin q cos f + r cos q sin f
hence:
x' = x cos f - y sin f
y' = y cos f + x sin f