Made some progress!
Some improvements: I now display the graph and equations in separate windows, so that it's not terribly confusing to have multiple graphs on the same square. Now I just need to add the equations I wanna display to one vector<string> and it'll draw those graphs and also display the equations in the window.
Yup, I went ahead and did the recursive descent parser. It could still use improvements - I have to end it with an arbitrary character so the program won't try and parse invalid data (right now I'm using an exclamation point). It's not good at error handling and it assumes the data is fed to it perfectly. It won't even handle white space yet, and I can only use whole numbers because it doesn't know how to deal with decimal points yet. So I'll need to work on that but it's a start.
Also, all of this is in one file and I don't like that. The recursive descent parser should at least be in a separate file, it not more functions. With C# or Java it's really easy to separate out things into different files, not quite fluent with C++ so simple things like this are really difficult.
Of course this program could use a lot of improvement but a lot of the extra functionality I wanted to include are in here now.
Click
here to see my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "constants.h"
using namespace std;
/////////////////////////////////////
/////////////////////////////////////
int angle_index = 2;
string angles[3][11] = {
{"PI/2", "PI", "3PI/2", "2PI", "5PI/2", "3PI", "7PI/2", "4PI", "9PI/2", "5PI", "11PI/2"},
{"PI/3", "2PI/3", "PI", "4PI/3", "5PI/3", "2PI", "7PI/3", "10PI/3", "11PI/3", "4PI", "13PI/3"},
{"PI/4", "PI/2", "3PI/4", "PI", "9PI/4", "5PI/2", "11PI/4", "3PI", "13PI/4", "7PI/2", "15PI/4"}
};
vector<string> equations;
void InitializeEquations() {
equations.push_back("2*cos(1)!");
equations.push_back("2*cos(2)!");
equations.push_back("cos(3)!");
equations.push_back("1!");
}
void remove(char s[], int remove) {
for (size_t i = 0; i < strlen(s); i++) {
s[i] = s[i + remove];
}
}
float valueOfDigitSeq(char source[]) {
float value = 0;
if (source[0] == 'x') value = 10;
else if (source[0] >= '0' && source[0] <= '9') {
value = (double)(source[0] - '0');
}
remove(source, 1);
while (source[0] >= '0' && source[0] <= '9') {
value *= 10;
value += (float)(source[0] - '0');
remove(source, 1);
}
return value;
}
float valueOfFactor(char source[]) {
float value;
if (source[0] == '(' || source[0] == 's' || source[0] == 'c')
{
if (source[0] == '(')
{
remove(source, 1);
value = valueOfExpr(source);
remove(source, 1);
}
else if (source[0] == 's')
{
remove(source, 3);
value = sin(valueOfFactor(source));
}
else
{
remove(source, 3);
value = cos(valueOfExpr(source));
}
}
else
{
value = valueOfDigitSeq(source);
}
return value;
}
float valueOfTerm(char source[]) {
float value = valueOfFactor(source);
while (source[0] == '*' || source[0] == '/')
{
char mystery = source[0];
remove(source, 1);
if (mystery == '*')
{
value = value * valueOfTerm(source);
}
else if (mystery == '/')
{
value = value / valueOfTerm(source);
}
}
return value;
}
float valueOfExpr(char source[]) {
float value = valueOfTerm(source);
while (source[0] == '+' || source[0] == '-')
{
char mystery = source[0];
remove(source, 1);
if (mystery == '+')
{
value = value + valueOfTerm(source);
}
else
{
value = value - valueOfTerm(source);
}
}
return value;
}
void writeText(int xPos, int yPos, float size, string message) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_width, 0.0, window_height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(xPos, yPos, 0);
glScalef(size, size, 0);
glColor3f(1, 1, 1);
for (size_t i = 0; i < message.length(); i++) {
glutStrokeCharacter(GLUT_STROKE_ROMAN, message[i]);
}
}
float determineAngleIncrement() {
float angle_increment;
switch (angle_index) {
case 0:
angle_increment = PI/2;
break;
case 1:
angle_increment = PI/3;
break;
case 2:
angle_increment = PI/4;
break;
}
return angle_increment;
}
void drawAngle(int i, int equation) {
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
glLoadIdentity ();
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glBegin(GL_POINTS);
float angle_increment = determineAngleIncrement();
for (float angle = 0; angle < i * angle_increment + angle_increment; angle += .005) {
char *a = new char[equations[equation].size() + 1];
a[equations[equation].size()] = 0;
memcpy(a, equations[equation].c_str(), equations[equation].size());
float r = valueOfExpr(a);
float x = r * cos(angle);
float y = r * sin(angle);
glVertex3f(x, y, 0);
}
glEnd();
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
}
void displayGraphs()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1,1,1,1);
float header_font_size = .2, text_size = .3;
int numOfSquares = 9, numOfCols = sqrt(numOfSquares);
int mask = 0x3;
int space = 10;
int yScale = window_height / numOfCols, xScale = window_width / numOfCols;
for (int i = 0; i < numOfSquares; i++) {
int xToggle = (i % numOfCols) & mask, yToggle = (i / numOfCols) & mask;
int xMin = xToggle * xScale, yMin = yToggle * yScale;
int xCorrection = xToggle * (space / numOfCols), yCorrection = yToggle * (space / numOfCols);
int width = xScale - (space / numOfCols), height = yScale - (space / numOfCols);
glViewport(xMin + xCorrection, yMin + yCorrection, width, height);
// each different angle should have a different color
for (size_t graph = 0; graph < equations.size(); graph++) {
drawAngle(i, graph);
}
writeText(xPos, yPos, .3, angles[angle_index][i]);
}
glFlush();
}
void displayEquations() {
InitializeEquations();
for (size_t i = 0, yCorrection = 0; i < equations.size(); i++, yCorrection += 50) {
writeText(xPos, yPos + yCorrection, .25, "r = " + equations[i]);
}
}
///////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(window_width, window_height);
glutCreateWindow("polar graphs");
glutDisplayFunc(displayGraphs);
glutInitWindowSize(200, 200);
glutCreateWindow("equations");
glutPositionWindow(540, 40);
glutDisplayFunc(displayEquations);
glutMainLoop();
}
Picture:
Not too fond of how it displays the exclamation points still in the display but I'll fix that