IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 25256 for trunk/psLib


Ignore:
Timestamp:
Sep 2, 2009, 2:36:52 PM (17 years ago)
Author:
Paul Price
Message:

Merging branches/pap_mops into trunk. ppMops now merges multiple skycells, and these get published for MOPS as a single file per exposure. Tested and works.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/psLib/src/sys/psType.h

    r21183 r25256  
    141141} psDataType;
    142142
    143 // macros to abstract the generic mask type : these values must be consistent 
     143// macros to abstract the generic mask type : these values must be consistent
    144144#define PS_TYPE_MASK PS_TYPE_U8        /**< the psElemType to use for mask image */
    145145#define PS_TYPE_MASK_DATA U8           /**< the data member to use for mask image */
     
    152152// alternate versions if needed
    153153// #define PS_NOT_MASK(A)(UINT16_MAX-(A))
    154 // #define PS_NOT_MASK(A)(UINT32_MAX-(A)) 
     154// #define PS_NOT_MASK(A)(UINT32_MAX-(A))
    155155// #define PS_NOT_MASK(A)(UINT64_MAX-(A))
    156156
    157 // macros to abstract the vector mask type : these values must be consistent 
     157// macros to abstract the vector mask type : these values must be consistent
    158158#define PS_TYPE_VECTOR_MASK PS_TYPE_U8        /**< the psElemType to use for mask image */
    159159#define PS_TYPE_VECTOR_MASK_DATA U8           /**< the data member to use for mask image */
     
    161161#define PS_MIN_VECTOR_MASK_TYPE 0             /**< minimum valid Vector Mask value */
    162162#define PS_MAX_VECTOR_MASK_TYPE UINT8_MAX     /**< maximum valid Vector Mask value */
    163 typedef psU8 psVectorMaskType;                    ///< the C datatype for a mask image
     163typedef psU8 psVectorMaskType;                    ///< the C datatype for a mask image
    164164#define PS_NOT_VECTOR_MASK(A)(UINT8_MAX-(A))
    165165
    166 // macros to abstract the image mask type : these values must be consistent 
    167 #define PS_TYPE_IMAGE_MASK PS_TYPE_U16       /**< the psElemType to use for mask image */
    168 #define PS_TYPE_IMAGE_MASK_DATA U16          /**< the data member to use for mask image */
    169 #define PS_TYPE_IMAGE_MASK_NAME "psU16"      /**< the data type for mask as a string */
     166// macros to abstract the image mask type : these values must be consistent
     167#define PS_TYPE_IMAGE_MASK PS_TYPE_U16       /**< the psElemType to use for mask image */
     168#define PS_TYPE_IMAGE_MASK_DATA U16          /**< the data member to use for mask image */
     169#define PS_TYPE_IMAGE_MASK_NAME "psU16"      /**< the data type for mask as a string */
    170170#define PS_MIN_IMAGE_MASK_TYPE 0             /**< minimum valid Image Mask value */
    171171#define PS_MAX_IMAGE_MASK_TYPE UINT16_MAX    /**< maximum valid Image Mask value */
     
    246246};
    247247
    248 /// Macro to get the bad pixel reason code (stored as part of mask value)
    249 #define PS_BADPIXEL_BITMASK 0x0f
    250 #define PS_GET_BADPIXEL(maskValue) (maskValue & PS_BADPIXEL_BITMASK)
    251 
    252 #define PS_IS_BADPIXEL(maskValue) (PS_GET_BADPIXEL(maskValue) != 0)
    253 
    254 /// Macro to apply a bad pixel reason code to mask image
    255 #define PS_SET_BADPIXEL(maskValue, reasonCode) \
    256 { \
    257     maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \
    258 }
    259 
    260248/// Macro to determine if the psElemType is an integer.
    261249#define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100)
  • trunk/psLib/src/types/psTree.c

    r18344 r25256  
    1414#include "psTree.h"
    1515
     16//#define INPUT_CHECK                   // Check inputs for functions that may be in a tight loop?
     17
    1618
    1719// XXX Upgrades:
     
    8486}
    8587
    86 psTree *psTreeAlloc(int dim, int maxLeafContents, long numNodes)
     88psTree *psTreeAlloc(int dim, int maxLeafContents, psTreeType type, long numNodes)
    8789{
    8890    psAssert(dim > 0, "Dimensionality (%d) must be positive", dim);
     
    9597    tree->dim = dim;
    9698    tree->maxLeafContents = maxLeafContents;
     99    tree->type = type;
    97100
    98101    tree->numNodes = numNodes;
     
    115118
    116119
    117 psTree *psTreePlant(int dim, int maxLeafContents, ...)
     120psTree *psTreePlant(int dim, int maxLeafContents, psTreeType type, ...)
    118121{
    119122    PS_ASSERT_INT_POSITIVE(dim, NULL);
     
    122125    // Parse coordinate list
    123126    va_list args;                       // Variable argument list
    124     va_start(args, maxLeafContents);
     127    va_start(args, type);
    125128    psArray *coords = psArrayAlloc(dim); // Array of coordinates
    126129    long numData = 0;                   // Number of data points
     
    145148        long pow2;                      // Smallest power of two >= numData
    146149        for (pow2 = 1; pow2 < numData; pow2 <<= 1);
    147         numNodes = PS_MIN(pow2 - 1, 2 * numData - pow2 / 2 - 1);
    148     }
    149 
    150     psTree *tree = psTreeAlloc(dim, maxLeafContents, numNodes);
     150        numNodes = PS_MAX(PS_MIN(pow2 - 1, 2 * numData - pow2 / 2 - 1), 1);
     151    }
     152
     153    psTree *tree = psTreeAlloc(dim, maxLeafContents, type, numNodes);
    151154    tree->data = psTreeCoordArrayAlloc(numData, dim);
    152155    tree->numData = numData;
     
    199202    }
    200203
     204    if (numData <= maxLeafContents) {
     205        // Don't need to do any more work
     206        return tree;
     207    }
     208
    201209    psArray *work = psArrayAlloc(numNodes); // Work queue
    202210    work->data[0] = root;
     
    365373psTreeNode *psTreeLeaf(const psTree *tree, const psVector *coords)
    366374{
    367 #if 1 // Might be in a tight loop
     375#ifdef INPUT_CHECK // Might be in a tight loop
    368376    PS_ASSERT_TREE_NON_NULL(tree, NULL);
    369377    PS_ASSERT_VECTOR_NON_NULL(coords, NULL);
     
    403411{
    404412    int dim = tree->dim;                // Dimensionality
    405     switch (dim) {
    406       case 2:
    407         return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
    408             PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]);
    409       case 3:
    410         return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
    411             PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]) +
    412             PS_SQR(coords->data.F64[2] - tree->data->F64[index][2]);
    413       default: {
    414           double distance2 = 0.0;             // Distance of interest
    415           for (int i = 0; i < dim; i++) {
    416               distance2 += PS_SQR(coords->data.F64[i] - tree->data->F64[index][i]);
     413    switch (tree->type) {
     414      case PS_TREE_EUCLIDEAN:
     415        switch (dim) {
     416          case 2:
     417            return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
     418                PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]);
     419          case 3:
     420            return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
     421                PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]) +
     422                PS_SQR(coords->data.F64[2] - tree->data->F64[index][2]);
     423          default: {
     424              double distance2 = 0.0;             // Distance of interest
     425              for (int i = 0; i < dim; i++) {
     426                  distance2 += PS_SQR(coords->data.F64[i] - tree->data->F64[index][i]);
     427              }
     428              return distance2;
    417429          }
    418           return distance2;
    419       }
    420     }
     430        }
     431        break;
     432      case PS_TREE_SPHERICAL:
     433        switch (dim) {
     434          case 2: {
     435              // Haversine formula
     436              double dphi = coords->data.F64[1] - tree->data->F64[index][1];
     437              double sindphi = sin(dphi / 2.0);
     438              double dlambda = coords->data.F64[0] - tree->data->F64[index][0];
     439              double sindlambda = sin(dlambda / 2.0);
     440              return PS_SQR(sindphi) +
     441                  cos(coords->data.F64[1]) * cos(tree->data->F64[index][1]) * PS_SQR(sindlambda);
     442          }
     443          default:
     444            psAbort("Spherical distances not supported for more than 2 dimensions");
     445        }
     446      default:
     447        psAbort("Unrecognised type: %x", tree->type);
     448    }
     449
    421450    return NAN;
    422451}
     
    430459        double minDiff = tree->min->F64[index][i] - coords->data.F64[i];
    431460        if (minDiff > 0) {
    432             distance += PS_SQR(minDiff);
     461            switch (tree->type) {
     462              case PS_TREE_EUCLIDEAN:
     463                distance += PS_SQR(minDiff);
     464                break;
     465              case PS_TREE_SPHERICAL: {
     466                  double sinDiff = sin(minDiff / 2.0);
     467                  distance += PS_SQR(sinDiff);
     468                  break;
     469              }
     470              default:
     471                psAbort("Unrecognised type: %x", tree->type);
     472            }
    433473            continue;
    434474        }
    435475        double maxDiff = coords->data.F64[i] - tree->max->F64[index][i];
    436476        if (maxDiff > 0) {
    437             distance += PS_SQR(maxDiff);
     477            switch (tree->type) {
     478              case PS_TREE_EUCLIDEAN:
     479                distance += PS_SQR(maxDiff);
     480                break;
     481              case PS_TREE_SPHERICAL: {
     482                  double sinDiff = sin(maxDiff / 2.0);
     483                  distance += PS_SQR(sinDiff);
     484                  break;
     485              }
     486              default:
     487                psAbort("Unrecognised type: %x", tree->type);
     488            }
    438489            continue;
    439490        }
     
    479530}
    480531
    481 // Return the index of the nearest neighbour to given coordinates, within some radius
     532// Return the index of the nearest neighbour to given coordinates, within some distance measure
    482533// This is the engine for psTreeNearest() and psTreeNearestWithin()
    483534static inline long treeNearestWithin(const psTree *tree, // Tree
    484535                                     const psVector *coordinates, // Coordinates of interest
    485                                      double bestDistance // Distance (radius-squared) to best point
     536                                     double bestDistance // Distance measure to best point
    486537    )
    487538{
    488 #if 1 // Might be in a tight loop
     539#ifdef INPUT_CHECK // Might be in a tight loop
    489540    PS_ASSERT_TREE_NON_NULL(tree, -1);
    490541    PS_ASSERT_VECTOR_NON_NULL(coordinates, -1);
     
    545596
    546597
     598// Convert a radius to our internal "distance measure"
     599// Often, we're given a search radius, but for efficiency reasons, we don't use that internally.
     600static double treeRadiusToDistance(const psTree *tree, double radius)
     601{
     602    switch (tree->type) {
     603      case PS_TREE_EUCLIDEAN:
     604        // Using the square of the distance as the distance measure
     605        return PS_SQR(radius);
     606      case PS_TREE_SPHERICAL: {
     607          // Using a rearrangement of the Haversine formula
     608          double sindist = sin(radius / 2.0);
     609          return PS_SQR(sindist);
     610      }
     611      default:
     612        psAbort("Unrecognised type: %x", tree->type);
     613    }
     614}
     615
     616
    547617long psTreeNearestWithin(const psTree *tree, const psVector *coords, double radius)
    548618{
    549     return treeNearestWithin(tree, coords, PS_SQR(radius));
    550 }
    551 
    552 
    553 // Search a leaf node for points within radius squared
    554 static inline long treeLeafSearchWithin(double radius2, // Radius squared to search
     619    return treeNearestWithin(tree, coords, treeRadiusToDistance(tree, radius));
     620}
     621
     622
     623// Search a leaf node for points within distance
     624static inline long treeLeafSearchWithin(double distance, // Distance to search
    555625                                        const psTree *tree, // Tree of interest
    556626                                        const psTreeNode *leaf, // Leaf to search
     
    561631    for (int i = 0; i < leaf->num; i++) {
    562632        long index = leaf->contents[i]; // Index of point
    563         double distance = treeContentDistance(tree, index, coords); // Distance to point
    564         if (distance < radius2) {
     633        if (treeContentDistance(tree, index, coords) < distance) {
    565634            num++;
    566635        }
     
    572641long psTreeWithin(const psTree *tree, const psVector *coordinates, double radius)
    573642{
    574 #if 1 // Might be in a tight loop
     643#ifdef INPUT_CHECK // Might be in a tight loop
    575644    PS_ASSERT_TREE_NON_NULL(tree, -1);
    576645    PS_ASSERT_VECTOR_NON_NULL(coordinates, -1);
     
    581650                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
    582651
    583     radius *= radius;                   // We work with the radius-squared
     652    double distance = treeRadiusToDistance(tree, radius); // Distance measure
    584653    long num = 0;                       // Number of points in circle
    585654
     
    588657    // Find the closest point in the leaf that contains the point of interest
    589658    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
    590     num += treeLeafSearchWithin(radius, tree, leaf, coords);
     659    num += treeLeafSearchWithin(distance, tree, leaf, coords);
    591660
    592661    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
     
    605674            }
    606675            // Leaf node
    607             num += treeLeafSearchWithin(radius, tree, node, coords);
     676            num += treeLeafSearchWithin(distance, tree, node, coords);
    608677            work->data[workIndex] = NULL;
    609678            workIndex--;
     
    618687}
    619688
    620 // Search a leaf node for any points within radius squared
    621 static inline bool treeLeafSearchWithinAny(double radius2, // Radius squared to search
    622                                            const psTree *tree, // Tree of interest
    623                                            const psTreeNode *leaf, // Leaf to search
    624                                            const psVector *coords // Coordinates of interest
     689// Search a leaf node for points within distance
     690static inline void treeLeafSearchAllWithin(psVector *result,       // Result vector
     691                                          double distance, // Distance to search
     692                                          const psTree *tree, // Tree of interest
     693                                          const psTreeNode *leaf, // Leaf to search
     694                                          const psVector *coords // Coordinates of interest
    625695    )
    626696{
    627697    for (int i = 0; i < leaf->num; i++) {
    628698        long index = leaf->contents[i]; // Index of point
    629         double distance = treeContentDistance(tree, index, coords); // Distance to point
    630         if (distance < radius2) {
    631             return true;
    632         }
    633     }
    634     return false;
    635 }
    636 
    637 // Given an arbitrary point and a matching radius, return whether there are any points within that radius
    638 bool psTreeWithinAny(const psTree *tree, const psVector *coordinates, double radius)
    639 {
    640 #if 1 // Might be in a tight loop
    641     PS_ASSERT_TREE_NON_NULL(tree, false);
    642     PS_ASSERT_VECTOR_NON_NULL(coordinates, false);
    643     PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, false);
     699        if (treeContentDistance(tree, index, coords) < distance) {
     700            psVectorAppend(result, index);
     701        }
     702    }
     703    return;
     704}
     705
     706// Given an arbitrary point and a matching radius, return the index of all points within that radius
     707psVector *psTreeAllWithin(const psTree *tree, const psVector *coordinates, double radius)
     708{
     709#ifdef INPUT_CHECK // Might be in a tight loop
     710    PS_ASSERT_TREE_NON_NULL(tree, NULL);
     711    PS_ASSERT_VECTOR_NON_NULL(coordinates, NULL);
     712    PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, NULL);
    644713#endif
    645714
     
    647716                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
    648717
    649     radius *= radius;                   // We work with the radius-squared
    650 
    651     // This is essentially the same as psTreeWithin, except we can bail as soon as we find something
     718    double distance = treeRadiusToDistance(tree, radius); // Distance measure
     719
     720    psVector *result = psVectorAllocEmpty(4, PS_TYPE_S64); // Indices of points within match radius
     721
     722    // This is essentially the same as psTreeNearest, except we're not allowed to prune
    652723
    653724    // Find the closest point in the leaf that contains the point of interest
    654725    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
    655     if (treeLeafSearchWithinAny(radius, tree, leaf, coords)) {
    656         psFree(coords);
    657         return true;
    658     }
     726    treeLeafSearchAllWithin(result, distance, tree, leaf, coords);
    659727
    660728    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
     
    673741            }
    674742            // Leaf node
    675             if (treeLeafSearchWithinAny(radius, tree, node, coords)) {
     743            treeLeafSearchAllWithin(result, distance, tree, node, coords);
     744            work->data[workIndex] = NULL;
     745            workIndex--;
     746        }
     747
     748        leaf = up;
     749    }
     750    psFree(work);
     751    psFree(coords);
     752
     753    return result;
     754}
     755
     756// Search a leaf node for any points within distance measure
     757static inline bool treeLeafSearchWithinAny(double distance, // Distance to search
     758                                           const psTree *tree, // Tree of interest
     759                                           const psTreeNode *leaf, // Leaf to search
     760                                           const psVector *coords // Coordinates of interest
     761    )
     762{
     763    for (int i = 0; i < leaf->num; i++) {
     764        long index = leaf->contents[i]; // Index of point
     765        if (treeContentDistance(tree, index, coords) < distance) {
     766            return true;
     767        }
     768    }
     769    return false;
     770}
     771
     772// Given an arbitrary point and a matching radius, return whether there are any points within that radius
     773bool psTreeWithinAny(const psTree *tree, const psVector *coordinates, double radius)
     774{
     775#ifdef INPUT_CHECK // Might be in a tight loop
     776    PS_ASSERT_TREE_NON_NULL(tree, false);
     777    PS_ASSERT_VECTOR_NON_NULL(coordinates, false);
     778    PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, false);
     779#endif
     780
     781    psVector *coords = (coordinates->type.type == PS_TYPE_F64 ? psMemIncrRefCounter((psVector*)coordinates) :
     782                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
     783
     784    double distance = treeRadiusToDistance(tree, radius); // Distance measure
     785
     786    // This is essentially the same as psTreeWithin, except we can bail as soon as we find something
     787
     788    // Find the closest point in the leaf that contains the point of interest
     789    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
     790    if (treeLeafSearchWithinAny(distance, tree, leaf, coords)) {
     791        psFree(coords);
     792        return true;
     793    }
     794
     795    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
     796    while (leaf->up) {
     797        psTreeNode *up = leaf->up;      // Parent node
     798
     799        long workIndex = 0;
     800        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
     801        while (workIndex >= 0) {
     802            psTreeNode *node = work->data[workIndex];
     803            if (node->left) {
     804                // Branch node
     805                work->data[workIndex] = node->right;
     806                work->data[++workIndex] = node->left;
     807                continue;
     808            }
     809            // Leaf node
     810            if (treeLeafSearchWithinAny(distance, tree, node, coords)) {
    676811                // Clear out the work queue
    677812                memset(work->data, 0, (workIndex + 1) * sizeof(void));
     
    695830psVector *psTreeCoords(psVector *out, const psTree *tree, long index)
    696831{
    697 #if 1 // Might be in a tight loop
     832#ifdef INPUT_CHECK // Might be in a tight loop
    698833    PS_ASSERT_TREE_NON_NULL(tree, NULL);
    699834    PS_ASSERT_INT_NONNEGATIVE(index, NULL);
  • trunk/psLib/src/types/psTree.h

    r19539 r25256  
    1616} psTreeCoordArray;
    1717
     18/// Type of tree
     19///
     20/// Specifies how distances are measured
     21typedef enum {
     22    PS_TREE_EUCLIDEAN,                  // d^2 = dx^2 + dy^2 + ...
     23    PS_TREE_SPHERICAL,                  // sin(dist/2)^2 = sin(dphi/2)^2 + cos(phi1)cos(phi2)sin(dlambda/2)^2
     24} psTreeType;
     25
    1826/// A simple kd-tree implementation
    1927///
     
    2331    int dim;                            ///< Dimensionality
    2432    int maxLeafContents;                ///< Maximum number of points on a leaf
     33    psTreeType type;                    ///< Type of tree
    2534    long numNodes;                      ///< Number of nodes
    2635    long numData;                       ///< Number of data points
     
    6776psTree *psTreeAlloc(int dim,            ///< Dimensionality
    6877                    int maxLeafContents,///< Maximum number of points on a leaf
     78                    psTreeType type,    ///< Type of tree
    6979                    long numNodes       ///< Number of nodes in tree
    7080                    );
     
    7585psTree *psTreePlant(int dim,            ///< Dimensionality
    7686                    int maxLeafContents,///< Maximum number of points on a leaf
     87                    psTreeType type,    ///< Type of tree
    7788                    ...                 ///< psVector for each coordinate
    7889                    );
     
    108119                     );
    109120
     121/// Return the index of all points within some radius of given coordinates
     122psVector *psTreeAllWithin(const psTree *tree,          ///< Tree
     123                          const psVector *coordinates, ///< Coordinates of interest
     124                          double radius                ///< Radius of interest
     125                          );
     126
    110127/// Return the coordinates of a point in the tree, specified by its index
    111128psVector *psTreeCoords(psVector *out,   ///< Output vector, or NULL
  • trunk/psLib/test/optime

    • Property svn:ignore
      •  

        old new  
        22Makefile.in
        33.deps
         4tap_psStatsTiming
  • trunk/psLib/test/types/tap_psTree.c

    r23259 r25256  
    33#include "pstap.h"
    44
    5 #define NUM 10000                       // Number of points
     5#define NUM 1000000                      // Number of points
     6#define SPHERICAL_DISTANCE 3.0          // Distance of interest for spherical test
    67
    78int main(int argc, char *argv[])
    89{
    910    psLibInit(NULL);
    10     plan_tests(6);
     11    plan_tests(13);
    1112
     13    // Euclidean geometry: 6 tests
    1214    {
    1315        psMemId id = psMemGetId();
     
    2325        psFree(rng);
    2426
    25         psTree *tree = psTreePlant(2, 2, x, y);
     27        psTree *tree = psTreePlant(2, 2, PS_TREE_EUCLIDEAN, x, y);
    2628
    2729        ok(tree, "Tree planted");
     
    3537            long closeIndex = psTreeNearest(tree, coords);
    3638            psFree(coords);
    37             ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found point: %ld", closeIndex);
     39            ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found closest point: %ld", closeIndex);
    3840
    3941            long bestIndex = -1;
     
    6870    }
    6971
     72    // Spherical geometry: 7 tests
     73    {
     74        psMemId id = psMemGetId();
     75
     76        psVector *ra = psVectorAlloc(NUM, PS_TYPE_F64);
     77        psVector *dec = psVectorAlloc(NUM, PS_TYPE_F64);
     78
     79        psRandom *rng = psRandomAllocSpecific(PS_RANDOM_TAUS, 0);
     80        for (int i = 0; i < NUM; i++) {
     81            // Using http://mathworld.wolfram.com/SpherePointPicking.html
     82            ra->data.F64[i] = psRandomUniform(rng);
     83            dec->data.F64[i] = acos(2.0 * psRandomUniform(rng) - 1.0) - M_PI_2;
     84        }
     85
     86        psTree *tree = psTreePlant(2, 2, PS_TREE_SPHERICAL, ra, dec);
     87
     88        ok(tree, "Tree planted");
     89        skip_start(!tree, 4, "tree died");
     90        {
     91            //            psTreePrint(stderr, tree);
     92
     93            psVector *coords = psVectorAlloc(2, PS_TYPE_F64);
     94            coords->data.F64[0] = psRandomUniform(rng);
     95            coords->data.F64[1] = acos(2.0 * psRandomUniform(rng) - 1.0) - M_PI_2;
     96
     97            psVector *indices = psTreeAllWithin(tree, coords, DEG_TO_RAD(SPHERICAL_DISTANCE));
     98            ok(indices && indices->type.type == PS_TYPE_S64, "got list of indices (%ld points)", indices->n);
     99            long closeIndex = psTreeNearest(tree, coords);
     100            ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found closest point: %ld", closeIndex);
     101
     102            ok(psVectorSortInPlace(indices), "sorted indices");
     103
     104            bool allgood = true;        // All points in the appropriate place?
     105            double bestDistance = INFINITY; // Distance to best point
     106            long bestIndex = -1;        // Index of best point
     107            for (long i = 0, j = 0; i < NUM; i++) {
     108#if 1
     109                // Traditional formula
     110                double dist = acos(sin(coords->data.F64[1]) * sin(dec->data.F64[i]) +
     111                                   cos(coords->data.F64[1]) * cos(dec->data.F64[i]) *
     112                                   cos(coords->data.F64[0] - ra->data.F64[i]));
     113#else
     114                // Haversine formula: used in psTree
     115                double dphi = coords->data.F64[1] - dec->data.F64[i];
     116                double sindphi = sin(dphi/2.0);
     117                double dlambda = coords->data.F64[0] - ra->data.F64[i];
     118                double sindlambda = sin(dlambda/2.0);
     119                double dist = 2.0 * asin(sqrt(PS_SQR(sindphi) +
     120                                              cos(coords->data.F64[1]) * cos(dec->data.F64[i]) *
     121                                              PS_SQR(sindlambda)));
     122#endif
     123                                              if (dist < bestDistance) {
     124                    bestDistance = dist;
     125                    bestIndex = i;
     126                }
     127                if (i == indices->data.S64[j]) {
     128                    j++;
     129                    if (dist > DEG_TO_RAD(SPHERICAL_DISTANCE)) {
     130                        diag("%ld is in the list, but shouldn't be (%lf vs %lf)",
     131                             i, RAD_TO_DEG(dist), SPHERICAL_DISTANCE);
     132                        allgood = false;
     133                    }
     134                } else if (dist <= DEG_TO_RAD(SPHERICAL_DISTANCE)) {
     135                    diag("%ld is not in the list, but should be (%lf vs %lf)",
     136                         i, RAD_TO_DEG(dist), SPHERICAL_DISTANCE);
     137                    allgood = false;
     138                }
     139            }
     140            ok(allgood, "list is acurate");
     141            ok(bestIndex == closeIndex, "correct point: %ld vs %ld", closeIndex, bestIndex);
     142
     143            psFree(coords);
     144            psFree(indices);
     145
     146        }
     147        skip_end();
     148
     149        psFree(rng);
     150        psFree(tree);
     151        psFree(ra);
     152        psFree(dec);
     153
     154        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
     155    }
     156
    70157    psLibFinalize();
    71158}
Note: See TracChangeset for help on using the changeset viewer.