Solved

# X and Y coordinates

Posted on 1998-09-27
381 Views
Okay, here is my problem... hope i can find some kind souls here to help me.

Here is a part of my code for Segment 1 Dialog Box.

void CSegOne::OnSegoneapplyButton()
{
// to update the controls
UpdateData(TRUE);

// m_DispType and m_MotionType are basically combo
// box for deciding which equations to use and
// m_MaxHt and m_TwoAngle are variable determine
// by the users

if(m_DispType == 1 && m_MotionType == 0)
{
for (theta=0; theta<m_TwoAngle; theta+5)
{
displacement = (m_MaxHt/2)*(1-(cos(0.5*theta)));
}
OnOK();
Invalidate();
}
The problem is... after generating the various values for the displacement and theta, how to I update them to my OnDraw function so that I can plot the points out?

Here is a small part of my OnDraw function.
I have omitted certain lines to keep this question short.

void CCamView::OnDraw(CDC* pDC)
{
CCamDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

pDC->MoveTo(50, 150);
pDC->LineTo(450, 150);
pDC->LineTo(450, 350);
pDC->LineTo(50, 350);
pDC->LineTo(50, 150);

// Draw the vertical gridlines
pDC->SelectObject(&thin_line);
pDC->MoveTo(150, 150);
pDC->LineTo(150, 350);
pDC->MoveTo(250, 150);
pDC->LineTo(250, 350);
pDC->MoveTo(350, 150);
pDC->LineTo(350, 350);

// Draw the horizontal gridlines
pDC->MoveTo(50, 150);
pDC->LineTo(450, 150);
pDC->MoveTo(50, 200);
pDC->LineTo(450, 200);
pDC->MoveTo(50, 250);
pDC->LineTo(450, 250);
pDC->MoveTo(50, 300);
pDC->LineTo(450, 300);

// Label the x-axis
pDC->TextOut(50, 360, "0");
pDC->TextOut(150, 360, "100");
pDC->TextOut(250, 360, "200");
pDC->TextOut(350, 360, "300");
pDC->TextOut(450, 360, "400");

// To display the 4 different views
pDC->SelectObject(pOldPen);
CFont * pOldFont = pDC->SelectObject(&big_font);

if (m_SelectedView == "DISPLACEMENT")
{
CCamDoc* pDoc = GetDocument();
pDC->TextOut(50, 100, "Displacement Diagram");
pDC->SelectObject(&blue_line);

//here is essentially a str line
//m_XCoord is my theta and m_YCoord is my
//displacement. m_XCoord and m_YCoord have been
//initialised to 50 and 348 respectively.

pDC->MoveTo(m_XCoord, m_YCoord);
pDC->LineTo(m_XCoord+360, m_YCoord);

//On apply button, here is where i need to add in
//the codes for plotting of the points

}
0
Question by:ksmak
• 16
• 16

Author Comment

ID: 1173820
0

LVL 1

Accepted Solution

Booth882 earned 210 total points
ID: 1173821
well there are essentially two things I see you can do.  right now when you go through the loop that determines displacement from a regular theta, you are losing all of the values because you assign each value to the same variable, thereby overwriting the previous value.  when you are done all that will be in the displacement variable is the last displacement calculated and all of the previous ones will be erased. to remedy this you can make two arrays, one for displacement and one for theta, and put all of the data you receive from your calculations into the corresponding places in the arrays.  then in a simple for loop you can access all of the values in order.  if you dont mind the memory overhead that solution is fine.  the other one is to pass your pDC from OnDraw in to your OnsegoneApplyButton method by reference, and draw each point as it comes up.  this is quicker and costs less memory, but again each value is lost, so once you draw it there is no way to access it again.  if you just need to draw the points though and have no need of the values once you have finished, this would be the best solution.
0

LVL 1

Expert Comment

ID: 1173822
I can show you how to do either if you need me to.
0

Author Comment

ID: 1173823
Booth882,

i will appreciate very much if you can show me how to do it. i do not really need the values. however, it would definitely be a plus point if the i can generate and show the different values to the user.

anyhow, can you show me how i should go abt plotting the points, without regards to the value first.

thanx.

0

LVL 1

Expert Comment

ID: 1173824
ok, change the first line of your button function to take a CDC *, like this

void CSegOne::OnsegoneapplyButton( CDC * pDC )

then in the loop when you assign displacement its value put a draw command, like this

for (theta=0; theta<m_TwoAngle; theta+5)
{
displacement = (m_MaxHt/2)*(1-(cos(0.5*theta)));
pDC->LineTo( theta, displacement );
}

and then whenever you call the function, make sure you pass in the CDC.  thats it!  now there is one thing.  if the OnsegoneapplyButton is a callback function in response to a windows message you may not be able to adjust the parameters of the function.   but if it is a function that you call explicitly from OnDraw then it will work just fine.   try it out and see if it works.  if not then we will need to make another function that is independent of windows messaging or we can use the arrays.  tell me what happens.
0

Author Comment

ID: 1173825
Booth882

forgive me for i am very new to visual c. i don't really understand what do you mean by "whenever you call the function, make sure you pass in the CDC". anyway, i did wat you suggest, ie, adding a CDC* and the lineto function. however, when i compile the file, i get an error of " error C2511: 'OnSegoneapplyButton' : overloaded member function not found in 'CSegOne'"

0

LVL 1

Expert Comment

ID: 1173826
yeah, when you changed the OnSegoneappyButton function you made it take a parameter ( the CDC * ) whereas before it took none.  but when you changed it there you did not change it in the class declaration.  where do you declare the class?  the part of the class where you list all the functions and their return types and parameters but dont have any of the actual code of the function there is called the declaration.  the part where you show all the code for what the function does ( as in the part you showed me ) is called the implementation.  you changed it in the implementation but not in the declaration.  whenever you change the return type or parameters of a function you must change it in both the declaration and implementation, they have to match.  try that and see what happens.

I am worried about the name of the function though.  it sounds like an OnWindowsMessage function, one that is called in response to a message rather than called explicitly.  when you call a function explicitly you have a class object and specify the function and pass in the needed parameters, like

CSegOne MySegOne;

MySegOne.OnSegoneapplyButton( pDC );

now I declared MySegOne there you can do it anywhere.  that is an explicit function call.  one in response to a windows message though you dont actually write anywhere, you just declare it and windows calls it for you when it needs to.  the problem with this is you cant change the parameters that are passed in because windows supplies the parameters, not you.  if that is the case then this method will fail and we will have to do it using arrays or an independent function.  try this for now though, because this would be the best and easiest way to do it.  if it doesnt work though let me know, and what would also be extremely helpful is to email me the complete code of your program.  send me a package of all the code files ( .h files, .cpp files ...) that are relevant, including the CSegOne files, and I will look through them.  then I could tell you exactly what to do.  dont worry though, we will make this work!!  I have made this my personal crusade.  my email address is Booth866@aol.com (not Booth882).  try this first though.  if it works then we dont need to worry about any of the other stuff.
0

LVL 1

Expert Comment

ID: 1173827
alright I got the file, I'll get on it right away.
0

Author Comment

ID: 1173828
Booth,

thanz, i hope it is not too much trouble for you.
0

Author Comment

ID: 1173829
0

LVL 1

Expert Comment

ID: 1173830
ok, the problem is that you had two different views and no way to share data between them.  all of the displacement calculations were going on in the CCamForm view class while all the drawing was going on in the CCamView view class.  so what you have to do is find a way for them to share the data.  Visual C++ AppWizard is set in the Document/View architecture.  this is a way of separating the data from the ways you display that data.  for example, a cube, with all of its vertices and surface colors, would be the document, because those are the raw data of the thing.  the way that cube appears when observed from say twenty feet above it would be the view, because that is how the data, in this case the raw vertices, is seen when looked upon in a certain way.  with this document/view architecture you can have mulitple views of one single document, depending on how you want it displayed.

you have two views in this application, the one where you fill in the values and the one where the screen is drawn upon according to those values.  so what you have to do is stick the variables you want to be part of both of the views in your CCamDoc document class.  in this case that would be an array for the displacements and an array for the thetas of each point to be plotted on the grid, along with the maximum number of points in the arrays.

first of all change your code back to the way it was.  the old method will be of no use to us.  I will send this now and piece together all of the necessary code changes on another comment.
0

LVL 1

Expert Comment

ID: 1173831
ok here they are, file by file...

in CamDoc.h add these variables into the class declaration under a public heading

int * displacement;
int * theta;
int maxcount;

in CamDoc.cpp add this to the constructor

displacement = new int[80];
theta = new int[80];

for(int d = 0; d < 80; d++)
{
displacement[d] = 0;
theta[d] = 0;
}

maxcount = 0;

this to the destructor

delete [] displacement;
displacement = 0;
delete [] theta;
theta = 0;

these allocate and clean up the new document variables

in CamForm.h, #include "CamDoc.h", add this function to a public field of the class declaration of CCamForm

CCamDoc * GetDocument();

this is the function that will allow us to access the data in CCamDoc, our document.  there is a similar function in CCamView that allows us to do it there as well.  so our aim is to take the data we get from CSegOne which is part of the CCamForm view and put it in CCamDoc where we can access and draw it from CCamView view class.

be right back.
0

LVL 1

Expert Comment

ID: 1173832
in CamForm.cpp add this function implementation

CCamDoc* CCamForm::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCamDoc)));
return (CCamDoc*)m_pDocument;
}

