Commit acd18a24af5ccc73f44815c0e167686969c552d4

Authored by Jürgen Knödlseder
1 parent 6c9c273a

Implement comprehensive unit tests for all sky region types (#3248)

src/sky/GSkyRegionCircle.cpp
@@ -494,31 +494,33 @@ std::string GSkyRegionCircle::print(const GChatter& chatter) const @@ -494,31 +494,33 @@ std::string GSkyRegionCircle::print(const GChatter& chatter) const
494 * @brief Checks if sky direction lies within region 494 * @brief Checks if sky direction lies within region
495 * 495 *
496 * @param[in] dir Sky direction. 496 * @param[in] dir Sky direction.
  497 + * @return True if sky direction is contained in region.
497 * 498 *
498 * A sky direction lies within a region when its distance to the region 499 * A sky direction lies within a region when its distance to the region
499 * centre is not larger than the region radius. 500 * centre is not larger than the region radius.
500 ***************************************************************************/ 501 ***************************************************************************/
501 bool GSkyRegionCircle::contains(const GSkyDir& dir) const 502 bool GSkyRegionCircle::contains(const GSkyDir& dir) const
502 { 503 {
503 - // Initialise return value  
504 - bool dir_is_in = false; 504 + // Initialise containment flag
  505 + bool contains = false;
505 506
506 // calculate distance from dir to centre 507 // calculate distance from dir to centre
507 double distance = dir.dist_deg(m_centre); 508 double distance = dir.dist_deg(m_centre);
508 509
509 // Check if distance < radius 510 // Check if distance < radius
510 if (distance <= radius()) { 511 if (distance <= radius()) {
511 - dir_is_in = true; 512 + contains = true;
512 } 513 }
513 514
514 - // Return bool  
515 - return dir_is_in; 515 + // Return containment flag
  516 + return contains;
516 } 517 }
517 518
518 /***********************************************************************//** 519 /***********************************************************************//**
519 * @brief Checks if region is fully contained within this region 520 * @brief Checks if region is fully contained within this region
520 * 521 *
521 * @param[in] reg Sky region. 522 * @param[in] reg Sky region.
  523 + * @return True if region is contained in region.
522 * 524 *
523 * @exception GException::feature_not_implemented 525 * @exception GException::feature_not_implemented
524 * Regions differ in type. 526 * Regions differ in type.
@@ -570,7 +572,7 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const @@ -570,7 +572,7 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const
570 const GSkyRegionMap* map = static_cast<const GSkyRegionMap*>(&reg); 572 const GSkyRegionMap* map = static_cast<const GSkyRegionMap*>(&reg);
571 573
572 // Get non-zero indices 574 // Get non-zero indices
573 - std::vector<int> indices = map->nonzero_indices(); 575 + const std::vector<int>& indices = map->nonzero_indices();
574 576
575 // Initialise containment flag to true 577 // Initialise containment flag to true
576 contains = true; 578 contains = true;
@@ -579,7 +581,7 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const @@ -579,7 +581,7 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const
579 for (int i = 0; i < indices.size(); ++i) { 581 for (int i = 0; i < indices.size(); ++i) {
580 582
581 // Get sky direction of map pixel 583 // Get sky direction of map pixel
582 - GSkyDir dir = map->map().inx2dir(i); 584 + GSkyDir dir = map->map().inx2dir(indices[i]);
583 585
584 // If pixel is not contained then set containment flag to false 586 // If pixel is not contained then set containment flag to false
585 // and break 587 // and break
@@ -607,11 +609,10 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const @@ -607,11 +609,10 @@ bool GSkyRegionCircle::contains(const GSkyRegion&amp; reg) const
607 * @brief Checks if region is overlapping with this region 609 * @brief Checks if region is overlapping with this region
608 * 610 *
609 * @param[in] reg Sky region. 611 * @param[in] reg Sky region.
  612 + * @return True if region overlaps with region.
610 * 613 *
611 * @exception GException::feature_not_implemented 614 * @exception GException::feature_not_implemented
612 * Regions differ in type. 615 * Regions differ in type.
613 - *  
614 - * @todo Implement checks for rectangles and maps  
615 ***************************************************************************/ 616 ***************************************************************************/
616 bool GSkyRegionCircle::overlaps(const GSkyRegion& reg) const 617 bool GSkyRegionCircle::overlaps(const GSkyRegion& reg) const
617 { 618 {
src/sky/GSkyRegionRectangle.cpp
@@ -483,6 +483,7 @@ std::string GSkyRegionRectangle::write(void) const @@ -483,6 +483,7 @@ std::string GSkyRegionRectangle::write(void) const
483 * @brief Checks if sky direction lies within region 483 * @brief Checks if sky direction lies within region
484 * 484 *
485 * @param[in] dir Sky direction. 485 * @param[in] dir Sky direction.
  486 + * @return True if sky direction is contained in region.
486 * 487 *
487 * A sky direction lies within a region when its distance to the region 488 * A sky direction lies within a region when its distance to the region
488 * centre is not larger than the region extension in both axes directions. 489 * centre is not larger than the region extension in both axes directions.
@@ -504,6 +505,7 @@ bool GSkyRegionRectangle::contains(const GSkyDir&amp; dir) const @@ -504,6 +505,7 @@ bool GSkyRegionRectangle::contains(const GSkyDir&amp; dir) const
504 * @brief Checks if region is fully contained within this region 505 * @brief Checks if region is fully contained within this region
505 * 506 *
506 * @param[in] reg Sky region. 507 * @param[in] reg Sky region.
  508 + * @return True if region is contained in region.
507 * 509 *
508 * @exception GException::feature_not_implemented 510 * @exception GException::feature_not_implemented
509 * Not all region types supported currently. 511 * Not all region types supported currently.
@@ -611,10 +613,13 @@ bool GSkyRegionRectangle::contains(const GSkyRegion&amp; reg) const @@ -611,10 +613,13 @@ bool GSkyRegionRectangle::contains(const GSkyRegion&amp; reg) const
611 * @brief Checks if region is overlapping with this region 613 * @brief Checks if region is overlapping with this region
612 * 614 *
613 * @param[in] reg Sky region. 615 * @param[in] reg Sky region.
  616 + * @return True if region overlaps with region.
614 * 617 *
615 * @exception GException::feature_not_implemented 618 * @exception GException::feature_not_implemented
616 * Regions differ in type. 619 * Regions differ in type.
617 * 620 *
  621 + * Checks whether a region overlaps with the rectangle.
  622 + *
618 * @todo Improve implementation for rectangle-rectangle 623 * @todo Improve implementation for rectangle-rectangle
619 ***************************************************************************/ 624 ***************************************************************************/
620 bool GSkyRegionRectangle::overlaps(const GSkyRegion& reg) const 625 bool GSkyRegionRectangle::overlaps(const GSkyRegion& reg) const
@@ -623,7 +628,8 @@ bool GSkyRegionRectangle::overlaps(const GSkyRegion&amp; reg) const @@ -623,7 +628,8 @@ bool GSkyRegionRectangle::overlaps(const GSkyRegion&amp; reg) const
623 bool overlap = false; 628 bool overlap = false;
624 629
625 // If the region is a circle then check overlap between circle and 630 // If the region is a circle then check overlap between circle and
626 - // rectangle 631 + // rectangle using the alogrithm given under #292 at
  632 + // https://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
627 if (reg.type() == "Circle") { 633 if (reg.type() == "Circle") {
628 634
629 // Create circular region from reg 635 // Create circular region from reg
@@ -632,15 +638,34 @@ bool GSkyRegionRectangle::overlaps(const GSkyRegion&amp; reg) const @@ -632,15 +638,34 @@ bool GSkyRegionRectangle::overlaps(const GSkyRegion&amp; reg) const
632 638
633 // Transform circle center to local coordinate system 639 // Transform circle center to local coordinate system
634 GSkyPixel local = dir_to_local(circle->centre()); 640 GSkyPixel local = dir_to_local(circle->centre());
635 - double x_deg = local.x() * gammalib::rad2deg;  
636 - double y_deg = local.y() * gammalib::rad2deg; 641 + double x_deg = std::abs(local.x() * gammalib::rad2deg);
  642 + double y_deg = std::abs(local.y() * gammalib::rad2deg);
637 643
638 // Get circle radius in degrees 644 // Get circle radius in degrees
639 double radius = circle->radius(); 645 double radius = circle->radius();
640 646
641 - // Check whether circle overlaps within rectangle  
642 - if (std::abs(y_deg) <= (0.5 * m_height + radius)) {  
643 - if (std::abs(x_deg) <= (0.5 * m_width + radius)) { 647 + // Compute half width and height
  648 + double half_width = 0.5 * width();
  649 + double half_height = 0.5 * height();
  650 +
  651 + // Assess overlap
  652 + if (x_deg > (half_width + radius)) {
  653 + overlap = false;
  654 + }
  655 + else if (y_deg > (half_height + radius)) {
  656 + overlap = false;
  657 + }
  658 + else if (x_deg <= half_width) {
  659 + overlap = true;
  660 + }
  661 + else if (y_deg <= half_height) {
  662 + overlap = true;
  663 + }
  664 + else {
  665 + double dx = x_deg - half_width;
  666 + double dy = y_deg - half_height;
  667 + double d2 = dx * dx + dy * dy;
  668 + if (d2 <= radius*radius) {
644 overlap = true; 669 overlap = true;
645 } 670 }
646 } 671 }
test/test_GSky.cpp
@@ -1713,107 +1713,209 @@ void TestGSky::test_GSkyMap_io(void) @@ -1713,107 +1713,209 @@ void TestGSky::test_GSkyMap_io(void)
1713 ***************************************************************************/ 1713 ***************************************************************************/
1714 void TestGSky::test_GSkyRegionCircle(void) 1714 void TestGSky::test_GSkyRegionCircle(void)
1715 { 1715 {
1716 - // Define region for comparison  
1717 - GSkyDir refdir_radeczerozero;  
1718 - refdir_radeczerozero.radec_deg(0,0);  
1719 - double refradius = 10.; 1716 + // Test void constructor
  1717 + GSkyRegionCircle circle0;
  1718 + test_value(circle0.classname(), "GSkyRegionCircle", "Test classname of void constructor");
  1719 + test_value(circle0.type(), "Circle", "Test type of void constructor");
  1720 + test_value(circle0.centre().ra_deg(), 0.0, "Test Right Ascension of centre of void constructor");
  1721 + test_value(circle0.centre().dec_deg(), 0.0, "Test Declination of centre of void constructor");
  1722 + test_value(circle0.ra(), 0.0, "Test Right Ascension of void constructor");
  1723 + test_value(circle0.dec(), 0.0, "Test Declination of void constructor");
  1724 + test_value(circle0.radius(), 0.0, "Test radius of void constructor");
  1725 +
  1726 + // Test sky direction constructor
  1727 + GSkyDir dir1;
  1728 + dir1.radec_deg(83.6331,22.0145);
  1729 + GSkyRegionCircle circle1(dir1, 3.1);
  1730 + test_value(circle1.centre().ra_deg(), 83.6331, "Test Right Ascension of centre of sky direction constructor");
  1731 + test_value(circle1.centre().dec_deg(), 22.0145, "Test Declination of centre of sky direction constructor");
  1732 + test_value(circle1.ra(), 83.6331, "Test Right Ascension of sky direction constructor");
  1733 + test_value(circle1.dec(), 22.0145, "Test Declination of sky direction constructor");
  1734 + test_value(circle1.radius(), 3.1, "Test radius of sky direction constructor");
  1735 +
  1736 + // Test Right Ascension and Declination constructor
  1737 + GSkyRegionCircle circle2(83.6331, 22.0145, 3.1);
  1738 + test_value(circle2.centre().ra_deg(), 83.6331, "Test Right Ascension of centre of (RA,Dec) constructor");
  1739 + test_value(circle2.centre().dec_deg(), 22.0145, "Test Declination of centre of (RA,Dec) constructor");
  1740 + test_value(circle2.ra(), 83.6331, "Test Right Ascension of (RA,Dec) constructor");
  1741 + test_value(circle2.dec(), 22.0145, "Test Declination of (RA,Dec) constructor");
  1742 + test_value(circle2.radius(), 3.1, "Test radius of (RA,Dec) constructor");
  1743 +
  1744 + // Test line constructor
  1745 + GSkyRegionCircle circle3("fk5;circle(83.6331, 22.0145, 3.1)");
  1746 + test_value(circle3.centre().ra_deg(), 83.6331, "Test Right Ascension of centre of line constructor");
  1747 + test_value(circle3.centre().dec_deg(), 22.0145, "Test Declination of centre of line constructor");
  1748 + test_value(circle3.ra(), 83.6331, "Test Right Ascension of line constructor");
  1749 + test_value(circle3.dec(), 22.0145, "Test Declination of line constructor");
  1750 + test_value(circle3.radius(), 3.1, "Test radius of line constructor");
1720 1751
1721 - // Test constructing:  
1722 - test_try("Test constructor"); 1752 + // Test copy constructor
  1753 + GSkyRegionCircle circle4(circle3);
  1754 + test_value(circle4.centre().ra_deg(), 83.6331, "Test Right Ascension of centre of copy constructor");
  1755 + test_value(circle4.centre().dec_deg(), 22.0145, "Test Declination of centre of copy constructor");
  1756 + test_value(circle4.ra(), 83.6331, "Test Right Ascension of copy constructor");
  1757 + test_value(circle4.dec(), 22.0145, "Test Declination of copy constructor");
  1758 + test_value(circle4.radius(), 3.1, "Test radius of copy constructor");
  1759 +
  1760 + // Test assignment operator
  1761 + GSkyRegionCircle circle5;
  1762 + circle5 = circle3;
  1763 + test_value(circle5.centre().ra_deg(), 83.6331, "Test Right Ascension of centre of assignment operator");
  1764 + test_value(circle5.centre().dec_deg(), 22.0145, "Test Declination of centre of assignment operator");
  1765 + test_value(circle5.ra(), 83.6331, "Test Right Ascension of assignment operator");
  1766 + test_value(circle5.dec(), 22.0145, "Test Declination of assignment operator");
  1767 + test_value(circle5.radius(), 3.1, "Test radius of assignment operator");
  1768 +
  1769 + // Test clone method
  1770 + GSkyRegionCircle* circle6 = circle3.clone();
  1771 + test_value(circle6->centre().ra_deg(), 83.6331, "Test Right Ascension of centre of cloned instance");
  1772 + test_value(circle6->centre().dec_deg(), 22.0145, "Test Declination of centre of cloned instance");
  1773 + test_value(circle6->ra(), 83.6331, "Test Right Ascension of cloned instance");
  1774 + test_value(circle6->dec(), 22.0145, "Test Declination of cloned instance");
  1775 + test_value(circle6->radius(), 3.1, "Test radius of cloned instance");
  1776 + delete circle6;
  1777 +
  1778 + // Test constructor error modes
  1779 + test_try("Test invalid radius in sky direction constructor");
1723 try { 1780 try {
1724 - GSkyRegionCircle circle(refdir_radeczerozero,refradius); 1781 + GSkyRegionCircle circle(dir1, -1.0);
  1782 + test_try_failure();
  1783 + }
  1784 + catch (GException::invalid_argument &e) {
1725 test_try_success(); 1785 test_try_success();
1726 } 1786 }
1727 catch (std::exception &e) { 1787 catch (std::exception &e) {
1728 test_try_failure(e); 1788 test_try_failure(e);
1729 } 1789 }
1730 -  
1731 - // Test constructing with radius -1  
1732 - test_try("Test constructor2"); 1790 + //
  1791 + test_try("Test invalid radius in (RA,Dec) constructor");
1733 try { 1792 try {
1734 - GSkyRegionCircle circle(refdir_radeczerozero,-1);  
1735 - test_try_failure();  
1736 - }  
1737 - catch (GException::invalid_argument &e) { 1793 + GSkyRegionCircle circle(83.6331, 22.0145, -1.0);
  1794 + test_try_failure();
  1795 + }
  1796 + catch (GException::invalid_argument &e) {
  1797 + test_try_success();
  1798 + }
  1799 + catch (std::exception &e) {
  1800 + test_try_failure(e);
  1801 + }
  1802 + //
  1803 + test_try("Test invalid radius in line constructor");
  1804 + try {
  1805 + GSkyRegionCircle circle("fk5;circle(83.6331, 22.0145, -1.0)");
  1806 + test_try_failure();
  1807 + }
  1808 + catch (GException::invalid_argument &e) {
1738 test_try_success(); 1809 test_try_success();
1739 - }  
1740 - catch (std::exception &e) { 1810 + }
  1811 + catch (std::exception &e) {
1741 test_try_failure(e); 1812 test_try_failure(e);
1742 - } 1813 + }
1743 1814
1744 - // Test constructing with radius 0  
1745 - test_try("Test radius assignment after"); 1815 + // Test assignment methods
  1816 + GSkyRegionCircle circle7;
  1817 + circle7.radius(3.1);
  1818 + test_value(circle7.radius(), 3.1, "Test radius() methods");
  1819 +
  1820 + // Test assignment error modes
  1821 + test_try("Test invalid radius() assignment");
1746 try { 1822 try {
1747 - GSkyRegionCircle circle(refdir_radeczerozero,refradius);  
1748 - circle.radius(-1.0);  
1749 - test_try_failure();  
1750 - }  
1751 - catch (GException::invalid_argument &e) { 1823 + GSkyRegionCircle circle;
  1824 + circle.radius(-1.0);
  1825 + test_try_failure();
  1826 + }
  1827 + catch (GException::invalid_argument &e) {
1752 test_try_success(); 1828 test_try_success();
1753 - }  
1754 - catch (std::exception &e) { 1829 + }
  1830 + catch (std::exception &e) {
1755 test_try_failure(e); 1831 test_try_failure(e);
1756 - }  
1757 -  
1758 - // Check radius assignment  
1759 - GSkyRegionCircle refregion(refdir_radeczerozero,refradius);  
1760 - double refradius_check = refregion.radius();  
1761 - test_value(refradius,refradius_check,1.0e-10, "Test radius assignment");  
1762 -  
1763 - // Check solid angle assignment  
1764 - double solidangle_check = refregion.solidangle();  
1765 - double solidangle = 2*gammalib::pi*(1- std::cos(refradius /180 * gammalib::pi));  
1766 - test_value(solidangle_check,solidangle,1.0e-10, "Test solid angle assignment");  
1767 -  
1768 - // Set reference sky directions  
1769 - //GSkyDir refdir_radeczerozero;  
1770 - GSkyDir refdir_lbzerozero;  
1771 - GSkyDir refdir_outside_refregion;  
1772 - GSkyDir refdir_raoffset;  
1773 - GSkyDir refdir_decpole;  
1774 - GSkyDir refdir_ndecpole;  
1775 - GSkyDir refdir_rapole;  
1776 - refdir_radeczerozero.radec_deg(0,0);  
1777 - refdir_lbzerozero.lb_deg(0,0);  
1778 - refdir_outside_refregion.radec_deg(100,80);  
1779 - refdir_raoffset.radec_deg(5,0);  
1780 - refdir_decpole.radec_deg(0,89);  
1781 - refdir_ndecpole.radec_deg(100,89);  
1782 - refdir_rapole.radec_deg(359,0);  
1783 -  
1784 - // Set reference sky regions  
1785 - refregion = GSkyRegionCircle(refdir_radeczerozero, 10.0);  
1786 - GSkyDir centre = refregion.centre();  
1787 - GSkyRegionCircle refregion_smaller(refdir_radeczerozero, 5.0);  
1788 - GSkyRegionCircle refregion_larger(refdir_radeczerozero, 20.0);  
1789 - GSkyRegionCircle refregion_raoffset(refdir_raoffset, 10.0);  
1790 - GSkyRegionCircle refregion_rapole(refdir_rapole, 3.0);  
1791 - GSkyRegionCircle refregion_decpole(refdir_decpole, 3.0);  
1792 -  
1793 - // Test contain dirs  
1794 - test_assert(refregion.contains(refdir_radeczerozero),"Test for containment");  
1795 - test_assert(refregion.contains(centre), "Test if centre in circle");  
1796 - test_assert(!refregion.contains(refdir_outside_refregion), "Test2 for containment");  
1797 -  
1798 - // Test contain regions  
1799 - test_assert(refregion.contains(refregion_smaller),"Test for containment region");  
1800 - test_assert(!refregion.contains(refregion_larger), "Test for containment region2 ");  
1801 - test_assert(refregion.contains(refregion), "Test3 for containment region");  
1802 -  
1803 - test_assert(refregion.contains(refdir_rapole), "Test rapole for containment region");  
1804 - test_assert(refregion_decpole.contains(refdir_ndecpole), "Test rapole for containment region");  
1805 -  
1806 - // Test overlaps  
1807 - test_assert(refregion.overlaps(refregion_smaller),"Test for overlap");  
1808 - test_assert(refregion.overlaps(refregion_larger),"Test2 for overlap");  
1809 - test_assert(refregion.overlaps(refregion_raoffset),"Test3 for overlap");  
1810 - test_assert(!refregion.overlaps(refregion_decpole),"Test4 for overlap"); 1832 + }
  1833 +
  1834 + // Test solid angle computation
  1835 + GSkyRegionCircle circle8(83.6331, 22.0145, 3.1);
  1836 + double ref = 2.0 * gammalib::pi * (1.0 - std::cos(3.1 * gammalib::deg2rad));
  1837 + test_value(circle8.solidangle(), ref, "Test solid angle computation");
  1838 +
  1839 + // Test sky direction contains() method
  1840 + GSkyRegionCircle circle9(1.0, 1.0, 3.0);
  1841 + GSkyDir test_dir;
  1842 + test_dir.radec_deg(1.0, 1.0);
  1843 + test_assert(circle9.contains(test_dir), "Test whether (1,1) lies inside circle");
  1844 + test_dir.radec_deg(1.0, 3.99999);
  1845 + test_assert(circle9.contains(test_dir), "Test whether (1,4) lies inside circle");
  1846 + test_dir.radec_deg(1.0, -2.0);
  1847 + test_assert(circle9.contains(test_dir), "Test whether (1,-2) lies inside circle");
  1848 + test_dir.radec_deg(4.0, 1.0);
  1849 + test_assert(circle9.contains(test_dir), "Test whether (4,1) lies inside circle");
  1850 + test_dir.radec_deg(4.0, 4.0);
  1851 + test_assert(!circle9.contains(test_dir), "Test whether (4,4) lies outside circle");
  1852 + test_dir.radec_deg(-4.0, 4.0);
  1853 + test_assert(!circle9.contains(test_dir), "Test whether (-4,4) lies outside circle");
  1854 + test_dir.radec_deg(4.0, -4.0);
  1855 + test_assert(!circle9.contains(test_dir), "Test whether (4,-4) lies outside circle");
  1856 + test_dir.radec_deg(-4.0, -4.0);
  1857 + test_assert(!circle9.contains(test_dir), "Test whether (-4,-5) lies outside circle");
  1858 +
  1859 + // Test region contains() and overlaps() methods for circle
  1860 + GSkyRegionCircle circle10(1.0, 1.0, 3.1);
  1861 + GSkyRegionCircle circle11(1.0, 7.0, 3.0);
  1862 + test_assert(circle9.contains(circle9), "Test whether circle is contained in circle");
  1863 + test_assert(!circle9.contains(circle10), "Test whether circle is not contained in circle");
  1864 + test_assert(circle9.overlaps(circle10), "Test whether circle overlaps with circle");
  1865 + test_assert(!circle9.overlaps(circle11), "Test whether circle does not overlap with circle");
  1866 +
  1867 + // Test region contains() and overlaps() methods for rectangles
  1868 + GSkyRegionRectangle rect1(1.0, 1.0, 4.24, 4.24, 45.0);
  1869 + GSkyRegionRectangle rect2(1.0, 1.0, 4.25, 4.25, 45.0);
  1870 + GSkyRegionRectangle rect3(1.0, 7.0, 4.23, 4.23, 45.0);
  1871 + test_assert(circle9.contains(rect1), "Test whether rectangle is contained in circle");
  1872 + test_assert(!circle9.contains(rect2), "Test whether rectangle is not contained in circle");
  1873 + test_assert(circle9.overlaps(rect2), "Test whether circle overlaps with rectangle");
  1874 + test_assert(!circle9.overlaps(rect3), "Test whether circle does not overlap with rectangle");
  1875 +
  1876 + // Test region contains() and overlaps() methods for maps. The map region
  1877 + // is centred at (0,0) and has a radius of 0.3 deg.
  1878 + GSkyRegionMap map1(sky_region_map);
  1879 + GSkyRegionCircle circle12(0.0, 0.0, 0.31);
  1880 + GSkyRegionCircle circle13(0.0, 0.0, 0.29);
  1881 + GSkyRegionCircle circle14(0.6, 0.0, 0.3);
  1882 + test_assert(circle12.contains(map1), "Test whether map is contained in circle");
  1883 + test_assert(!circle13.contains(map1), "Test whether map is not contained in circle");
  1884 + test_assert(circle13.overlaps(map1), "Test whether circle overlaps with map");
  1885 + test_assert(!circle14.overlaps(map1), "Test whether circle does not overlap with map");
  1886 +
  1887 + // Test print() method
  1888 + test_assert(!circle9.print().empty(), "Test whether print() method returns something");
  1889 +
  1890 + // Test read() and write() methods
  1891 + GSkyRegionCircle circle15;
  1892 + circle15.read("fk5;circle(83.6331, 22.0145, 3.1)");
  1893 + test_value(circle15.centre().ra_deg(), 83.6331, "Test Right Ascension of centre after read()");
  1894 + test_value(circle15.centre().dec_deg(), 22.0145, "Test Declination of centre after read()");
  1895 + test_value(circle15.ra(), 83.6331, "Test Right Ascension after read()");
  1896 + test_value(circle15.dec(), 22.0145, "Test Declination after read()");
  1897 + test_value(circle15.radius(), 3.1, "Test radius after read()");
  1898 + std::string region = circle15.write();
  1899 + circle14.read(region);
  1900 + test_value(circle14.centre().ra_deg(), 83.6331, "Test Right Ascension of centre after second read()");
  1901 + test_value(circle14.centre().dec_deg(), 22.0145, "Test Declination of centre after second read()");
  1902 + test_value(circle14.ra(), 83.6331, "Test Right Ascension after second read()");
  1903 + test_value(circle14.dec(), 22.0145, "Test Declination after second read()");
  1904 + test_value(circle14.radius(), 3.1, "Test width after second read()");
  1905 +
  1906 + // Test clear method
  1907 + circle9.clear();
  1908 + test_value(circle9.centre().ra_deg(), 0.0, "Test Right Ascension of centre after clear()");
  1909 + test_value(circle9.centre().dec_deg(), 0.0, "Test Declination of centre after clear()");
  1910 + test_value(circle9.ra(), 0.0, "Test Right Ascension after clear()");
  1911 + test_value(circle9.dec(), 0.0, "Test Declination after clear()");
  1912 + test_value(circle9.radius(), 0.0, "Test radius after clear()");
1811 1913
1812 // Test equality and non-equality operators 1914 // Test equality and non-equality operators
1813 - test_assert(refregion_smaller == refregion_smaller,"Test for equality");  
1814 - test_assert(!(refregion_smaller == refregion_larger),"Test for equality");  
1815 - test_assert(!(refregion_smaller != refregion_smaller),"Test for non-equality");  
1816 - test_assert(refregion_smaller != refregion_larger,"Test for non-equality"); 1915 + test_assert(circle15 == circle15, "Test equality operator for equal circles");
  1916 + test_assert(!(circle15 == circle12), "Test equality operator for non-equal circles");
  1917 + test_assert(!(circle15 != circle15), "Test for non-equality operator for equal circles");
  1918 + test_assert(circle15 != circle12, "Test for non-equality operator for non-equal circles");
1817 1919
1818 // Exit test 1920 // Exit test
1819 return; 1921 return;
@@ -1916,7 +2018,7 @@ void TestGSky::test_GSkyRegionRectangle(void) @@ -1916,7 +2018,7 @@ void TestGSky::test_GSkyRegionRectangle(void)
1916 // 2018 //
1917 test_try("Test invalid width in (RA,Dec) constructor"); 2019 test_try("Test invalid width in (RA,Dec) constructor");
1918 try { 2020 try {
1919 - GSkyRegionRectangle rect(83.6331, 22.0145, 3.1, -1.0, 43.7); 2021 + GSkyRegionRectangle rect(83.6331, 22.0145, -1.0, 2.9, 43.7);
1920 test_try_failure(); 2022 test_try_failure();
1921 } 2023 }
1922 catch (GException::invalid_argument &e) { 2024 catch (GException::invalid_argument &e) {
@@ -2152,70 +2254,108 @@ void TestGSky::test_GSkyRegionRectangle(void) @@ -2152,70 +2254,108 @@ void TestGSky::test_GSkyRegionRectangle(void)
2152 ***************************************************************************/ 2254 ***************************************************************************/
2153 void TestGSky::test_GSkyRegionMap(void) 2255 void TestGSky::test_GSkyRegionMap(void)
2154 { 2256 {
2155 - // Test file constructor:  
2156 - test_try("Test file constructor");  
2157 - try {  
2158 - GSkyRegionMap regmap(sky_region_map);  
2159 - test_try_success();  
2160 - }  
2161 - catch (std::exception &e) {  
2162 - test_try_failure(e);  
2163 - } 2257 + // Test void constructor
  2258 + GSkyRegionMap map0;
  2259 + test_value(map0.classname(), "GSkyRegionMap", "Test classname of void constructor");
  2260 + test_value(map0.type(), "Map", "Test type of void constructor");
  2261 + test_assert(map0.map().is_empty(), "Test map() method of void constructor");
  2262 +
  2263 + // Test filename constructor
  2264 + GSkyRegionMap map1(sky_region_map);
  2265 + test_assert(!map1.map().is_empty(), "Test map() method of filename constructor");
2164 2266
2165 // Test skymap constructor 2267 // Test skymap constructor
2166 - GSkyMap skymap("TAN", "CEL", 0.0, 0.0, 0.1, 0.1, 100, 100);  
2167 - test_try("Test skymap constructor");  
2168 - try {  
2169 - GSkyRegionMap regmap(skymap);  
2170 - test_try_success();  
2171 - }  
2172 - catch (std::exception &e) {  
2173 - test_try_failure(e);  
2174 - } 2268 + GSkyMap skymap(sky_region_map);
  2269 + GSkyRegionMap map2(skymap);
  2270 + test_assert(!map2.map().is_empty(), "Test map() method of skymap constructor");
  2271 +
  2272 + // Test region constructors
  2273 + GSkyRegionCircle circle1(83.6331, 22.0145, 3.1);
  2274 + GSkyRegionRectangle rect1(83.6331, 22.0145, 3.1, 2.9, 43.7);
  2275 + GSkyRegionMap map3(&circle1);
  2276 + GSkyRegionMap map4(&rect1);
  2277 + test_assert(!map3.map().is_empty(), "Test map() method of circle region constructor");
  2278 + test_assert(!map4.map().is_empty(), "Test map() method of rectangular region constructor");
2175 2279
2176 - // Load reference region map (a mask centred on (RA,Dec)=(0,0) with radius 0.3deg)  
2177 - GSkyRegionMap regmap(sky_region_map); 2280 + // Test copy constructor
  2281 + GSkyRegionMap map5(map2);
  2282 + test_assert(!map5.map().is_empty(), "Test map() method of copy constructor");
2178 2283
2179 - // Set reference directions and regions  
2180 - GSkyDir refdir_radeczerozero = GSkyDir();  
2181 - GSkyDir refdir_radeclargeshift = GSkyDir();  
2182 - GSkyDir refdir_radecsmallshift = GSkyDir();  
2183 - refdir_radeczerozero.radec_deg(0.0,0.0);  
2184 - refdir_radeclargeshift.radec_deg(2.0,0.0);  
2185 - refdir_radecsmallshift.radec_deg(0.3,0.0); 2284 + // Test assignment operator
  2285 + GSkyRegionMap map6;
  2286 + map6 = map5;
  2287 + test_assert(!map6.map().is_empty(), "Test map() method of copy constructor");
2186 2288
2187 - // Test contains dirs  
2188 - test_assert(regmap.contains(refdir_radeczerozero),"test for direction containment");  
2189 - test_assert(!regmap.contains(refdir_radeclargeshift),"test2 for direction containment"); 2289 + // Test clone method
  2290 + GSkyRegionMap* map7 = map6.clone();
  2291 + test_assert(!map7->map().is_empty(), "Test map() method of copy constructor");
  2292 + delete map7;
2190 2293
  2294 + // Test constructor error modes
2191 2295
2192 - // Test circles  
2193 - GSkyRegionCircle inregion(refdir_radeczerozero,0.2);  
2194 - GSkyRegionCircle outregion(refdir_radeclargeshift,0.2);  
2195 - GSkyRegionCircle overregion(refdir_radecsmallshift,0.3); 2296 + // Test assignment methods
  2297 + GSkyRegionMap map8;
  2298 + map8.map(skymap);
  2299 + test_assert(!map8.map().is_empty(), "Test map() method");
2196 2300
2197 - // Test contains regions  
2198 - test_assert(regmap.contains(inregion),"test for region containment");  
2199 - test_assert(!regmap.contains(outregion),"test2 for region containment"); 2301 + // Test solid angle computation
  2302 + GSkyRegionMap map9(sky_region_map);
  2303 + double ref = 8.72406098e-05 ;
  2304 + test_value(map9.solidangle(), ref, "Test solid angle computation");
2200 2305
2201 - // Test overlaps regions  
2202 - test_assert(regmap.overlaps(inregion),"test for region overlap");  
2203 - test_assert(regmap.overlaps(overregion),"test2 for region overlap"); 2306 + // Test sky direction contains() method
  2307 + GSkyDir test_dir;
  2308 + test_dir.radec_deg(0.0, 0.0);
  2309 + test_assert(map9.contains(test_dir), "Test whether (0,0) lies inside map");
  2310 + test_dir.radec_deg(0.29, 0.0);
  2311 + test_assert(map9.contains(test_dir), "Test whether (0.29,0) lies inside map");
  2312 + test_dir.radec_deg(0.0,-0.29);
  2313 + test_assert(map9.contains(test_dir), "Test whether (0,-0.29) lies inside circle");
  2314 + test_dir.radec_deg(0.0, 0.29);
  2315 + test_assert(map9.contains(test_dir), "Test whether (0,0.29) lies inside circle");
  2316 + test_dir.radec_deg(0.3, 0.3);
  2317 + test_assert(!map9.contains(test_dir), "Test whether (0.3,0.3) lies outside circle");
  2318 + test_dir.radec_deg(0.31, 0.0);
  2319 + test_assert(!map9.contains(test_dir), "Test whether (0.31,0) lies outside circle");
  2320 + test_dir.radec_deg(-0.31, 0.0);
  2321 + test_assert(!map9.contains(test_dir), "Test whether (-0.31,0) lies outside circle");
2204 2322
  2323 + // Test region contains() and overlaps() methods for circle
  2324 + GSkyRegionCircle circle2(0.0, 0.0, 0.28);
  2325 + GSkyRegionCircle circle3(0.0, 0.0, 0.31);
  2326 + GSkyRegionCircle circle4(0.0, 0.6, 0.3);
  2327 + test_assert(map9.contains(circle2), "Test whether circle is contained in map");
  2328 + test_assert(!map9.contains(circle3), "Test whether circle is not contained in map");
  2329 + test_assert(map9.overlaps(circle3), "Test whether map overlaps with circle");
  2330 + test_assert(!map9.overlaps(circle4), "Test whether map does not overlap with circle");
2205 2331
2206 - // Test rectangles  
2207 - GSkyRegionRectangle inrect(refdir_radeczerozero, 0.3, 0.3, 0);  
2208 - GSkyRegionRectangle outrect(refdir_radeclargeshift, 0.3, 0.3, 0);  
2209 - GSkyRegionRectangle overrect(refdir_radecsmallshift, 0.3, 0.3, 0); 2332 + // Test region contains() and overlaps() methods for rectangles
  2333 + GSkyRegionRectangle rect2(0.0, 0.0, 0.42, 0.42, 45.0);
  2334 + GSkyRegionRectangle rect3(0.0, 0.0, 0.44, 0.44, 45.0);
  2335 + GSkyRegionRectangle rect4(0.0, 6.0, 0.42, 0.42, 45.0);
  2336 + test_assert(map9.contains(rect2), "Test whether rectangle is contained in map");
  2337 + test_assert(!map9.contains(rect3), "Test whether rectangle is not contained in map");
  2338 + test_assert(map9.overlaps(rect3), "Test whether map overlaps with rectangle");
  2339 + test_assert(!map9.overlaps(rect4), "Test whether map does not overlap with rectangle");
  2340 +
  2341 + // Test region contains() and overlaps() methods for maps
  2342 + GSkyRegionMap map_circle2(&circle2);
  2343 + GSkyRegionMap map_circle3(&circle3);
  2344 + GSkyRegionMap map_circle4(&circle4);
  2345 + test_assert(map9.contains(map_circle2), "Test whether map is contained in circle");
  2346 + test_assert(!map9.contains(map_circle3), "Test whether map is not contained in circle");
  2347 + test_assert(map9.overlaps(map_circle3), "Test whether circle overlaps with map");
  2348 + test_assert(!map9.overlaps(map_circle4), "Test whether circle does not overlap with map");
2210 2349
2211 - // Test contains regions  
2212 - test_assert(regmap.contains(inrect),"test for region containment");  
2213 - test_assert(!regmap.contains(outrect),"test2 for region containment"); 2350 + // Test print() method
  2351 + test_assert(!map9.print().empty(), "Test whether print() method returns something");
2214 2352
2215 - // Test overlaps regions  
2216 - test_assert(regmap.overlaps(inrect),"test for region overlap");  
2217 - test_assert(regmap.overlaps(overrect),"test2 for region overlap"); 2353 + // Test read() and write() methods
  2354 + // Not implemented
2218 2355
  2356 + // Test clear method
  2357 + map9.clear();
  2358 + test_assert(map9.map().is_empty(), "Test map() method after clear()");
2219 2359
2220 // Exit test 2360 // Exit test
2221 return; 2361 return;