How do I make a custom vertical axis? - c#

How do I make a custom vertical axis?
I'm making a game in C# and I have no idea how to make this idea work.
I want to there to be a invisible vertical line in the middle of the screen that mirrors specific things to the other side. I was thinking that it work in a way like this:
The new axis would be STH in this example, Left is negative numbers and right is positive.
let STHaxis = SetX(GetCenterX);
//I have no idea how to define this
let oppSTH = GetPlayerSTH;
//True Items
CreatePlayerShot01(GetPlayerSTH(), GetPlayerY(), 15, 270, 1.5, 3, 1);
//Mirrored Items ↓‎Ignore these numbers.↑
CreatePlayerShot01(oppSTH * -1, GetPlayerY(), 15, 270, 1.5, 3, 1);
But I need something that would make the STH axis exist...
Any ideas to have a mirror, even if it doesn't involve using this code at all. Thanks for reading this, I know I write a lot.
I could work with just moving the Y axis to the middle of my X axis.

let PX = GetPlayerX; //Gets your X
let MX = GetClipMaxX; // Gets the max X can be (complete right)
let MMX = GetClipMinX; // Gets the min X can be (complete left)
let agr = MMX + PX; // Agr = PX in this case
let mir = MX - PX; // Takes distance from minX and subtracts it from maxX

Related

How to get a parabola shape according to a moved point and nearest points

Being not very good at math, I have a problem with my project.
The objective is boundary correction on 3D files.
In my application, the user moves a 3D point on X-axis in order to correct or modify the boundary of the object.
I want to move the nearest boundary points in the same direction but decreasingly. I mean no point should move more than the main point. The nearest points move most and, the farthest points should move less.
On the image, the red dots represent the initial status of points. And the user pulls the P0 in the x-direction. And the other points follow it. The last status of the points is represented by violet dots.
Here is what I tried.
//On point moved event
//Get nearest boundary Points (Uses Geometry3D to get boundary points).
(var clothDMesh, _) = Utilities3D.BuildDMesh(baseMesh);
CreateClothModel(clothDMesh);
var boundryVertices = nodes.Where(ro => ro.Value.isBorder).Select(ro => ro.Value.vertex).ToList();
var refPoint = CustomPoint.FromPoint3D(movedPoint);
//Gets the delta X.
var deltaX = p.X - initialX;
//Gets nearest country points, so 15 points above and 15 points below to move only a given number of points (I know maybe this should be calculated according to delta).
var nearestPoints = refPoint.GetNearesPoints(boundryVertices, 30);
foreach (var item in nearestPoints)
{
//This is only one of what I tried as a function. None of them worked correctly.
item.X += deltaX - (deltaX * 1/ Math.Pow(item.Distance, 2));
}
Any help will be appreciated.
Thanks in advance.
Here's the math part:
I call "a" your "deltaX".
We also need a second parameter: "b", the maximum height of the red dots. I assume it is symetrical and "-b" would be the minimum height of the red dots.
So, if you look for the value X, horizontal move, in fonction of the coordinate Y of the dot:
X = a - a * Y * Y / (b * b);
You can verify that for Y = 0, you obtain X = a and for Y = b (or -b) you get X = 0.
You have your parabola (X is function of Y^2).

Best way to find if a point is within another Vector2?

