Commit 3460fe3701b612145b46e022de2769136004de28
1 parent
bed0350a
Adjust sky rectangle code (#3248)
Showing
5 changed files
with
99 additions
and
83 deletions
include/GSkyRegionRect.hpp
| ... | ... | @@ -30,10 +30,8 @@ |
| 30 | 30 | /* __ Includes ___________________________________________________________ */ |
| 31 | 31 | #include <vector> |
| 32 | 32 | #include <string> |
| 33 | -//#include "GMath.hpp" | |
| 34 | 33 | #include "GSkyDir.hpp" |
| 35 | 34 | #include "GSkyRegion.hpp" |
| 36 | -//#include "GTools.hpp" | |
| 37 | 35 | |
| 38 | 36 | /* __ Forward declarations _______________________________________________ */ |
| 39 | 37 | ... | ... |
src/sky/GSkyRegionCircle.cpp
| ... | ... | @@ -28,9 +28,10 @@ |
| 28 | 28 | #ifdef HAVE_CONFIG_H |
| 29 | 29 | #include <config.h> |
| 30 | 30 | #endif |
| 31 | +#include "GTools.hpp" | |
| 31 | 32 | #include "GSkyRegionCircle.hpp" |
| 32 | 33 | #include "GSkyRegionRect.hpp" |
| 33 | -#include "GTools.hpp" | |
| 34 | +#include "GSkyRegionMap.hpp" | |
| 34 | 35 | |
| 35 | 36 | /* __ Method name definitions ____________________________________________ */ |
| 36 | 37 | #define G_RADIUS "GSkyRegionCircle::radius(double&)" |
| ... | ... | @@ -70,10 +71,10 @@ GSkyRegionCircle::GSkyRegionCircle(void) : GSkyRegion() |
| 70 | 71 | * @brief Direction constructor |
| 71 | 72 | * |
| 72 | 73 | * @param[in] centre Centre sky direction. |
| 73 | - * @param[in] radius Region radius [deg]. | |
| 74 | + * @param[in] radius Region radius (degrees). | |
| 74 | 75 | ***************************************************************************/ |
| 75 | -GSkyRegionCircle::GSkyRegionCircle(const GSkyDir& centre, const double& radius) : | |
| 76 | - GSkyRegion() | |
| 76 | +GSkyRegionCircle::GSkyRegionCircle(const GSkyDir& centre, | |
| 77 | + const double& radius) : GSkyRegion() | |
| 77 | 78 | { |
| 78 | 79 | // Initialise members |
| 79 | 80 | init_members(); |
| ... | ... | @@ -93,11 +94,12 @@ GSkyRegionCircle::GSkyRegionCircle(const GSkyDir& centre, const double& radius) |
| 93 | 94 | /***********************************************************************//** |
| 94 | 95 | * @brief Direction constructor |
| 95 | 96 | * |
| 96 | - * @param[in] ra Right Ascension of region centre [deg]. | |
| 97 | - * @param[in] dec Declination of region centre [deg]. | |
| 98 | - * @param[in] radius Region radius [deg]. | |
| 97 | + * @param[in] ra Right Ascension of region centre (degrees). | |
| 98 | + * @param[in] dec Declination of region centre (degrees). | |
| 99 | + * @param[in] radius Region radius (degrees). | |
| 99 | 100 | ***************************************************************************/ |
| 100 | -GSkyRegionCircle::GSkyRegionCircle(const double& ra, const double& dec, | |
| 101 | +GSkyRegionCircle::GSkyRegionCircle(const double& ra, | |
| 102 | + const double& dec, | |
| 101 | 103 | const double& radius) : GSkyRegion() |
| 102 | 104 | { |
| 103 | 105 | // Initialise members |
| ... | ... | @@ -243,7 +245,7 @@ GSkyRegionCircle* GSkyRegionCircle::clone(void) const |
| 243 | 245 | /***********************************************************************//** |
| 244 | 246 | * @brief Set radius of circular region |
| 245 | 247 | * |
| 246 | - * @param[in] radius Radius [deg]. | |
| 248 | + * @param[in] radius Radius (degrees). | |
| 247 | 249 | * |
| 248 | 250 | * @exception GException::invalid_argument |
| 249 | 251 | * Radius value is less than 0. |
| ... | ... | @@ -256,10 +258,9 @@ void GSkyRegionCircle::radius(const double& radius) |
| 256 | 258 | // Check if radius is valid |
| 257 | 259 | if (radius < 0.0) { |
| 258 | 260 | std::string msg = |
| 259 | - "A radius of "+gammalib::str(radius)+" degrees has been" | |
| 260 | - " specified for a circular sky region.\n" | |
| 261 | - "The radius of a circular sky region can't be less than 0" | |
| 262 | - " degrees."; | |
| 261 | + "A negative radius of "+gammalib::str(radius)+" degrees has been " | |
| 262 | + "specified for a circular sky region. Please specify a " | |
| 263 | + "non-negative radius."; | |
| 263 | 264 | throw GException::invalid_argument(G_RADIUS, msg); |
| 264 | 265 | } |
| 265 | 266 | |
| ... | ... | @@ -296,8 +297,7 @@ void GSkyRegionCircle::read(const std::string& line) |
| 296 | 297 | if (region_def.find("circle") == std::string::npos) { |
| 297 | 298 | std::string msg = |
| 298 | 299 | "Unable to find the key word \"circle\" in provided string" |
| 299 | - " \""+line+"\".\n" | |
| 300 | - "The \"circle\" key word is mandatory."; | |
| 300 | + " \""+line+"\". The \"circle\" key word is mandatory."; | |
| 301 | 301 | throw GException::invalid_value(G_READ, msg); |
| 302 | 302 | } |
| 303 | 303 | |
| ... | ... | @@ -314,8 +314,8 @@ void GSkyRegionCircle::read(const std::string& line) |
| 314 | 314 | std::vector<std::string> values = gammalib::split(circlestring,","); |
| 315 | 315 | if (values.size() != 3) { |
| 316 | 316 | std::string msg = |
| 317 | - "Invalid number of "+gammalib::str(values.size())+" arguments" | |
| 318 | - " after the \"circle\" key word in provided string \""+line+"\".\n" | |
| 317 | + "Invalid number of "+gammalib::str(values.size())+" arguments " | |
| 318 | + "after the \"circle\" key word in provided string \""+line+"\". " | |
| 319 | 319 | "Exactly 3 arguments are expected."; |
| 320 | 320 | throw GException::invalid_value(G_READ, msg); |
| 321 | 321 | } |
| ... | ... | @@ -343,10 +343,9 @@ void GSkyRegionCircle::read(const std::string& line) |
| 343 | 343 | } |
| 344 | 344 | else { |
| 345 | 345 | std::string msg = |
| 346 | - "Unsupported coordinate system \""+system+"\" in provided string" | |
| 347 | - " \""+line+"\".\n" | |
| 348 | - "Only the following coordinate systems are supported: " | |
| 349 | - "\"fk5\", \"icrs\" and \"galactic\"."; | |
| 346 | + "Unsupported coordinate system \""+system+"\" in provided string " | |
| 347 | + "\""+line+"\". Only the following coordinate systems are " | |
| 348 | + "supported: \"fk5\", \"icrs\" and \"galactic\"."; | |
| 350 | 349 | throw GException::invalid_value(G_READ, msg); |
| 351 | 350 | } |
| 352 | 351 | |
| ... | ... | @@ -479,11 +478,11 @@ std::string GSkyRegionCircle::print(const GChatter& chatter) const |
| 479 | 478 | |
| 480 | 479 | // Append sky circle information |
| 481 | 480 | result.append("\n"+gammalib::parformat("Right Ascension of centre")); |
| 482 | - result.append(gammalib::str(m_centre.ra_deg())+" deg"); | |
| 481 | + result.append(gammalib::str(ra())+" deg"); | |
| 483 | 482 | result.append("\n"+gammalib::parformat("Declination of centre")); |
| 484 | - result.append(gammalib::str(m_centre.dec_deg())+" deg"); | |
| 483 | + result.append(gammalib::str(dec())+" deg"); | |
| 485 | 484 | result.append("\n"+gammalib::parformat("Radius")); |
| 486 | - result.append(gammalib::str(m_radius)+" deg"); | |
| 485 | + result.append(gammalib::str(radius())+" deg"); | |
| 487 | 486 | |
| 488 | 487 | } // endif: chatter was not silent |
| 489 | 488 | |
| ... | ... | @@ -539,9 +538,6 @@ bool GSkyRegionCircle::contains(const GSkyRegion& reg) const |
| 539 | 538 | // Calculate angular distance between the centres |
| 540 | 539 | double ang_dist = m_centre.dist_deg(regcirc->centre()); |
| 541 | 540 | |
| 542 | - // Calculate angular distance between the centres | |
| 543 | - double ang_dist = m_centre.dist_deg(regcirc->centre()); | |
| 544 | - | |
| 545 | 541 | // Check if the region is contained in this |
| 546 | 542 | if ((ang_dist + regcirc->radius()) <= m_radius) { |
| 547 | 543 | fully_inside = true; |
| ... | ... | @@ -557,16 +553,16 @@ bool GSkyRegionCircle::contains(const GSkyRegion& reg) const |
| 557 | 553 | dynamic_cast<const GSkyRegionRect*>(®); |
| 558 | 554 | |
| 559 | 555 | // Check containment of all edges |
| 560 | - fully_inside = contains(regrect->get_corner(0)) & | |
| 561 | - contains(regrect->get_corner(1)) & | |
| 562 | - contains(regrect->get_corner(2)) & | |
| 556 | + fully_inside = contains(regrect->get_corner(0)) && | |
| 557 | + contains(regrect->get_corner(1)) && | |
| 558 | + contains(regrect->get_corner(2)) && | |
| 563 | 559 | contains(regrect->get_corner(3)); |
| 564 | 560 | } |
| 565 | 561 | |
| 566 | 562 | // ... otherwise throw an exception |
| 567 | 563 | else { |
| 568 | 564 | throw GException::feature_not_implemented(G_CONTAINS, |
| 569 | - "Cannot compare to region type \""+reg.type()+"\" yet"); | |
| 565 | + "Cannot compare to region type \""+reg.type()+"\" yet."); | |
| 570 | 566 | } |
| 571 | 567 | |
| 572 | 568 | // Return value |
| ... | ... | @@ -581,13 +577,16 @@ bool GSkyRegionCircle::contains(const GSkyRegion& reg) const |
| 581 | 577 | * |
| 582 | 578 | * @exception GException::feature_not_implemented |
| 583 | 579 | * Regions differ in type. |
| 580 | + * | |
| 581 | + * @todo Implement checks for rectangles and maps | |
| 584 | 582 | ***************************************************************************/ |
| 585 | 583 | bool GSkyRegionCircle::overlaps(const GSkyRegion& reg) const |
| 586 | 584 | { |
| 587 | 585 | // Initialise return value |
| 588 | 586 | bool overlap = false; |
| 589 | 587 | |
| 590 | - // If other region is circle use a simple way to calculate | |
| 588 | + // If region is circle then check overlap by comparing the centre | |
| 589 | + // distances | |
| 591 | 590 | if (reg.type() == "Circle") { |
| 592 | 591 | |
| 593 | 592 | // Create circular region from reg |
| ... | ... | @@ -602,12 +601,36 @@ bool GSkyRegionCircle::overlaps(const GSkyRegion& reg) const |
| 602 | 601 | overlap = true; |
| 603 | 602 | } |
| 604 | 603 | |
| 605 | - } | |
| 604 | + } // endif: region was circle | |
| 605 | + | |
| 606 | + // ... otherwise if region is rectangle then check overlap | |
| 607 | + else if (reg.type() == "Rect") { | |
| 608 | + | |
| 609 | + // Create rectangular region from reg | |
| 610 | + const GSkyRegionRect* regrect = | |
| 611 | + dynamic_cast<const GSkyRegionRect*>(®); | |
| 612 | + | |
| 613 | + // Check overlap with circle | |
| 614 | + overlap = regrect->overlaps(*this); | |
| 615 | + | |
| 616 | + } // endif: region was rectangle | |
| 617 | + | |
| 618 | + // ... otherwise if region is map then check overlap with map | |
| 619 | + else if (reg.type() == "Map") { | |
| 620 | + | |
| 621 | + // Create map from reg | |
| 622 | + const GSkyRegionMap* regmap = | |
| 623 | + dynamic_cast<const GSkyRegionMap*>(®); | |
| 624 | + | |
| 625 | + // Check overlap with circle | |
| 626 | + overlap = regmap->overlaps(*this); | |
| 627 | + | |
| 628 | + } // endif: region was map | |
| 606 | 629 | |
| 607 | 630 | // ... otherwise throw an exception |
| 608 | 631 | else { |
| 609 | - throw GException::feature_not_implemented(G_OVERLAPS, | |
| 610 | - "Cannot compare two different region types yet"); | |
| 632 | + throw GException::feature_not_implemented(G_CONTAINS, | |
| 633 | + "Cannot compare to region type \""+reg.type()+"\" yet."); | |
| 611 | 634 | } |
| 612 | 635 | |
| 613 | 636 | // Return value | ... | ... |
src/sky/GSkyRegionRect.cpp
| ... | ... | @@ -28,7 +28,6 @@ |
| 28 | 28 | #ifdef HAVE_CONFIG_H |
| 29 | 29 | #include <config.h> |
| 30 | 30 | #endif |
| 31 | -//#include "GMath.hpp" | |
| 32 | 31 | #include "GTools.hpp" |
| 33 | 32 | #include "GSkyRegionCircle.hpp" |
| 34 | 33 | #include "GSkyRegionRect.hpp" |
| ... | ... | @@ -598,8 +597,7 @@ bool GSkyRegionRect::contains(const GSkyRegion& reg) const |
| 598 | 597 | // ... otherwise throw an exception |
| 599 | 598 | else { |
| 600 | 599 | throw GException::feature_not_implemented(G_CONTAINS, |
| 601 | - "Cannot compare rectangular region with other than rectangle or" | |
| 602 | - " circle yet."); | |
| 600 | + "Cannot compare to region type \""+reg.type()+"\" yet."); | |
| 603 | 601 | } |
| 604 | 602 | |
| 605 | 603 | // Return value |
| ... | ... | @@ -615,14 +613,15 @@ bool GSkyRegionRect::contains(const GSkyRegion& reg) const |
| 615 | 613 | * @exception GException::feature_not_implemented |
| 616 | 614 | * Regions differ in type. |
| 617 | 615 | * |
| 618 | - * @todo: - Improve implementation for rectangle-rectangle | |
| 616 | + * @todo Improve implementation for rectangle-rectangle | |
| 617 | + * @todo Implement check for map | |
| 619 | 618 | ***************************************************************************/ |
| 620 | 619 | bool GSkyRegionRect::overlaps(const GSkyRegion& reg) const |
| 621 | 620 | { |
| 622 | 621 | // Initialise return value |
| 623 | - bool is_overlapping = false; | |
| 622 | + bool overlap = false; | |
| 624 | 623 | |
| 625 | - // If other region is circle use a simple way to calculate | |
| 624 | + // If region is circle then check overlap between circle and rectangle | |
| 626 | 625 | if (reg.type() == "Circle") { |
| 627 | 626 | |
| 628 | 627 | // Create circular region from reg |
| ... | ... | @@ -641,33 +640,46 @@ bool GSkyRegionRect::overlaps(const GSkyRegion& reg) const |
| 641 | 640 | // Check extension of circle along right ascension axis |
| 642 | 641 | if (std::abs(local_centre.ra_deg()) <= (0.5 * m_width + circ_rad)) { |
| 643 | 642 | |
| 644 | - // Circle is fully contained in this rectangle | |
| 645 | - is_overlapping = true; | |
| 643 | + // Circle is overlapping with rectangle | |
| 644 | + overlap = true; | |
| 646 | 645 | } |
| 647 | 646 | } |
| 648 | - } // Region was of type "Circle" | |
| 647 | + } // endif: region was of type "Circle" | |
| 649 | 648 | |
| 649 | + // ... otherwise if region is a rectangle then check overlap between | |
| 650 | + // two rectangles | |
| 650 | 651 | else if (reg.type() == "Rect") { |
| 651 | 652 | |
| 652 | 653 | // Create rectangular region from reg |
| 653 | 654 | const GSkyRegionRect* regrect = |
| 654 | 655 | dynamic_cast<const GSkyRegionRect*>(®); |
| 655 | 656 | |
| 656 | - // Dirty kludge: compare vs map | |
| 657 | + // Dirty kludge: compare with map | |
| 657 | 658 | GSkyRegionMap regmap = GSkyRegionMap(regrect); |
| 658 | - is_overlapping = regmap.overlaps(*this); | |
| 659 | + overlap = regmap.overlaps(*this); | |
| 659 | 660 | |
| 660 | - } // Region was of type "Rect" | |
| 661 | + } // endif: region was of type "Rect" | |
| 662 | + | |
| 663 | + // ... otherwise if region is map then check overlap with map | |
| 664 | + else if (reg.type() == "Map") { | |
| 665 | + | |
| 666 | + // Create map from reg | |
| 667 | + const GSkyRegionMap* regmap = | |
| 668 | + dynamic_cast<const GSkyRegionMap*>(®); | |
| 669 | + | |
| 670 | + // Check overlap with circle | |
| 671 | + overlap = regmap->overlaps(*this); | |
| 672 | + | |
| 673 | + } // endif: region was map | |
| 661 | 674 | |
| 662 | 675 | // ... otherwise throw an exception |
| 663 | 676 | else { |
| 664 | - throw GException::feature_not_implemented(G_OVERLAPS, | |
| 665 | - "Cannot compare rectangular region with other than rectangle or" | |
| 666 | - " circle yet."); | |
| 677 | + throw GException::feature_not_implemented(G_CONTAINS, | |
| 678 | + "Cannot compare to region type \""+reg.type()+"\" yet."); | |
| 667 | 679 | } |
| 668 | 680 | |
| 669 | 681 | // Return value |
| 670 | - return is_overlapping; | |
| 682 | + return overlap; | |
| 671 | 683 | } |
| 672 | 684 | |
| 673 | 685 | ... | ... |
src/sky/GSkyRegions.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * GSkyRegions.cpp - Sky region container class * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2013-2018 by Pierrick Martin * | |
| 4 | + * copyright (C) 2013-2020 by Pierrick Martin * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -536,7 +536,7 @@ void GSkyRegions::load(const GFilename& filename) |
| 536 | 536 | coordsys = "icrs"; |
| 537 | 537 | } |
| 538 | 538 | |
| 539 | - // If region is a circle | |
| 539 | + // If region is a circle then read circle | |
| 540 | 540 | if (std::string::npos != fileline.find("circle")) { |
| 541 | 541 | |
| 542 | 542 | // Create instance of GSkyRegion object |
| ... | ... | @@ -558,32 +558,14 @@ void GSkyRegions::load(const GFilename& filename) |
| 558 | 558 | region.read(newfileline); |
| 559 | 559 | append(region); |
| 560 | 560 | } |
| 561 | - } | |
| 562 | 561 | |
| 563 | - // If region is a rectangle | |
| 564 | - if (std::string::npos != fileline.find("box")) { | |
| 562 | + } // endif: region was circle | |
| 565 | 563 | |
| 566 | - // Create instance of GSkyRegion object | |
| 567 | - GSkyRegionRect region; | |
| 568 | - | |
| 569 | - // If coordinate system and region defined on the same line | |
| 570 | - if ((std::string::npos != fileline.find("fk5")) || | |
| 571 | - (std::string::npos != fileline.find("icrs")) || | |
| 572 | - (std::string::npos != fileline.find("galactic"))) { | |
| 573 | - region.read(fileline); | |
| 574 | - append(region); | |
| 575 | - } | |
| 576 | - | |
| 577 | - // else, prepend the coordinate system | |
| 578 | - else { | |
| 579 | - coordsys = "icrs"; | |
| 580 | - } | |
| 581 | - | |
| 582 | - // If region is a circle | |
| 583 | - if (std::string::npos != fileline.find("circle")) { | |
| 564 | + // ... otherwise if region is a box then read rectangle | |
| 565 | + else if (std::string::npos != fileline.find("box")) { | |
| 584 | 566 | |
| 585 | 567 | // Create instance of GSkyRegion object |
| 586 | - GSkyRegionCircle region; | |
| 568 | + GSkyRegionRect region; | |
| 587 | 569 | |
| 588 | 570 | // If coordinate system and region defined on the same line |
| 589 | 571 | if ((std::string::npos != fileline.find("fk5")) || |
| ... | ... | @@ -601,8 +583,10 @@ void GSkyRegions::load(const GFilename& filename) |
| 601 | 583 | region.read(newfileline); |
| 602 | 584 | append(region); |
| 603 | 585 | } |
| 604 | - } | |
| 605 | - } | |
| 586 | + | |
| 587 | + } // endif: region was box | |
| 588 | + | |
| 589 | + } // endwhile: looped over file | |
| 606 | 590 | |
| 607 | 591 | // Close file |
| 608 | 592 | ds9file.close(); | ... | ... |
test/test_GSky.cpp
| ... | ... | @@ -1913,7 +1913,7 @@ void TestGSky::test_GSkyRegionRect(void) |
| 1913 | 1913 | test_try("Test posang assignment after"); |
| 1914 | 1914 | try { |
| 1915 | 1915 | GSkyRegionRect rect(refdir_radeczerozero, ref_width, ref_height, ref_pa_deg); |
| 1916 | - rect.posang_deg(-1.0); | |
| 1916 | + rect.posang(-1.0); | |
| 1917 | 1917 | test_try_success(); |
| 1918 | 1918 | } |
| 1919 | 1919 | catch (GException::invalid_argument &e) { |
| ... | ... | @@ -1932,7 +1932,7 @@ void TestGSky::test_GSkyRegionRect(void) |
| 1932 | 1932 | double check_height = rect.width(); |
| 1933 | 1933 | test_value(ref_height, check_height, 1.0e-10, "Test height assignment"); |
| 1934 | 1934 | |
| 1935 | - double check_pa_deg = rect.posang_deg(); | |
| 1935 | + double check_pa_deg = rect.posang(); | |
| 1936 | 1936 | test_value(ref_pa_deg, check_pa_deg, 1.0e-10, "Test posang assignment"); |
| 1937 | 1937 | |
| 1938 | 1938 | // Check solid angle assignment |
| ... | ... | @@ -1941,7 +1941,7 @@ void TestGSky::test_GSkyRegionRect(void) |
| 1941 | 1941 | test_value(solidangle_check, solidangle, 1.0e-10, "Test solid angle"); |
| 1942 | 1942 | |
| 1943 | 1943 | // Initialise objects |
| 1944 | - GSkyDir refdir_radeczerozero = GSkyDir(); | |
| 1944 | + refdir_radeczerozero = GSkyDir(); | |
| 1945 | 1945 | GSkyDir test_dir_0 = GSkyDir(); |
| 1946 | 1946 | GSkyDir test_dir_1 = GSkyDir(); |
| 1947 | 1947 | GSkyDir test_dir_2 = GSkyDir(); |
| ... | ... | @@ -2050,7 +2050,6 @@ void TestGSky::test_GSkyRegionRect(void) |
| 2050 | 2050 | test_assert(refregion.overlaps(refregion_raoffset),"test3 for overlap"); |
| 2051 | 2051 | test_assert(!refregion.overlaps(refregion_decpole),"test4 for overlap"); |
| 2052 | 2052 | |
| 2053 | - | |
| 2054 | 2053 | // Exit test |
| 2055 | 2054 | return; |
| 2056 | 2055 | } | ... | ... |