158 lines
4.1 KiB
C++
158 lines
4.1 KiB
C++
|
/*
|
||
|
* Copyright 2019 University of Toronto
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
* Authors: Mario Badr, Sameh Attia and Tanner Young-Schultz
|
||
|
*/
|
||
|
|
||
|
#ifndef EZGL_CAMERA_HPP
|
||
|
#define EZGL_CAMERA_HPP
|
||
|
|
||
|
#include "ezgl/point.hpp"
|
||
|
#include "ezgl/rectangle.hpp"
|
||
|
|
||
|
namespace ezgl {
|
||
|
|
||
|
/**
|
||
|
* Manages the transformations between coordinate systems.
|
||
|
* Application code doesn't (and can't) call these functions; they are for ezgl internal use.
|
||
|
*
|
||
|
* The camera class manages transformations between a GTK widget, world, and "screen" coordinate system. A GTK widget
|
||
|
* has dimensions that change based on the user, and its aspect ratio may not match the world coordinate system. The
|
||
|
* camera maintains a "screen" within the widget that keeps the same aspect ratio as the world coordinate system,
|
||
|
* regardless of the dimensions of the widget.
|
||
|
*
|
||
|
* A camera object can only be created by an ezgl::canvas object, who has the responsibility of updating the camera with
|
||
|
* changes to the widget's dimensions. The only state that can be mutated outside the library is the camera's world
|
||
|
* coordinate system.
|
||
|
*/
|
||
|
class camera {
|
||
|
public:
|
||
|
/**
|
||
|
* Convert a point in world coordinates to screen coordinates.
|
||
|
*/
|
||
|
point2d world_to_screen(point2d world_coordinates) const;
|
||
|
|
||
|
/**
|
||
|
* Convert a point in widget coordinates to screen coordinates.
|
||
|
*/
|
||
|
point2d widget_to_screen(point2d widget_coordinates) const;
|
||
|
|
||
|
/**
|
||
|
* Convert a point in widget coordinates to world coordinates.
|
||
|
*/
|
||
|
point2d widget_to_world(point2d widget_coordinates) const;
|
||
|
|
||
|
/**
|
||
|
* Get the currently visible bounds of the world.
|
||
|
*/
|
||
|
rectangle get_world() const
|
||
|
{
|
||
|
return m_world;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the dimensions of the screen.
|
||
|
*/
|
||
|
rectangle get_screen() const
|
||
|
{
|
||
|
return m_screen;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the dimensions of the widget.
|
||
|
*/
|
||
|
rectangle get_widget() const
|
||
|
{
|
||
|
return m_widget;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the initial bounds of the world. Needed for zoom_fit
|
||
|
*/
|
||
|
rectangle get_initial_world() const
|
||
|
{
|
||
|
return m_initial_world;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the visible bounds of the world.
|
||
|
*
|
||
|
* Used in panning and zooming.
|
||
|
*/
|
||
|
void set_world(rectangle new_world);
|
||
|
|
||
|
/**
|
||
|
* Reset the world coordinates
|
||
|
*
|
||
|
* Used by change_canvas_world_coordinates().
|
||
|
*/
|
||
|
void reset_world(rectangle new_world);
|
||
|
|
||
|
/**
|
||
|
* Get the screen to world scaling factor.
|
||
|
*/
|
||
|
point2d get_world_scale_factor() const
|
||
|
{
|
||
|
return m_screen_to_world;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
// Only an ezgl::canvas can create a camera.
|
||
|
friend class canvas;
|
||
|
|
||
|
/**
|
||
|
* Create a camera.
|
||
|
*
|
||
|
* @param bounds The initial bounds of the coordinate system.
|
||
|
*/
|
||
|
explicit camera(rectangle bounds);
|
||
|
|
||
|
/**
|
||
|
* Update the dimensions of the widget.
|
||
|
*
|
||
|
* This will change the screen where the world is projected. The screen will maintain the aspect ratio of the world's
|
||
|
* coordinate system while being centered within the screen.
|
||
|
*
|
||
|
* @see canvas::configure_event
|
||
|
*/
|
||
|
void update_widget(int width, int height);
|
||
|
|
||
|
/**
|
||
|
* Update the scaling factors.
|
||
|
*/
|
||
|
void update_scale_factors();
|
||
|
|
||
|
private:
|
||
|
// The dimensions of the parent widget.
|
||
|
rectangle m_widget = {{0, 0}, 1.0, 1.0};
|
||
|
|
||
|
// The dimensions of the world (user-defined bounding box).
|
||
|
rectangle m_world;
|
||
|
|
||
|
// The dimensions of the screen, which may not match the widget.
|
||
|
rectangle m_screen;
|
||
|
|
||
|
// The dimensions of the initial world (user-defined bounding box). Needed for zoom_fit
|
||
|
rectangle m_initial_world;
|
||
|
|
||
|
// The x and y scaling factors.
|
||
|
point2d m_world_to_widget = {1.0, 1.0};
|
||
|
point2d m_widget_to_screen = {1.0, 1.0};
|
||
|
point2d m_screen_to_world = {1.0, 1.0};
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif //EZGL_CAMERA_HPP
|