4

The code generates a strain-stress curve. How can the code be simplified? How can the code be make smarter?

Can I make the Bezier curve with one draw command? \ShowintersectionB prints just the coordinates of the intersection point. I don't know how to do this without the circle (0pt) command. Can I save the coordinates of the intersection point and print them later in the text?

I took some of the code from:


\documentclass[12pt]{standalone}

\usepackage[per-mode=symbol]{siunitx}

\usepackage{pgfplots}
\pgfplotsset{compat=1.11}

\usepackage{tikz}

\usetikzlibrary{intersections}
\usetikzlibrary{calc}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{shapes.misc}

\tikzset{
  crossp/.style={
    thick,
    draw=gray,
    cross out,
    inner sep=0pt,
    outer sep=0pt,
    minimum size=2*(#1-\pgflinewidth),
  },
}

\begin{document}

\makeatletter
\newcommand\transformxdimension[1]{
\pgfmathparse{((#1/\pgfplots@x@veclength)+\pgfplots@data@scale@trafo@SHIFT@x)/10^\pgfplots@data@scale@trafo@EXPONENT@x}
}

\newcommand\transformydimension[1]{
\pgfmathparse{((#1/\pgfplots@y@veclength)+\pgfplots@data@scale@trafo@SHIFT@y)/10^\pgfplots@data@scale@trafo@EXPONENT@y}
}
\makeatother

\newcommand*{\ShowIntersectionA}{
\fill 
  [name intersections={of=Hardening and Hooke, name=i, total=\t}] 
  [red, opacity=1, every node/.style={above left, black, opacity=1}] 
  \foreach \s in {1,...,\t}{(i-\s) circle (2pt)
    node [above left] {\s}};
}

\newcommand*{\ShowIntersectionB}{
\fill
  [name intersections={of=Hardening and Hooke, name=i, total=\t}] 
  [every node/.style={below right, black, opacity=1}] 
  \foreach \s in {1,...,\t}{(i-\s) circle (0pt)
    node [below right] { 
    \pgfgetlastxy{\macrox}{\macroy}
    \transformxdimension{\macrox}
    \pgfmathprintnumber{\pgfmathresult},%
    \transformydimension{\macroy}%
    \pgfmathprintnumber{\pgfmathresult}}};
}

\begin{tikzpicture}
\begin{axis}[
    x={(2cm,0)}, 
    y={(0,0.02cm)},
    compat=newest,
    axis y line=left,
    axis x line=left,
    axis line style=
        {-{Stealth[inset=1pt, angle=30:15pt]}, very thick},
    ymin=0,     % start the diagram at this y-coordinate
    ymax=500,   % end   the diagram at this y-coordinate
    xmin = 0,
    xmax = 7,
    ylabel style={rotate=-90},
    every axis y label/.style=
     {at={(ticklabel* cs:1.02)},anchor=south,},
    ylabel=$\sigma$ in \si{\mega\pascal},
    every axis x label/.style=
         {at={(ticklabel* cs:1.02)},below left = 8pt},
    every tick/.style={thick},
    ytick={0,100,...,400},
    xtick={0,1,...,6},
    yticklabels={0,100,200,300,400},
    xlabel=$\epsilon$ in \si{\percent},
    xticklabels={0,1,...,6},
    minor y tick num={1},
    minor x tick num={4},
    tick align=outside]

\addplot[thick, domain=0:1]{300*x};

\coordinate (O) at (0,0);
\coordinate (A) at (1,300);
\coordinate (B) at (4,450);
\coordinate (C) at (6,400);
\coordinate (P) at (0.2,0);
\coordinate (Q) at ($(2,{300*(2-0.2)})$);

\draw[name path global=Hooke] (P) -- +($2*($(A)-(O)$)$);
%\draw[red, name path global=GraphCurve] (P) -- (Q);

\node[crossp=5pt,rotate=130] at (C) {};
\node[right=4pt] at (C) {Break};

%\addplot[only marks] coordinates {(3,300) (25,450) (30,400)};

%\foreach \x in {A,B,C} 
%   {\edef\temp{\noexpand\fill [red] (\x) circle (0.1cm);} \temp}; 

\draw[blue, name path global=Hardening]
    (A) .. controls +(71.5651:1.637cm) and +(180:2cm) .. (B);

\ShowIntersectionA
\ShowIntersectionB

% This is not working
%\fill[yellow,name intersections={of=Hardening and Hooke}] circle (2pt); 

\draw[green] (B) .. controls +(0:2cm) and +(130:5mm) .. (C);
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • Welcome to TeX.SX! You can have a look at our starter guide to familiarize yourself further with our format. – cfr Jan 1 '15 at 23:50
3

No doubt this could be simplified further. However, for a start:

  • combine the \ShowIntersectionsA and \ShowIntersectionsB into \ShowIntersection;
  • eliminate the definition and use of O;
  • use a label to add 'Break' rather than a second node operation;
  • don't declare 2 different, potentially conflicting, compatibility levels for pgfplots;
  • opacity=1 is default - no need for this unless you have declared a different default;
  • black is default (for most cases) so if you write fill=red rather than just red, then you don't need draw=black for all the label nodes;
  • don't define Q as you don't use it.

One good way to find out what bits do what is to add a colour to the style specification or, even, comment it out and see if stuff breaks. If you leave comments for yourself about what does what, it is easier to cut unused code when you are done.

It is, however, not easy to draw the bezier curve in one step since you want it to be in two different colours. Simplicity probably dictates leaving well alone in that case!

\documentclass[12pt,tikz,border=5pt]{standalone}

\usepackage[per-mode=symbol]{siunitx}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}


\usetikzlibrary{intersections}
\usetikzlibrary{calc}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{shapes.misc}

\tikzset{
  crossp/.style={
    thick,
    draw=gray,
    cross out,
    inner sep=0pt,
    outer sep=0pt,
    minimum size=2*(#1-\pgflinewidth),
  },
}

\begin{document}

  \makeatletter
  \newcommand\transformxdimension[1]{
    \pgfmathparse{((#1/\pgfplots@x@veclength)+\pgfplots@data@scale@trafo@SHIFT@x)/10^\pgfplots@data@scale@trafo@EXPONENT@x}
  }

  \newcommand\transformydimension[1]{
    \pgfmathparse{((#1/\pgfplots@y@veclength)+\pgfplots@data@scale@trafo@SHIFT@y)/10^\pgfplots@data@scale@trafo@EXPONENT@y}
  }
  \makeatother

  \newcommand*{\ShowIntersection}{%
    \fill
    [
      name intersections={of=Hardening and Hooke, name=i, total=\t},
      fill=red
    ]
    \foreach \s in {1,...,\t}{(i-\s) circle (2pt)
      node [above left] {\s} (i-\s) node [below right] {%
        \pgfgetlastxy{\macrox}{\macroy}
        \transformxdimension{\macrox}
        \pgfmathprintnumber{\pgfmathresult},
        \transformydimension{\macroy}
        \pgfmathprintnumber{\pgfmathresult}}};}

  \begin{tikzpicture}
    \begin{axis}[
      x={(2cm,0)},
      y={(0,0.02cm)},
      axis y line=left,
      axis x line=left,
      axis line style=
      {-{Stealth[inset=1pt, angle=30:15pt]}, very thick},
      ymin=0,     % start the diagram at this y-coordinate
      ymax=500,   % end   the diagram at this y-coordinate
      xmin = 0,
      xmax = 7,
      ylabel style={rotate=-90},
      every axis y label/.style=
      {at={(ticklabel* cs:1.02)},anchor=south,},
      ylabel=$\sigma$ in \si{\mega\pascal},
      every axis x label/.style=
      {at={(ticklabel* cs:1.02)},below left = 8pt},
      every tick/.style={thick},
      ytick={0,100,...,400},
      xtick={0,1,...,6},
      yticklabels={0,100,200,300,400},
      xlabel=$\epsilon$ in \si{\percent},
      xticklabels={0,1,...,6},
      minor y tick num={1},
      minor x tick num={4},
      tick align=outside]

      \addplot[thick, domain=0:1]{300*x};

      \coordinate (A) at (1,300);
      \coordinate (B) at (4,450);
      \coordinate (C) at (6,400);
      \coordinate (P) at (0.2,0);

      \draw[name path global=Hooke] (P) -- +($2*(A)$);

      \node[crossp=5pt, rotate=130, label=-130:{Break}] at (C) {};

      \draw[blue, name path global=Hardening]
      (A) .. controls +(71.5651:1.637cm) and +(180:2cm) .. (B);

      \ShowIntersection

      \draw[green] (B) .. controls +(0:2cm) and +(130:5mm) .. (C);
    \end{axis}
  \end{tikzpicture}

\end{document}

simpler plotting?

  • I don't need the different colours. How can I zoom the diagram? I want the epsilon from 0 to 2. But the labels sigma and epsilon still visible and no distortion of circles, ticks, ticklabels, etc. With x post scale = 2 the slopes at (1,300) differ. I know the reason for this: angle: r cm. How can this be improved? Should I change the whole approach? – Nik Jan 2 '15 at 10:13
  • @Nik That seems entirely different from your original question, unless I've just misunderstood. You have defined a maximum value for x of 7. If you don't want that, define it differently. – cfr Jan 2 '15 at 12:44
  • What the intersection concerns: thank you. When I just change xmax = 2 I get no zoom. When I change x={(4cm,0)} I get the distortion at (1,300). If I change the control points to coordinates of the axis cs I'm not sure if then I can zoom in the prescribed way. And then it is more difficult to adjust the slope. I just want the easiest way to get a curve defined by 4 points with defined slopes. (And the intersection of this curve with a straight line.) Sorry for being not very clear. – Nik Jan 2 '15 at 16:54
  • 1
    @Nik But none of that is in your question. If you think that is the same as your original question, edit it to clarify things. If you are now asking a different question, ask a new question. – cfr Jan 2 '15 at 20:04
1

First I want to mention that I totally agree with cfr's answer. That is why my answer bases on his answer.

The main change is that with the release of PGFPlots v1.16 it now is now possible to store (axis) coordinates with \pgfplotspointgetcoordinates in data point, which then can be called by \pgfkeysvalueof.

(Besides that I made some other (minor) changes to the code to improve it a bit.)

% PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage[per-mode=symbol]{siunitx}
\usepackage{pgfplots}
    \usetikzlibrary{
        arrows.meta,
        calc,
        intersections,
        shapes.misc,
    }
    \tikzset{
        crossp/.style={
            thick,
            draw=gray,
            cross out,
            inner sep=0pt,
            outer sep=0pt,
            minimum size={2*(#1-\pgflinewidth)},
        },
    }
    \pgfplotsset{compat=1.11}
    \newcommand*{\ShowIntersection}{
        \fill [
            name intersections={
                of=Hardening and Hooke,
                name=i,
                total=\t,
            },
            fill=red,
        ] \foreach \s in {1,...,\t} {
            (i-\s) circle (2pt)
            node [above left] {\s} (i-\s)
            node [below right] {
                % -------------------------------------------------------------
                % using `\pgfplotspointgetcoordinates' stores the (axis)
                % coordinates in `data point' which then can be called by
                % `\pgfkeysvalueof'
                \pgfplotspointgetcoordinates{(i-\s)}
                $\pgfmathprintnumber{\pgfkeysvalueof{/data point/x}}$,
                $\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}$
                % -------------------------------------------------------------
            }
        };
    }
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        x=2cm,      y=0.02cm,
        xmin=0,     xmax=6.99,
        ymin=0,     ymax=499,
        xlabel={$\epsilon$ in \si{\percent}},
        ylabel={$\sigma$ in \si{\mega\pascal}},
        axis lines=left,
        axis line style={
            -{Stealth[inset=1pt,angle=30:15pt]},
            very thick,
        },
        ylabel style={
            at={(ticklabel* cs:1.02)},
            anchor=south,
            rotate=-90,
        },
        xlabel style={
            at={(ticklabel* cs:1.02)},
            below left=8pt,
        },
        every tick/.style={
            thick,
        },
        xtick distance=1,
        ytick distance=100,
        minor y tick num={1},
        minor x tick num={4},
        tick align=outside,
    ]

        \addplot [thick,domain=0:1,samples=2] {300*x};

        \coordinate (A) at (1,300);
        \coordinate (B) at (4,450);
        \coordinate (C) at (6,400);
        \coordinate (P) at (0.2,0);

        \draw [name path global=Hooke] (P) -- +($2*(A)$);

        \node [crossp=5pt,rotate=40,label=-40:Break] at (C) {};

        \draw [blue, name path global=Hardening]
            (A) .. controls +(71.5651:1.637cm) and +(180:2cm) .. (B);

        \ShowIntersection

        \draw [green]
            (B) .. controls +(0:2cm) and +(130:5mm) .. (C);

    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.