Generating a nebula cloud in circle [duplicate] - c#

This question already has answers here:
Generate a random point within a circle (uniformly)
(22 answers)
Closed 8 years ago.
I'm trying to generate a nebula cloud in a specified radius around a Vector2 (Point).
Currently I'm using this code
public static Vector2 GeneratePosition(Vector2 position, float radius)
{
float X = GenerateScaleFloat() * (GenerateInt(2) == 1 ? 1 : -1);
float Y = GenerateInt((int)(radius * -(1 - Math.Abs(X))),
(int)(radius * (1 - Math.Abs(X)))) / radius;
X *= radius;
Y *= radius;
return new Vector2(X, Y);
}
which gives me this result:
(Origin: 0;0, Radius: 300, Particles: 5000)
It looks to me like my code is generating a rotated square. How can I make it generate the positions of the particles in (and within) a more circular pattern?
GenerateScaleFloat: Returns a value between 0.0 and 1.0
GenerateInt: The standard rand.Next
EDIT:
This post has now been flagged as duplicate, which was not my intention. I will however leave my answer here for other googlers to find since I know how helpful it is:
New code:
public static Vector2 GeneratePosition(Vector2 position, float radius)
{
float X = GenerateScaleFloat() * (GenerateInt(2) == 1 ? 1 : -1) * radius;
float Y = float.PositiveInfinity;
while(Y > Math.Sqrt(Math.Pow(radius, 2) - Math.Pow(X, 2))
|| Y < -Math.Sqrt(Math.Pow(radius, 2) - Math.Pow(X, 2)))
{
Y = GenerateScaleFloat() * (GenerateInt(2) == 1 ? 1 : -1) * radius;
}
return new Vector2(X, Y) + position;
}
New output: (Origin: 0;0, Radius 100, Particles: 5000)
Hope it'll help somebody else

The formula for a circle area is
x^2 + y^2 <= r^2
Given a x you can calculate y like this
y <= +/-sqrt( r^2 - x^2 )
By applying different scaling factors to the axis you can create an ellipse.
Another possibility is to generate points in a rectangle and look if they are within the ellipse:
a = width / 2
b = height / 2
(x/a)^2 + (y/b)^2 <= 1 Where the ellipse will be centered on
the origin of the coordinate system.
This might generate more evenly distributed points.
EDIT: You can improve your new code. Instead of comparing ...
y > Sqrt(r^2 - x^2) OR y < -Sqrt(r^2 - x^2)
... you can compare
y^2 > r^2 - x^2
y^2 is always positive since minus times minus is plus. It is often worth transforming an otherwise correct mathematical correct formula in order to make it more efficient for the computer. Calculating a square root is expensive, Math.Pow as well.
Also the generation of Y values between -1 and plus +1 can be achieved in an easier way by first generating a random number between 0 and 1, multiplying it by twice the radius and finally subtracting the radius.
float y2max = radius * radius - X * X;
do {
Y = 2 * radius * GenerateScaleFloat() - radius;
} while (Y * Y > y2max);

Related

C# intersect a line bettween 2 Vector3 point on a plane

