C# Drawing a radar scaling and centering problems - c#

I would like to draw a radar on a pictureBox. Drawing points is no problem but I am struggling with basic maths. Maybe I am too tired.
I have a pictureBox that is 200x200. I have loaded a small, centered image inside the picturebox (4x4) which symbolizes the current player.
I have build a function called
PaintRadar(int meX, int meY, int enemyX, int enemyY)
The parameters could have the following values: meX = 27000, meY = 30000, enemyX = 26000, enemyY = 28000
The desired result is to have the enemies around me and I am always centered in the pictureBox. What do I have to calculate to center meX and meY in the pictureBox?
Thanks

Assume the player is in the middle of the enemies and draw the enemies around the center based on the difference between their positions and the player's position.
Think about it as though the player is the origin. By subtracting the player's position from the enemy's position you are putting the enemy position into a coordinate system with the player at the center. This is essentially what you're radar is.
Example:
// Get differences. d is short for difference (or delta :)).
int dy = enemyY - meY;
int dx = enemyX - meX;
// Then scale the dy and dx values so they fix in the picture box.
dy *= scaleY;
dx *= scaleX;
Then you would draw the enemies at (dx,dy) on the picture box.
Scale should be a formula like this:
scaleY = (1 / maxDetectionDistance) * (heightOfRadarBox / 2);
scaleX = (1 / maxDetectionDistance) * (widthOfRadarBox / 2);
Anything greater than your radar's limit should not be drawn.
// Don't draw if enemy is too far away for radar to pick up.
if (Math.Abs(dy) > maxDetectionDistance || Math.Abs(dx) > maxDetectionDistance)
{
return;
}

Related

Arc lines between 2 objects on a sphere Unity3D

I need a little help with maths for drawing lines between 2 points on a sphere. I have a 3d globe and some markers on it. I need to draw curved line from point 1 to point 2. I managed to draw lines from point to point with LineRenderer, but they are drawn with the wrong angle and I can't figure out, how to implement lines that go at the right angle. The code by far:
public static void DrawLine(Transform From, Transform To){
float count = 12f;
LineRenderer linerenderer;
GameObject line = new GameObject("Line");
linerenderer = line.AddComponent<LineRenderer>();
var points = new List<Vector3>();
Vector3 center = new Vector3(
(From.transform.position.x + To.transform.position.x) / 2f,
(From.transform.position.y + To.transform.position.y) ,
(From.transform.position.z + To.transform.position.z) / 2f
);
for (float ratio = 0; ratio <= 1; ratio += 1 / count)
{
var tangent1 = Vector3.Lerp(From.position, center, ratio);
var tangent2 = Vector3.Lerp(center, To.position, ratio);
var curve = Vector3.Lerp(tangent1, tangent2, ratio);
points.Add(curve);
}
linerenderer.positionCount = points.Count;
linerenderer.SetPositions(points.ToArray());
}
So what I have now is creepy lines rising above along y axis:
What should I take into account to let lines go along the sphere?
I suggest you to find the normal vector of your two points with a cross product (if your sphere is centered at the origin) and then normalize it to use it as a rotation axis for a rotation using quaternions. To make the interpolations, you can simply rotate the first point around this vector with an angle of k * a where k is a parameter from 0 to 1 and a is the angle between your first two vectors which you can find with the acos() of the dot product of your two normalized points
EDIT : I thought about a much easier solution (again, if the sphere is centered) : you can do a lerp between your two vectors and then normalize the result and multiply it by the radius of the sphere. However, the spacings between the resulting points wont be constant, especially if they are far from each other.
EDIT 2 : you can fix the problem of the second solution by using a function instead of a linear parameter for the lerp : f(t) = sin(t*a)/sin((PI+a*(1-2*t))/2)/dist(point1, point2) where a is the angle between the two points.

When image size change, how do you calculate to counter the real-size coordinate value?

I want to know the coordinates value when the image is stretched from the center.
I know one pixel coordinate in texture image, and I'm using ray cast by matching it to mobile screen.
But I don't know how the coordinate value changes when the image grows.
When images grow, how do you calculate to counter the real-size coordinate value?
The image will increase to 1.33f size.
There may be simpler ways in Unity3D - I don't have any experience there - but this sounds like a fairly simple scaling problem.
You'll need to know the following:
The image coordinates of the centre of the image
This is the vector (width/2, height/2)
The screen coordinates of the centre of the image
Where the center of the image is on the screen
The scaling factor (1.33f in this example)
Given the above you can calculate the pixel being touched using simple math:
public Vector2Int ScaleTouch(Vector2Int imgCentre, Vector2Int dispCentre, float scale, Vector2Int touch)
{
var x = imgCentre.x + (touch.x - dispCentre.x) * scale;
var y = imgCentre.y + (touch.y - dispCentre.y) * scale;
return Vector2Int.RoundToInt(new Vector2(x, y));
}
Or using the methods in Vector2 and Vector2Int you might be able to do this:
public Vector2Int ScaleTouch(Vector2Int imgCentre, Vector2Int dispCentre, float scale, Vector2Int touch)
{
var offset = Vector2.Scale(touch - dispCentre, new Vector2(scale, scale));
return offset + imgCentre;
}
Both assume that your scale is homogeneous in x and y. You could provide a scale vector if you want it to be flexible about scaling in different axes.

