Changeset 25256 for trunk/psLib
- Timestamp:
- Sep 2, 2009, 2:36:52 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
-
. (modified) (1 prop)
-
psLib/src/sys/psType.h (modified) (4 diffs)
-
psLib/src/types/psTree.c (modified) (21 diffs)
-
psLib/src/types/psTree.h (modified) (5 diffs)
-
psLib/test/optime (modified) (1 prop)
-
psLib/test/types/tap_psTree.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/pap_mops (added) merged: 25137-25138,25162,25180-25183,25186-25193,25201-25202,25225,25231-25236,25239-25240,25245,25247-25255
- Property svn:mergeinfo changed
-
trunk/psLib/src/sys/psType.h
r21183 r25256 141 141 } psDataType; 142 142 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 144 144 #define PS_TYPE_MASK PS_TYPE_U8 /**< the psElemType to use for mask image */ 145 145 #define PS_TYPE_MASK_DATA U8 /**< the data member to use for mask image */ … … 152 152 // alternate versions if needed 153 153 // #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)) 155 155 // #define PS_NOT_MASK(A)(UINT64_MAX-(A)) 156 156 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 158 158 #define PS_TYPE_VECTOR_MASK PS_TYPE_U8 /**< the psElemType to use for mask image */ 159 159 #define PS_TYPE_VECTOR_MASK_DATA U8 /**< the data member to use for mask image */ … … 161 161 #define PS_MIN_VECTOR_MASK_TYPE 0 /**< minimum valid Vector Mask value */ 162 162 #define PS_MAX_VECTOR_MASK_TYPE UINT8_MAX /**< maximum valid Vector Mask value */ 163 typedef psU8 psVectorMaskType; ///< the C datatype for a mask image163 typedef psU8 psVectorMaskType; ///< the C datatype for a mask image 164 164 #define PS_NOT_VECTOR_MASK(A)(UINT8_MAX-(A)) 165 165 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 */ 170 170 #define PS_MIN_IMAGE_MASK_TYPE 0 /**< minimum valid Image Mask value */ 171 171 #define PS_MAX_IMAGE_MASK_TYPE UINT16_MAX /**< maximum valid Image Mask value */ … … 246 246 }; 247 247 248 /// Macro to get the bad pixel reason code (stored as part of mask value)249 #define PS_BADPIXEL_BITMASK 0x0f250 #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 image255 #define PS_SET_BADPIXEL(maskValue, reasonCode) \256 { \257 maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \258 }259 260 248 /// Macro to determine if the psElemType is an integer. 261 249 #define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100) -
trunk/psLib/src/types/psTree.c
r18344 r25256 14 14 #include "psTree.h" 15 15 16 //#define INPUT_CHECK // Check inputs for functions that may be in a tight loop? 17 16 18 17 19 // XXX Upgrades: … … 84 86 } 85 87 86 psTree *psTreeAlloc(int dim, int maxLeafContents, long numNodes)88 psTree *psTreeAlloc(int dim, int maxLeafContents, psTreeType type, long numNodes) 87 89 { 88 90 psAssert(dim > 0, "Dimensionality (%d) must be positive", dim); … … 95 97 tree->dim = dim; 96 98 tree->maxLeafContents = maxLeafContents; 99 tree->type = type; 97 100 98 101 tree->numNodes = numNodes; … … 115 118 116 119 117 psTree *psTreePlant(int dim, int maxLeafContents, ...)120 psTree *psTreePlant(int dim, int maxLeafContents, psTreeType type, ...) 118 121 { 119 122 PS_ASSERT_INT_POSITIVE(dim, NULL); … … 122 125 // Parse coordinate list 123 126 va_list args; // Variable argument list 124 va_start(args, maxLeafContents);127 va_start(args, type); 125 128 psArray *coords = psArrayAlloc(dim); // Array of coordinates 126 129 long numData = 0; // Number of data points … … 145 148 long pow2; // Smallest power of two >= numData 146 149 for (pow2 = 1; pow2 < numData; pow2 <<= 1); 147 numNodes = PS_M IN(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); 151 154 tree->data = psTreeCoordArrayAlloc(numData, dim); 152 155 tree->numData = numData; … … 199 202 } 200 203 204 if (numData <= maxLeafContents) { 205 // Don't need to do any more work 206 return tree; 207 } 208 201 209 psArray *work = psArrayAlloc(numNodes); // Work queue 202 210 work->data[0] = root; … … 365 373 psTreeNode *psTreeLeaf(const psTree *tree, const psVector *coords) 366 374 { 367 #if 1// Might be in a tight loop375 #ifdef INPUT_CHECK // Might be in a tight loop 368 376 PS_ASSERT_TREE_NON_NULL(tree, NULL); 369 377 PS_ASSERT_VECTOR_NON_NULL(coords, NULL); … … 403 411 { 404 412 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; 417 429 } 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 421 450 return NAN; 422 451 } … … 430 459 double minDiff = tree->min->F64[index][i] - coords->data.F64[i]; 431 460 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 } 433 473 continue; 434 474 } 435 475 double maxDiff = coords->data.F64[i] - tree->max->F64[index][i]; 436 476 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 } 438 489 continue; 439 490 } … … 479 530 } 480 531 481 // Return the index of the nearest neighbour to given coordinates, within some radius532 // Return the index of the nearest neighbour to given coordinates, within some distance measure 482 533 // This is the engine for psTreeNearest() and psTreeNearestWithin() 483 534 static inline long treeNearestWithin(const psTree *tree, // Tree 484 535 const psVector *coordinates, // Coordinates of interest 485 double bestDistance // Distance (radius-squared)to best point536 double bestDistance // Distance measure to best point 486 537 ) 487 538 { 488 #if 1// Might be in a tight loop539 #ifdef INPUT_CHECK // Might be in a tight loop 489 540 PS_ASSERT_TREE_NON_NULL(tree, -1); 490 541 PS_ASSERT_VECTOR_NON_NULL(coordinates, -1); … … 545 596 546 597 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. 600 static 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 547 617 long psTreeNearestWithin(const psTree *tree, const psVector *coords, double radius) 548 618 { 549 return treeNearestWithin(tree, coords, PS_SQR(radius));550 } 551 552 553 // Search a leaf node for points within radius squared554 static inline long treeLeafSearchWithin(double radius2, // Radius squaredto search619 return treeNearestWithin(tree, coords, treeRadiusToDistance(tree, radius)); 620 } 621 622 623 // Search a leaf node for points within distance 624 static inline long treeLeafSearchWithin(double distance, // Distance to search 555 625 const psTree *tree, // Tree of interest 556 626 const psTreeNode *leaf, // Leaf to search … … 561 631 for (int i = 0; i < leaf->num; i++) { 562 632 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) { 565 634 num++; 566 635 } … … 572 641 long psTreeWithin(const psTree *tree, const psVector *coordinates, double radius) 573 642 { 574 #if 1// Might be in a tight loop643 #ifdef INPUT_CHECK // Might be in a tight loop 575 644 PS_ASSERT_TREE_NON_NULL(tree, -1); 576 645 PS_ASSERT_VECTOR_NON_NULL(coordinates, -1); … … 581 650 psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates 582 651 583 radius *= radius; // We work with the radius-squared652 double distance = treeRadiusToDistance(tree, radius); // Distance measure 584 653 long num = 0; // Number of points in circle 585 654 … … 588 657 // Find the closest point in the leaf that contains the point of interest 589 658 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); 591 660 592 661 psArray *work = psArrayAlloc(tree->numNodes); // Work queue … … 605 674 } 606 675 // Leaf node 607 num += treeLeafSearchWithin( radius, tree, node, coords);676 num += treeLeafSearchWithin(distance, tree, node, coords); 608 677 work->data[workIndex] = NULL; 609 678 workIndex--; … … 618 687 } 619 688 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 690 static 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 625 695 ) 626 696 { 627 697 for (int i = 0; i < leaf->num; i++) { 628 698 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 707 psVector *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); 644 713 #endif 645 714 … … 647 716 psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates 648 717 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 652 723 653 724 // Find the closest point in the leaf that contains the point of interest 654 725 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); 659 727 660 728 psArray *work = psArrayAlloc(tree->numNodes); // Work queue … … 673 741 } 674 742 // 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 757 static 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 773 bool 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)) { 676 811 // Clear out the work queue 677 812 memset(work->data, 0, (workIndex + 1) * sizeof(void)); … … 695 830 psVector *psTreeCoords(psVector *out, const psTree *tree, long index) 696 831 { 697 #if 1// Might be in a tight loop832 #ifdef INPUT_CHECK // Might be in a tight loop 698 833 PS_ASSERT_TREE_NON_NULL(tree, NULL); 699 834 PS_ASSERT_INT_NONNEGATIVE(index, NULL); -
trunk/psLib/src/types/psTree.h
r19539 r25256 16 16 } psTreeCoordArray; 17 17 18 /// Type of tree 19 /// 20 /// Specifies how distances are measured 21 typedef 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 18 26 /// A simple kd-tree implementation 19 27 /// … … 23 31 int dim; ///< Dimensionality 24 32 int maxLeafContents; ///< Maximum number of points on a leaf 33 psTreeType type; ///< Type of tree 25 34 long numNodes; ///< Number of nodes 26 35 long numData; ///< Number of data points … … 67 76 psTree *psTreeAlloc(int dim, ///< Dimensionality 68 77 int maxLeafContents,///< Maximum number of points on a leaf 78 psTreeType type, ///< Type of tree 69 79 long numNodes ///< Number of nodes in tree 70 80 ); … … 75 85 psTree *psTreePlant(int dim, ///< Dimensionality 76 86 int maxLeafContents,///< Maximum number of points on a leaf 87 psTreeType type, ///< Type of tree 77 88 ... ///< psVector for each coordinate 78 89 ); … … 108 119 ); 109 120 121 /// Return the index of all points within some radius of given coordinates 122 psVector *psTreeAllWithin(const psTree *tree, ///< Tree 123 const psVector *coordinates, ///< Coordinates of interest 124 double radius ///< Radius of interest 125 ); 126 110 127 /// Return the coordinates of a point in the tree, specified by its index 111 128 psVector *psTreeCoords(psVector *out, ///< Output vector, or NULL -
trunk/psLib/test/optime
- Property svn:ignore
-
old new 2 2 Makefile.in 3 3 .deps 4 tap_psStatsTiming
-
- Property svn:ignore
-
trunk/psLib/test/types/tap_psTree.c
r23259 r25256 3 3 #include "pstap.h" 4 4 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 6 7 7 8 int main(int argc, char *argv[]) 8 9 { 9 10 psLibInit(NULL); 10 plan_tests( 6);11 plan_tests(13); 11 12 13 // Euclidean geometry: 6 tests 12 14 { 13 15 psMemId id = psMemGetId(); … … 23 25 psFree(rng); 24 26 25 psTree *tree = psTreePlant(2, 2, x, y);27 psTree *tree = psTreePlant(2, 2, PS_TREE_EUCLIDEAN, x, y); 26 28 27 29 ok(tree, "Tree planted"); … … 35 37 long closeIndex = psTreeNearest(tree, coords); 36 38 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); 38 40 39 41 long bestIndex = -1; … … 68 70 } 69 71 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 70 157 psLibFinalize(); 71 158 }
Note:
See TracChangeset
for help on using the changeset viewer.
