/*
 *******************************************************************************
 *
 *  Copyright 2026 RIEGL Laser Measurement Systems
 *
 *  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.
 *
 *  SPDX-License-Identifier: Apache-2.0
 *
 *******************************************************************************
 */
/*!
 *******************************************************************************
 *
 * \file    queryInvert.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Point invert query
 * \version 2016-11-14/AW: Initial version
 *
 * This class can be used to invert point attributes for all points or just
 * those that meet some filter criteria. Calculating the inverted value (v')
 * from the original value (v) and the attribute limits (min and max) is done
 * as follows:
 *
 *   v' = max - (v - min)"
 *
 * For dynamic point attributes (bits/flags) this simply means to flip the
 * bit (e.g. set "riegl.selected" to 1 if it was 0, otherwise set it to 0).
 *
 * This query is similar to using select() and update() and manually inverting
 * the point attributes except that it might be faster (less processing time)
 * and easier to use.
 *
 * \see riegl::rdb::Pointcloud::invert()
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_QUERYINVERT_H
#define RIEGL_RDB_POINTCLOUD_QUERYINVERT_H

//---< INCLUDES >---------------------------------------------------------------

#include "riegl/rdb.h"

//---< TYPE DEFINITIONS >-------------------------------------------------------

typedef struct RDBPointcloudQueryInvert RDBPointcloudQueryInvert; // forward declaration of implementation details

//---< FUNCTIONS >--------------------------------------------------------------

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Constructor
 * \see   riegl::rdb::Pointcloud::invert()
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_new,
    RDBContext                *context,    //!< [in] library context
    RDBPointcloud             *pointcloud, //!< [in] point cloud
    RDBPointcloudGraphNodeID   node,       //!< [in] index node ID
    RDBString                  filter,     //!< [in] filter string
    RDBPointcloudQueryInvert **query       //!< [out] query handle
);

//______________________________________________________________________________
/*!
 * \brief Constructor
 * \see   riegl::rdb::Pointcloud::invert()
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_nodes_new,
    RDBContext                     *context,    //!< [in] library context
    RDBPointcloud                  *pointcloud, //!< [in] point cloud
    const RDBPointcloudGraphNodeID *nodes,      //!< [in] pointer to first element of node ID array
    uint32_t                        count,      //!< [in] number of elements in node ID array
    RDBString                       filter,     //!< [in] filter string
    RDBPointcloudQueryInvert      **query       //!< [out] query handle
);

//______________________________________________________________________________
/*!
 * \brief Destroy query instance
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_delete,
    RDBContext                *context, //!< [in] library context
    RDBPointcloudQueryInvert **query    //!< [in] query handle
);

//______________________________________________________________________________
/*!
 * \brief Define attribute
 *
 * Use this function to define the point attribute to be inverted. To
 * define multiple attributes, simply call this function once for each.
 *
 * \note Point attributes having a length greater than 1 (vectors like
 *       the true color attribute "riegl.rgba") can only be inverted
 *       as a whole, i.e. you cannot invert particular vector elements
 *       (e.g. using "riegl.rgba[0]" will not work).
 *
 * \see riegl::rdb::pointcloud::PointAttributes
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_attribute,
    RDBContext               *context,  //!< [in] library context
    RDBPointcloudQueryInvert *query,    //!< [in] query handle
    RDBString                 attribute //!< [in] attribute name
);

//______________________________________________________________________________
/*!
 * \brief Invert points
 *
 * Use this function to actually invert the point attribute(s).
 *
 * To process all points, you need to repeatedly call next() until it
 * returns 0 (zero, see example 8). The number of points to process in
 * one step is defined by 'count'. Please note that the actual number
 * of processed points may be slightly different. To cancel processing
 * just stop calling next() and cancel (rollback) the transaction.
 *
 * \returns the number of points processed
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_next,
    RDBContext               *context,                       //!< [in] library context
    RDBPointcloudQueryInvert *query,                         //!< [in] query handle
    uint32_t                  count,                         //!< [in] number of points to process
    uint32_t                 *processed RDB_DEFAULT_VALUE(0) //!< [out] number of processed points (optional)
);

//______________________________________________________________________________
/*!
 * \brief Progress
 *
 * This function returns a coarse progress information in percent (0..100%).
 * Since the total number of returned points is not known in advance, this
 * value just reflects the progress of the (internal) index traversal.
 */
RDB_FUNCTION(rdb_pointcloud_query_invert_progress,
    RDBContext               *context, //!< [in] library context
    RDBPointcloudQueryInvert *query,   //!< [in] query handle
    uint32_t                 *progress //!< [out] progress [0..100%]
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_QUERYINVERT_H
