
// THis program will output the huffman tree in graphics window and will show the huffman code in command window
// huff.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include "math.h"
//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include "glut.h"
#endif
typedef struct node {
    char name[20]; // name of the node
    float data;
    struct node* right;
    struct node* left;
    struct node* parent;
    struct node* next;
}NODE;
NODE* root = NULL;
using namespace std;
void display_list(NODE* head) {
    if(head) {
        cout<<"\nList contents:\n";
        NODE* temp = head;
        while(temp) {
            cout<<"Node : "<<temp->name<<"  probability:"<<temp->data<<endl;
            temp = temp->next;
        }
    } else {
        cout<<"\nEmpty List";
    }
}
void find_smallest(NODE* head,NODE** smallest1, NODE** smallest2) {
    *smallest1 = NULL;
    *smallest2 = NULL;
    NODE* t = head;
    while(t) {
        // Skip the nodes who has parent 
        if(t->parent) {
            t = t->next;
            continue;
        }
        if(!*smallest1) {
            *smallest1 = t;
        } else if(!*smallest2) {
            *smallest2 = t;
        } else if(t->data < (*smallest1)->data) {
            if ((*smallest1)->data < (*smallest2)->data) {
                *smallest2 = *smallest1;
            }
            *smallest1 = t;
        } else if(t->data < (*smallest2)->data) {
            *smallest2 = t;
        } else {
            // Do nothing
        }
        if(*smallest1 && *smallest2) {
            if((*smallest1)->data > (*smallest2)->data) {
                NODE* temp = *smallest1;
                *smallest1 = *smallest2;
                *smallest2 = temp;
            }
        }
        t = t->next;
    } 
}
void add_element(NODE** head,NODE** e) {
    if(!*head) {
        *head = *e;
    } else {
        NODE* t = *head;
        while(t->next!=NULL) {
            t = t->next;
        }
        t->next = *e;
    }
}
void tree_traversal(NODE* root,char code[20]) {
    if(!root) {
        return;
    }
    //cout<<"\n NODE : "<<root->name<<"  prob: "<<root->data;
    if(root->left==NULL && root->right==NULL) {
        cout<<" \nNODE : "<<root->name<<"  prob : "<<root->data<<"  code: "<<code;
        return;
    }
    int len = strlen(code);
    if(root->left) {
        code[len]='1';
        code[len+1]='\0';
        tree_traversal(root->left,code);
    }
    if(root->right) {
        code[len]='0';
        code[len+1]='\0';
        tree_traversal(root->right,code);
    }
}
void drawCircle(float segments, float radius, float sx, float sy)
{
    float theta = 2 * 3.1415926 / segments;
    float tan_factor = tanf(theta);
    float radial_factor = cosf(theta);
    float x = radius;
    float y = 0;
    int cache_pt = 0;
    double cache_x;
    double cache_y;
    glBegin(GL_LINES);
    for (int ii = 0; ii < segments; ii++) {
        if(!cache_pt) {
            cache_x = x+sx;
            cache_y = y+sy;
            cache_pt = 1;
        } else {
            //glVertex2f(cache_x,cache_y);
            glVertex2f(x + sx, y + sy);
            cache_x = x+sx;
            cache_y = y+sy;
        }
        float tx = -y;
        float ty = x;
        x += tx * tan_factor;
        y += ty * tan_factor;
        x *= radial_factor;
        y *= radial_factor;
    }
    glEnd();
}
void draw_line(float x1,float y1,float x2, float y2) {
    glBegin(GL_LINES);
    glVertex2f(x1,y1);
    glVertex2f(x2,y2);
    glEnd();
}
void draw_text(char* text,float x, float y) {
     GLvoid *font_style = GLUT_BITMAP_TIMES_ROMAN_24;
     glRasterPos3f(x, y, 0);
     for (int i = 0; text[i] != '\0'; i++){
         glutBitmapCharacter(font_style, text[i]);
     }
}
void drawNode(NODE* t_root,float x1,float y1,int level) {
    if (t_root==NULL) {
        return;
    }
    float segments = 25;
    float radius = 1.0;
    float left_angle = 245;
    float right_angle = 115;
    float branch_length = 12 - level*2.5;
    float angle_change = 20;
    // Draw the current circle
 
    drawCircle(segments,radius,x1,y1);
    
    char buff[5];
    //itoa(t_root->name,buff,10);
    draw_text(t_root->name,x1,y1);
    if(t_root->left) {
        // Draw the Left circle
        float angle = left_angle - level*angle_change;
        double radian = angle*3.14/180;
        float m = (double)tan((double)radian);
        float x2 = x1 + branch_length * sin((double) radian);
        float y2 = y1 + branch_length * cos((double) radian);
        drawNode(t_root->left,x2,y2,level+1);
        draw_line(x1,y1,x2,y2);
        float x3 = (x1+x2) / 2;
        float y3 = (y1+y2) / 2;
        char label[2];
        label[0]='1';
        label[1]='\0';
        draw_text(label,x3,y3);
    }
    if(t_root->right) {
        // Draw the Right circle
        float angle = right_angle + level*angle_change;
        float radian = angle*3.14/180;
        float m = (double)tan((double)radian);
        float x2 = x1 + branch_length * sin((double) radian);
        float y2 = y1 + branch_length * cos((double) radian);
        drawNode(t_root->right,x2,y2,level+1);
        draw_line(x1,y1,x2,y2);
        float x3 = (x1+x2) / 2;
        float y3 = (y1+y2) / 2;
        char label[2];
        label[0]='0';
        label[1]='\0';
        draw_text(label,x3,y3);
    }
}
void display(void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0,10,-30);
    glColor3f(1,1,1);
    drawNode(root,0,0,0);
    glutSwapBuffers();
}
void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 0.1, 100.0);
    glMatrixMode (GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}
