Milling holes and circles in Gcode

It's not as difficult as it seems.
Gcode is a simple language and creating your own code is just a matter of logical thinking and some basic math.
The picture at the left shows how to mill a large hole using a small mill. Remember, the mill rotates in a clockwise direction so if we are cutting a hole out of a sheet or a block, we need to make sure we mill in the right direction  which is also clockwise.
Moving counterclockwise would be pulling the cutter out of the work piece and results in a bad result. 
Now let's get going with some Gcode. Milling a circle or an arc needs three sets of coordinates:
 a starting point
 a centre point
 the end point
The mill now moves from point 1 to 3 around the centre point 3. If the start and endpoint are the same a complete circle is made.
A circle always has to be located in a specific plane being either the XY, YZ or XZ plane and since I mostly just create 2.5D objects I am always milling circles in the XY plane.
To mill a hole (or actually only the contour of the hole, we need to take a number of steps:

 move to the starting point and place the mill at the required depth
 create a full circle by specifying the current point as endpoint and the centre coordinates as delta from the current point
 move the mill up, away from the workpiece

So to mill a circle with a radius of 4 and the centre at x,y = 10,10 at a depth of 1 we have to move to a starting point at the arc first, I take the given point in the picture above as starting point, this is as the same Y coordinate as the centre and the X coordinate is at x  radius (in this case 104 = 6). A move is always done in a straight line so only after arriving at the starting point we move down to 1. This is done using the following Gcode:
G0 x 6 y 10
G1 z 1
A G0 (this is a zero, not the letter O) will move at high speed to the starting point and G1 will move the mill down at the feedrate (set with the F... command), for now I assume that the F speed is already set.
Now we are ready to move in a circle. We have to specify the XY plane (using G17) before starting to mill a clockwise circle (using G2). The centre location is specified relative from the starting point so for the center X equals to 4 (the radius) and Y 0. To mill a whole circle, we have to end at the same coordinates as we started from (so 6, 10):
G17 G2 x 6 y 10 i 4 j 0 z 1
As you can see there are two sets of coordinates specified in the line above: x, y specifies the end point and i, j the centre. I always specify the z coordinate also telling to stay at the same depth. Moving to a different Zvalue would mill a helix (i.e. the mill would move up or down along the arc).
And clear away from the workpiece:
G0 z 1
So that's it, we are done  right?
No, all we did is move a full circle and if I had a 3mm flat tip cutter this will result in a hole that is too large. The centre of the cutter moves along the circle so we have removed too much material (on all sides the radius of the cutter) so we have to compensate for the cutter radius:
 We have to start 1.5 mm further to the right from the starting point so we start at x = 6 + 1.5
 The centre has to stay at the same location so the relative coordinate for the centre x is now 4  1.5
This results in the following piece of code:
G0 x 7.5 y 10
G1 z 1
G17 G2 x 7.5 y 10 i 2.5 j 0 z 1
G0 z 1
And now we are done! We have a contour that might leave a hole of the given size at the wanted location. If we need a hole with a large radius we need to repeat the movement starting with smaller circles and moving to larger ones until the wanted diameter is reached. Same goes for the depth, we can not remove too much material at once depending on the material, cutter type, spindle speed and feedrate. 