Graphics in C Language

graphics.h Reference

In a C program, first step is to initialize the graphics drivers on the computer. This is done using the initgraph() method provided in graphics.h library. In the next few pages we will discuss graphics.h library in more details. Important functions in graphic.h library will be discussed in details and samples programs will be provided to show the power of C programming language especially for graphic programming developing graphical user interfaces.

Table of Contents

We will restrict our discussion on Graphics in C to 16 bit C programming, MS DOS environment and 640×480 VGA monitor. Complete reference of graphics.h library and explanation of each method in that library can be found in the following articles.

  1. Graphics Library (graphics.h) Reference (part 1)
  2. Graphics Library (graphics.h) Reference (part 2)
  3. Graphics Library (graphics.h) Reference (part 3)

Graphics mode Initialization – initgraph() function

First of all we call the initgraph() function that will initialize the graphics mode on the computer. The method initigraph()

has the following prototype.

 void initgraph(int far *graphdriver, int far *graphmode, char far *pathtodriver);

The method initgraph() initializes the graphics system by loading the graphics driver from disk (or validating a registered driver) then putting the system into graphics mode. The method initgraph() also resets all graphics settings (color, palette, current position, viewport, etc.) to their defaults. The initialization result is set to 0 which can be retrieved by calling graphresult().

The initgraph() method has the following parameters.

The *graphdriver

This is an integer value that specifies the graphics driver to be used. You can give graphdriver a value using a constant of the graphics_drivers enumeration type which is listed in graphics.h . Normally we use value as “0” (requests auto-detect). Other values are 1 to 10 and description of each enumeration type is listed here.

The *graphmode

This is an integer value that specifies the initial graphics mode (unless *graphdriver = DETECT ). If *graphdriver = DETECT, then initgraph() method sets *graphmode to the highest resolution available for the detected graphics driver. You can give *graphmode a value using a constant of the graphics_modes enumeration type and description of each enumeration type is listed here.

The *pathtodriver

Specifies the directory path where initgraph() looks for graphics drivers (*.BGI) first.

  1. If they’re not there, initgraph() method looks in the current directory.
  2. If pathtodriver is null, the driver files must be in the current directory.

Both *graphdriver and *graphmode parameters must be set to valid graphics_drivers and graphics_mode values or you’ll get unpredictable results. (The exception is graphdriver = DETECT.)

After a call to initgraph(), *graphdriver is set to the current graphics driver, and *graphmode is set to the current graphics mode. You can tell initgraph to use a particular graphics driver and mode, or to auto detect the attached video adapter at run time and pick the corresponding driver. If you tell initgraph to auto detect, it calls detectgraph to select a graphics driver and mode.

The initgraph() method loads a graphics driver by allocating memory for the driver (through _graphgetmem() method call), then loading the appropriate .BGI file from disk. As an alternative to this dynamic loading scheme, you can link a graphics driver file (or several of them) directly into your executable program file.

Here is a simple program that initializes the graphics mode in C programming language and print the line in graphics mode.

#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main(void)
{
  /* request auto detection */  int gdriver = DETECT, gmode, errorcode;
  
  /* initialize graphics mode */  initgraph(&gdriver, &gmode, "");
  
  /* read result of initialization */  errorcode = graphresult();
  
  if (errorcode != grOk) /* an error occurred */  {
    printf("Graphics error: %s\n", grapherrormsg(errorcode));
    printf("Press any key to halt:");
    getch();
    exit(1); /* return with error code */  }
  
  /* draw a line */  line(0, 0, getmaxx(), getmaxy());
  
  /* clean up */  getch();
  closegraph();
  return 0;
}

The below program draws a circle in the current drawing color with its center at (150,150) and the radius (100) given by radius.

#include<graphics.h>
#include<conio.h>

main()
{
  int gd=DETECT,gm;
  initgraph(&gd,&gm,""); /* initialization of graphic mode */  circle(150,150,100);
  getch();
  closegraph(); /* Restore orignal screen mode */}

Normally the screen which we see in DOS/Command Mode is in the text mode which means it is meant for text only. And for graphics we need to initialize graphics mode using initgraph() method defined in graphics.h?

circle(x coordinate ,y coordinate , radius);

The circle command takes a X coordinate which means Vertical axis and Y coordinate which means Horizontal axis. And the last one is the radius of the circle.

The closegraph() Function

This function unloads the graphics drivers and returns the screen back to text mode.

#include<graphics.h>
#include<stdio.h>

