Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
ac4666cb
Commit
ac4666cb
authored
Mar 22, 2015
by
Davis King
Browse files
Added the perspective_display and perspective_window GUI tools.
parent
3ff14401
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
799 additions
and
0 deletions
+799
-0
dlib/gui_widgets/widgets.cpp
dlib/gui_widgets/widgets.cpp
+300
-0
dlib/gui_widgets/widgets.h
dlib/gui_widgets/widgets.h
+229
-0
dlib/gui_widgets/widgets_abstract.h
dlib/gui_widgets/widgets_abstract.h
+270
-0
No files found.
dlib/gui_widgets/widgets.cpp
View file @
ac4666cb
...
...
@@ -5652,6 +5652,306 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// perspective_display member functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
perspective_display::
perspective_display(
drawable_window& w
) :
drawable(w,MOUSE_MOVE|MOUSE_CLICK|MOUSE_WHEEL)
{
clear_overlay();
enable_events();
}
// ----------------------------------------------------------------------------------------
perspective_display::
~perspective_display(
)
{
disable_events();
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
set_size (
unsigned long width,
unsigned long height
)
{
auto_mutex lock(m);
rectangle old(rect);
rect = resize_rect(rect,width,height);
tform = camera_transform(tform.get_camera_pos(),
tform.get_camera_looking_at(),
tform.get_camera_up_direction(),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
parent.invalidate_rectangle(old+rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
add_overlay (
const std::vector<overlay_line>& overlay
)
{
auto_mutex M(m);
if (overlay.size() == 0)
return;
// push this new overlay into our overlay vector
overlay_lines.insert(overlay_lines.end(), overlay.begin(), overlay.end());
for (unsigned long i = 0; i < overlay.size(); ++i)
{
sum_pts += overlay[i].p1;
sum_pts += overlay[i].p2;
max_pts.x() = std::max(overlay[i].p1.x(), max_pts.x());
max_pts.x() = std::max(overlay[i].p2.x(), max_pts.x());
max_pts.y() = std::max(overlay[i].p1.y(), max_pts.y());
max_pts.y() = std::max(overlay[i].p2.y(), max_pts.y());
max_pts.z() = std::max(overlay[i].p1.z(), max_pts.z());
max_pts.z() = std::max(overlay[i].p2.z(), max_pts.z());
}
tform = camera_transform(max_pts,
sum_pts/(overlay_lines.size()*2+overlay_dots.size()),
vector<double>(0,0,1),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
// make the parent window redraw us now that we changed the overlay
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
add_overlay (
const std::vector<overlay_dot>& overlay
)
{
auto_mutex M(m);
if (overlay.size() == 0)
return;
// push this new overlay into our overlay vector
overlay_dots.insert(overlay_dots.end(), overlay.begin(), overlay.end());
for (unsigned long i = 0; i < overlay.size(); ++i)
{
sum_pts += overlay[i].p;
max_pts.x() = std::max(overlay[i].p.x(), max_pts.x());
max_pts.y() = std::max(overlay[i].p.y(), max_pts.y());
max_pts.z() = std::max(overlay[i].p.z(), max_pts.z());
}
tform = camera_transform(max_pts,
sum_pts/(overlay_lines.size()*2+overlay_dots.size()),
vector<double>(0,0,1),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
// make the parent window redraw us now that we changed the overlay
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
clear_overlay (
)
{
auto_mutex lock(m);
overlay_dots.clear();
overlay_lines.clear();
sum_pts = vector<double>();
max_pts = vector<double>(-std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity());
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
set_dot_double_clicked_handler (
const any_function<void(const vector<double>&)>& event_handler_
)
{
auto_mutex M(m);
dot_clicked_event_handler = event_handler_;
}
// ----------------------------------------------------------------------------------------
void perspective_display::
draw (
const canvas& c
) const
{
rectangle area = rect.intersect(c);
fill_rect(c, area, 0);
for (unsigned long i = 0; i < overlay_dots.size(); ++i)
{
point p = tform(overlay_dots[i].p) + rect.tl_corner();
if (area.contains(p))
assign_pixel(c[p.y()-c.top()][p.x()-c.left()], overlay_dots[i].color);
}
for (unsigned long i = 0; i < overlay_lines.size(); ++i)
{
draw_line(c, tform(overlay_lines[i].p1), tform(overlay_lines[i].p2), overlay_lines[i].color, area);
}
}
// ----------------------------------------------------------------------------------------
void perspective_display::
on_wheel_up (
unsigned long state
)
{
if (rect.contains(lastx,lasty) == false || hidden || !enabled)
return;
const double alpha = 0.10;
const vector<double> delta = alpha*(tform.get_camera_pos() - tform.get_camera_looking_at());
tform = camera_transform(
tform.get_camera_pos() - delta,
tform.get_camera_looking_at(),
tform.get_camera_up_direction(),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
on_wheel_down (
unsigned long state
)
{
if (rect.contains(lastx,lasty) == false || hidden || !enabled)
return;
const double alpha = 0.10;
const vector<double> delta = alpha*(tform.get_camera_pos() - tform.get_camera_looking_at());
tform = camera_transform(
tform.get_camera_pos() + delta,
tform.get_camera_looking_at(),
tform.get_camera_up_direction(),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
void perspective_display::
on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
)
{
if (btn == base_window::LEFT || btn == base_window::RIGHT)
{
last = point(x,y);
}
if (is_double_click && btn == base_window::LEFT && enabled && !hidden && overlay_dots.size() != 0)
{
double best_dist = std::numeric_limits<double>::infinity();
unsigned long best_idx = 0;
const dpoint pp(x,y);
for (unsigned long i = 0; i < overlay_dots.size(); ++i)
{
dpoint p = tform(overlay_dots[i].p) + rect.tl_corner();
double dist = length_squared(p-pp);
if (dist < best_dist)
{
best_dist = dist;
best_idx = i;
}
}
if (dot_clicked_event_handler.is_set())
dot_clicked_event_handler(overlay_dots[best_idx].p);
}
}
// ----------------------------------------------------------------------------------------
void perspective_display::
on_mouse_move (
unsigned long state,
long x,
long y
)
{
if (!enabled || hidden)
return;
if (state == base_window::LEFT)
{
const point cur(x, y);
dpoint delta = last-cur;
last = cur;
const vector<double> radius = tform.get_camera_pos()-tform.get_camera_looking_at();
delta *= 2*pi*length(radius)/600.0;
vector<double> tangent_x = tform.get_camera_up_direction().cross(radius).normalize();
vector<double> tangent_y = radius.cross(tangent_x).normalize();
vector<double> new_pos = tform.get_camera_pos() + tangent_x*delta.x() + tangent_y*-delta.y();
// now make it have the correct radius relative to the looking at point.
new_pos = (new_pos-tform.get_camera_looking_at()).normalize()*length(radius) + tform.get_camera_looking_at();
tform = camera_transform(new_pos,
tform.get_camera_looking_at(),
tangent_y,
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
parent.invalidate_rectangle(rect);
}
else if (state == (base_window::LEFT|base_window::SHIFT) ||
state == base_window::RIGHT)
{
const point cur(x, y);
dpoint delta = last-cur;
last = cur;
const vector<double> radius = tform.get_camera_pos()-tform.get_camera_looking_at();
delta *= 2*pi*length(radius)/600.0;
vector<double> tangent_x = tform.get_camera_up_direction().cross(radius).normalize();
vector<double> tangent_y = radius.cross(tangent_x).normalize();
vector<double> offset = tangent_x*delta.x() + tangent_y*-delta.y();
tform = camera_transform(
tform.get_camera_pos()+offset,
tform.get_camera_looking_at()+offset,
tform.get_camera_up_direction(),
tform.get_camera_field_of_view(),
std::min(rect.width(),rect.height()));
parent.invalidate_rectangle(rect);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// image_display member functions
...
...
dlib/gui_widgets/widgets.h
View file @
ac4666cb
...
...
@@ -3586,6 +3586,235 @@ namespace dlib
image_display
&
operator
=
(
image_display
&
);
// assignment operator
};
// ----------------------------------------------------------------------------------------
class
perspective_display
:
public
drawable
,
noncopyable
{
public:
perspective_display
(
drawable_window
&
w
);
~
perspective_display
(
);
virtual
void
set_size
(
unsigned
long
width
,
unsigned
long
height
);
struct
overlay_line
{
overlay_line
()
{
assign_pixel
(
color
,
0
);}
overlay_line
(
const
vector
<
double
>&
p1_
,
const
vector
<
double
>&
p2_
)
:
p1
(
p1_
),
p2
(
p2_
)
{
assign_pixel
(
color
,
255
);
}
template
<
typename
pixel_type
>
overlay_line
(
const
vector
<
double
>&
p1_
,
const
vector
<
double
>&
p2_
,
pixel_type
p
)
:
p1
(
p1_
),
p2
(
p2_
)
{
assign_pixel
(
color
,
p
);
}
vector
<
double
>
p1
;
vector
<
double
>
p2
;
rgb_pixel
color
;
};
struct
overlay_dot
{
overlay_dot
()
{
assign_pixel
(
color
,
0
);}
overlay_dot
(
const
vector
<
double
>&
p_
)
:
p
(
p_
)
{
assign_pixel
(
color
,
255
);
}
template
<
typename
pixel_type
>
overlay_dot
(
const
vector
<
double
>&
p_
,
pixel_type
color_
)
:
p
(
p_
)
{
assign_pixel
(
color
,
color_
);
}
vector
<
double
>
p
;
rgb_pixel
color
;
};
void
add_overlay
(
const
std
::
vector
<
overlay_line
>&
overlay
);
void
add_overlay
(
const
std
::
vector
<
overlay_dot
>&
overlay
);
void
clear_overlay
(
);
template
<
typename
T
>
void
set_dot_double_clicked_handler
(
T
&
object
,
void
(
T
::*
event_handler_
)(
const
vector
<
double
>&
)
)
{
auto_mutex
M
(
m
);
dot_clicked_event_handler
=
make_mfp
(
object
,
event_handler_
);
}
void
set_dot_double_clicked_handler
(
const
any_function
<
void
(
const
vector
<
double
>&
)
>&
event_handler_
);
private:
void
draw
(
const
canvas
&
c
)
const
;
void
on_wheel_up
(
unsigned
long
state
);
void
on_wheel_down
(
unsigned
long
state
);
void
on_mouse_down
(
unsigned
long
btn
,
unsigned
long
state
,
long
x
,
long
y
,
bool
is_double_click
);
void
on_mouse_move
(
unsigned
long
state
,
long
x
,
long
y
);
point
last
;
std
::
vector
<
overlay_line
>
overlay_lines
;
std
::
vector
<
overlay_dot
>
overlay_dots
;
camera_transform
tform
;
vector
<
double
>
sum_pts
;
vector
<
double
>
max_pts
;
any_function
<
void
(
const
vector
<
double
>&
)
>
dot_clicked_event_handler
;
};
// ----------------------------------------------------------------------------------------
class
perspective_window
:
public
drawable_window
,
noncopyable
{
public:
typedef
perspective_display
::
overlay_line
overlay_line
;
typedef
perspective_display
::
overlay_dot
overlay_dot
;
perspective_window
(
)
:
disp
(
*
this
)
{
set_size
(
100
,
100
);
}
perspective_window
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
point_cloud
)
:
disp
(
*
this
)
{
set_size
(
100
,
100
);
add_overlay
(
point_cloud
);
show
();
}
perspective_window
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
point_cloud
,
const
std
::
string
&
title
)
:
disp
(
*
this
)
{
set_size
(
100
,
100
);
add_overlay
(
point_cloud
);
set_title
(
title
);
show
();
}
~
perspective_window
(
)
{
// You should always call close_window() in the destructor of window
// objects to ensure that no events will be sent to this window while
// it is being destructed.
close_window
();
}
void
add_overlay
(
const
std
::
vector
<
overlay_line
>&
overlay
)
{
disp
.
add_overlay
(
overlay
);
}
void
add_overlay
(
const
std
::
vector
<
overlay_dot
>&
overlay
)
{
disp
.
add_overlay
(
overlay
);
}
void
clear_overlay
(
)
{
disp
.
clear_overlay
();
}
void
add_overlay
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
d
)
{
add_overlay
(
d
,
255
);
}
template
<
typename
pixel_type
>
void
add_overlay
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
d
,
pixel_type
p
)
{
std
::
vector
<
overlay_dot
>
temp
;
temp
.
resize
(
d
.
size
());
for
(
unsigned
long
i
=
0
;
i
<
temp
.
size
();
++
i
)
temp
[
i
]
=
overlay_dot
(
d
[
i
],
p
);
add_overlay
(
temp
);
}
template
<
typename
T
>
void
set_dot_double_clicked_handler
(
T
&
object
,
void
(
T
::*
event_handler_
)(
const
vector
<
double
>&
)
)
{
disp
.
set_dot_double_clicked_handler
(
object
,
event_handler_
);
}
void
set_dot_double_clicked_handler
(
const
any_function
<
void
(
const
vector
<
double
>&
)
>&
event_handler_
)
{
disp
.
set_dot_double_clicked_handler
(
event_handler_
);
}
private:
void
on_window_resized
(
)
{
drawable_window
::
on_window_resized
();
unsigned
long
width
,
height
;
get_size
(
width
,
height
);
disp
.
set_size
(
width
,
height
);
}
perspective_display
disp
;
};
// ----------------------------------------------------------------------------------------
class
image_window
:
public
drawable_window
...
...
dlib/gui_widgets/widgets_abstract.h
View file @
ac4666cb
...
...
@@ -3158,6 +3158,276 @@ namespace dlib
image_window
&
operator
=
(
image_window
&
);
};
// ----------------------------------------------------------------------------------------
class
perspective_display
:
public
drawable
,
noncopyable
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a tool for displaying 3D point clouds on a screen. You can
navigate the display with the mouse. Left click and drag rotates the
camera around the displayed data. Scrolling the mouse wheel zooms and
shift+left click (or just right click) and drag pans the view around.
!*/
public:
perspective_display
(
drawable_window
&
w
);
/*!
ensures
- #*this is properly initialized
- #*this has been added to window w
- #parent_window() == w
!*/
~
perspective_display
(
);
/*!
ensures
- all resources associated with *this have been released
!*/
void
set_size
(
unsigned
long
width
,
unsigned
long
height
);
/*!
ensures
- #width() == width
- #height() == height
- #top() == top()
- #left() == left()
- i.e. The location of the upper left corner of this widget stays the
same but its width and height are modified.
!*/
struct
overlay_line
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a line that is drawn on the screen. Each line
is represented by its two end points (p1 and p2) as well as a color.
!*/
overlay_line
()
{
assign_pixel
(
color
,
0
);}
overlay_line
(
const
vector
<
double
>&
p1_
,
const
vector
<
double
>&
p2_
)
:
p1
(
p1_
),
p2
(
p2_
)
{
assign_pixel
(
color
,
255
);
}
template
<
typename
pixel_type
>
overlay_line
(
const
vector
<
double
>&
p1_
,
const
vector
<
double
>&
p2_
,
pixel_type
p
)
:
p1
(
p1_
),
p2
(
p2_
)
{
assign_pixel
(
color
,
p
);
}
vector
<
double
>
p1
;
vector
<
double
>
p2
;
rgb_pixel
color
;
};
struct
overlay_dot
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a dot that is drawn on the screen. Each dot is
represented by one point and a color.
!*/
overlay_dot
()
{
assign_pixel
(
color
,
0
);}
overlay_dot
(
const
vector
<
double
>&
p_
)
:
p
(
p_
)
{
assign_pixel
(
color
,
255
);
}
template
<
typename
pixel_type
>
overlay_dot
(
const
vector
<
double
>&
p_
,
pixel_type
color_
)
:
p
(
p_
)
{
assign_pixel
(
color
,
color_
);
}
vector
<
double
>
p
;
// The location of the dot
rgb_pixel
color
;
};
void
add_overlay
(
const
std
::
vector
<
overlay_line
>&
overlay
);
/*!
ensures
- Adds the given overlay lines into this object such that it will be
displayed.
!*/
void
add_overlay
(
const
std
::
vector
<
overlay_dot
>&
overlay
);
/*!
ensures
- Adds the given overlay dots into this object such that it will be
displayed.
!*/
void
clear_overlay
(
);
/*!
ensures
- Removes all overlays from this object. The display will be empty.
!*/
template
<
typename
T
>
void
set_dot_double_clicked_handler
(
T
&
object
,
void
(
T
::*
event_handler
)(
const
vector
<
double
>&
)
);
/*
requires
- event_handler is a valid pointer to a member function in T
ensures
- The event_handler function is called on object when the user double
clicks on one of the overlay dots. The selected dot will be passed to
event_handler().
- Any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
*/
void
set_dot_double_clicked_handler
(
const
any_function
<
void
(
const
vector
<
double
>&
)
>&
event_handler
);
/*
ensures
- The event_handler function is called when the user double clicks on one
of the overlay dots. The selected dot will be passed to event_handler().
- Any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
*/
};
// ----------------------------------------------------------------------------------------
class
perspective_window
:
public
drawable_window
,
noncopyable
{
/*!
WHAT THIS OBJECT REPRESENTS
This is a simple window that is just a container for a perspective_display.
It exists to make it easy to throw perspective_displays onto the screen
without having to put together your own drawable_window objects.
!*/
public:
typedef
perspective_display
::
overlay_line
overlay_line
;
typedef
perspective_display
::
overlay_dot
overlay_dot
;
perspective_window
(
);
/*!
ensures
- The window is displayed on the screen and is 100x100 pixels in size.
!*/
perspective_window
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
point_cloud
);
/*!
ensures
- The window is displayed on the screen and is 100x100 pixels in size.
- This window will have point_cloud added to it via add_overlay() and the
points will all be white.
!*/
perspective_window
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
point_cloud
,
const
std
::
string
&
title
);
/*!
ensures
- The window is displayed on the screen and is 100x100 pixels in size.
- This window will have point_cloud added to it via add_overlay() and the
points will all be white.
- The title of the window will be set to the given title string.
!*/
~
perspective_window
(
);
/*!
ensures
- any resources associated with this object have been released
!*/
void
add_overlay
(
const
std
::
vector
<
overlay_line
>&
overlay
);
/*!
ensures
- Adds the given overlay lines into this object such that it will be
displayed.
!*/
void
add_overlay
(
const
std
::
vector
<
overlay_dot
>&
overlay
);
/*!
ensures
- Adds the given overlay dots into this object such that it will be
displayed.
!*/
void
clear_overlay
(
);
/*!
ensures
- Removes all overlays from this object. The display will be empty.
!*/
void
add_overlay
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
d
);
/*!
ensures
- Adds the given dots into this object such that it will be
displayed. They will be colored white.
!*/
template
<
typename
pixel_type
>
void
add_overlay
(
const
std
::
vector
<
dlib
::
vector
<
double
>
>&
d
,
pixel_type
p
);
/*!
ensures
- Adds the given dots into this object such that it will be
displayed. They will be colored by pixel color p.
!*/
template
<
typename
T
>
void
set_dot_double_clicked_handler
(
T
&
object
,
void
(
T
::*
event_handler
)(
const
vector
<
double
>&
)
);
/*
requires
- event_handler is a valid pointer to a member function in T
ensures
- The event_handler function is called on object when the user double
clicks on one of the overlay dots. The selected dot will be passed to
event_handler().
- Any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
*/
void
set_dot_double_clicked_handler
(
const
any_function
<
void
(
const
vector
<
double
>&
)
>&
event_handler
);
/*
ensures
- The event_handler function is called when the user double clicks on one
of the overlay dots. The selected dot will be passed to event_handler().
- Any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
*/
};
// ----------------------------------------------------------------------------------------
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment