Drawing a parabola

I'm not sure if this is in the right place or not, but I still feel like a beginner so I figure I'll ask here first and move it if necessary.

The problem I'm having is that I just started a new programming class that uses API and there's no book for API since it's a math course, and I've never taken an API class before. I'm completely lost and am hoping for some insight into figuring out how everything works, and how to complete this assignment. The assignment is to modify an already set up code that plots each point of a parabola so that it draws the entire parabola with a solid line. I have added a DrawLine function, but for some reason it draws a line from the first point to the next point, deletes that line, then draws the line to the next point, and does that til it meets the boundaries.


Here's the cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
parabola2.cpp

Draws a parabola with horizontal axis (pg 52)
made up of line segments
*/

#include <stdio.h>
#include <windows.h>

#include "resource.h"

// your path for this include may vary
#include "GraphicsFramework.h"


// Global variable to store the graphics framwork object
GraphicsFramework* PGraphics;

HWND HOutput = 0;  // handle to the output control
HWND HDialog = 0;

// function to get the absolute value of an integer
int Abs(int x) {
	if (x < 0)  return -x;
	else        return x;
}

// function to get the sign (+1 or -1) of an integer
int Sign(int x) {
	if (x < 0)  return -1;
	else        return 1;
}
void DrawLine(int x2, int y2, int x1, int y1, unsigned int color)
{
	COLORREF green = RGB(0, 255, 0);     // green color to draw with
	COLORREF purple = RGB(255, 0, 255);  // purple color to draw with
	int dy, dx, y, x;
    // calculate changes in y and x between the points
    dy = y2 - y1;
    dx = x2 - x1;

    // clear the scene and add an axis
    PGraphics->ClearScene(RGB(0, 0, 0));
    PGraphics->AddAxis(RGB(150, 150, 150), 10);

    if (Abs(dy) > Abs(dx)) {
        // since there is a greater change in y than x we must
        // loop in y, calculate x and draw
        for (y=y1; y != y2; y += Sign(dy)) {
            x = x1 + (y - y1) * dx / dy;
            PGraphics->AddPoint(x, y, green);
        }
    }
    else {
        // since there is a greater (or equal) change in x than y we must
        // loop in x, calculate y and draw
        for (x=x1; x != x2; x += Sign(dx)) {
            y = y1 + (x - x1) * dy / dx;
            PGraphics->AddPoint(x, y, green);
        }
    }
	PGraphics->Draw();
	return;

}
void DrawStuff() {
	COLORREF green = RGB(0, 255, 0);     // green color to draw with
	COLORREF purple = RGB(255, 0, 255);  // purple color to draw with

	char str[32];                       // string to store user input
	int h, k;                           // parabola vertex
	double a;                           // parabola constant - might be a decimal
	int x, y;                           // loop and point variables
	int xPrev, yPrev;                   // previous point for drawng line segments
	int ymin, ymax;                     // limits for y loop
	RECT rect;                          // rectangle for the output window

	// get the user input from the edit boxes and 
	// convert string input to integer
	GetDlgItemText(HDialog, IDC_EDIT_VERTEXX, str, 32);
	h = atoi(str);
	GetDlgItemText(HDialog, IDC_EDIT_VERTEXY, str, 32);
	k = atoi(str);
	GetDlgItemText(HDialog, IDC_EDIT_CONSTA, str, 32);
	a = atof(str);                              // use atof to allow user to enter a decimal

	// get the rect for this window
	GetClientRect(HOutput, &rect);

	// use the rectangle info to set up y loop limits
	ymin = -(rect.bottom - rect.top) / 2;
	ymax =  (rect.bottom - rect.top) / 2;

	// clear the scene and add an axis
	PGraphics->ClearScene(RGB(0, 0, 0));
	PGraphics->AddAxis(RGB(150, 150, 150), 10);

	yPrev = ymin;
	xPrev = (int)( a * (yPrev-k) * (yPrev-k) ) + h;
	// loop in y, calculate x and draw
	for (y = ymin; y <= ymax; y++) {
		x = (int)( a * (y-k) * (y-k) ) + h;
		DrawLine(x, y, xPrev, yPrev, green);
		PGraphics->AddPoint(x, y, green); 
	}

	// draw the points
	PGraphics->Draw();
}


