IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 18317


Ignore:
Timestamp:
Jun 24, 2008, 4:15:46 PM (18 years ago)
Author:
Paul Price
Message:

Adding psTreeWithin and psTreeWithinAny

Location:
trunk/psLib/src/types
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/types/psTree.c

    r18174 r18317  
    294294}
    295295
    296 static void treePrint(FILE *fptr, const psTreeNode *node, int level)
     296// Print a representation of the node; called recursively
     297static void treeNodePrint(FILE *fptr,   // File pointer to which to print
     298                          const psTreeNode *node, // Node to print
     299                          int level     // Level at which to print
     300    )
    297301{
    298302    long index = node->index;           // Index of node
     
    322326    if (node->left && node->right) {
    323327        fprintf(fptr, " ==> %lf\n", tree->division[index]);
    324         treePrint(fptr, node->left, level);
    325         treePrint(fptr, node->right, level);
     328        treeNodePrint(fptr, node->left, level);
     329        treeNodePrint(fptr, node->right, level);
    326330        return;
    327331    }
     
    354358    PS_ASSERT_TREE_NON_NULL(tree, );
    355359
    356     treePrint(fptr, tree->root, 0);
     360    treeNodePrint(fptr, tree->root, 0);
    357361    return;
    358362}
     
    375379
    376380// Returns the square of the distance between a point on the tree and an aribtary point
    377 static inline double treeContentDistance(const psTree *tree, long index, const psVector *coords)
     381static inline double treeContentDistance(const psTree *tree, // Tree of interest
     382                                         long index, // Index of point on tree
     383                                         const psVector *coords // Coordinates of interest
     384    )
    378385{
    379386    int dim = tree->dim;                // Dimensionality
     
    418425
    419426// Returns whether the designated leaf contains an arbitrary point
    420 static inline bool treeBranchInside(const psTree *tree, long index, const psVector *coords)
     427static inline bool treeBranchInside(const psTree *tree, // Tree of interest
     428                                    long index, // Index of leaf on tree
     429                                    const psVector *coords // Coordinates of interest
     430    )
    421431{
    422432    int dim = tree->dim;                // Dimensionality
     
    433443
    434444// Search a leaf node for a closer point
    435 static inline void treeLeafSearch(long *bestIndex,
    436                                   double *bestDistance,
    437                                   const psTree *tree,
    438                                   const psTreeNode *leaf,
    439                                   const psVector *coords
    440                                   )
     445static inline void treeLeafSearchNearest(long *bestIndex, // Index of closest point
     446                                         double *bestDistance, // Distance to closest point
     447                                         const psTree *tree, // Tree of interest
     448                                         const psTreeNode *leaf, // Leaf to search
     449                                         const psVector *coords // Coordinates of interest
     450    )
    441451{
    442452    for (int i = 0; i < leaf->num; i++) {
     
    452462
    453463
    454 
    455464// Given an arbitrary point, return the index of the nearest neighbour
    456465long psTreeNearest(const psTree *tree, const psVector *coords)
     
    467476    long bestIndex = -1;                // Index of best point
    468477    double bestDistance = INFINITY;     // Distance to best point
    469     treeLeafSearch(&bestIndex, &bestDistance, tree, leaf, coords);
     478    treeLeafSearchNearest(&bestIndex, &bestDistance, tree, leaf, coords);
    470479
    471480    // Work up from the leaf containing the point of interest, and for each in turn, search down the other
     
    494503            }
    495504            // Leaf node
    496             treeLeafSearch(&bestIndex, &bestDistance, tree, node, coords);
     505            treeLeafSearchNearest(&bestIndex, &bestDistance, tree, node, coords);
    497506            work->data[workIndex] = NULL;
    498507            workIndex--;
     
    504513
    505514    return bestIndex;
     515}
     516
     517// Search a leaf node for points within radius squared
     518static inline long treeLeafSearchWithin(double radius2, // Radius squared to search
     519                                        const psTree *tree, // Tree of interest
     520                                        const psTreeNode *leaf, // Leaf to search
     521                                        const psVector *coords // Coordinates of interest
     522    )
     523{
     524    long num = 0;                       // Number within circle
     525    for (int i = 0; i < leaf->num; i++) {
     526        long index = leaf->contents[i]; // Index of point
     527        double distance = treeContentDistance(tree, index, coords); // Distance to point
     528        if (distance < radius2) {
     529            num++;
     530        }
     531    }
     532    return num;
     533}
     534
     535// Given an arbitrary point and a matching radius, return the number of points within that radius
     536long psTreeWithin(const psTree *tree, const psVector *coords, double radius)
     537{
     538#if 1 // Might be in a tight loop
     539    PS_ASSERT_TREE_NON_NULL(tree, -1);
     540    PS_ASSERT_VECTOR_NON_NULL(coords, -1);
     541    PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F64, -1);
     542    PS_ASSERT_VECTOR_SIZE(coords, (long)tree->dim, -1);
     543#endif
     544
     545    radius *= radius;                   // We work with the radius-squared
     546    long num = 0;                       // Number of points in circle
     547
     548    // This is essentially the same as psTreeNearest, except we're not allowed to prune
     549
     550    // Find the closest point in the leaf that contains the point of interest
     551    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
     552    num += treeLeafSearchWithin(radius, tree, leaf, coords);
     553
     554    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
     555    while (leaf->up) {
     556        psTreeNode *up = leaf->up;      // Parent node
     557
     558        long workIndex = 0;
     559        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
     560        while (workIndex >= 0) {
     561            psTreeNode *node = work->data[workIndex];
     562            if (node->left) {
     563                // Branch node
     564                work->data[workIndex] = node->right;
     565                work->data[++workIndex] = node->left;
     566                continue;
     567            }
     568            // Leaf node
     569            num += treeLeafSearchWithin(radius, tree, node, coords);
     570            work->data[workIndex] = NULL;
     571            workIndex--;
     572        }
     573
     574        leaf = up;
     575    }
     576    psFree(work);
     577
     578    return num;
     579}
     580
     581// Search a leaf node for any points within radius squared
     582static inline bool treeLeafSearchWithinAny(double radius2, // Radius squared to search
     583                                           const psTree *tree, // Tree of interest
     584                                           const psTreeNode *leaf, // Leaf to search
     585                                           const psVector *coords // Coordinates of interest
     586    )
     587{
     588    for (int i = 0; i < leaf->num; i++) {
     589        long index = leaf->contents[i]; // Index of point
     590        double distance = treeContentDistance(tree, index, coords); // Distance to point
     591        if (distance < radius2) {
     592            return true;
     593        }
     594    }
     595    return false;
     596}
     597
     598// Given an arbitrary point and a matching radius, return whether there are any points within that radius
     599bool psTreeWithinAny(const psTree *tree, const psVector *coords, double radius)
     600{
     601#if 1 // Might be in a tight loop
     602    PS_ASSERT_TREE_NON_NULL(tree, false);
     603    PS_ASSERT_VECTOR_NON_NULL(coords, false);
     604    PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F64, false);
     605    PS_ASSERT_VECTOR_SIZE(coords, (long)tree->dim, false);
     606#endif
     607
     608    radius *= radius;                   // We work with the radius-squared
     609
     610    // This is essentially the same as psTreeWithin, except we can bail as soon as we find something
     611
     612    // Find the closest point in the leaf that contains the point of interest
     613    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
     614    if (treeLeafSearchWithinAny(radius, tree, leaf, coords)) {
     615        return true;
     616    }
     617
     618    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
     619    while (leaf->up) {
     620        psTreeNode *up = leaf->up;      // Parent node
     621
     622        long workIndex = 0;
     623        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
     624        while (workIndex >= 0) {
     625            psTreeNode *node = work->data[workIndex];
     626            if (node->left) {
     627                // Branch node
     628                work->data[workIndex] = node->right;
     629                work->data[++workIndex] = node->left;
     630                continue;
     631            }
     632            // Leaf node
     633            if (treeLeafSearchWithinAny(radius, tree, node, coords)) {
     634                // Clear out the work queue
     635                memset(work->data, 0, (workIndex + 1) * sizeof(void));
     636                psFree(work);
     637                return true;
     638            }
     639            work->data[workIndex] = NULL;
     640            workIndex--;
     641        }
     642
     643        leaf = up;
     644    }
     645    psFree(work);
     646
     647    return false;
    506648}
    507649
  • trunk/psLib/src/types/psTree.h

    r18145 r18317  
    8989                   );
    9090
     91/// Return the number of points within some radius of given coordinates
     92long psTreeWithin(const psTree *tree,   ///< Tree
     93                  const psVector *coords, ///< Coordinates of interest
     94                  double radius         ///< Radius of interest
     95                  );
     96
     97/// Return whether there are any points within some radius of given coordinates
     98bool psTreeWithinAny(const psTree *tree,   ///< Tree
     99                     const psVector *coords, ///< Coordinates of interest
     100                     double radius         ///< Radius of interest
     101                     );
     102
    91103/// Return the coordinates of a point in the tree, specified by its index
    92104psVector *psTreeCoords(psVector *out,   ///< Output vector, or NULL
Note: See TracChangeset for help on using the changeset viewer.