A TikZ-only solution that also draws arrows-heads and dots where necessary. It works with any inequality, not only rational functions, and requires only TikZ.
Update, casting the whole thing into something like a macro as suggested by @AndréC and with help from @marmot:
Code:
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{intersections,arrows.meta}
\makeatletter\long\def\ifnodedefined#1#2{\@ifundefined{pgf@sh@ns@#1}{}{#2}}\makeatother
\tikzset{
%line-styles
OO/.style={fill=blue,draw=blue,{Circle[width=1mm,length=1mm]}-{Circle[width=1mm,length=1mm]},shorten <= -0.5mm,shorten >= -0.5mm}, <O/.style={stealth-{Circle[width=1mm,length=1mm]},shorten <= 0mm}, O>/.style={{Circle[width=1mm,length=1mm]}-stealth,shorten >= 0mm}, <OO>/.style={stealth-stealth,shorten <= 0mm,shorten >= 0mm},every edge/.append style={OO},
%how to plot:
pics/.cd, plot inequality/.code n args={4}{
%all the paths we need to figure out the intersections etc.
\path[name path=conditionline] plot[variable=\x,domain={#2*1.01}:{#3*1.01},samples=300] ({\x},{ifthenelse(#1,{1+#4},{-1+#4})}); \path[name path=zeroline] (#2,#4) -- (#3,#4);\path[name path=start] (#2,{#4+1.1}) -- (#2,{#4+.9});\path[name path=end] (#3,{#4+1.1}) -- (#3,{#4+0.9});\path[name intersections={of=conditionline and start,name=startt}];\path[name intersections={of=conditionline and end,name=endd}];\path[name intersections={of=conditionline and zeroline,name=zerolinee}];\coordinate (intersection-0) at (#2,#4);
%draw lines, nots and arrows
\ifnum0\ifnodedefined{zerolinee-1}{1}\ifnodedefined{startt-1}{1}>0\draw[name intersections={of=zeroline and conditionline,total=\t,by=x}]\foreach \i [count=\s, evaluate=\s as \startswitch using iseven(\s+0\ifnodedefined{startt-1}{1})] in {0,...,{\t}}{\ifnum\i=\t coordinate (intersection-\s) at (#3,#4)\fi\if1\startswitch(intersection-\i) edge [\ifnodedefined{startt-1}{\ifnum\i=0<O\fi}\ifnodedefined{endd-1}{\ifnum\i=\t O>\fi}] (intersection-\s)\fi};\pgfnoderename{}{startt-1}\pgfnoderename{}{endd-1}\pgfnoderename{}{zerolinee-1}\fi}
}
\begin{document}
\begin{tikzpicture}
%real line
\draw[stealth-stealth] (-3.5,-.2) -- (3.5,-.2);\foreach \X in {-3,...,3} {\draw (\X,-0.1) -- (\X,-0.3) node[below]{$\X$}; }
\pic{plot inequality={0.05*(\x*\x-1)>sin(deg(\x*3)) }{-3.5}{3.5}{0}}; \node at (5.5,0) {\(\frac{(x^2-1)}{20}>\sin(3x)\)};
\pic{plot inequality={0.05*(\x*\x-1)<sin(deg(\x*3)) }{-3.5}{3.5}{1}}; \node at (5.5,1) {\(\frac{(x^2-1)}{20}<\sin(3x)\)};
\pic{plot inequality={\x*\x>=1 }{-3.5}{3.5}{2}}; \node at (5.5,2) {\(x^2\geq1\)};
\pic{plot inequality={0<1 }{-3.5}{3.5}{3}}; \node at (5.5,3) {\(0<1\)};
\end{tikzpicture}
\end{document}
Result:
[For the sake of brevity I'm deleting some intermediate solutions that are now obsolete. The current solution is more compact, more general and more precise than what I had before, but uses the same logic.]
The idea is to find all intersections of the indicator function for inequality with the 0-line. We then take those intersections and connect every second of with the next one. Depending on whether the inequality is true or false left side of the function, we start with the odd ones or the even ones. This logic is best illustrated by looking at the output from my first example, plotted against the left hand side of the inequality:
Advantages:
- Works with any mathematical expression that can be evaluated by
pgfmath
- Automatically draws dots or arrows to indicate whether or not the condition is true or false at the end of the displayed interval.
- Now (after first update) also correctly deals with cases where the condition is never or always true (ht @marmot)
- Now (after second update) test condition exactly at the two margins. No resolution-based uncertainty left.
Code-snippet with explanations:
% path that is at 1 where the condition is true and at -1 where it's not
\path[name path=conditionline] plot[variable=\x,domain={#2*1.01}:{#3*1.01},samples=300] ({\x},{ifthenelse(#1,{1+#4},{-1+#4})});
% the zero-line
\path[name path=zeroline] (#2,#4) -- (#3,#4);
% two lines that intersect the conditionline if it is true at the margins of the interval
\path[name path=start] (#2,{#4+1.1}) -- (#2,{#4+.9});\path[name path=end] (#3,{#4+1.1}) -- (#3,{#4+0.9});
%testing whether the conditionline intersects these two lines and the zero line
\path[name intersections={of=conditionline and start,name=startt}];\path[name intersections={of=conditionline and end,name=endd}];\path[name intersections={of=conditionline and zeroline,name=zerolinee}];
coordinate at the left margin
\coordinate (intersection-0) at (#2,#4);
%draw lines, nots and arrows
%only draw something if the condition-line intersects the zero-line at all or if it's always true:
\ifnum0\ifnodedefined{zerolinee-1}{1}\ifnodedefined{startt-1}{1}>0
%loop over all intersections with the zero line (including a fictonal one for the left margin at (intersection-0):
\draw[name intersections={of=zeroline and conditionline,total=\t,by=x}]
\foreach \i [count=\s, evaluate=\s as \startswitch using iseven(\s+0\ifnodedefined{startt-1}{1})] in {0,...,{\t}}{
%if we're in the last round. create a coordinate for the right arrow-tip
\ifnum\i=\t coordinate (intersection-\s) at (#3,#4)\fi
%draw an edge from this intersection to the next, determine arrow heads depending on whether we are in the middle or the margins and whether the condition is true at the margins or not
\if1\startswitch(intersection-\i) edge [\ifnodedefined{startt-1}{\ifnum\i=0<O\fi}\ifnodedefined{endd-1}{\ifnum\i=\t O>\fi}] (intersection-\s)\fi};
%Delete all the old nodes used for testing in case another plot is drawn later
\pgfnoderename{}{startt-1}\pgfnoderename{}{endd-1}\pgfnoderename{}{zerolinee-1}
\fi
}
}
Old solution:
\documentclass[tikz,border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections,arrows.meta}
\makeatletter
\long\def\ifnodedefined#1#2#3{\@ifundefined{pgf@sh@ns@#1}{#3}{#2}}
\makeatother
\begin{document}
\begin{tikzpicture}
%define condition
\path[name path=conditionline] plot[variable=\x,domain=-3.5:3.5,samples=150] ({\x},{ifthenelse(%
0.05*(\x*\x-1)+sin(deg(\x*3))>=0%<=any condition
,1,-1)});
%real line
\draw[stealth-stealth] (-3.5,-.2) -- (3.5,-.2);\foreach \X in {-3,...,3} {\draw (\X,-0.1) -- (\X,-0.3) node[below]{$\X$}; }
%helpers / testing if corners of interval are in or out
\path[name path=zeroline] (-3.5,0) -- (3.5,0);
\path[name path=start] (-3.5,1) -- (-3.5,0);
\path[name path=end] (3.5,1) -- (3.5,0);
\path[name intersections={of=conditionline and start,name=startt}];
\path[name intersections={of=conditionline and end,name=endd}];
%draw lines, nots and arrows
\def\lasts{1}
\draw[fill=blue,draw=blue,name intersections={of=zeroline and conditionline,total=\t,by=x}]
\foreach[remember=\s as \lasts] \s in {1,...,{\t}}{
%if required, draw left arrow
\if\s1\ifnodedefined{startt-1}{ (intersection-1) edge [-stealth ] (startt-1|-0,0)}\fi
%if required, draw right arrow
\if\s\t\ifnodedefined{endd-1}{ (intersection-\t) edge [-stealth] (endd-1|-0,0)}\fi
%draw intermediate lines
\ifodd\s
\ifnodedefined{startt-1}{(intersection-\s) -- (intersection-\lasts)}{}
\else
\ifnodedefined{startt-1}{}{(intersection-\s) -- (intersection-\lasts)}
\fi
%draw points
(intersection-\s) circle (2pt) node {}
};
\end{tikzpicture}
\end{document}
For completeness: I copied the code for the real line from @marmot's solution to this questions and \ifnodedefined
from here
pgfplots
withgnuplot
does that out of the box.) And what are the a_i and b_i? (And why don't you ask a new question. This is not an implicit criticism, but a question.)