[vtkusers] Writing (imaging) algorithm for which output extent has no relation with input extent.
David Gobbi
david.gobbi at gmail.com
Tue Jan 14 17:40:39 EST 2014
Well, maybe I can't convince you to give up on the Abort, but at least
consider calling VisibilityOn() and VisibilityOff() on your actors as an
alternative way of controlling the rendering. If visibility is off, then no
pipeline update occurs.
On Tue, Jan 14, 2014 at 3:15 PM, Maarten Beek <beekmaarten at yahoo.com> wrote:
> I do get a nice black renderwindow, because I set up the callback-observer
> connection sometime after the first render. But I get your point.
>
> If I create the pipeline and add the input before the render, everything
> works fine.
> The if statement is never true.
>
> I like my code better (stupid me?) when I add the input later, so it isn't
> shown automatically, but after a button press... don't understand why I
> cannot abort the render (even if it were to come from the interactor)...
>
>
>
>
> On Tuesday, January 14, 2014 5:04:43 PM, David Gobbi <david.gobbi at gmail.com>
> wrote:
> Like I said a couple emails ago, I think that the best choice is to
> not add the actors to the renderer until the data is loaded.
>
> If you abort the first render, then the window is likely to show
> whatever was left over in the GPU's pixel buffer. It might show
> black, it might show garbage, or it might show something from a recent
> websurfing session. In any case, I advise that you do not abort the
> first render. Let the window render a nice, black background like it
> should.
>
>
> On Tue, Jan 14, 2014 at 2:41 PM, Maarten Beek <beekmaarten at yahoo.com> wrote:
>> I almost have to thing working!
>>
>> One last question:
>> I added the following to the render callback class:
>>
>> virtual void RenderCallBack::Execute(vtkObject* obj, unsigned long
>> eventId, void* callData)
>> {
>> vtkRenderWindow* renderWindow = vtkRenderWindow::SafeDownCast(obj);
>> if( eventId == vtkCommand::StartEvent && NULL != renderWindow )
>> {
>> if( !m_pWidget->m_pDRRGenerator ||
>> !m_pWidget->m_pDRRGenerator->GetInputDataObject(0, 0) )
>> {
>> // if no input set, abort render
>> renderWindow->SetInAbortCheck(1);
>> return;
>> }
>>
>> <...>
>> }
>> }
>>
>> However, it looks like the renderwindow is rendered anyway...
>>
>> If I call GetRenderWindow()->GetInteractor()->EnableRenderOff(); it seems
>> to
>> be working as desired.
>>
>> But I think I want the interactor to be able to initiate renders, but how
>> do
>> I abort a render from the interactor?
>>
>> Thanks so much for your help today - Maarten
>>
>>
>>
>> On Tuesday, January 14, 2014 2:12:15 PM, David Gobbi
>> <david.gobbi at gmail.com>
>> wrote:
>> Just make sure you don't add the actor to the renderer in your
>> constructor. The actor should only be added after the data is loaded.
>> Or, if this isn't possible, you can just make a dummy data set to use
>> as the initial input.
>>
>> For the window/level, probably the best thing is to catch the
>> StartEvent from the render window. In the callback, manually call
>> Update() on your pipeline and set the window/level.
>>
>> On Tue, Jan 14, 2014 at 11:31 AM, Maarten Beek <beekmaarten at yahoo.com>
>> wrote:
>>> Thanks for all your help, David
>>>
>>> I removed RequestDataObject() from the algorithm. Still working fine and
>>> no
>>> speed difference. I am not surprised this was somewhat "vtk-illegal", a
>>> remainder from when the algorithm was inheriting from vtkAlgorithm (now
>>> vtkImageAlgorithm).
>>>
>>> I now have a different question:
>>> I have a QVTKWidget that has a pipeline to display the output image of
>>> the
>>> algorithm. I would like to set up the pipeline in the constructor of the
>>> QVTKWidget and make the connection with the algorithm at the start of the
>>> pipeline later. Of course, vtk starts complaining about a missing input
>>> that's required as soon as the QVTKWidget is displayed (and its
>>> renderwindow
>>> subsequently rendered). How do I solve this?
>>>
>>> I assume calls to vtkImageActor::GetProperty()->SetColorWindow(window);
>>> and
>>> similar in the pipeline should be made in a callback (inheriting from
>>> vtkCommand) each time the input to my algorithm is changed?
>>>
>>> The value for window is calculated from the range of an algorithm
>>> somewhere
>>> halfway the pipeline. The pipeline has several of these constants, just
>>> using SetColorWindow as an example.
>>>
>>> Maarten
>>>
>>>
>>> On Tuesday, January 14, 2014 1:02:51 PM, David Gobbi
>>> <david.gobbi at gmail.com>
>>> wrote:
>>> I really don't think you should be using RequestDataObject at all.
>>> Since it's an image filter, the fact that the output is a vtkImageData
>>> will be set in SetOutputPortInformation(), and the data object will be
>>> created automatically. The data type (e.g. float) and the
>>> WHOLE_EXTENT should be set in RequestInformation().
>>>
>>> Does your filter derives from vtkImageAlgorithm? Then the data should
>>> definitely be allocated in RequestData(). Calling SetExtent() after
>>> the memory has already been allocated makes no sense, because if the
>>> new extent is different from the old extent then you end up with an
>>> invalid data object. Allocate the data in the same way that
>>> vtkImageAccumulate allocates data, like this:
>>>
>>>
>>>
>>>
>>> outData->SetExtent(outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()));
>>> outData->AllocateScalars(outInfo);
>>>
>>> Calling AllocateScalars() is efficient because it will only
>>> re-allocate the data if the Extent changes, and as shown above, the
>>> Extent will always be the WHOLE_EXTENT.
>>>
>>> You can ignore the UPDATE_EXTENT() for the output, it is completely
>>> irrelevant to your particular filter and no matter what it is set to,
>>> allocating the WHOLE_EXTENT for your output is always safe. But you
>>> must still override RequestUpdateExtent() to set your input's update
>>> extent to your input's whole extent.
>>>
>>> David
>>>
>>>
>>>
>>> On Tue, Jan 14, 2014 at 9:58 AM, Maarten Beek <beekmaarten at yahoo.com>
>>> wrote:
>>>> I create data in RequestDataObject() with:
>>>>
>>>> vtkImageData* newoutput = vtkImageData::New();
>>>> outinfo->Set(vtkDataObject::DATA_OBJECT(), newoutput);
>>>> output->ReleaseData(); // so filters know it's empty
>>>> output->Delete();
>>>>
>>>> I've seen other filters do this as well. I've also seen it happen in the
>>>> constructor of the filter.
>>>>
>>>> I also allocate the memory for the output in RequestDataObject(). This
>>>> might
>>>> be a hack because should happen after setting extent in RequestData(),
>>>> but
>>>> it improves the speed somewhat. The size of the renderwindow determines
>>>> the
>>>> size of the output image (class has setter for this).
>>>>
>>>> In RequestData() I do:
>>>> this->InternalRenderWindow->Render();
>>>> this->InternalRenderWindow->WaitForCompletion();
>>>>
>>>> int* size = this->InternalRenderWindow->GetSize();
>>>>
>>>> vtkInformation* info = outVector->GetInformationObject(0);
>>>> vtkImageData* output =
>>>> vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
>>>>
>>>>
>>>>
>>>> output->SetExtent(info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()));
>>>>
>>>> vtkFloatData* data =
>>>> vtkFloatData::SafeDownCast(output->GetPointData()->GetScalars());
>>>> this->InternalRenderWindow->GetRGBAPixelData(0, 0, size[0]-1, size[1]-1,
>>>> data);
>>>>
>>>>
>>>> On Tuesday, January 14, 2014 11:39:34 AM, David Gobbi
>>>> <david.gobbi at gmail.com> wrote:
>>>> The order in which requests are processed is:
>>>> RequestDataObject()
>>>> RequestInformation()
>>>> RequestUpdateExtent()
>>>> RequestData()
>>>>
>>>> So I am a bit confused about how you are creating the data before you
>>>> Render the window that you get it from.
>>>>
>>>> On Tue, Jan 14, 2014 at 9:20 AM, Maarten Beek <beekmaarten at yahoo.com>
>>>> wrote:
>>>>> Yes, it has an internal pipeline. Apologies for not mentioning this,
>>>>> thought
>>>>> I did, must have been in an earlier email to the mailinglist...
>>>>>
>>>>> I started with the vtkWindowToImageFilter class, but now taking data
>>>>> directly from an internal renderwindow because I want floats instead of
>>>>> unsigned chars.
>>>>> I don't make a ShallowCopy of the output, instead I create the data in
>>>>> RequestDataObject(). I do call Render() on the internal renderwindow in
>>>>> RequestData().
>>>>>
>>>>> Basically I am trying to make a nice drr generator algorithm using the
>>>>> gpu
>>>>> mapper in vtk.
>>>>>
>>>>> Maarten
>>>>>
>>>>>
>>>>> On Tuesday, January 14, 2014 11:07:21 AM, David Gobbi
>>>>> <david.gobbi at gmail.com> wrote:
>>>>> Your filter has an internal pipeline? That would have been worth
>>>>> mentioning in your first email.
>>>>>
>>>>> Are you doing a shallow copy to copy the output of the internal
>>>>> pipeline to the output of your filter? Does your RequestData() method
>>>>> call the Update() method of the internal pipeline?
>>>>>
>>>>> On Tue, Jan 14, 2014 at 8:42 AM, Maarten Beek <beekmaarten at yahoo.com>
>>>>> wrote:
>>>>>> Thanks David,
>>>>>>
>>>>>> Just before reading your email, I already added
>>>>>> inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt);
>>>>>> inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt,
>>>>>> 6);
>>>>>> to the code in RequestUpdateExtent() and that caused the errors to
>>>>>> disappear. But it is good to see it seems to work in another filter
>>>>>> too
>>>>>> ;-)
>>>>>>
>>>>>> Something is still wrong in the algorithm code though, because I need
>>>>>> to
>>>>>> call Update() to get a sensible output. Without it, the output
>>>>>> disappears
>>>>>> from the renderwindow after a new render (although the algorithm's
>>>>>> RequestData is called...?)
>>>>>>
>>>>>> Maybe vtkImageHistogram will give me a clue, although I don't see an
>>>>>> internal pipeline in it...
>>>>>>
>>>>>> Maarten
>>>>>>
>>>>>>
>>>>>> On Tuesday, January 14, 2014 9:58:09 AM, David Gobbi
>>>>>> <david.gobbi at gmail.com>
>>>>>> wrote:
>>>>>> Hi Maarten,
>>>>>>
>>>>>> In order to set the output extent independent of the input extent,
>>>>>> all you should have to do is override RequestInformation() and
>>>>>> RequestUpdateExtent(). It is definitely not necessary to set
>>>>>> UNRESTRICTED_UPDATE_EXTENT or EXACT_EXTENT.
>>>>>> Take a look at vtkImageHistogram.cxx as an example of a filter
>>>>>> that has a 3D input and an independently-sized 2D output.
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Mon, Jan 13, 2014 at 1:45 PM, Maarten Beek <beekmaarten at yahoo.com>
>>>>>> wrote:
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I am trying to write an (image) algorithm that generates a 2d image
>>>>>>> from
>>>>>>> a
>>>>>>> 3d image.
>>>>>>> I would like to be able to set the resolution of the 2d image.
>>>>>>> The extents of the input and output are therefore unrelated.
>>>>>>>
>>>>>>> I have the algorithm working when I set the algorithm's input in an
>>>>>>> unofficial way (SetNumberOfInputPorts(0), using a custom function
>>>>>>> SetInput
>>>>>>> instead of SetInputConnection or SetInputData). This way there is no
>>>>>>> pipeline created, which I would like to happen.
>>>>>>>
>>>>>>> I set the whole extent of the algorithm's output to the desired (2d)
>>>>>>> extent
>>>>>>> in RequestInformation. However, the function
>>>>>>> vtkStreamingDemandDrivenPipeline::VerifyOutputInformation() fails
>>>>>>> because
>>>>>>> this whole extent miraculously gets re-set to whole (3d) extent of
>>>>>>> the
>>>>>>> input.
>>>>>>> I have tried to prevent this check using
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> outInfo->Set(vtkStreamingDemandDrivenPipeline::UNRESTRICTED_UPDATE_EXTENT(),
>>>>>>> 1) and
>>>>>>> outInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 0) to
>>>>>>> no
>>>>>>> avail.
>>>>>>>
>>>>>>> How do I prevent the adjustment of the whole extent after I have set
>>>>>>> it
>>>>>>> to
>>>>>>> the desired value?
>>>>>>>
>>>>>>> Thanks - Maarten
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>
More information about the vtkusers
mailing list