rbtree
diff test/test.c @ 0:6621337b6378
red-black tree lib
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Sun, 09 Oct 2011 07:48:14 +0300 |
parents | |
children | 7205a7d8d3d6 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/test.c Sun Oct 09 07:48:14 2011 +0300 1.3 @@ -0,0 +1,395 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <ctype.h> 1.8 +#include <math.h> 1.9 +#include <assert.h> 1.10 +#include <alloca.h> 1.11 + 1.12 +#ifndef __APPLE__ 1.13 +#include <GL/glut.h> 1.14 +#else 1.15 +#include <GLUT/glut.h> 1.16 +#endif 1.17 +#include <rbtree.h> 1.18 +#include <drawtext.h> 1.19 + 1.20 +#define FONTSZ 18 1.21 + 1.22 +void init_gl(int argc, char **argv); 1.23 +float rbvis_width(struct rbnode *tree); 1.24 +void rbvis_draw(struct rbnode *tree, float x, float y); 1.25 + 1.26 +void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol); 1.27 +void draw_fillet(float rad, int segm); 1.28 + 1.29 +struct rbtree *tree; 1.30 +int num_nodes; 1.31 +struct dtx_font *font; 1.32 +char input_buffer[64]; 1.33 +int win_xsz, win_ysz; 1.34 + 1.35 +int main(int argc, char **argv) 1.36 +{ 1.37 + int i; 1.38 + 1.39 + if(argv[1]) { 1.40 + if(!isdigit(argv[1][0])) { 1.41 + fprintf(stderr, "pass a fucking number, not: %s\n", argv[1]); 1.42 + return 1; 1.43 + } 1.44 + num_nodes = atoi(argv[1]); 1.45 + } 1.46 + 1.47 + if(!(font = dtx_open_font("linux-libertine.ttf", FONTSZ))) { 1.48 + fprintf(stderr, "failed to open font\n"); 1.49 + return 1; 1.50 + } 1.51 + 1.52 + if(!(tree = rb_create(RB_KEY_INT))) { 1.53 + return 1; 1.54 + } 1.55 + 1.56 + for(i=0; i<num_nodes; i++) { 1.57 + rb_inserti(tree, i, 0); 1.58 + } 1.59 + 1.60 + init_gl(argc, argv); 1.61 + return 0; 1.62 +} 1.63 + 1.64 +#define NWIDTH 28.0 1.65 +#define NHEIGHT 24.0 1.66 +#define PADDING 0 1.67 +#define DY (NHEIGHT + NHEIGHT / 2.0) 1.68 + 1.69 +#define VIS(node) ((struct visinfo*)(node)->data) 1.70 + 1.71 +void disp(void); 1.72 +void reshape(int x, int y); 1.73 +void keyb(unsigned char key, int x, int y); 1.74 +void draw_rect(float x, float y, float width, float height, const char *text, int red); 1.75 +void draw_link(float x0, float y0, float x1, float y1, int red); 1.76 + 1.77 +void init_gl(int argc, char **argv) 1.78 +{ 1.79 + glutInitWindowSize(1280, 720); 1.80 + glutInit(&argc, argv); 1.81 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); 1.82 + 1.83 + glutCreateWindow("foo"); 1.84 + 1.85 + dtx_use_font(font, FONTSZ); 1.86 + 1.87 + glutDisplayFunc(disp); 1.88 + glutReshapeFunc(reshape); 1.89 + glutKeyboardFunc(keyb); 1.90 + 1.91 + glEnable(GL_DEPTH_TEST); 1.92 + glEnable(GL_MULTISAMPLE); 1.93 + 1.94 + glutMainLoop(); 1.95 +} 1.96 + 1.97 +void disp(void) 1.98 +{ 1.99 + struct rbnode *root = rb_root(tree); 1.100 + 1.101 + glClearColor(0.57, 0.64, 0.59, 1.0); 1.102 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.103 + 1.104 + glMatrixMode(GL_MODELVIEW); 1.105 + glLoadIdentity(); 1.106 + 1.107 + if(input_buffer[0]) { 1.108 + char *prompt = "select node to delete: "; 1.109 + char *buf = alloca(strlen(prompt) + strlen(input_buffer)); 1.110 + 1.111 + glPushMatrix(); 1.112 + glTranslatef(10, 10, -0.9); 1.113 + glColor3f(0, 0, 0); 1.114 + sprintf(buf, "%s%s", prompt, input_buffer); 1.115 + dtx_string(buf); 1.116 + glPopMatrix(); 1.117 + } 1.118 + 1.119 + if(root) { 1.120 + rbvis_draw(root, rbvis_width(root->left) + NWIDTH, 550); 1.121 + } 1.122 + 1.123 + glutSwapBuffers(); 1.124 + assert(glGetError() == GL_NO_ERROR); 1.125 +} 1.126 + 1.127 + 1.128 +float rbvis_width(struct rbnode *tree) 1.129 +{ 1.130 + if(!tree) 1.131 + return NWIDTH; 1.132 + 1.133 + return NWIDTH + rbvis_width(tree->left) + rbvis_width(tree->right) + PADDING * 3.0; 1.134 +} 1.135 + 1.136 +void rbvis_draw(struct rbnode *tree, float x, float y) 1.137 +{ 1.138 + float leftx, rightx, nexty; 1.139 + static const float hxsz = NWIDTH / 2.0; 1.140 + static const float hysz = NHEIGHT / 2.0; 1.141 + char text[16]; 1.142 + 1.143 + if(!tree) 1.144 + return; 1.145 + 1.146 + leftx = x - (tree->left ? rbvis_width(tree->left->right) + NWIDTH : rbvis_width(tree->left) / 2.0); 1.147 + rightx = x + (tree->right ? rbvis_width(tree->right->left) + NWIDTH : rbvis_width(tree->right) / 2.0); 1.148 + 1.149 + nexty = y - DY; 1.150 + 1.151 + sprintf(text, "%d", rb_node_keyi(tree)); 1.152 + draw_rect(x - hxsz, y - hysz, NWIDTH, NHEIGHT, text, tree->red); 1.153 + 1.154 + rbvis_draw(tree->left, leftx, nexty); 1.155 + rbvis_draw(tree->right, rightx, nexty); 1.156 + 1.157 + if(tree->left) 1.158 + draw_link(x, y, leftx, nexty, tree->left->red); 1.159 + if(tree->right) 1.160 + draw_link(x, y, rightx, nexty, tree->right->red); 1.161 +} 1.162 + 1.163 +void draw_rect(float x, float y, float width, float height, const char *text, int red) 1.164 +{ 1.165 + float node_col[] = {0.63, 0.71, 0.82, 1.0}; 1.166 + float bord_col[] = {0, 0, 0, 1}; 1.167 + 1.168 + if(red) { 1.169 + bord_col[0] = 1.0; 1.170 + } 1.171 + 1.172 + glMatrixMode(GL_MODELVIEW); 1.173 + glPushMatrix(); 1.174 + glTranslatef(x + width / 2.0, y + height / 2.0, 0.0); 1.175 + 1.176 + draw_roundbox(width, height, 8, 6, node_col, 1.2, bord_col); 1.177 + 1.178 + glColor3f(0.15, 0.15, 0.15); 1.179 + glTranslatef(-dtx_string_width(text) / 2.0, -dtx_string_height(text) / 2.0, 0.1); 1.180 + dtx_string(text); 1.181 + glMatrixMode(GL_MODELVIEW); 1.182 + glPopMatrix(); 1.183 +} 1.184 + 1.185 +void draw_link(float x0, float y0, float x1, float y1, int red) 1.186 +{ 1.187 + glPushAttrib(GL_LINE_BIT); 1.188 + if(red) { 1.189 + glLineWidth(3); 1.190 + } else { 1.191 + glLineWidth(2); 1.192 + } 1.193 + 1.194 + glBegin(GL_LINES); 1.195 + if(red) { 1.196 + glColor3f(0.8, 0.36, 0.3); 1.197 + } else { 1.198 + glColor3f(0, 0, 0); 1.199 + } 1.200 + glVertex3f(x0, y0, -0.8); 1.201 + glVertex3f(x1, y1, -0.8); 1.202 + glEnd(); 1.203 + 1.204 + glPopAttrib(); 1.205 +} 1.206 + 1.207 +void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol) 1.208 +{ 1.209 + float hin_xsz, hin_ysz; 1.210 + 1.211 + if(border > 0.0f) { 1.212 + glPushMatrix(); 1.213 + glTranslatef(0, 0, -0.001); 1.214 + draw_roundbox(xsz + 2 * border, ysz + 2 * border, rad + border, segm, bcol, 0.0, bcol); 1.215 + glPopMatrix(); 1.216 + } 1.217 + 1.218 + /* half inner size */ 1.219 + hin_xsz = (xsz - 2.0 * rad) / 2.0; 1.220 + hin_ysz = (ysz - 2.0 * rad) / 2.0; 1.221 + 1.222 + glColor4fv(col); 1.223 + 1.224 + glBegin(GL_QUADS); 1.225 + /* center */ 1.226 + glVertex2f(-hin_xsz, -hin_ysz); 1.227 + glVertex2f(hin_xsz, -hin_ysz); 1.228 + glVertex2f(hin_xsz, hin_ysz); 1.229 + glVertex2f(-hin_xsz, hin_ysz); 1.230 + /* right */ 1.231 + glVertex2f(hin_xsz, -hin_ysz); 1.232 + glVertex2f(hin_xsz + rad, -hin_ysz); 1.233 + glVertex2f(hin_xsz + rad, hin_ysz); 1.234 + glVertex2f(hin_xsz, hin_ysz); 1.235 + /* top */ 1.236 + glVertex2f(-hin_xsz, hin_ysz); 1.237 + glVertex2f(hin_xsz, hin_ysz); 1.238 + glVertex2f(hin_xsz, hin_ysz + rad); 1.239 + glVertex2f(-hin_xsz, hin_ysz + rad); 1.240 + /* left */ 1.241 + glVertex2f(-hin_xsz - rad, -hin_ysz); 1.242 + glVertex2f(-hin_xsz, -hin_ysz); 1.243 + glVertex2f(-hin_xsz, hin_ysz); 1.244 + glVertex2f(-hin_xsz - rad, hin_ysz); 1.245 + /* bottom */ 1.246 + glVertex2f(-hin_xsz, -hin_ysz - rad); 1.247 + glVertex2f(hin_xsz, -hin_ysz - rad); 1.248 + glVertex2f(hin_xsz, -hin_ysz); 1.249 + glVertex2f(-hin_xsz, -hin_ysz); 1.250 + glEnd(); 1.251 + 1.252 + glMatrixMode(GL_MODELVIEW); 1.253 + 1.254 + glPushMatrix(); 1.255 + glTranslatef(hin_xsz, hin_ysz, 0); 1.256 + draw_fillet(rad, segm); 1.257 + glPopMatrix(); 1.258 + 1.259 + glPushMatrix(); 1.260 + glTranslatef(-hin_xsz, hin_ysz, 0); 1.261 + glRotatef(90, 0, 0, 1); 1.262 + draw_fillet(rad, segm); 1.263 + glPopMatrix(); 1.264 + 1.265 + glPushMatrix(); 1.266 + glTranslatef(-hin_xsz, -hin_ysz, 0); 1.267 + glRotatef(180, 0, 0, 1); 1.268 + draw_fillet(rad, segm); 1.269 + glPopMatrix(); 1.270 + 1.271 + glPushMatrix(); 1.272 + glTranslatef(hin_xsz, -hin_ysz, 0); 1.273 + glRotatef(270, 0, 0, 1); 1.274 + draw_fillet(rad, segm); 1.275 + glPopMatrix(); 1.276 +} 1.277 + 1.278 +void draw_fillet(float rad, int segm) 1.279 +{ 1.280 + int i; 1.281 + 1.282 + glBegin(GL_TRIANGLE_FAN); 1.283 + glVertex2f(0, 0); 1.284 + for(i=0; i<segm; i++) { 1.285 + float theta = 0.5 * M_PI * (float)i / (float)(segm - 1); 1.286 + float x = cos(theta) * rad; 1.287 + float y = sin(theta) * rad; 1.288 + glVertex2f(x, y); 1.289 + } 1.290 + glEnd(); 1.291 +} 1.292 + 1.293 + 1.294 +void reshape(int x, int y) 1.295 +{ 1.296 + win_xsz = x; 1.297 + win_ysz = y; 1.298 + 1.299 + glViewport(0, 0, x, y); 1.300 + 1.301 + glMatrixMode(GL_PROJECTION); 1.302 + glLoadIdentity(); 1.303 + glOrtho(0, x, 0, y, -1, 1); 1.304 +} 1.305 + 1.306 +void keyb(unsigned char key, int x, int y) 1.307 +{ 1.308 + static int wposx = -1, wposy; 1.309 + static char *inp_next; 1.310 + 1.311 + switch(key) { 1.312 + case 27: 1.313 + exit(0); 1.314 + 1.315 + case 'f': 1.316 + case 'F': 1.317 + if(wposx >= 0) { 1.318 + glutPositionWindow(wposx, wposy); 1.319 + wposx = -1; 1.320 + } else { 1.321 + wposx = glutGet(GLUT_WINDOW_X); 1.322 + wposy = glutGet(GLUT_WINDOW_Y); 1.323 + glutFullScreen(); 1.324 + } 1.325 + break; 1.326 + 1.327 + case 'a': 1.328 + rb_inserti(tree, num_nodes++, 0); 1.329 + glutPostRedisplay(); 1.330 + break; 1.331 + 1.332 + case 'r': 1.333 + { 1.334 + int x; 1.335 + do { 1.336 + x = rand() % 1024; 1.337 + } while(rb_findi(tree, x)); 1.338 + 1.339 + rb_inserti(tree, x, 0); 1.340 + } 1.341 + glutPostRedisplay(); 1.342 + break; 1.343 + 1.344 + case 'd': 1.345 + inp_next = input_buffer; 1.346 + *inp_next++ = ' '; 1.347 + *inp_next = 0; 1.348 + glutPostRedisplay(); 1.349 + break; 1.350 + 1.351 + case '0': 1.352 + case '1': 1.353 + case '2': 1.354 + case '3': 1.355 + case '4': 1.356 + case '5': 1.357 + case '6': 1.358 + case '7': 1.359 + case '8': 1.360 + case '9': 1.361 + if(inp_next) { 1.362 + *inp_next++ = key; 1.363 + *inp_next = 0; 1.364 + glutPostRedisplay(); 1.365 + } 1.366 + break; 1.367 + 1.368 + case '\b': 1.369 + if(inp_next > input_buffer) { 1.370 + *--inp_next = 0; 1.371 + glutPostRedisplay(); 1.372 + } 1.373 + break; 1.374 + 1.375 + case '\n': 1.376 + case '\r': 1.377 + if(inp_next) { 1.378 + int x; 1.379 + char *endp; 1.380 + 1.381 + *inp_next = 0; 1.382 + inp_next = 0; 1.383 + 1.384 + if((x = strtol(input_buffer, &endp, 10)), endp == input_buffer) { 1.385 + fprintf(stderr, "invalid input: %s\n", input_buffer); 1.386 + } else if(!rb_findi(tree, x)) { 1.387 + fprintf(stderr, "%d not found in the tree\n", x); 1.388 + } else { 1.389 + printf("deleting: %d\n", x); 1.390 + rb_deletei(tree, x); 1.391 + } 1.392 + input_buffer[0] = 0; 1.393 + glutPostRedisplay(); 1.394 + } 1.395 + break; 1.396 + } 1.397 +} 1.398 +