Vertical Curve Formula - c#

I'm making just a basic application that just writes pixels along a curve in C#.
I came across this website with a formula that looks promising. I believe this website is also talking about the same thing here.
What I don't really understand is how to implement it. I tried looking at the JavaScript code on the first link but I can't really tell what data I need to supply. The things involving the PVC, PVI, or PVT are the things I don't understand.
The example situation I'm going to set up is just both of the grades (vertical incline/decline) is just 5 and -5. Let's say point 1 is at 0, 0 and point 2 is 100, 100.
Can someone explain some of the obscure variables in the formula and how would I use the formula to draw the curve?

Generally, to draw a curve in 2D you vary one parameter, and then collect x,y point pairs, and plot the pairs. In your case it will work to just vary the horizontal distance (x), and then collect the corresponding y-values, and then you can plot these.
As for the formula, it is very unclear. Basically it's just a parabola with a bunch of (poorly defined) jargon around it. To graph this, you want to vary x from 0 to L (this isn't obvious, btw, I had to work out the math, i.e., how to vary x so that the slopes would be as they suggest in the figure, anyway, it's 0 to L, and they should have said so).
I don't have C# running now, but hopefully you can translate this Python code:
from matplotlib.pyplot import plot, show
from numpy import arange
G1 = .1 # an initial slope (grade) of 10% (note that one never uses percentages directly in calculations, it's always %/100)
G2 = -.02 # a final slope (grade) of 2%
c = 0 # elevation (value of curve when x=0, that is, y at PVC
L = 10. # the length of the curve in whatever unit you want to use (ft, m, mi, etc), but this basically sets your unit system
N = 1000 # I'm going to calculate and plot 100 points to illustrate this curve
x = arange(0, L, float(L)/N) # an array of N x values from 0 to (almost) L
# calculate the curve
a = (G2-G1)/(2*L)
b = G1
y = a*x*x + b*x + c # this is shorthand for a loop y[0]=a*x[0]*x[0] + b*...
plot(x, y)
show()
print (y[1]-y[0])/(x[1]-x[0]), (y[-1]-y[-2])/(x[-1]-x[-2])
The final line prints the initial and final slopes as a check (in Python neg indexing counts from the back of the array), and this match what I specified for G1 and G2. The plot looks like:
As for your requests: "The example situation I'm going to set up is just both of the grades (vertical incline/decline) is just 5 and -5. Let's say point 1 is at 0, 0 and point 2 is 100, 100.", in a parabola you basically get three free parameters (corresponding to a, b, and c), and here, I think, you over-specified it.
What are PVC, PVT, and PVI? PVC: the starting point, so Y_PVC is the height of the starting point. PVT: the ending point. PVI: if you draw a line from PVC at the initial slope G1 (ie the tangent to the curve on the left), and similarly from PVT, the point where they intersect is called PVI (though why someone would ever care about this point is beyond me).

Related

How do you calculate a rectangular wave from input values?

Here's a picture to make it a little easier:
The blue line represents some input values that resemble waves with variable amplitudes and lengths. The y axis represents the values, the x axis represents time. Please note that there is quite some jitter in the wave. However, every wave has a certain minimum and maximum length.
The green line shows how the input values should be transformed.
Please note: The above picture is just a hand drawn example to explain the task. In an ideal case, the position of the rising and falling edges of the rectangular (green) wave are close to the blue waves average value. The height/amplitude of the green wave segments should match the values of the blue wave.
How do you calculate the green line?
Do you know of any C# libraries or algorithms to do that? I guess this could be a rather common task for electrical engineers, so there are most likely some common approaches available. If so, how are hey called?
How would you approach this requirements?
Any advice that helps in getting started is welcome.
Take a base frequency (f) at an amplitude (a).
Then add ODD harmonics with the inverse amplitude ie f * a + f3 * a/3 + f5 * a/5 + f7 * a/7 ...
This will tend towards a square wave as you add harmonics.
BTW Try doing the same with even harminics, and with all the harmonics - Great fun!!!
Good luck
Tony

Check if the mouse is over a Bézier curve [duplicate]