add this in void CCamForm::OnSegoneButton() after DoModal()

CCamDoc * pCCamDoc = GetDocument();

pCCamDoc->maxcount = m_SegOne.MaxCount;

for(int count = 0; count < pCCamDoc->maxcount; count++)
{
pCCamDoc->displacement[count]= m_SegOne.Displacement[count];
pCCamDoc->theta[count] = m_SegOne.Theta[count];
}

in CSegOne.h add these variables in a public field to the declaration of CSegOne

int Displacement[80];
int Theta[80];
int MaxCount;

these are the CSegOne values for the CCamDoc variables of the same name.  these values are transfered over after DoModal() in CCamForm.

in CSegOne.cpp add this initialization to the constructor

MaxCount = 0;

for(int i = 0; i < 80; i++)
{
Displacement[i] = 0;
Theta[i] = 0;
}

replace the previous for loop calculations of displacement and theta with this one

for(int count = 0; count * 5 < m_TwoAngle; count++)
{
Theta[count] = count * 5;
Displacement[count] = (m_MaxHt / 2) * (1 - (cos(0.5 * Theta[count])));
}

MaxCount = count;

and finally to OnDraw in CCamView.cpp add these lines in the place you specified before

for(int count = 0; count < pDoc->maxcount; count++)
pDC->LineTo(pDoc->theta[count], pDoc->displacement[count]);

