C Exercise Example65
# C Programming Exercise Example 65: Drawing an Elegant Geometric Pattern
In legacy C programming, particularly within MS-DOS environments like Turbo C (TC), developers used the Borland Graphics Interface (`graphics.h`) to create rich visual displays. This tutorial demonstrates how to draw a highly symmetrical, elegant geometric pattern (a complete graph or "mystic rose") by connecting evenly spaced points along the circumference of a circle.
---
## 1. Introduction
The goal of this exercise is to generate an intricate geometric pattern using basic trigonometric functions and line-drawing routines.
The program calculates $N$ equidistant points along the perimeter of a circle. It then draws a line (chord) from every point to every other point. This mathematical structure is known in graph theory as a **Complete Graph ($K_n$)**. When rendered, it forms a beautiful, rosette-like geometric pattern.
---
## 2. Mathematical and Logical Analysis
To construct this pattern, we perform the following steps:
1. **Determine the Center and Radius**: Find the center of the active viewport and calculate a suitable radius based on the screen's aspect ratio.
2. **Calculate Circumference Points**: Divide the $360^\circ$ circle into $N$ equal angular increments (where $N = 15$ in this example).
3. **Convert to Radians**: Since standard C math library functions (`sin`, `cos`) expect angles in radians, convert degrees using the formula:
$$\text{radians} = \text{angle} \times \frac{\pi}{180}$$
4. **Map Coordinates**: Calculate the $(x, y)$ coordinates for each of the $15$ points:
$$x = x_{\text{center}} + \cos(\theta) \times \text{radius}$$
$$y = y_{\text{center}} - \sin(\theta) \times \text{radius} \times \text{AspectRatio}$$
5. **Connect All Points**: Use a nested loop to draw a line from each point $i$ to every subsequent point $j$ (where $j \ge i$).
---
## 3. Source Code Implementation
Below is the complete C program. This code is designed for compilers that support the legacy Turbo C graphics library (`graphics.h`).
```c
/*
Created by www.runoob.com on 15/11/9.
Copyright Β© 2015 Runoob. All rights reserved.
English translation and annotations for YouTip.
*/
#include "graphics.h"
#include "math.h"
#include "dos.h"
#include "conio.h"
#include "stdlib.h"
#include "stdio.h"
#include "stdarg.h"
#define MAXPTS 15
#define PI 3.1415926
struct PTS {
int x, y;
};
double AspectRatio = 0.85;
void LineToDemo(void)
{
struct viewporttype vp;
struct PTS points;
int i, j, h, w, xcenter, ycenter;
int radius, angle, step;
double rads;
printf(" MoveTo / LineTo Demonstration" );
/* Retrieve current viewport settings to determine screen dimensions */
getviewsettings(&vp);
h = vp.bottom - vp.top;
w = vp.right - vp.left;
/* Determine the center of the circle */
xcenter = w / 2;
ycenter = h / 2;
/* Calculate the radius adjusted for aspect ratio */
radius = (h - 30) / (AspectRatio * 2);
/* Determine the angular step size for 15 points */
step = 360 / MAXPTS;
angle = 0; /* Start at 0 degrees */
/* Calculate and store the coordinates of the 15 points */
for (i = 0; i < MAXPTS; ++i) {
rads = (double)angle * PI / 180.0; /* Convert angle to radians */
points.x = xcenter + (int)(cos(rads) * radius);
points.y = ycenter - (int)(sin(rads) * radius * AspectRatio);
angle += step; /* Move to the next point */
}
/* Draw the outer bounding circle */
circle(xcenter, ycenter, radius);
/* Draw the chords connecting every point to every other point */
for (i = 0; i < MAXPTS; ++i) {
for (j = i; j < MAXPTS; ++j) { /* Connect to all subsequent points */
moveto(points.x, points.y); /* Move pen to starting point */
lineto(points.x, points.y); /* Draw line to target point */
}
}
}
int main()
{
int driver, mode;
/* Initialize graphics system using CGA mode */
driver = CGA;
mode = CGAC0;
initgraph(&driver, &mode, "");
/* Set drawing color and background color */
setcolor(3);
setbkcolor(GREEN);
/* Run the geometric pattern demonstration */
LineToDemo();
/* Wait for user input before closing the graphics window */
getch();
closegraph();
return 0;
}
```
---
## 4. Code Explanation
* **`struct PTS`**: A simple structure used to store the $(x, y)$ coordinate pairs of the points on the circle.
* **`getviewsettings()`**: A Borland Graphics Interface (BGI) function that retrieves the boundaries of the current viewport, allowing the program to dynamically center the drawing regardless of screen resolution.
* **`moveto(x, y)` and `lineto(x, y)`**:
* `moveto` shifts the virtual drawing cursor to the specified coordinates without drawing.
* `lineto` draws a line from the current cursor position to the new coordinates.
* **Nested Loops**: The outer loop selects a starting point $i$, and the inner loop iterates through all points $j \ge i$. This ensures that every unique pair of points is connected by exactly one line, preventing redundant drawing operations.
---
## 5. Compilation and Compatibility Considerations
Because this program relies on the legacy `` library, compiling it on modern operating systems requires specific configurations:
1. **Using Turbo C++ / DOSBox**:
* The easiest way to run this code unmodified is inside a pre-configured DOSBox environment running Turbo C++ 3.0.
* Ensure that the linker is set to include the Graphics Library (`Options > Linker > Libraries > Graphics library` set to **ON**).
* Make sure the path to the BGI directory (usually `C:\TC\BGI`) is correctly configured in your environment.
2. **Using Modern Compilers (GCC / Clang)**:
* Standard modern compilers do not support `graphics.h` natively.
* To run this on modern Windows, macOS, or Linux, you can use alternative libraries such as **WinBGIm** (a C++ graphics library emulation for GCC) or modern multimedia libraries like **SDL2** or **SFML** to recreate the drawing logic.
YouTip