gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master c8cc907 2/2: Crop: input polygon not sorted by


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master c8cc907 2/2: Crop: input polygon not sorted by default, must use --polygonsort
Date: Sun, 29 Mar 2020 12:15:42 -0400 (EDT)

branch: master
commit c8cc9074933792334e69b9306d385ebae2cb5db3
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Crop: input polygon not sorted by default, must use --polygonsort
    
    Until now, polygon sorting was done by default and the users had to use the
    `--polygonnosort' option to disable it. But this is very un-intuitive,
    especially when the input is a concave polygon (where the sorted result may
    be different). It is just necessary to make sure the polygon's orientation
    is counterclockwise.
    
    With this commit, the added functions in the previous commit are used to
    reveerse the input polygon vertices into a counter-clockwise orientation by
    default (if necessary!), but it will not re-arrange the polygon vertices
    beyond that. If the user knows that their points may not be sorted properly
    and would like to have the old behavior of sorting the vertices, they can
    use the new `--polygonsort' option.
    
    While doing this, I also cleaned up the two newly added functions
    (`gal_polygon_is_counterclockwise' and `gal_polygon_to_counterclockwise')
    of the previous commit. In particular, since the output of
    `gal_polygon_is_counterclockwise' is a binary, the `switch' statement was
    replaced with a simple `if' statement.
    
    This completes task #15578.
---
 NEWS               |  24 +++++++------
 bin/crop/args.h    |   8 ++---
 bin/crop/main.h    |   2 +-
 bin/crop/onecrop.c |  15 ++++----
 bin/crop/ui.h      |   2 +-
 doc/gnuastro.texi  |  72 +++++++++++++++++++------------------
 lib/polygon.c      | 103 +++++++++++++++++++++++------------------------------
 7 files changed, 109 insertions(+), 117 deletions(-)

diff --git a/NEWS b/NEWS
index 582145a..9d44ada 100644
--- a/NEWS
+++ b/NEWS
@@ -19,12 +19,12 @@ See the end of the file for license conditions.
 
   Crop:
    --polygon: can now also crop concave polygons (when atleast one inner
-     angle is more than 180 degrees).
-   --polygonnosort: Don't sort the given set of vertices to the `--polygon'
-     option. For a concave polyton, this is redundant, but for a convex
-     polygon, this option may be necessary because there is no unique
-     solution and if automatic sorting is not disabled, the output polygon
-     may not correspond to what you wanted (the vertices will the correct).
+     angle is more than 180 degrees). Concave polygons occur a lot in deep
+     astronomical imaging: in the shape of the deepest regions.
+   --polygonsort: Sort the given set of vertices to the `--polygon'
+     option. For a concave polyton, the sorting will be correct, but for a
+     convex polygon, there is no unique solution/sorting, so it may not be
+     what you expect, see the manual.
 
   Fits:
    --datasum: Calculate and print the given HDU's "datasum" to stdout.
@@ -53,8 +53,10 @@ See the end of the file for license conditions.
    - GAL_SPECLINES_INVALID_MAX: Total number of spectral lines, plus 1.
    - GAL_ARITHMETIC_OP_QUANTILE: operator for `gal_arithmetic'.
    - gal_txt_trim_space: trim white space before and after a string.
-   - gal_polygon_isconvex: identify if a polygon is convex or concave.
-   - gal_polygon_isinside: if point is inside polygon (convex or concave).
+   - gal_polygon_is_convex: identify if a polygon is convex or concave.
+   - gal_polygon_is_inside: if point is inside polygon (convex or concave).
+   - gal_polygon_is_counterclockwise: check if polygon is counter-clockwise.
+   - gal_polygon_to_counterclockwise: convert to counter-clockwise if it isn't.
 
 ** Removed features
 
@@ -77,7 +79,9 @@ See the end of the file for license conditions.
      printing the problematic string and its location.
 
   Crop:
-   - `--polygonout' is the new name for `--outpolygon'. Having `polygon' at
+   --polygon: by default it will no longer attempt to sort the polygon
+     vertices, sorting can be requested with the new `--polygonsort' option.
+   --polygonout: is the new name for `--outpolygon'. Having `polygon' at
      the start of the option name, makes it easier to find in the help list
      and also to understand generally.
 
