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