Test whether a circle fully lies within a polygon in TikZ
Given the following TikZ picture with an irregularly shaped polygon:
documentclass{article}
usepackage{tikz}
begin{document}
begin{tikzpicture}
path[draw=blue] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (3.5,0.4) {};
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (1.03,1.3) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (3.3,2) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (0.7,1.8) {};
end{tikzpicture}
end{document}
The two green circles in the picture lie completely inside the polygon, while the red ones lie partially or fully outside. Is there a way to automate that "ownership" test in TikZ? I know algorithms exist for such kind of tests, but does TikZ already provide this or similar features (e.g. tests for single points)?
tikz-pgf
add a comment |
Given the following TikZ picture with an irregularly shaped polygon:
documentclass{article}
usepackage{tikz}
begin{document}
begin{tikzpicture}
path[draw=blue] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (3.5,0.4) {};
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (1.03,1.3) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (3.3,2) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (0.7,1.8) {};
end{tikzpicture}
end{document}
The two green circles in the picture lie completely inside the polygon, while the red ones lie partially or fully outside. Is there a way to automate that "ownership" test in TikZ? I know algorithms exist for such kind of tests, but does TikZ already provide this or similar features (e.g. tests for single points)?
tikz-pgf
2
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use theeven odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.
– Andrew
Dec 26 '18 at 7:20
add a comment |
Given the following TikZ picture with an irregularly shaped polygon:
documentclass{article}
usepackage{tikz}
begin{document}
begin{tikzpicture}
path[draw=blue] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (3.5,0.4) {};
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (1.03,1.3) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (3.3,2) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (0.7,1.8) {};
end{tikzpicture}
end{document}
The two green circles in the picture lie completely inside the polygon, while the red ones lie partially or fully outside. Is there a way to automate that "ownership" test in TikZ? I know algorithms exist for such kind of tests, but does TikZ already provide this or similar features (e.g. tests for single points)?
tikz-pgf
Given the following TikZ picture with an irregularly shaped polygon:
documentclass{article}
usepackage{tikz}
begin{document}
begin{tikzpicture}
path[draw=blue] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (3.5,0.4) {};
node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (1.03,1.3) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (3.3,2) {};
node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (0.7,1.8) {};
end{tikzpicture}
end{document}
The two green circles in the picture lie completely inside the polygon, while the red ones lie partially or fully outside. Is there a way to automate that "ownership" test in TikZ? I know algorithms exist for such kind of tests, but does TikZ already provide this or similar features (e.g. tests for single points)?
tikz-pgf
tikz-pgf
asked Dec 26 '18 at 6:32
siracusasiracusa
4,97511428
4,97511428
2
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use theeven odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.
– Andrew
Dec 26 '18 at 7:20
add a comment |
2
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use theeven odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.
– Andrew
Dec 26 '18 at 7:20
2
2
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use the
even odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.– Andrew
Dec 26 '18 at 7:20
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use the
even odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.– Andrew
Dec 26 '18 at 7:20
add a comment |
2 Answers
2
active
oldest
votes
Here is a solution using a ray casting method. The c
point is an arbitrary point outside of the polygon. The quality of the result depends on the accuracy of the intersection calculation.
Note: to remove help lines, you can comment the draw[help lines,...
line and uncomment the path[name path...
line.
documentclass[tikz]{standalone}
usetikzlibrary{intersections}
defmycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
begin{document}
begin{tikzpicture}
path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
foreach cname/ccolor/ccoord in mycircles {
node [circle,name path global=cname,draw=none,fill=ccolor,minimum size=3mm] (cname) at (ccoord) {};
}
begin{scope}[overlay]
coordinate (c) at (-100,300);
foreach cname/ccolor/ccoord in mycircles {
draw[help lines,dashed,name path global=line-cname] (cname.center) -- (c);
%path[name path global=line-mypath] (mypath.center) -- (c);
}
end{scope}
coordinate (text) at (0,0);
foreach cname/ccolor/ccoord in mycircles {
path[%
name intersections={of=polygon and cname,total=npc},
name intersections={of=polygon and line-cname,total=nplc},
]
pgfextra{
node[align=flush left,at=(text),anchor=north west,node font=scriptsize,inner sep=.1em] (desc) {
pgfmathsetmacromypartial{int((npc != 0)}
pgfmathsetmacromyin{int(mod(nplc,2)!=0)}
pgfmathsetmacromytexti{mypartial==1?"intersects":(myin==1?"is in":"is out")}
pgfmathsetmacromytextii{myin==1?"center is in":"center is out")}
ccolor{} circle mytexti{} (mytextii)
};
coordinate (text) at (desc.south west);
};
}
end{tikzpicture}
end{document}
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
add a comment |
Here is an alternative to Paul Gaborit's nice answer that is specific to polygons (or more generally shapes) of your type. Your shape is called a "star-shape" since there exists (at least) one point with the virtue that any point in the shape can be connected to this point with a straight line that does not intersect with the boundary. Given this point, it is straightforward to test the ownership: a circle is completely inside the polygon if
- the line connecting its center with the star point does not intersect with the boundary and
- the circle does not intersect with the boundary.
In the following MWE I picked a star point by hand (and also draw it) and perform the ownership test.
documentclass{article}
usepackage{tikz}
usetikzlibrary{intersections}
makeatletter % https://tex.stackexchange.com/a/38995/121799
tikzset{
use path/.code={pgfsyssoftpath@setcurrentpath{#1}}
}
makeatother
begin{document}
begin{tikzpicture}[broadcast/.code n args={2}{xdef#2{#1}}]
path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
coordinate (star) at (2,2);
fill[blue] (star) circle (1pt);
foreach X [count=Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{path[name path=aux] X coordinate (X) to[bend left=0] (star);
path[name intersections={of=poly and aux,total=t},broadcast={t}{intT}];
node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=pathC] (c-Y) at (X) {};
path[name intersections={of=poly and circ,total=t},broadcast={t}{intS}];
pgfmathtruncatemacro{itest}{intS+intT}
ifnumitest=0
fill[green,use path=pathC];
else
fill[red,use path=pathC];
fi}
end{tikzpicture}
end{document}
This method is restricted to star-shaped boundaries. However, there it does not suffer from problems that will arise when the test path hits a corner in Paul Gaborit's very nice answer.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f467358%2ftest-whether-a-circle-fully-lies-within-a-polygon-in-tikz%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here is a solution using a ray casting method. The c
point is an arbitrary point outside of the polygon. The quality of the result depends on the accuracy of the intersection calculation.
Note: to remove help lines, you can comment the draw[help lines,...
line and uncomment the path[name path...
line.
documentclass[tikz]{standalone}
usetikzlibrary{intersections}
defmycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
begin{document}
begin{tikzpicture}
path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
foreach cname/ccolor/ccoord in mycircles {
node [circle,name path global=cname,draw=none,fill=ccolor,minimum size=3mm] (cname) at (ccoord) {};
}
begin{scope}[overlay]
coordinate (c) at (-100,300);
foreach cname/ccolor/ccoord in mycircles {
draw[help lines,dashed,name path global=line-cname] (cname.center) -- (c);
%path[name path global=line-mypath] (mypath.center) -- (c);
}
end{scope}
coordinate (text) at (0,0);
foreach cname/ccolor/ccoord in mycircles {
path[%
name intersections={of=polygon and cname,total=npc},
name intersections={of=polygon and line-cname,total=nplc},
]
pgfextra{
node[align=flush left,at=(text),anchor=north west,node font=scriptsize,inner sep=.1em] (desc) {
pgfmathsetmacromypartial{int((npc != 0)}
pgfmathsetmacromyin{int(mod(nplc,2)!=0)}
pgfmathsetmacromytexti{mypartial==1?"intersects":(myin==1?"is in":"is out")}
pgfmathsetmacromytextii{myin==1?"center is in":"center is out")}
ccolor{} circle mytexti{} (mytextii)
};
coordinate (text) at (desc.south west);
};
}
end{tikzpicture}
end{document}
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
add a comment |
Here is a solution using a ray casting method. The c
point is an arbitrary point outside of the polygon. The quality of the result depends on the accuracy of the intersection calculation.
Note: to remove help lines, you can comment the draw[help lines,...
line and uncomment the path[name path...
line.
documentclass[tikz]{standalone}
usetikzlibrary{intersections}
defmycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
begin{document}
begin{tikzpicture}
path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
foreach cname/ccolor/ccoord in mycircles {
node [circle,name path global=cname,draw=none,fill=ccolor,minimum size=3mm] (cname) at (ccoord) {};
}
begin{scope}[overlay]
coordinate (c) at (-100,300);
foreach cname/ccolor/ccoord in mycircles {
draw[help lines,dashed,name path global=line-cname] (cname.center) -- (c);
%path[name path global=line-mypath] (mypath.center) -- (c);
}
end{scope}
coordinate (text) at (0,0);
foreach cname/ccolor/ccoord in mycircles {
path[%
name intersections={of=polygon and cname,total=npc},
name intersections={of=polygon and line-cname,total=nplc},
]
pgfextra{
node[align=flush left,at=(text),anchor=north west,node font=scriptsize,inner sep=.1em] (desc) {
pgfmathsetmacromypartial{int((npc != 0)}
pgfmathsetmacromyin{int(mod(nplc,2)!=0)}
pgfmathsetmacromytexti{mypartial==1?"intersects":(myin==1?"is in":"is out")}
pgfmathsetmacromytextii{myin==1?"center is in":"center is out")}
ccolor{} circle mytexti{} (mytextii)
};
coordinate (text) at (desc.south west);
};
}
end{tikzpicture}
end{document}
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
add a comment |
Here is a solution using a ray casting method. The c
point is an arbitrary point outside of the polygon. The quality of the result depends on the accuracy of the intersection calculation.
Note: to remove help lines, you can comment the draw[help lines,...
line and uncomment the path[name path...
line.
documentclass[tikz]{standalone}
usetikzlibrary{intersections}
defmycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
begin{document}
begin{tikzpicture}
path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
foreach cname/ccolor/ccoord in mycircles {
node [circle,name path global=cname,draw=none,fill=ccolor,minimum size=3mm] (cname) at (ccoord) {};
}
begin{scope}[overlay]
coordinate (c) at (-100,300);
foreach cname/ccolor/ccoord in mycircles {
draw[help lines,dashed,name path global=line-cname] (cname.center) -- (c);
%path[name path global=line-mypath] (mypath.center) -- (c);
}
end{scope}
coordinate (text) at (0,0);
foreach cname/ccolor/ccoord in mycircles {
path[%
name intersections={of=polygon and cname,total=npc},
name intersections={of=polygon and line-cname,total=nplc},
]
pgfextra{
node[align=flush left,at=(text),anchor=north west,node font=scriptsize,inner sep=.1em] (desc) {
pgfmathsetmacromypartial{int((npc != 0)}
pgfmathsetmacromyin{int(mod(nplc,2)!=0)}
pgfmathsetmacromytexti{mypartial==1?"intersects":(myin==1?"is in":"is out")}
pgfmathsetmacromytextii{myin==1?"center is in":"center is out")}
ccolor{} circle mytexti{} (mytextii)
};
coordinate (text) at (desc.south west);
};
}
end{tikzpicture}
end{document}
Here is a solution using a ray casting method. The c
point is an arbitrary point outside of the polygon. The quality of the result depends on the accuracy of the intersection calculation.
Note: to remove help lines, you can comment the draw[help lines,...
line and uncomment the path[name path...
line.
documentclass[tikz]{standalone}
usetikzlibrary{intersections}
defmycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
begin{document}
begin{tikzpicture}
path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
foreach cname/ccolor/ccoord in mycircles {
node [circle,name path global=cname,draw=none,fill=ccolor,minimum size=3mm] (cname) at (ccoord) {};
}
begin{scope}[overlay]
coordinate (c) at (-100,300);
foreach cname/ccolor/ccoord in mycircles {
draw[help lines,dashed,name path global=line-cname] (cname.center) -- (c);
%path[name path global=line-mypath] (mypath.center) -- (c);
}
end{scope}
coordinate (text) at (0,0);
foreach cname/ccolor/ccoord in mycircles {
path[%
name intersections={of=polygon and cname,total=npc},
name intersections={of=polygon and line-cname,total=nplc},
]
pgfextra{
node[align=flush left,at=(text),anchor=north west,node font=scriptsize,inner sep=.1em] (desc) {
pgfmathsetmacromypartial{int((npc != 0)}
pgfmathsetmacromyin{int(mod(nplc,2)!=0)}
pgfmathsetmacromytexti{mypartial==1?"intersects":(myin==1?"is in":"is out")}
pgfmathsetmacromytextii{myin==1?"center is in":"center is out")}
ccolor{} circle mytexti{} (mytextii)
};
coordinate (text) at (desc.south west);
};
}
end{tikzpicture}
end{document}
edited Dec 26 '18 at 21:55
answered Dec 26 '18 at 8:15
Paul GaboritPaul Gaborit
55k7139224
55k7139224
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
add a comment |
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
1
1
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
I like it! +1. Nevertheless I cannot resist remarking that if you were to move the red circle a bit to the right such that the dashed line hits the corner precisely, you'd find two, i.e. an even number of, intersections and hence conclude the red circle is outside. This is regardless of the accuracy with which you compute the intersections.
– marmot
Dec 26 '18 at 18:37
add a comment |
Here is an alternative to Paul Gaborit's nice answer that is specific to polygons (or more generally shapes) of your type. Your shape is called a "star-shape" since there exists (at least) one point with the virtue that any point in the shape can be connected to this point with a straight line that does not intersect with the boundary. Given this point, it is straightforward to test the ownership: a circle is completely inside the polygon if
- the line connecting its center with the star point does not intersect with the boundary and
- the circle does not intersect with the boundary.
In the following MWE I picked a star point by hand (and also draw it) and perform the ownership test.
documentclass{article}
usepackage{tikz}
usetikzlibrary{intersections}
makeatletter % https://tex.stackexchange.com/a/38995/121799
tikzset{
use path/.code={pgfsyssoftpath@setcurrentpath{#1}}
}
makeatother
begin{document}
begin{tikzpicture}[broadcast/.code n args={2}{xdef#2{#1}}]
path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
coordinate (star) at (2,2);
fill[blue] (star) circle (1pt);
foreach X [count=Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{path[name path=aux] X coordinate (X) to[bend left=0] (star);
path[name intersections={of=poly and aux,total=t},broadcast={t}{intT}];
node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=pathC] (c-Y) at (X) {};
path[name intersections={of=poly and circ,total=t},broadcast={t}{intS}];
pgfmathtruncatemacro{itest}{intS+intT}
ifnumitest=0
fill[green,use path=pathC];
else
fill[red,use path=pathC];
fi}
end{tikzpicture}
end{document}
This method is restricted to star-shaped boundaries. However, there it does not suffer from problems that will arise when the test path hits a corner in Paul Gaborit's very nice answer.
add a comment |
Here is an alternative to Paul Gaborit's nice answer that is specific to polygons (or more generally shapes) of your type. Your shape is called a "star-shape" since there exists (at least) one point with the virtue that any point in the shape can be connected to this point with a straight line that does not intersect with the boundary. Given this point, it is straightforward to test the ownership: a circle is completely inside the polygon if
- the line connecting its center with the star point does not intersect with the boundary and
- the circle does not intersect with the boundary.
In the following MWE I picked a star point by hand (and also draw it) and perform the ownership test.
documentclass{article}
usepackage{tikz}
usetikzlibrary{intersections}
makeatletter % https://tex.stackexchange.com/a/38995/121799
tikzset{
use path/.code={pgfsyssoftpath@setcurrentpath{#1}}
}
makeatother
begin{document}
begin{tikzpicture}[broadcast/.code n args={2}{xdef#2{#1}}]
path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
coordinate (star) at (2,2);
fill[blue] (star) circle (1pt);
foreach X [count=Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{path[name path=aux] X coordinate (X) to[bend left=0] (star);
path[name intersections={of=poly and aux,total=t},broadcast={t}{intT}];
node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=pathC] (c-Y) at (X) {};
path[name intersections={of=poly and circ,total=t},broadcast={t}{intS}];
pgfmathtruncatemacro{itest}{intS+intT}
ifnumitest=0
fill[green,use path=pathC];
else
fill[red,use path=pathC];
fi}
end{tikzpicture}
end{document}
This method is restricted to star-shaped boundaries. However, there it does not suffer from problems that will arise when the test path hits a corner in Paul Gaborit's very nice answer.
add a comment |
Here is an alternative to Paul Gaborit's nice answer that is specific to polygons (or more generally shapes) of your type. Your shape is called a "star-shape" since there exists (at least) one point with the virtue that any point in the shape can be connected to this point with a straight line that does not intersect with the boundary. Given this point, it is straightforward to test the ownership: a circle is completely inside the polygon if
- the line connecting its center with the star point does not intersect with the boundary and
- the circle does not intersect with the boundary.
In the following MWE I picked a star point by hand (and also draw it) and perform the ownership test.
documentclass{article}
usepackage{tikz}
usetikzlibrary{intersections}
makeatletter % https://tex.stackexchange.com/a/38995/121799
tikzset{
use path/.code={pgfsyssoftpath@setcurrentpath{#1}}
}
makeatother
begin{document}
begin{tikzpicture}[broadcast/.code n args={2}{xdef#2{#1}}]
path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
coordinate (star) at (2,2);
fill[blue] (star) circle (1pt);
foreach X [count=Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{path[name path=aux] X coordinate (X) to[bend left=0] (star);
path[name intersections={of=poly and aux,total=t},broadcast={t}{intT}];
node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=pathC] (c-Y) at (X) {};
path[name intersections={of=poly and circ,total=t},broadcast={t}{intS}];
pgfmathtruncatemacro{itest}{intS+intT}
ifnumitest=0
fill[green,use path=pathC];
else
fill[red,use path=pathC];
fi}
end{tikzpicture}
end{document}
This method is restricted to star-shaped boundaries. However, there it does not suffer from problems that will arise when the test path hits a corner in Paul Gaborit's very nice answer.
Here is an alternative to Paul Gaborit's nice answer that is specific to polygons (or more generally shapes) of your type. Your shape is called a "star-shape" since there exists (at least) one point with the virtue that any point in the shape can be connected to this point with a straight line that does not intersect with the boundary. Given this point, it is straightforward to test the ownership: a circle is completely inside the polygon if
- the line connecting its center with the star point does not intersect with the boundary and
- the circle does not intersect with the boundary.
In the following MWE I picked a star point by hand (and also draw it) and perform the ownership test.
documentclass{article}
usepackage{tikz}
usetikzlibrary{intersections}
makeatletter % https://tex.stackexchange.com/a/38995/121799
tikzset{
use path/.code={pgfsyssoftpath@setcurrentpath{#1}}
}
makeatother
begin{document}
begin{tikzpicture}[broadcast/.code n args={2}{xdef#2{#1}}]
path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
coordinate (star) at (2,2);
fill[blue] (star) circle (1pt);
foreach X [count=Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{path[name path=aux] X coordinate (X) to[bend left=0] (star);
path[name intersections={of=poly and aux,total=t},broadcast={t}{intT}];
node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=pathC] (c-Y) at (X) {};
path[name intersections={of=poly and circ,total=t},broadcast={t}{intS}];
pgfmathtruncatemacro{itest}{intS+intT}
ifnumitest=0
fill[green,use path=pathC];
else
fill[red,use path=pathC];
fi}
end{tikzpicture}
end{document}
This method is restricted to star-shaped boundaries. However, there it does not suffer from problems that will arise when the test path hits a corner in Paul Gaborit's very nice answer.
answered Dec 26 '18 at 19:28
marmotmarmot
93.8k4109208
93.8k4109208
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f467358%2ftest-whether-a-circle-fully-lies-within-a-polygon-in-tikz%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
As far as I am aware, tikz does not provide any tools for this sort of thing but, visually, you could use the
even odd rule
(section 15.5.2 of the manual) to test this. Of this would almost certainly be subject to rounding errors.– Andrew
Dec 26 '18 at 7:20