Agisoft Metashape

Agisoft Metashape => Python and Java API => Topic started by: Thibaud Capra on March 09, 2017, 05:00:48 PM

Title: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 09, 2017, 05:00:48 PM
Hello,
I'm currently willing to be exporting shapes in a different coordinate system than my project's.
My photos are in WGS 84 so are my dense clouds etc. but I can export them in Lambert 93 / CC 48 without any issue. The only exception is the shapefiles I have, is there any way to do it?

Some coworker suggested me to use ogr2ogr from GDAL (http://www.mercatorgeosystems.com/blog-articles/2008/05/30/using-ogr2ogr-to-re-project-a-shape-file/) but I don't really understand how.

Any help is appreciated.
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 09, 2017, 05:03:58 PM
Hello Thibaud,

Do you have a EPSG code for this system?
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 09, 2017, 05:08:06 PM
Hello Alexey,

Sure: Lambert 93 / CC48 code is EPSG::3948
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 09, 2017, 05:54:18 PM
Hello Thibaud,

Then you probably should use the following:
Code: [Select]
crs = PhotoScan.CoordinateSystem("EPSG::3948")
chunk.exportShapes(path, projection = crs)
Doesn't it work correctly on your projects?
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 13, 2017, 11:29:29 AM
Hello Alexey,

On my projects, I choose the crs during the exports individually, ie. the orthomosaics are exported as follows:

Code: [Select]
        # Export Orthophoto
        path_ortho = path_export_chk + chunk.label + "_Ortho" + ".jpg"
        chunk.exportOrthomosaic(path_ortho, format = "jpg",
        raster_transform = PhotoScan.RasterTransformNone,
        projection = PhotoScan.CoordinateSystem("EPSG::3948"),
        write_world = True)

I tried using your code (PhotoScan version 1.2.6) and it's not working, projection = crs being and incompatible keyword. Here's my current code, more or less working. More less than more though, as I get the error message "Can't export shapes." when running it.

Any idea why?

Code: [Select]
import os
import PhotoScan

print(""">>> Initialisation du script IV <<<""")

doc = PhotoScan.app.document

path_export = PhotoScan.app.getExistingDirectory("""Spécifiez le dossier
 contenant les exports en fin de traitement""")
path_export += "\\"

print(""">>> Génération des fichiers de sortie <<<""")

for chunk in doc.chunks:
        # Create a new folder
        path_export_chk = path_export + "_SHP"
        if not os.path.exists(path_export_chk):
            os.makedirs(path_export_chk)
        path_export_chk += "\\"

        path_export_shp = path_export_chk + chunk.label
        if not os.path.exists(path_export_shp):
            os.makedirs(path_export_shp)
        path_export_shp += "\\"

        crs = PhotoScan.CoordinateSystem("EPSG::3948")
        chunk.exportShapes(path_export_shp)
       
        PhotoScan.app.update()

print(""">>> Fichiers exportés ! <<<""")

doc.save()

PhotoScan.app.update()
print(""">>> Script Partie IV terminé <<<""")
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 15, 2017, 01:11:34 PM
Bumping topic, is it because my shapes are in a different layer that is not the default one?
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 15, 2017, 01:23:11 PM
Hello Thibaud,

In the version 1.2.6 it wasn't possible to specify the export coordinate system for shapes, so it has been exported in actual shapes.crs system.

In your code line crs = PhotoScan.CoordinateSystem("EPSG::3948") is meaningless, as crs variable is not utilized after that. But export problem seems to be related to the incorrect path specified. The last modification of the export path variable is path_export_shp += "\\" - it means that the path is not ending with the file extension, for example, ".shp", but is the path to the folder.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 15, 2017, 01:29:02 PM
Hello Alexey,

I thought that since the exportShapes command created multiple files with different types, it did not require any extension for the path.

Thanks for your help, I'll run it ASAP and see if the fix works.
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 15, 2017, 01:32:58 PM
Hello Thibaud,

There could be additional files if you are saving in .shp format, but you still need to specify the full export path including filename to that .shp file.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 15, 2017, 01:39:24 PM
Hello Alexey,

Thanks for the explicit answer!

To get my shapes in the coordinate system I want, could there be a way to get them by transforming the project's coordinate system from WGS84 to L93/CC48 before exporting the files? If so, how can I do it in 1.2.6 ?
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 15, 2017, 02:00:28 PM
Hello Thibauld,

Switching the coordinate system of the chunk wouldn't help, because the shape coordinate system is stored separately. I think the only way inside PhotoScan would be transforming the coordinates of every shape in the project from the source coordinate system to the new one.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on March 15, 2017, 02:05:17 PM
Hello Alexey,

How would you do this in 1.2.6? I understood you can't change it during exports?
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on March 15, 2017, 03:33:29 PM
Hello Thibaud,

I would modify the coordinates of the shape vertices recalculating the coordinates from WGS84 to L93/CC48, then (when all the modifications are performed) re initialize shapes.crs to the new coordinate system and then export shapes.

For testing you can use a single simple shape.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 12, 2017, 07:06:49 PM
Hello Alexey,

I'm kind of bumping this topic because I haven't figured out how to do it.

A simple piece of code exporting the shape from whatever his coordinate system is (here I believe it's WGS84) into L93/CC48 would do... Could you help me once again ?
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 13, 2017, 12:21:33 PM
I guess I should use something the like of:

Code: [Select]
PhotoScan.Shapes.crs.transform(EPSG::4326, EPSG::3948)
PhotoScan.Shapes.crs.update

Then I'd export my shapes, right?
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 13, 2017, 12:44:44 PM
Hello Thibaud,

You need to loop through all the vertices of every shapes and convert the coordinates from EPSG::4326 to EPSG::3948. Then change chunk.shapes.crs.
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 13, 2017, 01:06:19 PM
I think it should be something like the following:

Code: [Select]
chunk = PhotoScan.app.document.chunk
shapes = chunk.shapes
source = shapes.crs
out = PhotoScan.CoordinateSystem("EPSG::3948")
for shape in chunk.shapes:
      shape.vertices = [PhotoScan.CoordinateSystem.transform(v, source, out) for v in shape.vertices]
shapes.crs = out
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 12:11:41 PM
Hello Alexey,

Thanks for your precious help, as usual!

I'm also trying to export my shapes, using chunk.exportShapes as you recommended. My question is, if I have multiple shape layers, will it create one shape file per layer or one merged shape file?

I'd like to keep my shapes separated according to the shape layers, using maybe the shape layer's name to identify them. Is it possible?
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 12:18:16 PM
Hello Thibaud,

In chunk.exportShapes() function there's optional "groups" argument that can be used, if you wish to export only certain layers. Otherwise, all shape layers will be saved to the same file.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 01:46:43 PM
Hello Alexey,

I don't get the shape group creation part.
Are groups the corresponding layers by default? Or do I have to assign them first to each different ShapeGroup key? If need be, how do I do that?
For example, I made a small test project with two layers I want to export (see below) as two different shape files.
(http://i.imgur.com/FAyYQr6.png)

For now, I have the following code:

Code: [Select]
import os, PhotoScan

doc = PhotoScan.app.document
chunk = doc.chunk
shapes = chunk.shapes
source = shapes.crs
out = PhotoScan.CoordinateSystem("EPSG::3948")
type_chunk = ['Green']

for chunk in doc.chunks:
    if not any(type_chunk[0] in chunk.label for type_chunk in type_chunk):
        for shape in chunk.shapes:
            shape.vertices = [PhotoScan.CoordinateSystem.transform(v, source, out) for v in shape.vertices]
        shapes.crs = out
    print("""Les SHP de """ + chunk.label + """ ont été transformées avec succès !""")

for chunk in doc.chunks:   
    for shape in chunk.shapes:
        if not any(type_chunk[0] in chunk.label for type_chunk in type_chunk):
            chunk.exportShapes(path = "C:\\PFE_CAPRA\\Essais_Shapes\\Green.shp", groups = ShapeGroup(key = 1))
            chunk.exportShapes(path = "C:\\PFE_CAPRA\\Essais_Shapes\\Approche.shp", groups = ShapeGroup(key = 2))

Thanks
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 02:10:03 PM
Hello Thibaud,

I would rather use something like the following:
Code: [Select]
for layer in chunk.shapes.groups:
      chunk.exportShapes(path, groups = layer)
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 03:12:17 PM
Hello Alexey,

Code: [Select]
for layer in chunk.shapes.layers:
      chunk.exportShapes(path, groups = layer)

I think this layer export method works in 1.3.x, I am currently using PhotoScan 1.2.6 Build 2834... I have the following error message:

Traceback (most recent call last):
File "C:\PFE_CAPRA\Essais_Shapes\Script_Shapes.py", line 18, in <module>
for layer in chunk.shapes.layers:
AttributeError: 'PhotoScan.Shapes' object has no attribute 'layers'


Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 03:20:18 PM
Hello Thibaud,

It was my mistake, should be chunk.shapes.groups.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 04:52:01 PM
Hello Alexey,

I think this layer grouping is too recent, as I have the following error now:

     chunk.exportShapes(path, groups = layer)
 TypeError: 'groups' is an invalid keyword argument for this function


Or is it some error in my code?

Code: [Select]
import os, PhotoScan

doc = PhotoScan.app.document
chunk = doc.chunk
shapes = chunk.shapes

path = "C:\\PFE_CAPRA\\Essais_Shapes\\Shapes"
for chunk in doc.chunks:   
    for layer in chunk.shapes.groups:
        chunk.exportShapes(path, groups = layer)
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 04:56:21 PM
Hello Thibaud,

In the version 1.2.6 exportShapes() has only path and items arguments, so it seems that the code can be applied to version 1.3 only.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 05:04:58 PM
Hello Alexey,

Too bad, I'll see if I change the rest of the scripts I wrote to adapt it to 1.3.x to allow me to export automatically all my shapes, or stick to what I have for now and export my shapes the old-fashioned way, aka manually!

As usual, thanks for the great support!
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 05:06:44 PM
Hello Thibaud,

Alternative way in 1.2.6 could be removing all shape layers, except the required, export, then re-open of the project. Or duplicating the original chunk for each layer export and then removing the duplicate.
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 05:13:21 PM
Hello Alexey,

The problem is, I have shapes in multiple chunks, would this work in a for loop doing roughly this:

Code: [Select]
for chunk in doc.chunks:
    Delete all layers but one based on layer labels
    Export layer
    Reopen project
    Export next layer the same way
    Loop through chunks

Additional difficulty (but I found a way around for this one), it musn't loop through all the chunks but only those with some specific keyword in the chunk label.
Wouldn't closing the project reset the progress in the various chunks?

I'm aware of the fact that this is a very specific question, but my aim is to automatize as much of the processing as possible!
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 05:32:19 PM
Hello Thibaud,

Then you can consider using chunk duplicates:

for chunk in list(doc.chunks):
     loop though the index of the shape layers
           temp_chunk = chunk.copy()
           remove all layers but one
           export layer
           remove temp_chunk
Title: Re: Exporting shapes in a different coordinate system
Post by: Thibaud Capra on April 18, 2017, 05:40:00 PM
Hello Alexey,

Can I remove layers based on their labels? If so, how?
I'm using keywords in the labels to determine where to export the file. (The same way I use keywords in chunk labels to process different LODs in one batch)
Title: Re: Exporting shapes in a different coordinate system
Post by: Alexey Pasumansky on April 18, 2017, 05:51:30 PM
Hello Thubaud,

You can write a custom function:

Code: [Select]
def getShapeLayer(chunk, label):
     for layer in chunk.shapes.groups:
          if layer.label == label:
               return layer
     print("Label not found")
     return None