1 // This is oxl/mvl/LineSegSet.cxx
2 //:
3 //  \file
4 
5 #include <iostream>
6 #include <fstream>
7 #include <vector>
8 #include "LineSegSet.h"
9 
10 #ifdef _MSC_VER
11 #  include "vcl_msvc_warnings.h"
12 #endif
13 
14 #include <mvl/ImageMetric.h>
15 #include <mvl/HomgPoint2D.h>
16 
17 // Default ctor
LineSegSet()18 LineSegSet::LineSegSet():
19   hlines_(0)
20 {
21   conditioner_ = nullptr;
22 }
23 
24 // Copy ctor
LineSegSet(const LineSegSet & that)25 LineSegSet::LineSegSet(const LineSegSet& that):
26   hlines_(0)
27 {
28   operator=(that);
29 }
30 
31 // Assignment
32 LineSegSet& LineSegSet::operator=(const LineSegSet& that) = default;
33 
34 // Destructor
35 LineSegSet::~LineSegSet() = default;
36 
37 //: Construct from ascii file
LineSegSet(const char * filename,const HomgMetric & c)38 LineSegSet::LineSegSet(const char* filename, const HomgMetric& c)
39 {
40   std::ifstream f(filename);
41   load_ascii(f, c);
42 }
43 
44 //: Load lines from ASCII file
load_ascii(std::istream & f,HomgMetric const & c)45 bool LineSegSet::load_ascii(std::istream& f, HomgMetric const& c)
46 {
47   vnl_matrix<double> L;
48   f >> L;
49 
50   int cols = L.columns();
51   if (cols != 6 && cols != 4) {
52     std::cerr << "Load failed -- there are " << L.columns() << " data per row\n";
53     return false;
54   }
55 
56   conditioner_ = c;
57   hlines_.resize(0);
58   for (unsigned i = 0; i < L.rows(); ++i) {
59     double x1 = L(i,0);
60     double y1 = L(i,1);
61     double x2 = L(i,2);
62     double y2 = L(i,3);
63 #if 0
64     double theta;
65     double avemag;
66     if (cols == 6) {
67       theta = L(i,4);
68       avemag = L(i,5);
69     } else {
70       theta = 0;
71       avemag = 0;
72     }
73 #endif
74     HomgPoint2D p1(x1, y1);
75     HomgPoint2D p2(x2, y2);
76     HomgLineSeg2D line(p1, p2);
77     hlines_.push_back(c.image_to_homg_line(line));
78   }
79 
80   std::cerr << "Loaded " << size() << " line segments\n";
81   return true;
82 }
83 
FindNearestLineIndex(double,double)84 int LineSegSet::FindNearestLineIndex(double /*x*/, double /*y*/)
85 {
86   std::cerr <<"LineSegSet::FindNearestLineIndex not yet implemented\n";
87   return -1;
88 #if 0 // commented out
89   double mindist=-1.0f;
90   int mini=-1;
91   for (unsigned int i=0; i<size(); ++i)
92   {
93     HomgLineSeg2D& dl = get_homg(i);
94     double t = ( dl.get_point1().x() - x ) * ( dl.get_point2() - x )
95              + ( dl.get_point1().y() - y ) * ( dl.get_point2() - y );
96     // i.e.: t = dot_product ( startpt - pt , endpt - pt ) ;
97 
98     double dist;
99     if (t<0)     // P lies inbetween the two end points
100       dist = vgl_distance(dl.get_line(),vgl_point_2d<double>(x,y)); // distance to the support line
101     else
102       dist = std::min(// closest distance with endpoints
103                      vgl_distance(dl.get_point1(),vgl_point_2d<double>(x,y)),
104                      vgl_distance(dl.get_point2(),vgl_point_2d<double>(x,y)));
105     if (mini<0 || dist<mindist){ mindist = dist; mini = i; }
106   }
107   return mini;
108 #endif
109 }
110 
111 //: Save lines to ASCII file
save_ascii(std::ostream & f) const112 bool LineSegSet::save_ascii(std::ostream& f) const
113 {
114   for (const auto & l : hlines_) {
115     vnl_double_2 p1 = conditioner_.homg_to_image(l.get_point1());
116     vnl_double_2 p2 = conditioner_.homg_to_image(l.get_point2());
117 
118     f << p1[0] << " " << p1[1] << "\t"
119       << p2[0] << " " << p2[1] << std::endl;
120   }
121   std::cerr << "LineSegSet: Saved " << hlines_.size() << " line segments\n";
122   return true;
123 }
124 
125 //: Return line selected by mouse click at (x,y) in image coordinates.
pick_line_index(double x,double y)126 int LineSegSet::pick_line_index(double x, double y)
127 {
128   HomgPoint2D p(x, y);
129   HomgMetric metric(conditioner_);
130 
131   double dmin = 1e20;
132   int imin = -1;
133   int nlines = hlines_.size();
134   for (int i = 0; i < nlines; ++i) {
135     const HomgLineSeg2D& l = hlines_[i];
136     HomgLineSeg2D l_decond = metric.homg_line_to_image(l);
137 
138     double d = l_decond.picking_distance(p);
139 
140     if (d < dmin) {
141       dmin = d;
142       imin = i;
143     }
144   }
145 
146   return imin;
147 }
148 
149 //: Return line selected by mouse click at (x,y) in image coordinates.
pick_line(double x,double y)150 HomgLineSeg2D* LineSegSet::pick_line(double x, double y)
151 {
152   int i = pick_line_index(x,y);
153   if (i >= 0)
154     return &hlines_[i];
155   else
156     return nullptr;
157 }
158