Drawing a circle of unknown number of circles

I am currently working on a WinForms app, which at some point has to draw some stuff. Basically, it has to draw an unknown number of circles (f.e 3, 5, 10) in organized in a shape of a circle. Something like this:
I know it looks horrible. So I thought about defining a center of a circle and a radius. Then I just have to go f.e from the top of the big circle and draw a small circle every x-degrees (like for 3 circles it would be 120 degrees, for 4 circles 90 degrees etc.).
My question here is: Is there an algorithm, which would give me the center point of a circle to draw? Like I define my big circle with f.e center X = 50, Y = 50 and a radius R = 10. And then I draw a circle at the top, decide that I want to draw the next one 120 degrees far from the first one and I just need a point (X, Y) which is on the big circle?
Basically, you just need some math to figure out the coordinate of where the angle lands at the end of perimeter of the circle (a distance of the radius of the circle from the center of the circle). Here's psuedocode for this situation.
var center = new Point(0,0);
var radius = 5;
var degrees = 83;
var angle = Math.PI * degrees / 180;
var xPos = center.X + (radius * Math.cos(angle));
var yPos = center.Y + (radius * Math.sin(angle));
var newPosition = new Point(xPos,yPos);
Here, newPosition becomes the center point for the circled you'll be drawing along your imaginary circle. As for gathering the angles, simply use 360 / count * index.

Detecting collision between circles drawn in an array c#

I am drawing 10 circles in an array, these circles are moving around and bouncing across the screen. How would I take these drawn circles and detect when they collide with each other. When they collide I need them to bounce off of each other. These circles have random widths and heights. random speeds and all spawn at center screen.
How the circles are drawn:
private void pbGamescreen_Paint(object sender, PaintEventArgs e)
{
for (int mt = 0; mt < spawn; mt++)
{
e.Graphics.FillEllipse(ballBrush[mt], (int)xPos[mt], (int)yPos[mt], ballSizex[mt], ballSizey[mt]);
e.Graphics.DrawEllipse(Pens.Gray, (int)xPos[mt], (int)yPos[mt], ballSizex[mt], ballSizey[mt]);
}
}
Two circles intersect if the distance between their center points is smaller than the addition of their radiuses. You need to iterate each of your circle and check this against each other circle.
For instance, say you have these two circles on a horizontal axis:
(-----o-----) (---o---)
They do not intersect, as the distance between their center points is 12, and the sum of their radiuses is 8. However, these two do:
(-----o----(-)--o---)
The formula for the distance between two 2D points is:
var xdiff = x2 - x1;
var ydiff = y2 - y1;
return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
if r1 and r2 are radiuses of the two circles, and d is the distance between the centers of teh two circles then
bounce off when d<=r1 + r2;
ideally you should do it when d == r1 + r2;
Just a suggestion:
also keep the mass of the circle proportional to their r(radius) and then using the law of conservation momentum m1v1 = m2v2; bounce them offf in a way that looks real

Space represented by a single Kinect pixel at a given depth

Basically I want to take a fixed straight line across the devices point of view and determine if anything intercepts it but in my example I want to make the "laser line" configurable with regards to the distance from the top of the field of view.
Now it's easy enough to get the depth data at a given pixel point simply by doing this.
var depthInMM = DepthImagePixel.Depth;
and its also easy to simply say I want to focus on the 100th line of pixels from the top by doing something like this.
for (int i = 0; i < this._DepthPixels.Length; ++i) //_DepthPixels.Length is obviously 307200 for 640x480
{
if (i >= 64000 && i <= 64640) //Hundredth vertical pixel line
{
//Draw line or whatever
}
}
Which ends up with something like this.
BUT for example I might want to have the line intercept at 50 cm from the top of the field of view at 3 meters depth. Now obviously I understand that as the depth increases so does the area represented but I cannot find any reference or myself work out how to calculate this relationship.
So, how can one calculate the coordinate space represented at a given depth utilizing the Kinect sensor. Any help sincerely appreciated.
EDIT:
So if I understand correctly this can be implemented as such in C#
double d = 2; //2 meters depth
double y = 100; //100 pixels from top
double vres = 480; //480 pixels vertical resolution
double vfov = 43; //43 degrees vertical field of view of Kinect
double x = (2 * Math.Sin(Math.PI * vfov / 360) * d * y) / vres;
//x = 0.30541768893691434
//x = 100 pixels down is 30.5 cm from top field of view at 2 meters depth
2 sin(PI VFOV / 360) D Y
X = --------------------------
VRES
X: distance of your line from the top of the image in meters
D: distance - orthogonal to the image plane - of your line from the camera in meters
Y: distance of your line from the top of the image in pixels
VRES: vertical resolution of the image in pixels
VFOV: vertical field of view of the camera in degrees

Categories

Resources