{*
 *******************************************************************************
 *
 *  Copyright 2025 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    riegl.rdb.pointcloud.graphNode.pas
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Index graph node (Pascal wrapper code)
 * \version 2015-10-14/AW: Initial version
 *
 *******************************************************************************
 *}

unit riegl.rdb.pointcloud.graphNode;

{******************************************************************************}
{***} INTERFACE {**************************************************************}
{******************************************************************************}

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

uses
  Contnrs,
  Classes,
  riegl.rdb,
  riegl.rdb.context,
  riegl.rdb.pointcloud.dataTypes,
  riegl.rdb.pointcloud.transaction;

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

type
  TRDBPointcloudGraphNodeID         =  TRDBUInt32;
  PRDBPointcloudGraphNodeID         = ^TRDBPointcloudGraphNodeID;
  TRDBPointcloudGraphNodeIDArray    =  array of TRDBPointcloudGraphNodeID;
  PRDBPointcloudGraphNodeIDArray    = ^TRDBPointcloudGraphNodeIDArray;
  TRDBPointcloudGraphNodeChildCount =  TRDBUInt32;
  TRDBPointcloudGraphNodePointCount =  TRDBUInt64;
  TRDBPointcloudGraphNodeHandle     =  System.Pointer;

//---< CLASS TRDBPointcloudGraphNode >------------------------------------------
{*!
 * \brief Graph Node
 *
 * This class represents an index graph node. The index structure is
 * used to organize the point cloud and consists of at least one node.
 *
 * The index space is given by the primary point attribute defined
 * during point cloud database creation (see class CreateSettings).
 *
 * Each graph node covers a certain range of the index space and
 * has a number of sub-nodes (aka. "child nodes"). All child nodes
 * lie within the range of the parent node whereas they are usually
 * smaller. A node without child nodes is called a leaf node. Note
 * that any nodes may overlap in index space as well as all other
 * point dimensions (attributes).
 *
 * This documentation uses the term "branch" for a node and all
 * children and grandchildren up to and including the leaf nodes.
 *
 * \see riegl::rdb::Pointcloud::stat()
 *}
type
  TRDBPointcloudGraphNode = class(System.TObject)
  private
    FId              : TRDBPointcloudGraphNodeID;
    FRevision        : TRDBPointcloudTransactionID;
    FPointCountTotal : TRDBPointcloudGraphNodePointCount;
    FPointCountNode  : TRDBPointcloudGraphNodePointCount;
    FChildren        : Contnrs.TObjectList;

    function  GetChildCount : TRDBPointcloudGraphNodeChildCount;
    procedure SetChildCount(Value : TRDBPointcloudGraphNodeChildCount);

    function  GetChild(Index : Integer) : TRDBPointcloudGraphNode;
    procedure SetChild(Index : Integer; Value : TRDBPointcloudGraphNode);

  public
    constructor Create;  reintroduce;
    destructor  Destroy; override;

  public
    property Id                        : TRDBPointcloudGraphNodeID         read FId              write FId;              //!< unique node identifier
    property Revision                  : TRDBPointcloudTransactionID       read FRevision        write FRevision;        //!< ID of last transaction that has modified any attribute of this branch
    property PointCountTotal           : TRDBPointcloudGraphNodePointCount read FPointCountTotal write FPointCountTotal; //!< total number of points in all leaf nodes of the branch
    property PointCountNode            : TRDBPointcloudGraphNodePointCount read FPointCountNode  write FPointCountNode;  //!< number of points in this node (see notes about LOD)
    property ChildCount                : TRDBPointcloudGraphNodeChildCount read GetChildCount    write SetChildCount;    //!< number of child nodes (without grandchildren)
    property Children[Index : Integer] : TRDBPointcloudGraphNode           read GetChild         write SetChild;         //!< list of child nodes
  end;

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

//______________________________________________________________________________
{*!
 * \brief Create graph node
 *}
function rdb_pointcloud_graph_node_new(
  Context  : TRDBContextHandle;            //!< [in] library context
  var Node : TRDBPointcloudGraphNodeHandle //!< [out] graph node
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Delete graph node
 *}
function rdb_pointcloud_graph_node_delete(
  Context  : TRDBContextHandle;            //!< [in] library context
  var Node : TRDBPointcloudGraphNodeHandle //!< [out] graph node
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

{******************************************************************************}
{***} IMPLEMENTATION {*********************************************************}
{******************************************************************************}

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

uses
  SysUtils;

//---< TRDBPointcloudGraphNode::PUBLIC >----------------------------------------

constructor TRDBPointcloudGraphNode.Create;
begin
  inherited Create;
  FId              := 0;
  FRevision        := 0;
  FPointCountTotal := 0;
  FPointCountNode  := 0;
  FChildren        := Contnrs.TObjectList.Create(TRUE);
end; // Create()

destructor TRDBPointcloudGraphNode.Destroy;
begin
  SysUtils.FreeAndNil(FChildren);
  inherited;
end; // Destroy()

//---< TRDBPointcloudGraphNode::PRIVATE >---------------------------------------

function TRDBPointcloudGraphNode.GetChildCount : TRDBPointcloudGraphNodeChildCount;
begin
  Result := FChildren.Count;
end; // GetChildCount()

procedure TRDBPointcloudGraphNode.SetChildCount(Value : TRDBPointcloudGraphNodeChildCount);
begin
  FChildren.Count := Value; // shorten: delete objects, lengthen: do NOT create objects!
end; // SetChildCount()

function TRDBPointcloudGraphNode.GetChild(Index : Integer) : TRDBPointcloudGraphNode;
begin
  if (FChildren[Index] = nil) then FChildren[Index] := TRDBPointcloudGraphNode.Create;
  Result := FChildren[Index] as TRDBPointcloudGraphNode;
end; // GetChild()

procedure TRDBPointcloudGraphNode.SetChild(Index : Integer; Value : TRDBPointcloudGraphNode);
begin
  FChildren[Index] := Value; // delete old and store new TRDBPointcloudGraphNode instance
end; // SetChild()

end.