/*
DialogProc
this is the window event handler for the main dialog
*/
BOOL CALLBACK DialogProc (HWND hwnd, 
						  UINT message, 
						  WPARAM wParam, 
						  LPARAM lParam)
{
	switch(message)
	{
	case WM_INITDIALOG:
		// dialog is initializing - store the picture box handle in a global variable for later
		HOutput = GetDlgItem(hwnd, IDC_PICTURE_OUTPUT);        

		// instantiate and initialize our graphics framework object
		PGraphics = new GraphicsFramework(HOutput);

		break;

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDC_BTN_DRAW:
			// draw button was pressed
			DrawStuff();
			break;
		case IDC_BTN_CLEAR:
			// clear button was pressed so clear the scene and draw the empty scene
			PGraphics->ClearScene(RGB(0, 0, 0));
			PGraphics->Draw();
			break;
		case IDCANCEL:
			// user is quitting so release the GraphicsFramework object and quit
			delete PGraphics;
			PostQuitMessage(0);
			break;
		}

	}
	return FALSE;
}

// this is the main function that starts the application
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
	// create the main window
	// store its handle in a global if needed
	HDialog = CreateDialog (GetModuleHandle(NULL), 
		MAKEINTRESOURCE(IDD_DIALOG1), 
		0, 
		DialogProc);

	// make the dialog visible
	ShowWindow(HDialog, SW_SHOW);

	// standard windows message loop
	MSG  msg;
	int status;
	while ((status = GetMessage (&msg, 0, 0, 0)) != 0)
	{
		if (status == -1)
			return -1;
		// avoid processing messages for the dialog
		if (!IsDialogMessage (HDialog, & msg))
		{
			TranslateMessage ( & msg );
			DispatchMessage ( & msg );
		}
	}

	return (int)(msg.wParam);
}


Last edited on
and the header files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// GraphicsFramework.h

#ifndef GRAPHICSFRAMEWORK_H
#define GRAPHICSFRAMEWORK_H

#include <windows.h>        // must include this for windows programs

// A graphics framework class used to implement a drawing area within a windows control.
// This class implements a back buffer as a memory bitmap which will store pixels and then
// copy them with a call to the Draw method.
class GraphicsFramework {
private:
	HBITMAP     memBMP;					// back buffer
	HDC         memHDC;
	HANDLE oldHDC;
	int wd, ht;
    int wdOver2;
    int htOver2;
    RECT rect;                          // rect for this window
    HWND hwnd;							// handle to the output control

public:
    GraphicsFramework() {
        this->hwnd = NULL;
    }

	// construct from a windows handle
    GraphicsFramework(HWND hwnd) {
		BITMAPINFO bmi;					// bitmap info structure for creating the back buffer
		HDC hdc;

        this->hwnd = hwnd;

		// get the window's client rectangle and its center
		hdc = GetDC(hwnd);
		GetClientRect(hwnd, &rect);
		wd = rect.right - rect.left;
		ht = rect.bottom - rect.top;
		wdOver2 = wd / 2;
		htOver2 = ht / 2;

		// set up a 32bit rgb dib for an offscreen (memory) render target (the back buffer)
		memHDC = CreateCompatibleDC(hdc);
		bmi.bmiHeader.biWidth = wd;
		bmi.bmiHeader.biHeight = ht;
		bmi.bmiHeader.biBitCount = 32;
		bmi.bmiHeader.biCompression = BI_RGB;
		bmi.bmiHeader.biClrUsed = 0;
		bmi.bmiHeader.biClrImportant = 0;
		bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		bmi.bmiHeader.biPlanes = 1;
		bmi.bmiHeader.biSizeImage = 0;

		memBMP = CreateDIBSection(memHDC, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);

		// select this memory bmp for drawing
		// note: it will remain selected until destructor is called
		oldHDC = SelectObject(memHDC, memBMP);

		// release the device context
        ReleaseDC(hwnd, hdc);
    }

