GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__contourc__.cc
Go to the documentation of this file.
1 /* Contour lines for function evaluated on a grid.
2 
3 Copyright (C) 2007-2018 Kai Habel
4 Copyright (C) 2004, 2007 Shai Ayal
5 
6 Adapted to an oct file from the stand alone contourl by Victro Munoz
7 Copyright (C) 2004 Victor Munoz
8 
9 Based on contour plot routine (plcont.c) in PLPlot package
10 http://plplot.org/
11 
12 Copyright (C) 1995, 2000, 2001 Maurice LeBrun
13 Copyright (C) 2000, 2002 Joao Cardoso
14 Copyright (C) 2000, 2001, 2002, 2004 Alan W. Irwin
15 Copyright (C) 2004 Andrew Ross
16 
17 This file is part of Octave.
18 
19 Octave is free software: you can redistribute it and/or modify it
20 under the terms of the GNU General Public License as published by
21 the Free Software Foundation, either version 3 of the License, or
22 (at your option) any later version.
23 
24 Octave is distributed in the hope that it will be useful, but
25 WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28 
29 You should have received a copy of the GNU General Public License
30 along with Octave; see the file COPYING. If not, see
31 <https://www.gnu.org/licenses/>.
32 
33 */
34 
35 #if defined (HAVE_CONFIG_H)
36 # include "config.h"
37 #endif
38 
39 #include <limits>
40 
41 #include "defun.h"
42 #include "ov.h"
43 
44 // FIXME: this looks like trouble...
47 static int elem;
48 
49 // This is the quanta in which we increase this_contour.
50 #define CONTOUR_QUANT 50
51 
52 // Add a coordinate point (x,y) to this_contour.
53 
54 static void
55 add_point (double x, double y)
56 {
57  if (elem % CONTOUR_QUANT == 0)
59 
60  this_contour (0, elem) = x;
61  this_contour (1, elem) = y;
62  elem++;
63 }
64 
65 // Add contents of current contour to contourc.
66 // this_contour.cols () - 1;
67 
68 static void
70 {
71  if (elem > 2)
72  {
73  this_contour (1, 0) = elem - 1;
75  }
76 
77  this_contour = Matrix ();
78  elem = 0;
79 }
80 
81 // Start a new contour, and add contents of current one to contourc.
82 
83 static void
84 start_contour (double lvl, double x, double y)
85 {
86  end_contour ();
87  this_contour.resize (2, 0);
88  add_point (lvl, 0);
89  add_point (x, y);
90 }
91 
92 static void
93 drawcn (const RowVector& X, const RowVector& Y, const Matrix& Z,
94  double lvl, int r, int c, double ct_x, double ct_y,
95  unsigned int start_edge, bool first, charMatrix& mark)
96 {
97  double px[4], py[4], pz[4], tmp;
98  unsigned int stop_edge, pt[2];
99 
100  // Continue while next facet is not done yet.
101  while (r >= 0 && c >= 0 && r < mark.rows () && c < mark.cols ()
102  && mark(r, c) > 0)
103  {
104 
105  //get x, y, and z - lvl for current facet
106  px[0] = px[3] = X(c);
107  px[1] = px[2] = X(c+1);
108 
109  py[0] = py[1] = Y(r);
110  py[2] = py[3] = Y(r+1);
111 
112  pz[3] = Z(r+1, c) - lvl;
113  pz[2] = Z(r+1, c + 1) - lvl;
114  pz[1] = Z(r, c+1) - lvl;
115  pz[0] = Z(r, c) - lvl;
116 
117  // Facet edge and point naming assignment.
118  //
119  // 0-----1 .-0-.
120  // | | | |
121  // | | 3 1
122  // | | | |
123  // 3-----2 .-2-.
124 
125  // Get mark value of current facet.
126  char id = static_cast<char> (mark(r, c));
127 
128  // Check startedge s.
129  if (start_edge == 255)
130  {
131  // Find start edge.
132  for (unsigned int k = 0; k < 4; k++)
133  if (static_cast<char> (1 << k) & id)
134  start_edge = k;
135  }
136 
137  if (start_edge == 255)
138  break;
139 
140  // Decrease mark value of current facet for start edge.
141  mark(r, c) -= static_cast<char> (1 << start_edge);
142 
143  // Next point (clockwise).
144  pt[0] = start_edge;
145  pt[1] = (pt[0] + 1) % 4;
146 
147  // Calculate contour segment start if first of contour.
148  if (first)
149  {
150  tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);
151 
152  if (octave::math::isnan (tmp))
153  ct_x = ct_y = 0.5;
154  else
155  {
156  ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);
157  ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);
158  }
159 
160  start_contour (lvl, ct_x, ct_y);
161  first = false;
162  }
163 
164  // Find stop edge.
165  // FIXME: perhaps this should use a while loop?
166  for (unsigned int k = 1; k <= 4; k++)
167  {
168  if (start_edge == 0 || start_edge == 2)
169  stop_edge = (start_edge + k) % 4;
170  else
171  stop_edge = (start_edge - k) % 4;
172 
173  if (static_cast<char> (1 << stop_edge) & id)
174  break;
175  }
176 
177  pt[0] = stop_edge;
178  pt[1] = (pt[0] + 1) % 4;
179  tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);
180 
181  if (octave::math::isnan (tmp))
182  ct_x = ct_y = 0.5;
183  else
184  {
185  ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);
186  ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);
187  }
188 
189  // Add point to contour.
190  add_point (ct_x, ct_y);
191 
192  // Decrease id value of current facet for start edge.
193  mark(r, c) -= static_cast<char> (1 << stop_edge);
194 
195  // Find next facet.
196  if (stop_edge == 0)
197  r--;
198  else if (stop_edge == 1)
199  c++;
200  else if (stop_edge == 2)
201  r++;
202  else if (stop_edge == 3)
203  c--;
204 
205  // Go to next facet.
206  start_edge = (stop_edge + 2) % 4;
207 
208  }
209 }
210 
211 static void
212 mark_facets (const Matrix& Z, charMatrix& mark, double lvl)
213 {
214  unsigned int nr = mark.rows ();
215  unsigned int nc = mark.cols ();
216 
217  double f[4];
218 
219  for (unsigned int c = 0; c < nc; c++)
220  for (unsigned int r = 0; r < nr; r++)
221  {
222  f[0] = Z(r, c) - lvl;
223  f[1] = Z(r, c+1) - lvl;
224  f[3] = Z(r+1, c) - lvl;
225  f[2] = Z(r+1, c+1) - lvl;
226 
227  for (unsigned int i = 0; i < 4; i++)
228  if (fabs(f[i]) < std::numeric_limits<double>::epsilon ())
229  f[i] = std::numeric_limits<double>::epsilon ();
230 
231  if (f[1] * f[2] < 0)
232  mark(r, c) += 2;
233 
234  if (f[0] * f[3] < 0)
235  mark(r, c) += 8;
236  }
237 
238  for (unsigned int r = 0; r < nr; r++)
239  for (unsigned int c = 0; c < nc; c++)
240  {
241  f[0] = Z(r, c) - lvl;
242  f[1] = Z(r, c+1) - lvl;
243  f[3] = Z(r+1, c) - lvl;
244  f[2] = Z(r+1, c+1) - lvl;
245 
246  for (unsigned int i = 0; i < 4; i++)
247  if (fabs(f[i]) < std::numeric_limits<double>::epsilon ())
248  f[i] = std::numeric_limits<double>::epsilon ();
249 
250  if (f[0] * f[1] < 0)
251  mark(r, c) += 1;
252 
253  if (f[2] * f[3] < 0)
254  mark(r, c) += 4;
255  }
256 }
257 
258 static void
259 cntr (const RowVector& X, const RowVector& Y, const Matrix& Z, double lvl)
260 {
261  unsigned int nr = Z.rows ();
262  unsigned int nc = Z.cols ();
263 
264  charMatrix mark (nr - 1, nc - 1, 0);
265 
266  mark_facets (Z, mark, lvl);
267 
268  // Find contours that start at a domain edge.
269 
270  for (unsigned int c = 0; c < nc - 1; c++)
271  {
272  // Top.
273  if (mark(0, c) & 1)
274  drawcn (X, Y, Z, lvl, 0, c, 0.0, 0.0, 0, true, mark);
275 
276  // Bottom.
277  if (mark(nr - 2, c) & 4)
278  drawcn (X, Y, Z, lvl, nr - 2, c, 0.0, 0.0, 2, true, mark);
279  }
280 
281  for (unsigned int r = 0; r < nr - 1; r++)
282  {
283  // Left.
284  if (mark(r, 0) & 8)
285  drawcn (X, Y, Z, lvl, r, 0, 0.0, 0.0, 3, true, mark);
286 
287  // Right.
288  if (mark(r, nc - 2) & 2)
289  drawcn (X, Y, Z, lvl, r, nc - 2, 0.0, 0.0, 1, true, mark);
290  }
291 
292  for (unsigned int r = 0; r < nr - 1; r++)
293  for (unsigned int c = 0; c < nc - 1; c++)
294  if (mark (r, c) > 0)
295  drawcn (X, Y, Z, lvl, r, c, 0.0, 0.0, 255, true, mark);
296 }
297 
298 DEFUN (__contourc__, args, ,
299  doc: /* -*- texinfo -*-
300 @deftypefn {} {} __contourc__ (@var{x}, @var{y}, @var{z}, @var{levels})
301 Undocumented internal function.
302 @end deftypefn */)
303 {
304  if (args.length () != 4)
305  print_usage ();
306 
307  RowVector X = args(0).row_vector_value ();
308  RowVector Y = args(1).row_vector_value ();
309  Matrix Z = args(2).matrix_value ();
310  RowVector L = args(3).row_vector_value ();
311 
312  contourc.resize (2, 0);
313 
314  for (int i = 0; i < L.numel (); i++)
315  cntr (X, Y, Z, L (i));
316 
317  end_contour ();
318 
319  return octave_value (contourc);
320 }
321 
322 /*
323 ## No test needed for internal helper function.
324 %!assert (1)
325 */
uint32_t id
Definition: graphics.cc:12193
octave_idx_type rows(void) const
Definition: Array.h:404
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:148
static Matrix this_contour
Definition: __contourc__.cc:45
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
for large enough k
Definition: lu.cc:617
bool isnan(bool)
Definition: lo-mappers.h:187
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
F77_RET_T const F77_INT const F77_INT const F77_INT F77_DBLE const F77_INT F77_DBLE const F77_INT F77_DBLE const F77_INT F77_DBLE * Z
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
static void start_contour(double lvl, double x, double y)
Definition: __contourc__.cc:84
octave_idx_type cols(void) const
Definition: Array.h:412
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit first
Definition: file-io.cc:587
#define CONTOUR_QUANT
Definition: __contourc__.cc:50
static int elem
Definition: __contourc__.cc:47
double tmp
Definition: data.cc:6252
Matrix append(const Matrix &a) const
Definition: dMatrix.cc:264
static void cntr(const RowVector &X, const RowVector &Y, const Matrix &Z, double lvl)
Definition: dMatrix.h:36
static void drawcn(const RowVector &X, const RowVector &Y, const Matrix &Z, double lvl, int r, int c, double ct_x, double ct_y, unsigned int start_edge, bool first, charMatrix &mark)
Definition: __contourc__.cc:93
static void end_contour(void)
Definition: __contourc__.cc:69
static Matrix contourc
Definition: __contourc__.cc:46
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
static void mark_facets(const Matrix &Z, charMatrix &mark, double lvl)
the element is set to zero In other the statement xample y
Definition: data.cc:5264
for i
Definition: data.cc:5264
static void add_point(double x, double y)
Definition: __contourc__.cc:55
Matrix extract_n(octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const
Definition: dMatrix.cc:406
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x