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