summaryrefslogtreecommitdiff
path: root/inst/orientPolygon.m
diff options
context:
space:
mode:
authorRafael Laboissière <rafael@debian.org>2020-02-09 05:51:46 -0300
committerRafael Laboissière <rafael@debian.org>2020-02-09 05:51:46 -0300
commita45e15f167ef0a7cba3e9ed572209f3522658320 (patch)
tree481982ed20977db86d2e3309ee5e709da54e2b79 /inst/orientPolygon.m
parent87f1c69f10eb490ae5bdfbd551ba386b58e199e3 (diff)
New upstream version 4.0.0
Diffstat (limited to 'inst/orientPolygon.m')
-rw-r--r--inst/orientPolygon.m140
1 files changed, 140 insertions, 0 deletions
diff --git a/inst/orientPolygon.m b/inst/orientPolygon.m
new file mode 100644
index 0000000..fe783fe
--- /dev/null
+++ b/inst/orientPolygon.m
@@ -0,0 +1,140 @@
+## Copyright (C) 2016 - Juan Pablo Carbajal
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+## Author: Juan Pablo Carbajal <ajuanpi+dev@gmail.com>
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{q} =} orientPolygon (@var{p})
+## @deftypefnx {} {@dots{} =} orientPolygon (@var{p}, [], @var{dir})
+## @deftypefnx {} {[@var{qx} @var{qy}] =} orientPolygon (@var{px}, @var{py})
+## @deftypefnx {} {@dots{} =} orientPolygon (@var{px}, @var{py}, @var{dir})
+## Orient polygon counterclockwise or clockwise.
+##
+## @var{p} is a N-by-2 array containing coordinates of vertices. The coordinates
+## of the vertices of the polygon can also be given as two N-by-1 arrways
+## @var{px}, @var{py}. It can also be cells of polygons or NaN separated polygons.
+## The output has the same format as the input.
+##
+## The optional argument @var{dir} can be @asis{"ccw"} or @asis{"cw"}.
+## By default it orients polygon counterclockwise (@code{@var{dir} == "ccw"}).
+## To orient the polygon clockwise, use @code{@var{dir} == "cw"}.
+##
+## Holes are treated as independet polygons, that is a cw polygon with a cw hole
+## will be seen as two cw polygons.
+##
+## If polygon is self-crossing, the result is undefined.
+##
+## @seealso{isPolygonCCW}
+## @end deftypefn
+
+function [x y] = orientPolygon (x, y=[], d = "ccw");
+ #case of wrong number of input arguments
+ if (nargin > 3 || nargin < 1)
+ print_usage ();
+ endif
+
+ if (!isempty (y))
+ if (!strcmp (typeinfo (x), typeinfo (y)))
+ error ('Octave:invalid-input-arg', 'X and Y should be of the same type');
+ endif
+ if(any (size (x) != size (y)) )
+ error ('Octave:invalid-input-arg', 'X and Y should be of the same size');
+ endif
+ endif
+
+ # define orientation mode
+ mode_ccw = strcmpi (d, "ccw");
+
+ if (iscell (x))
+ # Cell Array Format
+ # Call this function on each cell
+ if (isempty (y))
+ y = cell (size (x));
+ endif
+
+ [x y] = cellfun (@(u,v) orientPolygon (u,v,d), x, y, "unif", 0);
+
+ else
+ # Input are matrices
+ # merge them to one
+ x = [x y];
+
+ if any (isnan (x(:)))
+ # Inputs are many polygons separated with NaN
+ # Split them and call this function on each of them
+ x = splitPolygons (x);
+ x = cellfun (@(u) orientPolygon (u,[],d), x, "unif", 0);
+ x = joinPolygons (x);
+
+ else ## Here do the actual work
+ #Check the orientation of the polygons
+ if ( (!isPolygonCCW (x) && mode_ccw) || (isPolygonCCW (x) && !mode_ccw) );
+ x = reversePolygon (x);
+ endif
+ endif
+
+ if (!isempty (y))
+ y = x(:,2);
+ x = x(:,1);
+ endif
+
+ endif
+
+endfunction
+
+%!shared pccw, pcw, pxccw, pyccw, pxnan, pynan, pnan
+%! pccw = [0 0; 1 0; 1 1; 0 1];
+%! pcw = reversePolygon (pccw);
+%! pxccw = pccw(:,1);
+%! pyccw = pccw(:,2);
+%! pxnan = [2; 2; 0; 0; NaN; 0; 0; 2];
+%! pynan = [0; 2; 2; 0; NaN; 0; 3; 0];
+%! pnan = [pxnan pynan];
+
+%!test
+%! x = orientPolygon (pccw,[],"ccw");
+%! assert (x, pccw);
+
+%!test
+%! x = orientPolygon (pccw,[],"cw");
+%! assert (x, pcw);
+
+%!test
+%! x = orientPolygon (pcw,[],"ccw");
+%! assert (x, pccw);
+
+%!test
+%! x = orientPolygon (pcw,[],"cw");
+%! assert (x, pcw);
+
+%!test
+%! x = orientPolygon (pnan,[],"cw");
+%! y = splitPolygons (pnan);
+%! y = joinPolygons ({reversePolygon(y{1}); y{2}});
+%! assert (x, y);
+
+%!test
+%! x = orientPolygon (pnan,[],"ccw");
+%! y = splitPolygons (pnan);
+%! y = joinPolygons ({y{1}; reversePolygon(y{2})});
+%! assert (x, y);
+
+%!test
+%! [x y] = orientPolygon (pxccw,pyccw,"ccw");
+%! assert ([x y], pccw);
+
+%!test
+%! [x y] = orientPolygon (pxccw,pyccw,"cw");
+%! assert ([x y], pcw);