/*
 *******************************************************************************
 *
 *  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    queryFill.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Point fill query
 * \version 2016-11-08/AW: Initial version
 *
 * This class can be used to set attributes of existing points to a (one)
 * specific value (e.g. set "riegl.selected" to "1" for all points). This
 * query is similar to using select() and update() except that it only accepts
 * one value per point attribute and this value is copied to all points.
 *
 * \see riegl::rdb::Pointcloud::fill()
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_QUERYFILL_H
#define RIEGL_RDB_POINTCLOUD_QUERYFILL_H

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

#include "riegl/rdb.h"

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

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

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

RDB_LIBRARY_API_BEGIN

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

//______________________________________________________________________________
/*!
 * \brief Constructor
 * \see   riegl::rdb::Pointcloud::fill()
 */
RDB_FUNCTION(rdb_pointcloud_query_fill_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
    RDBPointcloudQueryFill        **query       //!< [out] query handle
);

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

//______________________________________________________________________________
/*!
 * \brief Bind attribute buffer
 *
 * Use this function to define a source buffer for a point attribute.
 * Exactly one buffer can be defined for an attribute (i.e. only the
 * most recently defined buffer will be used).
 *
 * The buffer is expected to be 1*s*d bytes large, where
 * __s__ is the size of one element as defined by 'dataType' and
 * __d__ is the number of attribute dimensions (elements).
 *
 * \note This function just stores the buffer pointer. So make
 *       sure that the buffer remains valid until you call next().
 *
 * \note If the value contained in the buffer is equal to the value
 *       of a point in the database, then the point is not updated.
 *       So if the values of all points are equal to the given value,
 *       then no points are updated and the point attribute revision
 *       stored at the primary index node will not change.
 *
 * \see riegl::rdb::pointcloud::PointAttributes
 */
RDB_FUNCTION(rdb_pointcloud_query_fill_bind,
    RDBContext             *context,   //!< [in] library context
    RDBPointcloudQueryFill *query,     //!< [in] query handle
    RDBString               attribute, //!< [in] attribute name
    uint32_t                dataType,  //!< [in] buffer data type \see dataTypes.h
    const void             *buffer     //!< [in] buffer location
);

//______________________________________________________________________________
/*!
 * \brief Fill points
 *
 * Use this function to actually read the point attributes from
 * all defined buffers and update the points in the database.
 *
 * To process all points, you need to repeatedly call next() until it
 * returns 0 (zero, see example 7). 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.
 *
 * \note IEEE-754 "NaN" values contained in floating point source
 *       buffers are ignored and the attribute's default value is
 *       used instead. Furthermore IEEE-754 "Infinity" values will
 *       always cause next() to fail with error code 10414, i.e.
 *       riegl::rdb::Error::QueryAttributeValueOutOfRange.
 *
 * \note Since version 2.4.2, unit vector point attributes (e.g.
 *       "riegl.direction") are automatically normalized (divided
 *       by the vector length) on insertion. This is done for all
 *       point attributes that meet the following requirements:
 *       `length` is 3, `minimumValue` is -1, `maximumValue` is 1,
 *       `resolution` is not 1, `scaleFactor` is 1, `unitSymbol` is
 *       empty, `invalidValue` is undefined and `tags` contains the
 *       "direction" tag but not the "do-not-normalize" tag.
 *
 * \returns the number of points processed
 */
RDB_FUNCTION(rdb_pointcloud_query_fill_next,
    RDBContext             *context,                       //!< [in] library context
    RDBPointcloudQueryFill *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_fill_progress,
    RDBContext             *context, //!< [in] library context
    RDBPointcloudQueryFill *query,   //!< [in] query handle
    uint32_t               *progress //!< [out] progress [0..100%]
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_QUERYFILL_H