that should do it!  try it out and tell me what happens.
0

Author Comment

ID: 1173833
Booth,

okay... i did all the steps that you suggested and the program was able to execute nicely. however, the curve doesn't seem to be wat i thot i would see. i will go and work on it again.

will update you what happens.

btw, thanz... you have been a great help already. at least now when i click the apply button, something happened to the CamView. :>
0

LVL 1

Expert Comment

ID: 1173834
I'll be gone alot today but when I get back I'll look at it too.  what is it supposed to look like?  can you give me some values for base radius and all that are supposed to make it appear normally?  I will see what I can do.
0

Author Comment

ID: 1173835
sigh...

still couldn't manage to figure out wat's the problem, although i seriously susupect it might be due to the mapping of the displacement and theta to the coordinates of the windows, ie the CCamView.

it's supposed to be a normal sinusodal curve. when theta is zero, displacement is zero. and it will increase as theta increase until theta reaches m_TwoAngle, then the displacement will be m_MaxHt that the user entered.

i will go and work on it again. thanz for the help, booth.
0

Author Comment

ID: 1173836
sigh...

still couldn't manage to figure out wat's the problem, although i seriously susupect it might be due to the mapping of the displacement and theta to the coordinates of the windows, ie the CCamView.

it's supposed to be a normal sinusodal curve. when theta is zero, displacement is zero. and it will increase as theta increase until theta reaches m_TwoAngle, then the displacement will be m_MaxHt that the user entered.

i will go and work on it again. thanz for the help, booth.
0

