GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
tsearch.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2002-2025 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
40inline double
41max (double a, double b, double c)
42{
43 return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
44}
45
46inline double
47min (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// The algorithm is O(M*N) for M points and N triangles.
55// Faster performance (closer to linear) happens if the points form a
56// contiguous path, such as a person on a walk recording their position every
57// few seconds and querying which map sector they are in.
58
59DEFUN (tsearch, args, ,
60 doc: /* -*- texinfo -*-
61@deftypefn {} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})
62Search for the enclosing Delaunay convex hull.
63
64For @code{@var{t} = delaunay (@var{x}, @var{y})}, finds the index in @var{t}
65containing the points @code{(@var{xi}, @var{yi})}. For points outside the
66convex hull, @var{idx} is NaN.
67
68Programming Note: The algorithm is @qcode{O}(@var{M}*@var{N}) for locating
69@var{M} points in @var{N} triangles. Performance is typically much faster if
70the points to be located are in a single continuous path; a point is first
71checked against the region its predecessor was found in, speeding up lookups
72for points along a continuous path.
73
74@seealso{delaunay, delaunayn}
75@end deftypefn */)
76{
77 if (args.length () != 5)
78 print_usage ();
79
80 const double eps = 1.0e-12;
81
82 const ColumnVector x (args(0).vector_value ());
83 const ColumnVector y (args(1).vector_value ());
84 const Matrix elem (args(2).matrix_value ());
85 const ColumnVector xi (args(3).vector_value ());
86 const ColumnVector yi (args(4).vector_value ());
87
88 const octave_idx_type nelem = elem.rows ();
89
90 ColumnVector minx (nelem);
91 ColumnVector maxx (nelem);
92 ColumnVector miny (nelem);
93 ColumnVector maxy (nelem);
94 for (octave_idx_type k = 0; k < nelem; k++)
95 {
96 minx(k) = min (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) - eps;
97 maxx(k) = max (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) + eps;
98 miny(k) = min (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) - eps;
99 maxy(k) = max (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) + eps;
100 }
101
102 const octave_idx_type np = xi.numel ();
103 ColumnVector values (np);
104
105 double x0 = 0.0, y0 = 0.0;
106 double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
107 double xt = 0.0, yt = 0.0;
108 double dx1 = 0.0, dx2 = 0.0, c1 = 0.0, c2 = 0.0;
109
110 octave_idx_type k = nelem; // k is more than just an index variable.
111
112 for (octave_idx_type kp = 0; kp < np; kp++) // for each point
113 {
114 xt = xi (kp);
115 yt = yi (kp);
116
117 // Check if point (xt,yt) is in the triangle that was last examined.
118 // This is for inputs where points are in contiguous order,
119 // like when the points are sampled from a continuous path.
120 if (k < nelem) // This check will be false for the very first point.
121 {
122 // If we are here, then x0, y0, det all exist from before.
123 dx1 = xt - x0;
124 dx2 = yt - y0;
125 c1 = (a22 * dx1 - a21 * dx2) / det;
126 c2 = (-a12 * dx1 + a11 * dx2) / det;
127 if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)
128 {
129 values (kp) = k+1;
130 continue;
131 }
132 }
133
134 // The point is not in the same triangle, so go through all triangles.
135 for (k = 0; k < nelem; k++)
136 {
137 if (xt >= minx(k) && xt <= maxx(k) && yt >= miny(k) && yt <= maxy(k))
138 {
139 // Point is inside the triangle's bounding rectangle:
140 // See if it's inside the triangle itself.
141 x0 = REF (x, k, 0);
142 y0 = REF (y, k, 0);
143 a11 = REF (x, k, 1) - x0;
144 a12 = REF (y, k, 1) - y0;
145 a21 = REF (x, k, 2) - x0;
146 a22 = REF (y, k, 2) - y0;
147 det = a11 * a22 - a21 * a12;
148
149 // solve the system
150 dx1 = xt - x0;
151 dx2 = yt - y0;
152 c1 = (a22 * dx1 - a21 * dx2) / det;
153 c2 = (-a12 * dx1 + a11 * dx2) / det;
154 if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= 1 + eps)
155 {
156 values (kp) = k+1;
157 break;
158 }
159 } //end see if it's inside the triangle itself
160 } //end for each triangle
161
162 if (k == nelem)
163 values (kp) = lo_ieee_nan_value ();
164
165 } //end for each point
166
167 return ovl (values);
168}
169
170/*
171%!shared x, y, tri
172%! x = [-1;-1;1];
173%! y = [-1;1;-1];
174%! tri = [1, 2, 3];
175%!assert (tsearch (x,y,tri,-1,-1), 1)
176%!assert (tsearch (x,y,tri, 1,-1), 1)
177%!assert (tsearch (x,y,tri,-1, 1), 1)
178%!assert (tsearch (x,y,tri,-1/3, -1/3), 1)
179%!assert (tsearch (x,y,tri, 1, 1), NaN)
180
181%!error tsearch ()
182*/
183
184OCTAVE_END_NAMESPACE(octave)
octave_idx_type rows() const
Definition Array.h:463
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
T eps(const T &x)
Definition data.cc:5008
void print_usage()
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:217
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