GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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