Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have the following diagram I would like to convert (approximately) to tikz:

enter image description here

So far, I've succeeded at doing everything except the shading. I am a newbie to tikz and learning the best I can so please bear with me - horrible code patched up from various tutorials ahead:

\begin{tikzpicture}
\tikzstyle{mark coordinate}=[minimum size=0pt,inner sep=0,outer
 sep=0,fill=none,circle]

\coordinate[mark coordinate] (M) at ( 0,0); 
\coordinate[mark coordinate] (L) at (-4,0);
\coordinate[mark coordinate] (R) at ( 4,0);
\coordinate[mark coordinate] (N) at ( 0,4);

% Horizontal axis (surface)
\draw[solid] (L) to (R);

% Normal vector (+ label)
\draw [ultra thick,-latex,black] (M) to (N);
\node[anchor=west] (note1) at (-0.5,3.5) {$\mathbf{n}$};

 % Draw arc
 \coordinate[mark coordinate] (P) at (-4,0);
 \coordinate[mark coordinate] (Phat) at (4,0);
 \draw[solid] let \p1=(P), \p2=(Phat), \n0={0.5*veclen(\x1-\x2,\y1-
 \y2)} in
 [rotate={atan((\y1-\y2)/(\x1-\x2))}] (P) arc (180:0:\n0);

% The area delimiters
\coordinate[mark coordinate] (left) at (-0.5,0);
\coordinate[mark coordinate] (right) at (0.5,0);

% The two destination point pairs
\coordinate[mark coordinate] (left_d) at (3.696844, 1.527526);
\coordinate[mark coordinate] (right_d) at (3.813822, 1.206132);

\coordinate[mark coordinate] (left2_d) at (-2.363246, 3.227237);
\coordinate[mark coordinate] (right2_d) at (-1.613246, 3.660250);

% The parallel lines
\definecolor{darkgreen}{rgb}{0,0.5,0}
\draw[red] (left) to (left_d);
\draw[red] (right) to (right_d);
\draw[darkgreen] (left) to (left2_d);
\draw[darkgreen] (right) to (right2_d);

\end{tikzpicture}

The result is this:

enter image description here

I am unsure how to get the shading working - I have looked around but I only see examples on how to shade the area between two or more curves, however I am not using curves but geometric objects. How would I go about achieving this? And if my original code can be rewritten more elegantly to simplify shading, please go ahead!

share|improve this question

1 Answer 1

up vote 6 down vote accepted

Method 1: Approx Solution: Rectangular Fill

You can apply a fill to a path consisting of the four corners that you want to fill:

\fill [fill=green!25] (left) -- (left2_d) -- (right2_d) -- (right) -- cycle;

\fill [fill=red!25] (left) -- (left_d) -- (right_d) -- (right) -- (left) -- cycle;

This yields what looks like the desired results, but does not curve along the arc.

Method 2: Circular Fill

Instead of a rectangular fill, you could actually define the curve along the path which will certainly yield the correct results, but I think an easier method would be to use a \clip instead.

Method 3: Clip

I would recommend that you over fill the area, and clip it to the desired region. Easiest way to over fill the area is to extend the vectors from near the origin to the circular edge using a syntax such as ($(left)!1.1!(left2_d)$) to locate the point 10% past the circular arc. So before we apply the \clip the fill region looks like:

enter image description here

By adding \clip (P) arc (180:0:4) -- (Phat) -- cycle we limit all the drawing to be within the desired region and achieve:

enter image description here

