Formula to compute an arcuate segment length - c#

Considering the class:
public class Point3D
{
public double X;
public double Y;
public double Z;
public Point3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public double DistanceTo(Point3D to)
{
double dX = Math.Abs(to.X - X);
double dY = Math.Abs(to.Y - Y);
double dZ = Math.Abs(to.Z - Z);
return Math.Sqrt(dX * dX + dY * dY + dZ * dZ);
}
}
And the class:
public class Segment
{
public Point3D From;
public Point3D To;
public double? Radius;
public Segment(Point3D from, Point3D to, double? radius)
{
From = from;
To = to;
Radius = radius;
}
public double Length
{
get
{
double straightLength = From.DistanceTo(To);
if (Radius == null)
return straightLength;
if (Radius < straightLength/ 2d)
throw new Exception();
// Compute the arcuate segment length
}
}
}
I would like to compute the length of the arc (with Radius) passing through From and To 3D points.
Some help will be welcome!

According to http://mathworld.wolfram.com/IsoscelesTriangle.html
straightLength / 2 = Radius * sin( 1/2 * angle)
Therefore:
angle = 2 * arcsin( straightLength / 2 / Radius)
and
arcLength = Radius * angle;

One more reference:
from math.stackexchange
S=length of the arc = r*theta,
where r= radius and Cos(theta)=(dotproduct of 2 vectors)/(product of the modulus of those vectors)

Related

Algorithm for finding new points of rotating a vector

I am trying to programmatically find the point created from rotating a vector around it's origin point (could be anywhere in 2D space).
We see that we have our line (or vector for the math) A at some point of (x, y) that might be anywhere in 2D space. It runs to point B at some (x, y). We rotate it by Theta which then moves to some point C at an (x, y). The problem for me comes with trying to programmatically use math to solve for such.
Originally the thought was to form a triangle and use trig but this angle could be exactly 180 (unlikely but possible) which obviously no triangle can work. Would anyone have ideas?
I am using C# and my own vector object (below) to test out the creation of lines. Any help is appreciated!
struct Vector2D {
double x, y, theta;
Vector2D(double x, double y) {
(this.x, this.y) = (x, y);
theta = x != 0 ? Math.Atan(y / x) : 0;
}
double Magnitude() {
return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
}
(double,double) PointFromRotation(double angle) {
// This is where I need some help...
return (0,0); // hopefully a point of x and y from the angle argument
}
}
I think it would be best to use the following code.
I've made some minor modifications and supplements to your code.
The calculation part of 'theta' was slightly modified.
And, you can refer to the rotation algorithm from the following URL.
Rotation (mathematics)
struct Vector2D
{
public double x;
public double y;
public double theta;
public Vector2D(double x, double y)
{
(this.x, this.y) = (x, y);
theta = x != 0 ? Math.Atan(y / x) : Math.Sign(y) * Math.PI / 2.0;
}
public double Magnitude()
{
return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
}
public (double x, double y) PointFromRotation(double angle)
{
double Sint = Math.Sin(angle);
double Cost = Math.Cos(angle);
double rX = x * Cost - y * Sint;
double rY = x * Sint + y * Cost;
return (rX, rY);
}
}
You can convert cartesian coordinates (x, y) into polar ones (R, fi),
add theta to fi and then convert back to cartesian:
// Rotate B around A by angle theta
private static (double x, double y) Rotate(
(double x, double y) A,
(double x, double y) B,
double theta) {
double fi = Math.Atan2(B.y - A.y, B.x - A.x) + theta;
double R = Math.Sqrt((A.y - B.y) * (A.y - B.y) + (A.x - B.x) * (A.x - B.x));
return (A.x + R * Math.Cos(fi), A.y + R * Math.Sin(fi));
}
the only possible difficulty is to compute fi which can be done with a help of Math.Atan2 method.
Another option:
// Rotate B around A by angle theta clockwise
private static (double x, double y) Rotate(
(double x, double y) A,
(double x, double y) B,
double theta)
{
double s = Math.Sin(theta);
double c = Math.Cos(theta);
// translate point back to origin:
B.x -= A.x;
B.y -= A.y;
// rotate point clockwise
double xnew = B.x * c - B.y * s;
double ynew = B.x * s + B.y * c;
// translate point back:
B.x = xnew + A.x;
B.y = ynew + A.y;
return B;
}
inspired by this answer

Changing the value of a variable in a function and using it in outside the scoop

