blob: 64dcb2248815a0f04c5749192daad7a417e79616 [file] [log] [blame]
Austin Schuh405fa6c2015-09-06 18:13:55 -07001(*
2
3 Unfolding Convex Polytopes
4
5 Version 1.0 Beta
6 February, 1992
7
8 Copyright (c) 1992 by
9 Makoto Namiki
10
11This package contains Mathematica implementations
12of unfolding 3-dimsional polytope.
13
14This package is copyright 1992 by Makoto Namiki.
15This package may be copied in its entirety for
16nonprofit purposes only. Sale, other than for
17the direct cost of the media, is prohibited.
18This copyright notice must accompany all copies.
19
20The authors make no representations, express or
21implied, with respond to this documentation, of
22the software it describes and contains, including
23without limitations, any implied warranties of
24mechantability or fitness for a particular purpose,
25all of which are expressly disclaimed. The authors
26shall in no event be liable for any indirect,
27incidental, or consequential damages.
28
29This beta release is designed to run under
30Version 1.2 & 2.0 of Mathematica. Any comments,
31bug reports, or requests to get on the
32UnfoldPolytope mailing list should be
33forwarded to:
34
35 Makoto Namiki
36 Department of Information Science,
37 Tokyo Institute of Technology, Tokyo
38 2-12-1 Oh-okayama, Meguro-ku
39 Tokyo 145, Japan
40
41 +81-3-3726-1111 (Ex. 4131)
42 namiki@titisna.is.titech.ac.jp
43
44*)
45
46BeginPackage["UnfoldPolytope`"]
47
48UnfoldPolytope::usage="UnfoldPolytope[facets] gives graphics of unfoldings of a polytope which is given as a list of facets.";
49
50OrderFacets::usage="OrderFacets[facets] returns a correctly order lists of facets.";
51
52ProperSubsetQ::usage="ProperSubsetQ[t,s] returns True if t is a proper subset of s.";
53
54MakeEdgesFromFacets::usage="MakeEdgesFromFacets[faces] returns a cordinats of lower faces and a adjacency of faces.";
55
56MakeFacetsFromZerosets::usage="MakeFacetsFromZerosets[v,z] returns a list of facets consisting of cordinates of vertices, where v denotes a list of vertices and z denotes a list of zerosets.";
57
58MakeAdjTable::usage="MakeAdjTable[n,l] or MakeAdjTable[n,l,costs] return an adjacency table where l denotes a list of unordered pairs consist of {1,2,...,n} and a costs denotes an adjacency cost.";
59
60BreadthFirstSearch::usage="BreadthFirstSearch[adj_list,n] gives a incidence matrix representing a tree of a graph obtained by breadth first search from a vertex n, where this graph is given as a incidence matrix of adj_list.";
61
62DepthFirstSearch::usage="DepththFirstSearch[adj_list,n] gives a incidence matrix representing a tree of a graph obtained by depth first search from a vertex n, where this graph is given as a incidence matrix of adj_list.";
63
64IntersectionOfList::usage="IntersectionOfList[{l_1,l_2,...l_n}] returns a Intersection[l_1,l_2,...,l_n].";
65
66SelectLeaf::usage="SelectLeaf[adj_Mat] returns {i,j} such that node i is a child of node j for adjacent matrix adj_Mat.";
67
68ProjectVertex::usage="ProjectVetex[v1,v2,v3,v4] returns coordinates which is a projection of v4 onto affine space {v1,v2,v3} around the line {v1,v2}.";
69
70ProjectFaces::usage="ProjectFaces[child,parent,faces,vervect] argument child is a list of faces, parent is a face, and faces is a list of all faces. This procedure project faces of child onto a face of parent by using ProjectVertices.";
71
72IntersectOfFaces::usage="IntersectOfFaces[f1_List,f2_List] returns veticeswhich commonly belong to f1 and f2.";
73
74VectEQ::usage="VectEQ[v1,v2] returns True if v1 == v2 otherwise False";
75
76Unfold::usage="Unfold[sptree,tree,maxf] open one of a leaf of Tree of Facet.";
77
78Zonotope::usage="Zonotope[vlist] returns a list extreme points of zonotope which is defined by vlist, a list of vectors.";
79
80VerticalVector::usage="VerticalVector[maxf_List] returns a list of Vertical vector of each face.";
81
82OrderFace::usage="OrderFace[facet]: reorder a facet correctly.
83 where argument facet consits of {v_1,v_2,..,v_n}
84 ,v_i is a cordinat of a vetex.";
85
86Begin["`private`"]
87
88UnfoldPolytope[facets_List]:=
89 Block[{odfacets,edg,faAdj,vertices,veAdj,
90 t,tree,cotree,sptree,i,tr,vervec},
91 odfacets = facets;
92 {edg,faAdj} = MakeEdgesFromFacets[odfacets];
93 vertices = Union[Flatten[facets,1]];
94 veAdj = Flatten[{Position[vertices,#[[1]]],
95 Position[vertices,#[[2]]]}]& /@ edg;
96 t = BreadthFirstSearch[MakeAdjTable[Length[vertices],veAdj],1];
97 tree = Flatten[Position[veAdj,#]& /@ Position[t,1]];
98 cotree = Complement[Table[i,{i,1,Length[edg]}],tree];
99 sptree = MakeAdjTable[Length[odfacets],faAdj[[cotree]]];
100 tr = Table[{i},{i,Length[facets]}];
101 vervec = VerticalVector[odfacets];
102 Show[Graphics3D[Polygon /@ odfacets],Boxed->False];
103 Do[{sptree,tr,odfacets,vervec} = Unfold[sptree,tr,N[odfacets],vervec];
104 Show[Graphics3D[(Polygon /@ odfacets)],Boxed->False];
105 ,{i,1,Length[odfacets]-1}];
106 Show[Graphics3D[(Polygon /@ odfacets)],Boxed->False,ViewPoint->vervec[[1]][[1]]];
107 ];
108
109
110OrderFacets[facets_List]:=
111 Block[{i,edges,facetsAdj,f,out,cyc,cand,cand2cyc,ff},
112 {edges,facetsAdj} = MakeEdgesFromFacets[facets];
113 out = {};
114 For[i=1,i<=Length[facets],i++,
115 f = edges[[Transpose[Position[facetsAdj,i]][[1]]]];
116 cand = Drop[f,1];
117 cyc = {First[f]};
118 ff = {};
119 While[(cand2cyc = Select[cand,(Length[Intersection[Last[cyc],#]]==1)&]) != {},
120 AppendTo[ff,Intersection[Last[cyc],cand2cyc[[1]]][[1]]];
121 AppendTo[cyc,cand2cyc[[1]]];
122 cand = Complement[cand,{cand2cyc[[1]]}];
123 ];
124 AppendTo[ff,Intersection[Last[cyc],First[cyc]][[1]]];
125 AppendTo[out,ff];
126 ];
127 Return[out];
128 ];
129
130NonNegativeVectorQ[v_List]:=
131 Block[{i},
132 For[i=1, i<= Length[v], ++i,
133 If [v[[i]] < 0, Return[False]];
134 ];
135 Return[True];
136 ];
137
138
139MakeEdgesFromFacets[l_List] :=
140 Block[{i,j,lf={},adj={}},
141 For[i=1,i<Length[l],i++,
142 For[j=i+1,j<=Length[l],j++,
143 If[Length[Intersection[l[[i]],l[[j]]]] == 2,
144 AppendTo[lf,Intersection[l[[i]],l[[j]]]];
145 AppendTo[adj,{i,j}];
146 ];
147 ];
148 ];
149 Return[{lf,adj}];
150 ];
151
152MakeFacetsFromZerosets[v_List,z_List]:=
153 Block[{i,j,flist,maxf,flag,out},
154 flist = Transpose[Position[z,#]][[1]]& /@ Union[Flatten[z]];
155 maxf = {};
156 For[i=1,i<=Length[flist],i++,
157 flag = 0;
158 For[j=1,j<=Length[flist],j++,
159 If[ProperSubsetQ[flist[[i]],flist[[j]]],
160 flag = 1,
161 If[SubsetQ[flist[[i]],flist[[j]]] && i<j,
162 flag = 1;
163 ];
164 ];
165 ];
166 If[flag == 0,
167 AppendTo[maxf,flist[[i]]];
168 ];
169 ];
170 (* Return[maxf]; *)
171 out = v[[#]]& /@ (MakeOrder[#,z]& /@ maxf);
172 Return[out];
173 ];
174
175MakeOrder[ver_List,zerova_List]:=
176 Block[{candidates, cycle ,candidate2cycle},
177 candidates = Drop[ver,1];
178 cycle = { First[ver] };
179 (* when one is list, comparing needs other is list *)
180 While[{} != (candidate2cycle = Select[candidates,AdjQ[Last[cycle],#,zerova] &]),
181 AppendTo[cycle,candidate2cycle[[1]]];
182 candidates = Complement[candidates,candidate2cycle[[{1}]]];
183 ];
184 While[{} != (candidate2cycle = Select[candidates,AdjQ[First[cycle],#,zerova] &]),
185 PrependTo[cycle,candidate2cycle[[1]]];
186 candidates = Complement[candidates,candidate2cycle[[{1}]]];
187 ];
188 cycle
189 ];
190
191
192AdjQ[i_Integer,j_Integer,l_List]:=
193 Block[{subface},
194 subface=Intersection[l[[i]],l[[j]]];
195 Length[Select[l,SubsetQ[subface,#]&]]==2];
196
197ProperSubsetQ[s_List,t_List]:=
198 Length[s]==Length[Intersection[s,t]] && Length[s]<Length[t];
199
200SubsetQ[s_List,t_List]:=
201 Length[s]==Length[Intersection[s,t]];
202
203MakeAdjTable[n_Integer,l_List]:=
204 Block[{t=Table[Table[0,{n}],{n}],i},
205 For[i=1,i<=Length[l],i++,
206 t[[l[[i,1]],l[[i,2]]]] = 1;
207 t[[l[[i,2]],l[[i,1]]]] = 1;
208 ];
209 Return[t];
210 ];
211
212MakeAdjTable[n_Integer,l_List,c_List]:=
213 Block[{t=Table[Table[0,{n}],{n}],i},
214 For[i=1,i<=Length[l],i++,
215 t[[l[[i,1]],l[[i,2]]]] = c[[i]];
216 t[[l[[i,2]],l[[i,1]]]] = c[[i]];
217 ];
218 Return[t];
219 ];
220
221BreadthFirstSearch[adj_?MatrixQ,n_Integer]:=
222 Block[{out={},search,find={},output,
223 i,obj,cd,l=Length[adj]},
224 search = {n};
225 While[search != {},
226 obj = search[[1]];
227 search = Drop[search,1];
228 cd = {};
229 For[i=1, i<=l, i++,
230 If[adj[[obj,i]] != 0, AppendTo[cd,i]];
231 ];
232 cd = Complement[cd,search];
233 cd = Complement[cd,find];
234 For[i=1, i<=Length[cd],i++,
235 AppendTo[search,cd[[i]]];
236 AppendTo[out,{obj,cd[[i]]}];
237 AppendTo[out,{cd[[i]],obj}];
238 ];
239 AppendTo[find,obj];
240 ];
241 Return[MakeAdjTable[l,out]];
242 ];
243
244DepthFirstSearch[adj_?MatrixQ,n_Integer]:=
245 Block[{out={},search,find={},output,
246 i,obj,cd,l=Length[adj]},
247 search = {n};
248 While[search != {},
249 obj = search[[1]];
250 search = Drop[search,1];
251 cd = {};
252 For[i=1, i<=l, i++,
253 If[adj[[obj,i]] != 0, AppendTo[cd,i]];
254 ];
255 cd = Complement[cd,search];
256 cd = Complement[cd,find];
257 search = Flatten[Append[cd,search]];
258 For[i=1, i<=Length[cd],i++,
259 AppendTo[out,{obj,cd[[i]]}];
260 AppendTo[out,{cd[[i]],obj}];
261 ];
262 AppendTo[find,obj];
263 ];
264 Return[MakeAdjTable[l,out]];
265 ];
266
267
268IntersectionOfList[l_List]:=
269 Block[{},
270 If[Length[l]==1,Return[l[[1]]],
271 Return[Intersection[l[[1]],
272 IntersectionOfList[Drop[l,{1}]]]];
273 ];
274 ];
275
276Maximals[l_List]:=
277 Block[{i,maximals={}},
278 Do[If[MaximalQ[i,l],
279 AppendTo[maximals,l[[i]]]
280 ], {i,Length[l]}
281 ];
282 maximals]
283
284MaximalQ[i_Integer,l_List]:=
285 Block[{candidate},
286 candidate=l[[i]];
287 Length[Union[Select[l,ProperSubsetQ[candidate,#]&]]]==0]
288
289SubsetQ[s_List,t_List]:=
290 Length[s]==Length[Intersection[s,t]];
291
292Is[s_List]:=
293 Block[{},
294 If [Length[s] == 1,
295 Return[s[[1]]],
296 Return[Intersection[s[[1]],Is[Drop[s,1]]]]
297 ];
298 ];
299
300SelectLeaf[g_List]:=
301 Block[{size,i,j,deg,child,par,cp},
302 size = Length[g];
303 For[i=2,i<=size,i++,
304 deg = 0;
305 child = i;
306 For[j=1,j<=size,j++,
307 If[g[[i]][[j]] > 0,
308 deg = deg + 1;
309 par = j;
310 ];
311 ];
312 If[deg == 1,
313 Return[{child,par}];
314 ];
315 ];
316 ]
317
318ProjectFaces[child_List,par_Integer,face_List,vervec_List]:=
319 Block[{v1,v2,nch,i,fl},
320 {v1,v2} = IntersectOfFaces[face[[child[[1]]]],face[[par]]];
321 For[i=1, i<=Length[face[[par]]], ++i,
322 If[!VectEQ[face[[par]][[i]],v1] && !VectEQ[face[[par]][[i]],v2],
323 v3 = face[[par]][[i]];
324 Break[];
325 ];
326 ];
327 fl = {};
328 For[i=1, i<=Length[child], i++,
329 AppendTo[fl,ProjectVertex[v1,v2,v3,#,vervec]& /@ face[[child[[i]]]]];
330 ];
331 Return[fl];
332 ]
333
334IntersectOfFaces[f1_List,f2_List]:=
335 Block[{i,j,lvect},
336 lvect = {};
337 For[i=1,i<=Length[f1],i++,
338 For[j=1,j<=Length[f2],j++,
339 If[VectEQ[f1[[i]],f2[[j]]],AppendTo[lvect,f1[[i]]]];
340 ];
341 ];
342 Return[{lvect[[1]],lvect[[2]]}];
343 ]
344
345VectEQ[v1_List,v2_List]:=
346 Block[{i},
347 For[i=1,i<=Length[v1],i++,
348 If[v1[[i]] != v2[[i]],Return[False]];
349 ];
350 Return[True];
351 ]
352
353
354ProjectVertex[v1_List,v2_List,v3_List,v4_List,a_List]:=
355 Block[{x,y},
356 If [N[a[[1]].v4] <= a[[2]] + 10^(-10),
357 x = (v2-v1).(v2-v4)/(v2-v1).(v2-v1)*v1 + (v1-v2).(v1-v4)/(v1-v2).(v1-v2)*v2;
358 y = (v2-v1).(v2-v3)/(v2-v1).(v2-v1)*v1 + (v1-v2).(v1-v3)/(v1-v2).(v1-v2)*v2;
359 Return[x + Sqrt[(v4-x).(v4-x)/(y-v3).(y-v3)]*(y-v3)]
360 ];
361 If [N[a[[1]].v4] >= a[[2]] - 10^(-10),
362 x = (v2-v1).(v2-v4)/(v2-v1).(v2-v1)*v1 + (v1-v2).(v1-v4)/(v1-v2).(v1-v2)*v2;
363 y = (v2-v1).(v2-v3)/(v2-v1).(v2-v1)*v1 + (v1-v2).(v1-v3)/(v1-v2).(v1-v2)*v2;
364 Return[x + Sqrt[(v4-x).(v4-x)/(y-v3).(y-v3)]*(v3-y)]
365 ];
366 ]
367
368Unfold[sptree1_List,tree1_List,maxf1_List,vervec_List]:=
369 Block[{j,child,par,posch,ch,of,pospa,sptree=sptree1,tree=tree1,maxf=maxf1,vv=vervec},
370 {child, par} = SelectLeaf[sptree];
371 sptree[[child,par]] = -1;
372 sptree[[par,child]] = -1;
373
374 {posch} = Transpose[Position[tree,child]][[1]];
375 ch = tree[[posch]];
376 of = ProjectFaces[ch,par,maxf,vv[[par]]];
377 For[j=1, j<=Length[ch],j++,
378 maxf[[ch[[j]]]] = of[[j]];
379 ];
380 {pospa} = Transpose[Position[tree,par]][[1]];
381 tree[[pospa]] = (AppendTo[tree[[pospa]],#]& /@ ch)[[Length[ch]]];
382 tree = Drop[tree,{posch}];
383 Return[{sptree,tree,maxf,vv}];
384 ]
385
386Zonotope[vectors_List]:=
387 Block[{vlist},
388 vlist = Sum[(#)[[i]],{i,Length[#]}]& /@ ((vectors * (#)&) /@ Pow[Length[vectors]]);
389 Return[vlist];
390 ]
391
392Pow[n_Integer]:=
393 Block[{p,a,b},
394 If[n == 1, Return[{{1},{-1}}]
395 ];
396 p = Pow[n-1];
397 a = Append[#,1]& /@ p;
398 b = Append[#,-1]& /@ p;
399 Return[(AppendTo[a,#]& /@ b)[[Length[b]]]];
400 ]
401
402NonEmptyFaces[zerova_List]:=
403 Map[Function[Transpose[Position[zerova,#]][[1]]],Union[Flatten[zerova]]]
404
405VerticalVector[maxf_List]:=
406 Block[{i,vervec,a1,a2,x,y,z,b,v,vv={}},
407 For[i=1,i<=Length[maxf],i++,
408 a1 = maxf[[i]][[3]]-maxf[[i]][[2]];
409 a2 = maxf[[i]][[1]]-maxf[[i]][[3]];
410 Clear[x,y,z];
411 vervec = {x,y,z};
412 {vervec} = vervec /. Solve[{a1.vervec == 0, a2.vervec == 0}];
413 x = 1; y = 1; z = 1;
414 b = vervec.maxf[[i]][[1]];
415 v = Complement[Union[Flatten[maxf,1]],maxf[[i]]][[1]];
416 If[v.vervec > b, vervec = -vervec; b = -b];
417 AppendTo[vv,{vervec,b}];
418 ];
419 Return[vv];
420 ]
421
422End[]
423EndPackage[]