private static TrLibException TR_ErrorToTrLibException(TrLib.TR_Error error)
        {
            switch (error)
            {
            case TrLib.TR_Error.TR_LABEL_ERROR:
                return(new TrLibException(TrLibException.ErrorTypes.Label, TrLib.TR_GetLastError()));

            case TrLib.TR_Error.TR_TRANSFORMATION_ERROR:
                return(new TrLibException(TrLibException.ErrorTypes.Transformation, TrLib.TR_GetLastError()));

            case TrLib.TR_Error.TR_ALLOCATION_ERROR:
                return(new TrLibException(TrLibException.ErrorTypes.Allocation, TrLib.TR_GetLastError()));

            default:
                throw new ArgumentException($"{error} is not a known TRLIB error");
            }
        }
        public Point Transform(Point from, int toEpsgId)
        {
            if (!epsgIdToMiniLabelMap.ContainsKey(from.EpsgId))
            {
                throw new UnsupportedEpsgIdException(from.EpsgId);
            }

            if (!epsgIdToMiniLabelMap.ContainsKey(toEpsgId))
            {
                throw new UnsupportedEpsgIdException(toEpsgId);
            }

            var fromMiniLabel = epsgIdToMiniLabelMap[from.EpsgId];
            var toMiniLabel   = epsgIdToMiniLabelMap[toEpsgId];

            if (fromMiniLabel.StartsWith("geo"))
            {
                from.X = DegToRad(from.X);
                from.Y = DegToRad(from.Y);
            }

            IntPtr tr = IntPtr.Zero;

            TrLib.TR_Error error;
            double         oX, oY, oZ;

            error = TrLib.InitLibrary(geoidsDirectory);

            if (error != TrLib.TR_Error.TR_OK)
            {
                //In some situations TrLib will report a TR_TRANSFORMATION_ERROR on initialization
                //even though the library is able to perform transformations just fine.
                //Haven't been able to find out what causes the situation, but a workaround is to continue if the error code is zero
                var errorCode = TrLib.TR_GetLastError();
                if (errorCode != 0)
                {
                    throw new TrLibException(TrLibException.ErrorTypes.Initialization, errorCode);
                }
            }

            tr = TrLib.TR_Open(fromMiniLabel, toMiniLabel, "");

            if (tr == IntPtr.Zero)
            {
                throw new TrLibException(TrLibException.ErrorTypes.Open, TrLib.TR_GetLastError());
            }

            try
            {
                TrLib.TR_AllowUnsafeTransformations();
                error = TrLib.TR_TransformPoint(tr, from.X, from.Y, from.Z, out oX, out oY, out oZ);
            }
            finally
            {
                TrLib.TR_Close(tr);
            }

            if (error != TrLib.TR_Error.TR_OK)
            {
                throw TR_ErrorToTrLibException(error);
            }

            if (toMiniLabel.StartsWith("geo"))
            {
                oX = RadToDeg(oX);
                oY = RadToDeg(oY);
                oZ = RadToDeg(oZ);
            }

            Point to = new Point()
            {
                X      = oX,
                Y      = oY,
                Z      = oZ,
                EpsgId = toEpsgId
            };

            return(to);
        }