main()
{
  int gd=DETECT,gm;
  int i,x,y;
  initgraph(&gd,&gm,"");
  line(0,0,640,0);
  line(0,0,0,480);
  line(639,0,639,480);
  line(639,479,0,479);
  for(i=0;i<=1000;i++)
  {
    x=rand()%639;
    y=rand()%480;
    putpixel(x,y,15);
  }
  getch();
  closegraph();
}

Here a sample program to illustrate how to use BARS which are used for visual statistics. The bar is filled using the current fill pattern and fill color. Bar method accepts parameters i.e. left, top, right and bottom. The setfillstyle() method can be used to fill the bar with a different color or pattern.

#include <graphics.h>
#include <conio.h>

main() {
  int gd=DETECT,gm,maxx,maxy,x,y,button;
  initgraph(&gd,&gm,"");
  line(80,150,200,150);
  line(80,150,80,50);
  settextstyle(1,HORIZ_DIR,1);
  outtextxy(100,153,"<-X axis");
  settextstyle(1,VERT_DIR,1);
  outtextxy(60,50,"<-Y axis");
  bar(100,100,120,150);
  bar(130,120,150,150);
  getch();
  closegraph();
}

Minimum Distance between a Point and a Line

This article now describes the technique and gives the solution to finding the shortest distance from a point to a line or line segment. The equation of a line defined through two points P1 (x1,y1) and P2 (x2,y2) is:

P = P1 + u (P2P1)

The point P3 (x3,y3) is closest to the line at the tangent to the line which passes through P3, that is, the dot product of the tangent and line is 0, thus

(P3P) dot (P2P1) = 0

Substituting the equation of the line gives: [P3 P1 – u(P2P1)] dot (P2P1) = 0

Solving this gives the value of u

Substituting this into the equation of the line gives the point of intersection (x,y) of the tangent as

x = x1 + u (x2 – x1)
y = y1 + u (y2 – y1)

The distance therefore between the point P3 and the line is the distance between (x,y) above and P3.

Notes

  • The only special testing for a software implementation is to ensure that P1 and P2 are not coincident (denominator in the equation for u is 0)
  • If the distance of the point to a line segment is required then it is only necessary to test that u lies between 0 and 1.
  • The solution is similar in higher dimensions.

Source code

//================
//
// DistancePointLine Unit Test
// Copyright (c) 2002, All rights reserved
//
// Damian Coventry
// Tuesday, 16 July 2002
//
// Implementation of theory by Paul Bourke
//
//================
#include <stdio.h>
#include <math.h>
typedef struct tagXYZ
{
 float X, Y, Z;
}
XYZ;
float Magnitude( XYZ *Point1, XYZ *Point2 )
{
 XYZ Vector;
 Vector.X = Point2->X - Point1->X;
 Vector.Y = Point2->Y - Point1->Y;
 Vector.Z = Point2->Z - Point1->Z;
 return (float)sqrt( Vector.X * Vector.X + Vector.Y * Vector.Y + Vector.Z * Vector.Z );
}
int DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd, float *Distance )
{
 float LineMag;
 float U;
 XYZ Intersection;
 LineMag = Magnitude( LineEnd, LineStart );
 U = ( ( ( Point->X - LineStart->X ) * ( LineEnd->X - LineStart->X ) ) +
 ( ( Point->Y - LineStart->Y ) * ( LineEnd->Y - LineStart->Y ) ) +
 ( ( Point->Z - LineStart->Z ) * ( LineEnd->Z - LineStart->Z ) ) ) /
 ( LineMag * LineMag );

 if( U < 0.0f || U > 1.0f )
 return 0; // closest point does not fall within the line segment
 Intersection.X = LineStart->X + U * ( LineEnd->X - LineStart->X );
 Intersection.Y = LineStart->Y + U * ( LineEnd->Y - LineStart->Y );
 Intersection.Z = LineStart->Z + U * ( LineEnd->Z - LineStart->Z );
 *Distance = Magnitude( Point, &Intersection );
 return 1;
}
void main( void )
{
 XYZ LineStart, LineEnd, Point;
 float Distance;
 LineStart.X = 50.0f; LineStart.Y = 80.0f; LineStart.Z = 300.0f;
 LineEnd.X = 50.0f; LineEnd.Y = -800.0f; LineEnd.Z = 1000.0f;
 Point.X = 20.0f; Point.Y = 1000.0f; Point.Z = 400.0f;
 if( DistancePointLine( &Point, &LineStart, &LineEnd, &Distance ) )
 printf( "closest point falls within line segment, distance = %f\n", Distance );
 else
 printf( "closest point does not fall within line segment\n" );
 LineStart.X = 0.0f; LineStart.Y = 0.0f; LineStart.Z = 50.0f;
 LineEnd.X = 0.0f; LineEnd.Y = 0.0f; LineEnd.Z = -50.0f;
 Point.X = 10.0f; Point.Y = 50.0f; Point.Z = 10.0f;
 if( DistancePointLine( &Point, &LineStart, &LineEnd, &Distance ) )
 printf( "closest point falls within line segment, distance = %f\n", Distance );
 else
 printf( "closest point does not fall within line segment\n" );
}


