/** * This is region handler for a rectangular region. This can also work * for circular regions by making a 0 width/height feature. * @author Pinkfish * @started Mon Apr 1 12:15:24 PST 2002 */ inherit "/std/room/inherit/terrain_map/geometry"; class feature_pos { int xstart; int ystart; int width; int height; } private mixed *_feature_direcs = ({ ({ "southwest", "south", "southeast" }), ({ "west", "Oops", "east" }), ({ "northwest", "north", "northeast" }) }); private class feature_pos* _positions = ({ }); /** * This method sets the position of the feature. * @param x the x coordinate of the feature * @param y the y coordinate of the feature * @param width the width of the feature * @param height the height of the feature */ void add_feature_position(int x, int y, int width, int height) { class feature_pos pos; pos = new(class feature_pos, xstart : x, ystart : y, width : width, height : height); _positions += ({ pos }); } /** * This is the function that finds the distance and direction to the * current region. * @param x the x-coordinate * @param y the y-coordinate * @param z the z-coordinate * @return ({ direction, distance }) */ mapping query_feature_desc_from(int x, int y, int z) { int h; int v; int width; int height; float distance; float min_distance; string direc; class feature_pos pos; float xmod; float ymod; int xd; int yd; foreach (pos in _positions) { h = pos->xstart; v = pos->ystart; width = pos->width; height = pos->height; if (x >= (h + width)) { h = h + width - 1; } else if (x >= h) { h = x; } if (y >= (v + height)) { v = v + height - 1; } else if (y >= v) { v = y; } distance = sqrt(pow(x - h, 2) + pow(y - v, 2)); if (distance > 0.0000001 && (distance < min_distance || !min_distance)) { xmod = ((h - x) < 0) ? -0.5 : 0.5; ymod = ((v - y) < 0) ? -0.5 : 0.5; xd = to_int(xmod + to_float(h - x) / distance) + 1; yd = to_int(ymod + to_float(v - y) / distance) + 1; direc = _feature_direcs[yd][xd]; min_distance = distance; } } if (!direc) { return ([ ]); } return ([ direc : to_int(min_distance) ]); } /** @ignore yes */ void dest_me() { destruct(this_object()); } /** * Find out if this rectangle is inside the region, given the specified range * at which it can be seen. This will work by adding the ranges onto the * lines and checking for distance from the points of the polygon to the line * bordering the region and also checking for intersection with the bordering * line. It also checks to see if all of the points are inside the region. * @param x1 the top x * @param y1 the top y * @param x2 the bottom x * @param y2 the bottom y */ int is_inside_region(int x1, int y1, int x2, int y2, int range) { class feature_pos position; int height; int width; foreach (position in _positions) { height = position->height; width = position->width; if (position->xstart >= x1 && position->xstart <= x2 && position->ystart >= y1 && position->ystart <= y2) { return 1; } if (position->xstart >= x1 && position->xstart <= x2 && position->ystart + height >= y1 && position->ystart + height <= y2) { return 1; } if (position->xstart +width >= x1 && position->xstart +width <= x2 && position->ystart + height >= y1 && position->ystart + height <= y2) { return 1; } if (position->xstart +width >= x1 && position->xstart +width <= x2 && position->ystart >= y1 && position->ystart <= y2) { return 1; } /* if (distance_between_two_line_segments(x1, y1, x1, y2, position->xstart + width, position->ystart, position->xstart +width, position->ystart + height) < range) { return 1; } if (distance_between_two_line_segments(x1, y1, x2, y1, position->xstart, position->ystart + height, position->xstart +width, position->ystart + height) < range) { return 1; } if (distance_between_two_line_segments(x2, y1, x2, y2, position->xstart, position->ystart, position->xstart, position->ystart + height) < range) { return 1; } if (distance_between_two_line_segments(x1, y2, x2, y2, position->xstart, position->ystart, position->xstart +width, position->ystart) < range) { return 1; } */ } return 0; }