Files
vroni/graphics_ogl.cc
T
SaraP f3e15b8c8d vroni 7.6 :
- aggiunti file della libreria e progetto visual studio.
2023-09-06 15:44:02 +02:00

1477 lines
43 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 2005-2023 M. Held */
/* */
/* This code is not in the public domain. All rights reserved! Please make */
/* sure to read the full copyright statement contained in "README.txt" or in */
/* the "main" file of this code, such as "main.cc". */
/* */
/*****************************************************************************/
/* */
/* Written by: Martin Held */
/* */
/* E-Mail: held@cs.sbg.ac.at */
/* Fax Mail: (+43 662) 8044-172 */
/* Voice Mail: (+43 662) 8044-6304 */
/* Snail Mail: Martin Held */
/* FB Informatik */
/* Universitaet Salzburg */
/* A-5020 Salzburg, Austria */
/* */
/*****************************************************************************/
#ifdef OGL_GRAPHICS
//Uncomment this to enable text printing in opengl environments
#define OGL_ENABLE_TEXT
#ifdef OGL_ENABLE_TEXT
#include <stdarg.h>
int enableText = 0;
#endif
/* */
/* get standard libraries */
/* */
#include <stdio.h>
//#define MARTINS_FLASH_DEMO
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#ifdef MARTINS_FLASH_DEMO
#include <unistd.h>
#endif
/* */
/* get OpenGL include files */
/* */
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h> /* glut.h includes gl.h and glu.h */
#endif
/* */
/* get my header files */
/* */
#include "fpkernel.h"
#include "vronivector.h"
#include "vroni_object.h"
#include "defs.h"
#include "numerics.h"
#include "dvi_graphics_header.h"
#include "approx.h"
/* */
/* some global constants */
/* */
#define XNumPixel 1000
#define YNumPixel 1000
#define XPosition 0
#define YPosition 0
#define Radius 5.0
#define RadiusLarge 8.0
#define ESC 27
/* */
/* OpenGL-specific declarations */
/* */
#ifdef MARTINS_FLASH_DEMO
static vr_bool flash_demo = true;
static vr_bool vd_computed = false;
#endif
static vr_bool zoom = false;
static vr_bool query = false;
static vr_bool query_seg = false;
static vr_bool query_pnt = false;
static vr_bool query_nde = false;
static vr_bool enter_polygon = false;
static vr_bool full_screen_mode = false;
static vr_bool one_corner_received = false;
static double xl, yl, xr, yr;
static double scale, xm, ym;
static GLint im, jm;
static coord start, end;
static GLint pix_i1, pix_j1;
static GLint x_pos = XPosition, y_pos = YPosition;
static GLint x_size = XNumPixel, y_size = YNumPixel;
static GLint width_pxl = XNumPixel, height_pxl = YNumPixel;
typedef struct {
GLdouble r;
GLdouble g;
GLdouble b;
GLdouble a;
} tcolor;
static tcolor colors[10];
static int BGcolor = Black;
static vronivector<coord> apx_vtx;
static int max_num_apx_vtx = 0;
typedef enum {quit,
togglePNT,
toggleSEG,
toggleARC,
toggleVDE,
toggleVDN,
toggleDTE,
toggleMAT,
toggleMIC,
toggleOFF,
zoomIn,
zoomOut,
unZoom} oglMenu;
/* */
/* OpenGL-specific graphics functions */
/* */
void FreeArcMemory(void)
{
apx_vtx.clear();
max_num_apx_vtx = 0;
return;
}
void vroniObject::ResetRubberLine(void)
{
one_corner_received = false;
return;
}
void SetUpColorTable(vr_bool color_graphics)
{
int i;
if (color_graphics) {
colors[Brown].r = 165.0 / 255.0;
colors[Brown].g = 42.0 / 255.0;
colors[Brown].b = 42.0 / 255.0;
colors[Brown].a = 0.0;
colors[Green].r = 0.0;
colors[Green].g = 1.0;
colors[Green].b = 0.0;
colors[Green].a = 0.0;
colors[Blue].r = 0.0;
colors[Blue].g = 0.0;
colors[Blue].b = 1.0;
colors[Blue].a = 0.0;
colors[White].r = 1.0;
colors[White].g = 1.0;
colors[White].b = 1.0;
colors[White].a = 0.0;
colors[Red].r = 1.0;
colors[Red].g = 0.0;
colors[Red].b = 0.0;
colors[Red].a = 0.0;
colors[Cyan].r = 0.0;
colors[Cyan].g = 1.0;
colors[Cyan].b = 1.0;
colors[Cyan].a = 0.0;
colors[Yellow].r = 1.0;
colors[Yellow].g = 1.0;
colors[Yellow].b = 0.0;
colors[Yellow].a = 0.0;
colors[Orange].r = 1.0;
colors[Orange].g = 165.0 / 255.0;
colors[Orange].b = 0.0;
colors[Orange].a = 0.0;
colors[Magenta].r = 1.0;
colors[Magenta].g = 0.0;
colors[Magenta].b = 1.0;
colors[Magenta].a = 0.0;
colors[Black].r = 0.0;
colors[Black].g = 0.0;
colors[Black].b = 0.0;
colors[Black].a = 0.0;
BGcolor = Black;
}
else {
for (i = 0; i < NumColors; ++i) {
colors[i].r = 0.0;
colors[i].g = 0.0;
colors[i].b = 0.0;
colors[i].a = 0.0;
}
colors[White].r = 1.0;
colors[White].g = 1.0;
colors[White].b = 1.0;
colors[White].a = 0.0;
BGcolor = White;
}
return;
}
void SetBB(double_arg xl_bb, double_arg yl_bb,
double_arg xr_bb, double_arg yr_bb)
{
xl = xl_bb;
xr = xr_bb;
yl = yl_bb;
yr = yr_bb;
return;
}
/* */
/* maps world coordinates to window pixels; the origin of the window is */
/* assumed to be located in the lower-left corner. im and jm denote the */
/* pixel coordinates of the rectangle's center (with world coordinates xm */
/* and ym). */
/* */
void MapWorldCoordinates(double x, double y, GLint *pix_i, GLint *pix_j)
{
*pix_i = im + REAL_TO_GLINT((x - xm) * scale);
*pix_j = jm + REAL_TO_GLINT((y - ym) * scale);
return;
}
/* */
/* maps window pixels to world coordinates; the origin of the window is */
/* assumed to be located in the lower-left corner. im and jm denote the */
/* pixel coordinates of the rectangle's center (with world coordinates xm */
/* and ym). */
/* */
void MapWindowCoordinates(GLint pix_i, GLint pix_j, double *x, double *y)
{
*x = ((double) (pix_i - im)) / scale + xm;
*y = ((double) (pix_j - jm)) / scale + ym;
return;
}
void AdjustClipCoords(void)
{
MapWindowCoordinates(0, 0, &xl, &yl);
MapWindowCoordinates(width_pxl, height_pxl, &xr, &yr);
return;
}
void InitializeMapping(void)
{
double scale_x, scale_y;
/* */
/* compute a scale factor such that the real-world data inside the */
/* bounding box [xl,xr] times [yl,yr] fits nicely into a window of size */
/* width_pxl times height_pxl, without causing distortion. */
/* */
scale_x = ((double) width_pxl) / (ZERO + xr - xl);
scale_y = ((double) height_pxl) / (ZERO + yr - yl);
if (scale_x <= scale_y) scale = scale_x;
else scale = scale_y;
assert(scale > 0.0);
/* */
/* obtain the coordinates of the center in real-world and screen space */
/* */
xm = (xl + xr) / 2.0;
ym = (yl + yr) / 2.0;
im = width_pxl / 2;
jm = height_pxl / 2;
/* */
/* adjust the bounding box such that it reflects the real-world region */
/* that will be visible on the screen */
/* */
AdjustClipCoords();
return;
}
void DefineCamera(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(TO_MDOUBLE(xl), TO_MDOUBLE(xr), TO_MDOUBLE(yl), TO_MDOUBLE(yr));
return;
}
void DefineView(void)
{
InitializeMapping();
DefineCamera();
return;
}
void vroniObject::UpdateScaleData(void)
{
double delta_x, delta_y;
delta_x = (API_VD().bb_max.x - API_VD().bb_min.x) / 16.0;
delta_y = (API_VD().bb_max.y - API_VD().bb_min.y) / 16.0;
SetBB(API_VD().bb_min.x - delta_x, API_VD().bb_min.y - delta_y,
API_VD().bb_max.x + delta_x, API_VD().bb_max.y + delta_y);
DefineView();
return;
}
void DrawRectangle(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2,
GLdouble r1, GLdouble g1, GLdouble b1, GLdouble a1,
GLdouble r2, GLdouble g2, GLdouble b2, GLdouble a2,
vr_bool filled,
GLint stipple_factor, GLushort stipple_pattern)
{
if (filled) {
glColor4d(r1, g1, b1, a1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glRectd(x1, y1, x2, y2);
glLineWidth(2.0);
}
glColor4d(r2, g2, b2, a2);
if (stipple_pattern != 0xFFFF) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(stipple_factor, stipple_pattern);
glLineWidth(1.0);
}
else {
glDisable(GL_LINE_STIPPLE);
}
glBegin(GL_LINE_LOOP);
glVertex2d(x1, y1);
glVertex2d(x2, y1);
glVertex2d(x2, y2);
glVertex2d(x1, y2);
glEnd();
glLineWidth(1.0);
return;
}
void DrawRect(coord pnt1, coord pnt2, int obj_color,
vr_bool filled, GLint stipple_factor, GLushort stipple_pattern)
{
DrawRectangle(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y),
TO_MDOUBLE(pnt2.x), TO_MDOUBLE(pnt2.y),
colors[obj_color].r, colors[obj_color].g,
colors[obj_color].b, colors[obj_color].a,
colors[obj_color].r, colors[obj_color].g,
colors[obj_color].b, colors[obj_color].a,
filled, stipple_factor, stipple_pattern);
return;
}
void DrawTriangle(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2,
GLdouble x3, GLdouble y3,
GLdouble r1, GLdouble g1, GLdouble b1, GLdouble a1,
GLdouble r2, GLdouble g2, GLdouble b2, GLdouble a2,
vr_bool filled,
GLint stipple_factor, GLushort stipple_pattern)
{
if (filled) {
glColor4d(r1, g1, b1, a1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_TRIANGLES);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glVertex2d(x3, y3);
glEnd();
glLineWidth(2.0);
}
glColor4d(r2, g2, b2, a2);
if (stipple_pattern != 0xFFFF) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(stipple_factor, stipple_pattern);
glLineWidth(1.0);
}
else {
glDisable(GL_LINE_STIPPLE);
}
glBegin(GL_LINE_LOOP);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glVertex2d(x3, y3);
glEnd();
glLineWidth(1.0);
return;
}
void DrawTri(coord pnt1, coord pnt2, coord pnt3, int color1, int color2)
{
DrawTriangle(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y), TO_MDOUBLE(pnt2.x),
TO_MDOUBLE(pnt2.y), TO_MDOUBLE(pnt3.x), TO_MDOUBLE(pnt3.y),
colors[color1].r, colors[color1].g,
colors[color1].b, colors[color1].a,
colors[color2].r, colors[color2].g,
colors[color2].b, colors[color2].a,
true, 1, 0xFFFF);
return;
}
void vroniObject::DrawArc(coord pnt1, coord pnt2, coord pnt3, double radius,
int color)
{
int k, number;
double apx_absolute = 0.005;
double max_incr = M_PI_4;
vr_bool ccw_orientation = true;
/* */
/* check whether the bounding box of the full circle overlaps with the */
/* current display area */
/* */
if (xr < (pnt3.x - radius)) return;
if (yr < (pnt3.y - radius)) return;
if (xl > (pnt3.x + radius)) return;
if (xl > (pnt3.x + radius)) return;
if (radius > 1e100) return;
/* */
/* compute an approximation of the arc; the approximation threshold */
/* depends on how large the arc is relative to the currently displayed */
/* range of the input data */
/* */
apx_absolute /= scale;
ApproxArc(pnt1, pnt2, pnt3.x, pnt3.y, radius, ccw_orientation,
apx_absolute, apx_vtx, max_num_apx_vtx, max_incr, number);
/* */
/* output the line segments */
/* */
glColor4d(colors[color].r, colors[color].g,
colors[color].b, colors[color].a);
glDisable(GL_LINE_STIPPLE);
glLineWidth(1.0);
glBegin(GL_LINE_STRIP);
glVertex2d(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y));
for (k = 0; k < number; ++k) {
glVertex2d(TO_MDOUBLE(apx_vtx[k].x), TO_MDOUBLE(apx_vtx[k].y));
}
glVertex2d(TO_MDOUBLE(pnt2.x), TO_MDOUBLE(pnt2.y));
glEnd();
return;
}
void vroniObject::DrawText(coord pos, int color, const char* fmt, ...)
{
#ifdef OGL_ENABLE_TEXT
static int off=0;
char text[201];
va_list ap;
char *c;
double x1, width;
void* font;
if( ! enableText )
return;
off++;
//It might be good to use a prime-number as modul, such
//that there are no "cyclic sub-groups".
pos.y += -1/500000.0 + (off%31)/5000000.0;
memset(text, 0, sizeof(char)*200);
//Get text itself with va_args (man va_arg)
va_start(ap, fmt);
vsnprintf(text, 200, fmt, ap);
va_end(ap);
//Nice tutorial: http://www.lighthouse3d.com/opengl/glut/index.php?bmpfont
x1=pos.x;
width = Abs(xl-xr);
font = GLUT_BITMAP_HELVETICA_12;
for (c=text; *c!='\0' && (c-text)<=200 ; c++)
{
glRasterPos2d(TO_MDOUBLE(x1),TO_MDOUBLE(pos.y));
glutBitmapCharacter(font, *c);
//The factor w/618 is for compensating the re-scaling after VD-computation
x1 += glutBitmapWidth(font,*c) * width/1000.0;
}
#endif// OGL_ENABLE_TEXT
pos.x = 0.0;
color = 0;
return;
}
void vroniObject::DrawCircle(coord pnt3, double radius, int color)
{
coord pnt1, pnt2;
pnt1.x = pnt3.x + radius;
pnt1.y = pnt3.y;
pnt2.x = pnt3.x - radius;
pnt2.y = pnt3.y;
DrawArc(pnt1, pnt2, pnt3, radius, color);
DrawArc(pnt2, pnt1, pnt3, radius, color);
return;
}
void DrawSegment(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2,
GLdouble r, GLdouble g, GLdouble b, GLdouble a,
GLdouble line_width,
GLint stipple_factor, GLushort stipple_pattern)
{
glColor4d(r, g, b, a);
glLineWidth(line_width);
if (stipple_pattern != 0xFFFF) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(stipple_factor, stipple_pattern);
}
else {
glDisable(GL_LINE_STIPPLE);
}
glBegin(GL_LINES);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glEnd();
return;
}
void vroniObject::DrawSeg(coord pnt1, coord pnt2, int color)
{
DrawSegment(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y),
TO_MDOUBLE(pnt2.x), TO_MDOUBLE(pnt2.y),
colors[color].r, colors[color].g,
colors[color].b, colors[color].a,
1.0, 1, 0xFFFF);
return;
}
void DrawPoint(GLdouble x1, GLdouble y1,
GLdouble r, GLdouble g, GLdouble b, GLdouble a,
GLfloat pnt_size)
{
glColor4d(r, g, b, a);
glPointSize(pnt_size);
glBegin(GL_POINTS);
glVertex2d(x1, y1);
glEnd();
return;
}
void vroniObject::DrawPnt(coord pnt, int color, vr_bool large_radius)
{
if (large_radius) {
DrawPoint(TO_MDOUBLE(pnt.x), TO_MDOUBLE(pnt.y),
colors[color].r, colors[color].g,
colors[color].b, colors[color].a, RadiusLarge);
}
else {
DrawPoint(TO_MDOUBLE(pnt.x), TO_MDOUBLE(pnt.y),
colors[color].r, colors[color].g,
colors[color].b, colors[color].a, Radius);
}
return;
}
void vroniObject::FlushDisplay(void)
{
/*
glutPostRedisplay();
*/
glFlush();
return;
}
void QuickDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
API_VD().Redraw();
/* */
/* draw "rubber bands" to indicate objects that are currently been drawn */
/* by moving the mouse */
/* */
if (one_corner_received) {
if (zoom) {
DrawRect(start, end, Magenta, false, 1, 0x00FF);
}
else if (enter_polygon) {
DrawSegment(TO_MDOUBLE(start.x), TO_MDOUBLE(start.y),
TO_MDOUBLE(end.x), TO_MDOUBLE(end.y),
colors[SegColor].r,
colors[SegColor].g,
colors[SegColor].b,
colors[SegColor].a, 1.0, 1, 0x00FF);
}
}
glutSwapBuffers();
return;
}
void vroniObject::ResetGraphicsData(void)
{
API_VD().ResetOnlineGraphicsData();
one_corner_received = false;
zoom = false;
enter_polygon = false;
query = false;
glClear(GL_COLOR_BUFFER_BIT);
return;
}
void SelectInputEvents(void)
{
return;
}
void UnZoom(void)
{
API_VD().UpdateScaleData();
glutPostRedisplay();
return;
}
void ZoomOut(void)
{
scale *= 0.5;
AdjustClipCoords();
DefineCamera();
glutPostRedisplay();
return;
}
void ZoomIn(void)
{
scale *= 2.0;
AdjustClipCoords();
DefineCamera();
glutPostRedisplay();
return;
}
void ScrollLeft(void)
{
double delta;
delta = (xr - xl) / 8.0;
xr -= delta;
xl -= delta;
DefineView();
glutPostRedisplay();
return;
}
void ScrollRight(void)
{
double delta;
delta = (xr - xl) / 8.0;
xr += delta;
xl += delta;
DefineView();
glutPostRedisplay();
return;
}
void ScrollUp(void)
{
double delta;
delta = (yr - yl) / 8.0;
yr += delta;
yl += delta;
DefineView();
glutPostRedisplay();
return;
}
void ScrollDown(void)
{
double delta;
delta = (yr - yl) / 8.0;
yr -= delta;
yl -= delta;
DefineView();
glutPostRedisplay();
return;
}
void TrackLine(GLint pix_i2, GLint pix_j2, double *x1, double *y1,
double *x2, double *y2)
{
MapWindowCoordinates(pix_i1, pix_j1, x1, y1);
MapWindowCoordinates(pix_i2, pix_j2, x2, y2);
return;
}
void TrackRectangle(GLint pix_i2, GLint pix_j2, double *x1, double *y1,
double *x2, double *y2)
{
if (pix_i1 == pix_i2) pix_i2 += 1;
if (pix_j1 == pix_j2) pix_j2 += 1;
if (pix_i1 < pix_i2) {
if (pix_j1 < pix_j2) {
MapWindowCoordinates(pix_i1, pix_j1, x1, y1);
MapWindowCoordinates(pix_i2, pix_j2, x2, y2);
}
else {
MapWindowCoordinates(pix_i1, pix_j2, x1, y1);
MapWindowCoordinates(pix_i2, pix_j1, x2, y2);
}
}
else {
if (pix_j1 < pix_j2) {
MapWindowCoordinates(pix_i2, pix_j1, x1, y1);
MapWindowCoordinates(pix_i1, pix_j2, x2, y2);
}
else {
MapWindowCoordinates(pix_i2, pix_j2, x1, y1);
MapWindowCoordinates(pix_i1, pix_j1, x2, y2);
}
}
return;
}
void ZoomToRegion(GLint pix_i2, GLint pix_j2)
{
double new_xl, new_xr, new_yl, new_yr;
if (one_corner_received) {
TrackRectangle(pix_i2, pix_j2, &new_xl, &new_yl, &new_xr, &new_yr);
SetBB(new_xl, new_yl, new_xr, new_yr);
DefineView();
zoom = false;
one_corner_received = false;
glutPostRedisplay();
}
else {
pix_i1 = pix_i2;
pix_j1 = pix_j2;
one_corner_received = true;
}
return;
}
void ToggleScreenMode(void)
{
full_screen_mode = !full_screen_mode;
if (full_screen_mode) {
/* */
/* save current parameters and go to full-screen mode */
/* */
x_pos = glutGet((GLenum)GLUT_WINDOW_X);
y_pos = glutGet((GLenum)GLUT_WINDOW_Y);
x_size = glutGet((GLenum)GLUT_WINDOW_WIDTH);
y_size = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
glutFullScreen();
width_pxl = glutGet((GLenum)GLUT_WINDOW_WIDTH);
height_pxl = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
}
else {
/* */
/* restore old settings */
/* */
glutReshapeWindow(x_size, y_size);
glutPositionWindow(x_pos, y_pos);
width_pxl = x_size;
height_pxl = y_size;
}
glViewport(0, 0, width_pxl, height_pxl);
DefineView();
glutPostRedisplay();
return;
}
void HandleMouseButton(int button, int state, GLint pix_i2, GLint pix_j2)
{
double x2, y2;
if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN)) {
/* */
/* convert from screen coords to OpenGL pixel coords, where the origin */
/* is at the lower-left corner of the window. */
/* */
pix_j2 = height_pxl - pix_j2;
if (zoom) {
ZoomToRegion(pix_i2, pix_j2);
}
else if (query_pnt || query_seg || query_nde) {
MapWindowCoordinates(pix_i2, pix_j2, &x2, &y2);
if (query_pnt) API_VD().FindClosestPnt(x2, y2);
else if (query_seg) API_VD().FindClosestSeg(x2, y2);
else if (query_nde) API_VD().FindClosestNode(x2, y2);
query_pnt = query_seg = query_nde = query = false;
glutPostRedisplay();
}
else if (enter_polygon) {
/* */
/* read mouse input from graphics window */
/* */
MapWindowCoordinates(pix_i2, pix_j2, &x2, &y2);
API_VD().AddPolygonVertex(x2, y2);
pix_i1 = pix_i2;
pix_j1 = pix_j2;
one_corner_received = true;
}
}
return;
}
void HandleKeyPress(unsigned char key, GLint pix_i1, GLint pix_j1)
{
void API_ResetAll(void);
zoom = false;
switch (key) {
#ifdef OGL_ENABLE_TEXT
case 'b':
enableText = !enableText;
glutPostRedisplay();
break;
#endif
case '?':
/* */
/* prepare for interactive debug query */
/* */
query = true;
break;
case 'h':
case 'H':
/* */
/* print help message */
/* */
API_VD().Help();
API_VD().EvalError();
break;
case 'v':
case 'V':
/* */
/* compute VD */
/* */
API_VD().HandleComputeVD();
if (API_VD().num_arcs > 0) {
API_VD().UpdateScaleData();
}
one_corner_received = false;
start = end;
glutPostRedisplay();
break;
case 'd':
case 'D':
/* */
/* delete; clear drawing canvas and reset all variables */
/* */
API_VD().ResetGraphicsData();
API_VD().FlushDisplay();
glutPostRedisplay();
API_ResetAll();
API_VD().ResetDriverData();
break;
case 'f':
case 'F':
/* */
/* toggle the drawing of offsets */
/* */
API_VD().draw_off = !API_VD().draw_off;
glutPostRedisplay();
break;
case 'a':
case 'A':
/* */
/* toggle the drawing of the arcs */
/* */
API_VD().draw_arcs = !API_VD().draw_arcs;
glutPostRedisplay();
break;
case 'e':
case 'E':
API_VD().draw_vde = !API_VD().draw_vde;
glutPostRedisplay();
break;
case 's':
case 'S':
if (query) {
query = false;
query_seg = true;
}
else {
/* */
/* toggle the drawing of the segments */
/* */
API_VD().draw_segs = !API_VD().draw_segs;
glutPostRedisplay();
}
break;
case 'n':
case 'N':
if (query) {
query = false;
query_nde = true;
}
else {
/* */
/* toggle the drawing of the Voronoi nodes */
/* */
API_VD().draw_vdn = !API_VD().draw_vdn;
glutPostRedisplay();
}
break;
case 't':
case 'T':
/* */
/* toggle the drawing of VD/DT/wMAT */
/* */
if ((API_VD().num_segs > 0) || (API_VD().num_arcs > 0)) {
if ( API_VD().draw_vde && API_VD().draw_mat) API_VD().draw_mat = false;
else if ( API_VD().draw_vde && !API_VD().draw_mat) API_VD().draw_vde = false;
else if (!API_VD().draw_vde && !API_VD().draw_mat) API_VD().draw_mat = true;
else API_VD().draw_vde = true;
API_VD().draw_dte = false;
}
else {
if ( API_VD().draw_vde && API_VD().draw_dte) API_VD().draw_dte = false;
else if ( API_VD().draw_vde && !API_VD().draw_dte) API_VD().draw_vde = false;
else if (!API_VD().draw_vde && !API_VD().draw_dte) API_VD().draw_dte = true;
else API_VD().draw_vde = true;
API_VD().draw_mat = false;
}
glutPostRedisplay();
break;
case 'x':
case 'X':
/* */
/* toggle the drawing of the maximum-inscribed circle */
/* */
API_VD().draw_mic = !API_VD().draw_mic;
glutPostRedisplay();
break;
case 'm':
case 'M':
/* */
/* toggle the drawing of the vertex markers */
/* */
API_VD().draw_pnts = !API_VD().draw_pnts;
glutPostRedisplay();
break;
case 'p':
case 'P':
/* */
/* read data from the graphics window */
/* */
if (query) {
query = false;
query_pnt = true;
}
else {
/* */
/* start new polygon */
/* */
enter_polygon = true;
query = false;
one_corner_received = false;
API_VD().StartNewPolygon();
start = end;
glutPostRedisplay();
}
break;
case 'c':
case 'C':
/* */
/* close polygon */
/* */
API_VD().ClosePolygon();
enter_polygon = false;
glutPostRedisplay();
break;
case 'i':
case 'I':
/* */
/* zoom in */
/* */
ZoomIn();
break;
case 'o':
case 'O':
/* */
/* zoom out */
/* */
ZoomOut();
break;
case 'u':
case 'U':
/* */
/* unzoom */
/* */
UnZoom();
break;
case 'z':
case 'Z':
/* */
/* prepare for zooming */
/* */
zoom = true;
query = false;
enter_polygon = false;
one_corner_received = false;
break;
case 'q':
case 'Q':
case ESC:
/* */
/* termination of program */
/* */
// FreeArcMemory();
//API_TerminateProgram();
exit(0);
break;
default:
API_VD().VD_Info("HandleKeyPress() - unknown key pressed!\n");
pix_i1 = pix_j1 = 0;
break;
}
return;
}
void IdleFunction(void)
{
#ifdef MARTINS_FLASH_DEMO
if (flash_demo) {
if (vd_computed) {
sleep(4);
HandleKeyPress('q', 0, 0);
}
else {
sleep(1);
vd_computed = true;
HandleKeyPress('v', 0, 0);
}
}
#endif
return;
}
void HandleMouseMotion(GLint pix_i2, GLint pix_j2)
{
pix_j2 = height_pxl - pix_j2;
if (one_corner_received) {
if (zoom) {
TrackRectangle(pix_i2, pix_j2, &start.x, &start.y, &end.x, &end.y);
glutPostRedisplay();
}
else if (enter_polygon) {
TrackLine(pix_i2, pix_j2, &start.x, &start.y, &end.x, &end.y);
glutPostRedisplay();
}
}
return;
}
void HandleReshape(GLint width, GLint height)
{
width_pxl = width;
height_pxl = height;
glViewport(0, 0, width_pxl, height_pxl);
DefineView();
glutPostRedisplay();
return;
}
void HandleSpecialKeys(int key, GLint pix_i1, GLint pix_j1)
{
switch (key) {
case GLUT_KEY_F1:
/* */
/* toggle full-screen mode */
/* */
ToggleScreenMode();
break;
case GLUT_KEY_LEFT:
/* */
/* scroll to the left */
/* */
ScrollLeft();
break;
case GLUT_KEY_UP:
/* */
/* scroll to the left */
/* */
ScrollUp();
break;
case GLUT_KEY_RIGHT:
/* */
/* scroll to the left */
/* */
ScrollRight();
break;
case GLUT_KEY_DOWN:
/* */
/* scroll to the left */
/* */
ScrollDown();
break;
default:
API_VD().VD_Info("HandleSpecialKeys() - key of unkown type!\n");
pix_i1 = pix_j1 = 0;
break;
}
return;
}
void HandleMenu(int item)
{
switch (item) {
case quit:
HandleKeyPress('q', 0, 0);
break;
case zoomIn:
HandleKeyPress('i', 0, 0);
break;
case zoomOut:
HandleKeyPress('o', 0, 0);
break;
case unZoom:
HandleKeyPress('u', 0, 0);
break;
}
return;
}
void HandleZoomMenu(int item)
{
switch (item) {
case zoomIn:
HandleKeyPress('i', 0, 0);
break;
case zoomOut:
HandleKeyPress('o', 0, 0);
break;
case unZoom:
HandleKeyPress('u', 0, 0);
break;
}
return;
}
void ChangeMenuItem(vr_bool *item_flag, const char* menuString, int item)
{
char my_string[100];
my_string[0] = '\0';
strcat(my_string, menuString);
if (*item_flag) {
*item_flag = false;
strcat(my_string, ": on");
glutChangeToMenuEntry(item, my_string, item);
}
else {
*item_flag = true;
strcat(my_string, ": off");
glutChangeToMenuEntry(item, my_string, item);
}
glutPostRedisplay();
return;
}
void HandleViewMenu(int item)
{
switch (item) {
case togglePNT:
ChangeMenuItem(&API_VD().draw_pnts, "Points/vertices", togglePNT);
break;
case toggleSEG:
ChangeMenuItem(&API_VD().draw_segs, "Line segments", toggleSEG);
break;
case toggleARC:
ChangeMenuItem(&API_VD().draw_arcs, "Circular arcs", toggleARC);
break;
case toggleVDE:
ChangeMenuItem(&API_VD().draw_vde, "Voronoi diagram edges", toggleVDE);
break;
case toggleVDN:
ChangeMenuItem(&API_VD().draw_vdn, "Voronoi diagram nodes", toggleVDN);
break;
case toggleDTE:
ChangeMenuItem(&API_VD().draw_dte, "Delaunay triangulation", toggleDTE);
break;
case toggleMAT:
ChangeMenuItem(&API_VD().draw_mat, "Medial axis", toggleMAT);
break;
case toggleMIC:
ChangeMenuItem(&API_VD().draw_mic, "Maximum inscribed circle", toggleMIC);
break;
case toggleOFF:
ChangeMenuItem(&API_VD().draw_off, "Offset curves", toggleOFF);
break;
}
glutPostRedisplay();
return;
}
void InitializeGraphics(int argc, char *argv[], vr_bool color_graphics,
vr_bool full_screen)
{
int zoomMenu, viewMenu;
char window_name[80];
/* */
/* graphics start-up */
/* */
glutInit(&argc, argv); /* init OpenGL */
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* double buffering,
and RGB colors */
/* */
/* set window position and size */
/* */
glutInitWindowSize(width_pxl, height_pxl);/* XNumPixel x YNumPixel window */
glutInitWindowPosition(x_pos, y_pos); /* upper-left corner of window */
/* */
/* window creation */
/* */
sprintf(window_name,
"%9s %3s (C) M. Held %9s",
API_GetProgName(), API_GetProgVersion(), API_GetProgYear());
glutCreateWindow(window_name); /* window title */
if (full_screen) {
glutFullScreen(); /* Go to full screen */
width_pxl = glutGet((GLenum)GLUT_WINDOW_WIDTH);
height_pxl = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
full_screen_mode = true;
}
/* */
/* init graphics variables */
/* */
SetUpColorTable(color_graphics);
glViewport(0, 0, width_pxl, height_pxl);
glClearColor(colors[BGcolor].r, /* set background color */
colors[BGcolor].g,
colors[BGcolor].b,
colors[BGcolor].a);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glLineWidth(1.0);
/* */
/* initialize the bounding box of the data */
/* */
API_VD().bb_min.x = xl = 0.0;
API_VD().bb_min.y = yl = 0.0;
API_VD().bb_max.x = xr = (double) width_pxl;
API_VD().bb_max.y = yr = (double) height_pxl;
if (!API_VD().bbox_initialized) API_VD().SetBoundingBox();
API_VD().UpdateScaleData();
/* */
/* input event selection */
/* */
glutDisplayFunc(QuickDisplay);
glutKeyboardFunc(HandleKeyPress);
glutReshapeFunc(HandleReshape);
glutMouseFunc(HandleMouseButton);
glutMotionFunc(HandleMouseMotion);
glutPassiveMotionFunc(HandleMouseMotion);
glutSpecialFunc(HandleSpecialKeys);
#ifdef MARTINS_FLASH_DEMO
if (flash_demo) glutIdleFunc(IdleFunction);
#endif
/* */
/* create menus */
/* */
zoomMenu = glutCreateMenu(HandleZoomMenu);
glutAddMenuEntry("Zoom in", zoomIn);
glutAddMenuEntry("Zoom out", zoomOut);
glutAddMenuEntry("Unzoom", unZoom);
viewMenu = glutCreateMenu(HandleViewMenu);
if (API_VD().draw_pnts) glutAddMenuEntry("Points/vertices: off", togglePNT);
else glutAddMenuEntry("Points/vertices: on", togglePNT);
if (API_VD().draw_segs) glutAddMenuEntry("Line segments: off", toggleSEG);
else glutAddMenuEntry("Line segments: on", toggleSEG);
if (API_VD().draw_arcs) glutAddMenuEntry("Circular arcs: off", toggleARC);
else glutAddMenuEntry("Circular arcs: on", toggleARC);
if (API_VD().draw_vde) glutAddMenuEntry("Voronoi diagram edges: off", toggleVDE);
else glutAddMenuEntry("Voronoi diagram edges: on", toggleVDE);
if (API_VD().draw_vdn) glutAddMenuEntry("Voronoi diagram nodes: off", toggleVDN);
else glutAddMenuEntry("Voronoi diagram nodes: on", toggleVDN);
if (API_VD().draw_dte) glutAddMenuEntry("Delaunay triangulation: off", toggleDTE);
else glutAddMenuEntry("Delaunay triangulation: on", toggleDTE);
if (API_VD().draw_mat) glutAddMenuEntry("Medial axis: off", toggleMAT);
else glutAddMenuEntry("Medial axis: on", toggleMAT);
if (API_VD().draw_mic) glutAddMenuEntry("Maximum inscribed circle: off", toggleMIC);
else glutAddMenuEntry("Maximum inscribed circle: on", toggleMIC);
if (API_VD().draw_off) glutAddMenuEntry("Offset curves: off", toggleOFF);
else glutAddMenuEntry("Offset curves: on", toggleOFF);
(void) glutCreateMenu(HandleMenu);
glutAddSubMenu("Zoom in/out", zoomMenu);
glutAddSubMenu("Toggle display parameters", viewMenu);
glutAddMenuEntry("Quit", quit);
glutAttachMenu(GLUT_RIGHT_BUTTON);
return;
}
void ProcessGraphicsEvents(void)
{
API_VD().UpdateScaleData();
glutMainLoop(); /* OpenGL's event-handling loop */
return;
}
void TerminateGraphics(void)
{
return;
}
#endif /* OGL_GRAPHICS */