3

I am trying to connect the origin of my picture (Black dot) and the different colored dots around it by drawing and filling arcs. As you can see in the image attached, its relatively easy to do by using "raw" tikZ and calculating by hand the different points where the arcs should start and end (I did not do it for this MWE). My question is:

Knowing the starting point (Colored),the "middle" point of the arc (Origin), and how long they should be in degrees (lets say 30 deg) is it possible to automatize the generation of these arcs using tikZ?

I would guess it implies moving the "origin" of the command arc to the straight line between the colored points and the origin, and then draw an arch from (-degrees/2 : degrees/2), but I do not know how I should implement this or whether it is possible. I would appreciate any help or guidance.

Below the MWE:

enter image description here

\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{positioning,calc}
\tikzstyle{help lines}=[thin,gray!40]

\begin{document}
    \begin{tikzpicture}
        \draw[help lines,step=1] (-3,-3) grid (3,3);
        \coordinate (Origin) at (0,0);
        
        %- Red
        \begin{scope}[thick,color=red,shift={(-3,1)}]
            \coordinate (Red) at (0,0);
            \draw[fill] (Red) circle (4pt)  node[above,yshift=0.1cm]  {Red};
            \draw[dashed] (Red) -- (Origin) node[midway,above]{$r_\mathrm{1}$};
            \fill[opacity=0.3] (0,0) -- (-10:3.5) arc (-10:-40:3.5) -- cycle;  
        \end{scope}
        
        %- Blue
        \begin{scope}[thick,color=blue,shift={(-2,-2)}]
            \coordinate (Blue) at (0,0);
            \draw[fill] (Blue) circle (4pt)  node[below,yshift=-0.1cm]  {Blue};
            \draw[dashed] (Blue) -- (Origin) node[midway,above left]{$r_\mathrm{2}$};
            \fill[opacity=0.3] (0,0) -- (25:3.3) arc (25:55:3.3) -- cycle;  
        \end{scope}
        
        %- Orange
        \begin{scope}[thick,color=orange,shift={(1,2.5)}]
            \coordinate (Orange) at (0,0);
            \draw[fill] (Orange) circle (4pt)  node[above,yshift=0.1cm]  {Orange};
            \draw[dashed] (Orange) -- (Origin) node[midway,above left]{$r_\mathrm{3}$};
            \fill[opacity=0.3] (0,0) -- (240:3) arc (240:270:3) -- cycle;  
        \end{scope}
        
        \draw[fill] (Origin) circle (4pt)  node[right,xshift=0.1cm]  {Origin};
        
    \end{tikzpicture}
\end{document}
3
  • 1
    Not sure I fully understand the question, but perhaps you are looking for something like \draw [red] (Red) -- ++(-40:3.5) arc (-40:-10:3.5) -- cycle;? Commented Feb 10, 2021 at 19:30
  • Thanks for your comment @Peter Grill, but that is very similar of what I've done, just using realive coordinates. I was thinking along the lines of creating a macro that acceptes the "Begin point", "End Point" and degrees, so the arcs will be perfectly centered regarding the origin. For instance, /drawArcArea(Red, Origin, 30) would draw a triangle starting at Red, going to - 15 deg below origin, then arc between - 15 and +15 deg and then cycle back to red.
    – Jes
    Commented Feb 10, 2021 at 19:54
  • 1
    Sounds like you just need to wrap what you have in a macro and compute the length from #1 to #2 within the \drawArcArea macro. The \veclen macro should be able to help with that. Commented Feb 10, 2021 at 20:05

3 Answers 3

1

Here is an automated solution. We define a new command \sector that takes one optional and two required arguments. The command \sector[green,opacity=0.3]{(1,2)}{(3,1)} will produce the following image (help lines added with (0,0) in the lower left):

enter image description here

The first required argument is the center point, which is (1,2) in the image. The second required argument is the point near the end of the sector (3,1). Optional tikz commands can be added if desired.

The sector extends beyond the second point by a distance of \overlen, which is set globally (3mm in the diagram). The angle of the sector is 30°, set globally as \arclen.

The three sectors in your image are created with the following code:

\sector[red,opacity=0.3]{(Red)}{(Origin)}
\sector[blue,opacity=0.3]{(Blue)}{(Origin)}
\sector[orange,opacity=0.3]{(Orange)}{(Origin)}

enter image description here

