2D Graphics Inheritance Homework 7. Inheritance, 2D graphics Ján Dugá£ek September 20, 2017 Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Table of Contents 1 2D Graphics How does it work? A black image A rectangle A line Fast square root Circle Exercises 2 Inheritance Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises 3 Homework Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises 2D Graphics: How does it work? An image is typically compressed using a long and complicated algorithm that should better be avoided using a library like FreeImage It is planned that C++ would be added io2d to deal with this, but the proposal is not nished yet The function to read and save a .bmp le is quite simple and available An opened image is a 3D array of type unsigned char (or uint8_t) with dimensions height, width and colour (2D without colour if it's greyscale) All operations are done on the array until it's saved and this array is the same for all libraries (though it might be ipped) Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises A black image struct image300x200 { unsigned char [ 3 0 0 ] [ 2 0 0 ] [ 3 ] ; unsigned char& at ( int x , int y , int col ) { return char [ x ] [ y ] [ col ] ; } } image300x200 pic ; for ( int i = 0; i < 300; i++) for ( int j = 0; j < 200; j++) for ( int k = 0; k < 3; k++) pic . at ( i , j , k) = 0; To make the image black, we set all values to 0 Arrays of higher dimension are not very practical when passed as function arguments (a 3D array of unsigned char is not the same as unsigned char***), so it's wrapped in a struct Images are large objects, large images might not t on stack and it's better to have them dynamically allocated Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises A rectangle // pic i s as written on previous s l i d e for ( int i = 100; i < 200; i++) for ( int j = 66; j < 133; j++) pic . at ( i , j , 1) = 255; Drawing a rectangle is as simple as locating the pixels whose colour will be changed The colour will most likely be green, but it may depend on implementation Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises A line // pic i s as written on previous s l i d e auto l i n e = [&] ( int x1 , int x2 , int y1 , int y2 ) { int length = sqrt (( x2 − x1 ) ∗ ( x2 − x1 ) + ( y2 − y1 ) ∗ ( y2 − y1 ) ) ; f l o a t xIncr = ( x2 − x1 ) / length ; f l o a t yIncr = ( y2 − y1 ) / length ; for ( int i = 0; i <= length ; i++) pic . at ( x1 + xIncr ∗ i , y1 + yIncr ∗ i , 2) = 255; } This is not the most ecient algorithm, by the way Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises Fast square root f l o a t f s q r t ( f l o a t x ) { f l o a t xhalf = 0.5 f ∗ x ; int i = ∗( int ∗)&x ; i = 0x5f375a86 − ( i >> 1); x = ∗( f l o a t ∗)& i ; x = 1 / ( x ∗ (1.5 f − xhalf ∗ x ∗ x ) ) ; return x ; } This very fast algorithm computes the square root with a decent precision (better than 1%), the imprecision is not visible to nakedeye Don't ask why it works or how it works It was invented by Id Software for game Quake for normalising vectors (apparent colour of a surface is the light intensity multiplied by the surface's colour multiplied by the normalised dot product of the vector of incident light and normal of the surface) Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises Circle // pic i s as written on previous s l i d e auto c i r c l e = [&] ( int x , int y , int radius ) { for ( int i = 0; i < radius ; i++) { int width = f s q r t ( radius ∗ radius − i ∗ i ) ; for ( int j = −width ; j <= width ; j++) { pic . at ( i + x , j , 0) = 255; pic . at ( i − x , j , 0) = 255; } } } This algorithm uses the circle equation f (x) = √ r2 − x2 Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework How does it work? A black image A rectangle A line Fast square root Circle Exercises Exercises 1 Use the le available with these slides to create an image class that has methods for drawing of dots, lines, rectangles and circles 2 Add methods for drawing ellipses, arrows, empty circles and empty triangles 3 Challenge: Add a method to draw a lled triangle Advanced: 1 Use the le available with these slides to create a program that reads a le containing data in two columns, x and f (x) and draws a graph of the function into a picture Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Inheritance: Why? struct a { int val ; void increment () { val++; } }; struct b { int val ; int m u l t i p l i e r ; int operator ∗( int n) { return m u l t i p l i e r ∗ n ; } }; b∗ orig = new b ; a∗ changed = (a∗) orig ; If we convert b to a, nothing bad happens, the increment() method works as it should, the multiplier eld is not changed If b had some dynamically allocated stu, it would leak because its destructor would not be called Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Inheritance: Why? #2 struct a { int val ; }; struct b { f l o a t val ; }; struct c { int asA ; f l o a t asB ; }; c∗ orig = new c ; a∗ changed = (a∗) orig ; b∗ changed2 = (b∗)& orig . asB ; Now it gets even more impractical Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Inheritance struct a { int val ; void increment () { val++; } }; struct b : public a { int m u l t i p l i e r ; int operator ∗( int n) { return m u l t i p l i e r ∗ n ; } }; b∗ orig = new b ; a∗ changed = orig ; Inheritance is a way to expand a class to a new one that has added functionality In this case, a called parent class and b is called child class Conversion to parent class is done implicitly Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Inheritance #2 Inheritance is mostly public, but there is also private inheritance, that makes all parent classes' contents private Child classes can't access their parents classes' private methods and attributes (they are a dierent class), but can access their protected members (they are the same object) Friend methods and classes are not inherited Conversion from child class to parent class is not checked in any way and may cause problems if the new type is incorrect b∗ orig = new b ; a∗ changed = orig ; b∗ reconstructed = static_cast (changed ) ; Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Virtual methods struct a { int val ; void increment () { val++; } }; struct b : public a { void increment () { val += 2; } }; b orig ; a& changed = orig ; changed . increment ( ) ; In this case, the compiler calls a's method because the type it's looking through is a Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Virtual methods #2 struct a { int val ; v i r t u a l void increment () { val++; } }; struct b : public a { v i r t u a l void increment () { val += 2; } }; b orig ; a& changed = orig ; changed . increment ( ) ; In this case, the compiler calls b's method because it checks the underlying type in runtime and learns it's b Virtual function calls are inherently slower because they require additional checks and can't be inlined It allows us to create a child class from an existing class and use an existing function on it that will call our code Note: it's not necessary to declare the child's method as virtual, but it makes the code clearer Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Pure virtual methods struct a { int val ; v i r t u a l void increment () = 0; }; struct b : public a { v i r t u a l void increment () { val += 2; } }; In this case, class a does not even have a denition of the virtual method, so it's called pure virtual Class a is called abstract and cannot be created, only other types can be changed to it; it is only a way to use multiple classes by the same code Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Constructors and destructors struct a { int val ; a( int set ) : val ( set ) {} v i r t u a l ~a () { val = 0; } // destroy the evidence }; struct b : public a { int val2 ; b( int set1 , int set2 ) : a( set1 ) , val2 ( set2 ) {} v i r t u a l ~b () { val = 0; val2 = 0; } }; Child classes' constructors may call parent classes' constructors to construct the parent class (is mandatory if the parent class has no default constructor) We need to call the right destructor, so all destructors must be virtual if inheritance is used Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Why? Inheritance Virtual methods Pure virtual methods Constructors and destructors Exercises Exercises 1 Create a ball class that has its direction, speed and weight as attributes, a bigBall class that has all the properties of ball, but also size and aerial friction coecient 2 Write a program that calculates the path of thrown balls, acting dierently if the ball is small enough to neglect the aerial friction or not Advanced: 1 Create a particle class that has its direction, speed and size as attributes, an atom class that has all the properties of particle, but also mass and internal energy and a photon class that has all the properties of particle, but also wavelength 2 Write a program that simulates interaction of thousands of atoms and photons in a cube limited by mirror walls, making use of inheritance (neglect photon momentum, assume that atoms can absorb anything and will radiate it out into a random direction after some time) Ján Dugá£ek 7. Inheritance, 2D graphics 2D Graphics Inheritance Homework Homework Write a library for manipulating images; its main object is image, it can contain other images, squares, circles and lines, all at any position; squares, circles and lines also have colours besides their geometric properties; it must have a method to create an image of all the content on it (and save it) Use inheritance, I recommend using a class abstractShape (attributes position, scale,) that has subclasses shape and image, shape has further subclasses square, circle and line Advanced homework: Same as the regular one, but implement also a triangle class, add scaling to image and transparency to all You can also add functionality to delete all shapes whose container was deleted Ján Dugá£ek 7. Inheritance, 2D graphics