(*２次元平面上の点集合から，凸包を計算する関数．反時計回りにソートされた，凸包の境界上の点集合を返す*)
Conv2D[list_]:=Module[{lis,p0,p1,p2,minang,maxang,tmp,pi,conv},
conv={};
lis=list;
p0=MinimalBy[list,N[100*#[[1]]+#[[2]]]&]//First(*x座標，y座標の優先順位でソート．最初の点をp0とする*);
AppendTo[conv,p0];lis=DeleteCases[lis,p0];
(*p0を中心として，偏角が最小のものをp1とする*)
minang=Table[Arg[p[[1]]+I*p[[2]]-(p0[[1]]+I*p0[[2]])//N],{p,lis}]//Min;
tmp=Select[lis,Abs[minang-Arg[#[[1]]+I*#[[2]]-(p0[[1]]+I*p0[[2]])//N]]<10^-3&];
(*同一偏角のものが複数存在する場合はp0からの距離が最小のものを選ぶ*)
p1=MinimalBy[tmp,Norm[#-p0//N]&][[1]];
AppendTo[conv,p1];lis=DeleteCases[lis,p1];
AppendTo[lis,p0];pi=p0;
While[True,
(*角度p1-p2-pが最大のpをp2とする*)
maxang=Table[Chop[VectorAngle[p0-p1//N,p-p1//N],10^-5],{p,lis}]//Max;
tmp=Select[lis,Abs[maxang-VectorAngle[p0-p1//N,#-p1//N]]<10^-3&];
(*同一角のものが複数存在する場合はp1からの距離が最小のものを選ぶ*)
p2=MinimalBy[tmp,Norm[#-p1//N]&][[1]];
If[p2==pi,Break[]];
AppendTo[conv,p2];lis=DeleteCases[lis,p2];
p0=p1;p1=p2;
];
Return[conv]];

(*サンプル*)
lis=Table[RandomInteger[{1,10}],{sam,10},{j,2}];
ListPlot[lis]
ListPlot[Conv2D[lis]]