This C program calculates the distance between a given point and a line segment in 3D space. The code defines a structure XYZ to represent 3D points, includes necessary headers, and implements a function Magnitude to calculate the magnitude of a vector between two points using the sqrt function from the math.h library. The DistancePointLine function determines the closest point on a line segment to a given point, along with the distance between them. It utilizes basic mathematical operations and the sqrt function for distance calculations.

The Shortest Line Between Two Lines in 3D

Two lines in 3 dimensions generally don’t intersect at a point, they may be parallel (no intersections) or they may be coincident (infinite intersections) but most often only their projection onto a plane intersect.. When they don’t exactly intersect at a point they can be connected by a line segment, the shortest line segment is unique and is often considered to be their intersection in 3D.

typedef struct {
   double x,y,z;
} XYZ;

/*
   Calculate the line segment PaPb that is the shortest route between
   two lines P1P2 and P3P4. Calculate also the values of mua and mub where
      Pa = P1 + mua (P2 - P1)
      Pb = P3 + mub (P4 - P3)
   Return FALSE if no solution exists.
*/int LineLineIntersect(
   XYZ p1,XYZ p2,XYZ p3,XYZ p4,XYZ *pa,XYZ *pb,
   double *mua, double *mub)
{
   XYZ p13,p43,p21;
   double d1343,d4321,d1321,d4343,d2121;
   double numer,denom;

   p13.x = p1.x - p3.x;
   p13.y = p1.y - p3.y;
   p13.z = p1.z - p3.z;
   p43.x = p4.x - p3.x;
   p43.y = p4.y - p3.y;
   p43.z = p4.z - p3.z;
   if (ABS(p43.x)  < EPS && ABS(p43.y)  < EPS && ABS(p43.z)  < EPS)
      return(FALSE);
   p21.x = p2.x - p1.x;
   p21.y = p2.y - p1.y;
   p21.z = p2.z - p1.z;
   if (ABS(p21.x)  < EPS && ABS(p21.y)  < EPS && ABS(p21.z)  < EPS)
      return(FALSE);

   d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z;
   d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z;
   d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z;
   d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z;
   d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z;

   denom = d2121 * d4343 - d4321 * d4321;
   if (ABS(denom) < EPS)
      return(FALSE);
   numer = d1343 * d4321 - d1321 * d4343;

   *mua = numer / denom;
   *mub = (d1343 + d4321 * (*mua)) / d4343;

   pa->x = p1.x + *mua * p21.x;
   pa->y = p1.y + *mua * p21.y;
   pa->z = p1.z + *mua * p21.z;
   pb->x = p3.x + *mub * p43.x;
   pb->y = p3.y + *mub * p43.y;
   pb->z = p3.z + *mub * p43.z;

   return(TRUE);
}

Simple Graphic Functions

I am providing few functions here with some description to make you start with graphics programming. I have posted the complete description with a demo C/C++ graphics program at my C and C++ Programming Blog. You can find my blog here, there are three parts of the posts about graphics.h library. First part of the post discusses the necessary functions to get the program ready to draw shapes and styles, second post provides description of necessary functions to draw different shapes and fill them with colors or textures. And the last part is a sample program to demonstrate that how you can write programs in graphics mode.

Function circle

Draws the circle on the screen using a point(x,y) and the radius for the circle.

void far circle(int x, int y, int radius)

Function line

This function draws a line in the graphics mode.

void far line(int startx, int starty, int endx, int endy)

Function outtext

Displays a text string on the grpahics screen.

void far outtext(char far *str)

Function outtextxy

Displays the text at a specified position in graphics mode.

void far outtext(int x, int y, char *str)

Function rectangle

Draws a rectangular box on the screen using the points given in the parameters.

void far rectangle(int left, int top, int right, int bottom)
M. Saqib: Saqib is Master-level Senior Software Engineer with over 14 years of experience in designing and developing large-scale software and web applications. He has more than eight years experience of leading software development teams. Saqib provides consultancy to develop software systems and web services for Fortune 500 companies. He has hands-on experience in C/C++ Java, JavaScript, PHP and .NET Technologies. Saqib owns and write contents on mycplus.com since 2004.
Related Post