void MOD_FreeBrushes (hull_t *hull) { int i, j; int numnodes; if (!hull || !hull->nodeleafs) return; numnodes = hull->lastclipnode + 1; for (i = 0; i < numnodes; i++) { for (j = 0; j < 2; j++) free_leaf (hull->nodeleafs[i].leafs[j]); } free (hull->nodeleafs); hull->nodeleafs = 0; }
int entlim_free_ctx(void *ctx, void free_leaf(void *)) { pbs_entlim_key_t *leaf; int rc; leaf = entlim_create_key(NULL); /* alloc space for max sized key */ if (leaf == NULL) return -1; avl_first_key((AVL_IX_DESC *)ctx); while ((rc = avl_next_key((AVL_IX_REC *)leaf, (AVL_IX_DESC *)ctx)) == AVL_IX_OK) { free_leaf(leaf->recptr); } free(leaf); avl_destroy_index((AVL_IX_DESC *)ctx); free(ctx); return 0; }
/** * @brief * entlim_delete - delete record with a key based on the keystr * * @param[in] keystr - key string whose key is to be built * @param[in] recptr - pointer to record * @param[in] ctx - pointer to avl descending order tree info * @param[in] free_leaf() - function to free the data structure associated * with the key. * * @return int * @retval 0 delete success * @retval -1 delete failed */ int entlim_delete(const char *keystr, void *ctx, void free_leaf(void *)) { pbs_entlim_key_t *pkey; int rc; void *prec; pkey = entlim_create_key(keystr); if (pkey == NULL) return -1; rc = avl_delete_key((AVL_IX_REC *)pkey, (AVL_IX_DESC *)ctx); prec = pkey->recptr; free(pkey); if (rc == AVL_IX_OK) { free_leaf(prec); return 0; } else return -1; }
void node_free(struct node *node) { int i; nassert(node != NULL); for (i = 0; i < (node->n_children - 1); i++) xfree(node->pivots[i].data); for (i = 0; i < node->n_children; i++) { struct child_pointer *ptr = &node->parts[i].ptr; if (node->height > 0) free_nonleaf(ptr->u.nonleaf); else free_leaf(ptr->u.leaf); } xfree(node->pivots); xfree(node->parts); xfree(node); }
// does not check that the element is already there static int tree23_delete (tree23_root_t *R, int x) { int *P = 0, *PP = 0; tree23_t *st[40]; int sp, *y_Data = 0; tree23_t *cur = R->root, *up, *succ; int extra_words = R->extra_words; for (sp = 0; sp < R->depth; sp++) { st[sp] = cur; if (x > cur->x2) { cur = cur->right; } else if (x < cur->x1) { cur = cur->left; } else if (x == cur->x1) { P = &cur->x1; y_Data = DATA(cur->x1); if (cur->x2 == cur->x1) { PP = &cur->x2; } x++; break; } else if (x < cur->x2) { cur = cur->middle; } else { P = &cur->x2; y_Data = DATA(cur->x2); x++; break; } } // if x belongs to an inner node: // - P points to the key equal to (original) x in node cur // - PP points to cur->x2 if cur->x2 = cur->x1 = (original) x // - x equals original x+1 for some reason // if x is in a leaf, cur is this leaf, and P=PP=0 while (sp < R->depth) { st[sp++] = cur; if (x < cur->x1) { cur = cur->left; // actually will go left at all steps except the first one } else if (x > cur->x2) { cur = cur->right; } else { cur = cur->middle; } } // now cur is the leaf containing next value after (original) x, if x was in a inner node // otherwise, cur is the leaf containing x if (P) { // case 1: x was found in some inner node, ancestor of leaf cur // then x':=cur->x1 is the next value in tree after x // and we replace references to x with references to x' *P = cur->x1; if (PP) { *PP = cur->x1; } DCPY (y, cur->x1); // copy extra data words as well // after that, we just need to remove x' from leaf node cur if (cur->x1 < cur->x2) { // case 1a: cur: [ x' y ] , replace with [ y ] LET (cur->x1, cur->x2); return 1; } } else if (x == cur->x1) { if (x < cur->x2) { // case 0a: x was found in leaf cur: [ x y ], x < y // replace with [ y ] LET (cur->x1, cur->x2); return 1; } } else if (x == cur->x2) { // case 0b: x was found in leaf cur: [ u x ], u < x // simply replace it with [ u ] cur->x2 = cur->x1; return 1; } else { // x NOT FOUND in tree (?) return 0; } // here we have to remove x' from leaf node cur: [ x' ] //oh, no... //printf ("%d\n", sp); if (sp == 0) { // we are deleting the root! free_leaf (cur, Extra_words); R->root = 0; return 1; } up = st[--sp]; // up is the parent of leaf cur: [ x' ] ( we are deleting x': "cur --> []") if (up->right == cur) { if (IS_2N(up)) { // up: [ (left) x1 cur:[ x' ] ] if (IS_2N(up->left)) { // up: [ [ u ] x1 cur:[ x' ] ] // --> [ [ u ] x1 [] ] // --> [ succ:[ u x1 ] ] LET (up->left->x2, up->x1); free_leaf (cur, Extra_words); succ = up->left; //continue to the top } else { // up: [ [ u v ] x1 cur:[ x' ] ] // --> [ [ u v ] x1 [] ] // --> [ [ u ] v [ x1 ] ] cur->x1 = cur->x2 = up->x1; DCPY (cur->x1, up->x1); LET (up->x1, up->left->x2); up->left->x2 = up->left->x1; up->x2 = up->x1; return 1; } } else { // up: [ (left) x1 (middle) x2 cur:[ x' ] ] if (IS_2N(up->middle)) { // ! ELIMINATED CASE: if (up->left->x2 == up->left->x1) // up: [ (left) x1 [ u ] x2 cur:[ x' ] ] // --> [ (left) x1 [ u ] x2 [] ] // --> [ (left) x1 [ u x2 ] ] LET (up->middle->x2, up->x2); up->x2 = up->x1; up->right = up->middle; free_leaf (cur, Extra_words); return 1; } else { // up: [ (left) x1 [ u v ] x2 cur:[ x' ] ] // --> [ (left) x1 [ u v ] x2 [] ] // --> [ (left) x1 [ u ] v [ x2 ] ] LET (cur->x1, up->x2); cur->x2 = cur->x1; LET (up->x2, up->middle->x2); up->middle->x2 = up->middle->x1; return 1; } } } else if (up->left == cur) { if (IS_2N(up)) { // up: [ cur:[ x' ] x1 (right) ] if (IS_2N(up->right)) { // up: [ cur:[ x' ] x1 succ:[ y ] ] // --> [ ? ? succ: [ x1 y ] ] DCPY (up->right->x2, up->right->x1) LET (up->right->x1, up->x1); free_leaf (cur, Extra_words); succ = up->right; //continue to the top } else { // up: [ cur:[ x' ] x1 [ y z ] ] // --> [ [] x1 [ y z ] ] // --> [ [ x1 ] y [ z ] ] LET (cur->x1, up->x1); cur->x2 = cur->x1; LET (up->x1, up->right->x1); up->x2 = up->x1; LET (up->right->x1, up->right->x2); return 1; } } else { // up: [ cur:[ x' ] x1 (middle) x2 (right) ] if (IS_2N(up->middle)) { // ! ELIMINATED CASE: if (up->right->x2 & 1) { // up: [ cur:[ x' ] x1 [ y ] x2 (right) ] // --> [ [] x1 [ y ] x2 (right) ] // --> [ [ x1 y ] x2 (right) ] DCPY (up->middle->x2, up->middle->x1); LET (up->middle->x1, up->x1); up->left = up->middle; LET (up->x1, up->x2); free_leaf (cur, Extra_words); return 1; } else { // up: [ cur:[ x' ] x1 [ y z ] x2 (right) ] // --> [ [] x1 [ y z ] x2 (right) ] // --> [ [ x1 ] y [ z ] x2 (right) ] LET (cur->x1, up->x1); cur->x2 = cur->x1; LET (up->x1, up->middle->x1); LET (up->middle->x1, up->middle->x2); return 1; } } } else { // here cur == up->middle // up: [ (left) x1 cur:[ x' ] x2 (right) ] if (IS_2N(up->left)) { // up: [ [ v ] x1 cur:[ x' ] x2 (right) ] if (IS_2N(up->right)) { // up: [ [ v ] x1 cur:[ x' ] x2 [ y ] ] // --> [ [ v ] x1 [] x2 [ y ] ] // --> [ [ v ] x1 [ x2 y ] ] DCPY (up->right->x2, up->right->x1); LET (up->right->x1, up->x2); up->x2 = up->x1; free_leaf (cur, Extra_words); return 1; } else { // up: [ [ v ] x1 cur:[ x' ] x2 [ y z ] ] // --> [ [ v ] x1 [] x2 [ y z ] ] // --> [ [ v x1 ] x2 [ y z ] ] // ! WAS: --> [ [ v ] x1 [ x2 ] y [ z ] ] LET (up->left->x2, up->x1); LET (up->x1, up->x2); free_leaf (cur, Extra_words); return 1; } } else { // up: [ [ u v ] x1 cur:[ x' ] x2 (right) ] // --> [ [ u v ] x1 [] x2 (right) ] // up: [ [ u ] v cur:[ x1 ] x2 (right) ] LET (cur->x1, up->x1); cur->x2 = cur->x1; LET (up->x1, up->left->x2); up->left->x2 = up->left->x1; return 1; } } // we come here exactly in two of the above cases: // namely, if `cur`, its parent `up` and sibling `succ` are 2-nodes // then the subtree at `up` contains only 3 elements, and after removal of x' // it must contain only two entries, which is impossible // here: succ: [.u.v.] is the new replacement for the tree at `up` // informally: "current" value of `up` is assumed to be [ succ:[.u.v.] ] // but actually `up` cannot be a "1-node", so we want to correct this while (sp) { cur = up; up = st[--sp]; // now `cur` is the root of the subtree to be replaced with `succ` // `up` is the parent of `cur` if (up->right == cur) { // up: [ ... cur:(right) ] if (IS_2N(up)) { // up: [ (left) x1 cur:(right) ] if (IS_2N(up->left)) { // up: [ [.t.] x1 cur:(right) ] // --> [ [.t.] x1 cur:[ (succ) ] ] , succ has incorrect depth! // --> [ new_succ:[.t.x1 (succ) ] ] // after that: succ is at a good place, but up is to be replaced with [ new_succ ] LET (up->left->x2, up->x1); up->left->middle = up->left->right; up->left->right = succ; free_node (cur, Extra_words); succ = up->left; } else { // up: [ [.s.t.] x1 cur:(right) ] // --> [ [.s.t.] x1 cur:[ (succ) ] ] // --> [ [.s.] t cur:[.x1 (succ) ] ] LET (cur->x1, up->x2); cur->x2 = cur->x1; cur->right = succ; cur->left = up->left->right; LET (up->x1, up->left->x2); up->x2 = up->x1; up->left->x2 = up->left->x1; up->left->right = up->left->middle; return 1; } } else { // up: [ (left) x1 (middle) x2 cur:(right) ] if (IS_2N(up->middle)) { // up: [ (left) x1 [.t.] x2 cur:[ (succ) ] ] // --> [ (left) x1 [.t.x2.(succ)] ] up->right = up->middle; LET (up->right->x2, up->x2); up->x2 = up->x1; up->right->middle = up->right->right; up->right->right = succ; free_node (cur, Extra_words); return 1; } else { // up: [ (left) x1 [.s.t.] x2 cur:[ (succ) ] ] // --> [ (left) x1 [.s.] t cur:[.x2 (succ)] ] LET (cur->x1, up->x2); cur->x2 = cur->x1; cur->right = succ; cur->left = up->middle->right; LET (up->x2, up->middle->x2); up->middle->x2 = up->middle->x1; up->middle->right = up->middle->middle; return 1; } } } else if (up->left == cur) { // up: [ cur:(left) ... ] if (IS_2N(up)) { // up: [ cur:(left) x1 (right) ] if (IS_2N(up->right)) { // up: [ cur:[ (succ) ] x1 [.y.] ] // --> [ new_succ:[ (succ) x1.y.] ] DCPY (up->right->x2, up->right->x1); LET (up->right->x1, up->x1); up->right->middle = up->right->left; up->right->left = succ; succ = up->right; free_node (cur, Extra_words); //continue to the top } else { // up: [ cur:[ (succ) ] x1 [.y.z.] ] // --> [ cur:[ (succ) x1. ] y [.z.] ] LET (cur->x1, up->x1); cur->x2 = cur->x1; cur->left = succ; cur->right = up->right->left; up->right->left = up->right->middle; LET (up->x1, up->right->x1); up->x2 = up->x1; LET (up->right->x1, up->right->x2); return 1; } } else { // up: [ cur:(left) x1 (middle) x2 (right) ] if (IS_2N(up->middle)) { // up: [ cur:[(succ)] x1 [.y.] x2 (right) ] // --> [ [(succ) x1.y.] x2 (right) ] DCPY (up->middle->x2, up->middle->x1); LET (up->middle->x1, up->x1); up->middle->middle = up->middle->left; up->middle->left = succ; up->left = up->middle; LET (up->x1, up->x2); free_node (cur, Extra_words); return 1; } else { // up: [ cur:[(succ)] x1 [.y.z.] x2 (right) ] // --> [ [(succ) x1.] y [.z.] x2 (right) ] cur->left = succ; cur->right = up->middle->left; LET (cur->x1, up->x1); cur->x2 = cur->x1; up->middle->left = up->middle->middle; LET (up->x1, up->middle->x1); LET (up->middle->x1, up->middle->x2); return 1; } } } else { // now up->middle == cur // up: [ (left) x1 cur:[(succ)] x2 (right) ] if (IS_2N(up->left)) { // up: [ [.s.] x1 cur:[(succ)] x2 (right) ] // --> [ [.s.x1 (succ)] x2 (right) ] LET (up->left->x2, up->x1); up->left->middle = up->left->right; up->left->right = succ; LET (up->x1, up->x2); free_node (cur, Extra_words); return 1; } else { // up: [ [.s.t.] x1 cur:[(succ)] x2 (right) ] // --> [ [.s.] t [.x1 (succ)] x2 (right) ] LET (cur->x1, up->x1); cur->x2 = cur->x1; cur->right = succ; cur->left = up->left->right; up->left->right = up->left->middle; LET (up->x1, up->left->x2); up->left->x2 = up->left->x1; return 1; } } } // If we come here, this means that `up` is the root // and we want to replace it with "1-node" [ (succ) ] // Instead, we decrease the depth by one, and make `succ` the new root free_node (up, Extra_words); R->root = succ; R->depth--; return 1; }
void cut_leaf (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct leaf *lf) { int j, k, n, nx, nw, orn, sgn, i, used0, used1, nused; double t, xsmin, sangle, fsgn; double base[3], xpnts[2][3], vect[3]; char message[MAXLINE]; struct circle *cir; struct arc *al, *a; struct variety *vty; struct face *fac; struct leaf *lfcut; struct lax *xsptr, *xsend, *xsp; struct cycle *cyc; struct edge *edg; struct lax laxes[MAX_LAX]; struct cept *ex; fac = lf -> fac; /* count number of edges for face */ n = 2 * edges_in_face (fac); /* if toroidal, no cutting */ if (fac -> shape == SADDLE || n <= 0) { /* clip and render leaf */ clip_leaf (ms, current_surface, fine_pixel, lf); return; } /* determine sign (plus for convex, minus for concave) */ fsgn = ((lf -> shape == CONVEX) ? 1.0 : -1.0); /* create arc for leaf */ al = leaf_to_arc (lf); vty = fac -> vty; cir = lf -> cir; for (k = 0; k < 3; k++) base[k] = lf -> ends[0][k] - cir -> center[k]; normalize (base); /* determine intersection points between leaf and arcs of face */ xsptr = &(laxes[0]); for (cyc = fac -> first_cycle; cyc != NULL; cyc = cyc -> next) for (edg = cyc -> first_edge; edg != NULL; edg = edg -> next) { a = edg -> arcptr; orn = edg -> orn; sgn = 1 - 2 * orn; /* call arc-arc intersection function */ nx = arc_arc (al, a, xpnts); if (nx <= 0) continue; /* no intersections */ /* fill data into list */ for (i = 0; i < nx; i++) { if (xsptr - &(laxes[0]) >= n) { ex = new_cept (ARRAY_ERROR, MSOVERFLOW, FATAL_SEVERITY); add_function (ex, "cut_leaf"); add_source (ex, "msrender.c"); add_long (ex, "maximum number of leaf-arc intersections", n); return; } for (k = 0; k < 3; k++) { xsptr -> co[k] = xpnts[i][k]; vect[k] = fsgn * (xsptr -> co[k] - vty -> center[k]); } t = sgn * triple_product (al -> cir -> axis, a -> cir -> axis, vect); xsptr -> ent = (t < 0); xsptr -> used = 0; xsptr++; } } xsend = xsptr; /* mark end of list of intersection points */ nx = xsend - &(laxes[0]); /* compute number of intersection points */ /* intersection parity error checking */ if ((lf -> where[0] == lf -> where[1]) == (nx % 2)) { /* parity check fails, flag leaf to check accessibility of every pixel of leaf */ ms -> n_bdy_parity++; lf -> cep = 1; clip_leaf (ms, current_surface, fine_pixel, lf); lf -> cep = 0; frearc (al); return; } /* kludge to work around undiscovered bug for quartet cusps */ if (lf -> atmnum[3] != 0) { /* flag leaf to check accessibility of every pixel of leaf */ lf -> cep = 1; clip_leaf (ms, current_surface, fine_pixel, lf); lf -> cep = 0; frearc (al); return; } /* check for no intersection points */ if (nx == 0) { if (lf -> where[0] == INACCESSIBLE) { /* entire leaf inaccessible: nothing to render */ /* free temporary memory */ frearc (al); return; } /* entire leaf accessible: render entire leaf */ clip_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; /* free temporary memory */ frearc (al); return; } /* calculate angles for transitions between accessible and inaccessible */ for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { for (k = 0; k < 3; k++) vect[k] = xsptr -> co[k] - cir -> center[k]; normalize (vect); xsptr -> angle = positive_angle (base, vect, cir -> axis); } /* initialization */ used0 = 0; used1 = 0; nused = 0; nw = 0; /* count number of accessible endpoints of originial leaf */ for (j = 0; j < 2; j++) if (lf -> where[j]) nw++; /* create new leaves */ while (nused < nx + nw) { /* get starting point */ if (!used0 && lf -> where[0] == ACCESSIBLE) { /* start at original endpoint */ used0 = 1; /* first originial endpoint used */ nused++; /* increment number used */ lfcut = duplicate_leaf (lf); /* duplicate leaf */ sangle = 0.0; /* starting angle */ } else { /* look for unused cut vertex */ xsmin = 4 * PI; xsp = NULL; for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { if (xsptr -> used) continue; if (xsptr -> angle < xsmin) { xsmin = xsptr -> angle; xsp = xsptr; } } if (xsp == NULL) { if (lf -> where[1] == INACCESSIBLE) break; ms -> n_missing_leaves++; return; } if (!xsp -> ent) { ms -> n_missing_leaves++; return; } xsp -> used = 1; /* mark as used */ nused++; /* increment number used */ sangle = xsp -> angle; /* starting angle */ lfcut = duplicate_leaf (lf); /* duplicate leaf */ for (k = 0; k < 3; k++) lfcut -> ends[0][k] = xsp -> co[k]; } /* get ending point */ /* initialization */ xsmin = 4 * PI; xsp = NULL; for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { if (xsptr -> used) continue; /* already used */ if (xsptr -> angle < sangle) continue; /* end after start */ if (xsptr -> angle < xsmin) { /* best so far, save */ xsmin = xsptr -> angle; xsp = xsptr; } } if (xsp == NULL) { if (used1 || lf -> where[1] == INACCESSIBLE) { ms -> n_missing_leaves++; return; } /* use East */ used1 = 1; /* mark East original endpoint used */ nused++; /* increment number used */ for (k = 0; k < 3; k++) lfcut -> ends[1][k] = lf -> ends[1][k]; } else { /* use cut point */ for (k = 0; k < 3; k++) lfcut -> ends[1][k] = xsp -> co[k]; xsp -> used = 1; /* mark as used */ nused++; /* increment number used */ } /* we have a cut leaf; clip and render leaf */ clip_leaf (ms, current_surface, fine_pixel, lfcut); free_leaf (lfcut); /* free temporary memory */ } /* free temporary memory */ frearc (al); return; }
void slice_sphere (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac) { int k, j; double yinc, y, rad, fsgn; double cir_center[3], cir_axis[3]; char message[MAXLINE]; struct leaf *lf; struct circle *cir; struct variety *vty; struct cept *ex; vty = fac -> vty; if (vty -> type != SPHERE) { ex = new_cept (ENUM_ERROR, INVALID_VALUE, FATAL_SEVERITY); add_function (ex, "slice_sphere"); add_source (ex, "msrender.c"); add_long (ex, "variety type", (long) vty -> type); return; } /* check versus window */ for (k = 0; k < 3; k++) { if (vty -> center[k] + vty -> radii[0] < ms -> window[0][k]) return; if (vty -> center[k] - vty -> radii[0] > ms -> window[1][k]) return; } /* plus one for convex; minus one for concave */ fsgn = ((fac -> shape == CONVEX) ? 1.0 : -1.0); /* set up circle for leaf */ for (k = 0; k < 3; k++) { cir_center[k] = vty -> center[k]; cir_axis[k] = ((k == 1) ? fsgn : 0.0); } cir = new_circle (cir_center, (double) 0.0, cir_axis); if (cir == NULL) { add_object (tail_cept, CIRCLE, "leaf circle"); add_function (tail_cept, "slice_sphere"); return; } lf = allocate_leaf (); if (lf == NULL) { add_object (tail_cept, LEAF, "leaf"); add_function (tail_cept, "slice_sphere"); return; } /* copy atom number from variety to leaf */ for (j = 0; j < MAXPA; j++) lf -> atmnum[j] = fac -> vty -> atmnum[j]; for (k = 0; k < 3; k++) lf -> focus[k] = vty -> center[k]; /* set up leaf fields */ lf -> cir = cir; lf -> shape = fac -> shape; lf -> type = fac -> vty -> type; lf -> fac = fac; lf -> side = OUTSIDE; lf -> comp = fac -> comp; lf -> input_hue = fac -> input_hue; /* y increment for lines of latitude on sphere */ yinc = fine_pixel; /* one leaf per line of latitude */ for (y = vty -> center[1] - vty -> radii[0] - yinc / 2; y < vty -> center[1] + vty -> radii[0]; y += yinc) { /* change circle center */ cir -> center[1] = y; /* radius of circle of latitude */ rad = (vty -> radii[0] * vty -> radii[0]) - (y - vty -> center[1]) * (y - vty -> center[1]); if (rad <= 0.0) continue; rad = sqrt (rad); if (rad <= 0.0) continue; cir -> radius = rad; /* leaf endpoints: west and east */ for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lf -> ends[j][k] = cir -> center[k]; lf -> ends[0][0] -= rad; lf -> ends[1][0] += rad; /* determine accessibility of endpoints of leaf */ for (j = 0; j < 2; j++) { lf -> where[j] = point_in_face (lf -> ends[j], fac, 1); if (lf -> where[j] < 0) { ms -> n_bad_projection++; lf -> where[j] = 0; } } /* cut, clip and render (outer) leaf */ lf -> cep = 0; lf -> clip_ep = 0; cut_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; if (current_surface -> clipping) { /* cut, clip and render (inner) leaf */ for (k = 0; k < 3; k++) cir -> axis[k] = ((k == 1) ? -fsgn : 0.0); lf -> cep = 0; lf -> clip_ep = 0; lf -> side = INSIDE; cut_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; /* reset what we changed */ lf -> side = OUTSIDE; for (k = 0; k < 3; k++) cir -> axis[k] = ((k == 1) ? fsgn : 0.0); } } free_leaf (lf); free_circle (cir); return; }
void slice_cylinder (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac) { int k, j; double axis_inc, a; double half_length, big_radius, cyl_radius; double cyl_axis[3], z_axis[3], base[3]; struct leaf *lf; struct circle *lfcir; struct variety *vty; struct cept *ex; vty = fac -> vty; cyl_radius = vty -> radii[0]; half_length = vty -> length / 2; big_radius = ((half_length > cyl_radius) ? half_length : cyl_radius); /* check versus window */ for (k = 0; k < 3; k++) { if (vty -> center[k] + big_radius < ms -> window[0][k]) return; if (vty -> center[k] - big_radius > ms -> window[1][k]) return; } /* leaf circle */ lfcir = allocate_circle (); if (lfcir == NULL) { ex = new_cept (MEMORY_ERROR, ALLOCATION, FATAL_SEVERITY); add_object (ex, CIRCLE, "leaf circle"); add_function (ex, "slice_cylinder"); add_source (ex, "msrender.c"); return; } /* leaf */ lf = allocate_leaf (); if (lf == NULL) { add_object (tail_cept, LEAF, "leaf"); add_function (tail_cept, "slice_sphere"); return; } /* set up circle for leaf */ lfcir -> radius = cyl_radius; for (k = 0; k < 3; k++) { lfcir -> center[k] = vty -> center[k]; lfcir -> axis[k] = vty -> axis[k]; cyl_axis[k] = vty -> axis[k]; lf -> focus[k] = vty -> center[k]; } /* check for end-on */ if (cyl_axis[0] == 0.0 && cyl_axis[1] == 0.0) { free_leaf (lf); free_circle (lfcir); return; } for (k = 0; k < 3; k++) z_axis[k] = ((k == 2) ? 1.0 : 0.0); cross (cyl_axis, z_axis, base); if (norm (base) <= 0.0) { free_leaf (lf); free_circle (lfcir); return; } normalize (base); /* copy 3 atom number from variety to leaf */ for (k = 0; k < MAXPA; k++) lf -> atmnum[k] = vty -> atmnum[k]; /* set up leaf fields */ lf -> cir = lfcir; lf -> shape = fac -> shape; lf -> type = fac -> vty -> type; lf -> fac = fac; lf -> side = OUTSIDE; lf -> comp = fac -> comp; lf -> input_hue = fac -> input_hue; /* increment for lines of latitude on cylinder */ axis_inc = fine_pixel; /* one leaf per line of latitude */ for (a = (-half_length-axis_inc/2); a < half_length; a += axis_inc) { /* change circle center */ for (k = 0; k < 3; k++) { lfcir -> center[k] = vty -> center[k] + a * cyl_axis[k]; lf -> focus[k] = lfcir -> center[k]; } /* leaf endpoints: west and east */ for (k = 0; k < 3; k++) { lf -> ends[0][k] = lfcir -> center[k] - cyl_radius * base[k]; lf -> ends[1][k] = lfcir -> center[k] + cyl_radius * base[k]; } /* determine accessibility of endpoints of leaf */ for (j = 0; j < 2; j++) lf -> where[j] = 1; /* cut, clip and render (outer) leaf */ lf -> cep = 0; lf -> clip_ep = 0; clip_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; if (current_surface -> clipping) { /* cut, clip and render (inner) leaf */ for (k = 0; k < 3; k++) lfcir -> axis[k] = (-cyl_axis[k]); lf -> cep = 0; lf -> clip_ep = 0; lf -> side = INSIDE; clip_leaf (ms, current_surface, fine_pixel, lf); /* reset what we changed */ lf -> side = OUTSIDE; for (k = 0; k < 3; k++) lfcir -> axis[k] = cyl_axis[k]; } } free_leaf (lf); free_circle (lfcir); return; }
void slice_elbow (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac) { char message[MAXLINE]; struct leaf *lf; struct circle *lfcir, *torcir; struct arc *torarc; struct vertex *torvtx[2]; int i, j, k, nfocus, atmnum; double anginc, bigrad; double atmcen[3], ccens[2][3], cradii[2]; double focus[3], vect[3], z_axis[3], base[3]; struct variety *vty; double *foci; struct cept *ex; vty = fac -> vty; atmnum = vty -> atmnum[0]; if (debug >= 2) { sprintf (message,"render elbow face for atom %5d", atmnum); inform(message); } for (k = 0; k < 3; k++) atmcen[k] = *(current_surface -> atom_centers + 3 * (atmnum - 1) + k); for (j = 0; j < 2; j++) cradii[j] = vty -> radii[1]; for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) { ccens[j][k] = vty -> ccens[j][k]; } bigrad = distance (atmcen, ccens[0]) + cradii[0]; for (k = 0; k < 3; k++) { if (atmcen[k] + bigrad < ms -> window[0][k]) return; if (atmcen[k] - bigrad > ms -> window[1][k]) return; } /* leaf circle */ lfcir = allocate_circle (); if (lfcir == NULL) { ex = new_cept (MEMORY_ERROR, ALLOCATION, FATAL_SEVERITY); add_object (ex, CIRCLE, "leaf circle"); add_function (ex, "slice_elbow"); add_source (ex, "msrender.c"); return; } /* leaf */ lf = allocate_leaf (); if (lf == NULL) { add_object (tail_cept, LEAF, "leaf"); add_function (tail_cept, "slice_sphere"); return; } /* torus circle radius, center, axis */ torcir = new_circle (vty -> center, vty -> radii[0], vty -> axis); if (torcir == NULL) { add_object (tail_cept, CIRCLE, "torus circle"); add_function (tail_cept, "slice_elbow"); return; } /* torus arc */ torarc = allocate_arc (); if (torarc == NULL) { add_object (tail_cept, ARC, "torus arc"); add_function (tail_cept, "slice_elbow"); add_source (tail_cept, "msrender.c"); return; } for (j = 0; j < 2; j++) { torvtx[j] = allocate_vertex (); if (error()) { add_object (tail_cept, VERTEX, "torus vertex"); add_function (tail_cept, "slice_elbow"); add_source (tail_cept, "msrender.c"); return; } } /* set up leaf fields */ for (k = 0; k < MAXPA; k++) lf -> atmnum[k] = vty -> atmnum[k]; lf -> cir = lfcir; lf -> shape = CONVEX; /* to avoid reversing normal vector */ lf -> type = vty -> type; lf -> fac = fac; lf -> cep = 0; lf -> clip_ep = 0; lf -> side = OUTSIDE; lf -> comp = fac -> comp; lf -> input_hue = fac -> input_hue; for (j = 0; j < 2; j++) lf -> where[j] = ACCESSIBLE; /* setup torus central circle for subdivision */ anginc = fine_pixel / ((vty -> radii[0] + cradii[0])); torcir -> radius = vty -> radii[0]; for (k = 0; k < 3; k++) { torcir -> center[k] = vty -> center[k]; torcir -> axis[k] = vty -> axis[k]; } torarc -> cir = torcir; for (j = 0; j < 2; j++) { torarc -> vtx[j] = torvtx[j]; for (k = 0; k < 3; k++) torvtx[j] -> center[k] = ccens[j][k]; } foci = (double *) NULL; nfocus = render_sub_arc (torarc, &foci, anginc); if (nfocus < 2) { ex = new_cept (LOGIC_ERROR, MSUNDERFLOW, FATAL_SEVERITY); add_function (ex, "slice_elbow"); add_source (ex, "msrender.c"); add_long (ex, "number of foci", (long) nfocus); return; } /* create leaves */ for (i = 0; i < nfocus; i++) { for (k = 0; k < 3; k++) { focus[k] = (*(foci + 3 * i + k)); lfcir -> center[k] = focus[k]; lf -> focus[k] = focus[k]; } lfcir -> radius = cradii[0]; /* compute tangent to torus central circle */ for (k = 0; k < 3; k++) vect[k] = focus[k] - vty -> center[k]; cross (vty -> axis, vect, lfcir -> axis); normalize (lfcir -> axis); for (k = 0; k < 3; k++) z_axis[k] = ((k == 2) ? 1.0 : 0.0); cross (lfcir -> axis, z_axis, base); if (norm (base) <= 0.0) { continue; } normalize (base); for (k = 0; k < 3; k++) { lf -> ends[0][k] = lfcir -> center[k] - lfcir -> radius * base[k]; lf -> ends[1][k] = lfcir -> center[k] + lfcir -> radius * base[k]; } /* clip and render leaf */ clip_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; } free_doubles (foci, 0, VERTS); free_leaf (lf); free_arc (torarc); free_circle (torcir); free_circle (lfcir); for (j = 0; j < 2; j++) free_vertex (torvtx[j]); }
void slice_torus (struct msscene *ms, struct surface *current_surface, double fine_pixel, double probe_radius, struct face *fac) { int k, j, i, nfocus, near1, naif; double anginc, bigrad; double focus[3], vect1[3], vect2[3], vect[3], qvect[3]; double dtq, tcv[3]; double *foci = (double *) NULL; char message[MAXLINE]; struct leaf *lf; struct circle *cir1, *cir2, *cir3; struct circle *lfcir, *torcir; struct variety *vty, *atm1, *atm2; struct arc *a, *nxta; struct arc *torarc; struct vertex *torvtx[2]; struct vertex *qvtx; struct vertex *conevtx; struct cycle *cyc; struct edge *edg; struct cept *ex; vty = fac -> vty; if (vty -> type != TORUS) { ex = new_cept (GEOMETRY_ERROR, INCONSISTENCY, FATAL_SEVERITY); add_function (ex, "slice_torus"); add_source (ex, "msrender.c"); add_long (ex, "variety type", (long) vty -> type); return; } if (vty -> tube) { slice_elbow (ms, current_surface, fine_pixel, fac); return; } if (debug >= 2) { sprintf (message,"render saddle face for atoms %5d %5d", vty -> atmnum[0], vty -> atmnum[1]); inform(message); } /* get pointers to atom varieties */ atm1 = *(current_surface -> variety_handles + fac -> vty -> atmnum[0] - 1); atm2 = *(current_surface -> variety_handles + fac -> vty -> atmnum[1] - 1); /* check versus window */ bigrad = distance (atm1 -> center, atm2 -> center) + atm1 -> radii[0] + atm2 -> radii[0]; for (k = 0; k < 3; k++) { if (vty -> center[k] + bigrad < ms -> window[0][k]) return; if (vty -> center[k] - bigrad > ms -> window[1][k]) return; } /* leaf circle */ lfcir = allocate_circle (); if (error()) { add_object (tail_cept, CIRCLE, "leaf circle"); add_function (tail_cept, "slice_torus"); return; } /* leaf */ lf = allocate_leaf (); if (error()) { add_object (tail_cept, LEAF, "leaf"); add_function (tail_cept, "slice_sphere"); return; } /* torus circle radius, center, axis */ torcir = new_circle (vty -> center, vty -> radii[0], vty -> axis); if (torcir == NULL) { add_object (tail_cept, CIRCLE, "torus circle"); add_function (tail_cept, "slice_circle"); return; } /* torus arc */ torarc = allocate_arc (); if (error()) { add_object (tail_cept, ARC, "torus arc"); add_function (tail_cept, "slice_torus"); add_source (tail_cept, "msrender.c"); return; } for (j = 0; j < 2; j++) { torvtx[j] = allocate_vertex (); if (error()) { add_object (tail_cept, VERTEX, "torus vertex"); add_function (tail_cept, "slice_torus"); add_source (tail_cept, "msrender.c"); return; } } torarc -> cir = torcir; /* copy atom numbers from variety to leaf */ for (k = 0; k < MAXPA; k++) lf -> atmnum[k] = fac -> vty -> atmnum[k]; /* set up leaf fields */ lf -> cir = lfcir; lf -> shape = fac -> shape; lf -> type = fac -> vty -> type; lf -> fac = fac; lf -> cep = 0; lf -> clip_ep = 0; lf -> side = OUTSIDE; lf -> comp = fac -> comp; lf -> input_hue = fac -> input_hue; /* both endpoints of saddle face leaf are always accessible */ for (j = 0; j < 2; j++) lf -> where[j] = ACCESSIBLE; /* angular increment for rotation of leaf about torus axis */ anginc = fine_pixel / (vty -> radii[0]); /* next we need endpoints for torus arc */ /* get them from concave arcs bounding saddle face */ /* intialization */ cir1 = NULL; cir2 = NULL; cir3 = NULL; qvtx = NULL; conevtx = NULL; near1 = 0; /* look for concave arcs */ naif = 0; for (cyc = fac -> first_cycle; cyc != NULL; cyc = cyc -> next) for (edg = cyc -> first_edge; edg != NULL; edg = edg -> next) { naif++; a = edg -> arcptr; if (a -> shape == CONVEX) { cir3 = a -> cir; continue; } if (edg -> next == NULL) nxta = cyc -> first_edge -> arcptr; else nxta = edg -> next -> arcptr; if (along (edg, vty -> axis)) cir2 = a -> cir; else cir1 = a -> cir; /* check for cusp vertex */ if (a -> shape == CONCAVE && nxta -> shape == CONCAVE) { /* cusp point joints two concave arcs */ qvtx = a -> vtx[1-edg->orn]; } } dtq = probe_radius * probe_radius - vty -> radii[0] * vty -> radii[0]; /* later: note: check PI in bubbles */ if (naif == 1) { if (dtq <= 0.0) { ex = new_cept (GEOMETRY_ERROR, INCONSISTENCY, FATAL_SEVERITY); add_function (ex, "slice_torus"); add_source (ex, "msrender.c"); add_message(ex, "toroidal face with only one arc, but not cone"); return; } if (cir3 == NULL) { ex = new_cept (GEOMETRY_ERROR, INCONSISTENCY, FATAL_SEVERITY); add_function (ex, "slice_torus"); add_source (ex, "msrender.c"); add_message(ex, "toroidal face with only one arc, but no contact circle"); return; } /* cone */ qvtx = allocate_vertex (); if (error()) { add_object (tail_cept, VERTEX, "CUSP VERTEX"); add_function (tail_cept, "slice_torus"); add_source (tail_cept, "msrender.c"); return; } conevtx = qvtx; dtq = sqrt (dtq); for (k = 0; k < 3; k++) tcv[k] = cir3 -> center[k] - torcir -> center[k]; normalize (tcv); for (k = 0; k < 3; k++) qvtx -> center[k] = torcir -> center[k] + dtq * tcv[k]; /* hope this is enough */ } if (cir1 == NULL) informd2 ("cir1 null"); if (cir2 == NULL) informd2 ("cir2 null"); if (qvtx != NULL) informd2 ("cusp present"); /* check for cusp vertex */ if (qvtx != NULL) { for (k = 0; k < 3; k++) qvect[k] = qvtx -> center[k] - vty -> center[k]; near1 = (dot_product (qvect, vty -> axis) < 0.0); } /* check for hoop saddle face */ if (cir1 == NULL || cir2 == NULL) { for (j = 0; j < 2; j++) torarc -> vtx[j] = NULL; informd2 ("complete toroidal hoop"); } else { /* concave arc circle centers are endpoints of sphere rolling */ for (k = 0; k < 3; k++) { torvtx[0] -> center[k] = cir1 -> center[k]; torvtx[1] -> center[k] = cir2 -> center[k]; } for (j = 0; j < 2; j++) torarc -> vtx[j] = torvtx[j]; sprintf (message, "saddle rendering (from): %8.3f %8.3f %8.3f", cir1 -> center[0], cir1 -> center[1], cir1 -> center[2]); informd2 (message); sprintf (message, "saddle rendering (to) : %8.3f %8.3f %8.3f", cir2 -> center[0], cir2 -> center[1], cir2 -> center[2]); informd2 (message); } /* the probe sphere centers are the foci of the leaves */ nfocus = render_sub_arc (torarc, &foci, anginc); if (nfocus < 2) { ex = new_cept (LOGIC_ERROR, MSUNDERFLOW, FATAL_SEVERITY); add_function (ex, "slice_torus"); add_source (ex, "msrender.c"); add_long (ex, "number of foci", (long) nfocus); return; } sprintf (message, "nfocus = %d", nfocus); informd2 (message); /* create leaves */ for (i = 0; i < nfocus; i++) { for (k = 0; k < 3; k++) { focus[k] = (*(foci + 3 * i + k)); lfcir -> center[k] = focus[k]; lf -> focus[k] = focus[k]; } /* unit vectors from focus toward atoms */ for (k = 0; k < 3; k++) { vect1[k] = atm1 -> center[k] - focus[k]; vect2[k] = atm2 -> center[k] - focus[k]; } /* correct for cusp vertex */ if (qvtx != NULL) { if (near1) for (k = 0; k < 3; k++) vect2[k] = qvtx -> center[k] - focus[k]; else for (k = 0; k < 3; k++) vect1[k] = qvtx -> center[k] - focus[k]; } /* normalize vectors to unit length */ normalize (vect1); normalize (vect2); /* leaf circle radius is probe radius */ lfcir -> radius = probe_radius; /* set up endpoints of leaf */ for (k = 0; k < 3; k++) { lf -> ends[0][k] = focus[k] + lfcir -> radius * vect1[k]; lf -> ends[1][k] = focus[k] + lfcir -> radius * vect2[k]; } /* compute leaf circle axis */ for (k = 0; k < 3; k++) vect[k] = focus[k] - vty -> center[k]; cross (vty -> axis, vect, lfcir -> axis); normalize (lfcir -> axis); /* clip and render leaf */ clip_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; } /* return temporary memory */ if (!free_doubles (foci, 0, VERTS)) { ex = new_cept (MEMORY_ERROR, FREEING, FATAL_SEVERITY); add_variable (ex, VERTS, "foci"); add_function (ex, "slice_torus"); add_source (ex, "msrender.c"); return; } free_leaf (lf); free_arc (torarc); free_circle (torcir); free_circle (lfcir); for (j = 0; j < 2; j++) free_vertex (torvtx[j]); if (conevtx != NULL) free_vertex (conevtx); return; }
void clip_leaf (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct leaf *lf) { int j, k, n, nx, nw, i, used0, used1, nused; double t, xsmin, sangle; double base[3], xpnts[2][3], vect[3]; double clip_center[3], clip_axis[3]; struct circle *cir; struct arc *al; struct leaf *lfcut; struct lax *xsptr, *xsend, *xsp; struct lax laxes[MAX_LAX]; /* count double number of clipping planes */ n = 0; if (ms -> clipping) n += 2; if (n <= 0 || !(current_surface -> clipping)) { lf -> clip_ep = 0; render_leaf (ms, current_surface, fine_pixel, lf); return; } /* determine accessibility of endpoints of leaf */ for (j = 0; j < 2; j++) lf -> when[j] = !(current_surface -> clipping && clipped (ms, lf -> ends[j])); /* create arc for leaf */ al = leaf_to_arc (lf); cir = lf -> cir; for (k = 0; k < 3; k++) base[k] = lf -> ends[0][k] - cir -> center[k]; normalize (base); /* determine intersection points between leaf and clipping planes */ xsptr = &(laxes[0]); if (ms -> clipping) { for (k = 0; k < 3; k++) { clip_center[k] = ms -> clip_center[k]; clip_axis[k] = ms -> clip_axis[k]; } /* call arc-plane intersection function */ nx = arc_plane (al, clip_center, clip_axis, xpnts); if (nx < 0) return; /* if (nx == 0) continue; no intersections */ /* fill data into list */ /* figure out enter or exit */ for (i = 0; i < nx; i++) { if (xsptr - &(laxes[0]) >= n) { ms -> n_missing_leaves++; return; } for (k = 0; k < 3; k++) xsptr -> co[k] = xpnts[i][k]; for (k = 0; k < 3; k++) vect[k] = xsptr -> co[k] - al -> cir -> center[k]; t = triple_product (al -> cir -> axis, clip_axis, vect); xsptr -> ent = (t > 0); /* or reverse? */ xsptr -> used = 0; xsptr++; } } xsend = xsptr; /* mark end of list of intersection points */ nx = xsend - &(laxes[0]); /* compute number of intersection points */ /* error checking */ if ((lf -> when[0] == lf -> when[1]) == (nx % 2)) { /* parity check fails, flag leaf to check clipping of every pixel of leaf */ ms -> n_clip_parity++; lf -> clip_ep = 1; render_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; lf -> clip_ep = 0; frearc (al); return; } /* check for no intersection points */ if (nx == 0) { if (lf -> when[0] == CLIPPED) { /* entire leaf clipped: nothing to render */ /* free temporary memory */ frearc (al); return; } /* entire leaf unclipped: render entire leaf */ render_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; /* free temporary memory */ frearc (al); return; } /* calculate angles for transitions between unclipped and clipped */ for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { for (k = 0; k < 3; k++) vect[k] = xsptr -> co[k] - cir -> center[k]; normalize (vect); xsptr -> angle = positive_angle (base, vect, cir -> axis); } /* initialization */ used0 = 0; used1 = 0; nused = 0; nw = 0; /* count number of unclipped endpoints of originial leaf */ for (j = 0; j < 2; j++) if (lf -> when[j]) nw++; /* create new leaves */ while (nused < nx + nw) { /* get starting point */ if (!used0 && lf -> when[0] == UNCLIPPED) { /* start at original endpoint */ used0 = 1; /* first originial endpoint used */ nused++; /* increment number used */ lfcut = duplicate_leaf (lf); /* duplicate leaf */ sangle = 0.0; /* starting angle */ } else { /* look for unused cut vertex */ xsmin = 4 * PI; xsp = NULL; for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { if (xsptr -> used) continue; if (xsptr -> angle < xsmin) { xsmin = xsptr -> angle; xsp = xsptr; } } if (xsp == NULL) { if (lf -> when[1] == CLIPPED) break; ms -> n_missing_leaves++; return; } if (!xsp -> ent) { ms -> n_missing_leaves++; return; } xsp -> used = 1; /* mark as used */ nused++; /* increment number used */ sangle = xsp -> angle; /* starting angle */ lfcut = duplicate_leaf (lf); /* duplicate leaf */ for (k = 0; k < 3; k++) lfcut -> ends[0][k] = xsp -> co[k]; } /* get ending point */ /* initialization */ xsmin = 4 * PI; xsp = NULL; for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) { if (xsptr -> used) continue; /* already used */ if (xsptr -> angle < sangle) continue; /* end after start */ if (xsptr -> angle < xsmin) { /* best so far, save */ xsmin = xsptr -> angle; xsp = xsptr; } } if (xsp == NULL) { if (used1 || lf -> when[1] == CLIPPED) { ms -> n_missing_leaves++; return; } /* use East */ used1 = 1; /* mark East original endpoint used */ nused++; /* increment number used */ for (k = 0; k < 3; k++) lfcut -> ends[1][k] = lf -> ends[1][k]; } else { /* use cut point */ for (k = 0; k < 3; k++) lfcut -> ends[1][k] = xsp -> co[k]; xsp -> used = 1; /* mark as used */ nused++; /* increment number used */ } /* we have a cut leaf */ /* clip and render leaf */ render_leaf (ms, current_surface, fine_pixel, lfcut); if (error()) return; free_leaf (lfcut); /* free temporary memory */ } /* free temporary memory */ frearc (al); return; }