Agisoft Metashape
Agisoft Metashape => Python and Java API => Topic started by: andrevall on March 29, 2021, 01:23:50 PM
-
Hello everyone,
I have a bunding box of which the following quantities are known: center coordinates (northing and easting), width, height and rotation angle, as shown below:
(https://i.imgur.com/pl7amMR.png)
The problem is that all the quantities (center, size) are expressed in the chunk's geographic coordinate system (in this case EPSG:7416).
I would like to set the reconstruction region (chunk.region) using this rectangle, but the units need to be converted to the local reference system first. Furthermore, the rotation angle needs to be converted into a rotation matrix, by assuming that the rotation around the other axes is zero (there is rotation only on the xy plane).
Does anyone have any idea of how to perform (using Python) this conversion, so that I can set:
- chunk.region.center
- chunk.region.size
- chunk.region.rot
starting from a rectangle expressed in the geographic CRS?
The region center.z value, and the size.z value should remain unchanged, only the xy values must be changed according to the rectangle.
I would like to thank anyone in advance,
Andrea
-
Hello Andrea,
Please check, if the following script solves the task.
The required input:
ROTATION - rotation angle in degrees,
WIDTH, DEPTH and HEIGHT in meteres for the bounding box size (width - dimension along X axis, when rotation is zero).
XYZ - coordinates of the bounding box center in the chunk's coordinate system.
import Metashape, math
ROTATION = 75 #in degrees
s = math.sin(ROTATION * math.pi / 180.)
c = math.cos(ROTATION * math.pi / 180.)
ROT_z = Metashape.Matrix([[c, -s, 0], [s, c, 0], [0, 0, 1]])
WIDTH = 200.0
DEPTH = 100.0
HEIGHT = 20.0
X = 12.465076
Y = 47.195569
Z = 620.05
CENTER = Metashape.Vector([X, Y, Z])
chunk = Metashape.app.document.chunk
crs = chunk.crs
T = chunk.transform.matrix
new_region = Metashape.Region()
new_center = CENTER #input values in chunk's crs
new_center = T.inv().mulp(crs.unproject(new_center))
new_size = Metashape.Vector([WIDTH, DEPTH, HEIGHT])
m = crs.localframe(T.mulp(new_center)) * T
R = m.rotation() * (1. / m.scale())
new_rotation = R.t() *ROT_z
new_region.rot = new_rotation
new_region.center = new_center
new_region.size = new_size
chunk.region = new_region
print("Script finished")
-
As always, thank you very much Alexey, that was very helpful! The code worked perfectly, but I noticed that it is also required to scale the region size. The complete working code, for anyone who might be interested is as follows:
def placeRegion(center,size,angle):
crs = chunk.crs
T = chunk.transform.matrix
center = Metashape.Vector((center[0],center[1],center[2]))
center = T.inv().mulp(crs.unproject(center))
m = crs.localframe(T.mulp(center)) * T
R = m.rotation() * (1. / m.scale())
size = Metashape.Vector((size[0],size[1],size[2])) / m.scale() # scaling the size is required
angle = np.radians(angle)
rot = Metashape.Matrix([[np.cos(angle), -np.sin(angle), 0], [np.sin(angle), np.cos(angle), 0], [0, 0, 1]])
rotation = R.t() * rot
chunk.region.rot = rotation
chunk.region.center = center
chunk.region.size = size
where:
center = (X,Y,Z) # in CRS coordinates
size = (width,depth,height) # in meters
angle = float # rotation angle of the region (in degrees)
-
Hello Andrea,
Thank you for the correction.