    ~GraphicsFramework() {
		// deselect and delete the memory dc that was selected in the constructor
		SelectObject(memHDC, oldHDC);		
		DeleteObject(memBMP);
		DeleteDC(memHDC);
    }

	// this method copies the back buffer to the output window
	void Draw()    {
        HDC graphics;                       // graphics device context

		graphics = GetDC(hwnd);

		// copy from offscreen memory bmp to screen
		BitBlt(graphics, 0, 0, wd, ht, memHDC, 0, 0, SRCCOPY);

        // release the device context
        ReleaseDC(hwnd, graphics);
    }

	void DrawPixel(int x, int y, COLORREF color) {
		if (x  < -wdOver2 || x >= wdOver2 ||
            y <= -htOver2 || y >  htOver2) 
        {
            // x and/or y is out of bounds so don't draw

        } else {
            // move origin from upper left to center of buffer
            // draw the pixel 
            SetPixel(memHDC, wdOver2 + x, htOver2 - y, color);
        }
	}

    void ClearScene(COLORREF backColor)
    {
        // clear the offscreen memory bmp to backColor
        HBRUSH hBrush;

		// create the brush with specified color
        hBrush = CreateSolidBrush(backColor);

        // fill the rectangle with black
		rect.left = 0;
		rect.right = wd;
		rect.top = 0;
		rect.bottom = ht;
        FillRect(memHDC, &rect, hBrush);

        // release the brush
        DeleteObject(hBrush);
    }
    
    // add a point to be drawn
    void AddPoint(int x, int y, COLORREF color) {
		SetPixel(memHDC, wdOver2 + x, htOver2 - y, color);
    }

    // draw x and y axis in specifice color, with single dot every tic step
    void AddAxis(COLORREF color, int ticStep) {
        int x, y;

        // draw horizontal line
        for (x = -wdOver2; x <= wdOver2; x++) {
            if (x % ticStep == 0)     {
                //pList.Add(x, 0, color);
		        DrawPixel(x, 0, color);

            }
        }

        // draw vertical line
        for (y = -htOver2; y < htOver2; y++) {
            if (y % ticStep == 0){
                //pList.Add(0, y, color);
				DrawPixel(0, y, color);

            }
        }
    }
};

#endif 


head file 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by parabola.rc
//
#define IDD_DIALOG1                     101
#define IDC_EDIT_WIDTH                  1001
#define IDC_EDIT_NUMTIMES               1001
#define IDC_EDIT_X1                     1001
#define IDC_EDIT_VERTEXX                1001
#define IDC_EDIT_HEIGHT                 1002
#define IDC_EDIT_Y1                     1002
#define IDC_RADIO_ROWMAJOR              1003
#define IDC_EDIT_X2                     1003
#define IDC_EDIT_PTX                    1003
#define IDC_RADIO_COLMAJOR              1004
#define IDC_EDIT_Y2                     1004
#define IDC_EDIT3                       1005
#define IDC_EDIT_OUTPUT                 1005
#define IDC_EDIT_VERTEXY                1005
#define IDC_COMBO1                      1006
#define IDC_CBO_OPERATION               1006
#define IDC_EDIT_CONSTA                 1006
#define IDC_BTN_DRAW                    1007
#define IDC_BTN_CLEAR                   1008
#define IDC_PIC_OUTPUT                  1009
#define IDC_PICTURE_OUTPUT              1009
#define IDC_X2                          1010
#define IDC_Y2                          1011
#define IDC_X4                          1013

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1012
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif 
Topic archived. No new replies allowed.