The code adds some completely useless invisible (or rather white) stuff. The lines
\clip(0pt,403pt) -- (389.957pt,403pt) -- (389.957pt,99.6166pt) -- (0pt,99.6166pt) -- (0pt,403pt);
\color[rgb]{1,1,1}
\fill(3.76406pt,399.236pt) -- (380.923pt,399.236pt) -- (380.923pt,253.19pt) -- (3.76406pt,253.19pt) -- (3.76406pt,399.236pt);
\fill(53.4497pt,394.719pt) -- (374.901pt,394.719pt) -- (374.901pt,289.325pt) -- (53.4497pt,289.325pt) -- (53.4497pt,394.719pt);
draw a white background that is larger than the actual picture. TikZ sees that and thinks it is part of the picture. Simply removing/uncommenting these lines removes most of the whitespace.
Near the end of the first scope,
\color[rgb]{1,1,1}
\fill(3.76406pt,249.426pt) -- (386.193pt,249.426pt) -- (386.193pt,103.381pt) -- (3.76406pt,103.381pt) -- (3.76406pt,249.426pt);
does the same.
Additionally (near the end of the second scope
),
\pgftext[center, base, at={\pgfpoint{220.95pt}{106.392pt}}]{\sffamily\fontsize{9}{0}\selectfont{\textbf{ }}}
adds a blank node below the picture, again enlarging the bounding box.
Removing all those lines gives a tight bounding box.
As far as I know, TikZ cannot do the cropping for you, as it can't know whether the white stuff is intentional or not (there might for example be a dark background behind the image so that white is visible).
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)
Best Answer
One can compute the correct angle using pgfmath and atan2.