Below is the example of simple script that sets region parallel to XY plane and defines its top side to Max level and bottom - to Min level input by the user:
import Metashape
def cross(a, b):
"""
vector product of two vectors
"""
result = Metashape.Vector([a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y *b.x])
return result.normalized()
def get_min_max_region(chunk):
if not chunk.region:
return [None, None]
region = chunk.region
center = region.center
size = region.size
rotate = region.rot
T = chunk.transform.matrix
s = chunk.transform.scale
crs = chunk.crs
corners = [T.mulp(center + rotate * Metashape.Vector([size[0] * ((i & 1) - 0.5), 0.5 * size[1] * ((i & 2) - 1), 0.25 * size[2] * ((i & 4) - 2)])) for i in range(8)]
if chunk.crs:
corners = [chunk.crs.project(x) for x in list(corners)]
max_z = max([corner.z for corner in corners])
min_z = min([corner.z for corner in corners])
print("Estimating min&max Z values for region")
print(min_z, max_z)
return [min_z, max_z]
def set_region():
chunk = Metashape.app.document.chunk
z_min, z_max = get_min_max_region(chunk)
z_min = Metashape.app.getFloat("Specify MIN altitude value for region:", z_min)
z_max = Metashape.app.getFloat("Specify MAX altitude value for region:", z_max)
if z_min == z_max:
print("Z min = Z max, so no region correction applied")
return 0
if z_min > z_max:
z_min, z_max = z_max, z_min
region = chunk.region
center = region.center
size = region.size
rotate = region.rot
T = chunk.transform.matrix
s = chunk.transform.scale
crs = chunk.crs
corners = [T.mulp(center + rotate * Metashape.Vector([size[0] * ((i & 1) - 0.5), 0.5 * size[1] * ((i & 2) - 1), 0.25 * size[2] * ((i & 4) - 2)])) for i in range(8)]
if chunk.crs:
corners = [chunk.crs.project(x) for x in list(corners)]
for i in range(len(corners)):
corner = corners[i]
if i < 4:
corners[i] = Metashape.Vector([corner.x, corner.y, z_max])
else: #corner.z < z_min:
corners[i] = Metashape.Vector([corner.x, corner.y, z_min])
new_region = Metashape.Region()
if chunk.crs:
corners = [T.inv().mulp(crs.unproject(x)) for x in list(corners)]
else:
corners = [T.inv().mulp(x) for x in list(corners)]
new_center = (corners[0] + corners[-1]) / 2.
new_region.center = new_center
side1 = corners[0] - corners[2]
side2 = corners[0] - corners[1]
side1g = T.mulp(corners[0]) - T.mulp(corners[2])
side2g = T.mulp(corners[0]) - T.mulp(corners[1])
side3g = z_max - z_min
new_size = Metashape.Vector([side2g.norm()/s, side1g.norm()/s, side3g/s])
new_region.size = new_size
horizontal = side2
vertical = side1
normal = cross(vertical, horizontal)
horizontal = -cross(vertical, normal)
vertical = vertical.normalized()
R = Metashape.Matrix ([horizontal, vertical, -normal])
new_region.rot = R.t()
chunk.region = new_region
print("Region set to {:.3f} - {:.3f} Z range".format(z_min, z_max))
return 1
label = "Custom menu/Set min&&max Z for region"
Metashape.app.addMenuItem(label, set_region)
print("To execute this script press {}".format(label))