Throughout this paper, a segment is a line connecting two points. A contour is a series of connected line segments forming a closed loop. Outer contours are formed by the intersection of the slicing plane with the external surfaces of the model. Hole contours are formed by the intersection of the slicing plane with internal surfaces in the model. Offset contours are formed by offsetting either outer contours or hole contours. A path or a sub-path is also a series of continuously connected line segments, but it does not need to be a closed loop. Figure 1 shows the flow diagram of the proposed method. Given a CAD model of an object, the first step is to slice it into flat or planar layers, regularly spaced along the z-direction. Each slice consists of outer contours and hole contours. Figure 2 shows an example of a CAD model and one of its slices when cut normal to the z-direction. In this section, we will take this model to intuitively show the output of each step in the proposed method. In Fig. 2b, a red contour is an outer contour, and a green contour is a hole contour. Planar slicing of a 3D model has been thoroughly investigated in many studies [24][25] and, therefore, will not be discussed in depth here.

## 3.1 Contour Offsetting

Given a slice consisting consists of identified outer and hole contours, the second step of the proposed method is obtaining offset contours. A regular offset distance or linespacing, *d* is used. The contour offsetting algorithm from the Clipper library was adopted to offset input contours [26]. The library implements Vatti’s clipping algorithm [27]. The offsetting algorithm takes the set of outer and hole contours as an input. By convention, the segments of an outer contour are ordered in the counterclockwise direction, while those of a hole contour follow a clockwise order. The Clipper library does one iteration offsetting and outputs a list of isolated offset contours. To fill a polygon with offset contours, we iteratively apply the offsetting function until no space remains to implement any further offsets. Figure 2c shows the result after iteratively applying the offsetting function to the polygon shown in Fig. 2b. In this example, the outer contour has two offsets, as does the hole contour. The outer contour and the hole contour are at level 0. The offset contours obtained by one iteration of offsetting are in level 1 and so on.

The third step of the proposed method is to reorder all contours obtained from the offsetting algorithm using Algorithm 1. The contours will be ordered incrementally inward, with the inner-most one having the highest level.

**Algorithm 1**

Re-level the offset contours

**Input**: List of all offset contours: *All_contours*

**Output**

Contours with level

### 1. Distinguish Outer Contour And Hole Contours In Level 0

For all contour in level 0 of *All_contours*:

If *contour[i]* is a hole:

*All_contours [0][i].type = num_hole++*

End If

End For

### 2. Re-level Offset Contours Level

For all level *i* in *All_contours* from the highest to 0:

For all contours *j* in level *i*:

If *All_contours[i][j]* is from a hole:

*Type1 = All_contours [i][j].type*

For *i1* from *i* to 0:

For *i2* from 0 to the highest level of *All_contours*:

If (*All_contours [i1][i2].type = type1*):

*New_pos = (i + 1) + (i-i1)*

End If

End For

End For

*All_contours [New_pos] = All_contours [i1][i2]*

Delete *All_contours [i1][i2]*

End If

End For

End For

### 3. Return

3. Return *All_contours*

After applying algorithm 1 to the input shown in Fig. 2c, we obtain the contour set shown in Fig. 2d. The levels of these contours have been renumbered to increase inwardly, which facilitates the breakpoint searching algorithm.

## 3.2 Finding breakpoints

The next step is to identify breakpoints in each contour that will be used to connect one contour to another. This procedure is described in Algorithm 2. Within each contour, we find a pair of breakpoints *p1* and *p2* with the distance from *p1* to *p2* equal to the line spacing, *d*. The projected points *p1’* and *p2’* of *p1* and *p2* onto a candidate neighbouring contour are also identified using Algorithm 2. *p0* is the first point in a contour. A segment for *p1* is selected based on the accumulated length from *p0*. After selecting an appropriate segment, *p1* is the first point of that segment. Two new segments will be added to connect *p1* with *p1’*, and *p2* with *p2’*. The breakpoint selection will be repeated every *n* layers. Figure 2e shows the result after identifying breakpoints and their projection.

## 3.3 Forming sub-paths

After adding connecting line segments to join adjacent contours at each breakpoint, Algorithm 3 forms sub-paths. The idea is to loop through each contour in the counterclockwise direction and find continuous sections. Sub-paths are displayed in different colours in Fig. 2f. Each colour represents a sub-path.

## 3.4 Generating continuous path

This step connects all sub-paths to form a continuous global toolpath. The global toolpath starts from the first sub-path in the list, and all points in that sub-path are added to the global toolpath. Each sub-path added to the global path is removed from the sub-path list. The current end point of the global toolpath will be connected to the next sub-path which shares an identical start point or end point. If the next sub-path has its starting point identical to the ending point of the global toolpath, all points of that sub-path will be added to the global toolpath in incremental order. We loop until the list of sub-paths is empty.

Pattison *et al.* showed that a multi-layer cold spray deposit develops a natural taper, becoming thinner as it grows taller [16]. However, this could be compensated for by tilting the nozzle inwards at the edges. The technique has since been used to build vertical features [23][28]. Paths along the original outer and hole contours are separated from the infill path. By adjusting the nozzle angle and speed for contour movements vertical or overhanging edges can be produced with greater geometrical accuracy. Given an outer contour *ABC*, shown in Fig. 3, the orientation of the nozzle corresponding to a tilting angle *x* is calculated as follows. With is the normal vector of the planar slice, is a vector lied on that slice and be the bisector of. The vector of the nozzle when moving from point *A* to point *B* is calculated from two equations:

Figure 2g shows the final continuous toolpath to print the polygon shown in Fig. 2b. The blue curves are infill paths in which the nozzle is perpendicular to the substrate. The red curves are outer and hole paths in which the nozzle is tilted at an angle *x*.