TransWikia.com

Painting the outline of a circle

TeX - LaTeX Asked on December 17, 2021

How can I paint the outline of the circle? Like this:

enter image description here

MWE:

documentclass{article}
usepackage{tikz}

defMD{%
begin{tikzpicture}
    draw[text=white,font=Largesffamily,draw=none,fill={rgb:red,54;green,58;blue,142}] (0,0) circle[radius=.8cm] node {MD};
end{tikzpicture}
}

begin{document}
Test: MD
end{document}

3 Answers

I can't resist using the beautiful decoration created by @Circumscribe here to paint (like a real artist) the outline of your circle.

New colouring: Painting the background colour with the brush

circumscribe brush

Just replace the MD command in the previous example to get a figure that looks like it (each painting is unique because the plots are random with the circumscribe decoration)

defMD{%
begin{tikzpicture}
definecolor{yourcolor}{RGB}{54,58,142}
begin{scope}
    clip (0,0) circle[radius=.8cm];
   path[brush={color 1=orange,
              color 2=orange!90!yourcolor!50!yellow,  
            hair amplitude=.5pt,
            hair thickness=1pt,
              thickness=4mm,        %% <- make the circle 
              max overshoot=.5mm,   %% <- positive overshoot
             }] (0,0)circle [radius=.7cm];
end{scope}
% draw (0,0) circle[radius=.8cm];
% draw (0,0) circle[radius=.6cm];
begin{scope}
  %% Background:
  clip (0,0) circle[radius=.6cm];
  path[brush={color 1=yourcolor!90!orange!90!black,
               color 2=yourcolor!70,
               thickness=1.5cm,
               hair amplitude=2.5pt,
               min period=50pt,
               max period=100pt,
               hair thickness=1.5pt,
               hair separation=.5pt,
                % max overshoot=0pt,
              }] (-.8,0) to[out=10,in=190,looseness=1] (.8,0);
end{scope}
node [text=white,font=Largesffamily]at(0,0) {MD};

end{tikzpicture}
}

First version painting the perimeter of the circle only

Circumscribe brush

documentclass[tikz,margin=10pt]{standalone}
usetikzlibrary{decorations.pathreplacing}

