Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpMbScanLine.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Make the complete tracking of an object by using its CAD model
33  *
34  * Authors:
35  * Aurelien Yol
36  *
37 *****************************************************************************/
38 
39 #include <visp3/core/vpConfig.h>
40 
41 #if defined _MSC_VER && _MSC_VER >= 1200
42 #define NOMINMAX
43 #endif
44 
45 #include <algorithm>
46 #include <cmath>
47 #include <cstddef>
48 #include <iostream>
49 #include <utility>
50 
51 #include <visp3/core/vpMeterPixelConversion.h>
52 #include <visp3/mbt/vpMbScanLine.h>
53 
54 #if defined(DEBUG_DISP)
55 #include <visp3/gui/vpDisplayGDI.h>
56 #include <visp3/gui/vpDisplayX.h>
57 #endif
58 
59 #ifndef DOXYGEN_SHOULD_SKIP_THIS
60 BEGIN_VISP_NAMESPACE
61 vpMbScanLine::vpMbScanLine()
62  : w(0), h(0), K(), maskBorder(0), mask(), primitive_ids(), visibility_samples(), depthTreshold(1e-06)
63 #if defined(DEBUG_DISP)
64  ,
65  dispMaskDebug(nullptr), dispLineDebug(nullptr), linedebugImg()
66 #endif
67 {
68 #if defined(VISP_HAVE_X11) && defined(DEBUG_DISP)
69  dispLineDebug = new vpDisplayX();
70  dispMaskDebug = new vpDisplayX();
71 #elif defined(VISP_HAVE_GDI) && defined(DEBUG_DISP)
72  dispLineDebug = new vpDisplayGDI();
73  dispMaskDebug = new vpDisplayGDI();
74 #endif
75 }
76 
77 vpMbScanLine::~vpMbScanLine()
78 {
79 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)) && defined(DEBUG_DISP)
80  if (dispLineDebug != nullptr)
81  delete dispLineDebug;
82  if (dispMaskDebug != nullptr)
83  delete dispMaskDebug;
84 #endif
85 }
96 void vpMbScanLine::drawLineY(const vpColVector &a, const vpColVector &b, const vpMbScanLineEdge &edge, const int ID,
97  std::vector<std::vector<vpMbScanLineSegment> > &scanlines)
98 {
99  double x0 = a[0] / a[2];
100  double y0 = a[1] / a[2];
101  double z0 = a[2];
102  double x1 = b[0] / b[2];
103  double y1 = b[1] / b[2];
104  double z1 = b[2];
105  if (y0 > y1) {
106  std::swap(x0, x1);
107  std::swap(y0, y1);
108  std::swap(z0, z1);
109  }
110 
111  // if (y0 >= h - 1 || y1 < 0 || y1 == y0)
112  if (y0 >= h - 1 || y1 < 0 || std::fabs(y1 - y0) <= std::numeric_limits<double>::epsilon())
113  return;
114 
115  const unsigned int _y0 = std::max<unsigned int>((unsigned int)0, (unsigned int)(std::ceil(y0)));
116  const double _y1 = std::min<double>((double)h, (double)y1);
117 
118  const bool b_sample_Y = (std::fabs(y0 - y1) > std::fabs(x0 - x1));
119 
120  for (unsigned int y = _y0; y < _y1; ++y) {
121  double x = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
122  const double alpha = getAlpha(y, y0 * z0, z0, y1 * z1, z1);
123  vpMbScanLineSegment s;
124  s.p = x;
125  s.type = POINT;
126  s.Z2 = s.Z1 = mix(z0, z1, alpha);
127  s.P2 = s.P1 = s.p * s.Z1;
128  s.ID = ID;
129  s.edge = edge;
130  s.b_sample_Y = b_sample_Y;
131  scanlines[y].push_back(s);
132  }
133 }
134 
145 void vpMbScanLine::drawLineX(const vpColVector &a, const vpColVector &b, const vpMbScanLineEdge &edge, const int ID,
146  std::vector<std::vector<vpMbScanLineSegment> > &scanlines)
147 {
148  double x0 = a[0] / a[2];
149  double y0 = a[1] / a[2];
150  double z0 = a[2];
151  double x1 = b[0] / b[2];
152  double y1 = b[1] / b[2];
153  double z1 = b[2];
154  if (x0 > x1) {
155  std::swap(x0, x1);
156  std::swap(y0, y1);
157  std::swap(z0, z1);
158  }
159 
160  // if (x0 >= w - 1 || x1 < 0 || x1 == x0)
161  if (x0 >= w - 1 || x1 < 0 || std::fabs(x1 - x0) <= std::numeric_limits<double>::epsilon())
162  return;
163 
164  const unsigned int _x0 = std::max<unsigned int>((unsigned int)0, (unsigned int)(std::ceil(x0)));
165  const double _x1 = std::min<double>((double)w, (double)x1);
166 
167  const bool b_sample_Y = (std::fabs(y0 - y1) > std::fabs(x0 - x1));
168 
169  for (unsigned int x = _x0; x < _x1; ++x) {
170  double y = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
171  const double alpha = getAlpha(x, x0 * z0, z0, x1 * z1, z1);
172  vpMbScanLineSegment s;
173  s.p = y;
174  s.type = POINT;
175  s.Z2 = s.Z1 = mix(z0, z1, alpha);
176  s.P2 = s.P1 = s.p * s.Z1;
177  s.ID = ID;
178  s.edge = edge;
179  s.b_sample_Y = b_sample_Y;
180  scanlines[x].push_back(s);
181  }
182 }
183 
191 void vpMbScanLine::drawPolygonY(const std::vector<std::pair<vpPoint, unsigned int> > &polygon, const int ID,
192  std::vector<std::vector<vpMbScanLineSegment> > &scanlines)
193 {
194  if (polygon.size() < 2)
195  return;
196 
197  if (polygon.size() == 2) {
198  vpColVector p1, p2;
199  createVectorFromPoint(polygon.front().first, p1, K);
200  createVectorFromPoint(polygon.back().first, p2, K);
201 
202  drawLineY(p1, p2, makeMbScanLineEdge(polygon.front().first, polygon.back().first), ID, scanlines);
203  return;
204  }
205 
206  std::vector<std::vector<vpMbScanLineSegment> > local_scanlines;
207  local_scanlines.resize(h);
208 
209  for (size_t i = 0; i < polygon.size(); ++i) {
210  vpColVector p1, p2;
211  createVectorFromPoint(polygon[i].first, p1, K);
212  createVectorFromPoint(polygon[(i + 1) % polygon.size()].first, p2, K);
213 
214  drawLineY(p1, p2, makeMbScanLineEdge(polygon[i].first, polygon[(i + 1) % polygon.size()].first), ID,
215  local_scanlines);
216  }
217 
218  createScanLinesFromLocals(scanlines, local_scanlines, h);
219 }
220 
228 void vpMbScanLine::drawPolygonX(const std::vector<std::pair<vpPoint, unsigned int> > &polygon, const int ID,
229  std::vector<std::vector<vpMbScanLineSegment> > &scanlines)
230 {
231  if (polygon.size() < 2)
232  return;
233 
234  if (polygon.size() == 2) {
235  vpColVector p1, p2;
236  createVectorFromPoint(polygon.front().first, p1, K);
237  createVectorFromPoint(polygon.back().first, p2, K);
238 
239  drawLineX(p1, p2, makeMbScanLineEdge(polygon.front().first, polygon.back().first), ID, scanlines);
240  return;
241  }
242 
243  std::vector<std::vector<vpMbScanLineSegment> > local_scanlines;
244  local_scanlines.resize(w);
245 
246  for (size_t i = 0; i < polygon.size(); ++i) {
247  vpColVector p1, p2;
248  createVectorFromPoint(polygon[i].first, p1, K);
249  createVectorFromPoint(polygon[(i + 1) % polygon.size()].first, p2, K);
250 
251  drawLineX(p1, p2, makeMbScanLineEdge(polygon[i].first, polygon[(i + 1) % polygon.size()].first), ID,
252  local_scanlines);
253  }
254 
255  createScanLinesFromLocals(scanlines, local_scanlines, w);
256 }
257 
267 void vpMbScanLine::createScanLinesFromLocals(std::vector<std::vector<vpMbScanLineSegment> > &scanlines,
268  std::vector<std::vector<vpMbScanLineSegment> > &localScanlines,
269  const unsigned int &size)
270 {
271  for (unsigned int j = 0; j < size; ++j) {
272  std::vector<vpMbScanLineSegment> &scanline = localScanlines[j];
273  sort(scanline.begin(), scanline.end(),
274  vpMbScanLineSegmentComparator()); // Not sure its necessary
275 
276  bool b_start = true;
277  for (size_t i = 0; i < scanline.size(); ++i) {
278  vpMbScanLineSegment s = scanline[i];
279  if (b_start) {
280  s.type = START;
281  s.P1 = s.p * s.Z1;
282  b_start = false;
283  }
284  else {
285  vpMbScanLineSegment &prev = scanlines[j].back();
286  s.type = END;
287  s.P1 = prev.P1;
288  s.Z1 = prev.Z1;
289  s.P2 = s.p * s.Z2;
290  prev.P2 = s.P2;
291  prev.Z2 = s.Z2;
292  b_start = true;
293  }
294  scanlines[j].push_back(s);
295  }
296  }
297 }
298 
308 void vpMbScanLine::drawScene(const std::vector<std::vector<std::pair<vpPoint, unsigned int> > *> &polygons,
309  std::vector<int> listPolyIndices, const vpCameraParameters &cam, unsigned int width,
310  unsigned int height)
311 {
312  this->w = width;
313  this->h = height;
314  this->K = cam;
315 
316  visibility_samples.clear();
317 
318  std::vector<std::vector<vpMbScanLineSegment> > scanlinesY;
319  scanlinesY.resize(h);
320  std::vector<std::vector<vpMbScanLineSegment> > scanlinesX;
321  scanlinesX.resize(w);
322 
323  mask.resize(h, w, 0);
324 
325  vpImage<unsigned char> maskY(h, w, 0);
326  vpImage<unsigned char> maskX(h, w, 0);
327 
328  primitive_ids.resize(h, w, -1);
329 
330  for (unsigned int ID = 0; ID < polygons.size(); ++ID) {
331  drawPolygonY(*(polygons[ID]), listPolyIndices[ID], scanlinesY);
332  drawPolygonX(*(polygons[ID]), listPolyIndices[ID], scanlinesX);
333  }
334 
335  // Y
336  int last_ID = -1;
337  vpMbScanLineSegment last_visible;
338  for (unsigned int y = 0; y < scanlinesY.size(); ++y) {
339  std::vector<vpMbScanLineSegment> &scanline = scanlinesY[y];
340  sort(scanline.begin(), scanline.end(), vpMbScanLineSegmentComparator());
341 
342  std::vector<std::pair<double, vpMbScanLineSegment> > stack;
343  for (size_t i = 0; i < scanline.size(); ++i) {
344  const vpMbScanLineSegment &s = scanline[i];
345 
346  switch (s.type) {
347  case START:
348  stack.push_back(std::make_pair(s.Z1, s));
349  break;
350  case END:
351  for (size_t j = 0; j < stack.size(); ++j)
352  if (stack[j].second.ID == s.ID) {
353  if (j != stack.size() - 1)
354  stack[j] = stack.back();
355  stack.pop_back();
356  break;
357  }
358  break;
359  case POINT:
360  break;
361  }
362 
363  for (size_t j = 0; j < stack.size(); ++j) {
364  const vpMbScanLineSegment &s0 = stack[j].second;
365  stack[j].first = mix(s0.Z1, s0.Z2, getAlpha(s.type == POINT ? s.p : (s.p + 0.5), s0.P1, s0.Z1, s0.P2, s0.Z2));
366  }
367  sort(stack.begin(), stack.end(), vpMbScanLineSegmentComparator());
368 
369  int new_ID = stack.empty() ? -1 : stack.front().second.ID;
370 
371  if (new_ID != last_ID || s.type == POINT) {
372  if (s.b_sample_Y)
373  switch (s.type) {
374  case POINT:
375  if (new_ID == -1 || s.Z1 - depthTreshold <= stack.front().first)
376  visibility_samples[s.edge].insert((int)y);
377  break;
378  case START:
379  if (new_ID == s.ID)
380  visibility_samples[s.edge].insert((int)y);
381  break;
382  case END:
383  if (last_ID == s.ID)
384  visibility_samples[s.edge].insert((int)y);
385  break;
386  }
387 
388  // This part will only be used for MbKltTracking
389  if (last_ID != -1) {
390  const unsigned int x0 = std::max<unsigned int>((unsigned int)0, (unsigned int)(std::ceil(last_visible.p)));
391  double x1 = std::min<double>((double)w, (double)s.p);
392  for (unsigned int x = x0 + maskBorder; x < x1 - maskBorder; ++x) {
393  primitive_ids[(unsigned int)y][(unsigned int)x] = last_visible.ID;
394 
395  if (maskBorder != 0)
396  maskY[(unsigned int)y][(unsigned int)x] = 255;
397  else
398  mask[(unsigned int)y][(unsigned int)x] = 255;
399  }
400  }
401 
402  last_ID = new_ID;
403  if (!stack.empty()) {
404  last_visible = stack.front().second;
405  last_visible.p = s.p;
406  }
407  }
408  }
409  }
410 
411  // X
412  last_ID = -1;
413  for (unsigned int x = 0; x < scanlinesX.size(); ++x) {
414  std::vector<vpMbScanLineSegment> &scanline = scanlinesX[x];
415  sort(scanline.begin(), scanline.end(), vpMbScanLineSegmentComparator());
416 
417  std::vector<std::pair<double, vpMbScanLineSegment> > stack;
418  for (size_t i = 0; i < scanline.size(); ++i) {
419  const vpMbScanLineSegment &s = scanline[i];
420 
421  switch (s.type) {
422  case START:
423  stack.push_back(std::make_pair(s.Z1, s));
424  break;
425  case END:
426  for (size_t j = 0; j < stack.size(); ++j)
427  if (stack[j].second.ID == s.ID) {
428  if (j != stack.size() - 1)
429  stack[j] = stack.back();
430  stack.pop_back();
431  break;
432  }
433  break;
434  case POINT:
435  break;
436  }
437 
438  for (size_t j = 0; j < stack.size(); ++j) {
439  const vpMbScanLineSegment &s0 = stack[j].second;
440  stack[j].first = mix(s0.Z1, s0.Z2, getAlpha(s.type == POINT ? s.p : (s.p + 0.5), s0.P1, s0.Z1, s0.P2, s0.Z2));
441  }
442  sort(stack.begin(), stack.end(), vpMbScanLineSegmentComparator());
443 
444  int new_ID = stack.empty() ? -1 : stack.front().second.ID;
445 
446  if (new_ID != last_ID || s.type == POINT) {
447  if (!s.b_sample_Y)
448  switch (s.type) {
449  case POINT:
450  if (new_ID == -1 || s.Z1 - depthTreshold <= stack.front().first)
451  visibility_samples[s.edge].insert((int)x);
452  break;
453  case START:
454  if (new_ID == s.ID)
455  visibility_samples[s.edge].insert((int)x);
456  break;
457  case END:
458  if (last_ID == s.ID)
459  visibility_samples[s.edge].insert((int)x);
460  break;
461  }
462 
463  // This part will only be used for MbKltTracking
464  if (maskBorder != 0 && last_ID != -1) {
465  const unsigned int y0 = std::max<unsigned int>((unsigned int)0, (unsigned int)(std::ceil(last_visible.p)));
466  double y1 = std::min<double>((double)h, (double)s.p);
467  for (unsigned int y = y0 + maskBorder; y < y1 - maskBorder; ++y) {
468  // primitive_ids[(unsigned int)y][(unsigned int)x] =
469  // last_visible.ID;
470  maskX[(unsigned int)y][(unsigned int)x] = 255;
471  }
472  }
473 
474  last_ID = new_ID;
475  if (!stack.empty()) {
476  last_visible = stack.front().second;
477  last_visible.p = s.p;
478  }
479  }
480  }
481  }
482 
483  if (maskBorder != 0)
484  for (unsigned int i = 0; i < h; i++)
485  for (unsigned int j = 0; j < w; j++)
486  if (maskX[i][j] == 255 && maskY[i][j] == 255)
487  mask[i][j] = 255;
488 
489 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)) && defined(DEBUG_DISP)
490  if (!dispMaskDebug->isInitialised()) {
491  dispMaskDebug->init(mask, 800, 600);
492  }
493 
494  vpDisplay::display(mask);
495 
496  for (unsigned int ID = 0; ID < polygons.size(); ++ID) {
497  for (unsigned int i = 0; i < polygons[ID]->size(); i++) {
498  vpPoint p1 = (*(polygons[ID]))[i].first;
499  vpPoint p2 = (*(polygons[ID]))[(i + 1) % polygons[ID]->size()].first;
500  double i1 = 0, j1 = 0, i2 = 0, j2 = 0;
501  p1.project();
502  p2.project();
503  vpMeterPixelConversion::convertPoint(K, p1.get_x(), p1.get_y(), j1, i1);
504  vpMeterPixelConversion::convertPoint(K, p2.get_x(), p2.get_y(), j2, i2);
505 
506  vpDisplay::displayLine(mask, i1, j1, i2, j2, vpColor::red, 3);
507  }
508  }
509 
510  vpDisplay::flush(mask);
511 
512  if (!dispLineDebug->isInitialised()) {
513  linedebugImg.resize(h, w, 0);
514  dispLineDebug->init(linedebugImg, 800, 100);
515  }
516  vpDisplay::display(linedebugImg);
517 #endif
518 }
519 
530 void vpMbScanLine::queryLineVisibility(const vpPoint &a, const vpPoint &b,
531  std::vector<std::pair<vpPoint, vpPoint> > &lines, const bool &displayResults)
532 {
533  vpColVector _a, _b;
534  createVectorFromPoint(a, _a, K);
535  createVectorFromPoint(b, _b, K);
536 
537  double x0 = _a[0] / _a[2];
538  double y0 = _a[1] / _a[2];
539  double z0 = _a[2];
540  double x1 = _b[0] / _b[2];
541  double y1 = _b[1] / _b[2];
542  double z1 = _b[2];
543 
544  vpMbScanLineEdge edge = makeMbScanLineEdge(a, b);
545  lines.clear();
546 
547  if (displayResults) {
548 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)) && defined(DEBUG_DISP)
549  double i1(0.0), j1(0.0), i2(0.0), j2(0.0);
550  vpPoint a_(a), b_(b);
551  a_.project();
552  b_.project();
553  vpMeterPixelConversion::convertPoint(K, a_.get_x(), a_.get_y(), j1, i1);
554  vpMeterPixelConversion::convertPoint(K, b_.get_x(), b_.get_y(), j2, i2);
555 
556  vpDisplay::displayLine(linedebugImg, i1, j1, i2, j2, vpColor::yellow, 3);
557 #endif
558  }
559 
560  if (!visibility_samples.count(edge))
561  return;
562 
563  // Initialized as the biggest difference between the two points is on the
564  // X-axis
565  double *v0(&x0), *w0(&z0);
566  double *v1(&x1), *w1(&z1);
567  unsigned int size(w);
568 
569  if (std::fabs(y0 - y1) > std::fabs(x0 - x1)) // Test if the biggest difference is on the Y-axis
570  {
571  v0 = &y0;
572  v1 = &y1;
573  size = h;
574  }
575 
576  // Cannot call swap(a,b) since a and b are const
577  // The fix consists in 2 new points that contain the right points
578  vpPoint a_;
579  vpPoint b_;
580 
581  if (*v0 > *v1) {
582  std::swap(v0, v1);
583  std::swap(w0, w1);
584  // std::swap(a, b);
585  // Cannot call swap(a,b) since a and b are const
586  // Instead of swap we set the right address of the corresponding pointers
587  a_ = b;
588  b_ = a;
589  }
590  else {
591  a_ = a;
592  b_ = b;
593  }
594 
595  // if (*v0 >= size - 1 || *v1 < 0 || *v1 == *v0)
596  if (*v0 >= size - 1 || *v1 < 0 || std::fabs(*v1 - *v0) <= std::numeric_limits<double>::epsilon())
597  return;
598 
599  const int _v0 = std::max<int>(0, int(std::ceil(*v0)));
600  const int _v1 = std::min<int>((int)(size - 1), (int)(std::ceil(*v1) - 1));
601 
602  const std::set<int> &visible_samples = visibility_samples[edge];
603  int last = _v0;
604  vpPoint line_start;
605  vpPoint line_end;
606  bool b_line_started = false;
607  for (std::set<int>::const_iterator it = visible_samples.begin(); it != visible_samples.end(); ++it) {
608  const int v = *it;
609  const double alpha = getAlpha(v, (*v0) * (*w0), (*w0), (*v1) * (*w1), (*w1));
610  // const vpPoint p = mix(a, b, alpha);
611  const vpPoint p = mix(a_, b_, alpha);
612  if (last + 1 != v) {
613  if (b_line_started)
614  lines.push_back(std::make_pair(line_start, line_end));
615  b_line_started = false;
616  }
617  if (v == _v0) {
618  // line_start = a;
619  line_start = a_;
620  line_end = p;
621  b_line_started = true;
622  }
623  else if (v == _v1) {
624  // line_end = b;
625  line_end = b_;
626  if (!b_line_started)
627  line_start = p;
628  b_line_started = true;
629  }
630  else {
631  line_end = p;
632  if (!b_line_started)
633  line_start = p;
634  b_line_started = true;
635  }
636  last = v;
637  }
638  if (b_line_started)
639  lines.push_back(std::make_pair(line_start, line_end));
640 
641  if (displayResults) {
642 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)) && defined(DEBUG_DISP)
643  double i1(0.0), j1(0.0), i2(0.0), j2(0.0);
644  for (unsigned int i = 0; i < lines.size(); i++) {
645  lines[i].first.project();
646  lines[i].second.project();
647  vpMeterPixelConversion::convertPoint(K, lines[i].first.get_x(), lines[i].first.get_y(), j1, i1);
648  vpMeterPixelConversion::convertPoint(K, lines[i].second.get_x(), lines[i].second.get_y(), j2, i2);
649 
650  vpDisplay::displayLine(linedebugImg, i1, j1, i2, j2, vpColor::red, 3);
651  }
652  vpDisplay::flush(linedebugImg);
653 #endif
654  }
655 }
656 
665 vpMbScanLine::vpMbScanLineEdge vpMbScanLine::makeMbScanLineEdge(const vpPoint &a, const vpPoint &b)
666 {
667  vpColVector _a(3);
668  vpColVector _b(3);
669 
670  _a[0] = std::ceil((a.get_X() * 1e8) * 1e-6);
671  _a[1] = std::ceil((a.get_Y() * 1e8) * 1e-6);
672  _a[2] = std::ceil((a.get_Z() * 1e8) * 1e-6);
673 
674  _b[0] = std::ceil((b.get_X() * 1e8) * 1e-6);
675  _b[1] = std::ceil((b.get_Y() * 1e8) * 1e-6);
676  _b[2] = std::ceil((b.get_Z() * 1e8) * 1e-6);
677 
678  bool b_comp = false;
679  for (unsigned int i = 0; i < 3; ++i)
680  if (_a[i] < _b[i]) {
681  b_comp = true;
682  break;
683  }
684  else if (_a[i] > _b[i])
685  break;
686 
687  if (b_comp)
688  return std::make_pair(_a, _b);
689 
690  return std::make_pair(_b, _a);
691 }
692 
700 void vpMbScanLine::createVectorFromPoint(const vpPoint &p, vpColVector &v, const vpCameraParameters &K)
701 {
702  v = vpColVector(3);
703 
704  v[0] = p.get_X() * K.get_px() + K.get_u0() * p.get_Z();
705  v[1] = p.get_Y() * K.get_py() + K.get_v0() * p.get_Z();
706  v[2] = p.get_Z();
707 }
708 
718 double vpMbScanLine::getAlpha(double x, double X0, double Z0, double X1, double Z1)
719 {
720  const double N = X0 - x * Z0;
721  const double D = x * (Z1 - Z0) - (X1 - X0);
722  double alpha = N / D;
723  if (vpMath::isNaN(alpha) || vpMath::isInf(alpha))
724  return 0.0;
725 
726  alpha = std::min<double>(1.0, alpha);
727  alpha = std::max<double>(0.0, alpha);
728  return alpha;
729 }
730 
740 double vpMbScanLine::mix(double a, double b, double alpha) { return a + (b - a) * alpha; }
741 
751 vpPoint vpMbScanLine::mix(const vpPoint &a, const vpPoint &b, double alpha)
752 {
753  vpPoint res;
754  res.set_X(a.get_X() + (b.get_X() - a.get_X()) * alpha);
755  res.set_Y(a.get_Y() + (b.get_Y() - a.get_Y()) * alpha);
756  res.set_Z(a.get_Z() + (b.get_Z() - a.get_Z()) * alpha);
757 
758  return res;
759 }
760 
769 double vpMbScanLine::norm(const vpPoint &a, const vpPoint &b)
770 {
771  return sqrt(vpMath::sqr(a.get_X() - b.get_X()) + vpMath::sqr(a.get_Y() - b.get_Y()) +
772  vpMath::sqr(a.get_Z() - b.get_Z()));
773 }
774 END_VISP_NAMESPACE
775 #endif
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static const vpColor red
Definition: vpColor.h:217
static const vpColor yellow
Definition: vpColor.h:225
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void flush(const vpImage< unsigned char > &I)
static bool isNaN(double value)
Definition: vpMath.cpp:92
static double sqr(double x)
Definition: vpMath.h:203
static bool isInf(double value)
Definition: vpMath.cpp:136
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:426
double get_Y() const
Get the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:408
void set_X(double cX)
Set the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:450
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:424
void set_Y(double cY)
Set the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:452
double get_Z() const
Get the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:410
void set_Z(double cZ)
Set the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:454
double get_X() const
Get the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:406