-
Notifications
You must be signed in to change notification settings - Fork 529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds option to DataSetFilters.glyph
to orient using vector or normal mode
#6824
base: main
Are you sure you want to change the base?
Conversation
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
DataSetFilters.glyph
to orient using vector or normal mode
if vector_mode == 'vector': | ||
alg.SetVectorModeToUseVector() | ||
elif vector_mode == 'normal': | ||
alg.SetVectorModeToUseNormal() | ||
else: | ||
raise ValueError(f"Invalid vector mode '{vector_mode}'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your contribution! Could you add some test code for this code? Other than that, it's perfect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tkoyama010 I was a little bit quick writing this fix... when I started making tests it is not as simple as I thought.
Looking at the vtk code in more detail it the SetVectorModeToUseNormal
doesn't change the way the glyphs are interpreted rather it changes to using an attribute on the vtk object inNormals... See here.
What confused me is the different behaviour between how normal is interpreted as a property of a pyvista geometry class and how that normal is used by the glyph filter...
import pyvista as pv
p1 = pv.PolyData(np.array([[0, 0, 0]]))
p1["norm"] = np.array([[1, 0, 0]])
p2 = pv.PolyData(np.array([[1, 1, 1]]))
p2["norm"] = np.array([[0, 1, 0]])
p3 = pv.PolyData(np.array([[2, 2, 2]]))
p3["norm"] = np.array([[0, 0, 1]])
disk1 = pv.Disc(center=[0, 0, 0], normal=[1, 0, 0], inner=0)
disk2 = pv.Disc(center=[1, 1, 1], normal=[0, 1, 0], inner=0)
disk3 = pv.Disc(center=[2, 2, 2], normal=[0, 0, 1], inner=0)
geom = pv.Disc()
p1 = p1.glyph(
geom=geom,
orient="norm",
)
p2 = p2.glyph(
geom=geom,
orient="norm",
)
p3 = p3.glyph(
geom=geom,
orient="norm",
)
view = pv.Plotter()
view.add_mesh(disk1, name="disk1", color="red")
view.add_mesh(disk2, name="disk2", color="green")
view.add_mesh(disk3, name="disk3", color="blue")
view.add_mesh(p1, name="p1", color="red")
view.add_mesh(p2, name="p2", color="green")
view.add_mesh(p3, name="p3", color="blue")
view.show()
If we use a glyph like arrow
import pyvista as pv
p1 = pv.PolyData(np.array([[0, 0, 0]]))
p1["norm"] = np.array([[1, 0, 0]])
p2 = pv.PolyData(np.array([[1, 1, 1]]))
p2["norm"] = np.array([[0, 1, 0]])
p3 = pv.PolyData(np.array([[2, 2, 2]]))
p3["norm"] = np.array([[0, 0, 1]])
disk1 = pv.Arrow(start=[0, 0, 0], direction=[1, 0, 0], )
disk2 = pv.Arrow(start=[1, 1, 1], direction=[0, 1, 0], )
disk3 = pv.Arrow(start=[2, 2, 2], direction=[0, 0, 1], )
geom = pv.Arrow()
p1 = p1.glyph(
geom=geom,
orient="norm",
)
p2 = p2.glyph(
geom=geom,
orient="norm",
)
p3 = p3.glyph(
geom=geom,
orient="norm",
)
view = Loop3DView()
view.add_mesh(disk1, name="disk1", color="red")
view.add_mesh(disk2, name="disk2", color="green")
view.add_mesh(disk3, name="disk3", color="blue")
view.add_mesh(p1, name="p1", color="red")
view.add_mesh(p2, name="p2", color="green")
view.add_mesh(p3, name="p3", color="blue")
view.show()
I found that if I rotate the geometry by 90 degrees before passing it to the glyph method it will give me the results I expect.
import pyvista as pv
p1 = pv.PolyData(np.array([[0, 0, 0]]))
p1["norm"] = np.array([[1, 0, 0]])
p2 = pv.PolyData(np.array([[1, 1, 1]]))
p2["norm"] = np.array([[0, 1, 0]])
p3 = pv.PolyData(np.array([[2, 2, 2]]))
p3["norm"] = np.array([[0, 0, 1]])
disk1 = pv.Disc(center=[0, 0, 0], normal=[1, 0, 0], inner=0)
disk2 = pv.Disc(center=[1, 1, 1], normal=[0, 1, 0], inner=0)
disk3 = pv.Disc(center=[2, 2, 2], normal=[0, 0, 1], inner=0)
geom = pv.Disc()
geom = geom.rotate_y(90)
p1 = p1.glyph(
geom=geom,
orient="norm",
)
p2 = p2.glyph(
geom=geom,
orient="norm",
)
p3 = p3.glyph(
geom=geom,
orient="norm",
)
view = pv.Plotter()
view.add_mesh(disk1, name="disk1", color="red")
view.add_mesh(disk2, name="disk2", color="green")
view.add_mesh(disk3, name="disk3", color="blue")
view.add_mesh(p1, name="p1", color="red")
view.add_mesh(p2, name="p2", color="green")
view.add_mesh(p3, name="p3", color="blue")
view.add_arrows(np.array([[0,0,0],[1,1,1],[2,2,2]]),np.array([[1,0,0],[0,1,0],[0,0,1]]),color='black')
view.show()
I noticed the same issue with the rectangle glyph and parametric ellipsoid depending on the aspect ratio of the ellipsoid. I can modify this PR to just rotate the geometry by 90 degrees in the y direction if "normals" is chosen but I am not sure if it would be better to use a different name.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6824 +/- ##
==========================================
- Coverage 97.49% 97.48% -0.02%
==========================================
Files 143 143
Lines 28181 28185 +4
==========================================
+ Hits 27476 27477 +1
- Misses 705 708 +3
|
I don't think it is worthwhile adding this change anymore, unless its worth adding a parameter to rotate the initial glyph orientation. But this can just be done to the glyph before passing it to the filter. Happy to update or for it to be closed. |
My understanding is that this option in the vtk filter changes the active attribute that is used to orient the object. The You can do Up to you on whether to continue on this or not. But either way, thank you for getting involved here! |
Overview
Add the ability to choose whether to orient with vector or normal model when using the DataSetFilters.glyph method. Default is vector mode which is consistent with the existing implementation.
resolve #6823
Details
Similar to recently added color_mode, as a flag allowing the user to specify the vector mode.