i need to draw an arrow representing the rotation of a circle in WPF. The best i got so far is this one. But it seems that the arrowhead is not correctly aligned with the angle of the arrowarc.
private void InternalDrawArrowGeometry(StreamGeometryContext context)
{
var angleWidth = 45;
var startAngle = Rotation + 90;
var endAngle = Rotation + angleWidth + 90;
var xEnd = Radius * Math.Cos(startAngle * Math.PI / 180.0);
var yEnd = Radius * Math.Sin(startAngle * Math.PI / 180.0);
var xStart = Radius * Math.Cos(endAngle * Math.PI / 180.0);
var yStart = Radius * Math.Sin(endAngle * Math.PI / 180.0);
var b = angleWidth * Math.PI/180;
var pt1 = new Point(CentreX + xStart, CentreY - yStart);
var pt2 = new Point(CentreX + xEnd, CentreY - yEnd);
var len2 = 1;
const int angle = 45;
var pt3 = new Point(
pt2.X + (len2 / b) * ((pt1.X - pt2.X) * Math.Cos(angle) + (pt1.Y - pt2.Y) * Math.Sin(angle)),
pt2.Y + (len2 / b) * ((pt1.Y - pt2.Y) * Math.Cos(angle) - (pt1.X - pt2.X) * Math.Sin(angle)));
var pt4 = new Point(
pt2.X + (len2 / b) * ((pt1.X - pt2.X) * Math.Cos(angle) - (pt1.Y - pt2.Y) * Math.Sin(angle)),
pt2.Y + (len2 / b) * ((pt1.Y - pt2.Y) * Math.Cos(angle) + (pt1.X - pt2.X) * Math.Sin(angle)));
context.BeginFigure(pt1,
false, // Filled
false); // Closed
context.ArcTo(pt2,
new Size(Radius, Radius),
0.0, // rotationAngle
startAngle - endAngle > 180, // greater than 180 deg?
SweepDirection.Clockwise,
true, // isStroked
false);
context.LineTo(pt3, true, false);
context.LineTo(pt2, true, false);
context.LineTo(pt4, true, false);
}
Has anyone coded something like this correctly and give me the code or can tell me whats wrong with my code?
Related
I am currently creating a rubiks cube project. The cube solves, but now I'm trying to implement a 3d model of this cube.
At the moment the x axis and z axis rotations work correctly, but the y axis rotation seems to start of as a cube but as it rotates round becomes more of a trapezium as it rotates 180'.
I have this code:
Point3D final;
double x = rotation.x;
final.x = original.x;
final.y = original.y * Math.Cos(x) - original.z * Math.Sin(x);
final.z = original.y * Math.Sin(x) + original.z * Math.Cos(x);
original.x = final.x;
original.y = final.y;
original.z = final.z;
x = rotation.y;
final.x = original.z * Math.Sin(x) + original.x * Math.Cos(x);
final.y = original.y;
final.z = original.y * Math.Cos(x) - original.x * Math.Sin(x);
original.x = final.x;
original.y = final.y;
original.z = final.z;
x = rotation.z;
final.x = original.x * Math.Cos(x) - original.y * Math.Sin(x);
final.y = original.x * Math.Sin(x) + original.y * Math.Cos(x);
final.z = original.z;
typo. Change line for y-rotation to
final.z = original.z * Math.Cos(x) - original.x * Math.Sin(x);
You were using original.y instead of original.z, but for a y-rotation the value of y does not play into the rotation.
May I suggest you define the rotations in methods
public static class Rotations
{
public static Point3D RotateAboutX(this Point3D point, double angle)
{
return new Point3D(
point.X,
Math.Cos(angle) * point.Y- Math.Sin(angle) * point.Z,
Math.Sin(angle) * point.Y+ Math.Cos(angle) * point.Z);
}
public static Point3D RotateAboutY(this Point3D point, double angle)
{
return new Point3D(
Math.Cos(angle) * point.X + Math.Sin(angle) * point.Z,
point.Y,
-Math.Sin(angle) * point.X + Math.Cos(angle) * point.Z);
}
public static Point3D RotateAboutZ(this Point3D point, double angle)
{
return new Point3D(
Math.Cos(angle) * point.X - Math.Sin(angle) * point.Y,
Math.Sin(angle) * point.X + Math.Cos(angle) * point.Y,
point.Z);
}
}
and then used them as needed. For Example
Point3D final = original.RotateAboutX(rotation.x)
.RotateAboutY(rotation.y)
.RotateAboutZ(rotation.z);
or the remain true to the original code
Point3D final = original.RotateAboutX(rotation.x);
original = final;
final = original.RotateAboutY(rotation.y);
original = final;
final = original.RotateAboutZ(rotation.z);
How can I adjust Theta 4_1 which should return 0 rather than 180? What is causing the result to go in the wrong quadrant in C#. Everything else works fine, therefore in the codes provided below theta 4_1 is the main focus. I've checked a few documentations but still can't figure it out. I'll appreciate some guidance. Thanks in advance. ** This is already worked out in MATLAB, hence I know what values that should be returned.**
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IK
{
class Inverse
{
static void Main()
{
{
//Link lenghts & Offsets in Millimeters(mm)
double a2 = 380.0; double a3 = 0.0; double d3 = 0.0; double d4 = 351.0; double L5 = 89.00;
//End Effector points at **home position**
double p1x = 362.50;
double p1y = 12.50;
double p1z = -420;
double p2x = 397.50;
double p2y = 12.50;
double p2z = -420;
double p3x = 362.50;
double p3y = -12.50;
double p3z = -420;
double p4x = 362.50;
double p4y = 12.50;
double p4z = -432;
// Tool tip points
double epx = 380.00; double epy = 0.00; double epz = -440.00;
//double epx = X; double epy = Y; double epz = Z;
// M points computation nx ny nz
double nx = (p2x - p1x) / Math.Sqrt(Math.Pow(p2x - p1x, 2) + Math.Pow(p2y - p1y, 2) + Math.Pow(p2z - p1z, 2));
//Console.WriteLine("nx = "+ nx);
double ny = (p2y - p1y) / Math.Sqrt(Math.Pow(p2x - p1x, 2) + Math.Pow(p2y - p1y, 2) + Math.Pow(p2z - p1z, 2));
//Console.WriteLine("ny = " + ny);
double nz = (p2z - p1z) / Math.Sqrt(Math.Pow(p2x - p1x, 2) + Math.Pow(p2y - p1y, 2) + Math.Pow(p2z - p1z, 2));
//Console.WriteLine("nz = " + nz);
// M points computation sx sy sz
double sx = (p3x - p1x) / Math.Sqrt(Math.Pow(p3x - p1x, 2) + Math.Pow(p3y - p1y, 2) + Math.Pow(p3z - p1z, 2));
//Console.WriteLine("sx = " + sx);
double sy = (p3y - p1y) / Math.Sqrt(Math.Pow(p3x - p1x, 2) + Math.Pow(p3y - p1y, 2) + Math.Pow(p3z - p1z, 2));
//Console.WriteLine("sy = " + sy);
double sz = (p3z - p1z) / Math.Sqrt(Math.Pow(p3x - p1x, 2) + Math.Pow(p3y - p1y, 2) + Math.Pow(p3z - p1z, 2));
//Console.WriteLine("sz = " + sz);
// M points computation ax ay az
double ax = (p4x - p1x) / Math.Sqrt(Math.Pow(p4x - p1x, 2) + Math.Pow(p4y - p1y, 2) + Math.Pow(p4z - p1z, 2));
//Console.WriteLine("ax = " + ax);
double ay = (p4y - p1y) / Math.Sqrt(Math.Pow(p4x - p1x, 2) + Math.Pow(p4y - p1y, 2) + Math.Pow(p4z - p1z, 2));
//Console.WriteLine("ay = " + ay);
double az = (p4z - p1z) / Math.Sqrt(Math.Pow(p4x - p1x, 2) + Math.Pow(p4y - p1y, 2) + Math.Pow(p4z - p1z, 2));
//Console.WriteLine("az = " + az);
// End points calulations
double px = epx - ax * L5;
//Console.WriteLine("px = " + px);
double py = epy - ay * L5;
//Console.WriteLine("py = " + py);
double pz = epz - az * L5;
//Console.WriteLine("pz = " + pz);
// Trigonometric substitution using element (2,4)
double p1 = Math.Sqrt(Math.Pow(px, 2) + Math.Pow(py, 2)); // Rho value in the manuscript for theta 1
//Console.WriteLine("p1 = " + p1);
double p3 = Math.Sqrt(Math.Pow(d4, 2) + Math.Pow(a3, 2)); // Rho value in the manuscript for theta 3
//Console.WriteLine("p3 = " + p3);
// Finding joint angle 1
double theta1_1 = Math.Atan2(py, px) - Math.Atan2(d3/p1, Math.Sqrt(Math.Pow(1 - (d3/p1),2)));
double theta1_2 = Math.Atan2(py, px) - Math.Atan2(d3/p1, -Math.Sqrt(Math.Pow(1 - (d3/p1),2)));
// Finding joint angle 3
double K = Math.Pow(px, 2) + Math.Pow(py, 2) + Math.Pow(pz, 2) - Math.Pow(a3,2) - Math.Pow(d4, 2)
- Math.Pow(a2, 2) - Math.Pow(d3, 2) / (2*a2);
//Console.WriteLine("K = " + K);
double theta3_1 = Math.Atan2(a3, d4) - Math.Atan2(K/p3, Math.Sqrt(Math.Pow(1 - (K / p3), 2)));
double theta3_2 = Math.Atan2(a3, d4) - Math.Atan2(K/p3, -Math.Sqrt(Math.Pow(1 - (K / p3), 2)));
// Finding joint angle 2
// Theta2_1
double s23_1 = ((-a2 * Math.Cos(theta3_1) - a3) * pz + (a2 * Math.Sin(theta3_1) - d4) *
(px * Math.Cos(theta1_1) + py * Math.Sin(theta1_1))); //Y in our formula
double c23_1 = ((a2 * Math.Sin(theta3_1) - d4) * pz + (a2 * Math.Cos(theta3_1) + a3) *
(px * Math.Cos(theta1_1) + py * Math.Sin(theta1_1))); //X in our formula
double theta23_1 = Math.Atan2(s23_1, c23_1);
double theta2_1 = (theta23_1 - theta3_1);
// Theta2_2
double s23_2 = ((-a2 * Math.Cos(theta3_2) - a3) * pz + (a2 * Math.Sin(theta3_2) - d4) *
(px * Math.Cos(theta1_1) + py * Math.Sin(theta1_1))); //Y in our formula
double c23_2 = ((a2 * Math.Sin(theta3_2) - d4) * pz + (a2 * Math.Cos(theta3_2) + a3) *
(px * Math.Cos(theta1_1) + py * Math.Sin(theta1_1))); //X in our formula
double theta23_2 = Math.Atan2(s23_2, c23_2);
double theta2_2 = (theta23_2 - theta3_2);
// Theta2_3
double s23_3 = ((-a2 * Math.Cos(theta3_1) - a3) * pz + (a2 * Math.Sin(theta3_1) - d4) *
(px * Math.Cos(theta1_2) + py * Math.Sin(theta1_2))); //Y in our formula
double c23_3 = ((a2 * Math.Sin(theta3_1) - d4) * pz + (a2 * Math.Cos(theta3_1) + a3) *
(px * Math.Cos(theta1_2) + py * Math.Sin(theta1_2))); //X in our formula
double theta23_3 = Math.Atan2(s23_3, c23_3);
double theta2_3 = (theta23_3 - theta3_1);
// Theta2_4
double s23_4 = ((-a2 * Math.Cos(theta3_2) - a3) * pz + (a2 * Math.Sin(theta3_2) - d4) *
(px * Math.Cos(theta1_2) + py * Math.Sin(theta1_2))); //Y in our formula
double c23_4 = ((a2 * Math.Sin(theta3_2) - d4) * pz + (a2 * Math.Cos(theta3_2) + a3) *
(px * Math.Cos(theta1_2) + py * Math.Sin(theta1_2))); //X in our formula
double theta23_4 = Math.Atan2(s23_4, c23_4);
double theta2_4 = (theta23_4 - theta3_2);
// Finding joint angle 4
// Theta4_1
double s4_1 = Math.Cos(theta1_1) * ay - Math.Sin(theta1_1) * ax ; //Y
//Console.WriteLine($"s4_1 = {s4_1:f64}"); // Checking s4_1
double c4_1 = -Math.Cos(theta1_1) * Math.Cos(theta23_1) * ax - Math.Sin(theta1_1) *
Math.Cos(theta23_1) * ay + Math.Sin(theta23_1) * az;//X
//Console.WriteLine($"c4_1 = {c4_1:f64}"); // Checking s4_1
double theta4_1 = Math.Atan2(s4_1, c4_1); //negate X to get the value of the second quadrant
// Theta4_2
double s4_2 = Math.Cos(theta1_1) * ay - Math.Sin(theta1_1) * ax;
double c4_2 = -Math.Cos(theta1_1) * Math.Cos(theta23_2) * ax - Math.Sin(theta1_1) *
Math.Cos(theta23_2) * ay + Math.Sin(theta23_2) * az;
double theta4_2 = Math.Atan2(s4_2, c4_2);
// Theta4_3
double s4_3 = Math.Cos(theta1_2) * ay - Math.Sin(theta1_2) * ax;
double c4_3 = -Math.Cos(theta1_2) * Math.Cos(theta23_3) * ax - Math.Sin(theta1_2) *
Math.Cos(theta23_3) * ay + Math.Sin(theta23_3) * az;
double theta4_3 = Math.Atan2(s4_3, c4_3);
// Theta4_4
double s4_4 = Math.Cos(theta1_2) * ay - Math.Sin(theta1_2) * ax;
double c4_4 = -Math.Cos(theta1_2) * Math.Cos(theta23_4) * ax - Math.Sin(theta1_2) *
Math.Cos(theta23_4) * ay + Math.Sin(theta23_4) * az;
double theta4_4 = Math.Atan2(s4_4, c4_4);
//Converting from radians to degrees & Display
//theta 1
Console.WriteLine("theta1_1 = " + theta1_1 * 180 / (Math.PI));
Console.WriteLine("theta1_2 = " + theta1_2 * 180 / (Math.PI));
//thetha 3
Console.WriteLine("theta3_1 = " + theta3_1 * 180 / (Math.PI));
Console.WriteLine("theta3_2 = " + theta3_2 * 180 / (Math.PI));
//theta 2
Console.WriteLine("theta2_1 = " + theta2_1 * 180 / (Math.PI));
Console.WriteLine("theta2_2 = " + theta2_2 * 180 / (Math.PI));
Console.WriteLine("theta2_3 = " + theta2_3 * 180 / (Math.PI));
Console.WriteLine("theta2_4 = " + theta2_4 * 180 / (Math.PI));
//theta 4
Console.WriteLine("theta4_1 = " + theta4_1 * 180 / (Math.PI));
Console.WriteLine("theta4_2 = " + theta4_2 * 180 / (Math.PI));
Console.WriteLine("theta4_3 = " + theta4_3 * 180 / (Math.PI));
Console.WriteLine("theta4_4 = " + theta4_4 * 180 / (Math.PI));
}
Console.ReadLine();
}
}
}
Diagram
Comparison of the results gained from C#, MATLAB & Python
MATLAB's atan2 has a few behaviors that differ from those of IEEE®-754 Standard.
Source: atan2, MATLAB's page
There is a line at which we know the coordinates of the extreme points.
We can also measure the distance between the starting and ending points.
delta_x: -45.5
delta_y: 59
delta_z: -4
delta_x1: -38.5
delta_y1: 40.5
delta_z1: 17
The goal is to move the green line to the blue. The first action, knowing the distance to the extreme point(B and V), I move point B to point V. Now we need to determine at what angles the line should be rotated relative to point V so that it coincides with the blue one.
Coordinates and distances to points are slightly different, but do not pay attention to it.
The illustration is on the link:
I expressed the angles of rotation from the matrix of stratifying cosines during rotation with respect to x y z. But they think not true angles.
I also tried other formulas but they only work with positive changes in coordinates.
double rotx1 = -((t[2] * t1[1] - t1[2] * t[1]) / (t1[1] * t1[1] + t1[2] * t1[2]));
double rotx11 = Math.Asin(rotx1) / Math.PI * 180;
double roty1 = -((t[2] * t1[0] - t1[2] * t[0]) / (t1[0] * t1[0] + t1[2] * t1[2]));
double roty11 = Math.Asin(roty1) / Math.PI * 180;
double rotz1 = -((t[1] * t1[0] - t1[1] * t[0]) / (t1[0] * t1[0] + t1[1] * t1[1]));
double rotz11 = Math.Asin(rotz1) / Math.PI * 180;
Console.WriteLine("X=" + Convert.ToString(rotx11) + " Y=" +
Convert.ToString(roty11) + " Z=" + Convert.ToString(rotz11));
or this
double[] pos = { 395, -0, 37, 90, 90, 0 };//The coordinates of the first marker.
double[] pos1 = { 321, -0, 37, 90, 90, 0 };//The coordinates of the second marker.
double[] t = { 0, 0, 0, 0, 0, 0 };
double[] t1 = { 0, 0, 0, 0, 0, 0 };
double[] t2= { 0, 0, 0, 0, 0, 0 };
double x = -45.5;//Known changes in the coordinates of the point of the first marker
double y = 59;
double z = 33 ;
double x1 = -38.5;// Known changes in the coordinates of the point of the second marker
double y1 = 40.5;
double z1 = 54;
t[0] = pos[0] + x;
t[1] = pos[1] + y;
t[2] = pos[2] -4;
t[3] = pos[3];
t[4] = pos[4];
t[5] = pos[5];
t1[0] = pos1[0] + x1;
t1[1] = pos1[1] + y1;
t1[2] = pos1[2] + 17;
t1[3] = pos1[3];
t1[4] = pos1[4];
t1[5] = pos1[5];
double Ayx21 = Math.Atan2(t[1] - t1[1], t[0] - t1[0]) / Math.PI * 180;
double rotx = Math.Atan2(t[1] - t1[1], t[2] - t1[2]);
double roty1111 = -Math.Atan2((t[2] - t1[2]) * Math.Cos(rotx), (t[1] - t1[1]));
double rotz = Math.Atan2(Math.Sin(roty1111), Math.Sin(rotx) * Math.Cos(rotx)) / Math.PI * 180;
double rotx11111 = (rotz) - (Ayx21);
double roty = -Math.Atan2((t[2] - t1[2]) * Math.Cos(rotx), (t[1] - t1[1])) / Math.PI * 180;
t2[0] = pos[0] + x;
t2[1] = pos[1] + y;
t2[2] = pos[2] + z ;//убрать потом -37
t2[3] = (rotx11111);
t2[4] = (90 + roty);
t2[5] = (180 + rotz);
string position1 = Convert.ToString(t2[0]).Replace(',', '.');
string position2 = Convert.ToString(t2[1]).Replace(',', '.');
string position3 = Convert.ToString(t2[2]).Replace(',', '.');
string angle1 = Convert.ToString(t2[3]).Replace(',', '.');
string angle2 = Convert.ToString(t2[4]).Replace(',', '.');
string angle3 = Convert.ToString(t2[5]).Replace(',', '.');
Console.WriteLine("[" + Convert.ToString(position1) + "," + Convert.ToString(position2) + "," + Convert.ToString(position3) + "," + Convert.ToString(angle1) + "," + Convert.ToString(angle2) + "," + Convert.ToString(angle3) + "]");
In android , I have drawn an arc based on startangle, sweepangle and radius. Let width be 400 and height be 500 as rectangle bounds in which radius is calculated as
var radius = Math.Min(Width,Height)/2;
Also if centre is calculated as
var x = (float)(Width * 0.5);
var y = (float)(Height * 0.5);
var centre = new PointF(x,y);
If above centre value is used, centre remains same for all start angle and sweepangle for rectangle. I need to change the centre if startangle and sweep angle changes
In the below image, rectangle bounds is 400,500 and the startangle is 0 and sweepangle is 360
If I change start angle to 180 and sweepangle to 180, centre remains same
I need the below image output,if I change startangle and sweepangle based on circle bounds, centre point should vary
I have done calculations for the above ,
private SystemPointF GetActualCenter(float x, float y, float radius)
{
SystemPointF actualCenter = new SystemPointF(x, y);
double startAngle1 = GetWrapAngle(StartAngle, -630, 630);
double endAngle1 = GetWrapAngle(EndAngle, -630, 630);
float[] regions = new float[] { -630, -540, -450, -360, -270, -180, -90, 0, 90, 180, 270, 360, 450, 540, 630 };
List<int> region = new List<int>();
if (startAngle1 < endAngle1)
{
for (int i = 0; i < regions.Length; i++)
{
if (regions[i] > startAngle1 && regions[i] < endAngle1)
region.Add((int)((regions[i] % 360) < 0 ? (regions[i] % 360) + 360 : (regions[i] % 360)));
}
}
else
{
for (int i = 0; i < regions.Length; i++)
{
if (regions[i] < startAngle1 && regions[i] > endAngle1)
region.Add((int)((regions[i] % 360) < 0 ? (regions[i] % 360) + 360 : (regions[i] % 360)));
}
}
double startRadian = 2 * Math.PI * (startAngle1) / 360;
double endRadian = 2 * Math.PI * (endAngle1) / 360;
SystemPointF startPoint = new SystemPointF((float)(x + radius * Math.Cos(startRadian)),
(float)(y + radius * Math.Sin(startRadian)));
SystemPointF endPoint = new SystemPointF((float)(x + radius * Math.Cos(endRadian)),
(float)(y + radius * Math.Sin(endRadian)));
switch (region.Count)
{
case 0:
float longX = Math.Abs(x - startPoint.X) > Math.Abs(x - endPoint.X) ? startPoint.X : endPoint.X;
float longY = Math.Abs(y - startPoint.Y) > Math.Abs(y - endPoint.Y) ? startPoint.Y : endPoint.Y;
SystemPointF midPoint = new SystemPointF(Math.Abs((x + longX)) / 2, Math.Abs((y + longY)) / 2);
actualCenter.X = x + (x - midPoint.X);
actualCenter.Y = y + (y - midPoint.Y);
break;
case 1:
SystemPointF point1 = new SystemPointF(), point2 = new SystemPointF();
float maxRadian = (float)(2 * Math.PI * region[0] / 360);
SystemPointF maxPoint = new SystemPointF((float)(x + radius * Math.Cos(maxRadian)),
(float)(y + radius * Math.Sin(maxRadian)));
switch (region[0])
{
case 270:
point1 = new SystemPointF(startPoint.X, maxPoint.Y);
point2 = new SystemPointF(endPoint.X, y);
break;
case 0:
case 360:
point1 = new SystemPointF(x, endPoint.Y);
point2 = new SystemPointF(maxPoint.X, startPoint.Y);
break;
case 90:
point1 = new SystemPointF(endPoint.X, y);
point2 = new SystemPointF(startPoint.X, maxPoint.Y);
break;
case 180:
point1 = new SystemPointF(maxPoint.X, startPoint.Y);
point2 = new SystemPointF(x, endPoint.Y);
break;
}
midPoint = new SystemPointF((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
actualCenter.X = x + ((x - midPoint.X) >= radius ? 0 : (x - midPoint.X));
actualCenter.Y = y + ((y - midPoint.Y) >= radius ? 0 : (y - midPoint.Y));
break;
case 2:
float minRadian = (float)(2 * Math.PI * region[0] / 360);
maxRadian = (float)(2 * Math.PI * (region[1]) / 360);
maxPoint = new SystemPointF((float)(x + radius * Math.Cos(maxRadian)),
(float)(y + radius * Math.Sin(maxRadian)));
SystemPointF minPoint = new SystemPointF((float)(x + radius * Math.Cos(minRadian)),
(float)(y + radius * Math.Sin(minRadian)));
if (region[0] == 0 && region[1] == 90 || region[0] == 180
&& region[1] == 270)
point1 = new SystemPointF(minPoint.X, maxPoint.Y);
else
point1 = new SystemPointF(maxPoint.X, minPoint.Y);
if (region[0] == 0 || region[0] == 180)
point2 = new SystemPointF(GetMinMaxValue(startPoint, endPoint, region[0]),
GetMinMaxValue(startPoint, endPoint, region[1]));
else
point2 = new SystemPointF(GetMinMaxValue(startPoint, endPoint, region[1]),
GetMinMaxValue(startPoint, endPoint, region[0]));
midPoint = new SystemPointF(Math.Abs(point1.X - point2.X) / 2 >= radius ? 0 : (point1.X + point2.X) / 2,
Math.Abs(point1.Y - point2.Y) / 2 >= radius ? 0 : (point1.Y + point2.Y) / 2);
actualCenter.X = x + (midPoint.X == 0 ? 0 : (x - midPoint.X) >= radius ? 0 : (x - midPoint.X));
actualCenter.Y = y + (midPoint.Y == 0 ? 0 : (y - midPoint.Y) >= radius ? 0 : (y - midPoint.Y));
break;
}
return actualCenter;
}
This works when startangle and sweep angle changed for all cases except the case startangle 179 and sweep angle changed to above 180. case 3 includes the region 180,270,0 . how to write calculations for regions 3.
Any help is really appreciated.
Thanks in advance
When you want to draw an object in the center of something you should do this :
Object.Point =
new Point((something.Width / 2) - (object.Widht /2) ,(something.Height / 2) - object.Height / 2));
I am creating a 2D physics engine, and I am having trouble with a certain type of collision between movable and immovable objects. What I mean by movable is that the (x,y) values can change, not that the frame of reference can or can't change.
For example, a ball hitting a wall would be something that is movable colliding with something immovable.
I believe that I need to use something like Normal Force in this situation, but I am no sure how that would be used for finding the outcome of the collision.
Here is the code that I have so far. This code is for collision between two moving entities, but I need to add a case for when one is not moving:
private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b)
{
var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X);
var angleA = a.Velocity.Direction - collisionAngle;
var angleB = b.Velocity.Direction - collisionAngle;
var vAx = a.Velocity.Magnitude * Math.Cos(angleA);
var vAy = a.Velocity.Magnitude * Math.Sin(angleA);
var vBx = b.Velocity.Magnitude * Math.Cos(angleB);
var vBy = b.Velocity.Magnitude * Math.Sin(angleB);
var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx) / (a.Mass + b.Mass)) * a.Material.Elasticity;
var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx) / (a.Mass + b.Mass)) * b.Material.Elasticity;
var vfAy = vAy * a.Material.Elasticity;
var vfBy = vBy * b.Material.Elasticity;
var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2));
var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2));
var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle;
var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle;
a.Velocity.X = magA * Math.Cos(dirA);
a.Velocity.Y = magA * Math.Sin(dirA);
b.Velocity.X = magB * Math.Cos(dirB);
b.Velocity.Y = magB * Math.Sin(dirB);
}
I tried setting the velocity of the immovable object to the opposite of the movable object's velocity, but that caused things to phase into each other.
I was able to get help from a friend and we worked out this algorithm to have objects reflect off of immovable objects during a collision.
Modified Original Function:
private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b)
{
var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X);
if (a.IsMoveable && b.IsMoveable)
{
var angleA = a.Velocity.Direction - collisionAngle;
var angleB = b.Velocity.Direction - collisionAngle;
var vAx = a.Velocity.Magnitude * Math.Cos(angleA);
var vAy = a.Velocity.Magnitude * Math.Sin(angleA);
var vBx = b.Velocity.Magnitude * Math.Cos(angleB);
var vBy = b.Velocity.Magnitude * Math.Sin(angleB);
var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx) / (a.Mass + b.Mass)) * a.Material.Elasticity;
var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx) / (a.Mass + b.Mass)) * b.Material.Elasticity;
var vfAy = vAy * a.Material.Elasticity;
var vfBy = vBy * b.Material.Elasticity;
var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2));
var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2));
var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle;
var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle;
a.Velocity.X = magA * Math.Cos(dirA);
a.Velocity.Y = magA * Math.Sin(dirA);
b.Velocity.X = magB * Math.Cos(dirB);
b.Velocity.Y = magB * Math.Sin(dirB);
}
else
{
var sign = Math.Sign(collisionAngle);
collisionAngle *= sign;
while (collisionAngle > Math.PI/2)
{
collisionAngle -= Math.PI / 2;
}
collisionAngle *= sign;
if (a.IsMoveable)
{
Reflection(ref a, b, collisionAngle);
}
else
{
Reflection(ref b, a, collisionAngle);
}
}
}
Reflection Function:
private static void Reflection(ref PhysicsEntity movable, PhysicsEntity immovable, double collisionAngle)
{
if (Math.Abs(collisionAngle - Math.PI / 2) < Universe.Epsilon)
{
// take the velocity vector, rotate it 180 degrees, scale it
movable.Velocity.X *= -1;
movable.Velocity.Y *= -1;
}
else if (Math.Abs(movable.Position.Y - immovable.Position.Y) < Universe.Epsilon ||
(movable.Position.X > movable.CollisionPoint.X ^ movable.Position.Y < movable.CollisionPoint.Y))
{
//take velocity vector, rotate CCW by 2*collisionAngle, scale it
var rotateAngle = 2 * collisionAngle;
var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle);
var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle);
movable.Velocity.X = xPrime;
movable.Velocity.Y = yPrime;
}
else
{
//take the vector, rotate it CCW by 360-2*collisionAngle, scale it
var rotateAngle = 2 * (Math.PI - collisionAngle);
var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle);
var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle);
movable.Velocity.X = xPrime;
movable.Velocity.Y = yPrime;
}
movable.Velocity.X *= movable.Material.Elasticity;
movable.Velocity.Y *= movable.Material.Elasticity;
}