/object-oriented-principles

A simple tool for defining and handling basic geometric shapes in 2D

Primary LanguageC++

Advanced Programming - Object Oriented Principles (CMP2801M_Assessment_01)

Overview

A program that implements a simple tool for defining and handling basic geometric shapes in 2D. Classes and inheritance are effectively used to meet the task goals. The use of OOP principles are heavily required in order to allow the functions created to be passed and work as intended.

To begin with, the program prompts the user to enter a command, once a command is entered that is valid, the user is shown multiple lines showing what they have created. The first line contains the name of the shapes they chose from a collection of three possible (rectangle, square, and circle) along with a certain property related to that shape. If a rectangle is chosen, height and width are displayed, if a square is chosen, just the size of a single edge is displayed and finally, if a circle is chosen, the radius is shown. The following line displays the 4 corner coordinates of the shape, in the case of the circle, only the top left and right bottom coordinates. The last line displays the computer-calculated area and perimeter of the user-created shape.

Any amount of shapes can be created and will be stored by the program. The user can choose from the pre-existing shapes that they would like to either move or scale. When the move command is input, the corresponding shape is moved to the new location, and again, all the other information is displayed. However, if the scale command is used the selected shape will be scaled in the x and y direction as required. This will affect all properties of the shape so the program is required to recalculate. Finally, a display feature was implemented to show all the created shapes in order from when the program was initially started.

Summary of Implementation

All 3 shapes, Circle, Square and Rectangle are implemented to derive from both Shape and Movable. These classes both contain virtual functions used in each shape, with the shape class containing the member functions of calculateArea, calculatePerimeter, calculatePoints and toString, the movable class also has move and scale member functions. However the program does not use the isCircular variable, this was not implemented as the circle shape properties were calculated in the same way as the other two shapes. Another variation the program has is that the correct points are calculated in calculatePoints function like required however they are also printed here along with the calculations. This differs from the brief as they are supposed to be printed in the toString section. The other properties are still printed in the correct toString.

Virtual functions are used in the program and declared in the appropriate classes. They are used to allow the derived classes to override functions when needed. Doing this allows the use of late binding, which in turn forms a basis for polymorphism, which was required in this problem. In the program in each individual shape the virtual functions are redefined, this is done as each shape requires different parameters and calculations to get the desired output.

The program is designed to firstly take an input from the console from the user, once received a new string character is created, then the function “strcpy_s” copies characters from the converted string into a destination character array, this includes the null characters. Then using another function “strtok_s” which is a string tokenizer that allows each of the tokens that are entered get passed into a parameter vector, with [0] being the first word. Error checking is done here to protected against nothing being passed into the vector and causing a crash. This is done using “paramters.empty()” and checking the input against this.

The corresponding if statement is then entered and the parameters that were created are converted to individual strings and then converted to integers using the “stoi” built-in function. These are converted to allow the use of integers and similar value types when created and calculating the shapes. After this a new corresponding object is created with the parameters needed, for example in rectangle: x, y, h, w are needed. As this is created the member functions added to the shape is called, in the case of this program calculateArea, calculatePerimeter and calculatePoints are called and executed. Each of the individual functions are then ran through.

In the case of calculating both area and perimeter in all the shapes x and y are used as the parameters and then the relevant property for each shape is also used when calculating, such as radius in circle. In calculatePoints the shape class is called along with the point class. The point class contains integer values for the coordinates that will be calculated. It also contains the functions getX + Y which when called, return the x and y variables. In order to calculate the points since the shape class variable has been called it can be accessed in this function and runs the addCoord function which exists in shape. This uses the vector push_back function in order to add the point to the back of the vector. The other function in shape called getCoord returns the vector with the correct coordinates in it. After this in the same calculatePoints member function is where the points are printed.

When the user has previously created a shape and is using either the move or scale function, again as before, the command is eventually converted into individual integers. An empty nulltpr is created at this point and this new pointer calls the class. ShapeNo-1 is used as the first shape stored is a 0. Afterwards the scale or move function is called and executed. In the move member function this simply gets the inputted coordinates and times them by the previous height and width. However in scale the properties of the shape (height / edge) are multiplied by the inputted scale values and the functions are ran thorough again. However my program has the issue of not being able to call the previously stored x and y values. At the end of each loop the user is presented with the “Enter a command:” screen and is asked for values and the loop starts over again.

A few other error checks included are; if a command is entered that doesn’t match any of those outlined in the driver file and else statement will catch the input and tell the user what they entered doesn’t match and again prompt them to re-enter values, this will loop until the correct format of input is entered with appropriate values. In each individual shapes function more exception handling is done to check the user is entering valid values. Firstly, an if loop checks that the height and width are both above zero as negative values of these properties are not possible, the same thing is then done in the scale function for each shape to check these values are not negative integers, if this is the case in either, the line “A positive value is required for...” is printed to the user and they must enter the parameters again.

When creating the program a stoi function was used in order to simply convert string to integer. In terms of the complexity it is linear for the amount of characters used, either 3 or 4 depending on the input. Another algorithm chosen to use was strtok_s, this finds the next token in a set string after each chosen delimiter. The delimiter chosen was a space character as the user is entering a command where this can be split by the spaces.