ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_del.c
Revision: 3.3
Committed: Fri Sep 11 11:52:25 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.2: +93 -30 lines
Log Message:
fixed triangle insertion using edge tracing

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