well, this will not be a short answer. In fact, it will be a very long answer, but will solve the problems of this type in a generic way. Here are some examples of what you can do with this proposal.
![Exemplo 2](https://i.stack.imgur.com/8N1xd.png)
Libraries and packages
We used a feature of tikz called decorations.markings
to recreate the path with nodes. Below is the statement:
\tikzset{
split/.style = {
, name path = #1
, /utils/exec={\setcounter{cnt}{0}}
, postaction = {
, decorate
, decoration={
markings
, mark = between positions 0 and 1 step 2pt with {
\node [
circle
, minimum size = 0pt
, inner sep = .2pt
, /utils/exec={\stepcounter{cnt} \setpointsof{#1}{\thecnt}}
] (#1-\thecnt) {};
}
}
}
}
}
We also use the library intersections
to find the points of intersection between paths.
Furthermore, we use the package etoolbox
that provides the means to store values in a very specific and also features flow control (if
, while
, etc.).
Macros
First I will explain the macros.
The next two macros store and retrieve the number of points of intersection between two paths.
% #1: path 1
% #2: path 2
% #3: intersect points
\newcommand{\setintersectpointsof}[3]{\csxdef{intersectpointsof#1and#2}{#3}}
% #1: path 1
% #2: path 2
\newcommand{\getintersectpointsof}[2]{\csuse{intersectpointsof#1and#2}}
The next two macros store and retrieve the number of points of a path.
% #1: path
\newcommand{\pointsof}[1]{\csuse{pointsof#1}}
% #1: path
% #2: intersect points
\newcommand{\setpointsof}[2]{\csnumgdef{pointsof#1}{#2}}
The next two macros store and retrieve values related to indexed variables. Something close to the vectors in programming.
% #1: name of path
% #2: name of the paths
% #3: index of the data
% #4: data
\newcommand\setstorageof[4]{\csnumgdef{#1in#2#3}{#4}}
% #1: name of the path
% #1: name of the paths
% #2: index of the data
\newcommand\getstorageof[3]{\csuse{#1in#2#3}}
The next macro identifies the intersection points in each path. Therefore, it is also used a margin of error for fine tuning.
% #1: first path
% #2: second path
% #3: margin of error
\newcommand{\getintersectionsof}[3]{
\path [
name intersections = {of = #1 and #2, name = j, total=\t, sort by = #1}
, /utils/exec = {\xdef\total{\t}}
];
\setintersectpointsof{#1}{#2}{\total}
\pgfmathsetlengthmacro{\marginoferror}{#3}
\foreach \q in {1, ..., \getintersectpointsof{#1}{#2}} {
\pgfextractx{\xref}{\pgfpointanchor{j-\q}{center}}
\pgfextracty{\yref}{\pgfpointanchor{j-\q}{center}}
\foreach \p in {#1, #2} {
\foreach \r in {1, ..., \pointsof{\p}}{
\pgfextractx{\xone}{\pgfpointanchor{\p-\r}{center}}
\pgfextracty{\yone}{\pgfpointanchor{\p-\r}{center}}
\ifboolexpr{
test {\ifdimless{\xref - \marginoferror}{\xone}} and test {\ifdimless{\xone}{\xref + \marginoferror}}
and
test {\ifdimless{\yref - \marginoferror}{\yone}} and test {\ifdimless{\yone}{\yref + \marginoferror}}
}{
\setstorageof{\p}{#1#2}{\q}{\r}
}{
}
}
}
}
}
The next two macros build the paths taken between intersections. Can be made directly or reverse with respect to the recreation paths made by the markings
.
% #1: working path
% #2: first element
% #3: last element
% #4: resulting path
% #5: next position of resulting path
\newcommand{\constructreversepath}[5]{
\pgfmathtruncatemacro{\k}{#2}
\csedef{#4}{};
\unlessboolexpr{test{\ifnumequal{\k}{#3}}}{
\stepcounter{innercnt}
\node (#4-\theinnercnt) at (#1-\k.center) {};
\csxdef{#4}{\csuse{#4} (#4-\theinnercnt)};
\pgfmathtruncatemacro{\k}{\k - 1}
\ifnumless{\k}{1}{
\pgfmathtruncatemacro{\k}{\pointsof{#1} - \k}
}{
\ifnumgreater{\k}{\pointsof{#1}}{
\pgfmathtruncatemacro{\k}{\k - \pointsof{#1}}
}{
}
}
}
\stepcounter{innercnt}
\node (#4-\theinnercnt) at (#1-\k.center) {};
\csedef{#4}{\csuse{#4} (#4-\theinnercnt)};
}
% #1: working path
% #2: first element
% #3: last element
% #4: resulting path
% #5: next position of resulting path
\newcommand{\constructdirectpath}[5]{
\pgfmathtruncatemacro{\k}{#2}
\csedef{#4}{};
\unlessboolexpr{test{\ifnumequal{\k}{#3}}}{
\stepcounter{innercnt}
\node (#4-\theinnercnt) at (#1-\k.center) {};
\csxdef{#4}{\csuse{#4} (#4-\theinnercnt)};
\pgfmathtruncatemacro{\k}{\k + 1}
\ifnumless{\k}{1}{
\pgfmathtruncatemacro{\k}{\pointsof{#1} - \i}
}{
\ifnumgreater{\k}{\pointsof{#1}}{
\pgfmathtruncatemacro{\k}{\k - \pointsof{#1}}
}{
}
}
}
\stepcounter{innercnt}
\node (#4-\theinnercnt) at (#1-\k.center){};
\csedef{#4}{\csuse{#4} (#4-\theinnercnt)};
}
And the next macro creates macros that store the full path between two points of intersection using the two previous macros according to the input option (direct or reverse).
% #1: first path
% #2: direct or reverse first path
% #3: second path
% #4: direct or reverse second path
% #5: index of first point
% #6: index of second point
% #7: name of resulting path
\newcommand{\constructpath}[7]{
\setcounter{innercnt}{0}
\pgfmathtruncatemacro{\indexone}{\getstorageof{#1}{#1#3}{#5}}
\pgfmathtruncatemacro{\indextwo}{\getstorageof{#1}{#1#3}{#6}}
\ifstrequal{#2}{direct}{
\constructdirectpath{#1}{\indexone}{\indextwo}{#7}{\theinnercnt}
}{
\constructreversepath{#1}{\indexone}{\indextwo}{#7}{\theinnercnt}
}
\pgfmathtruncatemacro{\indexone}{\getstorageof{#3}{#1#3}{#5}}
\pgfmathtruncatemacro{\indextwo}{\getstorageof{#3}{#1#3}{#6}}
\ifstrequal{#4}{direct}{
\constructdirectpath{#3}{\indextwo}{\indexone}{#7}{\theinnercnt}
}{
\constructreversepath{#3}{\indextwo}{\indexone}{#7}{\theinnercnt}
}
\setpointsof{#7}{\theinnercnt}
\csxdef{#7}{}
\foreach \k in {1, ..., \theinnercnt}{
\csxdef{#7}{\csuse{#7} (#7-\k)}
}
}
And that's it. Below I show, step by step, how to implement the proposed solution to the problem.
Structure
Let us begin making clear the basic structure of the document with packages, libraries, variables and counters. All subsequent changes will be made within the environment tikzpicture
.
\documentclass{standalone}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{intersections}
\usetikzlibrary{shapes.geometric}
\newcounter{cnt}
\newcounter{innercnt}
\newdimen\xone
\newdimen\yone
\newdimen\xref
\newdimen\yref
%
% here you must put the tikzset and macros.
%
\begin{document}
\begin{tikzpicture}
%
% here you must put all subsequent code
%
\end{tikzpicture}
\end{document}
Step by step
First let's create the three ellipses that form the basis of our paths
.
\path node [ellipse, split = path01, minimum width = 2cm, minimum height = 1cm] {};
\path node [ellipse, split = path02, minimum width = 2cm, minimum height = 1cm, rotate = 60] {};
\path node [ellipse, split = path03, minimum width = 2cm, minimum height = 1cm, rotate = 120] {};
And we will get:
![Ellipses base](https://i.stack.imgur.com/ZwJYH.png)
So we need the points of intersection between the ellipses. In this case, we are working with the first horizontal ellipse and the ellipse rotated 60 degrees. I put the indexes of each of the intersections to show how each can be referenced.
![Intersections](https://i.stack.imgur.com/3CvQA.png)
And now we need to build the paths
that we use between the points of intersection. In the image, the paths were painted to highlight the change. But the code below does not.
\constructpath{path01}{direct}{path02}{reverse}{1}{2}{path-1-2-1}
\constructpath{path01}{direct}{path02}{reverse}{2}{3}{path-1-2-2}
\constructpath{path01}{direct}{path02}{reverse}{3}{4}{path-1-2-3}
\constructpath{path01}{direct}{path02}{reverse}{4}{1}{path-1-2-4}
\path [name path = path-1-2-1] plot [smooth cycle] coordinates {\csuse{path-1-2-1}};
\path [name path = path-1-2-2] plot [smooth cycle] coordinates {\csuse{path-1-2-2}};
\path [name path = path-1-2-3] plot [smooth cycle] coordinates {\csuse{path-1-2-3}};
\path [name path = path-1-2-4] plot [smooth cycle] coordinates {\csuse{path-1-2-4}};
![Paths between points of intersection](https://i.stack.imgur.com/RXDaU.png)
We do the same for the remaining ellipse.
\getintersectionsof{path01}{path03}{0.8pt}
\constructpath{path01}{direct}{path03}{reverse}{1}{2}{path-1-3-1}
\constructpath{path01}{direct}{path03}{reverse}{2}{3}{path-1-3-2}
\constructpath{path01}{direct}{path03}{reverse}{3}{4}{path-1-3-3}
\constructpath{path01}{direct}{path03}{reverse}{4}{1}{path-1-3-4}
\path [name path = path-1-3-1] plot [smooth cycle] coordinates {\csuse{path-1-3-1}};
\path [name path = path-1-3-2] plot [smooth cycle] coordinates {\csuse{path-1-3-2}};
\path [name path = path-1-3-3] plot [smooth cycle] coordinates {\csuse{path-1-3-3}};
\path [name path = path-1-3-4] plot [smooth cycle] coordinates {\csuse{path-1-3-4}};
Now we define the final paths
using the paths
already prepared earlier.
\getintersectionsof{path02}{path-1-3-1}{0.8pt}
\getintersectionsof{path02}{path-1-3-3}{0.8pt}
\constructpath{path02}{direct}{path-1-3-1}{direct}{1}{2}{path-1-2-3-3}
\constructpath{path02}{direct}{path-1-3-3}{direct}{1}{2}{path-1-2-3-4}
\getintersectionsof{path03}{path-1-2-2}{0.8pt}
\getintersectionsof{path03}{path-1-2-4}{0.8pt}
\constructpath{path03}{direct}{path-1-2-2}{reverse}{1}{2}{path-1-2-3-5}
\constructpath{path03}{direct}{path-1-2-4}{reverse}{1}{2}{path-1-2-3-6}
And now just paint the interest areas.
\fill [orange!80] plot [smooth cycle] coordinates {\csuse{path-1-2-3-1}};
\fill [orange!80] plot [smooth cycle] coordinates {\csuse{path-1-2-3-4}};
\fill [orange!80] plot [smooth cycle] coordinates {\csuse{path-1-2-3-5}};
And TAH-DAH!!!
![Final result](https://i.stack.imgur.com/qvZjd.png)
A solution which allows to draw intersection segments
of any two intersections is available as tikz library fillbetween
.
This library works as general purpose tikz
library, but it is shipped with pgfplots
and you need to load pgfplots
in order to make it work:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\draw [name path=red,red] (120:1.06) circle (1.9);
%\draw [name path=yellow,yellow] (0:1.06) circle (2.12);
\draw [name path=green,green!50!black] (0:0.77) circle (2.41);
\draw [name path=blue,blue] (0:0) circle (1.06);
% substitute this temp path by `\path` to make it invisible:
\draw[name path=temp1, intersection segments={of=red and blue,sequence=L1}];
\draw[red,-stealth,ultra thick, intersection segments={of=temp1 and green,sequence=L3}];
\end{tikzpicture}
\end{document}
![enter image description here](https://i.stack.imgur.com/OVWVC.png)
The key intersection segments
is described in all detail in the pgfplots
reference manual section "5.6.6 Intersection Segment Recombination"; the key idea in this case is to
create a temporary path temp1
which is the first intersection segment of red and blue
, more precisely, it is the first intersection segment in the L
eft argument in red and blue
: red
. This path is drawn as thin black path. Substitute its \draw
statement by \path
to make it invisible.
Compute the desired intersection segment
by intersecting temp1
and green
and use the correct intersection segment. By trial and error I figured that it is the third segment of path temp1
which is written as L3
(L
= left argument in temp1 and green
and 3
means third segment of that path).
The argument involves some trial and error because fillbetween
is unaware of the fact that end and startpoint are connected -- and we as end users do not see start and end point.
Note that you can connect these path segments with other paths. If such an intersection segment
should be the continuation of another path, use --
as before the first argument in sequence. This allows to fill paths segments:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\draw [name path=red,red] (120:1.06) circle (1.9);
%\draw [name path=yellow,yellow] (0:1.06) circle (2.12);
\draw [name path=green,green!50!black] (0:0.77) circle (2.41);
\draw [name path=blue,blue] (0:0) circle (1.06);
% substitute this temp path by `\path` to make it invisible:
\draw[name path=temp1, intersection segments={of=red and blue,sequence=L1}];
\draw[red,fill=blue,-stealth,ultra thick, intersection segments={of=temp1 and green,sequence=L3}]
[intersection segments={of=temp1 and green, sequence={--R2}}]
;
\end{tikzpicture}
\end{document}
![enter image description here](https://i.stack.imgur.com/91jCt.png)
Best Answer
If we were dealing with circles, then the radius would be perpendicular to the tangent, so we would need to find a right triangle connecting the center C, point P, and the circle. If you recall your geometry, any triangle inscribed in a circle where one side of the triangle passes through the center will form a right triangle. So if we construct a circle whose center is the midpoint between P and C, the intersection of the two circles is the point(s) of tangency.
Since ellipses can be thought of as circles seen from an angle, instead of a circle we need an ellipse with the same aspect ratio.
For the purposes of illustration, I made the construct visible (pink).