I have a line going bettween two Vector3 points and I want to find when the line is intersected at a height along the Z axis.
I am trying to write a function to calculate the intersection point.
void Main()
{
Vector3 A = new Vector3(2.0f, 2.0f, 2.0f);
Vector3 B = new Vector3(7.0f, 10.0f, 6.0f);
float Z = 3.0f;
Vector3 C = getIntersectingPoint(A, B, Z);
//C should be X=3.25, Y=4.0, Z=3.0
}
But trying to figure out how to do the math to handle possible negative numbers correctly is really starting to confuse me.
This is what I have and the moment, but this isn't correct.
public static Vector3 getIntersectingPoint(Vector3 A, Vector3 B, float Z)
{
// Assume z is bettween A and B and we don't need to validate
// Get ratio of triangle hight, height Z divided by (Za to Zb)
("absolute value: " + Math.Abs(A.Z-B.Z)).Dump();
("z offset: " + (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))).Dump();
float ratio = (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))/Math.Abs(A.Z-B.Z);
("ratio: " + ratio.ToString()).Dump();
float difX = ratio*Math.Abs(A.X-B.X);//this still needs to be added to or taken from the zero point offset
("difX: " + difX.ToString()).Dump();
float difY = ratio*Math.Abs(A.Y-B.Y);//this still needs to be added to or taken from the zero point offset
("difY: " + difY.ToString()).Dump();
float X = difX + (A.X<B.X?A.X:B.X);
("X: " + X).Dump();
float Y = difY + (A.Y<B.Y?A.Y:B.Y);
("Y: " + Y).Dump();
return new Vector3(X,Y,Z);
}
Does anyone know if there are any Math libraries that will already do this or examples that show how to do this that I can follow?
You have the starting (2.0f) and ending (6.0f) Z coordinates. The Z distance between the two points is 4.0f. You want to know the X and Y coordinates at the point where Z is 3.0f.
Remember that Z changes linearly along the segment. The segment is 4 units long, The point you're interested in is 1 unit from the start, or 1/4 of the length of the segment.
The X distance of the entire segment is 7.0 - 2.0, or 5 units. 1/4 of 5 is 1.25, so the X coordinate at the intersection is 3.25.
The Y distance of the entire segment is 8. 1/4 of 8 is 2. So the Y coordinate of the intersection point is 6.0.
The intersection point is (3.25f, 6.0f, 3.0f).
How to compute:
// start is the starting point
// end is the ending point
// target is the point you're looking for.
// It's pre-filled with the Z coordinate.
zDist = Math.Abs(end.z - start.z);
zDiff = Math.Abs(target.z - start.z);
ratio = zDiff / zDist;
xDist = Math.Abs(end.x - start.x);
xDiff = xDist * ratio;
xSign = (start.x < end.x) ? 1 : -1;
target.x = start.x + (xDiff * xSign);
yDist = Math.Abs(end.y - start.y);
yDiff = yDist * ratio;
ySign = (start.y < end.y) ? 1 : -1;
target.y = start.y + (yDiff * ySign);
Come to think of it, the whole sign thing shouldn't be necessary. Consider this, when end.x = 10 and start.x = 18:
xDist = end.x - start.x; // xDist = -8
xDiff = xDist * ratio; // xDiff = -2
target.x = start.x + xDiff; // target.x = 18 + (-2) = 16
Yeah, no need for sign silliness.
Also no need for the calls to Math.Abs when computing the ratio. We know that zDist and zDiff will both have the same sign, so ratio will always be positive.

Filling closed shapes in XNA

I need to render a 2D image in which the axises are latitude (φ) representing the X-axis and longitude (λ) for Y-axis. Assuming the viewpoint is always at the origin(0,0,0) then a 3D line segment in Cartesian coordinate is a 2D curve segment in this image. Here each point along the curve represents φ and λ angles. Having a 3D line segment from P1 to P2, and knowing the equation of the corresponding 2D curve segment, λ= f(φ), the curve can be drawn from φ1 to φ2. Three lines make a triangle. Therefore a triangle is drawn as three curve segments which makes a closed shape.
The problem is that this shape is drawn like in wire-frame mode and the enclosed area is not filled. I can't think of any way to somehow fill in the area. Is it possible to achieve this? I appreciate any help and like to discuses it with other. Thanks
*Edit:
This cube has been drawn in Autocad:
The equation for a 3D line from P1(x1,y1,z1) to P2(x2,y2,z2) is:
(x-x1)/(x2-x1) = (y-y1)/(y2-y1) = (z-z1)/(z2-z1)
And This image(with latitude(φ) and longitude(λ) as axises) shows the same cube viewed from the origin:
The equation that gives λ along a 2D curved from φ1 to φ2(calculated from P1 and P2) is gained in this way:
λ= f(φ) = Atan((u/tan(φ)+z1)/ Sqrt((u/tan(φ)^2 + ((u/tan(φ))*w + y1)^2 ))
u and w are constants and are calculated thought P1 and P2 coordinates.
Here is the code for the above equation:
for (double tetha = φ1; tetha <= φ2; tetha += step){
double a = p1.X - p0.X;
double b = p1.Y - p0.Y;
double c = p1.Z - p0.Z;
double x = (a * p0.Y - b * p0.X) / (a * Math.Tan(tetha) - b);
double z = (((x - p0.X) * c) / a) + p0.Z;
double y = (((x - p0.X) * b) / a) + p0.Y;
if (a == 0)
{
y = (Math.Tan(tetha) * (b * p0.X - a * p0.Y)) / (b - a * Math.Tan(tetha));
z = (((y - p0.Y) * c) / b) + p0.Z;
x = (((y - p0.Y) * a) / b) + p0.X;
}
double landa = Math.Atan2(z, Math.Sqrt(x * x + y * y));
}

How to detect if the line intersects in C#?

I want to add additional feature of my project in C#, I can already draw lines in my program but I want to detect INTERSECTING LINES of a one line drawn and display the point they've intersect. Is it possible? Thank you
My program also includes computing for Perpendicular Distance, here is the sample code:
public static Double PerpendicularDistance(Point Point1, Point Point2, Point Point)
{
Double area = Math.Abs(.5 * (Point1.X * Point2.Y + Point2.X * Point.Y + Point.X * Point1.Y - Point2.X * Point1.Y - Point.X * Point2.Y - Point1.X * Point.Y));
Double bottom = Math.Sqrt(Math.Pow(Point1.X - Point2.X, 2) + Math.Pow(Point1.Y - Point2.Y, 2));
Double height = area / bottom * 2;
return height;
}
}
The POINT here is a class for my X and Y coordinates.
If you are trying to find the intersection of two line, then the solution is fairly trivial.
If the two line are in the form Ax + By = C:
float delta = a1*b2 - a2*b1;
if(delta == 0)
throw new ArgumentException("Lines are parallel");
float x = (b2*c1 - b1*c2)/delta;
float y = (a1*c2 - a2*c1)/delta;
My concern is comment above that says there is only one drawn line. I'm not sure what you mean. Does it mean that the app provides one line and the user the other, or are we dealing in curved lines where the line intersects itself?