I'm trying to find out if a point (mouse click) is within the boundaries of a box based on the top left x/y and bottom right x/y of the box. The position could be positive or negative. As you move up, y value increases, as you move down, y decreases. As you move right, x value increases, as you move left, x decreases.
Vector2 positions could be negative or positive depending on where is clicked.
I thought this would simply work but it doesn't seem to like negative numbers. Any suggestions? My brain is fried tonight after doing Vector arithmetic all night on other things. I wish I was one of you who seem to understand this without problem. ;)
if(point.x >= topLeft.x && point.y <= topLeft.y &&
point.x <= bottomRight.x && point.y >= bottomRight.y)
{
// is within box
}
Edit
Here is how the top left and bottom right are calculated. As it turns out, the problem was not with the above but rather I forgot to add the position.y to the top left calculation below.
Vector2 topLeft = new Vector2(transform.position.x - (transform.localScale.x/2),
transform.position.y + (transform.localScale.y/2));
Vector2 bottomRight = new Vector2(transform.position.x + (transform.localScale.x/2),
transform.position.y - (transform.localScale.y/2));
For anyone coming across this thread, the above check is correct.
Example 1:
Example 2:
I think you've wrongly inverted the boolean expression. It's easier to check for all cases where the click is outside the box.
Semantically, a certain point is outside of a rectangle if it is:
Higher than the highest point of the rectangle
Lower than the lowestpoint of the rectangle
More left than the left side of the rectangle
More right than the right side of the rectangle
If one of these is true, it's outside the box.
if(
clickPosition.x < topLeft.x
||
clickPosition.x > bottomRight.x
||
clickPosition.y < bottomRight.y
||
clickPosition.y > topLeft.y
)
{
//Now you're sure the click was outside the box.
}
Why not using a Rectangle and then check if it contains the point?
var rectangle = new Rectangle(-100,0,100,-100);
if(rectangle.Contains(-25,-25))
{
// is within box
}
For the rest, it appears your code should work. Then there may be a problem with the the assignment of the values of point, topLeft and bottomRight.
the problem with the negative numbers is that your top left isn't your top left
if you say
topY = max(corner1y, corner2y, corner3y)
bottomY = min (corner1y, corner2y, corner3y)
after that your check will work fine again.
I believe you're using the wrong signs on the Y checks.
If your topleft is 50, 100 and the bottom right is 100, 50, then 80 (y) still must be between 50 and 100, it doesn't matter which direction your Y is moving in relation to the screen, as long as you're also inverting your definition of top left.
if(point.x >= topLeft.x && point.y >= topLeft.y && //flipped sign in the second condition
point.x <= bottomRight.x && point.y <= bottomRight.y) //flipped sign in the second condition
{
// is within box
}
If you're not inverting your definition of top left, your original code is correct even for negative numbers.

How to update x, y coordinates on an rotating rectangle edge