I need to declare 3 variables in a class ,and creat a funtion to assign these variables to other values ,and creat another function to calculate the distance The new values are unreachable ,and my Changed(X/Y/Z) are always zero
class Point3D
{
public double x, y, z, ChangedX = 0, ChangedY = 0, ChangedZ = 0;
public void MoveTo(double NewX, double NewY, double NewZ)
{
x = NewX;
NewX = ChangedX;
y = NewY;
NewY = ChangedY;
z = NewZ;
NewZ = ChangedZ;
}
public double DistanceTo()
{
double DeltaX = Math.Pow((ChangedX - x), 2);
double DeltaY = Math.Pow((ChangedY - y), 2);
double DeltaZ = Math.Pow((ChangedZ - z), 2);
return Math.Sqrt(DeltaX + DeltaY + DeltaZ);
}
Also, I've started studying OOP not a long while ago
Are there any resources of courses that you recommend that may help me?
If I correctly understood the intention of your code, that is what I would do in your case:
internal class Point3D
{
public double x = 0, y = 0, z = 0, PreviousX, PreviousY, PreviousZ;
public void MoveTo(double NewX, double NewY, double NewZ)
{
PreviousX = x; // remember previous value to use in delta calculation
x = NewX;
PreviousY = y;
y = NewY;
PreviousZ = z;
z = NewZ;
}
public double DistanceTo()
{
double DeltaX = Math.Pow((x - PreviousX), 2);
double DeltaY = Math.Pow((y - PreviousY), 2);
double DeltaZ = Math.Pow((z - PreviousZ), 2);
return Math.Sqrt(DeltaX + DeltaY + DeltaZ);
}
}
As to courses recommendation, when you start it's always good to see some video courses at the beginning, for example https://www.pluralsight.com/courses/object-oriented-programming-fundamentals-csharp (you can see this course at their site, or search the web).

Calculating temporary coordinate if distance exceeds 100

I have a problem with coding a function that will do the following:
Function will take 2 sets of coordinates (x,y,z). First set is starting point and second one is end point.
Now first i will have to determine distance between those two points. If distance will be greater than lets say 100 then i will have to calculate a temporary point. I will then calculate distance between first set of coordinates and this temporary point. Please check illustration below i am sure things will be much more understandable.
Function that calculates new point between points A,B:
x = (x1+x2/2)
y = (y1+y2/2)
z = (z1+z2/2)
Function that calculates distance is:
public float DistanceTo(float x, float y, float z, float x2, float y2, float z2)
{
float a = x - x2;
float b = y - y2;
float c = z - z2;
return Math.Sqrt(a * a + b * b + c * c);
}
Link to illustration:
Perhaps my approach will be CPU heavy and perhaps slow (?) but currently i am out of ideas how to approach the problem.
Basically i need a function that will go from A to B in increments if (distance < 100).
Thank you for reading and thanks for any solution posted!
PS please dont make fun of my paint skills :)
Compute the distance d from (xb,yb,zb) (begin) to (xe,ye,ze) (end). Compute the number of parts N=(int)((d-1)/100)+1. Compute
xk = xb + (k*(xe-xb))/N
yk = yb + (k*(ye-yb))/N
zk = zb + (k*(ze-zb))/N
for k=1,...,N-1 to get equally spaced points on the segment with a distance not surpassing 100.
You can do it recursively
create a Point struct that represent a point in R3, with 2 utility methods to calculate the distance and midpoint.
struct Point
{
public double x;
public double y;
public double z;
public double Distance(Point b)
{
return Math.Sqrt(Math.Pow(b.x - this.x, 2) +
Math.Pow(b.y - this.y, 2) +
Math.Pow(b.z - this.z, 2));
}
public Point MidPoint(Point b)
{
return new Point()
{
x = (this.x + b.x) / 2,
y = (this.y + b.y) / 2,
z = (this.z + b.z) / 2
};
}
}
and write a simple recursive function that will calculate the distance and call itself recursively until the distance between point a and the temp point is less than maxSegmentLength which is 100 in your case:
public static Point GetPoint(Point a, Point b, double maxSegmentLength)
{
var distance = a.Distance(b);
if (distance < maxSegmentLength)
return b;
else
return GetPoint(a, a.MidPoint(b),maxSegmentLength);
}
Or more efficiently with vectors:
struct Vector
{
public double Vx;
public double Vy;
public double Vz;
public double R;
public Vector(Point a,Point b)
{
R = a.Distance(b);
Vx = (b.x - a.x)/R;
Vy = (b.y - a.y)/R;
Vz = (b.z - a.z)/R;
}
}
public static Point GetPoint(Point a, Point b,double maxSegmentLength)
{
var Vab = new Vector(a, b);
var dAC = Vab.R;
while (dAC > maxSegmentLength) { dAC /= 2; } //or replace this line and the one above it with var dAC=Math.Pow(0.5,(int)(-(Math.Log(maxSegmentLength / Vab.R) / Math.Log(2))) + 1)*Vab.R;
return new Point() {
x = a.x + Vab.Vx * dAC ,
y = a.y + Vab.Vy * dAC ,
z = a.z + Vab.Vz * dAC
};
}
If the point is always at a midpoint then its distance is always half of the original
public double Calc(Point A, Point B)
{
double d = Distance(A,B);
while(d>100)
{
d/=2;
}
return d;
}

