@@ -75,9 +75,11 @@ spiral_collides(spiral_t spiral, size_t index) {
7575}
7676
7777/*
78- * given a spiral struct that is known to collide and the index of the 'last'
79- * segment in the spiral (i.e. the one that was found to be colliding), return
80- * a suggested length to set the segment before this line to.
78+ * given a spiral struct that is known to collide, the index of the 'last'
79+ * segment in the spiral (i.e. the one that was found to be colliding) and a
80+ * perfection threshold (-1 for no perfection, or otherwise the maximmum line
81+ * length at which to allow aggressive optimisation), return a suggested length
82+ * to set the segment before this line to.
8183 *
8284 * NOTE: This function is not guaranteed to make suggestions that will not
8385 * collide. Every suggestion that is followed should then have the spiral
@@ -91,21 +93,31 @@ spiral_collides(spiral_t spiral, size_t index) {
9193 * line before the newly plotted line.
9294 */
9395static length_t
94- suggest_resize (spiral_t spiral , size_t index ) {
96+ suggest_resize (spiral_t spiral , size_t index , int perfection_threshold ) {
9597 // check if collides or not, return same size if no collision
9698 if (spiral .collides != -1 ) {
9799 /*
98- * if the colliding line's length is greater than 1, we cannot make any
99- * intelligent suggestions on the length to extend the previous line to
100- * (without the high likelihood of creating a line that wastes space),
101- * so we just return the previous line's length +1
100+ * if the perfection threshold is -1, then we can just use our suggestion,
101+ * as perfection is disabled.
102+ * otherwise, if the colliding line's length is greater than our
103+ * perfection threshold, we cannot make any intelligent suggestions on
104+ * the length to extend the previous line to (without the high
105+ * likelihood of creating a line that wastes space), so we just return
106+ * the previous line's length +1
102107 */
103- if (spiral .lines [index ].length > 1 ) {
108+ if (
109+ (perfection_threshold != -1 ) &&
110+ (spiral .lines [index ].length > (length_t )perfection_threshold )
111+ ) {
104112 return spiral .lines [index - 1 ].length + 1 ;
105113 }
106114 // store the 'previous' and 'rigid' lines.
107115 line_t p = spiral .lines [index - 1 ];
108116 line_t r = spiral .lines [spiral .collides ];
117+ // if pr and r are not parallel, we can return early
118+ if ((p .direction % 2 ) != (r .direction % 2 )) {
119+ return spiral .lines [index - 1 ].length + 1 ;
120+ }
109121 // create variables to store the start and end co-ords of these lines
110122 co_ord_t pa , pb , ra , rb ;
111123 /*
@@ -155,11 +167,15 @@ suggest_resize(spiral_t spiral, size_t index) {
155167
156168/*
157169 * given a spiral struct, the index of one of it's lines and a target length to
158- * set that line to, attempt to set the target line to that length,
159- * back-tracking to resize the previous line if it collides.
170+ * set that line to and a perfection threshold (-1 for no perfection, or
171+ * otherwise the maximmum line length at which to allow aggressive optimisation)
172+ * attempt to set the target line to that length, back-tracking to resize the
173+ * previous line if it collides.
160174 */
161175spiral_t
162- resize_spiral (spiral_t spiral , size_t index , length_t length ) {
176+ resize_spiral (
177+ spiral_t spiral , size_t index , uint32_t length , int perfection_threshold
178+ ) {
163179 /*
164180 * setup state variables, these are used in place of recursion for managing
165181 * state of which line is being resized, and what size it should be.
@@ -185,7 +201,9 @@ resize_spiral(spiral_t spiral, size_t index, length_t length) {
185201 * function to get the suggested length to resize the previous
186202 * segment to
187203 */
188- current_length = suggest_resize (spiral , current_index );
204+ current_length = suggest_resize (
205+ spiral , current_index , perfection_threshold
206+ );
189207 current_index -- ;
190208 } else if (current_index != index ) {
191209 /*
@@ -206,22 +224,24 @@ resize_spiral(spiral_t spiral, size_t index, length_t length) {
206224}
207225
208226/*
209- * given a spiral for which the length of all its lines are not yet known,
210- * calculate the length needed for each line in the spiral (to avoid line overlap)
211- * and store these in a spiral struct and return that
227+ * given a spiral for which the length of all its lines are not yet known and
228+ * a perfection threshold (-1 for no perfection, or otherwise the maximmum line
229+ * length at which to allow aggressive optimisation) calculate the length needed
230+ * for each line in the spiral (to avoid line overlap) and store these in a
231+ * spiral struct and return that
212232 */
213233spiral_t
214- plot_spiral (spiral_t input ) {
234+ plot_spiral (spiral_t spiral , int perfection_threshold ) {
215235 // allocate new struct as copy of input struct
216- spiral_t output = { .size = input .size , };
236+ spiral_t output = { .size = spiral .size , };
217237 output .lines = calloc (sizeof (line_t ), output .size );
218238 // copy across the spiral lines
219239 for (size_t i = 0 ; i < output .size ; i ++ ) {
220- output .lines [i ] = input .lines [i ];
240+ output .lines [i ] = spiral .lines [i ];
221241 }
222242 // calculate the length of each line
223243 for (size_t i = 0 ; i < output .size ; i ++ ) {
224- output = resize_spiral (output , i , 1 );
244+ output = resize_spiral (output , i , 1 , perfection_threshold );
225245 }
226246 // free the co_ord_cache member's dynamic memory if required
227247 if (output .co_ord_cache .co_ords .size > 0 ) {
0 commit comments