Here is the complete code. Explanation of the calculation follows.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\arclen}{30} % arc measure in degrees
\newcommand{\overlen}{.3} % length beyond second point in cm
\newcommand{\sector}[3][]{\fill[#1]
    let\p1=($#3-#2$), \n1={atan2(\y1,\x1)}, \n2={veclen(\x1,\y1)+\overlen cm}
    in #2--($#2+(\n1-.5*\arclen:\n2)$) arc (\n1-.5*\arclen:\n1+.5*\arclen:\n2)--cycle;
    }

\begin{document}

\begin{tikzpicture}
\draw[help lines,step=1] (-3,-3) grid (3,3);

\coordinate (Red) at (-3,1);
\coordinate (Blue) at (-2,-2);
\coordinate (Orange) at (1,2.5);
\coordinate (Origin) at (0,0);

\sector[red,opacity=0.3]{(Red)}{(Origin)}
\sector[blue,opacity=0.3]{(Blue)}{(Origin)}
\sector[orange,opacity=0.3]{(Orange)}{(Origin)}

\draw[fill, red] (Red) circle (4pt)  node[above,yshift=0.1cm]  {Red};
    \draw[dashed, thick, red] (Red) -- (Origin) node[midway,above]{$r_\mathrm{1}$};
    
\draw[fill, blue] (Blue) circle (4pt)  node[above,yshift=-0.1cm, below]  {Blue};
    \draw[dashed, thick, blue] (Blue) -- (Origin) node[midway,above left]{$r_\mathrm{2}$};
    
\draw[fill, orange] (Orange) circle (4pt)  node[above,yshift=0.1cm]  {Orange};
    \draw[dashed, thick, orange] (Orange) -- (Origin) node[midway,above left]{$r_\mathrm{3}$};
    
\draw[fill] (Origin) circle (4pt)  node[right,xshift=0.1cm]  {Origin};

\end{tikzpicture}

\end{document}

The function atan2 calculates the arctangent of y/x. So we calculate the "vector"

(x,y) = (terminal point)-(initial point)

so that atan2(y,x) gives us the angle of the line from the initial point to the terminal point, relative to the positive x-axis. The angle is assigned to \n1 with the let command, which also assigns \p1 the needed vector. \x1 and \y1 are automatically assigned the respective x and y coordinates. The $..$ is needed (with the calc tikzlibrary) to do calculations with coordinates.

We can then draw the sector using the angles \n1 ± 15°, and the radius calculated with veclen(\x1,\y1) + \overlen cm.

3
  • Beautiful solution, thank you! Also, the code is waay simpler than with my solution using tikzmath :D
    – Jes
    Commented Feb 11, 2021 at 21:59
  • If I want to define different angle and overlength, would it be enough using the following command? : \newcommand{\sector}[5][]{\fill[#1] let\p1=($#3-#2$), \n1={atan2(\y1,\x1)}, \n2={veclen(\x1,\y1)+#4 cm} in #2--($#2+(\n1-.5*#5:\n2)$) arc (\n1-.5*#5:\n1+.5*#5:\n2)--cycle; } and then call it using \sector[red, opacity=0.3]{(Red)} {(Origin)} {. 3}{30}?
    – Jes
    Commented Feb 11, 2021 at 22:11
  • 1
    @Jes, Yes. That works if you want different angles and lengths for each sector.
    – Sandy G
    Commented Feb 11, 2021 at 22:27
1

With tkz-euclide and the \tkzDrawSector command (you can create a macro with it too, if you feel).

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

\usepackage{tkz-euclide}

\begin{document}
    \begin{tikzpicture}
        \coordinate (A) at (0,0);
        \coordinate (B) at (20:3);
        \coordinate (C) at (50:3);
        
        \tkzDrawPoints(A,B,C)
        \tkzLabelPoints[above right](B,C)
        \tkzLabelPoints[above left](A)
        \tkzDrawSector[fill=blue,opacity=0.5](A,B)(C)
    \end{tikzpicture}
\end{document}

tkzDrawSector

2
  • Thanks for the answer, but then I still have to manually compute the different points of the arc, which is something I'd rather not do.
    – Jes
    Commented Feb 11, 2021 at 7:33
  • 1
    Sorry. It seems that I didn't understand what you needed.
    – SebGlav
    Commented Feb 11, 2021 at 17:25
0

I found a solution by combinining a macro for calculating length and angle between two points, credits are due to Alain Matthes, and tikzmath. It throws an error of the type "tikz cannot parse this coordinate", but compiles and works nevertheless (magic!).

Also, it is possible to define the width of the arc and even an extra length so it goes further from the origin. See the image below, where the arcs are defined to have 30 degree width and to be "1" longer than required :

EDIT: To work, it requires two compilations, the first one without errors. So in the first compilation, the following lines must be commented:

\fill[opacity = 0.3] (Red) -- (\angleStart:\scanRadius ) --++ arc(\angleStart:\angleEnd:\scanRadius ) -- cycle;

And finally the MWE:

\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{positioning,calc,math}
\tikzstyle{help lines}=[thin,gray!40]
%- Credits to https://tex.stackexchange.com/users/3144/alain-matthes
\makeatletter      
\newcommand{\getLengthAndAngle}[2]{%
    \pgfmathanglebetweenpoints{\pgfpointanchor{#1}{center}}
    {\pgfpointanchor{#2}{center}}
    \global\let\myangle\pgfmathresult % we need a global macro 
    \pgfpointdiff{\pgfpointanchor{#1}{center}}
    {\pgfpointanchor{#2}{center}}
    \pgf@xa=\pgf@x % no need to use a new dimen
    \pgf@ya=\pgf@y
    \pgfmathparse{veclen(\pgf@xa,\pgf@ya)/28.45274} % to convert from pt to cm   
    \global\let\mylength\pgfmathresult % we need a global macro
}
\makeatother 
%- 
\begin{document}
    \begin{tikzpicture}

        \def\scanAngle{30}; % Define angular width of beam
        \def\extraRadius{1}; % A little extra length

        %\draw[help lines,step=1] (-3,-3) grid (3,3);
        \coordinate (Origin) at (0,0);
        
        %- Red
        \begin{scope}[thick,color=red,shift={(-3,1)}]
            \coordinate (Red) at (0,0);
            \draw[fill] (Red) circle (4pt)  node[above,yshift=0.1cm]  {Red};
            \draw[dashed] (Red) -- (Origin) node[midway,above]{$r_\mathrm{1}$}; 
            \getLengthAndAngle{Red}{Origin}
            \tikzmath{
                \angleStart = \myangle-\scanAngle/2;
                \angleEnd = \myangle + \scanAngle/2;
                \scanRadius = \mylength + \extraRadius;
            };
            \fill[opacity = 0.3] (Red) -- (\angleStart:\scanRadius ) --++ arc(\angleStart:\angleEnd:\scanRadius ) -- cycle;
        \end{scope}
        
        %- Blue
        \begin{scope}[thick,color=blue,shift={(-2,-2)}]
            \coordinate (Blue) at (0,0);
            \draw[fill] (Blue) circle (4pt)  node[below,yshift=-0.1cm]  {Blue};
            \draw[dashed] (Blue) -- (Origin) node[midway,above left]{$r_\mathrm{2}$};
            \getLengthAndAngle{Blue}{Origin}
            \tikzmath{
                \angleStart = \myangle-\scanAngle/2;
                \angleEnd = \myangle + \scanAngle/2;
                \scanRadius = \mylength + \extraRadius;
            };
            \fill[opacity = 0.3] (Blue) -- (\angleStart:\scanRadius ) --++ arc(\angleStart:\angleEnd:\scanRadius ) -- cycle;
        \end{scope}
        
        %- Orange
        \begin{scope}[thick,color=orange,shift={(1,2.5)}]
            \coordinate (Orange) at (0,0);
            \draw[fill] (Orange) circle (4pt)  node[above,yshift=0.1cm]  {Orange};
            \draw[dashed] (Orange) -- (Origin) node[midway,above left]{$r_\mathrm{3}$};
            \getLengthAndAngle{Orange}{Origin}
            \tikzmath{
                \angleStart = \myangle-\scanAngle/2;
                \angleEnd = \myangle + \scanAngle/2;
                \scanRadius = \mylength + \extraRadius;
            };
            \fill[opacity = 0.3] (Orange) -- (\angleStart:\scanRadius ) --++ arc(\angleStart:\angleEnd:\scanRadius ) -- cycle;  
        \end{scope}
        
        \draw[fill] (Origin) circle (4pt)  node[right,xshift=0.1cm]  {Origin};
        
    \end{tikzpicture}
\end{document}

You must log in to answer this question.

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