How can i save the image that appear in the right of the screen

1024
15
01-16-2018 08:36 AM
Amnahalabi
New Contributor II

15 Replies
ThomasFuchs
Esri Regular Contributor

Thank you for this question.
With a custom Python script, there is a way to accomplish this task.

Copy the attached script into your workspace, and add it to the scrips menu:

'''
Created on Oct 31, 2017
Modified on Apr 4, 2018 
@author: Esri R&D Zurich
'''
from scripting import *
import math

# get a CityEngine instance
ce = CE()

hRes = 1080

def getCamera(view):
    camPos      = view.getCameraPosition()
    camRot      = view.getCameraRotation()
    camAoV      = view.getCameraAngleOfView()
    camPoI      = view.getCameraPoI()
    camPoIDist  = math.sqrt(math.pow(camPoI[0]-camPos[0],2)+ \
                            math.pow(camPoI[1]-camPos[1],2)+ \
                            math.pow(camPoI[2]-camPos[2],2))
    camPersp    = view.getCameraPerspective()
    return camPos,camRot,camAoV,camPoIDist,camPersp

def setCamera(view,camPos,camRot,camAoV,camPoIDist,camPersp = True):
    view.setCameraPosition(camPos[0],camPos[1],camPos[2])
    view.setCameraRotation(camRot[0],camRot[1],camRot[2])
    view.setPoIDistance(camPoIDist)
    view.setCameraAngleOfView(min(160.0,camAoV))
    view.setCameraPerspective(camPersp)

def getViewshed(viewshed):
    vsPos   = ce.getObserverPoint(viewshed)
    vsRot   = [0.0, 0.0, 0.0]
    if ce.isViewshed(viewshed):
        vsRot[0]    = ce.getTiltAndHeadingAngles(viewshed)[0]
        vsRot[1]    = -ce.getTiltAndHeadingAngles(viewshed)[1]
        vsAoV       = ce.getAnglesOfView(viewshed)[0]
        vsPoIDist   = ce.getViewDistance(viewshed)
        vsRatio     = vsAoV/ce.getAnglesOfView(viewshed)[1]
    elif ce.isViewDome(viewshed):
        vsAoV       = 360.0
        vsPoIDist   = ce.getViewDistance(viewshed)
        vsRatio     = 1
    elif ce.isViewCorridor(viewshed):
        vsPoI       = ce.getPOI(viewshed)
        vsRot[0]    = math.atan2(vsPoI[1]-vsPos[1], \
                                math.sqrt(math.pow(vsPoI[0]-vsPos[0],2)+ \
                                math.pow(vsPoI[2]-vsPos[2],2)))*180/math.pi
        vsRot[1]    = -math.atan2(vsPoI[0]-vsPos[0], \
                                  -(vsPoI[2]-vsPos[2]))*180/math.pi
        vsAoV       = ce.getAnglesOfView(viewshed)[0]
        vsPoIDist   = math.sqrt(math.pow(vsPoI[0]-vsPos[0],2)+ \
                                math.pow(vsPoI[1]-vsPos[1],2)+ \
                                math.pow(vsPoI[2]-vsPos[2],2))
        vsRatio     = vsAoV/ce.getAnglesOfView(viewshed)[1]
    else:
        return
    vsName  = ce.getName(viewshed)
    return vsPos,vsRot,vsAoV,vsPoIDist,vsRatio,vsName

def snapshot360(view,vsName):
    # make six square snapshots
    view.setCameraAngleOfView(90.0)
    vdAoV = [(0,0),(0,90),(0,180),(0,-90),(90,0),(-90,0)]
    suffixes = ["_f","_l","_b","_r","_u","_d"]
    for i, suffix in enumerate(suffixes):
        view.setCameraRotation(vdAoV[i][0],vdAoV[i][1],0)
        view.snapshot(ce.toFSPath('images/'+vsName+suffix+'.png'),hRes,hRes)

def snapshotViewshed(view,viewshed):
    # get initial camera parameters
    camPos,camRot,camAoV,camPoIDist,camPersp = getCamera(view)
    # get viewshed parameters
    vsPos,vsRot,vsAoV,vsPoIDist,vsRatio,vsName = getViewshed(viewshed)
    if ce.isViewDome(viewshed):
        snapshot360(view,vsName)
    else:
        # set camera to viewshed parameters
        setCamera(view,vsPos,vsRot,vsAoV,vsPoIDist)
        # make a snapshot
        view.snapshot(ce.toFSPath('images/'+vsName+'.png'),hRes*vsRatio,hRes)
    # reset camera to initial camera parameters
    setCamera(view,camPos,camRot,camAoV,camPoIDist,camPersp)
    
