diff options
Diffstat (limited to 'lib/dialyzer/test/opaque_tests_SUITE_data/src/wings')
12 files changed, 0 insertions, 1818 deletions
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl deleted file mode 100644 index b9339a8eb1..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl +++ /dev/null @@ -1,205 +0,0 @@ -%% -%% wings.hrl -- -%% -%% Global record definition and defines. -%% -%% Copyright (c) 2001-2005 Bjorn Gustavsson -%% -%% See the file "license.terms" for information on usage and redistribution -%% of this file, and for a DISCLAIMER OF ALL WARRANTIES. -%% -%% $Id: wings.hrl,v 1.1 2009/01/25 18:55:33 kostis Exp $ -%% - --include("wings_intl.hrl"). - --ifdef(NEED_ESDL). --include_lib("esdl/include/sdl.hrl"). --include_lib("esdl/include/sdl_events.hrl"). --include_lib("esdl/include/sdl_video.hrl"). --include_lib("esdl/include/sdl_keyboard.hrl"). --include_lib("esdl/include/sdl_mouse.hrl"). --include_lib("esdl/src/sdl_util.hrl"). --define(CTRL_BITS, ?KMOD_CTRL). --define(ALT_BITS, ?KMOD_ALT). --define(SHIFT_BITS, ?KMOD_SHIFT). --define(META_BITS, ?KMOD_META). --endif. - --define(WINGS_VERSION, ?wings_version). - --define(CHAR_HEIGHT, wings_text:height()). --define(CHAR_WIDTH, wings_text:width()). - --define(LINE_HEIGHT, (?CHAR_HEIGHT+2)). --define(GROUND_GRID_SIZE, 1). --define(CAMERA_DIST, (8.0*?GROUND_GRID_SIZE)). --define(NORMAL_LINEWIDTH, 1.0). --define(DEGREE, 176). %Degree character. - --define(HIT_BUF_SIZE, (1024*1024)). - --define(PANE_COLOR, {0.52,0.52,0.52}). --define(BEVEL_HIGHLIGHT, {0.9,0.9,0.9}). --define(BEVEL_LOWLIGHT, {0.3,0.3,0.3}). --define(BEVEL_HIGHLIGHT_MIX, 0.5). --define(BEVEL_LOWLIGHT_MIX, 0.5). - --define(SLOW(Cmd), begin wings_io:hourglass(), Cmd end). --define(TC(Cmd), wings_util:tc(fun() -> Cmd end, ?MODULE, ?LINE)). - --ifdef(DEBUG). --define(ASSERT(E), case E of - true -> ok; - _ -> - erlang:error({assertion_failed,?MODULE,?LINE}) - end). --define(CHECK_ERROR(), wings_gl:check_error(?MODULE, ?LINE)). --else. --define(ASSERT(E),ok). --define(CHECK_ERROR(), ok). --endif. - -%% Display lists per object. -%% Important: Plain integers and integers in lists will be assumed to -%% be display lists. Arbitrary integers must be stored inside a tuple -%% or record to not be interpreted as a display list. --record(dlo, - {work=none, %Workmode faces. - smooth=none, %Smooth-shaded faces. - edges=none, %Edges and wire-frame. - vs=none, %Unselected vertices. - hard=none, %Hard edges. - sel=none, %Selected items. - orig_sel=none, %Original selection. - normals=none, %Normals. - pick=none, %For picking. - proxy_faces=none, %Smooth proxy faces. - proxy_edges=none, %Smooth proxy edges. - - %% Miscellanous. - hilite=none, %Hilite display list. - mirror=none, %Virtual mirror data. - ns=none, %Normals/positions per face. - - %% Source for display lists. - src_we=none, %Source object. - src_sel=none, %Source selection. - orig_mode=none, %Original selection mode. - split=none, %Split data. - drag=none, %For dragging. - transparent=false, %Object includes transparancy. - proxy_data=none, %Data for smooth proxy. - open=false, %Open (has hole). - - %% List of display lists known to be needed only based - %% on display modes, not whether the lists themselves exist. - %% Example: [work,edges] - needed=[] - }). - -%% Main state record containing all objects and other important state. --record(st, - {shapes, %All visible shapes - selmode, %Selection mode: - % vertex, edge, face, body - sh=false, %Smart highlight active: true|false - sel=[], %Current sel: [{Id,GbSet}] - ssels=[], %Saved selections: - % [{Name,Mode,GbSet}] - temp_sel=none, %Selection only temporary? - - mat, %Defined materials (GbTree). - pal=[], %Palette - file, %Current filename. - saved, %True if model has been saved. - onext, %Next object id to use. - bb=none, %Saved bounding box. - edge_loop=none, %Previous edge loop. - views={0,{}}, %{Current,TupleOfViews} - pst=gb_trees:empty(), %Plugin State Info - % gb_tree where key is plugin module - - %% Previous commands. - repeatable, %Last repeatable command. - ask_args, %Ask arguments. - drag_args, %Drag arguments for command. - def, %Default operations. - - %% Undo information. - top, %Top of stack. - bottom, %Bottom of stack. - next_is_undo, %State of undo/redo toggle. - undone %States that were undone. - }). - -%% The Winged-Edge data structure. -%% See http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/model/winged-e.html --record(we, - {id, %Shape id. - perm=0, %Permissions: - % 0 - Everything allowed. - % 1 - Visible, can't select. - % [] or {Mode,GbSet} - - % Invisible, can't select. - % The GbSet contains the - % object's selection. - name, %Name. - es, %gb_tree containing edges - fs, %gb_tree containing faces - he, %gb_sets containing hard edges - vc, %Connection info (=incident edge) - % for vertices. - vp, %Vertex positions. - pst=gb_trees:empty(), %Plugin State Info, - % gb_tree where key is plugin module - mat=default, %Materials. - next_id, %Next free ID for vertices, - % edges, and faces. - % (Needed because we never re-use - % IDs.) - mode, %'vertex'/'material'/'uv' - mirror=none, %Mirror: none|Face - light=none, %Light data: none|Light - has_shape=true %true|false - }). - --define(IS_VISIBLE(Perm), (Perm =< 1)). --define(IS_NOT_VISIBLE(Perm), (Perm > 1)). --define(IS_SELECTABLE(Perm), (Perm == 0)). --define(IS_NOT_SELECTABLE(Perm), (Perm =/= 0)). - --define(IS_LIGHT(We), ((We#we.light =/= none) and (not We#we.has_shape))). --define(IS_ANY_LIGHT(We), (We#we.light =/= none)). --define(HAS_SHAPE(We), (We#we.has_shape)). -%-define(IS_LIGHT(We), (We#we.light =/= none)). -%-define(IS_NOT_LIGHT(We), (We#we.light =:= none)). - -%% Edge in a winged-edge shape. --record(edge, - {vs, %Start vertex for edge - ve, %End vertex for edge - a=none, %Color or UV coordinate. - b=none, %Color or UV coordinate. - lf, %Left face - rf, %Right face - ltpr, %Left traversal predecessor - ltsu, %Left traversal successor - rtpr, %Right traversal predecessor - rtsu %Right traversal successor - }). - -%% The current view/camera. --record(view, - {origin, - distance, % From origo. - azimuth, - elevation, - pan_x, %Panning in X direction. - pan_y, %Panning in Y direction. - along_axis=none, %Which axis viewed along. - fov, %Field of view. - hither, %Near clipping plane. - yon %Far clipping plane. - }). - diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl deleted file mode 100644 index d7af9bb1d3..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl +++ /dev/null @@ -1,375 +0,0 @@ -%% -%% wings_dissolve.erl -- -%% -%% This module implements dissolve of faces. -%% - --module(wings_dissolve). - --export([faces/2, complement/2]). - --include("wings.hrl"). - -%% faces([Face], We) -> We' -%% Dissolve the given faces. -faces([], We) -> We; -faces(Faces, #we{fs=Ftab0}=We) -> - case gb_sets:is_empty(Faces) of - true -> We; - false when is_list(Faces) -> - Complement = ordsets:subtract(gb_trees:keys(Ftab0), - ordsets:from_list(Faces)), - dissolve_1(Faces, Complement, We); - false -> - Complement = ordsets:subtract(gb_trees:keys(Ftab0), - gb_sets:to_list(Faces)), - dissolve_1(Faces, Complement, We) - end. - -faces([], _, We) -> We; -faces(Faces,Complement,We) -> - case gb_sets:is_empty(Faces) of - true -> We; - false -> dissolve_1(Faces, Complement,We) - end. - -dissolve_1(Faces, Complement, We0) -> - We1 = optimistic_dissolve(Faces,Complement,We0#we{vc=undefined}), - NewFaces = wings_we:new_items_as_ordset(face, We0, We1), - We2 = wings_face:delete_bad_faces(NewFaces, We1), - We = wings_we:rebuild(We2), - case wings_we:is_consistent(We) of - true -> - We; - false -> - io:format("Dissolving would cause an inconsistent object structure.") - end. - -%% complement([Face], We) -> We' -%% Dissolve all faces BUT the given faces. Also invalidate the -%% mirror face if it existed and was dissolved. -complement(Fs0, #we{fs=Ftab0}=We0) when is_list(Fs0) -> - Fs = ordsets:subtract(gb_trees:keys(Ftab0), ordsets:from_list(Fs0)), - case faces(Fs, Fs0, We0) of - #we{mirror=none}=We -> We; - #we{mirror=Face,fs=Ftab}=We -> - case gb_trees:is_defined(Face, Ftab) of - false -> We; - true -> We#we{mirror=none} - end - end; -complement(Fs, We) -> complement(gb_sets:to_list(Fs), We). - -optimistic_dissolve(Faces0, Compl, We0) -> - %% Optimistically assume that we have a simple region without - %% any holes. - case outer_edge_loop(Faces0, We0) of - error -> - %% Assumption was wrong. We need to partition the selection - %% and dissolve each partition in turn. - Parts = wings_sel:face_regions(Faces0, We0), - complex_dissolve(Parts, We0); - [_|_]=Loop -> - %% Assumption was correct. - simple_dissolve(Faces0, Compl, Loop, We0) - end. - -%% simple_dissolve(Faces, Loop, We0) -> We -%% Dissolve a region of faces with no holes and no -%% repeated vertices in the outer edge loop. - -simple_dissolve(Faces0, Compl, Loop, We0) -> - Faces = to_gb_set(Faces0), - OldFace = gb_sets:smallest(Faces), - Mat = wings_facemat:face(OldFace, We0), - We1 = fix_materials(Faces, Compl, We0), - #we{es=Etab0,fs=Ftab0,he=Htab0} = We1, - {Ftab1,Etab1,Htab} = simple_del(Faces, Ftab0, Etab0, Htab0, We1), - {NewFace,We2} = wings_we:new_id(We1), - Ftab = gb_trees:insert(NewFace, hd(Loop), Ftab1), - Last = lists:last(Loop), - Etab = update_outer([Last|Loop], Loop, NewFace, Ftab, Etab1), - We = We2#we{es=Etab,fs=Ftab,he=Htab}, - wings_facemat:assign(Mat, [NewFace], We). - -fix_materials(Del,Keep,We) -> - case gb_sets:size(Del) < length(Keep) of - true -> - wings_facemat:delete_faces(Del,We); - false -> - wings_facemat:keep_faces(Keep,We) - end. - -to_gb_set(List) when is_list(List) -> - gb_sets:from_list(List); -to_gb_set(S) -> S. - -%% Delete faces and inner edges for a simple region. -simple_del(Faces, Ftab0, Etab0, Htab0, We) -> - case {gb_trees:size(Ftab0),gb_sets:size(Faces)} of - {AllSz,FaceSz} when AllSz < 2*FaceSz -> - %% At least half of the faces are selected. - %% It is faster to find the edges for the - %% unselected faces. - UnselFaces = ordsets:subtract(gb_trees:keys(Ftab0), - gb_sets:to_list(Faces)), - - UnselSet = sofs:from_external(UnselFaces, [face]), - Ftab1 = sofs:from_external(gb_trees:to_list(Ftab0), - [{face,edge}]), - Ftab2 = sofs:restriction(Ftab1, UnselSet), - Ftab = gb_trees:from_orddict(sofs:to_external(Ftab2)), - - Keep0 = wings_face:to_edges(UnselFaces, We), - Keep = sofs:set(Keep0, [edge]), - Etab1 = sofs:from_external(gb_trees:to_list(Etab0), - [{edge,info}]), - Etab2 = sofs:restriction(Etab1, Keep), - Etab = gb_trees:from_orddict(sofs:to_external(Etab2)), - - Htab = simple_del_hard(Htab0, sofs:to_external(Keep), undefined), - {Ftab,Etab,Htab}; - {_,_} -> - Ftab = lists:foldl(fun(Face, Ft) -> - gb_trees:delete(Face, Ft) - end, Ftab0, gb_sets:to_list(Faces)), - Inner = wings_face:inner_edges(Faces, We), - Etab = lists:foldl(fun(Edge, Et) -> - gb_trees:delete(Edge, Et) - end, Etab0, Inner), - Htab = simple_del_hard(Htab0, undefined, Inner), - {Ftab,Etab,Htab} - end. - -simple_del_hard(Htab, Keep, Remove) -> - case gb_sets:is_empty(Htab) of - true -> Htab; - false -> simple_del_hard_1(Htab, Keep, Remove) - end. - -simple_del_hard_1(Htab, Keep, undefined) -> - gb_sets:intersection(Htab, gb_sets:from_ordset(Keep)); -simple_del_hard_1(Htab, undefined, Remove) -> - gb_sets:difference(Htab, gb_sets:from_ordset(Remove)). - -%% complex([Partition], We0) -> We0 -%% The general dissolve. - -complex_dissolve([Faces|T], We0) -> - Face = gb_sets:smallest(Faces), - Mat = wings_facemat:face(Face, We0), - We1 = wings_facemat:delete_faces(Faces, We0), - Parts = outer_edge_partition(Faces, We1), - We = do_dissolve(Faces, Parts, Mat, We0, We1), - complex_dissolve(T, We); -complex_dissolve([], We) -> We. - -do_dissolve(Faces, Ess, Mat, WeOrig, We0) -> - We1 = do_dissolve_faces(Faces, We0), - Inner = wings_face:inner_edges(Faces, WeOrig), - We2 = delete_inner(Inner, We1), - #we{he=Htab0} = We = do_dissolve_1(Ess, Mat, We2), - Htab = gb_sets:difference(Htab0, gb_sets:from_list(Inner)), - We#we{he=Htab}. - -do_dissolve_1([EdgeList|Ess], Mat, #we{es=Etab0,fs=Ftab0}=We0) -> - {Face,We1} = wings_we:new_id(We0), - Ftab = gb_trees:insert(Face, hd(EdgeList), Ftab0), - Last = lists:last(EdgeList), - Etab = update_outer([Last|EdgeList], EdgeList, Face, Ftab, Etab0), - We2 = We1#we{es=Etab,fs=Ftab}, - We = wings_facemat:assign(Mat, [Face], We2), - do_dissolve_1(Ess, Mat, We); -do_dissolve_1([], _Mat, We) -> We. - -do_dissolve_faces(Faces, #we{fs=Ftab0}=We) -> - Ftab = lists:foldl(fun(Face, Ft) -> - gb_trees:delete(Face, Ft) - end, Ftab0, gb_sets:to_list(Faces)), - We#we{fs=Ftab}. - -delete_inner(Inner, #we{es=Etab0}=We) -> - Etab = lists:foldl(fun(Edge, Et) -> - gb_trees:delete(Edge, Et) - end, Etab0, Inner), - We#we{es=Etab}. - -update_outer([Pred|[Edge|Succ]=T], More, Face, Ftab, Etab0) -> - #edge{rf=Rf} = R0 = gb_trees:get(Edge, Etab0), - Rec = case gb_trees:is_defined(Rf, Ftab) of - true -> - ?ASSERT(false == gb_trees:is_defined(R0#edge.lf, Ftab)), - LS = succ(Succ, More), - R0#edge{lf=Face,ltpr=Pred,ltsu=LS}; - false -> - ?ASSERT(true == gb_trees:is_defined(R0#edge.lf, Ftab)), - RS = succ(Succ, More), - R0#edge{rf=Face,rtpr=Pred,rtsu=RS} - end, - Etab = gb_trees:update(Edge, Rec, Etab0), - update_outer(T, More, Face, Ftab, Etab); -update_outer([_], _More, _Face, _Ftab, Etab) -> Etab. - -succ([Succ|_], _More) -> Succ; -succ([], [Succ|_]) -> Succ. - -%% outer_edge_loop(FaceSet,WingedEdge) -> [Edge] | error. -%% Partition the outer edges of the FaceSet into a single closed loop. -%% Return 'error' if the faces in FaceSet does not form a -%% simple region without holes. -%% -%% Equvivalent to -%% case outer_edge_partition(FaceSet,WingedEdge) of -%% [Loop] -> Loop; -%% [_|_] -> error -%% end. -%% but faster. - -outer_edge_loop(Faces, We) -> - case lists:sort(collect_outer_edges(Faces, We)) of - [] -> error; - [{Key,Val}|Es0] -> - case any_duplicates(Es0, Key) of - false -> - Es = gb_trees:from_orddict(Es0), - N = gb_trees:size(Es), - outer_edge_loop_1(Val, Es, Key, N, []); - true -> error - end - end. - -outer_edge_loop_1({Edge,V}, _, V, 0, Acc) -> - %% This edge completes the loop, and we have used all possible edges. - [Edge|Acc]; -outer_edge_loop_1({_,V}, _, V, _N, _) -> - %% Loop is complete, but we haven't used all edges. - error; -outer_edge_loop_1({_,_}, _, _, 0, _) -> - %% We have used all possible edges, but somehow the loop - %% is not complete. I can't see how this is possible. - erlang:error(internal_error); -outer_edge_loop_1({Edge,Vb}, Es, EndV, N, Acc0) -> - Acc = [Edge|Acc0], - outer_edge_loop_1(gb_trees:get(Vb, Es), Es, EndV, N-1, Acc). - -any_duplicates([{V,_}|_], V) -> true; -any_duplicates([_], _) -> false; -any_duplicates([{V,_}|Es], _) -> any_duplicates(Es, V). - -%% outer_edge_partition(FaceSet, WingedEdge) -> [[Edge]]. -%% Partition the outer edges of the FaceSet. Each partion -%% of edges form a closed loop with no repeated vertices. -%% Outer edges are edges that have one face in FaceSet -%% and one outside. -%% It is assumed that FaceSet consists of one region returned by -%% wings_sel:face_regions/2. - -outer_edge_partition(Faces, We) -> - F0 = collect_outer_edges(Faces, We), - F = gb_trees:from_orddict(wings_util:rel2fam(F0)), - partition_edges(F, []). - -collect_outer_edges(Faces, We) when is_list(Faces) -> - collect_outer_edges_1(Faces, gb_sets:from_list(Faces), We); -collect_outer_edges(Faces, We) -> - collect_outer_edges_1(gb_sets:to_list(Faces), Faces, We). - -collect_outer_edges_1(Fs0, Faces0, #we{fs=Ftab}=We) -> - case {gb_trees:size(Ftab),gb_sets:size(Faces0)} of - {AllSz,FaceSz} when AllSz < 2*FaceSz -> - Fs = ordsets:subtract(gb_trees:keys(Ftab), Fs0), - Faces = gb_sets:from_ordset(Fs), - Coll = collect_outer_edges_a(Faces), - wings_face:fold_faces(Coll, [], Fs, We); - {_,_} -> - Coll = collect_outer_edges_b(Faces0), - wings_face:fold_faces(Coll, [], Fs0, We) - end. - -collect_outer_edges_a(Faces) -> - fun(Face, _, Edge, #edge{ve=V,vs=OtherV,lf=Face,rf=Other}, Acc) -> - case gb_sets:is_member(Other, Faces) of - false -> [{V,{Edge,OtherV}}|Acc]; - true -> Acc - end; - (Face, _, Edge, #edge{ve=OtherV,vs=V,rf=Face,lf=Other}, Acc) -> - case gb_sets:is_member(Other, Faces) of - false -> [{V,{Edge,OtherV}}|Acc]; - true -> Acc - end - end. - -collect_outer_edges_b(Faces) -> - fun(Face, _, Edge, #edge{vs=V,ve=OtherV,lf=Face,rf=Other}, Acc) -> - case gb_sets:is_member(Other, Faces) of - false -> [{V,{Edge,OtherV}}|Acc]; - true -> Acc - end; - (Face, _, Edge, #edge{vs=OtherV,ve=V,rf=Face,lf=Other}, Acc) -> - case gb_sets:is_member(Other, Faces) of - false -> [{V,{Edge,OtherV}}|Acc]; - true -> Acc - end - end. - -partition_edges(Es0, Acc) -> - case gb_trees:is_empty(Es0) of - true -> Acc; - false -> - {Key,Val,Es1} = gb_trees:take_smallest(Es0), - {Cycle,Es} = part_collect_cycle(Key, Val, Es1, []), - partition_edges(Es, [Cycle|Acc]) - end. - -%% part_collect_cycle(Vertex, VertexInfo, EdgeInfo, Acc0) -> -%% none | {[Edge],EdgeInfo} -%% Collect the cycle starting with Vertex. -%% -%% Note: This function can only return 'none' when called -%% recursively. - -part_collect_cycle(_, repeated, _, _) -> - %% Repeated vertex - we are not allowed to go this way. - %% Can only happen if we were called recursively because - %% a fork was encountered. - none; -part_collect_cycle(_Va, [{Edge,Vb}], Es0, Acc0) -> - %% Basic case. Only one way to go. - Acc = [Edge|Acc0], - case gb_trees:lookup(Vb, Es0) of - none -> - {Acc,Es0}; - {value,Val} -> - Es = gb_trees:delete(Vb, Es0), - part_collect_cycle(Vb, Val, Es, Acc) - end; -part_collect_cycle(Va, [Val|More], Es0, []) -> - %% No cycle started yet and we have multiple choice of - %% edges out from this vertex. It doesn't matter which - %% edge we follow, so we'll follow the first one. - {Cycle,Es} = part_collect_cycle(Va, [Val], Es0, []), - {Cycle,gb_trees:insert(Va, More, Es)}; -part_collect_cycle(Va, Edges, Es0, Acc) -> - %% We have a partially collected cycle and we have a - %% fork (multiple choice of edges). Here we must choose - %% an edge that closes the cycle without passing Va - %% again (because repeated vertices are not allowed). - Es = gb_trees:insert(Va, repeated, Es0), - part_fork(Va, Edges, Es, Acc, []). - -part_fork(Va, [Val|More], Es0, Acc, Tried) -> - %% Try to complete the cycle by following this edge. - case part_collect_cycle(Va, [Val], Es0, Acc) of - none -> - %% Failure - try the next edge. - part_fork(Va, More, Es0, Acc, [Val|Tried]); - {Cycle,Es} -> - %% Found a cycle. Update the vertex information - %% with all edges remaining. - {Cycle,gb_trees:update(Va, lists:reverse(Tried, More), Es)} - end; -part_fork(_, [], _, _, _) -> - %% None of edges were possible. Can only happen if this function - %% was called recursively (i.e. if we hit another fork while - %% processing a fork). - none. diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl deleted file mode 100644 index 3483acb711..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl +++ /dev/null @@ -1,243 +0,0 @@ -%% -%% wings_edge.erl -- -%% -%% This module contains most edge command and edge utility functions. -%% -%% Copyright (c) 2001-2008 Bjorn Gustavsson. -%% -%% See the file "license.terms" for information on usage and redistribution -%% of this file, and for a DISCLAIMER OF ALL WARRANTIES. -%% -%% $Id: wings_edge.erl,v 1.1 2009/01/25 18:55:33 kostis Exp $ -%% - --module(wings_edge). - --export([dissolve_edges/2]). - --include("wings.hrl"). - -%%% -%%% Dissolve. -%%% - -dissolve_edges(Edges0, We0) when is_list(Edges0) -> - #we{es=Etab} = We1 = lists:foldl(fun internal_dissolve_edge/2, We0, Edges0), - case [E || E <- Edges0, gb_trees:is_defined(E, Etab)] of - Edges0 -> - %% No edge was deleted in the last pass. We are done. - We = wings_we:rebuild(We0#we{vc=undefined}), - wings_we:validate_mirror(We); - Edges -> - dissolve_edges(Edges, We1) - end; -dissolve_edges(Edges, We) -> - dissolve_edges(gb_sets:to_list(Edges), We). - -internal_dissolve_edge(Edge, #we{es=Etab}=We0) -> - case gb_trees:lookup(Edge, Etab) of - none -> We0; - {value,#edge{ltpr=Same,ltsu=Same,rtpr=Same,rtsu=Same}} -> - Empty = gb_trees:empty(), - We0#we{vc=Empty,vp=Empty,es=Empty,fs=Empty,he=gb_sets:empty()}; - {value,#edge{rtpr=Back,ltsu=Back}=Rec} -> - merge_edges(backward, Edge, Rec, We0); - {value,#edge{rtsu=Forward,ltpr=Forward}=Rec} -> - merge_edges(forward, Edge, Rec, We0); - {value,Rec} -> - try dissolve_edge_1(Edge, Rec, We0) of - We -> We - catch - throw:hole -> We0 - end - end. - -%% dissolve_edge_1(Edge, EdgeRecord, We) -> We -%% Remove an edge and a face. If one of the faces is degenerated -%% (only consists of two edges), remove that one. Otherwise, it -%% doesn't matter which face we remove. -dissolve_edge_1(Edge, #edge{lf=Remove,rf=Keep,ltpr=Same,ltsu=Same}=Rec, We) -> - dissolve_edge_2(Edge, Remove, Keep, Rec, We); -dissolve_edge_1(Edge, #edge{lf=Keep,rf=Remove}=Rec, We) -> - dissolve_edge_2(Edge, Remove, Keep, Rec, We). - -dissolve_edge_2(Edge, FaceRemove, FaceKeep, - #edge{ltpr=LP,ltsu=LS,rtpr=RP,rtsu=RS}, - #we{fs=Ftab0,es=Etab0,he=Htab0}=We0) -> - %% First change face for all edges surrounding the face we will remove. - Etab1 = wings_face:fold( - fun (_, E, _, IntEtab) when E =:= Edge -> IntEtab; - (_, E, R, IntEtab) -> - case R of - #edge{lf=FaceRemove,rf=FaceKeep} -> - throw(hole); - #edge{rf=FaceRemove,lf=FaceKeep} -> - throw(hole); - #edge{lf=FaceRemove} -> - gb_trees:update(E, R#edge{lf=FaceKeep}, IntEtab); - #edge{rf=FaceRemove} -> - gb_trees:update(E, R#edge{rf=FaceKeep}, IntEtab) - end - end, Etab0, FaceRemove, We0), - - %% Patch all predecessors and successor of the edge we will remove. - Etab2 = patch_edge(LP, RS, Edge, Etab1), - Etab3 = patch_edge(LS, RP, Edge, Etab2), - Etab4 = patch_edge(RP, LS, Edge, Etab3), - Etab5 = patch_edge(RS, LP, Edge, Etab4), - - %% Remove the edge. - Etab = gb_trees:delete(Edge, Etab5), - Htab = hardness(Edge, soft, Htab0), - - %% Remove the face. Patch the face entry for the remaining face. - Ftab1 = gb_trees:delete(FaceRemove, Ftab0), - We1 = wings_facemat:delete_face(FaceRemove, We0), - Ftab = gb_trees:update(FaceKeep, LP, Ftab1), - - %% Return result. - We = We1#we{es=Etab,fs=Ftab,vc=undefined,he=Htab}, - AnEdge = gb_trees:get(FaceKeep, Ftab), - case gb_trees:get(AnEdge, Etab) of - #edge{lf=FaceKeep,ltpr=Same,ltsu=Same} -> - internal_dissolve_edge(AnEdge, We); - #edge{rf=FaceKeep,rtpr=Same,rtsu=Same} -> - internal_dissolve_edge(AnEdge, We); - _Other -> - case wings_we:is_face_consistent(FaceKeep, We) of - true -> - We; - false -> - io:format("Dissolving would cause a badly formed face.") - end - end. - -%% -%% We like winged edges, but not winged vertices (a vertex with -%% only two edges connected to it). We will remove the winged vertex -%% by joining the two edges connected to it. -%% - -merge_edges(Dir, Edge, Rec, #we{es=Etab}=We) -> - {Va,Vb,_,_,_,_,To,To} = half_edge(Dir, Rec), - case gb_trees:get(To, Etab) of - #edge{vs=Va,ve=Vb} -> - del_2edge_face(Dir, Edge, Rec, To, We); - #edge{vs=Vb,ve=Va} -> - del_2edge_face(Dir, Edge, Rec, To, We); - _Other -> - merge_1(Dir, Edge, Rec, To, We) - end. - -merge_1(Dir, Edge, Rec, To, #we{es=Etab0,fs=Ftab0,he=Htab0}=We) -> - OtherDir = reverse_dir(Dir), - {Vkeep,Vdelete,Lf,Rf,A,B,L,R} = half_edge(OtherDir, Rec), - Etab1 = patch_edge(L, To, Edge, Etab0), - Etab2 = patch_edge(R, To, Edge, Etab1), - Etab3 = patch_half_edge(To, Vkeep, Lf, A, L, Rf, B, R, Vdelete, Etab2), - Htab = hardness(Edge, soft, Htab0), - Etab = gb_trees:delete(Edge, Etab3), - #edge{lf=Lf,rf=Rf} = Rec, - Ftab1 = update_face(Lf, To, Edge, Ftab0), - Ftab = update_face(Rf, To, Edge, Ftab1), - merge_2(To, We#we{es=Etab,fs=Ftab,he=Htab,vc=undefined}). - -merge_2(Edge, #we{es=Etab}=We) -> - %% If the merged edge is part of a two-edge face, we must - %% remove that edge too. - case gb_trees:get(Edge, Etab) of - #edge{ltpr=Same,ltsu=Same} -> - internal_dissolve_edge(Edge, We); - #edge{rtpr=Same,rtsu=Same} -> - internal_dissolve_edge(Edge, We); - _Other -> We - end. - -update_face(Face, Edge, OldEdge, Ftab) -> - case gb_trees:get(Face, Ftab) of - OldEdge -> gb_trees:update(Face, Edge, Ftab); - _Other -> Ftab - end. - -del_2edge_face(Dir, EdgeA, RecA, EdgeB, - #we{es=Etab0,fs=Ftab0,he=Htab0}=We) -> - {_,_,Lf,Rf,_,_,_,_} = half_edge(reverse_dir(Dir), RecA), - RecB = gb_trees:get(EdgeB, Etab0), - Del = gb_sets:from_list([EdgeA,EdgeB]), - EdgeANear = stabile_neighbor(RecA, Del), - EdgeBNear = stabile_neighbor(RecB, Del), - Etab1 = patch_edge(EdgeANear, EdgeBNear, EdgeA, Etab0), - Etab2 = patch_edge(EdgeBNear, EdgeANear, EdgeB, Etab1), - Etab3 = gb_trees:delete(EdgeA, Etab2), - Etab = gb_trees:delete(EdgeB, Etab3), - - %% Patch hardness table. - Htab1 = hardness(EdgeA, soft, Htab0), - Htab = hardness(EdgeB, soft, Htab1), - - %% Patch the face table. - #edge{lf=Klf,rf=Krf} = gb_trees:get(EdgeANear, Etab), - KeepFaces = ordsets:from_list([Klf,Krf]), - EdgeAFaces = ordsets:from_list([Lf,Rf]), - [DelFace] = ordsets:subtract(EdgeAFaces, KeepFaces), - Ftab1 = gb_trees:delete(DelFace, Ftab0), - [KeepFace] = ordsets:intersection(KeepFaces, EdgeAFaces), - Ftab2 = update_face(KeepFace, EdgeANear, EdgeA, Ftab1), - Ftab = update_face(KeepFace, EdgeBNear, EdgeB, Ftab2), - - %% Return result. - We#we{vc=undefined,es=Etab,fs=Ftab,he=Htab}. - -stabile_neighbor(#edge{ltpr=Ea,ltsu=Eb,rtpr=Ec,rtsu=Ed}, Del) -> - [Edge] = lists:foldl(fun(E, A) -> - case gb_sets:is_member(E, Del) of - true -> A; - false -> [E|A] - end - end, [], [Ea,Eb,Ec,Ed]), - Edge. - -%%% -%%% Setting hard/soft edges. -%%% - -hardness(Edge, soft, Htab) -> gb_sets:delete_any(Edge, Htab); -hardness(Edge, hard, Htab) -> gb_sets:add(Edge, Htab). - -%%% -%%% Utilities. -%%% - -reverse_dir(forward) -> backward; -reverse_dir(backward) -> forward. - -half_edge(backward, #edge{vs=Va,ve=Vb,lf=Lf,rf=Rf,a=A,b=B,ltsu=L,rtpr=R}) -> - {Va,Vb,Lf,Rf,A,B,L,R}; -half_edge(forward, #edge{ve=Va,vs=Vb,lf=Lf,rf=Rf,a=A,b=B,ltpr=L,rtsu=R}) -> - {Va,Vb,Lf,Rf,A,B,L,R}. - -patch_half_edge(Edge, V, FaceA, A, Ea, FaceB, B, Eb, OrigV, Etab) -> - New = case gb_trees:get(Edge, Etab) of - #edge{vs=OrigV,lf=FaceA,rf=FaceB}=Rec -> - Rec#edge{a=A,vs=V,ltsu=Ea,rtpr=Eb}; - #edge{vs=OrigV,lf=FaceB,rf=FaceA}=Rec -> - Rec#edge{a=B,vs=V,ltsu=Eb,rtpr=Ea}; - #edge{ve=OrigV,lf=FaceA,rf=FaceB}=Rec -> - Rec#edge{b=B,ve=V,ltpr=Ea,rtsu=Eb}; - #edge{ve=OrigV,lf=FaceB,rf=FaceA}=Rec -> - Rec#edge{b=A,ve=V,ltpr=Eb,rtsu=Ea} - end, - gb_trees:update(Edge, New, Etab). - -patch_edge(Edge, ToEdge, OrigEdge, Etab) -> - New = case gb_trees:get(Edge, Etab) of - #edge{ltsu=OrigEdge}=R -> - R#edge{ltsu=ToEdge}; - #edge{ltpr=OrigEdge}=R -> - R#edge{ltpr=ToEdge}; - #edge{rtsu=OrigEdge}=R -> - R#edge{rtsu=ToEdge}; - #edge{rtpr=OrigEdge}=R -> - R#edge{rtpr=ToEdge} - end, - gb_trees:update(Edge, New, Etab). diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl deleted file mode 100644 index e478ec245b..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl +++ /dev/null @@ -1,91 +0,0 @@ -%% -%% wings_edge.erl -- -%% -%% This module contains most edge command and edge utility functions. -%% - --module(wings_edge_cmd). - --export([loop_cut/1]). - --include("wings.hrl"). - -%%% -%%% The Loop Cut command. -%%% - -loop_cut(St0) -> - {Sel,St} = wings_sel:fold(fun loop_cut/3, {[],St0}, St0), - wings_sel:set(body, Sel, St). - -loop_cut(Edges, #we{name=Name,id=Id,fs=Ftab}=We0, {Sel,St0}) -> - AdjFaces = wings_face:from_edges(Edges, We0), - case loop_cut_partition(AdjFaces, Edges, We0, []) of - [_] -> - io:format("Edge loop doesn't divide ~p into two parts.", [Name]); - Parts0 -> - %% We arbitrarily decide that the largest part of the object - %% will be left unselected and will keep the name of the object. - - Parts1 = [{gb_trees:size(P),P} || P <- Parts0], - Parts2 = lists:reverse(lists:sort(Parts1)), - [_|Parts] = [gb_sets:to_list(P) || {_,P} <- Parts2], - - %% Also, this first part will also contain any sub-object - %% that was not reachable from any of the edges. Therefore, - %% we calculate the first part as the complement of the union - %% of all other parts. - - FirstComplement = ordsets:union(Parts), - First = ordsets:subtract(gb_trees:keys(Ftab), FirstComplement), - - We = wings_dissolve:complement(First, We0), - Shs = St0#st.shapes, - St = St0#st{shapes=gb_trees:update(Id, We, Shs)}, - loop_cut_make_copies(Parts, We0, Sel, St) - end. - -loop_cut_make_copies([P|Parts], We0, Sel0, #st{onext=Id}=St0) -> - Sel = [{Id,gb_sets:singleton(0)}|Sel0], - We = wings_dissolve:complement(P, We0), - St = wings_shape:insert(We, cut, St0), - loop_cut_make_copies(Parts, We0, Sel, St); -loop_cut_make_copies([], _, Sel, St) -> {Sel,St}. - -loop_cut_partition(Faces0, Edges, We, Acc) -> - case gb_sets:is_empty(Faces0) of - true -> Acc; - false -> - {AFace,Faces1} = gb_sets:take_smallest(Faces0), - Reachable = collect_faces(AFace, Edges, We), - Faces = gb_sets:difference(Faces1, Reachable), - loop_cut_partition(Faces, Edges, We, [Reachable|Acc]) - end. - -collect_faces(Face, Edges, We) -> - collect_faces(gb_sets:singleton(Face), We, Edges, gb_sets:empty()). - -collect_faces(Work0, We, Edges, Acc0) -> - case gb_sets:is_empty(Work0) of - true -> Acc0; - false -> - {Face,Work1} = gb_sets:take_smallest(Work0), - Acc = gb_sets:insert(Face, Acc0), - Work = collect_maybe_add(Work1, Face, Edges, We, Acc), - collect_faces(Work, We, Edges, Acc) - end. - -collect_maybe_add(Work, Face, Edges, We, Res) -> - wings_face:fold( - fun(_, Edge, Rec, A) -> - case gb_sets:is_member(Edge, Edges) of - true -> A; - false -> - Of = wings_face:other(Face, Rec), - case gb_sets:is_member(Of, Res) of - true -> A; - false -> gb_sets:add(Of, A) - end - end - end, Work, Face, We). - diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl deleted file mode 100644 index 487c05aa58..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl +++ /dev/null @@ -1,127 +0,0 @@ -%% -%% wings_face.erl -- -%% -%% This module contains help routines for faces, such as fold functions -%% face iterators. -%% - --module(wings_face). - --export([delete_bad_faces/2, fold/4, fold_faces/4, from_edges/2, - inner_edges/2, to_edges/2, other/2]). - --include("wings.hrl"). - -from_edges(Es, #we{es=Etab}) when is_list(Es) -> - from_edges_1(Es, Etab, []); -from_edges(Es, We) -> - from_edges(gb_sets:to_list(Es), We). - -from_edges_1([E|Es], Etab, Acc) -> - #edge{lf=Lf,rf=Rf} = gb_trees:get(E, Etab), - from_edges_1(Es, Etab, [Lf,Rf|Acc]); -from_edges_1([], _, Acc) -> gb_sets:from_list(Acc). - -%% other(Face, EdgeRecord) -> OtherFace -%% Pick up the "other face" from an edge record. -other(Face, #edge{lf=Face,rf=Other}) -> Other; -other(Face, #edge{rf=Face,lf=Other}) -> Other. - -%% to_edges(Faces, We) -> [Edge] -%% Convert a set or list of faces to a list of edges. -to_edges(Fs, We) -> - ordsets:from_list(to_edges_raw(Fs, We)). - -%% inner_edges(Faces, We) -> [Edge] -%% Given a set of faces, return all inner edges. -inner_edges(Faces, We) -> - S = to_edges_raw(Faces, We), - inner_edges_1(lists:sort(S), []). - -inner_edges_1([E,E|T], In) -> - inner_edges_1(T, [E|In]); -inner_edges_1([_|T], In) -> - inner_edges_1(T, In); -inner_edges_1([], In) -> lists:reverse(In). - -%% Fold over all edges surrounding a face. - -fold(F, Acc, Face, #we{es=Etab,fs=Ftab}) -> - Edge = gb_trees:get(Face, Ftab), - fold(Edge, Etab, F, Acc, Face, Edge, not_done). - -fold(LastEdge, _, _, Acc, _, LastEdge, done) -> Acc; -fold(Edge, Etab, F, Acc0, Face, LastEdge, _) -> - case gb_trees:get(Edge, Etab) of - #edge{ve=V,lf=Face,ltsu=NextEdge}=E -> - Acc = F(V, Edge, E, Acc0), - fold(NextEdge, Etab, F, Acc, Face, LastEdge, done); - #edge{vs=V,rf=Face,rtsu=NextEdge}=E -> - Acc = F(V, Edge, E, Acc0), - fold(NextEdge, Etab, F, Acc, Face, LastEdge, done) - end. - -%% Fold over a set of faces. - -fold_faces(F, Acc0, [Face|Faces], #we{es=Etab,fs=Ftab}=We) -> - Edge = gb_trees:get(Face, Ftab), - Acc = fold_faces_1(Edge, Etab, F, Acc0, Face, Edge, not_done), - fold_faces(F, Acc, Faces, We); -fold_faces(_F, Acc, [], _We) -> Acc; -fold_faces(F, Acc, Faces, We) -> - fold_faces(F, Acc, gb_sets:to_list(Faces), We). - -fold_faces_1(LastEdge, _, _, Acc, _, LastEdge, done) -> Acc; -fold_faces_1(Edge, Etab, F, Acc0, Face, LastEdge, _) -> - case gb_trees:get(Edge, Etab) of - #edge{ve=V,lf=Face,ltsu=NextEdge}=E -> - Acc = F(Face, V, Edge, E, Acc0), - fold_faces_1(NextEdge, Etab, F, Acc, Face, LastEdge, done); - #edge{vs=V,rf=Face,rtsu=NextEdge}=E -> - Acc = F(Face, V, Edge, E, Acc0), - fold_faces_1(NextEdge, Etab, F, Acc, Face, LastEdge, done) - end. - -%% Return an unsorted list of edges for the faces (with duplicates). - -to_edges_raw(Faces, #we{es=Etab,fs=Ftab}) when is_list(Faces) -> - to_edges_raw(Faces, Ftab, Etab, []); -to_edges_raw(Faces, We) -> - to_edges_raw(gb_sets:to_list(Faces), We). - -to_edges_raw([Face|Faces], Ftab, Etab, Acc0) -> - Edge = gb_trees:get(Face, Ftab), - Acc = to_edges_raw_1(Edge, Etab, Acc0, Face, Edge, not_done), - to_edges_raw(Faces, Ftab, Etab, Acc); -to_edges_raw([], _, _, Acc) -> Acc. - -to_edges_raw_1(LastEdge, _, Acc, _, LastEdge, done) -> Acc; -to_edges_raw_1(Edge, Etab, Acc, Face, LastEdge, _) -> - case gb_trees:get(Edge, Etab) of - #edge{lf=Face,ltsu=NextEdge} -> - to_edges_raw_1(NextEdge, Etab, [Edge|Acc], Face, LastEdge, done); - #edge{rf=Face,rtsu=NextEdge} -> - to_edges_raw_1(NextEdge, Etab, [Edge|Acc], Face, LastEdge, done) - end. - -delete_bad_faces(Fs, #we{fs=Ftab,es=Etab}=We) when is_list(Fs) -> - Es = bad_edges(Fs, Ftab, Etab, []), - wings_edge:dissolve_edges(Es, We); -delete_bad_faces(Fs, We) -> - delete_bad_faces(gb_sets:to_list(Fs), We). - -bad_edges([F|Fs], Ftab, Etab, Acc) -> - case gb_trees:lookup(F, Ftab) of - {value,Edge} -> - case gb_trees:get(Edge, Etab) of - #edge{ltpr=Same,ltsu=Same,rtpr=Same,rtsu=Same} -> - erlang:error({internal_error,one_edged_face,F}); - #edge{ltpr=Same,ltsu=Same} -> - bad_edges(Fs, Ftab, Etab, [Edge|Acc]); - #edge{rtpr=Same,rtsu=Same} -> - bad_edges(Fs, Ftab, Etab, [Edge|Acc]); - _ -> bad_edges(Fs, Ftab, Etab, Acc) - end; - none -> bad_edges(Fs, Ftab, Etab, Acc) - end; -bad_edges([], _, _, Acc) -> Acc. diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl deleted file mode 100644 index 6e018e49b5..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl +++ /dev/null @@ -1,299 +0,0 @@ -%% -%% wings_facemat.erl -- -%% -%% This module keeps tracks of the mapping from a face number -%% to its material name. -%% -%% Copyright (c) 2001-2005 Bjorn Gustavsson -%% -%% See the file "license.terms" for information on usage and redistribution -%% of this file, and for a DISCLAIMER OF ALL WARRANTIES. -%% -%% $Id: wings_facemat.erl,v 1.1 2009/01/25 18:55:33 kostis Exp $ -%% -%% -%% - --module(wings_facemat). --export([all/1,face/2,used_materials/1,mat_faces/2, - assign/2,assign/3, - delete_face/2,delete_faces/2,keep_faces/2, - hide_faces/1,show_faces/1, - renumber/2,gc/1,merge/1]). - --include("wings.hrl"). --import(lists, [keysearch/3,reverse/1,reverse/2,sort/1]). - -%%% -%%% API functions for retrieving information. -%%% - -%% all(We) -> [{Face,MaterialName}] -%% Return materials for all faces as an ordered list. -all(#we{mat=M}=We) when is_atom(M) -> - Vis = visible_faces(We), - make_tab(Vis, M); -all(#we{mat=L}) when is_list(L) -> - remove_invisible(L). - -%% face(Face, We) -> MaterialName -%% Return the material for the face Face. -face(_, #we{mat=M}) when is_atom(M) -> M; -face(Face, #we{mat=Tab}) -> - {value,{_,Mat}} = keysearch(Face, 1, Tab), - Mat. - -%% used_materials(We) -> [MaterialName] -%% Return an ordered list of all materials used in the We. -used_materials(#we{mat=M}) when is_atom(M) -> [M]; -used_materials(#we{mat=L}) when is_list(L) -> - used_materials_1(L, []). - -%% mat_faces([{Face,Info}], We) -> [{Mat,[{Face,Info}]}] -%% Group face tab into groups based on material. -%% Used for displaying objects. -mat_faces(Ftab, #we{mat=AtomMat}) when is_atom(AtomMat) -> - [{AtomMat,Ftab}]; -mat_faces(Ftab, #we{mat=MatTab}) -> - mat_faces_1(Ftab, remove_invisible(MatTab), []). - -%%% -%%% API functions for updating material name mapping. -%%% - -%% assign([{Face,MaterialName}], We) -> We' -%% Assign materials. -assign([], We) -> We; -assign([{F,M}|_]=FaceMs, We) when is_atom(M), is_integer(F) -> - Tab = ordsets:from_list(FaceMs), - assign_face_ms(Tab, We). - -%% assign(MaterialName, Faces, We) -> We' -%% Assign MaterialName to all faces Faces. -assign(Mat, _, #we{mat=Mat}=We) when is_atom(Mat) -> We; -assign(Mat, Fs, We) when is_atom(Mat), is_list(Fs) -> - assign_1(Mat, Fs, We); -assign(Mat, Fs, We) when is_atom(Mat) -> - assign_1(Mat, gb_sets:to_list(Fs), We). - -%% delete_face(Face, We) -> We' -%% Delete the material name mapping for the face Face. -delete_face(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We; -delete_face(Face, #we{mat=MatTab0}=We) -> - MatTab = orddict:erase(Face, MatTab0), - We#we{mat=MatTab}. - -%% delete_face(Faces, We) -> We' -%% Delete the material name mapping for all faces Faces. -delete_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We; -delete_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) -> - Faces = sofs:from_external(Faces0, [face]), - MatTab1 = sofs:from_external(MatTab0, [{face,mat}]), - MatTab2 = sofs:drestriction(MatTab1, Faces), - MatTab = sofs:to_external(MatTab2), - We#we{mat=MatTab}; -delete_faces(Faces, We) -> - delete_faces(gb_sets:to_list(Faces), We). - -%% keep_faces(Faces, We) -> We' -%% Delete all the other material names mapping for all faces other Faces. -keep_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We; -keep_faces([Face], We) -> - Mat = face(Face,We), - We#we{mat=[{Face,Mat}]}; -keep_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) -> - Faces = sofs:from_external(Faces0, [face]), - MatTab1 = sofs:from_external(MatTab0, [{face,mat}]), - MatTab2 = sofs:restriction(MatTab1, Faces), - MatTab = sofs:to_external(MatTab2), - We#we{mat=MatTab}; -keep_faces(Faces, We) -> - keep_faces(gb_sets:to_list(Faces), We). - -%% hide_faces(We) -> We' -%% Update the material name mapping in the We to reflect -%% the newly hidden faces in the face tab. -hide_faces(#we{mat=M}=We) when is_atom(M) -> We; -hide_faces(#we{mat=L0,fs=Ftab}=We) -> - L = hide_faces_1(L0, Ftab, []), - We#we{mat=L}. - -%% show_faces(We) -> We' -%% Update the material name mapping in the We to reflect -%% that all faces are again visible. -show_faces(#we{mat=M}=We) when is_atom(M) -> We; -show_faces(#we{mat=L0}=We) -> - L = show_faces_1(L0, []), - We#we{mat=L}. - -%% renumber(MaterialMapping, FaceOldToNew) -> MaterialMapping. -%% Renumber face number in material name mapping. -renumber(Mat, _) when is_atom(Mat) -> Mat; -renumber(L, Fmap) when is_list(L) -> renumber_1(L, Fmap, []). - -%% gc(We) -> We' -%% Garbage collect the material mapping information, removing -%% the mapping for any face no longer present in the face table. -gc(#we{mat=Mat}=We) when is_atom(Mat) -> We; -gc(#we{mat=Tab0,fs=Ftab}=We) -> - Fs = sofs:from_external(gb_trees:keys(Ftab), [face]), - Tab1 = sofs:from_external(Tab0, [{face,material}]), - Tab2 = sofs:restriction(Tab1, Fs), - Tab = sofs:to_external(Tab2), - We#we{mat=compress(Tab)}. - -%% merge([We]) -> [{Face,MaterialName}] | MaterialName. -%% Merge materials for several objects. -merge([#we{mat=M}|Wes]=L) when is_atom(M) -> - case merge_all_same(Wes, M) of - true -> M; - false -> merge_1(L, []) - end; -merge(L) -> merge_1(L, []). - -merge_1([#we{mat=M,es=Etab}|T], Acc) when is_atom(M) -> - FsM = merge_2(gb_trees:values(Etab), M, []), - merge_1(T, [FsM|Acc]); -merge_1([#we{mat=FsMs}|T], Acc) -> - merge_1(T, [FsMs|Acc]); -merge_1([], Acc) -> lists:merge(Acc). - -merge_2([#edge{lf=Lf,rf=Rf}|T], M, Acc) -> - merge_2(T, M, [{Lf,M},{Rf,M}|Acc]); -merge_2([], _, Acc) -> ordsets:from_list(Acc). - -merge_all_same([#we{mat=M}|Wes], M) -> merge_all_same(Wes, M); -merge_all_same([_|_], _) -> false; -merge_all_same([], _) -> true. - -%%% -%%% Local functions. -%%% - -assign_1(Mat, Fs, #we{fs=Ftab}=We) -> - case length(Fs) =:= gb_trees:size(Ftab) of - true -> We#we{mat=Mat}; - false -> assign_2(Mat, Fs, We) - end. - -assign_2(Mat, Fs0, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) -> - Fs = ordsets:from_list(Fs0), - OtherFaces = ordsets:subtract(gb_trees:keys(Ftab), Fs), - Tab0 = make_tab(OtherFaces, Mat0), - Tab1 = make_tab(Fs, Mat), - Tab = lists:merge(Tab0, Tab1), - We#we{mat=Tab}; -assign_2(Mat, Fs0, #we{mat=Tab0}=We) when is_list(Tab0) -> - Fs = ordsets:from_list(Fs0), - Tab1 = make_tab(Fs, Mat), - Tab = mat_merge(Tab1, Tab0, []), - We#we{mat=Tab}. - -assign_face_ms(Tab, #we{fs=Ftab}=We) -> - case length(Tab) =:= gb_trees:size(Ftab) of - true -> We#we{mat=compress(Tab)}; - false -> assign_face_ms_1(Tab, We) - end. - -assign_face_ms_1(Tab1, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) -> - Tab0 = make_tab(gb_trees:keys(Ftab), Mat0), - Tab = mat_merge(Tab1, Tab0, []), - We#we{mat=Tab}; -assign_face_ms_1(Tab1, #we{mat=Tab0}=We) when is_list(Tab0) -> - Tab = mat_merge(Tab1, Tab0, []), - We#we{mat=Tab}. - -mat_merge([{Fn,_}|_]=Fns, [{Fo,_}=Fold|Fos], Acc) when Fo < Fn -> - mat_merge(Fns, Fos, [Fold|Acc]); -mat_merge([{Fn,_}=Fnew|Fns], [{Fo,_}|_]=Fos, Acc) when Fo > Fn -> - mat_merge(Fns, Fos, [Fnew|Acc]); -mat_merge([Fnew|Fns], [_|Fos], Acc) -> % Equality - mat_merge(Fns, Fos, [Fnew|Acc]); -mat_merge([], Fos, Acc) -> - rev_compress(Acc, Fos); -mat_merge(Fns, [], Acc) -> - rev_compress(Acc, Fns). - -make_tab(Fs, M) -> - make_tab_1(Fs, M, []). - -make_tab_1([F|Fs], M, Acc) -> - make_tab_1(Fs, M, [{F,M}|Acc]); -make_tab_1([], _, Acc) -> reverse(Acc). - - -visible_faces(#we{fs=Ftab}) -> - visible_faces_1(gb_trees:keys(Ftab)). - -visible_faces_1([F|Fs]) when F < 0 -> - visible_faces_1(Fs); -visible_faces_1(Fs) -> Fs. - -remove_invisible([{F,_}|Fs]) when F < 0 -> - remove_invisible(Fs); -remove_invisible(Fs) -> Fs. - -hide_faces_1([{F,_}=P|Fms], Ftab, Acc) when F < 0 -> - hide_faces_1(Fms, Ftab, [P|Acc]); -hide_faces_1([{F,M}=P|Fms], Ftab, Acc) -> - case gb_trees:is_defined(F, Ftab) of - false -> hide_faces_1(Fms, Ftab, [{-F-1,M}|Acc]); - true -> hide_faces_1(Fms, Ftab, [P|Acc]) - end; -hide_faces_1([], _, Acc) -> sort(Acc). - -show_faces_1([{F,M}|Fms], Acc) when F < 0 -> - show_faces_1(Fms, [{-F-1,M}|Acc]); -show_faces_1(Fs, Acc) -> sort(Acc++Fs). - -renumber_1([{F,M}|T], Fmap, Acc) -> - renumber_1(T, Fmap, [{gb_trees:get(F, Fmap),M}|Acc]); -renumber_1([], _, Acc) -> sort(Acc). - -%% rev_compress([{Face,Mat}], [{Face,Mat}]) -> [{Face,Mat}] | Mat. -%% Reverse just like lists:reverse/2, but if all materials -%% turns out to be just the same, return that material. -rev_compress(L, Acc) -> - case same_mat(Acc) of - [] -> reverse(L, Acc); - M -> rev_compress_1(L, M, Acc) - end. - -rev_compress_1([{_,M}=E|T], M, Acc) -> - %% Same material. - rev_compress_1(T, M, [E|Acc]); -rev_compress_1([_|_]=L, _, Acc) -> - %% Another material. Finish by using reverse/2. - reverse(L, Acc); -rev_compress_1([], M, _) -> - %% All materials turned out to be the same. - M. - -%% compress(MaterialTab) -> [{Face,Mat}] | Mat. -%% Compress a face mapping if possible. -compress(M) when is_atom(M) -> M; -compress(L) when is_list(L) -> - case same_mat(L) of - [] -> L; - M -> M - end. - -same_mat([]) -> []; -same_mat([{_,M}|T]) -> same_mat_1(T, M). - -same_mat_1([{_,M}|T], M) -> same_mat_1(T, M); -same_mat_1([], M) -> M; -same_mat_1(_, _) -> []. - -used_materials_1([{_,M}|T], [M|_]=Acc) -> - used_materials_1(T, Acc); -used_materials_1([{_,M}|T], Acc) -> - used_materials_1(T, [M|Acc]); -used_materials_1([], Acc) -> - ordsets:from_list(Acc). - -mat_faces_1([{F1,_}|_]=Fs, [{F2,_}|Ms], Acc) when F2 < F1 -> - mat_faces_1(Fs, Ms, Acc); -mat_faces_1([{F,Info}|Fs], [{F,Mat}|Ms], Acc) -> - mat_faces_1(Fs, Ms, [{Mat,{F,Info}}|Acc]); -mat_faces_1([], _, Acc) -> wings_util:rel2fam(Acc). diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl deleted file mode 100644 index ebcb560f27..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl +++ /dev/null @@ -1,15 +0,0 @@ -%% -%% wings_intl.hrl -- -%% -%% Defines for translations -%% -%% Copyright (c) 2001-2005 Bjorn Gustavsson -%% -%% See the file "license.terms" for information on usage and redistribution -%% of this file, and for a DISCLAIMER OF ALL WARRANTIES. -%% -%% $Id: wings_intl.hrl,v 1.1 2009/01/25 18:55:33 kostis Exp $ -%% - --define(STR(A,B,Str), wings_lang:str({?MODULE,A,B},Str)). --define(__(Key,Str), wings_lang:str({?MODULE,Key},Str)). diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl deleted file mode 100644 index 39002c675d..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl +++ /dev/null @@ -1,37 +0,0 @@ -%% -%% wings_io.erl -- -%% -%% This module contains most of the low-level GUI for Wings. -%% - --module(wings_io). - --export([get_matching_events/1]). - --define(EVENT_QUEUE, wings_io_event_queue). - -%%% -%%% Input. -%%% - -get_matching_events(Filter) -> - Eq = get(?EVENT_QUEUE), - get_matching_events_1(Filter, Eq, [], []). - -get_matching_events_1(Filter, Eq0, Match, NoMatch) -> - case queue:out(Eq0) of - {{value,Ev},Eq} -> - case Filter(Ev) of - false -> - get_matching_events_1(Filter, Eq, Match, [Ev|NoMatch]); - true -> - get_matching_events_1(Filter, Eq, [Ev|Match], NoMatch) - end; - {empty,{In,Out}} -> - case Match of - [] -> []; - _ -> - put(?EVENT_QUEUE, {In, lists:reverse(NoMatch, Out)}), - Match - end - end. diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl deleted file mode 100644 index eef797027e..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl +++ /dev/null @@ -1,68 +0,0 @@ -%% -%% wings_sel.erl -- -%% -%% This module implements selection utilities. -%% - --module(wings_sel). - --export([face_regions/2, fold/3, set/3]). - --include("wings.hrl"). - -set(Mode, Sel, St) -> - St#st{selmode=Mode, sel=lists:sort(Sel), sh=false}. - -%%% -%%% Fold over the selection. -%%% - -fold(F, Acc, #st{sel=Sel,shapes=Shapes}) -> - fold_1(F, Acc, Shapes, Sel). - -fold_1(F, Acc0, Shapes, [{Id,Items}|T]) -> - We = gb_trees:get(Id, Shapes), - ?ASSERT(We#we.id =:= Id), - fold_1(F, F(Items, We, Acc0), Shapes, T); -fold_1(_F, Acc, _Shapes, []) -> Acc. - -%%% -%%% Divide the face selection into regions where each face shares at least -%%% one edge with another face in the same region. Two faces can share a -%%% vertex without necessarily being in the same region. -%%% - -face_regions(Faces, We) when is_list(Faces) -> - face_regions_1(gb_sets:from_list(Faces), We); -face_regions(Faces, We) -> - face_regions_1(Faces, We). - -face_regions_1(Faces, We) -> - find_face_regions(Faces, We, fun collect_face_fun/5, []). - -find_face_regions(Faces0, We, Coll, Acc) -> - case gb_sets:is_empty(Faces0) of - true -> Acc; - false -> - {Face,Faces1} = gb_sets:take_smallest(Faces0), - Ws = [Face], - {Reg,Faces} = collect_face_region(Ws, We, Coll, [], Faces1), - find_face_regions(Faces, We, Coll, [Reg|Acc]) - end. - -collect_face_region([_|_]=Ws0, We, Coll, Reg0, Faces0) -> - Reg = Ws0++Reg0, - {Ws,Faces} = wings_face:fold_faces(Coll, {[],Faces0}, Ws0, We), - collect_face_region(Ws, We, Coll, Reg, Faces); -collect_face_region([], _, _, Reg, Faces) -> - {gb_sets:from_list(Reg),Faces}. - -collect_face_fun(Face, _, _, Rec, {Ws,Faces}=A) -> - Of = case Rec of - #edge{lf=Face,rf=Of0} -> Of0; - #edge{rf=Face,lf=Of0} -> Of0 - end, - case gb_sets:is_member(Of, Faces) of - true -> {[Of|Ws],gb_sets:delete(Of, Faces)}; - false -> A - end. diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl deleted file mode 100644 index 0df8ca68eb..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl +++ /dev/null @@ -1,69 +0,0 @@ -%% -%% wings_shape.erl -- -%% -%% Utilities for shape records. -%% - --module(wings_shape). - --export([insert/3]). - --include("wings.hrl"). - -%%% -%%% Exported functions. -%%% - -%% new(We, Suffix, St0) -> St. -%% Suffix = cut | clone | copy | extract | sep -%% -%% Create a new object based on an old object. The name -%% will be created from the old name (with digits and known -%% suffixes stripped) with the given Suffix and a number -%% appended. -insert(#we{name=OldName}=We0, Suffix, #st{shapes=Shapes0,onext=Oid}=St) -> - Name = new_name(OldName, Suffix, Oid), - We = We0#we{id=Oid,name=Name}, - Shapes = gb_trees:insert(Oid, We, Shapes0), - St#st{shapes=Shapes,onext=Oid+1}. - -%%% -%%% Local functions follow. -%%% - -new_name(OldName, Suffix0, Id) -> - Suffix = suffix(Suffix0), - Base = base(lists:reverse(OldName)), - lists:reverse(Base, "_" ++ Suffix ++ integer_to_list(Id)). - -%% Note: Filename suffixes are intentionally not translated. -%% If we are to translate them in the future, base/1 below -%% must be updated to strip suffixes (both for the current language -%% and for English). - -suffix(cut) -> "cut"; -suffix(clone) -> "clone"; -suffix(copy) -> "copy"; -suffix(extract) -> "extract"; -suffix(mirror) -> "mirror"; -suffix(sep) -> "sep". - -%% base_1(ReversedName) -> ReversedBaseName -%% Given an object name, strip digits and known suffixes to -%% create a base name. Returns the unchanged name if -%% no known suffix could be stripped. - -base(OldName) -> - case base_1(OldName) of - error -> OldName; - Base -> Base - end. - -base_1([H|T]) when $0 =< H, H =< $9 -> base_1(T); -base_1("tuc_"++Base) -> Base; %"_cut" -base_1("enolc_"++Base) -> Base; %"_clone" -base_1("ypoc_"++Base) -> Base; %"_copy" -base_1("tcartxe_"++Base) -> Base; %"_extract" -base_1("rorrim_"++Base) -> Base; %"_mirror" -base_1("pes_"++Base) -> Base; %"_sep" -base_1(_Base) -> error. diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl deleted file mode 100644 index 9572e19955..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl +++ /dev/null @@ -1,39 +0,0 @@ -%% -%% wings_util.erl -- -%% -%% Various utility functions that not obviously fit somewhere else. -%% - --module(wings_util). - --export([gb_trees_smallest_key/1, gb_trees_largest_key/1, - gb_trees_map/2, rel2fam/1]). - --include("wings.hrl"). - -rel2fam(Rel) -> - sofs:to_external(sofs:relation_to_family(sofs:relation(Rel))). - -%% a definition that does not violate the opaqueness of gb_tree() -gb_trees_smallest_key(Tree) -> - {Key, _V} = gb_trees:smallest(Tree), - Key. - -%% a definition that violates the opaqueness of gb_tree() -gb_trees_largest_key({_, Tree}) -> - largest_key1(Tree). - -largest_key1({Key, _Value, _Smaller, nil}) -> - Key; -largest_key1({_Key, _Value, _Smaller, Larger}) -> - largest_key1(Larger). - -gb_trees_map(F, {Size,Tree}) -> - {Size,gb_trees_map_1(F, Tree)}. - -gb_trees_map_1(_, nil) -> nil; -gb_trees_map_1(F, {K,V,Smaller,Larger}) -> - {K,F(K, V), - gb_trees_map_1(F, Smaller), - gb_trees_map_1(F, Larger)}. - diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl deleted file mode 100644 index d782144def..0000000000 --- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl +++ /dev/null @@ -1,250 +0,0 @@ -%% -%% wings_we.erl -- -%% -%% This module contains functions to build and manipulate -%% we records (winged-edged records, the central data structure -%% in Wings 3D). - --module(wings_we). - --export([rebuild/1, is_consistent/1, is_face_consistent/2, new_id/1, - new_items_as_ordset/3, validate_mirror/1, visible/1, visible_edges/1]). - --include("wings.hrl"). - -%%% -%%% API. -%%% - -validate_mirror(#we{mirror=none}=We) -> We; -validate_mirror(#we{fs=Ftab,mirror=Face}=We) -> - case gb_trees:is_defined(Face, Ftab) of - false -> We#we{mirror=none}; - true -> We - end. - -%% rebuild(We) -> We' -%% Rebuild any missing 'vc' and 'fs' tables. If there are -%% fewer elements in the 'vc' table than in the 'vp' table, -%% remove redundant entries in the 'vp' table. Updated id -%% bounds. -rebuild(#we{vc=undefined,fs=undefined,es=Etab0}=We0) -> - Etab = gb_trees:to_list(Etab0), - Ftab = rebuild_ftab(Etab), - VctList = rebuild_vct(Etab), - We = We0#we{vc=gb_trees:from_orddict(VctList),fs=Ftab}, - rebuild_1(VctList, We); -rebuild(#we{vc=undefined,es=Etab}=We) -> - VctList = rebuild_vct(gb_trees:to_list(Etab), []), - rebuild_1(VctList, We#we{vc=gb_trees:from_orddict(VctList)}); -rebuild(#we{fs=undefined,es=Etab}=We) -> - Ftab = rebuild_ftab(gb_trees:to_list(Etab)), - rebuild(We#we{fs=Ftab}); -rebuild(We) -> update_id_bounds(We). - -%%% Utilities for allocating IDs. - -new_id(#we{next_id=Id}=We) -> - {Id,We#we{next_id=Id+1}}. - -%%% Returns sets of newly created items. - -new_items_as_ordset(vertex, #we{next_id=Wid}, #we{next_id=NewWid,vp=Tab}) -> - new_items_as_ordset_1(Tab, Wid, NewWid); -new_items_as_ordset(edge, #we{next_id=Wid}, #we{next_id=NewWid,es=Tab}) -> - new_items_as_ordset_1(Tab, Wid, NewWid); -new_items_as_ordset(face, #we{next_id=Wid}, #we{next_id=NewWid,fs=Tab}) -> - new_items_as_ordset_1(Tab, Wid, NewWid). - -any_hidden(#we{fs=Ftab}) -> - not gb_trees:is_empty(Ftab) andalso - wings_util:gb_trees_smallest_key(Ftab) < 0. - -%%% -%%% Local functions. -%%% - -rebuild_1(VctList, #we{vc=Vct,vp=Vtab0}=We) -> - case {gb_trees:size(Vct),gb_trees:size(Vtab0)} of - {Same,Same} -> rebuild(We); - {Sz1,Sz2} when Sz1 < Sz2 -> - Vtab = vertex_gc_1(VctList, gb_trees:to_list(Vtab0), []), - rebuild(We#we{vp=Vtab}) - end. - -rebuild_vct(Es) -> - rebuild_vct(Es, []). - -rebuild_vct([{Edge,#edge{vs=Va,ve=Vb}}|Es], Acc0) -> - Acc = rebuild_maybe_add(Va, Vb, Edge, Acc0), - rebuild_vct(Es, Acc); -rebuild_vct([], VtoE) -> - build_incident_tab(VtoE). - -rebuild_ftab(Es) -> - rebuild_ftab_1(Es, []). - -rebuild_ftab_1([{Edge,#edge{lf=Lf,rf=Rf}}|Es], Acc0) -> - Acc = rebuild_maybe_add(Lf, Rf, Edge, Acc0), - rebuild_ftab_1(Es, Acc); -rebuild_ftab_1([], FtoE) -> - gb_trees:from_orddict(build_incident_tab(FtoE)). - -rebuild_maybe_add(Ka, Kb, E, [_,{Ka,_}|_]=Acc) -> - [{Kb,E}|Acc]; -rebuild_maybe_add(Ka, Kb, E, [_,{Kb,_}|_]=Acc) -> - [{Ka,E}|Acc]; -rebuild_maybe_add(Ka, Kb, E, [{Ka,_}|_]=Acc) -> - [{Kb,E}|Acc]; -rebuild_maybe_add(Ka, Kb, E, [{Kb,_}|_]=Acc) -> - [{Ka,E}|Acc]; -rebuild_maybe_add(Ka, Kb, E, Acc) -> - [{Ka,E},{Kb,E}|Acc]. - -vertex_gc_1([{V,_}|Vct], [{V,_}=Vtx|Vpos], Acc) -> - vertex_gc_1(Vct, Vpos, [Vtx|Acc]); -vertex_gc_1([_|_]=Vct, [_|Vpos], Acc) -> - vertex_gc_1(Vct, Vpos, Acc); -vertex_gc_1([], _, Acc) -> - gb_trees:from_orddict(lists:reverse(Acc)). - -%%% -%%% Handling of hidden faces. -%%% - -visible(#we{mirror=none,fs=Ftab}) -> - visible_2(gb_trees:keys(Ftab)); -visible(#we{mirror=Face,fs=Ftab}) -> - visible_2(gb_trees:keys(gb_trees:delete(Face, Ftab))). - -visible_2([F|Fs]) when F < 0 -> visible_2(Fs); -visible_2(Fs) -> Fs. - -visible_edges(#we{es=Etab,mirror=Face}=We) -> - case any_hidden(We) of - false -> gb_trees:keys(Etab); - true -> visible_es_1(gb_trees:to_list(Etab), Face, []) - end. - -visible_es_1([{E,#edge{lf=Lf,rf=Rf}}|Es], Face, Acc) -> - if - Lf < 0 -> - %% Left face hidden. - if - Rf < 0; Rf =:= Face -> - %% Both faces invisible (in some way). - visible_es_1(Es, Face, Acc); - true -> - %% Right face is visible. - visible_es_1(Es, Face, [E|Acc]) - end; - Lf =:= Face, Rf < 0 -> - %% Left face mirror, right face hidden. - visible_es_1(Es, Face, Acc); - true -> - %% At least one face visible. - visible_es_1(Es, Face, [E|Acc]) - end; -visible_es_1([], _, Acc) -> ordsets:from_list(Acc). - -update_id_bounds(#we{vp=Vtab,es=Etab,fs=Ftab}=We) -> - case gb_trees:is_empty(Etab) of - true -> We#we{next_id=0}; - false -> - LastId = lists:max([wings_util:gb_trees_largest_key(Vtab), - wings_util:gb_trees_largest_key(Etab), - wings_util:gb_trees_largest_key(Ftab)]), - We#we{next_id=LastId+1} - end. - -%% build_incident_tab([{Elem,Edge}]) -> [{Elem,Edge}] -%% Elem = Face or Vertex -%% Build the table of incident edges for either faces or vertices. -%% Returns an ordered list where each Elem is unique. - -build_incident_tab(ElemToEdgeRel) -> - T = ets:new(?MODULE, [ordered_set]), - ets:insert(T, ElemToEdgeRel), - R = ets:tab2list(T), - ets:delete(T), - R. - -%%% -%%% Calculate normals. -%%% - -new_items_as_ordset_1(Tab, Wid, NewWid) when NewWid-Wid < 32 -> - new_items_as_ordset_2(Wid, NewWid, Tab, []); -new_items_as_ordset_1(Tab, Wid, _NewWid) -> - [Item || Item <- gb_trees:keys(Tab), Item >= Wid]. - -new_items_as_ordset_2(Wid, NewWid, Tab, Acc) when Wid < NewWid -> - case gb_trees:is_defined(Wid, Tab) of - true -> new_items_as_ordset_2(Wid+1, NewWid, Tab, [Wid|Acc]); - false -> new_items_as_ordset_2(Wid+1, NewWid, Tab, Acc) - end; -new_items_as_ordset_2(_Wid, _NewWid, _Tab, Acc) -> lists:reverse(Acc). - -%%% -%%% Test the consistency of a #we{}. -%%% - -is_consistent(#we{}=We) -> - try - validate_vertex_tab(We), - validate_faces(We) - catch error:_ -> false - end. - -is_face_consistent(Face, #we{fs=Ftab,es=Etab}) -> - Edge = gb_trees:get(Face, Ftab), - try validate_face(Face, Edge, Etab) - catch error:_ -> false - end. - -validate_faces(#we{fs=Ftab,es=Etab}) -> - validate_faces_1(gb_trees:to_list(Ftab), Etab). - -validate_faces_1([{Face,Edge}|Fs], Etab) -> - validate_face(Face, Edge, Etab), - validate_faces_1(Fs, Etab); -validate_faces_1([], _) -> true. - -validate_face(Face, Edge, Etab) -> - Ccw = walk_face_ccw(Edge, Etab, Face, Edge, []), - Edge = walk_face_cw(Edge, Etab, Face, Ccw), - [V|Vs] = lists:sort(Ccw), - validate_face_vertices(Vs, V). - -validate_face_vertices([V|_], V) -> - erlang:error(repeated_vertex); -validate_face_vertices([_], _) -> - true; -validate_face_vertices([V|Vs], _) -> - validate_face_vertices(Vs, V). - -walk_face_ccw(LastEdge, _, _, LastEdge, [_|_]=Acc) -> Acc; -walk_face_ccw(Edge, Etab, Face, LastEdge, Acc) -> - case gb_trees:get(Edge, Etab) of - #edge{ve=V,lf=Face,ltpr=Next} -> - walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc]); - #edge{vs=V,rf=Face,rtpr=Next} -> - walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc]) - end. - -walk_face_cw(Edge, _, _, []) -> Edge; -walk_face_cw(Edge, Etab, Face, [V|Vs]) -> - case gb_trees:get(Edge, Etab) of - #edge{vs=V,lf=Face,ltsu=Next} -> - walk_face_cw(Next, Etab, Face, Vs); - #edge{ve=V,rf=Face,rtsu=Next} -> - walk_face_cw(Next, Etab, Face, Vs) - end. - -validate_vertex_tab(#we{es=Etab,vc=Vct}) -> - lists:foreach(fun({V,Edge}) -> - case gb_trees:get(Edge, Etab) of - #edge{vs=V} -> ok; - #edge{ve=V} -> ok - end - end, gb_trees:to_list(Vct)). |