I also placed the portions that needed clipping within a scope so that the clip does not affect the lines that are drawn on top of the clip path. Comment out the \begin{scope} and\end{scope}` to see what I mean.

Notes:

  • Using mark coordinate on a \coordinate does not make sense as \coordinate does not do any drawing, just locates a coordinate, so I have removed that.
  • Also, I rearranged the order of the drawing to show the things I think you wanted to be on top. An alternate way would be to use layers, but simply rearranging the drawing order suffices for many uses.
  • Nodes can be placed at the end of the path -- this is usually an easier option than placing the label manually based on coordinates. I adjust the placement of the n label yo illustrate this.
  • I am not sure exactly why this was necessary, but the horizontal line needed a tweak of 0.5\pgflinewidth on either end to get the edges to meet properly.

As far as your other request to bend the colors over the shaded region you could use opacity as Lionel MANSUY suggested, but I find it clearer if you combine opacity with some sort of pattern, which requires \usetikzlibrary{patterns}:

\fill [fill=green, pattern=crosshatch dots] 
    (left) -- ($(left)!1.1!(left2_d)$) -- 
    ($(right)!1.1!(right2_d)$) -- (right) -- cycle;

\fill [draw=none, fill=red!50, fill opacity=0.25] 
    (left) -- ($(left)!1.1!(left_d)$) -- 
    ($(right)!1.1!(right_d)$) -- (right)  -- cycle;

which yields:

enter image description here


Code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
%\tikzstyle{mark coordinate}=[minimum size=0pt,inner sep=0,outer
% sep=0,fill=none,circle]

\coordinate (M) at ( 0,0); 
\coordinate (L) at (-4,0);
\coordinate (R) at ( 4,0);
\coordinate (N) at ( 0,4);

% The area delimiters
\coordinate (left) at (-0.5,0);
\coordinate (right) at (0.5,0);

% The two destination point pairs
\coordinate (left_d) at (3.696844, 1.527526);
\coordinate (right_d) at (3.813822, 1.206132);

\coordinate (left2_d) at (-2.363246, 3.227237);
\coordinate (right2_d) at (-1.613246, 3.660250);


 % Draw arc
 \coordinate (P)    at (-4,0);
 \coordinate (Phat) at (4,0);
 \begin{scope}
    \clip  (P) arc (180:0:4) -- (Phat) -- cycle;


    \fill [fill=green!25] 
        (left) -- 
        ($(left)!1.1!(left2_d)$) -- 
        ($(right)!1.1!(right2_d)$) -- 
        (right) --
        cycle;

    \fill [draw=none, fill=red!25] 
        (left) -- 
        ($(left)!1.1!(left_d)$) -- 
        ($(right)!1.1!(right_d)$) --
        (right)   -- 
        (left) -- cycle;
 \end{scope}

 \draw [solid, ultra thick] 
        let \p1=(P), 
            \p2=(Phat), 
            \n0={0.5*veclen(\x1-\x2,\y1-\y2)} 
        in [rotate={atan((\y1-\y2)/(\x1-\x2))}] (P) arc (180:0:\n0);

% The parallel lines
 \definecolor{darkgreen}{rgb}{0,0.5,0}
 \draw[red] (left) to (left_d);
 \draw[red] (right) to (right_d);
 \draw[darkgreen] (left) to (left2_d);
 \draw[darkgreen] (right) to (right2_d);

% Horizontal axis (surface)
 \draw[solid, ultra thick] ($(L)-(0.5\pgflinewidth,0)$) -- 
    ($(R)+(0.5\pgflinewidth,0)$);

% Normal vector (+ label)
%\draw [ultra thick,-latex,black] (M) to (N);
%\node[anchor=west] (note1) at (-0.5,3.5) {$\mathbf{n}$};
\draw [ultra thick,-latex,black] (M) to (N) 
    node [below left, yshift=-7] {$\mathbf{n}$};
\end{tikzpicture}
\end{document}
share|improve this answer
    
Oh, \fill is very nice! This still misses the subtended arc but I think I can get that part on my own now that I understand the method. Thanks! Is there a way to blend the two shades at the bottom or is tikz not designed that way? (I could fill that triangle separately but just wondering) –  Thomas Nov 29 '12 at 7:09
    
@Thomas: Sorry had a phone call, updated solution should be ready in about 10 minutes. –  Peter Grill Nov 29 '12 at 7:48
    
@Thomas To blend the two shades at the bottom, you could either determine the intersection point and redraw/refill the surface with an appropriate color, or use transparency (see command \pgfsetfillopacity in the Tikz manual) –  Lionel MANSUY Nov 29 '12 at 9:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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