Assignment 1 – C Billiards Physics Library Version 1.03 (last update: Jan. 22, 12:00) Fixed a one-letter typo in Case 3: of phylib_bounce Changed the word position to velocity in in Case 5: of phylib_bounce Fixed x and y in the cut and paste text at top of p.10, vrel in phylib_bounce and rubrik. Changes highlighted in yellow Due date: Monday, Jan 29, 9:00 AM Summary and Purpose For this assignment, you will be writing a small C library that implements a number of functions to simulate the collision of billiard balls with cushions and other balls. Although the assignment will be entirely written in the (non-object-oriented/procedural) C programming language, the design and implementation of the code is object-oriented (including polymorphism) and you will gain a strong understanding of how object-oriented languages actually work (“under the hood”). Deliverables You will be submitting: 1) A file called phylib.h that contains your typedefs, structure definitions and function prototypes (see below). 2) A file called phylib.c that contains your function code. 3) A makefile that contains the instructions for the following targets: a. phylib.o – a position independent (-fpic) object code file created from phylib.c. b. libphylib.so – a shared library (-shared) created from phylib.o. c. clean – this target should delete all .o, .so and executable files. All files (input and output) must be in the same directory (sorry, but this makes grading much easier). All compilation must be done with the -std=c99 -Wall -pedantic options and the clang compiler, and produce no warnings or errors. The makefile must correctly identify all relevant dependencies and include them as prerequisites in its rules. You will submit all of your work via git to the School’s gitlab server. (As per instructions in the labs.) Under no condition will an assignment be accepted by any other means. This is an individual assignment. Any evidence of code sharing will be investigated and, if appropriate, adjudicated using the University’s Academic Integrity rules. Setting up your work environment and using git: Decide on your development environment. You can work on your own machine, the SoCS VM, no machine, the SoCS Docker container, or the SoCS ssh servers. However, you must test your code on the SoCS servers or SoCS VM or Docker as this is where it will be evaluated. If your code does not work properly on the SoCS systems, then it does not work. git clone https://gitlab.socs.uoguelph.ca/2750W24/skremer/A1 But, use your own login ID instead of skremer. Then, cd A1, to move to the assignment directory. Work in the A1 directory. Use the command: git add filename For each file that you create as part of your code (one .c file, one .h file, and the makefile). Every so often (especially if you get something working), use the command: git commit -a to commit your changes. Use the command: git tag -a Jan11a -m ’implemented the first two functions’ You will need to use a tag like “Jan11a” to request help with your code via the course help page. And then make sure to use: git push –-all –-follow-tags to push everything to the server with the tag included. If you want to make sure you know exactly what’s on the server you can rename the A1 directory to A1.day1 and then use git clone https://gitlab.socs.uoguelph.ca/2750W24/skremer/A1 to get a copy of exactly what is currently in the repo. You can use the same command to retrieve your code on a different machine or architecture. E.g. to move your code from your laptop development to the SoCS server for testing. PART I: For the first part of this assignment, you will implement a C library to support a number of objects in the game of billiards. Constants (subject to change, hahaha – include these in your .h file) #define PHYLIB_BALL_RADIUS #define PHYLIB_BALL_DIAMETER (28.5) // mm (2*PHYLIB_BALL_RADIUS) #define PHYLIB_HOLE_RADIUS #define PHYLIB_TABLE_LENGTH #define PHYLIB_TABLE_WIDTH (2*PHYLIB_BALL_DIAMETER) (2700.0) // mm (PHYLIB_TABLE_LENGTH/2.0) // mm #define PHYLIB_SIM_RATE #define PHYLIB_VEL_EPSILON (0.0001) // s (0.01) // mm/s #define PHYLIB_DRAG #define PHYLIB_MAX_TIME (150.0) // mm/s^2 (600) // s #define PHYLIB_MAX_OBJECTS (26) Polymorphic object types defined as enum (include this in your .h file) typedef enum { PHYLIB_STILL_BALL PHYLIB_ROLLING_BALL PHYLIB_HOLE PHYLIB_HCUSHION PHYLIB_VCUSHION } phylib_obj; = = = = = 0, 1, 2, 3, 4, enums are like grouped constants. Class representing a vector in 2 dimensions (include this in your .h file) typedef struct { double x; double y; } phylib_coord; (Child) Classes representing objects on the table (include these in your .h file) First, a ball that is not in motion (i.e. still). It has a number (cue ball is 0) and a position on the table. typedef struct { unsigned char number; phylib_coord pos; } phylib_still_ball; Next, a ball that is rolling (i.e. not still). It has a number (cue ball is 0) and a position on the table. It also has a velocity and a (negative) acceleration (due to friction). typedef struct { unsigned char number; phylib_coord pos; phylib_coord vel; phylib_coord acc; } phylib_rolling_ball; Next, one of the 6 holes on the table. It has a position. typedef struct { phylib_coord pos; } phylib_hole; Next, a horizontal cushion (i.e. a cushion along either of the two the short sides of the table). It has only a y-coordinate. typedef struct { double y; } phylib_hcushion; Rather predictably, a vertical cushion (i.e. a cushion along either of the two the long sides of the table). It has only an x-coordinate. typedef struct { double x; } phylib_vcushion; Polymorphic Parent Class of objects on the table (include these in your .h file) First, we need a C union that can store any of the above classes/structure in the same space. typedef union { phylib_still_ball still_ball; phylib_rolling_ball rolling_ball; phylib_hole hole; phylib_hcushion hcushion; phylib_vcushion vcushion; } phylib_untyped; While this union can store an object of any of the above classes/structures, it cannot identify what the class of the object is, so we need another structure for that. typedef struct { phylib_obj type; phylib_untyped obj; } phylib_object; Here, the type is the enum indicating the class of the object, and obj is the object itself. We can now use phylib_object to represent a generic object in the billiards world. Finally, the table (include this in your .h file) typedef struct { double time; phylib_object *object[PHYLIB_MAX_OBJECTS]; } phylib_table; As the game proceeds there will be multiple table configurations at different points in time, so each table “knows” its time. There can be a maximum of 26 objects on the table: 15 numbered balls, 1 cue ball, 4 cushions, and 6 holes. Function prototypes for constructor methods and descriptions for your assignment phylib_object *phylib_new_still_ball( unsigned char number, phylib_coord *pos ); This function will allocate memory for a new phylib_object, set its type to PHYLIB_STILL_BALL and transfer the information provided in the function parameters into the structure. It will return a pointer to the phylib_object. If the malloc function fails, it will return NULL (before trying to store the function parameters in the (non-existent) structure). phylib_object *phylib_new_rolling_ball( unsigned char number, phylib_coord *pos, phylib_coord *vel, phylib_coord *acc ); phylib_object *phylib_new_hole( phylib_coord *pos ); phylib_object *phylib_new_hcushion( double y ); phylib_object *phylib_new_vcushion( double x ); These functions will do the same thing as the phylib_new_still_ball function for their respective structures. phylib_table *phylib_new_table( void ); This function will allocate memory for a table structure, returning NULL if the memory allocation fails. The member variable, time, will be set to 0.0. It will then assign the values of its array elements to pointers to new objects created by the phylib_new_* functions provided above. Specifically, it will add elements in this order: 1) a horizontal cushion at y=0.0; 2) 3) 4) 5) a horizontal cushion at y=PHYLIB_TABLE_LENGTH; a vertical cushion at x=0.0; a vertical cushion at x=PHYLIB_TABLE_WIDTH; 6 holes: positioned in the four corners where the cushions meet and two more midway between the top holes and bottom holes. The remaining pointers will all be set to NULL. PART II: Create utility functions as follows: void phylib_copy_object( phylib_object **dest, phylib_object **src ); This function should allocate new memory for a phylib_object. Save the address of that object at the location pointed to by dest, and copy over the contents of the object from the location pointed to by src. Hint, you can use memcpy to make this a one-step operation that works for any type of phylib_object. If src points to a location containing a NULL pointer, then the location pointed to by dest should be assigned the value of NULL. phylib_table *phylib_copy_table( phylib_table *table ) This function should allocate memory for a new phylib_table, returning NULL if the malloc fails. Then the contents pointed to by table should be copied to the new memory location and the address returned. void phylib_add_object( phylib_table *table, phylib_object *object ); This function should iterate over the object array in the table until it finds a NULL pointer. It should then assign that pointer to be equal to the address of object. If there are no NULL pointers in the array, the function should do nothing. void phylib_free_table( phylib_table *table ); This function should free every non-NULL pointer in the object array of table. It should then also free table as well. phylib_coord phylib_sub( phylib_coord c1, phylib_coord c2 ); This function should return the difference between c1 and c2. That is the result’s x value should be c1.x-c2.x and similarly for y. double phylib_length( phylib_coord c ); This function should return the length of the vector/coordinate c. You can calculate this length by using Pythagorean theorem. Important, you must not use the exp function from the math library. That function is designed for raising values to a real power and is extremely inefficient for something as simple as squaring a value. double phylib_dot_product( phylib_coord a, phylib_coord b ); This function should compute the dot-product between two vectors. Hint: the dot product is equal to the sum of: the product of the x-values and the product of the y-values. double phylib_distance( phylib_object *obj1, phylib_object *obj2 ); This function should calculate the distance between two objects, obj1 and obj2. obj1 must be a PHYLIB_ROLLING_BALL; if it is not the function should return -1.0. Otherwise ,the distance between the obj1 (PHYLIB_ROLLING_BALL) and obj2 is given by the following rules: 1) If obj2 is another BALL (ROLLING or STILL), then compute the distance between the centres of the two balls and subtract two radii (i.e. one PHYLIB_BALL_DIAMETER). k clic r r 2) If obj2 is a HOLE, then compute the distance between the centre of the ball and the hole and subtract the HOLE_RADIUS. r p plo … h oos Wh 3) If obj2 is a CUSHION calculate the distance between the centre of the ball and the CUSION and subtract the BALL_RADIUS. Hint: use abs since the ball might be left/above or right/below to CUSHION. p tho r Return -1.0 if obj2 isn’t any valid type. PART III: These functions simulate the balls moving on the table. void phylib_roll( phylib_object *new, phylib_object *old, double time ); This function updates a new phylib_object that represents the old phylib_object after it has rolled for a period of time. If new and old are not PHYLIB_ROLLING_BALLs, then the function should do nothing. Otherwise, it should update the values in new. Specifically the position, and velocities should be updated as follows: <latexit sha1_base64="obo5vhggsAul+4RSOioeDPg/Sa4=">AAACDnicbVDLSgMxFM1UrbW+Rl3qIlgKglBmWtvahVBw47KCfUA7lkyaaUMzD5JMoQzzBW7c+CFuXCji1rU7v0L8A9MHvi8k93DOvSTn2AGjQhrGq5ZYWFxKLqdW0qtr6xub+tZ2Q/ghx6SOfebzlo0EYdQjdUklI62AE+TajDTt4elEb44IF9T3LuQ4IJaL+h51KEZSUV09G8ATGHRNeAhH6paqdxyOcGTGUT6GaMJd5rt6xsgZ04J/gTkHmWpyL1d4e7+pdfWXTs/HoUs8iRkSom0agbQixCXFjMTpTihIgPAQ9UlbQQ+5RFjR1E4Ms4rpQcfn6ngSTtnvGxFyhRi7tpp0kRyI39qE/E9rh9I5tiLqBaEkHp495IQMSh9OsoE9ygmWbKwAwpyqv0I8QCoNqRJMT0MolMqFYl55rxwZldKX90/QyOfMUq54rtLQwaxSYBfsgwNggjKogjNQA3WAwRW4BffgQbvW7rRH7Wk2mtDmOzvgR2nPH2wmnDo=</latexit> 1 p = p1 + v 1 t + a 1 t2 2 (For physics/math fans, this is the second integral of the acceleration.) Here, the variable p represents either the x or y position of the ball, the variable v represents either the x or y velocity of the ball, and a represents either the x or y acceleration of the ball. The subscript 1 indicates we are talking about the old ball. The velocity of the new ball (in either the x or y dimension) is given by: <latexit sha1_base64="+DAZjZX2jaM3tzNJhRMGwr9d7J4=">AAAB6HicbVC7TgJBFJ3FF+Jr1dJmIjGxIrsgIBUkNpaQyCOBDZkdBhiZnd3MzJqQDbWFjYXG2Fj4J/4CnZ/gL1g5LMT3SW5ycs69ufdcN2BUKst6NRJLyyura8n11Mbm1vaOubvXkH4oMKljn/mi5SJJGOWkrqhipBUIgjyXkaY7Opv5zSsiJPX5hRoHxPHQgNM+xUhpqRZ0zbSVsWLAv8RekHT57br8/jJ9qnbNaafn49AjXGGGpGzbVqCcCAlFMSOTVCeUJEB4hAakrSlHHpFOFB86gUda6cG+L3RxBWP1+0SEPCnHnqs7PaSG8rc3E//z2qHqnzoR5UGoCMfzRf2QQeXDWWrYo4JgxcaaICyovhXiIRIIK/2bVPyEXKGYy2d19tKJVSp8Zf8kjWzGLmTyNStdMcEcSXAADsExsEERVMA5qII6wICAG3AH7o1L49Z4MB7nrQljMbMPfsB4/gC/AJIV</latexit> <latexit sha1_base64="XEs6xvKin4Dzcrh9y2+BvI2b4E4=">AAAB6HicbVDJTgJBEO3BDXEbl5uXjsTEE5kBATlJ4kGPkMiSwIT0ND3Q0tMz6e4hwQlf4MUDxnj1A/wYbx79E5sl7i+p5OW9qlS9ckNGpbKsNyOxtLyyupZcT21sbm3vmLt7dRlEApMaDlggmi6ShFFOaooqRpqhIMh3GWm4g4up3xgSIWnAr9UoJI6Pepx6FCOlpeqwY6atjDUD/EvsBUmfT27fL18O4krHfG13Axz5hCvMkJQt2wqVEyOhKGZknGpHkoQID1CPtDTlyCfSiWeHjuGxVrrQC4QuruBM/T4RI1/Kke/qTh+pvvztTcX/vFakvDMnpjyMFOF4vsiLGFQBnKaGXSoIVmykCcKC6lsh7iOBsNK/Sc2ekCsUc/mszl46tUqFr+yfpJ7N2IVMvmqlyyaYIwkOwRE4ATYogjK4AhVQAxgQcAcm4MG4Me6NR+Np3powFjP74AeM5w/nE5C0</latexit> <latexit sha1_base64="MSS4kjJOa7zV18TL1N9DY5FPmkw=">AAAB6HicbVDLTsJAFJ3iC/FVHzs3E4mJK9KCgKwkcaFLSOSRQEOmwxRGptNmZmqCDV/gxgXGuPUD/Bh3Lv0Th2J8n+QmJ+fcm3vPdUNGpbKsVyO1sLi0vJJezaytb2xumds7TRlEApMGDlgg2i6ShFFOGooqRtqhIMh3GWm5o7OZ37omQtKAX6pxSBwfDTj1KEZKS3XUM7NWzkoA/xL7g2RPpzdv5897ca1nvnT7AY58whVmSMqObYXKiZFQFDMyyXQjSUKER2hAOppy5BPpxMmhE3iolT70AqGLK5io3ydi5Es59l3d6SM1lL+9mfif14mUd+LElIeRIhzPF3kRgyqAs9SwTwXBio01QVhQfSvEQyQQVvo3meQJhVK5UMzr7JVjq1L6yv5JmvmcXcoV61a2aoI50mAfHIAjYIMyqIILUAMNgAEBt2AK7o0r4854MB7nrSnjY2YX/IDx9A7HP5Cf</latexit> <latexit sha1_base64="Cnaw/6/m7ezibdm/gSRTC1ywy2M=">AAAB+HicbVDLSgMxFM3UV62Pjrp0EyyCIJSZPu1CKLhxWcE+oB2GTJppQzOZIckU6tAvceNCEbd+ijv/xrQdfB9IOJxzL/fe40WMSmVZ70ZmbX1jcyu7ndvZ3dvPmweHHRnGApM2Dlkoeh6ShFFO2ooqRnqRICjwGOl6k6uF350SIWnIb9UsIk6ARpz6FCOlJdfMT+ElnLo2PIdI/8o1C1bRWgL+JXZKCiBFyzXfBsMQxwHhCjMkZd+2IuUkSCiKGZnnBrEkEcITNCJ9TTkKiHSS5eJzeKqVIfRDoR9XcKl+70hQIOUs8HRlgNRY/vYW4n9eP1b+hZNQHsWKcLwa5McMqhAuUoBDKghWbKYJwoLqXSEeI4Gw0lnlliGUa/VytaRvb1SsRu3r9k/SKRXtWrF6Uyk0zTSOLDgGJ+AM2KAOmuAatEAbYBCDe/AInow748F4Nl5WpRkj7TkCP2C8fgDBqZE2</latexit> v = v1 + a1 t One additional constraint must be observed. If either velocity changes sign, then that velocity and its corresponding acceleration (x, or y) must be set to zero (if both velocities change sign, then both velocities and both accelerations must be set to zero). unsigned char phylib_stopped( phylib_object *object ); This function will check whether a ROLLING_BALL has stopped, and if it has, will convert it to a STILL_BALL. You may assume that object is a ROLLING_BALL. The function will return 1 if it converts the ball, 0 if it does not. For the purposes of this simulation a ball is considered to have stopped if its speed (which is the length of its velocity) is less than PHYLIB_VEL_EPSILON. Do not assume that the number, and x and y positions of the rolling ball will be automatically transferred to the still ball. void phylib_bounce( phylib_object **a, phylib_object **b ); This is the most complicated function in the assignment but it can be handled by divide and conquer based on the type of object b. You may assume that object a is a ROLLING_BALL. Note that the two arguments to this function are double pointers. That is, they are pointers to pointers to phylib_objectss. CASE 1: b is a HCUSHION: In this case the y velocity and y acceleration of a are reversed (negated). This is the physical principle of angle of incidence equals angle of reflection. CASE 2: b is a VCUSION: In this case the x velocity and x acceleration of a are reversed (negated). This is the physical principle of angle of incidence equals angle of reflection. CASE 3: b is a HOLE: In this case, free the memory of a and set it to NULL. This represents the ball falling off the table. CASE 4: b is a STILL_BALL: In this case, “upgrade” the STILL_BALL to a ROLLING BALL and proceed directly to CASE 5 (do not collect $200). HINT: if you leave out the break statement at the end of a case condition, the code will continue with the next case. CASE 5: b is a ROLLING_BALL: This one is a little bit tricky and will require us to calculate a few intermediate values before we can know the speeds and directions of the two balls after they collide. Compute the position of a with respect to b: subtract the position of b from a; call it r_ab. Compute the relative velocity of a with respect to b: subtract the velocity of b from a; call it v_rel. Divide the x and y components of r_ab by the length of r_ab; call that a normal vector, n. Calculate the ratio of the relative velocity, v_rel, in the direction of ball a by computing the dot_product of v_rel with respect to n; call that v_rel_n. Now, ball a will roll perpendicular to the direction from a to b, and b will run in the direction from a to b. Update the x velocity of ball a by subtracting v_rel_n multipied by the x component of vector n. Similarly, Update the y velocity of ball a by subtracting v_rel_n multipied by the y component of vector n. Update the x and y velocities of ball b by adding the product of v_rel_n and vector n. Compute the speed of a and b as the lengths of their velocities. If the speed is greater than PHYLIB_VEL_EPSILON then set the acceleration of the ball to the negative velocity divided by the speed multiplied by PHYLIB_DRAG. If you are curious about the physics: Let's consider the scenario where ball A and ball B collide and then move apart. We'll assume that the collision is perfectly elastic, meaning both momentum and kinetic energy are conserved. The initial conditions are as follows: - Initial velocity of ball A: vA = (vAx , vAy ) - Initial velocity of ball B: vB = (vBx , vBy ) - A vector pointing from the centre of A to the centre of B at the instant of collision: rAB = rA rB <latexit sha1_base64="L9YGKFsrZXgwrh3ICHzRfF9TBFQ=">AAACDXicbVDLSgMxFM34rPU16tJNsAotSJm2trULocWNywr2AZ0yZNKMDc08SDLFMswPuPFX3LhQxK17d/6Nmbb4PhByOOde7r3HDhgV0jDetYXFpeWV1dRaen1jc2tb39ltCz/kmLSwz3zetZEgjHqkJalkpBtwglybkY49Ok/8zphwQX3vSk4C0nfRtUcdipFUkqUfmlnTRXJoO9E4thrwDGbHVtS4iY9h8k/inJmDlp4x8sYU8C8pzEkGzNG09Ddz4OPQJZ7EDAnRKxiB7EeIS4oZidNmKEiA8Ahdk56iHnKJ6EfTa2J4pJQBdHyunifhVP3eESFXiIlrq8pkc/HbS8T/vF4ondN+RL0glMTDs0FOyKD0YRINHFBOsGQTRRDmVO0K8RBxhKUKMD0NoVSplspFdXvtxKhVvm7/JO1ivlDJly+Lmbo+jyMF9sEByIICqII6uABN0AIY3IJ78AietDvtQXvWXmalC9q8Zw/8gPb6ARcKmkk=</latexit> <latexit sha1_base64="hr37zP7I+VnorAysw+6nl0xNees=">AAACDXicbVDLSgMxFM34rPU16tJNsAotSJm2trULodSNywr2AZ0yZNKMDc08SDLFMswPuPFX3LhQxK17d/6Nmbb4PhByOOde7r3HDhgV0jDetYXFpeWV1dRaen1jc2tb39ltCz/kmLSwz3zetZEgjHqkJalkpBtwglybkY49Ok/8zphwQX3vSk4C0nfRtUcdipFUkqUfQjNrukgObScax1YDnsHs2IoaN/ExTP5JnDNzlp4x8sYU8C8pzEkGzNG09Ddz4OPQJZ7EDAnRKxiB7EeIS4oZidNmKEiA8Ahdk56iHnKJ6EfTa2J4pJQBdHyunifhVP3eESFXiIlrq8pkcfHbS8T/vF4ondN+RL0glMTDs0FOyKD0YRINHFBOsGQTRRDmVO0K8RBxhKUKMD0NoVSplspFdXvtxKhVvm7/JO1ivlDJly+Lmbo+jyMF9sEByIICqII6uABN0AIY3IJ78AietDvtQXvWXmalC9q8Zw/8gPb6ARQRmkw=</latexit> <latexit sha1_base64="izoO2K3kUIS4KPI3Pil5R9kt6zY=">AAACG3icbVDLSgMxFM34rPU16tJNsAh1YZlObWsXQls3LivYB3SGkkkzbWjmQZIRyjD/4cZfceNCEVeCC//G9IHWx4HAyTn3cu89TsiokIbxoS0tr6yurac20ptb2zu7+t5+SwQRx6SJAxbwjoMEYdQnTUklI52QE+Q5jLSd0eXEb98SLmjg38hxSGwPDXzqUoykknq6aWUtD8mh48Y86cW1egIv4IJSg6eL37p1ku7pGSNnTAH/kvycZMAcjZ7+ZvUDHHnEl5ghIbp5I5R2jLikmJEkbUWChAiP0IB0FfWRR4QdT29L4LFS+tANuHq+hFN1sSNGnhBjz1GVkzXFb28i/ud1I+me2zH1w0gSH88GuRGDMoCToGCfcoIlGyuCMKdqV4iHiCMsVZyzEAqlcqFoqtsrZ0al9H37F2mZuXwpV7w2M1V9HkcKHIIjkAV5UAZVcAUaoAkwuAMP4Ak8a/fao/aivc5Kl7R5zwH4Ae39E3fnoGk=</latexit> After the collision, the final velocities of the two balls can be calculated as follows: 1. Calculate the relative velocity of A with respect to B just before the collision: vrel = vA vB 2. Calculate the unit vector ( n̂ ) pointing from the center of B to the center of A: n̂ = krrAB AB k <latexit sha1_base64="I5zYsBfpD0tvINxRvU6fpP/VU/Q=">AAACJnicbVDJSgNBEO1xN26jHr00BiEeDJPERD0ILhePCkYDmRB6OjXa2LPQXSOGYb7Gi7/ixYMi4s1PsbOgcXnQ8Pq9KqrqebEUGh3n3Robn5icmp6Zzc3NLywu2csrFzpKFIc6j2SkGh7TIEUIdRQooRErYIEn4dK7Oe75l7egtIjCc+zG0ArYVSh8wRkaqW3vU0rdghswvPb89DZrpy7CHaYKZJbRfTriHNKt0e+Ru5lr23mn6PRB/5LSkOTJEKdt+9ntRDwJIEQumdbNkhNjK2UKBZeQ5dxEQ8z4DbuCpqEhC0C30v6ZGd0wSof6kTIvRNpXRztSFmjdDTxT2VtT//Z64n9eM0F/t5WKME4QQj4Y5CeSYkR7mdGOUMBRdg1hXAmzK+XXTDGOJtlBCJXaTqVaNrfvbTt7te/bv8hFuViqFatn5fyBPYxjhqyRdVIgJbJDDsgJOSV1wsk9eSTP5MV6sJ6sV+ttUDpmDXtWyQ9YH59me6Uc</latexit> <latexit sha1_base64="PYJrTuW5XmXne4VJNLVp995edqk=">AAAB+XicbVDLSsNAFJ3UV62v+Ni5CRbBVUlb29qVBRe6rGAf0IQymU7aoZNJmJkUashfuHTjQhEXbvwTdy79Eydp8X1g4HDOvcy5xwkoEdI037TMwuLS8kp2Nbe2vrG5pW/vtIUfcoRbyKc+7zpQYEoYbkkiKe4GHEPPobjjjM8SvzPBXBCfXclpgG0PDhlxCYJSSX1dt0ZQRpYH5chxIxbHfT1vFswUxl9SnJP86c31+/nzXtTs66/WwEehh5lEFArRK5qBtCPIJUEUxzkrFDiAaAyHuKcogx4WdpQmj41DpQwM1+fqMWmk6veNCHpCTD1HTSYRxW8vEf/zeqF0T+yIsCCUmKHZR25IDekbSQ3GgHCMJJ0qAhEnKquBRpBDJFVZubSEcrVWrpTU7fVjs179uv2TtEuFYrVQuTTzDR3MkAX74AAcgSKogQa4AE3QAghMwC24Bw9apN1pj9rTbDSjzXd2wQ9oLx9Kq5fK</latexit> <latexit sha1_base64="xnulxj8ACJJPD2A58B/GfJhT/J8=">AAACK3icbVDLTgIxFO34RHyNunTTSEx0QwYQkIWJj41LTERMKCGd0pGGTmfSdkzIMP/jxl9xoQsfcet/2AHiAz1Jk5Nz7k3vOW7ImdKO82rNzM7NLyxmlrLLK6tr6/bG5pUKIklogwQ8kNcuVpQzQRuaaU6vQ0mx73LadPtnqd+8pVKxQFzqQUjbPr4RzGMEayN17FO0h3pYx8jHuud6sUgSeASRJzH50mTSiU9OkyRGwykJDRO037FzTt4ZAf4lhQnJgQnqHfsRdQMS+VRowrFSrYIT6naMpWaE0ySLIkVDTPr4hrYMFdinqh2PsiZw1yhd6AXSPKHhSP25EWNfqYHvmsn0VjXtpeJ/XivS3mE7ZiKMNBVk/JEXcagDmBYHu0xSovnAEEwkM7dC0sOmJ23qzY5KKFWqpXLRZK8dOLXKd/YvclXMFyr58kUxd2xP6siAbbAD9kABVMExOAd10AAE3IEH8AxerHvryXqz3sejM9ZkZwv8gvXxCeE+qVA=</latexit> 3. Calculate the relative velocity of A with respect to B along the line of impact ( vreln ): vreln = vrel · n̂ <latexit sha1_base64="0wJWYMNAgqUBh4MlApGfRF/KxKo=">AAAB+XicbVBNS8NAEN34WavWqEcvwSJ4Kmlrq54sePGoYFVoS9hsp+3azSbsTool9J948aCIV/+GJ2/+C/+A4DYVvx8MPN6bYWaeHwmu0XVfrKnpmdm5+cxCdnFpObdir66d6TBWDOosFKG68KkGwSXUkaOAi0gBDXwB537/cOyfD0BpHspTHEbQCmhX8g5nFI3k2fbAS5oIV5goECNPjjw77xbcFM5fUvwg+YPXkyc7d/l27NnPzXbI4gAkMkG1bhTdCFsJVciZgFG2GWuIKOvTLjQMlTQA3UrSy0fOllHaTidUpiQ6qfp9IqGB1sPAN50BxZ7+7Y3F/7xGjJ29VsJlFCNINlnUiYWDoTOOwWlzBQzF0BDKFDe3OqxHFWVowsqmIZSru+VKyfy+v+PuV79+/yRnpUKxWqicuPmaTSbIkA2ySbZJkeySGjkix6ROGBmQa3JL7qzEurHurYdJ65T1MbNOfsB6fAfAYZga</latexit> <latexit sha1_base64="Q1tS2XF4dAujo5HgusKKRtvmD9c=">AAACMXicbVDLSsNAFJ34tr6iLt0MFkE3Ja1adSEIblwqWBWaEibTGzs4mYSZm2IJ+SU3/om4caGIW3/Caa1vDwwczrmXueeEqRQGPe/BGRkdG5+YnJouzczOzS+4i0tnJsk0hwZPZKIvQmZACgUNFCjhItXA4lDCeXh12PfPu6CNSNQp9lJoxexSiUhwhlYK3CNKqb/eDXIf4RpzDbIIVEH3qR8z7IRR3i2+ewX1eTtB6ncY5h8jqij8jcAtexVvAPqXVIekTIY4Dtw7v53wLAaFXDJjmlUvxVbONAouoSj5mYGU8St2CU1LFYvBtPJB4oKuWaVNo0Tbp5AO1O8bOYuN6cWhnewfaX57ffE/r5lhtNvKhUozBMXfP4oySTGh/fpoW2jgKHuWMK6FvZXyDtOMoy25NChhs76zuV2z2fe2vL36V/ZPclarVOuV7ZNa+cAd1jFFVsgqWSdVskMOyBE5Jg3CyQ25J4/kybl1Hpxn5+V9dMQZ7iyTH3Be3wD5MKtb</latexit> <latexit sha1_base64="V+XXnGfy2uj9my38sUrSHeAuiIc=">AAACBXicbVDLTgIxFO34RHyNutRFIzGBDRlAQHaoG5eYyCNhCOmUDjR0OpO2Q0ImbNz4K25caIxb/8Gdf2MZJr5P0uTcc+7N7T1OwKhUlvVuLC2vrK6tpzbSm1vbO7vm3n5L+qHApIl95ouOgyRhlJOmooqRTiAI8hxG2s74cu63J0RI6vMbNQ1Iz0NDTl2KkdJS3zzK2tlJPzp3Z3YOIj6AcXkxL3Owb2asvBUD/iWFhGRAgkbffLMHPg49whVmSMpuwQpUL0JCUczILG2HkgQIj9GQdDXlyCOyF8VXzOCJVgbQ9YV+XMFY/T4RIU/KqefoTg+pkfztzcX/vG6o3LNeRHkQKsLxYpEbMqh8OI8EDqggWLGpJggLqv8K8QgJhJUOLh2HUKpUS+Wivr12atUqX7d/klYxX6jky9fFTN1M4kiBQ3AMsqAAqqAOrkADNAEGt+AePIIn4854MJ6Nl0XrkpHMHIAfMF4/AIjxlqw=</latexit> 4. Use the conservation of momentum to find the final velocities (vAf and vBf ) of A and B along the line of impact: mvreln = mvAf mvBf <latexit sha1_base64="6nv9MGPwTDlscXpwjXMoorWOkgs=">AAACGHicbVDBbtNAFFy3pYRAWwNHLisipHJoaqckIQekFC4cU4m0leLIWm+e21XXa2v3OSKy/Bm98CtcOFAhrrnxN2wcq4XCSCuNZt7T25kok8Kg5/1yNja3Hmw/bDxqPn6ys7vnPn12atJccxjzVKb6PGIGpFAwRoESzjMNLIkknEVXH1b+2Ry0Ean6hIsMpgm7UCIWnKGVQveQUhrsJ3QeFgHCZyw0yDJUJX1HK/E4LunBmr6Py+B16La8tleB/kv8mrRIjVHoLoNZyvMEFHLJjJn4XobTgmkUXELZDHIDGeNX7AImliqWgJkWVbCSvrLKjMaptk8hrdQ/NwqWGLNIIjuZMLw0972V+D9vkmP8dloIleUIiq8PxbmkmNJVS3QmNHCUC0sY18L+lfJLphlH22WzKuGo1z/qdmz2wRtv0LvLfktOO22/1+6edFpDt66jQV6Ql2Sf+KRPhuQjGZEx4eSafCXfyY3zxfnm/HB+rkc3nHrnOfkLzvI3z0ieZA==</latexit> <latexit sha1_base64="vCnZU61zcHYMvdNzh/uljkRyWWU=">AAACB3icbVDLTgIxFO34RHyNujQxjcQENmQAAdlh3LjERB4JENIpHWjodCZthziZsHPjr7hxoTFu/QV3/o0dmPg+SZNzz7k3t/fYPqNSWda7sbS8srq2ntpIb25t7+yae/st6QUCkyb2mCc6NpKEUU6aiipGOr4gyLUZaduTi9hvT4mQ1OPXKvRJ30UjTh2KkdLSwDzK9rLTQXTu3Mx6OYj4ECZ1GNe5gZmx8tYc8C8pJCQDEjQG5ltv6OHAJVxhhqTsFixf9SMkFMWMzNK9QBIf4Qkaka6mHLlE9qP5HTN4opUhdDyhH1dwrn6fiJArZejautNFaix/e7H4n9cNlHPWjyj3A0U4XixyAgaVB+NQ4JAKghULNUFYUP1XiMdIIKx0dOl5CKVKtVQu6ttrp1at8nX7J2kV84VKvnxVzNTNJI4UOATHIAsKoArq4BI0QBNgcAvuwSN4Mu6MB+PZeFm0LhnJzAH4AeP1A1Wfl7A=</latexit> 5. Calculate the final velocities (vAf x and vAf y ) of ball A in the x and y directions: vAf x = vAx vreln · n̂x vAf y = vAy vreln · n̂y <latexit sha1_base64="pGBa+YllSoTOGQwylAsDZMlCLCE=">AAACLXicbZBNa9tAEIZXSZsPt0mU9JjLUhNIDzWSk9jJIeDSHnpMoU4ClhGr1SheslqJ3ZGxEfpDueSvhEIPLqXX/o2ubNOv5IWFh3dm2Jk3yqUw6HkzZ2X12fO19Y3NxouXW9s77u7epckKzaHPM5np64gZkEJBHwVKuM41sDSScBXdvq/rV2PQRmTqM05zGKbsRolEcIbWCt0PlNLgcByW75JJRc9pTRbe1hAgTLDUIKtQVTTgcYY0GDEsg5ThKEpKVVXhJHjTCN2m1/Lmoo/BX0KTLHURul+COONFCgq5ZMYMfC/HYck0Ci6hagSFgZzxW3YDA4uKpWCG5fzaih5YJ6ZJpu1TSOfu3xMlS42ZppHtrPc0/9dq86naoMDkdFgKlRcIii8+SgpJMaN1dDQWGjjKqQXGtbC7Uj5imnG0AS9COOp0j07a9vazY++s8+f233DZbvmd1smndrPnLuPYIPvkNTkkPumSHvlILkifcHJHHsiMfHPuna/Od+fHonXFWc68Iv/I+fkL5g2oBA==</latexit> <latexit sha1_base64="SJjBplPESO6ok4MX8ALhPEeOB1U=">AAACKnicbZBNT9tAEIbXFCgNX245clk1QoIDkRNIIAekIC49UqkBpDiy1psxWbFeW7vjCMvy7+mlf4ULByrUa39I10lUPl9ppUfvzGhn3jCVwqDnPToLHxaXlj+ufKqtrq1vbLqfv1yYJNMc+jyRib4KmQEpFPRRoISrVAOLQwmX4c1ZVb+cgDYiUT8wT2EYs2slIsEZWitwT/3dSVCcRnlJT2hFFvYr8BFusdAgy0CV1OejBKk/Zlj4McNxGBWqLIPc36sFbt1reFPRt9CcQ53MdR649/4o4VkMCrlkxgyaXorDgmkUXEJZ8zMDKeM37BoGFhWLwQyL6akl3bHOiEaJtk8hnbrPJwoWG5PHoe2s9jSva5X5Xm2QYXQ8LIRKMwTFZx9FmaSY0Co3OhIaOMrcAuNa2F0pHzPNONp0ZyEcdI4O2i17e/fQ63aebv8PF61Gs9Nof2/Ve+48jhWyTb6SXdIkR6RHvpFz0iec/CR35IH8dn45986j82fWuuDMZ7bICzl//wHQJ6eJ</latexit> <latexit sha1_base64="xOPq+bPlyoEfYsc0SH/LkNviMMk=">AAACB3icbVDLTgIxFO34RHyNujQxjcQENmQAAdkR3bjERB4JENIpHWjodCZthziZsHPjr7hxoTFu/QV3/o1lmPg+SZNzz7k3t/fYPqNSWda7sbS8srq2ntpIb25t7+yae/st6QUCkyb2mCc6NpKEUU6aiipGOr4gyLUZaduTi7nfnhIhqcevVeiTvotGnDoUI6WlgXmU7WWng+jcuZn1chDxIUzqUNc5ODAzVt6KAf+SQkIyIEFjYL71hh4OXMIVZkjKbsHyVT9CQlHMyCzdCyTxEZ6gEelqypFLZD+K75jBE60MoeMJ/biCsfp9IkKulKFr604XqbH87c3F/7xuoJyzfkS5HyjC8WKREzCoPDgPBQ6pIFixUBOEBdV/hXiMBMJKR5eOQyhVqqVyUd9eO7Vqla/bP0mrmC9U8uWrYqZuJnGkwCE4BllQAFVQB5egAZoAg1twDx7Bk3FnPBjPxsuidclIZg7ADxivH1jOl7I=</latexit> 6. Calculate the final velocities (vBf x and vBf y ) of ball B in the x and y directions: vBf x = vBx + vreln · n̂x vBf y = vBy + vreln · n̂y <latexit sha1_base64="MYqEGj+0yjGoYON2Znwh1Nz8YBU=">AAACLXicbZBNa9tAEIZXSZsPt0mU9JjLUhNIKRjJSezkEDBtDz2mUCcBy4jVahQvWa3E7sjYCP2hXPJXQqEHl9Jr/0ZXtulX8sLCwzsz7Mwb5VIY9LyZs7L67Pna+sZm48XLre0dd3fv0mSF5tDnmcz0dcQMSKGgjwIlXOcaWBpJuIpu39f1qzFoIzL1Gac5DFN2o0QiOENrhe4HSmlwOA7Ld8mkoue0JgtvawgQJlhqkFWoKhrwOEMajBiWQcpwFCWlqqpwErxphG7Ta3lz0cfgL6FJlroI3S9BnPEiBYVcMmMGvpfjsGQaBZdQNYLCQM74LbuBgUXFUjDDcn5tRQ+sE9Mk0/YppHP374mSpcZM08h21nua/2u1+VRtUGByOiyFygsExRcfJYWkmNE6OhoLDRzl1ALjWthdKR8xzTjagBchHHW6Rydte/vZsXfW+XP7b7hst/xO6+RTu9lzl3FskH3ymhwSn3RJj3wkF6RPOLkjD2RGvjn3zlfnu/Nj0briLGdekX/k/PwF5h+oBA==</latexit> <latexit sha1_base64="kaEw4RDr3Cmy44F+JTeWNsmtj1Q=">AAACK3icbZBNT9tAEIbXFGgavtz2yGVFhARCipwACRyQEFw4UqkBpDiy1psxWbFeW7tjhGX5//TSv8KhPRQqrv0fXScR36+00qN3ZrQzb5hKYdDz7p2ZD7Nz8x9rn+oLi0vLK+7nL2cmyTSHHk9koi9CZkAKBT0UKOEi1cDiUMJ5eHVc1c+vQRuRqO+YpzCI2aUSkeAMrRW4R9TfuA6Koygv6QGtyMJWBT7CDRYaZBmokvp8mCD1RwwLP2Y4CqNClWWQ+5v1wG14TW8s+hZaU2iQqU4D95c/THgWg0IumTH9lpfioGAaBZdQ1v3MQMr4FbuEvkXFYjCDYnxrSdetM6RRou1TSMfu84mCxcbkcWg7qz3N61plvlfrZxjtDQqh0gxB8clHUSYpJrQKjg6FBo4yt8C4FnZXykdMM4423kkI253u9m7b3r6/4+13nm5/hLN2s9Vp7n5rNw7daRw1skrWyAZpkS45JCfklPQIJz/ILflD7pyfzm/nr/MwaZ1xpjNfyQs5//4DLmunsw==</latexit> These formulas will give you the final velocities of balls A and B in two dimensions after the collision, given the initial conditions at the instant of collision. unsigned char phylib_rolling( phylib_table *t ); This function should return the number of ROLLING_BALLS on the table. phylib_table *phylib_segment( phylib_table *table ); This function should return a segment of a pool shot, as follows. If there are no ROLLING_BALLs on the table, it should return NULL. Otherwise, it should return a phylib_copy_table. The returned table should be the result of applying the phylib_roll function to each ROLLING_BALL with a value of time that starts at PHYLIB_SIM_RATE and increments by PHYLIB_SIM_RATE. All the balls should roll at the same time, so make sure to put the loop over the OBJECTS inside the loop over the time. The loop over the time should end if: 1) PHYLIB_MAX_TIME is reached, 2) The phylib_distance between the ball and another phylib_object is less than 0.0. If this happens, apply the phylib_bounce function to the ball and the object before returning the copy of the table. 3) A ROLLING_BALL has stopped. You can (and should) write additional helper functions as necessary to make sure your code is modular, readable, and easy to modify. Testing You are responsible for testing your code to make sure that it works as required. The CourseLink web-site will be updated with some test programs to get you started. However, we will use a different set of test programs to grade your code, so you need to make sure that your code performs according to the instructions above by writing a lot more test code. Your assignment will be tested on the SoCS servers. If you are developing in a different environment, you will need to allow yourself enough time to test and debug your code on the target machine. If your code works on one machine/environment but not another, you code is incorrect. Correct code will work consistently across all machines/environments. We will NOT test your code on YOUR machine/environment. Ask Questions The instructions above are intended to be as complete and clear as possible. However, it is YOUR responsibility to resolve any ambiguities or confusion about the instructions by asking questions in class, via the discussion forums, or by e-mailing the course e-mail. Nightmare mode Students who want an extra challenge for zero extra grades can complete the additional following requirements. There are no extra or bonus remarks for students who complete the assignment in “Nightmare mode”. The experience gained is its own reward. This is only recommended for students who have completed the other parts of the assignment. In a separate version of your code (separate from that you are handing in for grading) add the ability to add “top spin”, “bottom spin” and “side spin” to a ROLLING_BALL. Students who complete all assignments in Nightmare mode, may get a small token of recognition at the end of the course. Git You must submit your .c, .h and makefile using git to the School’s git server. Only code submitted to the server will be graded. Place all three files in the A1 directory (so subdirectories, sorry). Do not e-mail your assignment to the instructor. We will only grade one submission; we will only grade the last submission that you make to the server and apply any late penalty based on the last submission. So once your code is complete and you have tested it and you are ready to have it graded make sure to commit and push all of your changes to the server, and then do not make any more changes to the A1 files on the server. Academic Integrity Throughout the entire time that you are working on this assignment. You must not look at another student’s code, nor allow your code to be accessible to any other student. You can share additional test cases (beyond those supplied by the instructor) or discuss what the correct outputs of the test programs should be, but do not share ANY code with your classmates. Also, do your own work, do not hire someone to do the work for you. If you used internet resources to write any of the code, provide a reference to the resource that you used in a comment by the code. Grading Rubric phylib_new_still_ball phylib_new_rolling_ball phylib_new_hole phylib_new_hcushion phylib_new_vcushion phylib_new_table 1 1 1 1 1 2 phylib_copy_object phylib_copy_table phylib_add_object phylib_free_table phylib_sub phylib_length phylib_dot_product phylib_distance 1 2 1 1 1 1 1 1 phylib_roll phylib_stopped phylib_bounce phylib_rolling phylib_segment 2 1 5 4 3 makefile comments/indentation Total 2 2 35