1%% -*- erlang-indent-level: 2 -*- 2%%---------------------------------------------------------------------------- 3%% Copy of inf_loop1.erl, where the calls mentioned below have been 4%% restored. 5 6%% Non-sensical (i.e., stripped-down) program that sends the analysis 7%% into an infinite loop. The #we.es field was originally a gb_trees:tree() 8%% but the programmer declared it as an array in order to change it to 9%% that data type instead. In the file, there are two calls to function 10%% gb_trees:get/2 which seem to be the ones responsible for sending the 11%% analysis into an infinite loop. Currently, these calls are marked and 12%% have been changed to gbee_trees:get/2 in order to be able to see that 13%% the analysis works if these two calls are taken out of the picture. 14%%---------------------------------------------------------------------------- 15-module(inf_loop2). 16 17-export([command/1]). 18 19-record(we, {id, 20 es = array:new() :: array:array(), 21 vp, 22 mirror = none}). 23-record(edge, {vs,ve,a = none,b = none,lf,rf,ltpr,ltsu,rtpr,rtsu}). 24 25command(St) -> 26 State = drag_mode(offset_region), 27 SetupSt = wings_sel_conv:more(St), 28 Tvs = wings_sel:fold(fun(Faces, #we{id = Id} = We, Acc) -> 29 FaceRegions = wings_sel:face_regions(Faces, We), 30 {AllVs0,VsData} = 31 collect_offset_regions_data(FaceRegions, We, [], []), 32 AllVs = ordsets:from_list(AllVs0), 33 [{Id,{AllVs,offset_regions_fun(VsData, State)}}|Acc] 34 end, 35 [], 36 SetupSt), 37 wings_drag:setup(Tvs, 42, [], St). 38 39drag_mode(Type) -> 40 {Mode,Norm} = wings_pref:get_value(Type, {average,loop}), 41 {Type,Mode,Norm}. 42 43collect_offset_regions_data([Faces|Regions], We, AllVs, VsData) -> 44 {FaceNormTab,OuterEdges,RegVs} = 45 some_fake_module:faces_data_0(Faces, We, [], [], []), 46 {LoopNorm,LoopVsData,LoopVs} = 47 offset_regions_loop_data(OuterEdges, Faces, We, FaceNormTab), 48 Vs = RegVs -- LoopVs, 49 RegVsData = vertex_normals(Vs, FaceNormTab, We, LoopVsData), 50 collect_offset_regions_data(Regions, We, RegVs ++ AllVs, 51 [{LoopNorm,RegVsData}|VsData]); 52collect_offset_regions_data([], _, AllVs, VsData) -> 53 {AllVs,VsData}. 54 55offset_regions_loop_data(Edges, Faces, We, FNtab) -> 56 EdgeSet = gb_sets:from_list(Edges), 57 offset_loop_data_0(EdgeSet, Faces, We, FNtab, [], [], []). 58 59offset_loop_data_0(EdgeSet0, Faces, We, FNtab, LNorms, VData0, Vs0) -> 60 case gb_sets:is_empty(EdgeSet0) of 61 false -> 62 {Edge,EdgeSet1} = gb_sets:take_smallest(EdgeSet0), 63 {EdgeSet,VData,Links,LoopNorm,Vs} = 64 offset_loop_data_1(Edge, EdgeSet1, Faces, We, FNtab, VData0, Vs0), 65 offset_loop_data_0(EdgeSet, Faces, We, FNtab, 66 [{Links,LoopNorm}|LNorms], VData, Vs); 67 true -> 68 AvgLoopNorm = average_loop_norm(LNorms), 69 {AvgLoopNorm,VData0,Vs0} 70 end. 71 72offset_loop_data_1(Edge, EdgeSet, _Faces, 73 #we{es = Etab, vp = Vtab} = We, FNtab, VData, Vs) -> 74 #edge{vs = Va, ve = Vb, lf = Lf, ltsu = NextLeft} = gb_trees:get(Edge, Etab), 75 VposA = gb_trees:get(Va, Vtab), 76 VposB = gb_trees:get(Vb, Vtab), 77 VDir = e3d_vec:sub(VposB, VposA), 78 FNorm = wings_face:normal(Lf, We), 79 EdgeData = gb_trees:get(NextLeft, Etab), 80 offset_loop_data_2(NextLeft, EdgeData, Va, VposA, Lf, Edge, We, FNtab, 81 EdgeSet, VDir, [], [FNorm], VData, [], Vs, 0). 82 83offset_loop_data_2(CurE, #edge{vs = Va, ve = Vb, lf = PrevFace, 84 rtsu = NextEdge, ltsu = IfCurIsMember}, 85 Vb, VposB, PrevFace, LastE, 86 #we{mirror = M} = We, 87 FNtab, EdgeSet0, VDir, EDir0, VNorms0, VData0, VPs0, Vs0, 88 Links) -> 89 Mirror = M == PrevFace, 90 offset_loop_is_member(Mirror, Vb, Va, VposB, CurE, IfCurIsMember, VNorms0, 91 NextEdge, EdgeSet0, VDir, EDir0, FNtab, PrevFace, 92 LastE, We, VData0, VPs0, Vs0, Links). 93 94offset_loop_is_member(Mirror, V1, V2, Vpos1, CurE, NextE, VNorms0, NEdge, 95 EdgeSet0, VDir, EDir0, FNtab, PFace, LastE, We, 96 VData0, VPs0, Vs0, Links) -> 97 #we{es = Etab, vp = Vtab} = We, 98 Vpos2 = gb_trees:get(V2, Vtab), 99 Dir = e3d_vec:sub(Vpos2, Vpos1), 100 NextVDir = e3d_vec:neg(Dir), 101 EdgeSet = gb_sets:delete(CurE, EdgeSet0), 102 EdgeData = gb_trees:get(NextE, Etab), %% HERE 103 [FNorm|_] = VNorms0, 104 VData = offset_loop_data_3(Mirror, V1, Vpos1, VNorms0, NEdge, VDir, 105 Dir, EDir0, FNtab, We, VData0), 106 VPs = [Vpos1|VPs0], 107 Vs = [V1|Vs0], 108 offset_loop_data_2(NextE, EdgeData, V2, Vpos2, PFace, LastE, We, FNtab, 109 EdgeSet, NextVDir, [], [FNorm], VData, VPs, Vs, Links + 1). 110 111offset_loop_data_3(false, V, Vpos, VNorms0, NextEdge, 112 VDir, Dir, EDir0, FNtab, We, VData0) -> 113 #we{es = Etab} = We, 114 VNorm = e3d_vec:norm(e3d_vec:add(VNorms0)), 115 NV = wings_vertex:other(V, gb_trees:get(NextEdge, Etab)), %% HERE 116 ANorm = vertex_normal(NV, FNtab, We), 117 EDir = some_fake_module:average_edge_dir(VNorm, VDir, Dir, EDir0), 118 AvgDir = some_fake_module:evaluate_vdata(VDir, Dir, VNorm), 119 ScaledDir = some_fake_module:along_edge_scale_factor(VDir, Dir, EDir, ANorm), 120 [{V,{Vpos,AvgDir,EDir,ScaledDir}}|VData0]. 121 122average_loop_norm([{_,LNorms}]) -> 123 e3d_vec:norm(LNorms); 124average_loop_norm([{LinksA,LNormA},{LinksB,LNormB}]) -> 125 case LinksA < LinksB of 126 true -> 127 e3d_vec:norm(e3d_vec:add(e3d_vec:neg(LNormA), LNormB)); 128 false -> 129 e3d_vec:norm(e3d_vec:add(e3d_vec:neg(LNormB), LNormA)) 130 end; 131average_loop_norm(LNorms) -> 132 LoopNorms = [Norm || {_,Norm} <- LNorms], 133 e3d_vec:norm(e3d_vec:neg(e3d_vec:add(LoopNorms))). 134 135vertex_normals([V|Vs], FaceNormTab, #we{vp = Vtab, mirror = M} = We, Acc) -> 136 FaceNorms = 137 wings_vertex:fold(fun(_, Face, _, A) when Face == M -> 138 [e3d_vec:neg(wings_face:normal(M, We))|A]; 139 (_, Face, _, A) -> 140 [gb_trees:get(Face, FaceNormTab)|A] 141 end, [], V, We), 142 VNorm = e3d_vec:norm(e3d_vec:add(FaceNorms)), 143 Vpos = gb_trees:get(V, Vtab), 144 vertex_normals(Vs, FaceNormTab, We, [{V,{Vpos,VNorm}}|Acc]); 145vertex_normals([], _, _, Acc) -> 146 Acc. 147 148vertex_normal(V, FaceNormTab, #we{mirror = M} = We) -> 149 wings_vertex:fold(fun(_, Face, _, A) when Face == M -> 150 [e3d_vec:neg(wings_face:normal(Face, We))|A]; 151 (_, Face, _, A) -> 152 N = gb_trees:get(Face, FaceNormTab), 153 case e3d_vec:is_zero(N) of 154 true -> A; 155 false -> [N|A] 156 end 157 end, [], V, We). 158 159offset_regions_fun(OffsetData, {_,Solution,_} = State) -> 160 fun(new_mode_data, {NewState,_}) -> 161 offset_regions_fun(OffsetData, NewState); 162 ([Dist,_,_,Bump|_], A) -> 163 lists:foldl(fun({LoopNormal,VsData}, VsAcc0) -> 164 lists:foldl(fun({V,{Vpos0,VNorm}}, VsAcc) -> 165 [{V,Vpos0}|VsAcc]; 166 ({V,{Vpos0,Dir,EDir,ScaledEDir}}, VsAcc) -> 167 Vec = case Solution of 168 average -> Dir; 169 along_edges -> EDir; 170 scaled -> ScaledEDir 171 end, 172 [{V,Vpos0}|VsAcc] 173 end, VsAcc0, VsData) 174 end, A, OffsetData) 175 end. 176