# HG changeset patch # User dbateman # Date 1196109731 0 # Node ID e8d953d03f6a5266236f552fe7df101936c52a1b # Parent fdd7cd70dc14abe8af9762cc7facd02afac652d4 [project @ 2007-11-26 20:42:09 by dbateman] diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-11-26 David Bateman + + * PROJECTS: condest now implemented. + + * NEWS: Document the TeX interpreter mode and its limitations with + gnuplot 4.0. + + * NEWS: Document the use of "colormap gmap40" to workaround some + gnuplot 4.0 colormap issues. + 2007-11-14 John W. Eaton * configure.in: Don't create Makefrag.bsd. diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -20,6 +20,12 @@ and 1 for the R, G and B values. Invalid values are all mapped to the same color. + This also affects patch objects used in the bar, countour, meshc + and surfc functions, where the bars and contours will be + monochrome. A workaround for this is to type "colormap gmap40" + that loads a colormap that in many cases will be adequate for + simple bar and contour plots. + + You can control the width of lines using (for example): line (x, y, "linewidth", 4, "color", [1, 0, 0.5]); @@ -34,6 +40,12 @@ this allows you to plot additional 2-d data on top of a contour plot. + + With the gnuplot "extended" terminals the TeX interpreter is + emulated. However, this means that the TeX interpreter is only + supported on the postscript terminals with gnuplot 4.0. Under + gnuplot 4.2 the terminals aqua, dumb, png, jpeg, gif, pm, windows, + wxt, svg and x11 are supported as well. + + The following plot commands are now considered obsolete and will be removed from a future version of Octave: diff --git a/PROJECTS b/PROJECTS --- a/PROJECTS +++ b/PROJECTS @@ -109,7 +109,6 @@ - colmmd Superseded by colamd - treelayout - cholinc - - condest - bicg Can this be taken from octave-forge? - bicgstab - cgs diff --git a/doc/ChangeLog b/doc/ChangeLog --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,15 @@ +2007-11-26 David Bateman + + * interpreter/sparse.txi: Document condest. + * interpreter/plot.txi: Document the new text properties and the + TeX interpreter mode of text objects. + * interpreter/plotimages.m: Add an example for the TeX + interpreter. + * interpreter/Makefile.in (PLOTIMAGES): Add the TeX example + + * interpreter/plot.txi: Document caxis. + * interpreter/image.txi: Document gmap40. + 2007-11-12 Joseph P. Skudlarek * interpreter/gpl.txi: Move index commands after sectioning commands. diff --git a/doc/interpreter/Makefile.in b/doc/interpreter/Makefile.in --- a/doc/interpreter/Makefile.in +++ b/doc/interpreter/Makefile.in @@ -61,7 +61,7 @@ GEOMETRYIMAGES_PDF = $(addsuffix .pdf, $(GEOMETRYIMAGES)) GEOMETRYIMAGES_PNG = $(addsuffix .png, $(GEOMETRYIMAGES)) -PLOTIMAGES = plot hist errorbar polar mesh plot3 +PLOTIMAGES = plot hist errorbar polar mesh plot3 extended PLOTIMAGES_EPS = $(addsuffix .eps, $(PLOTIMAGES)) PLOTIMAGES_PDF = $(addsuffix .pdf, $(PLOTIMAGES)) PLOTIMAGES_PNG = $(addsuffix .png, $(PLOTIMAGES)) diff --git a/doc/interpreter/image.txi b/doc/interpreter/image.txi --- a/doc/interpreter/image.txi +++ b/doc/interpreter/image.txi @@ -152,6 +152,15 @@ @DOCSTRING(winter) +An additional colormap is @code{gmap40}. This code map contains only +colors with integer values of the red, green and blue components. This +workaround a limitation on gnuplot 4.0, that does not allow the color of +line or patch objects to be set, and so @code{gmap40} is useful for +gnuplot 4.0 users, and in particular in conjunction with the @var{bar}, +@var{barh} or @var{contour} functions. + +@DOCSTRING(gmap40) + @node Plotting on top of Images @section Plotting on top of Images diff --git a/doc/interpreter/plot.txi b/doc/interpreter/plot.txi --- a/doc/interpreter/plot.txi +++ b/doc/interpreter/plot.txi @@ -189,6 +189,11 @@ @DOCSTRING(axis) +Similarly the axis limits of the colormap can be changed with the caxis +function. + +@DOCSTRING(caxis) + @node Three-Dimensional Plotting @subsection Three-Dimensional Plotting @@ -806,8 +811,190 @@ @item color The color of the text. @xref{Colors}. + +@item fontname +The font used for the text. + +@item fontsize +The size of the font, in points to use. + +@item fontangle +Flag whether the font is italic or normal. Valid values are 'normal', +'italic' and 'oblique'. + +@item fontweight +Flag whether the font is bold, etc. Valid values are 'normal', 'bold', +'demi' or 'light'. + +@item interpreter +Determines how the text is rendered. Valid values are 'none', 'tex' or +'latex'. @end table +All text objects, including titles, labels, legends, and text, include +the property 'interpreter', this property determines the manner in which +special control sequences in the text are rendered. If the interpreter +is set to 'none', then no rendering occurs. At this point the 'latex' +option is not implemented and so the 'latex' interpreter also does not +interpret the text. + +The 'tex' option implements a subset of @sc{TeX} functionality in the +rendering of the text. This allows the insertion of special characters +such as Greek or mathematical symbols within the text. The special +characters are also inserted with a code starting with the back-slash +(\) character, as in the table @ref{tab:extended}. + +In addition, the formating of the text can be changed within the string +with the codes + +@multitable @columnfractions .2 .2 .6 .2 +@item @tab \bf @tab Bold font @tab +@item @tab \it @tab Italic font @tab +@item @tab \sl @tab Oblique Font @tab +@item @tab \rm @tab Normal font @tab +@end multitable + +These are be used in conjunction with the @{ and @} characters to limit +the change in the font to part of the string. For example + +@example +xlabel ('@{\bf H@} = a @{\bf V@}') +@end example + +where the character 'a' will not appear in a bold font. Note that to +avoid having Octave interpret the backslash characters in the strings, +the strings should be in single quotes. + +It is also possible to change the fontname and size within the text + +@multitable @columnfractions .1 .4 .6 .1 +@item @tab \fontname@{@var{fontname}@} @tab Specify the font to use @tab +@item @tab \fontsize@{@var{size}@} @tab Specify the size of the font to +use @tab +@end multitable + +Finally, the superscript and subscripting can be controlled with the '^' +and '_' characters. If the '^' or '_' is followed by a @{ character, +then all of the block surrounded by the @{ @} pair is super- or +sub-scripted. Without the @{ @} pair, only the character immediately +following the '^' or '_' is super- or sub-scripted. + +@float Table,tab:extended +@iftex +@tex +\vskip 6pt +{\hbox to \hsize {\hfill\vbox{\offinterlineskip \tabskip=0pt +\halign{ +\vrule height2.0ex depth1.ex width 0.6pt #\tabskip=0.3em & +# \hfil & \vrule # & # \hfil & # \vrule & +# \hfil & \vrule # & # \hfil & # \vrule & +# \hfil & \vrule # & # \hfil & # \vrule +width 0.6pt \tabskip=0pt\cr +\noalign{\hrule height 0.6pt} +& Code && Sym && Code && Sym && Code && Sym &\cr +\noalign{\hrule} +& $\backslash$forall && $\forall$ && $\backslash$exists && $\exists$ && $\backslash$ni && $\ni$ &\cr +& $\backslash$cong && $\cong$ && $\backslash$Delta && $\Delta$ && $\backslash$Phi && $\Phi$ &\cr +& $\backslash$Gamma && $\Gamma$ && $\backslash$vartheta && $\vartheta$ && $\backslash$Lambda && $\Lambda$ &\cr +& $\backslash$Pi && $\Pi$ && $\backslash$Theta && $\Theta$ && $\backslash$Sigma && $\Sigma$ &\cr +& $\backslash$varsigma && $\varsigma$ && $\backslash$Omega && $\Omega$ && $\backslash$Xi && $\Xi$ &\cr +& $\backslash$Psi && $\Psi$ && $\backslash$perp && $\perp$ && $\backslash$alpha && $\alpha$ &\cr +& $\backslash$beta && $\beta$ && $\backslash$chi && $\chi$ && $\backslash$delta && $\delta$ &\cr +& $\backslash$epsilon && $\epsilon$ && $\backslash$phi && $\phi$ && $\backslash$gamma && $\gamma$ &\cr +& $\backslash$eta && $\eta$ && $\backslash$iota && $\iota$ && $\backslash$kappa && $\kappa$ &\cr +& $\backslash$lambda && $\lambda$ && $\backslash$mu && $\mu$ && $\backslash$nu && $\nu$ &\cr +& $\backslash$o && $\o$ && $\backslash$pi && $\pi$ && $\backslash$theta && $\theta$ &\cr +& $\backslash$rho && $\rho$ && $\backslash$sigma && $\sigma$ && $\backslash$tau && $\tau$ &\cr +& $\backslash$upsilon && $\upsilon$ && $\backslash$varpi && $\varpi$ && $\backslash$omega && $\omega$ &\cr +& $\backslash$xi && $\xi$ && $\backslash$psi && $\psi$ && $\backslash$zeta && $\zeta$ &\cr +& $\backslash$sim && $\sim$ && $\backslash$Upsilon && $\Upsilon$ && $\backslash$prime && $\prime$ &\cr +& $\backslash$leq && $\leq$ && $\backslash$infty && $\infty$ && $\backslash$clubsuit && $\clubsuit$ &\cr +& $\backslash$diamondsuit && $\diamondsuit$ && $\backslash$heartsuit && $\heartsuit$ && $\backslash$spadesuit && $\spadesuit$ &\cr +& $\backslash$leftrightarrow && $\leftrightarrow$ && $\backslash$leftarrow && $\leftarrow$ && $\backslash$uparrow && $\uparrow$ &\cr +& $\backslash$rightarrow && $\rightarrow$ && $\backslash$downarrow && $\downarrow$ && $\backslash$circ && $\circ$ &\cr +& $\backslash$pm && $\pm$ && $\backslash$geq && $\geq$ && $\backslash$times && $\times$ &\cr +& $\backslash$propto && $\propto$ && $\backslash$partial && $\partial$ && $\backslash$bullet && $\bullet$ &\cr +& $\backslash$div && $\div$ && $\backslash$neq && $\neq$ && $\backslash$equiv && $\equiv$ &\cr +& $\backslash$approx && $\approx$ && $\backslash$ldots && $\ldots$ && $\backslash$mid && $\mid$ &\cr +& $\backslash$aleph && $\aleph$ && $\backslash$Im && $\Im$ && $\backslash$Re && $\Re$ &\cr +& $\backslash$wp && $\wp$ && $\backslash$otimes && $\otimes$ && $\backslash$oplus && $\oplus$ &\cr +& $\backslash$oslash && $\oslash$ && $\backslash$cap && $\cap$ && $\backslash$cup && $\cup$ &\cr +& $\backslash$supset && $\supset$ && $\backslash$supseteq && $\supseteq$ && $\backslash$subset && $\subset$ &\cr +& $\backslash$subseteq && $\subseteq$ && $\backslash$in && $\in$ && $\backslash$langle && $\langle$ &\cr +& $\backslash$rangle && $\rangle$ && $\backslash$nabla && $\nabla$ && $\backslash$surd && $\surd$ &\cr +& $\backslash$cdot && $\cdot$ && $\backslash$neg && $\neg$ && $\backslash$wedge && $\wedge$ &\cr +& $\backslash$vee && $\vee$ && $\backslash$copyright && $\copyright$ && $\backslash$rfloor && $\rfloor$ &\cr +& $\backslash$lceil && $\lceil$ && $\backslash$lfloor && $\lfloor$ && $\backslash$rceil && $\rceil$ &\cr +& $\backslash$int && $\int$ && && && && &\cr +\noalign{\hrule height 0.6pt} +}}\hfill}} +@end tex +@end iftex +@ifnottex +@multitable @columnfractions .125 .25 .25 .25 .125 +@item @tab \forall @tab \exists @tab \ni @tab +@item @tab \cong @tab \Delta @tab \Phi @tab +@item @tab \Gamma @tab \vartheta @tab \Lambda @tab +@item @tab \Pi @tab \Theta @tab \Sigma @tab +@item @tab \varsigma @tab \Omega @tab \Xi @tab +@item @tab \Psi @tab \perp @tab \alpha @tab +@item @tab \beta @tab \chi @tab \delta @tab +@item @tab \epsilon @tab \phi @tab \gamma @tab +@item @tab \eta @tab \iota @tab \kappa @tab +@item @tab \lambda @tab \mu @tab \nu @tab +@item @tab \o @tab \pi @tab \theta @tab +@item @tab \rho @tab \sigma @tab \tau @tab +@item @tab \upsilon @tab \varpi @tab \omega @tab +@item @tab \xi @tab \psi @tab \zeta @tab +@item @tab \sim @tab \Upsilon @tab \prime @tab +@item @tab \leq @tab \infty @tab \clubsuit @tab +@item @tab \diamondsuit @tab \heartsuit @tab \spadesuit @tab +@item @tab \leftrightarrow @tab \leftarrow @tab \uparrow @tab +@item @tab \rightarrow @tab \downarrow @tab \circ @tab +@item @tab \pm @tab \geq @tab \times @tab +@item @tab \propto @tab \partial @tab \bullet @tab +@item @tab \div @tab \neq @tab \equiv @tab +@item @tab \approx @tab \ldots @tab \mid @tab +@item @tab \aleph @tab \Im @tab \Re @tab +@item @tab \wp @tab \otimes @tab \oplus @tab +@item @tab \oslash @tab \cap @tab \cup @tab +@item @tab \supset @tab \supseteq @tab \subset @tab +@item @tab \subseteq @tab \in @tab \langle @tab +@item @tab \rangle @tab \nabla @tab \surd @tab +@item @tab \cdot @tab \neg @tab \wedge @tab +@item @tab \vee @tab \copyright @tab \rfloor @tab +@item @tab \lceil @tab \lfloor @tab \rceil @tab +@item @tab \int @tab @tab @tab +@end multitable +@end ifnottex +@caption{Available special characters in @sc{TeX} mode} +@end float + +A complete example showing the capabilities of the extended text is + +@example +@group +x = 0:0.01:3; +plot(x,erf(x)); +hold on; +plot(x,x,"r"); +axis([0, 3, 0, 1]); +text(0.65, 0.6175, strcat('\leftarrow x = @{2/\surd\pi', +' @{\fontsize@{16@}\int_@{\fontsize@{8@}0@}^@{\fontsize@{8@}x@}@}', +' e^@{-t^2@} dt@} = 0.6175')) +@end group +@end example + +@ifnotinfo +@noindent +The result of which can be seen in @ref{fig:extendedtext} + +@float Figure,fig:extendedtext +@image{extended,8cm} +@caption{Example of inclusion of text with the @sc{TeX} interpreter} +@end float +@end ifnotinfo + @node Image Properties @subsubsection Image Properties diff --git a/doc/interpreter/plotimages.m b/doc/interpreter/plotimages.m --- a/doc/interpreter/plotimages.m +++ b/doc/interpreter/plotimages.m @@ -48,6 +48,15 @@ z = linspace (0, 1, numel (t)); plot3 (r.*sin(t), r.*cos(t), z); print (strcat (nm, ".", typ), strcat ("-d", typ)) + elseif (strcmp (nm, "extended")) + x = 0:0.01:3; + plot(x,erf(x)); + hold on; + plot(x,x,"r"); + axis([0, 3, 0, 1]); + text(0.65, 0.6175, strcat('\leftarrow x = {2/\surd\pi {\fontsize{16}', + '\int_{\fontsize{8}0}^{\fontsize{8}x}} e^{-t^2} dt} = 0.6175')) + print (strcat (nm, ".", typ), strcat ("-d", typ)) else error ("unrecognized plot requested"); endif diff --git a/doc/interpreter/sparse.txi b/doc/interpreter/sparse.txi --- a/doc/interpreter/sparse.txi +++ b/doc/interpreter/sparse.txi @@ -490,9 +490,9 @@ @item Linear algebra: @dfn{matrix_type}, @dfn{spchol}, @dfn{cpcholinv}, @dfn{spchol2inv}, @dfn{spdet}, @dfn{spinv}, @dfn{spkron}, - @dfn{splchol}, @dfn{splu}, @dfn{spqr}, @dfn{normest}, + @dfn{splchol}, @dfn{splu}, @dfn{spqr}, @dfn{normest}, @dfn{condest}, @dfn{sprank} -@c @dfn{condest}, @dfn{spaugment} +@c @dfn{spaugment} @c @dfn{eigs}, @dfn{svds} but these are in octave-forge for now @item Iterative techniques: @@ -828,6 +828,8 @@ @DOCSTRING(normest) +@DOCSTRING(condest) + @DOCSTRING(spchol) @DOCSTRING(spcholinv) diff --git a/liboctave/Array.cc b/liboctave/Array.cc --- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -2315,7 +2315,13 @@ { Array retval; - assert (ndims () == 2); + if (ndims () != 2) + { + Array ra_idx (2); + ra_idx(0) = idx_i; + ra_idx(1) = idx_j; + return index (ra_idx, resize_ok, rfv); + } octave_idx_type nr = dim1 (); octave_idx_type nc = dim2 (); diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,28 @@ +2007-11-26 David Bateman + + * intNDArray.cc (template intNDArray + intNDArray::max (int) const, template intNDArray + intNDArray::max (ArrayN&, int) const, + template intNDArray intNDArray::min (int) const, + template intNDArray intNDArray::min + (ArrayN&, int) const): New methods for integer + classes. + * intNDArray.h (class intNDArray): Add min/max methods + * mx-op-defs.h (MIXMAX_DECLS, MINMAX_FCNS, SND_MINMAX_FCN, + NDS_MINMAX_FCN, NDND_MINMAX_FCN): New macro for instantiation of + min/max functions. + * int8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h, + uint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h + (MINMAX_DECLS(T)): Declare the min/max functions for integer + types. + * int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc, + uint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc + (MINMAX_FCNS(T)): Instantiate the min/max functions for integer + types. + + * Arrayc.cc (Array::index (idx_vector&, idx_vector&, int, + const T& rfv) const): If ndims != 2 call ND version of index. + 2007-11-14 John W. Eaton * oct-inttypes.h (opeator T (void) const): New conversion operator. diff --git a/liboctave/int16NDArray.cc b/liboctave/int16NDArray.cc --- a/liboctave/int16NDArray.cc +++ b/liboctave/int16NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (int16NDArray, , int16NDArray, ) NDND_BOOL_OPS (int16NDArray, int16NDArray, octave_int16 (0)) +MINMAX_FCNS (int16) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/int16NDArray.h b/liboctave/int16NDArray.h --- a/liboctave/int16NDArray.h +++ b/liboctave/int16NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, int16NDArray, octave_int16) +MINMAX_DECLS (int16) + #endif /* diff --git a/liboctave/int32NDArray.cc b/liboctave/int32NDArray.cc --- a/liboctave/int32NDArray.cc +++ b/liboctave/int32NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (int32NDArray, , int32NDArray, ) NDND_BOOL_OPS (int32NDArray, int32NDArray, octave_int32 (0)) +MINMAX_FCNS (int32) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/int32NDArray.h b/liboctave/int32NDArray.h --- a/liboctave/int32NDArray.h +++ b/liboctave/int32NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, int32NDArray, octave_int32) +MINMAX_DECLS (int32) + #endif /* diff --git a/liboctave/int64NDArray.cc b/liboctave/int64NDArray.cc --- a/liboctave/int64NDArray.cc +++ b/liboctave/int64NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (int64NDArray, , int64NDArray, ) NDND_BOOL_OPS (int64NDArray, int64NDArray, octave_int64 (0)) +MINMAX_FCNS (int64) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/int64NDArray.h b/liboctave/int64NDArray.h --- a/liboctave/int64NDArray.h +++ b/liboctave/int64NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, int64NDArray, octave_int64) +MINMAX_DECLS (int64) + #endif /* diff --git a/liboctave/int8NDArray.cc b/liboctave/int8NDArray.cc --- a/liboctave/int8NDArray.cc +++ b/liboctave/int8NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (int8NDArray, , int8NDArray, ) NDND_BOOL_OPS (int8NDArray, int8NDArray, octave_int8 (0)) +MINMAX_FCNS (int8) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/int8NDArray.h b/liboctave/int8NDArray.h --- a/liboctave/int8NDArray.h +++ b/liboctave/int8NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, int8NDArray, octave_int8) +MINMAX_DECLS (int8) + #endif /* diff --git a/liboctave/intNDArray.cc b/liboctave/intNDArray.cc --- a/liboctave/intNDArray.cc +++ b/liboctave/intNDArray.cc @@ -229,6 +229,140 @@ MX_ND_REDUCTION (retval(result_idx) += intNDArray::elem (iter_idx), 0, intNDArray); } +template +intNDArray +intNDArray::max (int dim) const +{ + ArrayN dummy_idx; + return max (dummy_idx, dim); +} + +template +intNDArray +intNDArray::max (ArrayN& idx_arg, int dim) const +{ + dim_vector dv = this->dims (); + dim_vector dr = this->dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return intNDArray (); + + dr(dim) = 1; + + intNDArray result (dr); + idx_arg.resize (dr); + + octave_idx_type x_stride = 1; + octave_idx_type x_len = dv(dim); + for (int i = 0; i < dim; i++) + x_stride *= dv(i); + + for (octave_idx_type i = 0; i < dr.numel (); i++) + { + octave_idx_type x_offset; + if (x_stride == 1) + x_offset = i * x_len; + else + { + octave_idx_type x_offset2 = 0; + x_offset = i; + while (x_offset >= x_stride) + { + x_offset -= x_stride; + x_offset2++; + } + x_offset += x_offset2 * x_stride * x_len; + } + + octave_idx_type idx_j = 0; + + T tmp_max = this->elem (x_offset); + + for (octave_idx_type j = 1; j < x_len; j++) + { + T tmp = this->elem (j * x_stride + x_offset); + + if (tmp > tmp_max) + { + idx_j = j; + tmp_max = tmp; + } + } + + result.elem (i) = tmp_max; + idx_arg.elem (i) = idx_j; + } + + return result; +} + +template +intNDArray +intNDArray::min (int dim) const +{ + ArrayN dummy_idx; + return min (dummy_idx, dim); +} + +template +intNDArray +intNDArray::min (ArrayN& idx_arg, int dim) const +{ + dim_vector dv = this->dims (); + dim_vector dr = this->dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return intNDArray (); + + dr(dim) = 1; + + intNDArray result (dr); + idx_arg.resize (dr); + + octave_idx_type x_stride = 1; + octave_idx_type x_len = dv(dim); + for (int i = 0; i < dim; i++) + x_stride *= dv(i); + + for (octave_idx_type i = 0; i < dr.numel (); i++) + { + octave_idx_type x_offset; + if (x_stride == 1) + x_offset = i * x_len; + else + { + octave_idx_type x_offset2 = 0; + x_offset = i; + while (x_offset >= x_stride) + { + x_offset -= x_stride; + x_offset2++; + } + x_offset += x_offset2 * x_stride * x_len; + } + + octave_idx_type idx_j = 0; + + T tmp_min = this->elem (x_offset); + + for (octave_idx_type j = 1; j < x_len; j++) + { + T tmp = this->elem (j * x_stride + x_offset); + + if (tmp < tmp_min) + { + idx_j = j; + tmp_min = tmp; + } + } + + result.elem (i) = tmp_min; + idx_arg.elem (i) = idx_j; + } + + return result; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/intNDArray.h b/liboctave/intNDArray.h --- a/liboctave/intNDArray.h +++ b/liboctave/intNDArray.h @@ -73,6 +73,11 @@ boolNDArray all (int dim = -1) const; boolNDArray any (int dim = -1) const; + intNDArray max (int dim = 0) const; + intNDArray max (ArrayN& index, int dim = 0) const; + intNDArray min (int dim = 0) const; + intNDArray min (ArrayN& index, int dim = 0) const; + intNDArray sum (int dim) const; intNDArray squeeze (void) const diff --git a/liboctave/mx-op-defs.h b/liboctave/mx-op-defs.h --- a/liboctave/mx-op-defs.h +++ b/liboctave/mx-op-defs.h @@ -1159,6 +1159,95 @@ #endif +#define SND_MINMAX_FCN(FCN, OP, T) \ +T ## NDArray \ +FCN (octave_ ## T d, const T ## NDArray& m) \ +{ \ + dim_vector dv = m.dims (); \ + octave_idx_type nel = dv.numel (); \ +\ + if (nel == 0) \ + return T ## NDArray (dv); \ +\ + T ## NDArray result (dv); \ +\ + for (octave_idx_type i = 0; i < nel; i++) \ + { \ + OCTAVE_QUIT; \ + result (i) = d OP m (i) ? d : m(i); \ + } \ +\ + return result; \ +} + +#define NDS_MINMAX_FCN(FCN, OP, T) \ +T ## NDArray \ +FCN (const T ## NDArray& m, octave_ ## T d) \ +{ \ + dim_vector dv = m.dims (); \ + octave_idx_type nel = dv.numel (); \ +\ + if (nel == 0) \ + return T ## NDArray (dv); \ +\ + T ## NDArray result (dv); \ +\ + for (octave_idx_type i = 0; i < nel; i++) \ + { \ + OCTAVE_QUIT; \ + result (i) = m (i) OP d ? m(i) : d; \ + } \ +\ + return result; \ +} + +#define NDND_MINMAX_FCN(FCN, OP, T) \ +T ## NDArray \ +FCN (const T ## NDArray& a, const T ## NDArray& b) \ +{ \ + dim_vector dv = a.dims (); \ + octave_idx_type nel = dv.numel (); \ +\ + if (dv != b.dims ()) \ + { \ + (*current_liboctave_error_handler) \ + ("two-arg min expecting args of same size"); \ + return T ## NDArray (); \ + } \ +\ + if (nel == 0) \ + return T ## NDArray (dv); \ +\ + T ## NDArray result (dv); \ +\ + for (octave_idx_type i = 0; i < nel; i++) \ + { \ + OCTAVE_QUIT; \ + result (i) = a(i) OP b(i) ? a(i) : b(i); \ + } \ +\ + return result; \ +} + +#define MINMAX_FCNS(T) \ + SND_MINMAX_FCN (min, <, T) \ + NDS_MINMAX_FCN (min, <, T) \ + NDND_MINMAX_FCN (min, <, T) \ + SND_MINMAX_FCN (max, >, T) \ + NDS_MINMAX_FCN (max, >, T) \ + NDND_MINMAX_FCN (max, >, T) + +#define MINMAX_DECLS(T) \ + extern OCTAVE_API T ## NDArray min (octave_ ## T d, const T ## NDArray& m); \ + extern OCTAVE_API T ## NDArray min (const T ## NDArray& m, octave_ ## T d); \ + extern OCTAVE_API T ## NDArray min (const T ## NDArray& a, \ + const T ## NDArray& b); \ + extern OCTAVE_API T ## NDArray max (octave_ ## T d, const T ## NDArray& m); \ + extern OCTAVE_API T ## NDArray max (const T ## NDArray& m, octave_ ## T d); \ + extern OCTAVE_API T ## NDArray max (const T ## NDArray& a, \ + const T ## NDArray& b); + + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/uint16NDArray.cc b/liboctave/uint16NDArray.cc --- a/liboctave/uint16NDArray.cc +++ b/liboctave/uint16NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (uint16NDArray, , uint16NDArray, ) NDND_BOOL_OPS (uint16NDArray, uint16NDArray, octave_uint16 (0)) +MINMAX_FCNS (uint16) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/uint16NDArray.h b/liboctave/uint16NDArray.h --- a/liboctave/uint16NDArray.h +++ b/liboctave/uint16NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, uint16NDArray, octave_uint16) +MINMAX_DECLS (uint16) + #endif /* diff --git a/liboctave/uint32NDArray.cc b/liboctave/uint32NDArray.cc --- a/liboctave/uint32NDArray.cc +++ b/liboctave/uint32NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (uint32NDArray, , uint32NDArray, ) NDND_BOOL_OPS (uint32NDArray, uint32NDArray, octave_uint32 (0)) +MINMAX_FCNS (uint32) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/uint32NDArray.h b/liboctave/uint32NDArray.h --- a/liboctave/uint32NDArray.h +++ b/liboctave/uint32NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, uint32NDArray, octave_uint32) +MINMAX_DECLS (uint32) + #endif /* diff --git a/liboctave/uint64NDArray.cc b/liboctave/uint64NDArray.cc --- a/liboctave/uint64NDArray.cc +++ b/liboctave/uint64NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (uint64NDArray, , uint64NDArray, ) NDND_BOOL_OPS (uint64NDArray, uint64NDArray, octave_uint64 (0)) +MINMAX_FCNS (uint64) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/uint64NDArray.h b/liboctave/uint64NDArray.h --- a/liboctave/uint64NDArray.h +++ b/liboctave/uint64NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, uint64NDArray, octave_uint64) +MINMAX_DECLS (uint64) + #endif /* diff --git a/liboctave/uint8NDArray.cc b/liboctave/uint8NDArray.cc --- a/liboctave/uint8NDArray.cc +++ b/liboctave/uint8NDArray.cc @@ -48,6 +48,8 @@ NDND_CMP_OPS (uint8NDArray, , uint8NDArray, ) NDND_BOOL_OPS (uint8NDArray, uint8NDArray, octave_uint8 (0)) +MINMAX_FCNS (uint8) + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/liboctave/uint8NDArray.h b/liboctave/uint8NDArray.h --- a/liboctave/uint8NDArray.h +++ b/liboctave/uint8NDArray.h @@ -40,6 +40,8 @@ MARRAY_FORWARD_DEFS (MArrayN, uint8NDArray, octave_uint8) +MINMAX_DECLS (uint8) + #endif /* diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,95 @@ +2007-11-26 David Bateman + + * plot/quiver3.m, plot/surfnorm.m, plot/__quiver__.m: New functions. + * plot/Makefile.in (SOURCES): Add them to the sources. + * plot/quiver.m: Modify to use __quiver__.m. + + * plot/hist.m: Avoid saturation when the x values are in an + inetger type. + +2007-11-26 Jason Riedy + + * linear-algebra/condest.m, linear-algebra/onenormest.m: New + functions. + * linear-algebra/Makefile.in (SOURCES): Add them to the sources. + +2007-11-26 David Bateman + + * plot/__go_draw_axes__.m: Prevent the cbrange from being of zero + extent. + + * plot/colorbar.m: New function. + * plot/Makefile.in (SOURCES): Add it to the sources. + * plot/__go_draw_axes__.m: Calculate the colorbar position, + precalculate the clim, set pm3d except for mesh. + * plot/__contour__.m: Don't scale the contours to clim, but rather + save the real values so that colorbar corresponds to the contour + levels. + + * plot/stem.m: Set marker color the same as the line color. Draw + a single discontinous line object for the stems. + + * plot/sphere.m: New function ported from JHandles. + * plot/Makefile.in (SOURCES): Add it to the sources. + + * plot/__go_draw_axes__.m: Pass the have_newer_gnuplot arg to + __maybe_munge_text__. Use it to reforce fontname for gnuplot 4.0 + to get enhanced mode to work correctly for the X11 terminal. + + * plot/imagesc.m, plot/image.m: Scale colormap to image and not + the reverse. Allow an axes handle to be passed and/or returned. + * plot/__go_draw_axes__.m: Autoscale colormap for images. + + * plot/__go_draw_axes__.m: Add depthorder flag to "set pm3d" to + sort surface patches by their depth and not the order they are + rendered in. + + * plot/__patch__.m: Set clim correctly. + * plot__go_draw_axes__.m: Allow patch objects to have markers, and + the marker color is determined by the cmap. + * plot/scatter.m: New function to 2D scatter plots. + * plot/scatter3.m: New function to 3D scatter plots. + * plot/__scatter__.m: Support function for scatter plots + * Makefile.in (SOURCES): Ad dnew functions here. + + * plot/drawnow.m (open_gnuplot_stream, init_gnuplot_stream): + Return whether the terminal supports enhanced text or not. + (drawnow:enhanced_term): New sub-function to determine if terminal + supports enhanced mode. + * plot/__go_draw_figure__.m: Accept enhanced flag and pass to + __go_draw_axes__. + * plot/__go_draw_axes__.m: Accept enhanced flag and munge text if + needed to support the enhanced mode. + * plot/print.m: Remove "enhanced" option as this is now treated in + drawnow.m. + + + * plot/caxis.m: New function to control the color axis limits. + * plot/Makefile.in (SOURCES): Include it. + * plot/axis.m: Allow the first argument to be an axes handle. + * plot/__go_draw_axes__.m: Move the setting of the caxis, also + autoscale caxis for patches. If any(isinf(clim)) don't set the + caxis limits. + + * image/gmap40.m: New gnuplot 4.0 specific colormap fucntion. + * image/Makefile.in (SOURCES): Include it. + * plot/__bar__.h: Allow axis handles to be passed. Set the color + of the bars for the colormap. + * plot/bar.m, plot/barh.m: Document that axis handles can be + passed. + * plot/__contour.m: Avoid possible divide by zero error. + * plot/contour.m: Missing semicolon. + * plot/surface.m: Don't attempt to set additional arguments if + there are none. + * plot/Makefile.in (SOURCES): Include __bars__.m + +2007-11-19 Michael Goffioul + + * plot/__bar__.m: put bar creation code into separate function + to allow easy hook up from other graphic backends + + * plot/__bars__.m: new function containing bar creation code + 2007-11-26 Alexander Barth * general/accumarray.m: Correct dimension check. diff --git a/scripts/image/Makefile.in b/scripts/image/Makefile.in --- a/scripts/image/Makefile.in +++ b/scripts/image/Makefile.in @@ -34,9 +34,9 @@ INSTALL_DATA = @INSTALL_DATA@ SOURCES = __img__.m __img_via_file__.m autumn.m bone.m brighten.m colormap.m \ - cool.m copper.m flag.m gray.m gray2ind.m hot.m hsv.m hsv2rgb.m image.m \ - image_viewer.m imagesc.m imshow.m ind2gray.m ind2rgb.m jet.m loadimage.m \ - ntsc2rgb.m ocean.m pink.m prism.m rainbow.m rgb2hsv.m rgb2ind.m \ + cool.m copper.m flag.m gmap40.m gray.m gray2ind.m hot.m hsv.m hsv2rgb.m \ + image.m image_viewer.m imagesc.m imshow.m ind2gray.m ind2rgb.m jet.m \ + loadimage.m ntsc2rgb.m ocean.m pink.m prism.m rainbow.m rgb2hsv.m rgb2ind.m \ rgb2ntsc.m saveimage.m spring.m summer.m white.m winter.m IMAGES = default.img diff --git a/scripts/image/gmap40.m b/scripts/image/gmap40.m new file mode 100644 --- /dev/null +++ b/scripts/image/gmap40.m @@ -0,0 +1,49 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} gmap40 (@var{n}) +## Create a color colormap. The colormap is red, green, blue, yellow, +## magneta and cyan. These are the colors that are allowed with patch +## objects using gnuplot 4.0, and so this colormap function is specially +## designed for users of gnuplot 4.0. The argument @var{n} should be +## a scalar. If it is omitted, a length of 6 is assumed. Larger values +## of @var{n} result in a repetition of the above colors +## @seealso{colormap} +## @end deftypefn + +function map = gmap40 (number) + + if (nargin == 0) + number = 6; + elseif (nargin == 1) + if (! isscalar (number)) + error ("gmap40: argument must be a scalar"); + endif + else + print_usage (); + endif + + if (number >= 1) + map = repmat ([1, 0, 0; 0, 1, 0; 0, 0, 1; 1, 1, 0; 1, 0, 1; 0, 1, 1], + ceil (number / 6), 1) (1:number, :); + else + map = []; + endif + +endfunction diff --git a/scripts/image/image.m b/scripts/image/image.m --- a/scripts/image/image.m +++ b/scripts/image/image.m @@ -21,8 +21,8 @@ ## @deftypefn {Function File} {} image (@var{img}) ## @deftypefnx {Function File} {} image (@var{x}, @var{y}, @var{img}) ## Display a matrix as a color image. The elements of @var{x} are indices -## into the current colormap and should have values between 1 and the -## length of the colormap. +## into the current colormap, and the colormap will be scaled so that the +## extremes of @var{x} are mapped to the extremes of teh colormap. ## ## It first tries to use @code{gnuplot}, then @code{display} from ## @code{ImageMagick}, then @code{xv}, and then @code{xloadimage}. @@ -39,35 +39,57 @@ ## Created: July 1994 ## Adapted-By: jwe -function h = image (x, y, img) +function retval = image (varargin) + + if (nargin < 2) + print_usage (); + elseif (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("image: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + tmp = __image__ (h, varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + tmp = __image__ (gca (), varargin{:}); + endif + + if (nargout > 0) + retval = tmp; + endif + +endfunction + +function h = __image__ (ax, x, y, img) ## Deprecated zoom. Remove this hunk of code if old zoom argument ## is outmoded. - if ((nargin == 2 && isscalar (y)) || nargin == 4) + if ((nargin == 3 && isscalar (y)) || nargin == 5) warning ("image: zoom argument ignored -- use GUI features"); endif - if (nargin == 4) - nargin = 3; + if (nargin == 5) + nargin = 4; endif - if (nargin == 2 && isscalar (y)) - nargin = 1; + if (nargin == 3 && isscalar (y)) + nargin = 2; endif - if (nargin == 0) + if (nargin == 1) ## Load Bobbie Jo Richardson (Born 3/16/94) img = loadimage ("default.img"); x = y = []; - elseif (nargin == 1) + elseif (nargin == 2) img = x; x = y = []; - elseif (nargin == 2 || nargin > 3) + elseif (nargin == 3 || nargin > 4) print_usage (); endif - tmp = __img__ (x, y, img); - - if (nargout > 0) - h = tmp; - endif + h = __img__ (x, y, img); endfunction diff --git a/scripts/image/imagesc.m b/scripts/image/imagesc.m --- a/scripts/image/imagesc.m +++ b/scripts/image/imagesc.m @@ -21,92 +21,100 @@ ## @deftypefn {Function File} {} imagesc (@var{A}) ## @deftypefnx {Function File} {} imagesc (@var{x}, @var{y}, @var{A}) ## @deftypefnx {Function File} {} imagesc (@dots{}, @var{limits}) -## @deftypefnx {Function File} { @var{B} = } imagesc (@dots{}) +## @deftypefnx {Function File} {} imagesc (@var{h}, @dots{}) +## @deftypefnx {Function File} { @var{h} = } imagesc (@dots{}) ## Display a scaled version of the matrix @var{A} as a color image. The -## matrix is scaled so that its entries are indices into the current -## colormap. The scaled matrix is returned. If @var{limits} = [@var{lo}, @var{hi}] are -## given, then that range maps into the full range of the colormap rather -## than the minimum and maximum values of @var{A}. +## colormap is scaled so that the entries of the matrix occupy the entire +## colormap. If @var{limits} = [@var{lo}, @var{hi}] are given, then that +## range is set to the 'clim' of the current axes. ## ## The axis values corresponding to the matrix elements are specified in ## @var{x} and @var{y}, either as pairs giving the minimum and maximum ## values for the respective axes, or as values for each row and column ## of the matrix @var{A}. -## @seealso{image, imshow} +## +## @seealso{image, imshow, clim, caxis} ## @end deftypefn ## Author: Tony Richardson ## Created: July 1994 ## Adapted-By: jwe -function ret = imagesc (x, y, A, limits, DEPRECATEDZOOM) +function retval = imagesc (varargin) + + if (nargin < 1) + print_usage (); + elseif (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("imagesc: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + tmp = __imagesc__ (h, varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + tmp = __imagesc__ (gca (), varargin{:}); + endif + + if (nargout > 0) + retval = tmp; + endif + +endfunction + +function ret = __imagesc__ (ax, x, y, A, limits, DEPRECATEDZOOM) ## Deprecated zoom. Remove this hunk of code if old zoom argument ## is outmoded. - if ((nargin == 2 && isscalar (y)) - || (nargin == 3 && (isscalar (y) || isscalar (A))) - || (nargin == 4 && isscalar (limits)) - || nargin == 5) + if ((nargin == 3 && isscalar (y)) + || (nargin == 4 && (isscalar (y) || isscalar (A))) + || (nargin == 5 && isscalar (limits)) + || nargin == 6) warning ("image: zoom argument ignored -- use GUI features"); endif - if (nargin == 5) + if (nargin == 6) if (isscalar (limits)) limits = DEPRECATEDZOOM; endif + nargin = 5; + endif + if (nargin == 5 && isscalar (limits)) nargin = 4; endif - if (nargin == 4 && isscalar (limits)) - nargin = 3; - endif - if (nargin == 3 && (isscalar (y) || isscalar (A))) + if (nargin == 4 && (isscalar (y) || isscalar (A))) if (isscalar (y)) y = A; endif - nargin = 2; + nargin = 3; endif - if (nargin == 2 && isscalar (y)) - nargin = 1; + if (nargin == 3 && isscalar (y)) + nargin = 2; endif - if (nargin < 1 || nargin > 4) + if (nargin < 2 || nargin > 5) print_usage (); - elseif (nargin == 1) + elseif (nargin == 2) A = x; x = y = limits = []; - elseif (nargin == 2) + elseif (nargin == 3) A = x; limits = y; x = y = []; - elseif (nargin == 3 && !isscalar (x) && !isscalar (y) && !isscalar (A)) + elseif (nargin == 4 && !isscalar (x) && !isscalar (y) && !isscalar (A)) limits = []; endif + ret = image (ax, x, y, A); + ## use given limits or guess them from the matrix if (length (limits) == 2 && limits(2) >= limits(1)) - minval = limits(1); - maxval = limits(2); - A(A < minval) = minval; - A(A > maxval) = maxval; - elseif (length (limits) == 0) - maxval = max (A(:)); - minval = min (A(:)); - else + set (ax, "clim", limits); + elseif (!isempty (limits)) error ("expected data limits to be [lo, hi]"); endif - ## scale the limits to the range of the colormap - if (maxval == minval) - B = ones (size (A)); - else - ## Rescale values to between 1 and length (colormap) inclusive. - B = round ((A - minval) / (maxval - minval) * (rows (colormap) - 1)) + 1; - endif - - ## display or return the image - if (nargout == 0) - image (x, y, B); - else - ret = B; - endif - endfunction diff --git a/scripts/linear-algebra/Makefile.in b/scripts/linear-algebra/Makefile.in --- a/scripts/linear-algebra/Makefile.in +++ b/scripts/linear-algebra/Makefile.in @@ -33,9 +33,9 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ -SOURCES = __norm__.m commutation_matrix.m cond.m cross.m dmult.m \ - dot.m duplication_matrix.m housh.m krylov.m krylovb.m logm.m \ - null.m orth.m qzhess.m rank.m rref.m trace.m vec.m vech.m +SOURCES = __norm__.m commutation_matrix.m cond.m condest.m cross.m \ + dmult.m dot.m duplication_matrix.m housh.m krylov.m krylovb.m logm.m \ + null.m onenormest.m orth.m qzhess.m rank.m rref.m trace.m vec.m vech.m DISTFILES = $(addprefix $(srcdir)/, Makefile.in $(SOURCES)) diff --git a/scripts/linear-algebra/condest.m b/scripts/linear-algebra/condest.m new file mode 100644 --- /dev/null +++ b/scripts/linear-algebra/condest.m @@ -0,0 +1,218 @@ +## Copyright (C) 2007, Regents of the University of California +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{est}, @var{v}] =} condest (@var{A}, @var{t}) +## @deftypefnx {Function File} {[@var{est}, @var{v}] =} condest (@var{A}, @var{solve}, @var{solve_t}, @var{t}) +## @deftypefnx {Function File} {[@var{est}, @var{v}] =} condest (@var{apply}, @var{apply_t}, @var{solve}, @var{solve_t}, @var{n}, @var{t}) +## +## Estimate the 1-norm condition number of a matrix matrix @var{A} +## using @var{t} test vectors using a randomized 1-norm estimator. +## If @var{t} exceeds 5, then only 5 test vectors are used. +## +## If the matrix is not explicit, e.g. when estimating the condition +## number of @var{A} given an LU factorization, @code{condest} uses the +## following functions: +## +## @table @var +## @item apply +## @code{A*x} for a matrix @code{x} of size @var{n} by @var{t}. +## @item apply_t +## @code{A'*x} for a matrix @code{x} of size @var{n} by @var{t}. +## @item solve +## @code{A \ b} for a matrix @code{b} of size @var{n} by @var{t}. +## @item solve_t +## @code{A' \ b} for a matrix @code{b} of size @var{n} by @var{t}. +## @end table +## +## The implicit version requires an explicit dimension @var{n}. +## +## @code{condest} uses a randomized algorithm to approximate +## the 1-norms. +## +## @code{condest} returns the 1-norm condition estimate @var{est} and +## a vector @var{v} satisfying @code{norm (@var{A}*@var{v}, 1) == norm +## (@var{A}, 1) * norm (@var{v}, 1) / @var{est}}. When @var{est} is +## large, @var{v} is an approximate null vector. +## +## References: +## @itemize +## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm +## for Matrix 1-Norm Estimation, with an Application to 1-Norm +## Pseudospectra." SIMAX vol 21, no 4, pp 1185-1201. +## @url{http://dx.doi.org/10.1137/S0895479899356080} +## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm +## for Matrix 1-Norm Estimation, with an Application to 1-Norm +## Pseudospectra." @url{http://citeseer.ist.psu.edu/223007.html} +## @end itemize +## +## @seealso{norm, cond, onenormest} +## +## @end deftypefn + +## Code originally licensed under +## +## Copyright (c) 2007, Regents of the University of California +## All rights reserved. +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## * Neither the name of the University of California, Berkeley nor the +## names of its contributors may be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR +## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +## Relicensed to GPL for inclusion in Octave. + +## Author: Jason Riedy +## Keywords: linear-algebra norm estimation +## Version: 0.2 + +function [est, v] = condest (varargin) + if size (varargin, 2) < 1 || size (varargin, 2) > 5, + usage("condest: Incorrect arguments."); + endif + + default_t = 5; + + if (ismatrix (varargin{1})) + n = size (varargin{1}, 1); + if (n != size (varargin{1}, 2)) + error ("condest: matrix must be square."); + endif + A = varargin{1}; + + if (size (varargin, 2) > 1) + if (isscalar (varargin{2})) + t = varargin{2}; + else + if (size (varargin, 2) < 3) + error ("condest: must supply both solve and solve_t."); + else + solve = varargin{2}; + solve_t = varargin{3}; + if size (varargin, 2) > 3, + t = varargin{4}; + endif + endif + endif + endif + else + if (size (varargin, 2) < 5) + error ("condest: implicit form of condest requires at least 5 arguments."); + endif + apply = varargin{1}; + apply_t = varargin{2}; + solve = varargin{3}; + solve_t = varargin{4}; + n = varargin{5}; + if (! isscalar (n)) + error ("condest: dimension argument of implicit form must be scalar."); + endif + if (size (varargin, 2) > 5) + t = varargin{6}; + endif + endif + + if (! exist ("t", "var")) + t = min (n, default_t); + endif + + if (! exist ("solve", "var")) + if (issparse (A)) + [L, U, P, Pc] = splu (A); + solve = @(x) Pc' * (U\ (L\ (P*x))); + solve_t = @(x) P'*(L'\ (U'\ (Pc*x))); + else + [L, U, P] = lu (A); + solve = @(x) U\ (L\ (P*x)); + solve_t = @(x) P' * (L'\ (U'\x)); + endif + endif + + if (exist ("A", "var")) + Anorm = norm (A, 1); + else + Anorm = onenormest (apply, apply_t, n, t); + endif + + [Ainv_norm, v, w] = onenormest (solve, solve_t, n, t); + + est = Anorm * Ainv_norm; + v = w / norm (w, 1); + +endfunction + +%!demo +%! N = 100; +%! A = randn (N) + eye (N); +%! condest (A) +%! [L,U,P] = lu (A); +%! condest (A, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x))) +%! condest (@(x) A*x, @(x) A'*x, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x)), N) +%! norm (inv (A), 1) * norm (A, 1) + +## Yes, these test bounds are really loose. There's +## enough randomization to trigger odd cases with hilb(). + +%!test +%! N = 6; +%! A = hilb (N); +%! cA = condest (A); +%! cA_test = norm (inv (A), 1) * norm (A, 1); +%! assert (cA, cA_test, 2^-12); + +%!test +%! N = 6; +%! A = hilb (N); +%! solve = @(x) A\x; solve_t = @(x) A'\x; +%! cA = condest (A, solve, solve_t); +%! cA_test = norm (inv (A), 1) * norm (A, 1); +%! assert (cA, cA_test, 2^-12); + +%!test +%! N = 6; +%! A = hilb (N); +%! apply = @(x) A*x; apply_t = @(x) A'*x; +%! solve = @(x) A\x; solve_t = @(x) A'\x; +%! cA = condest (apply, apply_t, solve, solve_t, N); +%! cA_test = norm (inv (A), 1) * norm (A, 1); +%! assert (cA, cA_test, 2^-6); + +%!test +%! N = 12; +%! A = hilb (N); +%! [rcondA, v] = condest (A); +%! x = A*v; +%! assert (norm(x, inf), 0, eps); diff --git a/scripts/linear-algebra/onenormest.m b/scripts/linear-algebra/onenormest.m new file mode 100644 --- /dev/null +++ b/scripts/linear-algebra/onenormest.m @@ -0,0 +1,265 @@ +## Copyright (C) 2007, Regents of the University of California +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{A}, @var{t}) +## @deftypefnx {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{apply}, @var{apply_t}, @var{n}, @var{t}) +## +## Apply Higham and Tisseur's randomized block 1-norm estimator to +## matrix @var{A} using @var{t} test vectors. If @var{t} exceeds 5, then +## only 5 test vectors are used. +## +## If the matrix is not explicit, e.g. when estimating the norm of +## @code{inv (@var{A})} given an LU factorization, @code{onenormest} applies +## @var{A} and its conjugate transpose through a pair of functions +## @var{apply} and @var{apply_t}, respectively, to a dense matrix of size +## @var{n} by @var{t}. The implicit version requires an explicit dimension +## @var{n}. +## +## Returns the norm estimate @var{est}, two vectors @var{v} and +## @var{w} related by norm +## @code{(@var{w}, 1) = @var{est} * norm (@var{v}, 1)}, +## and the number of iterations @var{iter}. The number of +## iterations is limited to 10 and is at least 2. +## +## References: +## @itemize +## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm +## for Matrix 1-Norm Estimation, with an Application to 1-Norm +## Pseudospectra." SIMAX vol 21, no 4, pp 1185-1201. +## @url{http://dx.doi.org/10.1137/S0895479899356080} +## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm +## for Matrix 1-Norm Estimation, with an Application to 1-Norm +## Pseudospectra." @url{http://citeseer.ist.psu.edu/223007.html} +## @end itemize +## +## @seealso{condest, norm, cond} +## @end deftypefn + +## Code originally licensed under +## +## Copyright (c) 2007, Regents of the University of California +## All rights reserved. +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## * Neither the name of the University of California, Berkeley nor the +## names of its contributors may be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR +## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +## Relicensed to GPL for inclusion in Octave. + +## Author: Jason Riedy +## Keywords: linear-algebra norm estimation +## Version: 0.2 + +function [est, v, w, iter] = onenormest (varargin) + + if (size (varargin, 2) < 1 || size (varargin, 2) > 4) + print_usage (); + endif + + default_t = 5; + itmax = 10; + + if (ismatrix (varargin{1})) + n = size (varargin{1}, 1); + if n != size (varargin{1}, 2), + error ("onenormest: matrix must be square."); + endif + apply = @(x) varargin{1} * x; + apply_t = @(x) varargin{1}' * x; + if (size (varargin) > 1) + t = varargin{2}; + else + t = min (n, default_t); + endif + else + if (size (varargin, 2) < 3) + print_usage(); + endif + n = varargin{3}; + apply = varargin{1}; + apply_t = varargin{2}; + if (size (varargin) > 3) + t = varargin{4}; + else + t = default_t; + endif + endif + + ## Initial test vectors X. + X = rand (n, t); + X = X ./ (ones (n,1) * sum (abs (X), 1)); + + been_there = zeros (n, 1); # Track if a vertex has been visited. + est_old = 0; # To check if the estimate has increased. + S = zeros (n, t); # Normalized vector of signs. The normalization is + + for iter = 1 : itmax + 1 + Y = feval (apply, X); + + ## Find the initial estimate as the largest A*x. + [est, ind_best] = max (sum (abs (Y), 1)); + if (est > est_old || iter == 2) + w = Y(:,ind_best); + endif + if (iter >= 2 && est < est_old) + ## No improvement, so stop. + est = est_old; + break; + endif + + est_old = est; + S_old = S; + if (iter > itmax), + ## Gone too far. Stop. + break; + endif + + S = sign (Y); + + ## Test if any of S are approximately parallel to previous S + ## vectors or current S vectors. If everything is parallel, + ## stop. Otherwise, replace any parallel vectors with + ## rand{-1,+1}. + partest = any (abs (S_old' * S - n) < 4*eps*n); + if (all (partest)) + ## All the current vectors are parallel to old vectors. + ## We've hit a cycle, so stop. + break; + endif + if (any (partest)) + ## Some vectors are parallel to old ones and are cycling, + ## but not all of them. Replace the parallel vectors with + ## rand{-1,+1}. + numpar = sum (partest); + replacements = 2*(rand (n,numpar) < 0.5) - 1; + S(:,partest) = replacements; + endif + ## Now test for parallel vectors within S. + partest = any ( (S' * S - eye (t)) == n ); + if (any (partest)) + numpar = sum (partest); + replacements = 2*(rand (n,numpar) < 0.5) - 1; + S(:,partest) = replacements; + endif + + Z = feval (apply_t, S); + + ## Now find the largest non-previously-visted index per + ## vector. + h = max (abs (Z),2); + [mh, mhi] = max (h); + if (iter >= 2 && mhi == ind_best) + ## Hit a cycle, stop. + break; + endif + [h, ind] = sort (h, 'descend'); + if (t > 1) + firstind = ind(1:t); + if (all (been_there(firstind))) + ## Visited all these before, so stop. + break; + endif + ind = ind (!been_there (ind)); + if (length (ind) < t) + ## There aren't enough new vectors, so we're practically + ## in a cycle. Stop. + break; + endif + endif + + ## Visit the new indices. + X = zeros (n, t); + for zz = 1 : t + X(ind(zz),zz) = 1; + endfor + been_there (ind (1 : t)) = 1; + endfor + + ## The estimate est and vector w are set in the loop above. The + ## vector v selects the ind_best column of A. + v = zeros (n, 1); + v(ind_best) = 1; +endfunction + +%!demo +%! N = 100; +%! A = randn(N) + eye(N); +%! [L,U,P] = lu(A); +%! nm1inv = onenormest(@(x) U\(L\(P*x)), @(x) P'*(L'\(U'\x)), N, 30) +%! norm(inv(A), 1) + +%!test +%! N = 10; +%! A = ones (N); +%! [nm1, v1, w1] = onenormest (A); +%! [nminf, vinf, winf] = onenormest (A', 6); +%! assert (nm1, N, -2*eps); +%! assert (nminf, N, -2*eps); +%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) +%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) + +%!test +%! N = 10; +%! A = ones (N); +%! [nm1, v1, w1] = onenormest (@(x) A*x, @(x) A'*x, N, 3); +%! [nminf, vinf, winf] = onenormest (@(x) A'*x, @(x) A*x, N, 3); +%! assert (nm1, N, -2*eps); +%! assert (nminf, N, -2*eps); +%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) +%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) + +%!test +%! N = 5; +%! A = hilb (N); +%! [nm1, v1, w1] = onenormest (A); +%! [nminf, vinf, winf] = onenormest (A', 6); +%! assert (nm1, norm (A, 1), -2*eps); +%! assert (nminf, norm (A, inf), -2*eps); +%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) +%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) + +## Only likely to be within a factor of 10. +%!test +%! N = 100; +%! A = rand (N); +%! [nm1, v1, w1] = onenormest (A); +%! [nminf, vinf, winf] = onenormest (A', 6); +%! assert (nm1, norm (A, 1), -.1); +%! assert (nminf, norm (A, inf), -.1); +%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) +%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) diff --git a/scripts/plot/Makefile.in b/scripts/plot/Makefile.in --- a/scripts/plot/Makefile.in +++ b/scripts/plot/Makefile.in @@ -38,6 +38,7 @@ __axes_limits__.m \ __axis_label__.m \ __bar__.m \ + __bars__.m \ __contour__.m \ __default_plot_options__.m \ __errcomm__.m \ @@ -62,6 +63,8 @@ __plt_get_axis_arg__.m \ __pltopt1__.m \ __pltopt__.m \ + __quiver__.m \ + __scatter__.m \ ancestor.m \ area.m \ axes.m \ @@ -69,9 +72,11 @@ bar.m \ barh.m \ box.m \ + caxis.m \ clf.m \ close.m \ closereq.m \ + colorbar.m \ contour3.m \ contour.m \ contourc.m \ @@ -110,8 +115,11 @@ polar.m \ print.m \ quiver.m \ + quiver3.m \ replot.m \ ribbon.m \ + scatter.m \ + scatter3.m \ semilogx.m \ semilogxerr.m \ semilogy.m \ @@ -120,6 +128,7 @@ shg.m \ slice.m \ sombrero.m \ + sphere.m \ spinmap.m \ stairs.m \ stem.m \ @@ -127,6 +136,7 @@ surf.m \ surface.m \ surfc.m \ + surfnorm.m \ text.m \ title.m \ view.m \ diff --git a/scripts/plot/__bar__.m b/scripts/plot/__bar__.m --- a/scripts/plot/__bar__.m +++ b/scripts/plot/__bar__.m @@ -22,15 +22,36 @@ function varargout = __bar__ (vertical, func, varargin) + varargout = cell (nargout, 1); + if (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin{1}; + if (! strcmp (get (h, "type"), "axes")) + error ("%s: expecting first argument to be an axes object", func); + endif + oldh = gca (); + unwind_protect + axes (h); + [varargout{:}] = __bar2__ (h, vertical, func, varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + [varargout{:}] = __bar2__ (gca(), vertical, func, varargin{:}); + endif + +endfunction + +function varargout = __bar2__ (h, vertical, func, varargin) + ## Slightly smaller than 0.8 to avoid clipping issue in gnuplot 4.0 width = 0.8 - 10 * eps; group = true; - if (nargin < 3) + if (nargin < 4) print_usage (); endif - if (nargin > 3 && isnumeric (varargin{2})) + if (nargin > 4 && isnumeric (varargin{2})) x = varargin{1}; if (isvector (x)) x = x(:); @@ -63,7 +84,7 @@ newargs = {}; have_line_spec = false; - while (idx <= nargin -2) + while (idx <= nargin - 3) if (isstr (varargin{idx}) && strcmp (varargin{idx}, "grouped")) group = true; idx++; @@ -83,7 +104,7 @@ endif if (isscalar(varargin{idx})) width = varargin{idx++}; - elseif (idx == nargin - 2) + elseif (idx == nargin - 3) newargs = [newargs,varargin(idx++)]; else newargs = [newargs,varargin(idx:idx+1)]; @@ -107,9 +128,8 @@ width = width / ycols; endif - cutoff = (x(1:end-1) + x(2:end)) / 2; - delta_p = [(cutoff - x(1:end-1)); (x(end) - cutoff(end))] * width; - delta_m = [(cutoff(1) - x(1)); (x(2:end) - cutoff)] * width; + cutoff = min (diff (double(x))) / 2; + delta_p = delta_m = repmat (cutoff * width, size (x)); x1 = (x - delta_m)(:)'; x2 = (x + delta_p)(:)'; xb = repmat ([x1; x1; x2; x2](:), 1, ycols); @@ -137,43 +157,19 @@ xb = reshape (xb, [4, numel(xb) / 4 / ycols, ycols]); yb = reshape (yb, [4, numel(yb) / 4 / ycols, ycols]); - color = [1, 0, 0; 0, 1, 0; 0, 0, 1; 1, 1, 0; 1, 0, 1; 0, 1, 1]; - if (vertical) - if (nargout < 2) - newplot (); - tmp = []; - for i = 1 : ycols - if (! have_line_spec) - tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), color(i,:), newargs {:})]; - else - tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), newargs {:})]; - endif - endfor - if (nargout == 1) - varargout{1} = tmp; - endif - else + if (nargout < 2) + newplot (); + tmp = __bars__ (h, vertical, x, y, xb, yb, width, group, have_line_spec, newargs {:}); + if (nargout == 1) + varargout{1} = tmp; + endif + else + if (vertical) varargout{1} = xb; varargout{2} = yb; - endif - else - if (nargout < 2) - newplot (); - tmp = []; - for i = 1 : ycols - if (! have_line_spec) - tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), color(i,:), newargs {:})]; - else - tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), newargs {:})]; - endif - endfor - if (nargout == 1) - varargout{1} = tmp; - endif else varargout{1} = yb; varargout{2} = xb; endif endif - endfunction diff --git a/scripts/plot/__bars__.m b/scripts/plot/__bars__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/__bars__.m @@ -0,0 +1,59 @@ +## Copyright (C) 1996, 1997, 2007 John W. Eaton +## +## 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 +## . + +## Undocumented internal function. + +## Author: jwe + +function tmp = __bars__ (h, vertical, x, y, xb, yb, width, group, have_color_spec, varargin) + + ycols = columns (y); + clim = get (h, "clim"); + + if (vertical) + tmp = []; + for i = 1 : ycols + if (! have_color_spec) + if (ycols == 1) + lev = clim (1); + else + lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1); + endif + tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), "FaceColor", "flat", + "cdata", lev, varargin {:})]; + else + tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), varargin {:})]; + endif + endfor + else + tmp = []; + for i = 1 : ycols + if (! have_color_spec) + if (ycols == 1) + lev = clim (1) + else + lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1); + endif + tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), "FaceColor", "flat", + "cdata", lev, varargin {:})]; + else + tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), varargin {:})]; + endif + endfor + endif +endfunction diff --git a/scripts/plot/__contour__.m b/scripts/plot/__contour__.m --- a/scripts/plot/__contour__.m +++ b/scripts/plot/__contour__.m @@ -38,15 +38,11 @@ endif endif - clim = get (ax, "clim"); - [c, lev] = contourc (varargin{3:end}); ## Decode contourc output format. i1 = 1; h = []; - maxlev = max (lev); - minlev = min (lev); while (i1 < length (c)) clev = c(1,i1); clen = c(2,i1); @@ -57,17 +53,15 @@ p = [c(:, i1+1:i1+clen), NaN(2, 1)]; endif - lev = (clev - minlev) * (clim(2) - clim(1)) / (maxlev - minlev) + clim(1); - if (isnan (z)) h = [h; patch(ax, p(1,:), p(2,:), "facecolor", "none", - "edgecolor", "flat", "cdata", lev)]; + "edgecolor", "flat", "cdata", clev)]; elseif (!ischar(z)) h = [h; patch(ax, p(1,:), p(2,:), z * ones (1, columns (p)), "facecolor", - "none", "edgecolor", "flat", "cdata", lev)]; + "none", "edgecolor", "flat", "cdata", clev)]; else h = [h; patch(ax, p(1,:), p(2,:), clev * ones (1, columns (p)), - "facecolor", "none", "edgecolor", "flat", "cdata", lev)]; + "facecolor", "none", "edgecolor", "flat", "cdata", clev)]; endif i1 += clen+1; endwhile diff --git a/scripts/plot/__go_draw_axes__.m b/scripts/plot/__go_draw_axes__.m --- a/scripts/plot/__go_draw_axes__.m +++ b/scripts/plot/__go_draw_axes__.m @@ -20,9 +20,9 @@ ## Author: jwe -function __go_draw_axes__ (h, plot_stream) +function __go_draw_axes__ (h, plot_stream, enhanced) - if (nargin == 2) + if (nargin == 3) axis_obj = get (h); @@ -32,19 +32,23 @@ = compare_versions (__gnuplot_version__ (), "4.0", ">"); ## Set axis properties here? - + pos = [0,0,1,1]; if (! isempty (axis_obj.outerposition)) pos = axis_obj.outerposition; - fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2)); - fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4)); endif if (! isempty (axis_obj.position)) pos = axis_obj.position; - fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2)); - fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4)); endif + if (! strcmp (axis_obj.__colorbar__, "none")) + [pos, cbox_orient, cbox_size, cbox_origin, cbox_mirror] = ... + gnuplot_postion_colorbox (pos, axis_obj.__colorbar__); + endif + + fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2)); + fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4)); + if (strcmpi (axis_obj.dataaspectratiomode, "manual")) r = axis_obj.dataaspectratio; fprintf (plot_stream, "set size ratio %.15g;\n", -r(2)/r(1)); @@ -52,6 +56,7 @@ fputs (plot_stream, "set size noratio;\n"); endif + fputs (plot_stream, "set pm3d;\n"); fputs (plot_stream, "unset label;\n"); if (! isempty (axis_obj.title)) @@ -59,9 +64,10 @@ if (isempty (t.string)) fputs (plot_stream, "unset title;\n"); else - [f, s] = get_fontname_and_size (t); + [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string", + have_newer_gnuplot); fprintf (plot_stream, "set title \"%s\" font \"%s,%d\";\n", - undo_string_escapes (t.string), f, s); + undo_string_escapes (tt), f, s); endif endif @@ -71,9 +77,10 @@ if (isempty (t.string)) fputs (plot_stream, "unset xlabel;\n"); else - [f, s] = get_fontname_and_size (t); + [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string", + have_newer_gnuplot); fprintf (plot_stream, "set xlabel \"%s\" font \"%s,%d\"", - undo_string_escapes (t.string), f, s); + undo_string_escapes (tt), f, s); if (have_newer_gnuplot) ## Rotation of xlabel not yet support by gnuplot as of 4.2, but ## there is no message about it. @@ -89,9 +96,10 @@ if (isempty (t.string)) fputs (plot_stream, "unset ylabel;\n"); else - [f, s] = get_fontname_and_size (t); + [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string", + have_newer_gnuplot); fprintf (plot_stream, "set ylabel \"%s\" font \"%s,%d\"", - undo_string_escapes (t.string), f, s); + undo_string_escapes (tt), f, s); if (have_newer_gnuplot) fprintf (plot_stream, " rotate by %f;\n", angle); endif @@ -105,8 +113,10 @@ if (isempty (t.string)) fputs (plot_stream, "unset zlabel;\n"); else - fprintf (plot_stream, "set zlabel \"%s\"", - undo_string_escapes (t.string)); + [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string", + have_newer_gnuplot); + fprintf (plot_stream, "set zlabel \"%s\" font \"%s,%d\"", + undo_string_escapes (tt), f, s); if (have_newer_gnuplot) ## Rotation of zlabel not yet support by gnuplot as of 4.2, but ## there is no message about it. @@ -210,6 +220,27 @@ xmax = ymax = zmax = cmax = -Inf; xmin = ymin = zmin = cmin = Inf; + ## This has to be done here as some of the code below depends on the + ## final clim + if (cautoscale) + for i = 1:length (kids) + obj = get (kids(i)); + if (isfield (obj, "cdata")) + [cmin, cmax, cminp] = get_data_limits (cmin, cmax, cminp, + obj.cdata(:)); + endif + endfor + if (cmin == cmax) + cmax = cmin + 1; + endif + clim = [cmin, cmax]; + else + clim = axis_obj.clim; + if (clim(1) == clim(2)) + clim = [clim(1), clim(1) + 1]; + endif + endif + [view_cmd, view_fcn, view_zoom] = image_viewer (); use_gnuplot_for_images = (ischar (view_fcn) && strcmp (view_fcn, "gnuplot_internal")); @@ -232,7 +263,6 @@ endif img_data = obj.cdata; - img_colormap = parent_figure_obj.colormap; img_xdata = obj.xdata; img_ydata = obj.ydata; @@ -281,15 +311,6 @@ data{data_idx} = img_data(:); format = "1"; imagetype = "image"; - - palette_size = rows (img_colormap); - fprintf (plot_stream, - "set palette positive color model RGB maxcolors %i;\n", - palette_size); - fprintf (plot_stream, - "set palette file \"-\" binary record=%d using 1:2:3:4;\n", - palette_size); - fwrite (plot_stream, [1:palette_size; img_colormap'], "float32"); endif titlespec{data_idx} = "title \"\""; @@ -315,7 +336,7 @@ if (isempty (obj.keylabel)) titlespec{data_idx} = "title \"\""; else - tmp = undo_string_escapes (obj.keylabel); + tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot)); titlespec{data_idx} = strcat ("title \"", tmp, "\""); endif [style, typ, with] = do_linestyle_command (obj, data_idx, plot_stream); @@ -435,9 +456,14 @@ case "patch" cmap = parent_figure_obj.colormap; - clim = axis_obj.clim; [nr, nc] = size (obj.xdata); + if (! isempty (obj.cdata)) + cdat = obj.cdata; + else + cdat = []; + endif + for i = 1:nc xcol = obj.xdata(:,i); ycol = obj.ydata(:,i); @@ -480,29 +506,40 @@ if (i > 1 || isempty (obj.keylabel)) titlespec{data_idx} = "title \"\""; else - tmp = undo_string_escapes (obj.keylabel); + tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot)); titlespec{data_idx} = strcat ("title \"", tmp, "\""); endif usingclause{data_idx} = ""; - if (isfield (obj, "facecolor") && isfield (obj, "cdata")) - if (strncmp (obj.facecolor, "flat", 4) - || strncmp (obj.facecolor, "interp", 6)) + if (isfield (obj, "facecolor")) + if ((strncmp (obj.facecolor, "flat", 4) + || strncmp (obj.facecolor, "interp", 6)) && + isfield (obj, "cdata")) if (ndims (obj.cdata) == 2 - && ((nr > 3 && size (obj.cdata, 2) == nc) - || (size (obj.cdata, 1) > 1 - && size (obj.cdata, 2) == nc))) - ccol = obj.cdata (:, i); + && (size (obj.cdata, 2) == nc + && (size (obj.cdata, 1) == 1 + || size (obj.cdata, 1) == 3))) + ccol = cdat (:, i); + elseif (ndims (obj.cdata) == 2 + && (size (obj.cdata, 1) == nc + && (size (obj.cdata, 2) == 1 + || size (obj.cdata, 2) == 3))) + ccol = cdat (i, :); elseif (ndims (obj.cdata) == 3) - ccol = permute (obj.cdata (:, i, :), [1, 3, 2]); + ccol = permute (cdat (:, i, :), [1, 3, 2]); else - ccol = obj.cdata; + ccol = cdat; endif if (strncmp (obj.facecolor, "flat", 4)) if (numel(ccol) == 3) color = ccol; else - r = 1 + round ((size (cmap, 1) - 1) - * (ccol - clim(1))/(clim(2) - clim(1))); + if (cautoscale) + r = 1 + round ((size (cmap, 1) - 1) + * (ccol - cmin)/(cmax - cmin)); + else + r = 1 + round ((size (cmap, 1) - 1) + * (ccol - clim(1))/(clim(2) - clim(1))); + endif r = max (1, min (r, size (cmap, 1))); color = cmap(r, :); endif @@ -512,8 +549,10 @@ r = max (1, min (r, size (cmap, 1))); color = cmap(r,:); endif + elseif (isnumeric (obj.facecolor)) + color = obj.facecolor; else - color = obj.facecolor; + color = [0, 1, 0]; endif else color = [0, 1, 0]; @@ -564,25 +603,41 @@ have_cdata(data_idx) = false; titlespec{data_idx} = "title \"\""; usingclause{data_idx} = ""; - if (isfield (obj, "edgecolor") && isfield (obj, "cdata")) - if (strncmp (obj.edgecolor, "flat", 4) - || strncmp (obj.edgecolor, "interp", 6)) + + if (isfield (obj, "markersize")) + mdat = obj.markersize; + endif + + if (isfield (obj, "edgecolor")) + if ((strncmp (obj.edgecolor, "flat", 4) + || strncmp (obj.edgecolor, "interp", 6)) && + isfield (obj, "cdata")) if (ndims (obj.cdata) == 2 - && ((nr > 3 && size (obj.cdata, 2) == nc) - || (size (obj.cdata, 1) > 1 - && size (obj.cdata, 2) == nc))) - ccol = obj.cdata (:, i); + && (size (obj.cdata, 2) == nc + && (size (obj.cdata, 1) == 1 + || size (obj.cdata, 1) == 3))) + ccol = cdat (:, i); + elseif (ndims (obj.cdata) == 2 + && (size (obj.cdata, 1) == nc + && (size (obj.cdata, 2) == 1 + || size (obj.cdata, 2) == 3))) + ccol = cdat (i, :); elseif (ndims (obj.cdata) == 3) - ccol = permute (obj.cdata (:, i, :), [1, 3, 2]); + ccol = permute (cdat (:, i, :), [1, 3, 2]); else - ccol = obj.cdata; + ccol = cdat; endif if (strncmp (obj.edgecolor, "flat", 4)) - if (numel (ccol) == 3) + if (numel(ccol) == 3) color = ccol; else - r = 1 + round ((size (cmap, 1) - 1) - * (ccol - clim(1))/(clim(2) - clim(1))); + if (cautoscale) + r = 1 + round ((size (cmap, 1) - 1) + * (ccol - cmin)/(cmax - cmin)); + else + r = 1 + round ((size (cmap, 1) - 1) + * (ccol - clim(1))/(clim(2) - clim(1))); + endif r = max (1, min (r, size (cmap, 1))); color = cmap(r, :); endif @@ -592,16 +647,105 @@ r = max (1, min (r, size (cmap, 1))); color = cmap(r,:); endif + elseif (isnumeric (obj.edgecolor)) + color = obj.edgecolor; + else + color = [0, 0, 0]; endif - elseif (isfield (obj, "edgecolor") && isnumeric (obj.edgecolor)) - color = obj.edgecolor; else - color = [0, 0, 0]; + color = [0, 0, 0]; endif + + if (isfield (obj, "linestyle")) + switch (obj.linestyle) + case "-" + lt = "1"; + case "--" + lt = "2"; + case ":" + lt = "3"; + case "-." + lt = "6"; + case "none" + lt = ""; + otherwise + lt = ""; + endswitch + else + lt = ""; + endif + + if (isfield (obj, "marker")) + if (isfield (obj, "marker")) + switch (obj.marker) + case "+" + pt = "pt 1"; + case "o" + pt = "pt 6"; + case "*" + pt = "pt 3"; + case "." + pt = "pt 0"; + case "x" + pt = "pt 2"; + case {"square", "s"} + pt = "pt 5"; + case {"diamond", "d"} + pt = "pt 13"; + case "^" + pt = "pt 9"; + case "v" + pt = "pt 11"; + case ">" + pt = "pt 8"; + case "<" + pt = "pt 10"; + case {"pentagram", "p"} + pt = "pt 4"; + case {"hexagram", "h"} + pt = "pt 12"; + case "none" + pt = ""; + otherwise + pt = ""; + endswitch + endif + else + pt = ""; + endif + + style = "lines"; + if (isempty (lt)) + if (! isempty (pt)) + style = "points"; + endif + elseif (! isempty (pt)) + style = "linespoints"; + endif + + if (isfield (obj, "markersize")) + if (length (mdat) == nc) + m = mdat(i); + else + m = mdat; + endif + if (! strcmpi (style, "lines")) + if (have_newer_gnuplot) + ps = sprintf("pointsize %f", m); + else + ps = sprintf("ps %f", m); + endif + else + ps = ""; + endif + else + ps = ""; + endif + if (have_newer_gnuplot) withclause{data_idx} ... - = sprintf ("with lines lc rgb \"#%02x%02x%02x\"", - round (255*color)); + = sprintf ("with %s %s %s lc rgb \"#%02x%02x%02x\"", + style, pt, ps, round (255*color)); else if (isequal (color, [0,0,0])) typ = -1; @@ -622,7 +766,8 @@ else typ = -1; endif - withclause{data_idx} = sprintf ("with lines lt %d", typ); + withclause{data_idx} = sprintf ("with %s %s %s lt %d", + style, pt, ps, typ); endif if (! isempty (zcol)) @@ -657,7 +802,7 @@ if (isempty (obj.keylabel)) titlespec{data_idx} = "title \"\""; else - tmp = undo_string_escapes (obj.keylabel); + tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot)); titlespec{data_idx} = strcat ("title \"", tmp, "\""); endif usingclause{data_idx} = ""; @@ -686,10 +831,6 @@ tz = zdat(:); [zmin, zmax, zminp] = get_data_limits (zmin, zmax, zminp, tz); endif - if (cautoscale) - tc = cdat(:); - [cmin, cmax, cminp] = get_data_limits (cmin, cmax, cminp, tc); - endif err = false; if (! size_equal(zdat, cdat)) @@ -729,18 +870,15 @@ data{data_idx} = zz.'; endif usingclause{data_idx} = "using ($1):($2):($3):($4)"; - withclause{data_idx} = "with line palette"; fputs (plot_stream, "unset parametric;\n"); fputs (plot_stream, "set style data lines;\n"); fputs (plot_stream, "set surface;\n"); fputs (plot_stream, "unset contour;\n"); - fprintf (plot_stream, "set cbrange [%g:%g];\n", cmin, cmax); ## Interpolation does not work for flat surfaces (e.g. pcolor) ## and color mapping --> currently set empty. interp_str = ""; - surf_colormap = parent_figure_obj.colormap; flat_interp_face = (strncmp (obj.facecolor, "flat", 4) || strncmp (obj.facecolor, "interp", 6)); flat_interp_edge = (strncmp (obj.edgecolor, "flat", 4) @@ -749,8 +887,6 @@ facecolor_none_or_white = (strncmp (obj.facecolor, "none", 4) || (isnumeric (obj.facecolor) && all (obj.facecolor == 1))); - palette_data = []; - if (strncmp (obj.facecolor, "none", 4)) if (isnan (hidden_removal)) hidden_removal = false; @@ -761,28 +897,32 @@ if (flat_interp_face || (flat_interp_edge && facecolor_none_or_white)) - palette_data = [1:rows(surf_colormap); surf_colormap']; - elseif (isnumeric (obj.facecolor)) - palette_data = [1:2; [obj.facecolor; obj.facecolor]']; + withclause{data_idx} = "with line palette"; endif - if (facecolor_none_or_white && isnumeric (obj.edgecolor)) - palette_data = [1:2; [obj.edgecolor; obj.edgecolor]']; - endif + if (have_newer_gnuplot) + dord = "depthorder"; + else + dord = ""; + endif if (facecolor_none_or_white) - ## Do nothing. + ## Ensure faces aren't drawn + fprintf (plot_stream, "unset pm3d;\n"); elseif (flat_interp_face && strncmp (obj.edgecolor, "flat", 4)) - fprintf (plot_stream, "set pm3d at s %s;\n", interp_str); + fprintf (plot_stream, "set pm3d at s %s %s;\n", + interp_str, dord); else if (strncmp (obj.edgecolor, "none", 4)) - fprintf (plot_stream, "set pm3d at s %s;\n", interp_str); + fprintf (plot_stream, "set pm3d at s %s ;\n", + interp_str, dord); else edgecol = obj.edgecolor; if (ischar (obj.edgecolor)) edgecol = [0,0,0]; endif - fprintf (plot_stream, "set pm3d at s hidden3d %d %s;\n", data_idx, interp_str); + fprintf (plot_stream, "set pm3d at s hidden3d %d %s %s;\n", + data_idx, interp_str, dord); if (have_newer_gnuplot) fprintf (plot_stream, @@ -814,37 +954,12 @@ endif endif endif - - if (have_newer_gnuplot) - if (length(palette_data) > 0) - fprintf (plot_stream, - "set palette positive color model RGB maxcolors %i;\n", - columns(palette_data)); - fprintf (plot_stream, - "set palette file \"-\" binary record=%d using 1:2:3:4;\n", - columns(palette_data)); - fwrite (plot_stream, palette_data, "float32"); - endif - else - fputs (plot_stream, "set palette defined ("); - for i = 1: columns(palette_data) - col = floor(palette_data(2:end,i).' * 255); - if (i == 1) - fputs (plot_stream, sprintf("%d \"#%02X%02X%02X\"", i - 1, - col(1), col(2), col(3))); - else - fputs (plot_stream, sprintf(", %d \"#%02X%02X%02X\"", i - 1, - col(1), col(2), col(3))); - endif - endfor - fputs (plot_stream, ");\n"); - endif - fputs (plot_stream, "unset colorbox;\n"); endif case "text" + [label, f, s] = __maybe_munge_text__ (enhanced, obj, "string", + have_newer_gnuplot); lpos = obj.position; - label = obj.string; halign = obj.horizontalalignment; angle = obj.rotation; units = obj.units; @@ -883,8 +998,6 @@ endif endif - [f, s] = get_fontname_and_size (obj); - if (nd == 3) fprintf (plot_stream, "set label \"%s\" at %s %.15g,%.15g,%.15g font \"%s,%d\" %s rotate by %f %s;\n", @@ -964,6 +1077,13 @@ fprintf (plot_stream, "set zrange [%.15e:%.15e] %s;\n", zlim, zdir); endif + if (cautoscale && have_data) + set (h, "clim", clim, "climmode", "auto"); + endif + if (! any (isinf (clim))) + fprintf (plot_stream, "set cbrange [%g:%g];\n", clim); + endif + if (strcmpi (axis_obj.box, "on")) if (nd == 3) fputs (plot_stream, "set border 4095;\n"); @@ -1051,6 +1171,43 @@ endfor endif + cmap = parent_figure_obj.colormap; + cmap_sz = rows(cmap); + if (length(cmap) > 0) + if (have_newer_gnuplot) + fprintf (plot_stream, + "set palette positive color model RGB maxcolors %i;\n", + cmap_sz); + fprintf (plot_stream, + "set palette file \"-\" binary record=%d using 1:2:3:4;\n", + cmap_sz); + fwrite (plot_stream, [1:cmap_sz; cmap.'], "float32"); + else + fputs (plot_stream, "set palette defined ("); + for i = 1: cmap_sz + col = floor(cmap(i, :) * 255); + if (i == 1) + fputs (plot_stream, sprintf("%d \"#%02X%02X%02X\"", i - 1, + col(1), col(2), col(3))); + else + fputs (plot_stream, sprintf(", %d \"#%02X%02X%02X\"", i - 1, + col(1), col(2), col(3))); + endif + endfor + fputs (plot_stream, ");\n"); + endif + endif + + if (strcmp (axis_obj.__colorbar__, "none")) + fputs (plot_stream, "unset colorbox;\n"); + else + ## FIXME If cbox_mirror is true we want to invert the tic labels + ## but gnuplot doesn't allow that + fputs (plot_stream, + sprintf ("set colorbox %s user origin %f,%f size %f,%f;\n", + cbox_orient, cbox_origin, cbox_size)); + endif + if (have_data) if (nd == 2) plot_cmd = "plot"; @@ -1436,24 +1593,31 @@ endif endfunction -function [f, s] = get_fontname_and_size (t) +function [f, s, fnt, it, bld] = get_fontname_and_size (t) if (isempty (t.fontname)) - f = "helvetica"; + fnt = "helvetica"; else - f = tolower (t.fontname); + fnt = tolower (t.fontname); endif + f = fnt; + it = false; + bld = false; if (! isempty (t.fontweight) && strcmp (tolower (t.fontweight), "bold")) if (! isempty(t.fontangle) && (strcmp (tolower (t.fontangle), "italic") || strcmp (tolower (t.fontangle), "oblique"))) f = strcat (f, "-bolditalic"); + it = true; + bld = true; else f = strcat (f, "-bold"); + bld = true; endif elseif (! isempty(t.fontangle) && (strcmp (tolower (t.fontangle), "italic") || strcmp (tolower (t.fontangle), "oblique"))) f = strcat (f, "-italic"); + it = true; endif if (isempty (t.fontsize)) s = 10; @@ -1461,3 +1625,394 @@ s = t.fontsize; endif endfunction + +function [str, f, s] = __maybe_munge_text__ (enhanced, obj, fld, + have_newer_gnuplot) + persistent warned_latex = false; + + if (strcmp (fld, "string")) + [f, s, fnt, it, bld] = get_fontname_and_size (obj); + else + f = "Helvectica"; + s = 10; + fnt = f; + it = false; + bld = false; + endif + + str = getfield (obj, fld); + if (enhanced) + if (strcmp (obj.interpreter, "tex")) + str = __tex2enhanced__ (str, fnt, it, bld); + if (! have_newer_gnuplot) + ## Set the font to work around gnuplot 4.0 X11 enhanced terminal bug + str = strcat ('{/', f, ' ', str, ' }'); + endif + elseif (strcmp (obj.interpreter, "latex")) + if (! warned_latex) + warning ("latex text objects not supported"); + warned_latex = true; + endif + endif + endif +endfunction + +function str = __tex2enhanced__ (str, fnt, it, bld) + persistent sym = __setup_sym_table__ (); + persistent flds = fieldnames (sym); + + [s, e, m] = regexp(str,'\\([a-zA-Z]+|0)','start','end','matches'); + + for i = length (s) : -1 : 1 + ## special case for "\0" and replace with "{/Symbol \306}' + if (strncmp (m{i}, '\0', 2)) + str = strcat (str(1:s(i) - 1), '{\Symbol \306}', str(s(i) + 2:end)); + else + f = m{i}(2:end); + if (isfield (sym, f)) + g = getfield(sym, f); + ## FIXME The symbol font doesn't seem to support bold or italic + ##if (bld) + ## if (it) + ## g = regexprep (g, '/Symbol', '/Symbol-bolditalic'); + ## else + ## g = regexprep (g, '/Symbol', '/Symbol-bold'); + ## endif + ##elseif (it) + ## g = regexprep (g, '/Symbol', '/Symbol-italic'); + ##endif + str = strcat (str(1:s(i) - 1), g, str(e(i) + 1:end)); + elseif (strncmp (f, "rm", 2)) + bld = false; + it = false; + str = strcat (str(1:s(i) - 1), '/', fnt, ' ', str(s(i) + 3:end)); + elseif (strncmp (f, "it", 2) || strncmp (f, "sl", 2)) + it = true; + if (bld) + str = strcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ', + str(s(i) + 3:end)); + else + str = strcat (str(1:s(i) - 1), '/', fnt, '-italic ', + str(s(i) + 3:end)); + endif + elseif (strncmp (f, "bf", 2)) + bld = true; + if (it) + str = strcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ', + str(2(i) + 3:end)); + else + str = strcat (str(1:s(i) - 1), '/', fnt, '-bold ', + str(s(i) + 3:end)); + endif + elseif (strcmp (f, "color")) + ## FIXME Ignore \color but remove trailing {} block as well + d = strfind(str(e(i) + 1:end),'}'); + if (isempty (d)) + warning ('syntax error in \color argument'); + else + str = strcat (str(1:s(i) - 1), str(e(i) + d + 1:end)); + endif + elseif(strcmp (f, "fontname")) + b1 = strfind(str(e(i) + 1:end),'{'); + b2 = strfind(str(e(i) + 1:end),'}'); + if (isempty(b1) || isempty(b2)) + warning ('syntax error in \fontname argument'); + else + str = strcat (str(1:s(i) - 1), '/', + str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}', + str(e(i) + b2(1) + 1:end)); + endif + elseif(strcmp (f, "fontsize")) + b1 = strfind(str(e(i) + 1:end),'{'); + b2 = strfind(str(e(i) + 1:end),'}'); + if (isempty(b1) || isempty(b2)) + warning ('syntax error in \fontname argument'); + else + str = strcat (str(1:s(i) - 1), '/=', + str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}', + str(e(i) + b2(1) + 1:end)); + endif + else + ## Last desperate attempt to treat the symbol. Look for things + ## like \pix, that should be translated to the symbol Pi and x + for j = 1 : length (flds) + if (strncmp (flds{j}, f, length (flds{j}))) + g = getfield(sym, flds{j}); + ## FIXME The symbol font doesn't seem to support bold or italic + ##if (bld) + ## if (it) + ## g = regexprep (g, '/Symbol', '/Symbol-bolditalic'); + ## else + ## g = regexprep (g, '/Symbol', '/Symbol-bold'); + ## endif + ##elseif (it) + ## g = regexprep (g, '/Symbol', '/Symbol-italic'); + ##endif + str = strcat (str(1:s(i) - 1), g, + str(s(i) + length (flds{j}) + 1:end)); + break; + endif + endfor + endif + endif + endfor + + ## Prepend @ to things things like _0^x or _{-100}^{100} for alignment + ## But need to put the shorter of the two arguments first. Carful of + ## nested {} and unprinted characters when defining shortest.. Don't + ## have to worry about things like ^\theta as they are already converted to + ## ^{/Symbol q}. + + ## FIXME.. This is a mess... Is it worth it just for a "@" character? + + [s, m] = regexp(str,'[_\^]','start','matches'); + i = 1; + p = 0; + while (i < length (s)) + if (i < length(s)) + if (str(s(i) + p + 1) == "{") + s1 = strfind(str(s(i) + p + 2:end),'{'); + si = 1; + l1 = strfind(str(s(i) + p + 1:end),'}'); + li = 1; + while (li <= length (l1) && si <= length (s1)) + if (l1(li) < s1(si)) + if (li == si) + break; + endif + li++; + else + si++; + endif + endwhile + l1 = l1 (min (length(l1), si)); + if (s(i) + l1 + 1 == s(i+1)) + if (str(s(i + 1) + p + 1) == "{") + s2 = strfind(str(s(i + 1) + p + 2:end),'{'); + si = 1; + l2 = strfind(str(s(i + 1) + p + 1:end),'}'); + li = 1; + while (li <= length (l2) && si <= length (s2)) + if (l2(li) < s2(si)) + if (li == si) + break; + endif + li++; + else + si++; + endif + endwhile + l2 = l2 (min (length(l2), si)); + if (length_string (str(s(i)+p+2:s(i)+p+l1-1)) <= + length_string(str(s(i+1)+p+2:s(i+1)+p+l2-1))) + ## shortest already first! + str = strcat (str(1:s(i)+p-1), "@", str(s(i)+p:end)); + else + ## Have to swap sub/super-script to get shortest first + str = strcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+l2), + str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+l2+1:end)); + endif + else + ## Have to swap sub/super-script to get shortest first + str = strcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+1), + str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+2:end)); + endif + i += 2; + p ++; + else + i++; + endif + else + if (s(i+1) == s(i) + 2) + ## shortest already first! + str = strcat (str(1:s(i)+p-1), "@", str(s(i)+p:end)); + p ++; + i += 2; + else + i ++; + endif + endif + else + i ++; + endif + endwhile + +endfunction + +function l = length_string (s) + l = length (s) - length (strfind(s,'{')) - length (strfind(s,'}')); + m = regexp (s, '/([\w\-]+|[\w\-]+=\d+)', 'matches'); + if (!isempty (m)) + l = l - sum (cellfun (@length, m)); + endif +endfunction + +function sym = __setup_sym_table__ () + ## Setup the translation table for TeX to gnuplot enhanced mode. + sym.forall = '{/Symbol \042}'; + sym.exists = '{/Symbol \044}'; + sym.ni = '{/Symbol \047}'; + sym.cong = '{/Symbol \100}'; + sym.Delta = '{/Symbol D}'; + sym.Phi = '{/Symbol F}'; + sym.Gamma = '/Symbol G}'; + sym.vartheta = '{\Symbol J}'; + sym.Lambda = '{/Symbol L}'; + sym.Pi = '{/Symbol P}'; + sym.Theta = '{/Symbol Q}'; + sym.Sigma = '{/Symbol S}'; + sym.varsigma = '{/Symbol V}'; + sym.Omega = '{/Symbol O}'; + sym.Xi = '{/Symbol X}'; + sym.Psi = '{/Symbol Y}'; + sym.perp = '{/Symbol \136}'; + sym.alpha = '{/Symbol a}'; + sym.beta = '{/Symbol b}'; + sym.chi = '{/Symbol c}'; + sym.delta = '{/Symbol d}'; + sym.epsilon = '{/Symbol e}'; + sym.phi = '{/Symbol f}'; + sym.gamma = '/Symbol g}'; + sym.eta = '{/Symbol h}'; + sym.iota = '{/Symbol i}'; + sym.kappa = '{/Symbol k}'; + sym.lambda = '{/Symbol l}'; + sym.mu = '{/Symbol m}'; + sym.nu = '{/Symbol n}'; + sym.o = '{/Symbol o}'; + sym.pi = '{/Symbol p}'; + sym.theta = '{/Symbol q}'; + sym.rho = '{/Symbol r}'; + sym.sigma = '{/Symbol s}'; + sym.tau = '{/Symbol t}'; + sym.upsilon = '{/Symbol u}'; + sym.varpi = '{/Symbol v}'; + sym.omega = '{/Symbol w}'; + sym.xi = '{/Symbol x}'; + sym.psi = '{/Symbol y}'; + sym.zeta = '{/Symbol z}'; + sym.sim = '{/Symbol \176}'; + sym.Upsilon = '{/Symbol \241}'; + sym.prime = '{/Symbol \242}'; + sym.leq = '{/Symbol \243}'; + sym.infty = '{/Symbol \245}'; + sym.clubsuit = '{/Symbol \247}'; + sym.diamondsuit = '{/Symbol \250}'; + sym.heartsuit = '{/Symbol \251}'; + sym.spadesuit = '{/Symbol \252}'; + sym.leftrightarrow = '{/Symbol \253}'; + sym.leftarrow = '{/Symbol \254}'; + sym.uparrow = '{/Symbol \255}'; + sym.rightarrow = '{/Symbol \256}'; + sym.downarrow = '{/Symbol \257}'; + sym.circ = '{/Symbol \260}'; + sym.pm = '{/Symbol \261}'; + sym.geq = '{/Symbol \263}'; + sym.times = '{/Symbol \264}'; + sym.propto = '{/Symbol \265}'; + sym.partial = '{/Symbol \266}'; + sym.bullet = '{/Symbol \267}'; + sym.div = '{/Symbol \270}'; + sym.neq = '{/Symbol \271}'; + sym.equiv = '{/Symbol \272}'; + sym.approx = '{/Symbol \273}'; + sym.ldots = '{/Symbol \274}'; + sym.mid = '{/Symbol \275}'; + sym.aleph = '{/Symbol \300}'; + sym.Im = '{/Symbol \301}'; + sym.Re = '{/Symbol \302}'; + sym.wp = '{/Symbol \303}'; + sym.otimes = '{/Symbol \304}'; + sym.oplus = '{/Symbol \305}'; + sym.oslash = '{/Symbol \306}'; + sym.cap = '{/Symbol \307}'; + sym.cup = '{/Symbol \310}'; + sym.supset = '{/Symbol \311}'; + sym.supseteq = '{/Symbol \312}'; + sym.subset = '{/Symbol \314}'; + sym.subseteq = '{/Symbol \315}'; + sym.in = '{/Symbol \316}'; + sym.langle = '{/Symbol \320}'; + sym.rangle = '{/Symbol \320}'; + sym.nabla = '{/Symbol \321}'; + sym.surd = '{/Symbol \326}'; + sym.cdot = '{/Symbol \327}'; + sym.neg = '{/Symbol \330}'; + sym.wedge = '{/Symbol \331}'; + sym.vee = '{/Symbol \332}'; + sym.copyright = '{/Symbol \343}'; + sym.rfloor = '{/Symbol \353}'; + sym.lceil = '{/Symbol \351}'; + sym.lfloor = '{/Symbol \373}'; + sym.rceil = '{/Symbol \371}'; + sym.int = '{/Symbol \362}'; +endfunction + +function [pos, orient, sz, origin, mirr] = gnuplot_postion_colorbox (pos, cbox) + ## This is an emprically derived function that + + if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5)) + scl = pos([2,4]); + else + scl = pos([1,3]); + endif + + if (length(cbox) > 7 && strncmp (cbox(end-6:end), "outside", 7)) + scl(2) -= 0.2 * scl(2); + if (strncmp (cbox, "west", 4) || strncmp (cbox, "south", 5)) + scl(1) += 0.2 * scl(2); + endif + endif + + switch (cbox) + case "northoutside" + sz = pos(3:4) - 0.08; + origin = [0.05, 0.06] + [0.00, 0.88] .* sz + pos(1:2); + mirr = true; + orient = "horizontal"; + case "north" + sz = pos(3:4) - 0.16; + origin = [0.09, 0.09] + [0.00, 0.94] .* sz + pos(1:2); + mirr = false; + orient = "horizontal"; + case "southoutside" + sz = pos(3:4) - 0.08; + origin = [0.05, 0.06] + [0.00, 0.00] .* sz + pos(1:2); + mirr = false; + orient = "horizontal"; + case "south" + sz = pos(3:4) - 0.16; + origin = [0.08, 0.09] + [0.03, 0.05] .* sz + pos(1:2); + mirr = true; + orient = "horizontal"; + case "eastoutside" + sz = pos(3:4) - 0.08; + origin = [0.00, 0.06] + [0.94, 0.00] .* sz + pos(1:2); + mirr = false; + orient = "vertical"; + case "east" + sz = pos(3:4) - 0.16; + origin = [0.09, 0.10] + [0.91, 0.01] .* sz + pos(1:2); + mirr = true; + orient = "vertical"; + case "westoutside" + sz = pos(3:4) - 0.08; + origin = [0.00, 0.06] + [0.06, 0.00] .* sz + pos(1:2); + mirr = true; + orient = "vertical"; + case "west" + sz = pos(3:4) - 0.16; + origin = [0.06, 0.09] + [0.04, 0.03] .* sz + pos(1:2); + mirr = false; + orient = "vertical"; + endswitch + + if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5)) + sz = sz .* [1, 0.07]; + pos([2,4]) = scl; + else + sz = sz .* [0.07, 1]; + pos([1,3]) = scl; + endif + +endfunction diff --git a/scripts/plot/__go_draw_figure__.m b/scripts/plot/__go_draw_figure__.m --- a/scripts/plot/__go_draw_figure__.m +++ b/scripts/plot/__go_draw_figure__.m @@ -20,9 +20,9 @@ ## Author: jwe -function __go_draw_figure__ (f, plot_stream) +function __go_draw_figure__ (f, plot_stream, enhanced) - if (nargin == 2) + if (nargin == 3) if (strcmp (f.type, "figure")) ## Set figure properties here? @@ -52,8 +52,7 @@ obj = get (kids(i)); switch (obj.type) case "axes" - __go_draw_axes__ (kids(i), plot_stream); - + __go_draw_axes__(kids (i), plot_stream, enhanced); otherwise error ("__go_draw_figure__: unknown object class, %s", obj.type); diff --git a/scripts/plot/__patch__.m b/scripts/plot/__patch__.m --- a/scripts/plot/__patch__.m +++ b/scripts/plot/__patch__.m @@ -127,11 +127,11 @@ idx(t1,i) = idx(t2,i); endif endfor - x = vert(:,1)(idx); - y = vert(:,2)(idx); + x = reshape (vert(:,1)(idx), size (idx)); + y = reshape (vert(:,2)(idx), size (idx)); if (size(vert,2) > 2) have_z = true; - z = vert(:,3)(idx); + z = reshape (vert(:,3)(idx), size (idx)); endif else error ("patch: not supported"); @@ -159,6 +159,7 @@ clim = get(ax, "clim"); if (c(1) < clim(1)) set (ax, "clim", [c(1), clim(2)]) + clim(1) = c(1); endif if (c(1) > clim(2)) set (ax, "clim", [clim(1), c(1)]) diff --git a/scripts/plot/__quiver__.m b/scripts/plot/__quiver__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/__quiver__.m @@ -0,0 +1,222 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## Undocumented internal function + +function hlist = __quiver__ (varargin) + h = varargin {1}; + is3d = varargin {2}; + + s = 1; + arrowsize = 0.33; + + firstnonnumeric = Inf; + for i = 3:nargin + if (! isnumeric (varargin {i})) + firstnonnumeric = i; + break; + endif + endfor + + ioff = 3; + if (nargin < (6 + is3d) || firstnonnumeric < (6 + is3d)) + u = varargin{ioff++}; + v = varargin{ioff++}; + if (is3d) + w = varargin{ioff++} + [x, y, z] = meshgrid (1:size(u,1), 1:size(u,2), 1:max(size(w))); + else + [x, y] = meshgrid (1:size(u,1), 1:size(u,2)); + endif + if (nargin >= ioff && isnumeric (varargin{ioff}) && + isscalar (varargin{ioff})) + s = varargin{ioff++}; + endif + else + x = varargin{ioff++}; + y = varargin{ioff++}; + if (is3d) + z = varargin{ioff++}; + endif + u = varargin{ioff++}; + v = varargin{ioff++}; + if (is3d) + w = varargin{ioff++}; + if (isvector(x) && isvector(y) && isvector(z) && + (!isvector (u) || !isvector (v) || !isvector(w))) + [x, y, z] = meshgrid (x, y, z); + endif + else + if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v))) + [x, y] = meshgrid (x, y); + endif + endif + if (nargin >= ioff && isnumeric (varargin{ioff}) && + isscalar (varargin{ioff})) + s = varargin{ioff++}; + endif + endif + + have_filled = false; + have_line_spec = false; + while (ioff <= nargin) + arg = varargin {ioff++}; + if (ischar (arg) && strncmp (tolower (arg), "filled", 6)) + have_filled = true; + elseif ((isstr (arg) || iscell (arg)) + && ! have_line_spec) + [linespec, valid] = __pltopt__ ("quiver", arg, false); + if (valid) + have_line_spec = true; + if (strncmp (linespec.linestyle, "none", 4)) + linespec.linestyle = "-"; + endif + else + error ("quiver: invalid linespec"); + endif + else + error ("quiver: unrecognized argument"); + endif + endwhile + + if (s) + ## Scale the arrows to fit in the grid + dx = (max(x(:)) - min(x(:))) ./ size (x, 2); + dy = (max(y(:)) - min(y(:))) ./ size (y, 1); + if (is3d) + ## What should this be divided by? The below seems right + dz = (max(z(:)) - min(z(:))) ./ max (size (z)); + len = max (sqrt (u(:).^2 + dy(:).^2) + dz(:).^2); + else + len = max (sqrt (u(:).^2 + dy(:).^2)); + dz = 0; + endif + if (len > 0) + s = s / sqrt (2) * sqrt (dx.^2 + dy.^2 + dz.^2) / len; + u = s * u; + v = s * v; + if (is3d) + w = s*w; + endif + endif + endif + + x = x(:); + y = y(:); + xend = x + u(:); + yend = y + v(:); + if (is3d) + z = z(:); + zend = z + w(:); + endif + + hstate = get (h, "nextplot"); + unwind_protect + if (have_line_spec) + if (is3d) + h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:), + [y.'; yend.'; NaN(1, length (y))](:), + [z.'; zend.'; NaN(1, length (z))](:), + "linestyle", linespec.linestyle); + else + h1 = plot ([x.'; xend.'; NaN(1, length (x))](:), + [y.'; yend.'; NaN(1, length (y))](:), + "linestyle", linespec.linestyle); + endif + else + if (is3d) + h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:), + [y.'; yend.'; NaN(1, length (y))](:), + [z.'; zend.'; NaN(1, length (z))](:)); + else + h1 = plot ([x.'; xend.'; NaN(1, length (x))](:), + [y.'; yend.'; NaN(1, length (y))](:)); + endif + endif + hold on; + + xtmp = x + u(:) .* (1 - arrowsize); + ytmp = y + v(:) .* (1 - arrowsize); + xarrw1 = xtmp + (y - yend) * arrowsize / 3; + xarrw2 = xtmp - (y - yend) * arrowsize / 3; + yarrw1 = ytmp - (x - xend) * arrowsize / 3; + yarrw2 = ytmp + (x - xend) * arrowsize / 3; + if (is3d) + zarrw1 = zarrw2 = zend - w(:) * arrowsize / 3; + endif + + if (have_line_spec) + if (isfield (linespec, "marker") && + ! strncmp (linespec.marker, "none", 4)) + if (is3d) + h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), + [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:), + "linestyle", "none"); + else + h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), + "linestyle", "none"); + endif + else + if (is3d) + h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), + [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:), + "linestyle", linespec.linestyle); + else + h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), + "linestyle", linespec.linestyle); + endif + endif + elseif (is3d) + h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), + [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:)); + else + h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), + [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:)); + endif + + if (! have_line_spec || (isfield (linespec, "marker") && + strncmp (linespec.marker, "none", 4))) + if (is3d) + h3 = plot3 (x, y, z, "linestyle", "none", "marker", "none"); + else + h3 = plot (x, y, "linestyle", "none", "marker", "none"); + endif + else + if (is3d) + h3 = plot3 (x, y, z, "linestyle", "none", "marker", linespec.marker); + else + + h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker); + endif + endif + if (have_filled) + ## FIXME gnuplot doesn't respect the markerfacecolor field + set(h3, "markerfacecolor", get (h1, "color")); + endif + unwind_protect_cleanup + set (h, "nextplot", hstate); + end_unwind_protect + + hlist = [h1; h2; h3]; + +endfunction diff --git a/scripts/plot/__scatter__.m b/scripts/plot/__scatter__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/__scatter__.m @@ -0,0 +1,124 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## Undocumented internal function. + +function h = __scatter__ (varargin) + h = varargin {1}; + nd = varargin {2}; + fcn = varargin {3}; + x = varargin {4}(:); + y = varargin {5}(:); + istart = 6; + if (nd == 3) + z = varargin {6}(:); + istart = 7; + else + z = zeros (length(x), 0); + endif + + firstnonnumeric = Inf; + for i = istart:nargin + if (! isnumeric (varargin {i})) + firstnonnumeric = i; + break; + endif + endfor + + if (firstnonnumeric > istart) + s = varargin {istart}; + if (isempty (s)) + s = 8; + endif + else + s = 8; + endif + ## Note markersize is in points^2 for 2D and points for 3D, and + ## the below is an approximation, that is empircally visually correct. + if (nd == 2) + s = sqrt (s) / 2; + else + s = s / 4; + endif + + if (istart < nargin && firstnonnumeric > istart + 1) + c = varargin {istart + 1}; + if (isvector (c)) + c = c(:); + endif + elseif (firstnonnumeric == istart + 1 && ischar (varargin {istart + 1})) + c = varargin{istart + 1}; + firstnonnumeric++; + else + c = 1 : length(x); + endif + + newargs = {}; + filled = false; + have_marker = false; + marker = "o"; + iarg = firstnonnumeric; + while (iarg <= nargin) + arg = varargin {iarg++}; + if (ischar (arg) && strncmp (tolower (arg), "filled", 6)) + filled = true; + elseif ((isstr (arg) || iscell (arg)) && ! have_marker) + [linespec, valid] = __pltopt__ ("scatter", arg, false); + if (valid) + have_marker = true; + marker = linespec.marker; + if (strncmp (marker, "none", 4)) + marker = "o"; + endif + else + error ("scatter: invalid linespec"); + endif + else + newargs{end+1} = arg; + if (iarg <= nargin) + newargs{end+1} = varagin{iarg++}; + endif + endif + endwhile + + if (ischar (c)) + h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor', + 'none', 'edgecolor', c, 'marker', marker, + 'markersize', s, 'linestyle', 'none'); + if (filled) + set(h, 'markerfacecolor', c); + endif + else + h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor', + 'none', 'edgecolor', 'flat', 'cdata', c, 'marker', marker, + 'markersize', s, 'linestyle', 'none'); + if (filled) + set(h, 'markerfacecolor', 'flat'); + endif + ax = get (h, "parent"); + clim = get (ax, "clim"); + if (min(c(:)) < clim(1)) + clim(1) = min(c(:)); + set (ax, "clim", clim); + endif + if (max(c(:)) > clim(2)) + set (ax, "clim", [clim(1), max(c(:))]); + endif + endif + +endfunction diff --git a/scripts/plot/axis.m b/scripts/plot/axis.m --- a/scripts/plot/axis.m +++ b/scripts/plot/axis.m @@ -29,7 +29,6 @@ ## Without any arguments, @code{axis} turns autoscaling on. ## ## With one output argument, @code{x=axis} returns the current axes -## (this is not yet implemented for automatic axes). ## ## The vector argument specifying limits is optional, and additional ## string arguments may be used to specify various axis properties. For @@ -109,17 +108,47 @@ ## Restore y-axis, so higher values are nearer the top. ## @end table ## +## If an axes handle is passed as the first argument, then operate on +## this axes rather than the current axes. ## @end deftypefn ## Author: jwe ## PKG_ADD: mark_as_command axis -function curr_axis = axis (ax, varargin) +function varargout = axis (varargin) - ca = gca (); + if (nargin > 0 && isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin{1}; + if (! strcmp (get (h, "type"), "axes")) + error ("axis: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + varargout = cell (max (nargin == 1, nargout), 1); + if (isempty (varargout)) + __axis__ (h, varargin{2:end}); + else + [varargout{:}] = __axis__ (h, varargin{2:end}); + endif + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + varargout = cell (max (nargin == 0, nargout), 1); + if (isempty (varargout)) + __axis__ (gca (), varargin{:}); + else + [varargout{:}] = __axis__ (gca (), varargin{:}); + endif + endif - if (nargin == 0) +endfunction + +function curr_axis = __axis__ (ca, ax, varargin) + + if (nargin == 1) if (nargout == 0) set (ca, "xlimmode", "auto", "ylimmode", "auto", "zlimmode", "auto"); else @@ -254,8 +283,8 @@ error ("axis: expecting no args, or a vector with 2, 4, or 6 elements"); endif - if (nargin > 1) - axis (varargin{:}); + if (nargin > 2) + __axis__ (ca, varargin{:}); endif endfunction diff --git a/scripts/plot/bar.m b/scripts/plot/bar.m --- a/scripts/plot/bar.m +++ b/scripts/plot/bar.m @@ -23,6 +23,7 @@ ## @deftypefnx {Function File} {} bar (@var{x}, @var{y}, @var{w}) ## @deftypefnx {Function File} {} bar (@var{x}, @var{y}, @var{w}, @var{style}) ## @deftypefnx {Function File} {@var{h} =} bar (@dots{}, @var{prop}, @var{val}) +## @deftypefnx {Function File} {} bar (@var{h}, @dots{}) ## Produce a bar graph from two vectors of x-y data. ## ## If only one argument is given, it is taken as a vector of y-values @@ -37,6 +38,7 @@ ## or @code{"stacked"}. ## ## The optional return value @var{h} provides a handle to the patch object. +## Whereas the option input handle @var{h} allows an axis handle to be passed. ## Properties of the patch graphics object can be changed using ## @var{prop}, @var{val} pairs. ## diff --git a/scripts/plot/barh.m b/scripts/plot/barh.m --- a/scripts/plot/barh.m +++ b/scripts/plot/barh.m @@ -22,6 +22,7 @@ ## @deftypefnx {Function File} {} barh (@var{x}, @var{y}, @var{w}) ## @deftypefnx {Function File} {} barh (@var{x}, @var{y}, @var{w}, @var{style}) ## @deftypefnx {Function File} {@var{h} =} barh (@dots{}, @var{prop}, @var{val}) +## @deftypefnx {Function File} {} barh (@var{h}, @dots{}) ## Produce a horizontal bar graph from two vectors of x-y data. ## ## If only one argument is given, it is taken as a vector of y-values @@ -36,6 +37,7 @@ ## or @code{"stacked"}. ## ## The optional return value @var{h} provides a handle to the patch object. +## Whereas the option input handle @var{h} allows an axis handle to be passed. ## Properties of the patch graphics object can be changed using ## @var{prop}, @var{val} pairs. ## diff --git a/scripts/plot/caxis.m b/scripts/plot/caxis.m new file mode 100644 --- /dev/null +++ b/scripts/plot/caxis.m @@ -0,0 +1,102 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} caxis (@var{limits}) +## @deftypefnx {Function File} {} caxis (@var{h}, @dots{}) +## Set color axis limits for plots. +## +## The argument @var{limits} should be a 2 element vector specifying the +## lower and upper limits to assign to the first and last value in the +## colormap. Values outside this range are clamped to the first and last +## colormap entries. +## +## If @var{limits} is 'auto', then automatic colormap scaling is applied, +## whereas if @var{limits} is 'manual' the colormap scaling is set to manual. +## +## Called without any arguments to current color axis limits are returned. +## +## If an axes handle is passed as the first argument, then operate on +## this axes rather than the current axes. +## @end deftypefn + +## PKG_ADD: mark_as_command caxis + +function varargout = caxis (varargin) + + if (nargin > 0 && isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin{1}; + if (! strcmp (get (h, "type"), "axes")) + error ("caxis: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + varargout = cell (max (nargin == 1, nargout), 1); + if (isempty (varargout)) + __caxis__ (h, varargin{2:end}); + else + [varargout{:}] = __caxis__ (h, varargin{2:end}); + endif + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + varargout = cell (max (nargin == 0, nargout), 1); + if (isempty (varargout)) + __caxis__ (gca (), varargin{:}); + else + [varargout{:}] = __caxis__ (gca (), varargin{:}); + endif + endif + +endfunction + +function [cmin, cmax] = __caxis__ (ca, ax, varargin) + + if (nargin == 1) + cmin = get (ca, "clim"); + if (nargout > 1) + cmax = cmin(2); + cmin = cmin(1); + endif + elseif (ischar (ax)) + ax = tolower (ax); + if (strcmp (ax, "auto")) + set (ca, "climmode", "auto"); + elseif (strcmp (ax, "manual")) + set (ca, "climmode", "manual"); + endif + elseif (isvector (ax)) + len = length (ax); + + if (len != 2) + error ("caxis: expecting vector with 2 elements"); + endif + + set (ca, "clim", [ax(1), ax(2)]); + else + error ("caxis: expecting no args, a string or a 2 element vector"); + endif + + if (nargin > 2) + __caxis__ (ca, varargin{:})' + endif + +endfunction + diff --git a/scripts/plot/colorbar.m b/scripts/plot/colorbar.m new file mode 100644 --- /dev/null +++ b/scripts/plot/colorbar.m @@ -0,0 +1,149 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} colorbar (@var{s}) +## @deftypefnx {Function File} {} colorbar ('peer', @var{h}, @dots{}) +## Adds a colorbar to the current axes. Valid values for @var{s} are +## +## @table @asis +## @item 'EastOutside' +## Place the colorbar outside the plot to the right. This is the default. +## @item 'East' +## Place the colorbar inside the plot to the right. +## @item 'WestOutside' +## Place the colorbar outside the plot to the left. +## @item 'West' +## Place the colorbar inside the plot to the left. +## @item 'NorthOutside' +## Place the colorbar above the plot. +## @item 'North' +## Place the colorbar at the top of the plot. +## @item 'SouthOutside' +## Place the colorbar under the plot. +## @item 'South' +## Place the colorbar at the bottom of the plot. +## @item 'Off', 'None' +## Remove any existing colorbar from the plot. +## @end table +## +## If the argument 'peer' is given, then the following argument is treated a +## the axes handle on which to add the colorbar. +## @end deftypefn + + +## PKG_ADD: mark_as_command colorbar + +function colorbar (varargin) + + if (nargin > 0 && strcmpi(varargin{1}, "peer")) + if (nargin > 1) + ax = varargin{2}; + if (!isscalar (ax) || !ishandle (ax) || + strcmp (get (ax, "type"), "axes")) + error ("colorbar: expecting an axes handle following 'peer'"); + endif + else + error ("colorbar: misisng axes handle after 'peer'"); + endif + else + ax = gca (); + endif + + pos = "eastoutside"; + for i = 1 : length (varargin) + arg = varargin {i}; + if (length(arg) < 1) + pos = "eastoutside"; + elseif (ischar (arg)) + arg = tolower (arg); + if (strcmp (arg, "off") || strcmp (arg, "none")) + pos = "none"; + elseif (strcmp (arg, "north") || strcmp (arg, "south") || + strcmp (arg, "east") || strcmp (arg, "west") || + strcmp (arg, "northoutside") || strcmp (arg, "southoutside") || + strcmp (arg, "eastoutside") || strcmp (arg, "westoutside")) + pos = arg; + else + error ("colorbar: unrecognized position argument"); + endif + else + error ("colorbar: expecting string arguments"); + endif + endfor + + set (ax, "__colorbar__", pos); +endfunction + + +%!demo +%! hold off; +%! close all; +%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); +%! imagesc(x) +%! colorbar(); + +%!demo +%! hold off; +%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); +%! imagesc(x) +%! colorbar("westoutside"); + +%!demo +%! hold off; +%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); +%! imagesc(x) +%! colorbar("northoutside"); + +%!demo +%! hold off; +%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); +%! imagesc(x) +%! colorbar("southoutside"); + +%!demo +%! hold off; +%! subplot(2,2,1) +%! contour(peaks()) +%! colorbar("east"); +%! subplot(2,2,2) +%! contour(peaks()) +%! colorbar("west"); +%! subplot(2,2,3) +%! contour(peaks()) +%! colorbar("north"); +%! subplot(2,2,4) +%! contour(peaks()) +%! colorbar("south"); + +%!demo +%! hold off; +%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); +%! subplot(2,2,1) +%! imagesc(x) +%! colorbar(); +%! subplot(2,2,2) +%! imagesc(x) +%! colorbar("westoutside"); +%! subplot(2,2,3) +%! imagesc(x) +%! colorbar("northoutside"); +%! subplot(2,2,4) +%! imagesc(x) +%! colorbar("southoutside"); + diff --git a/scripts/plot/contour.m b/scripts/plot/contour.m --- a/scripts/plot/contour.m +++ b/scripts/plot/contour.m @@ -69,7 +69,7 @@ if (nargout > 0) c = ctmp; - h = htmp + h = htmp; endif endfunction diff --git a/scripts/plot/drawnow.m b/scripts/plot/drawnow.m --- a/scripts/plot/drawnow.m +++ b/scripts/plot/drawnow.m @@ -45,12 +45,12 @@ plot_stream = []; fid = []; unwind_protect - plot_stream = open_gnuplot_stream ([], term, file); - __go_draw_figure__ (f, plot_stream); + [plot_stream, enhanced] = open_gnuplot_stream ([], term, file); + __go_draw_figure__ (f, plot_stream, enhanced); if (nargin == 3) fid = fopen (debug_file, "wb"); - init_plot_stream (fid, [], term, file); - __go_draw_figure__ (f, fid); + enhanced = init_plot_stream (fid, [], term, file); + __go_draw_figure__ (f, fid, enhanced); endif unwind_protect_cleanup if (! isempty (plot_stream)) @@ -72,12 +72,16 @@ figure_is_visible = strcmp (f.visible, "on"); if (figure_is_visible) if (isempty (plot_stream)) - plot_stream = open_gnuplot_stream (h); + [plot_stream, enhanced] = open_gnuplot_stream (h); + set (h, "__enhanced__", enhanced); + else + enhanced = f.__enhanced__; endif - __go_draw_figure__ (f, plot_stream); + __go_draw_figure__ (f, plot_stream, enhanced); elseif (! isempty (plot_stream)) pclose (plot_stream); set (h, "__plot_stream__", []); + set (h, "__enhanced__", false); endif set (h, "__modified__", false); endif @@ -96,7 +100,7 @@ endfunction -function plot_stream = open_gnuplot_stream (h, varargin) +function [plot_stream, enhanced] = open_gnuplot_stream (h, varargin) ## If drawnow is cleared, it is possible to register __go_close_all__ ## more than once, but that is not fatal. @@ -114,7 +118,7 @@ set (h, "__plot_stream__", plot_stream); endif - init_plot_stream (plot_stream, h, varargin{:}) + enhanced = init_plot_stream (plot_stream, h, varargin{:}); if (isempty (__go_close_all_registered__)) atexit ("__go_close_all__"); @@ -125,11 +129,16 @@ endfunction -function init_plot_stream (plot_stream, h, term, file) +function enhanced = init_plot_stream (plot_stream, h, term, file) if (nargin == 4) + enhanced = enhanced_term (term); if (! isempty (term)) - fprintf (plot_stream, "set terminal %s;\n", term); + if (enhanced) + fprintf (plot_stream, "set terminal %s enhanced;\n", term); + else + fprintf (plot_stream, "set terminal %s;\n", term); + endif endif if (! isempty (file)) fprintf (plot_stream, "set output \"%s\";\n", file); @@ -153,24 +162,62 @@ endif endif + enhanced = enhanced_term (term); + if (enhanced) + enh_str = "enhanced"; + else + enh_str = ""; + endif + ## If no 'h' (why not?) then open the terminal as Figure 0. if (isempty (h)) h = 0; endif if (strcmp (term, "x11")) - fprintf (plot_stream, "set terminal x11 title \"Figure %d\"\n", h); + fprintf (plot_stream, "set terminal x11 %s title \"Figure %d\"\n", + enh_str, h); elseif (strcmp (term, "aqua")) ## Aqua doesn't understand the 'title' option despite what the ## gnuplot 4.2 documentation says. - fprintf (plot_stream, "set terminal aqua %d\n", h); + fprintf (plot_stream, "set terminal aqua %d %s\n", h, enh_str); elseif (strcmp (term, "wxt")) - fprintf (plot_stream, "set terminal wxt title \"Figure %d\"\n", h); + fprintf (plot_stream, "set terminal wxt %s title \"Figure %d\"\n", + enh_str, h); + + elseif (enhanced) + fprintf (plot_stream "set terminal %s %s\n", term, enh_str); endif ## gnuplot will pick up the GNUTERM environment variable itself ## so no need to set the terminal type if not also setting the - ## figure title. + ## figure title or enhanced mode. endif endfunction + +function have_enhanced = enhanced_term (term) + persistent enhanced_terminals; + + if (isempty (enhanced_terminals)) + ## Don't include pstex, pslatex or epslatex here as the TeX commands + ## should not be interpreted in that case. + if (compare_versions (__gnuplot_version__ (), "4.0", ">")) + enhanced_terminals = {"aqua", "dumb", "png", "jpeg", "gif", "pm", ... + "windows", "wxt", "svg", "postscript", "x11"}; + else + enhanced_terminals = {"x11", "postscript"}; + endif + endif + + term = tolower (term); + + have_enhanced = false; + for i = 1 : length (enhanced_terminals) + t = enhanced_terminals{i}; + if (strncmp (term, t, min (length (term), length(t)))) + have_enhanced = true; + break; + endif + endfor +endfunction diff --git a/scripts/plot/hist.m b/scripts/plot/hist.m --- a/scripts/plot/hist.m +++ b/scripts/plot/hist.m @@ -91,6 +91,10 @@ endif endif + ## Avoid issues with integer types for x and y + x = double (x); + y = double (y); + cutoff = (x(1:end-1,:) + x(2:end,:)) / 2; n = rows (x); if (n < 30 && columns (x) == 1) diff --git a/scripts/plot/print.m b/scripts/plot/print.m --- a/scripts/plot/print.m +++ b/scripts/plot/print.m @@ -257,7 +257,6 @@ else options = strcat (orientation, " "); endif - options = strcat (options, "enhanced "); termn = "postscript"; endif diff --git a/scripts/plot/quiver.m b/scripts/plot/quiver.m --- a/scripts/plot/quiver.m +++ b/scripts/plot/quiver.m @@ -69,13 +69,13 @@ unwind_protect axes (h); newplot (); - tmp = __quiver__ (h, varargin{2:end}); + tmp = __quiver__ (h, 0, varargin{2:end}); unwind_protect_cleanup axes (oldh); end_unwind_protect else newplot (); - tmp = __quiver__ (gca (), varargin{:}); + tmp = __quiver__ (gca (), 0, varargin{:}); endif if (nargout > 0) @@ -84,138 +84,6 @@ endfunction -function hlist = __quiver__ (varargin) - h = varargin {1}; - - s = 1; - arrowsize = 0.33; - - firstnonnumeric = Inf; - for i = 2:nargin - if (! isnumeric (varargin {i})) - firstnonnumeric = i; - break; - endif - endfor - - if (nargin < 5 || firstnonnumeric < 5) - u = varargin{2}; - v = varargin{3}; - if (nargin == 4 && isnumeric (varargin{4}) && isscalar (varargin{4})) - s = varargin{4}; - iarg = 5; - else - iarg = 4; - endif - [x, y] = meshgrid (1:size(u,1), 1:size(u,2)); - else - x = varargin{2}; - y = varargin{3}; - u = varargin{4}; - v = varargin{5}; - if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v))) - [x, y] = meshgrid (x, y); - endif - if (nargin > 5 && isnumeric (varargin{6}) && isscalar (varargin{6})) - s = varargin{6}; - iarg = 7; - else - iarg = 6; - endif - endif - - have_filled = false; - have_line_spec = false; - while (iarg <= nargin) - arg = varargin {iarg++}; - if (ischar (arg) && strncmp (tolower (arg), "filled", 6)) - have_filled = true; - elseif ((isstr (arg) || iscell (arg)) - && ! have_line_spec) - [linespec, valid] = __pltopt__ ("quiver", arg, false); - if (valid) - have_line_spec = true; - if (strncmp (linespec.linestyle, "none", 4)) - linespec.linestyle = "-"; - endif - else - error ("quiver: invalid linespec"); - endif - else - error ("quiver: unrecognized argument"); - endif - endwhile - - if (s) - ## Scale the arrows to fit in the grid - dx = (max(x(:)) - min(x(:))) ./ size (x, 2); - dy = (max(y(:)) - min(y(:))) ./ size (y, 1); - len = max (sqrt (u(:).^2 + dy(:).^2)); - if (len > 0) - s = s / sqrt (2) * sqrt (dx.^2 + dy.^2) / len; - u = s * u; - v = s * v; - endif - endif - - x = x(:); - y = y(:); - xend = x + u(:); - yend = y + v(:); - - hstate = get (h, "nextplot"); - unwind_protect - if (have_line_spec) - h1 = plot ([x.'; xend.'; NaN(1, length (x))](:), - [y.'; yend.'; NaN(1, length (y))](:), - "linestyle", linespec.linestyle); - else - h1 = plot ([x.'; xend.'; NaN(1, length (x))](:), - [y.'; yend.'; NaN(1, length (y))](:)); - endif - hold on; - - xtmp = x + u(:) .* (1 - arrowsize); - ytmp = y + v(:) .* (1 - arrowsize); - xarrw1 = xtmp + (y - yend) * arrowsize / 3; - xarrw2 = xtmp - (y - yend) * arrowsize / 3; - yarrw1 = ytmp - (x - xend) * arrowsize / 3; - yarrw2 = ytmp + (x - xend) * arrowsize / 3; - - if (have_line_spec) - if (isfield (linespec, "marker") && - ! strncmp (linespec.marker, "none", 4)) - h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), - [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), - "linestyle", "none"); - else - h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), - [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:), - "linestyle", linespec.linestyle); - endif - else - h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:), - [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:)); - endif - - if (! have_line_spec || (isfield (linespec, "marker") && - strncmp (linespec.marker, "none", 4))) - h3 = plot (x, y, "linestyle", "none", "marker", "none"); - else - h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker); - endif - if (have_filled) - ## FIXME gnuplot doesn't respect the markerfacecolor field - set(h3, "markerfacecolor", get (h1, "color")); - endif - unwind_protect_cleanup - set (h, "nextplot", hstate); - end_unwind_protect - - hlist = [h1; h2; h3]; - -endfunction - %!demo %! [x,y] = meshgrid(1:2:20); %! quiver(x,y,sin(2*pi*x/10),sin(2*pi*y/10)) diff --git a/scripts/plot/quiver3.m b/scripts/plot/quiver3.m new file mode 100644 --- /dev/null +++ b/scripts/plot/quiver3.m @@ -0,0 +1,97 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} quiver3 (@var{u}, @var{v}, @var{w}) +## @deftypefnx {Function File} {} quiver3 (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w}) +## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{s}) +## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{style}) +## @deftypefnx {Function File} {} quiver3 (@dots{}, 'filled') +## @deftypefnx {Function File} {} quiver3 (@var{h}, @dots{}) +## @deftypefnx {Function File} {@var{h} =} quiver3 (@dots{}) +## +## Plot the @code{(@var{u}, @var{v}, @var{w})} components of a vector field in +## an @code{(@var{x}, @var{y}), @var{z}} meshgrid. If the grid is uniform, you +## can specify @var{x}, @var{y} @var{z} as vectors. +## +## If @var{x}, @var{y} and @var{z} are undefined they are assumed to be +## @code{(1:@var{m}, 1:@var{n}, 1:@var{p})} where @code{[@var{m}, @var{n}] = +## size(@var{u})} and @code{@var{p} = max (size (@var{w}))}. +## +## The variable @var{s} is a scalar defining a scaling factor to use for +## the arrows of the field relative to the mesh spacing. A value of 0 +## disables all scaling. The default value is 1. +## +## The style to use for the plot can be defined with a line style @var{style} +## in a similar manner to the line styles used with the @code{plot} command. +## If a marker is specified then markers at the grid points of the vectors are +## printed rather than arrows. If the argument 'filled' is given then the +## markers as filled. +## +## The optional return value @var{h} provides a list of handles to the +## the parts of the vector field (body, arrow and marker). +## +## @example +## @group +## [x, y, z] = peaks (25); +## surf (x, y, z); +## hold on; +## [u, v, w] = surfnorm (x, y, z / 10); +## quiver3 (x, y, z, u, v, w); +## @end group +## @end example +## +## @seealso{plot} +## @end deftypefn + +function retval = quiver3 (varargin) + + if (nargin < 2) + print_usage (); + elseif (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("quiver: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + newplot (); + tmp = __quiver__ (h, 1, varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + newplot (); + tmp = __quiver__ (gca (), 1, varargin{:}); + endif + + if (nargout > 0) + retval = tmp; + endif + +endfunction + +%!demo +%! [x,y]=meshgrid (-1:0.1:1); +%! z=sin(2*pi*sqrt(x.^2+y.^2)); +%! theta=2*pi*sqrt(x.^2+y.^2)+pi/2; +%! quiver3(x,y,z,sin(theta),cos(theta),ones(size(z))); +%! hold on; +%! mesh(x,y,z); +%! hold off; diff --git a/scripts/plot/scatter.m b/scripts/plot/scatter.m new file mode 100644 --- /dev/null +++ b/scripts/plot/scatter.m @@ -0,0 +1,83 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} scatter (@var{x}, @var{y}, @var{s}, @var{c}) +## @deftypefnx {Function File} {} scatter (@dots{}, 'filled') +## @deftypefnx {Function File} {} scatter (@dots{}, @var{style}) +## @deftypefnx {Function File} {} scatter (@dots{}, @var{prop}, @var{val}) +## @deftypefnx {Function File} {} scatter (@var{h}, @dots{}) +## @deftypefnx {Function File} {@var{h} =} scatter (@dots{}) +## +## Plot a scatter plot of the data. A marker is ploted at each point +## defined by the points in the vectors @var{x} and @var{y}. The size of +## the markers used is determined by the @var{s}, which can be a scalar, +## a vector of the same length of @var{x} and @var{y}. If @var{s} is not +## given or is an empty matrix, then the default value of 8 points is used. +## +## The color of the markers is determined by @var{c}, which can be a string +## defining a fixed color, a 3 element vector giving the red, green and blue +## components of the color, a vector of the same length as @var{x} that gives +## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining +## the colors of each of the markers individually. +## +## The marker to use can be changed with the @var{style} argument, that is a +## string defining a marker in the same manner as the @code{plot} command. +## If the argument 'filled' is given then the markers as filled. All +## additional arguments are passed to the underlying patch command. +## +## The optional return value @var{h} provides a handle to the patch object +## +## @example +## @group +## x = randn (100, 1); +## y = randn (100, 1); +## scatter (x, y, [], sqrt(x.^2 + y.^2)); +## @end group +## @end example +## +## @seealso{plot, patch, scatter3} +## @end deftypefn + +function retval = scatter (varargin) + + if (nargin < 2) + print_usage (); + elseif (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("scatter: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + newplot (); + tmp = __scatter__ (h, 2, "scatter", varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + newplot (); + tmp = __scatter__ (gca (), 2, "scatter", varargin{:}); + endif + + if (nargout > 0) + retval = tmp; + endif + +endfunction diff --git a/scripts/plot/scatter3.m b/scripts/plot/scatter3.m new file mode 100644 --- /dev/null +++ b/scripts/plot/scatter3.m @@ -0,0 +1,86 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} scatter3 (@var{x}, @var{y}, @var{s}, @var{c}) +## @deftypefnx {Function File} {} scatter3 (@dots{}, 'filled') +## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{style}) +## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{prop}, @var{val}) +## @deftypefnx {Function File} {} scatter3 (@var{h}, @dots{}) +## @deftypefnx {Function File} {@var{h} =} scatter3 (@dots{}) +## +## Plot a scatter plot of the data in 3D. A marker is ploted at each point +## defined by the points in the vectors @var{x} and @var{y}. The size of +## the markers used is determined by the @var{s}, which can be a scalar, +## a vector of the same length of @var{x} and @var{y}. If @var{s} is not +## given or is an empty matrix, then the default value of 8 points is used. +## +## The color of the markers is determined by @var{c}, which can be a string +## defining a fixed color, a 3 element vector giving the red, green and blue +## components of the color, a vector of the same length as @var{x} that gives +## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining +## the colors of each of the markers individually. +## +## The marker to use can be changed with the @var{style} argument, that is a +## string defining a marker in the same manner as the @code{plot} command. +## If the argument 'filled' is given then the markers as filled. All +## additional arguments are passed to the underlying patch command. +## +## The optional return value @var{h} provides a handle to the patch object +## +## @example +## @group +## [x, y, z] = peaks (20); +## scatter3 (x(:), y(:), z(:), [], z(:)); +## @end group +## @end example +## +## @seealso{plot, patch, scatter} +## @end deftypefn + +function retval = scatter3 (varargin) + + if (nargin < 2) + print_usage (); + elseif (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("scatter3: expecting first argument to be an axes object"); + endif + oldh = gca (); + unwind_protect + axes (h); + newplot (); + tmp = __scatter__ (h, 3, "scatter3", varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + newplot (); + tmp = __scatter__ (gca (), 3, "scatter3", varargin{:}); + endif + + if (! ishold ()) + set (get (tmp, "parent"), "view", [-37.5, 30]); + endif + + if (nargout > 0) + retval = tmp; + endif + +endfunction diff --git a/scripts/plot/sphere.m b/scripts/plot/sphere.m new file mode 100644 --- /dev/null +++ b/scripts/plot/sphere.m @@ -0,0 +1,77 @@ +## Copyright (C) 2007 Michael Goffioul +## +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{x}, @var{y}, @var{z}] =} sphere (@var{n}) +## @deftypefnx {Function File} {} sphere (@var{h}, @dots{}) +## Generates three matrices in @code{meshgrid} format, such that +## @code{surf (@var{x}, @var{y}, @var{z})} generates a unit sphere. +## The matrices of @code{@var{n}+1}-by-@code{@var{n}+1}. If @var{n} is +## omitted then a default value of 20 is assumed. +## +## Called with no return arguments, @code{sphere} call directly +## @code{surf (@var{x}, @var{y}, @var{z})}. If an axes handle is passed +## as the first argument, the the surface is plotted to this set of axes. +## @seealso{peaks} +## @end deftypefn + +function [xx,yy,zz] = sphere (h, n) + + have_h = false; + if (nargin > 1 && isscalar (h) && ishandle (h)) + if (! strcmp (get (h, "type"), "axes")) + error ("sphere: expecting first argument to be an axes object"); + endif + if (nargin == 1) + n = 20; + endif + have_h = true; + else + if (nargin == 1) + n = h; + else + n = 20; + endif + endif + + theta = linspace (0, 2*pi, n+1); + phi = linspace (-pi/2, pi/2, n+1); + [theta,phi] = meshgrid (theta, phi); + + x = cos(phi).*cos(theta); + y = cos(phi).*sin(theta); + z = sin(phi); + + if (nargout > 0) + xx = x; + yy = y; + zz = z; + else + if (have_h) + oldh = gca (); + unwind_protect + axes (h); + surf (x, y, z); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + surf (x, y, z); + endif + endif + +endfunction diff --git a/scripts/plot/stem.m b/scripts/plot/stem.m --- a/scripts/plot/stem.m +++ b/scripts/plot/stem.m @@ -107,11 +107,12 @@ endif newplot (); - - z = zeros (1, numel (x)); + nx = numel (x); xt = x(:)'; + xt = [xt; xt; NaN(1, nx)](:); yt = y(:)'; - h_stems = plot ([xt; xt], [z; yt], "color", lc, "linestyle", ls, + yt = [zeros(1, nx); yt; NaN(1, nx)](:); + h_stems = plot (xt, yt, "color", lc, "linestyle", ls, x, y, "color", mc, "marker", ms, "linestyle", "", "markerfacecolor", fc); @@ -262,10 +263,8 @@ ## Parse the line specifier string. cur_props = __pltopt__ ("stem", str, false); for i = 1:length(cur_props) - if (isfield (cur_props(i), "markeredgecolor")) - mc = cur_props(i).markeredgecolor; - elseif (isfield (cur_props(i), "color") && ! isempty (cur_props(i).color)); # means line color - lc = cur_props(i).color; + if (isfield (cur_props(i), "color") && ! isempty (cur_props(i).color)); # means line color + mc = lc = cur_props(i).color; elseif (isfield (cur_props(i), "linestyle")) ls = cur_props(i).linestyle; elseif (isfield (cur_props(i), "marker") && ! strcmp (cur_props(i).marker, "none")) diff --git a/scripts/plot/surface.m b/scripts/plot/surface.m --- a/scripts/plot/surface.m +++ b/scripts/plot/surface.m @@ -123,7 +123,9 @@ ## Make a default surface object. tmp = __go_surface__ (ax, "xdata", x, "ydata", y, "zdata", z, "cdata", c); set (tmp, "facecolor","flat"); - set (tmp, varargin {firststring:end}); + if (firststring <= nargin) + set (tmp, varargin {firststring:end}); + endif if (! ishold ()) set (ax, "view", [0, 90], "box", "off", "xgrid", "on", "ygrid", "on", "zgrid", "on"); diff --git a/scripts/plot/surfnorm.m b/scripts/plot/surfnorm.m new file mode 100644 --- /dev/null +++ b/scripts/plot/surfnorm.m @@ -0,0 +1,155 @@ +## Copyright (C) 2007 David Bateman +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} surfnorm (@var{x}, @var{y}, @var{z}) +## @deftypefnx {Function File} {} surfnorm (@var{z}) +## @deftypefnx {Function File} {[@var{nx}, @var{ny}, @var{nz}] =} surfnorm (@dots{}) +## @deftypefnx {Function File} {} surfnorm (@var{h}, @dots{}) +## Find the vectors normal to a meshgridded surface. The meshed gridded +## surface is defined by @var{x}, @var{y}, and @var{z}. If @var{x} and +## @var{y} are not defined, then it is assumed that they are given by +## +## @example +## [@var{x}, @var{y}] = meshgrid (1:size(@var{z}, 1), +## 1:size(@var{z}, 2)); +## @end example +## +## If no return arguments are requested, a surface plot with the normal +## vectors to the surface is plotted. Otherwise the componets of the normal +## vectors at the mesh gridded points are returned in @var{nx}, @var{ny}, +## and @var{nz}. +## +## The normal vectors are calculated by taking the cross product of the +## diagonals of eash of teh quadrilaterals in the meshgrid to find the +## normal vectors of the centers of these quadrilaterals. The four nearest +## normal vectors to the meshgrid points are then averaged to obtain the +## normal to the surface at the meshgridded points. +## +## An example of the use of @code{surfnorm} is +## +## @example +## surfnorm (peaks (25)); +## @end example +## @seealso{surf, quiver3} +## @end deftypefn + +function varargout = surfnorm (varargin) + + if (nargout > 0) + varargout = cell (nargout, 1); + else + varargout = cell (0, 0); + endif + if (isscalar (varargin{1}) && ishandle (varargin{1})) + h = varargin {1}; + if (! strcmp (get (h, "type"), "axes")) + error ("surfnorm: expecting first argument to be an axes object"); + endif + if (nargin != 2 && nargin != 4) + print_usage (); + endif + oldh = gca (); + unwind_protect + axes (h); + [varargout{:}] = __surfnorm__ (h, varargin{2:end}); + unwind_protect_cleanup + axes (oldh); + end_unwind_protect + else + if (nargin != 1 && nargin != 3) + print_usage (); + endif + [varargout{:}] = __surfnorm__ (gca (), varargin{:}); + endif + +endfunction + +function [Nx, Ny, Nz] = __surfnorm__ (h, varargin) + + if (nargin == 2) + z = varargin{1}; + [x, y] = meshgrid (1:size(z,1), 1:size(z,2)); + ioff = 2; + else + x = varargin{1}; + y = varargin{2}; + z = varargin{3}; + ioff = 4; + endif + + if (nargout == 0) + newplot(); + surf (x, y, z, varargin{ioff:end}); + hold on; + endif + + ## Make life easier, and avoid having to do the extrapolation later, do + ## a simpler linear extrapolation here. This is approximative, and works + ## badly for closed surfaces like spheres. + xx = [2 .* x(:,1) - x(:,2), x, 2 .* x(:,end) - x(:,end-1)]; + xx = [2 .* xx(1,:) - xx(2,:); xx; 2 .* xx(end,:) - xx(end-1,:)]; + yy = [2 .* y(:,1) - y(:,2), y, 2 .* y(:,end) - y(:,end-1)]; + yy = [2 .* yy(1,:) - yy(2,:); yy; 2 .* yy(end,:) - yy(end-1,:)]; + zz = [2 .* z(:,1) - z(:,2), z, 2 .* z(:,end) - z(:,end-1)]; + zz = [2 .* zz(1,:) - zz(2,:); zz; 2 .* zz(end,:) - zz(end-1,:)]; + + u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end); + u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end); + u.z = zz(1:end-1,1:end-1) - zz(2:end,2:end); + v.x = xx(1:end-1,2:end) - xx(2:end,1:end-1); + v.y = yy(1:end-1,2:end) - yy(2:end,1:end-1); + v.z = zz(1:end-1,2:end) - zz(2:end,1:end-1); + + c = cross ([u.x(:), u.y(:), u.z(:)], [v.x(:), v.y(:), v.z(:)]); + w.x = reshape (c(:,1), size(u.x)); + w.y = reshape (c(:,2), size(u.y)); + w.z = reshape (c(:,3), size(u.z)); + + ## Create normal vectors as mesh vectices from normals at mesh centers + nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) + + w.x(2:end,1:end-1) + w.x(2:end,2:end)) ./ 4; + ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) + + w.y(2:end,1:end-1) + w.y(2:end,2:end)) ./ 4; + nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) + + w.z(2:end,1:end-1) + w.z(2:end,2:end)) ./ 4; + + ## Normalize the normal vectors + len = sqrt (nx.^2 + ny.^2 + nz.^2); + nx = nx ./ len; + ny = ny ./ len; + nz = nz ./ len; + + if (nargout == 0) + plot3 ([x(:)'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:), + [y(:)'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:), + [z(:)'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:), + varargin{ioff:end}); + else + Nx = nx; + Ny = ny; + Nz = nz; + endif +endfunction + +%!demo +%! [x, y, z] = peaks(10); +%! surfnorm (x, y, z); + +%!demo +%! surfnorm (peaks(10)); diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,29 @@ +2007-11-26 David Bateman + + * DLD-FUNCTIONS/minmax.cc (MINMAX_DOUBLE_BODY): New version of + MINMAX_BODY macro without the initialization. + (MINMAX_INT_BODY): Macro for min/max for the integer types + (MINMAX_BODY): New macro that calls the appropriate instantiation + of the other two macros. + + * graphics.cc (class axes): Add __colorbar__ property. + * graphics.h.in (class axes): ditto. + + * data.cc (Fnorm): Document the "inf" string argument for matrice + and vectors and the "fro" argument for vectors. + + * graphics.h.in (class figure): Add __enhanced__ property to cache + whether the terminal supports enhanced mode. Add interpreter + property to all text classes, to determine the renderer for the + text. + * graphics.cc (class figure): ditto. + +2007-11-26 Shai Ayal + + * graphics.cc (string_properties): delete class + (property_name): rename class to caseless_str. + (radio_values::possible_vals): change type to caseless_str. + 2007-11-26 Michael Goffioul * builtins.h (install_builtins): Tag with OCTINTERP_API. diff --git a/src/DLD-FUNCTIONS/minmax.cc b/src/DLD-FUNCTIONS/minmax.cc --- a/src/DLD-FUNCTIONS/minmax.cc +++ b/src/DLD-FUNCTIONS/minmax.cc @@ -40,65 +40,8 @@ #include "ov-cx-mat.h" -#define MINMAX_BODY(FCN) \ - \ - octave_value_list retval; \ - \ - int nargin = args.length (); \ - \ - if (nargin < 1 || nargin > 3 || nargout > 2) \ - { \ - print_usage (); \ - return retval; \ - } \ - \ - octave_value arg1; \ - octave_value arg2; \ - octave_value arg3; \ - \ - switch (nargin) \ - { \ - case 3: \ - arg3 = args(2); \ - \ - case 2: \ - arg2 = args(1); \ - \ - case 1: \ - arg1 = args(0); \ - break; \ - \ - default: \ - panic_impossible (); \ - break; \ - } \ - \ - int dim; \ - dim_vector dv = arg1.dims (); \ - if (error_state) \ - { \ - gripe_wrong_type_arg (#FCN, arg1); \ - return retval; \ - } \ - \ - if (nargin == 3) \ - { \ - dim = arg3.nint_value () - 1; \ - if (dim < 0 || dim >= dv.length ()) \ - { \ - error ("%s: invalid dimension", #FCN); \ - return retval; \ - } \ - } \ - else \ - { \ - dim = 0; \ - while ((dim < dv.length ()) && (dv (dim) <= 1)) \ - dim++; \ - if (dim == dv.length ()) \ - dim = 0; \ - } \ - \ +#define MINMAX_DOUBLE_BODY(FCN) \ +{ \ bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3); \ \ if (single_arg && (nargout == 1 || nargout == 0)) \ @@ -271,8 +214,185 @@ } \ } \ } \ +} + +#define MINMAX_INT_BODY(FCN, TYP) \ + { \ + bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3); \ \ - return retval + if (single_arg && (nargout == 1 || nargout == 0)) \ + { \ + TYP ## NDArray m = arg1. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + TYP ## NDArray n = m. FCN (dim); \ + retval(0) = n; \ + } \ + } \ + else if (single_arg && nargout == 2) \ + { \ + ArrayN index; \ + \ + TYP ## NDArray m = arg1. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + TYP ## NDArray n = m. FCN (index, dim); \ + retval(0) = n; \ + } \ + \ + octave_idx_type len = index.numel (); \ + \ + if (len > 0) \ + { \ + double nan_val = lo_ieee_nan_value (); \ + \ + NDArray idx (index.dims ()); \ + \ + for (octave_idx_type i = 0; i < len; i++) \ + { \ + OCTAVE_QUIT; \ + int tmp = index.elem (i) + 1; \ + idx.elem (i) = (tmp <= 0) \ + ? nan_val : static_cast (tmp); \ + } \ + \ + retval(1) = idx; \ + } \ + else \ + retval(1) = NDArray (); \ + } \ + else \ + { \ + int arg1_is_scalar = arg1.is_scalar_type (); \ + int arg2_is_scalar = arg2.is_scalar_type (); \ + \ + if (arg1_is_scalar) \ + { \ + octave_ ## TYP d1 = arg1. TYP ## _scalar_value (); \ + TYP ## NDArray m2 = arg2. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + TYP ## NDArray result = FCN (d1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else if (arg2_is_scalar) \ + { \ + TYP ## NDArray m1 = arg1. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + octave_ ## TYP d2 = arg2. TYP ## _scalar_value (); \ + TYP ## NDArray result = FCN (m1, d2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else \ + { \ + TYP ## NDArray m1 = arg1. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + TYP ## NDArray m2 = arg2. TYP ## _array_value (); \ + \ + if (! error_state) \ + { \ + TYP ## NDArray result = FCN (m1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + } \ +} + +#define MINMAX_BODY(FCN) \ + \ + octave_value_list retval; \ + \ + int nargin = args.length (); \ + \ + if (nargin < 1 || nargin > 3 || nargout > 2) \ + { \ + print_usage (); \ + return retval; \ + } \ + \ + octave_value arg1; \ + octave_value arg2; \ + octave_value arg3; \ + \ + switch (nargin) \ + { \ + case 3: \ + arg3 = args(2); \ + \ + case 2: \ + arg2 = args(1); \ + \ + case 1: \ + arg1 = args(0); \ + break; \ + \ + default: \ + panic_impossible (); \ + break; \ + } \ + \ + int dim; \ + dim_vector dv = arg1.dims (); \ + if (error_state) \ + { \ + gripe_wrong_type_arg (#FCN, arg1); \ + return retval; \ + } \ + \ + if (nargin == 3) \ + { \ + dim = arg3.nint_value () - 1; \ + if (dim < 0 || dim >= dv.length ()) \ + { \ + error ("%s: invalid dimension", #FCN); \ + return retval; \ + } \ + } \ + else \ + { \ + dim = 0; \ + while ((dim < dv.length ()) && (dv (dim) <= 1)) \ + dim++; \ + if (dim == dv.length ()) \ + dim = 0; \ + } \ + \ + if (arg1.is_integer_type ()) \ + { \ + if (arg1.is_uint8_type ()) \ + MINMAX_INT_BODY (FCN, uint8) \ + else if (arg1.is_uint16_type ()) \ + MINMAX_INT_BODY (FCN, uint16) \ + else if (arg1.is_uint32_type ()) \ + MINMAX_INT_BODY (FCN, uint32) \ + else if (arg1.is_uint64_type ()) \ + MINMAX_INT_BODY (FCN, uint64) \ + else if (arg1.is_int8_type ()) \ + MINMAX_INT_BODY (FCN, int8) \ + else if (arg1.is_int16_type ()) \ + MINMAX_INT_BODY (FCN, int16) \ + else if (arg1.is_int32_type ()) \ + MINMAX_INT_BODY (FCN, int32) \ + else if (arg1.is_int64_type ()) \ + MINMAX_INT_BODY (FCN, int64) \ + } \ + else \ + MINMAX_DOUBLE_BODY (FCN) \ + \ + return retval; DEFUN_DLD (min, args, nargout, "-*- texinfo -*-\n\ diff --git a/src/data.cc b/src/data.cc --- a/src/data.cc +++ b/src/data.cc @@ -2775,7 +2775,7 @@ @item @var{p} = @code{2}\n\ Largest singular value of @var{a}.\n\ \n\ -@item @var{p} = @code{Inf}\n\ +@item @var{p} = @code{Inf} or @code{\"inf\"}\n\ @cindex infinity norm\n\ Infinity norm, the largest row sum of the absolute values of @var{a}.\n\ \n\ @@ -2787,12 +2787,15 @@ If @var{a} is a vector or a scalar:\n\ \n\ @table @asis\n\ -@item @var{p} = @code{Inf}\n\ +@item @var{p} = @code{Inf} or @code{\"inf\"}\n\ @code{max (abs (@var{a}))}.\n\ \n\ @item @var{p} = @code{-Inf}\n\ @code{min (abs (@var{a}))}.\n\ \n\ +@item @var{p} = @code{\"fro\"}\n\ +Frobenius norm of @var{a}, @code{sqrt (sumsq (abs (a)))}.\n\ +\n\ @item other\n\ p-norm of @var{a}, @code{(sum (abs (@var{a}) .^ @var{p})) ^ (1/@var{p})}.\n\ @end table\n\ diff --git a/src/graphics.cc b/src/graphics.cc --- a/src/graphics.cc +++ b/src/graphics.cc @@ -219,7 +219,7 @@ void -property_list::set (const property_name& name, const octave_value& val) +property_list::set (const caseless_str& name, const octave_value& val) { size_t offset = 0; @@ -227,7 +227,7 @@ if (len > 4) { - property_name pfx = name.substr (0, 4); + caseless_str pfx = name.substr (0, 4); if (pfx.compare ("axes") || pfx.compare ("line") || pfx.compare ("text")) @@ -266,7 +266,7 @@ bool remove = false; if (val.is_string ()) { - property_name tval = val.string_value (); + caseless_str tval = val.string_value (); remove = tval.compare ("remove"); } @@ -290,7 +290,7 @@ } octave_value -property_list::lookup (const property_name& name) const +property_list::lookup (const caseless_str& name) const { octave_value retval; @@ -300,7 +300,7 @@ if (len > 4) { - property_name pfx = name.substr (0, 4); + caseless_str pfx = name.substr (0, 4); if (pfx.compare ("axes") || pfx.compare ("line") || pfx.compare ("text")) @@ -398,7 +398,7 @@ { for (int i = 0; i < nargin; i += 2) { - property_name name = args(i).string_value (); + caseless_str name = args(i).string_value (); if (! error_state) { @@ -406,7 +406,7 @@ if (val.is_string ()) { - property_name tval = val.string_value (); + caseless_str tval = val.string_value (); if (tval.compare ("default")) val = get_default (name); @@ -485,7 +485,7 @@ gh_manager *gh_manager::instance = 0; static void -xset (const graphics_handle& h, const property_name& name, +xset (const graphics_handle& h, const caseless_str& name, const octave_value& val) { graphics_object obj = gh_manager::get_object (h); @@ -504,7 +504,7 @@ static octave_value -xget (const graphics_handle& h, const property_name& name) +xget (const graphics_handle& h, const caseless_str& name) { graphics_object obj = gh_manager::get_object (h); return obj.get (name); @@ -784,7 +784,7 @@ } void -root_figure::properties::set (const property_name& name, +root_figure::properties::set (const caseless_str& name, const octave_value& val) { if (name.compare ("tag")) @@ -813,7 +813,7 @@ } octave_value -root_figure::properties::get (const property_name& name) const +root_figure::properties::get (const caseless_str& name) const { octave_value retval; @@ -844,6 +844,7 @@ const graphics_handle& p) : base_properties (go_name, mh, p), __plot_stream__ (Matrix ()), + __enhanced__ (false), nextplot ("replace"), closerequestfcn (make_fcn_handle ("closereq")), currentaxes (octave_NaN), @@ -879,7 +880,7 @@ } void -figure::properties::set (const property_name& name, const octave_value& val) +figure::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -894,6 +895,8 @@ } else if (name.compare ("__plot_stream__")) set___plot_stream__ (val); + else if (name.compare ("__enhanced__")) + set___enhanced__ (val); else if (name.compare ("nextplot")) set_nextplot (val); else if (name.compare ("closerequestfcn")) @@ -927,6 +930,7 @@ m.assign ("children", children); m.assign ("__modified__", __modified__); m.assign ("__plot_stream__", __plot_stream__); + m.assign ("__enhanced__", __enhanced__); m.assign ("nextplot", nextplot); m.assign ("closerequestfcn", closerequestfcn); m.assign ("currentaxes", currentaxes.as_octave_value ()); @@ -938,7 +942,7 @@ } octave_value -figure::properties::get (const property_name& name) const +figure::properties::get (const caseless_str& name) const { octave_value retval; @@ -954,6 +958,8 @@ retval = __modified__; else if (name.compare ("__plot_stream__")) retval = __plot_stream__; + else if (name.compare ("__enhanced__")) + retval = __enhanced__; else if (name.compare ("nextplot")) retval = nextplot; else if (name.compare ("closerequestfcn")) @@ -1008,7 +1014,7 @@ } octave_value -figure::get_default (const property_name& name) const +figure::get_default (const caseless_str& name) const { octave_value retval = default_properties.lookup (name); @@ -1106,7 +1112,8 @@ view (), visible ("on"), nextplot ("replace"), - outerposition () + outerposition (), + __colorbar__ (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside")) { Matrix tlim (1, 2, 0.0); tlim(1) = 1; @@ -1192,7 +1199,7 @@ } void -axes::properties::set (const property_name& name, const octave_value& val) +axes::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -1307,6 +1314,8 @@ set_nextplot (val); else if (name.compare ("outerposition")) set_outerposition (val); + else if (name.compare ("__colorbar__")) + set___colorbar__ (val); else { modified = false; @@ -1393,6 +1402,8 @@ outerposition = touterposition; } + __colorbar__ = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside")); + delete_children (); children = Matrix (); @@ -1496,12 +1507,13 @@ m.assign ("visible", visible); m.assign ("nextplot", nextplot); m.assign ("outerposition", outerposition); + m.assign ("__colorbar__", __colorbar__); return m; } octave_value -axes::properties::get (const property_name& name) const +axes::properties::get (const caseless_str& name) const { octave_value retval; @@ -1615,6 +1627,8 @@ retval = nextplot; else if (name.compare ("outerposition")) retval = outerposition; + else if (name.compare ("__colorbar__")) + retval = __colorbar__; else warning ("get: invalid property `%s'", name.c_str ()); @@ -1721,12 +1735,13 @@ touterposition(3) = 1; m["outerposition"] = touterposition; + m["__colorbar__"] = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside")); return m; } octave_value -axes::get_default (const property_name& name) const +axes::get_default (const caseless_str& name) const { octave_value retval = default_properties.lookup (name); @@ -1773,11 +1788,12 @@ markeredgecolor ("auto"), markerfacecolor ("none"), markersize (1), - keylabel ("") + keylabel (""), + interpreter (radio_values ("{tex}|none|latex")) { } void -line::properties::set (const property_name& name, const octave_value& val) +line::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -1822,6 +1838,8 @@ set_markersize (val); else if (name.compare ("keylabel")) set_keylabel (val); + else if (name.compare ("interpreter")) + set_interpreter (val); else { modified = false; @@ -1857,12 +1875,13 @@ m.assign ("markerfacecolor", markerfacecolor); m.assign ("markersize", markersize); m.assign ("keylabel", keylabel); + m.assign ("interpreter", interpreter); return m; } octave_value -line::properties::get (const property_name& name) const +line::properties::get (const caseless_str& name) const { octave_value retval; @@ -1906,6 +1925,8 @@ retval = markersize; else if (name.compare ("keylabel")) retval = keylabel; + else if (name.compare ("interpreter")) + retval = interpreter; else warning ("get: invalid property `%s'", name.c_str ()); @@ -1932,6 +1953,8 @@ m["markerfacecolor"] = "none"; m["markersize"] = 1; m["keylabel"] = ""; + m["interpreter"] = + radio_property (radio_values ("{tex}|none|latex")); return m; } @@ -1952,11 +1975,12 @@ fontname ("Helvetica"), fontsize (10), fontangle (radio_values ("{normal}|italic|oblique")), - fontweight (radio_values ("{normal}|bold|demi|light")) + fontweight (radio_values ("{normal}|bold|demi|light")), + interpreter (radio_values ("{tex}|none|latex")) { } void -text::properties::set (const property_name& name, const octave_value& val) +text::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -1991,6 +2015,8 @@ set_fontangle (val); else if (name.compare ("fontweight")) set_fontweight (val); + else if (name.compare ("interpreter")) + set_interpreter (val); else { modified = false; @@ -2021,12 +2047,13 @@ m.assign ("fontsize", fontsize); m.assign ("fontangle", fontangle); m.assign ("fontweight", fontweight); + m.assign ("interpreter", interpreter); return m; } octave_value -text::properties::get (const property_name& name) const +text::properties::get (const caseless_str& name) const { octave_value retval; @@ -2060,6 +2087,8 @@ retval = fontangle; else if (name.compare ("fontweight")) retval = fontweight; + else if (name.compare ("interpreter")) + retval = interpreter; else warning ("get: invalid property `%s'", name.c_str ()); @@ -2080,9 +2109,11 @@ m["fontname"] = "Helvetica"; m["fontsize"] = 10; m["fontangle"] = - string_property ("normal", radio_values ("{normal}|italic|oblique")); + radio_property (radio_values ("{normal}|italic|oblique")); m["fontweight"] = - string_property ("normal", radio_values ("{normal}|bold|demi|light")); + radio_property (radio_values ("{normal}|bold|demi|light")); + m["interpreter"] = + radio_property (radio_values ("{tex}|none|latex")); return m; } @@ -2100,7 +2131,7 @@ { } void -image::properties::set (const property_name& name, +image::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -2150,7 +2181,7 @@ } octave_value -image::properties::get (const property_name& name) const +image::properties::get (const caseless_str& name) const { octave_value retval; @@ -2210,11 +2241,12 @@ markeredgecolor ("auto"), markerfacecolor ("none"), markersize (1), - keylabel ("") + keylabel (""), + interpreter (radio_values ("{tex}|none|latex")) { } void -patch::properties::set (const property_name& name, +patch::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -2262,6 +2294,8 @@ set_markersize (val); else if (name.compare ("keylabel")) set_keylabel (val); + else if (name.compare ("interpreter")) + set_interpreter (val); else { modified = false; @@ -2298,12 +2332,13 @@ m.assign ("markerface", markerfacecolor); m.assign ("markersize", markersize); m.assign ("keylabel", keylabel); + m.assign ("interpreter", interpreter); return m; } octave_value -patch::properties::get (const property_name& name) const +patch::properties::get (const caseless_str& name) const { octave_value retval; @@ -2349,6 +2384,8 @@ retval = markersize; else if (name.compare ("keylabel")) retval = keylabel; + else if (name.compare ("interpreter")) + retval = interpreter; else warning ("get: invalid property `%s'", name.c_str ()); @@ -2376,6 +2413,8 @@ m["markerfacecolor"] = "none"; m["markersize"] = 1; m["keylabel"] = ""; + m["interpreter"] = + radio_property (radio_values ("{tex}|none|latex")); return m; } @@ -2400,11 +2439,12 @@ markeredgecolor ("auto"), markerfacecolor ("none"), markersize (1), - keylabel ("") + keylabel (""), + interpreter (radio_values ("{tex}|none|latex")) { } void -surface::properties::set (const property_name& name, +surface::properties::set (const caseless_str& name, const octave_value& val) { bool modified = true; @@ -2448,6 +2488,8 @@ set_markersize (val); else if (name.compare ("keylabel")) set_keylabel (val); + else if (name.compare ("interpreter")) + set_interpreter (val); else { modified = false; @@ -2482,12 +2524,13 @@ m.assign ("markerface", markerfacecolor); m.assign ("markersize", markersize); m.assign ("keylabel", keylabel); + m.assign ("interpreter", interpreter); return m; } octave_value -surface::properties::get (const property_name& name) const +surface::properties::get (const caseless_str& name) const { octave_value retval; @@ -2529,6 +2572,8 @@ retval = markersize; else if (name.compare ("keylabel")) retval = keylabel; + else if (name.compare ("interpreter")) + retval = interpreter; else warning ("get: invalid property `%s'", name.c_str ()); @@ -2554,6 +2599,8 @@ m["markerfacecolor"] = "none"; m["markersize"] = 1; m["keylabel"] = ""; + m["interpreter"] = + radio_property (radio_values ("{tex}|none|latex")); return m; } @@ -2563,7 +2610,7 @@ // --------------------------------------------------------------------- octave_value -base_graphics_object::get_default (const property_name& name) const +base_graphics_object::get_default (const caseless_str& name) const { graphics_handle parent = get_parent (); graphics_object parent_obj = gh_manager::get_object (parent); @@ -2572,7 +2619,7 @@ } octave_value -base_graphics_object::get_factory_default (const property_name& name) const +base_graphics_object::get_factory_default (const caseless_str& name) const { graphics_object parent_obj = gh_manager::get_object (0); @@ -2765,7 +2812,7 @@ vlist(n) = obj.get (); else { - property_name property = args(1).string_value (); + caseless_str property = args(1).string_value (); if (! error_state) vlist(n) = obj.get (property); @@ -3075,7 +3122,7 @@ if (obj) { - property_name p = std::string (property); + caseless_str p = std::string (property); retval = obj.get (p); } else @@ -3093,7 +3140,7 @@ if (obj) { - property_name p = std::string (property); + caseless_str p = std::string (property); obj.set (p, arg); if (!error_state) ret = true; diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -39,6 +39,49 @@ #include "oct-map.h" #include "ov.h" +class caseless_str : public std::string +{ +public: + typedef std::string::iterator iterator; + typedef std::string::const_iterator const_iterator; + + caseless_str (void) : std::string () { } + caseless_str (const std::string& s) : std::string (s) { } + caseless_str (const char *s) : std::string (s) { } + + caseless_str (const caseless_str& name) : std::string (name) { } + + caseless_str& operator = (const caseless_str& pname) + { + std::string::operator = (pname); + return *this; + } + + operator std::string (void) const { return *this; } + + // Case-insensitive comparison. + bool compare (const std::string& s, size_t limit = NPOS) const + { + const_iterator p1 = begin (); + const_iterator p2 = s.begin (); + + size_t k = 0; + + while (p1 != end () && p2 != s.end () && k++ < limit) + { + if (std::tolower (*p1) != std::tolower (*p2)) + return false; + + *p1++; + *p2++; + } + + return (limit == NPOS) ? size () == s.size () : k == limit; + } +}; + +// --------------------------------------------------------------------- + class radio_values { @@ -61,8 +104,6 @@ std::string default_value (void) const { return default_val; } - std::set possible_values (void) const { return possible_vals; } - bool validate (const std::string& val) { bool retval = true; @@ -84,7 +125,7 @@ private: // Might also want to cache std::string default_val; - std::set possible_vals; + std::set possible_vals; }; class @@ -115,10 +156,30 @@ { if (vals.validate (newval)) current_val = newval; + else + error ("invalid value"); return *this; } + radio_property& operator = (const octave_value& newval) + { + if (newval.is_string ()) + { + std::string s = newval.string_value (); + if (vals.validate (s)) + current_val = s; + else + error ("invalid value"); + } + else + error ("invalid value"); + + return *this; + } + + operator octave_value (void) const { return current_val; } + const std::string& current_value (void) const { return current_val; } private: @@ -352,152 +413,6 @@ Matrix cmap; }; -class -string_property -{ -public: - string_property (const octave_value& c = octave_value (std::string ()), - const radio_values& v = radio_values ()) - : radio_val (v) - { - if (c.is_defined ()) - { - std::string newval = c.string_value (); - - std::transform (newval.begin (), newval.end (), - newval.begin (), tolower); - - if (! error_state) - { - if (radio_val.validate (newval)) - current_val = newval; - } - } - else - current_val = v.default_value (); - } - - string_property (const radio_values& v) - : current_val (v.default_value()), radio_val (v) - { } - - string_property (const radio_values& v, const std::string& initial_value) - : radio_val (v) - { - current_val = initial_value; - std::transform (current_val.begin (), current_val.end (), - current_val.begin (), tolower); - } - - operator octave_value (void) const { return current_val; } - - string_property& operator = (const string_property& a) - { - if (&a != this) - { - current_val = a.current_val; - radio_val = a.radio_val; - } - - return *this; - } - - string_property& operator = (const std::string& s) - { - std::string newval = s; - - std::transform (newval.begin (), newval.end (), - newval.begin (), tolower); - - if (! newval.empty ()) - { - if (radio_val.contains (newval)) - current_val = newval; - else - error ("invalid string specification"); - } - else - error ("invalid string specification"); - - return *this; - } - - string_property& operator = (const octave_value& val) - { - if (val.is_string ()) - { - std::string newval = val.string_value (); - - std::transform (newval.begin (), newval.end (), - newval.begin (), tolower); - - if (! newval.empty ()) - { - if (radio_val.contains (newval)) - current_val = newval; - else - error ("invalid string specification"); - } - else - error ("invalid string specification"); - } - else - error ("invalid string specification"); - - return *this; - } - - const std::string& current_value (void) const { return current_val; } - -private: - std::string current_val; - radio_values radio_val; -}; - -// --------------------------------------------------------------------- - -class property_name : public std::string -{ -public: - typedef std::string::iterator iterator; - typedef std::string::const_iterator const_iterator; - - property_name (void) : std::string () { } - property_name (const std::string& s) : std::string (s) { } - property_name (const char *s) : std::string (s) { } - - property_name (const property_name& name) : std::string (name) { } - - property_name& operator = (const property_name& pname) - { - std::string::operator = (pname); - return *this; - } - - operator std::string (void) const { return *this; } - - // Case-insensitive comparison. - bool compare (const std::string& s, size_t limit = NPOS) const - { - const_iterator p1 = begin (); - const_iterator p2 = s.begin (); - - size_t k = 0; - - while (p1 != end () && p2 != s.end () && k++ < limit) - { - if (std::tolower (*p1) != std::tolower (*p2)) - return false; - - *p1++; - *p2++; - } - - return (limit == NPOS) ? size () == s.size () : k == limit; - } -}; - -// --------------------------------------------------------------------- class property_list { @@ -516,9 +431,9 @@ ~property_list (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); - octave_value lookup (const property_name& name) const; + octave_value lookup (const caseless_str& name) const; plist_map_iterator begin (void) { return plist_map.begin (); } plist_map_const_iterator begin (void) const { return plist_map.begin (); } @@ -668,7 +583,7 @@ void set_from_list (base_graphics_object& obj, property_list& defaults); - virtual void set (const property_name&, const octave_value&) { } + virtual void set (const caseless_str&, const octave_value&) { } std::string get_tag (void) const { return tag; } @@ -726,7 +641,7 @@ error ("base_graphics_object::set_from_list: invalid graphics object"); } - virtual void set (const property_name&, const octave_value&) + virtual void set (const caseless_str&, const octave_value&) { error ("base_graphics_object::set: invalid graphics object"); } @@ -742,15 +657,15 @@ return octave_value (); } - virtual octave_value get (const property_name&) const + virtual octave_value get (const caseless_str&) const { error ("base_graphics_object::get: invalid graphics object"); return octave_value (); } - virtual octave_value get_default (const property_name&) const; + virtual octave_value get_default (const caseless_str&) const; - virtual octave_value get_factory_default (const property_name&) const; + virtual octave_value get_factory_default (const caseless_str&) const; virtual octave_value get_defaults (void) const { @@ -857,7 +772,7 @@ rep->set_from_list (plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { rep->set (name, val); } @@ -874,7 +789,7 @@ return rep->get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return name.compare ("default") ? get_defaults () @@ -882,12 +797,12 @@ ? get_factory_defaults () : rep->get (name)); } - octave_value get_default (const property_name& name) const + octave_value get_default (const caseless_str& name) const { return rep->get_default (name); } - octave_value get_factory_default (const property_name& name) const + octave_value get_factory_default (const caseless_str& name) const { return rep->get_factory_default (name); } @@ -937,11 +852,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -984,7 +899,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& value) + void set (const caseless_str& name, const octave_value& value) { if (name.compare ("default", 7)) // strip "default", pass rest to function that will @@ -1000,7 +915,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { octave_value retval; @@ -1014,7 +929,7 @@ return retval; } - octave_value get_default (const property_name& name) const + octave_value get_default (const caseless_str& name) const { octave_value retval = default_properties.lookup (name); @@ -1024,7 +939,7 @@ return retval; } - octave_value get_factory_default (const property_name& name) const + octave_value get_factory_default (const caseless_str& name) const { octave_value retval = factory_properties.lookup (name); @@ -1081,11 +996,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; void close (void); @@ -1098,6 +1013,7 @@ BEGIN_PROPERTIES octave_value __plot_stream__ + octave_value __enhanced__ octave_value nextplot octave_value closerequestfcn graphics_handle currentaxes S @@ -1148,7 +1064,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& value) + void set (const caseless_str& name, const octave_value& value) { if (name.compare ("default", 7)) // strip "default", pass rest to function that will @@ -1164,7 +1080,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { octave_value retval; @@ -1176,7 +1092,7 @@ return retval; } - octave_value get_default (const property_name& name) const; + octave_value get_default (const caseless_str& name) const; octave_value get_defaults (void) const { @@ -1213,13 +1129,13 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); void set_defaults (base_graphics_object& obj, const std::string& mode); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; void remove_child (const graphics_handle& h); @@ -1283,7 +1199,8 @@ octave_value visible octave_value nextplot octave_value outerposition - END_PROPERTIES + radio_property __colorbar__ a + END_PROPERTIES static std::string go_name; }; @@ -1323,7 +1240,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& value) + void set (const caseless_str& name, const octave_value& value) { if (name.compare ("default", 7)) // strip "default", pass rest to function that will @@ -1344,7 +1261,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { octave_value retval; @@ -1357,7 +1274,7 @@ return retval; } - octave_value get_default (const property_name& name) const; + octave_value get_default (const caseless_str& name) const; octave_value get_defaults (void) const { @@ -1394,11 +1311,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -1423,6 +1340,7 @@ octave_value markerfacecolor octave_value markersize octave_value keylabel + radio_property interpreter a END_PROPERTIES static std::string go_name; @@ -1456,7 +1374,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { xproperties.set (name, val); } @@ -1466,7 +1384,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return xproperties.get (name); } @@ -1498,11 +1416,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -1520,8 +1438,9 @@ color_property color octave_value fontname octave_value fontsize - string_property fontangle a - string_property fontweight a + radio_property fontangle a + radio_property fontweight a + radio_property interpreter a END_PROPERTIES static std::string go_name; @@ -1555,7 +1474,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { xproperties.set (name, val); } @@ -1565,7 +1484,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return xproperties.get (name); } @@ -1597,11 +1516,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -1647,7 +1566,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { xproperties.set (name, val); } @@ -1657,7 +1576,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return xproperties.get (name); } @@ -1689,11 +1608,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -1719,6 +1638,7 @@ octave_value markerfacecolor octave_value markersize octave_value keylabel + radio_property interpreter a END_PROPERTIES static std::string go_name; @@ -1752,7 +1672,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { xproperties.set (name, val); } @@ -1762,7 +1682,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return xproperties.get (name); } @@ -1794,11 +1714,11 @@ ~properties (void) { } - void set (const property_name& name, const octave_value& val); + void set (const caseless_str& name, const octave_value& val); octave_value get (void) const; - octave_value get (const property_name& name) const; + octave_value get (const caseless_str& name) const; std::string graphics_object_name (void) const { return go_name; } @@ -1822,6 +1742,7 @@ octave_value markerfacecolor octave_value markersize octave_value keylabel + radio_property interpreter a END_PROPERTIES static std::string go_name; @@ -1855,7 +1776,7 @@ xproperties.set_from_list (*this, plist); } - void set (const property_name& name, const octave_value& val) + void set (const caseless_str& name, const octave_value& val) { xproperties.set (name, val); } @@ -1865,7 +1786,7 @@ return xproperties.get (); } - octave_value get (const property_name& name) const + octave_value get (const caseless_str& name) const { return xproperties.get (name); }