rbtree
changeset 5:56a08d00bb41
added rb_copy and rb_clear
moved the visualization test to test/vis/
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 12 Oct 2011 05:25:34 +0300 |
parents | c4f36d709ee9 |
children | 028a21468abf b266386d19ce |
files | Makefile.in src/rbtree.c src/rbtree.h test/Makefile test/test.c test/vis/Makefile test/vis/test.c |
diffstat | 7 files changed, 460 insertions(+), 436 deletions(-) [+] |
line diff
1.1 --- a/Makefile.in Wed Oct 12 05:01:11 2011 +0300 1.2 +++ b/Makefile.in Wed Oct 12 05:25:34 2011 +0300 1.3 @@ -11,7 +11,7 @@ 1.4 ifeq ($(shell uname -s), Darwin) 1.5 lib_a = $(name).a 1.6 lib_so = $(name).dylib 1.7 - shared = -dynamiclib $(lib_so) 1.8 + shared = -dynamiclib 1.9 else 1.10 lib_a = lib$(name).a 1.11 devlink = lib$(name).so
2.1 --- a/src/rbtree.c Wed Oct 12 05:01:11 2011 +0300 2.2 +++ b/src/rbtree.c Wed Oct 12 05:25:34 2011 +0300 2.3 @@ -90,6 +90,27 @@ 2.4 rb->del_cls = cls; 2.5 } 2.6 2.7 + 2.8 +void rb_clear(struct rbtree *rb) 2.9 +{ 2.10 + del_tree(rb->root, rb->del, rb->del_cls); 2.11 + rb->root = 0; 2.12 +} 2.13 + 2.14 +int rb_copy(struct rbtree *dest, struct rbtree *src) 2.15 +{ 2.16 + struct rbnode *node; 2.17 + 2.18 + rb_clear(dest); 2.19 + rb_begin(src); 2.20 + while((node = rb_next(src))) { 2.21 + if(rb_insert(dest, node->key, node->data) == -1) { 2.22 + return -1; 2.23 + } 2.24 + } 2.25 + return 0; 2.26 +} 2.27 + 2.28 int rb_size(struct rbtree *rb) 2.29 { 2.30 return count_nodes(rb->root);
3.1 --- a/src/rbtree.h Wed Oct 12 05:01:11 2011 +0300 3.2 +++ b/src/rbtree.h Wed Oct 12 05:25:34 2011 +0300 3.3 @@ -37,6 +37,9 @@ 3.4 void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func); 3.5 void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls); 3.6 3.7 +void rb_clear(struct rbtree *rb); 3.8 +int rb_copy(struct rbtree *dest, struct rbtree *src); 3.9 + 3.10 int rb_size(struct rbtree *rb); 3.11 3.12 int rb_insert(struct rbtree *rb, void *key, void *data);
4.1 --- a/test/Makefile Wed Oct 12 05:01:11 2011 +0300 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,32 +0,0 @@ 4.4 -obj = test.o 4.5 -bin = test 4.6 - 4.7 -font = linux-libertine.ttf 4.8 - 4.9 -CC = gcc 4.10 -CFLAGS = -pedantic -Wall -g -I../src -I/usr/local/include 4.11 -LDFLAGS = -L.. -L/usr/local/lib $(libgl) -lrbtree -ldrawtext 4.12 - 4.13 -ifeq ($(shell uname -s), Darwin) 4.14 - libgl = -framework OpenGL -framework GLUT 4.15 -else 4.16 - libgl = -lGL -lglut 4.17 -endif 4.18 - 4.19 -.PHONY: all 4.20 -all: $(bin) $(font) 4.21 - 4.22 -$(bin): $(obj) 4.23 - $(CC) -o $@ $(obj) $(LDFLAGS) 4.24 - 4.25 -$(font): 4.26 - wget http://downloads.sourceforge.net/project/linuxlibertine/linuxlibertine/5.1.3-2/LinLibertineTTF_5.1.3_2011_06_21.tgz 4.27 - mkdir -p linlibertine 4.28 - cd linlibertine; tar xzvf ../LinLibertineTTF_5.1.3_2011_06_21.tgz 4.29 - rm -f LinLibertineTTF_5.1.3_2011_06_21.tgz 4.30 - cp linlibertine/LinLibertine_R.ttf $@ 4.31 - 4.32 - 4.33 -.PHONY: clean 4.34 -clean: 4.35 - rm -f $(obj) $(bin)
5.1 --- a/test/test.c Wed Oct 12 05:01:11 2011 +0300 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,403 +0,0 @@ 5.4 -#include <stdio.h> 5.5 -#include <stdlib.h> 5.6 -#include <string.h> 5.7 -#include <ctype.h> 5.8 -#include <math.h> 5.9 -#include <assert.h> 5.10 -#include <alloca.h> 5.11 - 5.12 -#ifndef __APPLE__ 5.13 -#include <GL/glut.h> 5.14 -#else 5.15 -#include <GLUT/glut.h> 5.16 -#endif 5.17 -#include <rbtree.h> 5.18 -#include <drawtext.h> 5.19 - 5.20 -#define FONTSZ 18 5.21 - 5.22 -void init_gl(int argc, char **argv); 5.23 -float rbvis_width(struct rbnode *tree); 5.24 -void rbvis_draw(struct rbnode *tree, float x, float y); 5.25 - 5.26 -void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol); 5.27 -void draw_fillet(float rad, int segm); 5.28 - 5.29 -struct rbtree *tree; 5.30 -int num_nodes; 5.31 -struct dtx_font *font; 5.32 -char input_buffer[64]; 5.33 -int win_xsz, win_ysz; 5.34 - 5.35 -int main(int argc, char **argv) 5.36 -{ 5.37 - int i; 5.38 - 5.39 - if(argv[1]) { 5.40 - if(!isdigit(argv[1][0])) { 5.41 - fprintf(stderr, "pass a fucking number, not: %s\n", argv[1]); 5.42 - return 1; 5.43 - } 5.44 - num_nodes = atoi(argv[1]); 5.45 - } 5.46 - 5.47 - if(!(font = dtx_open_font("linux-libertine.ttf", FONTSZ))) { 5.48 - fprintf(stderr, "failed to open font\n"); 5.49 - return 1; 5.50 - } 5.51 - 5.52 - if(!(tree = rb_create(RB_KEY_INT))) { 5.53 - return 1; 5.54 - } 5.55 - 5.56 - for(i=0; i<num_nodes; i++) { 5.57 - rb_inserti(tree, i, 0); 5.58 - } 5.59 - 5.60 - init_gl(argc, argv); 5.61 - return 0; 5.62 -} 5.63 - 5.64 -#define NWIDTH 28.0 5.65 -#define NHEIGHT 24.0 5.66 -#define PADDING 0 5.67 -#define DY (NHEIGHT + NHEIGHT / 2.0) 5.68 - 5.69 -#define VIS(node) ((struct visinfo*)(node)->data) 5.70 - 5.71 -void disp(void); 5.72 -void reshape(int x, int y); 5.73 -void keyb(unsigned char key, int x, int y); 5.74 -void draw_rect(float x, float y, float width, float height, const char *text, int red); 5.75 -void draw_link(float x0, float y0, float x1, float y1, int red); 5.76 - 5.77 -void init_gl(int argc, char **argv) 5.78 -{ 5.79 - glutInitWindowSize(1280, 720); 5.80 - glutInit(&argc, argv); 5.81 - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); 5.82 - 5.83 - glutCreateWindow("foo"); 5.84 - 5.85 - dtx_use_font(font, FONTSZ); 5.86 - 5.87 - glutDisplayFunc(disp); 5.88 - glutReshapeFunc(reshape); 5.89 - glutKeyboardFunc(keyb); 5.90 - 5.91 - glEnable(GL_DEPTH_TEST); 5.92 - glEnable(GL_MULTISAMPLE); 5.93 - 5.94 - glutMainLoop(); 5.95 -} 5.96 - 5.97 -void disp(void) 5.98 -{ 5.99 - struct rbnode *root = rb_root(tree); 5.100 - 5.101 - glClearColor(0.57, 0.64, 0.59, 1.0); 5.102 - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 5.103 - 5.104 - glMatrixMode(GL_MODELVIEW); 5.105 - glLoadIdentity(); 5.106 - 5.107 - if(input_buffer[0]) { 5.108 - char *prompt = "select node: "; 5.109 - char *buf = alloca(strlen(prompt) + strlen(input_buffer)); 5.110 - 5.111 - glPushMatrix(); 5.112 - glTranslatef(10, 10, -0.9); 5.113 - glColor3f(0, 0, 0); 5.114 - sprintf(buf, "%s%s", prompt, input_buffer); 5.115 - dtx_string(buf); 5.116 - glPopMatrix(); 5.117 - } 5.118 - 5.119 - if(root) { 5.120 - rbvis_draw(root, rbvis_width(root->left) + NWIDTH, 550); 5.121 - } 5.122 - 5.123 - glutSwapBuffers(); 5.124 - assert(glGetError() == GL_NO_ERROR); 5.125 -} 5.126 - 5.127 - 5.128 -float rbvis_width(struct rbnode *tree) 5.129 -{ 5.130 - if(!tree) 5.131 - return NWIDTH; 5.132 - 5.133 - return NWIDTH + rbvis_width(tree->left) + rbvis_width(tree->right) + PADDING * 3.0; 5.134 -} 5.135 - 5.136 -void rbvis_draw(struct rbnode *tree, float x, float y) 5.137 -{ 5.138 - float leftx, rightx, nexty; 5.139 - static const float hxsz = NWIDTH / 2.0; 5.140 - static const float hysz = NHEIGHT / 2.0; 5.141 - char text[16]; 5.142 - 5.143 - if(!tree) 5.144 - return; 5.145 - 5.146 - leftx = x - (tree->left ? rbvis_width(tree->left->right) + NWIDTH : rbvis_width(tree->left) / 2.0); 5.147 - rightx = x + (tree->right ? rbvis_width(tree->right->left) + NWIDTH : rbvis_width(tree->right) / 2.0); 5.148 - 5.149 - nexty = y - DY; 5.150 - 5.151 - sprintf(text, "%d", rb_node_keyi(tree)); 5.152 - draw_rect(x - hxsz, y - hysz, NWIDTH, NHEIGHT, text, tree->red); 5.153 - 5.154 - rbvis_draw(tree->left, leftx, nexty); 5.155 - rbvis_draw(tree->right, rightx, nexty); 5.156 - 5.157 - if(tree->left) 5.158 - draw_link(x, y, leftx, nexty, tree->left->red); 5.159 - if(tree->right) 5.160 - draw_link(x, y, rightx, nexty, tree->right->red); 5.161 -} 5.162 - 5.163 -void draw_rect(float x, float y, float width, float height, const char *text, int red) 5.164 -{ 5.165 - float node_col[] = {0.63, 0.71, 0.82, 1.0}; 5.166 - float bord_col[] = {0, 0, 0, 1}; 5.167 - 5.168 - if(red) { 5.169 - bord_col[0] = 1.0; 5.170 - } 5.171 - 5.172 - glMatrixMode(GL_MODELVIEW); 5.173 - glPushMatrix(); 5.174 - glTranslatef(x + width / 2.0, y + height / 2.0, 0.0); 5.175 - 5.176 - draw_roundbox(width, height, 8, 6, node_col, 1.2, bord_col); 5.177 - 5.178 - glColor3f(0.15, 0.15, 0.15); 5.179 - glTranslatef(-dtx_string_width(text) / 2.0, -dtx_string_height(text) / 2.0, 0.1); 5.180 - dtx_string(text); 5.181 - glMatrixMode(GL_MODELVIEW); 5.182 - glPopMatrix(); 5.183 -} 5.184 - 5.185 -void draw_link(float x0, float y0, float x1, float y1, int red) 5.186 -{ 5.187 - glPushAttrib(GL_LINE_BIT); 5.188 - if(red) { 5.189 - glLineWidth(3); 5.190 - } else { 5.191 - glLineWidth(2); 5.192 - } 5.193 - 5.194 - glBegin(GL_LINES); 5.195 - if(red) { 5.196 - glColor3f(0.8, 0.36, 0.3); 5.197 - } else { 5.198 - glColor3f(0, 0, 0); 5.199 - } 5.200 - glVertex3f(x0, y0, -0.8); 5.201 - glVertex3f(x1, y1, -0.8); 5.202 - glEnd(); 5.203 - 5.204 - glPopAttrib(); 5.205 -} 5.206 - 5.207 -void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol) 5.208 -{ 5.209 - float hin_xsz, hin_ysz; 5.210 - 5.211 - if(border > 0.0f) { 5.212 - glPushMatrix(); 5.213 - glTranslatef(0, 0, -0.001); 5.214 - draw_roundbox(xsz + 2 * border, ysz + 2 * border, rad + border, segm, bcol, 0.0, bcol); 5.215 - glPopMatrix(); 5.216 - } 5.217 - 5.218 - /* half inner size */ 5.219 - hin_xsz = (xsz - 2.0 * rad) / 2.0; 5.220 - hin_ysz = (ysz - 2.0 * rad) / 2.0; 5.221 - 5.222 - glColor4fv(col); 5.223 - 5.224 - glBegin(GL_QUADS); 5.225 - /* center */ 5.226 - glVertex2f(-hin_xsz, -hin_ysz); 5.227 - glVertex2f(hin_xsz, -hin_ysz); 5.228 - glVertex2f(hin_xsz, hin_ysz); 5.229 - glVertex2f(-hin_xsz, hin_ysz); 5.230 - /* right */ 5.231 - glVertex2f(hin_xsz, -hin_ysz); 5.232 - glVertex2f(hin_xsz + rad, -hin_ysz); 5.233 - glVertex2f(hin_xsz + rad, hin_ysz); 5.234 - glVertex2f(hin_xsz, hin_ysz); 5.235 - /* top */ 5.236 - glVertex2f(-hin_xsz, hin_ysz); 5.237 - glVertex2f(hin_xsz, hin_ysz); 5.238 - glVertex2f(hin_xsz, hin_ysz + rad); 5.239 - glVertex2f(-hin_xsz, hin_ysz + rad); 5.240 - /* left */ 5.241 - glVertex2f(-hin_xsz - rad, -hin_ysz); 5.242 - glVertex2f(-hin_xsz, -hin_ysz); 5.243 - glVertex2f(-hin_xsz, hin_ysz); 5.244 - glVertex2f(-hin_xsz - rad, hin_ysz); 5.245 - /* bottom */ 5.246 - glVertex2f(-hin_xsz, -hin_ysz - rad); 5.247 - glVertex2f(hin_xsz, -hin_ysz - rad); 5.248 - glVertex2f(hin_xsz, -hin_ysz); 5.249 - glVertex2f(-hin_xsz, -hin_ysz); 5.250 - glEnd(); 5.251 - 5.252 - glMatrixMode(GL_MODELVIEW); 5.253 - 5.254 - glPushMatrix(); 5.255 - glTranslatef(hin_xsz, hin_ysz, 0); 5.256 - draw_fillet(rad, segm); 5.257 - glPopMatrix(); 5.258 - 5.259 - glPushMatrix(); 5.260 - glTranslatef(-hin_xsz, hin_ysz, 0); 5.261 - glRotatef(90, 0, 0, 1); 5.262 - draw_fillet(rad, segm); 5.263 - glPopMatrix(); 5.264 - 5.265 - glPushMatrix(); 5.266 - glTranslatef(-hin_xsz, -hin_ysz, 0); 5.267 - glRotatef(180, 0, 0, 1); 5.268 - draw_fillet(rad, segm); 5.269 - glPopMatrix(); 5.270 - 5.271 - glPushMatrix(); 5.272 - glTranslatef(hin_xsz, -hin_ysz, 0); 5.273 - glRotatef(270, 0, 0, 1); 5.274 - draw_fillet(rad, segm); 5.275 - glPopMatrix(); 5.276 -} 5.277 - 5.278 -void draw_fillet(float rad, int segm) 5.279 -{ 5.280 - int i; 5.281 - 5.282 - glBegin(GL_TRIANGLE_FAN); 5.283 - glVertex2f(0, 0); 5.284 - for(i=0; i<segm; i++) { 5.285 - float theta = 0.5 * M_PI * (float)i / (float)(segm - 1); 5.286 - float x = cos(theta) * rad; 5.287 - float y = sin(theta) * rad; 5.288 - glVertex2f(x, y); 5.289 - } 5.290 - glEnd(); 5.291 -} 5.292 - 5.293 - 5.294 -void reshape(int x, int y) 5.295 -{ 5.296 - win_xsz = x; 5.297 - win_ysz = y; 5.298 - 5.299 - glViewport(0, 0, x, y); 5.300 - 5.301 - glMatrixMode(GL_PROJECTION); 5.302 - glLoadIdentity(); 5.303 - glOrtho(0, x, 0, y, -1, 1); 5.304 -} 5.305 - 5.306 -void keyb(unsigned char key, int x, int y) 5.307 -{ 5.308 - static int wposx = -1, wposy; 5.309 - static char *inp_next; 5.310 - static char op; 5.311 - 5.312 - switch(key) { 5.313 - case 27: 5.314 - exit(0); 5.315 - 5.316 - case 'a': 5.317 - rb_inserti(tree, num_nodes++, 0); 5.318 - glutPostRedisplay(); 5.319 - break; 5.320 - 5.321 - case 'r': 5.322 - { 5.323 - int x; 5.324 - do { 5.325 - x = rand() % 1024; 5.326 - } while(rb_findi(tree, x)); 5.327 - 5.328 - rb_inserti(tree, x, 0); 5.329 - } 5.330 - glutPostRedisplay(); 5.331 - break; 5.332 - 5.333 - case 'd': 5.334 - case 'f': 5.335 - op = key; 5.336 - inp_next = input_buffer; 5.337 - *inp_next++ = ' '; 5.338 - *inp_next = 0; 5.339 - glutPostRedisplay(); 5.340 - break; 5.341 - 5.342 - case '0': 5.343 - case '1': 5.344 - case '2': 5.345 - case '3': 5.346 - case '4': 5.347 - case '5': 5.348 - case '6': 5.349 - case '7': 5.350 - case '8': 5.351 - case '9': 5.352 - if(inp_next) { 5.353 - *inp_next++ = key; 5.354 - *inp_next = 0; 5.355 - glutPostRedisplay(); 5.356 - } 5.357 - break; 5.358 - 5.359 - case '\b': 5.360 - if(inp_next > input_buffer) { 5.361 - *--inp_next = 0; 5.362 - glutPostRedisplay(); 5.363 - } 5.364 - break; 5.365 - 5.366 - case '\n': 5.367 - case '\r': 5.368 - if(inp_next) { 5.369 - int x; 5.370 - char *endp; 5.371 - 5.372 - *inp_next = 0; 5.373 - inp_next = 0; 5.374 - 5.375 - if((x = strtol(input_buffer, &endp, 10)), endp == input_buffer) { 5.376 - fprintf(stderr, "invalid input: %s\n", input_buffer); 5.377 - } else if(!rb_findi(tree, x)) { 5.378 - fprintf(stderr, "%d not found in the tree\n", x); 5.379 - } else { 5.380 - if(op == 'd') { 5.381 - printf("deleting: %d\n", x); 5.382 - rb_deletei(tree, x); 5.383 - } else { 5.384 - printf("%d found!\n", x); 5.385 - } 5.386 - } 5.387 - input_buffer[0] = 0; 5.388 - glutPostRedisplay(); 5.389 - } 5.390 - break; 5.391 - 5.392 - case 'p': 5.393 - { 5.394 - struct rbnode *node; 5.395 - 5.396 - rb_begin(tree); 5.397 - while((node = rb_next(tree))) { 5.398 - int key = rb_node_keyi(node); 5.399 - printf("%d ", key); 5.400 - } 5.401 - putchar('\n'); 5.402 - } 5.403 - break; 5.404 - } 5.405 -} 5.406 -
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/vis/Makefile Wed Oct 12 05:25:34 2011 +0300 6.3 @@ -0,0 +1,32 @@ 6.4 +obj = test.o 6.5 +bin = test 6.6 + 6.7 +font = linux-libertine.ttf 6.8 + 6.9 +CC = gcc 6.10 +CFLAGS = -pedantic -Wall -g -I../src -I/usr/local/include 6.11 +LDFLAGS = -L.. -L/usr/local/lib $(libgl) -lrbtree -ldrawtext 6.12 + 6.13 +ifeq ($(shell uname -s), Darwin) 6.14 + libgl = -framework OpenGL -framework GLUT 6.15 +else 6.16 + libgl = -lGL -lglut 6.17 +endif 6.18 + 6.19 +.PHONY: all 6.20 +all: $(bin) $(font) 6.21 + 6.22 +$(bin): $(obj) 6.23 + $(CC) -o $@ $(obj) $(LDFLAGS) 6.24 + 6.25 +$(font): 6.26 + wget http://downloads.sourceforge.net/project/linuxlibertine/linuxlibertine/5.1.3-2/LinLibertineTTF_5.1.3_2011_06_21.tgz 6.27 + mkdir -p linlibertine 6.28 + cd linlibertine; tar xzvf ../LinLibertineTTF_5.1.3_2011_06_21.tgz 6.29 + rm -f LinLibertineTTF_5.1.3_2011_06_21.tgz 6.30 + cp linlibertine/LinLibertine_R.ttf $@ 6.31 + 6.32 + 6.33 +.PHONY: clean 6.34 +clean: 6.35 + rm -f $(obj) $(bin)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/vis/test.c Wed Oct 12 05:25:34 2011 +0300 7.3 @@ -0,0 +1,403 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <string.h> 7.7 +#include <ctype.h> 7.8 +#include <math.h> 7.9 +#include <assert.h> 7.10 +#include <alloca.h> 7.11 + 7.12 +#ifndef __APPLE__ 7.13 +#include <GL/glut.h> 7.14 +#else 7.15 +#include <GLUT/glut.h> 7.16 +#endif 7.17 +#include <rbtree.h> 7.18 +#include <drawtext.h> 7.19 + 7.20 +#define FONTSZ 18 7.21 + 7.22 +void init_gl(int argc, char **argv); 7.23 +float rbvis_width(struct rbnode *tree); 7.24 +void rbvis_draw(struct rbnode *tree, float x, float y); 7.25 + 7.26 +void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol); 7.27 +void draw_fillet(float rad, int segm); 7.28 + 7.29 +struct rbtree *tree; 7.30 +int num_nodes; 7.31 +struct dtx_font *font; 7.32 +char input_buffer[64]; 7.33 +int win_xsz, win_ysz; 7.34 + 7.35 +int main(int argc, char **argv) 7.36 +{ 7.37 + int i; 7.38 + 7.39 + if(argv[1]) { 7.40 + if(!isdigit(argv[1][0])) { 7.41 + fprintf(stderr, "pass a fucking number, not: %s\n", argv[1]); 7.42 + return 1; 7.43 + } 7.44 + num_nodes = atoi(argv[1]); 7.45 + } 7.46 + 7.47 + if(!(font = dtx_open_font("linux-libertine.ttf", FONTSZ))) { 7.48 + fprintf(stderr, "failed to open font\n"); 7.49 + return 1; 7.50 + } 7.51 + 7.52 + if(!(tree = rb_create(RB_KEY_INT))) { 7.53 + return 1; 7.54 + } 7.55 + 7.56 + for(i=0; i<num_nodes; i++) { 7.57 + rb_inserti(tree, i, 0); 7.58 + } 7.59 + 7.60 + init_gl(argc, argv); 7.61 + return 0; 7.62 +} 7.63 + 7.64 +#define NWIDTH 28.0 7.65 +#define NHEIGHT 24.0 7.66 +#define PADDING 0 7.67 +#define DY (NHEIGHT + NHEIGHT / 2.0) 7.68 + 7.69 +#define VIS(node) ((struct visinfo*)(node)->data) 7.70 + 7.71 +void disp(void); 7.72 +void reshape(int x, int y); 7.73 +void keyb(unsigned char key, int x, int y); 7.74 +void draw_rect(float x, float y, float width, float height, const char *text, int red); 7.75 +void draw_link(float x0, float y0, float x1, float y1, int red); 7.76 + 7.77 +void init_gl(int argc, char **argv) 7.78 +{ 7.79 + glutInitWindowSize(1280, 720); 7.80 + glutInit(&argc, argv); 7.81 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); 7.82 + 7.83 + glutCreateWindow("foo"); 7.84 + 7.85 + dtx_use_font(font, FONTSZ); 7.86 + 7.87 + glutDisplayFunc(disp); 7.88 + glutReshapeFunc(reshape); 7.89 + glutKeyboardFunc(keyb); 7.90 + 7.91 + glEnable(GL_DEPTH_TEST); 7.92 + glEnable(GL_MULTISAMPLE); 7.93 + 7.94 + glutMainLoop(); 7.95 +} 7.96 + 7.97 +void disp(void) 7.98 +{ 7.99 + struct rbnode *root = rb_root(tree); 7.100 + 7.101 + glClearColor(0.57, 0.64, 0.59, 1.0); 7.102 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 7.103 + 7.104 + glMatrixMode(GL_MODELVIEW); 7.105 + glLoadIdentity(); 7.106 + 7.107 + if(input_buffer[0]) { 7.108 + char *prompt = "select node: "; 7.109 + char *buf = alloca(strlen(prompt) + strlen(input_buffer)); 7.110 + 7.111 + glPushMatrix(); 7.112 + glTranslatef(10, 10, -0.9); 7.113 + glColor3f(0, 0, 0); 7.114 + sprintf(buf, "%s%s", prompt, input_buffer); 7.115 + dtx_string(buf); 7.116 + glPopMatrix(); 7.117 + } 7.118 + 7.119 + if(root) { 7.120 + rbvis_draw(root, rbvis_width(root->left) + NWIDTH, 550); 7.121 + } 7.122 + 7.123 + glutSwapBuffers(); 7.124 + assert(glGetError() == GL_NO_ERROR); 7.125 +} 7.126 + 7.127 + 7.128 +float rbvis_width(struct rbnode *tree) 7.129 +{ 7.130 + if(!tree) 7.131 + return NWIDTH; 7.132 + 7.133 + return NWIDTH + rbvis_width(tree->left) + rbvis_width(tree->right) + PADDING * 3.0; 7.134 +} 7.135 + 7.136 +void rbvis_draw(struct rbnode *tree, float x, float y) 7.137 +{ 7.138 + float leftx, rightx, nexty; 7.139 + static const float hxsz = NWIDTH / 2.0; 7.140 + static const float hysz = NHEIGHT / 2.0; 7.141 + char text[16]; 7.142 + 7.143 + if(!tree) 7.144 + return; 7.145 + 7.146 + leftx = x - (tree->left ? rbvis_width(tree->left->right) + NWIDTH : rbvis_width(tree->left) / 2.0); 7.147 + rightx = x + (tree->right ? rbvis_width(tree->right->left) + NWIDTH : rbvis_width(tree->right) / 2.0); 7.148 + 7.149 + nexty = y - DY; 7.150 + 7.151 + sprintf(text, "%d", rb_node_keyi(tree)); 7.152 + draw_rect(x - hxsz, y - hysz, NWIDTH, NHEIGHT, text, tree->red); 7.153 + 7.154 + rbvis_draw(tree->left, leftx, nexty); 7.155 + rbvis_draw(tree->right, rightx, nexty); 7.156 + 7.157 + if(tree->left) 7.158 + draw_link(x, y, leftx, nexty, tree->left->red); 7.159 + if(tree->right) 7.160 + draw_link(x, y, rightx, nexty, tree->right->red); 7.161 +} 7.162 + 7.163 +void draw_rect(float x, float y, float width, float height, const char *text, int red) 7.164 +{ 7.165 + float node_col[] = {0.63, 0.71, 0.82, 1.0}; 7.166 + float bord_col[] = {0, 0, 0, 1}; 7.167 + 7.168 + if(red) { 7.169 + bord_col[0] = 1.0; 7.170 + } 7.171 + 7.172 + glMatrixMode(GL_MODELVIEW); 7.173 + glPushMatrix(); 7.174 + glTranslatef(x + width / 2.0, y + height / 2.0, 0.0); 7.175 + 7.176 + draw_roundbox(width, height, 8, 6, node_col, 1.2, bord_col); 7.177 + 7.178 + glColor3f(0.15, 0.15, 0.15); 7.179 + glTranslatef(-dtx_string_width(text) / 2.0, -dtx_string_height(text) / 2.0, 0.1); 7.180 + dtx_string(text); 7.181 + glMatrixMode(GL_MODELVIEW); 7.182 + glPopMatrix(); 7.183 +} 7.184 + 7.185 +void draw_link(float x0, float y0, float x1, float y1, int red) 7.186 +{ 7.187 + glPushAttrib(GL_LINE_BIT); 7.188 + if(red) { 7.189 + glLineWidth(3); 7.190 + } else { 7.191 + glLineWidth(2); 7.192 + } 7.193 + 7.194 + glBegin(GL_LINES); 7.195 + if(red) { 7.196 + glColor3f(0.8, 0.36, 0.3); 7.197 + } else { 7.198 + glColor3f(0, 0, 0); 7.199 + } 7.200 + glVertex3f(x0, y0, -0.8); 7.201 + glVertex3f(x1, y1, -0.8); 7.202 + glEnd(); 7.203 + 7.204 + glPopAttrib(); 7.205 +} 7.206 + 7.207 +void draw_roundbox(float xsz, float ysz, float rad, int segm, const float *col, float border, const float *bcol) 7.208 +{ 7.209 + float hin_xsz, hin_ysz; 7.210 + 7.211 + if(border > 0.0f) { 7.212 + glPushMatrix(); 7.213 + glTranslatef(0, 0, -0.001); 7.214 + draw_roundbox(xsz + 2 * border, ysz + 2 * border, rad + border, segm, bcol, 0.0, bcol); 7.215 + glPopMatrix(); 7.216 + } 7.217 + 7.218 + /* half inner size */ 7.219 + hin_xsz = (xsz - 2.0 * rad) / 2.0; 7.220 + hin_ysz = (ysz - 2.0 * rad) / 2.0; 7.221 + 7.222 + glColor4fv(col); 7.223 + 7.224 + glBegin(GL_QUADS); 7.225 + /* center */ 7.226 + glVertex2f(-hin_xsz, -hin_ysz); 7.227 + glVertex2f(hin_xsz, -hin_ysz); 7.228 + glVertex2f(hin_xsz, hin_ysz); 7.229 + glVertex2f(-hin_xsz, hin_ysz); 7.230 + /* right */ 7.231 + glVertex2f(hin_xsz, -hin_ysz); 7.232 + glVertex2f(hin_xsz + rad, -hin_ysz); 7.233 + glVertex2f(hin_xsz + rad, hin_ysz); 7.234 + glVertex2f(hin_xsz, hin_ysz); 7.235 + /* top */ 7.236 + glVertex2f(-hin_xsz, hin_ysz); 7.237 + glVertex2f(hin_xsz, hin_ysz); 7.238 + glVertex2f(hin_xsz, hin_ysz + rad); 7.239 + glVertex2f(-hin_xsz, hin_ysz + rad); 7.240 + /* left */ 7.241 + glVertex2f(-hin_xsz - rad, -hin_ysz); 7.242 + glVertex2f(-hin_xsz, -hin_ysz); 7.243 + glVertex2f(-hin_xsz, hin_ysz); 7.244 + glVertex2f(-hin_xsz - rad, hin_ysz); 7.245 + /* bottom */ 7.246 + glVertex2f(-hin_xsz, -hin_ysz - rad); 7.247 + glVertex2f(hin_xsz, -hin_ysz - rad); 7.248 + glVertex2f(hin_xsz, -hin_ysz); 7.249 + glVertex2f(-hin_xsz, -hin_ysz); 7.250 + glEnd(); 7.251 + 7.252 + glMatrixMode(GL_MODELVIEW); 7.253 + 7.254 + glPushMatrix(); 7.255 + glTranslatef(hin_xsz, hin_ysz, 0); 7.256 + draw_fillet(rad, segm); 7.257 + glPopMatrix(); 7.258 + 7.259 + glPushMatrix(); 7.260 + glTranslatef(-hin_xsz, hin_ysz, 0); 7.261 + glRotatef(90, 0, 0, 1); 7.262 + draw_fillet(rad, segm); 7.263 + glPopMatrix(); 7.264 + 7.265 + glPushMatrix(); 7.266 + glTranslatef(-hin_xsz, -hin_ysz, 0); 7.267 + glRotatef(180, 0, 0, 1); 7.268 + draw_fillet(rad, segm); 7.269 + glPopMatrix(); 7.270 + 7.271 + glPushMatrix(); 7.272 + glTranslatef(hin_xsz, -hin_ysz, 0); 7.273 + glRotatef(270, 0, 0, 1); 7.274 + draw_fillet(rad, segm); 7.275 + glPopMatrix(); 7.276 +} 7.277 + 7.278 +void draw_fillet(float rad, int segm) 7.279 +{ 7.280 + int i; 7.281 + 7.282 + glBegin(GL_TRIANGLE_FAN); 7.283 + glVertex2f(0, 0); 7.284 + for(i=0; i<segm; i++) { 7.285 + float theta = 0.5 * M_PI * (float)i / (float)(segm - 1); 7.286 + float x = cos(theta) * rad; 7.287 + float y = sin(theta) * rad; 7.288 + glVertex2f(x, y); 7.289 + } 7.290 + glEnd(); 7.291 +} 7.292 + 7.293 + 7.294 +void reshape(int x, int y) 7.295 +{ 7.296 + win_xsz = x; 7.297 + win_ysz = y; 7.298 + 7.299 + glViewport(0, 0, x, y); 7.300 + 7.301 + glMatrixMode(GL_PROJECTION); 7.302 + glLoadIdentity(); 7.303 + glOrtho(0, x, 0, y, -1, 1); 7.304 +} 7.305 + 7.306 +void keyb(unsigned char key, int x, int y) 7.307 +{ 7.308 + static int wposx = -1, wposy; 7.309 + static char *inp_next; 7.310 + static char op; 7.311 + 7.312 + switch(key) { 7.313 + case 27: 7.314 + exit(0); 7.315 + 7.316 + case 'a': 7.317 + rb_inserti(tree, num_nodes++, 0); 7.318 + glutPostRedisplay(); 7.319 + break; 7.320 + 7.321 + case 'r': 7.322 + { 7.323 + int x; 7.324 + do { 7.325 + x = rand() % 1024; 7.326 + } while(rb_findi(tree, x)); 7.327 + 7.328 + rb_inserti(tree, x, 0); 7.329 + } 7.330 + glutPostRedisplay(); 7.331 + break; 7.332 + 7.333 + case 'd': 7.334 + case 'f': 7.335 + op = key; 7.336 + inp_next = input_buffer; 7.337 + *inp_next++ = ' '; 7.338 + *inp_next = 0; 7.339 + glutPostRedisplay(); 7.340 + break; 7.341 + 7.342 + case '0': 7.343 + case '1': 7.344 + case '2': 7.345 + case '3': 7.346 + case '4': 7.347 + case '5': 7.348 + case '6': 7.349 + case '7': 7.350 + case '8': 7.351 + case '9': 7.352 + if(inp_next) { 7.353 + *inp_next++ = key; 7.354 + *inp_next = 0; 7.355 + glutPostRedisplay(); 7.356 + } 7.357 + break; 7.358 + 7.359 + case '\b': 7.360 + if(inp_next > input_buffer) { 7.361 + *--inp_next = 0; 7.362 + glutPostRedisplay(); 7.363 + } 7.364 + break; 7.365 + 7.366 + case '\n': 7.367 + case '\r': 7.368 + if(inp_next) { 7.369 + int x; 7.370 + char *endp; 7.371 + 7.372 + *inp_next = 0; 7.373 + inp_next = 0; 7.374 + 7.375 + if((x = strtol(input_buffer, &endp, 10)), endp == input_buffer) { 7.376 + fprintf(stderr, "invalid input: %s\n", input_buffer); 7.377 + } else if(!rb_findi(tree, x)) { 7.378 + fprintf(stderr, "%d not found in the tree\n", x); 7.379 + } else { 7.380 + if(op == 'd') { 7.381 + printf("deleting: %d\n", x); 7.382 + rb_deletei(tree, x); 7.383 + } else { 7.384 + printf("%d found!\n", x); 7.385 + } 7.386 + } 7.387 + input_buffer[0] = 0; 7.388 + glutPostRedisplay(); 7.389 + } 7.390 + break; 7.391 + 7.392 + case 'p': 7.393 + { 7.394 + struct rbnode *node; 7.395 + 7.396 + rb_begin(tree); 7.397 + while((node = rb_next(tree))) { 7.398 + int key = rb_node_keyi(node); 7.399 + printf("%d ", key); 7.400 + } 7.401 + putchar('\n'); 7.402 + } 7.403 + break; 7.404 + } 7.405 +} 7.406 +