f3e15b8c8d
- aggiunti file della libreria e progetto visual studio.
1477 lines
43 KiB
C++
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 */
|
|
|