Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
// 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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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]);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}