CS 330 Lecture 33 – Marching Squares: A C++ Case Study
Agenda
- what ?s
- contourer: a case study on OOP and C++
- bit manipulation
TODO
- Get two homeworks done before the networks students ruin us all.
Code
msquares.cpp
#include <iostream>
#include <fstream>
#include <limits>
#include <GL/glut.h>
using std::string;
class Map {
public:
Map() {}
Map(const string &path);
const int &operator()(int c, int r) const;
int &operator()(int c, int r);
int GetWidth() const;
int GetHeight() const;
int GetMin() const;
int GetMax() const;
private:
int *elevation;
int width;
int height;
int max;
int min;
};
Map::Map(const string &path) {
std::ifstream in(path.c_str());
int nfac, nocean, nland;
in >> width >> height >> nfac >> nocean >> nland;
elevation = new int[width * height];
min = std::numeric_limits<int>::max();
max = std::numeric_limits<int>::min();
for (int lat = 0; lat < height; ++lat) {
for (int lon = 0; lon < width; ++lon) {
int height;
in >> height;
if (height == nocean) {
height = 0;
}
if (height > max) {
max = height;
} else if (height < min) {
min = height;
}
(*this)(lon, GetHeight() - 1 - lat) = height;
}
}
in.close();
}
int &Map::operator()(int c, int r) {
return elevation[r * GetWidth() + c];
}
const int &Map::operator()(int c, int r) const {
return elevation[r * GetWidth() + c];
}
int Map::GetWidth() const {
return width;
}
int Map::GetHeight() const {
return height;
}
int Map::GetMin() const {
return min;
}
int Map::GetMax() const {
return max;
}
static int iso = 1000;
static Map map;
void on_draw() {
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(1.0f, 1.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, map.GetWidth(), 0.0f, map.GetHeight(), -1.0f, 1.0f);
// TODO draw contour lines
glBegin(GL_LINES);
for (int lat = 0; lat < map.GetHeight() - 1; ++lat) {
for (int lon = 0; lon < map.GetWidth() - 1; ++lon) {
int bl = map(lon, lat) >= iso;
int br = map(lon + 1, lat) >= iso;
int tl = map(lon, lat + 1) >= iso;
int tr = map(lon + 1, lat + 1) >= iso;
int config = bl | (br << 1) | (tl << 2) | (tr << 3);
if (config > 7) {
config = 15 - config;
}
switch (config) {
case 0:
break;
case 1:
glVertex2f(lon, lat + 0.5f);
glVertex2f(lon + 0.5f, lat);
break;
case 2:
glVertex2f(lon + 0.5f, lat);
glVertex2f(lon + 1.0f, lat + 0.5f);
break;
case 3:
glVertex2f(lon, lat + 0.5f);
glVertex2f(lon + 1.0f, lat + 0.5f);
break;
case 4:
glVertex2f(lon, lat + 0.5f);
glVertex2f(lon + 0.5f, lat + 1.0f);
break;
case 5:
glVertex2f(lon + 0.5f, lat);
glVertex2f(lon + 0.5f, lat + 1.0f);
break;
case 6:
glVertex2f(lon + 0.5f, lat);
glVertex2f(lon, lat + 0.5f);
glVertex2f(lon + 0.5f, lat + 1.0f);
glVertex2f(lon + 1.0f, lat + 0.5f);
break;
case 7:
glVertex2f(lon + 0.5f, lat + 1.0f);
glVertex2f(lon + 1.0f, lat + 0.5f);
break;
}
}
}
glEnd();
glutSwapBuffers();
}
void on_special_key(int key, int x, int y) {
switch (key) {
case GLUT_KEY_UP:
iso += 25;
break;
case GLUT_KEY_DOWN:
iso -= 25;
break;
default:
break;
}
std::cout << "iso: " << iso << std::endl;
glutPostRedisplay();
}
int main(int argc, char **argv) {
// open file
// read nlon, nlat, nfac, nocean, nland
// allocate
// read
map = Map("dem030_ascii.dat");
// TODO normalize
float *normalized = new float[map.GetWidth() * map.GetHeight()];
for (int lat = 0; lat < map.GetHeight(); ++lat) {
for (int lon = 0; lon < map.GetWidth(); ++lon) {
int i = lat * map.GetWidth() + lon;
normalized[i] = (map(lon, lat) - map.GetMin()) / (float) (map.GetMax() - map.GetMin());
}
}
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(1200, 600);
glutInit(&argc, argv);
glutCreateWindow("Contours");
glutDisplayFunc(on_draw);
glutSpecialFunc(on_special_key);
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, map.GetWidth(), map.GetHeight(), 0, GL_LUMINANCE, GL_FLOAT, normalized);
delete[] normalized;
glutMainLoop();
return 0;
}
Haiku
Boole cleaved us in two
Not just once, but many times
Don’t be only white
Not just once, but many times
Don’t be only white