marcomusy / vedo

A python module for scientific analysis of 3D data based on VTK and Numpy
https://vedo.embl.es
MIT License
2.04k stars 265 forks source link

cannot correctly adjust positions of axis titles #598

Closed JianboLong closed 2 years ago

JianboLong commented 2 years ago

Hello, @marcomusy

I am trying to visualize .vtu files from a specific camera view such that it feels that a 2-D perspective mesh only exist. The vtu files contain all 3 coordinates by with y=0. I could ajust the camera view for my purpose, however, the axes' titles and labels are "out of mesh plane" and appear to be missing, as shown in the pictures here captured from a few different camera angles. The example code is attached. The source code of Axes object seems to suggest many parameters (e.g., xTitleOffset, yrange, etc ) are interacting with each other. Any solution to this ? Thanks.

true_model_1_shot1 2-D perspective view, zTitle appears to be missing

true_model_1_shot2 true_model_1_shot3 2-D perspective view, zTitle and its labels are out of x-z plane

Minimum-work-example of code:

#!/usr/bin/env python3

import numpy as np
## see https://vedo.embl.es/ for vedo module
from vedo import UGrid, show, screenshot, settings, Picture, Text2D, Text3D, \
    Arrow, Plotter
#from wand import image
settings.defaultFont = 'Theemim'
settings.useParallelProjection = True # avoid perspective parallax
settings.multiSamples=8

vtu_file = "true_model_1"
Is_full_mesh = 0
mesh_file = vtu_file + ".vtu"

# unstructured grid object
ug = UGrid(mesh_file)

picture_file = vtu_file + ".png"
print( "writing file: " + picture_file)
# tomesh: Build a polygonal Mesh from the current Grid object.
if Is_full_mesh > 0:
    msh = ug.tomesh().lineWidth(1).lineColor([7, 15, 190])
else:
    msh = ug.tomesh().lineWidth(4).lineColor([7, 15, 190])

xlabels = [(-40000, '-40000'), (-20000, '-20000'), (0, '0'), (20000, '20000'), (40000, '40000')]
zlabels = [(-50000, '-50000'), (-25000, '-25000'), (0, '0'), (15000, '15000')]
# make a dictionary of axes options
axes_opt = dict(
    xyGrid=False,
    yzGrid=False,
    zxGrid=False,
    zxGridTransparent=True,
    showTicks=True,
    xtitle='Easting (m)',
    xTitlePosition=0.6,  # distance along axis
    xTitleOffset=[0.0, 1.0, 0.0],   # distances from axes
    #xTitleRotation=[0, -90, 0],
    #xLabelRotation=[0, 90, 0],
    xValuesAndLabels=xlabels,
    xLabelSize=0.018,
#    xrange=msh.xbounds(),
    xrange=[-40000, 40000+2000],  # range of values of x-axis
    xAxisRotation=90,  # rotate X axis elements (ticks and labels) around X axis.
#    ytitle='',
#    yTitlePosition=0.3,  # y is not used
#    yTitleOffset=0.2,
    yrange=[0, 5000],   # random values here; needed to ajust xTitleOffset; see source code for proper value
    ztitle='Northing (m)',
    zTitlePosition=0.65,
    zValuesAndLabels=zlabels,
#    zLabelRotation=90,
    zLabelSize=0.018,
#    zrange=msh.zbounds(),
    zrange=[-50000, 15000 + 2000],
    axesLineWidth=2,

    xUseBounds=False,
    yUseBounds=False,
    zUseBounds=False,
)

# add texts
# arrow = Arrow(startPoint=(504000, 6413500, 512),
#               endPoint=(504800, 6414150, 512),
#               s=3, c='w', res=200)

plt = Plotter()
plt.camera.SetFocalPoint( [0,0,0] )
plt.camera.SetPosition( [0,-5000,0] )
plt.camera.SetViewUp( [0,1,0] )
size = [3940, 2160]
plt.show(msh, axes=axes_opt, size=size, interactive=True, zoom=1.2)

screenshot(picture_file)

true_model_MWE.zip

marcomusy commented 2 years ago

sorry i don't understand.. you don't have a z depth in the file how should be the z-axis visible..? and if it's 2D in the xy plane the z is irrelevant anyway..

JianboLong commented 2 years ago

sorry i don't understand.. you don't have a z depth in the file how should be the z-axis visible..? and if it's 2D in the xy plane the z is irrelevant anyway..

The coordinates are 3D and have a z depth there. It's just that the y coordinates are all 0. As such, the mesh is essentially a 2D mesh.

marcomusy commented 2 years ago

I think this is probably a bug... but in any case you can always modify everithing in the axes manually by unpacking:

axes_opt = dict(
    xyGrid=False,
    yzGrid=False,
    zxGrid=False,
    zxGridTransparent=True,
    showTicks=True,
    xtitle='x - Easting (m)',
    xTitlePosition=0.6,  # distance along axis
    xTitleOffset=[0.0, 1.0, 0.0],   # distances from axes
    #xTitleRotation=[0, -90, 0],
    #xLabelRotation=[0, 90, 0],
    xValuesAndLabels=xlabels,
    xLabelSize=0.018,
#    xrange=msh.xbounds(),
    xrange=[-40000, 40000+2000],  # range of values of x-axis
    xAxisRotation=90,  # rotate X axis elements (ticks and labels) around X axis.
    ytitle='',
#    yTitlePosition=0.3,  # y is not used
#    yTitleOffset=0.2,
    yrange=[0, 5000],   # random values here; needed to ajust xTitleOffset; see source code for proper value
    zValuesAndLabels=zlabels,
    ztitle='z - Northing (m)',
    zTitlePosition=0.65,
    zTitleOffset=0,
    # zLabelRotation=90,
    zLabelSize=0.018,
    zLabelOffset=[0.9,0,0],
    zLabelRotation=0,
    zAxisRotation=-5,
#    zrange=msh.zbounds(),
    zrange=[-50000, 15000 + 2000],
    axesLineWidth=2,
    # xUseBounds=False,
    # yUseBounds=False,
    # zUseBounds=False,
)
axes = Axes(**axes_opt) #############

for a in axes.unpack():
    #print(a.name)
    if 'ztitle' in a.name:
        a.shift(-2000, 5500, 0)

plt = Plotter()
plt.show(msh, axes)

Screenshot from 2022-02-21 22-15-22

JianboLong commented 2 years ago

Thanks for the temporary solution above.

I can guess why the y-shift is 5500 here:

for a in axes.unpack():
    #print(a.name)
    if 'ztitle' in a.name:
        a.shift(-2000, 5500, 0)

What about x- and z-shifts here ? Why these numbers ?

marcomusy commented 2 years ago

sorry for the late reply.. the numbers are the shifts in world units... but it's basic trial & error until you get the desired output..