/*
Copyright (C) 2017 - Piyush Jain
Copyright (C) 2017 - 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 .
*/
#include "polygon.h"
#include "utilities.h"
#include "martinez.h"
#include "connector.h"
#include
#include
DEFUN_DLD(polybool_mrf, args, ,
"\
-*- texinfo -*-\n\
@deftypefn {Loadable Function} {} polybool_mrf (@var{subj} ,@var{clip}, @var{operation}\n\
Perform Boolean Operations on polygons\n\n\
@var{subj}-@var{clip} are NaN Delimited Column/Row Vectors\n\n\
@var{Operation} is a string representing the operation to perform. \n\
Valid Operations are: 0 (DIFFERENCE), 1 (INTERSECTION), 2 (XOR) , 3 (UNION).\n\
It is an optional argument. If not provided, INTERSECTION is the default operation.\n\n\
@end deftypefn")
{
int nargin = args.length();
if(nargin < 2 || nargin > 3)
print_usage();
else
{
Polygon subj, clip;
octave_map subpoly = args(0).map_value ();
octave_map clippoly = args(1).map_value ();
// Subject polygon
octave_idx_type ncontours = subpoly.numel();
double px, py;
octave_map::const_iterator px_iter = subpoly.seek ("x");
octave_map::const_iterator py_iter = subpoly.seek ("y");
for (octave_idx_type i = 0; i < ncontours; i++) {
Array X = subpoly.contents(px_iter)(i).array_value();
Array Y = subpoly.contents(py_iter)(i).array_value();
octave_idx_type npoints = X.numel();
subj.push_back (Contour ());
Contour& contour = subj.back ();
for (octave_idx_type j = 0; j < npoints; j++) {
px = X(j);
py = Y(j);
if (j > 0 && px == contour.back ().x && py == contour.back ().y)
continue;
if (j == npoints-1 && px == contour.vertex (0).x && py == contour.vertex (0).y)
continue;
contour.add (Point (px, py));
}
if (contour.nvertices () < 3) {
subj.pop_back ();
continue;
}
}
// Clipping polygon
ncontours = clippoly.numel();
px_iter = clippoly.seek ("x");
py_iter = clippoly.seek ("y");
for (octave_idx_type i = 0; i < ncontours; i++) {
Array X = clippoly.contents(px_iter)(i).array_value();
Array Y = clippoly.contents(py_iter)(i).array_value();
octave_idx_type npoints = X.numel();
clip.push_back (Contour ());
Contour& contour = clip.back ();
for (octave_idx_type j = 0; j < npoints; j++) {
px = X(j);
py = Y(j);
if (j > 0 && px == contour.back ().x && py == contour.back ().y)
continue;
if (j == npoints-1 && px == contour.vertex (0).x && py == contour.vertex (0).y)
continue;
contour.add (Point (px, py));
}
if (contour.nvertices () < 3) {
clip.pop_back ();
continue;
}
}
// Selecting operation
Martinez::BoolOpType op = Martinez::INTERSECTION;
if (nargin > 2) {
int opcode = args(2).scalar_value();
switch (opcode) {
case 0:
op = Martinez::DIFFERENCE;
break;
case 1:
op = Martinez::INTERSECTION;
break;
case 2:
op = Martinez::XOR;
break;
case 3:
op = Martinez::UNION;
break;
}
}
// Perform boolean operation
Polygon martinezResult;
martinezResult.clear ();
Martinez mr (subj, clip);
mr.compute (op, martinezResult);
// Passing the result into matrix
octave_value_list result;
octave_idx_type size = martinezResult.nvertices() + martinezResult.ncontours();
if(size > 0)
{
--size;
Matrix tempx(dim_vector(size,1));
Matrix tempy(dim_vector(size,1));
octave_idx_type k = 0;
for (octave_idx_type i = 0; i < martinezResult.ncontours (); i++)
{
Contour::iterator c = martinezResult.contour (i).begin();
while (c != martinezResult.contour (i).end()) {
tempx(k,0) = c->x;
tempy(k,0) = c->y;
k++;
++c;
}
if(i != martinezResult.ncontours()-1){
tempx(k,0) = std::numeric_limits::quiet_NaN();
tempy(k,0) = std::numeric_limits::quiet_NaN();
k++;
}
}
result(0) = tempx;
result(1) = tempy;
result(2) = martinezResult.ncontours();
}
else
{
result(0) = std::numeric_limits::quiet_NaN();
result(1) = std::numeric_limits::quiet_NaN();
result(2) = 0;
}
return result;
}
return octave_value_list();
}