C-Programmierung
kd-Tree Insertion
← kd-Tree Example | ● | kd-Tree Median Insertion →
Insertion of a Datum into a k-d-Tree:
Prerequisites:
- The class
Vector3D
is assumed to represent 3D vectors. - The
Vector3D
class supports + and - operators and the scalar product as denoted by the * operator. - The type
Datum
represents the data type of an item that is given at a specific point in 3D space.
Data structure definitions:
// definition of plane orientations
enum {
x_axis = 0,
y_axis = 1,
z_axis = 2
};
// definition of kdtree plane
typedef struct {
Vector3D point;
char orientation;
} Plane;
// node definition
typedef struct NodeStruct {
struct NodeStruct *leftSpace, *rightSpace;
Plane plane;
Datum item;
} Node;
enum {
x_axis = 0,
y_axis = 1,
z_axis = 2
};
// definition of kdtree plane
typedef struct {
Vector3D point;
char orientation;
} Plane;
// node definition
typedef struct NodeStruct {
struct NodeStruct *leftSpace, *rightSpace;
Plane plane;
Datum item;
} Node;
Helper functions:
// get normal of plane
// the normal points into the right half space
Vector3D getNormal(const Plane &plane)
{
Vector3D normal(0,0,0);
switch (plane.orientation)
{
case x_axis: normal = Vector3D(1,0,0); break;
case y_axis: normal = Vector3D(0,1,0); break;
case z_axis: normal = Vector3D(0,0,1); break;
}
return(normal);
}
// euclidean distance of two points
double getDistance(const Vector3D &point1, const Vector3D &point2)
{
Vector3D vec = point2-point1;
return(sqrt(vec * vec));
}
// signed distance of a point to a plane
// negative values indicate position in left half space
// positive values indicate position in right half space
double getDistance(const Vector3D &point, const Plane &plane)
{
Vector3D vec = point-plane.point;
Vector3D normal = getNormal(plane);
return(vec * normal);
}
// determines whether or not a point is in the left half space of a plane
bool isInLeftHalfSpace(const Vector3D &point, const Plane &plane)
{
double distance = getDistance(point, plane);
return(distance < 0.0);
}
// the normal points into the right half space
Vector3D getNormal(const Plane &plane)
{
Vector3D normal(0,0,0);
switch (plane.orientation)
{
case x_axis: normal = Vector3D(1,0,0); break;
case y_axis: normal = Vector3D(0,1,0); break;
case z_axis: normal = Vector3D(0,0,1); break;
}
return(normal);
}
// euclidean distance of two points
double getDistance(const Vector3D &point1, const Vector3D &point2)
{
Vector3D vec = point2-point1;
return(sqrt(vec * vec));
}
// signed distance of a point to a plane
// negative values indicate position in left half space
// positive values indicate position in right half space
double getDistance(const Vector3D &point, const Plane &plane)
{
Vector3D vec = point-plane.point;
Vector3D normal = getNormal(plane);
return(vec * normal);
}
// determines whether or not a point is in the left half space of a plane
bool isInLeftHalfSpace(const Vector3D &point, const Plane &plane)
{
double distance = getDistance(point, plane);
return(distance < 0.0);
}
Definition of kd-tree root:
// binary tree root
Node *root = NULL;
Node *root = NULL;
Iterative item insertion into a kd-tree at a specific point in 3D space:
// insert the Datum item
// at the position point
// below a specific node of a kd-tree
void insert(const Vector3D &point, const Datum &item, Node **node)
{
int level = 0;
while (*node!=NULL)
{
if (isInLeftHalfSpace(point, (*node)->plane))
node = &((*node)->leftSpace);
else
node = &((*node)->rightSpace);
level++;
}
*node = new Node;
(*node)->item = item;
(*node)->leftSpace = (*node)->rightSpace = NULL;
(*node)->plane.point = point;
(*node)->plane.orientation = level%3;
}
// insert the Datum item
// at the position point
// into a kd-tree given by its root node
void insert(const Vector3D &point, const Datum &item)
{
insert(point, item, &root);
}
// at the position point
// below a specific node of a kd-tree
void insert(const Vector3D &point, const Datum &item, Node **node)
{
int level = 0;
while (*node!=NULL)
{
if (isInLeftHalfSpace(point, (*node)->plane))
node = &((*node)->leftSpace);
else
node = &((*node)->rightSpace);
level++;
}
*node = new Node;
(*node)->item = item;
(*node)->leftSpace = (*node)->rightSpace = NULL;
(*node)->plane.point = point;
(*node)->plane.orientation = level%3;
}
// insert the Datum item
// at the position point
// into a kd-tree given by its root node
void insert(const Vector3D &point, const Datum &item)
{
insert(point, item, &root);
}
← kd-Tree Example | ● | kd-Tree Median Insertion →