Calculate coordinates of a regular polygon's vertices

I am writing a program in which I need to draw polygons of an arbitrary number of sides, each one being translated by a given formula which changes dynamically. There is some rather interesting mathematics involved but I am stuck on this probelm.
How can I calculate the coordinates of the vertices of a regular polygon (one in which all angles are equal), given only the number of sides, and ideally (but not neccessarily) having the origin at the centre?
For example: a hexagon might have the following points (all are floats):
( 1.5 , 0.5 *Math.Sqrt(3) )
( 0 , 1 *Math.Sqrt(3) )
(-1.5 , 0.5 *Math.Sqrt(3) )
(-1.5 , -0.5 *Math.Sqrt(3) )
( 0 , -1 *Math.Sqrt(3) )
( 1.5 , -0.5 *Math.Sqrt(3) )
My method looks like this:
void InitPolygonVertexCoords(RegularPolygon poly)
and the coordinates need to be added to this (or something similar, like a list):
Point[] _polygonVertexPoints;
I'm interested mainly in the algorithm here but examples in C# would be useful. I don't even know where to start. How should I implement it? Is it even possible?!
Thank you.
for (i = 0; i < n; i++) {
printf("%f %f\n",r * Math.cos(2 * Math.PI * i / n), r * Math.sin(2 * Math.PI * i / n));
}
where r is the radius of the circumsribing circle. Sorry for the wrong language No Habla C#.
Basically the angle between any two vertices is 2 pi / n and all the vertices are at distance r from the origin.
EDIT:
If you want to have the center somewher other than the origin, say at (x,y)
for (i = 0; i < n; i++) {
printf("%f %f\n",x + r * Math.cos(2 * Math.PI * i / n), y + r * Math.sin(2 * Math.PI * i / n));
}
The number of points equals the number of sides.
The angle you need is angle = 2 * pi / numPoints.
Then starting vertically above the origin with the size of the polygon being given by radius:
for (int i = 0; i < numPoints; i++)
{
x = centreX + radius * sin(i * angle);
y = centreY + radius * cos(i * angle);
}
If your centre is the origin then simply ignore the centreX and centreY terms as they'll be 0,0.
Swapping the cos and sin over will point the first point horizontally to the right of the origin.
Sorry, I dont have a full solution at hand right now, but you should try looking for 2D-Rendering of Circles. All classic implementations of circle(x,y,r) use a polygon like you described for drawing (but with 50+ sides).
Say the distance of the vertices to the origin is 1. And say (1, 0) is always a coordinate of the polygon.
Given the number of vertices (say n), the rotation angle required to position the (1, 0) to the next coordinate would be (360/n).
The computation required here is to rotate the coordinates. Here is what it is; Rotation Matrix.
Say theta = 360/n;
[cos(theta) -sin(theta)]
[sin(theta) cos(theta)]
would be your rotation matrix.
If you know linear algebra you already know what i mean. If dont just have a look at Matrix Multiplication
One possible implementation to generate a set of coordinates for regular polygon is to:
Define polygon center, radius and first vertex1. Rotate the vertex n-times2 at an angle of: 360/n.
In this implementation I use a vector to store the generated coordinates and a recursive function to generate them:
void generateRegularPolygon(vector<Point>& v, Point& center, int sidesNumber, int radius){
// converted to radians
double angRads = 2 * PI / double(sidesNumber);
// first vertex
Point initial(center.x, center.y - radius);
rotateCoordinate(v, center, initial, angRads, sidesNumber);
}
where:
void rotateCoordinate(vector<Point>& v, Point& axisOfRotation, Point& initial, double angRads, int numberOfRotations){
// base case: number of transformations < 0
if(numberOfRotations <= 0) return;
else{
// apply rotation to: initial, around pivot point: axisOfRotation
double x = cos(angRads) * (initial.x - axisOfRotation.x) - sin(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.x;
double y = sin(angRads) * (initial.x - axisOfRotation.x) + cos(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.y;
// store the result
v.push_back(Point(x, y));
rotateCoordinate(v, axisOfRotation, Point(x,y), angRads, --numberOfRotations);
}
}
Note:
Point is a simple class to wrap the coordinate into single data structure:
class Point{
public:
Point(): x(0), y(0){ }
Point(int xx, int yy): x(xx), y(yy) { }
private:
int x;
int y;
};
1 in terms of (relative to) the center, radius. In my case the first vertex is translated from the centre up horizontally by the radius lenght.
2 n-regular polygon has n vertices.
The simple method is:
Let's take N-gone(number of sides) and length of side L. The angle will be T = 360/N.
Let's say one vertices is located on origin.
* First vertex = (0,0)
* Second vertex = (LcosT,LsinT)
* Third vertex = (LcosT+Lcos2T, LsinT+Lsin2T)
* Fourth vertex = (LcosT+Lcos2T+Lcos3T, LsinT+Lsin2T+Lsin3T)
You can do in for loop
hmm if you test all the versions that are listed here you'll see that the implementation is not good. you can check the distance from the center to each generated point of the polygon with : http://www.movable-type.co.uk/scripts/latlong.html
Now i have searched a lot and i could not find any good implementation for calculating a polyogon using the center and the radius...so i went back to the math book and tried to implement it myself. In the end i came up with this...wich is 100% good:
List<double[]> coordinates = new List<double[]>();
#region create Polygon Coordinates
if (!string.IsNullOrWhiteSpace(bus.Latitude) && !string.IsNullOrWhiteSpace(bus.Longitude) && !string.IsNullOrWhiteSpace(bus.ListingRadius))
{
double lat = DegreeToRadian(Double.Parse(bus.Latitude));
double lon = DegreeToRadian(Double.Parse(bus.Longitude));
double dist = Double.Parse(bus.ListingRadius);
double angle = 36;
for (double i = 0; i <= 360; i += angle)
{
var bearing = DegreeToRadian(i);
var lat2 = Math.Asin(Math.Sin(lat) * Math.Cos(dist / earthRadius) + Math.Cos(lat) * Math.Sin(dist / earthRadius) * Math.Cos(bearing));
var lon2 = lon + Math.Atan2(Math.Sin(bearing) * Math.Sin(dist / earthRadius) * Math.Cos(lat),Math.Cos(dist / earthRadius) - Math.Sin(lat) * Math.Sin(lat2));
coordinates.Add(new double[] { RadianToDegree(lat2), RadianToDegree(lon2) });
}
poly.Coordinates = new[] { coordinates.ToArray() };
}
#endregion
If you test this you'll see that all the points are at the exact distance that you give ( radius ). Also don't forget to declare the earthRadius.
private const double earthRadius = 6371.01;
This calculates the coordinates of a decagon. You see the angle used is 36 degrees. You can split 360 degrees to any number of sides that you want and put the result in the angle variable.
Anyway .. i hope this helps you #rmx!

Shorten a line by a number of pixels

I'm drawing a custom diagram of business objects using .NET GDI+. Among other things, the diagram consists of several lines that are connecting the objects.
In a particular scenario, I need to shorten a line by a specific number of pixels, let's say 10 pixels, i.e. find the point on the line that lies 10 pixels before the end point of the line.
Imagine a circle with radius r = 10 pixels, and a line with start point (x1, y1) and end point (x2, y2). The circle is centered at the end point of the line, as in the following illustration.
How do I calculate the point marked with a red circle, i.e. the intersection between circle and line? This would give me the new end point of the line, shortening it by 10 pixels.
Solution
Thank you for your answers from which I was able to put together the following procedure. I named it LengthenLine, since I find it more natural to pass a negative number of pixels if I want the line shortened.
Specifically, I was trying to put together a function that could draw a line with rounded corners, which can be found here.
public void LengthenLine(PointF startPoint, ref PointF endPoint, float pixelCount)
{
if (startPoint.Equals(endPoint))
return; // not a line
double dx = endPoint.X - startPoint.X;
double dy = endPoint.Y - startPoint.Y;
if (dx == 0)
{
// vertical line:
if (endPoint.Y < startPoint.Y)
endPoint.Y -= pixelCount;
else
endPoint.Y += pixelCount;
}
else if (dy == 0)
{
// horizontal line:
if (endPoint.X < startPoint.X)
endPoint.X -= pixelCount;
else
endPoint.X += pixelCount;
}
else
{
// non-horizontal, non-vertical line:
double length = Math.Sqrt(dx * dx + dy * dy);
double scale = (length + pixelCount) / length;
dx *= scale;
dy *= scale;
endPoint.X = startPoint.X + Convert.ToSingle(dx);
endPoint.Y = startPoint.Y + Convert.ToSingle(dy);
}
}
Find the direction vector, i.e. let the position vectors be (using floats) B = (x2, y2) and A = (x1, y1), then AB = B - A. Normalize that vector by dividing by its length ( Math.Sqrt(xx + yy) ). Then multiply the direction vector AB by the original length minus the circle's radius, and add back to the lines starting position:
double dx = x2 - x1;
double dy = y2 - y1;
double length = Math.Sqrt(dx * dx + dy * dy);
if (length > 0)
{
dx /= length;
dy /= length;
}
dx *= length - radius;
dy *= length - radius;
int x3 = (int)(x1 + dx);
int y3 = (int)(y1 + dy);
Edit: Fixed the code, aaand fixed the initial explanation (thought you wanted the line to go out from the circle's center to its perimeter :P)
I'm not sure why you even had to introduce the circle. For a line stretching from (x2,y2) to (x1,y1), you can calculate any point on that line as:
(x2+p*(x1-x2),y2+p*(y1-y2))
where p is the percentage along the line you wish to go.
To calculate the percentage, you just need:
p = r/L
So in your case, (x3,y3) can be calculated as:
(x2+(10/L)*(x1-x2),y2+(10/L)*(y1-y2))
For example, if you have the two points (x2=1,y2=5) and (x1=-6,y1=22), they have a length of sqrt(72 + 172 or 18.38477631 and 10 divided by that is 0.543928293. Putting all those figures into the equation above:
(x2 + (10/l) * (x1-x2) , y2 + (10/l) * (y1-y2))
= (1 + 0.543928293 * (-6- 1) , 5 + 0.543928293 * (22- 5))
= (1 + 0.543928293 * -7 , 5 + 0.543928293 * 17 )
= (x3=-2.807498053,y3=14.24678098)
The distance between (x3,y3) and (x1,y1) is sqrt(3.1925019472 + 7.7532190152) or 8.384776311, a difference of 10 to within one part in a thousand million, and that's only because of rounding errors on my calculator.
You can use similar triangles. For the main triangle, d is the hypotenuses and the extension of r is the vertical line that meets the right angle. Inside the circle you will have a smaller triangle with a hypotenuses of length r.
r/d = (x2-a0)/(x2-x1) = (y2-b0)/(y2-y1)
a0 = x2 + (x2-x1)r/d
b0 = y2 + (y2-y1)r/d

Categories

Resources