Calculating a reflected arc - c#

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:

Related

3d cube y axis rotation not working properly

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 to find some additional points on a line between two points in 3D?

Is there a function in C# which can give me all the points on a straight line between two points in 3D?
To calculate the distance between those two points, I use this:
public class Position {
public float x;
public float y;
public float z;
}
public void CalculateDistance(Position position1, Position position2, int mapId){
float deltaX = position1.x - position2.x;
float deltaY = position1.y - position2.y;
float deltaZ = position1.z - position2.z;
float distance = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
Console.WriteLine("Distance is: " + distance);
}
Example coordinates:
Position pos1 = new Position();
pos1.x = 141.6586f;
pos1.y = 0.6852107f;
pos1.z = 153.2231f;
Position pos2 = new Position();
pos2.x = 142.336f;
pos2.y = 0.8685942f;
pos2.z = 130.8394f;
Let's say, the distance in line between those two 3d coordinates can be passed for 5 seconds. How can I print the current coordinate for every 1 second?
what you want to do is well described in this answer
And here is example of code how you can print your values:
var mx = pos2.x - pos1.x;
var my = pos2.y - pos1.y;
var mz = pos2.z - pos1.z;
for(var t=0; t < 10; t++) {
var x = pos1.x + mx * t;
var y = pos1.y + my * t;
var z = pos1.z + mz * t;
//TODO: use you 3D point
}
Hope this helps!

C# - generating points along a fraction of a circles circumference

I have the below algorithm which generates a number of points along the circumference of a circle for collision events in my program. (This works perfectly as far as I can tell).
bool Collision_True = false;
for (int Angle = 0; Angle <= 359; Angle += 5)
{
int X = (CentreX + (Radius * Math.Cos(Angle));
int Y = (CentreY + (Radius * Math.Sin(Angle));
Point point = new Point(X, Y);
if (Collision_True == false)
{
Collision_True = Player_Collisions(point);
}
}
return Collision_True;
However I want to change this so it only generates points on the bottom third of the circle, I tried changing the values in the for loop as follows:
for (int Angle = 120; Angle <= 240; Angle += 5)
{
...
}
But the points generated are still around the complete circumference of the circle instead of just the bottom third.
Any ideas? Thanks.
You need to convert to radians
for (int angleDegrees = 120; angleDegrees <= 240; angleDegrees += 5)
{
double angleRadians = angleDegrees / 180 * Math.PI;
int X = (CentreX + (Radius * Math.Cos(angleRadians));
int Y = (CentreY + (Radius * Math.Sin(angleRadians));
...

Rotate curve (serie of DataPoints) X degrees defined their new Baseline

I am using MSchart to plot serie into it, i need to rotate Curve (serie of datapoint) X degrees, P1 is fisrt click (mouseDown) and P2 second click (mouseUp), the angle between P1 and P2 represent the angle to rotate (i have this calculated), the problem is the curve deform when i apply different methods to do this
for (int x = 1; x < curve.nPoints; x++)
{
double X0 = curve.get_array_X[x];
double Y0 = curve.get_array_Y[x];
System.Windows.Media.Matrix m = new System.Windows.Media.Matrix();
m.Rotate(45 * (Math.PI / 180.0));
System.Windows.Vector v = new System.Windows.Vector(X0, Y0);
v = System.Windows.Vector.Multiply(v, m);
sAus.Points.AddXY(v.X, v.Y);
}
and this other code
public Series nueva(float X, float Y)
{
Series sAus = new Series(curvaActual.Tag);
int nearest1 = curvaActual.FindNearestXCV(new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X),
chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).XValue,
new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X), chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).YValues[0], 0, curvaActual.nPoints);
int nearest2 = curvaActual.FindNearestXCV(new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X),
chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).XValue,
new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X), chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).YValues[0], 0, curvaActual.nPoints);
double x1 = (double)curvaActual.get_array_X[nearest1];
double y1 = (double)curvaActual.get_array_Y[nearest1];
double x2 = (double)curvaActual.get_array_X[nearest2];
double y2 = (double)curvaActual.get_array_Y[nearest2];
double pendiente = Math.Atan2(y2 - y1, x2 - x1);
double anguloF = pendiente;
double deg = Math.PI * 45 / 180.0;
double coseno = Math.Cos(deg);
double seno = Math.Sin(deg);
double[] arrayX = new double[curvaActual.nPoints];
double[] arrayY = new double[curvaActual.nPoints];
for (int x = 1; x < curvaActual.nPoints; x++)
{
PointF rotatedPoint = RotatePoint(new PointF((float)curvaActual.get_array_X[x], (float)curvaActual.get_array_Y[x]), new PointF((float)curvaActual.get_array_X[x - 1], (float)curvaActual.get_array_Y[x - 1]), 45);
double angleRotatedPoint = angleFromPoint(rotatedPoint, new PointF((float)curvaActual.get_array_X[x - 1], (float)curvaActual.get_array_Y[x - 1]));
PointF pointROtado = RotatePoint(new PointF((float)curvaActual.get_array_X[x], (float)curvaActual.get_array_Y[x]), new PointF((float)0, (float)0), 45);
sAus.Points.AddXY((double)pointROtado.X, (double)pointROtado.Y);
}
return sAus;
}
[proof]
original serie
rotate 33
using your code (modify point to pointF)
void rotateSeries(Series src, Series tgt, DataPoint center, float angle)
{
PointF c = new PointF((float)center.XValue, (float)center.YValues[0]);
tgt.Points.Clear();
foreach (DataPoint dp in src.Points)
{
PointF p0 = new PointF((float)dp.XValue, (float)dp.YValues[0]);
PointF p = RotatePoint(p0, c, angle);
tgt.Points.AddXY(p.X, p.Y);
}
}
static PointF RotatePoint(PointF pointToRotate, PointF centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new PointF
{
X = (float)
(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y = (float)
(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
Here is one example of how you can do it. It..
assumes you have found the DataPoint center around which you want to rotate the graphic
assumes you have calculated the angle by which it shall be rotated
uses two Series s1 and s2, the first being the source and the latter the rotated target.
uses a version of RotatePoint from Fraser's anwser, slightly updated for PointF.
Here is the result for rotating around the 5th point by 33 degrees:
private void button1_Click(object sender, EventArgs e)
{
rotateSeries(s1, s2, s1.Points[4], 33);
}
void rotateSeries(Series src, Series tgt, DataPoint center, float angle)
{
PointF c = new PointF((float)center.XValue, (float)center.YValues[0]);
tgt.Points.Clear();
foreach (DataPoint dp in src.Points)
{
PointF p0 = new Point((float)dp.XValue, (float)dp.YValues[0]);
PointF p = RotatePoint(p0, c, angle);
tgt.Points.AddXY(p.X, p.Y);
}
}
static PointF RotatePoint(PointF pointToRotate, PointF centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new PointF
{
X = (float)
(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y = (float)
(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
If you want to use the MouseClick to determine the angle you can use the Points from the e parameter directly. But to find out the center you will need to convert the pixel coordinates to chart value coordinates.
Here is a call you can use during the MouseClick event:
DataPoint clickedValuePoint(ChartArea ca, Point pt)
{
return new DataPoint(ca.AxisX.PixelPositionToValue(pt.X),
ca.AxisY.PixelPositionToValue(pt.Y));
}
Now let's see it at work, using a DataPoint:
DataPoint centerPoint = null;
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
ChartArea ca = chart1.ChartAreas[0];
centerPoint = clickedValuePoint(ca, e.Location);
rotateSeries(s1, s2, centerPoint, 33);
}

Algorithm for finding a point in an irregular polygon

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

Categories

Resources