It doesn't seem you would need complex trigonometric equations here. You only wish to keep the object above ground(or on the ground), let's do just that.
Using a Driver
You can set up a driver for z location with a scripted function that finds the lowest vertex and then adjusts the location of the object accordingly:
import bpy
def aboveGround(object_name,floor_z):
obj = bpy.data.objects[object_name]
mesh = obj.data
z = 7 # because it's a lucky number...
# ...and 0 seems to be buggy inside the driver for some reason
for verts in mesh.vertices:
world_space_co = obj.matrix_world * verts.co
if world_space_co[2] < z :
z = world_space_co[2]
loc_z = obj.location[2]
return loc_z - z + floor_z
# # or this if we don't want the object to stick to the ground when it's above :
# if z<floor_z:
# return loc_z - z + floor_z
# else:
# return loc_z
# add function to driver_namespace
bpy.app.driver_namespace['aboveGround'] = aboveGround
You would need to have this in a text block and check Register (Autorun Python Script will need to be enabled in the user preferences as well) so it runs when you open the file:

You can just run it manually as well.
Then you can create a driver for z location of your object and put the function as the expression:


Using a Scene Update App Handler
It would also be possible to have only a function that would correct the position while working so you could set keyframes. Sort of like a tool. You could use a scene update app handler for that. You could just register it when you need it and then remove it once you don't need it any more:
import bpy
def AboveGroundHandler(scene):
obj = bpy.data.objects['Plane']
mesh = obj.data
floor_z = 0
z = 7
for verts in mesh.vertices:
world_space_co = obj.matrix_world * verts.co
if world_space_co[2] < z :
z = world_space_co[2]
obj.location[2] = obj.location[2] - z + floor_z
bpy.app.handlers.scene_update_pre.append(AboveGroundHandler)
#bpy.app.handlers.scene_update_pre.clear() # to remove it(can be run from Python console)