short int legalizeEdge(Point * p, Triangle * T){
	short int ut, ua;
	Triangle * A;
	Point * center;

	for(ut=0; ut<3 && T->points[ut] != p; ++ut);
	if(ut==3) return -1;

	ADJACENT(T, T->points[NEXT(ut)], T->points[PREV(ut)], A);

	if(!A) return 1;

	for(ua=0; ua<3 && IN_TRIA(T, A->points[ua]); ua++);

	center = calcCenter(T);
	if(!center) return -2;

	if(DISQR(A->points[ua], center) >= DISQR(center, P0)){
		free(center);
		return 1;
	}
	free(center);

	if((ua=swap(T, A))<0) return -3;

	if((ua=legalizeEdge(p, T))<0) return -ua;
	if((ua=legalizeEdge(p, A))<0) return -ua;

	return 1;
}
示例#2
0
int analyze_terrain(const unsigned char *types,
        unsigned int size,
        unsigned int x,
        unsigned int y,
        unsigned char *type,
        unsigned char *adjacent_same,
        unsigned char *adjacent_sand)
{
        /**
         * Macros for one dimensional coordinates for all adjacent tiles. 
         * Start with x coordinate, then add as many "rows" as the value y. 
        **/
        #define nw_coord  ((x - 1) + (size * (y - 1)))
        #define n_coord   (x + (size * (y - 1)))
        #define ne_coord  ((x + 1) + (size * (y - 1)))
        #define w_coord   ((x - 1) + (size * y))
        #define e_coord   ((x + 1) + (size * y))
        #define sw_coord  ((x - 1) + (size * (y + 1)))
        #define s_coord   ((x + (size * (y + 1))))
        #define se_coord  ((x + 1) + (size * (y + 1)))

        unsigned int c_type;
        unsigned int nw_type;
        unsigned int n_type;
        unsigned int ne_type;
        unsigned int w_type;
        unsigned int e_type;
        unsigned int sw_type;
        unsigned int s_type;
        unsigned int se_type;

        /* First only retrieve center tile's type */
        c_type  = types[x + (size * y)];
        *type   = c_type;

        /* NOTE: All info needed for SAND retrieved at this point */

        /** 
         * Get terrain types for all adjacent tiles, using their
         * one dimensional coordinates. First perform appropriate ternary
         * boundary checks for each case. Default to center tile type. 
        **/
        nw_type = (y > 0 && x > 0)?                     types[nw_coord] : c_type;
        n_type  = (y > 0)?                              types[n_coord]  : c_type;
        ne_type = (x < size - 1 && y > 0)?              types[ne_coord] : c_type;
        w_type  = (x > 0)?                              types[w_coord]  : c_type;
        e_type  = (x < size - 1)?                       types[e_coord]  : c_type;
        sw_type = (x > 0 && y < size - 1)?              types[sw_coord] : c_type;
        s_type  = (y < size - 1)?                       types[s_coord]  : c_type;
        se_type = (y < size - 1 && x < size - 1)?       types[se_coord] : c_type;

        /* NOTE: All info needed for WATER retrieved at this point */

        *adjacent_sand = ADJACENT(T_SAND)|ADJACENT(T_WATER)|ADJACENT(T_ROCK);

        /* NOTE: All info needed for DIRT retrieved at this point */

        *adjacent_same = ADJACENT(c_type);

        /* DEBUG_XY(79, 95); */

        return 0;
}
示例#3
0
static void delete_finish(ptst_t *ptst, node_t *x)
{
    qnode_t g_qn, p_qn, w_qn, x_qn;
    node_t *g, *p, *w;
    int done = 0;

    do {
        if ( IS_GARBAGE(x) ) return;

        p = x->p;
        g = p->p;

        mcs_lock(&g->lock, &g_qn);
        if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) || IS_GARBAGE(g) ) 
            goto unlock_g;
        
        mcs_lock(&p->lock, &p_qn);
        /* Removing unbalanced red nodes is okay. */
        if ( !ADJACENT(p, x) || (IS_UNBALANCED(p->v) && IS_BLACK(p->v)) )
            goto unlock_pg;

        mcs_lock(&x->lock, &x_qn);
        if ( IS_UNBALANCED(x->v) ) goto unlock_xpg;        
        if ( GET_VALUE(x->v) != NULL )
        {
            done = 1;
            goto unlock_xpg;
        }

        if ( p->l == x ) w = p->r; else w = p->l;
        assert(w != x);
        mcs_lock(&w->lock, &w_qn);
        if ( IS_UNBALANCED(w->v) ) goto unlock_wxpg;

        if ( g->l == p ) g->l = w; else g->r = w; 
        MK_GARBAGE(p); gc_free(ptst, p, gc_id);
        MK_GARBAGE(x); gc_free(ptst, x, gc_id);
        w->p = g;
        if ( IS_BLACK(p->v) && IS_BLACK(w->v) )
        {
            w->v = MK_UNBALANCED(w->v);
            done = 2;
        }
        else
        {
            w->v = MK_BLACK(w->v);
            done = 1;
        }

    unlock_wxpg:
        mcs_unlock(&w->lock, &w_qn);
    unlock_xpg:
        mcs_unlock(&x->lock, &x_qn);
    unlock_pg:
        mcs_unlock(&p->lock, &p_qn);
    unlock_g:
        mcs_unlock(&g->lock, &g_qn);
    }
    while ( !done );

    if ( done == 2 ) fix_unbalance_down(ptst, w);
}
示例#4
0
static void fix_unbalance_down(ptst_t *ptst, node_t *x)
{
    /* WN == W_NEAR, WF == W_FAR (W_FAR is further, in key space, from X). */
    qnode_t x_qn, w_qn, p_qn, g_qn, wn_qn, wf_qn;
    node_t *w, *p, *g, *wn, *wf;
    int done = 0;

    do {
        if ( !IS_UNBALANCED(x->v) || IS_GARBAGE(x) ) return;

        p = x->p;
        g = p->p;

        mcs_lock(&g->lock, &g_qn);
        if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) || IS_GARBAGE(g) )
            goto unlock_g;

        mcs_lock(&p->lock, &p_qn);
        if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pg;

        mcs_lock(&x->lock, &x_qn);

        if ( !IS_BLACK(x->v) || !IS_UNBALANCED(x->v) )
        {
            done = 1;
            goto unlock_xpg;
        }

        if ( IS_ROOT(x) )
        {
            x->v = MK_BALANCED(x->v);
            done = 1;
            goto unlock_xpg;
        }

        w = (x == p->l) ? p->r : p->l;
        mcs_lock(&w->lock, &w_qn);
        if ( IS_UNBALANCED(w->v) )
        {
            if ( IS_BLACK(w->v) )
            {
                /* Funky relaxed rules to the rescue. */
                x->v = MK_BALANCED(x->v);
                w->v = MK_BALANCED(w->v);
                if ( IS_BLACK(p->v) )
                {
                    p->v = MK_UNBALANCED(p->v);
                    done = 2;
                }
                else
                {
                    p->v = MK_BLACK(p->v);
                    done = 1;
                }
            }
            goto unlock_wxpg;
        }

        assert(!IS_LEAF(w));
        
        if ( x == p->l )
        {
            wn = w->l;
            wf = w->r;
        }
        else
        {
            wn = w->r;
            wf = w->l;
        }

        mcs_lock(&wn->lock, &wn_qn);
        /* Hanke has an extra relaxed transform here. It's not needed. */
        if ( IS_UNBALANCED(wn->v) ) goto unlock_wnwxpg;

        mcs_lock(&wf->lock, &wf_qn);
        if ( IS_UNBALANCED(wf->v) ) goto unlock_wfwnwxpg;

        if ( IS_RED(w->v) )
        {
            /* Case 1. Rotate at parent. */
            assert(IS_BLACK(p->v) && IS_BLACK(wn->v) && IS_BLACK(wf->v));
            w->v = MK_BLACK(w->v);
            p->v = MK_RED(p->v);
            if ( x == p->l ) left_rotate(ptst, p); else right_rotate(ptst, p);
            goto unlock_wfwnwxpg;
        }

        if ( IS_BLACK(wn->v) && IS_BLACK(wf->v) )
        {
            if ( IS_RED(p->v) )
            {
                /* Case 2. Simple recolouring. */
                p->v = MK_BLACK(p->v);
                done = 1;
            }
            else
            {
                /* Case 5. Simple recolouring. */
                p->v = MK_UNBALANCED(p->v);
                done = 2;
            }
            w->v = MK_RED(w->v);
            x->v = MK_BALANCED(x->v);
            goto unlock_wfwnwxpg;
        }

        if ( x == p->l )
        {
            if ( IS_RED(wf->v) )
            {
                /* Case 3. Single rotation. */
                wf->v = MK_BLACK(wf->v);
                w->v = SET_COLOUR(w->v, GET_COLOUR(p->v));
                p->v = MK_BLACK(p->v);
                x->v = MK_BALANCED(x->v);
                left_rotate(ptst, p);
            }
            else
            {
                /* Case 4. Double rotation. */
                assert(IS_RED(wn->v));
                wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v));
                p->v = MK_BLACK(p->v);
                x->v = MK_BALANCED(x->v);
                right_rotate(ptst, w);
                left_rotate(ptst, p);
            }
        }
        else /* SYMMETRIC CASE: X == P->R  */
        {
            if ( IS_RED(wf->v) )
            {
                /* Case 3. Single rotation. */
                wf->v = MK_BLACK(wf->v);
                w->v = SET_COLOUR(w->v, GET_COLOUR(p->v));
                p->v = MK_BLACK(p->v);
                x->v = MK_BALANCED(x->v);
                right_rotate(ptst, p);
            }
            else
            {
                /* Case 4. Double rotation. */
                assert(IS_RED(wn->v));
                wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v));
                p->v = MK_BLACK(p->v);
                x->v = MK_BALANCED(x->v);
                left_rotate(ptst, w);
                right_rotate(ptst, p);
            }
        }

        done = 1;

    unlock_wfwnwxpg:
        mcs_unlock(&wf->lock, &wf_qn);
    unlock_wnwxpg:
        mcs_unlock(&wn->lock, &wn_qn);
    unlock_wxpg:
        mcs_unlock(&w->lock, &w_qn);
    unlock_xpg:
        mcs_unlock(&x->lock, &x_qn);
    unlock_pg:
        mcs_unlock(&p->lock, &p_qn);
    unlock_g:
        mcs_unlock(&g->lock, &g_qn);
        
        if ( done == 2 )
        {
            x = p;
            done = 0;
        }
    }
    while ( !done );
}
示例#5
0
static void fix_unbalance_up(ptst_t *ptst, node_t *x)
{
    qnode_t x_qn, g_qn, p_qn, w_qn, gg_qn;
    node_t *g, *p, *w, *gg;
    int done = 0;

    do {
        assert(IS_UNBALANCED(x->v));
        if ( IS_GARBAGE(x) ) return;

        p  = x->p;
        g  = p->p;
        gg = g->p;

        mcs_lock(&gg->lock, &gg_qn);
        if ( !ADJACENT(gg, g) || IS_UNBALANCED(gg->v) || IS_GARBAGE(gg) ) 
            goto unlock_gg;

        mcs_lock(&g->lock, &g_qn);
        if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) ) goto unlock_ggg;

        mcs_lock(&p->lock, &p_qn);
        if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pggg;

        mcs_lock(&x->lock, &x_qn);
        
        assert(IS_RED(x->v));
        assert(IS_UNBALANCED(x->v));

        if ( IS_BLACK(p->v) )
        {
            /* Case 1. Nothing to do. */
            x->v = MK_BALANCED(x->v);
            done = 1;
            goto unlock_xpggg;
        }

        if ( IS_ROOT(x) )
        {
            /* Case 2. */
            x->v = MK_BLACK(MK_BALANCED(x->v));
            done = 1;
            goto unlock_xpggg;
        }

        if ( IS_ROOT(p) )
        {
            /* Case 2. */
            p->v = MK_BLACK(p->v);
            x->v = MK_BALANCED(x->v);
            done = 1;
            goto unlock_xpggg;
        }

        if ( g->l == p ) w = g->r; else w = g->l;
        mcs_lock(&w->lock, &w_qn);

        if ( IS_RED(w->v) )
        {
            /* Case 5. */
            /* In all other cases, doesn't change colour or subtrees. */
            if ( IS_UNBALANCED(w->v) ) goto unlock_wxpggg;
            g->v = MK_UNBALANCED(MK_RED(g->v));
            p->v = MK_BLACK(p->v);
            w->v = MK_BLACK(w->v);
            x->v = MK_BALANCED(x->v);
            done = 2;
            goto unlock_wxpggg;
        }

        /* Cases 3 & 4. Both of these need the great-grandfather locked. */
        if ( p == g->l )
        {
            if ( x == p->l )
            {
                /* Case 3. Single rotation. */
                x->v = MK_BALANCED(x->v);
                p->v = MK_BLACK(p->v);
                g->v = MK_RED(g->v);
                right_rotate(ptst, g);
            }
            else
            {
                /* Case 4. Double rotation. */
                x->v = MK_BALANCED(MK_BLACK(x->v));
                g->v = MK_RED(g->v);
                left_rotate(ptst, p);
                right_rotate(ptst, g);                
            }
        }
        else /* SYMMETRIC CASE */
        {
            if ( x == p->r )
            {
                /* Case 3. Single rotation. */
                x->v = MK_BALANCED(x->v);
                p->v = MK_BLACK(p->v);
                g->v = MK_RED(g->v);
                left_rotate(ptst, g);
            }
            else
            {
                /* Case 4. Double rotation. */
                x->v = MK_BALANCED(MK_BLACK(x->v));
                g->v = MK_RED(g->v);
                right_rotate(ptst, p);
                left_rotate(ptst, g);                
            }
        }

        done = 1;

    unlock_wxpggg:
        mcs_unlock(&w->lock, &w_qn);
    unlock_xpggg:
        mcs_unlock(&x->lock, &x_qn);
    unlock_pggg:
        mcs_unlock(&p->lock, &p_qn);
    unlock_ggg:
        mcs_unlock(&g->lock, &g_qn);
    unlock_gg:
        mcs_unlock(&gg->lock, &gg_qn);
        
        if ( done == 2 )
        {
            x = g;
            done = 0;
        }
    }
    while ( !done );
}