7

Does anyone have a macro for an "angular spring" ? I'm looking for something similar to that in pst-coil (PS-Tricks package) but the geometry of the "spring" is not straight but an arch (with eventually, variable opening).

user35737
  • 71
  • 1
  • 4
    \begin{commercial} If you consider using TikZ, you could look e.g. here. \end{commercial} –  Jan 19 '19 at 02:40

5 Answers5

11

Run with lualatex:

\documentclass{article} 
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
input metaobj
beginfig(1);
  newCircle.a(btex start etex);
  newCircle.b(btex end etex);
  a.c=origin;
  b.c-a.c=(3cm,2cm);
  drawObj(a,b);
  nccoil(a)(b) "coilwidth(3mm)", "linetension(0.8)",
               "angleA(-20)", "angleB(90)", "arrows(-)","linewidth(1pt)";
endfig;

clearObj a,b;
beginfig(2);
  newCircle.a(btex start etex);
  newCircle.b(btex end etex);
  a.c=(0cm,3cm);
  b.c=(5cm,4cm);
  drawObj(a,b);
  nccoil(a)(b) "doubleline(true)","coilwidth(3mm)","linetension(0.8)",
               "angleA(-90)", "angleB(90)", "arrows(-)","linewidth(1pt)";
endfig;
\end{mplibcode}
\end{document}

enter image description here

3

Another pstricks based solution for this problem can be achieved by using pst-solides3d and abusing the helix itself.

%&pdflatex
% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
\documentclass[a4paper, pdf, x11names]{standalone}
\usepackage{pstricks}
\usepackage{pstricks-add, auto-pst-pdf}
\usepackage{pst-solides3d}
\begin{document}
    \begin{pspicture}[solidmemory](-6.5,-3.5)(6.5,3)
    \psset{viewpoint=30 0 15 rtp2xyz,Decran=30,lightsrc=viewpoint}
    \pstVerb{/R1 5 def /R0 2 def /k 20 def /RL 0.15 def /kRL 40 def}%
    %https://tex.stackexchange.com/questions/151108/showcase-of-translations-to-asymptote-from-tikz-pstricks
    % abusing the helix to create a sprial spring-like structure
    \defFunction[algebraic]{helix}(t)
    {(R1+R0*cos(k*t))*sin(t)+RL*sin(kRL*k*t)}
    {(R1+R0*cos(k*t))*cos(t)+RL*cos(kRL*k*t)}
    {R0*sin(k*t)+RL*sin(kRL*k*t)}
    \psSolid[object=courbe,
    resolution=7800,
    fillcolor=white,incolor=black,
    r=0,
    range=-0.099 0,
    function=helix,action=none,name=Helix]%
    \psSolid[object=fusion,base=Helix]
    % start-stop circles
    \pscircle(4,-1.25){0.3}
    \pscircle(7.1,0.3){0.3}
    % texts
    \rput[c](4,-1.25){\tiny Stop}
    \rput[c](7.1,0.3){\tiny Start}
    %\put(-1,-3){$\text{multiples of 6}$}
    \end{pspicture}
\end{document}

which would give you:

enter image description here

Here one can play with the parameters in

\pstVerb{/R1 5 def /R0 2 def /k 20 def /RL 0.15 def /kRL 40 def}%

to get much more exotic variations.

3

The trivial balls at the ends are intentionally removed for the sake of simplicity.

