forked from fastalgorithms/rounding
-
Notifications
You must be signed in to change notification settings - Fork 0
/
polyframe.m
248 lines (202 loc) · 6.12 KB
/
polyframe.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
%
% (c) 2016 Charles L. Epstein and Michael O'Neil
%
% cle@math.upenn.edu
% oneil@cims.nyu.edu
%
% See the corresponding paper for technical information:
%
% C. L. Epstein and M. O'Neil, "Smoothed corners and scattered
% waves", arXiv:1506.08449, 2016.
%
function [Vout,Eout,Fout,lmn] = polyframe(V,E,F)
%
% This function inputs a geometric/combinatorial description of a
% polyhedron as:
%
% V = [[v1];[v2];...;[vnv]] is a matrix whose rows are
% the vertices.
% E = {[i11,i12],...,[ie1,ie2]} is a list of indices of
% the endpoints of edges
% F = {[j1i,...,jin1],...,[jf1,...,jffnf]} is
% list of the vertices that make up each face.
%
% It outputs data structures that facilitate that describe the local
% structure of the polyhedron in a neighborhood of each vertex, edge
% and face:
%
% Vout ={{[i11,...,i1m],[nv1],{j11,...,j1m},...,{..}} For each
% vertex we output the indices of the edges joined to it,
% sorted in the correct cyclic order, an outward pointing
% unit support vector, and the faces that define the edges in
% the corresponding cyclic order:
%
% e_{ikj} = f_{ikj} \cap f{ik(j+1)}.
%
% Eout = {{[i11,i12],[mdpnt],[ne],[nv1,a1],[nv2,a2]},...{...}} For
% each edge we output the indices of the faces that define
% it, the midpoint of the edge, a normalized vector in the
% direction of the edge, the equations of the faces defining
% the faces:
%
% <X,nvi> = ai.
%
% Fout = {{[nv1],a},...,{[nvf],af}} nvj is the outer normal vector
% to a face, and aj is the affine parameter:
%
% The equation of the face is <X,nvj> = aj.
%
%
% set the intersection (numerical) tolerance
%
tol = 10^(-10);
%
% Find out how many of each object we have:
%
nv = sz(V);
ne = sz(E);
nf = sz(F);
%
% For later applications we find the centroid of the polyhedron
%
cv = sum(V)/nv;
%
% Process the faces
%
for j=1:nf
nvf = sz(F{j});
i1 = F{j}(1);
i2 = F{j}(2);
i3 = F{j}(3);
v1 = V(i2,1:3)-V(i1,1:3);
v2 = V(i2,1:3)-V(i3,1:3);
%Compute the cross product to get the normal vector
nvec = cp(v1,v2);
nrm = sqrt(nvec*nvec');
nvec = nvec/nrm;
% Make sure the orientation is correct by comparing <nv,cv> to
% <nv,V(i1)>
if cv*nvec'>V(i1,1:3)*nvec';
nvec=-nvec;
end
ap = nvec*V(i1,1:3)';
% Check that the vertices lie on the face and find the centroid.
cent = [0,0,0];
for j2 = 1:nvf
if abs(V(F{j}(j2),1:3)*nvec'-ap)>tol
error('The vertices in face %d do not lie on the face',j)
end
cent = cent+V(F{j}(j2),1:3);
end
%Outer normal vector
Fout{j,1}=nvec;
%Affine parameter for face
Fout{j,2}=ap;
%The centroid of the face
Fout{j,3}(1:3)=cent(1:3)/nvf;
end
%
%Process the edges
%
for j = 1:ne
i1 = E{j}(1);
i2 = E{j}(2);
%The length of the edge
len(j) = sqrt((V(i1,1:3)-V(i2,1:3))*(V(i1,1:3)-V(i2,1:3))');
jf = 0;
clear faces
for j1 = 1:nf
if asubb(i1,F{j1})+asubb(i2,F{j1}) == 2
jf = jf +1;
faces(jf) = j1;
end
end
%Check that the edge lies on two faces
if jf ~= 2
error('Edge %d does not lie on two faces',j)
end
%Output the indices of the faces defining the edge.
Eout{j,1} = faces;
%Output the midpoint of the edge.
Eout{j,2} = (V(i1,1:3)+V(i2,1:3))/2;
ve = V(i1,1:3)-V(i2,1:3);
%Output the normalized direction of the edge.
Eout{j,3} = ve/sqrt(ve*ve');
%Output the equations of the faces as [nvec, ap].
Eout{j,4}= [Fout{faces(1),1},Fout{faces(1),2}];
Eout{j,5}= [Fout{faces(2),1},Fout{faces(2),2}];
%Output the indices of the vertices defining the edge.
Eout{j,6} = [i1, i2];
%This is the length of the shortest edge, which we use to scale all
%subsequent lengths.
lmn = min(len);
end
%
%Process the vertices
%
for j = 1:nv
clear edges ar ars ix Y
% Find the other vertices joined to our vertex
% At the end of the next loop this is the number of vertices
% joined to the current vertex
j1 = 0;
for j2 = 1:ne
if E{j2}(1) == j
j1 = j1+1;
% Index of the other vertex
verts(j1) = E{j2}(2);
% Also keep track of the indices of the edges
edges(j1) = j2;
elseif E{j2}(2) == j
j1 = j1 + 1;
% Index of the other vertex
verts(j1) = E{j2}(1);
% Also keep track of the indices of the edges
edges(j1) = j2;
end
end
% Find an outer support vector at the vertex
nv0=[0,0,0];
for j3=1:j1
% The indices of the next faces
findx1 = Eout{edges(j3),1}(1);
% The indices of the next faces
findx2 = Eout{edges(j3),1}(2);
%Add the faces' support vectors
nv0 = nv0 + Fout{findx1,1}(1:3) + Fout{findx2,1}(1:3);
end
nv0 = nv0/sqrt(nv0*nv0');
% Output the support vector at the vertex.
Vout{j,2} = nv0;
% Now we need to find the correct cyclic order for these vertices.
for j3 = 1:j1
vn = (V(verts(j3),1:3)-V(j,1:3));
vn = vn/sqrt(vn*vn');
Y(j3,1:3) = vn - (vn*nv0')*nv0;
Y(j3,1:3) = Y(j3,1:3)/sqrt(Y(j3,1:3)*Y(j3,1:3)');
end
% Choose and o/n basis for the plane <X,nv0>=0
e1 = Y(1,1:3);
e2 = cp(nv0,e1);
for j3 = 1:j1
ar(j3) = angle(e1*Y(j3,1:3)'+i*(e2*Y(j3,1:3)'));
end
[ars,ix] = sort(ar);
% Output the sorted indices of the vertices joined to our vertex.
Vout{j,1}=verts(ix);
% Now sort the indices of faces to be consistent with sorting of the
% edges.
for j3 = 1:j1
i1 = Eout{edges(ix(j3)),1}(1);
i2 = Eout{edges(ix(j3)),1}(2);
j3n = 1+mod(j3,j1);
i3 = Eout{edges(ix(j3n)),1}(1);
i4 = Eout{edges(ix(j3n)),1}(2);
if i1 == i3 | i1 == i4
Vout{j,3}(j3) = i2;
elseif i2 == i3 | i2 == i4
Vout{j,3}(j3) = i1;
else error('Edge %d on vertex %d is out of order', j3,j)
end
end
end