__contourc__.cc

Go to the documentation of this file.
00001 /* Contour lines for function evaluated on a grid.
00002 
00003 Copyright (C) 2007-2012 Kai Habel
00004 Copyright (C) 2004, 2007 Shai Ayal
00005 
00006 Adapted to an oct file from the stand alone contourl by Victro Munoz
00007 Copyright (C) 2004 Victor Munoz
00008 
00009 Based on contour plot routine (plcont.c) in PLPlot package
00010 http://plplot.org/
00011 
00012 Copyright (C) 1995, 2000, 2001 Maurice LeBrun
00013 Copyright (C) 2000, 2002 Joao Cardoso
00014 Copyright (C) 2000, 2001, 2002, 2004  Alan W. Irwin
00015 Copyright (C) 2004  Andrew Ross
00016 
00017 This file is part of Octave.
00018 
00019 Octave is free software; you can redistribute it and/or modify it
00020 under the terms of the GNU General Public License as published by the
00021 Free Software Foundation; either version 3 of the License, or (at your
00022 option) any later version.
00023 
00024 Octave is distributed in the hope that it will be useful, but WITHOUT
00025 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00026 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00027 for more details.
00028 
00029 You should have received a copy of the GNU General Public License
00030 along with Octave; see the file COPYING.  If not, see
00031 <http://www.gnu.org/licenses/>.
00032 
00033 */
00034 
00035 #ifdef HAVE_CONFIG_H
00036 #include <config.h>
00037 #endif
00038 
00039 #include <cfloat>
00040 
00041 #include "quit.h"
00042 
00043 #include "defun-dld.h"
00044 #include "error.h"
00045 #include "oct-obj.h"
00046 
00047 static Matrix this_contour;
00048 static Matrix contourc;
00049 static int elem;
00050 
00051 // This is the quanta in which we increase this_contour.
00052 #define CONTOUR_QUANT 50
00053 
00054 // Add a coordinate point (x,y) to this_contour.
00055 
00056 static void
00057 add_point (double x, double y)
00058 {
00059   if (elem % CONTOUR_QUANT == 0)
00060     this_contour = this_contour.append (Matrix (2, CONTOUR_QUANT, 0));
00061 
00062   this_contour (0, elem) = x;
00063   this_contour (1, elem) = y;
00064   elem++;
00065 }
00066 
00067 // Add contents of current contour to contourc.
00068 // this_contour.cols () - 1;
00069 
00070 static void
00071 end_contour (void)
00072 {
00073   if (elem > 2)
00074     {
00075       this_contour (1, 0) = elem - 1;
00076       contourc = contourc.append (this_contour.extract_n (0, 0, 2, elem));
00077     }
00078 
00079   this_contour = Matrix ();
00080   elem = 0;
00081 }
00082 
00083 // Start a new contour, and add contents of current one to contourc.
00084 
00085 static void
00086 start_contour (double lvl, double x, double y)
00087 {
00088   end_contour ();
00089   this_contour.resize (2, 0);
00090   add_point (lvl, 0);
00091   add_point (x, y);
00092 }
00093 
00094 static void
00095 drawcn (const RowVector& X, const RowVector& Y, const Matrix& Z,
00096         double lvl, int r, int c, double ct_x, double ct_y,
00097         unsigned int start_edge, bool first, charMatrix& mark)
00098 {
00099   double px[4], py[4], pz[4], tmp;
00100   unsigned int stop_edge, next_edge, pt[2];
00101   int next_r, next_c;
00102 
00103   //get x, y, and z - lvl for current facet
00104   px[0] = px[3] = X(c);
00105   px[1] = px[2] = X(c+1);
00106 
00107   py[0] = py[1] = Y(r);
00108   py[2] = py[3] = Y(r+1);
00109 
00110   pz[3] = Z(r+1, c) - lvl;
00111   pz[2] = Z(r+1, c + 1) - lvl;
00112   pz[1] = Z(r, c+1) - lvl;
00113   pz[0] = Z(r, c) - lvl;
00114 
00115   // Facet edge and point naming assignment.
00116   //
00117   //  0-----1   .-0-.
00118   //  |     |   |   |
00119   //  |     |   3   1
00120   //  |     |   |   |
00121   //  3-----2   .-2-.
00122 
00123   // Get mark value of current facet.
00124   char id = static_cast<char> (mark(r, c));
00125 
00126   // Check startedge s.
00127   if (start_edge == 255)
00128     {
00129       // Find start edge.
00130       for (unsigned int k = 0; k < 4; k++)
00131         if (static_cast<char> (1 << k) & id)
00132           start_edge = k;
00133     }
00134 
00135   if (start_edge == 255)
00136     return;
00137 
00138   // Decrease mark value of current facet for start edge.
00139   mark(r, c) -= static_cast<char> (1 << start_edge);
00140 
00141   // Next point (clockwise).
00142   pt[0] = start_edge;
00143   pt[1] = (pt[0] + 1) % 4;
00144 
00145   // Calculate contour segment start if first of contour.
00146   if (first)
00147     {
00148       tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);
00149 
00150       if (xisnan (tmp))
00151         ct_x = ct_y = 0.5;
00152       else
00153         {
00154           ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);
00155           ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);
00156         }
00157 
00158       start_contour (lvl, ct_x, ct_y);
00159     }
00160 
00161   // Find stop edge.
00162   // FIXME -- perhaps this should use a while loop?
00163   for (unsigned int k = 1; k <= 4; k++)
00164     {
00165       if (start_edge == 0 || start_edge == 2)
00166         stop_edge = (start_edge + k) % 4;
00167       else
00168         stop_edge = (start_edge - k) % 4;
00169 
00170       if (static_cast<char> (1 << stop_edge) & id)
00171         break;
00172     }
00173 
00174   pt[0] = stop_edge;
00175   pt[1] = (pt[0] + 1) % 4;
00176   tmp = fabs (pz[pt[1]]) / fabs (pz[pt[0]]);
00177 
00178   if (xisnan (tmp))
00179     ct_x = ct_y = 0.5;
00180   else
00181     {
00182       ct_x = px[pt[0]] + (px[pt[1]] - px[pt[0]])/(1 + tmp);
00183       ct_y = py[pt[0]] + (py[pt[1]] - py[pt[0]])/(1 + tmp);
00184     }
00185 
00186   // Add point to contour.
00187   add_point (ct_x, ct_y);
00188 
00189   // Decrease id value of current facet for start edge.
00190   mark(r, c) -= static_cast<char> (1 << stop_edge);
00191 
00192   // Find next facet.
00193   next_c = c;
00194   next_r = r;
00195 
00196   if (stop_edge == 0)
00197     next_r--;
00198   else if (stop_edge == 1)
00199     next_c++;
00200   else if (stop_edge == 2)
00201     next_r++;
00202   else if (stop_edge == 3)
00203     next_c--;
00204 
00205   // Check if next facet is not done yet.
00206   // Go to next facet.
00207   if (next_r >= 0 && next_c >= 0 && next_r < mark.rows ()
00208       && next_c < mark.cols () && mark(next_r, next_c) > 0)
00209     {
00210       next_edge = (stop_edge + 2) % 4;
00211       drawcn (X, Y, Z, lvl, next_r, next_c, ct_x, ct_y, next_edge, false, mark);
00212     }
00213 }
00214 
00215 static void
00216 mark_facets (const Matrix& Z, charMatrix& mark, double lvl)
00217 {
00218   unsigned int nr = mark.rows ();
00219   unsigned int nc = mark.cols ();
00220 
00221   double f[4];
00222 
00223   for (unsigned int c = 0; c < nc; c++)
00224     for (unsigned int r = 0; r < nr; r++)
00225       {
00226         f[0] = Z(r, c) - lvl;
00227         f[1] = Z(r, c+1) - lvl;
00228         f[3] = Z(r+1, c) - lvl;
00229         f[2] = Z(r+1, c+1) - lvl;
00230 
00231         for (unsigned int i = 0; i < 4; i++)
00232           if (fabs(f[i]) < DBL_EPSILON)
00233             f[i] = DBL_EPSILON;
00234 
00235         if (f[1] * f[2] < 0)
00236           mark(r, c) += 2;
00237 
00238         if (f[0] * f[3] < 0)
00239           mark(r, c) += 8;
00240       }
00241 
00242   for (unsigned int r = 0; r < nr; r++)
00243     for (unsigned int c = 0; c < nc; c++)
00244       {
00245         f[0] = Z(r, c) - lvl;
00246         f[1] = Z(r, c+1) - lvl;
00247         f[3] = Z(r+1, c) - lvl;
00248         f[2] = Z(r+1, c+1) - lvl;
00249 
00250         for (unsigned int i = 0; i < 4; i++)
00251           if (fabs(f[i]) < DBL_EPSILON)
00252             f[i] = DBL_EPSILON;
00253 
00254         if (f[0] * f[1] < 0)
00255           mark(r, c) += 1;
00256 
00257         if (f[2] * f[3] < 0)
00258           mark(r, c) += 4;
00259       }
00260 }
00261 
00262 static void
00263 cntr (const RowVector& X, const RowVector& Y, const Matrix& Z, double lvl)
00264 {
00265   unsigned int nr = Z.rows ();
00266   unsigned int nc = Z.cols ();
00267 
00268   charMatrix mark (nr - 1, nc - 1, 0);
00269 
00270   mark_facets (Z, mark, lvl);
00271 
00272   // Find contours that start at a domain edge.
00273 
00274   for (unsigned int c = 0; c < nc - 1; c++)
00275     {
00276       // Top.
00277       if (mark(0, c) & 1)
00278         drawcn (X, Y, Z, lvl, 0, c, 0.0, 0.0, 0, true, mark);
00279 
00280       // Bottom.
00281       if (mark(nr - 2, c) & 4)
00282         drawcn (X, Y, Z, lvl, nr - 2, c, 0.0, 0.0, 2, true, mark);
00283     }
00284 
00285   for (unsigned int r = 0; r < nr - 1; r++)
00286     {
00287       // Left.
00288       if (mark(r, 0) & 8)
00289         drawcn (X, Y, Z, lvl, r, 0, 0.0, 0.0, 3, true, mark);
00290 
00291       // Right.
00292       if (mark(r, nc - 2) & 2)
00293         drawcn (X, Y, Z, lvl, r, nc - 2, 0.0, 0.0, 1, true, mark);
00294     }
00295 
00296   for (unsigned int r = 0; r < nr - 1; r++)
00297     for (unsigned int c = 0; c < nc - 1; c++)
00298       if (mark (r, c) > 0)
00299         drawcn (X, Y, Z, lvl, r, c, 0.0, 0.0, 255, true, mark);
00300 }
00301 
00302 DEFUN_DLD (__contourc__, args, ,
00303   "-*- texinfo -*-\n\
00304 @deftypefn {Loadable Function} {} __contourc__ (@var{x}, @var{y}, @var{z}, @var{levels})\n\
00305 Undocumented internal function.\n\
00306 @end deftypefn")
00307 {
00308   octave_value retval;
00309 
00310   if (args.length () == 4)
00311     {
00312       RowVector X = args (0).row_vector_value ();
00313       RowVector Y = args (1).row_vector_value ();
00314       Matrix Z = args (2).matrix_value ();
00315       RowVector L = args (3).row_vector_value ();
00316 
00317       if (! error_state)
00318         {
00319           contourc.resize (2, 0);
00320 
00321           for (int i = 0; i < L.length (); i++)
00322             cntr (X, Y, Z, L (i));
00323 
00324           end_contour ();
00325 
00326           retval = contourc;
00327         }
00328       else
00329         error ("__contourc__: invalid argument values");
00330     }
00331   else
00332     print_usage ();
00333 
00334   return retval;
00335 }
00336 
00337 /*
00338 
00339 ## No test needed for internal helper function.
00340 %!assert (1)
00341 
00342 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines