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