int _tmain(int argc, char** argv)
{
    NODE* list = NULL;
    float arr[10];
    int n;
    cout<<"Enter n:";
    cin>>n;
    for(int i=0; i<n; i++) {
        cin>>arr[i];
        // Create a new node and append it to the list 
        NODE* current = new NODE;
        current->data = arr[i];
        current->next = NULL;
        current->left = NULL;
        current->right = NULL;
        current->parent = NULL;
        current->name[0] = 65+i; current->name[1] = '\0';
        // Appending the node to the list 
        add_element(&list,¤t);
    }
    // Display the nodes entered by the user along with their probabilities 
    display_list(list);
    while(1) {
        // Find the 2 smallest elements from the list 
        NODE* smallest1 = NULL;
        NODE* smallest2 = NULL;
        find_smallest(list,&smallest1,&smallest2);
        if(!smallest2) {
            root = smallest1;
            break;
        }
        float small1 = smallest1->data;
        float small2 = smallest2->data;
        NODE* current = new NODE;
        current->data = small1 + small2;
        current->left = smallest1;
        current->right = smallest2;
        current->parent = NULL;
        current->next = NULL;
        strcpy(current->name,smallest1->name);
        strcat(current->name,smallest2->name);
        smallest1->parent = current;
        smallest2->parent = current;
        add_element(&list,¤t);
        
    }
    cout<<"\n\nHuffman code :\n\n";
    char code[20];
    code[0]='\0';
    tree_traversal(root,code);
    // OPENGL Drawing functions 
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (1200, 800);
    glutInitWindowPosition (0, 0);
    glutCreateWindow ("A Binary search tree");
    // Register function pointers to the drawing framework 
    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);
    glutKeyboardFunc (keyboard);
    glutMainLoop ();
    cout<<endl;
    return 0;
}
 
gluperspective function is not working. Looks like the function is no more a part of open gl. can you please give an alternative? thanking in advance!
ReplyDeleteHi.... Can I know what platform u used to execute it
ReplyDelete