File: tsearch.cc

package info (click to toggle)
octave 6.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 124,192 kB
  • sloc: cpp: 322,665; ansic: 68,088; fortran: 20,980; objc: 8,121; sh: 7,719; yacc: 4,266; lex: 4,123; perl: 1,530; java: 1,366; awk: 1,257; makefile: 424; xml: 147
file content (177 lines) | stat: -rw-r--r-- 5,372 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2021 The Octave Project Developers
//
// See the file COPYRIGHT.md in the top-level directory of this
// distribution or <https://octave.org/copyright/>.
//
// This file is part of Octave.
//
// Octave is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Octave is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Octave; see the file COPYING.  If not, see
// <https://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////

#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <cmath>

#include "lo-ieee.h"

#include "defun.h"
#include "error.h"
#include "ovl.h"

inline double max (double a, double b, double c)
{
  if (a < b)
    return (b < c ? c : b);
  else
    return (a < c ? c : a);
}

inline double min (double a, double b, double c)
{
  if (a > b)
    return (b > c ? c : b);
  else
    return (a > c ? c : a);
}

#define REF(x,k,i) x(static_cast<octave_idx_type> (elem((k), (i))) - 1)

// for large data set the algorithm is very slow
// one should presort (how?) either the elements of the points of evaluation
// to cut down the time needed to decide which triangle contains the
// given point

// e.g., build up a neighbouring triangle structure and use a simplex-like
// method to traverse it

DEFUN (tsearch, args, ,
       doc: /* -*- texinfo -*-
@deftypefn {} {@var{idx} =} tsearch (@var{x}, @var{y}, @var{t}, @var{xi}, @var{yi})
Search for the enclosing Delaunay convex hull.

For @code{@var{t} = delaunay (@var{x}, @var{y})}, finds the index in @var{t}
containing the points @code{(@var{xi}, @var{yi})}.  For points outside the
convex hull, @var{idx} is NaN.
@seealso{delaunay, delaunayn}
@end deftypefn */)
{
  if (args.length () != 5)
    print_usage ();

  const double eps = 1.0e-12;

  const ColumnVector x (args(0).vector_value ());
  const ColumnVector y (args(1).vector_value ());
  const Matrix elem (args(2).matrix_value ());
  const ColumnVector xi (args(3).vector_value ());
  const ColumnVector yi (args(4).vector_value ());

  const octave_idx_type nelem = elem.rows ();

  ColumnVector minx (nelem);
  ColumnVector maxx (nelem);
  ColumnVector miny (nelem);
  ColumnVector maxy (nelem);
  for (octave_idx_type k = 0; k < nelem; k++)
    {
      minx(k) = min (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) - eps;
      maxx(k) = max (REF (x, k, 0), REF (x, k, 1), REF (x, k, 2)) + eps;
      miny(k) = min (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) - eps;
      maxy(k) = max (REF (y, k, 0), REF (y, k, 1), REF (y, k, 2)) + eps;
    }

  const octave_idx_type np = xi.numel ();
  ColumnVector values (np);

  double x0, y0, a11, a12, a21, a22, det;
  x0 = y0 = 0.0;
  a11 = a12 = a21 = a22 = 0.0;
  det = 0.0;

  octave_idx_type k = nelem; // k is a counter of elements
  for (octave_idx_type kp = 0; kp < np; kp++)
    {
      const double xt = xi(kp);
      const double yt = yi(kp);

      // check if last triangle contains the next point
      if (k < nelem)
        {
          const double dx1 = xt - x0;
          const double dx2 = yt - y0;
          const double c1 = (a22 * dx1 - a21 * dx2) / det;
          const double c2 = (-a12 * dx1 + a11 * dx2) / det;
          if (c1 >= -eps && c2 >= -eps && (c1 + c2) <= (1 + eps))
            {
              values(kp) = double(k+1);
              continue;
            }
        }

      // it doesn't, so go through all elements
      for (k = 0; k < nelem; k++)
        {
          octave_quit ();

          if (xt >= minx(k) && xt <= maxx(k) && yt >= miny(k) && yt <= maxy(k))
            {
              // element inside the minimum rectangle: examine it closely
              x0  = REF (x, k, 0);
              y0  = REF (y, k, 0);
              a11 = REF (x, k, 1) - x0;
              a12 = REF (y, k, 1) - y0;
              a21 = REF (x, k, 2) - x0;
              a22 = REF (y, k, 2) - y0;
              det = a11 * a22 - a21 * a12;

              // solve the system
              const double dx1 = xt - x0;
              const double dx2 = yt - y0;
              const double c1 = (a22 * dx1 - a21 * dx2) / det;
              const double c2 = (-a12 * dx1 + a11 * dx2) / det;
              if ((c1 >= -eps) && (c2 >= -eps) && ((c1 + c2) <= (1 + eps)))
                {
                  values(kp) = double(k+1);
                  break;
                }
            } //endif # examine this element closely
        } //endfor # each element

      if (k == nelem)
        values(kp) = lo_ieee_nan_value ();

    } //endfor # kp

  return ovl (values);
}

/*
%!shared x, y, tri
%! x = [-1;-1;1];
%! y = [-1;1;-1];
%! tri = [1, 2, 3];
%!assert (tsearch (x,y,tri,-1,-1), 1)
%!assert (tsearch (x,y,tri, 1,-1), 1)
%!assert (tsearch (x,y,tri,-1, 1), 1)
%!assert (tsearch (x,y,tri,-1/3, -1/3), 1)
%!assert (tsearch (x,y,tri, 1, 1), NaN)

%!error tsearch ()
*/