This question already has answers here:
Closest point on a cubic Bezier curve?
(6 answers)
Closed 4 years ago.
My approach was to loop trough the curve and check the mouse distance to various points
But the points get closer together as the curve get steeper, and if the mouse distance threshold is too high it prioritizes the first point in the loop instead of the closet to the mouse.
is there a way to get uniform points in it? Or to check if the mouse is over the Bézier curve and get the position in the curve?
I do it like this:
subdivide you curve to few chunks
tne number of chunks depends on the order of curve. As I usually use cubics I empirically find out that ~8 chunks is enough (for my purposes).
compute the closest point to a chunk
So simply handle each chunk as line and compute closest point on the line to the mouse position (minimal perpendicular distance). By computing it for each chunk and remember the closest one.
Now after this we know which chunk contain the "closest" point so from the intersection between line and perpendicular line to it going through mouse position from previous step we should have a parameter u=<0,1> telling us where on the chunk line the closest point is and we also know the curve parameter t of both endpoints of the chunk line (t0,t1). From this we can approximate t for the closest point simply by doing this:
t = t0 + (t1-t0)*u
On the image t0=0.25 and t1=0.375. This is sometimes enough but if you want better solution so after this just set:
dt = (t1-t0)/4
t0 = t-dt
t1 = t+dt
Use the t0,t,t1 to compute 3 endpoints of 2 chunks and look for the closest point again. You can recursively do this few times as with each iteration you increase precision of the result
The perpendicular distance of point to a line is computed by computing intersection between the line and axis perpendicular to it going through the point in question. So if the line is defined by endpoints p0,p1 and the queried point (mouse) is q then the axis in 2D will be:
dp=p1-p0 // line direction
dq=(dp.y,-dp.x) // axis direction is perpendicular to dp
dq/= |dq| // normalize
p(u) = p0+dp*u // point on line
p(v) = q +dq*v // point on axis
u = <0,1> // parameter on line
v = <-inf,+inf> // parameter on axis
And we want to know u,v from
p0+dp*u = q +dq*v
which is system of 2 linear equations in 2D. In 3D you need to exploit cross product to obtain the dq and the system would contain 3 equations. Solving this sytem will give you u,v where u will tell you where in the chunk the closest point is and |v| is the perpendicular distance itself. Do not forget that if u is not in the range <0,1> then you have to use closer endpoint of the line as the closest point.
The system can be solved either algebraically (but beware the edge cases as there are 2 solutions for the equations in 2D) or use inverse matrix...
There are two main approaches - subdivision of curve into small line segments and analytical solution.
For the second case you have to build polynomial for squared distance from point to curve depending on parameter t, differentiate it, and find zeros of result (5-th order polynomial). Then choose minimum from distances to point at t[i], t=0, t=1.
Another point of view - get projection of point onto curve, so curve tangent in this point is perpendicular to vector point-curvepoint, it should give the same expression.
About uniform points - it is rather hard problem because curve length could not be calculated analytically. But subdivision gives quite good approximation.

converting xinput coordinates to a square

i'm working on a small c# program that uses xinput to read the xbox 360 thumb stick.
i have no problem with reading the coordinates and normalizing the values so i get a float between -1 and +1 for X and Y directions.
the problem i have is that the stick itself is physically limited to a circle and in my case i would like to "stretch out" the coordinates so it becomes more of a square than a circle.
the reason is that each direction is controlling a motor and if i move the stick for example top right i would like both X and Y to become 1.
since the stick is circular this is not possible and this also makes it impossible to make both motors run at full speed.
any advice?
So you want a point on a circle of radius r to be mapped to a point on a square of radius r on the same ray through the origin. Toward that goal you have to compute the radius using the usual formula
r = sqrt(x*x+y*y)
and then from that the scale factor
f = r / max ( abs(x), abs(y) )
and in the end replace x by f*x and y by f*y.
One can vary this computation by noting that the factor is
f = sqrt ( 1 + (x*x)/(y*y) )
if abs(y) > abs(x) and
f = sqrt ( 1 + (y*y)/(x*x) )
in the opposite case. Or by noting that the largest coordinate gets replaced by r and the smaller scaled accordingly, which also does not reduce the logistics by much.

Barrel Distortion - Correcting image when expected/received control points are known

