Points&Forces (survey)
Software tools facilitating the task of surveying architecture
pixelpos.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2008-2019 Pierre SMARS (smars@yuntech.edu.tw)
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 2 of the License, or
6  (at your option) any later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 #include "vtkTIFFReader.h"
17 #include "vtkJPEGReader.h"
18 #include "vtkPNGReader.h"
19 #include "vtkRenderer.h"
20 #include "vtkRenderWindow.h"
21 #include "vtkRenderWindowInteractor.h"
22 #include "vtkPolyData.h"
23 #include "vtkPoints.h"
24 #include "vtkIntArray.h"
25 #include "vtkCellArray.h"
26 #include "vtkPolyDataMapper.h"
27 #include "vtkLookupTable.h"
28 #include "vtkActor.h"
29 #include "vtkFloatArray.h"
30 #include "vtkTexture.h"
31 #include "vtkImageResample.h"
32 #include "vtkImageClip.h"
33 #include "vtkCamera.h"
34 #include "vtkImageShiftScale.h"
35 
36 #include <sstream>
37 #include <string>
38 #include <iostream>
39 #include <vector>
40 
41 #include "SimpleOpt.h"
42 
43 #include "a_subpixel_interactor.h"
45 
46 CSimpleOpt::SOption g_rgOptions[] = {
47  { OPT_Xm, _T("-xm"), SO_REQ_SEP },
48  { OPT_Ym, _T("-ym"), SO_REQ_SEP },
49  { OPT_XM, _T("-xM"), SO_REQ_SEP },
50  { OPT_YM, _T("-yM"), SO_REQ_SEP },
51  { OPT_OUT, _T("-nof"), SO_NONE },
52  { OPT_OUT, _T("--no-output-file"), SO_NONE },
53  { OPT_IN, _T("-i"), SO_REQ_SEP },
54  { OPT_IN, _T("--input"), SO_REQ_SEP },
55  { OPT_QUIET, _T("-q"), SO_NONE },
56  { OPT_QUIET, _T("--quit"), SO_NONE },
57  { OPT_HELP, _T("-?"), SO_NONE },
58  { OPT_HELP, _T("-h"), SO_NONE },
59  { OPT_HELP, _T("--help"), SO_NONE },
60  SO_END_OF_OPTIONS
61 };
62 
63 //---------------------------------------------------------------------------
64 int error(int val)
65 {
66 #include "pixelpos.help"
67  return val;
68 }
69 
70 bool with_output = true;
71 bool small_window = false;
72 bool verbose = true;
73 int xm = 0;
74 int ym = 0;
75 int xM = 100000;
76 int yM = 100000;
77 std::string name;
78 std::string input_file("");
79 
80 //---------------------------------------------------------------------------
81 int error_tests(int argc, char ** argv)
82 {
83  CSimpleOpt args(argc, argv, g_rgOptions);
84  while (args.Next())
85  {
86  if (args.LastError() == SO_SUCCESS)
87  {
88  if (args.OptionId() == OPT_HELP)
89  return error(-1);
90  else if (args.OptionId() == OPT_OUT)
91  with_output = false;
92  else if (args.OptionId() == OPT_QUIET)
93  verbose = false;
94  else if (args.OptionId() == OPT_Xm)
95  {
96  std::ostringstream o;
97  o << args.OptionArg();
98  std::istringstream in(o.str().c_str());
99  in >> xm;
100  } else if (args.OptionId() == OPT_Ym)
101  {
102  std::ostringstream o;
103  o << args.OptionArg();
104  std::istringstream in(o.str().c_str());
105  in >> ym;
106  } else if (args.OptionId() == OPT_XM)
107  {
108  std::ostringstream o;
109  o << args.OptionArg();
110  std::istringstream in(o.str().c_str());
111  in >> xM;
112  } else if (args.OptionId() == OPT_YM)
113  {
114  std::ostringstream o;
115  o << args.OptionArg();
116  std::istringstream in(o.str().c_str());
117  in >> yM;
118  } else if (args.OptionId() == OPT_IN)
119  {
120  input_file = args.OptionArg();
121  } else
122  return error(-2);
123  // handle option, using OptionId(), OptionText() and OptionArg()
124  } else {
125  std::cerr << "Invalid argument: " << args.OptionText() << std::endl;
126  return error(args.LastError());
127  // handle error, one of: SO_OPT_INVALID, SO_OPT_MULTIPLE,
128  // SO_ARG_INVALID, SO_ARG_INVALID_TYPE, SO_ARG_MISSING
129  }
130  }
131  if (args.FileCount() != 1) return error(-3);
132  name = args.File(0);
133  return 0;
134 }
135 //---------------------------------------------------------------------------
136 int * window(int xm, int ym, int xM, int yM, int * dim)
137 {
138  auto val = new int[6];
139  val[0] = 0; val[1] = dim[0]-1;
140  val[2] = 0; val[3] = dim[1]-1;
141  val[4] = 0; val[5] = 0;
142  if ((xm>0)&&(xm<dim[0]-1))
143  {
144  val[0] = xm;
145  small_window = true;
146  }
147  if ((xM>xm)&&(xM<dim[0]-1))
148  {
149  val[1] = xM;
150  small_window = true;
151  }
152  if ((ym>0)&&(ym<dim[1]-1))
153  {
154  val[2] = ym;
155  small_window = true;
156  }
157  if ((yM>ym)&&(yM<dim[1]-1))
158  {
159  val[3] = yM;
160  small_window = true;
161  }
162  return val;
163 }
164 //--------------Stroustroup, p.591
165 //comparisons without case
166 int cmp_nocase(const std::string& s, const std::string& s2)
167 {
168  std::string::const_iterator p = s.begin();
169  std::string::const_iterator p2 = s2.begin();
170  while (p != s.end() && p2 != s2.end())
171  {
172  if (toupper(*p) != toupper(*p2))
173  return (toupper(*p) < toupper(*p2)) ? -1 : 1;
174  ++p;
175  ++p2;
176  }
177  return (s2.size() == s.size()) ? 0 : (s.size() < s2.size()) ? -1 : 1; //size is unsigned
178 }
179 //---------------------------------------------------------------------------
180 int main(int argc, char ** argv)
181 {
182  int val = error_tests(argc, argv);
183  if (val != 0) return val;
184  std::string ext = name.substr(name.find_last_of('.')+1,name.size());
185  vtkImageReader2 * reader;
186  if ((cmp_nocase(ext,"tif")==0)||(cmp_nocase(ext,"tiff")==0))
187  reader = (vtkImageReader2 *)vtkTIFFReader::New();
188  else if ((cmp_nocase(ext,"jpg")==0)||(cmp_nocase(ext,"jpeg")==0))
189  reader = (vtkImageReader2 *)vtkJPEGReader::New();
190  else if ((cmp_nocase(ext,"png")==0)||(cmp_nocase(ext,"png")==0))
191  reader = (vtkImageReader2 *)vtkPNGReader::New();
192  else return error(-3);
193  reader->SetFileName(name.c_str());
194  reader->Update();
195  int * dim = reader->GetOutput()->GetDimensions();
196 
197  if (verbose)
198  {
199  std::cerr << "Dimensions: " << dim[0] << " " << dim [1] << " [";
200  std::cerr << reader->GetNumberOfScalarComponents() << " x ";
201  }
202  int dtype = reader->GetDataScalarType();
203  if (verbose)
204  {
205  if (dtype == VTK_UNSIGNED_CHAR)
206  std::cerr << "unsigned char (8bits)";
207  else if (dtype == VTK_UNSIGNED_SHORT)
208  std::cerr << "unsigned short (16bits)";
209  else
210  std::cerr << "type (" << reader->GetDataScalarType() << ")";
211  //implement other types if needed
212  std::cerr << "]" << std::endl;
213  }
214 
215  vtkRenderer *ren = vtkRenderer::New();
216  vtkRenderWindow *renWin = vtkRenderWindow::New();
217  renWin->AddRenderer(ren);
218  ren->Delete();
219 
220  pixelpos_points coord(ren);
221  if (!verbose)
222  coord.quiet();
223 
224  int * dim2 = window(xm,ym,xM,yM,dim);
225  vtkImageClip * clip = vtkImageClip::New();
226  clip->SetInputConnection(reader->GetOutputPort());
227  clip->SetOutputWholeExtent(dim2);
228  double scale;
229  if (reader->GetDataScalarType()==5)
230  scale = 1./256.;
231  else
232  scale = 1.;
233  vtkImageShiftScale * cast = vtkImageShiftScale::New();
234  cast->SetInputConnection(clip->GetOutputPort());
235  clip->Delete();
236  cast->SetShift(0.);
237  cast->SetScale(scale);
238  cast->ClampOverflowOn();
239  cast->SetOutputScalarTypeToUnsignedChar();
240  vtkTexture * texture = vtkTexture::New();
241  texture->SetInputConnection(cast->GetOutputPort());
242  cast->Delete();
243  texture->InterpolateOff();
244  vtkFloatArray * tcoords = vtkFloatArray::New();
245  tcoords->SetNumberOfComponents(2);
246  tcoords->SetNumberOfTuples(4);
247  float p[] = {0.,0.};
248  tcoords->SetTuple(0,p);
249  p[0] = 1.;
250  tcoords->SetTuple(1,p);
251  p[1] = 1.;
252  tcoords->SetTuple(2,p);
253  p[0] = 0.;
254  tcoords->SetTuple(3,p);
256  style->SetImage(reader);
257  style->setpos(&coord);
258  style->setscale(cast,scale);
259  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
260  iren->SetRenderWindow(renWin);
261  iren->SetInteractorStyle(style);
262  style->Delete();
263 
264  float x[4][3]={{static_cast<float>(dim2[0]),static_cast<float>(dim2[2]),0.f},
265  {static_cast<float>(dim2[1]),static_cast<float>(dim2[2]),0.f},
266  {static_cast<float>(dim2[1]),static_cast<float>(dim2[3]),0.f},
267  {static_cast<float>(dim2[0]),static_cast<float>(dim2[3]),0.f}};
268  vtkIdType pts[1][4]={{0,1,2,3}};
269 
270  vtkPoints * points = vtkPoints::New();
271  for (int i=0; i<4; i++) points->InsertPoint(i,x[i]);
272  vtkCellArray * polys = vtkCellArray::New();
273  polys->InsertNextCell(4,pts[0]);
274  vtkPolyData * plane = vtkPolyData::New();
275  plane->SetPoints(points);
276  points->Delete();
277  plane->SetPolys(polys);
278  plane->GetPointData()->SetTCoords(tcoords);
279  vtkPolyDataMapper * map = vtkPolyDataMapper::New();
280  map->SetInputData(plane);
281  plane->Delete();
282  vtkActor * actor = vtkActor::New();
283  actor->SetMapper(map);
284  actor->DragableOff();
285  map->Delete();
286  actor->SetTexture(texture);
287  texture->Delete();
288  ren->AddActor(actor);
289  actor->Delete();
290 
291  style->set(points,clip,dim[0],dim[1]);
292 
293  if (small_window)
294  {
295  vtkImageResample * resample = vtkImageResample::New();
296  resample->SetInputConnection(reader->GetOutputPort());
297  resample->SetAxisMagnificationFactor(0,.1);
298  resample->SetAxisMagnificationFactor(1,.1);
299  vtkTexture * texture2 = vtkTexture::New();
300  texture2->SetInputConnection(resample->GetOutputPort());
301  resample->Delete();
302  float x2[4][3]={{0.f,0.f,0.f},
303  {static_cast<float>(dim[0]),0.f,-.5f},
304  {static_cast<float>(dim[0]),static_cast<float>(dim[1]),-.5f},
305  {0.f,static_cast<float>(dim[1]),-.5f}};
306  vtkPoints * points2 = vtkPoints::New();
307  for (int i=0; i<4; i++) points2->InsertPoint(i,x2[i]);
308  vtkIntArray * scalars = vtkIntArray::New();
309  scalars->SetNumberOfComponents(1);
310  scalars->SetNumberOfTuples(4);
311  for (int i=0; i<4; i++) scalars->SetTuple1(i,8);
312 
313  vtkPolyData * plane2 = vtkPolyData::New();
314  plane2->SetPoints(points2);
315  points2->Delete();
316  plane2->SetPolys(polys);
317  plane2->GetPointData()->SetScalars(scalars);
318  scalars->Delete();
319  plane2->GetPointData()->SetTCoords(tcoords);
320  vtkLookupTable * lut = vtkLookupTable::New();
321  lut->SetHueRange(0.6,0);
322  lut->SetSaturationRange(.2,.2);
323  lut->SetValueRange(1,1);
324  vtkPolyDataMapper * map2 = vtkPolyDataMapper::New();
325  map2->SetInputData(plane2);
326  plane2->Delete();
327  map2->SetScalarRange(0,10);
328  map2->SetLookupTable(lut);
329  lut->Delete();
330  vtkActor *actor2 = vtkActor::New();
331  actor2->SetMapper(map2);
332  actor2->DragableOff();
333  map2->Delete();
334  actor2->SetTexture(texture2);
335  texture2->Delete();
336  ren->AddActor(actor2);
337  actor2->Delete();
338  }
339  else
340  {
341  vtkActor * actor2 = vtkActor::New();
342  ren->AddActor(actor2);
343  }
344 
345  reader->Delete();
346  tcoords->Delete();
347  polys->Delete();
348 
349  vtkCamera * cam = ren->GetActiveCamera();
350  cam->SetFocalPoint(dim[0]/2,dim[1]/2,0);
351  cam->SetPosition(dim[0]/2,dim[1]/2,1);
352  cam->ParallelProjectionOn();
353  cam->SetParallelScale(dim[1]/2);
354  ren->ResetCameraClippingRange();
355  if (dim[1]<dim[0])
356  renWin->SetSize(800,int(800*(double(dim[1])/double(dim[0]))));
357  else
358  renWin->SetSize(int(800*(double(dim[0])/double(dim[1]))),800);
359 
360  renWin->Render();
361 
362  if (input_file != "")
363  {
364  std::ifstream in(input_file.c_str());
365  in >> coord;
366  in.close();
367  }
368 
369  renWin->SetWindowName(const_cast<char *>((std::string("PixelPos : ")+name).c_str()));
370  iren->Start();
371  renWin->Delete();
372  iren->Delete();
373 
374  // delete[] dim;
375  // delete[] dim2;
376  if (with_output)
377  {
378  if (verbose)
379  {
380  if (coord.size()==0)
381  {
382  std::cerr << std::endl << "no point extracted" << std::endl;
383  return 0;
384  }
385  if (coord.size()==1)
386  std::cerr << std::endl << "one point extracted" << std::endl;
387  else
388  std::cerr << std::endl << coord.size() << " points extracted" << std::endl;
389  std::cerr << std::endl;
390  }
391  std::cout << coord;
392  }
393 
394  return 0;
395 }
a_mat_sq x2(3)
a_subpixel_interactor
static a_subpixel_interactor * New()
void setpos(pixelpos_points *pos)
void setscale(vtkImageShiftScale *scale, double scale0)
void SetImage(vtkImageReader2 *image)
void set(vtkPoints *points, vtkImageClip *clip, int maxu, int maxv)
int xm
Definition: pixelpos.cxx:73
int * window(int xm, int ym, int xM, int yM, int *dim)
Definition: pixelpos.cxx:136
int ym
Definition: pixelpos.cxx:74
int error(int val)
Definition: pixelpos.cxx:64
CSimpleOpt::SOption g_rgOptions[]
Definition: pixelpos.cxx:46
int main(int argc, char **argv)
Definition: pixelpos.cxx:180
bool small_window
Definition: pixelpos.cxx:71
int xM
Definition: pixelpos.cxx:75
int yM
Definition: pixelpos.cxx:76
std::string input_file("")
int cmp_nocase(const std::string &s, const std::string &s2)
Definition: pixelpos.cxx:166
std::string name
Definition: pixelpos.cxx:77
int error_tests(int argc, char **argv)
Definition: pixelpos.cxx:81
bool verbose
Definition: pixelpos.cxx:72
@ OPT_YM
Definition: pixelpos.cxx:44
@ OPT_QUIET
Definition: pixelpos.cxx:44
@ OPT_XM
Definition: pixelpos.cxx:44
@ OPT_OUT
Definition: pixelpos.cxx:44
@ OPT_HELP
Definition: pixelpos.cxx:44
@ OPT_Xm
Definition: pixelpos.cxx:44
@ OPT_IN
Definition: pixelpos.cxx:44
@ OPT_Ym
Definition: pixelpos.cxx:44
bool with_output
Definition: pixelpos.cxx:70
std::istringstream in
Definition: ply2tri.cxx:32
vtkRenderer * ren
Definition: view_li.cxx:81