// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example surface
    \title Surface Example
    \ingroup qtdatavisualization_examples
    \brief Using Q3DSurface in a widget application.

    The surface example shows how to make a simple 3D surface graph using Q3DSurface and
    combining the use of widgets for adjusting several adjustable qualities. This example
    demonstrates the following features:

    \list
        \li How to set up a basic QSurfaceDataProxy and set data for it.
        \li How to use QHeightMapSurfaceDataProxy for showing 3D height maps.
        \li Three different selection modes for studying the graph.
        \li Axis range usage for displaying selected portions of the graph.
        \li Changing theme.
        \li How to set a custom surface gradient.
    \endlist

    For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}.

    \image surface-example.png

    \include examples-run.qdocinc

    \section1 Creating the Application

    First, in \c main.cpp, we create a QApplication, instantiate Q3DSurface, and a window container
    for it:

    \snippet surface/main.cpp 0

    The call to QWidget::createWindowContainer is required, as all data visualization graph classes
    (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
    as a widget any other way.

    Then we'll create horizontal and vertical layouts. We'll add the graph with the container and
    the vertical layout into the horizontal one:

    \snippet surface/main.cpp 1

    The rest of the code in \c main.cpp is creating control widgets for features in Q3DSurface. We
    have separated code for changing these features into \c surfacegraph.cpp and only connect
    signals from widgets into methods in \c surfacegraph.cpp. Next chapter explains more
    about using Q3DSurface.

    \section1 Setting up Proxies and Data

    First we instantiate a new QSurfaceDataProxy and attach it to a new QSurface3DSeries:

    \snippet surface/surfacegraph.cpp 0

    Then we fill the proxy with a simple square root and sine wave data. This is done by
    creating a new \c QSurfaceDataArray instance and adding \c QSurfaceDataRow elements to it.
    The created \c QSurfaceDataArray is set to be the data array for the QSurfaceDataProxy.

    \snippet surface/surfacegraph.cpp 1

    The height map is created by instantiating a QHeightMapSurfaceDataProxy with
    a QImage containing the height data. The method QHeightMapSurfaceDataProxy::setValueRanges() is
    used to define the value range of the map. In our example the map is from imaginary position of
    34.0\unicode 0x00B0 N - 40.0\unicode 0x00B0 N and 18.0\unicode 0x00B0 E - 24.0\unicode 0x00B0 E.
    These values are used to show and position the map to the axis.

    \snippet surface/surfacegraph.cpp 2

    For demonstrating different proxies this example has two radio buttons which
    the user can use to switch between the series. When the user selects the
    \c {Sqrt & Sin} radio button, the selected series is activated with the following
    code. First we set the decorative issues like enable the grid for the surface and
    select the flat shading mode. Next lines define the axis label format and value
    ranges. Automatic label rotation is set to improve label readability at low camera angles.
    Finally we make sure the correct series is added to the graph:

    \snippet surface/surfacegraph.cpp 3

    When the \c{Height Map} radio button is activated, the following code sets the correct series active.
    The axis label format is set to show N and E letters and ranges are set to the imaginary coordinates.
    Auto adjusting Y-axis range is fine for our height map surface, so we ensure it is set.

    \snippet surface/surfacegraph.cpp 4

    \section1 Selection Modes

    Q3Dsurface supports three different selection modes. These are demonstrated in the
    example with radio buttons, which the user can use to activate a suitable selection mode.
    The following inline methods are connected to radio buttons to activate the selected mode.

    \snippet surface/surfacegraph.h 0

    \section1 Axis Ranges for Studying the Graph

    The example has four slider controls for adjusting the min and max values for X and Z
    axis. When selecting the proxy these sliders are adjusted so that one step on the slider
    moves the range by one segment step:

    \snippet surface/surfacegraph.cpp 8

    The ranges are set for the axes like this:

    \snippet surface/surfacegraph.cpp 5

    \section1 Themes

    Q3DSurface supports all the themes Qt Data Visualization has. The example has a pull
    down menu for selecting the theme. The following method is connected to the
    menu to activate the selected theme. The theme type is changed to another predefined theme,
    which overwrites all theme properties to predefined values:

    \snippet surface/surfacegraph.cpp 6

    \section1 Custom Surface Gradients

    The example demonstrates the custom surface gradients with two push buttons. The gradient
    can be defined with QLinearGradient where the desired colors are set to positions. The following
    code shows how to create an example gradient and set it to the series. Note that you also need
    to change the color style to Q3DTheme::ColorStyleRangeGradient to actually use the gradient.

    \snippet surface/surfacegraph.cpp 7
*/
