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_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
%%----------------------------------------------------------------------------
17
es = array:new() :: array(),
20
-record(edge, {vs,ve,a = none,b = none,lf,rf,ltpr,ltsu,rtpr,rtsu}).
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),
28
collect_offset_regions_data(FaceRegions, We, [], []),
29
AllVs = ordsets:from_list(AllVs0),
30
[{Id,{AllVs,offset_regions_fun(VsData, State)}}|Acc]
34
wings_drag:setup(Tvs, 42, [], St).
37
{Mode,Norm} = wings_pref:get_value(Type, {average,loop}),
40
collect_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),
46
RegVsData = vertex_normals(Vs, FaceNormTab, We, LoopVsData),
47
collect_offset_regions_data(Regions, We, RegVs ++ AllVs,
48
[{LoopNorm,RegVsData}|VsData]);
49
collect_offset_regions_data([], _, AllVs, VsData) ->
52
offset_regions_loop_data(Edges, Faces, We, FNtab) ->
53
EdgeSet = gb_sets:from_list(Edges),
54
offset_loop_data_0(EdgeSet, Faces, We, FNtab, [], [], []).
56
offset_loop_data_0(EdgeSet0, Faces, We, FNtab, LNorms, VData0, Vs0) ->
57
case gb_sets:is_empty(EdgeSet0) of
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);
65
AvgLoopNorm = average_loop_norm(LNorms),
66
{AvgLoopNorm,VData0,Vs0}
69
offset_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).
80
offset_loop_data_2(CurE, #edge{vs = Va, ve = Vb, lf = PrevFace,
81
rtsu = NextEdge, ltsu = IfCurIsMember},
82
Vb, VposB, PrevFace, LastE,
84
FNtab, EdgeSet0, VDir, EDir0, VNorms0, VData0, VPs0, Vs0,
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).
91
offset_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
101
VData = offset_loop_data_3(Mirror, V1, Vpos1, VNorms0, NEdge, VDir,
102
Dir, EDir0, FNtab, We, VData0),
105
offset_loop_data_2(NextE, EdgeData, V2, Vpos2, PFace, LastE, We, FNtab,
106
EdgeSet, NextVDir, [], [FNorm], VData, VPs, Vs, Links + 1).
108
offset_loop_data_3(false, V, Vpos, VNorms0, NextEdge,
109
VDir, Dir, EDir0, FNtab, We, VData0) ->
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].
119
average_loop_norm([{_,LNorms}]) ->
120
e3d_vec:norm(LNorms);
121
average_loop_norm([{LinksA,LNormA},{LinksB,LNormB}]) ->
122
case LinksA < LinksB of
124
e3d_vec:norm(e3d_vec:add(e3d_vec:neg(LNormA), LNormB));
126
e3d_vec:norm(e3d_vec:add(e3d_vec:neg(LNormB), LNormA))
128
average_loop_norm(LNorms) ->
129
LoopNorms = [Norm || {_,Norm} <- LNorms],
130
e3d_vec:norm(e3d_vec:neg(e3d_vec:add(LoopNorms))).
132
vertex_normals([V|Vs], FaceNormTab, #we{vp = Vtab, mirror = M} = We, Acc) ->
134
wings_vertex:fold(fun(_, Face, _, A) when Face == M ->
135
[e3d_vec:neg(wings_face:normal(M, We))|A];
137
[gb_trees:get(Face, FaceNormTab)|A]
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]);
142
vertex_normals([], _, _, Acc) ->
145
vertex_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];
149
N = gb_trees:get(Face, FaceNormTab),
150
case e3d_vec:is_zero(N) of
156
offset_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) ->
163
({V,{Vpos0,Dir,EDir,ScaledEDir}}, VsAcc) ->
164
Vec = case Solution of