#include #include "constant.h" #include #include #include #include #include #include "extern.h" /****************************************************************************** shape_initialize () Initialize all the shapes necessary for a given tiling method. Set all positions, connection, horizons, selection and direction charts. ******************************************************************************/ shape_initialize () { int i, j, side; cell_type *cell; double factor; shape_type *shape, *shape2; /** Create an initialize the basic shape structures **/ for (side=0; sideside_count; side++) { Board->shapes[side][0] = (shape_type *)(malloc(sizeof(shape_type))); /** Set maximum values **/ Board->shapes[side][0]->max_value = Config->max_value[side]; Board->shapes[side][0]->max_max_value = Config->max_max_value; switch (Config->tile_type) { case TILE_HEX: hex_set_dimensions (Board->shapes[side][0], Config->cell_size[side], side); shape_set_chart (Board->shapes[side][0]); Board->shape_count = 1; break; /** Octagon tiling interleaves octagons (shape index 0) and small **/ /** squares (shape index 1). **/ case TILE_OCTAGON: octagon_set_dimensions (Board->shapes[side][0], Config->cell_size[side], side); Board->shapes[side][1] = (shape_type *)(malloc(sizeof(shape_type))); Board->shapes[side][1]->max_value = Board->shapes[side][0]->max_value; Board->shapes[side][1]->max_max_value = Board->shapes[side][0]->max_max_value; square_set_dimensions (Board->shapes[side][1], Board->shapes[side][0]->helper.x+2, side, TRUE); octagon_set_square_troops (Board->shapes[side][0], Board->shapes[side][1]); shape_set_chart (Board->shapes[side][0]); shape_set_chart (Board->shapes[side][1]); Board->shape_count = 2; break; case TILE_DIAMOND: diamond_set_dimensions (Board->shapes[side][0], Config->cell_size[side], side); shape_set_chart (Board->shapes[side][0]); Board->shape_count = 1; break; /** Triangle tiling interleaves triangles with points up (shape **/ /** index 0) and triangles with points down (shape index 1). **/ case TILE_TRIANGLE: triangle_set_dimensions (Board->shapes[side][0], Config->cell_size[side], side, TRUE); Board->shapes[side][1] = (shape_type *)(malloc(sizeof(shape_type))); Board->shapes[side][1]->max_value = Board->shapes[side][0]->max_value; Board->shapes[side][1]->max_max_value = Board->shapes[side][0]->max_max_value; triangle_set_dimensions (Board->shapes[side][1], Config->cell_size[side], side, FALSE); shape_set_chart (Board->shapes[side][0]); shape_set_chart (Board->shapes[side][1]); Board->shape_count = 2; break; case TILE_SQUARE: square_set_dimensions (Board->shapes[side][0], Config->cell_size[side], side, FALSE); shape_set_chart (Board->shapes[side][0]); Board->shape_count = 1; break; } } /** Set each cell's position and shape index, dependent upon its **/ /** position in the board grid. **/ for (j=0; jboard_y_size; j++) { for (i=0; iboard_x_size; i++) { for (side=0; sideside_count; side++) { switch (Config->tile_type) { case TILE_HEX: hex_set_center (CELL2(i,j), Board->shapes[side][0], side); break; case TILE_OCTAGON: octagon_set_center (CELL2(i,j), Board->shapes[side][0], Board->shapes[side][1], side); break; case TILE_DIAMOND: diamond_set_center (CELL2(i,j), Board->shapes[side][0], side); break; case TILE_TRIANGLE: triangle_set_center (CELL2(i,j), Board->shapes[side][0], Board->shapes[side][1], side); break; case TILE_SQUARE: square_set_center (CELL2(i,j), Board->shapes[side][0], side); break; } } } } /** Initialize pointers to neighboring cells **/ switch (Config->tile_type) { case TILE_HEX: hex_set_connections (); break; case TILE_OCTAGON: octagon_set_connections (); break; case TILE_DIAMOND: diamond_set_connections (); break; case TILE_TRIANGLE: triangle_set_connections (); break; case TILE_SQUARE: square_set_connections (); break; } /** Initialize horizon arrays **/ if (Config->enable_all[OPTION_HORIZON]) { for (side=0; sideside_count; side++) { switch (Config->tile_type) { case TILE_HEX: hex_set_horizons (Board->shapes[side][0]); break; case TILE_OCTAGON: octagon_set_horizons (Board->shapes[side][0], Board->shapes[side][1]); break; case TILE_DIAMOND: diamond_set_horizons (Board->shapes[side][0]); break; case TILE_TRIANGLE: triangle_set_horizons (Board->shapes[side][0], TRUE); triangle_set_horizons (Board->shapes[side][1], FALSE); break; case TILE_SQUARE: square_set_horizons (Board->shapes[side][0]); break; } } } /** Initialize selection grid which is used to determine which cell **/ /** corresponds to an arbitrary (x,y) coordinate. **/ for (side=0; sideside_count; side++) { Config->selects[side] = (select_type *)(malloc(sizeof(select_type))); switch (Config->tile_type) { case TILE_HEX: hex_set_selects (Board->shapes[side][0], Config->selects[side], side); break; case TILE_OCTAGON: octagon_set_selects (Board->shapes[side][0], Board->shapes[side][1], Config->selects[side], side); break; case TILE_DIAMOND: diamond_set_selects (Board->shapes[side][0], Config->selects[side], side); break; case TILE_TRIANGLE: triangle_set_selects (Board->shapes[side][0], Config->selects[side], side); break; case TILE_SQUARE: square_set_selects (Board->shapes[side][0], Config->selects[side], side); break; } } /** Initialize size of playing board. Depending on the tiling method **/ /** this may involve some complexities involving even and odd board **/ /** dimenions. **/ for (side=0; sideside_count; side++) { shape = Board->shapes[side][0]; shape2 = Board->shapes[side][1]; switch (Config->tile_type) { case TILE_HEX: Board->size[side].x = (Config->board_x_size-1)*3*(shape->side/2) + 2*shape->side; Board->size[side].y = Config->board_y_size*shape->size_bound.y + shape->center_bound.y + 1; break; case TILE_OCTAGON: Board->size[side].x = (Config->board_x_size/2) * (shape->size_bound.x + shape2->size_bound.x - 2) + (Config->board_x_size%2) * (shape->size_bound.x - 1) + (1 - Config->board_x_size%2) * shape->corner_vertex.x + 1; Board->size[side].y = (Config->board_y_size/2) * (shape->size_bound.y + shape2->size_bound.y - 2) + (Config->board_y_size%2) * (shape->size_bound.y - 1) + (1 - Config->board_y_size%2) * shape->corner_vertex.x + 1; break; case TILE_DIAMOND: Board->size[side].x = (Config->board_x_size+1) * (shape->side/2) + 1; Board->size[side].y = Config->board_y_size * (shape->side-1) + shape->side/2 + 1; break; case TILE_TRIANGLE: Board->size[side].x = (Config->board_x_size/2) * (shape->size_bound.x - 1); Board->size[side].y = Config->board_y_size * shape->size_bound.y + 1; if (Config->board_x_size%2) Board->size[side].x += shape->size_bound.x - 1; else Board->size[side].x += shape->size_bound.x/2; break; case TILE_SQUARE: if (Config->enable[OPTION_GRID][side]) { Board->size[side].x = Config->board_x_size * (shape->side-1) + 1; Board->size[side].y = Config->board_y_size * (shape->side-1) + 1; } else { Board->size[side].x = Config->board_x_size * shape->side + 1; Board->size[side].y = Config->board_y_size * shape->side + 1; } break; } } } /****************************************************************************** shape_set_draw_method (shape, side, disallow_pixmap) Based on OPTION_DRAW, as specified in the command line (or by default), set up the correct drawing method for 's . If then don't allow the DRAW_PIXMAP method (which is really only valid for rectangular cells). ******************************************************************************/ shape_set_draw_method (shape, side, disallow_pixmap) shape_type *shape; int side, disallow_pixmap; { /** Send warning message if user tries invalid method **/ if (disallow_pixmap && Config->value_int[OPTION_DRAW][side] == DRAW_PIXMAP) { throw_warning ("Cannot use DRAW_PIXMAP method, using DRAW_SIMPLE", NULL); Config->value_int[OPTION_DRAW][side] = DRAW_SIMPLE; } switch (Config->value_int[OPTION_DRAW][side]) { /** 1 erase, 0 copy **/ case DRAW_SIMPLE: shape->copy_method = COPY_NONE; shape->erase_method = ERASE_DRAW; break; /** 1 erase, 1 copy **/ case DRAW_BACKING: shape->copy_method = COPY_BACK; shape->erase_method = ERASE_DRAW; break; /** 0 erase, 2 copy **/ case DRAW_PIXMAP: shape->copy_method = COPY_PIXMAP; shape->erase_method = ERASE_NONE; break; /** 1 erase, 2 copy **/ case DRAW_WINDOW: shape->copy_method = COPY_WINDOW; shape->erase_method = ERASE_DRAW; break; /** 0 erase, 4 copy **/ case DRAW_MASKING: shape->copy_method = COPY_WINDOW; shape->erase_method = ERASE_MASK; break; } } /****************************************************************************** shape_set_growth (shape) Set the array for which maps a town's growth factor into a radius, based on circle_bound>. Might want to change this to use some fraction of center_erase.x>. ******************************************************************************/ shape_set_growth (shape) shape_type *shape; { int i, min_radius, max_radius; double growth_step, growth_radius; /** Compute the minimum and maximum radii **/ min_radius = (int)(TOWN_MIN_FRACTION * shape->circle_bound); if (min_radius < TOWN_MIN_RADIUS) min_radius = TOWN_MIN_RADIUS; max_radius = (int)(TOWN_MAX_FRACTION * shape->circle_bound); /** Compute the floating point step between each growth factor **/ growth_step = ((double)(max_radius - min_radius))/ (TOWN_MAX - TOWN_MIN); growth_radius = TOWN_MIN_RADIUS; /** For each valid growth factor, set mapping **/ for (i=TOWN_MIN; i<=TOWN_MAX; i++) { shape->growth_to_radius[i] = (int)(growth_radius + 0.5); growth_radius += growth_step; } } /****************************************************************************** shape_set_troops (shape) Set the array for which maps the number of troops into a radius based on circle_bound>. Might want to change this to use some fraction of center_erase.x>. ******************************************************************************/ shape_set_troops (shape) shape_type *shape; { int i, min_size, max_size; double troop_step, troop_size, full, sqrt(); /** Compute the minimum and maximum radii **/ min_size = (int)(TROOP_MIN_FRACTION * 2 * shape->circle_bound); max_size = (int)(TROOP_MAX_FRACTION * 2 * shape->circle_bound); if (min_size < TROOP_MIN_SIZE) min_size = TROOP_MIN_SIZE; if (max_size > 2*shape->circle_bound - TROOP_MIN_BUFFER) max_size = 2*shape->circle_bound - TROOP_MIN_BUFFER; /** Compute the floating point step between each troop **/ troop_step = ((double)(max_size - min_size))/shape->max_max_value; troop_size = min_size; /** For each valid number of troops (and then some), set mapping **/ if (Config->enable_all[OPTION_AREA]) { full = ((double)(shape->max_max_value))/((shape->max_max_value+4)* (shape->max_max_value+4)); for (i=0; i<=shape->max_max_value+2; i++) shape->troop_to_size[i] = (int)(max_size * sqrt (full*i) + 0.5); } else { shape->troop_to_size[0] = 0; for (i=1; i<=shape->max_max_value+2; i++) { shape->troop_to_size[i] = (int)(troop_size + 0.5); troop_size += troop_step; } } } /****************************************************************************** shape_set_chart (shape) Compute chart>, which determines how arbitrary (x,y) coordinates map into directions. This routine assumes that directions are evenly distributed (by angle) around center_bound> and that direction 0 begins at angle_offset>. ******************************************************************************/ shape_set_chart (shape) shape_type *shape; { int x, y, i, j, k, x_limit, y_limit, is_done, int_angle, mod_angle, sector_angle; double angle, base_angle, vertex_angle, secondary_angle, diff_angle, atan2(); /** Set the angle subtended by each side **/ sector_angle = 360/shape->direction_count; /** Set the upper limits on x and y offsets **/ x_limit = shape->size_bound.x - shape->center_bound.x; y_limit = shape->size_bound.y - shape->center_bound.y; /** Step through each point in the cell bounding box. Note that y **/ /** must be negated to accound for the fact that on the screen, y **/ /** values increase going down. **/ for (y = -shape->center_bound.y, j=0; y <= y_limit; y++, j++) { for (x = -shape->center_bound.x, i=0; x <= x_limit; x++, i++) { /** Determine the angle from the center of the cell to the position **/ if (x == 0) { if (y < 0) base_angle = 90.0; else base_angle = 270.0; } else { base_angle = atan2 (((double)(-y)), ((double)(x))); base_angle = base_angle * 180.0 / 3.1415927; } /** Subtract offset to Nth vertex **/ angle = base_angle - shape->angle_offset; /** Put angle in range (0,360) **/ if (angle < 0) angle = 360.0 + angle; else if (angle >= 360.0) angle = angle - 360.0; /** Round angle into one of shape->direction_count directions **/ int_angle = (int)(angle); mod_angle = int_angle/sector_angle; /** Based on rounded angle, set vector direction **/ shape->chart[i][j][0] = mod_angle; /** Now we must set the "secondary" angles which determine the **/ /** location of corner clicks which yield dual vectors. **/ /** Set the angle to the counterclockwise vertex of the 0 side **/ angle = base_angle - shape->angle_offset - sector_angle; /** Put angle in range (0,360) **/ if (angle < 0) angle = 360.0 + angle; else if (angle >= 360.0) angle = angle - 360.0; /** Compute the range of the secondary angle **/ secondary_angle = ((double)(sector_angle))/4.0; vertex_angle = 0.0; /** Step through each vertex and see if angle falls within the **/ /** secondary angle of it. **/ for (k=0, is_done=FALSE; kdirection_count && !is_done; k++) { diff_angle = angle - vertex_angle; if (diff_angle > 180.0) diff_angle = diff_angle - 360.0; if (diff_angle < 0 && diff_angle > -secondary_angle) { shape->chart[i][j][1] = (k + 1)%(shape->direction_count); is_done = TRUE; } else if (diff_angle >= 0 && diff_angle < secondary_angle) { shape->chart[i][j][1] = k; is_done = TRUE; } vertex_angle += sector_angle; } /** If point doesn't fall within angle, set to null **/ if (!is_done) shape->chart[i][j][1] = -1; /** If position is closer than center_size> to the **/ /** center of the cell, eliminate all directions. **/ if (x*x + y*y < 2*Config->center_size*Config->center_size) { shape->chart[i][j][0] = -1; shape->chart[i][j][1] = -1; } } } /** Uncomment this stuff if you want to print out primary and/or **/ /** secondary direction charts. **/ /** printf ("\n"); for (y = -shape->center_bound.y, j=0; y <= y_limit; y++, j++) { for (x = -shape->center_bound.x, i=0; x <= x_limit; x++, i++) { if (shape->chart[i][j][0] < 0) printf ("."); else printf ("%1d", shape->chart[i][j][0]); } printf ("\n"); } printf ("\n"); printf ("\n"); for (y = -shape->center_bound.y, j=0; y <= y_limit; y++, j++) { for (x = -shape->center_bound.x, i=0; x <= x_limit; x++, i++) { if (shape->chart[i][j][1] < 0) fprintf (stderr, "."); else fprintf (stderr, "%1d", shape->chart[i][j][1]); } fprintf (stderr, "\n"); } printf ("\n"); **/ } /****************************************************************************** shape_set_arrows (shape, offset) Assuming that is a regular polygon, set the coordinates for all its direction and marching vectors. If dealing with an oblique angle, subtract from the arrow length. This is currently used for octagon diagonals, when OCTAGON_OFFSET can warp the octagon such that it is not a regular polygon. ******************************************************************************/ shape_set_arrows (shape, offset) shape_type *shape; int offset; { int i, k, angle, angle_step, angle_base, width, troop_size, max_troop_size; /** Determine the step between vector angles and the starting angle **/ angle_step = 360/shape->direction_count; angle_base = (int)(shape->angle_offset + (180.0/shape->direction_count) + 0.5); /** Have to set full-length and half-length direction vectors **/ for (i=0; i<2; i++) { /** Set length of direction vector **/ if (i == 0) width = shape->center_erase.x; else width = shape->center_erase.x/2; /** For each direction **/ angle = angle_base; for (k=0; kdirection_count; k++) { /** Set direction vector, subtracting offset when appropriate **/ if (i == 1 || angle == 0 || angle == 90 || angle == 180 || angle == 270 || angle == 360) shape_set_single_arrow (width, 0, FALSE, angle, shape->arrow_source[k][i], shape->arrow_dester[k][i]); else shape_set_single_arrow (width-offset, 0, FALSE, angle, shape->arrow_source[k][i], shape->arrow_dester[k][i]); /** Increment angle **/ angle += angle_step; if (angle >= 360) angle -= 360; } } /** Set length of direction vector **/ width = shape->center_erase.x; max_troop_size = shape->troop_to_size[shape->max_max_value+2]; for (i=0; i<=max_troop_size/2; i++) { /** Set inset vector length **/ troop_size = i; /** For each direction **/ angle = angle_base; for (k=0; kdirection_count; k++) { /** Set direction vector, subtracting offset when appropriate **/ if (i == 1 || angle == 0 || angle == 90 || angle == 180 || angle == 270 || angle == 360) shape_set_single_arrow (width, troop_size, TRUE, angle, shape->arrow_source_x[i][k], shape->arrow_dester_x[i][k]); else shape_set_single_arrow (width-offset, troop_size, TRUE, angle, shape->arrow_source_x[i][k], shape->arrow_dester_x[i][k]); /** Increment angle **/ angle += angle_step; if (angle > 360) angle -= 360; } } /** For each direction **/ angle = angle_base; for (k=0; kdirection_count; k++) { /** Set march vector, subtracting offset when appropriate **/ if (i == 1 || angle == 0 || angle == 90 || angle == 180 || angle == 270 || angle == 360) shape_set_single_march (width, angle, shape->march_source[k], shape->march_dester[k]); else shape_set_single_march (width-offset, angle, shape->march_source[k], shape->march_dester[k]); /** Increment angle **/ angle += angle_step; if (angle > 360) angle -= 360; } } /****************************************************************************** shape_set_single_arrow (length, aux_length, use_split, angle, arrow_source, arrow_dester) Set endpoint coordinates for a single direction vector of and , using inset length of if . and are the coordinate arrays to be used. ******************************************************************************/ shape_set_single_arrow (length, aux_length, use_split, angle, arrow_source, arrow_dester) int length, aux_length, use_split, angle; XPoint arrow_source[], arrow_dester[]; { int x_offset, y_offset, x_aux_offset, y_aux_offset; double rad_angle, cos(), sin(); /** Handle horizontal and vertical vectors explicitly to ensure that **/ /** rounding errors in floating point conversion don't hurt things. **/ switch (angle) { case 0: x_offset = length; y_offset = 0; x_aux_offset = aux_length; y_aux_offset = 0; break; case 90: x_offset = 0; y_offset = -length; x_aux_offset = 0; y_aux_offset = -aux_length; break; case 180: x_offset = -length; y_offset = 0; x_aux_offset = -aux_length; y_aux_offset = 0; break; case 270: x_offset = 0; y_offset = length; x_aux_offset = 0; y_aux_offset = aux_length; break; /** Handle generic angle, determining (xoffset, y_offset) endpoints **/ default: rad_angle = ((double)(angle)) * PI/180.0; x_offset = (int)(cos(rad_angle) * length); y_offset = -(int)(sin(rad_angle) * length); x_aux_offset = (int)(cos(rad_angle) * aux_length); y_aux_offset = -(int)(sin(rad_angle) * aux_length); break; } /** If just set middle vector and inset and exit **/ if (use_split) { arrow_source[0].x = 0; arrow_source[0].y = 0; arrow_dester[0].x = x_aux_offset; arrow_dester[0].y = y_aux_offset; arrow_source[1].x = x_aux_offset; arrow_source[1].y = y_aux_offset; arrow_dester[1].x = x_offset; arrow_dester[1].y = y_offset; return; } /** Set middle vector **/ arrow_source[1].x = 0; arrow_source[1].y = 0; arrow_dester[1].x = x_offset; arrow_dester[1].y = y_offset; /** Set the flanking vectors, handling special cases explicitly **/ /** If vertical vector **/ if (x_offset == 0) { arrow_source[0].x = -1; arrow_source[0].y = 0; arrow_dester[0].x = -1; arrow_dester[0].y = y_offset; arrow_source[2].x = 1; arrow_source[2].y = 0; arrow_dester[2].x = 1; arrow_dester[2].y = y_offset; } else if (y_offset == 0) { /** Else if horizontal vector **/ arrow_source[0].x = 0; arrow_source[0].y = -1; arrow_dester[0].x = x_offset; arrow_dester[0].y = -1; arrow_source[2].x = 0; arrow_source[2].y = 1; arrow_dester[2].x = x_offset; arrow_dester[2].y = 1; } else if (angle == 45 || angle == 135 || angle == 225 || angle == 315) { /** Else if diagonal vector **/ arrow_source[0].x = 0; arrow_source[0].y = (y_offset < 0) ? -1 : 1; arrow_dester[0].x = x_offset + ((x_offset < 0) ? 1 : -1); arrow_dester[0].y = y_offset; arrow_source[2].x = (x_offset < 0) ? -1 : 1; arrow_source[2].y = 0; arrow_dester[2].x = x_offset; arrow_dester[2].y = y_offset + ((y_offset < 0) ? 1 : -1); } else { /** Else generic vector **/ arrow_source[0].x = (x_offset < 0) ? 1 : -1; arrow_source[0].y = 0; arrow_dester[0].x = x_offset + ((x_offset < 0) ? 1 : -1); arrow_dester[0].y = y_offset; arrow_source[2].x = 0; arrow_source[2].y = (y_offset < 0) ? 1 : -1; arrow_dester[2].x = x_offset; arrow_dester[2].y = y_offset + ((y_offset < 0) ? 1 : -1); } } /****************************************************************************** shape_set_single_march (length, angle, march_source, march_dester) Set endpoint coordinates for a single march vector of and , using and as coordinate arrays. ******************************************************************************/ shape_set_single_march (length, angle, march_source, march_dester) int length, angle; XPoint march_source[], march_dester[]; { int x_offset, y_offset, x_aux_offset, y_aux_offset, multer; double rad_angle, rad_aux_angle, cos(), sin(); /** Handle horizontal and vertical vectors explicitly to ensure that **/ /** rounding errors in floating point conversion don't hurt things. **/ switch (angle) { case 0: x_offset = length; y_offset = 0; break; case 90: x_offset = 0; y_offset = -length; break; case 180: x_offset = -length; y_offset = 0; break; case 270: x_offset = 0; y_offset = length; break; /** Handle generic angle, determining (xoffset, y_offset) endpoints **/ default: if (angle%45 != 0) length -= 1; rad_angle = ((double)(angle)) * PI/180.0; x_offset = (int)(cos(rad_angle) * length); y_offset = -(int)(sin(rad_angle) * length); break; } /** If vertical vector **/ if (x_offset == 0) { march_source[0].x = -2; march_source[0].y = 0; march_dester[0].x = -2; march_dester[0].y = y_offset; march_source[1].x = -3; march_source[1].y = 0; march_dester[1].x = -3; march_dester[1].y = y_offset; march_source[2].x = 2; march_source[2].y = 0; march_dester[2].x = 2; march_dester[2].y = y_offset; march_source[3].x = 3; march_source[3].y = 0; march_dester[3].x = 3; march_dester[3].y = y_offset; } else if (y_offset == 0) { /** Else if horizontal vector **/ march_source[0].x = 0; march_source[0].y = -2; march_dester[0].x = x_offset; march_dester[0].y = -2; march_source[1].x = 0; march_source[1].y = -3; march_dester[1].x = x_offset; march_dester[1].y = -3; march_source[2].x = 0; march_source[2].y = 2; march_dester[2].x = x_offset; march_dester[2].y = 2; march_source[3].x = 0; march_source[3].y = 3; march_dester[3].x = x_offset; march_dester[3].y = 3; } else if (angle == 45 || angle == 135 || angle == 225 || angle == 315) { /** Else if diagonal vector **/ if ((x_offset < 0 && y_offset < 0) || (x_offset > 0 && y_offset > 0)) multer = -1; else multer = 1; march_source[0].x = 2; march_source[0].y = 2*multer; march_dester[0].x = 2 + x_offset; march_dester[0].y = 2*multer + y_offset; march_source[1].x = 3; march_source[1].y = 3*multer; march_dester[1].x = 3 + x_offset; march_dester[1].y = 3*multer + y_offset; march_source[2].x = -2; march_source[2].y = -2*multer; march_dester[2].x = -2 + x_offset; march_dester[2].y = -2*multer + y_offset; march_source[3].x = -3; march_source[3].y = -3*multer; march_dester[3].x = -3 + x_offset; march_dester[3].y = -3*multer + y_offset; } else { /** Else generic vector, define orthogonal points **/ rad_aux_angle = rad_angle + PI/2.0; x_aux_offset = (int)(cos(rad_aux_angle) * 3); y_aux_offset = -(int)(sin(rad_aux_angle) * 3); march_source[0].x = x_aux_offset; march_source[0].y = y_aux_offset; march_dester[0].x = x_aux_offset + x_offset; march_dester[0].y = y_aux_offset + y_offset; march_source[2].x = -x_aux_offset; march_source[2].y = -y_aux_offset; march_dester[2].x = -x_aux_offset + x_offset; march_dester[2].y = -y_aux_offset + y_offset; march_source[1].x = march_source[0].x + ((x_offset < 0) ? 1 : -1); march_source[1].y = march_source[0].y; march_dester[1].x = march_dester[0].x + ((x_offset < 0) ? 1 : -1); march_dester[1].y = march_dester[0].y; march_source[3].x = march_source[2].x - ((x_offset < 0) ? 1 : -1); march_source[3].y = march_source[2].y; march_dester[3].x = march_dester[2].x - ((x_offset < 0) ? 1 : -1); march_dester[3].y = march_dester[2].y; } }