//================================================================
// E3D
//
// KD tree header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Jun-17 18:01:25
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_KDTree_h
#define _E3D_KDTree_h

#include <assert.h>
#include <unistd.h>
#include <stdint.h>    // For uint32_t etc. for E_Random

#ifndef _EClass_h
#include <EClass.h>
#endif

#ifndef _EThreads_h
#include <EThreads.h>
#endif

#ifndef _E3D_Node_h
#include <E3D/Node.h>
#endif

#ifndef _E3D_Camera_h
#include <E3D/Camera.h>
#endif

#ifndef _E3D_Window_h
#include <E3D/UI/Window.h>
#endif

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif





//------------------------------------------------
// Fast nearest neighbour query with KD-trees
//------------------------------------------------
#define E3dKDTreePointCore\
	union { E3dCoord3	Position;E3dCoordinate	Position3[3]; };\
	unsigned short  Plane        /* For the kd-tree  */

typedef struct
{
	E3dKDTreePointCore;
} E3dKDTreePoint;

typedef struct _E3dNearestKDTreePointList
{
	const E3dKDTreePoint**  Points;EIndex  Points_Count;    // This is an array of pointers, so we don't need to specialize to RGBPhoton, SpectralPhoton etc.
	float*                  DistanceSq;                     // Squared distance array
	EIndex                  HeapNMax;                       // Heap maximum size
	E3dCoordinate           QueryPosition[3];
	short                   HaveHeap;                       // Is the heap built?
} E3dNearestKDTreePointList;


#define E3dKDTREE_POINTMAP_MAX_THREAD_DEPTH  5

typedef struct E3dKDTreePointMap_S  E3dKDTreePointMap;

typedef struct
{
	int   NextThreadIndex;
} E3dKDTreePointMapBalancing;

typedef struct
{
	EThreadCore;

	E3dKDTreePointMap*  PointMap;
	E3dBBox             BBox;
	E3dKDTreePoint**    PBal;
	E3dKDTreePoint**    POrg;
	int                 Index;
	int                 Start, End;
} E3dKDPtreePointMapBalancingThread;


#define E3dKDTreePointMapCore\
	E3dKDTreePoint*  Points;       /* Actual point array used after _PhotonmapBalance() call                                    */\
	E3dKDTreePoint*  TmpPoints;    /* Temporary point array if _PhotonmapBalance() is called, this array is freed and not used  */\
\
	EIndex      Points_Count, Points_CountAllocated;  /* Number of points                           */\
	int         BytesPerPoint;\
	E3dBBox     BBox;                                 /* Bounding box                               */\
	ETime       BalancingStartMicroseconds;\
	E3dKDTreePointMapBalancing  Balancing;\
	EThreadSet  ThreadSet;                            /* For balancing the KDTree                   */\
	EBool       Balanced;                             /* Is KDTreePoints array a balanced kd-tree?  */

struct E3dKDTreePointMap_S
{
	E3dKDTreePointMapCore;
};



// Points arranged in a KD-tree, for fast nearest-neighbour queries
//
extern E3dKDTreePointMap*          E3dKDTreePointMap_Init(E3dKDTreePointMap* PPointMap, const EIndex PBytesPerPoint);
extern E3dKDTreePointMap*          E3dKDTreePointMap_New(const EIndex PStructSize, const EIndex PBytesPerPoint);
extern void                        E3dKDTreePointMap_FreeContents(E3dKDTreePointMap* PPointMap);

extern E3dNearestKDTreePointList*  E3dNearestKDTreePoints_New(const int PMaxCount);
extern void                        E3dNearestKDTreePoints_Free(E3dNearestKDTreePointList* PNearestPhotons);

extern EBool                       E3dKDTreePointMap_BuildTree(E3dKDTreePointMap* PPointMap,  XeProgressIndicator* PProgressIndicator, void (*PAbortCallbackFunc)(EPointer PClientData), const EPointer PAbortCallbackClientData);

extern void                        E3dNearestPoints_Jensen_iterative(const E3dKDTreePointMap* PPointMap, E3dNearestKDTreePointList* PNearestPoints, const E3dCoordinate PSearchRadiusSq);





#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _E3D_KDTree_h
