Skip to main content
Engineering LibreTexts

10.8: Understanding a View’s Camera

  • Page ID
    45915
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    A view’s camera represents the point of view from which the space is actually viewed.

    When translateBy: or translateTo: messages are sent to a view, what actually happens is that its camera moves instead of the view itself. The position of the camera is given by the position message. The camera’s position is set manually sending the same messages to the camera, translateBy: or translateTo:, but using negated values as parameters. This means that if the view has to be translated by 10 pixels horizontally and vertically, we can do it like this:

    view translateBy: 10@10
    

    Or translate the view’s camera by hand:

    view camera translateBy: (-10)@(-10)
    

    A camera has an extent, which is what we are seeing, and a real extent, which represents the far extent. The extent of the view’s camera affects the way a view is drawn in a canvas. When rendering a view, each point, rectangle or other shape that needs to be drawn will be plotted according to the camera’s extent. This is done by transforming each absolute position in virtual points relative to the camera’s vision. For example, when zooming in on a view, the content on the extent is “stretched” to fill the real extent, which makes objects bigger. The extent and the real extent of the camera are modified using extent: and realExtent: accessors, respectively. The camera also stores the window size of the visualization.

    The camera has an altitude from the view, which is computed using the extent. The smaller the extent is, the lower the camera is located, and vice-versa. The altitude of the camera can be set by sending the altitude: message using a number as parameter. A camera cannot be rotated, only translated. This also means that the camera is always perpendicularly looking at the view.

    Figure \(\PageIndex{1}\) illustrates what we have just mentioned. It indicates all of the information regarding the view for which it is associated. We also see that the visible part of the visualization is given by the camera’s extent.

    A camera diagram and extent example.
    Figure \(\PageIndex{1}\): Components of a view's camera.

    The ROZoomMove interaction affects the extent of the camera. This interaction modifies the camera’s position and extends it to fit a desired rectangle. For example, when zooming in to focus on a particular element of the view, the ROZoomMove translates and extends the camera to fit that element’s bounds. This movement is simulated by changing the camera’s altitude.

    Using the camera to build a minimap for navigation. The interaction and animation model offered by Roassal support complex behavior. Consider the following code:

    | view eltos |
    view := ROView new.
    view @ RODraggable .
    view on: ROMouseRightClick do: [ :event |
        ROZoomInMove new on: view ].
    view on: ROMouseLeftClick do: [ :event |
        ROZoomOutMove new on: view ].
    elts := ROElement spritesOn: (1 to: 400).
    elts do: [ :el | el + ROLabel ].
    view addAll: elts.
    ROGridLayout new on: view elements.
        "Mini map opens by pressing m"
    view @ ROMiniMap.
    view open.
    

    It opens a view with 400 labelled elements and elements are ordered using a grid layout. Pressing the left mouse button zooms in the view. The right mouse button zooms out. Pressing the m key will open a minimap. This feature is enabled using the ROMiniMap interaction.

    The ROMiniMap opens a new window that gives a complete vision of a visualization. It also eases the navigation by using the original view’s camera.

    The minimap is composed of a smaller version of the visualization and a lupa (magnifying glass), which represents the current visible part of the main view’s window.

    Coming back to our main example, the interaction is simply added by sending the @ROMiniMap message to a view and pressing “m” to open it (Figure \(\PageIndex{2}\)).

    ROMiniMap in the Collection Hierarchy example.
    Figure \(\PageIndex{2}\): ROMiniMap applied to the Collection Hierarchy example.

    The smaller version of the view is displayed using ROMiniMapDisplayer, a particular shape, subclass of ROViewDisplayer. ROViewDisplayer is a shape that displays a view on an element (it is essentially used for the popup view). The difference between both is that ROMiniMapDisplayer uses its own camera, which has a different extent than the view’s camera. This allows one to see the same view with different sizes.

    The magnifier size represents the visible part of the window and its position is related to the view’s camera position. When the view is translated to a point, the magnifier follows it by changing its position: the point representing the camera position is translated to a point on the ROMiniMapDisplayer camera extent. And when the view is zoomed in or zoomed out the extent of the camera is changed, increasing or decreasing the magnifier’s size.


    This page titled 10.8: Understanding a View’s Camera is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.