Programming AssignmentsOverviewThere will be four programming assignments in this course. But, these will be more than just exercises in writing code in C++. This will be an exercise in Software Engineering. You will learn about the Agile approach to Software Engineering, specifically that approach called Scrum. Details of Scrum will be discussed in class. On this page you will find the basics of what is required for each programming assignment.You can follow each of the links below to see how programming assignments will be posted and how you should execute each one.
|
||||||||||||||||||||||||||||||||||||||
|
the required documentation for all programming assignments. THIS IS NOT YOUR FIRST PROGRAMMING ASSIGNMENT. |
||||||||||||||||||||||||||||||||||||||
Programming Assignment 1Posted: Tuesday, January 26Sprint 1: January 26 - January 28 Sprint 2: January 28 - February 4 DDD: Thursday, February 11
Statement of Work
|
||||||||||||||||||||||||||||||||||||||
| 1.0 Overview | ||||||||||||||||||||||||||||||||||||||
|
There are many operations in Linear Algebra that are used in rendering
scenes in 3D graphics applications. Many of these operations are a part of the OpenGL libraries. In this programming assignment you will create a utility class which implements many of these operations. |
||||||||||||||||||||||||||||||||||||||
| 2.0 Requirements | ||||||||||||||||||||||||||||||||||||||
|
The student shall define, develop, document, prototype,
test, and modify as required the software system. |
||||||||||||||||||||||||||||||||||||||
|
2.1 This software system shall define a linear algebra utility
class called LinearAlgUtil (file names shall be LinearAlgUtil.h and
LinearAlgUtil.cpp) which contains a number of utility functions for performing graphics rendering related linear algebra operations. |
||||||||||||||||||||||||||||||||||||||
|
2.1.1 The LinearAlgUtilclass
shall contain private variables as described below: |
||||||||||||||||||||||||||||||||||||||
|
2.1.1.1 An instance of the structure Point2D (see section 2.1.3 below) called m_Pt. This structure shall
be used as an intermediate data container for the point rotation functions. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2 The LinearAlgUtil class shall contain public functions as described below: |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.1 LinearAlgUtil(), ~LinearAlgUtil() A default constructor and destructor. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.2 int DotProduct(int u[], int v[]). This function takes as
arguments 2 one-dimensional arrays, each containing 3 ints, representing two vectors u and v. The function calculates the Dot Product (u dot v) and returns the result as an int. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.3 void CrossProduct(int u[], int v[], int Result[]). This function takes as
arguments 3 one-dimensional arrays, each containing 3 ints. The first two array arguments represent two vectors u and v. The function calculates the Cross Product (u x v) and places the resulting vector in the third array argument. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.4 void MatrixMultiply4X4(int M1[][4], int M2[][4], int Result[][4]).
This function takes as arguments 3 two-dimensional arrays, each containing 4 rows and 4 columns ints. The first two array arguments represent two matrices which are to be multiplied together and the resulting matrix is placed in the third array argument. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.5 void RotatePoint2D_Ptr(Point2D *pt, double angle).
This function takes as arguments a pointer to a Point2D structure and a double giving the angle in degrees through which to rotate the given point. Upon return the x and y fields of the Point2D structure will hold the rotated point coordinates. |
||||||||||||||||||||||||||||||||||||||
|
2.1.2.6 void RotatePoint2D_Ref(Point2D& pt, double angle).
This function takes as arguments a reference to a Point2D structure and a double giving the angle in degrees through which to rotate the given point. Upon return the x and y fields of the Point2D structure will hold the rotated point coordinates. |
||||||||||||||||||||||||||||||||||||||
|
2.1.3 A structure called Point2D shall be defined in the LinearAlgUtil.h.
It shall contain 2 fields, a double called x and a double called y. It will be used to represent a point in 2D space. |
||||||||||||||||||||||||||||||||||||||
|
2.2 The class file and its' associated header file
must be capable of being compiled and linked in with the instructor's driver
program (which will main) for testing. Do not turn in your source file containing contain main. It will not be used for testing. |
||||||||||||||||||||||||||||||||||||||
| 3.0 Deliverables | ||||||||||||||||||||||||||||||||||||||
|
These products shall be delivered
electronically via e-mail as specified below to the instructor. 3.1 Scrum Report -- The student shall provide a Scrum Activity Report for instructor approval NLT (Not Later Than) Thursday, February 13. 3.2 Program source files -- The student shall provide fully tested electronic copies of the .cpp and .h files. These files must be submitted to the instructor via e-mail. The files shall be delivered NLT Thursday, February 13. |
||||||||||||||||||||||||||||||||||||||
| 4.0 Period of Performance | ||||||||||||||||||||||||||||||||||||||
|
The period of performance of this assignment is 21 days
from the date of assignment. Only under special circumstances will
any deliverables be accepted after the DDD date posted in the Course Syllabus. |
||||||||||||||||||||||||||||||||||||||
|
A note on program grading: The instructor will test your program
by compiling your LinearAlgUtil.cpp and LinearAlgUtil.h files with a driver
program containing a main() function. This driver will exhaustively
test your source code.
|
||||||||||||||||||||||||||||||||||||||
|
It is to be turned in with your source code. THIS IS NOT THE SCRUM REPORT FOR YOUR FIRST PROGRAMMING ASSIGNMENT. |
||||||||||||||||||||||||||||||||||||||
Programming Assignment 1 Scrum ReportSprint 1 Epic: As a student of CS 221 I need to create the basic program architecture.
Sprint 2 Epic: As a student of CS 221 I need to plan how to test each function. Epic: As a student of CS 221 I need to implement and verify each function.
|
||||||||||||||||||||||||||||||||||||||
Sprint 1 CodeBelow you will see the actual code created for this demonstration project during Sprint 1. This includes the file with main() showing the testing and the LinearAlgUtil.h and LinearAlgUtil.cpp files. There is also an image of the on-screen output after a run of the compiled program. |
||||||||||||||||||||||||||||||||||||||
File: Prog1Main.cpp
//=============================================================================
// Programming Assignment Demonstration
// File: Prog1Main.cpp
// This program demonstrates the steps to be completed in Sprint 1.
//
// Author: Dr. Rick Coleman
// History: Project created December 2015
//=============================================================================
#include <iostream>
#include "LinearAlgUtil.h"
using namespace std;
void main()
{
int vect1[3]; // Array of 3 ints to represent a vector in XYZ space
int vect2[3]; // Array of 3 ints to represent a vector in XYZ space
int vectResult[3]; // Array of 3 ints to represent a vector in XYZ space
int matrix1[4][4]; // 2-D Array of ints to represent a matrix
int matrix2[4][4]; // 2-D Array of ints to represent a matrix
int matrixResult[4][4]; // 2-D Array of ints to represent a matrix
Point2D pt; // Structure for testing point rotate functions
char ans; // Input from user
int testResult = 0; // Keep up with count of successful tests
int expectedResult = 0;
cout << "Running tests of LinearAlgUtil functions.\n\n";
LinearAlgUtil *lau = new LinearAlgUtil(); // Create test instance
// Test constructor by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil constructor.\"? (Press Y or N)";
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the DotProduct function
lau->DotProduct(vect1, vect2); // Call DotProcuct function
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil::DotProduct function.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the CrossProduct function
lau->CrossProduct(vect1, vect2, vectResult); // Call CrossProduct function
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil::CrossProduct function.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the MatrixMultiply4X4 function
lau->MatrixMultiply4X4(matrix1, matrix2, matrixResult); // Call MatrixMultiply4X4 function
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil::MatrixMultiply4X4 function.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the RotatePoint2D_Ptr function
lau->RotatePoint2D_Ptr(&pt, 0.0); // Call RotatePoint2D_Ptr function
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil::RotatePoint2D_Ptr function.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the RotatePoint2D_Ref function
lau->RotatePoint2D_Ref(pt, 0.0); // Call RotatePoint2D_Ptr function
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil::RotatePoint2D_Ref function.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Test the destructor
delete lau;
// Test function call by Observation
cout << "Did you see printed:\n\t\"Now executing LinearAlgUtil destructor.\"? (Press Y or N)";
cin.ignore(10, '\n'); // Flush buffer before next input
cin.get(ans);
if((ans == 'Y') || (ans == 'y'))
testResult++;
expectedResult++;
cout << "\n\n";
// Output result of testing
cout << "\nFinal result of testing = " << testResult << endl;
cout << "Expected to get a count of " << expectedResult << endl << endl;
}
|
||||||||||||||||||||||||||||||||||||||
File: LinearAlgUtil.h
//=======================================================================
// LinearAlgUtil.h
// Header file defining a class of Linear Algebra Utility functions.
// This program is a demonstration for programming assignments in
// CS 221 following the Agile approach of Scrum.
//
// Author: Dr. Rick Coleman
// History: Created December 2015
//=======================================================================
#pragma once;
// Define the point structure
struct Point2D
{
double x;
double y;
};
class LinearAlgUtil
{
private:
Point2D m_Pt; // Temp Point2D struct for use by point rotate functions
public:
LinearAlgUtil(); // Default constructor
~LinearAlgUtil(); // Destructor
int DotProduct(int u[], int v[]); // Calculate the Dot Product of vectors u and v
void CrossProduct(int u[], int v[], int Result[]); // Calculate the Cross Product of vectors u and v
void MatrixMultiply4X4(int M1[][4], int M2[][4], int Result[][4]);// Calculate a 4x4 matrix multiplication
void RotatePoint2D_Ptr(Point2D *pt, double angle); // Rotate a point in 2D using pointer to Point2D struct
void RotatePoint2D_Ref(Point2D& pt, double angle); // Rotate a point in 2D using reference to Point2D struct
};
|
||||||||||||||||||||||||||||||||||||||
File: LinearAlgUtil.CPP
//===========================================================================
// LinearAlgUtil.cpp
// Implementation file defining a class of Linear Algebra Utility functions.
// This program is a demonstration for programming assignments in
// CS 221 following the Agile approach of Scrum.
//
// This file demonstrates the implementation to be completed in Sprint 1.
//
// Author: Dr. Rick Coleman
// History: Created December 2015
//===========================================================================
#include "LinearAlgUtil.h"
#include <iostream>
using namespace std;
//------------------------------------------------
// Default constructor
//------------------------------------------------
LinearAlgUtil::LinearAlgUtil()
{
cout << "Now executing LinearAlgUtil constructor.\n";
}
//------------------------------------------------
// Destructor
//------------------------------------------------
LinearAlgUtil::~LinearAlgUtil()
{
cout << "Now executing LinearAlgUtil destructor.\n";
}
//-------------------------------------------------------
// Calculate the Dot Product of vectors u and v
//-------------------------------------------------------
int LinearAlgUtil::DotProduct(int u[], int v[])
{
cout << "Now executing LinearAlgUtil::DotProduct function.\n";
return 0;
}
//-------------------------------------------------------
// Calculate the Cross Product of vectors u and v
//-------------------------------------------------------
void LinearAlgUtil::CrossProduct(int u[], int v[], int Result[])
{
cout << "Now executing LinearAlgUtil::CrossProduct function.\n";
}
//-------------------------------------------------------
// Calculate a 4x4 matrix multiplication
//-------------------------------------------------------
void LinearAlgUtil::MatrixMultiply4X4(int M1[][4], int M2[][4], int Result[][4])
{
cout << "Now executing LinearAlgUtil::MatrixMultiply4X4 function.\n";
}
//-------------------------------------------------------
// Rotate a point in 2D using pointer to Point2D struct
//-------------------------------------------------------
void LinearAlgUtil::RotatePoint2D_Ptr(Point2D *pt, double angle)
{
cout << "Now executing LinearAlgUtil::RotatePoint2D_Ptr function.\n";
}
//-------------------------------------------------------
// Rotate a point in 2D using reference to Point2D struct
//-------------------------------------------------------
void LinearAlgUtil::RotatePoint2D_Ref(Point2D& pt, double angle)
{
cout << "Now executing LinearAlgUtil::RotatePoint2D_Ref function.\n";
}
|
||||||||||||||||||||||||||||||||||||||
Output from running the Sprint 1 code
|
||||||||||||||||||||||||||||||||||||||
Sprint 2 CodeBelow you will see the final code created for this demonstration project during Sprint 2.Note carefully the comments on testing given in the file with main(). There is also an image of the on-screen output after a run of the compiled program. |
||||||||||||||||||||||||||||||||||||||
File: Prog1Main.cpp
//=============================================================================
// Programming Assignment Demonstration
// File: Prog1Main.cpp
// This program demonstrates the steps to be completed in Sprint 2.
//
//
// Author: Dr. Rick Coleman
// History: Project created December 2015
//=============================================================================
#include "LinearAlgUtil.h"
#include <math.h>
#include <iomanip>
#include <iostream>
using namespace std;
#define SPRINT2
void main()
{
int vect1[3]; // Array of 3 ints to represent a vector in XYZ space
int vect2[3]; // Array of 3 ints to represent a vector in XYZ space
int vectResult[3]; // Array of 3 ints to represent a vector in XYZ space
int matrix1[4][4]; // 2-D Array of ints to represent a matrix
int matrix2[4][4]; // 2-D Array of ints to represent a matrix
int matrixResult[4][4]; // 2-D Array of ints to represent a matrix
Point2D pt; // Structure for testing point rotate functions
int testResult = 0; // Keep up with count of successful tests
int expectedResult = 0;
LinearAlgUtil *lau = new LinearAlgUtil(); // Create test instance
// Test the DotProduct function
vect1[0] = 1; // Init vector 1 to (X, 2Y, 3Z)
vect1[1] = 2;
vect1[2] = 3;
vect2[0] = 4; // Init vector 2 to (4X, 5Y, 6Z)
vect2[1] = 5;
vect2[2] = 6;
// Call DotProcuct function
int dotResult = lau->DotProduct(vect1, vect2);
// Expected result = (1x4)+(2*5)+(3*6) = 32
cout << "\nTest of DotProduct: Expected 32, got back " << dotResult << endl;
if(dotResult == 32)
{
cout << "Test successful\n";
testResult++; // Increment success counter
}
else
cout << "Test failed\n";
expectedResult++; // Increment test counter
// Test the CrossProduct function
// Use same vectors defined in test of DotProduct
lau->CrossProduct(vect1, vect2, vectResult); // Call CrossProduct function
// Expected result 1 2 3 4 5 6
// Given two vectors: a=(a0, a1, a2) and b=(b0, b1, b2)
// vect1 x vect2 = (a1b2 - a2b1), (a2b0 - a0b2), (a0b1 - a1b0)
// = (2*6 - 3*5), (3*4 - 1*6), (1*5 - 2*4)
// = (-3, 6, -3)
cout << "\nTest of CrossProduct got back: (" << vectResult[0] << ", " << vectResult[1] << ", " << vectResult[2] << ")\n";
if((vectResult[0] == -3) && (vectResult[1] == 6) && (vectResult[2] == -3))
{
cout << "Test successful\n";
testResult++; // Increment success counter
}
else
cout << "Test failed\n";
expectedResult++; // Increment test counter
// Test the MatrixMultiply4X4 function
// Build 2 test matrices | 1 2 3 4| |17 18 19 20|
// A = | 5 6 7 8| B = |21 22 23 24|
// | 9 10 11 12| |25 26 27 28|
// | 13 14 15 16| |29 30 31 32|
for(int row=0; row<4; row++) // For each row in the resulting matrix
{
for(int col=0; col<4; col++) // For each column in the resulting matrix
{
matrix1[row][col] = (row * 4) + col + 1;
matrix2[row][col] = matrix1[row][col] + 16;
matrixResult[row][col] = 0; // clear this one
}
}
// Manually calculate the result of A * B
// C00 = ( 1 * 17) + ( 2 * 21) + ( 3 * 25) + ( 4 * 29) = 250
// C01 = ( 1 * 18) + ( 2 * 22) + ( 3 * 26) + ( 4 * 30) = 260
// C02 = ( 1 * 19) + ( 2 * 23) + ( 3 * 27) + ( 4 * 31) = 270
// C03 = ( 1 * 20) + ( 2 * 24) + ( 3 * 28) + ( 4 * 32) = 280
//
// C10 = ( 5 * 17) + ( 6 * 21) + ( 7 * 25) + ( 8 * 29) = 618
// C11 = ( 5 * 18) + ( 6 * 22) + ( 7 * 26) + ( 8 * 30) = 644
// C12 = ( 5 * 19) + ( 6 * 23) + ( 7 * 27) + ( 8 * 31) = 670
// C13 = ( 5 * 20) + ( 6 * 24) + ( 7 * 28) + ( 8 * 32) = 696
//
// C20 = ( 9 * 17) + (10 * 21) + (11 * 25) + (12 * 29) = 986
// C21 = ( 9 * 18) + (10 * 22) + (11 * 26) + (12 * 30) = 1028
// C22 = ( 9 * 19) + (10 * 23) + (11 * 27) + (12 * 31) = 1070
// C23 = ( 9 * 20) + (10 * 24) + (11 * 28) + (12 * 32) = 1112
//
// C30 = (13 * 17) + (14 * 21) + (15 * 25) + (16 * 29) = 1354
// C31 = (13 * 18) + (14 * 22) + (15 * 26) + (16 * 30) = 1412
// C32 = (13 * 19) + (14 * 23) + (15 * 27) + (16 * 31) = 1470
// C33 = (13 * 20) + (14 * 24) + (15 * 28) + (16 * 32) = 1528
//
// This gives the matrix: | 250 260 270 280|
// C = | 618 644 670 696|
// | 986 1028 1070 1112|
// | 1354 1412 1470 1528|
lau->MatrixMultiply4X4(matrix1, matrix2, matrixResult); // Call MatrixMultiply4X4 function
// Test results
bool mmOK = true;
// Check row 0 | 250 260 270 280|
if(matrixResult[0][0] != 250) mmOK = false;
if(matrixResult[0][1] != 260) mmOK = false;
if(matrixResult[0][2] != 270) mmOK = false;
if(matrixResult[0][3] != 280) mmOK = false;
// Check row 1 | 618 644 670 696|
if(matrixResult[1][0] != 618) mmOK = false;
if(matrixResult[1][1] != 644) mmOK = false;
if(matrixResult[1][2] != 670) mmOK = false;
if(matrixResult[1][3] != 696) mmOK = false;
// Check row 2 | 986 1028 1070 1112|
if(matrixResult[2][0] != 986) mmOK = false;
if(matrixResult[2][1] != 1028) mmOK = false;
if(matrixResult[2][2] != 1070) mmOK = false;
if(matrixResult[2][3] != 1112) mmOK = false;
// Check row 3 | 1354 1412 1470 1528|
if(matrixResult[3][0] != 1354) mmOK = false;
if(matrixResult[3][1] != 1412) mmOK = false;
if(matrixResult[3][2] != 1470) mmOK = false;
if(matrixResult[3][3] != 1528) mmOK = false;
if(matrixResult)
{
cout << "\nTest of MatrixMultiply4x4 successful\n";
testResult++; // Increment success counter
}
else
cout << "\nTest of MatrixMultiply4x4 Test failed\n";
expectedResult++; // Increment test counter
// Test the RotatePoint2D_Ptr function
pt.x = 5.0;
pt.y = 0.0;
bool ptRot = true;
// Test Note: Because the rotation must work in all 4 quadrants this must be
// tested in all four quadrants.
// Perform rotation of point (5, 0) to 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330 degrees
for(int i=0; i<360; i+=30)
{
lau->RotatePoint2D_Ptr(&pt, (double)i); // Call RotatePoint2D_Ptr function
// Check the output
// This should create triangles with hypotenuse of 5 and other 2 sides of 4.3 and 2.5
// Note: The results below were obtained by calculating the two sides of a triangle with
// hypotenuse of 5 and angles of 30, 60, 90 degrees with the X and Y sides on
// the X and Y axes.
switch(i)
{
case 0 : if((pt.x != 5.0) && (pt.y != 0.0)) ptRot = false; break;
case 30 : if((pt.x != 4.3) && (pt.y != 2.5)) ptRot = false; break;
case 60 : if((pt.x != 2.5) && (pt.y != 4.3)) ptRot = false; break;
case 90 : if((pt.x != 0.0) && (pt.y != 5.0)) ptRot = false; break;
case 120 : if((pt.x != -2.5) && (pt.y != 4.3)) ptRot = false; break;
case 150 : if((pt.x != -4.3) && (pt.y != 2.5)) ptRot = false; break;
case 180 : if((pt.x != -5.0) && (pt.y != 0.0)) ptRot = false; break;
case 210 : if((pt.x != -4.3) && (pt.y != -2.5)) ptRot = false; break;
case 240 : if((pt.x != -2.5) && (pt.y != -4.3)) ptRot = false; break;
case 270 : if((pt.x != 0.0) && (pt.y != -5.0)) ptRot = false; break;
case 300 : if((pt.x != 2.5) && (pt.y != -4.3)) ptRot = false; break;
case 330 : if((pt.x != 4.3) && (pt.y != -2.5)) ptRot = false; break;
}
// Reset xy for next rotation
pt.x = 5.0;
pt.y = 0.0;
}
if(ptRot)
{
cout << "\nTest of RotatePoint2D_Ptr successful\n";
testResult++; // Increment success counter
}
else
cout << "\nTest of RotatePoint2D_Ptr Test failed\n";
expectedResult++; // Increment test counter
// Test the RotatePoint2D_Ref function
// This is the same test as for RotatePoint2D_Ptr. The only difference is that this
// function is passed a reference to the Point2D structure while in the previous
// function a pointer was passed.
pt.x = 5.0;
pt.y = 0.0;
ptRot = true;
// Test Note: Because the rotation must work in all 4 quadrants this must be
// tested in all four quadrants.
// Perform rotation of point (5, 0) to 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330 degrees
for(int i=0; i<360; i+=30)
{
lau->RotatePoint2D_Ref(pt, (double)i); // Call RotatePoint2D_Ref function
// Check the output
// This should create triangles with hypotenuse of 5 and other 2 sides of 4.3 and 2.5
// Note: The results below were obtained by calculating the two sides of a triangle with
// hypotenuse of 5 and angles of 30, 60, 90 degrees with the X and Y sides on
// the X and Y axes.
switch(i)
{
case 0 : if((pt.x != 5.0) && (pt.y != 0.0)) ptRot = false; break;
case 30 : if((pt.x != 4.3) && (pt.y != 2.5)) ptRot = false; break;
case 60 : if((pt.x != 2.5) && (pt.y != 4.3)) ptRot = false; break;
case 90 : if((pt.x != 0.0) && (pt.y != 5.0)) ptRot = false; break;
case 120 : if((pt.x != -2.5) && (pt.y != 4.3)) ptRot = false; break;
case 150 : if((pt.x != -4.3) && (pt.y != 2.5)) ptRot = false; break;
case 180 : if((pt.x != -5.0) && (pt.y != 0.0)) ptRot = false; break;
case 210 : if((pt.x != -4.3) && (pt.y != -2.5)) ptRot = false; break;
case 240 : if((pt.x != -2.5) && (pt.y != -4.3)) ptRot = false; break;
case 270 : if((pt.x != 0.0) && (pt.y != -5.0)) ptRot = false; break;
case 300 : if((pt.x != 2.5) && (pt.y != -4.3)) ptRot = false; break;
case 330 : if((pt.x != 4.3) && (pt.y != -2.5)) ptRot = false; break;
}
// Reset xy for next rotation
pt.x = 5.0;
pt.y = 0.0;
}
if(ptRot)
{
cout << "\nTest of RotatePoint2D_Ref successful\n";
testResult++; // Increment success counter
}
else
cout << "\nTest of RotatePoint2D_Ref Test failed\n";
expectedResult++; // Increment test counter
// Output result of testing
cout << "\nFinal result of testing = " << testResult << endl;
cout << "Expected to get a count of " << expectedResult << endl << endl;
}
|
||||||||||||||||||||||||||||||||||||||
File: LinearAlgUtil.h
//=======================================================================
// LinearAlgUtil.h
// Header file defining a class of Linear Algebra Utility functions.
// This program is a demonstration for programming assignments in
// CS 221 following the Agile approach of Scrum.
//
// Author: Dr. Rick Coleman
// History: Created December 2015
//=======================================================================
#pragma once;
// Define the point structure
struct Point2D
{
double x;
double y;
};
class LinearAlgUtil
{
private:
Point2D m_Pt; // Temp Point2D struct for use by point rotate functions
public:
LinearAlgUtil(); // Default constructor
~LinearAlgUtil(); // Destructor
int DotProduct(int u[], int v[]); // Calculate the Dot Product of vectors u and v
void CrossProduct(int u[], int v[], int Result[]); // Calculate the Cross Product of vectors u and v
void MatrixMultiply4X4(int M1[][4], int M2[][4], int Result[][4]);// Calculate a 4x4 matrix multiplication
void RotatePoint2D_Ptr(Point2D *pt, double angle); // Rotate a point in 2D using pointer to Point2D struct
void RotatePoint2D_Ref(Point2D& pt, double angle); // Rotate a point in 2D using reference to Point2D struct
};
|
||||||||||||||||||||||||||||||||||||||
File: LinearAlgUtil.CPP
//===========================================================================
// LinearAlgUtil.cpp
// Implementation file defining a class of Linear Algebra Utility functions.
// This program is a demonstration for programming assignments in
// CS 221 following the Agile approach of Scrum.
//
// This file demonstrates the implementation to be completed in Sprint 2.
// Author: Dr. Rick Coleman
// History: Created December 2015
//===========================================================================
#include "LinearAlgUtil.h"
#include <math.h>
//------------------------------------------------
// Default constructor
//------------------------------------------------
LinearAlgUtil::LinearAlgUtil()
{
// Nothing to do in the constructor.
// It was tested in Sprint 1
}
//------------------------------------------------
// Destructor
//------------------------------------------------
LinearAlgUtil::~LinearAlgUtil()
{
// Nothing to do in the destructor
// It was tested in Sprint 1
}
//-------------------------------------------------------
// Calculate the Dot Product of vectors u and v
//
// Given two vectors: a=(a0, a1, a2) and b=(b0, b1, b2)
// a dot b = a0b0 + a1b1 + a2b2.
//-------------------------------------------------------
int LinearAlgUtil::DotProduct(int u[], int v[])
{
int dp;
dp = (u[0] * v[0]) + (u[1] * v[1]) + (u[2] * v[2]);
return dp;
}
//-------------------------------------------------------
// Calculate the Cross Product of vectors u and v
// Given two vectors: a=(a0, a1, a2) and b=(b0, b1, b2)
// a x b = (a1b2 - a2b1), (a2b0 - a0b2), (a0b1 - a1b0)
//-------------------------------------------------------
void LinearAlgUtil::CrossProduct(int u[], int v[], int Result[])
{
// Calculate and store (a1b2 - a2b1)
Result[0] = (u[1] * v[2]) - (u[2] * v[1]);
// Calculate and store (a2b0 - a0b2)
Result[1] = (u[2] * v[0]) - (u[0] * v[2]);
// Calculate and store (a0b1 - a1b0)
Result[2] = (u[0] * v[1]) - (u[1] * v[0]);
}
//-------------------------------------------------------
// Calculate a 4x4 matrix multiplication
// Given: |a00 a01 a02 a03| |b00 b01 b02 b03|
// |a10 a11 a12 a13| |b10 b11 b12 b13|
// |a20 a21 a22 a23| x |b20 b21 b22 b23|
// |a30 a31 a32 a33| |b30 b31 b32 b33|
// Each element in the resulting 4x4 matrix is found by
// accessing the corresponding row in matrix A with the
// corresponding column of matrix B. Thus the element
// in position (0,0) is found with:
// c00 = a00*b00 + a01*b10 + a02*b20 + a03*b30;
// The element in position (3,3) is found with:
// c33 = a30*b03 + a31*b13 + a32*b23 + a33*b33;
//-------------------------------------------------------
void LinearAlgUtil::MatrixMultiply4X4(int M1[][4], int M2[][4], int Result[][4])
{
for(int row=0; row<4; row++) // For each row in the resulting matrix
{
for(int col=0; col<4; col++) // For each column in the resulting matrix
{
Result[row][col] = (M1[row][0] * M2[0][col]) + (M1[row][1] * M2[1][col]) +
(M1[row][2] * M2[2][col]) + (M1[row][3] * M2[3][col]);
}
}
}
//------------------------------------------------------------
// Rotate a point in 2D using pointer to Point2D struct
// This uses the matrix for rotating points about the Z axis
// and matrix multiplication.
// | cos A -sin A| |X|
// | sin A cos A| * |Y|
// Note: Because of some slight idiocyncracies in precision
// point coordinates are being rounded to the nearest 10th
// of a unit which for the purposes of this application is
// still more accuracy than is required.
//------------------------------------------------------------
void LinearAlgUtil::RotatePoint2D_Ptr(Point2D *pt, double angle)
{
// Copy the structure before rotating
m_Pt = *pt;
// Convert angle in degrees to radians (math functions require this)
// Angle in Radians = Angle in Degrees * PI/180 (0.0174532925)
double radDeg = angle * 0.01745;
pt->x = (m_Pt.x * cos(radDeg)) - (m_Pt.y * sin(radDeg));
pt->y = (m_Pt.x * sin(radDeg)) + (m_Pt.y * cos(radDeg));
// Now round to 2 decimal places
int temp = (int)floor((pt->x * 10.0) + 0.5);
pt->x = (double)temp / 10.0;
temp = (int)floor((pt->y * 10.0) + 0.5);
pt->y = (double)temp / 10.0;
// FYI: I know it looks weird but there is no round function in math.h
// If rounding to the nearest 10th, then any value from 4.45 to 4.54 must round to 4.5
// Example: Assume pt.x is 4.45678. Multiply by 10 to get 44.5678.
// If you took the floor of this you get 44 then divide by 10 to get 4.4
// which is not the value you needed. But if you add 0.5 to 44.5678 you
// get 45.0678. Now take the floor of this to get 45 and divide by 10
// to get 4.5. This then gives the accurate value 4.45678 rounded to the
// nearest 10th.
}
//-------------------------------------------------------
// Rotate a point in 2D using reference to Point2D struct
// This uses the matrix for rotating points about the Z axis
// and matrix multiplication.
// | cos A -sin A| |X|
// | sin A cos A| * |Y|
// Note: Because of some slight idiocyncracies in precision
// point coordinates are being rounded to the nearest 10th
// of a unit which for the purposes of this application is
// still more accuracy than is required.
//-------------------------------------------------------
void LinearAlgUtil::RotatePoint2D_Ref(Point2D& pt, double angle)
{
// Copy the structure before rotating
m_Pt = pt;
// Convert angle in degrees to radians (math functions require this)
// Angle in Radians = Angle in Degrees * PI/180 (0.0174532925)
double radDeg = angle * 0.01745;
pt.x = (m_Pt.x * cos(radDeg)) - (m_Pt.y * sin(radDeg));
pt.y = (m_Pt.x * sin(radDeg)) + (m_Pt.y * cos(radDeg));
// Now round to 2 decimal places
int temp = (int)floor((pt.x * 10.0) + 0.5);
pt.x = (double)temp / 10.0;
temp = (int)floor((pt.y * 10.0) + 0.5);
pt.y = (double)temp / 10.0;
// FYI: I know it looks weird but there is no round function in math.h
// If rounding to the nearest 10th, then any value from 4.45 to 4.54 must round to 4.5
// Example: Assume pt.x is 4.45678. Multiply by 10 to get 44.5678.
// If you took the floor of this you get 44 then divide by 10 to get 4.4
// which is not the value you needed. But if you add 0.5 to 44.5678 you
// get 45.0678. Now take the floor of this to get 45 and divide by 10
// to get 4.5. This then gives the accurate value 4.45678 rounded to the
// nearest 10th.
}
|
||||||||||||||||||||||||||||||||||||||
Output from running the Sprint 2 code
|
||||||||||||||||||||||||||||||||||||||
A programming assignment about Linear Algebra! |
||||||||||||||||||||||||||||||||||||||
|
But, Dr. Coleman, I haven't taken Linear Algebra.
|
|||||||||||||||||||||||||||||||||||||
Welcome to the real world of Software Engineering. In this example programming assignment Linear Algebra is known as the application Domain. That is, the specific subject matter, of the application. As a professional software engineer you will find many times you will get a contract from a customer or business about which you know nothing. It will then be your responsibility to become familiar with the customer's Domain. In the course of his career your instructor had to become educated in such diverse Application Domains as battle field tactics, how first responders handle emergency situations, how the petroleum industry drills for oil and what information they get from sensors on the wells, and several other areas. |
||||||||||||||||||||||||||||||||||||||