S Lazy-H
  • Home
  • About
  • Posts
  • Contact
  • Slide Rules
  • A Biker’s Tale

EDM With C++

transit
C++
Land Surveying
Author

Sam Hutchins

Published

November 9, 2025

I was recently speaking with a good friend, who is also a neighbor, and he mentioned that he was looking into swapping some land with another neighbor. The talk eventually got around to transits and how to find missing corners. I mentioned I had, as one of my hobbies, transits and theodolites, of which I had several different ones acquired over the years. After further investigation, I determined the setup most useful in a case like this would be the Sokkisha DT5A theodolite, mentioned in this post, along with the Sokkisha RED2L Electronic Distance Meter (EDM), mentioned in the same post. The RED2L came with a button/keypad, but it never worked properly. However, this was not a huge issue for me, as this is just a hobby.

What prompted this particular post was remembering that I had developed a program to process the data to determine actual distance, given that the angle of the theodolite to the target and the distance of the EDM from the theodolite, gave a different angle to the same target. In common use, the theodolite may be pointed at a range rod which would have the reflective target also mounted on the same rod, which would give an additional angle/separation to take into account. In my case, I use the reflector as the target for both the EDM and the transit.

That program I had written in R Core Team (2025). In that post, I also mentioned developing a C++ program. So, I searched that computer for the program so I wouldn’t be reinventing the wheel, and came to discover I had never actually completed (or started) that program. So, it’s back to scratch!

Hence this post, where I will attempt to define the C++ version. It is a fairly simple program, where we define not only the adjustment of the RED2L EDM, but also reduce the angles involved to determine the horizontal distance and vertical elevation of the target.

The first adjustment required for the EDM is inputting a ppm1 value, otherwise the distance could be off by, in extreme cases, many feet. What does that mean? It means we need an on-the-spot reading for barometric pressure and temperature. How can we do that, out in the willywogs?

Well, I just happen to have developed a portable weather station that will work perfectly for the task! And it fits in the palm of my hand. Enter the Pico weather station, where I have printed a small box to house all the pertinent parts, including a small battery. I don’t care that it is not polished and pretty.

Handheld weather station.

This device I can toss into the bag with the other accessories for the theodolite, where it is always available for a quick reading on station, wherever that may be! So now, we have all the necessary parts to do some surveying!

Disclaimer: I am not a professional computer programmer, or a licensed land surveyor, so any program errors, or measurements made in the field are just for academic interest!

Anyway, on to the C++ program. As mentioned above, the first value necessary for accurate readings is a ppm value, so we can set the adjusting knob on the RED2L. The formula to manually calculate the setting is:

\[Correction \; X = 278.96 - \frac{10.5 \times P}{1 + 0.002175 \times F}\]

where P is the atmospheric pressure in inches of mercury (inHg), F is temperature in degrees Fahrenheit and X is the ppm setting.

Adjusting knob.

Notice in the above image, the feet/meter switch is set to ft, as all my range rods and tapes are calibrated in feet. None are in meters, as all my instruments are vintage, before the metric system came into widespread use. The little snippet of code to determine the ppm setting is presented below.

Code
cout << "Enter atmospheric pressure (inHg): "; cin >> press;
cout << "Enter temperature (F): "; cin >> tempF;
ppm = 278.96 - ((10.5 * press) / (1 + 0.002175 * tempF)); // manually calculate ppm compensation
cout << "\n-> Set PPM knob to " << fixed << setprecision(0) << ppm << " <-\n" << endl;

After setting the ppm, we then proceed to take a measurement, where we have already set up and leveled the theodolite/EDM on the tripod, centered on the reflective target, obtained a vertical angle and distance reading.

At this juncture, we can enter the obtained measurement values into the program to determine the corrected distance. The formulae for the distance and elevation are as follows.

\[Horizontal = (d \cos{\varphi} + \sqrt{D^{2} - d^{2} \sin^{2}{\varphi}}) \times \sin{\varphi}\] \[Elevation = h + (d \cos{\varphi} + \sqrt{D^{2} - d^{2} \sin^{2}{\varphi}}) \times \cos{\varphi}\]

where \(\varphi\) is zenith angle (i.e., zero is straight up), D is EDM distance reading, d in this case is the distance from the DT5A theodolite and the RED2L EDM (0.625 feet) and h is the theodolite height, used in the below calculations.

If we wish to determine the actual altitude at the station and the target, we will need the station altitude. However, this measurement is beyond the capabilities of this simple program, as we would require, for example, a GPS2 reading, if we don’t already know the altitude. As in this post, it is possible to also determine, but I did not include that value, although the value is easily obtained and included in each NMEA-0183 (National Marine Electronics Association) sentence. For this simple exercise, it is not necessary. However, arbritary altitudes would be available from the first station set to zero altitude.

Code
cout << "Enter theodolite altitude: "; cin >> altitude;
cout << "Enter Theodolite height (ft): "; cin >> theoH;
cout << "Enter Reflector height (ft): "; cin >> reflH;
cout << "For below fields, enter all three with spaces between." << endl;
cout << "Enter angle reading (DD mm ss): "; cin >> angleDD >> angleMM >> angleSS;
cout << "Enter EDM distance reading (ft): "; cin >> Distance;

Now we have all the required information to determine the real distance. If any slope is involved, the real distance will be less than the reading obtained.

Code
double pi{3.141592653589793238462}; // overkill, we could possibly use 3.14.
angle = angleDD + (angleMM/60) + (angleSS/3600);
double angleR =  (pi / 180) * angle; // convert to radians
distH = (edm * cos(angleR) + sqrt(pow(Distance,2) - pow(edm,2) * (pow(sin(angleR),2)))) * sin(angleR);
distV = theoH + (edm * cos(angleR) + sqrt(pow(Distance,2) - pow(edm,2) * pow(sin(angleR),2))) * cos(angleR);
double slope = tan((pi/180)*(90-angle)) * 100;
if((slope > 100) | (slope < (-100))) slope = 100;
deltaV = distV - reflH;

The first line above (\(\pi\)) is only because that is the value I like to use, as in this post.

In C++, if we use sin, cos, tan, we must convert degree readings to radians, as on the third line above. Now that we have the corrected distance, the only step remaining is to display the values.

Code
cout << fixed << setprecision(3) <<  "\nDistance:  " << distH << " ft." << endl;
cout << setprecision(1) << "Vertical:  " << deltaV << " ft." << endl;
cout << setprecision(0) << "Slope:  " << slope << " %." << endl;
cout << "Theodolite altitude: " << fixed << setprecision(3) << altitude << endl;
cout << "Reflector altitude:  " << altitude + deltaV << endl;

One thing of note is #include <bits/stdc++.h> is needed in the program for the setprecision() statement. Also, the last line will only indicate the altitude delta without an accurate starting altitude. Most required variables are defined as double to hold generated values, and could be renamed anything desired.

That is about it for this program, pretty simple…

Have a great day, and keep God as your guiding compass throughout life, if you intend a smooth outcome.

References

R Core Team. 2025. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.

Footnotes

  1. Parts per million (PPM) on the RED2L is required to compensate for barometric pressure and temperature which affects distance readings.↩︎

  2. Global positioning system (GPS) is used to determine locations on the Earth.↩︎

© S Lazy-H 2019 -