3Copyright (C) 2002, 2007, 2009 Andreas Stahel
5This file is part of Octave.
7Octave is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
12Octave is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17You should have received a copy of the GNU General Public License
18along with Octave; see the file COPYING. If not, see
19<http://www.gnu.org/licenses/>.
23// Author: Andreas Stahel <Andreas.Stahel@hta-bi.bfh.ch>
41inline double max(double a, double b, double c)
44 return ( b < c ? c : b );
46 return ( a < c ? c : a );
49inline double min(double a, double b, double c)
52 return ( b > c ? c : b );
54 return ( a > c ? c : a );
57#define REF(x,k,i) x(static_cast<octave_idx_type>(elem((k), (i))) - 1)
59// for large data set the algorithm is very slow
60// one should presort (how?) either the elements of the points of evaluation
61// to cut down the time needed to decide which triangle contains the
64// e.g., build up a neighbouring triangle structure and use a simplex-like
65// method to traverse it
67DEFUN_DLD (tsearch, args, ,
69@deftypefn {Loadable Function} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})\n\
70Searches for the enclosing Delaunay convex hull. For @code{@var{t} =\n\
71delaunay (@var{x}, @var{y})}, finds the index in @var{t} containing the\n\
72points @code{(@var{xi}, @var{yi})}. For points outside the convex hull,\n\
74@seealso{delaunay, delaunayn}\n\
77 const double eps=1.0e-12;
79 octave_value_list retval;
80 const int nargin = args.length ();
86 const ColumnVector x(args(0).vector_value());
87 const ColumnVector y(args(1).vector_value());
88 const Matrix elem(args(2).matrix_value());
89 const ColumnVector xi(args(3).vector_value());
90 const ColumnVector yi(args(4).vector_value());
92 if (error_state) return retval;
94 const octave_idx_type nelem = elem.rows();
96 ColumnVector minx(nelem);
97 ColumnVector maxx(nelem);
98 ColumnVector miny(nelem);
99 ColumnVector maxy(nelem);
100 for(octave_idx_type k = 0; k < nelem; k++)
102 minx(k) = min(REF(x,k,0), REF(x,k,1), REF(x,k,2)) - eps;
103 maxx(k) = max(REF(x,k,0), REF(x,k,1), REF(x,k,2)) + eps;
104 miny(k) = min(REF(y,k,0), REF(y,k,1), REF(y,k,2)) - eps;
105 maxy(k) = max(REF(y,k,0), REF(y,k,1), REF(y,k,2)) + eps;
108 const octave_idx_type np = xi.length();
109 ColumnVector values(np);
111 double x0 = 0.0, y0 = 0.0;
112 double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
114 octave_idx_type k = nelem; // k is a counter of elements
115 for(octave_idx_type kp = 0; kp < np; kp++)
117 const double xt = xi(kp);
118 const double yt = yi(kp);
120 // check if last triangle contains the next point
123 const double dx1 = xt - x0;
124 const double dx2 = yt - y0;
125 const double c1 = (a22 * dx1 - a21 * dx2) / det;
126 const double c2 = (-a12 * dx1 + a11 * dx2) / det;
127 if ( c1 >= -eps && c2 >= -eps && (c1 + c2) <= (1 + eps))
129 values(kp) = double(k+1);
134 // it doesn't, so go through all elements
135 for (k = 0; k < nelem; k++)
138 if (xt >= minx(k) && xt <= maxx(k) &&
139 yt >= miny(k) && yt <= maxy(k) )
141 // element inside the minimum rectangle: examine it closely
148 det = a11 * a22 - a21 * a12;
151 const double dx1 = xt - x0;
152 const double dx2 = yt - y0;
153 const double c1 = (a22 * dx1 - a21 * dx2) / det;
154 const double c2 = (-a12 * dx1 + a11 * dx2) / det;
155 if ((c1 >= -eps) && (c2 >= -eps) && ((c1 + c2) <= (1 + eps)))
157 values(kp) = double(k+1);
160 } //endif # examine this element closely
161 } //endfor # each element
164 values(kp) = lo_ieee_nan_value ();
179%!assert (tsearch (x,y,tri,-1,-1), 1)
180%!assert (tsearch (x,y,tri, 1,-1), 1)
181%!assert (tsearch (x,y,tri,-1, 1), 1)
182%!assert (tsearch (x,y,tri,-1/3, -1/3), 1)
183%!assert (tsearch (x,y,tri, 1, 1), NaN)