1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkInteractorStyleDrawPolygon.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 "vtkInteractorStyleDrawPolygon.h"
16 
17 #include "vtkCommand.h"
18 #include "vtkNew.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkRenderer.h"
21 #include "vtkRenderWindow.h"
22 #include "vtkRenderWindowInteractor.h"
23 #include "vtkUnsignedCharArray.h"
24 #include "vtkVectorOperators.h"
25 
26 vtkStandardNewMacro(vtkInteractorStyleDrawPolygon);
27 
28 //-----------------------------------------------------------------------------
29 class vtkInteractorStyleDrawPolygon::vtkInternal
30 {
31 public:
32   std::vector<vtkVector2i> points;
33 
AddPoint(const vtkVector2i & point)34   void AddPoint(const vtkVector2i &point)
35     {
36     this->points.push_back(point);
37     }
38 
AddPoint(int x,int y)39   void AddPoint(int x, int y)
40     {
41     this->AddPoint(vtkVector2i(x, y));
42     }
43 
GetPoint(vtkIdType index) const44   vtkVector2i GetPoint(vtkIdType index) const
45     {
46     return this->points[index];
47     }
48 
GetNumberOfPoints() const49   vtkIdType GetNumberOfPoints() const
50     {
51     return this->points.size();
52     }
53 
Clear()54   void Clear()
55     {
56     this->points.clear();
57     }
58 
DrawPixels(const vtkVector2i & StartPos,const vtkVector2i & EndPos,unsigned char * pixels,int * size)59   void DrawPixels(const vtkVector2i& StartPos,
60     const vtkVector2i& EndPos, unsigned char *pixels, int *size)
61     {
62     int x1=StartPos.GetX(), x2=EndPos.GetX();
63     int y1=StartPos.GetY(), y2=EndPos.GetY();
64 
65     double x = x2 - x1;
66     double y = y2 - y1;
67     double length = sqrt( x*x + y*y );
68     if(length == 0)
69       {
70       return;
71       }
72     double addx = x / length;
73     double addy = y / length;
74 
75     x = x1;
76     y = y1;
77     int row, col;
78     for(double i = 0; i < length; i += 1)
79       {
80       col = (int)x;
81       row = (int)y;
82       pixels[3*(row*size[0]+col)] = 255 ^ pixels[3*(row*size[0]+col)];
83       pixels[3*(row*size[0]+col)+1] = 255 ^ pixels[3*(row*size[0]+col)+1];
84       pixels[3*(row*size[0]+col)+2] = 255 ^ pixels[3*(row*size[0]+col)+2];
85       x += addx;
86       y += addy;
87       }
88     }
89 };
90 
91 //----------------------------------------------------------------------------
vtkInteractorStyleDrawPolygon()92 vtkInteractorStyleDrawPolygon::vtkInteractorStyleDrawPolygon()
93 {
94   this->Internal = new vtkInternal();
95   this->StartPosition[0] = this->StartPosition[1] = 0;
96   this->EndPosition[0] = this->EndPosition[1] = 0;
97   this->Moving = 0;
98   this->DrawPolygonPixels = true;
99   this->PixelArray = vtkUnsignedCharArray::New();
100 }
101 
102 //----------------------------------------------------------------------------
~vtkInteractorStyleDrawPolygon()103 vtkInteractorStyleDrawPolygon::~vtkInteractorStyleDrawPolygon()
104 {
105   this->PixelArray->Delete();
106   delete this->Internal;
107 }
108 
109 //----------------------------------------------------------------------------
GetPolygonPoints()110 std::vector<vtkVector2i> vtkInteractorStyleDrawPolygon::GetPolygonPoints()
111 {
112   return this->Internal->points;
113 }
114 
115 //----------------------------------------------------------------------------
OnMouseMove()116 void vtkInteractorStyleDrawPolygon::OnMouseMove()
117 {
118   if (!this->Interactor || !this->Moving)
119     {
120     return;
121     }
122 
123   this->EndPosition[0] = this->Interactor->GetEventPosition()[0];
124   this->EndPosition[1] = this->Interactor->GetEventPosition()[1];
125   int *size = this->Interactor->GetRenderWindow()->GetSize();
126   if (this->EndPosition[0] > (size[0]-1))
127     {
128     this->EndPosition[0] = size[0]-1;
129     }
130   if (this->EndPosition[0] < 0)
131     {
132     this->EndPosition[0] = 0;
133     }
134   if (this->EndPosition[1] > (size[1]-1))
135     {
136     this->EndPosition[1] = size[1]-1;
137     }
138   if (this->EndPosition[1] < 0)
139     {
140     this->EndPosition[1] = 0;
141     }
142 
143   vtkVector2i lastPoint =
144     this->Internal->GetPoint(
145     this->Internal->GetNumberOfPoints() - 1);
146   vtkVector2i newPoint(this->EndPosition[0], this->EndPosition[1]);
147   if((lastPoint - newPoint).SquaredNorm() > 100)
148     {
149     this->Internal->AddPoint(newPoint);
150     if(this->DrawPolygonPixels)
151       {
152       this->DrawPolygon();
153       }
154     }
155 }
156 
157 //----------------------------------------------------------------------------
OnLeftButtonDown()158 void vtkInteractorStyleDrawPolygon::OnLeftButtonDown()
159 {
160   if (!this->Interactor)
161     {
162     return;
163     }
164   this->Moving = 1;
165 
166   vtkRenderWindow *renWin = this->Interactor->GetRenderWindow();
167 
168   this->StartPosition[0] = this->Interactor->GetEventPosition()[0];
169   this->StartPosition[1] = this->Interactor->GetEventPosition()[1];
170   this->EndPosition[0] = this->StartPosition[0];
171   this->EndPosition[1] = this->StartPosition[1];
172 
173   this->PixelArray->Initialize();
174   this->PixelArray->SetNumberOfComponents(3);
175   int *size = renWin->GetSize();
176   this->PixelArray->SetNumberOfTuples(size[0]*size[1]);
177 
178   renWin->GetPixelData(0, 0, size[0]-1, size[1]-1, 1, this->PixelArray);
179   this->Internal->Clear();
180   this->Internal->AddPoint(this->StartPosition[0], this->StartPosition[1]);
181   this->InvokeEvent(vtkCommand::StartInteractionEvent);
182 }
183 
184 //----------------------------------------------------------------------------
OnLeftButtonUp()185 void vtkInteractorStyleDrawPolygon::OnLeftButtonUp()
186 {
187   if (!this->Interactor || !this->Moving)
188     {
189     return;
190     }
191 
192   if(this->DrawPolygonPixels)
193     {
194     int *size = this->Interactor->GetRenderWindow()->GetSize();
195     unsigned char *pixels = this->PixelArray->GetPointer(0);
196     this->Interactor->GetRenderWindow()->SetPixelData(
197       0, 0, size[0]-1, size[1]-1, pixels, 1);
198     }
199 
200   this->Moving = 0;
201   this->InvokeEvent(vtkCommand::SelectionChangedEvent);
202   this->InvokeEvent(vtkCommand::EndInteractionEvent);
203 }
204 
205 //----------------------------------------------------------------------------
DrawPolygon()206 void vtkInteractorStyleDrawPolygon::DrawPolygon()
207 {
208   vtkNew<vtkUnsignedCharArray> tmpPixelArray;
209   tmpPixelArray->DeepCopy(this->PixelArray);
210   unsigned char *pixels = tmpPixelArray->GetPointer(0);
211   int *size = this->Interactor->GetRenderWindow()->GetSize();
212 
213   // draw each line segment
214   for(vtkIdType i = 0; i < this->Internal->GetNumberOfPoints() - 1; i++)
215     {
216     const vtkVector2i &a = this->Internal->GetPoint(i);
217     const vtkVector2i &b = this->Internal->GetPoint(i+1);
218 
219     this->Internal->DrawPixels(a, b, pixels, size);
220     }
221 
222   // draw a line from the end to the start
223   if(this->Internal->GetNumberOfPoints() >= 3)
224     {
225     const vtkVector2i &start = this->Internal->GetPoint(0);
226     const vtkVector2i &end = this->Internal->GetPoint(this->Internal->GetNumberOfPoints() - 1);
227 
228     this->Internal->DrawPixels(start, end, pixels, size);
229     }
230 
231   this->Interactor->GetRenderWindow()->SetPixelData(0, 0, size[0]-1, size[1]-1, pixels, 1);
232 }
233 
234 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)235 void vtkInteractorStyleDrawPolygon::PrintSelf(ostream& os, vtkIndent indent)
236 {
237   this->Superclass::PrintSelf(os, indent);
238   os << indent << "Moving: " << this->Moving << endl;
239   os << indent << "DrawPolygonPixels: " << this->DrawPolygonPixels << endl;
240   os << indent << "StartPosition: " << this->StartPosition[0] << "," << this->StartPosition[1] << endl;
241   os << indent << "EndPosition: " << this->EndPosition[0] << "," << this->EndPosition[1] << endl;
242 }
243