I'm working with a mounted industrial CCD camera and I have no information about its parameters. When an image is taken programmatically over WinUSB, the result in figure 1 is received. What you will notice is that the gaps between the lines differ greatly in the image. This is not the case in the actual image.
I have a technique for determining the location of the lines and have a list of pixel coordinates for where the lines must occur in a non-distorted image.
So I have
The pixel coordinate of the lines when the image is taken
The pixel coordinates of where the lines should be
What I need to do
Use these values to apply to every subsequent image taken with the camera, so that
each image is corrected.
However, I am pretty stuck on exisiting techniques which follow this approach. I know many algorithms exist on the internet which either make use of lens parameters or a strength parameter, but these techniques aren't very suitable in my scenario. The parameters aren't known and adjusting a strength value by the eye is not accurate enough.
Any pointers on techniques would be of great help; as I'm currently at a loss.
Figure 1. Distorted image taken by fixed location CCD camera
Hum, can you explain why the standard calibration techniques aren't suitable? You don't need to know the "true" camera parameters, but you do need to estimate the linear (actually, affine) part of the distortion, which is almost the same thing.
Explanation: assuming you are dealing with a plain old spherical-like lens, the first model I'd try for your case is a two-parameter radial distortion of the form:
X = f * |x - c|
Y = k1 * X^2 + k2 * X^4
y = c + Y / f
where
x = (u, v) are the distorted pixel coordinates;
c = (cu, cv) is an unknown center of distortion (i.e. the place in the image with zero
distortion, usually on (or very close to) the lens's focal axis.
|x -c| is the radial distance of x from c in the distorted image
f is an unknown scale factor
X is the location of the distorted pixel in scaled-centered coordinates
k1 and k2 are unknown distortion coefficients
Y is the undistorted pixel in scaled-centered coordinates
y is the undistorted pixel, located on the same radius c->x as x, at a distance Y/f from c.
So your unknowns are cu, cv, f, k1 and k2. It's starting to look like a camera calibration problem, isn't it?
Except you don't really need to estimate a "true" focal length f, since (I assume) you are not interested in computing rays in 3D space. So you can simplify the problem by assigning f as the value that makes the diameter of your data point distribution equal to, say, 2, so that all the centered-scaled points X will have coordinates no larger than 1.0 in absolute value. This helps in two ways: it improves the numerical conditioning of the problem, and drops the number of unknowns to 4.
You can usually initialize the estimation by using the center of your image for c, and zero values for k1 and k2, plug your data in your favorite least-squares optimizer, run, get the solution for the unknowns, and verify that it makes sense (on additional independent images). Rinse and repeat until you get something satisfactory.
Note that you can enrich the data set used for the estimation by using more than one image, assuming, of course, that the lens parameters are constant.

C# Date/Numerical Axis Scale

I'm developing a histogram container class and I'm trying to determine where the cut off points should be for the bins. I'd like the cutoff points to be nice looking numbers, in much that same way that graphs are scaled.
To distill my request into a basic question: Is there a basic method by which data axis labels can be determined from a list of numbers.
For example:
Array{1,6,8,5,12,15,22}
It would make sense to have 5 bins.
Bin Start Count
0 1
5 3
10 2
15 0
20 1
The bin start stuff is identical to selecting axis labels on a graph in this instance.
For the purpose of this question I don't really care about bins and the histogram, I'm more interested in the graph scale axis label portion of the question.
I will be using C# 4.0 for my app, so nifty solution using linq are welcome.
I've attempted stuff like this in the distant past using some log base 10 scaling stuff, but I never got it to work in great enough detail for this application. I don't want to do log scaling, I just used base 10 to round to nearest whole numbers. I'd like it to work for large numbers and very small numbers and possibly dates too; although dates can be converted to doubles and parsed that way.
Any resources on the subject would be greatly appreciated.
You could start with something simple:
NUM_BINS is a passed argument or constatn (e.g. NUM_BINS = 10)
x is your array of x-values (e.g. int[] x = new int[50])
int numBins = x.Length < NUM_BINS ? x.Length : NUM_BINS;
At this point you could calc a histogram of xPoints, and if the xPoints are heavily weighted to one side of distribution (maybe just count left of midpoint vs. right of midpoint), then use log/exp divisions over range of x[]. If the histogram is flat, use linear divisions.
double[] xAxis = new double[numBins];
double range = x[x.Length-1] - x[0];
CalcAxisValues(xAxis, range, TYPE); //Type is enum of LOG, EXP, or LINEAR
This function would then equally space points based on the TYPE.

Categories

Resources