I have an excel spreadsheet with header and survey drill data. Header data contains hole ID, and location coordinates, and the survey data contains related downhole survey with Distance, Azimuth and Dip values.

Since I know the hole location and surface elevation, I would like to be able to convert the survey table to XYZ coordinates as well. Does anyone has a function / procedure / example? (VB & ArcObjects)

Header Data:

Header Data

Survey Data:

enter image description here

  • Couldn't you just use them as xyz coordinates anyways? I assume that dip has an origin of 0, doesn't it?
    – Emily
    Commented Aug 11, 2011 at 19:17
  • 1
    @Emily - Yes the first XYZ is given (X:425990,Y:5409010,Z:350). The dip value is 0 and the distance is 0. How do I calculate the XYZ for Distance:41, Azimuth: 359, Dip: -71? (At each survey point the direction and inclination will be different, resulting deviated and spiraling downholes) There is probably a simple formula... Commented Aug 11, 2011 at 19:44

4 Answers 4


The question asks for conversion between spherical and cartesian coordinates. This spreadsheet lays out the formulas:

Spreadsheet screen shot

Blue lines are input, black are intermediate calculations, and red are output. Within the formulas, the values are referred to by the names in the [Parameter] column (assigned via the Insert|Name|Create operation).

They differ from those in most math/physics references because in geography, the azimuth is usually taken east of north rather than north of east. This makes the geographic azimuth the complement of the mathematical one (they sum to 90 degrees). Replacing an angle by its complement in any trig function interchanges it with its "co" partner: sine and cosine are interchanged, tangent and cotangent, secant and cosecant. Also, in many mathematical systems the "dip" is expressed as an angle from true vertical (a co-latitude) rather than as an angle from horizontal (a latitude), again causing an interchange of sine and cosine.

Edit 9/20/13

For a downhole distance you probably want to negate dZ.

  • Thanks. Looks good! Will have to confirm the azimuth type. How do I find the Radians in the formula? Commented Aug 11, 2011 at 20:19
  • Radians = Degrees / 180 * Pi
    – whuber
    Commented Aug 11, 2011 at 20:20
  • Right on. Thanks. I was staring at the formula in the link above and scratching my head. Clear as a bell now. Commented Aug 11, 2011 at 20:37
  • @Jakub You are aware that this is a working, valid spreadsheet, right? You can type these formulas into Excel, name the cells in the [Value] column as indicated in the [Parameter] column to its left, and it will run. Blue text is input; black is intermediate calculations; and red is output. Once you're comfortable with it you can modify your second spreadsheet to do the computations for every entry. The only trick is in joining the (X0,Y0,Z0) coordinates from the first: do it with a database or by means of VLOOKUP().
    – whuber
    Commented Aug 11, 2011 at 20:41
  • I wasn't aware. Even better! So RADIANS is obviously an Excel function to which I am passing either Azimuth or dip. Commented Aug 11, 2011 at 20:52

While this is an old question, the other answers are not appropriate. Converting Distance (Measured Depth), Dip (Inclination), Azimuth to 3D coordinates depends on how you interpret what is happening between the locations where measurements were taken (survey stations). The standard practice today is "Minimum Curvature" where the assumption is that a circular arc connects each survey location.

http://www.drillingformulas.com/minimum-curvature-method/ gives full details on how to calculate the X, Y and Z locations. The relevant portions are:

dMD = Distance2 - Distance1
B = acos(cos(I2 - I1) - (sin(I1)*sin(I2)*(1-cos(A2-A1))))
RF = 2 / B * tan(B / 2)
dX = dMD/2 * (sin(I1)*sin(A1) + sin(I2)*sin(A2))*RF
dY = dMD/2 * (sin(I1)*cos(A1) + sin(I2)*cos(A2))*RF
dZ = dMD/2 * (cos(I1) + cos(I2))*RF

X2 = X1 + dX
Y2 = Y1 + dX
Z2 = Z1 + dX
  • I found that if there's a straight segment (I1 == I2 and A1 == A2), then B ends up 0 and so RF produces a divide by zero error. In the case that B is zero, then I set RF to 1 (as the limit of RF as B goes to 0 is 1). Otherwise, this works great, thanks! Commented Sep 3, 2015 at 0:49

As Eric writes, you can easily end up with a div_by_zero error here: You can however avoid this without testing for exact zero: When abs(B) is less than about 1e-9, the tan(B/2) term will be exactly (within the 64/53-bit precision of a double) the inverse of 2/B.

The easiest way to show this is with the Taylor series for tan(x) which is x + 1/3*x^3 + 2/15*x^5 + .... This means that the x^3 term will be so small compared to x as to be effectively zero.

The main advantage of doing it this way is that you avoid calculating tan() of a very small number which is likely to lead to many operations on sub-normal numbers. Sub-normal support is still very slow on many architectures so it is better to avoid it in the first place.


To convert spherical coordinates (Distance, Azimuth, Dip) to Cartesian coordinates (XYZ), you can use the sph2cart function in MATLAB. Here are the steps to do it:

  1. First, make sure you have the necessary input arguments: Distance (r), Azimuth angle (azimuth), and Elevation angle (elevation).

  2. Call the sph2cart function with the input arguments:

[x, y, z] = sph2cart(azimuth, elevation, r);

This will calculate the Cartesian coordinates (x, y, z) based on the spherical coordinates (azimuth, elevation, r).

  1. The output arrays x, y, and z will contain the Cartesian coordinates for each corresponding input point.

It's important to note that the azimuth, elevation, and r inputs should have the same size, or sizes that are compatible. The azimuth angle is the counterclockwise angle in the x-y plane measured in radians from the positive x-axis, while the elevation angle is the angle in radians from the x-y plane.

The sph2cart function supports various data types, including single and double precision, and also supports complex numbers. It can handle scalar inputs as well as arrays of any size.

If you need to convert a large array that doesn't fit in memory, you can use tall arrays, which are supported by the sph2cart function. Additionally, this function can generate C and C++ code using MATLAB Coder, generate CUDA code for NVIDIA GPUs using GPU Coder, and run in a thread-based environment or on a graphics processing unit (GPU) using Parallel Computing Toolbox.

The sph2cart function in MATLAB has been available since at least R2006a.

You can find more in Directional Drilling Survey Calculations

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.