- September 11, 2020

ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 1 Fractal Generation: animating Julia sets Given two complex numbers, you will find the fractals associated with each of these values and the fractals associated with complex values on a path between the two numbers, producing a movie of chaos theory in action. NOTE: This is version 1 of the project document. If you find a typo please post it to the Piazza project typo thread. If any significant typos (beyond minor grammar and spelling errors) are found, a newer version of the project will be uploaded to Canvas, with those typos corrected. Project due date: You will need to upload your code before 11.59pm on Saturday the 19th of September. -0.79 + 0.15i -0.162 + 1.04i ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 2 Introduction This project requires you to write code that will allow you to create fractal images, which will then be combined to produce an animation. Fractals are remarkably beautiful geometric figures, where similar patterns recur as you zoom further and further in on parts of the figure. They occur in nature (e.g. ferns, snowflakes and coast lines) but can also be mathematically generated. Investigating fractals is part of a branch of mathematics known as chaos theory, where very complicated behaviour can be generated from surprisingly simple rules (and changing the starting value just a little can have a huge impact on what happens). The fractals we will be generating are known as Julia sets. They are named after the French mathematician Gaston Julia, who came up with the formula that generates the sets. Each complex number has a Julia set associated with it. As we will see, while generating a Julia set is relatively straight forward, the Julia sets associated with different complex numbers can look startlingly different. If we traverse a path from one complex number to another and generate a fractal for each step that we take along the path, the resulting sequence of images can be combined to produce an animation. You have been provided with a main script (AnimateJulia.m) and a few useful helper functions that take care of turning a sequence of images into animated gifs and mp4 files (MakeAnimatedGif.m and MakeMovie.m). In the pages that follow are detailed explanations of each of the eight functions that you need to write to fill in the gaps. On completion of the project you will have written code that allows you to generate Julia sets for a sequence of complex numbers and colour them with a colour map of your own creation (note that the cover image fractals were generated using Matlab’s built-in hot colormap called whereas the images below were created using custom colour maps. This document shows a few example calls for each function with, but it is expected that you will create your own test values to test your code (in many cases you can work out the answers on some very small sets of test data by hand, so that you know what you should expect as output). A few days prior to the submission date you will be supplied with some test data and test scripts which can be used to help check your code. If your code fails some of the supplied test code there is obviously work to be done. If your code passes the supplied test scripts it is a good sign you are on the right track, but please note that the supplied test code isn’t identical to that used to mark your code. If you rely just on the supplied test code (without doing tests of your own) you will run the very real risk of submitting code that will not pass all the marking tests. Do NOT rely solely on the supplied test scripts, part of doing the project is to learn how to extensively test your own code on a ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 3 range of different values (which is why the supplied test scripts are only released towards the end of the timeline). This project is designed to take the average student around 15 hours to code, but some people may find it takes upwards of 60 hours (and others will finish it in just a few hours). You will not know ahead of time how long it will take you, so please don’t leave it to the last minute to make a start! Remember the golden rule Write your own code and don’t give your code to anyone. Friends don’t let friends share code. This project needs to be YOUR work, it is an individual project, not a group project. Copying and/or sharing code is academic misconduct. Please note that every project submission is passed through software that detects plagiarism so if you copy you WILL be caught. Unfortunately, every year students discover the hard way that I’m not kidding. Let me repeat, DO NOT COPY: YOU WILL BE CAUGHT. If you give your code to another student and they copy it, you will both be guilty of misconduct. Copying or supplying code typically results in both the person who copied and the person who supplied the code being awarded a mark of zero for the project, as well as your names going on the academic misconduct register. If you have already been found guilty of academic misconduct on another course or assignment the penalty may be even greater (e.g. a fine or fail of the course). To help you avoid academic misconduct I have put together a very short best practices guide which you should read. It is attached as an appendix to this document. If you have any queries about what is or isn’t academic misconduct, please ask so that I can make sure everyone understands what is acceptable behaviour and what isn’t. How to tackle the project Do not be daunted by the length of this document. It is long because a lot of explanation is given as to exactly what each function needs to do. The best way to tackle a big programming task is to break it down into small manageable chunks. A lot of this work has already been done for you in the form of eight functions to write. Each function has a detailed description of what it needs to do and most of the functions can be written independently of each other. Have a read through the entire document and then pick a function to start on. Remember you don’t have to start with CreateComplexGrid, although it is one of the simplest functions. You may prefer to start with one of the other fairly straight forward functions such as IterateComplexQuadratic or CreateColourmap. Write as many of the functions as you can. When writing some of the specified functions you may find it useful to call one of the other functions you have written. You may even wish to write additional helper functions that have not been listed in the specifications. This is absolutely fine (in fact it is good coding practice to do so). Make sure you remember to submit any extra helper functions you write as they will be needed so that your code runs correctly. Please note that you will be able to submit up to 16 functions in total, which leaves room for up to 8 helper functions (which should be ample). Note that you do not need to submit any of the supplied code. Several functions require careful thought, particularly those that form the heart of creating the Julia sets (remember those 5 steps of problem solving!). If you are having trouble understanding how a function should work, remember to work through the problem by hand with a small data set. ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 4 Note that I don’t expect everyone to write all the functions. Some of them are relatively easy (e.g. CreateComplexGrid and IterateComplexQuadratic) while others are quite tricky (e.g. ReadColourValues). You can still get a pretty good mark even if you don’t complete all the functions. You will receive marks both for functionality (does your code work?), style (is it well written?) and execution time (how fast does it run?). An “A” grade student should be able to nut out everything except perhaps full marks for execution time (it can be extremely challenging to get things running quickly for larger images). B and C grade students might not get a fully working solution. Even if you only get three of the functions working, you can still get over 50% for the project, as long as the code you submit is well written (since you get marks for using good style). What Matlab functions do I need to know? The entire project can be completed using just the functions we have covered in the course manual, lectures and labs. What Matlab functions can I use? When writing your code, while you don’t need to use functions we haven’t covered in class, you may wish to do so. As well as being able to use any functions we have covered in class, you can also use any other functions that are part of Matlab’s core distribution (i.e. not functions from any toolboxes you may have installed). Note that for this project the use of functions that are only available in toolboxes is not permitted. Matlab features a large number of optional toolboxes that contain extra functions. The purpose of this project is for you to get practice at coding, not to simply call some toolbox functions that do all the hard work for you. A list of some of the core Matlab functions can be found in the Matlab command reference appendix on page 284 of the course manual. If you are uncertain whether a particular function is part of the Matlab’s core distribution or not, type the following at the command line which where the term is replaced by the name of the function you are interested in. Check the text displayed to see if the directory directly after the word toolbox is matlab (which means it is core) or something else (which means it is from a toolbox). For example: >> which median C:\Matlab\R2017b\Pro\toolbox\matlab\datafun\median.m This shows us that the median function is part of the standard core Matlab distribution (notice how the word matlab follows the word toolbox). You may use the median function if you wish to. >> which imadd C:\Matlab\R2017b\Pro\toolbox\images\images\imadd.m This shows us that the imadd function is part of the image processing toolbox and is therefore not permitted to be used for the project (notice how the word images follows the word toolbox). ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 5 1+2i An overview of creating Julia sets Before we delve into the detail of what functions you will be writing, let’s take a quick high-level outline of how Julia sets are created. Recall that complex numbers have a real and imaginary part, e.g. 1+2i, and can be represented graphically as points on a complex number plane (with the real part being shown on the x axis and the imaginary part on the y axis) A Julia set is associated with a particular complex number, c. For example, c = −0.79 + 0.15i was used to generate the fractal on the left-hand side of the cover page. For any point, z, in the complex plane we can determine if that point is within the Julia set by investigating its behaviour when repeatedly applying the complex quadratic polynomial formula: () = 2 + The result of applying the formula, (), is fed back in as the new z value and we repeat this over and over again. If repeated iterations of this formula (with a fixed c value) result in the sequence of f values staying within the bounds of a circular region around the origin, we say that the original z value is in the Julia set, and colour it accordingly (typically as black). A common choice of circular region is one with radius 2, but for this project we will use the region defined by the radius = 3 (I have chosen this particular radius because it means that all the points we will be working with in this project start out inside the region, which makes our code a little simpler). Note that a complex point is within a circular region of radius R if the magnitude of that point, ||, is less than R. The magnitude of z is often referred to as the complex modulus of z (or the absolute value of z). Suppose we want to investigate the point z = 1 + 2i when c = −0.79 + 0.15i We first find () = 2 + (1 + 2) = (1 + 2)2 + = (1 + 2)2 + (−0.79 + 0.15i) = −3.79 + 4.15i Checking the magnitude, |−3.79 + 4.15i| = 5.6202 > 3 so our point is NOT in the Julia set. Now let’s try a different point, eg. z = 0 + i We first find () = 2 + (0 + ) = (0 + )2 + = (0 + )2 + (−0.79 + 0.15i) = −1.79 + 0.15i Checking the magnitude, |−1.79 + 0.15| = 1.7963 < 3 so our point MIGHT be in the Julia set. We now repeat the process using the value from above, z = −1.79 + 0.15i, as our new z value. real imaginary 1 2i ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 6 (−1.79 + 0.15) = (−1.79 + 0.15)2 + = (−1.79 + 0.15)2 + (−0.79 + 0.15i) = 2.3916 − 0.3870i Checking the magnitude, |2.3916 − 0.3870i | = 2.4227 < 3 so our point still MIGHT be in the Julia set. We keep repeating the process using the value from above, always taking the result of the function and feeding it in as our new z value. If as we do this |()| always stays less than = 3 then the original value we started with is a member of the Julia set. If as we repeatedly iterate we ever find |()| ≥ then our original starting z value is NOT a member of the Julia set. Obviously when using a computer, we can’t iterate forever, so in practice we set a cutoff for the number of iterations to perform and if the value is still within the circular region when that cutoff is reached, we will deem the point a member of the Julia set associated with the complex value c. Also it should be obvious that it would be impractical to work on classifying the infinite number of points in the complex number plane, so instead we work on classifying a very small subset of points, equally spaced in a grid pattern over the complex plane. Performing this calculation for a whole grid of points and colouring pixels for each point on the grid gives us a fractal image. When colouring the pixels, we will use black for those points deemed to be in the set. For points not in the set, we will choose a shade of colour based on how many iterations it took for that point to move out of the circular region. Overview of Functions to Write There are eight in total: Function Difficulty Level Where used CreateComplexGrid Relatively straightforward, once you get your head around working with complex numbers in Matlab Called from the main script, likely to be a useful helper function when writing GenerateJuliaSets IterateComplexQuadratic Fairly easy, a good starting point Helper function, likely to be called from JuliaSetPoints JuliaSetPoints Medium in difficulty Called from the main script, likely to be a useful helper function when writing GenerateJuliaSets ColourJulia Fairly challenging Called from the main script, likely to be a useful helpful function when writing GenerateJuliaSets GenerateJuliaSets A little challenging but not too bad if you make use of some of the other functions as helper functions Called from the main script ReadColourValues Fairly challenging, one of the longer functions Called from the main script LookupColourValues A little challenging Called from the main script CreateColourmap Fairly straightforward, another good starting point Called from the main script ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 7 All functions except IterateComplexQuadratic are called directly from the supplied main script file named AnimateJulia.m. IterateComplexQuadratic is a great warm up function and is likely to be a useful helper function for when you when you write your JuliaSetPoints function. Even if you decide not to call your IterateComplexQuadratic function from your JuliaSetPoints function you should still write it, as it will be marked. You will need to implement CreateComplexGrid, JuliaSetPoints, ColourJulia and GenerateJuliaSets before being able to use the supplied script file to generate animated fractals. To use custom colour maps to colour your fractals you will also need to implement ReadColourValues, LookupColourValues and CreateColourmap. The pages following have detailed specifications of what each function should do. Note that while the functions are designed to work together with the supplied main script (to allow the creation of animated fractals in a colour map of your choice), many of the functions can be written and tested in isolation. Even if you get stuck on one function you should still try and write the others. Keep the following general principles in mind: • Note the capital letters used in function names. Case matters in Matlab and you should take care that your function names EXACTLY match those in the projection specification. E.g. if the function name is specified as CreateColourmap don’t use the name CreateColormap, createcolourmap, Create_Colourmap or CreateColourMap. • The order type and dimension of input arguments matters. Make sure you have the required number of inputs in the correct order. E.g. if a function requires 2 inputs, as ColourJulia does (where the first input is a 2D array of values for points in the Julia set and the second input is a 2D array containing a colour map) then the order matters (i.e. the first input should be the array of points not the colour map, to match the specifications). The number of inputs also matters (so don’t change a function that requires 2 inputs to require more inputs). • The order, type and dimensions of the outputs matter, e.g. ReadColourValues returns two outputs, the first of which is a cell array (where each element contains a colour name, stored as a string), then the second element is a 2D array of colour values (with each row containing the colour values for the named colour from the corresponding row of the first array). Muddling up the order or returning the wrong type of array would lose you all the marks for this function. • Matlab supports complex numbers and all the usual operations work as expected, as demonstrated by this short script: % demonstrate some basic complex arithmetic z1 = 3 + 4i z2 = 2 – 5i zAdd = z1 + z2 % add z1 and z2 together zSubtract = z2 – z1 % subtract z1 from z2 zMultiply = z1 * z2 % multiply z1 by z2 zDivide = z1/z2 % divide z1 by z2 zCubed = z1^3 % cube z1 % find the complex modulus (magnitude) of z1 zMagnitude = abs(z1) ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 8 imaginary 2+2i 2-2i -2-2i -2+2i The CreateComplexGrid function Purpose CreateComplexGrid creates a 2D array of size × which stores complex values drawn from a square grid of equally spaced points (from the complex plane) bounded by the lines x=-2, x=2 and y=2i, y=-2i i.e. the 4 corners of the grid are the points -2+2i (top left), 2+2i (top right), -2-2i (bottom left) and 2-2i (bottom right) Input(s) It takes one input, n, a positive integer specifying the number of rows and columns for the output array Output(s) It returns a single output, an × 2D array of equally spaced complex values representing a grid over the complex plane, where the 4 corners of the grid are the points -2+2i (top left), 2+2i (top right), -2-2i (bottom left) and 2-2i (bottom right) Example calls Here are some examples of calls to CreateComplexGrid >> grid2 = CreateComplexGrid(2) grid2 = -2.0000 + 2.0000i 2.0000 + 2.0000i -2.0000 – 2.0000i 2.0000 – 2.0000i >> grid3 = CreateComplexGrid(3) grid3 = -2.0000 + 2.0000i 0.0000 + 2.0000i 2.0000 + 2.0000i -2.0000 + 0.0000i 0.0000 + 0.0000i 2.0000 + 0.0000i -2.0000 – 2.0000i 0.0000 – 2.0000i 2.0000 – 2.0000i >> grid4 = CreateComplexGrid(4) grid4 = -2.0000 + 2.0000i -0.6667 + 2.0000i 0.6667 + 2.0000i 2.0000 + 2.0000i -2.0000 + 0.6667i -0.6667 + 0.6667i 0.6667 + 0.6667i 2.0000 + 0.6667i -2.0000 – 0.6667i -0.6667 – 0.6667i 0.6667 – 0.6667i 2.0000 – 0.6667i -2.0000 – 2.0000i -0.6667 – 2.0000i 0.6667 – 2.0000i 2.0000 – 2.0000i real Example of points in the grid created by the call CreateComplexGrid(3) ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 9 The IterateComplexQuadratic function Purpose IterateComplexQuadratic repeatedly applies the complex quadratic () = 2 + for a specified value of z and c (with z being replaced by f in the next iteration). This continues until the value of f is no longer within the bounded region (i.e. |()| ≥ 3) or the maximum number of iterations is reached (specified by the cutoff). If |()| ≥ 3 we return the number of iterations it took until this condition was met (indicating the initial z value is not in the Julia set associated with c) If the maximum number of iterations was reached and f is still within the bounded region (i.e. |()| < 3 ) we return 0 (indicating the initial z value is a member of the Julia set associated with c) Input(s) It takes three input(s) in the following order: 1. z, the initial complex value that we begin the iteration process with (this is the value to determine the nature of) 2. c, a specified complex value (used to generate a particular Julia set) 3. a cutoff value that determines the maximum number of iterations to perform (this will be a positive integer value) Output(s) It returns a single output, the number of iterations it took until |()| ≥ 3 or 0 if the maximum number of iterations was reached and |()| < 3 Consider a call to IterateComplexQuadratic(0,0.5+i,10) The initial value of z is = 0 and = 0.5 + i and we have a cutoff of 10 iterations (so will perform a maximum of 10 iterations) Keeping track of iterations in a table we have Iteration () || 1 (0) = (0)2 + (0.5 + ) = 0.5 + i |0.5 + i| = 1.118 < 3 2 (0.5 + ) = (0.5 + )2 + (0.5 + ) = −0.25 + 2 |−0.25 + 2| = 2.0156 < 3 3 (−0.25 + 2) = (−0.25 + 2)2 + (0.5 + )= −3.4375 |−3.4375| = . ≥ After three iterations |()| ≥ 3 and hence we return 3. Now consider a call to IterateComplexQuadratic(0,0.5+i,3) The initial value of z is = 0 and = 0.5 + i but now our cutoff has been reduced to 3. We would still perform the same three iterations as shown in the table above, and after performing these iterations, |()| ≥ 3 so we would return a value of 3. Now consider a call to IterateComplexQuadratic(0,0.5+i,2) The initial value of z is = 0 and = 0.5 + i but our cutoff has been reduced to 2. This would correspond to performing just the first two iterations shown in the table above. After two iterations we have |()| < 3 , so we would return 0. ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 10 Example calls Here are some examples of calls to IterateComplexQuadratic >> p=IterateComplexQuadratic(0,0.5+i,10) p = 3 >> p=IterateComplexQuadratic(0,0.5+i,3) p = 3 >> p=IterateComplexQuadratic(0,0.5+i,2) p = 0 >> p=IterateComplexQuadratic(2+2i,0.5+i,10) p = 1 >> p=IterateComplexQuadratic(1+i,-i,100) p = 0 >> p=IterateComplexQuadratic(1+i,-1-i,10) p = 2 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 11 The JuliaSetPoints function Purpose JuliaSetPoints determines whether or not each point in a grid of complex values is a member of the Julia set associated with a specified complex value c. If a point in the grid is still within the bounded region after the maximum number of iterations has been performed, it is deemed a member of the Julia set (and assigned a value of 0). If a point is not a member of the Julia set it will be assigned a value that corresponds to the number of complex quadratic iterations it took for that point to exit the bounded circular region. Note the 2D array that stores the grid of complex values could have any number of rows and columns (i.e. it does not have to be square). Input(s) It takes three input(s) in the following order: 1. a 2D array that stores the grid of complex values we will determine the nature of (i.e. whether or not they are points in the Julia set) 2. a specified complex value, c, (used to generate the particular Julia set) 3. a cutoff value that determines the maximum number of iterations to perform Output(s) It returns a single output, a 2D array describing the nature of each point on the grid. If a grid point is in the Julia set it will have a value of 0. If a grid point is not in the Julia set it will have a value that corresponds to the number of complex quadratic iterations it took to exit the bounded circular region (the maximum possible value of iterations will be determined by the cutoff used when generating the Julia set) Note that you will likely find it useful to use IterateComplexQuadratic as a helper function when writing JuliaSetPoints. Remember to write your code to handle any size 2D array (not just square arrays). This includes being able to handle row and column vectors. Example calls Here are some examples of calls to JuliaSetPoints >> row = [-1+i, i, 1+i] % note this is not a square array row = -1.0000 + 1.0000i 0.0000 + 1.0000i 1.0000 + 1.0000i >> points = JuliaSetPoints(row,0.5+0.5i,10) points = 3 6 2 >> points = JuliaSetPoints(row,0.5+0.5i,5) points = 3 0 2 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 12 >> grid2 = CreateComplexGrid(2) grid2 = -2.0000 + 2.0000i 2.0000 + 2.0000i -2.0000 – 2.0000i 2.0000 – 2.0000i >> points = JuliaSetPoints(grid2,1+i,10) points = 1 1 1 1 >> grid3 = CreateComplexGrid(3) grid3 = -2.0000 + 2.0000i 0.0000 + 2.0000i 2.0000 + 2.0000i -2.0000 + 0.0000i 0.0000 + 0.0000i 2.0000 + 0.0000i -2.0000 – 2.0000i 0.0000 – 2.0000i 2.0000 – 2.0000i >> points = JuliaSetPoints(grid3,-0.79+0.15i,10) points = 1 1 1 1 0 1 1 1 1 >> grid5 = CreateComplexGrid(5) grid5 = -2.0000 + 2.0000i -1.0000 + 2.0000i 0.0000 + 2.0000i 1.0000 + 2.0000i 2.0000 + 2.0000i -2.0000 + 1.0000i -1.0000 + 1.0000i 0.0000 + 1.0000i 1.0000 + 1.0000i 2.0000 + 1.0000i -2.0000 + 0.0000i -1.0000 + 0.0000i 0.0000 + 0.0000i 1.0000 + 0.0000i 2.0000 + 0.0000i -2.0000 – 1.0000i -1.0000 – 1.0000i 0.0000 – 1.0000i 1.0000 – 1.0000i 2.0000 – 1.0000i -2.0000 – 2.0000i -1.0000 – 2.0000i 0.0000 – 2.0000i 1.0000 – 2.0000i 2.0000 – 2.0000i >> points = JuliaSetPoints(grid5,-0.79+0.15i,100) points = 1 1 1 1 1 1 2 3 2 1 1 57 0 57 1 1 2 3 2 1 1 1 1 1 1 >> points = JuliaSetPoints(grid5,-0.79+0.15i,5) points = 1 1 1 1 1 1 2 3 2 1 1 0 0 0 1 1 2 3 2 1 1 1 1 1 1 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 13 The ColourJulia function Purpose ColourJulia colours the points in a Julia set black and the points outside of the set an appropriate shade of colour selected from a provided colour map1. All points within the Julia set are coloured black. If a grid point is not in the Julia set it will be coloured using the row from the colour map that corresponds to the value used to describe the nature of that point. Note the 2D array that describes the nature of each point could have any number of rows and columns (i.e. it does not have to be square). Input(s) It takes two input(s) in the following order: 1. a 2D array describing the nature of each point on a grid. If a grid point is in the Julia set, it will have a value of 0. If a grid point is not in the Julia set, it will have a positive integer value less than or equal to the cutoff used when generating the Julia set (this value corresponds to the number of complex quadratic iterations it took for that point to exit the bounded circular region) 2. a 2D array of size × 3 containing a colour map (the number of rows, r, in the colourmap must match the value of the cutoff used to generate the Julia set). The colour values in a row will be between 0 and 1 inclusive, representing the percentage of red, green and blue respectively, for the colour in that row. Output(s) It returns a single output, an RGB image of the Julia set. Points in the Julia set will be coloured as black. Points not in the set will be coloured using the provided colour map (where the value of the grid point corresponds to the row number of the colour to use from the map). The image is returned as a 3D array of uint8 values of size × × 3 (i.e. colour values will be unsigned integers between 0 and 255 inclusive) Note that when calculating uint8 colour values, any non-integer values will be rounded to the nearest integer using standard rounding rules (e.g. a red value of 100.5 will be rounded up to 101 whereas a red value of 100.4 would by rounded down to 100). Note that colour maps are arrays of doubles with values ranging between 0 and 1 inclusive. They are not arrays of unsigned 8 bit integers ranging between 0 and 255 inclusive. When using colour maps you will need to do some calculations to convert colour map colour values to equivalent uint8 RGB colour values. Each row in a colour map specifies a colour, with the values in a row representing the percentage or red, green and blue respectively. E.g. a red value of 0 indicates no red, a red value of 0.5 indicates 50% red and a red value of 1 would represent 100% red (this would be equivalent to uint8 values of 0, 128 and 255 respectively, if using unsigned 8 bit integers to store the amount of red for a pixel). 1 See the colormap documentation file for a full list of Matlab’s built in colormaps (note the US spelling of color): https://au.mathworks.com/help/matlab/ref/colormap.html ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 14 Example calls Here are some examples of calls to ColourJulia >> row = [-1+i, i, 1+i]; % note this is not a square array >> points = JuliaSetPoints(row,0.5+0.5i,10) points = 3 6 2 >> J = ColourJulia(points,jet(10)) % use jet colour map with 10 rows 1×3×3 uint8 array J(:,:,1) = 0 85 0 J(:,:,2) = 85 255 0 J(:,:,3) = 255 170 255 % script to generate a small 100 x 100 Julia set grid100 = CreateComplexGrid(100); points = JuliaSetPoints(grid100,-0.79+0.15i,10); % note cutoff of 10 J1 = ColourJulia(points,jet(10)); % use the jet colour map with 10 rows J2 = ColourJulia(points,hot(10)); % use the hot colour map with 10 rows figure(1) subplot(1,2,1) imshow(J1) % will produce the 100 x 100 pixel image below left subplot(1,2,2) imshow(J2) % will produce the 100 x 100 pixel image below right ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 15 >> grid5 = CreateComplexGrid(5); >> points = JuliaSetPoints(grid5,-0.79+0.15i,5) points = 1 1 1 1 1 1 2 3 2 1 1 0 0 0 1 1 2 3 2 1 1 1 1 1 1 >> J = ColourJulia(points,jet(5)) 5×5×3 uint8 array J(:,:,1) = 0 0 0 0 0 0 0 128 0 0 0 0 0 0 0 0 0 128 0 0 0 0 0 0 0 J(:,:,2) = 128 128 128 128 128 128 255 255 255 128 128 0 0 0 128 128 255 255 255 128 128 128 128 128 128 J(:,:,3) = 255 255 255 255 255 255 255 128 255 255 255 0 0 0 255 255 255 128 255 255 255 255 255 255 255 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 16 The GenerateJuliaSets function Purpose GenerateJuliaSets takes a sequence of complex values and generates the corresponding sequence of Julia set images. Input(s) It takes three input(s) in the following order: 1. a 1D array of complex values to generate Julia set fractals for 2. n, a value specifying the grid size to use (the grid will be × ) 3. a 2D array of size × 3 containing a colour map (the number of rows, r, in the colourmap will be used as the value for the cutoff when generating the Julia sets). The colour values in each row will be between 0 and 1 inclusive, representing the percentage of red, green and blue respectively, for the colour in that row. Output(s) It returns a single output, a cell array where each element contains an RGB image of a Julia set (as a 3D array of uint8 values of size × × 3) for the corresponding complex value from the complex values array, will all Julia sets coloured using the provided colour map. Note that we don’t need to pass in the cutoff value as an input to the function, as the cutoff value can be found by counting the number of rows in the 2D array that is passed in as the third input (the colourmap array). Example call Here is an example of a call to GenerateJuliaSets, using a jet colour map with 50 rows. % script to test GenerateJuliaSets, will produce images below cvalues = [-0.8 + 0.2i, -0.8 + 0i, 0 – 0.2i] % 1D array of complex values ImageArray = GenerateJuliaSets(cvalues,500,jet(50)); figure(1) subplot(1,3,1); imshow(ImageArray{1}) subplot(1,3,2); imshow(ImageArray{2}) subplot(1,3,3); imshow(ImageArray{3}) ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 17 The ReadColourValues function Purpose ReadColourValues reads in a list of colour names and their values from a specified text file, returning the colour names in a cell array and the colour values in a 2D array. If the text file cannot be opened, an error message will be displayed to the user saying Error opening file where is replaced by the name of the file. If the file could not be opened the output variables will not be assigned any values. Input(s) It takes a single input, a string containing the filename of a text file that stores a mapping of colour names to colour values. Each line of the text file will list the name of a colour followed by three colour values, all separated by spaces. The three values will be between 0 and 1 inclusive, representing the percentage or red, green and blue respectively for the colour on that line. Output(s) It returns two outputs in the following order: 1. a cell array of colour names, where each element of the cell array is a colour name stored as a string. This array should have r rows and 1 column where the number of rows corresponds to the number of colour names read from the file. 2. a 2D array of colour values of size × 3, where each row contains the three colour values read in from the file (for the colour in the corresponding row of the colour names array). The values in a row will be between 0 and 1 inclusive, representing the percentage of red, green and blue respectively. That is, the first column will be the amount of red, the second the amount of green and the third the amount of blue. Below is shown the contents of some sample text files, to demonstrate the format: BasicColours.txt RoyalColours.txt Monochrome.txt You may assume the text file is of the correct format and contains at least two colours. It could have many more colours. You may assume that colour names will use a single word. Colour values will range from 0 to 1 inclusive. Note that processing a line that includes both text and numerical values can be tricky. Think about what character separates the two parts and how you might go about splitting the two up, so that you have one substring containing a colour name and another substring containing the three values (which can then be easily scanned for the numerical values). Note that if you want to display an error message in red you can use the fprintf function to print the message to standard error (which has the file id 2). red 1 0 0 green 0 1 0 blue 0 0 1 yellow 1 1 0 magenta 1 0 1 cyan 0 1 1 black 0 0 0 white 1 1 1 navy 0 0 0.5 purple 0.5 0 0.5 silver 0.753 0.753 0.753 gold 1 0.843 0 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 18 Example calls Here are some examples of calls to ReadColourValues using the text files mentioned above >> [colours, values]=ReadColourValues(‘BasicColours.txt’) colours = 6×1 cell array {‘red’ } {‘green’ } {‘blue’ } {‘yellow’ } {‘magenta’} {‘cyan’ } values = 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 1 >> [colours, values]=ReadColourValues(‘RoyalColours.txt’) colours = 4×1 cell array {‘navy’ } {‘purple’} {‘silver’} {‘gold’ } values = 0 0 0.5000 0.5000 0 0.5000 0.7530 0.7530 0.7530 1.0000 0.8430 0 >> [colours, values]=ReadColourValues(‘RoyalColors.txt’) %mispelled filename Error opening file RoyalColors.txt Output argument “colourNames” (and maybe others) not assigned during call to “ReadColourValues”. ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 19 The LookupColourValues function Purpose LookupColourValues looks up the colour values for a named colour, from a list of provided colours and their values. It should ignore the case of the name. If the colour is not found an error message is displayed saying Colour not found and default colour values of 0 0 0 are returned. Input(s) It takes three inputs in the following order: 1. a string containing the name of a colour to look up 2. a cell array of colour names, where each element of the cell array is a colour name stored as a string. 3. a 2D array of colour values of size × 3, where each row contains the three colour values read in from the file (for the colour in the corresponding row of the colour names array). The values in a row will be between 0 and 1 inclusive, representing the percentage of red, green and blue respectively. Output(s) It returns a single output, a 1 × 3 element array of colour values for the colour to look up. The values in a row will be between 0 and 1 inclusive, where the first column will be the percentage of red, the second the percentage of green and the third the percentage of blue. Note that if you want to display an error message in red you can use the fprintf function to print the message to standard error (which has the file id 2). Remember that the case used for the name should not matter, e.g. if the colour gold is on the list then looking up values for the name Gold or even GOLD should still work. See the next page for example calls. ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 20 Example calls Here are some examples of calls to LookupColourValues using the colours from the sample text file RoyalColours.txt mentioned in the ReadColourValues section. >> [colours, values]=ReadColourValues(‘RoyalColours.txt’) colours = 4×1 cell array {‘navy’ } {‘purple’} {‘silver’} {‘gold’ } values = 0 0 0.5000 0.5000 0 0.5000 0.7530 0.7530 0.7530 1.0000 0.8430 0 >> NavyValues = LookupColourValues(‘navy’,colours,values) NavyValues = 0 0 0.5000 >> GoldValues = LookupColourValues(‘Gold’,colours,values) % note capital G GoldValues = 1.0000 0.8430 0 >> GreenValues = LookupColourValues(‘green’,colours,values) % no green on list Colour not found GreenValues = 0 0 0 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 21 The CreateColourmap function Purpose CreateColourmap creates a custom colour map, with n shades of colour that range from a specified starting colour through to a specified ending colour. Input(s) It takes three inputs in the following order: 1. a 1 × 3 element array of colour values for the starting colour for the map. The values in this row vector will be between 0 and 1 inclusive, representing the percentage or red, green and blue respectively. 2. a 1 × 3 element array of colour values for the ending colour for the map. The values in this row vector will be between 0 and 1 inclusive, representing the percentage or red, green and blue respectively. 3. n, the number of rows to generate for the colour map array Output(s) It returns a single output, a colour map in the form of an × 3 element array, where each row represents a colour. The values in a row will be between 0 and 1 inclusive, representing the percentage or red, green and blue respectively. The first column will contain the red values, which will be linearly spaced from the starting red value (in row 1) to the ending red value (in the final row) The second column will contain the green values, which will be linearly spaced from the starting green value (in row 1) to the ending green value (in the final row). The third column will contain the blue values, which will be linearly spaced from the starting blue value (in row 1) to the ending blue value (in the final row). Note that colour maps are arrays of doubles with values ranging between 0 and 1 inclusive. They are not arrays of unsigned 8 bit integers ranging between 0 and 255 inclusive. Each row in a colour map specifies a colour, with the values in a row representing the percentage or red, green and blue respectively. E.g. a red value of 0 indicates no red, a red value of 0.5 indicates 50% red and a red value of 1 would represent 100% red (this would be equivalent to uint8 values of 0, 128 and 255 respectively, if using unsigned 8 bit integers to store the amount of red for a pixel). Example calls Here are some examples of calls to CreateColourmap >> BlackToWhite = CreateColourmap([0 0 0],[1 1 1],5) BlackToWhite = 0 0 0 0.2500 0.2500 0.2500 0.5000 0.5000 0.5000 0.7500 0.7500 0.7500 1.0000 1.0000 1.0000 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 22 >> PurpleToGold = CreateColourmap([0.5 0 0.5],[1 0.843 0],5) PurpleToGold = 0.5000 0 0.5000 0.6250 0.2107 0.3750 0.7500 0.4215 0.2500 0.8750 0.6322 0.1250 1.0000 0.8430 0 >> RedToBlue = CreateColourmap([1 0 0],[0 0 1],10) RedToBlue = 1.0000 0 0 0.8889 0 0.1111 0.7778 0 0.2222 0.6667 0 0.3333 0.5556 0 0.4444 0.4444 0 0.5556 0.3333 0 0.6667 0.2222 0 0.7778 0.1111 0 0.8889 0 0 1.0000 ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 23 How the project is marked A mark schedule and some test scripts will be published prior to the due date, outlining exactly how marks will be allocated for each part of the project and giving you the opportunity to test your code. You will receive marks both for functionality (does your code work?), style (is it well written?) and execution time (how fast does it run?). There are 26 marks available for functionality (each function is marked out of 3, except ReadColourValues and LookupColourValues which are marked out of 4), 12 marks for style and 2 marks for execution time. Each of the eight required functions will be marked independently for functionality so even if you can’t get everything to work, please do submit the functions you have written. Some functions may be harder to write than others, so if you are having difficulty writing a function you might like to try working on a different function for a while and then come back to the harder one later. Note it is still possible to get marks for good style, even if your code does not work at all! Style includes elements such as using sensible variable names, having header comments, commenting the rest of your code, avoiding code repetition and using correct indentation. Each function can be written in less than 20 lines of code (not including comments) and some functions can be written using just a few lines but do not stress if your code is longer. It is perfectly fine if your project solution runs to several hundred lines of code, as long as your code works and uses good programming style. How the project is submitted Submission is done by uploading your code to the Aropa website. More information will be provided on how to submit the project to Aropa in a Canvas email announcement. You should be able to work on your project from anywhere assuming you have access to Matlab (either installed on a computer of running online) and can access the internet to upload your final submission. Submission Checklist Here is a list of the eight functions specified in this document. Remember to include all eight (or as many of them as you managed to write) in your project submission. The filenames should be EXACTLY the same as shown in this list (including case). They should also work EXACTLY as described in this document (pay close attention to the prescribed inputs and outputs and their order). In addition if your functions call any other “helper” functions that you may have written, remember to include them too (you can submit up to a total of 16 files, so may include up to 8 helper functions). The eight required functions are: • CreateComplexGrid • IterateComplexQuadratic • JuliaSetPoints • ColourJulia • GenerateJuliaSets • ReadColourValues • LookupColourValues • CreateColourmap ENGGEN131 2020 Matlab Project version 1 Due date: Saturday 19th September 11.59pm. 24 Any questions? If you have any questions regarding the project, please first check through this document. If it does not answer your question, then feel free to ask the question on the class Piazza forum. Remember that you should NOT be publicly posting any of your project code on Piazza, so if your question requires that you include some of your code, make sure that it is posted as a PRIVATE piazza query. Have fun! Enggen131 Good Practice Guidelines Acceptable % wholeNumberAverage function is responsible for checking whether or not % the average of the digits is a whole number % Inputs: s, an array of numbers representing a sequence to check % Outputs: b, zero if the array does NOT average to a whole number, % otherwise it returns the whole number average (which corresponds % to the number of balls required to juggle the pattern) function b = wholeNumberAverage(s) % calculate average av = mean(s); % check if the rounded average is equal to the original average roundedAv = round(av); if av > 0 && roundedAv == av b = av; else b = 0; end You used some of the project specification text in the header comments for your function A friend told you about the mean function, which can be used to find the average of an array. You looked up the matlab help on mean and decide to use it, then WROTE YOUR OWN CODE A group of you discussed ideas about how to check if a value is a whole number. As part of the group discussion, everyone figured out that if the original value is the same as the rounded value, then it must be a whole number. You then WROTE YOUR OWN CODE, using this idea. Acceptable % wholeNumberAverage function is responsible for checking whether or not % the average of the digits is a whole number % Inputs: s, an array of numbers representing a sequence to check % Outputs: b, zero if the array does NOT average to a whole number, % otherwise it returns the whole number average (which corresponds % to the number of balls required to juggle the pattern) function b = wholeNumberAverage(s) % check if the rounded average is equal to the original average % by seeing if the reminder after division by one is positive % algorithm retrieved from www.mycoolalgorithm.com/aGreatIdea if rem(s,1) > 0 b = mean(s); else b = 0; end You found an algorithm on the internet that described a method for checking for whole number values, by seeing if the remainder after division by one was a positive number. You credited the source of the algorithm and then WROTE YOUR OWN matlab code to implement it Unacceptable – DO NOT DO % checks whether a string consists of nonzero digits only % (i.e. the characters 1 to 9 inclusive) % Inputs: s, a string to check % Outputs: isValid, a Boolean variable, true if the string contains only % non zero digits and false otherwise function isValid = nonZeroDigitsOnly(s) isValid = true; i = 1; % loop through characters to see if they are within a valid ascii range while isValid==true && i <= length(s) if (s(i) < 49 || s(i) > 57) % if out of range, this sequence is invalid isValid = false; end i = i +1; end You didn’t know how to write an if statement that worked, so your friend came to your computer and typed out this line for you You were unsure what to write for the function header comments so took a photo of your neighbour’s work with your iphone and then typed in their comment lines later You were having trouble late at night with debugging your while loop. You asked your friend about it on msn and they sent through a few lines of their working code, so you used their while loop condition. Unacceptable – DO NOT DO % takes a string containing digits and coverts it to the corresponding % array of characters % Inputs: c, a string of characters containing only nonzero digits % Outputs: n, an array of numbers corresponding to the digits of the string function [n] = char2num(c) % convert to an array of numbers for i=1:length(c) n(i) = str2num(c(i)); end % generate carry path starting at height 0, going from an initial x position % to a final x position (specified in terms of cm from origin) % While this could be a straight line, it looks prettier if the ball dips % down below the y axis % % Inputs: 1) initial x co-ordinate (catch location) % 2) final x co-ordinate (throw location) % Outputs: 1) An array of x co-ordinates for the path through the hand % 2) An array of y co-ordinates for the path through the hand function [x,y]= generateParabolicPath(xinit,xfinal) x = linspace(xinit,xfinal,5); y = [0 -1 -2 -1 0]; You didn’t know how to write this function, so a friend emailed you their code, which you then copied. To make it look different you changed the wording of the comments and the variable names You couldn’t write this function by yourself so you and a friend worked on it together. After writing the entire thing together you each took a copy and put it into your project.