Ok so I have searched and searched for a solution to my problem, but non seem to fix it.
I need to make a game with a rotating "cannon", my cannon is a simple rectangle placed in the middle of my panel that I can rotate with my keyboard. It rotates around one edge. I want to shoot out of the edge on the other side. I have found the starting point of where to shoot my bullets by using:
x = a + dia * (float)Math.Cos(angle);
y = b + dia * (float)Math.Sin(angle)
where "a, b" is the center coordinate I rotate it around and "dia" is the diagonal of the rectangle and "angle" is the angle of the one half of my rectangle.
public float rotate = 0.0f;
g.TranslateTransform(a , b);
g.RotateTransform(rotate);
I have a own class for my bullets that I put in a List.
So far so good. But when I rotate my cannon, the bullets don't come out from the tip anymore..they just start appearing far off where I want them to. it's because of this code:
x = (float)((x * Math.Cos(rotate)) - (y * Math.Sin(rotate)));
y = (float)((x * Math.Sin(rotate)) + (y * Math.Cos(rotate)));
that's supposed to update the x, y coordinates of the tip of the cannon.
If I delete it, it just fires from the same spot(no shit).
Can someone please explain to me what code I need to write to update the X, Y so they come out of my rectangle edge? It's driving me crazy..
Edit:
Found my answer staring at the screen in the early mornings. I had no need for any "find new x, y coordinates". I simply made a updater that updated the original angle with the float number it needed to move a little bit each time i rotated it.
hah! so simple, yet so hard to see.
First of all,
x = (float)((x * Math.Cos(rotate)) - (y * Math.Sin(rotate)));
y = (float)((x * Math.Sin(rotate)) + (y * Math.Cos(rotate)));
needs to be something like:
float oldx = x;
float oldy = y;
x = (float)((oldx * Math.Cos(rotate)) - (oldy * Math.Sin(rotate)));
y = (float)((oldx * Math.Sin(rotate)) + (oldy * Math.Cos(rotate)));
your new values need to be based purely off the old values..
If there's any other problem after fixing this, it may be related to how the rectangle is translated on the plane.
Edit: If this were a code review, I'd say the solution I just gave isn't quite the best solution either (it just doesn't suffer from the bug you introduced by using the new value of x to calculate the new value of y). See, Math.Cos and Math.Sin are generally expensive operations compared to multiplication and addition. If you had a bunch of points that need transformed the same way, best to calculate Math.Sin(rotate) and Math.Cos(rotate) once and use those values for every point. This might be a good place to use the Flyweight pattern and define a class where an instance would hold all your points for a given object/context so that operations can be done in aggregate.

Draw 3D arc given start, middle, and endpoint

I am trying to make a user-defined arc with the Helix 3D toolkit. The user selects 3 points on the arc (start, middle, end) and the program finds the center of the circle and draws the arc from start to end. My problem is I'm not good at math and I am having problems making this work. My main problem is getting the start and end angles and having it draw arcs of all sizes accurately. Any help is appreciated. Here is my code:
private void Draw_Arc(object sender, MouseButtonEventArgs e)
{
linept = new List<Point3D>();
linept.Add(startPoint);
linept.Add(endPoint);
linept.Add((Point3D)GetPoints(e));
LinesVisual3D line = new LinesVisual3D();
line.Thickness = 2;
line.Color = Colors.Blue;
line.Points = linept;
port.Children.Add(line);
double startAngle, sweepAngle;
Point3D center = GetCenterOfArc(linept.ElementAt(0), linept.ElementAt(1), linept.ElementAt(2));
GetAngles(linept.ElementAt(0), linept.ElementAt(1), linept.ElementAt(2), out startAngle, out sweepAngle);
circle = new PieSliceVisual3D();
double RadiusX = Math.Abs(startPoint.X - center.X);
double RadiusY = Math.Abs(startPoint.Y - center.Y);
circle.Center = center;
if (RadiusX >= RadiusY)
circle.OuterRadius = RadiusX;
else
circle.OuterRadius = RadiusY;
circle.InnerRadius = circle.OuterRadius + 3;
circle.StartAngle = (180 / Math.PI * Math.Atan2(startPoint.Y - circle.Center.Y, startPoint.X - circle.Center.X));
circle.EndAngle = (180 / Math.PI * Math.Atan2(linept.ElementAt(2).Y - circle.Center.Y, linept.ElementAt(2).X - circle.Center.X));
port.Children.Add(circle);
}
I think that you have to know the center of the circle in order to know the starting and ending angle of the arc.
Say that you just have three points, and you want to find a circle that goes through all three, you basically have three equations with three variables:
(x-x0)^2 + (y-y0)^2 = R^2
(x-x1)^2 + (y-y1)^2 = R^2
(x-x2)^2 + (y-y2)^2 = R^2
Solving that can get a little tricky if you try to program that on your own and have average knowledge in math, but you can do it fairly easily using matrices. Read here for a bit information.
After you've solved the three equations, you should have X, Y, R.
X and Y will be the center point of the circle, and R - it's radius.
Now, as far as I remember, they count the arc's degrees starting from the positive X axis, going upwards. So you would need to calculate the angle between two lines - the line that stretches between the center to your floating point, and the line that stretches from your center point to the "limitless" right. You may just Google "calculate angle between two lines". Repeating that process for both your starting point and your ending point, will give each their respective entering/exiting angle.
The middle point isn't really used anymore, but the radius is. You just set it to be the radius and you're good to go.
I haven't really implemented anything - just giving you a fair direction. (and I bet that there's a much cleaner and nicer-to-work-with solution)

Need some math - Projecting Slope