if __name__ == '__main__':
    
    # get selected viewsheds, view domes and view corridors
    view            = ce.getObjectsFrom(ce.get3DViews())[0]
    viewsheds       = ce.getObjectsFrom(ce.selection(),ce.isViewshed)
    viewdomes       = ce.getObjectsFrom(ce.selection(),ce.isViewDome)
    viewCorridors   = ce.getObjectsFrom(ce.selection(),ce.isViewCorridor)
    
    # preparations
    initialSelection = ce.selection()
    ce.setSelection([])
    for al in ce.getObjectsFrom(ce.scene,ce.isAnalysisLayer):
        ce.setLayerPreferences(al,"Visible",False)
    tmpLayer = ce.addAnalysisLayer('TEMP Analysis Layer')
    
    # make snapshots
    for viewshed in (viewsheds+viewdomes+viewCorridors):
        if ce.isViewCorridor(viewshed):
            ce.setLayerPreferences(tmpLayer,"Visible",True)
        else:
            ce.setLayerPreferences(tmpLayer,"Visible",False)
        tmpViewshed = ce.copy(viewshed,False,tmpLayer)
        snapshotViewshed(view,tmpViewshed[0])
        ce.delete(tmpViewshed)
    
    # clean up
    ce.delete(tmpLayer)
    for al in ce.getObjectsFrom(ce.scene,ce.isAnalysisLayer):
        ce.setLayerPreferences(al,"Visible",True)
    ce.setSelection(initialSelection)
    
Luiz_AmadeuCoutinho
Occasional Contributor III

Hi Thomas

EDIT: How it works? I´m just trying to use the script and after add and run were the snapshot was saved?

I found the snapshot. It´s not the same image from View Dome (360 perspective).

I´m not python expert but...it´s possible to get exactly the same view? Here my printscreen (I got poor quality from printscreens)

I´m creating 360 panoramas from my project using printscreens from DomeView (low quality) and the script will be really usefull

Here a sample of my CityEngine project in 360 panorama(Low quality) Roundme - create Stock 360 VR panoramic pictures virtual tour online   . Also it´s possible to upload the same image on Facebook to view 360 on smartphones.

0 Kudos
ThomasFuchs
Esri Regular Contributor

Hi Luiz

Thank you for your input. I changed the script in my post above to add export support for 360 panoramas from CityEngine View Domes.

For View Domes it now creates six 90° x 90° square snapshots (back, down, front, left, right, up).

These can be stitched and re-projected from cubemap to equirectangular format with common VR/panorama tools.

Here is a link to a free online tool: 360Toolkit - Convert and View Panorama Pictures Instantly 

Luiz_AmadeuCoutinho
Occasional Contributor III

Amazing

I´ll try in few minutes and I´ll share here the result

0 Kudos
Luiz_AmadeuCoutinho
Occasional Contributor III

It works very well

Here the new panorama  Roundme - create Stock 360 VR panoramic pictures virtual tour online 

Thank you so much.

DavidWasserman
Regular Contributor

I have been looking for this as well! Thanks Thomas!

David Wasserman, AICP
0 Kudos
DavidWasserman
Regular Contributor

Hi Thomas, 
Is there any concern with me adapting this as a distributed script?
geodesign-toolkit-gis-cityengine-integration-tools/Scripts at master · Holisticnature/geodesign-tool... 

I was thinking about put a folder call "Esri Scripts". One concern that I had is a lot of the geonet snippits have no license attached. Should I assume it is Apache 2.0 like most esri projects? 

David Wasserman, AICP
0 Kudos
ThomasFuchs
Esri Regular Contributor

Code snippets published on Esri GeoNet protected by any license, need to respect the associated usage rights. They must be marked accordingly by the publisher. Any license violations need to be reported to the forum administrator. 

Generally, CityEngine CGA and Python snippets published by Esri employees, are meant to support our customers in achieving their goals in accordance with the product's software license. For further information please visit Esri Legal Information | Overview 

In your case distribution of GeoNet snippets under the Apache 2.0 license in a folder called "Esri Scripts" is appropriate.

DavidWasserman
Regular Contributor

Hi Thomas, 

Understood. This is the set up I did. If you have any required edits you can let me know. 

geodesign-toolkit-gis-cityengine-integration-tools/snapshotSelectedViewsheds.py at master · Holistic... 

I made minor edits to the script (I think for domes I need a small edit or two). I might work with it a little more to iterate through layers/ scenarios (not sure the API exposes scenarios yet). 
Thanks for sharing this. I have a sample image I did in a street scene. 

This is awesome, and I wish it was a one button click feature. 

David Wasserman, AICP