GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
tsearch.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2002-2013 Andreas Stahel
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Author: Andreas Stahel <[email protected]>
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32 
33 #include "lo-ieee.h"
34 #include "lo-math.h"
35 
36 #include "defun-dld.h"
37 #include "error.h"
38 #include "oct-obj.h"
39 #include "parse.h"
40 
41 inline double max (double a, double b, double c)
42 {
43  if (a < b)
44  return (b < c ? c : b);
45  else
46  return (a < c ? c : a);
47 }
48 
49 inline double min (double a, double b, double c)
50 {
51  if (a > b)
52  return (b > c ? c : b);
53  else
54  return (a > c ? c : a);
55 }
56 
57 #define REF(x,k,i) x(static_cast<octave_idx_type>(elem((k), (i))) - 1)
58 
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
62 // given point
63 
64 // e.g., build up a neighbouring triangle structure and use a simplex-like
65 // method to traverse it
66 
67 DEFUN_DLD (tsearch, args, ,
68  "-*- texinfo -*-\n\
69 @deftypefn {Loadable Function} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})\n\
70 Search for the enclosing Delaunay convex hull. For @code{@var{t} =\n\
71 delaunay (@var{x}, @var{y})}, finds the index in @var{t} containing the\n\
72 points @code{(@var{xi}, @var{yi})}. For points outside the convex hull,\n\
73 @var{idx} is NaN.\n\
74 @seealso{delaunay, delaunayn}\n\
75 @end deftypefn")
76 {
77  const double eps=1.0e-12;
78 
79  octave_value_list retval;
80  const int nargin = args.length ();
81  if (nargin != 5)
82  {
83  print_usage ();
84  return retval;
85  }
86 
87  const ColumnVector x (args(0).vector_value ());
88  const ColumnVector y (args(1).vector_value ());
89  const Matrix elem (args(2).matrix_value ());
90  const ColumnVector xi (args(3).vector_value ());
91  const ColumnVector yi (args(4).vector_value ());
92 
93  if (error_state)
94  return retval;
95 
96  const octave_idx_type nelem = elem.rows ();
97 
98  ColumnVector minx (nelem);
99  ColumnVector maxx (nelem);
100  ColumnVector miny (nelem);
101  ColumnVector maxy (nelem);
102  for (octave_idx_type k = 0; k < nelem; k++)
103  {
104  minx(k) = min (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) - eps;
105  maxx(k) = max (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) + eps;
106  miny(k) = min (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) - eps;
107  maxy(k) = max (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) + eps;
108  }
109 
110  const octave_idx_type np = xi.length ();
111  ColumnVector values (np);
112 
113  double x0 = 0.0, y0 = 0.0;
114  double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
115 
116  octave_idx_type k = nelem; // k is a counter of elements
117  for (octave_idx_type kp = 0; kp < np; kp++)
118  {
119  const double xt = xi(kp);
120  const double yt = yi(kp);
121 
122  // check if last triangle contains the next point
123  if (k < nelem)
124  {
125  const double dx1 = xt - x0;
126  const double dx2 = yt - y0;
127  const double c1 = (a22 * dx1 - a21 * dx2) / det;
128  const double c2 = (-a12 * dx1 + a11 * dx2) / det;
129  if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= (1 + eps))
130  {
131  values(kp) = double(k+1);
132  continue;
133  }
134  }
135 
136  // it doesn't, so go through all elements
137  for (k = 0; k < nelem; k++)
138  {
139  OCTAVE_QUIT;
140  if (xt >= minx(k) && xt <= maxx(k) && yt >= miny(k) && yt <= maxy(k))
141  {
142  // element inside the minimum rectangle: examine it closely
143  x0 = REF (x, k, 0);
144  y0 = REF (y, k, 0);
145  a11 = REF (x, k, 1) - x0;
146  a12 = REF (y, k, 1) - y0;
147  a21 = REF (x, k, 2) - x0;
148  a22 = REF (y, k, 2) - y0;
149  det = a11 * a22 - a21 * a12;
150 
151  // solve the system
152  const double dx1 = xt - x0;
153  const double dx2 = yt - y0;
154  const double c1 = (a22 * dx1 - a21 * dx2) / det;
155  const double c2 = (-a12 * dx1 + a11 * dx2) / det;
156  if ((c1 >= -eps) && (c2 >= -eps) && ((c1 + c2) <= (1 + eps)))
157  {
158  values(kp) = double(k+1);
159  break;
160  }
161  } //endif # examine this element closely
162  } //endfor # each element
163 
164  if (k == nelem)
165  values(kp) = lo_ieee_nan_value ();
166 
167  } //endfor # kp
168 
169  retval(0) = values;
170 
171  return retval;
172 }
173 
174 /*
175 %!shared x, y, tri
176 %! x = [-1;-1;1];
177 %! y = [-1;1;-1];
178 %! tri = [1, 2, 3];
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)
184 
185 %!error tsearch ()
186 */