Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: andrevall on March 29, 2021, 01:23:50 PM

Title: CRS coordinates to Region coordinates
Post 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:

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
Title: Re: CRS coordinates to Region coordinates
Post by: Alexey Pasumansky on March 29, 2021, 04:36:28 PM
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.

Code: [Select]
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")
Title: Re: CRS coordinates to Region coordinates
Post by: andrevall on March 30, 2021, 04:12:45 PM
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:

Code: [Select]
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:

Code: [Select]
center = (X,Y,Z) # in CRS coordinates
size = (width,depth,height) # in meters
angle = float # rotation angle of the region (in degrees)
Title: Re: CRS coordinates to Region coordinates
Post by: Alexey Pasumansky on March 30, 2021, 04:46:04 PM
Hello Andrea,

Thank you for the correction.