I have a rectangle.
Its height (RH) is 400.
Its width (RW) is 500.
I have circle.
Its height (CH) is 10.
Its width (CW) is 10.
Its starting location (CX1, CY1) is 20, 20.
The circle has moved.
Its new location (CX2, CY2) is 30, 35.
Assuming my circle continues to move in a straight line.
What is the circle's location when its edge reaches the boundary?
Hopefully you can provide a reusable formula.
Perhaps some C# method with a signature like this?
point GetDest(size itemSize, point itemPos1, point itemPos2, size boundarySize)
I need to calculate what that location WILL be once it arrives - knowing that it is not there yet.
Thank you.
PS: I need this because my application is watching the accelerometer on my Windows Phone. I am calculating the target necessary to animate the motion of the circle inside the rectangle as the user is tilting their device.
It is 1 radius away from the boundar(y/ies).
The answer is X=270 Y=395
first define the slope V as dy/dx =(y2-y1)/(x2-x1). In your example: (35-20)/(30-20)=1.5
the line equation is
y = V * (x-x1) + y1. You are interested in the horizontal locations x at:
y= CH/2 OR y= H-CH/2
so (not code, just math)
if (y2-y1)<0:
x=(CH/2 -y1)/V +x1 10 for your example. OR
if (y2-y1)>0:
x=(H-CH/2 -y1)/V +x1 270 for your example
else (that is: y2==y1)
the upper or lower lines were not hit.
if CH/2 <= x <= W-CH/2 the circle did hit the that upper or lower side: since V>0, we use x=270 and that is within CH/2 and W-CH/2.
So the answer to your question is y=H-CH/2 = 395 , X=270
For the side lines it's similar:
(if (x2-x1)<0)
y=(CH/2 -x1)*V +y1
(if (x2-x1)>0)
y=(W-CH/2 -x1)*V +y1
else (that is: x2==x1)
the side lines were not hit.
if CH/2 <= y <= H-CH/2 the circle did hit that side at that y.
be careful with the trivial cases of completely horizontal or vertical movement so that you don't divide by zero. when calculating V or 1/V. Also deal with the case where the circle did not move at all.
Since you now asked, here's metacode which you should easily be able to convert to a real method. It deals with the special cases too. The input is all the variables you listed in your example. I here use just one symbol for the circle size, since it's a circle not an ellipse.
method returning a pair of doubles getzy(x1,y1,W,H,CH){
if (y2!=y1){ // test for hitting upper or lower edges
Vinverse=(x2-x1)/(y2-y1)
if ((y2-y1)<0){
xout=(CH/2 -y1)*Vinverse +x1
if (CH/2 <= y <= H-CH/2) {
yout=CH/2
return xout,yout
}
}
if ((y2-y1)>0){
xout=(H-CH/2 -y1)*Vinverse +x1
if (CH/2 <= y <= H-CH/2) {
yout=H-CH/2
return xout,yout
}
}
}
// reaching here means upper or lower lines were not hit.
if (x2!=x1){ // test for hitting upper or lower edges
V=(y2-y1)/(x2-x1)
if ((x2-x1)<0){
yout=(CH/2 -x1)*V +y1
if (CH/2 <= x <= W-CH/2) {
xout=CH/2
return xout,yout
}
}
if ((x2-x1)>0){
yout=(H-CH/2 -x1)*V +y1
if (CH/2 <= x <= W-CH/2) {
xout=H-CH/2
return xout,yout
}
}
}
// if you reach here that means the circle does not move...
deal with using exceptions or some other way.
}
It's easy; no calculus required.
Your circle has radius R = CW/2 = CH/2, since the diameter of the circle D = CW = CH.
In order to have the circle touch the vertical edge of the rectangle at a tangent point, you have to move the circle to the right by a distance (W - (CX1 + CW/2))
Likewise, the circle will touch the bottom edge of the rectangle at a tangent point when you move it down by a distance (H - (CY1 + CH/2)).
If you do this in two separate translations (e.g., first to the right by the amount given, then down by the amount given or visa versa), you'll see that the circle will touch both the right hand vertical and the bottom horizontal edges at tangent points.
When the moving circle arrives at a wall (boundary) then it will be tangent at one of four points on the circle, call them N, S, E, and W. You know their initial coordinates.
The points travel in a line with a slope known to you: m=(y2-y1)/(x2-x1); where in your example (x1, y1) - (20,20) and (x2, y2)= (30, 35).
Your problem is to find the trajectory of the first point N, S, E, or W which reaches any wall. The trajectory will be a line with slope m.
You can do this by adding (or subtracting) the direction vector for the line to the point N, S, E, or W, scaled by some t.
For example, N is (20, 15). The direction vector is (x2-x1,y2-y1) = (10, 15). Then (20, 15) + t * (10, 15) will hit the boundary lines at different t's. You can solve for these; for example 20 + t*10 = 0, and 20 + t*10 = 400, etc.
The t that is smallest in magnitude, over all four trajectories, gives you your tangent point.
Not sure its calculus..wouldn't it just be the following:
if y >= 390 then it reached the top edge of the rectangle
if x >= 490 then it reached the right edge of the rectangle
if y <= 0 then it reached the bottom edge of the rectangle
if x <= 0 then it reached the left edge of the rectangle

Categories