\documentclass[pstricks,border=1cm]{standalone}
\usepackage{pst-plot}
\newcommand\circularSpring[4][]{%
    \curvepnodes[plotpoints=\numexpr#4*4+1]{#2 DegtoRad}{#3 DegtoRad}
        {(sin(#4*t)/5+2)*cos(t)|(sin(#4*t)/5+2)*sin(t)}{A}
    \psnline[linejoin=1,#1](0,\Anodecount){A}}


\begin{document}
\begin{pspicture}[showgrid](-3,-3)(3,3)
    \pscircle[linecolor=red,linestyle=dashed]{2}
    \circularSpring{45}{90}{100}
    \circularSpring{0}{-90}{200}
\end{pspicture}
\end{document}

enter image description here

Edit

Almost forgotten animation.

\documentclass[pstricks]{standalone}
\usepackage{pst-plot}
\newcommand\circularSpring[4][]{%
    \curvepnodes[plotpoints=\numexpr#4*4+1]{#2 DegtoRad}{#3 DegtoRad}
        {(sin(#4*t)/5+2)*cos(t)|(sin(#4*t)/5+2)*sin(t)}{A}
    \psnline[linejoin=1,#1](0,\Anodecount){A}}


\begin{document}
\multido{\i=0+36}{11}{%
\begin{pspicture}(-3,-3)(3,3)
    \pscircle[linecolor=red,linestyle=dashed]{2}
    \circularSpring{0}{\i}{50}
\end{pspicture}}
\end{document}

enter image description here

Note: few glitches due to incorrectly sampled points are left for your exercises.

Display Name
  • 46,933
2

[edit] Since I have been granted this bounty by "artificial" means I have decided to upcycle it please see Bountiful 2019 Questions

Not an answer but just a comment (with visual)

There are many excellent answers. (I love the marmot with a spring in the air)

However did I misread the question that what was wanted ? was it a coil with two "angles" i.e. with one flat side and one arched e.g. half of this

enter image description here

and what is meant by "variable opening" (but as OP has not been seen since posting) I guess that's moot. I'm thinking variable like this
enter image description here

  • A nice answer. You won! – Display Name Jan 23 '19 at 13:25
  • 3
    @GodMustBeCrazy I now feel double guilty (again :-) I did not even attempt an answer God must be really crazy but who am I to doubt his mysterious ways. –  Jan 23 '19 at 13:40
  • 1
    @ArtificialStupidity On checking back It was my treble inartificial stupidity to not look more closely at who awarded the bonus THANKS –  Jan 23 '19 at 17:35
0

A SkiaSharp solution just for comparison purpose. It can embed LaTeX equations as well.

using SkiaSharp;
using System.Diagnostics;
using static System.MathF;

class Diagram { const float scale = SKDocument.DefaultRasterDpi / 2.54f; // dots per cm

static float PtToCm(float pt) => pt / scale;

static readonly SKPaint blackStrokePaint = new SKPaint
{
    Style = SKPaintStyle.Stroke,
    StrokeWidth = PtToCm(0.8f),
    Color = SKColors.Black,
    StrokeCap = SKStrokeCap.Round,
    IsAntialias = true
};

static readonly SKPaint redStrokePaint = new SKPaint
{
    Style = SKPaintStyle.Stroke,
    StrokeWidth = PtToCm(0.8f),
    Color = SKColors.Red,
    StrokeCap = SKStrokeCap.Round,
    IsAntialias = true
};

static readonly SKRect domain = new SKRect(-2.5f, 2.5f, 2.5f, -2.5f);

static readonly float width = domain.Width * scale;
static readonly float height = -domain.Height * scale;

static readonly int k = 50; // wave number
static readonly int plotPoints = 4 * k + 1;
static readonly float dt = PI * 2 / (plotPoints - 1);

private static SKPoint GetPoint(int index)
{
    float t = index * dt;
    return new SKPoint
        (
            (Sin(k * t) / 5 + 2) * Cos(t),
            (Sin(k * t) / 5 + 2) * Sin(t)
        );
}

public static void Generate(string filename)
{
    using (var stream = new SKFileWStream($"{filename}.pdf"))
    using (var document = SKDocument.CreatePdf(stream))
    using (var canvas = document.BeginPage(width, height))
    {
        canvas.Scale(scale, -scale);
        canvas.Translate(-domain.Left, -domain.Top);

        canvas.DrawCircle(0, 0, 2, redStrokePaint);

        for (int i = 0; i < plotPoints - 1; i++)
            canvas.DrawLine(GetPoint(i), GetPoint(i + 1), blackStrokePaint);

        document.EndPage();
    }
}

}

class Invoker { static void Main() { string filename = "CircularSpring"; Diagram.Generate(filename);

    // convert to PNG with ImageMagick
    using (Process p = new Process())
    {
        p.StartInfo.FileName = "magick";
        p.StartInfo.Arguments = $"convert -compose copy -bordercolor red -border 2x2 -density 200 -alpha remove {filename}.pdf {filename}.png";
        p.Start();
        p.WaitForExit();
    }
}

}

enter image description here

Display Name
  • 46,933