// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// Copyright 2007, Daniel Fontijne, University of Amsterdam -- fontijne@science.uva.nl
#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <libgasandbox/common.h>
#include <libgasandbox/e2ga.h>
#include <libgasandbox/e2ga_draw.h>
#include <libgasandbox/gl_util.h>
#include <libgasandbox/glut_util.h>
using namespace e2ga;
using namespace mv_draw;
const char *WINDOW_TITLE = "Geometric Algebra, Chapter 2, Example 1: Drawing Bivectors";
// GLUT state information
int g_viewportWidth = 800;
int g_viewportHeight = 600;
int g_GLUTmenu;
bool g_drawParallelogram = true;
void display() {
doIntelWarning(); // warn for possible problems with pciking on Intel graphics chipsets
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, g_viewportWidth, g_viewportHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, g_viewportWidth, 0, g_viewportHeight, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// we store the label positions & text here:
std::vector<std::string> labelString;
std::vector<e2ga::vector> labelPos;
// how many bivectors? what spacing between them?:
const float entryWidth = 2.75f;
const float entryHeight = 3.5f;
const int nbBivectorX = 6;
const int nbBivectorY = 4;
// scale / translate to right transform:
const float scale = 40.0f;
glScalef(scale, scale, scale);
glTranslatef(entryWidth, ((float)nbBivectorY - 0.5f) * entryHeight, 0.0f);
int posX = 0;
e2ga::vector v1, v2, v1_plus_v2;
bivector B;
double step = 2 * M_PI / (nbBivectorX * nbBivectorY);
for (double a = 0; a < 2 * M_PI; a += step) {
// vector 1 is fixed to e1
v1 = e1;
// compute vector 2:
v2 = cos(a) * e1 + sin(a) * e2;
// compute the bivector:
B = v1 ^ v2;
// draw vector 1 (red), vector 2 (green)
glColor3f(1.0f, 0.0f, 0.0f);
draw(v1);
glColor3f(0.0f, 1.0f, 0.0f);
draw(v2);
// draw outer product v1^v2:
glColor3f(0.0f, 0.0f, 1.0f);
if (!g_drawParallelogram) {
draw(B);
}
else {
glDisable(GL_CULL_FACE);
v1_plus_v2 = v1 + v2;
// draw QUAD with vertices
// origin -> v1 -> (v1+v2) -> v2
glBegin(GL_QUADS);
glVertex2f(0.0f, 0.0f);
glVertex2f(v1.e1(), v1.e2());
glVertex2f(v1_plus_v2.e1(), v1_plus_v2.e2());
glVertex2f(v2.e1(), v2.e2());
glEnd();
}
// store label of bivector:
{
labelString.push_back(B.toString());
GLfloat pos[2];
viewportCoordinates(e3ga::_vector(0.35f * entryHeight * e3ga::e2).getC(e3ga::vector_e1_e2_e3), pos);
labelPos.push_back(e2ga::vector(vector_e1_e2, pos));
}
// translate to next entry:
glTranslatef(entryWidth, 0.0f, 0.0f);
posX++;
if (posX == nbBivectorX) {
posX = 0;
glTranslatef(-(float)nbBivectorX * entryWidth, -entryHeight, 0.0f);
}
}
glPopMatrix();
// draw the labels:
glColor3f(0.2f, 0.2f, 0.2f);
void *font = GLUT_BITMAP_HELVETICA_12;
for (unsigned int i = 0; i < labelString.size(); i++) {
float w = getBitmapStringWidth(font, labelString[i].c_str());
renderBitmapString(labelPos[i].e1() - 0.45f * w, labelPos[i].e2(), font, labelString[i].c_str());
}
glutSwapBuffers();
}
void reshape(GLint width, GLint height) {
g_viewportWidth = width;
g_viewportHeight = height;
}
void menuCallback(int value) {
g_drawParallelogram = value != 0;
// redraw viewport
glutPostRedisplay();
}
int main(int argc, char*argv[]) {
// profiling for Gaigen 2:
e2ga::g2Profiling::init();
e3ga::g2Profiling::init();
// GLUT Window Initialization:
glutInit (&argc, argv);
glutInitWindowSize(g_viewportWidth, g_viewportHeight);
glutInitDisplayMode( GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(WINDOW_TITLE);
// Register callbacks:
glutDisplayFunc(display);
glutReshapeFunc(reshape);
g_GLUTmenu = glutCreateMenu(menuCallback);
glutAddMenuEntry("disc", 0);
glutAddMenuEntry("parallelogram", 1);
glutAttachMenu(GLUT_LEFT_BUTTON);
glutAttachMenu(GLUT_MIDDLE_BUTTON);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0;
}