我的英语不够好,所以如果问题太长,请原谅我
下一个代码不是很有趣,但它可以正确说明我的问题。
我有很多宏,实际上我需要很多临时节点。到目前为止,我尝试使用不同的名称,但这些名称太多了。现在我尝试对临时节点使用相同的名称,但我得到了一些副作用。
A] 示例 1下一个代码显示节点未在环境“tikzpicture”本地定义。问题是节点继续存在于 tikzpicture 环境之间。我想有充分的理由...
当同一个文件上有多个环境时,请确保所有点仅在新环境中定义,而不是在最后一个环境中定义。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (1,2);
\coordinate (b) at (1,3);
\coordinate (c) at (1,4);
% save
\end{tikzpicture}
\begin{tikzpicture}
\foreach \c in {a,...,c}{ \fill[red] (\c) circle (1.5 pt); }
\end{tikzpicture}
\begin{tikzpicture}
\coordinate (a) at (2,2);
\coordinate (b) at (2,3);
\coordinate (c) at (2,4);
\foreach \c in {a,...,c}{ \fill[blue] (\c) circle (1.5 pt); }
\end{tikzpicture}
%restore I would like to use the same nodes like at the beginning
\begin{tikzpicture}
\foreach \c in {a,...,c}{ \fill[red] (\c) circle (1.5 pt); } % with
\end{tikzpicture}
\end{document}
有可能用以下方法擦除两个“tikzpictures”之间的所有点
\begin{tikzpicture}
\foreach \p in {a,b,c,pta,ptb,ptc}{\pgfnoderename{}{\p}}
% \draw (a) -- (b) ;
% Latex Error: ./nested_cs.tex:59 Package pgf Error: No shape named a is known.
\end{tikzpicture}
乙] 示例 2对我来说,这是主要问题。使用宏或控制序列。关于下一个代码的一些解释。\tr``\drawpoints
并且\labelpoints
仅用于控制结果
三个宏
第一个
\subone
在这里取三个点a
,b
然后c
在这里找到一些中点pta
,ptb
然后ptc
然后
\subtwo
也使用pta
,ptb
我ptc
想限制临时点的数量并且
\main
此宏使用最后两个宏\subone
和\subtwo
。由于\subtwo
我输了pta
,ptb
并且ptc
在中定义\subone
。
两个宏之间的问题是:我需要在宏中使用 pta、ptb 和 ptc 来定义一个对象,而这个宏调用另一个也使用 pta、ptb 和 ptc 的宏。会产生一些副作用...我认为用节点名称来解决这个问题很困难,但也许可以用等方法解决\pta
。\ptb
我的问题就是找到一种方法来保存第一个pta
,ptb
并ptc
在最后一个恢复它们\subtwo
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{quotes}
%-------------------------------------------------------------
\def\tr[#1](#2,#3,#4){\draw[#1] (#2) -- (#3) -- (#4) --cycle;}
\def\drawpoints(#1){%
\foreach \pt in {#1} {\fill (\pt) circle (2 pt);}}
\def\labelpoints(#1){%
\foreach \pt in {#1} {\path coordinate["\pt" below] () at (\pt) ;}}
%-------------------------------------------------------------
\def\subone(#1,#2,#3){% the macro defines midpoints of #1#2 #1#3 and #2#3
\path[coordinate](barycentric cs:#1=1,#2=1) coordinate (ptc);
\path[coordinate](barycentric cs:#1=1,#3=1) coordinate (ptb);
\path[coordinate](barycentric cs:#2=1,#3=1) coordinate (pta);
}
%-------------------------------------------------------------
\def\subtwo(#1,#2,#3){% the macro defines the centroid of (#1,#2,#3)
% then some symetric points and the last one result
\path[coordinate](barycentric cs:#1=1,#2=1,#3=1)coordinate (ptd);
\path[coordinate](barycentric cs:#1=1,ptd=-2) coordinate (pta);
\path[coordinate](barycentric cs:#2=1,ptd=-2) coordinate (ptb);
\path[coordinate](barycentric cs:#3=1,ptd=-2) coordinate (ptc);
\path[coordinate](barycentric cs:pta=1,ptb=1,ptc=-1) coordinate (result);
}
%-------------------------------------------------------------
\def\main(#1,#2,#3){%
\subone(#1,#2,#3) % call to the first macro
\subtwo(pta,ptb,ptc) % subtwo affects the values of pta,... etc.
\draw (result) -- (pta) (result) -- (ptb) (result) -- (ptc);
}
\begin{document}
\begin{tikzpicture}
\path coordinate (a) at (0,1)
coordinate (b) at (5,2)
coordinate (c) at (1,6);
\tr[red](a,b,c)
\subone(a,b,c)
\drawpoints(a,b,c)
\drawpoints(pta,pt...,ptc) % this is a test midpoints are defined
\labelpoints(pta,pt...,ptc)
% \subtwo(a,b,c) % test subtwo is correct
% \drawpoints(pta,pt...,ptd,result)
% \labelpoints(pta,pt...,ptd,result)
% \tr[blue](pta,ptb,ptc)
\main(a,b,c)
\drawpoints(pta,pt...,ptc)
\tr[green](pta,ptb,ptc)
\labelpoints(pta,pt...,ptd,result)
\end{tikzpicture}
\end{document}
C]研究
我尝试了不同的方法。第一个想法是使用 tikz/pgf 中的工具,如
\pgfnodealias
和,pgfnoderename
但这些宏似乎
无效。
指向\pgfnodealias{n_pta}{pta}
n_pta
但是pta
当pta
重新定义时则n_pta
指向新值所以我丢失了旧值。
用\pgfnoderename{n_pta}{pta}
n_pta
替换“pta”则这个丢失了!
下一个想法:我尝试使用宏来存储坐标。我认为这是解决方案,但我错过了一些东西……例如,下一个代码(我不确定它是否正确)可以保存坐标
\makeatletter
\newdimen\pt@xa
\newdimen\pt@ya
\def\SavedCoordPoint#1#2{%
\pgfextractx{\pt@xa}{\pgfpointanchor{#2}{center}}%
\pgfextracty{\pt@ya}{\pgfpointanchor{#2}{center}}%
\pgfextract@process\tkzsavepoint{\pgfpoint{\pt@xa}{\pt@ya}}%
\global\expandafter\edef\csname #1\endcsname{\tkzsavepoint}%
}
\makeatother
% ex \SavedCoordPoint{pta}{pta}
也许这个代码可以重写,但想法是将的坐标保存pta
到宏中\pta
。现在我需要重写所有代码,因为我需要使用宏而不是节点的名称。
\pgf@process
也许另一个宏对于恢复坐标有用 。
D]具体例子
为了得到三角形 ABC 的欧拉中心,我需要
1)获取(A,B,C)的 CentroidTriangle,其\tkzDefCentroidTriangle(A,B,C){tkz@pta,tkz@ptb,tkz@ptc}
{tkz@pta,tkz@ptb,tkz@ptc}
是每个线段的中点。
2)然后我需要得到{tkz@pta,tkz@ptb,tkz@ptc}
\tkzCircumCenter(tkz@pta,tkz@ptb,tkz@ptc)
3)为了得到外心,我需要得到一些中介线……等等
每次调用时我都需要使用临时点。如果我使用不同的名称(节点),则不会出现问题,但如果我更改了名称,代码就会失败。在每个宏的开头,一个好主意是保存{tkz@pta,tkz@ptb,tkz@ptc}
它们,然后使用它们,然后在退出之前恢复它们。但是该怎么做呢?
答案1
如果我理解正确的话,你想使用相对的保存的节点在新图片中的位置。也就是说,每个节点都应引用新图片中相对于新原点的位置。
以下是一些代码,用于保存指定节点列表的所有数据,然后稍后可以在文档中恢复这些数据。它在内部使用 LaTeX3 的东西,因为它更多的是关于编程和扩展,而 L3 可以做到这一点所以容易多了。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/307356/86}
\usepackage{tikz}
\usepackage{xparse}
\ExplSyntaxOn
% We save our information in a ``property list'', which is L3's
% version of an associative array or dictionary. They keys will give
% the ability to store several groups of nodes and restore them at
% will.
\prop_new:N \g__sn_prop
% We'll need a token list for constructing the saved data.
\tl_new:N \l__sn_tmpa_tl
% This is the command that actually does the work. It constructs a
% token list which contains the code that will restore the node data
% when invoked. The two arguments are the name of this group (for
% reference later) and a comma separated list of the node names to be
% saved.
\cs_new_nopar:Npn \save_nodes:nn #1#2
{
% Clear our token list
\tl_clear:N \l__sn_tmpa_tl
% Iterate over the list of node names
\clist_map_inline:nn {#2}
{
% Before we start trying to save the node, check that it exists.
% The macro \pgf@sh@ns@nodename is only defined if that node exists.
\tl_if_exist:cT {pgf@sh@ns@##1}
{
% The node information is stored in a series of macros of the form
% \pgf@sh@XX@nodename where XX is one of the following.
\clist_map_inline:nn {ns,np,ma,nt,pi}
{
% Our token list will look like:
%
% \tl_set:cn {pgf@sh@XX@nodename} {<current contents of that macro>}
%
% This will restore \pgf@sh@XX@nodename to its current value
% when this list is invoked.
%
% This part puts the \tl_set:cn {pgf@sh@XX@nodename} in place
\tl_put_right:Nn \l__sn_tmpa_tl
{
\tl_set:cn {pgf@sh@####1@##1}
}
% Now we put the current contents in place. We're doing this in
% an expansive context to get at the contents. The \exp_not:v
% part takes the current value of \pgf@sh@XX@nodename and puts
% it in place, preventing further expansion.
\tl_put_right:Nx \l__sn_tmpa_tl {{\exp_not:v {pgf@sh@####1@##1}}}
}
}
}
% Once we've assembled our token list, we store it in the property
% list using the key we were given.
\prop_gput:NnV \g__sn_prop {#1} \l__sn_tmpa_tl
}
\cs_new_nopar:Npn \restore_nodes:n #1
{
% Restoring nodes is simple: look in the property list for the key
% and if it exists, invoke the macro stored there.
\prop_get:NnNT \g__sn_prop {#1} \l__sn_tmpa_tl
{
\tl_use:N \l__sn_tmpa_tl
}
}
% These two are wrappers around our internal commands.
%
% The first argument is the label for our group of nodes (so that we
% can refer to them later) and the second argument is a comma
% separated list of nodes to save.
\DeclareDocumentCommand \SaveNodes {m m}
{
\save_nodes:nn {#1}{#2}
}
% The argument to this is the label for our group of nodes to restore.
\DeclareDocumentCommand \RestoreNodes {m}
{
\restore_nodes:n {#1}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (1,2);
\coordinate (b) at (1,3);
\coordinate (c) at (1,4);
% save
\SaveNodes{here}{a,b,c}
\end{tikzpicture}
\begin{tikzpicture}
\fill[black] (0,0) circle (1.5 pt);
\foreach \c in {a,...,c}{ \fill[red] (\c) circle (1.5 pt); }
\end{tikzpicture}
\begin{tikzpicture}
\coordinate (a) at (2,2);
\coordinate (b) at (2,3);
\coordinate (c) at (2,4);
\fill[black] (0,0) circle (1.5 pt);
\foreach \c in {a,...,c}{ \fill[blue] (\c) circle (1.5 pt); }
\end{tikzpicture}
%restore I would like to use the same nodes like at the beginning
\begin{tikzpicture}
\RestoreNodes{here}
\fill[black] (0,0) circle (1.5 pt);
\foreach \c in {a,...,c}{ \fill[red] (\c) circle (1.5 pt); } % with
\end{tikzpicture}
\end{document}
我在原点添加了黑色圆圈,以表明使用的是原始节点,而不是新节点。我思考我保存了有关节点的所有信息,而不仅仅是它们的坐标,因此此解决方案适用于一般节点,而不仅仅是坐标。再多做一点工作,就可以在恢复阶段获取节点列表并仅恢复这些节点。
这是非 L3 版本。它以每个节点为基础工作(但如果节点始终具有相同的名称,则您可能可以将其包装起来)。
\makeatletter
\def\@savecoord#1#2{%
\expandafter\let\expandafter\sn@temp\csname pgf@sh@#1@#2\endcsname
\expandafter\def\expandafter\sn@tempb\expandafter{%
\expandafter\gdef\csname pgf@sh@#1@#2\expandafter\endcsname\expandafter{%
\sn@temp
}%
}%
\expandafter\g@addto@macro\expandafter\sn@tempa\expandafter{\sn@tempb}%
}
% {ns,np,ma,nt,pi}
\def\savecoordinate#1#2{%
\def\sn@tempa{}%
%
\@savecoord{ns}{#2}%
\@savecoord{np}{#2}%
\@savecoord{ma}{#2}%
\@savecoord{nt}{#2}%
\@savecoord{pi}{#2}%
%
\expandafter\global\expandafter\let\csname sn@#1\endcsname\sn@tempa
}
\def\restorecoordinate#1{%
\csname sn@#1\endcsname
}
\makeatother
答案2
另一种方法是创建一个包含宏节点的堆栈。每次调用宏都会在堆栈中创建新级别,并在宏结束时删除该级别。可以通过挑选节点来保留所选节点,并且只保留对未来有用的节点。
在宏的开头声明一些节点(人类可读的名称),它们将充当本地节点:它们不会覆盖现有节点并在宏的末尾消失。声明顺序必须与输出列表顺序相同。
因此多次调用宏不会造成混淆或丢失。
所有节点都在一个宏中计算,绘图是可选的:
\CercleEuler[o,I,J,K,P1,P2,P3,J1,J2,J3,G,H,O]{%
a,b,c}<fill=lightgray!20,draw=gray,semithick>
\documentclass{article}
\usepackage{tikz,xparse}
\usetikzlibrary{quotes,through,calc}
\ExplSyntaxOn
\NewDocumentCommand{\ExtractFromList}{%
m % macro
m % list
m % number : -1 for the last
}
{
\tl_set:Nx #1 {\clist_item:Nn #2 { #3 } }
}
\NewDocumentCommand{\NewPoints}{m}
{
\clist_map_inline:nn { #1 }
{
\cs_set:cpx { ##1 } { a-\NumNode-\theLittNode }
\stepcounter{LittNode}
}
}
\ExplSyntaxOff
% counter for naming nodes
\newcounter{LittNode}
% level of calling
\pgfmathtruncatemacro{\NumNode}{0}
% node named #1 at the current level
\def\N#1{a-\NumNode-#1}
\makeatletter % ------------------------ #### Make @ Letter
% -------------------------------------- #### AtBeginTikzMacro
\newcommand{\AtBeginTikzMacro}[1]{%
\pgfmathtruncatemacro{\NumNode}{\NumNode+1}
\expandafter\edef\csname OutPut-\NumNode\endcsname{#1}
\setcounter{LittNode}{1}
\begingroup % au début de chaque macro
}
% -------------------------------------- #### KeepUsefullNodes
\newcommand{\KeepUsefullNodes}{%
\endgroup % à la fin de chaque macro
\edef\Sortie{\csname OutPut-\NumNode \endcsname}
\foreach \Nd [count=\i from 1]
in \Sortie {%
\coordinate (\Nd) at (\N{\i}) ;
}
\pgfmathtruncatemacro{\NumNode}{\NumNode-1}
}
%-----------------------------------------------------------
\def\tr[#1](#2,#3,#4){\draw[#1] (#2) -- (#3) -- (#4) --cycle;}
\def\drawpoints(#1){%
\foreach \pt in {#1} {\fill (\pt) circle (2 pt);}}
\def\labelpoints(#1){%
\foreach \pt in {#1} {\path coordinate["\pt" below] () at (\pt) ;}}
%-----------------------------------------------------------
% #### --------------------------------- #### NodeAngle ####
% #1 premier point
% #2 second point
% On récupère le résultat dans \MyAngle
\newcommand{\NodeAngle}[3][\MyAngle]{%
\pgfextra{
\pgfmathanglebetweenpoints%
{\pgfpointanchor{#2}{center}}%
{\pgfpointanchor{#3}{center}}%
\global\let#1\pgfmathresult
}}
% #### --------------------------------- #### NodeDist ####
% #1 premier point
% #2 second point
% On récupère le résultat dans \MyDist
\newcommand{\NodeDist}[3][\MyDist]{%
\pgfpointdiff{\pgfpointanchor{#2}{center}}
{\pgfpointanchor{#3}{center}}
% no need to use a new dimen
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
% to convert from pt to cm
\pgfmathparse{veclen(\pgf@xa,\pgf@ya)/28.45274}
\global\let#1\pgfmathresult % we need a global macro
}
% #### --------------------------------- #### AngleBAC ####
\newcommand{\AngleBAC}[2][A]{%
\begingroup
\edef\List{#2}
\ExtractFromList\A\List{2}
\ExtractFromList\B\List{1}
\ExtractFromList\C\List{3}
\pgfmathanglebetweenpoints
{\pgfpointanchor{\A}{center}}
{\pgfpointanchor{\B}{center}}
\let\Angl@A\pgfmathresult ;
\pgfmathanglebetweenpoints
{\pgfpointanchor{\A}{center}}
{\pgfpointanchor{\C}{center}}
\let\Angl@B\pgfmathresult ;
\pgfmathparse{\Angl@B-\Angl@A}
\let\Angl@A\pgfmathresult ;
\expandafter\xdef\csname angle#1\endcsname{\Angl@A}
\pgfmathparse{cos(\Angl@A)}
\expandafter\xdef\csname Cos#1\endcsname{\pgfmathresult}
\pgfmathparse{sin(\Angl@A)}
\expandafter\xdef\csname Sin#1\endcsname{\pgfmathresult}
\pgfmathparse{tan(\Angl@A)}
\expandafter\xdef\csname Tan#1\endcsname{\pgfmathresult}
\endgroup
}
% #### --------------------------------- #### Milieux ####
\NewDocumentCommand{\Milieux}{%
s % * liste de segments, polygone sinon
O{} % liste de retour
m % liste d'entrée
}{%
\AtBeginTikzMacro{#2}
\IfBooleanTF{#1}{%
% On peut utiliser foreach, mais il ne faut jamais
% que les noms de variables croisent les noms des nodes
\foreach \A@/\B@ in {#3} {%
% On utilise le même nom de macro,
% mais elle pointe à chaque fois un nouveau nom de node.
% A la fin on récupère les noms de node
% pas le nom des macros.
% On utilisera le même truc à chaque fois que
% c'est possible.
% On déclare un node local ou un liste à la fois,
% sans le \
\NewPoints{Milieu}
% Dans une macro, le nom des nodes locaux sont utilisés
% avec un \ puisque que ce sont des macros
\coordinate (\Milieu) at (barycentric cs:\A@=1,\B@=1) ;
}
}{%
\def\List{#3}
\ExtractFromList\Lastx\List{-1}
\foreach \x@
[remember=\x@ as \lastx (initially \Lastx)] in {#3} {%
\NewPoints{Milieu}
\coordinate (\Milieu) at (barycentric cs:\lastx=1,\x@=1) ;
}
}
\KeepUsefullNodes
}
% #### --------------------------------- #### DtEuler ####
\newcommand{\DtEuler}[2][]{%
\AtBeginTikzMacro{#1}
\NewPoints{G,H,O}
\edef\List{#2}
\ExtractFromList\A\List{1}
\ExtractFromList\B\List{2}
\ExtractFromList\C\List{3}
% Calcul des tangentes
\AngleBAC[@A]{\B,\A,\C}
\AngleBAC[@B]{\C,\B,\A}
\AngleBAC[@C]{\A,\C,\B}
% isobarycentre
\coordinate (\G) at (barycentric cs:\A=1,\B=1,\C=1) ;
% horthocentre
\coordinate (\H) at (barycentric
cs:\A=\Tan@A,\B=\Tan@B,\C=\Tan@C) ;
% centre du cercle circonscrit
\coordinate (\O) at (barycentric
cs:\A=\Tan@B+\Tan@C,\B=\Tan@A+\Tan@C,\C=\Tan@A+\Tan@B) ;
\KeepUsefullNodes
}
% #### --------------------------------- #### ProjMAB ####
\NewDocumentCommand{\ProjMAB}{O{}m}{%
\AtBeginTikzMacro{#1}
\NewPoints{H}
\edef\List{#2}
\ExtractFromList\M\List{1}
\ExtractFromList\A\List{2}
\ExtractFromList\B\List{3}
% Calcul des tangentes
\AngleBAC[@MAB]{\M,\A,\B}
\AngleBAC[@MBA]{\A,\B,\M}
% horthocentre
\coordinate (\H) at (barycentric
cs:\A=\Tan@MAB,\B=\Tan@MBA) ;
\KeepUsefullNodes
}
\makeatother % ------------------------- #### Make @ Other
% #### --------------------------------- #### ProjABC ####
\NewDocumentCommand{\ProjABC}{O{}m}{%
\AtBeginTikzMacro{#1}
\NewPoints{I,J,K}
\def\List{#2}
\ExtractFromList\B\List{2}
\ExtractFromList\C\List{3}
\ProjMAB[\J]{#2}
\ProjMAB[\I]{\C,#2}
\ProjMAB[\K]{\B,\C,#2}
\KeepUsefullNodes
}
% #### --------------------------------- #### CercleABC ####
\NewDocumentCommand{\CercleABC}{%
O{} % centre
m % A,B,C
D<>{} % option pour draw
}{%
\AtBeginTikzMacro{#1}
\NewPoints{O}
\edef\List{#2}
\ExtractFromList\A\List{1}
\ExtractFromList\B\List{2}
\ExtractFromList\C\List{3}
\DtEuler[,,\O]{\A,\B,\C}
\node[circle through=(\A),#3] at (\O) {};
\KeepUsefullNodes
}
% #### --------------------------------- #### CercleEuler ####
\NewDocumentCommand{\CercleEuler}{%
O{} % renvoie dans l'ordre:
% le centre,
% 3 milieux,
% 3 projetés,
% 3 milieux orthocentre-sommet
% G,H,O
m % A,B,C
D<>{} % option pour draw
}{%
\AtBeginTikzMacro{#1}
\NewPoints{o,I,J,K,P,Q,R,p,q,r,G,H,O}
\edef\List{#2}
\ExtractFromList\A\List{1}
\ExtractFromList\B\List{2}
\ExtractFromList\C\List{3}
\Milieux[\J,\K,\I]{\A,\B,\C}
\DtEuler[\G,\H,\O]{\A,\B,\C}
\ProjABC[\R,\P,\Q]{a,b,c}
\CercleABC[\o]{\I,\J,\K}<#3>
\Milieux*[\p,\q,\r]{\H/\A,\H/\B,\H/\C}
\KeepUsefullNodes
}
\tikzset{%
small dot/.style 2 args={fill=#1,circle,scale=#2},
small dot/.default={black}{.3},
}
\NewDocumentCommand{\Droite}{%
O{} % #1 option du path
m % #2 premier point sans ()
m % #3 second point sans ()
m % #4 longueur dans un sens
m % #5 longueur dans l'autre
}{%
\path[#1] ($(#3)!#4!(#2)$) -- ($(#2)!#5!(#3)$) ;
}
% #1 taille du carré defaut 5pt
% #2 Argument boucle foreach ---- Angle droit ----
% Point / Angle droit / Point
\NewDocumentCommand{\AngleDt}{
s % angle droite simple avec deux points
D<>{very thin} % option path
O{5pt} % taille du carré
m % liste de triplets ou de couples (*)
}{%
\IfBooleanTF{#1}{%
\foreach \B/\A in {#4} {%
\draw[#2] ($(\B)!#3!(\A)$)
--($ (\B)!2!($($(\B)!#3!(\A)$)!.5!($(\B)!#3!#190:(\A)$)$)$)
--($(\B)!#3!#190:(\A)$) ; }
}{%
\foreach \A/\B/\C in {#4} {%
\draw[#2] ($(\B)!#3!(\A)$)
--($ (\B)!2!($($(\B)!#3!(\A)$)!.5!($(\B)!#3!(\C)$)$) $)
--($(\B)!#3!(\C)$) ; }
}
}
\begin{document}
\begin{tikzpicture}[scale=1.1]
\coordinate (a) at (0,1) ;
\coordinate (b) at (7,1) ;
\coordinate (c) at (1,6.4) ;
\CercleEuler[o,I,J,K,P1,P2,P3,J1,J2,J3,G,H,O]{%
a,b,c}<fill=lightgray!20,draw=gray,semithick>
\tr[black](a,b,c)
\Droite[draw,blue,semithick]{H}{O}{1.6}{1.6}
\Droite[draw,yellow!95!black,semithick,dashed]{I}{O}{1.4}{1.5}
\Droite[draw,yellow!95!black,semithick,dashed]{J}{O}{1.2}{1.2}
\Droite[draw,yellow!95!black,semithick,dashed]{K}{O}{1.2}{1.2}
\draw[draw,red,dashed] (a)--(P1) (b)--(P2) (c)--(P3) ;
\draw[green,dashed] (a)--(I) (b)--(J) (c)--(K) ;
\AngleDt{a/P1/b,b/P2/c,c/P3/a,O/I/c,O/J/a,O/K/b}
\foreach \Coor/\Text/\Pos in
{a/$A$/-135,
b/$B$/-45,
c/$C$/90,
I/$I$/20,
J/$J$/130,
K/$K$/-50,
P1/$p_1$/60,
P2/$p_2$/190,
P3/$p_3$/-120,
J1/$j_1$/180,
J2/$j_2$/-60,
J3/$j_3$/130,
G/$G$/-110,
H/$H$/130,
O/$O$/-50,
o/$O'$/130
} {
\node[small dot] at (\Coor) {} ;
\node[shift=(\Pos:8pt),anchor=center] at (\Coor) {\small\Text} ;
}
\end{tikzpicture}
\end{document}