On Sat, 01 Sep 2007 18:23:07 -0000, robinson.inj@gmail.com wrote:
> Dear all,
> Does someone can show me (or point me out a link) how to generate
> ternary diagrams/plots in IDL?
> I will really appreciate your assistance.
> Robinson
There is nothing out there that I know of that generates ternary
diagrams. I tried to make something myself ones. Maybe it'll get you
started:
function NormToTriangle,Anorm,Bnorm,Cnorm,AP,BP,CP
; equation line : y=(x-x1).(y2-y1)/(x2-x1)+y1 (2 points)
; y=(x-x1).r+y1 (rico+point)
sqrt3=sqrt(3)
n=n_elements(Anorm)
PAx=CP[0]-0.5*Anorm
PAy=CP[1]+(sqrt3*0.5)*Anorm
;rC = 0
PBx=AP[0]-0.5*Bnorm
PBy=AP[1]-(sqrt3*0.5)*Bnorm
;rA = -sqrt3
PCx=BP[0]+Cnorm
PCy=BP[1]*replicate(1,n)
;rB = sqrt3
; find point where these three lines cross
; (bad code, just checked two lines)
Px=(-PAy+sqrt3*PBx+PBy)/sqrt3
Py=(PBx-Px)*sqrt3+PBy
return,{x:Px,y:Py}
end;function NormToTriangle
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%
pro TriangleConstr,AP,BP,CP,pfree,R=R,GAP=GAP,ArrowCoord=ArrowCo ord
; AP,BP,CP: corner coordinates
; pfree: procent of window size to leave free on one side of the
triangle
; R: vertex length
; GAP: scale the trangle and leave gaps
; ArrowCoord: ArrowCoord
; A
; / \
; / \
; / \
; / \
; / \
; B___________C
XS=!d.x_size
YS=!d.y_size
X0=XS/2.
Y0=YS/2.
XY0=X0<Y0
R0=(1-pfree)*XY0
R=R0*sqrt(3)
Y0=Y0-0.25*R0
dX=R*0.5
dY=R0*0.5
AP=[X0,Y0+R0]
BP=[X0-dX,Y0-dY]
CP=[X0+dX,Y0-dY]
if keyword_set(GAP) then begin
ct=sqrt(3)*0.5
DR=(1-GAP)*XY0-R0
dX=dR*ct
dY=dR*0.5
dZ=dY*[ct,0.5]
dU=dY*[-ct,0.5]
dV=[0,-dY]
ArrowCoord=[[BP+dV],[CP+dV],[CP+dZ],$
[AP+dZ],[AP+dU],[BP+dU]]
endif
end;pro TriangleConstr
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%
pro
TernaryDiagram,Ain,Bin,Cin,ATitle=ATitle,BTitle=BTitle,CTitl e=CTitle
; ----Check primary parameters----
if not keyword_set(ATitle) then ATitle='A'
if not keyword_set(BTitle) then BTitle='B'
if not keyword_set(CTitle) then CTitle='C'
nA=n_elements(Ain)
nB=n_elements(Bin)
nC=n_elements(Cin)
if (nA eq 0) or (nB eq 0) or (nC eq 0) or (nA ne nB) or (nA ne nC)
then $
message,'A,B,C dimensions are wrong.'
; ----Construct diagram----
pfree=0.02
gap=-0.1
gap2=-0.2
TriangleConstr,AP,BP,CP,pfree,R=R,GAP=gap,ArrowCoord=AC
TriangleConstr,APl,BPl,CPl,gap,GAP=gap2,ArrowCoord=AC2
plots,[BP[0],CP[0]],[BP[1],CP[1]],/device,thick=2
plots,[CP[0],AP[0]],[CP[1],AP[1]],/device,thick=2
plots,[AP[0],BP[0]],[AP[1],BP[1]],/device,thick=2
xyouts,BPl[0],BPl[1],BTitle,/device
xyouts,CPl[0],CPl[1],CTitle,/device
xyouts,APl[0],APl[1],ATitle,/device
arrow,AC[0,0],AC[1,0],AC[0,1],AC[1,1]
arrow,AC[0,2],AC[1,2],AC[0,3],AC[1,3]
arrow,AC[0,4],AC[1,4],AC[0,5],AC[1,5]
xyouts,(AC2[0,4]+AC2[0,5])/2,(AC2[1,4]+AC2[1,5])/2,BTitle+'
%',/device,ORIENTATION=60
xyouts,(AC2[0,0]+AC2[0,1])/2,(AC2[1,0]+AC2[1,1])/2,CTitle+'
%',/device,ORIENTATION=0
xyouts,(AC2[0,2]+AC2[0,3])/2,(AC2[1,2]+AC2[1,3])/2,ATitle+'
%',/device,ORIENTATION=-60
; ----Derive coordinates----
; sum must be 1, then scale between 0-R
sum=float(Ain+Bin+Cin)
Anorm=Ain/sum*R
Bnorm=Bin/sum*R
Cnorm=Cin/sum*R
data=NormToTriangle(Anorm,Bnorm,Cnorm,AP,BP,CP)
plots,data.x,data.y,psym=2,/device
; ----Grid----
n=10
m=n-1
ind=(indgen(1,m)+1.)/n
rind=reverse(ind,2)
zero=replicate(0.,1,m)
;CA
Anorm=[zero,ind]*R
Bnorm=[ind,zero]*R
Cnorm=[rind,rind]*R
data=NormToTriangle(Anorm,Bnorm,Cnorm,AP,BP,CP)
for i=0,m-1 do $
plots,data.x[*,i],data.y[*,i],linestyle=1,/device
;AB
Anorm=[ind,ind]*R
Bnorm=[zero,rind]*R
Cnorm=[rind,zero]*R
data=NormToTriangle(Anorm,Bnorm,Cnorm,AP,BP,CP)
for i=0,m-1 do $
plots,data.x[*,i],data.y[*,i],linestyle=1,/device
;BC
Anorm=[rind,zero]*R
Bnorm=[ind,ind]*R
Cnorm=[zero,rind]*R
data=NormToTriangle(Anorm,Bnorm,Cnorm,AP,BP,CP)
for i=0,m-1 do $
plots,data.x[*,i],data.y[*,i],linestyle=1,/device
end;pro TernaryDiagram
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%
pro example
window
A=[20,50,25,20]
B=[30,0,25,70]
C=[50,50,50,10]
TernaryDiagram,A,B,C
end;pro example
|