Why isn't my pictureBox moving (Visual C ++)? - c++

I am in the early stages of making a basic two-body problem program (for those of you that don't know, a 'two-body problem' is when you have two bodies in space being gravitationally attracted to each other). I have it set up so that on each timer tick the objects (which are pictureBoxes) move in accordance with the direction (in degrees) inputted into a textbox.
Once a couple of IF statements make sure that the values in the textbox are valid, they do this inside of a Button_Press event (the button will start the simulation):
this->SimTick->Enabled=true; //Master timer for simulation
radians1=(int::Parse(DirectionBox1->Text))*(3.14/180); //Converts the degrees entered for the first object into radians for use in trig functions
radians2=(int::Parse(DirectionBox2->Text))*(3.14/180); //Converts the degrees entered for the second object into radians for use in trig functions
Inside the timer_tick event:
this->Object1->Location.X+=(int::Parse(VelocityBox1->Text)*cos(radians1));
this->Object1->Location.Y+=(int::Parse(VelocityBox1->Text)*sin(radians1));
this->StartStop->Text=(radians1.ToString()); //This is just here to check that the math was correct, which it is
I haven't coded C++ in a while, so this might be a really simple mistake, but does anyone have any ideas, or need any more code pasted?

Besides updating the Location property properly to get it to take new values, you probably want to keep a temporary x & y as a float so that you can add fractional values to it.
typedef struct { float x, y ; } floatcoord ;
floatcoord tmpLocation ;
tmpLocation.x += int::Parse(VelocityBox1->Text)*cos(radians1) ;
tmpLocation.y += int::Parse(VelocityBox1->Text)*sin(radians1) ;
this->Object1->Location.set( (int) floorf( tmpLocation.x), (int) floorf( tmpLocation.y) ; // or however you update Location

Related

How to make a GUI that plots user-entered function(x)?

I'm developing a program that takes a function of x from the user, also it takes the min and max values of x, then the program have to plot this function.
for example:
user-entered function(x) is: x^2+2x-1
Max value of x is : 3
Min value of x is : -3
now the GUI have to display (if the entered function is free of errors otherwise the error will be displayed to the user) something similar to this image:
The entered function also maybe a little bit complex E.g.(sin(x), cos(2*x+1), etc..)
I'm trying to make this job with C++ and QT, so any advice how to make the plotting part of the program using QT, or if anyone knows better recommendation instead of QT that works with C++ and can do this job.
Thanks in advance.
You are going to need a library that interprets mathematical expressions (i.e: muparser). In the code i did my own math, but you will be doing that using a library. Considering you managed all those; with QCustomPlot you can draw your graphs.
Here's a sample to give an idea how you can use QCustomPlot:
/** I copy pasted the code from one of my projects, please ignore function & class namings
*/
/** somewhere in your window constructor, create a QCustomPlot
* widget and add graphs to your QCustomPlot widget.
* example: ui->plt_freq_domain->addGraph();
*/
void ControllerMain::plot_frequency_domain()
{
QVector <double> vec_keys(1024), vec_values(1024);
//fill x axis values with incrementing numbers from 0 to 1024 (or any other number you want)
// let's say your function is y = x^2 and calculate all y values and store them in vec_values
for(int i = 0; i < vec_keys.size(); i++)
{
vec_values[i] = std::pow(vec_keys[i], 2);
}
// we fill keys with continuous integers [0,1023] so our graph spans along x-axis
std::iota(vec_keys.begin(), vec_keys.end(), 0);
ui->plt_freq_domain->graph(0)->setData(vec_keys, vec_values, true);
ui->plt_freq_domain->graph(0)->setPen(QPen(QColor(245, 197, 66)));
ui->plt_freq_domain->yAxis->setLabel("A/m"); // change it with your unit or just keep empty
ui->plt_freq_domain->yAxis->setRange(*std::min_element(vec_values.begin(), vec_values.end()),
*std::max_element(vec_values.begin(), vec_values.end()));
ui->plt_freq_domain->xAxis->setLabel("f"); // change it with your unit or just keep empty
ui->plt_freq_domain->xAxis->setRange(vec_keys.constFirst(), vec_keys.constLast());
ui->plt_freq_domain->replot();
}

SDL/C++ movement: time and acceleration

I want to teach myself some basic physics programming by creating a simple 2d platformer with SDL 2. It seems I'm falling at the first hurdle though, because I can't get movement using both velocity and acceleration per time unit, rather than per frame, to work.
I start by calculating the time per frame in the usual way:
previous_time = current_time;
current_time = SDL_GetTicks();
delta_time = current_time - previous_time;
Then, after the movement flag is set to true by pressing a directional button, this is passed to a function to handle the movement.
//Pass the movement flag and the milliseconds per frame to the right movement function.
if ( player.get_x() <= 740 ) {
player.x_movement_right(delta_time, 1, moving_right);
}
The integer that's passed doesn't do anything yet. Anyway, the function then determines the acceleration based on if the movement flag is set to true, and what the current velocity is:
void Player::x_movement_right(float dt, int direction, bool moving_right) {
dt /= 1000;
if (moving_right == true && _x_velocity <= 200 ) {
_x_acceleration = 50;
}
else if ( moving_right == false && _x_velocity > 0 ) {
_x_acceleration = -50;
}
else {
_x_acceleration = 0;
}
_x_velocity += _x_acceleration * dt;
_x_position += _x_velocity * dt;
}
The same process occurs if the left movement flag is activated, with inverted values of course. Yet after compiling I hit the directional keys and nothing happens.
What I've already tried:
I removed the dt's at the bottom of the movement function. The player avatar moves with incredible speed, since the acceleration is now per frame, rather than per second.
Same thing when I don't divide dt at the beginning of the movement function, since it's now per millisecond rather than per second.
I tried rounding the velocity times dt at the bottom, since I suspected SDL might have trouble calculation positions with floating point numbers rather than integers. Still no movement.
Based on this I suspect it has something to do with the numbers being too small, but I can't quite wrap my head around what the problem is or how to solve it. So, does anyone know what undoubtedly obvious thing I'm missing? Thanks in advance!
There is no way to know with the information shown, but there are several points that may help you:
Are your _x_velocity and the like floating point types? In what units are you measuring distance? It may be that your increment has not enough resolution to be nonzero.
Have you printed the values of each variable or run the program in a debugger?
What do you mean by "SDL might have trouble calculation positions with floating point numbers"? If you are using SDL's basic 2D renderer, you just need to give it the type it needs in whatever units they ask. The conversions are up to you.
Overall, I'd recommend trying to code the simulation outside SDL or graphics in general. Getting acquainted with C++, debugging and floating-point is also a plus.

Collision Detection Between Rectangles - Resulting Angles

Basically I have a bunch of rectangles floating around at 8 different angles (45 degrees, 90 degrees etc). I have collision detection going on between all of them, but one thing still doesn't work as it should. I don't know if I'm just not thinking or what, but I can't seem to get the resulting angles right. I've also tried searching multiple places, but haven't really gained anything from what I've found.
NOTE: the angle system here starts at 0 at the top and increases clockwise.
NOTE: all rectangles have the same mass
Say one rectangle going straight right (90 degrees) hits another going straight left (270 degrees). They will hit off of each other just fine.
Now say one going left gets hit by one going up. Here I can't simply reverse the angles or anything.
If you have more than one way, consider the following: unless I rearrange the CD so it spreads into the other code, I have the positions of all of the rectangles. The CD checks by seeing if two are overlapping, not by comparing where they are going.
As I've been working on pretty much everything except for the collision detection until now, I only have tonight left to get it working and add a few other small things before I'm done.
If you know of a way to make the angles come out right without hardcoding, great. At this point I'm ready to hardcode it (not too much really) if all I have is which rectangle hits the other (ex 2), or if they both do (ex 1). Either one is really helpful.
I think you mean something like this...
Each Rectangle has this functionality, testing against, say an array of other objects.
Obstacle* obstacle = new Obstacle;
Obstacle** obstacles = obstacle*[];
For(int i = 0; i <3; i++)
{
obstacles[0] = New Obstacle(x,y, etc...);
etc...
}
Or something similar... this is a little rusty
void collision(obstacles)
{
for(int i = 0; i < obstacles.sizeOf();i++)
{
//bottom y
if((this.ypos + this.height) > (obstacles[i].ypos - obstacles[i].height))
obstacles[i].doYCollision(this);
//top y
if((this.ypos - this.height) < (obstacles[i].ypos + obstacles[i].height))
obstacles[i].doYCollision(this);
//right x
if((this.xpos + this.width) > (obstacles[i].xpos - obstacles[i].width))
obstacles[i].doXCollision(this);
//left x
if((this.xpos - this.width) < (obstacles[i].xpos + obstacles[i].width))
obstacles[i].doXCollision(this);
}
}
again im a little rusty but if you follow it you should be able to relaise what im doing.
then all you need is the resulting function calls.
void doYCollision(Obstacle obstacle)
{
// Whatever y direction they are going do the opposite
obstacle.yDir = obstacle.yDir * -1;
}
void doXCollision(Obstacle obstacle)
{
// Whatever x direction they are going do the opposite
obstacle.xDir = obstacle.xDir * -1;
}
where yDir, xDir is the x and y velocity of the current object.
i should point out again this is very rusty and without having some code from you this is the best ive got. but either way this should start you off into collision detection, the code above shoudl allow for all collisions with all obstacles/objects/pink flamingos/ whatever youve got. Im hoping also that itll do what you want when it comes to multiple collisions at the same time.
You shouldnt need to worry too much about the exact angle (unless you need it for something else), as velocity is a vector mass so has both speed and direction and you can get direction by treating x and y as two different elements. You can do this using the dot product method aswell => http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static, but if they are just rectangles this should be fine.
Hopes this helps

Help with code optimization

I've written a little particle system for my 2d-application. Here is raining code:
// HPP -----------------------------------
struct Data
{
float x, y, x_speed, y_speed;
int timeout;
Data();
};
std::vector<Data> mData;
bool mFirstTime;
void processDrops(float windPower, int i);
// CPP -----------------------------------
Data::Data()
: x(rand()%ScreenResolutionX), y(0)
, x_speed(0), y_speed(0), timeout(rand()%130)
{ }
void Rain::processDrops(float windPower, int i)
{
int posX = rand() % mWindowWidth;
mData[i].x = posX;
mData[i].x_speed = WindPower*0.1; // WindPower is float
mData[i].y_speed = Gravity*0.1; // Gravity is 9.8 * 19.2
// If that is first time, process drops randomly with window height
if (mFirstTime)
{
mData[i].timeout = 0;
mData[i].y = rand() % mWindowHeight;
}
else
{
mData[i].timeout = rand() % 130;
mData[i].y = 0;
}
}
void update(float windPower, float elapsed)
{
// If this is first time - create array with new Data structure objects
if (mFirstTime)
{
for (int i=0; i < mMaxObjects; ++i)
{
mData.push_back(Data());
processDrops(windPower, i);
}
mFirstTime = false;
}
for (int i=0; i < mMaxObjects; i++)
{
// Sleep until uptime > 0 (To make drops fall with randomly timeout)
if (mData[i].timeout > 0)
{
mData[i].timeout--;
}
else
{
// Find new x/y positions
mData[i].x += mData[i].x_speed * elapsed;
mData[i].y += mData[i].y_speed * elapsed;
// Find new speeds
mData[i].x_speed += windPower * elapsed;
mData[i].y_speed += Gravity * elapsed;
// Drawing here ...
// If drop has been falled out of the screen
if (mData[i].y > mWindowHeight) processDrops(windPower, i);
}
}
}
So the main idea is: I have some structure which consist of drop position, speed. I have a function for processing drops at some index in the vector-array. Now if that's first time of running I'm making array with max size and process it in cycle.
But this code works slower that all another I have. Please, help me to optimize it.
I tried to replace all int with uint16_t but I think it doesn't matter.
Replacing int with uint16_t shouldn't do any difference (it'll take less memory, but shouldn't affect running time on most machines).
The shown code already seems pretty fast (it's doing only what it's needed to do, and there are no particular mistakes), I don't see how you could optimize it further (at most you could remove the check on mFirstTime, but that should make no difference).
If it's slow it's because of something else. Maybe you've got too many drops, or the rest of your code is so slow that update gets called little times per second.
I'd suggest you to profile your program and see where most time is spent.
EDIT:
one thing that could speed up such algorithm, especially if your system hasn't got an FPU (! That's not the case of a personal computer...), would be to replace your floating point values with integers.
Just multiply the elapsed variable (and your constants, like those 0.1) by 1000 so that they will represent milliseconds, and use only integers everywhere.
Few points:
Physics is incorrect: wind power should be changed as speed makes closed to wind speed, also for simplicity I would assume that initial value of x_speed is the speed of the wind.
You don't take care the fraction with the wind at all, so drops getting faster and faster. but that depends on your want to model.
I would simply assume that drop fails in constant speed in constant direction because this is really what happens very fast.
Also you can optimize all this very simply as you don't need to solve motion equation using integration as it can be solved quite simply directly as:
x(t):= x_0 + wind_speed * t
y(t):= y_0 - fall_speed * t
This is the case of stable fall when the gravity force is equal to friction.
x(t):= x_0 + wind_speed * t;
y(t):= y_0 - 0.5 * g * t^2;
If you want to model drops that fall faster and faster.
Few things to consider:
In your processDrops function, you pass in windPower but use some sort of class member or global called WindPower, is that a typo? If the value of Gravity does not change, then save the calculation (i.e. mult by 0.1) and use that directly.
In your update function, rather than calculating windPower * elapsed and Gravity * elapsed for every iteration, calculate and save that before the loop, then add. Also, re-organise the loop, there is no need to do the speed calculation and render if the drop is out of the screen, do the check first, and if the drop is still in the screen, then update the speed and render!
Interestingly, you never check to see if the drop is out of the screen interms of it's x co-ordinate, you check the height, but not the width, you could save yourself some calculations and rendering time if you did this check as well!
In loop introduce reference Data& current = mData[i] and use it instead of mData[i]. And use this reference instead of index also in procesDrops.
BTW I think that consulting mFirstTime in processDrops serves no purpose because it will never be true. Hmm, I missed processDrops in initialization loop. Never mind this.
This looks pretty fast to me already.
You could get some tiny speedup by removing the "firsttime" code and putting it in it's own functions to call once rather that testing every calls.
You are doing the same calculation on lots of similar data so maybe you could look into using SSE intrinsics to process several items at once. You'l likely have to rearrange your data structure for that though to be a structure of vectors rather than a vector od structures like now. I doubt it would help too much though. How many items are in your vector anyway?
It looks like maybe all your time goes into ... Drawing Here.
It's easy enough to find out for sure where the time is going.

"Invalid Handle Object" when plotting 2 figures Matlab

I'm having a difficult time understanding the paradigm of Matlab classes vs compared to c++. I wrote code the other day, and I thought it should work. It did not... until I added
<handle
after the classdef.
So I have two classes, landmarks and robot, both are called from within the simulation class. This is the main loop of obj.simulation.animate() and it works, until I try to plot two things at once.
DATA.path is a record of all the places a robot has been on the map, and it's updated every time the position is updated.
When I try to plot it, by uncommenting the two marked lines below, I get this error:
??? Error using ==> set
Invalid handle object.
Error in ==> simulation>simulation.animate at 45
set(l.lm,'XData',obj.landmarks.apparentPositions(:,1),'YData',obj.landmarks.apparentPositions(:,2));
%INITIALIZE GLOBALS
global DATA XX
XX = [obj.robot.x ; obj.robot.y];
DATA.i=1;
DATA.path = XX;
%Setup Plots
fig=figure;
xlabel('meters'), ylabel('meters')
set(fig, 'name', 'Phil''s AWESOME 80''s Robot Simulator')
xymax = obj.landmarks.mapSize*3;
xymin = -(obj.landmarks.mapSize*3);
l.lm=scatter([0],[0],'b+');
%"UNCOMMENT ME"l.pth= plot(0,0,'k.','markersize',2,'erasemode','background'); % vehicle path
axis([xymin xymax xymin xymax]);
%Simulation Loop
for n = 1:720,
%Calculate and Set Heading/Location
XX = [obj.robot.x;obj.robot.y];
store_data(XX);
if n == 120,
DATA.path
end
%Update Position
headingChange = navigate(n);
obj.robot.updatePosition(headingChange);
obj.landmarks.updatePerspective(obj.robot.heading, obj.robot.x, obj.robot.y);
%Animate
%"UNCOMMENT ME" set(l.pth, 'xdata', DATA.path(1,1:DATA.i), 'ydata', DATA.path(2,1:DATA.i));
set(l.lm,'XData',obj.landmarks.apparentPositions(:,1),'YData',obj.landmarks.apparentPositions(:,2));
rectangle('Position',[-2,-2,4,4]);
drawnow
This is the classdef for landmarks
classdef landmarks <handle
properties
fixedPositions; %# positions in a fixed coordinate system. [ x, y ]
mapSize; %Map Size. Value is side of square
x;
y;
heading;
headingChange;
end
properties (Dependent)
apparentPositions
end
methods
function obj = landmarks(mapSize, numberOfTrees)
obj.mapSize = mapSize;
obj.fixedPositions = obj.mapSize * rand([numberOfTrees, 2]) .* sign(rand([numberOfTrees, 2]) - 0.5);
end
function apparent = get.apparentPositions(obj)
currentPosition = [obj.x ; obj.y];
apparent = bsxfun(#minus,(obj.fixedPositions)',currentPosition)';
apparent = ([cosd(obj.heading) -sind(obj.heading) ; sind(obj.heading) cosd(obj.heading)] * (apparent)')';
end
function updatePerspective(obj,tempHeading,tempX,tempY)
obj.heading = tempHeading;
obj.x = tempX;
obj.y = tempY;
end
end
end
To me, this is how I understand things. I created a figure l.lm that has about 100 xy points. I can rotate this figure by using
set(l.lm,'XData',obj.landmarks.apparentPositions(:,1),'YData',obj.landmarks.apparentPositions(:,2));
When I do that, things work. When I try to plot a second group of XY points, stored in DATA.path, it craps out and I can't figure out why.
I need to plot the robots path, stored in DATA.path, AND the landmarks positions. Ideas on how to do that?
Jonas:
I'm not saying you're wrong, because I don't know the answer, but I have code from another application that plots this way without calling axes('NextPlot','add');
if dtsum==0 & ~isempty(z) % plots related to observations
set(h.xf, 'xdata', XX(4:2:end), 'ydata', XX(5:2:end))
plines= make_laser_lines (z,XX(1:3));
set(h.obs, 'xdata', plines(1,:), 'ydata', plines(2,:))
pfcov= make_feature_covariance_ellipses(XX,PX);
set(h.fcov, 'xdata', pfcov(1,:), 'ydata', pfcov(2,:))
end
drawnow
The above works on the other code, but not mine. I'll try implementing your suggestion and let you know.
When you call plot multiple times on the same figure, the previous plot is by default erased, and the handle to the previous plot points to nothing. Thus the error.
To fix this, you need to set the NextPlot property of the axes to add. You can do this by calling hold on (that's what you'd do if you were plotting from command line), or you can write
fig=figure;
%# create a set of axes where additional plots will be added on top of each other
%# without erasing
axes('NextPlot','add');
If you want, you can store the axes handle as well, and use plot(ah,x,y,...) to make sure that you plot into the right set of axes and not somewhere strange if you happen to click on a different figure window between the time the figure is opened and the plot command is issued.