LVL 1

Expert Comment

ID: 1173837
I tried it and what happened is that the line went up into the corner of the displacement diagram and then squiggled around a bit.  you know I think I may know what the problem is.  are you using degrees or radians for your angles?  I think some math includes have cosines that evaluate in radians rather than degrees.  you can either change them all to radians or run it through a degree/radian converter before you put it into the function.
0

Author Comment

ID: 1173838
okie... here's the lastest story.

the program compile fines and run nicely, however, the values of theta and displacement generated is not correct. this is bcos...

// the code that generate the values
for (count = 0; count<m_TwoAngle; count=count+5)
{
Theta[count] = ((count/180)*3.14); //Convert Theta to radian
Displacement[count] = (m_MaxHt/2)*(1-(cos(0.5*Theta));
}

MaxCount=count;

// end of code

as the count is int, and bcos it is very small, it always return a value of zero, as a result, my cos theta is always 1 thus my displacement is always zero.

// During debugging stage, i tried changing the code to the
// following to see the effect of changing the count to double

double aaa;
double aab;
double aac;

for (double count = 0; count<m_TwoAngle; count=count+5)
{
aac = (count/360)*3.14;
aab = cos(aac);
aaa = 1000*(m_MaxHt/2)*(1-(cos(0.5*(count/360)*6.28)));
}

// end of code

and the values of the aaa, aab and aac were correct. however, when i did that in the original code, ie, changing the count to a double, i got a whole load of errors.

0

LVL 1

Expert Comment

ID: 1173839
here one is

{
float Radian = ( float ( Angle * Pi ) / 180 );

}

input theta into that before you put it into the cosine function, like

cos( DegreeToRadian( theta[ count ] ) );

see if that clears it up.

also what may be happening is you are starting at the wrong place.  in OnDraw you could say

pDC->LineTo( theta[ count ] + m_XCoord, displacement[ count ] + m_YCoord );

or wherever you wanted to start them from, because right now it looks like your starting in the corner, when you want to be starting somewhere on the graph.  that is why that first line goes across your displacement graph and ends up in the top corner.  once its there it does some stuff, but I think you want it on the graph.

change one thing at a time though.  see how it goes.
0

Author Comment

ID: 1173840
correction to the above entry...

double aaa;
double aab;
double aac;

if(m_DispType== 1 && m_MotionType == 0)
{
MessageBox("Equation 1","Cycloidal Return");

for (double count = 0; count<m_TwoAngle; count=count+5)
{
aac = (count/180)*3.14;
aab = cos(aac);
aaa = (m_MaxHt/2)*(1-(cos(0.5*(count/180)*3.148)));
}

just wanna add, aaa was supposed to be my displacement values... with this, i could get the correct values.
0

LVL 1

Expert Comment

ID: 1173841

divide by 180, not 360, because a whole circle is 2Pi.  1Pi is 180 degrees.

also to make sure the int doesnt cut off your data to an int, you can do this:

int IntNumber = 200;

float Float = ( float ( IntNumber / 180 ) );

this will assure that the number is a float and not an int, and therefore will not cut off your data.

0

LVL 1

Expert Comment

ID: 1173842
the reason you got all those errors when you changed count to a double is that you cannot call an element of an array ie displacement[ count ] with anything other than an int.  doing so causes the errors you mentioned.  there is no displacement[ 2.35 ] it just doesnt work
0

Author Comment

ID: 1173843
Booth, now let say my code is now...

for(int count = 0; count<m_TwoAngle; count=count+5)
{
Displacement[count] = (m_MaxHt/2)*(1-(cos(0.5*Theta[count])));
}

everything else remain status quo, but bcos Theta will always get a zero vale, Displacement will also be zero for all values of counts.

can you explain again to me how to solve this problem as i do not really understand what you meant in the last replies.

ps i am so sorry, i hope i haven't become a nuisance yet.

0

Author Comment

ID: 1173844
Booth, now let say my code is now...

for(int count = 0; count<m_TwoAngle; count=count+5)
{
Displacement[count] = (m_MaxHt/2)*(1-(cos(0.5*Theta[count])));
}

everything else remain status quo, but bcos Theta will always get a zero vale, Displacement will also be zero for all values of counts.

can you explain again to me how to solve this problem as i do not really understand what you meant in the last replies.

ps i am so sorry, i hope i haven't become a nuisance yet.

0

LVL 1

Expert Comment

ID: 1173845
no sweat.

when you assign those values to theta they come out to be in the range between 0 and 2Pi, but you want the whole range of values and not just the int ones.  you can change the theta array to be an array of floats ( or doubles if you prefer ), then when it assigns it the value from your degree converter it will be in float format instead of integer format.  so all you have to do is go to where you declare your theta arrays and change them from int to float ( or double, it doesnt really matter ).  that should do the trick.
0

LVL 1

Expert Comment

ID: 1173846
tell me what you find out.
0

Author Comment

ID: 1173847
okie okie... almost there!

everything is the same as the 'file-by-file' instructions you gave me the other time, EXCEPT... the affected variables has all changed to either float or double. now the following codes were able to give me the values that i wanted, i used debugger to check all the values at the differenet count.

for(int count = 0; count*5<m_TwoAngle; count++)
{
var1 = (count*31.42)/m_TwoAngle;
var2 = sin(var1);
var3 = var2/6.283;
var4 = count*5/m_TwoAngle;

Theta[count] = count*5;
Displacement[count] = m_MaxHt*(var4-var3);

when count=0, all is zero
when count=1, Theta = 5, Displacement = 0.0046790272881032
when count=5, Theta = 25, Displacement = 0.54589939870079
when count=12, Theta = 60, Displacement = 5.0006483310504
when count=23, Theta = 115, Displacement = 9.9940683680745

exactly wat i wanted!! however, as you can see, Displacement values are extremely small. so when the OnDraw call the function

if (m_SelectedView == "DISPLACEMENT")
{
CCamDoc* pDoc = GetDocument();

pDC->TextOut(50, 100, "Displacement Diagram");
pDC->SelectObject(&blue_line);

//Move to the starting point (50, 348)
pDC->MoveTo(m_XCoord, m_YCoord);

for (int count=0; count<pDoc->maxcount; count++)
{
pDC->LineTo(pDoc->theta[count], pDoc->displacement[count]);
}
}

it couldn't plot out the point correctly. i tried to add this line instead....

pDC->LineTo(pDoc->theta[count]+m_XCoord, pDoc->displacement[count]+m_YCoord);

i get this error : "conversion from 'double' to 'int', possible loss of data", plus i still can't plot the correct curve.

so, the problems now lies with the transfering of the Theta and Displacement values generated into the CCamView Coordinate which is (0,0) at the top left hand corner and 'Downwards' for positive y and 'Rightwards' for positive x, while my origin is at (50, 348), rightwards for positive x and upwards for positive y.

so there it is... Booth, you think you can help me in this. can we try scaling the points?? i am really stressed up here. thanz.

0

Author Comment

ID: 1173848
just something i forgot to add, ie

all the calculations are correct and okie now... just need to transfer the values generated correctly to the CCamView. ermm... i will go and figure it out again, mebbe i can pass the values through another set of equations?? Shhheeesssshhh....!!!!!!
0

Author Comment

ID: 1173849
arrrghh...

one last thing, the calculation i got from above is based on m_TwoAngle=120, m_MaxHt=10
0

LVL 1

Expert Comment

ID: 1173850
to scale something just multiply each part by a constant.  if your y is going down and you want it to go up, multiply each value by -1.  if its not going up high enough multiply it by -4 or something that will increase the distance of each.  same thing for x, if it is not going far enough multiply it by a value greater than 1.  that will extend it further.

also, that error about converting double to int possible loss of data should be a warning, right?  all that means is that LineTo takes ints and your putting in doubles.  this is no problem except that it gets cut off at every integer.  but each integer value is one pixel, so if you scale it correctly as above then this should turn out fine.

anything else?
0

Author Comment

ID: 1173851
i think the problem is solved. thanz booth, not oni have you been knowledgeable, you have also been patience and so helpful.

once again, Thanzzz.
0

## Featured Post

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generatâ€¦
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. â€¦
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relatâ€¦
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Botâ€¦