ifthenelse

Post a reply


This question is a means of preventing automated form submissions by spambots.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:

BBCode is ON
[img] is ON
[flash] is ON
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: ifthenelse

ifthenelse

by topsquark » Fri Aug 25, 2023 4:21 am

Aw! But if I want to mess myself up properly, I need to crowd in many many things I don't understand all at once! :twisted:

(Back in the early 2000s I had a problem with Norton SystemWorks. I finally got a tech on the phone that knew what they were doing and they had me edit the registry, which the program had somehow fouled up. I got really excited at the possibilities of what I could do with the registry...I could have some serious fun with this! Then I remembered that I had had to call someone all the way across the country to get a professional to fix my computer because something had crippled my computer when it did something bad to the registry. I decided there are some things I'm not going to mess with!)

Okay, I've decided it's time to end this project. I've learned quite a bit already and I have that article to study. I'm sure I'll be back with other questions, simple or complex. In the meantime, I rewrote most of this in tikzmath, and I've fixed up all the little issues like what if the point is at the origin.

Just for completeness, here it is. Thanks again, everyone, for all the help!

-Dan

Code: Select all

\documentclass{article}

\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{pgf}
\usetikzlibrary{math}

\begin{document}

\newcommand\PointInfo[2]{
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Takes in a point P as {P}{} or as (x,y) coordinates {x}{y}.               %
%  Coordinates are assumed to be in cm.                                      %
%  Outputs                                                                   %
%       (\Pxcoord,\Pycoord):      Coordinates                                %
%       \Pquadrant:     Quadrant                                             %
%       \Pdisttoorigin: Distance from point to origin                        %
%       \Prefangle:     Reference angle                                      %
%       \Pangle:        Angle measured from +x axis                          %
%  (Pquadrant is set to 0 if P is at the origin.)                            %
%  (Prefangle and Pangle are set to "undefined" if P is at the origin.)      %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Determine which input is being used and set (\Pxcoord,\Pycoord) coordinates

     \ifstrempty{#2}{
          \path[transform canvas] (#1);
          \pgfgetlastxy{\xcoord}{\ycoord}
          \pgfmathsetmacro{\Xcoord}{scalar{\xcoord}/28.452756}
          \pgfmathsetmacro{\Ycoord}{scalar{\ycoord}/28.452756}
          \xdef\Pxcoord{\Xcoord}
          \xdef\Pycoord{\Ycoord}
          }
          {
          \gdef\Pxcoord{#1}
          \gdef\Pycoord{#2}
          }

     \tikzmath{
%
%  Calculate the quadrant the point is in
          if and(\Pxcoord==0,\Pycoord==0) then { \Pquadrant = 0; };
          if and(\Pxcoord>0,\Pycoord==0) then { \Pquadrant = 1; };
          if and(\Pxcoord==0,\Pycoord>0) then { \Pquadrant = 2; };
          if and(\Pxcoord<0,\Pycoord==0) then { \Pquadrant = 3; };
          if and(\Pxcoord==0,\Pycoord<0) then { \Pquadrant = 4; };
          if and(notequal(\Pxcoord,0),notequal(\Pycoord,0)) then { \Pquadrant = int(round(5/2-(\Pycoord)/abs(\Pycoord)-1/2*(\Pxcoord*\Pycoord)/(abs(\Pxcoord*\Pycoord))); };
%
%  Calculate the distance from the point to the origin
          \Pdisttoorigin = sqrt((\Pxcoord)^2+(\Pycoord)^2);
%
%  Calcluate the reference angle
          if and(\Pxcoord==0,\Pycoord==0) then { \Prefangle = 999; };
          if and(\Pxcoord==0,\Pycoord>0) then { \Prefangle = 90; };
          if and(\Pxcoord==0,\Pycoord<0) then { \Prefangle = 90; };
          if notequal(\Pxcoord,0) then { \Prefangle = abs(atan(\Pycoord/\Pxcoord)); };
%
%  Calculate the angle from the +x axis
          if and(\Pxcoord==0,\Pycoord==0) then { \Pangle = 999; }
          else { \Pangle = 180*floor(\Pquadrant/2)-(-1)^(\Pquadrant)*\Prefangle); };
     }

%  Set Prefangle and Pangle to undefined if necessary
     \if \Prefangle=999
          \renewcommand\Prefangle{undefined}
     \fi
     \if \Pangle=999
          \renewcommand\Pangle{undefined}
     \fi
}

\begin{tikzpicture}
    \node at (0,0) {Points on a hexagon.};
     \foreach \s in {0,...,5} {
          \coordinate (P\s) at (\s*60:4);
          \PointInfo{P\s}{};
          \node at (0,-\s*0.6-0.6) {P is in Q\Pquadrant. The polar coordinates are (\Pdisttoorigin,\Pangle).};
     };
\end{tikzpicture}

\end{document}

ifthenelse

by rais » Thu Aug 24, 2023 9:23 pm

topsquark wrote: (though I'm not completely sure why you were so surprised that my current one does. :cry: )
I was surprised because you used the same \gdef definitions for \x, \y as in the previous code.
What I failed to realize was: said definitions no longer are within a TeX group. In other words: you may have just used \def instead of \gdef in your last code and it still would have worked.
You can write this off as `rais not fully awake yet' :D
topsquark wrote: I only have a base idea about "extensions"
the proper term would be "expansions".
To me, an extension is just .*, that is, if your file is called "foo.tex", its base name would be "foo" its extension would be ".tex", but then, that may just be me...
topsquark wrote: but I think I understand what you are saying. I was trying to copy the contents of \X to globally define \x, but if I understand what you are saying when I try to do that its copying the temporary variable \X and turning it into another temporary \x, even though I'm using \gdef.
Not quite. The definition

Code: Select all

\gdef\x{\X}
does define \x to be global (to escape the current group), but it uses an unexpanded `\X' as replacement text. After the group closes, \X is no longer defined (which \x tries to call on).

Code: Select all

\xdef\x{\X}
on the other hand expands \X for the definition, so if \X contains "1pt", \x will contain "1pt" (and not "\X" as defined by \gdef...)
kaiserkarl13 wrote: Welcome to the wonderful world of TeX macro expansion!
exactly :)
topsquark wrote: (catagory?)
Don't you start with category codes now, that's a whole different chapter (also covered by the aforementioned TeXbyTopic)

KR
Rainer

ifthenelse

by topsquark » Thu Aug 24, 2023 3:58 pm

rais wrote:Hi Dan,
I'm actually surprised your last code works :D

Code: Select all

\gdef\x{\X}
globally defines \x to look up \X, when called--it does not expand \X.
Replace \gdef by \xdef which is short for \global\edef, then \X gets expanded.

Code: Select all

\gdef\x{#2}
works as expected, because argument placeholders are always expanded.

\gdef and friends are plain TeX commands, see e.g. TeXbyTopic.

KR
Rainer
Okay, I just wrote a long response and it got dumped when my power glitched!

In short, thank you for the article; it's going to be a God-send to me!

I'll have to look at the code again. I think I understand more about why things weren't working before (though I'm not completely sure why you were so surprised that my current one does. :cry: ) But even a first-order skim through that article has shown me many things that now make a lot more sense. A detailed study is definitely in order!

I only have a base idea about "extensions" but I think I understand what you are saying. I was trying to copy the contents of \X to globally define \x, but if I understand what you are saying when I try to do that its copying the temporary variable \X and turning it into another temporary \x, even though I'm using \gdef. I need to use \xdef to change the (catagory?) to global. That might be gibberish. I'll read the article more carefully.

Thanks again!

-Dan

ifthenelse

by topsquark » Thu Aug 24, 2023 3:46 pm

[quote="rais"]Hi Dan,
I'm actually surprised your last code works :D

:?

Grrr....

Okay, emotional response over. :)

Thank you for that paper. IT'S AWESOME. Contains a lot more than I want on what I might call "word processing" but there are a number of surprising little tidbits even in there. I did a quick skim and it looks like this is going to be one of the more valuable resources I've got right now. I had thought the if then thing would be an easy to learn thing: apparently there's a lot more going on in the background than I had imagined. And all that time spent on explaining macros... Again, thank you!!

Okay, based on what I've read I have to do a solid once over on the code. It also looks like I might be able to compartmentalize some of the code to "subrountine it up" (as I call it. I have no idea what a more modern terminology for that might be.) I'll have to get the thing working correctly first, then investigate that. Ultimately, my goal here (beyond the overall goal to get down the if then coding) is to create a library-esque command that will take a point and produce quadrant, distance to origin, reference angle, and angle information all in one little command to help out with debugging a diagram. (I just tried to reproduce a mosaic I found tikz.net and I had to go through all sorts of fits and conniptions. It would just make like easier to have a single command line that will give everything, rather than write several lines of code over and over to get different pieces of information.)

I now have a base understanding of "extendable." I'll read that section more carefully and see what I can do with it.

Thanks again!

-Dan

ifthenelse

by rais » Thu Aug 24, 2023 9:49 am

Hi Dan,
I'm actually surprised your last code works :D

Code: Select all

\gdef\x{\X}
globally defines \x to look up \X, when called--it does not expand \X.
Replace \gdef by \xdef which is short for \global\edef, then \X gets expanded.

Code: Select all

\gdef\x{#2}
works as expected, because argument placeholders are always expanded.

\gdef and friends are plain TeX commands, see e.g. TeXbyTopic.

KR
Rainer

ifthenelse

by topsquark » Thu Aug 24, 2023 2:04 am

I was able to solve this using a completely different system for finding \q if I have a given point or given coordinates. I am happy about that, but I still don't know why the code in the last post didn't work. This uses the same method to define \x and \y.

-Dan

Code: Select all

\documentclass{article}

\usepackage{tikz}
\usepackage{pgf}
\usepackage{etoolbox}

\begin{document}

\newcommand\quadrant[2]{
     \ifstrempty{#2}{
          \path[transform canvas] (#1);
          \pgfgetlastxy{\X}{\Y}
          \gdef\x{\X}
          \gdef\y{\Y}
     }
     {
          \gdef\x{#1}
          \gdef\y{#2}
     }

     \pgfmathsetmacro\q{
          \ifdim\x > 0pt
               \ifdim\y > 0pt
                    1
               \else
                    \ifdim\y < 0pt         
                         4
                    \fi
               \fi
          \else
               \ifdim\x < 0pt
                   \ifdim\y > 0pt
                        2
                   \else
                        \ifdim\y < 0pt
                             3
                        \fi
                   \fi
               \fi
          \fi
     }
}

\begin{tikzpicture}
     \coordinate (P) at (4pt,-1pt);
     \quadrant{2pt}{3pt}; \node[anchor=west] at (0,0) {The point (\x,\y) is in Quadrant \q.};
     \quadrant{P}{}; \node[anchor=west] at (0,-1) {The point (\x,\y) is in Quadrant \q.};
     \quadrant{-5pt}{-1pt}; \node[anchor=west] at (0,-2) {The point (\x,\y) is in Quadrant \q.};
\end{tikzpicture}

\end{document}

ifthenelse

by topsquark » Thu Aug 24, 2023 12:51 am

Nope. We're back. I've done every test I can think of. The only explanation I can come up with is when I use point, the \x and \y are not being passed outside of scope. I am having the same problem if I do any calculation in point and assign the result to \x and \y. (I even checked to make sure that the calculated values had units, they did.) But coords works like a charm.

I hate to post questions step by step like this, but I'm flummoxed. (Again! :) )

I was able to find precious little on the net about \gdef, but what I found suggests that I am doing this right. So far as I know, my code below should work. Clearly, I'm missing something.

Along with this question: I've got Kottwitz's "LaTeX Graphics with Tikz"(excellent!) and, of course, the PGF/TikZ online manual (for what it's worth.) I am trying to expand what I know and \tikzset, for example, has .style, .pic, .code, .initial, .get, and .default options, the only two of which I can find out anything about on the net are .style and .pic. I'm looking for a more comprehensive TikZ guide (much more clearly written than the PGF/TikZ manual) that is still accessible to someone with a weak programming background. (I've got BASIC, FORTRAN, PASCAL, and Apple machine coding in my background, but nothing modern.) I am still learning by looking at examples and trying to figure things out, and I appreciate all the help I've been getting here, but I can't keep coming here hoping to be taught what are apparently basic commands. I need another resource. The net is hopeless and I have no money to spare, but if I'm going to learn this right, I guess I'm going to have to pay. I see the other two guides listed along with the posts. Are they what I might be looking for, or is there something else you might suggest?

Thanks!

-Dan

Code: Select all

\documentclass{article}

\usepackage{tikz}
\usepackage{pgf}

\begin{document}

\newif\ifpoint
\tikzset{
     point/.code={\pointtrue}
}

\newif\ifcoords
\tikzset{
     coords/.code={\coordstrue}
}

\newcommand\quadrant[3]{
     \begin{scope}[#1]
          \ifpoint
               \path[transform canvas] (#2);
               \pgfgetlastxy{\X}{\Y}
               \gdef\x{\X}
               \gdef\y{\Y}
          \fi
          
          \ifcoords
               \gdef\x{#2}
               \gdef\y{#3}
          \fi
     \end{scope}

     \pgfmathsetmacro\q{
          \ifdim\x > 0pt
               \ifdim\y > 0pt
                    1
               \else
                    \ifdim\y < 0pt         
                         4
                    \fi
               \fi
          \else
               \ifdim\x < 0pt
                   \ifdim\y > 0pt
                        2
                   \else
                        \ifdim\y < 0pt
                             3
                        \fi
                   \fi
               \fi
          \fi
     }
}

\begin{tikzpicture}
     \quadrant{coords}{3pt}{-2pt}; \node[anchor=west] at (0,0) {The point (\x,\y) is in Quadrant \q.};
     \quadrant{point}{4pt,-1pt}{}; \node[anchor=west] at (0,-1) {The point (\x,\y) is in Quadrant \q.};
     \quadrant{coords}{-5pt}{-1pt}; \node[anchor=west] at (0,-2) {The point (\x,\y) is in Quadrant \q.};
\end{tikzpicture}

\end{document}

ifthenelse

by topsquark » Wed Aug 23, 2023 11:41 pm

Thank you. I have some more tweaking to do. (The \gdef is working for coords, but something is going wrong in points, for some reason. I'm now putting in coordinates of a point given as (\x,\y), and all the code works up to the point I use \gdef. I need to work on that.) I'll post again if I have another question, and I'll post my final product.

-Dan

ifthenelse

by rais » Wed Aug 23, 2023 8:07 pm

Hi Dan,
yes, ending a scope (or any other LaTeX environment) also ends a TeX group after which definitions made in that scope are lost.

Code: Select all

\documentclass{article}

\def\A{foo}
\def\B{foo}
\def\C{foo}
\begin{document}
Before some group: \A, \B, \C

\begingroup %to simulate the scope
\def\A{bar}
\gdef\B{bar}
\def\C{baz}% in case some other macro defined \C:
\global\let\C=\C
Within some group: \A, \B, \C
\endgroup

After some group: \A, \B, \C

\end{document}
\gdef is short for \global\def, so the redefinition of \B made within a group is still valid after the group closes.
\global\let\C=\C is a way to, hmm, globalize the definition of \C, so even if you redefined \C within a group using some other macro that may use a non-global definition (like \def), you could still make its (re)definition global this way.

There are other ways, of course :)

KR
Rainer

ifthenelse

by topsquark » Wed Aug 23, 2023 4:28 am

Thank you so much, both of you. I understand what's been said so far.

I have added to the code a bit. I can state my eventual goal, now that the preliminaries are out of the way. I have just one little problem left.

What I want to do is determine the quadrant of a point, whether given in coordinates or as a coordinate. I need to distinguish if I'm looking at (X) or (\x,\y), respectively. Now, from an earlier question, I've actually learned how to do this. I can create a new pair of commands: point and coords, that will take care of that. What I need to do is structure the command "quadrant" to take the form:
\quadrant{point}{X}{}

or
\quadrant{coords}{3}{2}

I've even set this up already. (See the code below.) (Note: to print out the three possibles, I've added an extra argument to \quadrant to print out a dot on the correct line.)

My problem is this. In order for the command quadrant to use either point or coords, I have to put the "if" statement inside a scope. Now, I can do anything I want inside the scope (I've currently got it printing a red dot if I'm using point and a blue dot if I'm using coords), but I need to define \x and \y depending on which option is being used. But if I'm inside the scope, I lose that information when I end the scope.

To be more precise:
I have a subroutine to use to get the x,y coordinates from X, so if I'm using point I do that.
If I'm using coords, I already have the x,y coordinates and I just set them to be \x = x and \y = y.

But I lose this information once I pass outside the scope, so the coordinates \x and \y are undefined when I try to find the quadrant. (newcommand\q{...}). I need to "hard save" the macro values \x and \y.

I know (somewhere on the net) I've seen a solution to this problem, but I don't recall where or how to do it.

Any suggestions?

Thanks!

-Dan

Code: Select all

\documentclass{article}

\usepackage{tikz}

\begin{document}

\newif\ifpoint
\tikzset{
     point/.code={\pointtrue}
}

\newif\ifcoords
\tikzset{
     coords/.code={\coordstrue}
}

\newcommand\quadrant[4]{
     \begin{scope}[#1]
          \ifpoint
               \fill[red] (0,-#4) circle(2pt);
          \fi
          \ifcoords
               \fill[blue] (0,-#4) circle(2pt);
          \fi
     \end{scope}

     \def\x{#2}
     \def\y{#3}

     \pgfmathsetmacro\q{
          \ifdim\x > 0pt
               \ifdim\y > 0pt
                    1
               \else
                    \ifdim\y < 0pt         
                         4
                    \fi
               \fi
          \else
               \ifdim\x < 0pt
                   \ifdim\y > 0pt
                        2
                   \else
                        \ifdim\y < 0pt
                             3
                        \fi
                   \fi
               \fi
          \fi
     }
}

\begin{tikzpicture}
     \quadrant{coords}{3pt}{-2pt}{0}; \node[anchor=west] at (0.5,0) {The point (3,-2) is in Quadrant \q.};
     \quadrant{point}{4pt}{1pt}{1}; \node[anchor=west] at (0.5,-1) {The point (4,1) is in Quadrant \q.};
     \quadrant{coords}{-5pt}{-1pt}{2}; \node[anchor=west] at (0.5,-2) {The point (-5,-1) is in Quadrant \q.};
\end{tikzpicture}

\end{document}

Top