1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFocalPlaneContourRepresentation.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 "vtkFocalPlaneContourRepresentation.h"
16 #include "vtkHandleRepresentation.h"
17 #include "vtkCoordinate.h"
18 #include "vtkRenderer.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkBox.h"
21 #include "vtkInteractorObserver.h"
22 #include "vtkMath.h"
23 #include "vtkFocalPlanePointPlacer.h"
24 #include "vtkContourLineInterpolator.h"
25 #include "vtkLine.h"
26 #include "vtkCamera.h"
27 #include "vtkPolyData.h"
28 #include "vtkCellArray.h"
29 
30 #include <vector>
31 #include <set>
32 #include <algorithm>
33 #include <iterator>
34 
35 
36 //----------------------------------------------------------------------
vtkFocalPlaneContourRepresentation()37 vtkFocalPlaneContourRepresentation::vtkFocalPlaneContourRepresentation()
38 {
39   this->PointPlacer              = vtkFocalPlanePointPlacer::New();
40 }
41 
42 //----------------------------------------------------------------------
~vtkFocalPlaneContourRepresentation()43 vtkFocalPlaneContourRepresentation::~vtkFocalPlaneContourRepresentation()
44 {
45 }
46 
47 //----------------------------------------------------------------------
48 // Compute the world position from the display position for this given
49 // point using the renderer.
GetIntermediatePointWorldPosition(int n,int idx,double point[3])50 int vtkFocalPlaneContourRepresentation::GetIntermediatePointWorldPosition(int n,
51                                                                 int idx,
52                                                                 double point[3])
53 {
54   if ( n < 0 ||
55        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
56     {
57     return 0;
58     }
59 
60   if ( idx < 0 ||
61        static_cast<unsigned int>(idx) >= this->Internal->Nodes[n]->Points.size() )
62     {
63     return 0;
64     }
65 
66   double p[4], fp[4], z, dispPos[2];
67   this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
68   vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer,
69                                       fp[0], fp[1], fp[2], fp);
70   z = fp[2];
71 
72   dispPos[0] = this->Internal->Nodes[n]->Points[idx]->NormalizedDisplayPosition[0];
73   dispPos[1] = this->Internal->Nodes[n]->Points[idx]->NormalizedDisplayPosition[1];
74   this->Renderer->NormalizedDisplayToDisplay( dispPos[0], dispPos[1] );
75 
76   vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer,
77                                 dispPos[0], dispPos[1], z, p);
78 
79   point[0] = p[0];
80   point[1] = p[1];
81   point[2] = p[2];
82 
83   return 1;
84 }
85 
86 //----------------------------------------------------------------------
87 // Compute the world position from the display position for this given
88 // point using the renderer.
GetIntermediatePointDisplayPosition(int n,int idx,double point[3])89 int vtkFocalPlaneContourRepresentation::GetIntermediatePointDisplayPosition(int n,
90                                                                 int idx,
91                                                                 double point[3])
92 {
93   if ( n < 0 ||
94        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
95     {
96     return 0;
97     }
98 
99   if ( idx < 0 ||
100        static_cast<unsigned int>(idx) >= this->Internal->Nodes[n]->Points.size() )
101     {
102     return 0;
103     }
104 
105   point[0] = this->Internal->Nodes[n]->Points[idx]->NormalizedDisplayPosition[0];
106   point[1] = this->Internal->Nodes[n]->Points[idx]->NormalizedDisplayPosition[1];
107   this->Renderer->NormalizedDisplayToDisplay( point[0], point[1] );
108 
109   return 1;
110 }
111 
112 //----------------------------------------------------------------------
GetNthNodeDisplayPosition(int n,double displayPos[2])113 int vtkFocalPlaneContourRepresentation::GetNthNodeDisplayPosition(
114                                      int n, double displayPos[2] )
115 {
116   if ( n < 0 ||
117        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
118     {
119     return 0;
120     }
121 
122   displayPos[0] = this->Internal->Nodes[n]->NormalizedDisplayPosition[0];
123   displayPos[1] = this->Internal->Nodes[n]->NormalizedDisplayPosition[1];
124   this->Renderer->NormalizedDisplayToDisplay( displayPos[0], displayPos[1] );
125 
126   return 1;
127 }
128 
129 //----------------------------------------------------------------------
GetNthNodeWorldPosition(int n,double worldPos[3])130 int vtkFocalPlaneContourRepresentation::GetNthNodeWorldPosition(
131                                      int n, double worldPos[3] )
132 {
133   if ( n < 0 ||
134        static_cast<unsigned int>(n) >= this->Internal->Nodes.size() )
135     {
136     return 0;
137     }
138 
139   double p[4], fp[4], z, dispPos[2];
140   this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
141   vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer,
142                                       fp[0], fp[1], fp[2], fp);
143   z = fp[2];
144   dispPos[0] = this->Internal->Nodes[n]->NormalizedDisplayPosition[0];
145   dispPos[1] = this->Internal->Nodes[n]->NormalizedDisplayPosition[1];
146   this->Renderer->NormalizedDisplayToDisplay( dispPos[0], dispPos[1] );
147   vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer,
148                                 dispPos[0], dispPos[1], z, p);
149 
150   worldPos[0] = p[0];
151   worldPos[1] = p[1];
152   worldPos[2] = p[2];
153 
154   return 1;
155 }
156 
157 //----------------------------------------------------------------------
158 void vtkFocalPlaneContourRepresentation
UpdateContourWorldPositionsBasedOnDisplayPositions()159 ::UpdateContourWorldPositionsBasedOnDisplayPositions()
160 {
161   double p[4], fp[4], z, dispPos[2];
162   this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
163   vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer,
164                                       fp[0], fp[1], fp[2], fp);
165   z = fp[2];
166 
167   for(unsigned int i=0;i<this->Internal->Nodes.size();i++)
168     {
169 
170     dispPos[0] = this->Internal->Nodes[i]->NormalizedDisplayPosition[0];
171     dispPos[1] = this->Internal->Nodes[i]->NormalizedDisplayPosition[1];
172     this->Renderer->NormalizedDisplayToDisplay( dispPos[0], dispPos[1] );
173 
174     vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer,
175                                     dispPos[0], dispPos[1], z, p);
176 
177     this->Internal->Nodes[i]->WorldPosition[0] = p[0];
178     this->Internal->Nodes[i]->WorldPosition[1] = p[1];
179     this->Internal->Nodes[i]->WorldPosition[2] = p[2];
180 
181     for (unsigned int j=0;j<this->Internal->Nodes[i]->Points.size();j++)
182       {
183       dispPos[0] = this->Internal->Nodes[i]->Points[j]->NormalizedDisplayPosition[0];
184       dispPos[1] = this->Internal->Nodes[i]->Points[j]->NormalizedDisplayPosition[1];
185       this->Renderer->NormalizedDisplayToDisplay( dispPos[0], dispPos[1] );
186 
187       vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer,
188                                       dispPos[0], dispPos[1], z, p);
189 
190       this->Internal->Nodes[i]->Points[j]->WorldPosition[0] = p[0];
191       this->Internal->Nodes[i]->Points[j]->WorldPosition[1] = p[1];
192       this->Internal->Nodes[i]->Points[j]->WorldPosition[2] = p[2];
193       }
194     }
195 }
196 
197 //---------------------------------------------------------------------
UpdateContour()198 int vtkFocalPlaneContourRepresentation::UpdateContour()
199 {
200   this->PointPlacer->UpdateInternalState();
201 
202   if ( this->ContourBuildTime > this->Renderer->GetMTime() &&
203        this->ContourBuildTime > this->PointPlacer->GetMTime() )
204     {
205     // Contour does not need to be rebuilt
206     return 0;
207     }
208 
209   // The representation maintains its true positions based on display positions.
210   // Sync the world positions in terms of the current display positions.
211   // The superclass will do the line interpolation etc from the world positions
212   //
213   // TODO:
214   // I don't want to rebuild the contour every time the renderer changes
215   // state. For instance there is no reason for me to re-do this when a W/L
216   // action is performed on the window. How do I know if relevant events have
217   // transpired like zoom or scale changes ?
218   //   In the current state, the 'if' statement above is invariably true.
219   //
220   this->UpdateContourWorldPositionsBasedOnDisplayPositions();
221 
222   unsigned int i;
223   for(i=0; (i+1)<this->Internal->Nodes.size(); i++)
224     {
225     this->UpdateLine(i, i+1);
226     }
227 
228   if ( this->ClosedLoop )
229     {
230     this->UpdateLine( static_cast<int>(this->Internal->Nodes.size())-1, 0);
231     }
232   this->BuildLines();
233 
234   this->ContourBuildTime.Modified();
235   return 1;
236 }
237 
238 //----------------------------------------------------------------------
UpdateLines(int index)239 void vtkFocalPlaneContourRepresentation::UpdateLines( int index )
240 {
241   this->Superclass::UpdateLines(index);
242 }
243 
244 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)245 void vtkFocalPlaneContourRepresentation::PrintSelf(ostream& os, vtkIndent indent)
246 {
247   this->Superclass::PrintSelf(os,indent);
248 }
249 
250