You have too many unnecessary groups. Also, since you actually need 2 groups to match the same type of value, you may use a named capturing group, and grab all your required matches with a regex like
actual (?:lat|lon) (?<val>\d+\.\d{1,6})|(?<val>\d+\.\d{1,6}) (?:lat|lon)
See the regex demo. If you use a RegexOptions.ExplicitCapture flag, you can use capturing groups as non-capturing ones (only the named capturing groups will keep their submatches). See the C# demo:
var s = "lat range: 49.000000 to 50.000000 actual lat 49.212059 lon range: 16.000000 to 17.000000 actual lon 16.626276";
var pattern = @"actual (lat|lon) (?<val>\d+\.\d{1,6})|(?<val>\d+\.\d{1,6}) (lat|lon)";
var results = Regex.Matches(s, pattern)
        .Cast<Match>()
        .Select(m => m.Groups["val"].Value)
        .ToList();
Console.WriteLine(string.Join("\n", results));
// => 49.212059
//    16.626276
If you put the (lon|lat) into a named capturing group, you will be able to get a dictionary as a result:
var pattern = @"actual (?<type>lat|lon) (?<val>\d+\.\d{1,6})|(?<val>\d+\.\d{1,6}) (?<type>lat|lon)";
var results = Regex.Matches(s, pattern)
     .Cast<Match>()
     .ToDictionary(
            m => m.Groups["type"].Value,
            m => m.Groups["val"].Value);
foreach (var kv in results)
    Console.WriteLine("'{0}': '{1}'", kv.Key, kv.Value);
// => 'lat': '49.212059'
//    'lon': '16.626276'
See another C# demo.