From 33416ddfc3afdd68b8b5aef6938a91554c1210c3 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 23 Dec 2021 21:36:24 +0000 Subject: kinematikz (23dec21) git-svn-id: svn://tug.org/texlive/trunk@61392 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/kinematikz/README | 28 + .../texmf-dist/doc/latex/kinematikz/README.TEXLIVE | 9 + .../texmf-dist/tex/latex/kinematikz/kinematikz.sty | 2633 ++++++++++++++++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/libexec/ctan2tds | 1 + Master/tlpkg/tlpsrc/collection-pictures.tlpsrc | 1 + Master/tlpkg/tlpsrc/kinematikz.tlpsrc | 0 7 files changed, 2673 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/kinematikz/README create mode 100644 Master/texmf-dist/doc/latex/kinematikz/README.TEXLIVE create mode 100644 Master/texmf-dist/tex/latex/kinematikz/kinematikz.sty create mode 100644 Master/tlpkg/tlpsrc/kinematikz.tlpsrc (limited to 'Master') diff --git a/Master/texmf-dist/doc/latex/kinematikz/README b/Master/texmf-dist/doc/latex/kinematikz/README new file mode 100644 index 00000000000..485ea515cba --- /dev/null +++ b/Master/texmf-dist/doc/latex/kinematikz/README @@ -0,0 +1,28 @@ +kinematikz package by Vitor Santos (vitor@ua.pt) +Version 1.0 dated 21/Dec/2021 + +This package provides functionalities to draw kinematic diagrams +for mechanisms using dedicate symbols (some inspired on the ISO standard and others). +The intention is not to represent CAD mechanical drawings of mechanisms and +robots, but only to represent 2D and 3D kinematic chains. The package provides +links, joints and other symbols, mostly in the form of TikZ pic objects. +These pics can be placed in the canvas either by a central point for joints, +and start and end points for some links. + +The documentation consists of a PDF manual that describes the principles with the +syntax, examples and a reference listing of all the objects and their parameters. + +The package is author-maintained. +Permission is granted to copy, distribute and/or modify this +software under the terms of the LATEX Project Public License, +version 1.3.1, or the GNU Public License. This software is +provided ‘as is’, without warranty of any kind, either expressed +or implied, including, but not limited to, the implied warranties +of merchantability and fitness for a particular purpose. + +FILES: + +README +kinematikz.sty +kinematikzmanual.pdf + diff --git a/Master/texmf-dist/doc/latex/kinematikz/README.TEXLIVE b/Master/texmf-dist/doc/latex/kinematikz/README.TEXLIVE new file mode 100644 index 00000000000..454ed671803 --- /dev/null +++ b/Master/texmf-dist/doc/latex/kinematikz/README.TEXLIVE @@ -0,0 +1,9 @@ +The files below have been removed in the TeX Live installation of +the current package, possibly because of missing source (e.g., a +PDF with no source), possibly because their only purpose is to support +nonfree fonts or other software, possibly for other reasons. +More info: https://tug.org/texlive/pkgcontrib.html#requirements + +If this is a concern, please contact the package maintainer. + + kinematikzmanual.pdf diff --git a/Master/texmf-dist/tex/latex/kinematikz/kinematikz.sty b/Master/texmf-dist/tex/latex/kinematikz/kinematikz.sty new file mode 100644 index 00000000000..76b4b8f7de3 --- /dev/null +++ b/Master/texmf-dist/tex/latex/kinematikz/kinematikz.sty @@ -0,0 +1,2633 @@ +\NeedsTeXFormat{LaTeX2e}[1994/06/01] +\ProvidesPackage{kinematikz}[2021/12/21 kinematikz definitions Package] +%-------------------------- +% Vitor Santos +%-------------------------- + +\RequirePackage{tikz} +\RequirePackage{graphicx} +\RequirePackage{tikz-3dplot} + +\RequirePackage{xstring} +\RequirePackage{ifthen} + +\RequirePackage{listofitems} +\RequirePackage{xpatch} + +\usetikzlibrary{backgrounds,matrix,shapes,arrows} %and some special libraries for tikz +\usetikzlibrary{shapes.multipart,shadows} +\usetikzlibrary{calc} +\usetikzlibrary{decorations.pathreplacing} +\usetikzlibrary{decorations.pathmorphing} +\usetikzlibrary{positioning} %for pic +\usetikzlibrary{patterns} +\usetikzlibrary{scopes} %to use shorthands for scopes ;-) +\usetikzlibrary{angles} +\usetikzlibrary{hobby} %to use shorthands for smooth curves ;-) Use many Latex3 stuff... is that recommended...? +\usetikzlibrary{math} %for some more elaborate calculations ;-) +\usetikzlibrary{intersections} %for intersections +\usetikzlibrary{fit} %for fitting nodes after a list of points +\usetikzlibrary{arrows.meta} %for special line endings :-) + +%\pgfdeclarelayer{background} +%\pgfdeclarelayer{foreground} +%\pgfsetlayers{background,main,foreground} + +%https://tex.stackexchange.com/questions/86023/tikz-declare-function-and-babel-french-option +%\usetikzlibrary{babel} % For incompatibilities with tikz declarations and babel with french :-((( But it creates other problems :-((( +%Put it locally to test things.... + + +%----------------------------------- +%\newif\iftikziii %create a test of which tikz version we have. NOT YET USED +%\begingroup +%\def\getmainversion#1.#2\getmainversion{#1} +%\ifnum\expandafter\getmainversion\pgfversion\getmainversion=3 +%\global\tikziiitrue +%\fi +%\endgroup +%----------------------------------- +%Check the date of tikz (date is approximate - v3.1.5 or later required) +\makeatletter +\@ifpackagelater{tikz}{2020/01/01}{% + % Package is new enough +}{% + \PackageError{kinematikz}{Package tikz is too old for some kinematikz facilities}{Use another version of tikz package (v.3.1.5 or later)}% +} +\makeatother + + + +% file with kinematics chains symbology +% v. santos, v1, apr 2017 +% v2, aug 2017 +% minor adjustmente in Feb 2018 +% v3 - started in Oct 2018 - towards the first fotmal LaTeX package +% v4 - started in Sep 2020 - Changed name into kinematikz using previous stuff +% use prefix (kind of name space) km instead of vs for local defs and commands +% new creations follow that, later on change all existing +% v5 - started on Feb 2021 - pic arguments being managed with package listofitems. (but no all migrate yet) +% v6 - started on Sep 2021 - create pipc synonyms. Inside a tikzset do: +% new synonym/.pic={\pic {existing name={#1}};}, +% The previous construction works and the passed argument #1 is actually +% all the arguments regardless of their format. Some may even be +%decomposed in #1/#2/ etc.. or something else in the existing elements defined locally. This was a nice trick to create synonim seemlessly! +% +% v7 - Nov 2021 - prepare version for deployment +% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % +% The main ideia is: +% create symbols for: +% 2D and 3D representation +% ISO and non-ISO common +% Geometry must develop around a central point along rectangular bbox +% Expected connection/anchor points: +% east, west, north, south +% +% Symbols must have a central point (or more) that will define them +% Tikz coordinates should be defined (created) to ease the process of placement +% and establishing links. Arbitrary or possibily in a matrix (useful for more complex structures) +% +% TODOs +% +% migrate all vs prefixes to kn prefixes (DONE) +% erase all obsolete pics and styles (DONE) +% erase compulsory arguments in pics that still have it + + +% global definitions for kinematics chains. + +%%========================================================== +% from https://tex.stackexchange.com/questions/54358/custom-and-built-in-tikz-fill-patterns +% defining the new dimensions and parameters +\newlength{\hatchspread} +\newlength{\hatchthickness} +\newlength{\hatchshift} +\newcommand{\hatchcolor}{} +% declaring the keys in tikz +\tikzset{hatchspread/.code={\setlength{\hatchspread}{#1}}, + hatchthickness/.code={\setlength{\hatchthickness}{#1}}, + hatchshift/.code={\setlength{\hatchshift}{#1}},% must be >= 0 + hatchcolor/.code={\renewcommand{\hatchcolor}{#1}}} +% setting the default values +\tikzset{hatchspread=3pt, + hatchthickness=0.4pt, + hatchshift=0pt,% must be >= 0 + hatchcolor=black} +% declaring the pattern +\pgfdeclarepatternformonly[\hatchspread,\hatchthickness,\hatchshift,\hatchcolor]% variables + {custom north west lines}% name + {\pgfqpoint{\dimexpr-2\hatchthickness}{\dimexpr-2\hatchthickness}}% lower left corner + {\pgfqpoint{\dimexpr\hatchspread+2\hatchthickness}{\dimexpr\hatchspread+2\hatchthickness}}% upper right corner + {\pgfqpoint{\dimexpr\hatchspread}{\dimexpr\hatchspread}}% tile size + {% shape description + \pgfsetlinewidth{\hatchthickness} + \pgfpathmoveto{\pgfqpoint{0pt}{\dimexpr\hatchspread+\hatchshift}} + \pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread+0.15pt+\hatchshift}{-0.15pt}} + \ifdim \hatchshift > 0pt + \pgfpathmoveto{\pgfqpoint{0pt}{\hatchshift}} + \pgfpathlineto{\pgfqpoint{\dimexpr0.15pt+\hatchshift}{-0.15pt}} + \fi + \pgfsetstrokecolor{\hatchcolor} +% \pgfsetdash{{1pt}{1pt}}{0pt}% dashing cannot work correctly in all situation this way + \pgfusepath{stroke} + } + +\pgfdeclarepatternformonly[\hatchspread,\hatchthickness,\hatchshift,\hatchcolor]% variables + {custom north east lines}% name + {\pgfqpoint{\dimexpr-2\hatchthickness}{\dimexpr-2\hatchthickness}}% lower left corner + {\pgfqpoint{\dimexpr\hatchspread+2\hatchthickness}{\dimexpr\hatchspread+2\hatchthickness}}% upper right corner + {\pgfqpoint{\dimexpr\hatchspread}{\dimexpr\hatchspread}}% tile size + {% shape description + \pgfsetlinewidth{\hatchthickness} + \pgfpathmoveto{\pgfqpoint{\dimexpr\hatchshift-0.15pt}{-0.15pt}} + \pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread+0.15pt}{\dimexpr\hatchspread-\hatchshift+0.15pt}} + \ifdim \hatchshift > 0pt + \pgfpathmoveto{\pgfqpoint{-0.15pt}{\dimexpr\hatchspread-\hatchshift-0.15pt}} + \pgfpathlineto{\pgfqpoint{\dimexpr\hatchshift+0.15pt}{\dimexpr\hatchspread+0.15pt}} + \fi + \pgfsetstrokecolor{\hatchcolor} +% \pgfsetdash{{1pt}{1pt}}{0pt}% dashing cannot work correctly in all situation this way + \pgfusepath{stroke} + } + + +%%========================================================== + +\def\TikZ{Ti\emph{k}Z} +\def\Kinematikz{Kinema\TikZ} +\def\kinematikz{\Kinematikz} + +\newcommand{\knKinematikz}{ %A logo for the package still in development +\pic [scale=0.3,transform shape] (F) {frame=7cm}; +\pic [scale=0.3,transform shape,xshift=-3.2cm] (L1) at (F-end) {link bar generic={90:2/0/0/0//1}}; +\coordinate (tt) at ($(L1-start)!0.9!(L1-center)$); +\pic [scale=0.3,transform shape](L2) at (tt) {link bar generic={50:1.2/0//1//1}}; +\pic [scale=0.3,transform shape](L3) at (tt) {link bar generic={-38:1.1/0//1//1}}; +\node [at=(L3-end),xshift=-1pt, yshift=2.5pt,anchor=west,TSF] {inema\TikZ}; +\pic[scale=0.3,transform shape] (F) {frame=7cm}; %Just to cover if exposed... +} + + + +\makeatletter +\newcommand\currentcoordinate{\the\tikz@lastxsaved,\the\tikz@lastysaved} +\makeatother + +\def\pivotRadius{3pt} %radius of pivot elements +\def\linkWidth{6.42pt} %width of links for vsCustomLinks +\def\linkWidth{1pt} %width of links for vsCustomLinks +\def\gapGround{0.04} %separation of moving ground contact (unit is default -- cm) +\def\lAng{90} %default angle for link arms (can override locally) +\def\lLenA{0.5} %default length for link arm A (can override locally) +\def\lLenB{0.5} %default length for link arm B (can override locally) +\def\COMradius{0.4em} %radius of center of mass (because of "em" can scale with font size modifyers :-) +\def\LinkFillColor{gray!50} %default color of planar 2D links +\def\SubLinkFillColor{gray!30} %default color of planar 2D sublinks (like pistons in 2D) +\def\lockRadius{1.25*\pivotRadius} % to define the size of locks in ISO symbols + +\tikzset{TSF/.style={transform shape=false}} +% The "transform shape" is necessarry to also scale pic in case of scaling tikzpictures +%becase the global option scale=..., does not affect nodes or pics. But the problem +%is that it scales fonts as well.. so you can use a smaller font like \footnotesize which is OK for scales of 1.25 except minor issue in kerning. But, it's better to use +%an independnet solution which is to use "transform shape=false" locally on the node to avoid font scaling. So this is useful to keep nodes without drawn shapes with normal +%font sizes... +%So it is recomended to use the TSF style created above in nodes with only text and +%no shape to be drawn to keep text the default size + + +\newcommand{\lineTip}[1]{\fill #1 circle (0.6pt)} %was 0.4 pt, but 0.6 is adequate for "thick" lines. command to append small termination to some tips of lines to cover for poorer line joining :-( Accepts one argument which is the point where to put the terminations +%NOTE - in many cases the previous was replaced by [line cap=round] which is more automatic, but applies to both ends of line and that can be undesired in certain cases; actually a style knLineCap was created for that :-) + +%\draw [options] (center) +(start ang:radius) arc (start ang:end ang:radius); %technique to draw an arc with a center, radius, start and end angle + + +%---Code to allow callout overlay----------- +%code from: https://tex.stackexchange.com/questions/187165/callout-with-multiple-pointers-how-to-design-it +% The goal is to translate +% \overlaynode{hallo}; +% into +% \node[red]{hallo}; +% \node[blue]{hallo}; +\makeatletter +\def\overlaynode<#1>#2;{ + \gdef\stacknodecommonpart{#2} + \pgfkeys{/typeset node/.list={#1}} +} +\pgfkeys{ + /typeset node/.code={ + \edef\pgf@marshal{\noexpand\node[#1]\stacknodecommonpart;} + \pgf@marshal + } +} +\def\overlaynodedrawfill{\pgfutil@ifnextchar[{\overlaynodedrawfill@opt}{\overlaynodedrawfill@opt[]}} +\def\overlaynodedrawfill@opt[#1]<#2>#3;{ + \begin{scope}[transparency group,draw=black,fill=white,line cap=round,line join=round,#1] + \pgfmathsetmacro\pgflinewidthdouble{2\pgflinewidth} + \overlaynode<#2>[draw=pgfstrokecolor,line width=\pgflinewidthdouble]#3; + \overlaynode<#2>[fill=pgffillcolor]#3; + \end{scope} +} +\makeatother +%---------------------------------- + + +%---------------------------------- +%% Command to draw a coordinate system in 2D with 3rd axis (z) in perspective +% Accepts an optional argument which if the orientation of the system +% The second argument is the index of the coordinate system, +% and the thrid is the point where to draw that is: +% \knAddCoordFrame[ang]{num}{point} +% \knAddCoordFrame{num}{point} +% A special index should also be allowed (R,H, etc...) + +\def\knCoordScale{1} %Global scale for Coordinate frame sizes. Can be adjusted +\newcommand{\knAddCoordFrameZout}[3][0]{ %#1 - optional: angle; #2 - mandatory: suffix; #3 startingpoint +\ifthenelse{ \equal{#3}{} } +{ + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} +} +{ + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; + if ( \cSuff >= 0 ) then + { + \drawTheta=1; + } else + { + \cSuff = int(-\cSuff); + }; +} +\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[above,TSF] {$\hat x_{\cSuff}$}; +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++(0,{\knCoordScale*0.75}) node[left,TSF] {$\hat y_{\cSuff}$}; +\draw[robot coord system] \cOrigin -- ++({-\knCoordScale*0.5},{-\knCoordScale*0.5}) node[right,TSF] {$\hat z_{\cSuff}$}; +%\draw [options] (center) +(start ang:radius) arc (start ang:end ang:radius); +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw [angular lines no limits] \cOrigin ++(-135:{\knCoordScale*0.4}) +(-30:0.2) arc (-30:+150:0.2) node [left,xshift=3pt,TSF] {$ \theta_{\idxAng} $}; +} +{} +\draw [fill] \cOrigin circle (1pt); +} +%------- +\newcommand{\knAddCoordFrameZoutB}[4][0]{ %#1 - optional: tikz options; #2 rotation angle except for one axis; #3 - mandatory: suffix; #4 startingpoint +\ifthenelse{ \equal{#4}{} } %Only has 3 parameters +{ + \def\cOptions{} + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +{ %Has the 4 parameters + \def\cOptions{#1} + \def\cAng{#2} %This angle overrides angle potentially included in the general options + \def\cSuff{#3} + \def\cOrigin{#4} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; + %Comment next since this is now for special cases +% if ( \cSuff >= 0 ) then +% { +% \drawTheta=1; +% } else +% { +% \cSuff = int(-\cSuff); +% }; +} +%\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} \edef\idxAng{-} +\draw[robot coord system,\cOptions,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[above,TSF] {$\hat x_{\cSuff}$}; +\draw[robot coord system,\cOptions,rotate=\cAng] \cOrigin -- ++(0,{\knCoordScale*0.75}) node[left,TSF] {$\hat y_{\cSuff}$}; +\draw[robot coord system,\cOptions] \cOrigin -- ++({-\knCoordScale*0.5},{-\knCoordScale*0.5}) node[right,TSF] {$\hat z_{\cSuff}$}; +%\draw [options] (center) +(start ang:radius) arc (start ang:end ang:radius); +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw [angular lines no limits] \cOrigin ++(-135:{\knCoordScale*0.4}) +(-30:0.2) arc (-30:+150:0.2) node [left,xshift=3pt,TSF] {$ \theta_{\idxAng} $}; +} +{} +\draw [fill] \cOrigin circle (1pt); +} +%------- +\newcommand{\knAddCoordFrameZup}[3][0]{ %#1 - optional: angle; #2 - mandatory: suffix; #3 startingpoint +\ifthenelse{ \equal{#3}{} } +{ + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} +} +{ + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; %by default does not draw + if ( \cSuff >= 0 ) then + { + \drawTheta=1; + } + else + { + \cSuff = int(-\cSuff); + }; +} +\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[anchor=south west,inner sep=1pt,TSF] {$\hat x_{\cSuff}$}; +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++(0,{\knCoordScale*0.75}) node[anchor=south east,inner sep=1pt,TSF] {$\hat z_{\cSuff}$}; +\draw[robot coord system] \cOrigin -- ++({\knCoordScale*0.5},{\knCoordScale*0.5}) node[anchor=south east,inner sep=1pt,TSF] {$\hat y_{\cSuff}$}; +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw[angular lines no limits,rotate=\cAng] \cOrigin ++(90:{\knCoordScale*0.4}) node [left,xshift=-3pt,TSF] {$ \theta_{\idxAng} $} [partial ellipse=-250:60:0.25cm and 0.1cm]; +}{} + +\draw[fill] \cOrigin circle (1pt); +} + +%------ + +\newcommand{\knAddCoordFrameZdown}[3][0]{ %#1 - optional: angle; #2 - mandatory: suffix; #3 startingpoint +\ifthenelse{ \equal{#3}{} } +{ + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} +} +{ + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; %by default does not draw + if ( \cSuff >= 0 ) then + { + \drawTheta=1; + } + else + { + \cSuff = int(-\cSuff); + }; +} +\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[anchor=south east,inner sep=1pt,TSF] {$\hat x_{\cSuff}$}; +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++(0,-{\knCoordScale*0.75}) node[anchor=south east,inner sep=1pt,TSF] {$\hat z_{\cSuff}$}; +\draw[robot coord system] \cOrigin -- ++(-{\knCoordScale*0.5},{-\knCoordScale*0.5}) node[anchor=south east,inner sep=1pt,TSF] {$\hat y_{\cSuff}$}; +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw[angular lines no limits,rotate=\cAng] \cOrigin ++(-90:{\knCoordScale*0.4}) [partial ellipse=60:-250:0.25cm and 0.1cm] node [right,xshift=2pt,yshift=4pt,TSF] {$ \theta_{\idxAng} $}; +}{} + +\draw[fill] \cOrigin circle (1pt); +} + + + +%----- +\newcommand{\knAddCoordFrameZupRotX}[3][0]{ %#1 - optional: angle; #2 - mandatory: suffix; #3 startingpoint +\ifthenelse{ \equal{#3}{} } +{ + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} +} +{ + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; %by default does not draw + if ( \cSuff >= 0 ) then + { + \drawTheta=1; + } + else + { + \cSuff = int(-\cSuff); + }; +} +\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[anchor=south east,inner sep=1pt,TSF] {$\hat y_{\cSuff}$}; +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++(0,{\knCoordScale*0.75}) node[anchor=south east,inner sep=1pt,TSF] {$\hat z_{\cSuff}$}; +\draw[robot coord system] \cOrigin -- ++({-\knCoordScale*0.5},{-\knCoordScale*0.5}) node[anchor=south east,inner sep=1pt,TSF] {$\hat x_{\cSuff}$}; +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw[angular lines no limits,rotate=\cAng] \cOrigin ++(90:{\knCoordScale*0.4}) node [left,xshift=-3pt,TSF] {$ \theta_{\idxAng} $} [partial ellipse=-250:60:0.25cm and 0.1cm]; +}{} + +\draw[fill] \cOrigin circle (1pt); +} +%----- + + +\newcommand{\knAddCoordFrameZright}[3][0]{ %#1 - optional: angle; #2 - mandatory: suffix; #3 startingpoint (if suffix is < 0 does not draw angle :-) +\ifthenelse{ \equal{#3}{} } +{ + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} +} +{ + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} +} +\tikzmath{ + int \drawTheta; + \drawTheta=0; %by default does not draw + if ( \cSuff >= 0 ) then + { + \drawTheta=1; + } + else + { + \cSuff = int(-\cSuff); + }; +} +\pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places +\edef\idxAng{\pgfmathresult} +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++({\knCoordScale*0.5},0) node[above,TSF] {$\hat z_{\cSuff}$}; +\draw[robot coord system,rotate=\cAng] \cOrigin -- ++(0,{\knCoordScale*0.75}) node[left,TSF] {$\hat x_{\cSuff}$}; +\draw[robot coord system] \cOrigin -- ++({-\knCoordScale*0.5},{-\knCoordScale*0.5}) node[right,TSF] {$\hat y_{\cSuff}$}; +\ifthenelse{ \equal{\drawTheta}{1} } +{ +\draw[angular lines no limits,rotate=\cAng] \cOrigin ++(0:{\knCoordScale*0.2}) [partial ellipse=60:330:0.1cm and 0.25cm] node [below,anchor=north west,TSF] {$ \theta_{\idxAng} $}; +} +{} +\draw[fill] \cOrigin circle (1pt); +} + +%=========================================== +% Command intended to cover for all the above with flexibility +% The facilities in tikz 3D lib or tikz-3dplot do not help... +% Command must cover generates one of the following options +% System direction (order left to right, d means down) +% +% Y +% |__X (ZdYX) (default) +% / +% Z +% +% X +% |__Z (YdXZ) rotz90 * rotx90 * default +% / +% Y +% +% Z +% |__Y (XdZY) +% / +% X +% +% _X (YdZdX) +% /| +% Y Z +% +% Z Y +% |/__X (ZYX) +% +% + + +%Implement a switch case in latex +%from https://tex.stackexchange.com/questions/5116/making-switch-case-with-etoolboxs-ifdefequal/5210 +\newcommand{\CheckCase}[1]{% + \par\noindent%What is this for?? + \IfEqCase*{#1}{% + {ZdYX}{\def\zDir{-135:{\knCoordScale*0.4}} \def\yDir{90:{\knCoordScale*1}} \def\xDir{0:{\knCoordScale*1}} }% + {YdXZ}{}% + {XdZY}{}% + {YdZdX}{}% + {ZYX}{}% + }[Did not match any given case!]%Put the default here +}% + + +\newcommand{\knAddCoordFrame}[5][0]{ +% #1 - optional rotation angle in plane (default 0) +% #2 - suffix for system naming (0,1,2,..., H, R, ... other) +% #3 - starting point Where to draw origin in current picture +% #4 - type of system (ZdYX,YdXZ,XdZY,YdZdX,ZYX) +% #5 - draw joint around z , or along z; (0 - no drawing, 1 - circular, 2 - linear ) +%\def\zDir{-135:{\knCoordScale*0.4}} \def\yDir{90:{\knCoordScale*1}} \def\xDir{0:{\knCoordScale*1}} + \ifthenelse{\equal{#5}{} } %if not 5 params passed... + { + \def\cAng{0} + \def\cSuff{#1} + \def\cOrigin{#2} + \def\cType{#3} + \def\cJoint{#4} + } + { + \def\cAng{#1} + \def\cSuff{#2} + \def\cOrigin{#3} + \def\cType{#4} + \def\cJoint{#5} + } + + \tikzmath{ + int \drawTheta; + \drawTheta=0; + if ( \cSuff >= 1 ) then + { + \drawTheta=1; + } else + { + \cSuff = int(-\cSuff); + }; + } + \pgfmathparse{int(\cSuff+1)} %had to use int to avoid decimal places + \edef\idxAng{\pgfmathresult} + +% \CheckCase{\cType}%Extract type of coord system and adjust some macros accordingly + + \draw[robot coord system,rotate=\cAng] \cOrigin -- ++(\xDir) node[TSF] {$\hat x_{\cSuff}$}; + \draw[robot coord system,rotate=\cAng] \cOrigin -- ++(\yDir) node[TSF] {$\hat y_{\cSuff}$}; + \draw[robot coord system,rotate=\cAng] \cOrigin -- ++(\zdir) node[TSF] {$\hat z_{\cSuff}$}; + %\draw [options] (center) +(start ang:radius) arc (start ang:end ang:radius); + + \ifthenelse{ \equal{\drawTheta}{1} } + { +% \draw [angular lines no limits] \cOrigin ++(-135:{\knCoordScale*0.4}) +(-30:0.2) arc (-30:+150:0.2) node [left,xshift=3pt,TSF] {$ \theta_{\idxAng} $}; + } + {} + \draw [fill] \cOrigin circle (1pt); +} + +%=========================================== + +%----------------------------------- + +\tikzset{ +%https://tex.stackexchange.com/questions/23453/symbol-center-of-mass-dowelpin +pics/center of mass/.style={ % + code={ + \begin{scope}[radius=\COMradius] %use the same radius for all operations in scope + \fill (0,0) -- ++(\COMradius,0) arc [start angle=0,end angle=90] -- ++(0,-2*\COMradius) arc [start angle=270, end angle=180];% + \draw (0,0) circle;% + \end{scope} + }% + } +} + +\newcommand{\addCOM}[1][black] %alternative to "center of mass" pic. Accepts one argument which are the parameters to fill and draw operations. +%Valid only when there is a (-center) node defined, so most useful inside other figures (pic or other)... +{ +\begin{scope}[radius=\COMradius] %use the same radius for all operations in scope +\fill [#1] (-center) -- ++(\COMradius,0) arc [start angle=0,end angle=90] -- ++(0,-2*\COMradius) arc [start angle=270, end angle=180];% +\draw [#1] (-center) circle;% +\end{scope} +} + +%after https://tex.stackexchange.com/questions/39293/coordinates-a-b-compute-b-a-and-angle-between-x-and-b-a +\newcommand{\kmpgfextractangle}[2] +{ + \pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfpointanchor{#2}{center}} + \global\let#1\pgfmathresult +} + + + +%after https://tex.stackexchange.com/questions/98924/transform-defined-coordinates-in-tikz +\makeatletter +\newcommand{\gettikzxy}[3]{% + \tikz@scan@one@point\pgfutil@firstofone#1\relax + \edef#2{\the\pgf@x}% + \edef#3{\the\pgf@y}% +} +\makeatother + + +%Next definitions inspired from +%https://tex.stackexchange.com/questions/411726/how-to-connect-nodes-with-45-degree-and-0-degree-lines-possibly-via-style/411734 +\tikzset{ + 45-/.style={ + to path={ + let \p{start}=(\tikztostart), + \p{target}=(\tikztotarget), + \p{diff}=({\x{target}-\x{start}}, {\y{target}-\y{start}}), + \p{absdiff}=({abs(\x{diff})}, {abs(\y{diff})}), + \n{mindiff}={min(\x{absdiff}, \y{absdiff})}, + \p{inter}=( + {sign(\x{diff}) * \n{mindiff}}, + {sign(\y{diff}) * \n{mindiff}} + ) + in + \ifnum \ifdim\x{target}=\x{start} 1 + \else \ifdim\y{target}=\y{start} 1 + \else \ifdim\x{absdiff}=\y{absdiff} 1 + \else 0\fi\fi\fi=1 %primitive tex or condition + -- (\tikztotarget) + \else + --++ (\p{inter}) -- (\tikztotarget) + \fi + }, + }, +} + +%THIS STARTS WITH THE DIAGONAL PART AND ADDS THE VERTICAL/HORIZONTAL PART AFTER +%SWAP POINTS IF YOU WANT THE REVERSE. +\tikzset{ + -45/.style={ + to path={ + let \p{start}=(\tikztostart), + \p{target}=(\tikztotarget), + \p{diff}=({\x{target}-\x{start}}, {\y{target}-\y{start}}), + \p{absdiff}=({abs(\x{diff})}, {abs(\y{diff})}), + \n{mindiff}={min(\x{absdiff}, \y{absdiff})}, + \p{inter}=( + {sign(\x{diff}) * \n{mindiff}}, + {sign(\y{diff}) * \n{mindiff}} + ), + \p{inter}=( + \x{target}, + {sign(\y{diff}) * \n{mindiff}} + ) + in + \ifnum + \ifdim\x{target}=\x{start} 1 % points in horizontal? + \else \ifdim\y{target}=\y{start} 1 % points in vertical? + \else \ifdim\x{absdiff}=\y{absdiff} 1 % points in45º diagonal? + \else 0 % not any of those + \fi + \fi + \fi=1 %primitive tex or condition + -- (\tikztotarget) %single horizontal/vertical/diagonal line + \else + -- (\p{inter}) -- (\tikztotarget) %two steps: to intermediate and to target + \fi + }, + }, +} + +%%=============================================================== +\tikzset{ %definitions for some filling and line styles +ground/.style={ %style for a decoration (of a line) + % The border decoration is a path replacing decorator. + % For the ground style we want to draw the original path. + % The postaction option is therefore used to ensure that the + % border decoration is drawn *after* the original path. +% postaction={ %uncomment to also draw the path, but attention to the xshift + draw, + very thin, + decorate, + decoration={ + border, + angle=120, + mirror=true, + amplitude=0.2cm, + transform={xshift=2.5pt}, +% pre=lineto, pre length=3pt, post=border, %post length=2pt, + segment length=2pt, + }, +% } %uncomment to also draw the path + }, +%------------------------------------------ +ground2 texture/.style={ + pattern=custom north east lines, + hatchspread=2.5pt, +% hatchcolor=green!65!black, +% hatchcolor=black, + hatchshift=0pt, + hatchthickness=0.3pt, +% pattern=north east lines, pattern color=black, +}, +ground2/.style={ %style for a node (rectangle) - good only for multiple of 90º orientations + rectangle, + line width=0, + ground2 texture, + minimum height=5pt, + anchor=north west, + inner sep=0, + transform shape, %to rotate rectangle (but not pattern) + }, +%------------------------------------------ +knLinkStyle/.style={% main style for links - namely type of line + thick, %was very thick +% line join=round, %curved connections? May be yes to match line caps... + miter limit=5, %avoid long sharp corners in special edges + }, +knLineCap/.style={ %additional option for line cap in some drawings + line cap=round, + }, +knJointStyle/.style={ %Style for drawing joint parts - not the link parts, like ends or arms! + knLinkStyle, %similar to knLinkStyle. But can be adjusted if needed + line join=miter, %Reinforce the default, unless you want soft corners in rectangles. + }, +%------------------------------------------- +cube face 1/.style={ + knJointStyle, + line join=bevel, + fill=white, %to allow hidding lines in drawing + }, +gripper 1/.style={ + line join=bevel, + knJointStyle, %was very thick + }, +%% SEVERAL LINE STYLES +auxiliary lines/.style={ + very thin, + blue, + }, +symmetry lines/.style={ %to indicate symmetric longitudinal rotational axle + auxiliary lines, + line width=0.5pt, + densely dash dot, + }, +dimension lines no limits/.style={ + auxiliary lines, + red, + >=stealth, + <->, + }, +dimension lines/.style={ + dimension lines no limits, + |<->|, + }, +angular lines no limits/.style={ + dimension lines no limits, + red, + >=stealth, + ->, + }, +angular lines/.style={ + angular lines no limits, + ->|, %possibly |->| ? + }, +joint axis/.style={ + symmetry lines, + black, + }, +%%OTHER USEFUL STYLES +robot coord system/.style={ + thick, + ->, + >=stealth, + blue, + }, +partial ellipse/.style args={#1:#2:#3}{ + insert path={+ (#1:#3) arc (#1:#2:#3)} + }, +%------------------------------------------ +} + +% Check also https://tex.stackexchange.com/questions/463370/pass-an-argument-for-a-pic +% for how to pass arguments to pics +% And this https://tex.stackexchange.com/questions/250728/tikz-pics-with-optional-default-parameters +% to specify default arguments +%%=============================================================== +\tikzset{ +%=================================================== +pics/frame/.default=1cm, %default argument - base width +pics/frame/.style args={#1}{ %ISO frame 3952-1-3.1 % OK in man (passed to the manual) +% Arg 1 - dimension - base width [1cm] + code={ +% \pgfmathsetmacro\myW{#1/2}; %in case you need maths + \coordinate (-left) at (-#1/2,0); + \coordinate (-right) at (#1/2,0); + \coordinate (-center) at (0,0); + \coordinate (-centerTan) at (0,0.175); %This point of for tangency of a link polygon there + \coordinate (-north) at (0,0); + \coordinate (-in) at (0,0); + \coordinate (-out) at (-in); + \coordinate (-end) at (-out); + \coordinate (-south) at (-north); + \coordinate (-start) at (-in); + \node [ground2,minimum width=#1] at (-left) {}; % \draw [ground] (0,0) -- (2,0); + \draw [knJointStyle] (-left) -- ++(#1,0); + } %end of code for this particular pic +}, +%------------------------------------------ +pics/frame 3D/.default=1cm, %default argument - base width +pics/frame 3D/.style args={#1}{ %Frame 3D + % Arg 1 - dimension - base width [1cm] + code={ + % \pgfmathsetmacro\myW{#1/2}; %in case you need maths + \coordinate (-west) at (-#1/2,0); + \coordinate (-east) at (#1/2,0); + \coordinate (-center) at (0,0); + \coordinate (-south) at (-135:#1/4); + \coordinate (-north) at (45:#1/4); + \coordinate (-south west) at ($(-south)-(#1/2,0)$); + \coordinate (-south east) at ($(-south)+(#1/2,0)$); + \coordinate (-north west) at ($(-north)-(#1/2,0)$); + \coordinate (-north east) at ($(-north)+(#1/2,0)$); + \coordinate (-in) at (0,0); + \coordinate (-out) at (-in); + \coordinate (-end) at (-out); + \coordinate (-start) at (-in); + \coordinate (-left) at (-west); + \coordinate (-right) at (-east); + + \node [ground2,minimum width=#1] at (-south west) {}; + \draw [ground2 texture,draw=none, pattern=custom north west lines,] (-south east) -- (-north east) -- ++(0,-5pt) -- ($(-south east)-(0,5pt)$ ) --cycle ; + \draw [knJointStyle] (-south west) -- (-south east) -- (-north east) -- (-north west) -- cycle; + } %end of code for this particular pic +}, +%=================================================== +pics/base flat pivot/.style={ %simple flat ground with a pivot + code={ + \coordinate (-left) at (-1,0); + \coordinate (-right) at (1,0); + \coordinate (-center) at (0,0.175); %why this and not (0,0)? + \coordinate (-north) at (0,0); + \node [ground2,minimum width=2cm] at (-left) {}; % \draw [ground] (0,0) -- (2,0); + \draw [knJointStyle] (-left) -- ($(-north)+(-\pivotRadius-1.5pt,0)$) arc (180:0:\pivotRadius+1.5pt) -- (-right); + \draw [fill=white] (-north) circle (\pivotRadius); + } %end of code for this particular pic +}, +%------------------------------------------ +pics/frame pivot flat/.default=1cm, %simple flat frame with a pivot +pics/frame pivot flat/.style={ %simple flat ground with a pivot % OKinman + code={ + \coordinate (-left) at (-#1/2,0); + \coordinate (-right) at (#1/2,0); +% \coordinate (-center) at (0,0.175); %why this and not (0,0)? + \coordinate (-center) at (0,0); + \coordinate (-north) at (0,0); + \coordinate (-out) at (0,0); + \coordinate (-end) at (-out); + \coordinate (-in) at (0,0); + \coordinate (-start) at (-in); + \coordinate (-south) at (0,-\pivotRadius/2); + \node [ground2,minimum width=#1] at (-left) {}; % \draw [ground] (0,0) -- (2,0); + \draw [knJointStyle] (-left) -- ($(-north)+(-\pivotRadius-1.5pt,0)$) arc (180:0:\pivotRadius+1.5pt) -- (-right); + \draw [fill=white] (-north) circle (\pivotRadius); + } %end of code for this particular pic +}, +%=================================================== +pics/frame pivot trapezium/.default=0.8cm, %trapezium frame with a pivot +pics/frame pivot trapezium/.style={ %OKinman + code={ + \coordinate (-left) at (-#1/2,-#1/4); + \coordinate (-right) at (#1/2,-#1/4); + \coordinate (-center) at (0,0); + \coordinate (-north) at ($(-center)+(90:#1*0.355)$); + \coordinate (-in) at (-center); + \coordinate (-start) at (-center); + \coordinate (-out) at (-center); + \coordinate (-end) at (-center); + \coordinate (-south) at ($(-left)!0.5!(-right)$); + \draw [knJointStyle, line join=round] (-left) -- ++(0:#1) -- ++(120:#1*0.7) -- ++(180:#1*0.3) -- cycle; + \node at (-left) [ground2,minimum width=#1] {}; % \draw [ground] (0,0) -- (1,0); + \draw [] (-center) circle (\pivotRadius); + } %end of code for this particular pic + }, +%=================================================== +pics/frame pivot rounded/.default=0.5cm, %rounded frame with a pivot +pics/frame pivot rounded/.style={ %OKinman + code={ + \coordinate (-left) at (-#1/2,-#1/2); + \coordinate (-right) at ( #1/2,-#1/2); + \coordinate (-center) at (0,0); + \coordinate (-in) at (-center); + \coordinate (-out) at (-center); + \coordinate (-end) at (-out); + \coordinate (-start) at (-center); + \coordinate (-south) at ($(-left)!0.5!(-right)$); + \draw [knJointStyle, line join=round] (-left) -- ++(0:#1) -- ++(90:#1/2) arc (0:180:#1/2) node [midway,inner sep=0] (-north){} -- cycle; + \node at (-left) [ground2,minimum width=#1] {}; %\draw [ground] (0,0) -- (0.5,0); + \draw [] (-center) circle (\pivotRadius); + } %end of code for this particular pic + }, +%=================================================== +pics/frame pivot triangle/.default=0.7cm, %triangle frame with a pivot +pics/frame pivot triangle/.style={ %OKinman + code={ +% \pgfmathsetmacro\myH{2*sin(60)} + \pgfmathsetmacro\myH{1.3} + \coordinate (-left) at (-#1/2,-#1/\myH); + \coordinate (-right) at ( #1/2,-#1/\myH); + \coordinate (-center) at (0,0); + \coordinate (-north) at (-center); + \coordinate (-in) at (-center); + \coordinate (-end) at (-in); + \coordinate (-start) at (-in); + \coordinate (-out) at (-center); +% \coordinate (-south) at ($(-left)!0.5!(-right)$); %This is failing in the book!!! Problem was babel package with french option! + \coordinate (-south) at ($0.5*(-left)+0.5*(-right)$); %so use this... :-( + + \draw [knJointStyle, line join=round] (-center) -- (-left) -- (-right) -- cycle; + \node at (-left) [ground2,minimum width=#1] {};% \draw [ground] (0,0) -- (0.5,0); + \draw [fill=white] (-center) circle (\pivotRadius); + } %end of code for this particular pic + }, +%=================================================== +pics/frame dual pivot slide/.style={ %OKinman +%Arg 1 -> width [2cm] +%Arg 2 -> fraction of placement from -0.25 to +0.25 [0] %default is in the center +%Arg 3 -> fraction size of cursor of frame [0.5] %But there sre max and min absolute sizes + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\fLength} {\def\fLength{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\fFraction}{\def\fFraction{}} + \ifthenelse{ \myArgslen > 2} {\itemtomacro\myArgs[3]\fCursor}{\def\fCursor{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\fLength}{} }{\def\fLength{2cm}} {} + \ifthenelse{ \equal{\fFraction}{}}{\def\fFraction{0}} {} + \ifthenelse{ \equal{\fCursor}{}}{\def\fCursor{0.5}} {} +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \dimendef\myL=0 %first create a dimension register... +% \pgfmathsetlength\myL{max(2*\pivotRadius,\fCursor*\fLength)} %min size +% \pgfmathsetlength\myL{min(1cm,\fCursor*\fLength)} %max size + \pgfmathsetlength\myL{max(2*\pivotRadius,min(1cm,\fCursor*\fLength)} %min/max size + + + %limit excursion of cursor + \pgfmathsetmacro\fFraction{min(0.25,\fFraction)} + \pgfmathsetmacro\fFraction{max(-0.25,\fFraction)} + + \coordinate (-left) at (-\fLength/2,0); + \coordinate (-right) at (\fLength/2,0); + \coordinate (-center) at ($(-left)!0.5!(-right)$); + \coordinate (-in) at (\fFraction*\fLength,0); %proportion of displacement + \coordinate (-north) at ($(-left)!0.5!(-right)+(0,0.25)$); + \coordinate (-start) at (-in); + \coordinate (-out) at (-in); + \coordinate (-end) at (-out); + \coordinate (-south) at ($(-left)!0.5!(-right)-(0,0.25)$); + \draw [line width=1pt,fill=\LinkFillColor] ($(-in)+(-\myL/2,\gapGround-0.25)$) rectangle ++(\myL,0.5-2*\gapGround); + \node [ground2,minimum width=\fLength] at (-\fLength/2,-0.25) {}; % \draw [ground] (0,0) -- (2,0); + \node [ground2,minimum width=\fLength,anchor=south west] at (-\fLength/2,0.25) {}; %\draw [ground] (2,0.5) -- (0,0.5); + \draw [knJointStyle] (-\fLength/2,0.25) -- (\fLength/2,0.25); + \draw [knJointStyle] (-\fLength/2,-0.25) -- (\fLength/2,-0.25); +% \coordinate (-center) at (1,0.25); + \draw [fill=white] (-in) circle (\pivotRadius); + } %end of code for this particular pic + }, +%---------------------------------------------------------- +} % end of base/frame styles + + +\tikzset{ %definitions/pics for SYMBOLS INSPIRED FROM ISO 3952-1 +%=============================================================== +pics/revolute pair planar/.style={ % ISO +%Arg 1 -> destination point +%Arg 2 -> boolean: add or not COM (discarded -1 in legacy for a special case... :-( ) +%Arg 3 -> boolean: add or not pivot in destination (default is 1 yes) + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/} \def\noArgs{1} \def\addStartPivot{0} } {\def\allArgs{#1} \def\noArgs{0} \def\addStartPivot{1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\endPoint} {\def\endPoint{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\dCOM} {\def\dCOM{} } + \ifthenelse{ \myArgslen > 2} {\itemtomacro\myArgs[3]\addEndPivot}{\def\addEndPivot{} } + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\endPoint}{} }{\def\endPoint{15:1}}{} + \ifthenelse{ \equal{\dCOM}{} }{\def\dCOM{0}} {} + \ifthenelse{ \equal{\addEndPivot}{}}{\def\addEndPivot{1}} {} +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \coordinate (-in) at (0,0); + \coordinate (-start) at (-in); + \coordinate (-end) at (\endPoint); + \coordinate (-out) at (-end); +% \coordinate (-center) at ($(-start)!0.5!(-end)$); %This is failing... :-( + \coordinate (-center) at ($0.5*(-start)+0.5*(-end)$); %... so use this + + \draw [knLinkStyle] (-in) -- (-end); + %Test for a special case when no params are passed and append a second arm + \ifnum \noArgs=1 + \draw [knLinkStyle] (-end) -- ++(-10:0.7) coordinate (-end2); + \fi + + \ifthenelse{\addStartPivot=1}{ + \draw [knLinkStyle,fill=white] (-start) circle (\pivotRadius); + }{} + \ifthenelse{\addEndPivot=1}{ + \draw [knLinkStyle,fill=white] (-end) circle (\pivotRadius); + }{} + + \ifthenelse{\dCOM=1}{ \addCOM }{} + + } %end of code for this particular pic + }, +%=============================================================== +% +pics/revolute pair spatial/.default={45:1cm/0/0}, %ISO revolute pair - 3D %FOR CONSISTENCY PASSED POINT SHOULD NOT BE IN () CORRECT THAT IN CALLER +%param: point for link end (default: (45:1cm)); +%param: direction of end arm: 0 top, 1 bottom (default: 0); +%param: axle fixed to some frame: 0 not fixed, 1 fixed (default: 0) +pics/revolute pair spatial/.style args={#1/#2/#3}{ % ISO +% TODO: should accept partial parameters + code={ + \def\invGap{3pt} %inner separation of body 2 from limits of body 1 + \def\outvGap{6pt} %outer gap of axle (can be zero in fexed variant) + \def\argA{#1} + \def\argB{#2} \def\armTop {0} + \def\argC{#3} \def\fFixed {1} + + \coordinate (-center) at (\currentcoordinate); + + \def\rectW{0.6cm} + \def\rectH{0.4cm} + + \if\argC\fFixed + \def\outvGap{0pt} + \fi + +%NB. If param 1 is passed as literal its effect is local, if by a node name, global! +%That is why default parameter always has local referencing + %SO FOR EASIER LOCAL REPRESENTATIONS CENTER THE pic AROUND (0,0) + %But that may complicate anchoring.... + + + \coordinate (-in) at ($(-center) - (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-in2) at ($(-center) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-start) at (-in); + \coordinate (-start2) at (-in2); + \coordinate (-end) at (#1); %Note that this is an absolute point, not relative to -center + \coordinate (-out) at (-end); + \coordinate (-north) at ($(-center) + (0,\rectH/2)$); + \coordinate (-south) at ($(-center) - (0,\rectH/2)$); + \coordinate (-east) at ($(-center) + (0:\rectW/2+\invGap)$); + \coordinate (-west) at ($(-center) - (0:\rectW/2+\invGap)$); + + \if\argC\fFixed %expected to have a frame in one end - so shift all coordinate names + \coordinate (-in) at ($(-in) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-in2) at ($(-in2) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-start) at (-in); + \coordinate (-start2) at (-in2); + \coordinate (-end) at ($(-end) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-out) at (-end); + \coordinate (-north) at ($(-north) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-south) at ($(-south) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-east) at ($(-east) + (0:\rectW/2+\outvGap+\invGap)$); + \coordinate (-west) at ($(-west) + (0:\rectW/2+\outvGap+\invGap)$); + \fi + +%\node[inner sep=0, minimum width=\rectW+2*\outvGap+2*\invGap,circle,opacity=0.5] (-bbox) at (0,0) {}; + % previous node created to attempt anchoring pic by any of it internal nodes + % but it only works if not defined after other internal coordinates. Only explicit + % measumrents, otherwise the anchor is always at (0,0) and + % you need shift to anchor the pic :-( Moreover, only the node is relocated by anchoring + % and not the other drawings :-(((( Check more at + % https://tex.stackexchange.com/questions/185279/anchoring-tikz-pics + + +% \kmpgfextractangle{\nAng}{-end} %not #1, needs to be a node name :-( +% There is problem when pic is named because then -end is not found :-(( +% So I need to do the calculation myself + + \newdimen\XCoord + \newdimen\YCoord + \newdimen\XCoordN + \newdimen\YCoordN + \newdimen\XCoordS + \newdimen\YCoordS + \newdimen\XCoordiN + \newdimen\YCoordiN + +% \path ($#1-(-north) - (-in)$); \pgfgetlastxy{\XCoord}{\YCoord}; +% \pgfmathparse{atan2(\YCoord,\XCoord)} +% \edef\nAng{\pgfmathresult}% +% +% \path ($#1-(-south) - (-in)$); \pgfgetlastxy{\XCoord}{\YCoord}; +% \pgfmathparse{atan2(\YCoord,\XCoord)} +% \edef\sAng{\pgfmathresult}% + +%But that is a problem because \pgfgetlastxy works with absolute coordinates in the figure, which is a problem when there are transformations on parts of the image :-( +%So we need another trick to calculate the angles: + +% \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; +% \path (-north); \pgfgetlastxy{\XCoordN} {\YCoordN}; +% \path (-south); \pgfgetlastxy{\XCoordS} {\YCoordS}; +% \path #1; \pgfgetlastxy{\XCoordiN}{\YCoordiN}; + +%But this previous solution works for only translations (but not all rotations) +%So there is this one using the custom \gettikzxy: + +% \gettikzxy{(-in)} {\XCoord} {\YCoord} + \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; + \gettikzxy{(-north)} {\XCoordN} {\YCoordN} + \gettikzxy{(-south)} {\XCoordS} {\YCoordS} + \gettikzxy{(-end)} {\XCoordiN}{\YCoordiN} + + \pgfmathparse{atan2(\YCoordiN-\YCoordN,\XCoordiN-\XCoordN)} + \edef\nAng{\pgfmathresult}% + + \pgfmathparse{atan2(\YCoordiN-\YCoordS,\XCoordiN-\XCoordS)} + \edef\sAng{\pgfmathresult}% + +% In case I wanted the vector length +% \pgfmathparse{veclen(\XCoord...,\YCoord...)} +% \edef\lRadius{\pgfmathresult}% + + \draw [knLineCap,knLinkStyle] (-in) -- (-in2); % horiz axis. Round line extremities for better connection + \draw [knJointStyle] ($(-in)+(\outvGap,-\rectH/2-1pt)$) -- ++(90:\rectH+2pt); %vert bar left + \draw [knJointStyle] ($(-in2)+(-\outvGap,-\rectH/2-1pt)$) -- ++(90:\rectH+2pt); %vert bar right + + \if\argC\fFixed % two lines + \draw [knJointStyle] ($(-in)+(\outvGap, \rectH/2)+(\invGap,0)$) -- ++(\rectW,0); + \draw [knJointStyle] ($(-in)+(\outvGap,-\rectH/2)+(\invGap,0)$) -- ++(\rectW,0); + \else % a full rectangle + \draw [knJointStyle] ($(-in)+(\outvGap,-\rectH/2)+(\invGap,0)$) rectangle ++(\rectW,\rectH); %rectangle + \fi + + \if\argB\armTop + \draw [knLineCap,knLinkStyle] (-north) -- (-end); %arm + \fill [] (-north) -- ++(\lockRadius,0) arc (0:\nAng:\lockRadius) -- cycle; %lock, as arc + \else + \draw [knLineCap,knLinkStyle] (-south) -- (-end); %arm + \fill [] (-south) -- ++(\lockRadius,0) arc (0:\sAng:\lockRadius) -- cycle; %lock, as arc + \fi + } %end of code for this particular pic + }, +%----------------------------------- +linear pair/.pic={\pic {prismatic pair={#1}};}, %a synonym for prismatic pair. %always use #1 independetly of the number or arguments! +pics/prismatic pair/.default={45:1cm/0}, %ISO linear pair %FOR CONSISTENCY PASSED POINT SHOULD NOT BE IN () CHECK THAT IN CALLER +%param: point for link end (default: (45:1cm)); +%param: direction of end arm: 0 top, 1 bottom (default: 0); +pics/prismatic pair/.style args={#1/#2}{ % ISO + code={ + \def\argA{(#1)} + \def\argB{#2} \def\armTop {0} + + \def\endGap{8pt} + + \def\rectW{0.6cm} + \def\rectH{0.4cm} + +%NB. If param 1 is passed as literal its effect is local, if by a node name, global! +%That is why default parameter always has local referencing + %SO FOR EASIER LOCAL REPRESENTATIONS CENTER THE pic AROUND (0,0) + %But that may complicate anchoring.... + +% \coordinate (-center) at (\currentcoordinate); + \coordinate (-center) at (0,0); + \coordinate (-east) at ($(-center) + (0:\rectW/2)$); + \coordinate (-west) at ($(-center) - (0:\rectW/2)$); + \coordinate (-in) at ($(-west) - (0:\endGap)$); + \coordinate (-in2) at ($(-east) + (0:\endGap)$); + \coordinate (-start) at (-in); + \coordinate (-start2) at (-in2); + \coordinate (-end) at (#1); + \coordinate (-out) at (-end); + \coordinate (-north) at ($(-center) + (0,\rectH/2)$); + \coordinate (-south) at ($(-center) - (0,\rectH/2)$); + +%\node[inner sep=0, minimum width=\rectW,circle,opacity=0.5] (-bbox) at (0,0) {}; + % previous node created to attempt anchoring pic by any of it internal nodes + % but it only works if not defined after other internal coordinates. Only explicit + % measumrents, otherwise the anchor is always at (0,0) and + % you need shift to anchor the pic :-( Moreover, only the node is relocated by anchoring + % and not the other drawings :-(((( Check more at + % https://tex.stackexchange.com/questions/185279/anchoring-tikz-pics + + +% \kmpgfextractangle{\nAng}{-end} %not #1, needs to be a node name :-( +% There is problem when pic is named because then -end is not found :-(( +% So I need to do the calculation myself + + \newdimen\XCoord + \newdimen\YCoord + \newdimen\XCoordN + \newdimen\YCoordN + \newdimen\XCoordS + \newdimen\YCoordS + \newdimen\XCoordiN + \newdimen\YCoordiN + + +% \gettikzxy{(-in)} {\XCoord} {\YCoord} + \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; + \gettikzxy{(-north)} {\XCoordN} {\YCoordN} + \gettikzxy{(-south)} {\XCoordS} {\YCoordS} + \gettikzxy{(#1)} {\XCoordiN}{\YCoordiN} + + \pgfmathparse{atan2(\YCoordiN-\YCoordN,\XCoordiN-\XCoordN)} + \edef\nAng{\pgfmathresult}% + + \pgfmathparse{atan2(\YCoordiN-\YCoordS,\XCoordiN-\XCoordS)} + \edef\sAng{\pgfmathresult}% + +% In case I wanted the vector length +% \pgfmathparse{veclen(\XCoord...,\YCoord...)} +% \edef\lRadius{\pgfmathresult}% + + \coordinate (llCorner) at ($(-center) - (\rectW/2,\rectH/2)$); + + \draw [knJointStyle] (llCorner) rectangle ++(\rectW, \rectH); + \draw [knLinkStyle] (-in) -- (-west) (-in2) -- (-east); + + \if\argB\armTop + \draw [knLineCap,knLinkStyle] (-north) -- (-end);%arm + \fill [] (-north) -- ++(\lockRadius,0) arc (0:\nAng:\lockRadius) -- cycle; %lock, as arc + \else + \draw [knLineCap,knLinkStyle] (-south) -- (-end);%arm + \fill [] (-south) -- ++(\lockRadius,0) arc (0:\sAng:\lockRadius) -- cycle; %lock, as arc + \fi + } %end of code for this particular pic + }, +%=============================================================== +pics/spherical pair/.style={ % 2d socket and ball pair ISO + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\angR} {\def\angR{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\rFactor} {\def\rFactor{}} + \ifthenelse{ \myArgslen > 2} {\itemtomacro\myArgs[3]\lLenA} {\def\lLenA{}} + \ifthenelse{ \myArgslen > 3} {\itemtomacro\myArgs[4]\lLenB} {\def\lLenB{}} + \ifthenelse{ \myArgslen > 4} {\itemtomacro\myArgs[5]\atIn} {\def\atIn{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\angR}{}} {\def\angR{15}} {} %default angle of end arm + \ifthenelse{ \equal{\rFactor}{}} {\def\rFactor{1}} {} %default scale factor for ball + \ifthenelse{ \equal{\lLenA}{}} {\def\lLenA{0.8}} {} %default left arm length + \ifthenelse{ \equal{\lLenB}{}} {\def\lLenB{0.8}} {} %default right arm length + \ifthenelse{ \equal{\atIn}{}} {\def\atIn{0}} {} %1 to attach to -in instead of -center +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \def\gapBS{1.5pt} %gap between ball and socket + \def\ballRadius{\rFactor*\pivotRadius} + \def\tmpIn{(\lLenA,0)} %The temporary in for a shift if required + \def\inShift{(0,0)} %Default internal shift (null) + \ifthenelse{ \equal{\atIn}{1}} {\def\inShift{\tmpIn}} {} %new internal shift if attaching to -in + +% TODO this next option should also be available in other pics + \begin{scope}[shift={\inShift}] % to adjust the anchoring point as needed + \coordinate (-center) at (0,0); + \draw [knLinkStyle] (-center) -- ++(-\lLenA,0) coordinate (-in); + \fill [] ($(-center)-(\ballRadius+\gapBS,0)$) -- ++(-\ballRadius,0) arc (180:30:\ballRadius) -- cycle; %lock left +% \draw [vsISOLinkStyle,fill=white] (-center) arc (90:270:0.2); %socket + \draw [knLinkStyle,fill=white] ([shift=(60:\ballRadius+\gapBS)]-center) arc (60:300:\ballRadius+\gapBS); %This is way too smart: check https://tex.stackexchange.com/questions/66216/draw-arc-in-tikz-when-center-of-circle-is-specified + \draw [knLinkStyle] (-center) -- ++(\angR:\lLenB) coordinate (-end); %right arm + \fill [] ($ (-center) + (\angR:\ballRadius) $) -- ++(\angR:\ballRadius) arc (\angR:-120:\ballRadius) -- cycle; %lock right + \draw [knLinkStyle,fill=white] (-center) circle (\ballRadius); %ball + + \coordinate (-start) at (-in); + \coordinate (-out) at (-end); + \end{scope} + + } %end of code for this particular pic +}, +%------------------------------------------ +%%%% I AM HERE ... DURING THE MIGRATION TO ISO +%=============================================================== +% +pics/helical pair/.default={45:1cm/0}, % +%param: point for link end (default: (45:1cm)); +%param: direction of end arm: 0 top, 1 bottom (default: 0); +pics/helical pair/.style args={#1/#2}{ % + code={ + \def\argA{(#1)} + \def\argB{#2} \def\armTop {0} + + \def\endGap{8pt} + + \def\rectW{0.6cm} + \def\rectH{0.4cm} + +%NB. If param 1 is passed as literal its effect is local, if by a node name, global! +%That is why default parameter always has local referencing + %SO FOR EASIER LOCAL REPRESENTATIONS CENTER THE pic AROUND (0,0) + %But that may complicate anchoring.... + +% \coordinate (-center) at (\currentcoordinate); + \coordinate (-center) at (0,0); + \coordinate (-east) at ($(-center) + (0:\rectW/2)$); + \coordinate (-west) at ($(-center) - (0:\rectW/2)$); + \coordinate (-in) at ($(-west) - (0:\endGap)$); + \coordinate (-in2) at ($(-east) + (0:\endGap)$); + \coordinate (-start) at (-in); + \coordinate (-start2) at (-in2); + \coordinate (-end) at (#1); + \coordinate (-out) at (-end); + \coordinate (-north) at ($(-center) + (0,\rectH/2)$); + \coordinate (-south) at ($(-center) - (0,\rectH/2)$); + +\node[inner sep=0, minimum width=\rectW,circle,opacity=0.5] (-bbox) at (0,0) {}; + % previous node created to attempt anchoring pic by any of it internal nodes + % but it only works if not defined after other internal coordinates. Only explicit + % measumrents, otherwise the anchor is always at (0,0) and + % you need shift to anchor the pic :-( Moreover, only the node is relocated by anchoring + % and not the other drawings :-(((( Check more at + % https://tex.stackexchange.com/questions/185279/anchoring-tikz-pics + + +% \kmpgfextractangle{\nAng}{-end} %not #1, needs to be a node name :-( +% There is problem when pic is named because then -end is not found :-(( +% So I need to do the calculation myself + + \newdimen\XCoord + \newdimen\YCoord + \newdimen\XCoordN + \newdimen\YCoordN + \newdimen\XCoordS + \newdimen\YCoordS + \newdimen\XCoordiN + \newdimen\YCoordiN + + +% \gettikzxy{(-in)} {\XCoord} {\YCoord} + \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; + \gettikzxy{(-north)} {\XCoordN} {\YCoordN} + \gettikzxy{(-south)} {\XCoordS} {\YCoordS} + \gettikzxy{(#1)} {\XCoordiN}{\YCoordiN} + + \pgfmathparse{atan2(\YCoordiN-\YCoordN,\XCoordiN-\XCoordN)} + \edef\nAng{\pgfmathresult}% + + \pgfmathparse{atan2(\YCoordiN-\YCoordS,\XCoordiN-\XCoordS)} + \edef\sAng{\pgfmathresult}% + +% In case I wanted the vector length +% \pgfmathparse{veclen(\XCoord...,\YCoord...)} +% \edef\lRadius{\pgfmathresult}% + + \coordinate (llCorner) at ($(-center) - (\rectW/2,\rectH/2)$); + + \draw [knJointStyle] (llCorner) rectangle ++(\rectW, \rectH); + \draw [knLinkStyle] (-in) -- (-west) (-in2) -- (-east); +% \draw [knLinkStyle, decoration={snake,segment length=\rectW/2.75,amplitude=\rectH/3.5}] (-west) decorate {--(-east)}; + %The previous decoration is not adjusting to scale so using a compopund of sin/cos :-( + \draw [knLinkStyle] (-west) sin + ($(-west)+(\rectW/12,\rectH/4)$) cos + ($(-west)+(2*\rectW/12,0)$) sin + ($(-west)+(3*\rectW/12,-\rectH/4)$) cos + ($(-west)+(4*\rectW/12,0)$) sin + ($(-west)+(5*\rectW/12,\rectH/4)$) cos + ($(-west)+(6*\rectW/12,0)$) sin + ($(-west)+(7*\rectW/12,-\rectH/4)$) cos + ($(-west)+(8*\rectW/12,0)$) sin + ($(-west)+(9*\rectW/12,\rectH/4)$) cos + ($(-west)+(10*\rectW/12,0)$) sin + ($(-west)+(11*\rectW/12,-\rectH/4)$) cos + (-east); + + \if\argB\armTop + \draw [knLineCap,knLinkStyle] (-north) -- (-end); %arm + \fill [] (-north) -- ++(\lockRadius,0) arc (0:\nAng:\lockRadius) -- cycle; %lock, as arc + \else\ + \draw [knLineCap,knLinkStyle] (-south) -- (-end); %arm + \fill [] (-south) -- ++(\lockRadius,0) arc (0:\sAng:\lockRadius) -- cycle; %lock, as arc + \fi + } %end of code for this particular pic + }, +%------------------------------------------ +pics/cylindrical pair/.default={45:1cm/0},% +%param: point for link end (default: (45:1cm)); +%param: direction of end arm: 0 top, 1 bottom (default: 0); +pics/cylindrical pair/.style args={#1/#2}{ % cylindrical link ISO + code={ + \def\argA{(#1)} + \def\argB{#2} \def\armTop {0} + + \def\endGap{0.7cm} %Extension of axis for each side + + \def\rectW{0.6cm} %width + \def\rectH{0.4cm} %height + + \coordinate (-center) at (0,0); + \coordinate (-in) at ($(-center) - (0:\endGap)$); + \coordinate (-in2) at ($(-center) + (0:\endGap)$); + \coordinate (-start) at (-in); + \coordinate (-start2) at (-in2); + \coordinate (-end) at (#1); + \coordinate (-out) at (-end); + \coordinate (-east) at (-in2); + \coordinate (-west) at (-in); + \coordinate (-north) at ($(-center) + (0,\rectH/2)$); + \coordinate (-south) at ($(-center) - (0,\rectH/2)$); + +% \kmpgfextractangle{\nAng}{-end} %not #1, needs to be a node name :-( +% There is problem when pic is named because then -end is not found :-(( +% So I need to do the calculation myself + + \newdimen\XCoord + \newdimen\YCoord + \newdimen\XCoordN + \newdimen\YCoordN + \newdimen\XCoordS + \newdimen\YCoordS + \newdimen\XCoordiN + \newdimen\YCoordiN + +% \gettikzxy{(-in)} {\XCoord} {\YCoord} + \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; + \gettikzxy{(-north)} {\XCoordN} {\YCoordN} + \gettikzxy{(-south)} {\XCoordS} {\YCoordS} + \gettikzxy{(#1)} {\XCoordiN}{\YCoordiN} + + \pgfmathparse{atan2(\YCoordiN-\YCoordN,\XCoordiN-\XCoordN)} + \edef\nAng{\pgfmathresult}% angle in north arm + + \pgfmathparse{atan2(\YCoordiN-\YCoordS,\XCoordiN-\XCoordS)} + \edef\sAng{\pgfmathresult}% angle in south arm + +% In case I wanted the vector length +% \pgfmathparse{veclen(\XCoord...,\YCoord...)} +% \edef\lRadius{\pgfmathresult}% + + \coordinate (llCorner) at ($(-center) - (\rectW/2,\rectH/2)$); + + %Draw the joint parts + \draw [knJointStyle] (llCorner) -- ++(\rectW, 0); + \draw [knJointStyle] (llCorner) ++(0, \rectH) -- ++(\rectW, 0); + %Draw the link (axis) part + \draw [knLinkStyle] (-in) -- (-in2); + + \if\argB\armTop + \draw [knLineCap,knLinkStyle] (-north) -- (-end); %arm + \fill [] (-north) -- ++(\lockRadius,0) arc (0:\nAng:\lockRadius) -- cycle; %lock, as arc + \else\ + \draw [knLineCap,knLinkStyle] (-south) -- (-end); %arm + \fill [] (-south) -- ++(\lockRadius,0) arc (0:\sAng:\lockRadius) -- cycle; %lock, as arc + \fi + } %end of code for this particular pic +}, +%------------------------------------------ +pics/cylindrical pair F/.default={90:0.75cm},% +%param: point for link end (default: (90:0.75cm)); +pics/cylindrical pair F/.style args={#1}{ % cylindrical pair in Frontal view ISO + code={ + \def\diam{0.2cm} %radius + \coordinate (-center) at (0,0); + \coordinate (-in) at (-center); + \coordinate (-start) at (-in); + \coordinate (-out) at (#1); + \coordinate (-end) at (-out); + \draw [knLinkStyle] (-center) -- (#1); + \draw [knLinkStyle, fill=white] (-center) circle (\diam); + \draw [knLinkStyle, fill=black] (-center) circle (0.01); + } %end of code for this particular pic +}, +%------------------------------------------ +pics/planar contact pair/.default={60:0.5cm/-120:0.5cm},% +%param: point for upper link end (default: (45:0.5cm)); +%param: point for lower link end (default: (-135:0.5cm)); +pics/planar contact pair/.style args={#1/#2}{ % plannar link in 2D ISO. Replaces the previous plannarlink2D + code={ + \def\rectW{0.9cm} %width + \def\rectH{0.2cm} %height + + \draw [knJointStyle] (-0.5*\rectW,-0.5*\rectH) -- ++(0:\rectW); %horiz bottom + \draw [knJointStyle] (-0.5*\rectW, 0.5*\rectH) -- ++(0:\rectW); %horiz top + + \coordinate (-north) at (0, 0.5*\rectH); + \coordinate (-south) at (0,-0.5*\rectH); + + \coordinate (-center) at (0,0); + \coordinate (-end) at (#1); %top + \coordinate (-end1) at (-end); + \coordinate (-end2) at (#2); %bottom + \coordinate (-in) at (-end2); %bottom + \coordinate (-out) at (-end); %top + \coordinate (-start) at (-in); + + \newdimen\XCoord \newdimen\YCoord + \newdimen\XCoordN \newdimen\YCoordN + \newdimen\XCoordS \newdimen\YCoordS + \newdimen\XCoordiN \newdimen\YCoordiN + \newdimen\XCoordiS \newdimen\YCoordiS + +% \gettikzxy{(-in)} {\XCoord} {\YCoord} + \path (-in); \pgfgetlastxy{\XCoord} {\YCoord}; + \gettikzxy{(-north)} {\XCoordN} {\YCoordN} + \gettikzxy{(-south)} {\XCoordS} {\YCoordS} + \gettikzxy{(#1)} {\XCoordiN}{\YCoordiN} + \gettikzxy{(#2)} {\XCoordiS}{\YCoordiS} + + \pgfmathparse{atan2(\YCoordiN-\YCoordN,\XCoordiN-\XCoordN)} + \edef\nAng{\pgfmathresult}% angle in north arm + + \pgfmathparse{atan2(\YCoordiS-\YCoordS,\XCoordiS-\XCoordS)} + \edef\sAng{\pgfmathresult}% angle in south arm + + \draw [knLineCap,knLinkStyle] (-north) -- (-end); %arm + \fill [] (-north) -- ++(\lockRadius,0) arc (0:\nAng:\lockRadius) -- cycle; +%lock up + \draw [knLineCap,knLinkStyle] (-south) -- (-end2); %arm + \fill [] (-south) -- ++(-\lockRadius,0) arc (0:180+\sAng:-\lockRadius) -- cycle; + } %end of code for this particular pic +}, +%------------------------------------------ +rotating cam plate/.pic={\pic {camlink=#1};}, %ISO synonym of camlink which is the legacy name +pics/camlink/.default=-30, % default arguments for this pic +pics/camlink/.style args={#1}{ % cam link with triangular pivot ISO + code={ + \coordinate (-center) at (0.2,0.33); + { [shift=(-center),rotate=#1, local bounding box=bb] %translate into center (abbrev. for scope) + \draw [ + name path global=vsCurvedLine, %needed the global because of the scope :-( + use Hobby shortcut, closed=true, + scale=-1.75, + fill=\LinkFillColor + ] + (0,-0.7) .. (0.2,-0.6) .. (0,0.4) .. (-0.2,-0.6) .. (0,-0.7); + + \coordinate (-out) at (0,1); %anchor point in case you need it + \coordinate (-end) at (-out); +%This can be an amuseming alternative +% \node[name path global=vsCurvedLine, +% star, +% draw, +% minimum width=2cm, +% rounded corners=5pt, +% star points=6, +% rotate=#1, +% xshift=10pt, +% yscale=1.2, +%% shading = axis, left color=blue, right color=red!30!white, shading angle=135, +% ] at (-center) {}; + } + + %State a vertical passing some contact point (for example the (-center)) + %and extend it to the limit of the bounding box + \path let \p1=(bb.north), \p2=(-center) in coordinate (-toplimit) at (\x2,\y1); + \path let \p1=(bb.south), \p2=(-center) in coordinate (-bottomlimit) at (\x2,\y1); + \path [name path=vsVerticalLine] (-toplimit) -- (-bottomlimit); + \path [name intersections={of={vsVerticalLine} and {vsCurvedLine}}] ; +% \coordinate (-touchtop) at (intersection-1); +% \coordinate (-touchbottom) at (intersection-2); +% as intesections may change order must do a further text of which point is up... + + \path let \p1=(intersection-1), + \p2=(intersection-2) in coordinate (-touchtop) at (\x1,{max(\y1,\y2)}); + \path let \p1=(intersection-1), + \p2=(intersection-2) in coordinate (-touchbottom) at (\x1,{min(\y1,\y2)}); + +%Can do the same in horizontal + \path let \p1=(bb.west), \p2=(-center) in coordinate (-leftlimit) at (\x1,\y2); + \path let \p1=(bb.east), \p2=(-center) in coordinate (-rightlimit) at (\x1,\y2); + \path [name path=vsHorizontalLine] (-leftlimit) -- (-rightlimit); + \path [name intersections={of={vsHorizontalLine} and {vsCurvedLine}}] ; + \path let \p1=(intersection-1), + \p2=(intersection-2) in coordinate (-touchright) at ({max(\x1,\x2)},\y2); + + \path let \p1=(intersection-1), + \p2=(intersection-2) in coordinate (-touchleft) at ({min(\x1,\x2)},\y2); + + + \draw [line join=round,fill=white] (0,0) -- (0.4,0) -- (0.2,0.33) -- cycle; + \node [ground2,minimum width=0.8cm,xshift=-0.2cm] {};% \draw [ground] (0,0) -- (0.5,0); + \draw [thick,xshift=-0.2cm] (0,0) -- (0.8,0); + \draw [fill=white] (-center) circle (\pivotRadius); + } %end of code for this particular pic +}, %end of pic +%------------------------------------------ +campin/.pic={\pic {cam follower=4};}, %a way to keep compatibility with the early campin element that can now be emulated as a particular case of cam follower +%------------------------------------------ +pics/cam follower/.style={ % The ISO version of campin + code={ +%------------------------ + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\pinType} {\def\pinType{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\pinDir} {\def\pinDir{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\pinType}{}} {\def\pinType{0}} {} %default 0 for knifeedhe + \ifthenelse{ \equal{\pinDir}{}} {\def\pinDir{0}} {} %default 0 for vertical +%---------------------- + + \def\KNIFEEDGE{0} + \def\ARCUATE{1} + \def\ROLLER{2} + \def\FLATFACED{3} + \def\CAMPIN{4} %A special definition for an eralier version non ISO + \def\PINVERT{0} + \def\PINHORIZ{1} + + \def\armLen{1cm} %length or arm + \def\tipGap{20pt} % gap from contact to arm + + \coordinate (-in) at (0,0); + + \if\pinType\KNIFEEDGE % + \def\tipGap{8pt} % gap from contact to arm + \draw [knLinkStyle,line join=round] (-in) -- ++(-4pt,\tipGap) -- ++(8pt,0) -- cycle; + \else + \if\pinType\ARCUATE + \def\tipGap{6pt} % gap from contact to arm + \draw [knLinkStyle] (-6pt,\tipGap) arc (-180:0:\tipGap) -- cycle; + \else + \if\pinType\ROLLER + \def\tipGap{10pt} % gap from contact to arm + \draw [knLinkStyle,fill=white] (0,0.5*\tipGap) circle (0.5*\tipGap); + \draw [knLinkStyle,fill=white] (0,0.5*\tipGap) circle (0.25*\tipGap); + \else + \if\pinType\FLATFACED + \def\tipGap{3pt} % gap from contact to arm + \draw [knLinkStyle] (-5pt,0) rectangle ++(10pt,\tipGap); + \fi + \fi + \fi + \fi + + \coordinate (-topin) at (0,\tipGap); + + \if\pinDir\PINVERT % + \coordinate (-end) at (0,\armLen); + \else + \coordinate (-end) at (\armLen,\tipGap); + \fi + + \draw [knLinkStyle] (-topin) -- (-end); + + \coordinate (-out) at (-end); + \coordinate (-center) at (-in); + \coordinate (-start) at (-in); + + \if\pinType\CAMPIN %legacy for early campin + \coordinate (-center) at (0,17pt); + \draw [fill=\LinkFillColor] (0,0)--++(2pt,4pt)--++(0,30pt)--++(-2pt,0) coordinate (-end) --++(-2pt,0)--++(0,-30pt) --cycle; + \coordinate (-out) at (-end); + \fi + } %end of code for this particular pic +}, %end of pic +%------------------------------------------ +} %end of tikzset +% +%====== OTHER DEFINITIONS vsCustomLinks ================= + +\tikzset{ % definitions for my definitions of link pics () +% +% Technique adapted from https://tex.stackexchange.com/questions/218813/latex-access-every-character-of-an-string-variable using listofitems package +pics/link bar generic/.style=% +%Arg 1 -> point of end [0:30pt] %Point cannot come in ( ) because it gives problems below... :-( +%Arg 2 -> bool include the COM symbol in the geometric center [1] +%Arg 3 -> bool has pivot in -start [1] +%Arg 4 -> bool has pivot in -end [1] +%Arg 5 -> bool draw option crosshairs in extremes [0] +%Arg 6 -> line width undocumented :-) to manipulate line with +{ + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- +%Split joint argument in several args. If passed, use it, else put blanks. +%But first impose an empty list in case no args are passed to avoid error of readlist + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\def\destPoint {\myArgs[1]}} {\def\destPoint{}} + \ifthenelse{ \myArgslen > 1} {\def\hasCOM {\myArgs[2]}} {\def\hasCOM{}} + \ifthenelse{ \myArgslen > 2} {\def\hasStartPivot{\myArgs[3]}} {\def\hasStartPivot{}} + \ifthenelse{ \myArgslen > 3} {\def\hasEndPivot {\myArgs[4]}} {\def\hasEndPivot{}} + \ifthenelse{ \myArgslen > 4} {\def\hasCrossHairs{\myArgs[5]}} {\def\hasCrossHairs{}} + \ifthenelse{ \myArgslen > 5} {\def\hasThinLines {\myArgs[6]}} {\def\hasThinLines{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\destPoint}{}} {\def\destPoint {0:30pt}}{} + \ifthenelse{ \equal{\hasCOM}{}} {\def\hasCOM {1}} {} + \ifthenelse{ \equal{\hasStartPivot}{}}{\def\hasStartPivot{1}} {} + \ifthenelse{ \equal{\hasEndPivot}{}} {\def\hasEndPivot {1}} {} + \ifthenelse{ \equal{\hasCrossHairs}{}}{\def\hasCrossHairs{0}} {} + \ifthenelse{ \equal{\hasThinLines}{}} {\def\hasThinLines {0}} {} +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \coordinate (-start) at (\currentcoordinate); + \coordinate (-end) at (\destPoint); + \coordinate (-end1) at (-end); %a synonym for compatitility with others + + %AUX CALCS + \coordinate (A) at (-start); + \coordinate (B) at ($(A)+(-end)$); + %Calculate angle of point alignment + \gettikzxy{(A)} {\XCoordA} {\YCoordA} + \gettikzxy{(B)} {\XCoordB} {\YCoordB} + \pgfmathparse{atan2(\YCoordB-\YCoordA,\XCoordB-\XCoordA)} + \edef\nAng{\pgfmathresult}% + + \def\lWidth{0.75pt} %line width of drawings. + \ifthenelse{\hasThinLines=1}{\def\lWidth{0.2pt}}{}%Very very thin (0 in the limit) + + %Calculate base length + \pgfmathparse{veclen(\XCoordB-\XCoordA,\YCoordB-\YCoordA)} + \edef\lRadiusS{\pgfmathresult}% + + %Calculate extension factor beyond B and obtain posB + \pgfmathparse{1+5/\lRadiusS} %Extension of 5pt more to draw a pivot + \edef\lFact{\pgfmathresult}% + \coordinate (posB) at ($(A)!\lFact!(B)$); %Full extremity with the pivot point +% \coordinate (posB) at ($\lFact*(A)+(B)$); %Full extremity with the pivot point + + + %Calculate extension factor beyond A and obtain preA + \pgfmathparse{1+5/\lRadiusS} %Extension of 5pt more to draw a pivot + \edef\lFact{\pgfmathresult}% + \coordinate (preA) at ($(B)!\lFact!(A)$); %Full extremity with the pivot point +% \coordinate (preA) at ($\lFact*(B)+(A)$); %Full extremity with the pivot point + + + \def\rrWest{none} %ending type for the case in no pivot in West (left or start) + \def\rrEast{none} %ending type for the case in no pivot in East (right or end) + + \ifthenelse{\hasStartPivot=1}{\def\rrWest{convex}}{\coordinate (preA) at (A);} % if using pre extension keep the calculations + \ifthenelse{\hasEndPivot=1}{\def\rrEast{convex}}{\coordinate (posB) at (B);} % if using pre extension keep the calculations + + %After this point the final extremities are in preA and posB even if no pivots (coincide with A/B) +% \coordinate (-center) at ($(preA)!0.5!(posB)$); + \coordinate (-center) at ($0.5*(preA)+0.5*(posB)$); + + \gettikzxy{(preA)} {\XCoordA} {\YCoordA} + \gettikzxy{(posB)} {\XCoordB} {\YCoordB} + \pgfmathparse{veclen(\XCoordB-\XCoordA,\YCoordB-\YCoordA)} + \edef\lRadius{\pgfmathresult}% + + \coordinate (ppreA) at ($(preA)-(\nAng:\lWidth/2)$); %recalculate for correct drawing below + \node [rotate=\nAng, + inner sep=0, + rounded rectangle, + draw, + fill=\LinkFillColor, + line width=\lWidth, %controls line width + minimum width=\lRadius, %dimension (actually the longest dim or link length) + minimum height=10pt, %dimension (actually the shortests dim or link thickness) +% at=(-center); + at=(ppreA), %actully preA with a line width correction + anchor=west, %force this anchor to avoid external changes... + rounded rectangle west arc=\rrWest, %none, convex, concave %controls the ending type + rounded rectangle east arc=\rrEast, %none, convex, concave %controls the ending type + ] () {}; + \coordinate (-in) at (-start); + \coordinate (-out) at (-end); + \coordinate (-south) at ($ (-center) - (90+\nAng:5pt)$); + \coordinate (-north) at ($ (-center) + (90+\nAng:5pt)$); + + \ifthenelse{\hasStartPivot=1}{\draw [fill=white] (-start) circle (\pivotRadius);}{} % draw pivot in start + \ifthenelse{\hasEndPivot=1}{\draw [fill=white] (-end) circle (\pivotRadius);}{} % draw pivot in end + + \ifthenelse{\hasCOM=1}{ + \tiny \addCOM %[blue] or [fill=none,draw=none], etc. %addmits that (-center) is defined + } {} +\ifthenelse{\hasCrossHairs=1}{ + \draw (A) -- ++(90+\nAng:4pt) (A) -- ++(-90+\nAng:4pt) (A) -- ++(\nAng:4pt) (A) -- ++(180+\nAng:4pt); + \draw (B) -- ++(90+\nAng:4pt) (B) -- ++(-90+\nAng:4pt)(B) -- ++(\nAng:4pt) (B) -- ++(180+\nAng:4pt);} {} + } %end of code for this particular pic + }, +%------------------------------------------ +pics/linear joint bar/.style={% 2D linear joint bar +% arg 1 - fraction of insertion (default 0.5) - 0 is no insertion at all, 1 is fully inserted +% arg 2 - lenght of fixed part (default 1cm) +% arg 3 - boolean - has curved base (0 no - default, 1 - yes) +% arg 4 - boolean - has curved tip (0 no, 1 yes (default)) + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\fracDepth} {\def\fracDepth{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\fixLen} {\def\fixLen{}} + \ifthenelse{ \myArgslen > 2} {\itemtomacro\myArgs[3]\curvBase} {\def\curvBase{}} + \ifthenelse{ \myArgslen > 3} {\itemtomacro\myArgs[4]\curvTip} {\def\curvTip{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\fracDepth}{}} {\def\fracDepth{0.5}} {} %default 0.5 fraction of insertion + \ifthenelse{ \equal{\fixLen}{}} {\def\fixLen{1cm}} {} %default 1cm length of fixed part + \ifthenelse{ \equal{\curvBase}{}} {\def\curvBase{0}} {} %default is no curved base + \ifthenelse{ \equal{\curvTip}{}} {\def\curvTip{1}} {} %default is to have a curved tip +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \def\iGap{2pt} %inner separation of piston from body + \def\rectH{10pt} %height of outer cyl + + \begin{scope}[rotate=0] %No rotation draw it horizontally + \coordinate (-start) at (0,0); + \coordinate (-jpoint) at ($(0,0) + (\fixLen,0) $); + \coordinate (-center) at (-jpoint); + \coordinate (-end) at ($(0,0) + (2*\fixLen-\fracDepth*\fixLen,0) $); %size varies + \coordinate (-in) at (-start); + \coordinate (-out) at (-end); + \coordinate (-topright) at ([yshift=0.5*\rectH]-jpoint); + \coordinate (-topleft) at ([yshift=0.5*\rectH]-start); + \coordinate (-bottomleft) at ([yshift=-0.5*\rectH]-start); + \coordinate (-bottomright) at ([yshift=-0.5*\rectH]-jpoint); + + \coordinate (-toprightS) at ([yshift={0.5*\rectH-\iGap}]-end); + \coordinate (-topleftS) at ([yshift={0.5*\rectH-\iGap}]-jpoint); + \coordinate (-bottomleftS) at ([yshift={-0.5*\rectH+\iGap}]-jpoint); + \coordinate (-bottomrightS) at ([yshift={-0.5*\rectH+\iGap}]-end); + + \ifthenelse{ \equal{\curvTip}{0} } + { + \fill [\SubLinkFillColor] (-topleftS) -- (-toprightS) -- (-bottomrightS) -- (-bottomleftS) -- cycle; + } + { + \fill [\SubLinkFillColor] (-topleftS) -- (-toprightS) arc (90:-90:0.5*\rectH-\iGap) -- (-bottomleftS) -- cycle; + } + + + \ifthenelse{ \equal{\curvBase}{0} } + { + \draw [knLinkStyle,fill=\LinkFillColor] (-topright) -- (-topleft) -- (-bottomleft) -- (-bottomright); + } + { + \draw [knLinkStyle,fill=\LinkFillColor] (-topright) -- (-topleft) arc (90:270:0.5*\rectH) -- (-bottomright); + \draw [fill=white] (-start) circle (\pivotRadius); + } + + \end{scope} + } %end of code for this particular pic +}, +%------------------------------------------ +pics/link polygon/.style=% +%Arg 1 -> point of -end1 +%Arg 2 -> point of -end2 +%... +%Arg n -> point of -endn +{ + code={ +%Split joint argument in several args. Empty arguments are discarded. +%But first impose a default list with onde point in case no args at all are passed to avoid error of readlist + \ifthenelse{ \equal{#1}{}} {\def\allArgs{0:30pt}} {\def\allArgs{#1}} + \ignoreemptyitems %to discard empty entries in list of arguments + \setsepchar[.]{/} % "/" is the separator; "." is separator of sperators in the separator list + \readlist\myArgs{\allArgs} %separate the argments in their own variable (myArgs[1], myArgs[2], etc... + % studying second level separators to decide which pivot to draw, but it complicates too much the decoding code. So use a defined list (macro) of booleans to decide which pivot points to draw. + + %Lame solutions -- limited to a fixed number because could not implement the solution shown + \ifdefined\ListOfPivotPointsToDraw + %do nothing + \else +% \count=\myArgslen \def\ListOfPivotPointsToDraw{\loop \ifnum\count0>0 \advance\count0 by -1 {1,}\repeat} + \def\ListOfPivotPointsToDraw{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} %:-(( + \fi + + \setsepchar{,} % restore the "," separator; + \readlist\dPivots{\ListOfPivotPointsToDraw} % + + \coordinate (-start) at (\currentcoordinate); + \coordinate (-in) at (-start); + %Create all -end coordinates + \foreachitem\pPoint\in\myArgs{\coordinate [at=(\pPoint),name=-end\pPointcnt] ; \coordinate [at=(\pPoint),name=-out\pPointcnt] ;} + + \coordinate (-centerS) at (-start); %init this accumulator + \foreachitem\pPoint\in\myArgs{\coordinate [at=($(\pPoint)+(-centerS)$),name=-centerS] ;} %add allpoints + + \coordinate (-out) at (-out1); + \coordinate (-end) at (-out); + + + \xdef\AllPoints{(-in)} %start with -in + \foreach \n in {1,...,\myArgslen} {\xdef\AllPoints{\AllPoints(-end\n)} } %add all -ends + \node[fit=\AllPoints] (-box){}; %create a fit box + + \pgfmathsetmacro\vsWeight{1/(\myArgslen+1)} %because you cannot apply division in nodes :-(( and do not forget starting points + \coordinate (-center) at ($\vsWeight*(-centerS)$); + + %Trick draw a wide line first +%%OPTION A - The best except if you want a fill pattern + \draw [line join=round, line width=10pt,rounded corners=0pt, fill=\LinkFillColor] + (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; + %... and then the same with a thinner line with the same color as fill color + \draw [\LinkFillColor, line join=round, line width=8.25pt,rounded corners=0pt, fill=\LinkFillColor] + (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; + +%%OPTION B - The simplest and best for patterns but not the best for the geometry contour :-( +% \draw [line join=round, line width=0.75pt,rounded corners=0pt, pattern=north east lines] +% (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; + +%%OPTION C +% %This Alternative is more elegant but not faithfull geometrically and poorer for 2 points only :-( +% \def\exFact{1.15} +% \draw [line join=round, +% line width=0.75pt, +% rounded corners=5pt, +%% fill=\LinkFillColor, +% pattern=north east lines +% ] +% ($(-center)!\exFact!(-start)$) \foreach \n in {1,...,\myArgslen} {-- ($(-center)!\exFact!(-end\n)$)} -- cycle; + +%%OPTION D - Inspired in A and uses pattersn but leaves a white border. May confuse. Perhaps avoid +% \draw [line join=round, line width=10pt,rounded corners=0pt] %, fill=\LinkFillColor] +% (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; +%% %... and then the same with a thinner line with the same color as fill color +% \draw [white, line join=round, line width=8.25pt,rounded corners=0pt,fill=white] +% (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; +% \draw [draw=none,line join=round, line width=0pt,rounded corners=0pt, pattern=north east lines] +% (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; +% + +%%OPTION E +%% This would be a trick with clip but not very useful since line options cannot be passed to clip :-( +% \begin{scope} +% %Sets the clipping areas and also the limits to use as bounding box of polygon +% \clip [ use as bounding box ] +% (-start) \foreach \n in {1,...,\myArgslen} {-- (-end\n)} -- cycle; +% %Draw a rectangle filled with the correct pattern +% \draw [draw=none,pattern=north east lines] (current bounding box.south west) rectangle (current bounding box.north east); +% \end{scope} + + + \draw [fill=white] (-start) circle (\pivotRadius); %pivot at -start + + %Draw remainder pivots + \foreach \n in {1,...,\myArgslen} + { + \ifthenelse{ \dPivots[\n] = 1} + { + \draw [fill=white] (-end\n) circle (\pivotRadius); %pivot at -end\n + }{} + } + + \pic at (-center) {center of mass}; + } %end of code for this particular pic + }, +%------------------------------------------ +pics/linear piston/.style={% 2D linear piston-like pair. Replaces the previous 2 +% arg 1 - fraction of insertion (default 0.5) +% arg 2 - width of inner piston plate (default 5pt) + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- +% TODO Should be extended to all pics with params. Only some have it------ :-) + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\fracDepth} {\def\fracDepth{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\pWidth} {\def\pWidth{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\fracDepth}{}} {\def\fracDepth{0.5}} {} %default 0.5 fraction of insertion + \ifthenelse{ \equal{\pWidth}{}} {\def\pWidth{10pt}} {} %default 5pt width +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \def\iGap{2pt} %inner separation of piston plate from body + \def\rectH{0.5cm} %height of outer cyl + \edef\rectW{2*\iGap+\pWidth} %width of outer cyl + \def\armLen{0.4cm} %arm length + + \begin{scope}[rotate=90] + \coordinate (-center) at (0,0); + \coordinate (-innerend) at ($(-center) - (0, \fracDepth*\rectH) $); + \coordinate (-start) at (0,\armLen); + % \coordinate (-start) at ($(-innerend) - (0,\rectH-\fracDepth*\rectH+\armLen) $); %Keep size + \coordinate (-end) at ($(-innerend) - (0,0.5*\rectH+\armLen) $); %size varies + \coordinate (-in) at (-start); + \coordinate (-out) at (-end); + \coordinate (-iend) at (-innerend); + + \draw [knJointStyle] (-\iGap-0.5*\pWidth,-\rectH) -- ++(0,\rectH) -- ++(\rectW,0) -- ++(0, -\rectH); + \draw [knJointStyle, ultra thick] (-innerend) -- ++(-0.5*\pWidth,0)(-innerend)--++(0.5*\pWidth,0); + \draw [knLinkStyle] (-center) -- (-start) (-innerend) -- (-end); + \end{scope} + } %end of code for this particular pic +}, +%------------------------------------------ +} + +%=========== ALTERNATIVES TO ISO ================================= + +\tikzset{ %definitions/pics for link symbols alternatives to ISO +%------------------------------------------ +pics/rotational colinear/.style={ %~ alternative rotational joint with axis colinear with link + code={ + \def\vsLen{0.6} + \def\vsAng{30} + \coordinate (-center) at (0,0); + \coordinate (BP) at ($(-center)-(0,{\vsLen*sin(\vsAng)})$); %low point + \draw [knJointStyle] (BP) -- ++(\vsAng:\vsLen) coordinate[name=RP] -- ++(180-\vsAng:\vsLen) coordinate[name=TP] -- ++(180+\vsAng:\vsLen) coordinate[name=LP] -- cycle (LP) -- (RP); + \draw [knLinkStyle] (TP) --++(0, 0.25) coordinate[name=-end]; + \draw [knLinkStyle] (BP) --++(0,-0.25) coordinate[name=-start]; + + \coordinate (-in) at (-start); + \coordinate (-out) at (-end); + } +}, +%------------------------------------------ +} + +%%=============== the default XYZ convention in tikz +% +% YY +% ^ +% | +% | +% +-----> XX +% / +% / +% ZZ +% +%%======== ELEMENTS TO DRAW FULL CHAINS WITH 3D EQUIVALENTS ===== +\tikzset{ +%----------------------------------------------------------------------- +pics/linear 3D/.style={ % linear link in 3D generic that accepts one argument and no terminal lines +% Arg 1 -> direction of motion +% Meanings: +%Absent: defaults to the right (5) with simple ends drawn (for illustration) +%The remainder options do not draw end segments and add a plane for thr direction of motion: +%1 top +%2 bottom +%3 near (front/closer) +%4 far (back of page) +%5 right +%6 left + code={ + \def\cubedge{0.75}% cube edge + \def\plangap{0.15}% gap of extra plane for motion indication + %0.353553=cos(45)/2 + %some points below seem not perfect at larger vlues of cube size :-( + \def\halfEdge{\cubedge*0.512} %should be 0.5 but tikz is not using perfect ortogonal perspective and this is relevant for occluding cases.. :-( + \coordinate (-center) at (0,0,0); %The usual default + \coordinate (-refstart) at ($(-center)+(-\cubedge/2,-\cubedge/2,-\cubedge/2)$); %easier to start in the back left lower vertex :-) + \coordinate (-label) at ($(-refstart)+(\cubedge/4,\cubedge/4,\cubedge/4)$); %central place for a label + + %Command to draw the main cube. Invoke below in the right order +\newcommand{\knDrawMainCube}{ + \draw [cube face 1] (-refstart) -- ++(0,\cubedge,0) -- ++(\cubedge,0,0) -- ++(0,-\cubedge,0) -- cycle; %back + \draw [cube face 1] (-refstart) -- ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(0,0,-\cubedge) -- cycle; %left + \draw [cube face 1] (-refstart) -- ++(0,0,\cubedge) -- ++(\cubedge,0,0) -- ++(0,0,-\cubedge) -- cycle; %bottom + \draw [cube face 1] (-refstart) ++(0,\cubedge,0) -- ++(0,0,\cubedge) -- ++(\cubedge,0,0) -- ++(0,0,-\cubedge) -- cycle; %top + \draw [cube face 1] (-refstart) ++(\cubedge,0,0) -- ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(0,0,-\cubedge) -- cycle; %right + \draw [cube face 1] (-refstart) ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(\cubedge,0,0) -- ++(0,-\cubedge,0) -- cycle; %frontal +} + + \def\arg{#1} %if absent, a default to the right with simple ends drawn (for illustration) + \def\TTT {1} %no ends extra plane to top + \def\BBB {2} %no ends extra plane to bottom + \def\NNN {3} %no ends extra plane to near (front/closer) + \def\FFF {4} %no ends extra plane to far (back of page) + \def\RRR {5} %no ends extra plane to right + \def\LLL {6} %no ends extra plane to left + + %Adapt behavior depending on argument + \if\arg\TTT %1 is to draw plane on the top + \knDrawMainCube + \draw [cube face 1] (-refstart) ++(0,{\cubedge+\plangap},0) -- ++(0,0,\cubedge) -- ++(\cubedge,0,0) -- ++(0,0,-\cubedge) -- cycle; %after top + + \coordinate (-east) at ($(-center)+(\cubedge/2,0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge*1.353553,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,{\cubedge/2+\plangap},0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553,-\halfEdge*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-out) at (-north); + \coordinate (-in) at (-south); + \else + \if\arg\BBB %2 is to draw plane below +% \begin{pgfonlayer}{background} + \draw [cube face 1] (-refstart) ++(0,-\plangap,0) -- ++(0,0,\cubedge) -- ++(\cubedge,0,0) -- ++(0,0,-\cubedge) -- cycle; %after down +% \end{pgfonlayer}{background} + \knDrawMainCube + + \coordinate (-east) at ($(-center)+(\cubedge/2,0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge*1.353553-\plangap,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553,-\halfEdge*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-out) at (-south); + \coordinate (-in) at (-north); + \else + \if\arg\NNN %3 is to draw plane on the front (near) far) + \knDrawMainCube + \draw [cube face 1] (-refstart) ++(0,0,\cubedge+\plangap) -- ++(\cubedge,0,0) -- ++(0,\cubedge,0) -- ++(-\cubedge,0,0) -- cycle; %afterfront + + \coordinate (-east) at ($(-center)+(\cubedge/2,0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553-1.353553*\plangap*0.28,0,0)$); %adjust X for hidden line effect. Formula is approx but irregularities found in defining it + \coordinate (-south) at ($(-center)+(0,-\halfEdge*1.3536-1.353553*\plangap*0.28,0)$); %adjust Y for hidden line effect. Formula is approx but irregularities found in defining it + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553-\plangap/2*0.353553,-\halfEdge*0.353553-\plangap/2*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-in) at (-back); + \coordinate (-out) at (-front); + \else + \if\arg\FFF %4 is to draw plane on the back far) +% \begin{pgfonlayer}{background} + \draw [cube face 1] (-refstart) ++(0,0,-\plangap) -- ++(\cubedge,0,0) -- ++(0,\cubedge,0) -- ++(-\cubedge,0,0) -- cycle; + %afterback + % \end{pgfonlayer}{background} + \knDrawMainCube + + \coordinate (-east) at ($(-center)+(\cubedge/2,0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge*1.353553,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553-\plangap/2*0.353553,-\halfEdge*0.353553-\plangap/2*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553+\plangap*0.353553,\halfEdge*1.353553+\plangap*0.353553,0)$); + \coordinate (-out) at (-back); + \coordinate (-in) at (-front); + \else + \if\arg\RRR %5 is to draw plane on the right + \knDrawMainCube + \draw [cube face 1] (-refstart) ++({\cubedge+\plangap},0,0) -- ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(0,0,-\cubedge) -- cycle; %afterright + + \coordinate (-east) at ($(-center)+({\cubedge/2+\plangap},0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge2*1.353553,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553-\plangap/2*0.353553,-\halfEdge*0.353553-\plangap/2*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-out) at (-east); + \coordinate (-in) at (-west); + \else + \if\arg\LLL %6 is to draw plane on the left + % \begin{pgfonlayer}{background} + \draw [cube face 1] (-refstart) ++(-\plangap,0,0) -- ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(0,0,-\cubedge) -- cycle; %afterleft + % \end{pgfonlayer} + \knDrawMainCube + + \coordinate (-east) at ($(-center)+(\cubedge/2,0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553-\plangap,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge*1.353553,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553,-\halfEdge*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-out) at (-west); + \coordinate (-in) at (-east); + \else %other values (or none) is to draw a right and plane and simple pins right/left + \knDrawMainCube + \draw [cube face 1] (-refstart) ++({\cubedge+\plangap},0,0) -- ++(0,0,\cubedge) -- ++(0,\cubedge,0) -- ++(0,0,-\cubedge) -- cycle; %afterright + + \coordinate (-east) at ($(-center)+({\cubedge/2+\plangap},0,0)$); + \coordinate (-west) at ($(-center)+(-\halfEdge*1.353553,0,0)$); %adjust X for hidden line effect + \coordinate (-south) at ($(-center)+(0,-\halfEdge2*1.353553,0)$); %adjust Y for hidden line effect + \coordinate (-north) at ($(-center)+(0,\cubedge/2,0)$); + \coordinate (-front) at ($(-center)+(-\halfEdge*0.353553-\plangap/2*0.353553,-\halfEdge*0.353553-\plangap/2*0.353553,0)$); + \coordinate (-back) at ($(-center)+(\halfEdge*1.353553,\halfEdge*1.353553,0)$); + \coordinate (-out) at (-east); + \coordinate (-in) at (-west); + \draw [knLinkStyle] (-out) -- ++(0.5cm,0) node [inner sep=0] (-neweast) {}; + \draw [knLinkStyle] (-in) -- ++(-0.5cm,0) node [inner sep=0] (-newwest) {}; + \coordinate (-east) at (-neweast); + \coordinate (-west) at (-newwest); + \coordinate (-out) at (-east); + \coordinate (-in) at (-west); + \fi %of LLL + \fi %RRR + \fi %of FFF + \fi %of NNN + \fi %of BBB + \fi %of TTT + \coordinate (-top) at (-north); + \coordinate (-bottom) at (-south); + \coordinate (-end) at (-out); + \coordinate (-start) at (-in); + + % For illustration purposed only... +%\draw [red](-center) -- ++(3,0,0) +% (-center) -- ++(0,3,0) +% (-center) -- ++(0,0,6) +% ; +%\draw [dashed] (-center) -- ++(-3,0,0) +% (-center) -- ++(0,-3,0) +% (-center) -- ++(0,0,-6) +% ; + +% \foreach \n in {A,B,C,D,E,F,G,H,J,K,O} +% \foreach \n in {in,out} % +% \foreach \n in {start,end} % +% \foreach \n in {center,east,west,north,south,front,back,in,out}% +% \fill (-\n) circle (0.5pt) node [inner sep=0,anchor=south,yshift=1pt,font={\tiny\sffamily}] {\n}; + } %end of code for this particular pic +}, +%----------------------------------------------------------------------- +%Generic gripper with two fingers with variable orientation +pics/gripper/.style={ % +%Arg 1 -> direction (times 90º) to orient starting with 0 to the right [0] +%Arg 2 -> bool draw in pespective[0] + code={ +% ----START ANALYSE ARGUMENTS AND SET DEFAULTS -------------------------- + \ifthenelse{ \equal{#1}{}} {\def\allArgs{/}} {\def\allArgs{#1}} + \setsepchar[.]{/} % "/" is the separator "." is the second level separator + \readlist\myArgs{\allArgs} + \ifthenelse{ \myArgslen > 0} {\itemtomacro\myArgs[1]\fDir} {\def\fDir{}} + \ifthenelse{ \myArgslen > 1} {\itemtomacro\myArgs[2]\fPerspective}{\def\fPerspective{}} + %Test if any parameter is blank and put the default in that case + \ifthenelse{ \equal{\fDir}{} } {\def\fDir{0}} {} %default 0 - to the right + \ifthenelse{ \equal{\fPerspective}{}}{\def\fPerspective{0}} {} %default 0 - no perspective +%-----------------------END ANALYSE ARGUMENTS AND SET DEFAULTS ------------------- + + \coordinate (-center) at (0,0); + + \def\knxSLANT{0} %default: no slant + \def\knySCALE{1} %default: no change in y scale + \def\knYES{1} + + \if\fPerspective\knYES + \def\knySCALE{0.5} + \ifodd\fDir %1,3 + \def\knxSLANT{-1} + \else %even: 0,2 + \def\knxSLANT{1} + \fi + \fi + %Details: if perspective is 0 + % simple rotation + % if perspective is 1: + % yscale=0.5 (diagonal lengths are half in perspective) + % xslant= 1 if dir is even + % xslant=-1 if dir is odd + \begin{scope}[rotate={90*\fDir},xslant=\knxSLANT] + \coordinate (-fingertip1) at (0.5,\knySCALE*0.5); + \draw [gripper 1] (-fingertip1) -- ++(-0.5,0) -- ++(0,-1*\knySCALE) -- ++(0.5,0) coordinate (-fingertip2); + \coordinate (-in) at (0,0); + \coordinate (-start) at (-in); \coordinate (-out) at (-in); \coordinate (-end) at (-out); + \end{scope} + } %end of code for this particular pic +}, +% +} + +%Configurations for rotational 3D joints. Edit at will :-) +\def\Lcyl{1} %Cylinder length (1.75) %was 1.5 %was 1.25 +\def\Hcyl{0.75} %Cylinder height (diameter) (1) %was 0.75 +\def\Wcyl{0.15} %Ellipse minor semi-axis (valid for H and V versions) (0.2) +\def\armRight{0.3} %Arm on the right (0.4) +\def\armLeft{\armRight} %Arm on the left (similar to right) +\def\armGap{0.45} %Gap between cylinder and arm bar (0.7) + +%==================== NEW VARIANTS OF NON ISO =================== +\tikzset{ +%This pic can be rotated (and What about a V version to have node names consistent with actual position? Being built below) +pics/rotational 3D H/.style={ %rotational joint in 3D in Horizontal position +% Arg 1 %if absent a default with simple ends +% 0: no ends. A simple cylinder +% 1: arm at top +% 2: arm at bottom +% 3: arm at near (front/closer) +% 4: arm at far (back of page) + code={ + %Draw the horizontal cylinder with visible face on the right + \draw [knJointStyle] (\Lcyl/2,0) ellipse ({\Wcyl} and \Hcyl/2); %right ellipse + \draw [knJointStyle,fill=white] (\Lcyl/2,\Hcyl/2) -- ++(-\Lcyl,0) arc (90:270:{\Wcyl} and \Hcyl/2) -- ++(\Lcyl,0) arc (270:90:{\Wcyl} and \Hcyl/2) ; %Remainder + %Create auxiliary points + \coordinate (-center) at (0,0); %center point + \coordinate (-O) at (-center); %center point + \coordinate (-A) at (\Lcyl/2,0); %right center point + \coordinate (-C) at ($(-A) + (\armRight,0)$); %east extremity + \coordinate (-B) at (-\Lcyl/2-\Wcyl,0); %right center point + \coordinate (-D) at ($(-A) - (\Lcyl,0) - (\armLeft,0)$); %west extremity + \coordinate (-E) at (0,\Hcyl/2); %top point on surface + \coordinate (-F) at (0,-\Hcyl/2); %bottom point on surface + \coordinate (-G) at ($(-E) + (0,\armGap)$); %top arm center + \coordinate (-H) at ($(-F) - (0,\armGap)$); %bottom arm center + \coordinate (-J) at ($(0,0) + (45:{\armGap+\Hcyl/4})$); %back arm center + \coordinate (-K) at ($(0,0) + (-135:{\armGap+\Hcyl/4})$); %front arm center + \coordinate (-east) at (-C); + \coordinate (-west) at (-D); + \coordinate (-label) at ($(-center)-(\Hcyl/6,0pt)$); %adjusted a bit to the left + %Define some macros to test argument + \def\arg{#1} %if absent a default with simple ends + \edef\NOENDS{0}% no ends. A simple cylinder + \def\TTT {1} %top + \def\BBB {2} %bottom + \def\NNN {3} %near (front/closer) + \def\FFF {4} %far (back of page) + %Adapt behavior depending on argument + \if\arg\TTT %1 is to draw arm on the top (use \if not \ifx !!!) + \coordinate (-south) at (-F); \coordinate (-start) at (-south); \coordinate (-in) at (-south); + \coordinate (-north) at (-G); \coordinate (-end) at (-north); \coordinate (-out) at (-north); + \draw [knLinkStyle] (-A) -- (-C) |- (-G); %upper arm + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-G) -| (-D) -- (-B); %upper arm + \end{pgfonlayer}{background} + \else + \if\arg\BBB %2 is to draw arm on the bottom + \coordinate (-south) at (-H); \coordinate (-end) at (-south); \coordinate (-out) at (-south); + \coordinate (-north) at (-E); \coordinate (-in) at (-north); \coordinate (-start) at (-north); + \draw [knLinkStyle] (-A) -- (-C) |- (-H); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-H) -| (-D) -- (-B); %lower arm + \end{pgfonlayer}{background} + \else + \if\arg\NNN %3 is to draw arm on the front ()near) + \coordinate (-south) at (-F); \coordinate (-in2) at (-south); \coordinate (-start2) at (-south); + \coordinate (-north) at (-E); + \coordinate (-in) at ($(0,0) + (45:{0.707*\Hcyl})$); + \coordinate (-start) at (-in); + \coordinate (-out) at (-K); \coordinate (-end) at (-out); +% \draw [knJointStyle] (-A) -- (-C) to [45-] (-K) -- ++(-\Lcyl/2-\armRight,0) -- (-D) -- (-B); %front arm + \draw [knLinkStyle] (-A) -- (-C) to [45-] (-K); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-K) -- ++(-\Lcyl/2-\armRight,0) -- (-D) -- (-B); %front arm + \end{pgfonlayer}{background} + \else + \if\arg\FFF %4 is to draw arm on the back far) + \coordinate (-south) at (-F); + \coordinate (-in) at ($(0,0) + (-135:{\Hcyl/4})$); \coordinate (-start) at (-in); + \coordinate (-north) at (-J); \coordinate (-out) at (-north); \coordinate (-end) at (-north); +% \draw [knJointStyle] (-B) -- (-D) to [45-] (-J) -- ++(\Lcyl/2+\armRight,0) -- (-C) -- (-A); % back arm + \draw [knLinkStyle] (-A) -- (-C) -- ++(45:{\Hcyl/4+\armGap}) -- (-J); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-J) -- ++({-\Lcyl/2-\armLeft},0) -- (-D) -- (-B); + \end{pgfonlayer} + \else + \if\arg\NOENDS %0 is not to draw any ends or arms so adjust + \coordinate (-east) at (-A); + \coordinate (-west) at (-B); + \coordinate (-south) at (-F); + \coordinate (-north) at (-E); + \coordinate (-in) at (-west); \coordinate (-start) at (-in); + \coordinate (-out) at (-east); \coordinate (-end) at (-out); + \else %other values (or none) is not to draw arm only pins + \coordinate (-south) at (-F); + \coordinate (-north) at (-E); + \coordinate (-in) at (-west); \coordinate (-start) at (-in); + \coordinate (-out) at (-east); \coordinate (-end) at (-out); + \draw [knLinkStyle] (-A) -- (-C); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-B) -- (-D); + \end{pgfonlayer} + \fi %of NOENDS + \fi %of FFF + \fi %of NNN + \fi %of BBB + \fi %of TTT + % For illustration purposed only... +% \foreach \n in {A,B,C,D,E,F,G,H,J,K,O} +% \foreach \n in {in,out} % +% \foreach \n in {start,end} % +% \foreach \n in {center,east,west,north,south} % north,south coincide with in/out +% \fill (-\n) circle (0.5pt) node [inner sep=0,anchor=south,yshift=1pt,font={\tiny\sffamily}] {\n}; + } +}, +%------------------------------------------------- +pics/rotational 3D P/.style={ %rotational 3D joint in perspective +% Arg 1 -> direction of the arm coming out of the cylinder +% 1 %arm on right +% 2 %arm on left +% 3 %arm up +% 4 %arm down +% 0 or no argment % raw cylinder with no ends at all + code={ + %Create auxiliary points + \coordinate (-center) at (0,0); %center point + \coordinate (-O) at (-center); %center point + \coordinate (-A) at ($(-center) + (-135:{\Lcyl/4})$); %right cyl center, start point of circle +% \coordinate (-B) at ($ (-A) + (45:{\Lcyl/2+\Hcyl/2}) $); %Left cyl center + \coordinate (-B) at ($ (-A) + (45:{\Lcyl/2}) $); %Left cyl center + \coordinate (-C) at ($ (-A) + (-135:{\armRight/2)})$); %right arm extremity + \coordinate (-D) at ($ (-A) + (45:{\Lcyl/2+\armLeft/2)})$); %left arm extremity + \coordinate (-D) at ($ (-B) + (45:{\armLeft/2)})$); %left arm extremity + \coordinate (-E) at (0, \Hcyl/2); %top point of cylinder surface + + \coordinate (-G) at (0, {\Hcyl/2+\armGap}); % arm center top + \coordinate (-H) at (0, {-\Hcyl/2-\armGap}); %Arm center bottom + \coordinate (-J) at ({\Hcyl/2+\armGap},0); %Arm center right + \coordinate (-K) at ({-\Hcyl/2-\armGap},0); %Arm center left + \coordinate (-L) at (\Hcyl/2,0,0); % right side of cylinder surface + + \path [name path=vsLocalCirc] (-A) ellipse ({\Hcyl/2} and {\Hcyl/2}); + \path [name path=vsHorizLine] (-center) -- ++(-\Hcyl,0); + \path [name path=vsVertiLine] (-center) -- ++(0,-\Hcyl); + \path [name intersections={of={vsHorizLine} and {vsLocalCirc}}] ; + \coordinate (-M) at (intersection-1); % left point of cylinder surface + \path [name intersections={of={vsVertiLine} and {vsLocalCirc}}] ; + \coordinate (-F) at (intersection-1); % Bottom point of cylinder surface + + \path [name path=vsDiagLine] (-B) -- ++(45:\Hcyl); + \path [name path=vsRestOfCyl] ($(-A)+(135:{\Hcyl/2})$) -- + ++(45:\Lcyl/2) arc (135:-45:{\Hcyl/2} and {\Hcyl/2}) -- + ++(-135:\Lcyl/2) arc (-45:135:{\Hcyl/2} and {\Hcyl/2}); + \path [name intersections={of={vsDiagLine} and {vsRestOfCyl}}] ; + \coordinate (-N) at (intersection-1); % far point of cylinder in diag + + + \coordinate (-southwest) at (-C); + \coordinate (-northeast) at (-D); + \coordinate (-label) at ($(-center)!0.7!(-D)$); %some point to place label with enough clearance + \coordinate (-near) at (-C); + \coordinate (-far) at (-D); + + \coordinate (-west) at (-M); %default for simple cylinder + \coordinate (-east) at (-L); %default for simple cylinder + + %Draw the perspective cylinder with visible face on the right (facing out) + %Actually it is a circle in ortogonal projection... anyway... + \draw [knJointStyle] (-A) ellipse ({\Hcyl/2} and {\Hcyl/2}); %front ellipse + \newcommand{\knDrawCylinderLateral}{ + \draw [knJointStyle,fill=white] ($(-A)+(135:{\Hcyl/2})$) -- + ++(45:\Lcyl/2) arc (135:-45:{\Hcyl/2} and {\Hcyl/2}) -- + ++(-135:\Lcyl/2) arc (-45:135:{\Hcyl/2} and {\Hcyl/2}); %rest of cylinder filled with white + } + \def\arg{#1} + \def\RRR {1} %arm on right + \def\LLL {2} %arm on left + \def\UUU {3} %arm up + \def\DDD {4} %arm down + \def\NOENDS{0} %no ends at all + +% \begin{pgfonlayer}{background} %Needed to take advantage of hidden lines in some arms...) + \if\arg\RRR %1 is to draw arm on the right + \coordinate (-south) at (-F); \coordinate (-start bottom) at (-south); \coordinate (-in bottom) at (-south); + \coordinate (-east) at (-J); \coordinate (-end) at (-east); \coordinate (-out) at (-east); + \coordinate (-north) at (-E); \coordinate (-in top) at (-north); \coordinate (-start top) at (-north); + \coordinate (-west) at (-M); \coordinate (-in left) at (-west); \coordinate (-start left) at (-west); + \coordinate (-in) at (-in left); \coordinate (-start) at (-start left); + %Right + %Some tricks because to [45-] forces some specific path :-( +% \draw [knLinkStyle](-A) -- (-C)(-J) to[45-] (-C)(-J) -- ++(45:{\Lcyl/4+\armLeft/2}) -- (-D) -- (-B); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-J) -- ++(45:{\Lcyl/4+\armLeft/2}) -- (-D) -- (-B); %back part of arm + \knDrawCylinderLateral + \draw [knLinkStyle] (-A) -- (-C) -- ++({\Hcyl/2+\armGap},0) -- (-J); %front part of arm +% \end{pgfonlayer} + \else + \if\arg\LLL %2 is to draw arm on the left + \coordinate (-south) at (-F); \coordinate (-start bottom) at (-south); \coordinate (-in bottom) at (-south); + \coordinate (-east) at (-L); \coordinate (-in right) at (-east); \coordinate (-start right) at (-east); + \coordinate (-north) at (-E); \coordinate (-in top) at (-north); \coordinate (-start top) at (-north); + \coordinate (-west) at (-K); \coordinate (-out) at (-west); \coordinate (-end) at (-west); + \coordinate (-in) at (-in right); \coordinate (-start) at (-start right); + %Left + %\draw [knJointStyle](-A) -- (-C) -- ++(180:{\Hcyl/2+\armGap}) -- (-K) to[45-] (-D) -- (-B); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle](-K) to[45-] (-D) -- (-B); +% \end{pgfonlayer} + \knDrawCylinderLateral + \draw [knLinkStyle](-A) -- (-C) -- ++(180:{\Hcyl/2+\armGap}) -- (-K); + \else + \if\arg\UUU %3 is to draw arm on the upper part + \coordinate (-south) at (-F); \coordinate (-start bottom) at (-south); \coordinate (-in bottom) at (-south); + \coordinate (-east) at (-L); \coordinate (-in right) at (-east); \coordinate (-start right) at (-east); + \coordinate (-north) at (-G); \coordinate (-out) at (-north); \coordinate (-end) at (-north); + \coordinate (-west) at (-M); \coordinate (-in left) at (-west); \coordinate (-start left) at (-west); + \coordinate (-in) at (-in bottom); \coordinate (-start) at (-start bottom); + %Up +% \draw [knJointStyle](-A) -- (-C)(-G) to[45-] (-C)(-G) -- ++(45:{\Lcyl/4+\armLeft/2}) -- (-D) -- (-B); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-G) -- ++(45:{\Lcyl/4+\armLeft/2}) -- (-D) -- (-B); ; +% \end{pgfonlayer} + \knDrawCylinderLateral + \draw [knLinkStyle](-A) -- (-C) -- ++(0,\Hcyl/2+\armGap) -- (-G); + \else + \if\arg\DDD %4 is to draw arm on the lower part) + \coordinate (-south) at (-H); \coordinate (-end) at (-south); \coordinate (-out) at (-south); + \coordinate (-east) at (-L); \coordinate (-in right) at (-east); \coordinate (-start right) at (-east); + \coordinate (-north) at (-E); \coordinate (-in top) at (-north); \coordinate (-start top) at (-north); + \coordinate (-west) at (-M); \coordinate (-in left) at (-west); \coordinate (-start left) at (-west); + \coordinate (-in) at (-in top); \coordinate (-start) at (-start top); + %Down + %\draw [knJointStyle](-A) -- (-C) -- ++(-90:{\Hcyl/2+\armGap}) -- (-H) to[45-] (-D) -- (-B); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-H)to[45-] (-D) -- (-B); +% \end{pgfonlayer} + \knDrawCylinderLateral + \draw [knLinkStyle](-A) -- (-C) -- ++(-90:{\Hcyl/2+\armGap}) -- (-H); + \else + \if\arg\NOENDS %0 is to draw no extremities or arm + \coordinate (-south) at (-F); + \coordinate (-north) at (-E); + \coordinate (-southwest) at (-A); + \coordinate (-northeast) at (-B); + \coordinate (-in near) at (-A); + \coordinate (-in left) at (-M); \coordinate (-start left) at (-in left); + \coordinate (-in bottom) at (-south); \coordinate (-start bottom) at (-in bottom); + \coordinate (-in top) at (-north); \coordinate (-start top) at (-in top); + \coordinate (-out far) at (-N); \coordinate (-out right) at (-east); + \coordinate (-in) at (-in left); \coordinate (-start) at (-in); + \coordinate (-out) at (-out right); \coordinate (-end) at (-out); + \knDrawCylinderLateral + \else %other values (or none) is not to draw arm; only pins + \coordinate (-south) at (-F); + \coordinate (-north) at (-E); + \coordinate (-in) at (-near); \coordinate (-start) at (-in); + \coordinate (-out) at (-N); \coordinate (-end) at (-out); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-B) -- (-D); +% \end{pgfonlayer} + \knDrawCylinderLateral + \draw [knLinkStyle] (-A) -- (-C); + \fi %of NOENDS + \fi %of DDD + \fi %of UUU + \fi %of LLL + \fi %of RRR +% \end{pgfonlayer} + % For illustration purposed only... +% \foreach \n in {A,B,C,D,E,F,G,H,J,K,L,M} +% \foreach \n in {in,out} % +% \foreach \n in {start,end} % +% \foreach \n in {center,east,west,north,south} % north,south coincide with in/out +% \fill (-\n) circle (0.5pt) node [inner sep=0,anchor=south,yshift=1pt,font={\tiny\sffamily}] {\n}; + } +}, +%------------------------------------------------- +pics/rotational 3D V/.style={ %rotational joint in 3D in Vertical position +% Arg 1 %if absent a default with simple ends +% 0: no ends. A simple cylinder +% 1: arm at left +% 2: arm at right +% 3: arm at near (front/closer) +% 4: arm at far (back of page) + code={ %copied code orinally from the horizontal and rotated it :-) + \begin{scope}[rotate=90,yscale=-1] %use yscale -1 to have arm=1 on the right and the perspective variants in the right direction + %Draw the horizontal cylinder with visible face on the right + \draw [knJointStyle] (\Lcyl/2,0) ellipse ({\Wcyl} and \Hcyl/2); %right (top) ellipse + \draw [knJointStyle,fill=white] (\Lcyl/2,\Hcyl/2) -- ++(-\Lcyl,0) arc (90:270:{\Wcyl} and \Hcyl/2) -- + ++(\Lcyl,0) arc (270:90:{\Wcyl} and \Hcyl/2) ; %Remainder + + %%% + \path [name path=vsDiagLine] (0,0) -- ++(45:\Hcyl); + \path [name path=vsRestOfCyl] (\Lcyl/2,\Hcyl/2) -- ++(-\Lcyl,0) arc (90:270:{\Wcyl} and \Hcyl/2) -- + ++(\Lcyl,0) arc (270:90:{\Wcyl} and \Hcyl/2) ; + \path [name intersections={of={vsDiagLine} and {vsRestOfCyl}}] ; + \coordinate (-N) at (intersection-1); % lateral far point of cylinder in diag + + %Create auxiliary points + \coordinate (-center) at (0,0); %center point + \coordinate (-O) at (-center); %center point + \coordinate (-A) at (\Lcyl/2,0); %right center point + \coordinate (-C) at ($(-A) + (\armRight,0)$); %east extremity + \coordinate (-B) at (-\Lcyl/2-\Wcyl,0); %right center point + \coordinate (-D) at ($(-A) - (\Lcyl,0) - (\armLeft,0)$); %west extremity + \coordinate (-E) at (0,\Hcyl/2); %top point on surface + \coordinate (-F) at (0,-\Hcyl/2); %bottom point on surface + \coordinate (-G) at ($(-E) + (0,\armGap)$); %top arm center + \coordinate (-H) at ($(-F) - (0,\armGap)$); %bottom arm center + \coordinate (-J) at ($(0,0) + (45:{\armGap+\Hcyl/4})$); %back arm center + \coordinate (-K) at ($(0,0) + (-135:{\armGap+\Hcyl/4})$); %front arm center + \coordinate (-east) at (-E); + \coordinate (-west) at (-F); + \coordinate (-label) at ($(-center)-(\Hcyl/6,0pt)$); %adjusted a bit to the bottom + %Define some macros to test argument + \def\arg{#1} %if absent a default with simple ends + \edef\NOENDS{0}% no ends. A simple cylinder + \def\TTT {1} %top (when rotated - left) + \def\BBB {2} %bottom (when rotated - right) + \def\NNN {3} %near (front/closer) + \def\FFF {4} %far (back of page) + %Adapt behavior depending on argument + \if\arg\TTT %1 is to draw arm on the top (right) (use \if not \ifx !!!) + \coordinate (-south) at (-D); \coordinate (-start) at (-F); \coordinate (-in) at (-start); + \coordinate (-north) at (-C); \coordinate (-end) at (-G); \coordinate (-out) at (-end); +% \draw [knLinkStyle] (-A) -- (-C) |- (-G) -| (-D) -- (-B); %upper arm + \draw [knLinkStyle] (-A) -- (-C) |- (-G); %upper half arm +% \begin{pgfonlayer}{background} %not needed (and does not inherit all passed options :-(! ) + \draw [knLinkStyle] (-G) -| (-D) -- (-B); %lower half arm +% \end{pgfonlayer}{background} + \else + \if\arg\BBB %2 is to draw arm on the bottom (left) + \coordinate (-south) at (-D); \coordinate (-end) at (-H); \coordinate (-out) at (-end); + \coordinate (-west) at (-end); + \coordinate (-north) at (-C); \coordinate (-in) at (-E); \coordinate (-start) at (-in); +% \draw [knLinkStyle] (-A) -- (-C) |- (-H) -| (-D) -- (-B); %lower arm + \draw [knLinkStyle] (-A) -- (-C) |- (-H); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-H) -| (-D) -- (-B); %lower arm +% \end{pgfonlayer}{background} + \else + \if\arg\NNN %3 is to draw arm on the front (near) + \coordinate (-south) at (-D); \coordinate (-in2) at (-south); \coordinate (-start2) at (-south); + \coordinate (-north) at (-C); \coordinate (-in) at (-N); \coordinate (-start) at (-in); + \coordinate (-out) at (-K); \coordinate (-end) at (-out); +% \draw [knLinkStyle] (-A) -- (-C) to [45-] (-K) -- ++(-\Lcyl/2-\armRight,0) -- (-D) -- (-B); %front arm + \draw [knLinkStyle] (-A) -- (-C) to [45-] (-K); +% \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-K) -- ++(-\Lcyl/2-\armRight,0) -- (-D) -- (-B); %front arm +% \end{pgfonlayer}{background} + \else + \if\arg\FFF %4 is to draw arm on the back far) + \coordinate (-south) at (-D); \coordinate (-in) at ($(-center)+(-135:\Hcyl/4)$); \coordinate (-start) at (-in); + \coordinate (-north) at (-C); \coordinate (-out) at (-J); \coordinate (-end) at (-out); +% \draw [knLinkStyle] (-B) -- (-D) to [45-] (-J) -- ++(\Lcyl/2+\armRight,0) -- (-C) -- (-A); % back arm + \draw [knLinkStyle] (-A) -- (-C) -- ++(45:{\Hcyl/4+\armGap}) -- (-J); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-J) -- ++({-\Lcyl/2-\armLeft},0) -- (-D) -- (-B); + \end{pgfonlayer} + \else + \if\arg\NOENDS %0 is not to draw any ends or arms so adjust + \coordinate (-east) at (-F); + \coordinate (-west) at (-E); + \coordinate (-south) at (-B); + \coordinate (-north) at (-A); + \coordinate (-in) at (-south); \coordinate (-start) at (-in); + \coordinate (-out) at (-north); \coordinate (-end) at (-out); + \else %other values (or none) is not to draw arm only pins + \coordinate (-south) at (-D); + \coordinate (-north) at (-C); + \coordinate (-in) at (-south); \coordinate (-start) at (-in); + \coordinate (-out) at (-north); \coordinate (-end) at (-out); + \draw [knLinkStyle] (-A) -- (-C); + \begin{pgfonlayer}{background} + \draw [knLinkStyle] (-B) -- (-D); + \end{pgfonlayer} + \fi %of NOENDS + \fi %of FFF + \fi %of NNN + \fi %of BBB + \fi %of TTT + % For illustration purposed only... +% \foreach \n in {A,B,C,D,E,F,G,H,J,K,O} +% \foreach \n in {in,out} % +% \foreach \n in {start,end} % +% \foreach \n in {center,east,west,north,south} % north,south coincide with in/out +% \fill (-\n) circle (0.5pt) node [inner sep=0,anchor=south,yshift=1pt,font={\tiny\sffamily}] {\n}; + \end{scope} + } +}, +%------------------------------------------------- +% +} %end of tikzset +%------------------------------------------------ + +\endinput diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 7e6da476025..9ea38718747 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -427,7 +427,7 @@ my @TLP_working = qw( kalendarium kanaparser kantlipsum karnaugh karnaugh-map karnaughmap kastrup kblocks kdgdocs kdpcover kerkis kerntest ketcindy keycommand keyfloat keyindex keyparse keyreader keystroke - keyval2e keyvaltable kix kixfont + keyval2e keyvaltable kinematikz kix kixfont knitting knittingpattern knowledge knuth-errata knuth-lib knuth-local knuth-pdf koma-moderncvclassic koma-script koma-script-examples koma-script-sfs diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index ea7252cbeca..68bea293d83 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -3680,6 +3680,7 @@ $standardclean = '\.head|\.tmp|\.dvi|\.log|\.out|\.aux|\.toc|\.lof|\.lot' 'ieeetran' => 'IEEEtran.*HOWTO.pdf', 'jknapltx' => 'ubbold.fd', # clash bbold's Ubbold.fd; sauter bbold fails 'junicode' => '.pdf', # no source + 'kinematikz' => '.pdf', # no source 'latexmk' => '(sweave_|tex4ht-)latexmkrc', # case-folding clash 'maker' => 'maker_manual.pdf', # no source 'math-into-latex-4' => 'video.*zip|S.*\.pdf', # nonfree diff --git a/Master/tlpkg/tlpsrc/collection-pictures.tlpsrc b/Master/tlpkg/tlpsrc/collection-pictures.tlpsrc index ca04c9aaa68..271818c913c 100644 --- a/Master/tlpkg/tlpsrc/collection-pictures.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-pictures.tlpsrc @@ -75,6 +75,7 @@ depend hobby depend hvfloat depend istgame depend kblocks +depend kinematikz depend knitting depend knittingpattern depend ladder diff --git a/Master/tlpkg/tlpsrc/kinematikz.tlpsrc b/Master/tlpkg/tlpsrc/kinematikz.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3