Exemplo n.º 1
0
static void visit_coords(map_t *m,int startX, int startY, int x, int y, int dx, int dy,
                         TCOD_list_t active_views, bool light_walls) {
    // top left
    int tlx=x, tly=y+STEP_SIZE;
    // bottom right
    int brx=x+STEP_SIZE, bry=y;
    view_t *view=NULL;
    while (current_view != (view_t **)TCOD_list_end(active_views)) {
        view=*current_view;
        if ( ! BELOW_OR_COLINEAR(&view->steep_line,brx,bry) ) {
            break;
        }
        current_view++;
    }
    if ( current_view == (view_t **)TCOD_list_end(active_views) || ABOVE_OR_COLINEAR(&view->shallow_line,tlx,tly)) {
        // no more active view
        return;
    }
    if ( !is_blocked(m,view,startX,startY,x,y,dx,dy,light_walls) ) return;
    if (  ABOVE(&view->shallow_line,brx,bry)
            && BELOW(&view->steep_line,tlx,tly)) {
        // view blocked
        // slow !
        TCOD_list_remove_iterator(active_views,(void **)current_view);
    } else if ( ABOVE(&view->shallow_line,brx,bry)) {
        // shallow bump
        add_shallow_bump(tlx,tly,view);
        check_view(active_views,current_view);
    } else if (BELOW(&view->steep_line,tlx,tly)) {
        // steep bump
        add_steep_bump(brx,bry,view);
        check_view(active_views,current_view);
    } else {
        // view splitted
        int offset=startX+x*dx/STEP_SIZE + (startY+y*dy/STEP_SIZE)*m->width;
        view_t *shallower_view= & views[offset];
        int view_index=current_view - (view_t **)TCOD_list_begin(active_views);
        view_t **shallower_view_it;
        view_t **steeper_view_it;
        *shallower_view=**current_view;
        // slow !
        shallower_view_it = (view_t **)TCOD_list_insert_before(active_views,shallower_view,view_index);
        steeper_view_it=shallower_view_it+1;
        current_view=shallower_view_it;
        add_steep_bump(brx,bry,shallower_view);
        if (!check_view(active_views,shallower_view_it)) steeper_view_it--;
        add_shallow_bump(tlx,tly,*steeper_view_it);
        check_view(active_views,steeper_view_it);
        if ( view_index > TCOD_list_size(active_views)) current_view=(view_t **)TCOD_list_end(active_views);
    }
}
Exemplo n.º 2
0
static bool is_blocked(map_t *map, view_t *view, int startX, int startY, int x, int y, int dx, int dy, bool light_walls) {
    int posx=x*dx/STEP_SIZE+startX;
    int posy=y*dy/STEP_SIZE+startY;
    int offset=posx + (posy)*map->width;
    bool blocked=!map->cells[offset].transparent;
    int tlx,tly,brx,bry;
    if ( blocked ) {
        tlx=x;
        tly=y+STEP_SIZE;
        brx=x+STEP_SIZE;
        bry=y;
    } else {
        tlx=x+offset;
        tly=y+limit;
        brx=x+limit;
        bry=y+offset;
    }
    if ( light_walls ||
            (
                ABOVE(&view->steep_line,brx,bry)
                && BELOW(&view->shallow_line,tlx,tly)
            )
//		! blocked
       ) {
        map->cells[offset].fov=1;
    }
    return blocked;
}
Exemplo n.º 3
0
static void add_shallow_bump(int x, int y, view_t *view) {
    viewbump_t *shallow, *curbump;
    view->shallow_line.xf=x;
    view->shallow_line.yf=y;
    shallow= &bumps[bumpidx++];
    shallow->x=x;
    shallow->y=y;
    shallow->parent=view->shallow_bump;
    view->shallow_bump=shallow;
    curbump=view->steep_bump;
    while ( curbump ) {
        if ( ABOVE(&view->shallow_line,curbump->x,curbump->y)) {
            view->shallow_line.xi=curbump->x;
            view->shallow_line.yi=curbump->y;
        }
        curbump=curbump->parent;
    }
}
Exemplo n.º 4
0
Datum geography_gist_picksplit(PG_FUNCTION_ARGS)
{

	GistEntryVector	*entryvec = (GistEntryVector*) PG_GETARG_POINTER(0);

	GIST_SPLITVEC *v = (GIST_SPLITVEC*) PG_GETARG_POINTER(1);
	OffsetNumber i;
	/* One union box for each half of the space. */
	GIDX **box_union;
	/* One offset number list for each half of the space. */
	OffsetNumber **list;
	/* One position index for each half of the space. */
	int *pos;
	GIDX *box_pageunion;
	GIDX *box_current;
	int direction = -1;
	bool all_entries_equal = true;
	OffsetNumber max_offset;
	int nbytes, ndims_pageunion, d;
	int posmax = -1;

	POSTGIS_DEBUG(4, "[GIST] 'picksplit' function called");

	/*
	** First calculate the bounding box and maximum number of dimensions in this page.
	*/

	max_offset = entryvec->n - 1;
	box_current = (GIDX*) DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
	box_pageunion = gidx_copy(box_current);

	/* Calculate the containing box (box_pageunion) for the whole page we are going to split. */
	for ( i = OffsetNumberNext(FirstOffsetNumber); i <= max_offset; i = OffsetNumberNext(i) )
	{
		box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

		if ( all_entries_equal == true && ! gidx_equals (box_pageunion, box_current) )
			all_entries_equal = false;

		gidx_merge( &box_pageunion, box_current );
	}

	POSTGIS_DEBUGF(3, "[GIST] box_pageunion: %s", gidx_to_string(box_pageunion));

	/* Every box in the page is the same! So, we split and just put half the boxes in each child. */
	if ( all_entries_equal )
	{
		POSTGIS_DEBUG(4, "[GIST] picksplit finds all entries equal!");
		geography_gist_picksplit_fallback(entryvec, v);
		PG_RETURN_POINTER(v);
	}

	/* Initialize memory structures. */
	nbytes = (max_offset + 2) * sizeof(OffsetNumber);
	ndims_pageunion = GIDX_NDIMS(box_pageunion);
	POSTGIS_DEBUGF(4, "[GIST] ndims_pageunion == %d", ndims_pageunion);
	pos = palloc(2*ndims_pageunion * sizeof(int));
	list = palloc(2*ndims_pageunion * sizeof(OffsetNumber*));
	box_union = palloc(2*ndims_pageunion * sizeof(GIDX*));
	for ( d = 0; d < ndims_pageunion; d++ )
	{
		list[BELOW(d)] = (OffsetNumber*) palloc(nbytes);
		list[ABOVE(d)] = (OffsetNumber*) palloc(nbytes);
		box_union[BELOW(d)] = gidx_new(ndims_pageunion);
		box_union[ABOVE(d)] = gidx_new(ndims_pageunion);
		pos[BELOW(d)] = 0;
		pos[ABOVE(d)] = 0;
	}

	/*
	** Assign each entry in the node to the volume partitions it belongs to,
	** such as "above the x/y plane, left of the y/z plane, below the x/z plane".
	** Each entry thereby ends up in three of the six partitions.
	*/
	POSTGIS_DEBUG(4, "[GIST] 'picksplit' calculating best split axis");
	for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
	{
		box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

		for ( d = 0; d < ndims_pageunion; d++ )
		{
			if ( GIDX_GET_MIN(box_current,d)-GIDX_GET_MIN(box_pageunion,d) < GIDX_GET_MAX(box_pageunion,d)-GIDX_GET_MAX(box_current,d) )
			{
				geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
			}
			else
			{
				geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
			}

		}

	}

	/*
	** "Bad disposition", too many entries fell into one octant of the space, so no matter which
	** plane we choose to split on, we're going to end up with a mostly full node. Where the
	** data is pretty homogeneous (lots of duplicates) entries that are equidistant from the
	** sides of the page union box can occasionally all end up in one place, leading
	** to this condition.
	*/
	if ( geography_gist_picksplit_badratios(pos,ndims_pageunion) == TRUE )
	{
		/*
		** Instead we split on center points and see if we do better.
		** First calculate the average center point for each axis.
		*/
		double *avgCenter = palloc(ndims_pageunion * sizeof(double));

		for ( d = 0; d < ndims_pageunion; d++ )
		{
			avgCenter[d] = 0.0;
		}

		POSTGIS_DEBUG(4, "[GIST] picksplit can't find good split axis, trying center point method");

		for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
		{
			box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);
			for ( d = 0; d < ndims_pageunion; d++ )
			{
				avgCenter[d] += (GIDX_GET_MAX(box_current,d) + GIDX_GET_MIN(box_current,d)) / 2.0;
			}
		}
		for ( d = 0; d < ndims_pageunion; d++ )
		{
			avgCenter[d] /= max_offset;
			pos[BELOW(d)] = pos[ABOVE(d)] = 0; /* Re-initialize our counters. */
			POSTGIS_DEBUGF(4, "[GIST] picksplit average center point[%d] = %.12g", d, avgCenter[d]);
		}

		/* For each of our entries... */
		for ( i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i) )
		{
			double center;
			box_current = (GIDX*) DatumGetPointer(entryvec->vector[i].key);

			for ( d = 0; d < ndims_pageunion; d++ )
			{
				center = (GIDX_GET_MIN(box_current,d)+GIDX_GET_MAX(box_current,d))/2.0;
				if ( center < avgCenter[d] )
					geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
				else if ( FPeq(center, avgCenter[d]) )
					if ( pos[BELOW(d)] > pos[ABOVE(d)] )
						geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
					else
						geography_gist_picksplit_addlist(list[BELOW(d)], &(box_union[BELOW(d)]), box_current, &(pos[BELOW(d)]), i);
				else
					geography_gist_picksplit_addlist(list[ABOVE(d)], &(box_union[ABOVE(d)]), box_current, &(pos[ABOVE(d)]), i);
			}

		}

		/* Do we have a good disposition now? If not, screw it, just cut the node in half. */
		if ( geography_gist_picksplit_badratios(pos,ndims_pageunion) == TRUE )
		{
			POSTGIS_DEBUG(4, "[GIST] picksplit still cannot find a good split! just cutting the node in half");
			geography_gist_picksplit_fallback(entryvec, v);
			PG_RETURN_POINTER(v);
		}

	}

	/*
	** Now, what splitting plane gives us the most even ratio of
	** entries in our child pages? Since each split region has been apportioned entries
	** against the same number of total entries, the axis that has the smallest maximum
	** number of entries in its regions is the most evenly distributed.
	** TODO: what if the distributions are equal in two or more axes?
	*/
	for ( d = 0; d < ndims_pageunion; d++ )
	{
		int posd = Max(pos[ABOVE(d)],pos[BELOW(d)]);
		if ( posd > posmax )
		{
			direction = d;
			posmax = posd;
		}
	}
	if ( direction == -1 || posmax == -1 )
	{
		/* ERROR OUT HERE */
		elog(ERROR, "Error in building split, unable to determine split direction.");
	}

	POSTGIS_DEBUGF(3, "[GIST] 'picksplit' splitting on axis %d", direction);

	geography_gist_picksplit_constructsplit(v, list[BELOW(direction)],
	                                        pos[BELOW(direction)],
	                                        &(box_union[BELOW(direction)]),
	                                        list[ABOVE(direction)],
	                                        pos[ABOVE(direction)],
	                                        &(box_union[ABOVE(direction)]) );

	POSTGIS_DEBUGF(4, "[GIST] spl_ldatum: %s", gidx_to_string((GIDX*)v->spl_ldatum));
	POSTGIS_DEBUGF(4, "[GIST] spl_rdatum: %s", gidx_to_string((GIDX*)v->spl_rdatum));

	POSTGIS_DEBUGF(4, "[GIST] axis %d: parent range (%.12g, %.12g) left range (%.12g, %.12g), right range (%.12g, %.12g)",
	               direction,
	               GIDX_GET_MIN(box_pageunion, direction), GIDX_GET_MAX(box_pageunion, direction),
	               GIDX_GET_MIN((GIDX*)v->spl_ldatum, direction), GIDX_GET_MAX((GIDX*)v->spl_ldatum, direction),
	               GIDX_GET_MIN((GIDX*)v->spl_rdatum, direction), GIDX_GET_MAX((GIDX*)v->spl_rdatum, direction) );

	PG_RETURN_POINTER(v);

}
Exemplo n.º 5
0
/*
 +-----------------------------------------------------------+
 * @desc	FIXME
 +-----------------------------------------------------------+
 */
