0

I am trying to draw a circle at some specific coordinates defined by some simple arithmetic calculations. The reason why I am trying to do so is that eventually I would like to change the inclination of the line and compute some intersections with the background grid. Specifically I would like to draw a circle at the mid point of each segment form between the line and the background grid.

I have made the simplest possible example to reproduce the issue.

\documentclass[]{standalone}

\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{amsmath,amsthm}
\usepackage{bm}
\usepackage{bbold}
\usepackage{stmaryrd}
\usepackage{rotating}
\usepackage{graphicx,color}
\usepackage{tikz}

% .... remarks
% \theoremstyle{remark} 
% \newtheorem{remark}{\bf Remark}
\newtheorem{testcase}{\bf Test case}

% .... bar charts and plots
\usepackage{pgfplots}
\pgfplotsset{compat = 1.10}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{fit}                    
\usetikzlibrary{backgrounds}
\usetikzlibrary{patterns}

\begin{tikzpicture}
\def\Ax{0}
\def\Ay{0}
\def\Bx{20}
\def\By{20}

% mx + q
\def\Dy{\By - \Ay}
\def\Dx{\Bx - \Ax}
\def\m{(\Dy) / (\Dx) }
\def\q{\Ay -  \m*\Ax  }


\draw[black, step=4] (0,0) grid + (20,20);
\draw[very thick, black] (\Ax, \Ay) to  (\Bx, \By);

\def\ax{5}
\def\ay{\m * \ax + \q}
\draw[thin, blue, fill = blue] (\ax, \ay) circle (0.15);


\end{tikzpicture}

\end{document}

I do not understand why I receive a compilation error relative to how the coordinates of the node.

The error is the following:

Package tikz Error: Giving up on this path. Did you forget a semicolon?. \draw[thin, blue, fill = blue] (\ax, \ay)

0

3 Answers 3

0

I would simply use \pgfmathsetmacro instead of \def. Everything is going to be run through \pgfmathparse eventually (automatically), so calculate it now instead of later.

\documentclass[]{standalone}

\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{amsmath,amsthm}
\usepackage{bm}
\usepackage{bbold}
\usepackage{stmaryrd}
\usepackage{rotating}
\usepackage{graphicx,color}
\usepackage{tikz}

% .... remarks
% \theoremstyle{remark} 
% \newtheorem{remark}{\bf Remark}
\newtheorem{testcase}{\bf Test case}

% .... bar charts and plots
\usepackage{pgfplots}
\pgfplotsset{compat = 1.10}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{fit}                    
\usetikzlibrary{backgrounds}
\usetikzlibrary{patterns}

\begin{document}

\begin{tikzpicture}
\def\Ax{0}
\def\Ay{0}
\def\Bx{20}
\def\By{20}

% mx + q
\pgfmathsetmacro{\Dy}{\By - \Ay}
\pgfmathsetmacro{\Dx}{\Bx - \Ax}
\pgfmathsetmacro{\m}{\Dy / \Dx}
\pgfmathsetmacro{\q}{\Ay -  \m*\Ax}


\draw[black, step=4] (0,0) grid + (20,20);
\draw[very thick, black] (\Ax, \Ay) to  (\Bx, \By);

\def\ax{5}
\def\ay{\m * \ax + \q}
\draw[thin, blue, fill = blue] (\ax, \ay) circle (0.15);

\end{tikzpicture}

\end{document}
2

While I agree with Andrew that these \defs are not necessarily good practice, I regret (and I really mean regret) to disagree with the main statement that TikZ isn't able to parse these. It absolutely is. You only need to add braces since otherwise the parser gets confused by the parentheses. (Internally the pgf keys are also just macros, so obviously TikZ is able to parse macros.)

\documentclass[tikz,border=3mm]{standalone}
\begin{document}
\begin{tikzpicture}
\def\Ax{0}
\def\Ay{0}
\def\Bx{20}
\def\By{20}

% mx + q
\def\Dy{\By - \Ay}
\def\Dx{\Bx - \Ax}
\def\m{(\Dy) / (\Dx) }
\def\q{\Ay -  \m*\Ax  }
\draw[black, step=4] (0,0) grid + (20,20);
\draw[very thick, black] ({\Ax}, {\Ay}) to  ({\Bx}, {\By});
\def\ax{5}
\def\ay{\m * \ax + \q}
\draw[thin, blue, fill = blue] ({\ax},{\ay}) circle (0.15);
\end{tikzpicture}
\end{document}

enter image description here

With regards to best practices, like Andrew I do like pgf keys a lot, but one can also just declare functions. (A constant is a valid function, too.)

\documentclass[tikz,border=3mm]{standalone}
\begin{document}
\begin{tikzpicture}[declare function={Ax=0;Ay=0;Bx=20;By=20;
    Dy=By-Ay;Dx=Bx-Ax;m=Dy/Dx;q=Ay-m*Ax;ax=5;ay=m*ax+q;}]