@@ -90,7 +94,7 @@ See the end of the file for license conditions.
      extensions will be measured over all the tiles.
 
   Library:
-   - gal_polygon_isinside_convex: new name for `gal_polygon_pin'.
+   - gal_polygon_is_inside_convex: new name for `gal_polygon_pin'.
 
 ** Bugs fixed
   bug #57300: MakeCatalog memory crash when input dataset has units.
diff --git a/bin/crop/args.h b/bin/crop/args.h
index 1105af4..1c03781 100644
--- a/bin/crop/args.h
+++ b/bin/crop/args.h
@@ -281,13 +281,13 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_SET
     },
     {
-      "polygonnosort",
-      UI_KEY_POLYGONNOSORT,
+      "polygonsort",
+      UI_KEY_POLYGONSORT,
       0,
       0,
-      "Don't sort polygon vertices (are anticlockwise).",
+      "Sort polygon vertices as counter-clockwise.",
       UI_GROUP_REGION,
-      &p->polygonnosort,
+      &p->polygonsort,
       GAL_OPTIONS_NO_ARG_TYPE,
       GAL_OPTIONS_RANGE_0_OR_1,
       GAL_OPTIONS_NOT_MANDATORY,
diff --git a/bin/crop/main.h b/bin/crop/main.h
index 6620098..b167a5a 100644
--- a/bin/crop/main.h
+++ b/bin/crop/main.h
@@ -97,7 +97,7 @@ struct cropparams
   char                *section;  /* Section string.                       */
   char                *polygon;  /* Input string of polygon vertices.     */
   uint8_t           polygonout;  /* ==1: Keep the inner polygon region.   */
-  uint8_t        polygonnosort;  /* Don't sort polygon vertices.          */
+  uint8_t          polygonsort;  /* Don't sort polygon vertices.          */
 
   /* Internal */
   size_t                 numin;  /* Number of input images.               */
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index c984f26..014dbe0 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -351,7 +351,6 @@ polygonmask(struct onecropparams *crp, void *array, long 
*fpixel_i,
   int (*isinside)(double *, double *, size_t);
   size_t i, *ordinds, size=s0*s1, nvertices=crp->p->nvertices;
 
-
   /* First of all, allocate enough space to put a copy of the input
      coordinates (we will be using that after sorting in an
      anti-clickwise manner.) */
@@ -364,13 +363,15 @@ polygonmask(struct onecropparams *crp, void *array, long 
*fpixel_i,
     error(EXIT_FAILURE, errno, "%s: allocating %zu bytes for ordinds",
           __func__, nvertices*sizeof *ordinds);
 
-
-  /* Find the order of the polygons and put the elements in the proper
-     order.*/
-  if(crp->p->polygonnosort)
-    for(i=0;i<crp->p->nvertices;++i) ordinds[i]=i;
-  else
+  /* If the user wants to sort the edges, do it, if not, make sure its in
+     counter-clockwise orientation. */
+  if(crp->p->polygonsort)
     gal_polygon_ordered_corners(crp->ipolygon, crp->p->nvertices, ordinds);
+  else
+    {
+      for(i=0;i<crp->p->nvertices;++i) ordinds[i]=i;
+      gal_polygon_to_counterclockwise(crp->ipolygon, crp->p->nvertices);
+    }
 
   /* Fill the final polygon vertice positions within `ipolygon' and also
      the fpixel_i coordinates from all the vertices to bring them into the
diff --git a/bin/crop/ui.h b/bin/crop/ui.h
index 728a15b..daf22aa 100644
--- a/bin/crop/ui.h
+++ b/bin/crop/ui.h
@@ -69,7 +69,7 @@ enum option_keys_enum
   UI_KEY_HSTARTWCS,
   UI_KEY_HENDWCS,
   UI_KEY_POLYGONOUT,
-  UI_KEY_POLYGONNOSORT,
+  UI_KEY_POLYGONSORT,
   UI_KEY_CHECKCENTER,
 };
 
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 1bf8882..6732ae5 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9732,27 +9732,9 @@ If you want an even sided crop, you can run Crop 
afterwards with @option{--secti
 @item -l STR
 @itemx --polygon=STR
 String of vertices to define a polygon to crop.
-For a convex polygon, the vertices can be in any order: Crop will 
automatically sort them in an anti-clockwise fashion and use it.
-It also attempts to sort the vertices of a concave polygon, but in a concave 
polygon, there is no unique way to sort the vertices, so the output may not be 
what you want.
-In such scenarios, it may be better to ensure that the list of vertices is 
already sorted the way you like in an anti-clockwise manner and use the 
@option{--polygonnosort} option to disable the automatic sorting.
-
-@cindex Convex polygons
-@cindex Concave polygons
-@cindex Polygons, Convex
-@cindex Polygons, Concave
-Polygons come in two classes: convex and concave (or generally, non-convex!), 
see below for a demonstration.
-Convex polygons are those where all inner angles are less than 180 degrees.
-By contrast, a convex polygon is one where an inner angle may be more than 180 
degress.
-
-@example
-            Concave Polygon        Convex Polygon
-
-             D --------C          D------------- C
-              \        |        E /              |
-               \E      |          \              |
-               /       |           \             |
-              A--------B             A ----------B
-@end example
+The vertices are used to define the polygon in the same order given to this 
option.
+When the vertices are not necessarily ordered in the proper order (for example 
one vertice in a square comes after its diagonal opposite), you can add the 
@option{--polygonsort} option which will attempt to sort the vertices before 
cropping.
+Note that for concave polygons, sorting is not recommended because there is no 
unique solution, for more, see the description under @option{--polygonsort}.
 
 This option can be used both in the image and WCS modes, see @ref{Crop modes}.
 The cropped image will be the size of the rectangular region that completely 
encompasses the polygon.
@@ -9811,10 +9793,27 @@ This can lead to a very large area if large surveys 
like COSMOS are used.
 So Crop will abort and notify you.
 In such cases, it is best to crop out the larger region you want, then mask 
the smaller region with this option.
 
-@item --polygonnosort
-Don't sort the given set of vertices to the @option{--polygon} option.
-For a concave polyton, this is redundant, but for a convex polygon, this 
option may be necessary because there is no unique for a concave polygon.
-If automatic sorting is not disabled, the output polygon may not correspond to 
what you had in mind, the vertices will be correct though.
+@item --polygonsort
+Sort the given set of vertices to the @option{--polygon} option.
+For a concave polyton it will sort the vertices correctly, however for a 
convex polygon it there is no unique sorting, so be careful because the crop 
may not be what you expected.
+
+@cindex Convex polygons
+@cindex Concave polygons
+@cindex Polygons, Convex
+@cindex Polygons, Concave
+Polygons come in two classes: convex and concave (or generally, non-convex!), 
see below for a demonstration.
+Convex polygons are those where all inner angles are less than 180 degrees.
+By contrast, a convex polygon is one where an inner angle may be more than 180 
degress.
+
+@example
+            Concave Polygon        Convex Polygon
+
+             D --------C          D------------- C
+              \        |        E /              |
+               \E      |          \              |
+               /       |           \             |
+              A--------B             A ----------B
+@end example
 
 @item -s STR
 @itemx --section=STR
@@ -23192,7 +23191,7 @@ The @code{GAL_POLYGON_MAX_CORNERS} macro is defined so 
there will be no need to
 Since we are dealing with pixels, the polygon can't really have too many 
vertices.
 @end deftypefun
 
-@deftypefun int gal_polygon_is_convex(double @code{*v}, size_t @code{n})
+@deftypefun int gal_polygon_is_convex (double @code{*v}, size_t @code{n})
 Returns @code{1} if the polygon is convex with vertices defined by @code{v} 
and @code{0} if it is a concave polygon.
 Note that the vertices of the polygon should be sorted in an anti-clockwise 
manner.
 @end deftypefun
@@ -23202,7 +23201,7 @@ Find the area of a polygon with vertices defined in 
@code{v}.
 @code{v} points to an array of doubles which keep the positions of the 
vertices such that @code{v[0]} and @code{v[1]} are the positions of the first 
vertice to be considered.
 @end deftypefun
 
-@deftypefun int gal_polygon_is_inside(double @code{*v}, double @code{*p}, 
size_t @code{n})
+@deftypefun int gal_polygon_is_inside (double @code{*v}, double @code{*p}, 
size_t @code{n})
 Returns @code{0} if point @code{p} in inside a polygon, either convex or 
concave.
 The vertices of the polygon are defined by @code{v} and @code{0} otherwise, 
they have to be ordered in an anti-clockwise manner.
 This function uses the 
@url{https://en.wikipedia.org/wiki/Point_in_polygon#Winding_number_algorithm, 
winding number algorithm}, to check the points.
@@ -23220,16 +23219,19 @@ Similar to @code{gal_polygon_is_inside_convex}, 
except that if the point @code{p
 one of the edges of a polygon, this will return @code{0}.
 @end deftypefun
 
-@deftypefun int gal_polygon_is_counterclockwise(double @code{*v}, size_t 
@code{n})
-Returns  @code{1} if polygon is sorted in anti-clockwise and @code{0} 
otherwise.
-It uses winding which defines the relative order in which the vertices of a 
polygon are listed to determine the orientation of vertices.
-If orientation is positive vertices are in clockwise direction, else is 
negative for anti-clockwise direction. Zero sum implies a figure like @code{8}, 
with equal orientation in both direction.
+@deftypefun int gal_polygon_is_counterclockwise (double @code{*v}, size_t 
@code{n})
+Returns  @code{1} if the sorted polygon has a counter-clockwise orientation 
and @code{0} otherwise.
+This function uses the concept of ``winding'', which defines the relative 
order in which the vertices of a polygon are listed to determine the 
orientation of vertices.
+For complex polygons (where edges, or sides, intersect), the most significant 
orientation is returned.
+In a complex polygon, when the alternative windings are equal (for example an 
@code{8}-shape) it will return @code{1} (as if it was counter-clockwise).
+Note that the polygon vertices have to be sorted before calling this function.
 @end deftypefun
 
-@deftypefun int gal_polygon_to_counterclockwise(double @code{*v}, size_t 
@code{n})
-Arrange the vertices of polygon in counter-clockwise direction if input is in 
clockwise direction, otherwise do nothing.
-It uses @code{gal_polygon_is_counterclockwise} to determine the orientation of 
polygons.
-Return @code{1} on successful execution, @code{0} otherwise.
+@deftypefun int gal_polygon_to_counterclockwise (double @code{*v}, size_t 
@code{n})
+Arrange the vertices of the sorted polygon in place, to be in a 
counter-clockwise direction.
+If the input polygon already has a counter-clockwise direction it won't touch 
the input.
+The return value is @code{1} on successful execution.
+This function is just a wrapper over @code{gal_polygon_is_counterclockwise}, 
and will reverse the order of the vertices when necessary necessary.
 @end deftypefun
 
 @deftypefun void gal_polygon_clip (double @code{*s}, size_t @code{n}, double 
@code{*c}, size_t @code{m}, double @code{*o}, size_t @code{*numcrn})
diff --git a/lib/polygon.c b/lib/polygon.c
index c0fe4b1..33580a5 100644
--- a/lib/polygon.c
+++ b/lib/polygon.c
@@ -31,7 +31,9 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gsl/gsl_sort.h>
 
+#include <gnuastro/pointer.h>
 #include <gnuastro/polygon.h>
+#include <gnuastro/permutation.h>
 
 
 
@@ -360,19 +362,19 @@ gal_polygon_ppropin(double *v, double *p, size_t n)
 
 
 
-/* This function uses the concept of winding, which defines the
-   relative order in which the vertices of a polygon are
-   listed to determine the orientation of vertices. If orientation
-   is positive vertices are in clockwise direction, else is negative
-   for counter-clockwise direction. Zero sum implies a figure like 8, with
-   equal orientation in both direction.
+/* This function uses the concept of winding, which defines the relative
+   order in which the vertices of a polygon are listed to determine the
+   orientation of vertices. If orientation is positive vertices are in
+   clockwise direction, else is negative for counter-clockwise
+   direction. Zero sum implies a figure like 8, with equal orientation in
+   both direction.
 
    See the link below for a detailed description:
    "https://www.element84.com/blog/determining-the-winding-of-a-
-    polygon-given-as-a-set-of-ordered-points"
+   polygon-given-as-a-set-of-ordered-points"
 
-   return 1: sorted in counter-clockwise order.
-   return 0: sorted clockwise order or weight of orientation is equal.
+   return 1: sorted in counter-clockwise order or equal orientation.
+   return 0: sorted clockwise order.
    */
 int
 gal_polygon_is_counterclockwise(double *v, size_t n)
@@ -386,18 +388,17 @@ gal_polygon_is_counterclockwise(double *v, size_t n)
       j=i++;
     }
 
-  if(sum>0) return 0;
-  else      return 1;
-
+  return sum>0 ? 0 : 1;
 }
 
 
 
 
 
-/* This function checks if the vertices are actually sorted in
-   the counterclockwise. If they are do nothing, otherwise if
-   they are clockwise, convert them to counter-clockwise direction
+/* This function checks if the vertices are actually sorted in the
+   counterclockwise. If they are do nothing, otherwise if they are
+   clockwise, convert them to counter-clockwise direction
+
    return 1: success
    return 0: error
    */
@@ -407,58 +408,42 @@ gal_polygon_to_counterclockwise(double *v, size_t n)
   size_t i, j=0;
   size_t *permutation;
   gal_data_t *temp=NULL;
-  int orientation=gal_polygon_is_counterclockwise(v, n);
 
-  switch(orientation)
+  /* Operation only necesssary when polygon isn't counter-clockwise. */
+  if(gal_polygon_is_counterclockwise(v, n)==0)
     {
-      /* Polygon is already sorted in counterclockwise order, do nothing */
-      case 1:
-        return 1;
-
-      /* Polygon is sorted in clockwise order, convert to counterclockwise
-        direction. */
-      case 0:
-        /* Allocate space for permutation array, which stores the order of
-          index in which the vertices are to be ordered for a
-          counter-clockwise direction. */
-        permutation=gal_pointer_allocate(GAL_TYPE_SIZE_T, 2*n, 0,
-                                          __func__, "permutation");
-        for(i=0; i<=2*n-1;)
-          {
-            /* Below sequence of steps ensures that the permutation has
-               indexes reversed but in order (x,y). Simple reversing would
-               have turned it in (y,x) format. */
-            j++;
-            permutation[j]  =(2*n-1-i++);
-            permutation[j-1]=(2*n-1-i++);
-            j++;
-          }
+      /* Allocate space for permutation array, which stores the order of
+         index in which the vertices are to be ordered for a
+         counter-clockwise direction. */
+      permutation=gal_pointer_allocate(GAL_TYPE_SIZE_T, 2*n, 0,
+                                       __func__, "permutation");
+      for(i=0; i<=2*n-1;)
+        {
+          /* Below sequence of steps ensures that the permutation has
+             indexes reversed but in order (x,y). Simple reversing would
+             have turned it in (y,x) format. */
+          j++;
+          permutation[j]  =(2*n-1-i++);
+          permutation[j-1]=(2*n-1-i++);
+          j++;
+        }
 
-        /* Put the vertices in the `gal_data_t' object */
-        temp=gal_data_alloc(v, GAL_TYPE_FLOAT64, 1, &n, NULL, 0,
+      /* Put the vertices in the `gal_data_t' object */
+      temp=gal_data_alloc(v, GAL_TYPE_FLOAT64, 1, &n, NULL, 0,
                           -1, 0, NULL, NULL, NULL);
 
-        /* Apply permutations to just reverse the order of clockwise to
-          counter-clockwise. */
-        gal_permutation_apply(temp, permutation);
+      /* Apply permutations to just reverse the order of clockwise to
+         counter-clockwise. */
+      gal_permutation_apply(temp, permutation);
 
-        temp->array=NULL;
-
-        /* Free allocated spaces. */
-        gal_data_free(temp);
-        free(permutation);
-        return 1;
-
-
-      default:
-        error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s"
-          "polygon orientation code %d not recognized",
-          __func__, PACKAGE_BUGREPORT, orientation);
-        return 0;
+      /* Free allocated spaces. */
+      temp->array=NULL;
+      free(permutation);
+      gal_data_free(temp);
     }
 
-  return 0;
-
+  /* Return value, so far it will always return 1. */
+  return 1;
 }
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]