Best method to check if a point lies on an arc in c#

What I want to do should be simple but it has been a while since I studied math.
Let's say I have Point and Arc classes as below. How can I check if the Point p lies on Arc a.
public class Point
{
public double X;
public double Y;
}
public class Arc
{
public double Radius;
public double StartAngle;
public double EndAngle;
// center of the arc
public double Xc;
public double Yc;
}
Point p = new Point() { X = 5, Y = 5 };
Arc a = new Arc()
{
Radius = 5,
StartAngle = 0,
EndAngle = Math.PI/2,
Xc = 0,
Yc = 0
};
I came up with this answer which is posted here for future reference. I know it is not the most efficient method but it does the job.
// first check if the point is on a circle with the radius of the arc.
// Next check if it is between the start and end angles of the arc.
public static bool IsPointOnArc(Point p, Arc a)
{
if (p.Y * p.Y == a.Radius * a.Radius - p.X * p.X)
{
double t = Math.Acos(p.X / a.Radius);
if (t >= a.StartAngle && t <= a.EndAngle)
{
return true;
}
}
return false;
}

Implementing Geofence - C#

I need to implement Geofence in C#. Geofence area can be round, rectangle, polygon etc. Does anyone have Geofence implementation in C#?
I found Geo Fencing - point inside/outside polygon. But, it supports polygon only.
I have tested various implementations and this example worked properly for me:
Example
public static bool PolyContainsPoint(List<Point> points, Point p) {
bool inside = false;
// An imaginary closing segment is implied,
// so begin testing with that.
Point v1 = points[points.Count - 1];
foreach (Point v0 in points)
{
double d1 = (p.Y - v0.Y) * (v1.X - v0.X);
double d2 = (p.X - v0.X) * (v1.Y - v0.Y);
if (p.Y < v1.Y)
{
// V1 below ray
if (v0.Y <= p.Y)
{
// V0 on or above ray
// Perform intersection test
if (d1 > d2)
{
inside = !inside; // Toggle state
}
}
}
else if (p.Y < v0.Y)
{
// V1 is on or above ray, V0 is below ray
// Perform intersection test
if (d1 < d2)
{
inside = !inside; // Toggle state
}
}
v1 = v0; //Store previous endpoint as next startpoint
}
return inside;
}
Refer to my Implementation:
Polygon
Circle
Adding both C# implementation here
It worked for me!
//Location will hold the latitude and longitude.
public class Location
{
public double lat { get; set; }
public double lng { get; set; }
public Location(double lat, double lng)
{
this.lat = lat;
this.lng = lng;
}
}
//Implementation for the Polygon.
bool IsPointInPolygon(List<Location> poly, Location point)
{
int i, j;
bool c = false;
for (i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
{
if ((((poly[i].lat <= point.lat) && (point.lat < poly[j].lat))
|| ((poly[j].lat <= point.lat) && (point.lat < poly[i].lat)))
&& (point.lng < (poly[j].lng - poly[i].lng) * (point.lat - poly[i].lat)
/ (poly[j].lat - poly[i].lat) + poly[i].lng))
{
c = !c;
}
}
return c;
}
//Geofencing for the Circle.
//GetDistance will return total Kilometers
//p1 is the Center lat,long and p2 is the current location lat,long
//radius in meters
public bool IsPointInCircle(Location p1,Location p2,double radius)
{
return GetDistance(p1,p2)>radius*0.001?false:true;
}
public double GetDistance(Location pos1, Location pos2)
{
double e = pos1.lat * (Math.PI / 180);
double f = pos1.lng * (Math.PI / 180);
double g = pos2.lat * (Math.PI / 180);
double h = pos2.lng * (Math.PI / 180);
double i =
(Math.Cos(e) * Math.Cos(g) * Math.Cos(f) * Math.Cos(h)
+ Math.Cos(e) * Math.Sin(f) * Math.Cos(g) * Math.Sin(h)
+ Math.Sin(e) * Math.Sin(g));
double j = Math.Acos(i);
return (6371 * j);
}

Categories