1 #include <iostream>
2 #include <cmath>
3 #include "bwm_observer_img.h"
4 //:
5 // \file
6 
7 #include <bwm/algo/bwm_algo.h>
8 #include <bwm/algo/bwm_utils.h>
9 #include <bwm/algo/bwm_image_processor.h>
10 #include <bwm/bwm_tableau_mgr.h>
11 
12 #include <bgui/bgui_image_tableau.h>
13 #include <bgui/bgui_image_utils.h>
14 #include "vgui/vgui_section_render.h"
15 #include "vgui/vgui_projection_inspector.h"
16 
17 #include <bsol/bsol_algs.h>
18 #include <vsol/vsol_point_2d.h>
19 #include <vsol/vsol_box_2d.h>
20 #include <vsol/vsol_polygon_2d.h>
21 #include <vsol/vsol_polyline_2d.h>
22 #include <vsol/vsol_digital_curve_2d.h>
23 #include <vsol/vsol_line_2d.h>
24 
25 #include "vgl/vgl_box_2d.h"
26 #include "vgl/vgl_polygon.h"
27 
28 #include "vil/vil_image_view.h"
29 #include <vil/file_formats/vil_nitf2_image.h>
30 
31 #ifdef _MSC_VER
32 #  include "vcl_msvc_warnings.h"
33 #endif
34 
bwm_observer_img(bgui_image_tableau_sptr const & img,std::string name,std::string image_path,bool display_image_path)35 bwm_observer_img::bwm_observer_img(bgui_image_tableau_sptr const& img, std::string name, std::string image_path, bool display_image_path)
36 : bgui_vsol2D_tableau(img), lock_vgui_status_(false), vgui_status_on_(false), draw_mode_(MODE_2D_POLY), img_tab_(img), viewer_(nullptr),
37   change_type_("change"), show_image_path_(false), start_x_(0), start_y_(0), moving_p_(nullptr), moving_v_(nullptr), moving_vertex_(false),
38   moving_polygon_(false), in_jog_mode_(false), row_(0), col_(0)
39 {
40 // LOAD IMAGE
41 
42   vgui_range_map_params_sptr params;
43   vil_image_resource_sptr img_res = bwm_utils::load_image(image_path, params);
44   if (!img_res) {
45     //show_error("Image [" + image_path + "] NOT found");
46     return;
47   }
48   img->set_image_resource(img_res, params);
49 
50   img->show_image_path(display_image_path);
51   img->set_file_name(image_path);
52   set_tab_name(name);
53 }
54 
handle(const vgui_event & e)55 bool bwm_observer_img::handle(const vgui_event &e)
56 {
57   vgui_projection_inspector pi;
58 
59   if (e.type == vgui_BUTTON_DOWN &&
60       e.button == vgui_MIDDLE &&
61       e.modifier == vgui_SHIFT)
62   {
63     bgui_vsol_soview2D* p=nullptr;
64     bwm_soview2D_vertex* v = nullptr;
65 
66     // get the selected polyline or polygon
67     if ((p = (bgui_vsol_soview2D*) get_selected_object(POLYGON_TYPE)) ||
68         (p = (bgui_vsol_soview2D*) get_selected_object(POLYLINE_TYPE))) {
69       // take the position of the first point
70       pi.window_to_image_coordinates(e.wx, e.wy, start_x_, start_y_);
71       moving_p_ = p;
72       moving_polygon_ = true;
73       moving_vertex_ = false;
74       return true;
75     }
76     else if ((v = (bwm_soview2D_vertex*) get_selected_object(VERTEX_TYPE))) {
77       pi.window_to_image_coordinates(e.wx, e.wy, start_x_, start_y_);
78       moving_v_ = v;
79       moving_p_ = v->obj();
80       moving_vertex_ = true;
81       moving_polygon_ = false;
82       return true;
83     }
84   }
85   else if (e.type == vgui_MOTION && e.button == vgui_MIDDLE &&
86            e.modifier == vgui_SHIFT && moving_polygon_)
87   {
88     float x, y;
89     pi.window_to_image_coordinates(e.wx, e.wy, x, y);
90     float x_diff = x-start_x_;
91     float y_diff = y-start_y_;
92     moving_p_->translate(x_diff, y_diff);
93 
94     // move all the vertices of the polyline or polygon
95     std::vector<bwm_soview2D_vertex*> vertices = vert_list[moving_p_->get_id()];
96     for (unsigned i=0; i<vertices.size(); i++) {
97       bwm_soview2D_vertex* v = vertices[i];
98       v->translate(x_diff, y_diff);
99     }
100     start_x_ = x;
101     start_y_ = y;
102 
103     post_redraw();
104     return true;
105   }
106   else if (e.type == vgui_MOTION && e.button == vgui_MIDDLE &&
107            e.modifier == vgui_SHIFT && moving_vertex_)
108   {
109     float x, y;
110     pi.window_to_image_coordinates(e.wx, e.wy, x, y);
111     float x_diff = x-start_x_;
112     float y_diff = y-start_y_;
113     // find the polyline including this vertex
114     unsigned i = moving_v_->vertex_indx();
115     moving_v_->translate(x_diff, y_diff);
116     if (moving_p_->type_name().compare(POLYGON_TYPE) == 0) {
117       bgui_vsol_soview2D_polygon* polygon = (bgui_vsol_soview2D_polygon*) moving_p_;
118       polygon->sptr()->vertex(i)->set_x( polygon->sptr()->vertex(i)->x() + x_diff );
119       polygon->sptr()->vertex(i)->set_y( polygon->sptr()->vertex(i)->y() + y_diff );
120     }
121     else if (moving_p_->type_name().compare(POLYLINE_TYPE) == 0) {
122       bgui_vsol_soview2D_polyline* polyline = (bgui_vsol_soview2D_polyline*) moving_p_;
123       polyline->sptr()->vertex(i)->set_x( polyline->sptr()->vertex(i)->x() + x_diff );
124       polyline->sptr()->vertex(i)->set_y( polyline->sptr()->vertex(i)->y() + y_diff );
125     }
126     else {
127       std::cerr << moving_p_->type_name() << " is NOT movable!!!!\n";
128     }
129 
130     start_x_ = x;
131     start_y_ = y;
132     post_redraw();
133     return true;
134   }
135   else if (e.type == vgui_BUTTON_UP && e.button == vgui_MIDDLE && e.modifier == vgui_SHIFT) {
136     this->deselect_all();
137     moving_vertex_ = false;
138     moving_polygon_ = false;
139     in_jog_mode_ = false;
140     return true;
141   }
142   return base::handle(e);
143 }
144 
145 //eliminate the segmentation soviews
~bwm_observer_img()146 bwm_observer_img::~bwm_observer_img()
147 {
148   std::map<unsigned, std::vector<bgui_vsol_soview2D* > >::iterator mit =
149     seg_views.begin();
150   for (; mit!=seg_views.end(); ++mit)
151   {
152     std::vector<bgui_vsol_soview2D* > soviews = (*mit).second;
153     for (unsigned i=0; i<soviews.size(); i++) {
154       this->remove(soviews[i]);
155     }
156   }
157   seg_views.clear();
158   this->clear_reg_segmentation();
159 }
160 
set_draw_mode(BWM_2D_DRAW_MODE mode)161 void bwm_observer_img::set_draw_mode(BWM_2D_DRAW_MODE mode)
162 {
163   // if mode changed from the last time
164   if (mode != draw_mode_) {
165     draw_mode_ = mode;
166     bool selectable = true;
167 
168     if (mode == MODE_2D_VERTEX) // vertex mode
169       selectable = false;
170 
171     // polygons are mapped to soview ID, make them unselectable
172     for (std::map<unsigned, bgui_vsol_soview2D*>::iterator it = obj_list.begin();
173          it != obj_list.end(); it++) {
174       //vgui_soview* p = vgui_soview::id_to_object(it->first);
175       it->second->set_selectable(selectable);
176     }
177     // vector of vertices are mapped soview ID for each polygon
178     for (std::map<unsigned, std::vector<bwm_soview2D_vertex* > >::iterator it=vert_list.begin();
179          it != vert_list.end(); it++) {
180       std::vector<bwm_soview2D_vertex* > v_list = it->second;
181       for (unsigned i=0; i<v_list.size(); i++)
182         v_list[i]->set_selectable(!selectable);
183     }
184   }
185 }
186 
create_box(vsol_box_2d_sptr box)187 unsigned bwm_observer_img::create_box(vsol_box_2d_sptr box)
188 {
189   vsol_polygon_2d_sptr pbox = bsol_algs::poly_from_box(box);
190   return create_polygon(pbox);
191 }
192 
create_polygon(vsol_polygon_2d_sptr poly2d)193 unsigned bwm_observer_img::create_polygon(vsol_polygon_2d_sptr poly2d)
194 {
195   float *x, *y;
196   bwm_algo::get_vertices_xy(poly2d, &x, &y);
197   unsigned nverts = poly2d->size();
198 
199   this->set_foreground(1,1,0);
200   bgui_vsol_soview2D_polygon* polygon = this->add_vsol_polygon_2d(poly2d);
201   obj_list[polygon->get_id()] = polygon;
202   if (draw_mode_ == 1)
203     polygon->set_selectable(false);
204 
205   std::vector<bwm_soview2D_vertex*> verts;
206   this->set_foreground(0,1,0);
207   for (unsigned i = 0; i<nverts; ++i) {
208     bwm_soview2D_vertex* vertex = new bwm_soview2D_vertex(x[i],y[i],0.5f, polygon, i);
209     if (draw_mode_ == 0)
210       vertex->set_selectable(false);
211     this->add(vertex);
212     verts.push_back(vertex);
213   }
214   vert_list[polygon->get_id()] = verts;
215   return polygon->get_id();
216 }
217 
create_polyline(vsol_polyline_2d_sptr poly2d)218 unsigned bwm_observer_img::create_polyline(vsol_polyline_2d_sptr poly2d)
219 {
220   float *x, *y;
221   bwm_algo::get_vertices_xy(poly2d, &x, &y);
222   unsigned nverts = poly2d->size();
223   bgui_vsol_soview2D_polyline* polyline = this->add_vsol_polyline_2d(poly2d);
224   obj_list[polyline->get_id()] = polyline;
225 
226   std::vector<bwm_soview2D_vertex*> verts;
227   this->set_foreground(0,1,0);
228   for (unsigned i = 0; i<nverts; ++i) {
229     bwm_soview2D_vertex* vertex = new bwm_soview2D_vertex(x[i],y[i],0.5f, polyline, i);
230     this->add(vertex);
231     verts.push_back(vertex);
232   }
233   vert_list[polyline->get_id()] = verts;
234   return polyline->get_id();
235 }
236 
create_point(vsol_point_2d_sptr p)237 unsigned bwm_observer_img::create_point(vsol_point_2d_sptr p)
238 {
239   bgui_vsol_soview2D_point* point = this->add_vsol_point_2d(p);
240   obj_list[point->get_id()] = point;
241   return point->get_id();
242 }
243 
244 //: save the polygon to paste later, always stores the last selected
copy()245 void bwm_observer_img::copy()
246 {
247   std::vector<vgui_soview*> select_list = this->get_selected_soviews();
248   if (select_list.size() > 1) {
249     std::cerr << "Please select only one object to copy\n";
250     return;
251   }
252   copy_obj_ = (vgui_soview2D*) select_list[0];
253 }
254 
paste(float x,float y)255 void bwm_observer_img::paste(float x, float y)
256 {
257   if (!copy_obj_) {
258     std::cerr << "No object is selected to paste, COPY first\n";
259     return;
260   }
261 
262   float cx, cy;
263   if (copy_obj_->type_name().compare(POLYGON_TYPE) == 0) {
264     bgui_vsol_soview2D_polygon* obj = (bgui_vsol_soview2D_polygon*) copy_obj_;
265     obj->get_centroid(&cx, &cy);
266     vsol_polygon_2d_sptr p = obj->sptr();
267 
268     // translate it
269     unsigned int n = p->size();
270     std::vector<vsol_point_2d_sptr> vertices;
271 
272     for (unsigned int i=0; i<n;i++)
273       vertices.push_back(new vsol_point_2d(p->vertex(i)->x() + (x-cx), p->vertex(i)->y() + (y-cy)));
274 
275     vsol_polygon_2d_sptr new_p = new vsol_polygon_2d(vertices);
276     create_polygon(new_p);
277     post_redraw();
278   }
279   else if (copy_obj_->type_name().compare(POLYLINE_TYPE) == 0) {
280     bgui_vsol_soview2D_polyline* obj = (bgui_vsol_soview2D_polyline*) copy_obj_;
281     obj->get_centroid(&cx, &cy);
282     vsol_polyline_2d_sptr l = obj->sptr();
283     // translate it
284     unsigned int n = l->size();
285     std::vector<vsol_point_2d_sptr> vertices;
286 
287     for (unsigned int i=0; i<n;i++)
288       vertices.push_back(new vsol_point_2d(l->vertex(i)->x() + (x-cx), l->vertex(i)->y() + (y-cy)));
289 
290     vsol_polyline_2d_sptr new_p = new vsol_polyline_2d(vertices);
291     create_polyline(new_p);
292     post_redraw();
293   }
294 
295   this->deselect_all();
296 }
297 
clear_objects()298 void bwm_observer_img::clear_objects()
299 {
300   std::map<unsigned, bgui_vsol_soview2D*>::iterator oit = obj_list.begin();
301   for (; oit!=obj_list.end(); ++oit)
302     this->remove((*oit).second);
303   obj_list.clear();
304   std::map<unsigned, std::vector<bwm_soview2D_vertex* > >::iterator vsit =
305     vert_list.begin();
306   for (; vsit != vert_list.end(); ++vsit){
307     std::vector<bwm_soview2D_vertex* >::iterator vit = (*vsit).second.begin();
308     for (; vit != (*vsit).second.end(); ++vit)
309       this->remove(*vit);
310   }
311   vert_list.clear();
312 }
get_selected_line(bgui_vsol_soview2D_line_seg * & line)313 bool bwm_observer_img::get_selected_line(bgui_vsol_soview2D_line_seg* &line)
314 {
315   bgui_vsol_soview2D_line_seg* lseg = (bgui_vsol_soview2D_line_seg*)get_selected_object(LINE_SEG_TYPE);
316   if (lseg) {
317     line = lseg;
318     return true;
319   }
320   return false;
321 }
print_selected_line()322 void bwm_observer_img::print_selected_line(){
323   bgui_vsol_soview2D_line_seg* line_seg;
324   if(!get_selected_line(line_seg))
325     std::cout << "No selected line segment" << std::endl;
326   else{
327     vsol_point_2d_sptr p0 = line_seg->sptr()->p0();
328     vsol_point_2d_sptr p1 = line_seg->sptr()->p1();
329     std::cout << "sel line seg: " << vgl_point_2d<double>(p0->x(), p0->y()) << " -> " << vgl_point_2d<double>(p1->x(), p1->y()) << std::endl;
330   }
331 }
332 
get_selected_box(bgui_vsol_soview2D_polygon * & box)333 bool bwm_observer_img::get_selected_box(bgui_vsol_soview2D_polygon* &box)
334 {
335   bgui_vsol_soview2D_polygon* p = (bgui_vsol_soview2D_polygon*)get_selected_object(POLYGON_TYPE);
336   if (p) {
337 #if 0
338     if (p->sptr()->size() != 4) {
339       std::cerr << "Selected polygon is not a box\n";
340       return false;
341     }
342     vsol_polygon_2d_sptr poly = p->sptr();
343     box = poly->get_bounding_box();
344 #endif
345     box = p;
346     return true;
347   }
348 
349   return false;
350 }
get_selected_poly(bgui_vsol_soview2D_polygon * & poly)351 bool bwm_observer_img::get_selected_poly(bgui_vsol_soview2D_polygon* &poly){
352   bgui_vsol_soview2D_polygon* p = (bgui_vsol_soview2D_polygon*)get_selected_object(POLYGON_TYPE);
353   if(!p) return false;
354   poly = p;
355   return true;
356 }
get_selected_object(std::string type,bool warn)357 vgui_soview2D* bwm_observer_img::get_selected_object(std::string type,
358                                                      bool warn)
359 {
360   std::vector<vgui_soview*> select_list = this->get_selected_soviews();
361   std::vector<vgui_soview2D*> objs;
362   vgui_soview2D* obj;
363 
364   for (unsigned i=0; i<select_list.size(); i++) {
365 #if 0
366     std::cout << select_list[i]->type_name();
367 #endif
368     if (select_list[i]->type_name().compare(type) == 0) {
369       objs.push_back((vgui_soview2D*) select_list[i]);
370     }
371   }
372 
373   if (objs.size() == 1) {
374     obj = (vgui_soview2D*) objs[0];
375     return obj;
376   }
377 
378   if (warn)
379     std::cerr << "\nThe number of selected " << type << " is "
380              << objs.size() << ". Please select only one!!!\n";
381   return nullptr;
382 }
383 
get_selected_objects(std::string type)384 std::vector<vgui_soview2D*> bwm_observer_img::get_selected_objects(std::string type)
385 {
386   std::vector<vgui_soview*> select_list = this->get_selected_soviews();
387   std::vector<vgui_soview2D*> objs;
388 
389   for (unsigned i=0; i<select_list.size(); i++) {
390     std::cout << select_list[i]->type_name();
391     if (select_list[i]->type_name().compare(type) == 0) {
392       objs.push_back((vgui_soview2D*) select_list[i]);
393     }
394   }
395   std::cout << "Number of selected objects of type " << type << " = " << objs.size();
396   return objs;
397 }
398 
399 std::vector<vsol_spatial_object_2d_sptr>
get_spatial_objects_2d()400 bwm_observer_img::get_spatial_objects_2d()
401 {
402   std::vector<vsol_spatial_object_2d_sptr> sos;
403   for (std::map<unsigned, bgui_vsol_soview2D*>::iterator soit = obj_list.begin();
404        soit != obj_list.end(); ++soit)
405     sos.push_back((*soit).second->base_sptr());
406   return sos;
407 }
408 
delete_selected()409 void bwm_observer_img::delete_selected()
410 {
411   // first get the selected polygon
412   std::vector<vgui_soview*> select_list = this->get_selected_soviews();
413 
414   if (select_list.size() == 0)
415     return;
416 
417   if ((select_list.size() == 1) &&
418       ((select_list[0]->type_name().compare(POLYGON_TYPE) == 0) ||
419        (select_list[0]->type_name().compare(POLYLINE_TYPE) == 0)))
420   {
421     //first check to see if this is an image processing box
422 
423     std::map<unsigned, std::vector<bgui_vsol_soview2D* > >::iterator mit =
424       seg_views.begin();
425     std::map<unsigned, std::vector<bgui_vsol_soview2D* > >::iterator to_remove =
426       seg_views.end();
427     for (; mit!=seg_views.end();++mit)
428       if (select_list[0]->get_id()==(*mit).first)
429       {
430         std::vector<bgui_vsol_soview2D* > edges = (*mit).second;
431 
432         for (unsigned i=0; i<edges.size(); i++) {
433           this->remove(edges[i]);
434         }
435         to_remove = mit;
436       }
437     if (to_remove != seg_views.end())
438       seg_views.erase(to_remove);
439 
440     // remove the polygon and the vertices
441     delete_polygon(select_list[0]);
442   }
443   else if (select_list[0]->type_name().compare(VERTEX_TYPE) == 0)
444     delete_vertex(select_list[0]);
445   this->post_redraw();
446 }
447 
delete_all()448 void bwm_observer_img::delete_all()
449 {
450   this->clear_objects();
451   this->post_redraw();
452 }
453 
delete_polygon(vgui_soview * obj)454 void bwm_observer_img::delete_polygon(vgui_soview* obj)
455 {
456   // remove the polygon
457   unsigned poly_id = obj->get_id();
458   this->remove(obj);
459   obj_list.erase(poly_id);
460 
461   // remove the vertices
462   std::vector<bwm_soview2D_vertex*>  v = vert_list[poly_id];
463   for (unsigned i=0; i<v.size(); i++) {
464     this->remove(v[i]);
465   }
466   vert_list.erase(poly_id);
467   this->post_redraw();
468 }
469 
delete_vertex(vgui_soview * vertex)470 void bwm_observer_img::delete_vertex(vgui_soview* vertex)
471 {
472   bwm_soview2D_vertex* v = static_cast<bwm_soview2D_vertex*> (vertex);
473 
474   if (v) {
475     bgui_vsol_soview2D* obj = v->obj();
476     unsigned i = v->vertex_indx();
477 
478     // remove the vertex from the object
479     if (obj->type_name().compare(POLYGON_TYPE) == 0) {
480       bgui_vsol_soview2D_polygon* polygon = static_cast<bgui_vsol_soview2D_polygon*> (obj);
481       vsol_polygon_2d_sptr poly2d = polygon->sptr();
482       if (poly2d->size() == 3) {
483         std::cerr << "Cannot delete a vertex from a triangle\n";
484         return;
485       }
486 
487       if (i >= poly2d->size()) {
488         std::cerr << "The index is invalid [" << i << " of " << poly2d->size() << '\n';
489         return;
490       }
491 
492       std::vector<vsol_point_2d_sptr> new_vertices;
493       for (unsigned k=0; k < poly2d->size(); k++) {
494         if (k != i) // exclude the vertex to be deleted
495           new_vertices.push_back(poly2d->vertex(k));
496       }
497 
498       // delete the object
499       delete_polygon(obj);
500 
501       // draw the new one
502       vsol_polygon_2d_sptr new_poly = new vsol_polygon_2d(new_vertices);
503       create_polygon(new_poly);
504     }
505 
506     else if (obj->type_name().compare(POLYLINE_TYPE) == 0) {
507       bgui_vsol_soview2D_polyline* polyline = static_cast<bgui_vsol_soview2D_polyline*> (obj);
508       vsol_polyline_2d_sptr poly2d = polyline->sptr();
509       if (poly2d->size() == 2) {
510         std::cerr << "Cannot delete a vertex from a polyline with 2 vertices\n";
511         return;
512       }
513 
514       if (i >= poly2d->size()) {
515         std::cerr << "The index is invalid [" << i << " of " << poly2d->size() << '\n';
516         return;
517       }
518 
519       std::vector<vsol_point_2d_sptr> new_vertices;
520       for (unsigned k=0; k < poly2d->size(); k++) {
521         if (k != i) // exclude the vertex to be deleted
522           new_vertices.push_back(poly2d->vertex(k));
523       }
524 
525       // delete the object
526       delete_polygon(obj);
527 
528       // draw the new one
529       vsol_polyline_2d_sptr new_poly = new vsol_polyline_2d(new_vertices);
530       create_polyline(new_poly);
531     }
532   }
533 }
534 
clear_box()535 void bwm_observer_img::clear_box()
536 {
537   // get the selected box
538   bgui_vsol_soview2D_polygon* p = nullptr;
539 
540   if (!this->get_selected_box(p))
541   {
542     std::cerr << "In bwm_observer_img::clear_box() - no box selected\n";
543     return ;
544   }
545 
546   std::vector<bgui_vsol_soview2D* >& soviews = seg_views[p->get_id()];
547   for (unsigned i=0; i<soviews.size(); i++) {
548     this->remove(soviews[i]);
549   }
550 
551   soviews.clear();
552   seg_views[p->get_id()] = soviews;
553   this->post_redraw();
554   // do not delete the information about deleted edges, we may want to bring them back
555 }
556 
recover_edges()557 void bwm_observer_img::recover_edges()
558 {
559   //make sure the box is actually empty
560   this->clear_box();
561   // get the selected box
562   bgui_vsol_soview2D_polygon* p = nullptr;
563   if (!this->get_selected_box(p))
564   {
565     std::cerr << "In bwm_observer_img::clear_box() - no box selected\n";
566     return;
567   }
568 
569   std::vector<vsol_digital_curve_2d_sptr > edges;
570   edges = edge_list[p->get_id()];
571   std::vector<bgui_vsol_soview2D*> soviews;
572   for (unsigned i=0; i<edges.size(); i++) {
573     bgui_vsol_soview2D_digital_curve* curve
574       = this->add_digital_curve(edges[i]);
575     soviews.push_back(curve);
576   }
577   seg_views[p->get_id()] = soviews;
578   post_redraw();
579 }
580 
recover_lines()581 void bwm_observer_img::recover_lines()
582 {
583   //make sure the box is actually empty
584   this->clear_box();
585 
586   // get the selected box
587   bgui_vsol_soview2D_polygon* p = nullptr;
588   if (!this->get_selected_box(p))
589   {
590     std::cerr << "In bwm_observer_img::clear_box() - no box selected\n";
591     return ;
592   }
593 
594   std::vector<vsol_line_2d_sptr> lines;
595   lines = line_list[p->get_id()];
596   std::vector<bgui_vsol_soview2D*> soviews;
597   for (unsigned i=0; i<lines.size(); i++) {
598     bgui_vsol_soview2D_line_seg* line
599       = this->add_vsol_line_2d(lines[i]);
600     soviews.push_back(line);
601   }
602   seg_views[p->get_id()] = soviews;
603   post_redraw();
604 }
605 // display edges for experimental registration
606 void bwm_observer_img::
display_reg_seg(std::vector<vsol_digital_curve_2d_sptr> const & search_edges,std::vector<vsol_digital_curve_2d_sptr> const & model_edges)607 display_reg_seg(std::vector<vsol_digital_curve_2d_sptr> const& search_edges,
608                 std::vector<vsol_digital_curve_2d_sptr> const& model_edges)
609 {
610   this->clear_reg_segmentation();
611   vgui_style_sptr mstyle = vgui_style::new_style(0.1f, 0.8f, 0.1f, 1.0f, 3.0f);
612   vgui_style_sptr sstyle = vgui_style::new_style(0.8f, 0.1f, 0.8f, 1.0f, 3.0f);
613 
614   std::vector<vsol_digital_curve_2d_sptr>::const_iterator cit =
615     search_edges.begin();
616   for (; cit != search_edges.end(); ++cit)
617     reg_seg_views_.push_back(this->add_digital_curve(*cit, sstyle));
618 
619   cit = model_edges.begin();
620   for (; cit != model_edges.end(); ++cit)
621     reg_seg_views_.push_back(this->add_digital_curve(*cit, mstyle));
622 
623   this->post_redraw();
624 }
625 
626 // clear the edges displayed for the experimental registration tasks
clear_reg_segmentation()627 void bwm_observer_img::clear_reg_segmentation()
628 {
629   for (std::vector<bgui_vsol_soview2D* >::iterator sit = reg_seg_views_.begin();
630        sit != reg_seg_views_.end(); ++sit)
631     this->remove(*sit);
632   reg_seg_views_.clear();
633 }
634 
635 
hist_plot()636 void bwm_observer_img::hist_plot()
637 {
638   bwm_image_processor::hist_plot(img_tab_);
639 }
640 
hist_plot_in_poly()641 void bwm_observer_img::hist_plot_in_poly(){
642   bgui_vsol_soview2D_polygon* p;
643   if(!get_selected_poly(p)){
644     std::cerr << " No polygon to scan to produce hist plot\n";
645     return;
646   }
647   vsol_polygon_2d_sptr poly = p->sptr();
648   bwm_image_processor::hist_plot(img_tab_, poly);
649 }
650 
intensity_profile(float start_col,float start_row,float end_col,float end_row)651 void bwm_observer_img::intensity_profile(float start_col, float start_row,
652                                          float end_col, float end_row)
653 {
654   bwm_image_processor::intensity_profile(img_tab_, start_col, start_row, end_col, end_row);
655 }
656 
range_map()657 void bwm_observer_img::range_map()
658 {
659   bwm_image_processor::range_map(img_tab_);
660 }
661 
toggle_show_image_path()662 void bwm_observer_img::toggle_show_image_path()
663 {
664   show_image_path_ = !show_image_path_;
665   img_tab_->show_image_path(show_image_path_);
666 }
667 
step_edges_vd()668 void bwm_observer_img::step_edges_vd()
669 {
670   bgui_vsol_soview2D_polygon* p = nullptr;
671   if (!this->get_selected_box(p))
672   {
673     std::cerr << "In bwm_observer_img::step_edges_vd() - no box selected\n";
674     return;
675   }
676 
677   std::vector<vsol_digital_curve_2d_sptr> edges;
678   vsol_polygon_2d_sptr poly = p->sptr();
679   vsol_box_2d_sptr box = poly->get_bounding_box();
680   if (!bwm_image_processor::step_edges_vd(img_tab_, box, edges))
681   {
682     std::cerr << "In bwm_observer_img::step_edges_vd() - no edges\n";
683     return;
684   }
685 
686   // first clean up the box, if there is anything in it
687   clear_box();
688 
689   std::vector<bgui_vsol_soview2D*> soviews;
690   for (std::vector<vsol_digital_curve_2d_sptr>::iterator eit = edges.begin();
691        eit != edges.end(); ++eit)
692   {
693     bgui_vsol_soview2D_digital_curve* curve = this->add_digital_curve(*eit);
694     soviews.push_back(curve);
695   }
696   edge_list[p->get_id()] = edges;
697   seg_views[p->get_id()] = soviews;
698   this->post_redraw();
699 }
700 
lines_vd()701 void bwm_observer_img::lines_vd()
702 {
703   bgui_vsol_soview2D_polygon* p = nullptr;
704   if (!this->get_selected_box(p))
705   {
706     std::cerr << "In bwm_observer_img::lines_vd() - no box selected\n";
707     return ;
708   }
709 
710   std::vector<vsol_line_2d_sptr> lines;
711   vsol_polygon_2d_sptr poly = p->sptr();
712   vsol_box_2d_sptr box = poly->get_bounding_box();
713   if (!bwm_image_processor::lines_vd(img_tab_, box, lines))
714   {
715     std::cerr << "In bwm_observer_img::lines_vd() - no lines\n";
716     return;
717   }
718 
719   // first clean up the box, if there is anything in it
720   clear_box();
721 
722   std::vector<bgui_vsol_soview2D*> soviews;
723   for (std::vector<vsol_line_2d_sptr>::iterator lit = lines.begin();
724        lit != lines.end(); ++lit)
725   {
726     bgui_vsol_soview2D_line_seg* line = this->add_vsol_line_2d(*lit);
727     // store in object list in order to save later if desired
728     obj_list[line->get_id()] = line;
729     // Gamze - do not add the lines one by one: create a vector and map it to the box
730     soviews.push_back(line);
731   }
732   line_list[p->get_id()] = lines;
733   seg_views[p->get_id()] = soviews;
734 
735   this->post_redraw();
736 }
737 
crop_image(vil_image_resource_sptr & chip)738 bool bwm_observer_img::crop_image(vil_image_resource_sptr& chip)
739 {
740   bgui_vsol_soview2D_polygon* p = nullptr;
741   if (!this->get_selected_box(p))
742   {
743     std::cerr << "In bwm_observer_img::crop_image() - no box selected\n";
744     return false;
745   }
746   vsol_polygon_2d_sptr poly = p->sptr();
747   vsol_box_2d_sptr box = poly->get_bounding_box();
748   return bwm_image_processor::crop_to_box(img_tab_, box, chip);
749 }
750 
751 //: (x, y) is the target point to be positioned at the center of the grid cell containing this observer
752 //
move_to_point(float x,float y)753 void bwm_observer_img::move_to_point(float x, float y)
754 {
755   // the image size
756   unsigned ni = img_tab_->get_image_resource()->ni();
757   unsigned nj = img_tab_->get_image_resource()->nj();
758   if (x<0 || x>=ni || y<0 || y>=nj)
759     std::cerr << "In bwm_observer_img::move_to_point(.) -"
760              << " requested point outside of image bounds\n";
761   if (x<0) x=0;
762   if (x>=ni) x = ni-1;
763   if (y<0) y=0;
764   if (y>=nj) y = nj-1;
765   if (viewer_)
766   {
767     //Get the current viewer state (scale and offset)
768     float sx = viewer_->token.scaleX, sy = viewer_->token.scaleY;
769     float tx = viewer_->token.offsetX, ty = viewer_->token.offsetY;
770 
771     //The position of this observer in the grid
772     unsigned r = this->row(), c = this->col();
773 
774     //The grid tableau
775     vgui_grid_tableau_sptr grid = bwm_tableau_mgr::instance()->grid();
776     if (!grid)
777       return;
778 
779     //The bounds of the grid cell containing this observer
780     float xorig , yorig, xmax, ymax;
781     grid->cell_bounding_box(c, r, xorig , yorig, xmax, ymax);
782 
783     // target image point in window coordinates
784     float wx = sx*(x + tx/sx) + xorig;
785     float wy = (ymax-yorig - sy*(y + ty/sy))+ yorig;
786 
787     // cell center in window coordinates
788     float twx = (xorig + xmax)/2;
789     float twy = (yorig + ymax)/2;
790 
791     // The required translation to position in the center
792     float transx = twx-wx;
793     float transy = twy-wy;
794 
795     viewer_->token.offsetX += transx;
796     viewer_->token.offsetY -= transy;
797     viewer_->post_redraw();
798 
799 #if 0 // debug printouts
800     std::cout << "\n\n====--=====\n"
801              << "sx = " << sx << "  sy = " << sy << '\n'
802              << "tx = " << tx << "  ty = " << ty << '\n'
803              << "r = " << r << "  c = " << c << '\n'
804              << "target point (" << x << ' ' << y << ")\n"
805              << "target point in window coords (" << wx << ' ' << wy << ")\n"
806              << "cell center in window coords ("
807              << twx << ' ' << twy << ")\n"
808              << "required tx = " << transx
809              << "  required ty = " << transy << '\n'
810              << std::flush;
811 #endif
812   }
813 }
814 
zoom_to_fit()815 void bwm_observer_img::zoom_to_fit()
816 {
817   if (!viewer_ || !img_tab_)
818     return;
819 
820   if (!img_tab_->get_image_resource())
821     return;
822 
823   // the image size
824   unsigned ni = img_tab_->get_image_resource()->ni();
825   unsigned nj = img_tab_->get_image_resource()->nj();
826 
827 #if 0
828   // current viewer scale
829   float sx = viewer_->token.scaleX, sy = std::fabs(viewer_->token.scaleY);
830 
831   // the window size
832   vgui_projection_inspector p_insp;
833   vgl_box_2d<float> bb(p_insp.x1, p_insp.x2, p_insp.y1, p_insp.y2);
834   float w = bb.width()*sx;
835   float h = bb.height()*sy;
836 #endif
837   //The grid tableau
838   vgui_grid_tableau_sptr grid = bwm_tableau_mgr::instance()->grid();
839   if (!grid)
840     return;
841 
842   //The position of this observer in the grid
843   unsigned ro = this->row(), cl = this->col();
844 
845   //The bounds of the grid cell containing this observer
846   float xorig , yorig, xmax, ymax;
847   grid->cell_bounding_box(cl, ro, xorig , yorig, xmax, ymax);
848 
849   float w = xmax-xorig, h = ymax-yorig;
850 
851   // the required scale to fit the image in the window
852   float required_scale_x = w/ni;
853   float required_scale_y = h/nj;
854   float r = required_scale_x;
855   if (r>required_scale_y)
856     r = required_scale_y;
857 
858   // the center of the image
859   float cx = ni/2, cy = nj/2;
860 
861   // set the scale on the viewer
862   viewer_->token.scaleX = r;
863   viewer_->token.scaleY = r;
864 
865   // position so the image is centered
866   viewer_->token.offsetX = w/2.0-cx*r;
867   viewer_->token.offsetY = h/2.0-cy*r;
868 
869   viewer_->post_redraw();
870   viewer_->post_redraw();
871 #if 0 //debug printouts
872   std::cout << "sx = " << sx << "  sy = " << sy << '\n'
873            << "bb.w " << w << " bb.h " << h << '\n'
874            << "required scale = " << r << "  c(" << cx << ' '
875            << cy << ")\n";
876 #endif
877 }
878 
scroll_to_point()879 void bwm_observer_img::scroll_to_point()
880 {
881   static int ix = 0, iy = 0;
882   vgui_dialog zoom("Move to Image Position");
883   zoom.field ("image col", ix);
884   zoom.field ("image row", iy);
885   if (!zoom.ask())
886     return;
887   float x = static_cast<float>(ix), y = static_cast<float>(iy);
888   this->move_to_point(x,y);
889 }
890 
init_mask()891 void bwm_observer_img::init_mask()
892 {
893   mask_ = nullptr;
894   change_polys_.clear();
895 }
896 
set_change_type()897 void bwm_observer_img::set_change_type()
898 {
899   unsigned int type = 0;
900   vgui_dialog type_dialog("Change Type");
901 
902   if (this->change_choices_.empty())
903   {
904     this->change_choices_.push_back("change");
905     this->change_choices_.push_back("don't care");
906     this->change_choices_.push_back("vehicle");
907     this->change_choices_.push_back("building");
908     this->change_choices_.push_back("shadow");
909     this->change_choices_.push_back("sewage");
910     this->change_choices_.push_back("car");
911     this->change_choices_.push_back("pick-up truck");
912     this->change_choices_.push_back("utility");
913     this->change_choices_.push_back("van");
914     this->change_choices_.push_back("suv");
915     this->change_choices_.push_back("minivan");
916     this->change_choices_.push_back("high-quality");
917     this->change_choices_.push_back("New Change Type");
918   }
919   type_dialog.choice("Change Type", this->change_choices_, type);
920   if (!type_dialog.ask())
921     return;
922 
923   if (type > this->change_choices_.size()) {
924     std::cerr << "bwm_observer_img::set_change_type -- Invalid choice\n";
925     return;
926   }
927 
928   if (this->change_choices_[type] == "New Change Type")
929   {
930     vgui_dialog new_change_dialog("New Change Type");
931     std::string new_change_type;
932     new_change_dialog.field("New Change Type", new_change_type);
933     new_change_dialog.ask();
934 
935     bool already_listed = false;
936     for ( unsigned i = 0; i < this->change_choices_.size(); ++i )
937     {
938       if ( this->change_choices_[i] == new_change_type )
939         already_listed = true;
940     }
941     if ( !already_listed )
942     {
943       this->change_choices_.pop_back();
944       this->change_choices_.push_back(new_change_type);
945       this->change_choices_.push_back("New Change Type");
946     }
947 
948     this->change_type_ = new_change_type;
949   }
950   else
951     change_type_ = this->change_choices_[type];
952 }
953 
954 
add_poly_to_mask()955 void bwm_observer_img::add_poly_to_mask()
956 {
957   bgui_vsol_soview2D_polygon* p=nullptr;
958 
959   if (!ground_truth_)
960     ground_truth_ = new bvgl_changes();
961 
962   // get the selected polygon
963   std::vector<vgui_soview2D*> polys = get_selected_objects(POLYGON_TYPE);
964   for (unsigned i=0; i<polys.size(); i++) {
965     p = (bgui_vsol_soview2D_polygon*) polys[i];
966     vsol_polygon_2d_sptr poly = p->sptr();
967     if (!poly)
968       continue;
969     vgl_polygon<double> v_poly =  bsol_algs::vgl_from_poly(poly);
970     bvgl_change_obj_sptr obj = new bvgl_change_obj(v_poly, change_type_);
971     change_polys_[polys[i]->get_id()] = obj;
972     ground_truth_->add_obj(obj);
973   }
974 }
975 
remove_poly_from_mask()976 void bwm_observer_img::remove_poly_from_mask()
977 {
978   bgui_vsol_soview2D_polygon* p=nullptr;
979   std::vector<vgui_soview2D*> polys = get_selected_objects(POLYGON_TYPE);
980   for (unsigned i=0; i<polys.size(); i++) {
981     p = (bgui_vsol_soview2D_polygon*) polys[i];
982     std::map<unsigned int, bvgl_change_obj_sptr>::iterator poly;
983     // search the change polygons for deletion
984     poly = change_polys_.find(p->get_id());
985     if (poly != change_polys_.end()) {
986       ground_truth_->remove_obj(poly->second);
987       change_polys_.erase(poly->first);
988     }
989   }
990 }
991 
992 #if 0 // commented out
993 void bwm_observer_img::create_mask()
994 {
995   mask_ = 0;
996   //index through the polygons and create the boolean mask image
997   // the image size
998   unsigned ni = img_tab_->get_image_resource()->ni();
999   unsigned nj = img_tab_->get_image_resource()->nj();
1000   vil_image_view<unsigned char>* mask = new vil_image_view<unsigned char>(ni, nj);
1001   mask->fill(0);
1002 
1003   // fill the change areas
1004   for (std::map<unsigned int, vsol_polygon_2d_sptr>::iterator pit = mask_polys_.begin();
1005        pit != mask_polys_.end(); ++pit)
1006   {
1007     vgl_polygon<double> v_poly =  bsol_algs::vgl_from_poly(pit->second);
1008     vgl_polygon_scan_iterator<double> psi(v_poly, false);
1009     for (psi.reset(); psi.next();){
1010       int y = psi.scany();
1011       for (int x = psi.startx(); x<=psi.endx(); ++x)
1012       {
1013         unsigned u = static_cast<unsigned>(x);
1014         unsigned v = static_cast<unsigned>(y);
1015         (*mask)(u,v) = 255;
1016       }
1017     }
1018   }
1019 
1020   // fill the don't care areas
1021   for (std::map<unsigned int, vsol_polygon_2d_sptr>::iterator pit = mask_dontcare_polys_.begin();
1022        pit != mask_dontcare_polys_.end(); ++pit)
1023   {
1024     vgl_polygon<double> v_poly =  bsol_algs::vgl_from_poly(pit->second);
1025     vgl_polygon_scan_iterator<double> psi(v_poly, false);
1026     for (psi.reset(); psi.next();){
1027       int y = psi.scany();
1028       for (int x = psi.startx(); x<=psi.endx(); ++x)
1029       {
1030         unsigned u = static_cast<unsigned>(x);
1031         unsigned v = static_cast<unsigned>(y);
1032         (*mask)(u,v) = 125;
1033       }
1034     }
1035   }
1036   mask_ = mask;
1037 }
1038 #endif // 0
1039 
mask()1040 vil_image_view_base_sptr bwm_observer_img::mask()
1041 {
1042   return ground_truth_->create_mask_from_objs(img_tab_->get_image_resource()->ni(), img_tab_->get_image_resource()->nj(), "change");
1043 }
1044 
save_changes_binary()1045 bool bwm_observer_img::save_changes_binary()
1046 {
1047   std::string fname = bwm_utils::select_file();
1048   vsl_b_ofstream os(fname);
1049   ground_truth_->b_write(os);
1050   return true;
1051 }
1052 
load_changes_binary()1053 bool bwm_observer_img::load_changes_binary()
1054 {
1055   std::string fname = bwm_utils::select_file();
1056   vsl_b_ifstream is(fname);
1057   if (ground_truth_ == nullptr)
1058     ground_truth_= new bvgl_changes();
1059   ground_truth_->b_read(is);
1060 
1061   // draw the polygons on the image
1062   for (unsigned i=0; i<ground_truth_->size(); i++) {
1063     bvgl_change_obj_sptr obj = ground_truth_->obj(i);
1064     vgl_polygon<double> poly = obj->poly();
1065     vsol_polygon_2d_sptr poly2d = bsol_algs::poly_from_vgl(poly);
1066     unsigned id = this->create_polygon(poly2d);
1067     change_polys_[id] = obj;
1068   }
1069   return true;
1070 }
1071