1%%
2%%  e3d_util.erl --
3%%
4%%     Utility functions.
5%%
6%%  Copyright (c) 2002-2011 Bjorn Gustavsson
7%%
8%%  See the file "license.terms" for information on usage and redistribution
9%%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10%%
11%%     $Id: e3d_util.erl,v 1.2 2006/08/02 20:25:02 antoneos Exp $
12%%
13
14-module(e3d_util).
15-export([make_uniq/2, indexed_to_raw/2, raw_to_indexed/1]).
16
17-import(lists, [reverse/1,sort/1,sublist/2,sublist/3,all/2]).
18
19make_uniq([Name|_]=Ns0, Max) when is_atom(Name) ->
20    Ns1 = [atom_to_list(N) || N <- Ns0],
21    Ns = make_uniq(Ns1, Max),
22    [{list_to_atom(Orig),list_to_atom(New)} || {Orig,New} <- Ns];
23make_uniq(Ns, Max) -> make_uniq_0(Ns, Max).
24
25make_uniq_0(L0, Max) ->
26    L1 = [{sublist(Name, Max),Name} || Name <- L0],
27    L = make_uniq_1(L1, Max),
28    [{From,To} || {To,From} <- L].
29
30make_uniq_1(L, Max) ->
31    R = sofs:relation(L),
32    F0 = sofs:relation_to_family(R),
33    F = sofs:to_external(F0),
34    make_uniq_2(F, Max, [], done).
35
36make_uniq_2([{Short,[Orig]}|T], Max, Acc, Status) ->
37    make_uniq_2(T, Max, [{Short,Orig}|Acc], Status);
38make_uniq_2([{Short,Os0}|T], Max, Acc0, _) ->
39    Os = [{Short,Orig} || Orig <- Os0],
40    Acc = remove_chars(Os, Max, []) ++ Acc0,
41    make_uniq_2(T, Max, Acc, not_done);
42make_uniq_2([], _, Acc, done) -> Acc;
43make_uniq_2([], Max, Acc, not_done) ->
44    L0 = [{sublist(Key, Max),Key} || {Key,_} <- Acc],
45    L1 = make_uniq_1(L0, Max),
46    L2 = sofs:relation(L1),
47    L = sofs:relative_product(L2, sofs:relation(Acc)),
48    sofs:to_external(L).
49
50remove_chars([{Orig,Orig}=Pair|T], Max, Acc) when length(Orig) < Max ->
51    remove_chars(T, Max, [Pair|Acc]);
52remove_chars([{Key,Orig}|T], Max, Acc) when length(Key) >= Max ->
53    New = {sublist(Key, Max-1)++sublist(Orig, Max+1, 999999),Orig},
54    remove_chars(T, Max, [New|Acc]);
55remove_chars([{Key,Orig}|T], Max, Acc) ->
56    C = trunc($a+rand:uniform(26)),
57    remove_chars(T, Max, [{[C|Key],Orig}|Acc]);
58remove_chars([], Max, Acc) ->
59    L0 = [{sublist(Key, Max),Key} || {Key,_} <- Acc],
60    L1 = make_uniq_1(L0, Max),
61    L2 = sofs:relation(L1),
62    L = sofs:relative_product(L2, sofs:relation(Acc)),
63    sofs:to_external(L).
64
65%
66% Functions for meshes stored in indexed format (verts/faces lists)
67%
68indexed_to_raw(Verts, Faces) -> % replace indices with values
69    VertexArray = array:from_list(Verts),
70    Make_Raw_Face = fun(Face) ->
71			[array:get(Index, VertexArray) || Index <- Face]
72		    end,
73    lists:map(Make_Raw_Face, Faces).
74
75raw_to_indexed(RawTriangles) -> % replace values with indices
76    VertsWithDups = lists:append(RawTriangles),
77    Verts = remove_dups(VertsWithDups),
78    IndexedVerts = dict:from_list(add_indices(Verts)),
79    Get_Index = fun(Vertex) -> dict:fetch(Vertex, IndexedVerts) end,
80    Process_Face = fun(Face) -> lists:map(Get_Index, Face) end,
81    Faces = lists:map(Process_Face, RawTriangles),  % re-indexes the Faces list
82    {Verts, Faces}.
83
84remove_dups(List) -> % remove duplicates (uses Zero tolerance)
85    lists:usort(List).
86
87add_indices(List) ->
88    ListLen = length(List),
89    Indices = lists:seq(0, ListLen-1),
90    IndexedList = lists:zip(List, Indices),
91    IndexedList.
92
93