makeatletter %% <- make @ usable in macro names
pgfkeys{/pgf/decoration/brush/.cd,
         thickness/.initial      = 10pt,     %% <- total brush stroke width
         hair separation/.initial= .3pt,     %% <- avg. distance between hairs on the brush
         hair thickness/.initial = .4pt,     %% <- min. thickness of the individual hairs
         hair amplitude/.initial =.25pt,     %% <- amplitude of hair thickness oscillation
         min period/.initial     = 9pt,      %% <- min. value for the period of both oscillations
         max period/.initial     = 18pt,     %% <- max. value for the period of both oscillations
         period/.style           = {min period=#1,max period=#1},
         max overshoot/.initial  = 3pt,      %% <- max. distance hairs can overshoot at the end
         color 1/.initial        = red!90!black, %% <- primary colour
         color 2/.initial        = br@color1!80!black, %% <- secondary colour (slightly darker by default)
         color/.style            = {color 1=#1,color 2=br@color1!80!black}, %% color
         hair color/.initial     = black,    %% <- only used internally
         hair offset/.initial    = 0pt,      %% <- only used internally
}

%% Some fixed-point arithmetic operations using lengths
%% (N.B. both input and output are dimension registers but should be thought of as numbers)
newcommand*fpdivide[2]{%
  dimexprnumexpr #1*65536/#2relax sprelax
}

%% Human readable names for the dimensions used in qsplitbezier:
defbr@bezFrstAx {dimen0} defbr@bezFrstBx{ dimen2} defbr@bezFrstCx{dimen4}
defbr@bezFrstAy {dimen6} defbr@bezFrstBy {dimen8} defbr@bezFrstCy{dimen10}
defbr@bezScndAx{dimen12} defbr@bezScndBx{dimen14} defbr@bezThrdx {dimen16}
defbr@bezScndAy{dimen18} defbr@bezScndBy{dimen20} defbr@bezThrdy {dimen22}
newififfirstcomponent
%% Split up a Bézier curve with control points #2, #3, #4 and #5 at #1:
%%   (#1 is normally a parametric length between 0 and 1, but extrapolation is also possible)
newcommand*qsplitbezier[5]{begingroupedefx{endgroupnoexpandqsplitbezier@{#1}#2#3#4#5noexpandqsplitbezier@}x}
defqsplitbezier@#1(#2,#3)(#4,#5)(#6,#7)(#8,#9)qsplitbezier@{%
  begingroup
    edefs{#1}%
    %% Allow extrapolation but prevent numerical overflows:
    ifdims pt>9pt defs{9}fi
    ifdims pt<-8pt defs{-8}fi
    edeft{strip@ptdimexpr 1pt-s pt}%
    %% Linear curves:
    br@bezFrstAx=dimexprtdimexpr#2relax+sdimexpr#4relax
    br@bezFrstAy=dimexprtdimexpr#3relax+sdimexpr#5relax
    br@bezFrstBx=dimexprtdimexpr#4relax+sdimexpr#6relax
    br@bezFrstBy=dimexprtdimexpr#5relax+sdimexpr#7relax
    br@bezFrstCx=dimexprtdimexpr#6relax+sdimexpr#8relax
    br@bezFrstCy=dimexprtdimexpr#7relax+sdimexpr#9relax
    %% Quadratic curves:
    br@bezScndAx=dimexprtbr@bezFrstAx+sbr@bezFrstBxrelax
    br@bezScndAy=dimexprtbr@bezFrstAy+sbr@bezFrstByrelax
    br@bezScndBx=dimexprtbr@bezFrstBx+sbr@bezFrstCxrelax
    br@bezScndBy=dimexprtbr@bezFrstBy+sbr@bezFrstCyrelax
    %% Cubic curve:
    br@bezThrdx=dimexprtbr@bezScndAx+sbr@bezScndBxrelax
    br@bezThrdy=dimexprtbr@bezScndAy+sbr@bezScndByrelax
    %% Store output in macros:
    edefx{endgroup %% <-- perform assignments outside the group
      defnoexpandbezOneStart{#2,#3}%
      defnoexpandbezOneControlA{thebr@bezFrstAx,thebr@bezFrstAy}%
      defnoexpandbezOneControlB{thebr@bezScndAx,thebr@bezScndAy}%
      defnoexpandbezOneEnd{thebr@bezThrdx,thebr@bezThrdy}%
      defnoexpandbezTwoStart{thebr@bezThrdx,thebr@bezThrdy}%
      defnoexpandbezTwoControlA{thebr@bezScndBx,thebr@bezScndBy}%
      defnoexpandbezTwoControlB{thebr@bezFrstCx,thebr@bezFrstCy}%
      defnoexpandbezTwoEnd{#8,#9}%
    }x
}
%% Split up straight lines (so we can turn them into Bézier curves)
newcommand*splitstraighttwice[4]{begingroupedefx{endgroupnoexpandsplitstraight@{#1}#2#3noexpand#4noexpandsplitstraight@}x}
defsplitstraight@#1(#2,#3)(#4,#5)#6splitstraight@{%
  begingroup
    pgfmathsetmacrot{#1}%
    pgfpointlineattime{t}{pgfpoint{#2}{#3}}{pgfpoint{#4}{#5}}%
    edef#6{thepgf@x,thepgf@y}%
    pgfmath@smuggleone#6%
   endgroup
}
%% Orthogonal translation of the endpoints of a Bézier curve
newcommand*shiftbezier[6]{%
  begingroupedefx{endgroup
    %% Translate starting point
    unexpanded{shiftbezier@{dimexpr#1relax}}#3#4unexpanded{bezOneStartbezOneControlAshiftbezier@}%
    %% Translate end point
    unexpanded{shiftbezier@{dimexpr#2relax}}#5#6unexpanded{bezOneControlBbezOneEndshiftbezier@}%
  }x
}
defshiftbezier@#1(#2,#3)(#4,#5)#6#7shiftbezier@{%
  %% This method is faster than pgfpointnormalise + pgfpointscale
  begingroup
    %% Determine the angle with the positive x-axis:
    @nameuse{pgfmathatan2@}{strip@ptdimexpr#5-#3relax}{strip@ptdimexpr#4-#2relax}%
    %% Construct a vector of length #1 in the same direction:
    letpgf@tmppgfmathresult
    pgfmathcos@{pgf@tmp}%
    pgf@x=pgfmathresultdimexpr#1relax
    pgfmathsin@{pgf@tmp}%
    pgf@y=pgfmathresultdimexpr#1relax
    %% Add a 90 degree rotated version of it to (#2,#3) and (#4,#5) and store in #6 resp. #7:
  edefx{endgroup %% <-- perform assignments outside the group
    defnoexpand#6{thedimexpr#2-pgf@y,thedimexpr#3+pgf@x}%
    defnoexpand#7{thedimexpr#4-pgf@y,thedimexpr#5+pgf@x}%
  }x
}

%% The brush hair decoration code, separated to avoid code duplication
newcommand*br@haircurvetocode{%
  %%%%%%%%%%%%
  %% Setup: %%
  %%%%%%%%%%%%
  color{pgfkeysvalueof{/pgf/decoration/brush/hair color}}
  pgfsys@setlinewidth{br@hairwidth}
  edefbr@hairoffset{pgfkeysvalueof{/pgf/decoration/brush/hair offset}}
  pgfmathrandom{2}
  edefbr@hairamplitude{thedimexprbr@amplitude*(pgfmathresult*2-3)}
  edefbr@period@var{thedimexprbr@period@max-br@period@min}

  ifdimpgfdecoratedcompleteddistance<1pt %% <-- start of curve?
    %% Set the length of the first segment:
    pgfmathrnd
    edefbr@segmlength{thedimexprbr@period@min+pgfmathresultdimexprbr@period@var}
    %% Use a random initial phase for the thickness oscillation:
    pgfmathrnd
    edefbr@segmoffset{thedimexprpgfmathresultdimexprbr@segmlength}
    %% Introcude a random overshoot at the start:
    pgfmathrnd
    edefbr@extension@pre{thedimexprpgfmathresultdimexprbr@overshoot}
  else                                    %% <-- not start of curve?
    %% Set appropriate values for non-initial segments:
    letbr@segmoffsetbr@segmoffset@stored
    letbr@segmlengthbr@segmlength@stored
    letbr@hairamplitudebr@hairamplitude@stored
    defbr@extension@pre{0pt}
  fi
  ifdimdimexprpgfdecoratedremainingdistance-pgfdecoratedinputsegmentlength<1pt %% <-- end of segment?
    %% Introduce a random overshoot at the end:
    pgfmathrnd
    edefbr@extension@post{thedimexprpgfmathresultdimexprbr@overshoot}
  else
    defbr@extension@post{0pt}
  fi

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %% Extrapolate by br@segmoffset at the start: %%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  %% Make the first subsegment long enough to fit half a period:
  edefbr@placetosplit{strip@ptfpdivide{-dimexprbr@segmoffsetrelax}{dimexprpgfdecoratedinputsegmentlengthrelax}}
  qsplitbezier{br@placetosplit} {(tikzinputsegmentfirst)}    {(tikzinputsegmentsupporta)}
                                  {(tikzinputsegmentsupportb)} {(tikzinputsegmentlast)}
  %% Adjust the remaining length:
  edefbr@remaininglength{thedimexprpgfdecoratedinputsegmentlength+br@segmoffset}
  %% Then reduce br@segmoffset so that slightly less will be cut off later:
  ifdimbr@extension@pre=0ptelse
    edefbr@segmoffset{thedimexprbr@segmoffset-br@extension@pre}
  fi

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %% Loop until we've drawn the entire segment %%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  loop
    %% Split up the Bézier curve to isolate the first subsegment:
    edefbr@placetosplit{strip@ptfpdivide{dimexprbr@segmlengthrelax}{dimexprbr@remaininglengthrelax}}
    qsplitbezier{br@placetosplit} {(bezTwoStart)}    {(bezTwoControlA)}
                                    {(bezTwoControlB)} {(bezTwoEnd)}
    %% Draw the central part of the hair:
    br@haircurvetocode@{br@hairoffset}{br@hairoffset}
    %% Draw the oscillating part of the hair:
    edefbr@hairoffset@first{thedimexprbr@hairoffset+br@hairamplitude}
    edefbr@hairoffset@second{thedimexprbr@hairoffset-br@hairamplitude}
    br@haircurvetocode@{br@hairoffset@first}{br@hairoffset@second}

  %% Test if the loop should be continued:
  ifdimbr@remaininglength>br@segmlength
    %% Adjust the remaining length:
    edefbr@remaininglength{thedimexprbr@remaininglength-br@segmlength}
    %% Ensure that the next subsegment starts from the beginning:
    defbr@segmoffset{0pt}
    %% Flip the hair amplitude:
    edefbr@hairamplitude{thedimexpr-br@hairamplitude}
    %% Set the length of the next subsegment: (maybe a little gratuitous?)
    pgfmathrnd
    edefbr@segmlength{thedimexprpgfmathresultdimexprbr@period@varrelax+br@period@min}
  %% And repeat:
  repeat
  %% Store values to be used  by the next subsegment:
  globalletbr@segmoffset@storedbr@remaininglength
  globalletbr@segmlength@storedbr@segmlength
  globalletbr@hairamplitude@storedbr@hairamplitude
}

%% Separated the code that performs draws the segments to avoid code duplication:
newcommand*br@haircurvetocode@[2]{
  begingroup
    %% Translate the curve's endpoints by #1 at one end and by #2 on the other:
    shiftbezier{#1}{#2} {(bezOneStart)} {(bezOneControlA)} {(bezOneControlB)} {(bezOneEnd)}
    %% Throw away a bit at the start if this is the first segment:
    ifdimbr@segmoffset=0ptelse
      edefbr@placetosplit{strip@ptfpdivide{dimexprbr@segmoffsetrelax}{dimexprbr@segmlengthrelax}}
      qsplitbezier{br@placetosplit} {(bezOneStart)}    {(bezOneControlA)}
                                      {(bezOneControlB)} {(bezOneEnd)}
      letbezOneStartbezTwoStart
      letbezOneEndbezTwoEnd
      letbezOneControlAbezTwoControlA
      letbezOneControlBbezTwoControlB
      edefbr@segmlength{thedimexprbr@segmlength-br@segmoffset}
      edefbr@remaininglength{thedimexprbr@remaininglength-br@segmoffset}
    fi
    %% Throw away a bit at the end if this is the last segment:
    ifdimbr@segmlength>br@remaininglength
      edefbr@placetosplit{strip@ptfpdivide{dimexprbr@remaininglength+br@extension@postrelax}{dimexprbr@segmlengthrelax}}
      qsplitbezier{br@placetosplit} {(bezOneStart)}    {(bezOneControlA)}
                                      {(bezOneControlB)} {(bezOneEnd)}
    fi
    %% Draw the subsegment:
    pgfpathmoveto{br@pairtopgfpoint{bezOneStart}}
    pgfpathcurveto{br@pairtopgfpoint{bezOneControlA}}
                   {br@pairtopgfpoint{bezOneControlB}}
                   {br@pairtopgfpoint{bezOneEnd}}
    pgfsetroundcap
    pgfusepathqstroke
  endgroup
}
defbr@pairtopgfpoint#1{expandafterbr@pairtopgfpoint@#1br@pairtopgfpoint@}
defbr@pairtopgfpoint@#1,#2br@pairtopgfpoint@{pgfpoint{#1}{#2}}

%% Define the brush and brush hair styles
tikzset{
  brush hair@internal/.style={
    decorate,
    decoration={
      show path construction,
      curveto code={
        br@haircurvetocode
      },
      lineto code={
        %% Turn this straight line into a Bézier curves and draw those
        splitstraighttwice{0.333333}{(tikzinputsegmentfirst)}{(tikzinputsegmentlast)}tikzinputsegmentsupporta
        splitstraighttwice{0.666667}{(tikzinputsegmentfirst)}{(tikzinputsegmentlast)}tikzinputsegmentsupportb
        br@haircurvetocode
      },
      closepath code={
        ifdimpgfdecoratedremainingdistance<1ptelse %% <-- don't do anything if there is no distance to cover
          %% Turn this straight line into a Bézier curve and draw that
          splitstraighttwice{0.333333}{(tikzinputsegmentfirst)}{(tikzinputsegmentlast)}tikzinputsegmentsupporta
          splitstraighttwice{0.666667}{(tikzinputsegmentfirst)}{(tikzinputsegmentlast)}tikzinputsegmentsupportb
          br@haircurvetocode
        fi
      }
    }
  },
  brush/.code={
    %% Retrieve key values:
    pgfqkeys{/pgf/decoration/brush}{#1}
    colorlet{br@color1}{pgfkeysvalueof{/pgf/decoration/brush/color 1}}
    colorlet{br@color2}{pgfkeysvalueof{/pgf/decoration/brush/color 2}}
    pgfmathsetlength{@tempdima}{pgfkeysvalueof{/pgf/decoration/brush/hair separation}}
    pgfmathsetcount{@tempcnta}{pgfkeysvalueof{/pgf/decoration/brush/thickness}/the@tempdima}
    pgfmathsetlengthmacro{br@amplitude}{pgfkeysvalueof{/pgf/decoration/brush/hair amplitude}}
    pgfmathsetlengthmacro{br@period@min}{pgfkeysvalueof{/pgf/decoration/brush/min period}}
    pgfmathsetlengthmacro{br@period@max}{pgfkeysvalueof{/pgf/decoration/brush/max period}}
    pgfmathsetlengthmacro{br@overshoot}{pgfkeysvalueof{/pgf/decoration/brush/max overshoot}}
    pgfmathsetlengthmacro{br@hairwidth}{pgfkeysvalueof{/pgf/decoration/brush/hair thickness}}
    %% Draw brush stroke:
    loop
      %% Randomise colour mixing:
      pgfmathrandom{1,100}
      begingroupedefx{endgroup
        noexpandtikzset{postaction={
          brush hair@internal,
          /pgf/decoration/brush/hair color=br@color1!pgfmathresult!br@color2,
          /pgf/decoration/brush/hair offset=thedimexpr.5@tempdima*@tempcnta},
        }
      }x
      %% Abort after a central hair is drawn:
      ifnum@tempcnta=0
        @tempcnta=-1
      fi
      %% Decrement @tempcnta every other iteration:
      ifdim@tempdima>0ptelse
        advance@tempcnta by -2
      fi
      %% Flip the sign of the offset:
      @tempdima=-@tempdima
    ifnum@tempcnta>-1repeat
  }
}
makeatother


defMD{%
begin{tikzpicture}
    path[text=white,font=Largesffamily,fill={rgb:red,54;green,58;blue,142},
    brush={color 1=orange!70!yellow,         %% <- orange
               color 2=orange!70!red!95!black,    
               thickness=6.7pt,        %% <- make the circle thinner
               max overshoot=-1.5mm,   %% <- negative overshoot = undershoot
              }] (0,0)node {MD} (.8,0) arc [start angle=0,delta angle=370,radius=.8cm] ;
end{tikzpicture}
}



begin{document}
MD
end{document}

Answered by AndréC on December 17, 2021

If I understood you right, this should do the trick:

documentclass{standalone}
usepackage{tikz}

begin{document} 
begin{tikzpicture}

    draw[draw=none,fill=blue,text=white,font=Largesffamily] circle[radius=1.1cm] node{MD};
    draw[white] circle[radius=1cm];

end{tikzpicture}
end{document}

enter image description here

Answered by Cube on December 17, 2021

Just set the draw color to whatever color you want it, e.g. orange:

documentclass{article}
usepackage{tikz}

defMD{%
    begin{tikzpicture}
    draw[text=white,font=Largesffamily,draw=orange,line width=1mm,fill={rgb:red,54;green,58;blue,142}] (0,0) circle[radius=.8cm] node {MD};
    end{tikzpicture}
}

begin{document}
    Test: MD
end{document}

The additional line width=1mm determines how thick the line is, alternatively thick, thin and some other styles are available.

The result:

enter image description here

Answered by TobiBS on December 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP