ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_del.c
Revision: 3.11
Committed: Fri Mar 5 16:32:22 1999 UTC (25 years, 1 month ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.10: +5 -5 lines
Log Message:
small clean-up changes

File Contents

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * sm_del.c
9 */
10 #include "standard.h"
11 #include "sm_flag.h"
12 #include "sm_list.h"
13 #include "sm_geom.h"
14 #include "sm_qtree.h"
15 #include "sm_stree.h"
16 #include "sm.h"
17
18 static int Max_edges=200;
19 static EDGE *Edges=NULL;
20 static int Ecnt=0;
21
22 smFree_tri(sm,id)
23 SM *sm;
24 int id;
25 {
26 TRI *tri,*t;
27
28 tri = SM_NTH_TRI(sm,id);
29 /* Add to the free_list */
30 smClear_tri_flags(sm,id);
31 T_NEXT_FREE(tri) = SM_FREE_TRIS(sm);
32 SM_FREE_TRIS(sm) = id;
33 T_VALID_FLAG(tri) = -1;
34 }
35
36 /* Assumes mesh pointers have been cleaned up appropriately: just deletes from
37 Point location and triangle data structure
38 */
39 smDelete_tri(sm,t_id)
40 SM *sm;
41 int t_id;
42 {
43
44 /* NOTE: Assumes that a new triangle adjacent to each vertex
45 has been added- before the deletion: replacing
46 the old tri- and therefore dont need to dereference any pointers
47 to id because the vertices can no longer
48 point to tri id as being the first triangle pointer
49 */
50 SM_SAMPLE_TRIS(sm)--;
51 if(SM_IS_NTH_T_NEW(sm,t_id))
52 smNew_tri_cnt--;
53
54 smClear_tri_flags(sm,t_id);
55
56 smFree_tri(sm,t_id);
57 }
58
59
60 int
61 eNew_edge()
62 {
63 if(!Edges)
64 if(!(Edges = (EDGE *)realloc(NULL,(Max_edges+1)*sizeof(EDGE))))
65 goto memerr;
66
67 if(Ecnt >= Max_edges)
68 {
69 if(Max_edges > 10000)
70 {
71 eputs("Too many edges in vertex loop\n");
72 return(-1);
73 }
74 Max_edges += 100;
75 if(!(Edges = (EDGE *)realloc(Edges,(Max_edges+1)*sizeof(EDGE))))
76 goto memerr;
77 }
78 return(++Ecnt);
79
80 memerr:
81 error(SYSTEM,"eNew_edge(): Unable to allocate memory");
82 }
83
84 /* Return list of edges defining polygon formed by boundary of triangles
85 adjacent to id. Return set of triangles adjacent to id to delete in delptr
86 */
87 LIST
88 *smVertexStar(sm,id,del_ptr)
89 SM *sm;
90 int id;
91 LIST **del_ptr;
92 {
93 TRI *tri,*t_next;
94 LIST *elist,*end;
95 int e,t_id,v_next,t_next_id,b_id,v_id;
96
97 eClear_edges();
98 elist = end = NULL;
99
100 /* Get the first triangle adjacent to vertex id */
101 t_id = SM_NTH_VERT(sm,id);
102 tri = SM_NTH_TRI(sm,t_id);
103
104 e = eNew_edge();
105
106 /* Get the next vertex on the polygon boundary */
107 v_id = T_WHICH_V(tri,id);
108 b_id = (v_id + 1)%3;
109 /* Create an edge */
110 SET_E_NTH_VERT(e,0,T_NTH_V(tri,b_id));
111 SET_E_NTH_TRI(e,0,INVALID);
112 SET_E_NTH_TRI(e,1,T_NTH_NBR(tri,v_id));
113 v_next = T_NTH_V(tri,(b_id+1)%3);
114 SET_E_NTH_VERT(e,1,v_next);
115 elist = add_data_to_circular_list(elist,&end,e);
116 t_next_id = t_id;
117 t_next = tri;
118
119 *del_ptr = push_data(*del_ptr,t_id);
120 /* Create a set to hold all of the triangles for deletion later */
121
122 while((t_next_id = T_NTH_NBR(t_next,b_id)) != t_id)
123 {
124 e = eNew_edge();
125 if(e== INVALID)
126 return(NULL);
127 t_next = SM_NTH_TRI(sm,t_next_id);
128 SET_E_NTH_VERT(e,0,v_next);
129 SET_E_NTH_TRI(e,0,INVALID);
130 v_id = T_WHICH_V(t_next,id);
131 b_id = (v_id + 1)%3;
132 SET_E_NTH_TRI(e,1,T_NTH_NBR(t_next,v_id));
133 v_next = T_NTH_V(t_next,(b_id+1)%3);
134 SET_E_NTH_VERT(e,1,v_next);
135 elist = add_data_to_circular_list(elist,&end,e);
136 *del_ptr = push_data(*del_ptr,t_next_id);
137 }
138 return(elist);
139 }
140
141
142 int
143 smTriangulate_add_tri(sm,id0,id1,id2,e0,e1,e2ptr)
144 SM *sm;
145 int id0,id1,id2,e0,e1,*e2ptr;
146 {
147 int t_id;
148 int e2;
149
150 #ifdef DEBUG
151 if(id0 == INVALID || id1==INVALID || id2==INVALID)
152 error(CONSISTENCY,"bad id- smTriangulate_add_tri()\n");
153 #endif
154 t_id = smAdd_tri(sm,id0,id1,id2);
155 if(*e2ptr == 0)
156 {
157 e2 = eNew_edge();
158 SET_E_NTH_VERT(e2,0,id2);
159 SET_E_NTH_VERT(e2,1,id0);
160 }
161 else
162 e2 = *e2ptr;
163 /* set appropriate tri for each edge*/
164 SET_E_NTH_TRI(e0,0,t_id);
165 SET_E_NTH_TRI(e1,0,t_id);
166 SET_E_NTH_TRI(e2,0,t_id);
167
168 *e2ptr = e2;
169 return(t_id);
170 }
171
172 int
173 smTriangulateConvex(sm,plist,add_ptr)
174 SM *sm;
175 LIST *plist,**add_ptr;
176 {
177 int t_id,e_id0,e_id1,e_id2;
178 int v_id0,v_id1,v_id2;
179 LIST *lptr;
180
181 lptr = plist;
182 e_id0 = (int)LIST_DATA(lptr);
183 v_id0 = E_NTH_VERT(e_id0,0);
184 lptr = LIST_NEXT(lptr);
185 while(LIST_NEXT(lptr) != plist)
186 {
187 e_id1 = (int)LIST_DATA(lptr);
188 v_id1 = E_NTH_VERT(e_id1,0);
189 v_id2 = E_NTH_VERT(e_id1,1);
190 lptr = LIST_NEXT(lptr);
191
192 if(LIST_NEXT(lptr) != plist)
193 e_id2 = 0;
194 else
195 e_id2 = (int)LIST_DATA(lptr);
196 t_id = smTriangulate_add_tri(sm,v_id0,v_id1,v_id2,e_id0,e_id1,&e_id2);
197 *add_ptr = push_data(*add_ptr,t_id);
198 e_id0 = -e_id2;
199 }
200 free_list(plist);
201 return(TRUE);
202 }
203 #ifdef TEST_DRIVER
204 FVECT Norm[500],B_V[500];
205 int Ncnt,Bcnt,Del=0;
206 #endif
207
208
209 /* Triangulate the polygon defined by plist, and generating vertex p_id.
210 Return list of added triangles in list add_ptr. Returns TRUE if
211 successful, FALSE otherwise. This is NOT a general triangulation routine,
212 assumes polygon star relative to id
213 */
214
215 int
216 smTriangulate(sm,id,plist,add_ptr)
217 SM *sm;
218 int id;
219 LIST *plist,**add_ptr;
220 {
221 LIST *l,*prev,*t;
222 FVECT v0,v1,v2,n,p;
223 int is_tri,is_convex,cut,t_id,id0,id1,id2,e2,e1,enew;
224 double dp;
225 static int debug=0;
226
227 VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
228 enew = 0;
229 is_convex = TRUE;
230 cut = is_tri= FALSE;
231 l = prev = plist;
232
233 /* get v0,v1 */
234 e1 = (int)LIST_DATA(l);
235 id0 = E_NTH_VERT(e1,0);
236 id1 = E_NTH_VERT(e1,1);
237 VSUB(v0,SM_NTH_WV(sm,id0),SM_VIEW_CENTER(sm));
238 VSUB(v1,SM_NTH_WV(sm,id1),SM_VIEW_CENTER(sm));
239 #ifdef TEST_DRIVER
240 Del = TRUE;
241 VCOPY(B_V[0],v0);
242 VCOPY(B_V[1],v1);
243 Bcnt = 2;
244 Ncnt = 0;
245 #endif
246 while(l)
247 {
248 l = LIST_NEXT(l);
249 /* Get v2 */
250 e2 = (int)LIST_DATA(l);
251 id2 = E_NTH_VERT(e2,1);
252 VSUB(v2,SM_NTH_WV(sm,id2),SM_VIEW_CENTER(sm));
253 #ifdef TEST_DRIVER
254 VCOPY(B_V[Bcnt++],v2);
255 #endif
256 if(LIST_NEXT(LIST_NEXT(l)) == prev)
257 {/* Check if have a triangle */
258 is_tri = TRUE;
259 break;
260 }
261
262 /* determine if v0-v1-v2 is convex:defined clockwise on the sphere-
263 so switch orientation
264 */
265 if(convex_angle(v2,v1,v0))
266 {
267 /* test if safe to cut off v0-v1-v2 by testing if p lies outside of
268 triangle v0-v1-v2: if so, because plist is the star polygon around p,
269 the new edge v2-v0 cannot intersect any existing edges
270 */
271 VCROSS(n,v0,v2);
272 dp = DOT(n,p);
273 if(dp <= 0.0)
274 {
275 /* remove edges e1,e2 and add triangle id0,id1,id2 */
276 enew = 0;
277 t_id = smTriangulate_add_tri(sm,id0,id1,id2,e1,e2,&enew);
278 cut = TRUE;
279 *add_ptr = push_data(*add_ptr,t_id);
280 /* Insert edge enew into the list, reuse prev list element */
281 LIST_NEXT(prev) = LIST_NEXT(l);
282 LIST_DATA(prev) = e1 = -enew;
283 /* If removing head of list- reset plist pointer */
284 if(l== plist)
285 plist = prev;
286 /* free list element for e2 */
287 LIST_NEXT(l)=NULL;
288 free_list(l);
289 l = prev;
290 VCOPY(v1,v2);
291 id1 = id2;
292 continue;
293 }
294 }
295 else
296 is_convex = FALSE;
297 VCOPY(v0,v1);
298 VCOPY(v1,v2);
299 id0 = id1;
300 id1 = id2;
301 e1 = e2;
302 /* check if gone around circular list without adding any
303 triangles: prevent infinite loop */
304 if(l == plist)
305 {
306 if(LIST_NEXT(LIST_NEXT(l)) == prev)
307 {/* Check if have a triangle */
308 is_tri = TRUE;
309 break;
310 }
311
312 if(is_convex)
313 break;
314 if(!cut)
315 {
316 #ifdef DEBUG
317 eputs("smTriangulate():Unable to triangulate\n");
318 #endif
319 free_list(l);
320 while(*add_ptr)
321 {
322 t_id = pop_list(add_ptr);
323 smDelete_tri(sm,t_id);
324 }
325 return(FALSE);
326 }
327
328 cut = FALSE;
329 is_convex = TRUE;
330 }
331 prev = l;
332 }
333 if(is_tri)
334 {
335 l = LIST_NEXT(l);
336 enew = (int)LIST_DATA(l);
337 t_id = smTriangulate_add_tri(sm,id0,id1,id2,e1,e2,&enew);
338 *add_ptr = push_data(*add_ptr,t_id);
339 free_list(l);
340 }
341 else
342 if(!smTriangulateConvex(sm,l,add_ptr))
343 return(FALSE);
344
345 /* Set triangle adjacencies based on edge adjacencies */
346 FOR_ALL_EDGES(enew)
347 {
348 id0 = E_NTH_TRI(enew,0);
349 id1 = E_NTH_TRI(enew,1);
350
351 e1 = (T_WHICH_V(SM_NTH_TRI(sm,id0),E_NTH_VERT(enew,0))+2)%3;
352 T_NTH_NBR(SM_NTH_TRI(sm,id0),e1) = id1;
353
354 e2 = (T_WHICH_V(SM_NTH_TRI(sm,id1),E_NTH_VERT(enew,1))+2)%3;
355 T_NTH_NBR(SM_NTH_TRI(sm,id1),e2) = id0;
356 }
357 return(TRUE);
358 }
359
360 eIn_tri(e,t)
361 int e;
362 TRI *t;
363 {
364
365 if(T_NTH_V(t,0)==E_NTH_VERT(e,0))
366 return(T_NTH_V(t,1)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
367 else
368 if(T_NTH_V(t,1)==E_NTH_VERT(e,0))
369 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
370 else if(T_NTH_V(t,2)==E_NTH_VERT(e,0))
371 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,1)==E_NTH_VERT(e,1));
372
373 return(FALSE);
374 }
375
376 /* Test the new set of triangles for Delaunay condition. 'Edges' contains
377 all of the new edges added. The CCW triangle assoc with each edge is
378 tested against the opposite vertex of the CW triangle. If the vertex
379 lies inside the circle defined by the CCW triangle- the edge is swapped
380 for the opposite diagonal
381 */
382 smFixEdges(sm,add_list)
383 SM *sm;
384 LIST *add_list;
385 {
386 int e,t0_id,t1_id,e_new,e0,e1,e0_next,e1_next;
387 int i,v0_id,v1_id,v2_id,p_id,t0_nid,t1_nid;
388 FVECT v0,v1,v2,p,np,v;
389 TRI *t0,*t1;
390
391 FOR_ALL_EDGES(e)
392 {
393 t0_id = E_NTH_TRI(e,0);
394 t1_id = E_NTH_TRI(e,1);
395 if((t0_id==INVALID) || (t1_id==INVALID))
396 {
397 #ifdef DEBUG
398 error(CONSISTENCY,"smFix_edges: Unassigned edge nbr\n");
399 #endif
400 }
401 t0 = SM_NTH_TRI(sm,t0_id);
402 t1 = SM_NTH_TRI(sm,t1_id);
403 e0 = T_NTH_NBR_PTR(t1_id,t0);
404 e1 = T_NTH_NBR_PTR(t0_id,t1);
405
406 v0_id = E_NTH_VERT(e,0);
407 v1_id = E_NTH_VERT(e,1);
408 v2_id = T_NTH_V(t0,e0);
409 p_id = T_NTH_V(t1,e1);
410
411 smDir(sm,v0,v0_id);
412 smDir(sm,v1,v1_id);
413 smDir(sm,v2,v2_id);
414
415 VCOPY(p,SM_NTH_WV(sm,p_id));
416 VSUB(p,p,SM_VIEW_CENTER(sm));
417 if(point_in_cone(p,v0,v1,v2))
418 {
419 smTris_swap_edge(sm,t0_id,t1_id,e0,e1,&t0_nid,&t1_nid,&add_list);
420
421 /* Adjust the triangle pointers of the remaining edges to be
422 processed
423 */
424 FOR_ALL_EDGES_FROM(e,i)
425 {
426 if(E_NTH_TRI(i,0)==t0_id || E_NTH_TRI(i,0)==t1_id)
427 {
428 if(eIn_tri(i,SM_NTH_TRI(sm,t0_nid)))
429 SET_E_NTH_TRI(i,0,t0_nid);
430 else
431 SET_E_NTH_TRI(i,0,t1_nid);
432 }
433
434 if(E_NTH_TRI(i,1)==t0_id || E_NTH_TRI(i,1)==t1_id)
435 {
436 if(eIn_tri(i,SM_NTH_TRI(sm,t0_nid)))
437 SET_E_NTH_TRI(i,1,t0_nid);
438 else
439 SET_E_NTH_TRI(i,1,t1_nid);
440 }
441 }
442 t0_id = t0_nid;
443 t1_id = t1_nid;
444 e_new = eNew_edge();
445 SET_E_NTH_VERT(e_new,0,p_id);
446 SET_E_NTH_VERT(e_new,1,v2_id);
447 SET_E_NTH_TRI(e_new,0,t0_id);
448 SET_E_NTH_TRI(e_new,1,t1_id);
449 }
450 }
451 /* Add/Delete the appropriate triangles from the stree */
452 smUpdate_locator(sm,add_list);
453 }
454
455 /* Remove vertex "id" from the mesh- and retriangulate the resulting
456 hole: Returns TRUE if successful, FALSE otherwise.
457 */
458 int
459 smRemoveVertex(sm,id)
460 SM *sm;
461 int id;
462 {
463 LIST *b_list,*add_list,*del_list;
464 int t_id,i;
465 static int cnt=0;
466 OBJECT *optr,*os;
467 /* generate list of edges that form the boundary of the
468 polygon formed by the triangles adjacent to vertex 'id'
469 */
470 del_list = NULL;
471 b_list = smVertexStar(sm,id,&del_list);
472 if(!b_list)
473 {
474 if(del_list)
475 free_list(del_list);
476 return(FALSE);
477 }
478 add_list = NULL;
479 /* Triangulate polygonal hole */
480 if(!smTriangulate(sm,id,b_list,&add_list))
481 {
482 free_list(del_list);
483 return(FALSE);
484 }
485 else
486 {
487 while(del_list)
488 {
489 t_id = pop_list(&del_list);
490 smDelete_tri(sm,t_id);
491 }
492 }
493 /* Fix up new triangles to be Delaunay-delnode contains set of
494 triangles to delete,add_list is the set of new triangles to add
495 */
496 smFixEdges(sm,add_list);
497
498 return(TRUE);
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514