GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
tsearch.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2002-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cmath>
31 
32 #include "lo-ieee.h"
33 
34 #include "defun.h"
35 #include "error.h"
36 #include "ovl.h"
37 
39 
40 inline double
41 max (double a, double b, double c)
42 {
43  return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
44 }
45 
46 inline double
47 min (double a, double b, double c)
48 {
49  return (a < b) ? (a < c ? a : c) : (b < c ? b : c);
50 }
51 
52 #define REF(x,k,i) x(static_cast<octave_idx_type> (elem((k), (i))) - 1)
53 
54 // for large data set the algorithm is very slow
55 // one should presort (how?) either the elements of the points of evaluation
56 // to cut down the time needed to decide which triangle contains the
57 // given point
58 
59 // e.g., build up a neighbouring triangle structure and use a simplex-like
60 // method to traverse it
61 
62 DEFUN (tsearch, args, ,
63  doc: /* -*- texinfo -*-
64 @deftypefn {} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})
65 Search for the enclosing Delaunay convex hull.
66 
67 For @code{@var{t} = delaunay (@var{x}, @var{y})}, finds the index in @var{t}
68 containing the points @code{(@var{xi}, @var{yi})}. For points outside the
69 convex hull, @var{idx} is NaN.
70 @seealso{delaunay, delaunayn}
71 @end deftypefn */)
72 {
73  if (args.length () != 5)
74  print_usage ();
75 
76  const double eps = 1.0e-12;
77 
78  const ColumnVector x (args(0).vector_value ());
79  const ColumnVector y (args(1).vector_value ());
80  const Matrix elem (args(2).matrix_value ());
81  const ColumnVector xi (args(3).vector_value ());
82  const ColumnVector yi (args(4).vector_value ());
83 
84  const octave_idx_type nelem = elem.rows ();
85 
86  ColumnVector minx (nelem);
87  ColumnVector maxx (nelem);
88  ColumnVector miny (nelem);
89  ColumnVector maxy (nelem);
90  for (octave_idx_type k = 0; k < nelem; k++)
91  {
92  minx(k) = min (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) - eps;
93  maxx(k) = max (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) + eps;
94  miny(k) = min (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) - eps;
95  maxy(k) = max (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) + eps;
96  }
97 
98  const octave_idx_type np = xi.numel ();
99  ColumnVector values (np);
100 
101  double x0 = 0.0, y0 = 0.0;
102  double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
103  double xt = 0.0, yt = 0.0;
104  double dx1 = 0.0, dx2 = 0.0, c1 = 0.0, c2 = 0.0;
105 
106  octave_idx_type k = nelem; // k is more than just an index variable.
107 
108  for (octave_idx_type kp = 0; kp < np; kp++) // for each point
109  {
110  xt = xi (kp);
111  yt = yi (kp);
112 
113  // Check if point (xt,yt) is in the triangle that was last examined.
114  // This is for inputs where points are in contiguous order,
115  // like when the points are sampled from a continuous path.
116  if (k < nelem) // This check will be false for the very first point.
117  {
118  // If we are here, then x0, y0, det all exist from before.
119  dx1 = xt - x0;
120  dx2 = yt - y0;
121  c1 = (a22 * dx1 - a21 * dx2) / det;
122  c2 = (-a12 * dx1 + a11 * dx2) / det;
123  if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)
124  {
125  values (kp) = k+1;
126  continue;
127  }
128  }
129 
130  // The point is not in the same triangle, so go through all triangles.
131  for (k = 0; k < nelem; k++)
132  {
133  if (xt >= minx(k) && xt <= maxx(k) && yt >= miny(k) && yt <= maxy(k))
134  {
135  // Point is inside the triangle's bounding rectangle:
136  // See if it's inside the triangle itself.
137  x0 = REF (x, k, 0);
138  y0 = REF (y, k, 0);
139  a11 = REF (x, k, 1) - x0;
140  a12 = REF (y, k, 1) - y0;
141  a21 = REF (x, k, 2) - x0;
142  a22 = REF (y, k, 2) - y0;
143  det = a11 * a22 - a21 * a12;
144 
145  // solve the system
146  dx1 = xt - x0;
147  dx2 = yt - y0;
148  c1 = (a22 * dx1 - a21 * dx2) / det;
149  c2 = (-a12 * dx1 + a11 * dx2) / det;
150  if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)
151  {
152  values (kp) = k+1;
153  break;
154  }
155  } //end see if it's inside the triangle itself
156  } //end for each triangle
157 
158  if (k == nelem)
159  values (kp) = lo_ieee_nan_value ();
160 
161  } //end for each point
162 
163  return ovl (values);
164 }
165 
166 /*
167 %!shared x, y, tri
168 %! x = [-1;-1;1];
169 %! y = [-1;1;-1];
170 %! tri = [1, 2, 3];
171 %!assert (tsearch (x,y,tri,-1,-1), 1)
172 %!assert (tsearch (x,y,tri, 1,-1), 1)
173 %!assert (tsearch (x,y,tri,-1, 1), 1)
174 %!assert (tsearch (x,y,tri,-1/3, -1/3), 1)
175 %!assert (tsearch (x,y,tri, 1, 1), NaN)
176 
177 %!error tsearch ()
178 */
179 
180 OCTAVE_END_NAMESPACE(octave)
octave_idx_type rows() const
Definition: Array.h:459
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Definition: dMatrix.h:42
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
T eps(const T &x)
Definition: data.cc:4964
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
double lo_ieee_nan_value()
Definition: lo-ieee.cc:84
F77_RET_T const F77_DBLE * x
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
double min(double a, double b, double c)
Definition: tsearch.cc:47
double max(double a, double b, double c)
Definition: tsearch.cc:41
#define REF(x, k, i)
Definition: tsearch.cc:52