I have a cylinder. And yet I wish to draw its deformed picture. I tried
\pgfsetcurvilinearbeziercurve
{\pgfpointxyz{0}{0}{0}}
{\pgfpointxyz{0.1}{0.1}{1.5}}
{\pgfpointxyz{0.25}{0.25}{1.75}}
{\pgfpointxyz{0.5}{0.5}{2.5}}
\pgftransformnonlinear{\pgfgetlastxy\x\y\pgfpointcurvilinearbezierorthogonal{\y}{-\x}}
but rod’s axis and top circle are not in place, and deformation itself is too unnaturally weird
Here’s full TeX I’ve done for now. It draws a cylinder in true 3D filled with color with black bounding lines and then attempts to deform it
\documentclass[tikz,margin=5]{standalone}
\usepgfmodule{nonlineartransformations}
\usepgflibrary{curvilinear}
\usepackage{tikz}
\usepackage{tikz-3dplot} % needs tikz-3dplot.sty in same folder
\usetikzlibrary{calc}
\usetikzlibrary{arrows, arrows.meta}
\usepackage{bm}
\begin{document}
\begin{center}
\def\cameraangle{105}
\tdplotsetmaincoords{66}{\cameraangle} % orientation of camera
\def\rodheight{8}
\def\rodradius{0.2}
\pgfmathsetmacro{\beginangle}{\cameraangle}
\pgfmathsetmacro{\endangle}{\cameraangle - 180}
\tikzset{pics/rod/.style={code={
\coordinate (O) at ( 0, 0, 0 ) ;
\coordinate (rodTopCenter) at ($ (O) + ( 0, 0, \rodheight ) $) ;
% draw rod
%%\foreach \height in { 0, 0.02, ..., \rodheight }
%%\draw [line width=0.8pt, color=yellow, fill=yellow]
%%($ (O) + ( 0, 0, \height ) $) circle ( \rodradius ) ;
\pgfmathsetmacro{\stepangle}{\beginangle - 5}
\foreach \angle in { \beginangle, \stepangle, ..., \endangle }
\draw [line width=0.8pt, color=yellow]
( \angle:\rodradius ) -- ($ ( \angle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
\draw [line width=0.8pt, color=black, domain=\beginangle:\endangle]
plot ({\rodradius*cos(\x)}, {\rodradius*sin(\x)}) ;
\draw [line width=0.85pt, color=black, line cap=round]
( \beginangle:\rodradius ) -- ($ ( \beginangle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
\draw [line width=0.85pt, color=black, line cap=round]
( \endangle:\rodradius ) -- ($ ( \endangle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
\draw [line width=0.8pt, color=black, fill=yellow] (rodTopCenter) circle ( \rodradius ) ;
}}}
\tikzset{pics/rodaxis/.style={code={
\coordinate (O) at ( 0, 0, 0 ) ;
\coordinate (rodTopCenter) at ($ (O) + ( 0, 0, \rodheight ) $) ;
% draw axis
\draw [line width=0.5pt, blue, line cap=round, dash pattern=on 12pt off 2pt on \the\pgflinewidth off 2pt]
($ (O) - ( 0, 0, 0.4pt ) $) -- ($ (rodTopCenter) + ( 0, 0, 0.4pt ) $) ;
}}}
\begin{tikzpicture}[scale=1, tdplot_main_coords] % use 3dplot
\coordinate (O) at ( 0, 0, 0 ) ;
\coordinate (rodTopCenter) at ($ (O) + ( 0, 0, \rodheight ) $) ;
% draw circle
\def\circleradius{0.8}
\def\heightofhatch{0.5}
\pgfmathsetmacro{\stepangleforcircle}{\beginangle - 10}
\foreach \angle in { \beginangle, \stepangleforcircle, ..., \endangle }
\draw [line width=0.4pt, color=black]
( \angle:\circleradius ) -- ($ ( \angle:\circleradius ) - ( 0, 0, \heightofhatch ) $) ;
\draw [line width=0.8pt, color=black, fill=white] (O) circle ( \circleradius ) ;
% draw rod
\pic (initial) {rod} ;
\pic (initial) {rodaxis} ;
% draw force
\def\forcelength{1.2}
\draw [line width=1.4pt, blue, line cap=round, -{Triangle[round, length=3.6mm, width=2.4mm]}]
($ (rodTopCenter) + ( 0, 0, \forcelength) $) -- (rodTopCenter)
node [pos=0.5, above left, inner sep=0, outer sep=3.2pt]
{\scalebox{1.2}[1.2]{${\bm{F}}$}} ;
\scoped {
\pgfsetcurvilinearbeziercurve
{\pgfpointxyz{0}{0}{0}}
{\pgfpointxyz{0.1}{0.1}{1.5}}
{\pgfpointxyz{0.25}{0.25}{1.75}}
{\pgfpointxyz{0.5}{0.5}{2.5}}
\pgftransformnonlinear{\pgfgetlastxy\x\y\pgfpointcurvilinearbezierorthogonal{\y}{-\x}}
\pic (deformed) {rod} ;
\pic (deformed) {rodaxis} ;
}
\end{tikzpicture}
\end{center}
\end{document}
Why is it messed up? Can such transformation work with 3D? How to deal with these \pgfsetcurvilinearbeziercurve
, \pgftransformnonlinear
and \pgfpointcurvilinearbezierorthogonal
(and not to make hundreds of trials and mistakes)? Or maybe some other transformation will suit me better? Or doing deformation manually is the only way?
update
Thanks @marmot, all parts are together now. His variant is also faster, it doesn’t use loop to paint the rod’s side, but just single \draw
\tikzset{pics/rod/.style={code={
%%\coordinate (O) at ( 0, 0, 0 ) ;
% draw rod
%%
%% previous variant number first
%%
%%\foreach \height in { 0, 0.02, ..., \rodheight }
%%\draw [line width=0.8pt, color=yellow, fill=yellow]
%%($ (O) + ( 0, 0, \height ) $) circle ( \rodradius ) ;
%%
%% previous variant number second
%%
%%\pgfmathsetmacro{\stepangle}{\beginangle - 4}
%%\foreach \angle in { \beginangle, \stepangle, ..., \endangle }
%%\draw [line width=0.8pt, color=yellow!50!white, opacity=.9]
%%( \angle:\rodradius ) -- ($ ( \angle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
%%\draw [line width=0.8pt, color=black, domain=\beginangle:\endangle]
%%plot ( {\rodradius*cos(\x)}, {\rodradius*sin(\x)}, 0 ) ;
%%\draw [line width=0.85pt, color=black, line cap=round]
%%( \beginangle:\rodradius ) -- ($ ( \beginangle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
%%\draw [line width=0.85pt, color=black, line cap=round]
%%( \endangle:\rodradius ) -- ($ ( \endangle:\rodradius ) + ( 0, 0, \rodheight ) $) ;
%%
%% current variant by @marmot
%%
\draw [line width=0.8pt, color=black, fill=yellow!50!white, opacity=.9]
plot [domain=\beginangle:\endangle]
( {\rodradius*cos(\x)}, {\rodradius*sin(\x)}, 0 )
-- plot [domain=\endangle:\beginangle]
( {\rodradius*cos(\x)}, {\rodradius*sin(\x)}, \rodheight )
-- cycle ;
%%\draw [line width=0.8pt, color=black, fill=yellow, opacity=.9] ( 0, 0, \rodheight ) circle ( \rodradius ) ;
\draw [line width=0.8pt, color=black, fill=yellow!50!white, domain=0:360]
plot ( {-\rodradius*cos(\x)}, {-\rodradius*sin(\x)}, \rodheight ) ;
}}}
\tikzset{pics/rodaxis/.style={code={
% draw axis
\draw [line width=0.5pt, blue, line cap=round, dash pattern=on 12pt off 2pt on \the\pgflinewidth off 2pt]
( 0, 0, -0.2pt ) -- ( 0, 0, \rodheight + 0.2pt ) ;
}}}
But I am still unsatisfied with the transformation itself. Position the camera at angle 33 instead of 66
\def\cameraangle{100}
\tdplotsetmaincoords{33}{\cameraangle} % orientation of camera
to see the problem
If one wonders what is it expected to be. At first, rod’s cross-sections (circles here) need to remain undeformed. At second, the deformed axis— by Leonhard Euler’s small vibrations/stability theory— is sine (well, I don’t need exact sine, just something looking like smoothly increasing displacements from zero at bottom to maximum at top)