Smoothness of data generated by C++ - c++

I am trying to plot a function (gaussian function) with C++. The problem is that the outputs are not smooth and plot looks jagged. Below I attach the output of the same function one made with MATLAB and the other with C++ (Note: Plot is zoomed in so just the peak of function is visible to clarify the difference). And here is the C++ code:
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
int main(){
int matrix = 100000;
long double y[matrix], x=0.0, step=0.1;
double FWHM = 1000, alpha;
alpha = FWHM/(2*log(2));
for (int i=0; i<matrix; i++) {
x = x + step;
y[i] = exp(-pow((x-3000.0),2.0)/pow(alpha,2.0));
}
}
and this is MATLAB code:
matrix = 100000;
x=0.0; step=0.1;
FWHM = 1000;
alpha = FWHM/(2*log(2));
for i=1:matrix
x = x + step;
y(i) = exp(-((x-3000.0).^2.0)/alpha.^2.0);
end

How do you store data and plot that? Based on the graph shape, I think you dump y[i] in a text file, read from matlab, and plot them. Also I suspect you didn't set the precision while printing. If you don't set the precision, the default is 6, thus the output will be jagged as you mentioned (like, 11 of 1's in the graph and in the output).
Generally, it is not a good idea to dump double data in a text file, as you will lose precision. Use binary data, like hdf5, protobuf, etc...
std::cout << y[i] << std::endl;
std::cout << std::setprecision(16) << y[i] << std::endl;
The
# without std::setprecision. There are 11 of 1's. The graph has 11 of 1's too.
0.999998
0.999998
0.999999
0.999999
0.999999
1
1
1
1
1
1
1
1
1
1
1
0.999999
0.999999
0.999999
0.999998
# with std::setprecision
0.999998078189791
0.9999984433334466
0.9999987700410408
0.9999990583125361
0.9999993081478993
0.9999995195471015
0.9999996925101183
0.9999998270369299
0.9999999231275207
0.9999999807818797
1
0.9999999807818797
0.9999999231275207
0.9999998270369299
0.9999996925101183
0.9999995195471015
0.9999993081478993
0.9999990583125361
0.9999987700410408
0.9999984433334466

Related

Cubic function using pow() yielding incorrect values

I want to use a cubic function but I am getting incorrect values when compared to desmos.
I am currently using pow(), but have tried simply multiplying these numbers by themselves but got the same results.
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int distance = 1500;
double aX = (4.8264*pow(10,-8))*distance;
double bX = 0.000364*distance;
double cX = -0.8495*distance;
double rate = -pow(aX,3.0) + pow(bX,2.0) + cX + 592.628;
cout << rate << endl;
return 0;
}
I'm expecting rate to equal values ranging between -40 and 25, but I'm getting values starting at -681 and decreasing from there (I'm testing int distance at 1500 to 3300). Here is the desmos graph that I am using for the function and expected results: https://www.desmos.com/calculator/g9sdww9c9v.
Sorry about this post lol. Looks like I just needed to review what coefficients are because I was cubing and squaring those. All working now

Superimpose a line on a histogram in Gnuplot

I use C++ in Xcode on Mac and a pipe method to communicate with Gnuplot. I am interested in converting my arrays into graphs directly through the program, after I run it. Using
FILE *f = popen("gnuplot -persist", "w");
I open the file and then communicate using fprintf.
Now, I have some data in arrays of interest. w is a "proposed" array of standard normal variables and I intend to check if it is indeed a Gaussian distribution with mean = 0 and variance = 1 .To do that I plot a histogram. After that I want to superimpose a real Gaussian function, which has ex as a x coordinate values and gauss as y coordinate values directly on the histogram. How can I do that?
Here's the code so far:
double start = -4; //min
double end = 4 ; //max
double numberofbins = 100;
double width = (end-start)/numberofbins ;
fprintf (f,
"set ylabel '# of elements'\n"
"set xlabel 'The numbers'\n"
"Min = %g\n" //where binning starts
"Max = %g\n" // where binning ends
"n = %g\n" // the number of bins
"width = 10**(-1)\n" // binwidth; (Max-Min)/n
"bin(x) = width*(floor((x-Min)/width)+0.5) + Min\n"
"f(x)= e**((-x**2)/2) / sqrt(2*pi)\n"
"plot '-' using (bin($1)):(1) smooth freq with boxes,'' u $2:$3 with lines linestyle 1\n",start,end,numberofbins)
for (int i= 0; i < numberofpoints; i++){
fprintf(f, "%g %g %g\n", w[i], ex[i], gauss[i]);
}
fclose(f);
Here is the result if I run the demonstrated code:
As we can see, the binning was successful but the line was omitted and gives the following error:
gnuplot> plot '-' using (bin($1)):(1) smooth freq with boxes,'' u $2:$3 with lines linestyle 1
^
line 100000: column() called from invalid context
I have checked online but nobody is practicing communicating with Gnuplot that way.
If I plot only the 2:3 part (without binning), I get this graph:
Thus, the problem might be with the compatibility of these two plots.
there are different ways to plot "inline" data
plot '-' u 1:2 w lines
1 11
2 22
3 33
e
From gnuplot help special-filenames
If you use both '-' and '' on the same plot command, you'll need to
have two sets of inline data, ...
This means:
plot '-' u 1:2 w boxes, '' u 1:2 w lines
1 11
2 22
3 33
e
1 11
2 22
3 33
e
So, instead, I would generate a datablock in the beginning of your generated command string and reuse the data as many times as you need it during your plotting command.
$Data <<EOD
1 11
2 22
3 33
EOD
plot $Data u 1:2 w boxes, '' u 1:2 w lines
I have solved the problem by creating a second y axis on the same graph and plotting according to it. The code used was:
fprintf (f,
"set xlabel 'The numbers'\n"
"Min = %g\n" //where binning starts
"Max = %g\n" // where binning ends
"n = %g\n" // the number of bins
"width = 10**(-1)\n" // binwidth; (Max-Min)/n
"bin(x) = width*(floor((x-Min)/width)+0.5) + Min\n"
"set ytics 100 nomirror tc lt 1\n"
"set ylabel '# of elements' tc lt 1\n"
"set y2tics 0.4 nomirror tc lt 2\n"
"set y2label 'Theoretical Gaussian' tc lt 2\n"
"plot '-' using (bin($1)):(1) smooth freq with boxes title 'Generator Histogram','-' u 1:2 with l axes x1y2 title 'Theoretical Gaussian (mean=0, std = 1)'\n",start,end,numberofbins) ;
for (int i= 0; i < numberofpoints; i++){
fprintf(f, "%g\n", w[i]);
}
fprintf(f,"e\n");
for (int i= 0; i < numberofpoints; i++){
fprintf(f, "%g %g\n",ex[i], gauss[i]);
}
fprintf(f,"e\n");
fclose(f);
which plots this:

Why I get an incorrect answer when I substract 180 from the sum of the two angles when the sum itself shows as 180?

The program gets 4 points(their coords) that form a convex figure and should give me the angle A2+angle A4 - 180 degrees. For the example :
1 3
0 2
1 1
2 2
I get uA2=90 and uA4=90, but when I do uA2+uA4-180 I get 2.0568e-007, instead of 0. But when I do just uA2+uA4 I get 180. I am sorry if a similar question was asked, but I didn't know how to search for it. Can anyone tell me why it happens and how can I repair it to show the right answer? Tho code:
#include <iostream>
#include <fstream>
#include <cmath>
#define PI 3.14159265
using namespace std;
ifstream f("date.in");
struct punct
{
double x,y;
}A1,A2,A3,A4;
int main()
{
double uA2,uA4;
f>>A1.x>>A1.y>>A2.x>>A2.y>>A3.x>>A3.y>>A4.x>>A4.y;
//calculate cos of both angles
uA2=((A1.x-A2.x)*(A3.x-A2.x)+(A1.y-A2.y)*(A3.y-A2.y))/
(sqrt((A1.x-A2.x)*(A1.x-A2.x)+(A1.y-A2.y)*(A1.y-A2.y))*sqrt((A3.x-A2.x)*(A3.x-A2.x)+(A3.y-A2.y)*(A3.y-A2.y)));
uA4=((A1.x-A4.x)*(A3.x-A4.x)+(A1.y-A4.y)*(A3.y-A4.y))/
(sqrt((A1.x-A4.x)*(A1.x-A4.x)+(A1.y-A4.y)*(A1.y-A4.y))*sqrt((A3.x-A4.x)*(A3.x-A4.x)+(A3.y-A4.y)*(A3.y-A4.y)));
//calculate angles
uA2=acos(uA2)*180.0/PI;
uA4=acos(uA4)*180.0/PI;
//the part that gives me an incorrect answer
cout<<uA2+uA4-180<<endl;
}
For floating point computation, we can use some very small offset value for marginal error, for example 1e-6.
double diff = uA2 + uA4 - 180, threshold = 1e-6;
if (diff < threshold && diff > -threshold) cout << "0" << endl;
else cout << diff << endl;
// cout<<uA2+uA4-180<<endl;

About EulerAngles Conversion from Eigen C++ Library

Suppose that I have a 3-dimensional frame with rotation roll = 0, pitch = 0 and yaw = 0 about x, y and z axis respectively.
I want the frame to rotate about x-axis for 3.14159 (Pi) or roll = Pi.
Below is the code for said situation.
The problem is, when I want to convert the rotation matrix back to roll, pitch, and yaw, the code gives different answer.
Instead of roll = Pi, the result is roll = 0, pitch = pi, and yaw = pi.
I think RVC toolbox by Peter Corke on Matlab gives correct answer.
Maybe something is not right with with my program or eulerAngles in Eigen works differently? Please help.
Code:
#include <iostream>
#include <Eigen/Dense>
const double PI = 3.14159265359;
int main()
{
using ::Eigen::AngleAxisd;
using ::Eigen::Matrix3d;
using ::Eigen::Vector3d;
using ::std::cout;
using ::std::endl;
Matrix3d R,Rx;
R = AngleAxisd(PI, Vector3d::UnitX())
* AngleAxisd(0, Vector3d::UnitY())
* AngleAxisd(0, Vector3d::UnitZ());
Rx = AngleAxisd(PI, Vector3d::UnitX());
cout << R << endl << endl;
cout << Rx << endl << endl;
Vector3d ea = R.eulerAngles(0,1,2);
Vector3d eax = Rx.eulerAngles(0,1,2);
cout << ea << endl << endl;
cout << eax << endl << endl;
std::cin.ignore();
return 0;
}
Output (I round off numbers which are too small to zero):
1 0 0
0 -1 0
0 0 -1
1 0 0
0 -1 0
0 0 -1
0
3.14159
3.14159
0
3.14159
3.14159
Euler's angles are not unique. In your XYZ convention, both (0, pi, pi) and (pi,0,0) represents the same rotation, and both are correct. The Eigen::eulerAngles method consistently chooses to minimize first angles.
Please refer to the documentation of Eigen:eulerAngles. Details on various conventions of Euler-angles is well documented in Wikipedia and MathWorld.
Edit:
You will get exact results if you use M_PI, which is internally defined, instead of truncated value of PI.
The Euler-angle representation suffers from singularity. The test case that you are trying to compare is a singular position.
You may want to use quaternions or axis-angle representation if you wish to overcome the singularities.
Different order euler angles(roll1, pitch1, yaw1 or pitch2, yaw2, roll2, ...) can result in the same rotation matrix.
Actually, the Eigen document gave the answer.
Read the function declaration of Eigen document more carefully, and you will get the answer.
Matrix< typename MatrixBase< Derived >::Scalar, 3, 1 > Eigen::MatrixBase< Derived >::eulerAngles ( Index a0,
Index a1,
Index a2
) const
Each of the three parameters a0,a1,a2 represents the respective rotation axis as an integer in {0,1,2}. For instance, in:
Vector3f ea = mat.eulerAngles(2, 0, 2);
"2" represents the z axis and "0" the x axis, etc

Averaging circular values (particularly Hues in HSL color scheme)

So I was trying to puzzle out how to calculate the average hue of a number of objects whose colors are represented by HSL values. Thankfully, I stumbled across this Stack Overflow post, and set to work implementing the algorithm provided in the top answer (I am working in C++).
Unfortunately, my implementation doesn't seem to work. Here it is, in full; note that though I write "Hue" I am using angles, in degrees, as per the initial implementation (switching from 0-360 angles to 0-256 hues, once I know my code works, shouldn't be hard).
#include <iostream>
#include <vector>
#include <cmath>
#define PI (4*atan(1))
int main()
{
///
/// Calculations adapted from this source:
/// https://stackoverflow.com/questions/8169654/how-to-calculate-mean-and-standard-deviation-for-hue-values-from-0-to-360
std::vector<double> Hues = {355, 5, 5, 5, 5};
//These will be used to store the sum of the angles
double X = 0.0;
double Y = 0.0;
//Loop through all H values
for (int hue = 0; hue < Hues.size(); ++hue)
{
//Add the X and Y values to the sum X and Y
X += cos(Hues[hue] / 180 * PI);
Y += sin(Hues[hue] / 180 * PI);
}
//Now average the X and Y values
X /= Hues.size();
Y /= Hues.size();
//Get atan2 of those
double AverageColor = atan2(X, Y) * 180 / PI;
std::cout << "Average: " << AverageColor << "\n";
return 0;
}
Instead of the expected answer of 3 (since 355 should be equivalent to -5 in this scheme), I get 86.9951.
Can somebody point out what I'm doing wrong? This seems very basic.
atan2 takes its arguments in reverse order. I know, annoying! So try:
double AverageColor = atan2(Y, X) * 180 / PI;
The answer it gives now is 3.00488.
Try atan2(Y, X). atan2(a,b) is similar to atan(a/b), and you need the arctangent of the average sine over the average cosine.