\draw[black, step=4] (0,0) grid + (20,20);
\draw[very thick, black] (Ax, Ay) to  (Bx,By);
\draw[thin, blue, fill = blue] (ax,ay) circle[radius=0.15];
\end{tikzpicture}
\end{document}
2
  • 1
    @ Schrödinger's cat I like declare function. Commented Apr 28, 2020 at 3:38
  • +1 Very nice! I need to read up on how these functions work.
    – user30471
    Commented Apr 28, 2020 at 5:19
1

The main issue is that tikz is not able to work with the expressions that \ax and \ay expand to. [Actually, this is not quite right. See Schrödinger's cat's answer.] For example, you have:

ay=0-20/20-0+5+20-0-20/20-0*0

What you need to do is force these expressions to be evaluated. I recommend using pgfkeys to store and process your variables. To set this up looks like a mouthful when you first see it, but the syntax is not so complicated once you have read through it.

\newcommand\Var[1]{\pgfkeysvalueof{/Variables/#1}}
\newcommand\SetVar[1]{\pgfkeys{/Variables, #1, Calc}}
\tikzset{/Variables/.is family, /Variables,
  Ax/.initial=0,
  Ay/.initial=0,
  Bx/.initial=20,
  By/.initial=20,
  Dx/.initial=20,
  Dy/.initial=20,
  ax/.initial=5,
  ay/.initial=5,
  m/.initial=1,
  q/.initial=0,
  Calc/.style = {
      Dx=\the\numexpr\Var{Bx}-\Var{Ax}\relax,
      Dy=\the\numexpr\Var{By}-\Var{Ay}\relax,
      m=\the\numexpr\Var{Dy}/\Var{Dx}\relax,
      q=\the\numexpr\Var{Ay}-\Var{m}*\Var{Ax}\relax,
      ay=\the\numexpr\Var{m}+\Var{ax}+\Var{q}\relax
  }
}

From the point of view of your problem the most important point is the use of \numexpr to evaluate the expressions. What the rest of the code does is, first, initialise the variables Ax,Ay, Bx, By, Dx, Dy, ax, ay, m and q and it defines a Calc method that calculates Dx, Dy, m and q from the current values of Ax,Ay, Bx, By, ax anday. Finally, there are two helper macros, \Var for accessing the current values of the variables and \SetVar for setting new values -- and automatically applying Calc to recalulate the remaining values.

Putting this together the code below produces:

enter image description here

Here is the full code:

\documentclass[]{standalone}

\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{amsmath,amsthm}
\usepackage{bm}
\usepackage{bbold}
\usepackage{stmaryrd}
\usepackage{rotating}
\usepackage{graphicx,color}
\usepackage{tikz}

% .... remarks
% \theoremstyle{remark}
% \newtheorem{remark}{\bf Remark}
\newtheorem{testcase}{\bf Test case}

% .... bar charts and plots
\usepackage{pgfplots}
\pgfplotsset{compat = 1.10}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{fit}
\usetikzlibrary{backgrounds}
\usetikzlibrary{patterns}

\newcommand\Var[1]{\pgfkeysvalueof{/Variables/#1}}
\newcommand\SetVar[1]{\pgfkeys{/Variables, #1, Calc}}
\tikzset{/Variables/.is family, /Variables,
  Ax/.initial=0,
  Ay/.initial=0,
  Bx/.initial=20,
  By/.initial=20,
  Dx/.initial=20,
  Dy/.initial=20,
  ax/.initial=5,
  ay/.initial=5,
  m/.initial=1,
  q/.initial=0,
  Calc/.style = {
      Dx=\the\numexpr\Var{Bx}-\Var{Ax}\relax,
      Dy=\the\numexpr\Var{By}-\Var{Ay}\relax,
      m=\the\numexpr\Var{Dy}/\Var{Dx}\relax,
      q=\the\numexpr\Var{Ay}-\Var{m}*\Var{Ax}\relax,
      ay=\the\numexpr\Var{m}+\Var{ax}+\Var{q}\relax
  }
}

\begin{document}

  \begin{tikzpicture}

    \draw[black, step=4] (0,0) grid + (20,20);

    % default
    \draw[very thick, black] (\Var{Ax}, \Var{Ay}) to  (\Var{Bx}, \Var{By});
    \draw[thin, blue, fill = blue] (\Var{ax}, \Var{ay}) circle (0.15);

    \SetVar{Ax=4,Ay=16, Bx=16, By=4}
    \draw[very thick, black] (\Var{Ax}, \Var{Ay}) to  (\Var{Bx}, \Var{By});
    \draw[thin, blue, fill = blue] (\Var{ax}, \Var{ay}) circle (0.15);

  \end{tikzpicture}

\end{document}

I'm not sure that I understand where you want the blue dots but both dots are in accordance with your calculations.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .