ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_del.c
Revision: 3.2
Committed: Mon Aug 24 12:38:57 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.1: +8 -5 lines
Log Message:
optimized triangle addition/deletion during edge swapping

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
12 #include "sm_list.h"
13 #include "sm_geom.h"
14 #include "sm.h"
15
16 static EDGE Edges[MAX_EDGES];
17 static int Ecnt=0;
18
19
20 smLocator_remove_tri(sm,t_id)
21 SM *sm;
22 int t_id;
23 {
24 STREE *st;
25 char found;
26 TRI *t;
27 FVECT p0,p1,p2;
28
29 st = SM_LOCATOR(sm);
30
31 t = SM_NTH_TRI(sm,t_id);
32
33 smDir(sm,p0,T_NTH_V(t,0));
34 smDir(sm,p1,T_NTH_V(t,1));
35 smDir(sm,p2,T_NTH_V(t,2));
36
37 found = stRemove_tri(st,t_id,p0,p1,p2);
38
39 return(found);
40 }
41
42 smFree_tri(sm,id)
43 SM *sm;
44 int id;
45 {
46 TRI *tri;
47
48 tri = SM_NTH_TRI(sm,id);
49 /* Add to the free_list */
50 T_NEXT_FREE(tri) = SM_FREE_TRIS(sm);
51 SM_FREE_TRIS(sm) = id;
52 T_VALID_FLAG(tri) = -1;
53 }
54
55 /* Assumes mesh pointers have been cleaned up appropriately: just deletes from
56 Point location and triangle data structure
57 */
58 smDelete_tri(sm,t_id)
59 SM *sm;
60 int t_id;
61 {
62
63
64 /* NOTE: Assumes that a new triangle adjacent to each vertex
65 has been added- before the deletion: replacing
66 the old tri- and therefore dont need to dereference any pointers
67 to id because the vertices can no longer
68 point to tri id as being the first triangle pointer
69 */
70 if(!SM_IS_NTH_T_BASE(sm,t_id))
71 {
72 SM_NUM_TRIS(sm)--;
73 if(SM_IS_NTH_T_NEW(sm,t_id))
74 smNew_tri_cnt--;
75 }
76 smClear_tri_flags(sm,t_id);
77
78 smFree_tri(sm,t_id);
79
80 }
81
82
83
84 LIST
85 *smVertex_star_polygon(sm,id)
86 SM *sm;
87 int id;
88 {
89 TRI *tri,*t_next;
90 LIST *elist,*end,*tlist;
91 int t_id,v_next,t_next_id;
92 int e;
93
94 elist = end = NULL;
95 /* Get the first triangle adjacent to vertex id */
96 t_id = SM_NTH_VERT(sm,id);
97 tri = SM_NTH_TRI(sm,t_id);
98
99
100 if((e = eNew_edge()) == SM_INVALID)
101 {
102 #ifdef DEBUG
103 eputs("smVertex_star_polygon():Too many edges\n");
104 #endif
105 return(NULL);
106 }
107 elist = add_data_to_circular_list(elist,&end,e);
108 v_next = (T_WHICH_V(tri,id)+1)%3;
109 SET_E_NTH_VERT(e,0,T_NTH_V(tri,v_next));
110 SET_E_NTH_TRI(e,0,SM_INVALID);
111 SET_E_NTH_TRI(e,1,T_NTH_NBR(tri,v_next));
112 v_next = (T_WHICH_V(tri,id)+2)%3;
113 SET_E_NTH_VERT(e,1,T_NTH_V(tri,v_next));
114
115
116 t_next_id = t_id;
117 t_next = tri;
118
119 tlist = push_data(NULL,t_id);
120
121 while((t_next_id = smTri_next_ccw_nbr(sm,t_next,id)) != t_id)
122 {
123 if((e = eNew_edge()) == SM_INVALID)
124 {
125 #ifdef DEBUG
126 eputs("smVertex_star_polygon():Too many edges\n");
127 #endif
128 return(NULL);
129 }
130 elist = add_data_to_circular_list(elist,&end,e);
131 t_next = SM_NTH_TRI(sm,t_next_id);
132 v_next = (T_WHICH_V(t_next,id)+1)%3;
133 SET_E_NTH_VERT(e,0,T_NTH_V(t_next,v_next));
134 SET_E_NTH_TRI(e,0,SM_INVALID);
135 SET_E_NTH_TRI(e,1,T_NTH_NBR(t_next,v_next));
136 v_next = (T_WHICH_V(t_next,id)+2)%3;
137 SET_E_NTH_VERT(e,1,T_NTH_V(t_next,v_next));
138 tlist = push_data(tlist,t_next_id);
139 }
140 while(tlist)
141 {
142 t_id = (int)pop_list(&tlist);
143 /* first remove from point location structure */
144 smLocator_remove_tri(sm,t_id);
145 smDelete_tri(sm,t_id);
146 }
147 return(elist);
148 }
149
150 int
151 smEdge_intersect_polygon(sm,v0,v1,l)
152 SM *sm;
153 FVECT v0,v1;
154 LIST *l;
155 {
156 FVECT e0,e1;
157 int e,id_e0,id_e1;
158 LIST *el,*eptr;
159
160 /* Test the edges in l against v0v1 to see if v0v1 intersects
161 any other edges
162 */
163
164 el = l;
165
166 while(el)
167 {
168 e = (int)LIST_DATA(el);
169 id_e0 = E_NTH_VERT(e,0);
170 id_e1 = E_NTH_VERT(e,1);
171
172 smDir(sm,e0,id_e0);
173 smDir(sm,e1,id_e1);
174 if(spherical_polygon_edge_intersect(v0,v1,e0,e1))
175 return(TRUE);
176
177 el = LIST_NEXT(el);
178 if(el == l)
179 break;
180 }
181 return(FALSE);
182 }
183
184 int
185 smFind_next_convex_vertex(sm,id0,id1,v0,v1,l)
186 SM *sm;
187 int id0,id1;
188 FVECT v0,v1;
189 LIST *l;
190 {
191 int e,id;
192 LIST *el;
193 FVECT v;
194
195 /* starting with the end of edge at head of l, search sequentially for
196 vertex v such that v0v1v is a convex angle, and the edge v1v does
197 not intersect any other edges
198 */
199 id = SM_INVALID;
200 el = l;
201 while(id != id0)
202 {
203 e = (int)LIST_DATA(el);
204 id = E_NTH_VERT(e,1);
205
206 smDir(sm,v,id);
207
208 if(convex_angle(v0,v1,v) && !smEdge_intersect_polygon(sm,v1,v,l))
209 return(id);
210
211 el = LIST_NEXT(el);
212 if(el == l)
213 break;
214 }
215 return(SM_INVALID);
216 }
217
218 int
219 split_edge_list(id0,id_new,l,lnew)
220 int id0,id_new;
221 LIST **l,**lnew;
222 {
223 LIST *list,*lptr,*end;
224 int e,e1,e2,new_e;
225
226 e2 = SM_INVALID;
227 list = lptr = *l;
228
229 if((new_e = eNew_edge())==SM_INVALID)
230 {
231 #ifdef DEBUG
232 eputs("split_edge_list():Too many edges\n");
233 #endif
234 return(FALSE);
235 }
236 SET_E_NTH_VERT(new_e,0,id0);
237 SET_E_NTH_VERT(new_e,1,id_new);
238 SET_E_NTH_TRI(new_e,0,SM_INVALID);
239 SET_E_NTH_TRI(new_e,1,SM_INVALID);
240
241 while(e2 != id_new)
242 {
243 lptr = LIST_NEXT(lptr);
244 e = (int)LIST_DATA(lptr);
245 e2 = E_NTH_VERT(e,1);
246 if(lptr == list)
247 {
248 #ifdef DEBUG
249 eputs("split_edge_list():cant find vertex\n");
250 #endif
251 *lnew = NULL;
252 return(FALSE);
253 }
254
255 }
256 end = lptr;
257 lptr = LIST_NEXT(lptr);
258 list = add_data_to_circular_list(list,&end,-new_e);
259 *lnew = list;
260
261 /* now follow other cycle */
262
263 list = lptr;
264 e2 = SM_INVALID;
265 while(e2 != id0)
266 {
267 lptr = LIST_NEXT(lptr);
268 e = (int)LIST_DATA(lptr);
269 e2 = E_NTH_VERT(e,1);
270 if(lptr == list)
271 {
272 #ifdef DEBUG
273 eputs("split_edge_list():cant find intial vertex\n");
274 #endif
275 *l = NULL;
276 return(FALSE);
277 }
278
279 }
280 end = lptr;
281 list = add_data_to_circular_list(list,&end,new_e);
282 *l = list;
283 return(TRUE);
284 }
285
286
287
288 LIST
289 *smTriangulate_convex(sm,plist)
290 SM *sm;
291 LIST *plist;
292 {
293 TRI *tri;
294 int t_id,e_id0,e_id1,e_id2;
295 int v_id0,v_id1,v_id2;
296 LIST *lptr;
297 int cnt;
298
299 lptr = plist;
300 e_id0 = (int)LIST_DATA(lptr);
301 v_id0 = E_NTH_VERT(e_id0,0);
302 lptr = LIST_NEXT(lptr);
303 while(LIST_NEXT(lptr) != plist)
304 {
305 e_id1 = (int)LIST_DATA(lptr);
306 v_id1 = E_NTH_VERT(e_id1,0);
307 v_id2 = E_NTH_VERT(e_id1,1);
308 /* form a triangle for each triple of with v0 as base of star */
309 t_id = smAdd_tri(sm,v_id0,v_id1,v_id2,&tri);
310 smLocator_add_tri(sm,t_id,v_id0,v_id1,v_id2);
311 /* add which pointer?*/
312
313 lptr = LIST_NEXT(lptr);
314
315 if(LIST_NEXT(lptr) != plist)
316 {
317 e_id2 = eNew_edge();
318 SET_E_NTH_VERT(e_id2,0,v_id2);
319 SET_E_NTH_VERT(e_id2,1,v_id0);
320 }
321 else
322 e_id2 = (int)LIST_DATA(lptr);
323
324 /* set appropriate tri for each edge*/
325 SET_E_NTH_TRI(e_id0,0,t_id);
326 SET_E_NTH_TRI(e_id1,0,t_id);
327 SET_E_NTH_TRI(e_id2,0,t_id);
328
329 e_id0 = -e_id2;
330 }
331 free_list(plist);
332 }
333
334 smTriangulate_elist(sm,plist)
335 SM *sm;
336 LIST *plist;
337 {
338 LIST *l,*el1;
339 FVECT v0,v1,v2;
340 int id0,id1,id2,e,id_next;
341 char flipped;
342 int debug = TRUE;
343
344 l = plist;
345
346 while(l)
347 {
348 /* get v0,v1,v2 */
349 e = (int)LIST_DATA(l);
350 id0 = E_NTH_VERT(e,0);
351 id1 = E_NTH_VERT(e,1);
352 l = LIST_NEXT(l);
353 e = (int)LIST_DATA(l);
354 id2 = E_NTH_VERT(e,1);
355
356 smDir(sm,v0,id0);
357 smDir(sm,v1,id1);
358 smDir(sm,v2,id2);
359 /* determine if convex (left turn), or concave(right turn) angle */
360 if(convex_angle(v0,v1,v2))
361 {
362 if(l == plist)
363 break;
364 else
365 continue;
366 }
367 /* if concave: add edge and recurse on two sub polygons */
368 id_next = smFind_next_convex_vertex(sm,id0,id1,v0,v1,LIST_NEXT(l));
369 if(id_next == SM_INVALID)
370 {
371 #ifdef DEBUG
372 eputs("smTriangulate_elist():Unable to find convex vertex\n");
373 #endif
374 return;
375 }
376 /* add edge */
377 el1 = NULL;
378 /* Split edge list l into two lists: one from id1-id_next-id1,
379 and the next from id2-id_next-id2
380 */
381 debug = split_edge_list(id1,id_next,&l,&el1);
382 /* Recurse and triangulate the two edge lists */
383 if(debug)
384 debug = smTriangulate_elist(sm,l);
385 if(debug)
386 debug = smTriangulate_elist(sm,el1);
387
388 return(debug);
389 }
390 smTriangulate_convex(sm,plist);
391 return(TRUE);
392 }
393
394 int
395 smTriangulate_polygon(sm,plist)
396 SM *sm;
397 LIST *plist;
398 {
399 int e,id_t0,id_t1,e0,e1;
400 TRI *t0,*t1;
401 int test;
402
403 test = smTriangulate_elist(sm,plist,NULL);
404
405 if(!test)
406 return(test);
407 FOR_ALL_EDGES(e)
408 {
409 id_t0 = E_NTH_TRI(e,0);
410 id_t1 = E_NTH_TRI(e,1);
411 if((id_t0==SM_INVALID) || (id_t1==SM_INVALID))
412 {
413 #ifdef DEBUG
414 eputs("smTriangulate_polygon(): Unassigned edge neighbor\n");
415 #endif
416 continue;
417 }
418 t0 = SM_NTH_TRI(sm,id_t0);
419 t1 = SM_NTH_TRI(sm,id_t1);
420
421 e0 = T_WHICH_V(t0,E_NTH_VERT(e,0));
422 T_NTH_NBR(t0,e0) = id_t1;
423
424 e1 = T_WHICH_V(t1,E_NTH_VERT(e,1));
425 T_NTH_NBR(t1,e1) = id_t0;
426 }
427 return(test);
428 }
429
430 eIn_tri(e,t)
431 int e;
432 TRI *t;
433 {
434
435 if(T_NTH_V(t,0)==E_NTH_VERT(e,0))
436 return(T_NTH_V(t,1)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
437 else
438 if(T_NTH_V(t,1)==E_NTH_VERT(e,0))
439 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
440 else if(T_NTH_V(t,2)==E_NTH_VERT(e,0))
441 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,1)==E_NTH_VERT(e,1));
442 return(FALSE);
443 }
444 smFix_edges(sm)
445 SM *sm;
446 {
447 int e,id_t0,id_t1,e_new,e0,e1,e0_next,e1_next;
448 TRI *t0,*t1,*nt0,*nt1;
449 int i,id_v0,id_v1,id_v2,id_p,nid_t0,nid_t1;
450 FVECT v0,v1,v2,p,np,v;
451 LIST *add,*del;
452
453 add = del = NULL;
454 FOR_ALL_EDGES(e)
455 {
456 id_t0 = E_NTH_TRI(e,0);
457 id_t1 = E_NTH_TRI(e,1);
458 if((id_t0==SM_INVALID) || (id_t1==SM_INVALID))
459 {
460 #ifdef DEBUG
461 eputs("smFix_edges: Unassigned edge nbr\n");
462 #endif
463 continue;
464 }
465 t0 = SM_NTH_TRI(sm,id_t0);
466 t1 = SM_NTH_TRI(sm,id_t1);
467
468 e0 = T_WHICH_V(t0,E_NTH_VERT(e,0));
469 e1 = T_WHICH_V(t1,E_NTH_VERT(-e,0));
470 e0_next = (e0+2)%3;
471 e1_next = (e1+2)%3;
472 id_v0 = E_NTH_VERT(e,0);
473 id_v1 = E_NTH_VERT(e,1);
474 id_v2 = T_NTH_V(t0,e0_next);
475 id_p = T_NTH_V(t1,e1_next);
476
477 smDir(sm,v0,id_v0);
478 smDir(sm,v1,id_v1);
479 smDir(sm,v2,id_v2);
480
481 VCOPY(p,SM_NTH_WV(sm,id_p));
482 VSUB(p,p,SM_VIEW_CENTER(sm));
483 if(point_in_cone(p,v0,v1,v2))
484 {
485 smTris_swap_edge(sm,id_t0,id_t1,e0,e1,&nid_t0,&nid_t1,&add,&del);
486
487 nt0 = SM_NTH_TRI(sm,nid_t0);
488 nt1 = SM_NTH_TRI(sm,nid_t1);
489 FOR_ALL_EDGES_FROM(e,i)
490 {
491 if(E_NTH_TRI(i,0)==id_t0 || E_NTH_TRI(i,0)==id_t1)
492 {
493 if(eIn_tri(i,nt0))
494 SET_E_NTH_TRI(i,0,nid_t0);
495 else
496 SET_E_NTH_TRI(i,0,nid_t1);
497 }
498
499 if(E_NTH_TRI(i,1)==id_t0 || E_NTH_TRI(i,1)==id_t1)
500 {
501 if(eIn_tri(i,nt0))
502 SET_E_NTH_TRI(i,1,nid_t0);
503 else
504 SET_E_NTH_TRI(i,1,nid_t1);
505 }
506 }
507 id_t0 = nid_t0;
508 id_t1 = nid_t1;
509 e_new = eNew_edge();
510 SET_E_NTH_VERT(e_new,0,id_p);
511 SET_E_NTH_VERT(e_new,1,id_v2);
512 SET_E_NTH_TRI(e_new,0,id_t0);
513 SET_E_NTH_TRI(e_new,1,id_t1);
514 }
515 }
516 smUpdate_locator(sm,add,del);
517 }
518
519 int
520 smMesh_remove_vertex(sm,id)
521 SM *sm;
522 int id;
523 {
524 int tri;
525 LIST *elist;
526 int cnt,debug;
527 /* generate list of vertices that form the boundary of the
528 star polygon formed by vertex id and all of its adjacent
529 triangles
530 */
531 eClear_edges();
532 elist = smVertex_star_polygon(sm,id);
533 if(!elist)
534 return(FALSE);
535
536 /* Triangulate spherical polygon */
537 debug = smTriangulate_polygon(sm,elist);
538
539
540 /* Fix up new triangles to be Delaunay */
541 if(debug)
542 smFix_edges(sm);
543
544 return(TRUE);
545 }
546
547 /* Remove point from samples, and from mesh. Delete any triangles
548 adjacent to the point and re-triangulate the hole
549 Return TRUE is point found , FALSE otherwise
550 */
551 int
552 smDelete_point(sm,id)
553 SM *sm;
554 int id;
555 {
556
557 /* Remove the corresponding vertex from the mesh */
558 smMesh_remove_vertex(sm,id);
559 /* Free the sample point */
560 smDelete_sample(sm,id);
561 return(TRUE);
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576