ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_del.c
Revision: 3.8
Committed: Mon Dec 28 18:07:34 1998 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.7: +54 -68 lines
Log Message:
New insertion routine
New Culling routine based on insertion algorithm
Adapted old insertion code: now used by picking
Point location code returns on-vertex,on-edge, or in-triangle
Added on_edge case for subdivision
Implemented unordered sets
Removed deletion from quadtree- added set compression to replace functionality

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