[vtkusers] Problem with vtkContourTriangulator and vtkPlaneCutter (Jeffery Lewis)

Andrew Maclean andrew.amaclean at gmail.com
Mon Mar 5 23:24:06 EST 2018


Jeffery

​I think this is related to the ParametricFunctions. These functions are
generated by mapping R² -> R³ and are then triangulated.
I tried vtkParametricSuperToroid and sometimes the contouring and cutting
worked but in some orientations the triangulation failed.

​If you use a vtkSuperquadricSource e.g:
vtkSmartPointer<vtkSuperquadricSource> source =
vtkSmartPointer<vtkSuperquadricSource>::New();
source->SetCenter(0, 0, 0);
source->SetPhiRoundness(1.0);
source->SetThetaRoundness(1.0);
source->ToroidalOn();

Everything seems to work Ok.

Andrew


> ---------- Forwarded message ----------
> From: Jeffery Lewis <jlewis at accuray.com>
> To: "vtkusers at vtk.org" <vtkusers at vtk.org>
> Cc:
> Bcc:
> Date: Fri, 2 Mar 2018 23:46:09 +0000
> Subject: Re: [vtkusers] Problem with vtkContourTriangulator and
> vtkPlaneCutter (Jeffery Lewis)
> Seems like the attachments didn't go through. Here is the code.
>
> #include <vtkSmartPointer.h>
> #include <vtkParametricSuperToroid.h>
> #include <vtkParametricFunctionSource.h>
> #include <vtkSphereSource.h>
> #include <vtkCamera.h>
> #include <vtkPolyDataMapper.h>
> #include <vtkPolyDataMapper2D.h>
> #include <vtkDataSetMapper.h>
> #include <vtkCompositePolyDataMapper.h>
> #include <vtkActor.h>
> #include <vtkActor2D.h>
> #include <vtkPlane.h>
> #include <vtkCutter.h>
> #include <vtkPlaneCutter.h>
> #include <vtkProperty.h>
> #include <vtkProperty2D.h>
> #include <vtkRenderWindow.h>
> #include <vtkRenderer.h>
> #include <vtkRenderWindowInteractor.h>
> #include <vtkMath.h>
> #include <vtkInteractorStyle.h>
> #include <vtkInteractorStyleImage.h>
> #include <vtkTransform.h>
> #include <vtkContourTriangulator.h>
> #include <vtkCleanPolyData.h>
> #include <vtkConeSource.h>
> #include <vtkCommand.h>
> #include <vtkSliderWidget.h>
> #include <vtkSliderRepresentation2D.h>
>
> // Callbacks for the interactions
> class SliderCallbackN1 : public vtkCommand {
> public:
> static SliderCallbackN1 *New() {
> return new SliderCallbackN1;
> }
> virtual void Execute(vtkObject *caller, unsigned long, void*) {
> vtkSliderWidget *sliderWidget =
> reinterpret_cast<vtkSliderWidget*>(caller);
> double value = static_cast<vtkSliderRepresentation2D *>(sliderWidget->
> GetRepresentation())->GetValue();
> this->SuperToroid->SetN1(value);
> }
> SliderCallbackN1() :SuperToroid(0) {}
> vtkParametricSuperToroid *SuperToroid;
> };
>
> class SliderCallbackN2 : public vtkCommand {
> public:
> static SliderCallbackN2 *New() {
> return new SliderCallbackN2;
> }
> virtual void Execute(vtkObject *caller, unsigned long, void*) {
> vtkSliderWidget *sliderWidget =
> reinterpret_cast<vtkSliderWidget*>(caller);
> double value = static_cast<vtkSliderRepresentation2D *>(sliderWidget->
> GetRepresentation())->GetValue();
> this->SuperToroid->SetN2(value);
> }
> SliderCallbackN2() :SuperToroid(0) {}
> vtkParametricSuperToroid *SuperToroid;
> };
>
> /**This callback will rotate the surface model about x and y axis
> depending on the
> *current location of the mouse. This will in turn update the cut plane
> that is ment to
> *be normal to the camera and cuts through the middle of the model, showing
> a red
> *cut contour, and green filled contour. */
> class InteractionCallback : public vtkCommand {
> public:
> static InteractionCallback* New() {
> return new InteractionCallback;
> }
>
> virtual void Execute(vtkObject*, unsigned long eventID, void* pCallData)
> VTK_OVERRIDE {
> if (eventID == vtkCommand::MouseMoveEvent) {
> // Get the current mouse position.
> int aiCurrentPosition[2];
> m_pInteractor->GetEventPosition(aiCurrentPosition);
>
> // Get the view port size.
> int iViewPortWidth = m_pInteractor->GetRenderWindow()->GetSize()[0];
> int iViewPortHeight = m_pInteractor->GetRenderWindow()->GetSize()[1];
>
> // Compute rotations about x and y axis.
> int iMousePositionAboutCenterX = aiCurrentPosition[0] - iViewPortWidth/2.0;
> int iMousePositionAboutCenterY = aiCurrentPosition[1] -
> iViewPortHeight/2.0;
> double dRotationAboutX = -iMousePositionAboutCenterY/(
> iViewPortHeight/2.0)*180.0;
> double dRotationAboutY = iMousePositionAboutCenterX/(
> iViewPortWidth/2.0)*180.0;
>
> // Compute transform.
> vtkSmartPointer<vtkTransform> sptmSurfacModel =
> vtkSmartPointer<vtkTransform>::New();
> sptmSurfacModel->RotateX(dRotationAboutX);
> sptmSurfacModel->RotateY(dRotationAboutY);
>
> // Apply the rotation to the surface model actor.
> m_pActorSurface->SetUserMatrix(sptmSurfacModel->GetMatrix());
>
> // Apply the change to the cut plan normal vector.
> // Translations are not required to be removed from the matrix since there
> should be none.
> double adInitialVector[3];
> adInitialVector[0] = 0.0;
> adInitialVector[1] = 0.0;
> adInitialVector[2] = 1.0;
> double adTransformedVector[3];
> sptmSurfacModel->TransformPoint(adInitialVector, adTransformedVector);
> m_pCutPlane->SetNormal(adTransformedVector[0], adTransformedVector[1],
> adTransformedVector[2]);
>
> // Apply the rotation to the contour actor in the opposite direction to
> make normal to camera.
> sptmSurfacModel->Inverse();
> m_pActorContour->SetUserMatrix(sptmSurfacModel->GetMatrix());
>
> // Apply the rotation to the filled actor in the opposite direction to
> make normal to camera.
> m_pActorFilled->SetUserMatrix(sptmSurfacModel->GetMatrix());
>
> m_pInteractor->Render();
> }
> }
>
> // Member variables
> // ----------------
> vtkRenderWindowInteractor* m_pInteractor;
> vtkActor* m_pActorSurface;
> vtkPlane* m_pCutPlane;
> vtkActor* m_pActorContour;
> vtkActor* m_pActorFilled;
> };
>
>
> int main(int, char *[]) {
>
> vtkSmartPointer<vtkParametricSuperToroid> surface =vtkSmartPointer<
> vtkParametricSuperToroid>::New();
> vtkSmartPointer<vtkParametricFunctionSource> source = vtkSmartPointer<
> vtkParametricFunctionSource>::New();
> source->SetParametricFunction(surface);
>
> // Create a synthetic cone.
> /*// Un-commented out so can switch surface model source.
> vtkSmartPointer<vtkConeSource> source = vtkSmartPointer<vtkConeSource>
> ::New();
> source->SetCenter(0, 0, 0);
> source->SetRadius(1);
> source->SetHeight(2);
> source->SetResolution(30);
> source->Update();
> */
>
> vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>:
> :New();
> vtkSmartPointer<vtkPolyDataMapper> mapper =vtkSmartPointer<
> vtkPolyDataMapper>::New();
> vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
>
> mapper->SetInputConnection(source->GetOutputPort());
>
> vtkSmartPointer<vtkProperty> backProperty = vtkSmartPointer<vtkProperty>::
> New();
> backProperty->SetColor(0.8, 0.8, 0.8);
> backProperty->SetOpacity(0.6);
> actor->SetMapper(mapper);
> actor->SetBackfaceProperty(backProperty);
> actor->GetProperty()->SetDiffuseColor(1, 1, 1);
> actor->GetProperty()->SetOpacity(0.6);
>
> vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<
> vtkRenderWindow>::New();
> renderWindow->AddRenderer(renderer);
> renderWindow->SetSize(640, 480);
> renderer->AddActor(actor);
> renderer->SetBackground(.2, .3, .4);
>
> vtkSmartPointer<vtkRenderWindowInteractor> interactor =vtkSmartPointer<
> vtkRenderWindowInteractor>::New();
> interactor->SetRenderWindow(renderWindow);
>
> // Setup a slider widget for each varying parameter BEGIN
> double tubeWidth(.004);
> double sliderLength(.004);
> double titleHeight(.02);
> double labelHeight(.02);
>
> vtkSmartPointer<vtkSliderRepresentation2D> sliderRepN1 = vtkSmartPointer<
> vtkSliderRepresentation2D>::New();
>
> sliderRepN1->SetMinimumValue(0.0);
> sliderRepN1->SetMaximumValue(4.0);
> sliderRepN1->SetValue(1.0);
> sliderRepN1->SetTitleText("Z squareness");
>
> sliderRepN1->GetPoint1Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepN1->GetPoint1Coordinate()->SetValue(.1, .1);
> sliderRepN1->GetPoint2Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepN1->GetPoint2Coordinate()->SetValue(.9, .1);
>
> sliderRepN1->SetTubeWidth(tubeWidth);
> sliderRepN1->SetSliderLength(sliderLength);
> sliderRepN1->SetTitleHeight(titleHeight);
> sliderRepN1->SetLabelHeight(labelHeight);
>
> vtkSmartPointer<vtkSliderWidget> sliderWidgetN1 = vtkSmartPointer<
> vtkSliderWidget>::New();
> sliderWidgetN1->SetInteractor(interactor);
> sliderWidgetN1->SetRepresentation(sliderRepN1);
> sliderWidgetN1->SetAnimationModeToAnimate();
> sliderWidgetN1->EnabledOn();
>
> vtkSmartPointer<SliderCallbackN1> callbackN1 = vtkSmartPointer<
> SliderCallbackN1>::New();
> callbackN1->SuperToroid = surface;
>
> sliderWidgetN1->AddObserver(vtkCommand::InteractionEvent, callbackN1);
>
> vtkSmartPointer<vtkSliderRepresentation2D> sliderRepN2 = vtkSmartPointer<
> vtkSliderRepresentation2D>::New();
>
> sliderRepN2->SetMinimumValue(0.0001);
> sliderRepN2->SetMaximumValue(4.0);
> sliderRepN2->SetValue(1.0);
> sliderRepN2->SetTitleText("XY squareness");
>
> sliderRepN2->GetPoint1Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepN2->GetPoint1Coordinate()->SetValue(.1, .9);
> sliderRepN2->GetPoint2Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepN2->GetPoint2Coordinate()->SetValue(.9, .9);
>
> sliderRepN2->SetTubeWidth(tubeWidth);
> sliderRepN2->SetSliderLength(sliderLength);
> sliderRepN2->SetTitleHeight(titleHeight);
> sliderRepN2->SetLabelHeight(labelHeight);
>
> vtkSmartPointer<vtkSliderWidget> sliderWidgetN2 = vtkSmartPointer<
> vtkSliderWidget>::New();
> sliderWidgetN2->SetInteractor(interactor);
> sliderWidgetN2->SetRepresentation(sliderRepN2);
> sliderWidgetN2->SetAnimationModeToAnimate();
> sliderWidgetN2->EnabledOn();
>
> vtkSmartPointer<SliderCallbackN2> callbackN2 = vtkSmartPointer<
> SliderCallbackN2>::New();
> callbackN2->SuperToroid = surface;
>
> sliderWidgetN2->AddObserver(vtkCommand::InteractionEvent, callbackN2);
>
> vtkSmartPointer<vtkSliderRepresentation2D> sliderRepMinimumV =
> vtkSmartPointer<vtkSliderRepresentation2D>::New();
>
> sliderRepN1->SetMinimumValue(.0001);
> sliderRepMinimumV->SetMaximumValue(.9999*vtkMath::Pi());
> sliderRepMinimumV->SetValue(.0001);
> sliderRepMinimumV->SetTitleText("V min");
>
> sliderRepMinimumV->GetPoint1Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepMinimumV->GetPoint1Coordinate()->SetValue(.1, .1);
> sliderRepMinimumV->GetPoint2Coordinate()->SetCoordinateSystemToNormalize
> dDisplay();
> sliderRepMinimumV->GetPoint2Coordinate()->SetValue(.1, .9);
>
> sliderRepMinimumV->SetTubeWidth(tubeWidth);
> sliderRepMinimumV->SetSliderLength(sliderLength);
> sliderRepMinimumV->SetTitleHeight(titleHeight);
> sliderRepMinimumV->SetLabelHeight(labelHeight);
>
> surface->SetN1(1.0);
> surface->SetN2(1.0);
> // Setup a slider widget for each varying parameter END
>
> // Set up the cut plane.
> vtkSmartPointer<vtkPlane> planeCut = vtkSmartPointer<vtkPlane>::New();
> planeCut->SetOrigin(0.0, 0.0, 0.0);
> planeCut->SetNormal(0.0, 0.0, 1.0);
>
> // Set up the cutter which will produce the contour polygons.
> vtkSmartPointer<vtkCutter> polygonsContour = vtkSmartPointer<vtkCutter>::
> New();
> //vtkSmartPointer<vtkPlaneCutter> polygonsContour = vtkSmartPointer<vtkPlaneCutter>::New();
> // testjal
> polygonsContour->SetInputConnection(source->GetOutputPort());
> //polygonsContour->SetPlane(planeCut); // SetPlane only works with a
> vtkPlaneCutter. // testjal
> polygonsContour->SetCutFunction(planeCut);
>
> // Clean the polygons from the cutter. Note, this is an experiment to see
> if this helps the fills. It does not
> // seem to help.
> vtkSmartPointer<vtkCleanPolyData> polygonsContourClean = vtkSmartPointer<vtkCleanPolyData>::New();
> // testjal
> polygonsContourClean->SetInputConnection(polygonsContour->GetOutputPort());
> // testjal
>
> // Set up the filled polygons of the contour.
> vtkSmartPointer<vtkContourTriangulator> polygonsFilled = vtkSmartPointer<
> vtkContourTriangulator>::New();
> polygonsFilled->SetInputConnection(polygonsContourClean->GetOutputPort());
> polygonsFilled->TriangulationErrorDisplayOn(); // testjal
>
> // Set up the mapper of the contour.
> vtkSmartPointer<vtkDataSetMapper> mapperContour = vtkSmartPointer<
> vtkDataSetMapper>::New();
> mapperContour->SetInputConnection(polygonsContourClean->GetOutputPort());
> mapperContour->ScalarVisibilityOff();
>
> // Set up the mapper of the filled polygons of the contour
> vtkSmartPointer<vtkDataSetMapper> mapperFilled = vtkSmartPointer<
> vtkDataSetMapper>::New();
> mapperFilled->SetInputConnection(polygonsFilled->GetOutputPort());
> mapperFilled->ScalarVisibilityOff();
>
> // Set up the actor of the contour.
> vtkSmartPointer<vtkActor> actorContour = vtkSmartPointer<vtkActor>::New();
> actorContour->SetMapper(mapperContour);
> actorContour->GetProperty()->SetColor(1,0,0);
> actorContour->GetProperty()->SetLineWidth(5);
>
> // Set up the actor of the filled polygons of the contour.
> vtkSmartPointer<vtkActor> actorFilled = vtkSmartPointer<vtkActor>::New();
> actorFilled->SetMapper(mapperFilled);
> actorFilled->GetProperty()->SetColor(0, 1, 0);
>
> // Add the contour actor.
> renderer->AddActor(actorContour);
>
> // Add the filld polygons of the contour.
> renderer->AddActor(actorFilled);
>
> // Set up the interaction.
> vtkSmartPointer<InteractionCallback> callback = vtkSmartPointer<
> InteractionCallback>::New();
> callback->m_pInteractor = interactor.Get();
> callback->m_pActorSurface = actor.Get();
> callback->m_pCutPlane = planeCut.Get();
> callback->m_pActorContour = actorContour.Get();
> callback->m_pActorFilled = actorFilled.Get();
> vtkSmartPointer<vtkInteractorStyle> style = vtkSmartPointer<
> vtkInteractorStyle>::New();
> interactor->SetInteractorStyle(style);
> style->AddObserver(vtkCommand::MouseMoveEvent, callback);
>
> renderer->ResetCamera(-1, 1, -1, 1, -1, 1);
> renderer->GetActiveCamera()->ParallelProjectionOn();
> renderWindow->Render();
>
> interactor->Initialize();
>
> interactor->Start();
>
> return EXIT_SUCCESS;
> }
>
> -----Original Message-----
> From: vtkusers [mailto:vtkusers-bounces at vtk.org] On Behalf Of
> vtkusers-request at vtk.org
> Sent: Friday, March 02, 2018 3:19 PM
> To: vtkusers at vtk.org
> Subject: vtkusers Digest, Vol 167, Issue 6
>
> Send vtkusers mailing list submissions to
> vtkusers at vtk.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://urldefense.proofpoint.com/v2/url?u=https-3A__vtk.
> org_mailman_listinfo_vtkusers&d=DwICAg&c=xPsIBl5KrHsS6I-
> OqwKVfQ&r=D9BdhfXHHQX-uhgMiAohLoGTItPHXF-7rtsYkItEKmE&m=
> LEPlWwob3RaATj2F7NLtpCgz9jCbYxrZVKqUBxw04QA&s=
> Ej7w16ZJQy02Uvg3d2LzSZ7xIDDkBIUqNYKBToY2xxE&e=
> or, via email, send a message with subject or body 'help' to
> vtkusers-request at vtk.org
>
> You can reach the person managing the list at
> vtkusers-owner at vtk.org
>
> When replying, please edit your Subject line so it is more specific than
> "Re: Contents of vtkusers digest..."
>
>
> Today's Topics:
>
>    1. Problem with vtkContourTriangulator and vtkPlaneCutter
>       (Jeffery Lewis)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Fri, 2 Mar 2018 22:57:44 +0000
> From: Jeffery Lewis <jlewis at accuray.com>
> To: "vtkusers at vtk.org" <vtkusers at vtk.org>
> Subject: [vtkusers] Problem with vtkContourTriangulator and
> vtkPlaneCutter
> Message-ID:
> <DM5PR0501MB3749070F9E8CBAEFFE5D3241C5C50 at DM5PR0501MB3749.
> namprd05.prod.outlook.com>
>
> Content-Type: text/plain; charset="us-ascii"
>
> I have a prototype that generates a super toroid surface model. A cut
> plane is defined to be orthogonal to the camera line of sight, and cuts
> through the middle of the surface model. The cut contour (generated by
> vtkCutter), and filled cut contour (generated by vtkContourTriangulator) is
> rendered with the surface model. The surface model is shown transparent as
> it is only a reference. The rendering of interest is the cut contour (shown
> as red contour) and filled cut contour (shown as green). Moving the mouse
> rotates the surface model. The cut plane stays orthogonal to the camera
> while the surface model rotates. By rotating the surface model, you can see
> the cut contour and filled cut contour get updated interactively as it
> slices through the middle of the surface model.
>
> Unfortunately, the filled cut contour does not look right and I can't seem
> to figure it out. If I change the surface model to something simpler like a
> cone, then everything looks fine.
>
> Also of note is that if I switch out the vtkCutter with a vtkPlaneCutter,
> the program crashes. I would like to use the vtkPlaneCutter since from its
> documentation seems to indicate that it will get better performance. The
> vtkPlaneCutter crashes using either the super toroid or cone.
>
> Attached is the source code. The stuff between "// Setup a slider widget
> for each varying parameter BEGIN" and "// Setup a slider widget for each
> varying parameter END" can be ignored as this only involves setting up
> sliders to manipulate the super toroid, which comes from the
> ParametricSuperToroidDemo example. The setup of the pipleline for the cut
> contour and filled cut contour is near the bottom.
>
> Also attached is a sample screen shot of the incorrect filled cut contour.
>
>
>
>
> Jeffery Lewis
> Staff Software Engineer, Treatment Planning Systems
>
> 1310 Chesapeake Terrace
> Sunnyvale, CA 94089
> USA
> Tel: 1.408.789.4367
> jlewis at accuray.com
>
>
>
-- 
___________________________________________
Andrew J. P. Maclean

___________________________________________
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://vtk.org/pipermail/vtkusers/attachments/20180306/4d1746b5/attachment.html>


More information about the vtkusers mailing list