⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monotone.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "basic.h"#include <math.h>#define CROSS_SINE(v0, v1) ((v0).x * (v1).y - (v1).x * (v0).y)#define LENGTH(v0) (sqrt((v0).x * (v0).x + (v0).y * (v0).y))static monchain_t mchain[TRSIZE]; /* Table to hold all the monotone */				  /* polygons . Each monotone polygon */				  /* is a circularly linked list */static vertexchain_t vert[SEGSIZE]; /* chain init. information. This */				    /* is used to decide which */				    /* monotone polygon to split if */				    /* there are several other */				    /* polygons touching at the same */				    /* vertex  */static int mon[SEGSIZE];	/* contains position of any vertex in */				/* the monotone chain for the polygon */static int visited[TRSIZE];static int chain_idx, op_idx, mon_idx;/* Function returns TRUE if the trapezoid lies inside the polygon */static int inside_polygon(t)     trap_t *t;{  int rseg = t->rseg;  if (t->state == ST_INVALID)    return 0;  if ((t->lseg <= 0) || (t->rseg <= 0))    return 0;    if (((t->u0 <= 0) && (t->u1 <= 0)) ||       ((t->d0 <= 0) && (t->d1 <= 0))) /* triangle */    return (_greater_than(&seg[rseg].v1, &seg[rseg].v0));    return 0;}/* return a new mon structure from the table */static int newmon(){  return ++mon_idx;}/* return a new chain element from the table */static int new_chain_element(){  return ++chain_idx;}static double get_angle(vp0, vpnext, vp1)     point_t *vp0;     point_t *vpnext;     point_t *vp1;{  point_t v0, v1;    v0.x = vpnext->x - vp0->x;  v0.y = vpnext->y - vp0->y;  v1.x = vp1->x - vp0->x;  v1.y = vp1->y - vp0->y;  if (CROSS_SINE(v0, v1) >= 0)	/* sine is positive */    return DOT(v0, v1)/LENGTH(v0)/LENGTH(v1);  else    return (-1.0 * DOT(v0, v1)/LENGTH(v0)/LENGTH(v1) - 2);}/* (v0, v1) is the new diagonal to be added to the polygon. Find which *//* chain to use and return the positions of v0 and v1 in p and q */ static int get_vertex_positions(v0, v1, ip, iq)     int v0;     int v1;     int *ip;     int *iq;{  vertexchain_t *vp0, *vp1;  register int i;  double angle, temp;  int tp, tq;  vp0 = &vert[v0];  vp1 = &vert[v1];    /* p is identified as follows. Scan from (v0, v1) rightwards till */  /* you hit the first segment starting from v0. That chain is the */  /* chain of our interest */    angle = -4.0;  for (i = 0; i < 4; i++)    {      if (vp0->vnext[i] <= 0)	continue;      if ((temp = get_angle(&vp0->pt, &(vert[vp0->vnext[i]].pt), 			    &vp1->pt)) > angle)	{	  angle = temp;	  tp = i;	}    }  *ip = tp;  /* Do similar actions for q */  angle = -4.0;  for (i = 0; i < 4; i++)    {      if (vp1->vnext[i] <= 0)	continue;            if ((temp = get_angle(&vp1->pt, &(vert[vp1->vnext[i]].pt), 			    &vp0->pt)) > angle)	{	  angle = temp;	  tq = i;	}    }  *iq = tq;  return 0;}  /* v0 and v1 are specified in anti-clockwise order with respect to  * the current monotone polygon mcur. Split the current polygon into  * two polygons using the diagonal (v0, v1)  */static int make_new_monotone_poly(mcur, v0, v1)     int mcur;     int v0;     int v1;{  int p, q, ip, iq;  int mnew = newmon();  int i, j, nf0, nf1;  vertexchain_t *vp0, *vp1;    vp0 = &vert[v0];  vp1 = &vert[v1];  get_vertex_positions(v0, v1, &ip, &iq);  p = vp0->vpos[ip];  q = vp1->vpos[iq];  /* At this stage, we have got the positions of v0 and v1 in the */  /* desired chain. Now modify the linked lists */  i = new_chain_element();	/* for the new list */  j = new_chain_element();  mchain[i].vnum = v0;  mchain[j].vnum = v1;  mchain[i].next = mchain[p].next;  mchain[mchain[p].next].prev = i;  mchain[i].prev = j;  mchain[j].next = i;  mchain[j].prev = mchain[q].prev;  mchain[mchain[q].prev].next = j;  mchain[p].next = q;  mchain[q].prev = p;  nf0 = vp0->nextfree;  nf1 = vp1->nextfree;  vp0->vnext[ip] = v1;  vp0->vpos[nf0] = i;  vp0->vnext[nf0] = mchain[mchain[i].next].vnum;  vp1->vpos[nf1] = j;  vp1->vnext[nf1] = v0;  vp0->nextfree++;  vp1->nextfree++;#ifdef DEBUG  fprintf(stderr, "make_poly: mcur = %d, (v0, v1) = (%d, %d)\n", 	  mcur, v0, v1);  fprintf(stderr, "next posns = (p, q) = (%d, %d)\n", p, q);#endif  mon[mcur] = p;  mon[mnew] = i;  return mnew;}/* Main routine to get monotone polygons from the trapezoidation of  * the polygon. */int monotonate_trapezoids(n)     int n;{  register int i;  int tr_start;  memset((void *)vert, 0, sizeof(vert));  memset((void *)visited, 0, sizeof(visited));  memset((void *)mchain, 0, sizeof(mchain));  memset((void *)mon, 0, sizeof(mon));    /* First locate a trapezoid which lies inside the polygon */  /* and which is triangular */  for (i = 0; i < TRSIZE; i++)    if (inside_polygon(&tr[i]))      break;  tr_start = i;    /* Initialise the mon data-structure and start spanning all the */  /* trapezoids within the polygon */  for (i = 1; i <= n; i++)    {      mchain[i].prev = i - 1;      mchain[i].next = i + 1;      mchain[i].vnum = i;      vert[i].pt = seg[i].v0;      vert[i].vnext[0] = i + 1;	/* next vertex */      vert[i].vpos[0] = i;	/* locn. of next vertex */      vert[i].nextfree = 1;    }  mchain[1].prev = n;  mchain[n].next = 1;  vert[n].vnext[0] = 1;  vert[n].vpos[0] = n;  chain_idx = n;  mon_idx = 0;  mon[0] = 1;			/* position of any vertex in the first */				/* chain  */    /* traverse the polygon */  if (tr[tr_start].u0 > 0)    traverse_polygon(0, tr_start, tr[tr_start].u0, TR_FROM_UP);  else if (tr[tr_start].d0 > 0)    traverse_polygon(0, tr_start, tr[tr_start].d0, TR_FROM_DN);    /* return the number of polygons created */  return newmon();}/* recursively visit all the trapezoids */int traverse_polygon(mcur, trnum, from, dir)     int mcur;     int trnum;     int from;     int dir;{  trap_t *t = &tr[trnum];  int mnew;  int v0, v1;  int retval;  int do_switch = FALSE;  if ((trnum <= 0) || visited[trnum])    return 0;  visited[trnum] = TRUE;    /* We have much more information available here. */  /* rseg: goes upwards   */  /* lseg: goes downwards */  /* Initially assume that dir = TR_FROM_DN (from the left) */  /* Switch v0 and v1 if necessary afterwards */  /* special cases for triangles with cusps at the opposite ends. */  /* take care of this first */  if ((t->u0 <= 0) && (t->u1 <= 0))    {      if ((t->d0 > 0) && (t->d1 > 0)) /* downward opening triangle */	{	  v0 = tr[t->d1].lseg;	  v1 = t->lseg;	  if (from == t->d1)	    {	      do_switch = TRUE;	      mnew = make_new_monotone_poly(mcur, v1, v0);	      traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);	      traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);	    	    }	  else	    {	      mnew = make_new_monotone_poly(mcur, v0, v1);	      traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);	      traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);	    }	}      else	{	  retval = SP_NOSPLIT;	/* Just traverse all neighbours */	  traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);	  traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);	  traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);	  traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);      }    }    else if ((t->d0 <= 0) && (t->d1 <= 0))    {      if ((t->u0 > 0) && (t->u1 > 0)) /* upward opening triangle */	{	  v0 = t->rseg;	  v1 = tr[t->u0].rseg;	  if (from == t->u1)	    {	      do_switch = TRUE;	      mnew = make_new_monotone_poly(mcur, v1, v0);	      traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);	      traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);	    	    }	  else	    {	      mnew = make_new_monotone_poly(mcur, v0, v1);	      traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);	      traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);	    }	}      else	{	  retval = SP_NOSPLIT;	/* Just traverse all neighbours */	  traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);	  traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);	  traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);	  traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);	}    }    else if ((t->u0 > 0) && (t->u1 > 0))     {      if ((t->d0 > 0) && (t->d1 > 0)) /* downward + upward cusps */	{	  v0 = tr[t->d1].lseg;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -