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