It looks like in the field of representations there are some changes/improvements with PV5.8 (https://kitware.github.io/paraview-docs/v5.8.0/cxx/MajorAPIChanges.html), and indeed I have now successfully recompiled all my plugins and custom application with that version: Most things are looking fine, but representations are not working any more. Some are derived from the “Surface with Edges” represenation of the Render view, and some are customized “Spreadsheet views” (which I would always prefer to call “Table view” because a spreadsheed should have some calculation facilities in my understanding - but anyway…).
In the past I never fully understood what I was doing, but “somehow” managed to get different special representations running - which are now not working any more.
From the descriptions of the updates I conclude that deriving representations should be easier now, and if I look into the “MySpecialRepresentation” example it looks really pretty easy: You simply write a “mapper” class, and then “throw” it into a very simply custom representation class, like this:
// Replace the mappers created by the superclass.
this->Mapper = vtkMySpecialPolyDataMapper::New();
this->LODMapper = vtkMySpecialPolyDataMapper::New();
// Since we replaced the mappers, we need to call SetupDefaults() to ensure
// the pipelines are setup correctly.
Ok, I will simply try myself now, but I can also ask directly: Is this really now the “receipe” to derive representations, no matter whether it is for the render view or spreadsheet view or maybe also charts?
Would be great indeed! Dealing with pieces are no issue for my cases, nor is data delivery from server to client - but of course the entire architecture is built to support all these things.
vtkMySpecialRepresentation hasn’t really changed for 5.8. Hence, if all you were changing was your mapper, then that pattern is indeed workable. The thing that’s new in 5.8 is how cache is handled. Prevously, representations created a
vtkPVCacheKeeper class to manage cache and add it on the data-processing pipeline in the Representation. Now, the view take care of caching.
Thanks for the quick reply!
I will have to simply try then. I never created consciously any kind of cache keeper class, nor did I follow that “mapper only” approach - simply because I did not understand what the purpose of the different “kind of filters” (of which the mapper is one) are actually doing.
What I tried so far are four different “representations”:
a “georeferenced texturing representation” is: take a polydata (like triangulated topo surface) and a texture (like a georeferenced aearial photo, with georef info being extracted through the GDAL functions) and display it instead of the common “surface” representation. This is basically: take the object that would normally be passed to the output, but first add a “texture mapping” filter to it, with the texture as an attribute - and then make sure that the rendering is taking the output of this texture mapping filter instead of the original.
then a “category representation” that takes an unstructured grid and an attribute value that serves as a “category”. Then the unstructured grid is stripped down in such a way that only those blocks are shown where the chosen “category” has the chosen “value”. This is a similar exercise as the above: take the input unstructured grid and pass it through a filter that extracts only the cells of interest and again pass the result to the renderer.
an adapted “table view” is derived from the “Spreadsheet View” and only changes the ordering of the columns in such a way that it fits better for the problems I am dealing with, instead of being alphabetic “no matter what”. That turned out to be a bit more difficult even because I realized that certain functionalities of the “spreadsheet view” - like the sorting for example! - are hidden so deep inside certain “private” regions that they have to be cloned and adapted instead of simply derived. (That one still works now with 5.8!)
finally a “summary representation” that is again a “Spreadsheet”, but summarizes the data in a specific way. Yes, the same thing can be done with a filter (and I have that one as well), but the advantage is that the “summary representation” has the option to work on selected cells only - and with a specialized representation the user can manually select and unselect cells, and watch at the same time how the summary/averages are affected.
It looks like from these 4, number 1, 2 and 4 have to be rewritten/reorganized. Since I did not find any instructions about how to write own representations, I just tried - and managed to get it done “somehow”
What be of course of interest would be some kind of guide that “simply” tells what is the path of say a data object (like a polydata, unstructured grid or table) through different “processing units” until it finally ends up in the actual graphics output. With this it would be easier to find the right location to “plug in” the one or other class or function that applies another processing step. This includes the question what the terms “mapper”, “actor” and so on actually mean - which are probably like a mother tongue for longterm Kitware programmers!
Just already answering myself: Having a bit more close look into the mapper classes, I am getting the impression that for my first two representations I should have (and will now try to) simply derive a mapper class with more or less the “GetInput” function adapted in such a way that it takes the original input object, apply the actions that I want to do, and pass the result to the caller.
My representation class would then only have to provide the necessary parameters to that mapper and make sure that repainting happens if something has changed.
Maybe my life is even getting easier now with this change!
Let’s just consider the first type: georeferenced texturing representation. From your description, it seems to me all you really want to do is add a “pre-processing” filter to the standard geometry representation (aka
vtkGeometryRepresentationWithFaces). Is that correct? In otherwords, in ParaView could have simply created this
TextureMappingFilter and then shown that in the view to the same effect? If so, you have two options:
- do the texture mapping as part of preparing-data-for-rendering
- do the texture mapping as part of the rendering
1 is preferable since that would be done only once when the upstream pipeline changes. To do that, one approach is to subclass
vtkPVGeometryFilter and then replace
this->GeometryFilter with your subclass (similar to how the mapper is replaced in
vtkMySpecialRepresentation). In your
vtkPVGeometryFilter-subclass, you can pre-process or post-process the result obtained from the superclass in
RequestData to add the texture coordinates you want.
Another approach is to override
GetInternalOutputPort in your representation subclass and there return the output port from your texture-mapping-filter. Don’t forget to set your texture-mapping-filter’s input using the real input port in
RequesData. Take look at this to understand why that will result in you changing the input data used by representation pipeline.
Thanks a lot for your instructions! I already tried and realized that my previous attempt with the mapper was a dead-end road.
And yes: Basically I want to preprocess the geometric object to be displayed, and this is true for both the first and the second (slightly more complex) of my “representation” filters. Which means that your instructions are fully to the point, and I hope to get it done quickly now - because all the processing code is already there and only needs to be “connected” in a slightly different way.
For me it is also clear that your variant 1) looks more logical in my case. Only I have to take care that changes in the “display” properties will trigger a proper refresh of not only the rendering, but also the data preparation step.
Ah! that changes everything . Is it one specific display property or several ? If it’s just one or two and are not expected to change too frequently, then just calling
this->MarkModified() in those display property related methods in your representation subclass should be adequate. Otherwise an approach where the filter gets inserted on the “rendering” side, closer to the mapper may indeed be more appropriate.
I guess that MarkModified() should do then!
Actually some parts of the setup resemble now already the way how I “somehow” managed with the older versions, but this was without the subclassing of a geometry filter which makes it much less “hacky” and more clear and transparent!
Next I will be at the computer I still have to find out where the SetTexture() call has to happen: In the old solution I did that in the ProcessViewRequest() function of the vtkAtgTexturedRepresentation class.
Thanks Utkarsh: the texture is there again - and definitely in a less “hacky” way now!
Thanks to your hints, also the “category representation” is now working again and definitely more “clean” than before:
(In this example, cells were selected “in the volume” by scrolling through the attribute “Level” and on each level adding another “polygon selection” - just to show a possible use of that representation! Another one would be to “scroll” through the geological units - if the “Geology” attribute was chosen.)