1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkContourRepresentation.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkContourRepresentation.h"
16 
17 #include "vtkBox.h"
18 #include "vtkCamera.h"
19 #include "vtkCellArray.h"
20 #include "vtkContourLineInterpolator.h"
21 #include "vtkCoordinate.h"
22 #include "vtkHandleRepresentation.h"
23 #include "vtkIncrementalOctreePointLocator.h"
24 #include "vtkIntArray.h"
25 #include "vtkInteractorObserver.h"
26 #include "vtkLine.h"
27 #include "vtkMath.h"
28 #include "vtkMatrix4x4.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkPointPlacer.h"
31 #include "vtkPolyData.h"
32 #include "vtkRenderer.h"
33 #include "vtkWindow.h"
34 
35 #include <set>
36 #include <algorithm>
37 #include <iterator>
38 
39 vtkCxxSetObjectMacro(vtkContourRepresentation, PointPlacer, vtkPointPlacer);
40 vtkCxxSetObjectMacro(vtkContourRepresentation, LineInterpolator, vtkContourLineInterpolator);
41 
42 //----------------------------------------------------------------------
vtkContourRepresentation()43 vtkContourRepresentation::vtkContourRepresentation()
44 {
45   this->Internal = new vtkContourRepresentationInternals;
46 
47   this->PixelTolerance           = 7;
48   this->WorldTolerance           = 0.001;
49   this->PointPlacer              = nullptr;
50   this->LineInterpolator         = nullptr;
51   this->Locator                  = nullptr;
52   this->RebuildLocator           = false;
53   this->ActiveNode               = -1;
54   this->NeedToRender             = 0;
55   this->ClosedLoop               = 0;
56   this->ShowSelectedNodes        = 0;
57   this->CurrentOperation         = vtkContourRepresentation::Inactive;
58 
59   this->ResetLocator();
60 }
61 
62 //----------------------------------------------------------------------
~vtkContourRepresentation()63 vtkContourRepresentation::~vtkContourRepresentation()
64 {
65   this->SetPointPlacer(nullptr);
66   this->SetLineInterpolator(nullptr);
67   this->Internal->ClearNodes();
68 
69   delete this->Internal;
70 
71   if (this->Locator)
72   {
73     this->Locator->Delete();
74   }
75 }
76 
77 //----------------------------------------------------------------------
ResetLocator()78 void vtkContourRepresentation::ResetLocator()
79 {
80   if (this->Locator)
81   {
82     this->Locator->Delete();
83   }
84 
85   this->Locator = vtkIncrementalOctreePointLocator::New();
86   this->Locator->SetBuildCubicOctree(1);
87   this->RebuildLocator = true;
88 }
89 
90 //----------------------------------------------------------------------
ClearAllNodes()91 void vtkContourRepresentation::ClearAllNodes()
92 {
93   this->ResetLocator();
94   this->Internal->ClearNodes();
95 
96   this->BuildLines();
97   this->BuildLocator();
98   this->NeedToRender = 1;
99   this->Modified();
100 }
101 
102 //----------------------------------------------------------------------
AddNodeAtPositionInternal(double worldPos[3],double worldOrient[9],double displayPos[2])103 void vtkContourRepresentation::AddNodeAtPositionInternal( double worldPos[3],
104                                                           double worldOrient[9],
105                                                           double displayPos[2] )
106 {
107   // Add a new point at this position
108   vtkContourRepresentationNode *node = new vtkContourRepresentationNode;
109   node->WorldPosition[0] = worldPos[0];
110   node->WorldPosition[1] = worldPos[1];
111   node->WorldPosition[2] = worldPos[2];
112   node->Selected = 0;
113 
114   node->NormalizedDisplayPosition[0] = displayPos[0];
115   node->NormalizedDisplayPosition[1] = displayPos[1];
116   this->Renderer->DisplayToNormalizedDisplay(
117       node->NormalizedDisplayPosition[0],
118       node->NormalizedDisplayPosition[1] );
119 
120   memcpy(node->WorldOrientation, worldOrient, 9*sizeof(double) );
121 
122   this->Internal->Nodes.push_back(node);
123 
124   if ( this->LineInterpolator && this->GetNumberOfNodes() > 1 )
125   {
126     // Give the line interpolator a chance to update the node.
127     int didNodeChange = this->LineInterpolator->UpdateNode(
128         this->Renderer, this, node->WorldPosition, this->GetNumberOfNodes()-1 );
129 
130     // Give the point placer a chance to validate the updated node. If its not
131     // valid, discard the LineInterpolator's change.
132     if ( didNodeChange && !this->PointPlacer->ValidateWorldPosition(
133                 node->WorldPosition, worldOrient ) )
134     {
135       node->WorldPosition[0] = worldPos[0];
136       node->WorldPosition[1] = worldPos[1];
137       node->WorldPosition[2] = worldPos[2];
138     }
139   }
140 
141   this->UpdateLines( static_cast<int>(this->Internal->Nodes.size())-1);
142   this->NeedToRender = 1;
143 }
144 
145 //----------------------------------------------------------------------
GetNodePolyData(vtkPolyData * poly)146 void vtkContourRepresentation::GetNodePolyData( vtkPolyData* poly )
147 {
148   poly->Initialize();
149   int count = this->GetNumberOfNodes();
150 
151   if ( count == 0 )
152   {
153     return;
154   }
155 
156   vtkPoints *points = vtkPoints::New();
157   vtkCellArray *lines = vtkCellArray::New();
158 
159   points->SetNumberOfPoints( count );
160   vtkIdType numLines = count;
161 
162   if ( this->ClosedLoop )
163   {
164     numLines++;
165   }
166 
167   vtkIdType *lineIndices = new vtkIdType[numLines];
168 
169   int i;
170   vtkIdType index = 0;
171   double pos[3];
172 
173   for ( i = 0; i < this->GetNumberOfNodes(); ++i )
174   {
175     // Add the node
176     this->GetNthNodeWorldPosition( i, pos );
177     points->InsertPoint( index, pos );
178     lineIndices[index] = index;
179     index++;
180   }
181 
182   if ( this->ClosedLoop )
183   {
184     lineIndices[index] = 0;
185   }
186 
187   lines->InsertNextCell( numLines, lineIndices );
188   delete [] lineIndices;
189 
190   poly->SetPoints( points );
191   poly->SetLines( lines );
192 
193   points->Delete();
194   lines->Delete();
195 }
196 
197 //----------------------------------------------------------------------
AddNodeAtPositionInternal(double worldPos[3],double worldOrient[9],int displayPos[2])198 void vtkContourRepresentation::AddNodeAtPositionInternal( double worldPos[3],
199                                                           double worldOrient[9],
200                                                           int displayPos[2] )
201 {
202   double dispPos[2];
203   dispPos[0] = static_cast<double>(displayPos[0]);
204   dispPos[1] = static_cast<double>(displayPos[1]);
205   this->AddNodeAtPositionInternal( worldPos, worldOrient, dispPos );
206 }
207 
208 //----------------------------------------------------------------------
AddNodeAtWorldPosition(double worldPos[3],double worldOrient[9])209 int vtkContourRepresentation::AddNodeAtWorldPosition( double worldPos[3],
210                                                       double worldOrient[9] )
211 {
212   // Check if this is a valid location
213   if ( !this->PointPlacer->ValidateWorldPosition( worldPos, worldOrient ) )
214   {
215     return 0;
216   }
217 
218   double displayPos[2];
219   this->GetRendererComputedDisplayPositionFromWorldPosition(
220                           worldPos, worldOrient, displayPos );
221   this->AddNodeAtPositionInternal( worldPos, worldOrient, displayPos );
222 
223   return 1;
224 }
225 
226 //----------------------------------------------------------------------
AddNodeAtWorldPosition(double x,double y,double z)227 int vtkContourRepresentation::AddNodeAtWorldPosition(
228   double x, double y, double z)
229 {
230   double worldPos[3] = {x, y, z};
231   return this->AddNodeAtWorldPosition(worldPos);
232 }
233 
234 //----------------------------------------------------------------------
AddNodeAtWorldPosition(double worldPos[3])235 int vtkContourRepresentation::AddNodeAtWorldPosition( double worldPos[3] )
236 {
237   // Check if this is a valid location
238   if ( !this->PointPlacer->ValidateWorldPosition( worldPos ) )
239   {
240     return 0;
241   }
242 
243   double worldOrient[9] = {1.0,0.0,0.0,
244                            0.0,1.0,0.0,
245                            0.0,0.0,1.0};
246 
247   double displayPos[2];
248   this->GetRendererComputedDisplayPositionFromWorldPosition(
249                           worldPos, worldOrient, displayPos );
250   this->AddNodeAtPositionInternal( worldPos, worldOrient, displayPos );
251 
252   return 1;
253 }
254 
255 //----------------------------------------------------------------------
AddNodeAtDisplayPosition(double displayPos[2])256 int vtkContourRepresentation::AddNodeAtDisplayPosition(double displayPos[2])
257 {
258   double worldPos[3];
259   double worldOrient[9] = {1.0,0.0,0.0,
260                            0.0,1.0,0.0,
261                            0.0,0.0,1.0};
262 
263   // Compute the world position from the display position
264   // based on the concrete representation's constraints
265   // If this is not a valid display location return 0
266   if ( !this->PointPlacer->ComputeWorldPosition( this->Renderer,
267                                                  displayPos, worldPos,
268                                                  worldOrient) )
269   {
270     return 0;
271   }
272 
273   this->AddNodeAtPositionInternal( worldPos, worldOrient, displayPos );
274   return 1;
275 }
276 //----------------------------------------------------------------------
AddNodeAtDisplayPosition(int displayPos[2])277 int vtkContourRepresentation::AddNodeAtDisplayPosition(int displayPos[2])
278 {
279   double doubleDisplayPos[2];
280   doubleDisplayPos[0] = displayPos[0];
281   doubleDisplayPos[1] = displayPos[1];
282   return this->AddNodeAtDisplayPosition( doubleDisplayPos );
283 
284 }
285 //----------------------------------------------------------------------
AddNodeAtDisplayPosition(int X,int Y)286 int vtkContourRepresentation::AddNodeAtDisplayPosition(int X, int Y)
287 {
288   double displayPos[2];
289   displayPos[0] = X;
290   displayPos[1] = Y;
291   return this->AddNodeAtDisplayPosition( displayPos );
292 
293 }
294 
295 //----------------------------------------------------------------------
ActivateNode(double displayPos[2])296 int vtkContourRepresentation::ActivateNode( double displayPos[2] )
297 {
298   this->BuildLocator();
299   // Find closest node to this display pos that
300   // is within PixelTolerance
301   double dPos[3] = {displayPos[0],displayPos[1],0};
302   double closestDistance2 = VTK_DOUBLE_MAX;
303   int closestNode = this->Locator->FindClosestPointWithinRadius(
304     this->PixelTolerance,dPos,closestDistance2);
305   if ( closestNode != this->ActiveNode )
306   {
307     this->ActiveNode = closestNode;
308     this->NeedToRender = 1;
309   }
310   return ( this->ActiveNode >= 0 );
311 }
312 //----------------------------------------------------------------------
ActivateNode(int displayPos[2])313 int vtkContourRepresentation::ActivateNode( int displayPos[2] )
314 {
315   double doubleDisplayPos[2];
316 
317   doubleDisplayPos[0] = displayPos[0];
318   doubleDisplayPos[1] = displayPos[1];
319   return this->ActivateNode( doubleDisplayPos );
320 }
321 
322 //----------------------------------------------------------------------
ActivateNode(int X,int Y)323 int vtkContourRepresentation::ActivateNode( int X, int Y )
324 {
325   double doubleDisplayPos[2];
326 
327   doubleDisplayPos[0] = X;
328   doubleDisplayPos[1] = Y;
329   return this->ActivateNode( doubleDisplayPos );
330 }
331 
332 
333 //----------------------------------------------------------------------
SetActiveNodeToWorldPosition(double worldPos[3],double worldOrient[9])334 int vtkContourRepresentation::SetActiveNodeToWorldPosition( double worldPos[3],
335                                                             double worldOrient[9] )
336 {
337   if ( this->ActiveNode < 0 ||
338        static_cast<unsigned int>(this->ActiveNode) >= this->Internal->Nodes.size() )
339   {
340     return 0;
341   }
342 
343   // Check if this is a valid location
344   if ( !this->PointPlacer->ValidateWorldPosition( worldPos, worldOrient ) )
345   {
346     return 0;
347   }
348 
349   this->SetNthNodeWorldPositionInternal( this->ActiveNode,
350                                          worldPos,
351                                          worldOrient );
352   return 1;
353 }
354 
355 //----------------------------------------------------------------------
SetActiveNodeToWorldPosition(double worldPos[3])356 int vtkContourRepresentation::SetActiveNodeToWorldPosition( double worldPos[3] )
357 {
358   if ( this->ActiveNode < 0 ||
359        static_cast<unsigned int>(this->ActiveNode) >= this->Internal->Nodes.size() )
360   {
361     return 0;
362   }
363 
364   // Check if this is a valid location
365   if ( !this->PointPlacer->ValidateWorldPosition( worldPos ) )
366   {
367     return 0;
368   }
369 
370   double worldOrient[9] = {1.0,0.0,0.0,
371                            0.0,1.0,0.0,
372                            0.0,0.0,1.0};
373 
374   this->SetNthNodeWorldPositionInternal( this->ActiveNode,
375                                          worldPos,
376                                          worldOrient );
377   return 1;
378 }
379 
380 //----------------------------------------------------------------------
SetActiveNodeToDisplayPosition(double displayPos[2])381 int vtkContourRepresentation::SetActiveNodeToDisplayPosition( double displayPos[2] )
382 {
383   if ( this->ActiveNode < 0 ||
384        static_cast<unsigned int>(this->ActiveNode) >= this->Internal->Nodes.size() )
385   {
386     return 0;
387   }
388 
389   double worldPos[3];
390   double worldOrient[9] = {1.0,0.0,0.0,
391                            0.0,1.0,0.0,
392                            0.0,0.0,1.0};
393 
394   // Compute the world position from the display position
395   // based on the concrete representation's constraints
396   // If this is not a valid display location return 0
397   if ( !this->PointPlacer->ComputeWorldPosition( this->Renderer,
398                                                  displayPos, worldPos,
399                                                  worldOrient ) )
400   {
401     return 0;
402   }
403 
404   this->SetNthNodeWorldPositionInternal( this->ActiveNode,
405                                          worldPos,
406                                          worldOrient );
407   return 1;
408 }
409 //----------------------------------------------------------------------
SetActiveNodeToDisplayPosition(int displayPos[2])410 int vtkContourRepresentation::SetActiveNodeToDisplayPosition( int displayPos[2] )
411 {
412   double doubleDisplayPos[2];
413   doubleDisplayPos[0] = displayPos[0];
414   doubleDisplayPos[1] = displayPos[1];
415   return this->SetActiveNodeToDisplayPosition( doubleDisplayPos );
416 }
417 
418 //----------------------------------------------------------------------
SetActiveNodeToDisplayPosition(int X,int Y)419 int vtkContourRepresentation::SetActiveNodeToDisplayPosition( int X, int Y )
420 {
421   double doubleDisplayPos[2];
422   doubleDisplayPos[0] = X;
423   doubleDisplayPos[1] = Y;
424   return this->SetActiveNodeToDisplayPosition( doubleDisplayPos );
425 }
426 
427 //----------------------------------------------------------------------
ToggleActiveNodeSelected()428 int vtkContourRepresentation::ToggleActiveNodeSelected()
429 {
430 if ( this->ActiveNode < 0 ||
431     static_cast<unsigned int>(this->ActiveNode) >= this->Internal->Nodes.size() )
432 {
433   // Failed to toggle the value
434   return 0;
435 }
436 
437   this->Internal->Nodes[this->ActiveNode]->Selected =
438     this->Internal->Nodes[this->ActiveNode]->Selected ? 0 : 1;
439   this->NeedToRender = 1;
440   this->Modified();
441   return 1;
442 }
443 
444 //----------------------------------------------------------------------
GetNthNodeSelected(int n)445 int vtkContourRepresentation::GetNthNodeSelected(int n)
446 {
447   if ( n < 0 ||
448       static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
449   {
450     // This case is considered not Selected.
451     return 0;
452   }
453 
454   return this->Internal->Nodes[n]->Selected;
455 }
456 
457 //----------------------------------------------------------------------
SetNthNodeSelected(int n)458 int vtkContourRepresentation::SetNthNodeSelected(int n)
459 {
460   if ( n < 0 ||
461     static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
462   {
463     // Failed.
464     return 0;
465   }
466   int val =  n > 0 ? 1 : 0;
467   if(this->Internal->Nodes[n]->Selected != val)
468   {
469     this->Internal->Nodes[n]->Selected = val;
470     this->NeedToRender = 1;
471     this->Modified();
472   }
473   return 1;
474 }
475 
476 //----------------------------------------------------------------------
GetActiveNodeSelected()477 int vtkContourRepresentation::GetActiveNodeSelected()
478 {
479   return this->GetNthNodeSelected(this->ActiveNode);
480 }
481 
482 //----------------------------------------------------------------------
GetActiveNodeWorldPosition(double pos[3])483 int vtkContourRepresentation::GetActiveNodeWorldPosition( double pos[3] )
484 {
485   return this->GetNthNodeWorldPosition( this->ActiveNode, pos );
486 }
487 
488 //----------------------------------------------------------------------
GetActiveNodeWorldOrientation(double orient[9])489 int vtkContourRepresentation::GetActiveNodeWorldOrientation( double orient[9] )
490 {
491   return this->GetNthNodeWorldOrientation( this->ActiveNode, orient );
492 }
493 
494 //----------------------------------------------------------------------
GetActiveNodeDisplayPosition(double pos[2])495 int vtkContourRepresentation::GetActiveNodeDisplayPosition( double pos[2] )
496 {
497   return this->GetNthNodeDisplayPosition( this->ActiveNode, pos );
498 }
499 
500 //----------------------------------------------------------------------
GetNumberOfNodes()501 int vtkContourRepresentation::GetNumberOfNodes()
502 {
503   return static_cast<int>(this->Internal->Nodes.size());
504 }
505 
506 //----------------------------------------------------------------------
GetNumberOfIntermediatePoints(int n)507 int vtkContourRepresentation::GetNumberOfIntermediatePoints(int n)
508 {
509   if ( n < 0 ||
510        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
511   {
512     return 0;
513   }
514 
515   return static_cast<int>(this->Internal->Nodes[n]->Points.size());
516 }
517 
518 //----------------------------------------------------------------------
GetIntermediatePointWorldPosition(int n,int idx,double point[3])519 int vtkContourRepresentation::GetIntermediatePointWorldPosition(int n,
520                                                                 int idx,
521                                                                 double point[3])
522 {
523   if ( n < 0 ||
524        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
525   {
526     return 0;
527   }
528 
529   if ( idx < 0 ||
530        static_cast<unsigned int>(idx) >= this->Internal->Nodes[n]->Points.size() )
531   {
532     return 0;
533   }
534 
535   point[0] = this->Internal->Nodes[n]->Points[idx]->WorldPosition[0];
536   point[1] = this->Internal->Nodes[n]->Points[idx]->WorldPosition[1];
537   point[2] = this->Internal->Nodes[n]->Points[idx]->WorldPosition[2];
538 
539   return 1;
540 }
541 
542 //----------------------------------------------------------------------
543 // The display position for a given world position must be re-computed
544 // from the world positions... It should not be queried from the renderer
545 // whose camera position may have changed
GetNthNodeDisplayPosition(int n,double displayPos[2])546 int vtkContourRepresentation::GetNthNodeDisplayPosition(
547                            int n, double displayPos[2] )
548 {
549   if ( n < 0 ||
550        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
551   {
552     return 0;
553   }
554 
555   double pos[4];
556   pos[0] = this->Internal->Nodes[n]->WorldPosition[0];
557   pos[1] = this->Internal->Nodes[n]->WorldPosition[1];
558   pos[2] = this->Internal->Nodes[n]->WorldPosition[2];
559   pos[3] = 1.0;
560 
561   this->Renderer->SetWorldPoint( pos );
562   this->Renderer->WorldToDisplay();
563   this->Renderer->GetDisplayPoint( pos );
564 
565   displayPos[0] = pos[0];
566   displayPos[1] = pos[1];
567   return 1;
568 }
569 
570 //----------------------------------------------------------------------
GetNthNodeWorldPosition(int n,double worldPos[3])571 int vtkContourRepresentation::GetNthNodeWorldPosition( int n, double worldPos[3] )
572 {
573   if ( vtkContourRepresentationNode *node = this->GetNthNode(n) )
574   {
575     worldPos[0] = node->WorldPosition[0];
576     worldPos[1] = node->WorldPosition[1];
577     worldPos[2] = node->WorldPosition[2];
578     return 1;
579   }
580 
581   return 0;
582 }
583 
584 //----------------------------------------------------------------------
GetNthNode(int n)585 vtkContourRepresentationNode * vtkContourRepresentation::GetNthNode( int n )
586 {
587   if ( n < 0 ||
588        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
589   {
590     return nullptr;
591   }
592   return this->Internal->Nodes[n];
593 }
594 
595 //----------------------------------------------------------------------
GetNthNodeWorldOrientation(int n,double worldOrient[9])596 int vtkContourRepresentation::GetNthNodeWorldOrientation( int n, double worldOrient[9] )
597 {
598   if ( n < 0 ||
599        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
600   {
601     return 0;
602   }
603 
604   memcpy( worldOrient, this->Internal->Nodes[n]->WorldOrientation, 9*sizeof(double) );
605   return 1;
606 }
607 
608 //----------------------------------------------------------------------
SetNthNodeWorldPositionInternal(int n,double worldPos[3],double worldOrient[9])609 void vtkContourRepresentation::SetNthNodeWorldPositionInternal( int n, double worldPos[3],
610                                                                 double worldOrient[9] )
611 {
612   this->Internal->Nodes[n]->WorldPosition[0] = worldPos[0];
613   this->Internal->Nodes[n]->WorldPosition[1] = worldPos[1];
614   this->Internal->Nodes[n]->WorldPosition[2] = worldPos[2];
615 
616   this->GetRendererComputedDisplayPositionFromWorldPosition(
617         worldPos, worldOrient, this->Internal->Nodes[n]->NormalizedDisplayPosition );
618   this->Renderer->DisplayToNormalizedDisplay(
619       this->Internal->Nodes[n]->NormalizedDisplayPosition[0],
620       this->Internal->Nodes[n]->NormalizedDisplayPosition[1] );
621 
622   memcpy(this->Internal->Nodes[n]->WorldOrientation, worldOrient, 9*sizeof(double) );
623 
624   this->UpdateLines( n );
625   this->NeedToRender = 1;
626 }
627 
628 //----------------------------------------------------------------------
SetNthNodeWorldPosition(int n,double worldPos[3],double worldOrient[9])629 int vtkContourRepresentation::SetNthNodeWorldPosition( int n, double worldPos[3],
630                                                        double worldOrient[9] )
631 {
632   if ( n < 0 ||
633        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
634   {
635     return 0;
636   }
637 
638   // Check if this is a valid location
639   if ( !this->PointPlacer->ValidateWorldPosition( worldPos, worldOrient ) )
640   {
641     return 0;
642   }
643 
644   this->SetNthNodeWorldPositionInternal( n, worldPos, worldOrient );
645   return 1;
646 }
647 
648 //----------------------------------------------------------------------
SetNthNodeWorldPosition(int n,double worldPos[3])649 int vtkContourRepresentation::SetNthNodeWorldPosition( int n, double worldPos[3] )
650 {
651   if ( n < 0 ||
652        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
653   {
654     return 0;
655   }
656 
657   // Check if this is a valid location
658   if ( !this->PointPlacer->ValidateWorldPosition( worldPos ) )
659   {
660     return 0;
661   }
662 
663   double worldOrient[9] = {1.0,0.0,0.0,
664                            0.0,1.0,0.0,
665                            0.0,0.0,1.0};
666 
667   this->SetNthNodeWorldPositionInternal( n, worldPos, worldOrient );
668   return 1;
669 }
670 
671 //----------------------------------------------------------------------
SetNthNodeDisplayPosition(int n,double displayPos[2])672 int vtkContourRepresentation::SetNthNodeDisplayPosition( int n, double displayPos[2] )
673 {
674   double worldPos[3];
675   double worldOrient[9] = {1.0,0.0,0.0,
676                            0.0,1.0,0.0,
677                            0.0,0.0,1.0};
678 
679   // Compute the world position from the display position
680   // based on the concrete representation's constraints
681   // If this is not a valid display location return 0
682   if ( !this->PointPlacer->ComputeWorldPosition( this->Renderer,
683                                                  displayPos, worldPos,
684                                                  worldOrient) )
685   {
686     return 0;
687   }
688 
689   return this->SetNthNodeWorldPosition( n, worldPos, worldOrient );
690 }
691 
692 //----------------------------------------------------------------------
SetNthNodeDisplayPosition(int n,int displayPos[2])693 int vtkContourRepresentation::SetNthNodeDisplayPosition( int n, int displayPos[2] )
694 {
695   double doubleDisplayPos[2];
696   doubleDisplayPos[0] = displayPos[0];
697   doubleDisplayPos[1] = displayPos[1];
698   return this->SetNthNodeDisplayPosition( n, doubleDisplayPos );
699 }
700 
701 //----------------------------------------------------------------------
SetNthNodeDisplayPosition(int n,int X,int Y)702 int vtkContourRepresentation::SetNthNodeDisplayPosition( int n, int X, int Y )
703 {
704   double doubleDisplayPos[2];
705   doubleDisplayPos[0] = X;
706   doubleDisplayPos[1] = Y;
707   return this->SetNthNodeDisplayPosition( n, doubleDisplayPos );
708 }
709 
710 //----------------------------------------------------------------------
FindClosestPointOnContour(int X,int Y,double closestWorldPos[3],int * idx)711 int vtkContourRepresentation::FindClosestPointOnContour( int X, int Y,
712                                                          double closestWorldPos[3],
713                                                          int *idx )
714 {
715   // Make a line out of this viewing ray
716   double p1[4], p2[4], *p3=nullptr, *p4=nullptr;
717 
718   double tmp1[4], tmp2[4];
719   tmp1[0] = X;
720   tmp1[1] = Y;
721   tmp1[2] = 0.0;
722   this->Renderer->SetDisplayPoint( tmp1 );
723   this->Renderer->DisplayToWorld();
724   this->Renderer->GetWorldPoint(p1);
725 
726   tmp1[2] = 1.0;
727   this->Renderer->SetDisplayPoint( tmp1 );
728   this->Renderer->DisplayToWorld();
729   this->Renderer->GetWorldPoint(p2);
730 
731   double closestDistance2 = VTK_DOUBLE_MAX;
732   int closestNode=0;
733 
734   // compute a world tolerance based on pixel
735   // tolerance on the focal plane
736   double fp[4];
737   this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
738   fp[3] = 1.0;
739   this->Renderer->SetWorldPoint(fp);
740   this->Renderer->WorldToDisplay();
741   this->Renderer->GetDisplayPoint(tmp1);
742 
743   tmp1[0] = 0;
744   tmp1[1] = 0;
745   this->Renderer->SetDisplayPoint(tmp1);
746   this->Renderer->DisplayToWorld();
747   this->Renderer->GetWorldPoint(tmp2);
748 
749   tmp1[0] = this->PixelTolerance;
750   this->Renderer->SetDisplayPoint(tmp1);
751   this->Renderer->DisplayToWorld();
752   this->Renderer->GetWorldPoint(tmp1);
753 
754   double wt2 = vtkMath::Distance2BetweenPoints(tmp1, tmp2);
755 
756   // Now loop through all lines and look for closest one within tolerance
757   for(unsigned int i=0;i<this->Internal->Nodes.size();i++)
758   {
759     for (unsigned int j=0;j<=this->Internal->Nodes[i]->Points.size();j++)
760     {
761       if ( j == 0 )
762       {
763         p3 = this->Internal->Nodes[i]->WorldPosition;
764         if ( !this->Internal->Nodes[i]->Points.empty() )
765         {
766           p4 = this->Internal->Nodes[i]->Points[j]->WorldPosition;
767         }
768         else
769         {
770           if ( i < this->Internal->Nodes.size() - 1 )
771           {
772             p4 = this->Internal->Nodes[i+1]->WorldPosition;
773           }
774           else if ( this->ClosedLoop )
775           {
776             p4 = this->Internal->Nodes[0]->WorldPosition;
777           }
778         }
779       }
780       else if ( j == this->Internal->Nodes[i]->Points.size() )
781       {
782         p3 = this->Internal->Nodes[i]->Points[j-1]->WorldPosition;
783         if ( i < this->Internal->Nodes.size() - 1 )
784         {
785           p4 = this->Internal->Nodes[i+1]->WorldPosition;
786         }
787         else if ( this->ClosedLoop )
788         {
789           p4 = this->Internal->Nodes[0]->WorldPosition;
790         }
791         else
792         {
793           // Shouldn't be able to get here (only if we don't have
794           // a closed loop but we do have intermediate points after
795           // the last node - contradictary conditions)
796           continue;
797         }
798       }
799       else
800       {
801         p3 = this->Internal->Nodes[i]->Points[j-1]->WorldPosition;
802         p4 = this->Internal->Nodes[i]->Points[j]->WorldPosition;
803       }
804 
805       // Now we have the four points - check closest intersection
806       double u, v;
807 
808       if ( vtkLine::Intersection( p1, p2, p3, p4, u, v ) )
809       {
810         double p5[3], p6[3];
811         p5[0] = p1[0] + u*(p2[0]-p1[0]);
812         p5[1] = p1[1] + u*(p2[1]-p1[1]);
813         p5[2] = p1[2] + u*(p2[2]-p1[2]);
814 
815         p6[0] = p3[0] + v*(p4[0]-p3[0]);
816         p6[1] = p3[1] + v*(p4[1]-p3[1]);
817         p6[2] = p3[2] + v*(p4[2]-p3[2]);
818 
819         double d = vtkMath::Distance2BetweenPoints(p5, p6);
820 
821         if ( d < wt2 && d < closestDistance2 )
822         {
823           closestWorldPos[0] = p6[0];
824           closestWorldPos[1] = p6[1];
825           closestWorldPos[2] = p6[2];
826           closestDistance2 = d;
827           closestNode = static_cast<int>(i);
828         }
829       }
830       else
831       {
832         double d = vtkLine::DistanceToLine( p3, p1, p2 );
833         if ( d < wt2 && d < closestDistance2 )
834         {
835           closestWorldPos[0] = p3[0];
836           closestWorldPos[1] = p3[1];
837           closestWorldPos[2] = p3[2];
838           closestDistance2 = d;
839           closestNode = static_cast<int>(i);
840         }
841 
842         d = vtkLine::DistanceToLine( p4, p1, p2 );
843         if ( d < wt2 && d < closestDistance2 )
844         {
845           closestWorldPos[0] = p4[0];
846           closestWorldPos[1] = p4[1];
847           closestWorldPos[2] = p4[2];
848           closestDistance2 = d;
849           closestNode = static_cast<int>(i);
850         }
851       }
852     }
853   }
854 
855   if ( closestDistance2 < VTK_DOUBLE_MAX )
856   {
857     if ( closestNode < this->GetNumberOfNodes() -1 )
858     {
859       *idx = closestNode+1;
860       return 1;
861     }
862     else if ( this->ClosedLoop )
863     {
864       *idx = 0;
865       return 1;
866     }
867   }
868 
869   return 0;
870 }
871 
872 //----------------------------------------------------------------------
AddNodeOnContour(int X,int Y)873 int vtkContourRepresentation::AddNodeOnContour( int X, int Y )
874 {
875   int idx;
876 
877   double worldPos[3];
878   double worldOrient[9] = {1.0,0.0,0.0,
879                            0.0,1.0,0.0,
880                            0.0,0.0,1.0};
881 
882   // Compute the world position from the display position
883   // based on the concrete representation's constraints
884   // If this is not a valid display location return 0
885   double displayPos[2];
886   displayPos[0] = X;
887   displayPos[1] = Y;
888   if ( !this->PointPlacer->ComputeWorldPosition( this->Renderer,
889                                                  displayPos, worldPos,
890                                                  worldOrient) )
891   {
892     return 0;
893   }
894 
895   double pos[3];
896   if ( !this->FindClosestPointOnContour( X, Y, pos, &idx ) )
897   {
898     return 0;
899   }
900 
901   if ( !this->PointPlacer->ComputeWorldPosition( this->Renderer,
902                                                  displayPos,
903                                                  pos,
904                                                  worldPos,
905                                                  worldOrient) )
906   {
907     return 0;
908   }
909 
910   // Add a new point at this position
911   vtkContourRepresentationNode *node = new vtkContourRepresentationNode;
912   node->WorldPosition[0] = worldPos[0];
913   node->WorldPosition[1] = worldPos[1];
914   node->WorldPosition[2] = worldPos[2];
915   node->Selected = 0;
916 
917   this->GetRendererComputedDisplayPositionFromWorldPosition(
918           worldPos, worldOrient, node->NormalizedDisplayPosition );
919   this->Renderer->DisplayToNormalizedDisplay(
920          node->NormalizedDisplayPosition[0],
921          node->NormalizedDisplayPosition[1] );
922 
923   memcpy(node->WorldOrientation, worldOrient, 9*sizeof(double) );
924 
925   this->Internal->Nodes.insert(this->Internal->Nodes.begin() + idx, node);
926 
927   this->UpdateLines( idx );
928   this->NeedToRender = 1;
929 
930   return 1;
931 }
932 
933 //----------------------------------------------------------------------
DeleteNthNode(int n)934 int vtkContourRepresentation::DeleteNthNode( int n )
935 {
936   if ( n < 0 ||
937        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
938   {
939     return 0;
940   }
941 
942   for (unsigned int j=0;j<this->Internal->Nodes[n]->Points.size();j++)
943   {
944     delete this->Internal->Nodes[n]->Points[j];
945   }
946   this->Internal->Nodes[n]->Points.clear();
947   delete this->Internal->Nodes[n];
948   this->Internal->Nodes.erase( this->Internal->Nodes.begin() + n );
949   if ( n )
950   {
951     this->UpdateLines(n-1);
952   }
953   else
954   {
955     this->UpdateLines(this->GetNumberOfNodes()-1);
956   }
957 
958   this->NeedToRender = 1;
959   return 1;
960 }
961 
962 //----------------------------------------------------------------------
DeleteActiveNode()963 int vtkContourRepresentation::DeleteActiveNode()
964 {
965   return this->DeleteNthNode( this->ActiveNode );
966 }
967 
968 //----------------------------------------------------------------------
DeleteLastNode()969 int vtkContourRepresentation::DeleteLastNode()
970 {
971   return this->DeleteNthNode(
972     static_cast<int>(this->Internal->Nodes.size()) - 1 );
973 }
974 
975 //----------------------------------------------------------------------
SetClosedLoop(vtkTypeBool val)976 void vtkContourRepresentation::SetClosedLoop( vtkTypeBool val )
977 {
978   if ( this->ClosedLoop != val )
979   {
980     this->ClosedLoop = val;
981     this->UpdateLines(this->GetNumberOfNodes()-1);
982     this->NeedToRender = 1;
983     this->Modified();
984   }
985 }
986 
987 //----------------------------------------------------------------------
UpdateLines(int index)988 void vtkContourRepresentation::UpdateLines( int index )
989 {
990   int indices[2];
991 
992   if (this->LineInterpolator)
993   {
994     vtkIntArray *arr = vtkIntArray::New();
995     this->LineInterpolator->GetSpan( index, arr, this );
996 
997     int nNodes = arr->GetNumberOfTuples();
998     for (int i = 0; i < nNodes; i++)
999     {
1000       arr->GetTypedTuple( i, indices );
1001       this->UpdateLine( indices[0], indices[1] );
1002     }
1003     arr->Delete();
1004   }
1005 
1006   // A check to make sure that we have no line segments in
1007   // the last node if the loop is not closed
1008   if ( !this->ClosedLoop && this->GetNumberOfNodes() > 0 )
1009   {
1010     int idx = static_cast<int>(this->Internal->Nodes.size()) -1;
1011     for (unsigned int j=0;j<this->Internal->Nodes[idx]->Points.size();j++)
1012     {
1013       delete this->Internal->Nodes[idx]->Points[j];
1014     }
1015     this->Internal->Nodes[idx]->Points.clear();
1016   }
1017 
1018   this->BuildLines();
1019   this->RebuildLocator = true;
1020 }
1021 
1022 //----------------------------------------------------------------------
AddIntermediatePointWorldPosition(int n,double pos[3])1023 int vtkContourRepresentation::AddIntermediatePointWorldPosition( int n,
1024                                                                  double pos[3] )
1025 {
1026   return this->AddIntermediatePointWorldPosition(n, pos, 0);
1027 }
1028 
1029 //----------------------------------------------------------------------
1030 int vtkContourRepresentation
AddIntermediatePointWorldPosition(int n,double pos[3],vtkIdType ptId)1031 ::AddIntermediatePointWorldPosition( int n, double pos[3], vtkIdType ptId )
1032 {
1033   if ( n < 0 ||
1034        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
1035   {
1036     return 0;
1037   }
1038 
1039   vtkContourRepresentationPoint *point = new vtkContourRepresentationPoint;
1040   point->WorldPosition[0] = pos[0];
1041   point->WorldPosition[1] = pos[1];
1042   point->WorldPosition[2] = pos[2];
1043   point->PointId = ptId;
1044 
1045   double worldOrient[9] = {1.0,0.0,0.0,
1046                            0.0,1.0,0.0,
1047                            0.0,0.0,1.0};
1048 
1049   this->GetRendererComputedDisplayPositionFromWorldPosition(
1050                           pos, worldOrient, point->NormalizedDisplayPosition );
1051   this->Renderer->DisplayToNormalizedDisplay(
1052       point->NormalizedDisplayPosition[0],
1053       point->NormalizedDisplayPosition[1] );
1054 
1055   this->Internal->Nodes[n]->Points.push_back(point);
1056   return 1;
1057 }
1058 
1059 //----------------------------------------------------------------------
GetNthNodeSlope(int n,double slope[3])1060 int vtkContourRepresentation::GetNthNodeSlope( int n, double slope[3] )
1061 {
1062   if ( n < 0 ||
1063        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
1064   {
1065     return 0;
1066   }
1067 
1068   int idx1, idx2;
1069 
1070   if ( n == 0 && !this->ClosedLoop )
1071   {
1072     idx1 = 0;
1073     idx2 = 1;
1074   }
1075   else if ( n == this->GetNumberOfNodes()-1 && !this->ClosedLoop )
1076   {
1077     idx1 = this->GetNumberOfNodes()-2;
1078     idx2 = idx1+1;
1079   }
1080   else
1081   {
1082     idx1 = n - 1;
1083     idx2 = n + 1;
1084 
1085     if ( idx1 < 0 )
1086     {
1087       idx1 += this->GetNumberOfNodes();
1088     }
1089     if ( idx2 >= this->GetNumberOfNodes() )
1090     {
1091       idx2 -= this->GetNumberOfNodes();
1092     }
1093   }
1094 
1095   slope[0] =
1096     this->Internal->Nodes[idx2]->WorldPosition[0] -
1097     this->Internal->Nodes[idx1]->WorldPosition[0];
1098   slope[1] =
1099     this->Internal->Nodes[idx2]->WorldPosition[1] -
1100     this->Internal->Nodes[idx1]->WorldPosition[1];
1101   slope[2] =
1102     this->Internal->Nodes[idx2]->WorldPosition[2] -
1103     this->Internal->Nodes[idx1]->WorldPosition[2];
1104 
1105   vtkMath::Normalize( slope );
1106   return 1;
1107 }
1108 
1109 //----------------------------------------------------------------------
UpdateLine(int idx1,int idx2)1110 void vtkContourRepresentation::UpdateLine( int idx1, int idx2 )
1111 {
1112   if ( !this->LineInterpolator )
1113   {
1114     return;
1115   }
1116 
1117   // Clear all the points at idx1
1118   for (unsigned int j=0;j<this->Internal->Nodes[idx1]->Points.size();j++)
1119   {
1120     delete this->Internal->Nodes[idx1]->Points[j];
1121   }
1122   this->Internal->Nodes[idx1]->Points.clear();
1123 
1124   this->LineInterpolator->InterpolateLine( this->Renderer,
1125                                            this,
1126                                            idx1, idx2 );
1127 }
1128 
1129 //----------------------------------------------------------------------
ComputeInteractionState(int vtkNotUsed (X),int vtkNotUsed (Y),int vtkNotUsed (modified))1130 int vtkContourRepresentation::ComputeInteractionState(
1131     int vtkNotUsed(X), int vtkNotUsed(Y), int vtkNotUsed(modified))
1132 {
1133   return this->InteractionState;
1134 }
1135 
1136 //---------------------------------------------------------------------
UpdateContour()1137 int vtkContourRepresentation::UpdateContour()
1138 {
1139   this->PointPlacer->UpdateInternalState();
1140 
1141   //even if just the camera has moved we need to mark the locator
1142   //as needing to be rebuilt
1143   if ( this->Locator->GetMTime() < this->Renderer->GetActiveCamera()->GetMTime())
1144   {
1145     this->RebuildLocator = true;
1146   }
1147 
1148   if ( this->ContourBuildTime > this->PointPlacer->GetMTime())
1149   {
1150     // Contour does not need to be rebuilt
1151     return 0;
1152   }
1153 
1154   unsigned int i;
1155   for(i=0; i<this->Internal->Nodes.size(); i++)
1156   {
1157     this->PointPlacer->
1158       UpdateWorldPosition( this->Renderer,
1159                            this->Internal->Nodes[i]->WorldPosition,
1160                            this->Internal->Nodes[i]->WorldOrientation );
1161   }
1162 
1163   for(i=0; (i+1)<this->Internal->Nodes.size(); i++)
1164   {
1165     this->UpdateLine(i, i+1);
1166   }
1167 
1168   if ( this->ClosedLoop )
1169   {
1170     this->UpdateLine( static_cast<int>(this->Internal->Nodes.size())-1, 0);
1171   }
1172   this->BuildLines();
1173   this->RebuildLocator = true;
1174 
1175   this->ContourBuildTime.Modified();
1176 
1177   return 1;
1178 }
1179 
1180 //----------------------------------------------------------------------
1181 void vtkContourRepresentation
GetRendererComputedDisplayPositionFromWorldPosition(double worldPos[3],double worldOrient[9],int displayPos[2])1182 ::GetRendererComputedDisplayPositionFromWorldPosition( double worldPos[3],
1183                                 double worldOrient[9], int displayPos[2] )
1184 {
1185   double dispPos[2];
1186   dispPos[0] = static_cast<double>(displayPos[0]);
1187   dispPos[1] = static_cast<double>(displayPos[1]);
1188   this->GetRendererComputedDisplayPositionFromWorldPosition( worldPos,
1189                                                 worldOrient, dispPos );
1190   displayPos[0] = static_cast<int>(dispPos[0]);
1191   displayPos[1] = static_cast<int>(dispPos[1]);
1192 }
1193 
1194 //----------------------------------------------------------------------
1195 void vtkContourRepresentation
GetRendererComputedDisplayPositionFromWorldPosition(double worldPos[3],double * vtkNotUsed (worldOrient[9]),double displayPos[2])1196 ::GetRendererComputedDisplayPositionFromWorldPosition( double worldPos[3],
1197                                 double * vtkNotUsed(worldOrient[9]), double displayPos[2] )
1198 {
1199   double pos[4];
1200   pos[0] = worldPos[0];
1201   pos[1] = worldPos[1];
1202   pos[2] = worldPos[2];
1203   pos[3] = 1.0;
1204 
1205   this->Renderer->SetWorldPoint( pos );
1206   this->Renderer->WorldToDisplay();
1207   this->Renderer->GetDisplayPoint( pos );
1208 
1209   displayPos[0] = pos[0];
1210   displayPos[1] = pos[1];
1211 }
1212 
1213 //----------------------------------------------------------------------
Initialize(vtkPolyData * pd)1214 void vtkContourRepresentation::Initialize( vtkPolyData * pd )
1215 {
1216   // For backward compatibility
1217   this->InitializeContour(pd, nullptr);
1218 }
1219 
1220 //----------------------------------------------------------------------
1221 void vtkContourRepresentation
Initialize(vtkPolyData * pd,vtkIdList * nodeIds)1222 ::Initialize( vtkPolyData * pd, vtkIdList *nodeIds )
1223 {
1224   if (!nodeIds)
1225   {
1226     this->Initialize(pd);
1227     return;
1228   }
1229 
1230   this->InitializeContour(pd, nodeIds);
1231 }
1232 
1233 //----------------------------------------------------------------------
1234 void vtkContourRepresentation
InitializeContour(vtkPolyData * pd,vtkIdList * nodeIds)1235 ::InitializeContour( vtkPolyData * pd, vtkIdList *nodeIds )
1236 {
1237   vtkPoints *points   = pd->GetPoints();
1238   vtkIdType nPoints = points->GetNumberOfPoints();
1239   if (nPoints <= 0)
1240   {
1241     return; // Yeah right.. build from nothing !
1242   }
1243 
1244   // Clear all existing nodes.
1245   for(unsigned int i=0;i<this->Internal->Nodes.size();i++)
1246   {
1247     for (unsigned int j=0;j<this->Internal->Nodes[i]->Points.size();j++)
1248     {
1249       delete this->Internal->Nodes[i]->Points[j];
1250     }
1251     this->Internal->Nodes[i]->Points.clear();
1252     delete this->Internal->Nodes[i];
1253   }
1254   this->Internal->Nodes.clear();
1255 
1256   vtkPolyData *tmpPoints = vtkPolyData::New();
1257   tmpPoints->DeepCopy(pd);
1258   this->Locator->SetDataSet(tmpPoints);
1259   tmpPoints->Delete();
1260 
1261   //reserver space in memory to speed up vector push_back
1262   this->Internal->Nodes.reserve(nPoints);
1263 
1264   vtkIdList *pointIds = pd->GetCell(0)->GetPointIds();
1265 
1266   // Get the worldOrient from the point placer
1267   double ref[3], displayPos[2], worldPos[3];
1268   double worldOrient[9] = {1.0,0.0,0.0,
1269                            0.0,1.0,0.0,
1270                            0.0,0.0,1.0};
1271   ref[0] = 0.0; ref[1] = 0.0; ref[2] = 0.0;
1272   displayPos[0] = 0.0; displayPos[1] = 0.0;
1273   this->PointPlacer->ComputeWorldPosition(this->Renderer,
1274                                  displayPos, ref, worldPos, worldOrient );
1275 
1276   // Add nodes without calling rebuild lines
1277   // to improve performance dramatically(~15x) on large datasets
1278   double *pos;
1279   for ( vtkIdType i=0; i < nPoints; i++ )
1280   {
1281     pos = points->GetPoint( i );
1282     this->GetRendererComputedDisplayPositionFromWorldPosition(
1283                           pos, worldOrient, displayPos );
1284 
1285     // Add a new point at this position
1286     vtkContourRepresentationNode *node = new vtkContourRepresentationNode;
1287     node->WorldPosition[0] = pos[0];
1288     node->WorldPosition[1] = pos[1];
1289     node->WorldPosition[2] = pos[2];
1290     node->Selected = 0;
1291 
1292     // Give the point placer a chance to update the node
1293     if (nodeIds && nodeIds->GetNumberOfIds() == nPoints)
1294     {
1295       this->PointPlacer->UpdateNodeWorldPosition( pos, nodeIds->GetId(i) );
1296     }
1297 
1298     node->NormalizedDisplayPosition[0] = displayPos[0];
1299     node->NormalizedDisplayPosition[1] = displayPos[1];
1300 
1301     this->Renderer->DisplayToNormalizedDisplay(
1302       node->NormalizedDisplayPosition[0],
1303       node->NormalizedDisplayPosition[1] );
1304 
1305     memcpy(node->WorldOrientation, worldOrient, 9*sizeof(double) );
1306 
1307     this->Internal->Nodes.push_back(node);
1308 
1309     if ( this->LineInterpolator && this->GetNumberOfNodes() > 1 )
1310     {
1311       // Give the line interpolator a chance to update the node.
1312       int didNodeChange = this->LineInterpolator->UpdateNode(
1313         this->Renderer, this,
1314         node->WorldPosition, this->GetNumberOfNodes()-1 );
1315 
1316       // Give the point placer a chance to validate the updated node. If its
1317       // not valid, discard the LineInterpolator's change.
1318       if ( didNodeChange && !this->PointPlacer->ValidateWorldPosition(
1319                 node->WorldPosition, worldOrient ) )
1320       {
1321         node->WorldPosition[0] = worldPos[0];
1322         node->WorldPosition[1] = worldPos[1];
1323         node->WorldPosition[2] = worldPos[2];
1324       }
1325     }
1326   }
1327 
1328   if ( pointIds->GetNumberOfIds() > nPoints )
1329   {
1330     this->ClosedLoopOn();
1331   }
1332 
1333   // Update the contour representation from the nodes using the line interpolator
1334   for (vtkIdType i=1; i <= nPoints; ++i)
1335   {
1336     this->UpdateLines(i);
1337   }
1338   this->BuildRepresentation();
1339 
1340   // Show the contour.
1341   this->VisibilityOn();
1342 }
1343 
1344 //----------------------------------------------------------------------
BuildLocator()1345 void vtkContourRepresentation::BuildLocator()
1346 {
1347 if (!this->RebuildLocator && !this->NeedToRender)
1348 {
1349     //rebuild if rebuildLocator or needtorender are true
1350     return;
1351 }
1352 
1353   vtkIdType size = (vtkIdType)this->Internal->Nodes.size();
1354   vtkPoints *points = vtkPoints::New();
1355   points->SetNumberOfPoints(size);
1356 
1357   //setup up the matrixes needed to transform
1358   //world to display. We are going to do this manually
1359   // as calling the renderer will create a new matrix for each call
1360   vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
1361   matrix->DeepCopy(this->Renderer->GetActiveCamera()
1362     ->GetCompositeProjectionTransformMatrix(
1363     this->Renderer->GetTiledAspectRatio(),0,1));
1364 
1365   //viewport info
1366   double viewPortRatio[2];
1367   int sizex,sizey;
1368 
1369   /* get physical window dimensions */
1370   if ( this->Renderer->GetVTKWindow() )
1371   {
1372     double *viewPort = this->Renderer->GetViewport();
1373     sizex = this->Renderer->GetVTKWindow()->GetSize()[0];
1374     sizey = this->Renderer->GetVTKWindow()->GetSize()[1];
1375     viewPortRatio[0] = (sizex*(viewPort[2]-viewPort[0])) / 2.0 +
1376         sizex*viewPort[0];
1377     viewPortRatio[1] = (sizey*(viewPort[3]-viewPort[1])) / 2.0 +
1378         sizey*viewPort[1];
1379   }
1380   else
1381   {
1382     //can't compute the locator without a vtk window
1383     return;
1384   }
1385 
1386   double     view[4];
1387   double pos[3] = {0,0,0};
1388   double *wp;
1389   for(vtkIdType i=0; i < size; ++i)
1390   {
1391     wp = this->Internal->Nodes[i]->WorldPosition;
1392     pos[0] = this->Internal->Nodes[i]->WorldPosition[0];
1393     pos[1] = this->Internal->Nodes[i]->WorldPosition[1];
1394     pos[2] = this->Internal->Nodes[i]->WorldPosition[2];
1395 
1396     //convert from world to view
1397     view[0] = wp[0]*matrix->Element[0][0] + wp[1]*matrix->Element[0][1] +
1398       wp[2]*matrix->Element[0][2] + matrix->Element[0][3];
1399     view[1] = wp[0]*matrix->Element[1][0] + wp[1]*matrix->Element[1][1] +
1400       wp[2]*matrix->Element[1][2] + matrix->Element[1][3];
1401     view[2] = wp[0]*matrix->Element[2][0] + wp[1]*matrix->Element[2][1] +
1402       wp[2]*matrix->Element[2][2] + matrix->Element[2][3];
1403     view[3] = wp[0]*matrix->Element[3][0] + wp[1]*matrix->Element[3][1] +
1404       wp[2]*matrix->Element[3][2] + matrix->Element[3][3];
1405     if (view[3] != 0.0)
1406     {
1407       pos[0] = view[0]/view[3];
1408       pos[1] = view[1]/view[3];
1409     }
1410 
1411     //now from view to display
1412     pos[0] = (pos[0] + 1.0) * viewPortRatio[0];
1413     pos[1] = (pos[1] + 1.0) * viewPortRatio[1];
1414     pos[2] = 0;
1415 
1416     points->InsertPoint(i,pos);
1417   }
1418 
1419   matrix->Delete();
1420   vtkPolyData *tmp = vtkPolyData::New();
1421   tmp->SetPoints(points);
1422   this->Locator->SetDataSet(tmp);
1423   tmp->FastDelete();
1424   points->FastDelete();
1425 
1426   //we fully updated the display locator
1427   this->RebuildLocator = false;
1428 }
1429 
1430 //----------------------------------------------------------------------
SetShowSelectedNodes(vtkTypeBool flag)1431 void vtkContourRepresentation::SetShowSelectedNodes(vtkTypeBool flag )
1432 {
1433   if (this->ShowSelectedNodes != flag)
1434   {
1435     this->ShowSelectedNodes = flag;
1436     this->Modified();
1437   }
1438 }
1439 
1440 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1441 void vtkContourRepresentation::PrintSelf(ostream& os, vtkIndent indent)
1442 {
1443   //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
1444   this->Superclass::PrintSelf(os,indent);
1445 
1446   os << indent << "Pixel Tolerance: " << this->PixelTolerance <<"\n";
1447   os << indent << "World Tolerance: " << this->WorldTolerance <<"\n";
1448 
1449   os << indent << "Closed Loop: " << (this->ClosedLoop ? "On\n" : "Off\n");
1450   os << indent << "ShowSelectedNodes: " << this->ShowSelectedNodes <<endl;
1451   os << indent << "Rebuild Locator: " <<
1452      (this->RebuildLocator ? "On" : "Off") << endl;
1453 
1454   os << indent << "Current Operation: ";
1455   if ( this->CurrentOperation == vtkContourRepresentation::Inactive )
1456   {
1457     os << "Inactive\n";
1458   }
1459   else
1460   {
1461     os << "Translate\n";
1462   }
1463 
1464   os << indent << "Line Interpolator: " << this->LineInterpolator << "\n";
1465   os << indent << "Point Placer: " << this->PointPlacer << "\n";
1466 
1467 }
1468