static void
visit_coords(RLFL_map_t *m,int startX, int startY, int x, int y, int dx, int dy,
			 RLFL_list_t active_views, bool light_walls)
{
	// top left
	int tlx = x, tly = (y+1);

	// bottom right
	int brx = (x+1), bry = y;

	int realX = (x*dx), realY = (y*dy);
	int offset;
	view_t *view = NULL;

	while (current_view != (view_t **)RLFL_list_end(active_views))
	{
		view = *current_view;
		if ( !BELOW_OR_COLINEAR(&view->steep_line, brx, bry) ) {
			break;
		}
		current_view++;
	}
	if(current_view == (view_t **)RLFL_list_end(active_views)
			|| ABOVE_OR_COLINEAR(&view->shallow_line, tlx, tly)) {
		return;
	}

	offset = (startX + realX + ((startY+realY) * m->width));
	if (light_walls || RLFL_has_flag(m->mnum, startX+realX, startY+realY, CELL_OPEN)) {
		RLFL_set_flag(m->mnum, startX+realX, startY+realY, CELL_FOV);
	}

	if (RLFL_has_flag(m->mnum, startX+realX, startY+realY, CELL_OPEN))
		return;

	if ( ABOVE(&view->shallow_line, brx, bry)
		&& BELOW(&view->steep_line, tlx, tly)) {
		// slow !
		RLFL_list_remove_iterator(active_views, (void **)current_view);
	}
	else if( ABOVE(&view->shallow_line, brx, bry))
	{
		add_shallow_bump(tlx, tly, view);
		check_view(active_views, current_view);
	}
	else if(BELOW(&view->steep_line, tlx, tly))
	{
		add_steep_bump(brx,bry,view);
		check_view(active_views,current_view);
	}
	else
	{
		view_t *shallower_view = &views[offset];
		int view_index = (current_view - (view_t **)RLFL_list_begin(active_views));
		view_t **shallower_view_it;
		view_t **steeper_view_it;
		*shallower_view = **current_view;
		// slow !
		shallower_view_it = (view_t **)RLFL_list_insert(active_views, shallower_view, view_index);
		steeper_view_it = shallower_view_it+1;
		current_view = shallower_view_it;
		add_steep_bump(brx, bry, shallower_view);
		if (!check_view(active_views,shallower_view_it)) {
			steeper_view_it--;
		}
		add_shallow_bump(tlx, tly, *steeper_view_it);
		check_view(active_views, steeper_view_it);
		if ( view_index > RLFL_list_size(active_views)) {
			current_view = (view_t **)RLFL_list_end(active_views);
		}
	}
}