C language bresenhamLine Algorithm - c

I am confused about what could be the problem in this algorithm:
With these parameters:
ine temp = {(Vector){10, 150}, (Vector){120, 40}, polygon->color};
drawaLine(monitor, &temp);
However, when I change the coordinates to 120, 20 it fails:
Line temp = {(Vector){10, 150}, (Vector){120, 20}, polygon->color};
drawaLine(monitor, &temp);
My code is:
int changed = 0;
int x = line->start.x;
int y = line->start.y;
int dx = (line->end.x - line->start.x);
int dy = (line->end.y - line->start.y);
dx = (dx < 0) ? -dx : dx;
dy = (dy < 0) ? -dy : dy;
int signx;
int signy;
if ((line->end.x - line->start.x) == 0) {
signx = 0;
} else {
int tempsignx = (line->end.x - line->start.x);
signx = (tempsignx < 0) ? -1 : 1;
}
if ((line->end.y - line->start.y) == 0) {
signy = 0;
} else {
int tempsingy = (line->end.y - line->start.y);
signy = (tempsingy < 0) ? -1 : 1;
}
//swap values
if (dy > dx) {
int temp = dy;
dy = dx;
dx = temp;
changed = 1; //changed = true
}
int e = 2 * dy - dx;
for (int i = 1; i <= dx; i++) {
Vector temp = {x, y};
drawPixel(monitor, temp, line->color);
while (e >= 0) {
if (changed) {
x = x + signx;
} else {
y = y + signy;
e = e - 2 * dx;
}
}
if (changed) {
y += signy;
} else {
x += signx;
e = e + 2 * dy;
}
Vector x2y2 = {line->end.x, line->end.y};
drawPixel(monitor, x2y2, line->color);
}
}

Related

Ray Casting (GONE WRONG)

i'm building a raycasting engine and i've done the 2d projection, with wall collisions, now shifting to 3d i'm not being able to render a proper 3d image, i'll throw my code below:
i've tried all types of things by now, even changing my line function
include "../incs/Cub3d.h"
#define DOWN 0
#define UP 1
#define LEFT 2
#define RIGHT 3
#define RAY_NUM 816
t_point horizontalinter(t_mlx *m, float ang)
{
t_point inter;
inter.hit = 1;
double xinter, yinter;
double xstep, ystep;
double xwall, ywall;
xwall = 0;
ywall = 0;
int hit = 0;
float r_angle;
r_angle = (ang);
int r_dir = upordown(r_angle);
int r_lor = leftorright(r_angle);
yinter = floor(m->p->y / TILES) * TILES;
if (r_dir == DOWN)
yinter += TILES;
xinter = m->p->x + (yinter - m->p->y)/tan(r_angle);
ystep = TILES;
if (r_dir == UP)
ystep *= -1;
xstep = TILES / tan(r_angle);
if ((r_lor == LEFT && xstep > 0) || (r_lor == RIGHT && xstep < 0))
xstep *= -1;
double nextx = xinter;
double nexty = yinter;
while (nextx >= 0 && nextx <= WIDTH && nexty >= 0 && nexty <= HEIGHT)
{
if (has_wall(nextx, nexty - (r_dir == UP ? 1 : 0) , m))
{
hit = 1;
xwall = nextx;
ywall = nexty;
break;
}
else
{
nextx += xstep;
nexty += ystep;
}
}
inter.x = xwall;
inter.y = ywall;
if (hit)
{
inter.dist2pl = distancebetween(m->p->x, m->p->y, xwall, ywall);
return(inter);
}
inter.dist2pl = INT_MAX;
return(inter);
}
t_point verticalinter(t_mlx *m, float ang)
{
t_point inter;
inter.hit = 0;
double xinter, yinter;
double xstep, ystep;
double xwall, ywall;
int hit = 0;
xwall = 0;
ywall = 0;
float r_angle = normalize_ang(ang);
int r_dir = upordown(r_angle);
int r_lor = leftorright(r_angle);
//FIND X-interseption
xinter = floor(m->p->x / TILES) * TILES;
if (r_lor == RIGHT)
xinter += TILES;
//FIND Y-interseption
yinter = m->p->y + (xinter - m->p->x) * tan(r_angle);
//find STEPS
//xstep
xstep = TILES;
if (r_lor == LEFT)
xstep *= -1;
//ystep
ystep = TILES * tan(r_angle);
if ((r_dir == UP && ystep > 0) || (r_dir == DOWN && ystep < 0))
ystep *= -1;
// next intersection
double nextx = xinter;
double nexty = yinter;
//make sure that mf hits a wall
// loop untill it finds a wall or leaves canvas, increments with x and y step
while (nextx >= 0 && nextx <= WIDTH && nexty >= 0 && nexty <= HEIGHT)
{
if (has_wall(nextx - (r_lor == LEFT ? 1 : 0) , nexty, m))
{
hit = 1;
xwall = nextx;
ywall = nexty;
break;
}
else
{
nextx += xstep;
nexty += ystep;
}
}
inter.x = xwall;
inter.y = ywall;
if (hit)
{
inter.dist2pl = distancebetween(m->p->x, m->p->y, xwall, ywall);
return(inter);
}
inter.dist2pl = INT_MAX;
return(inter);
}
void calc_rays(t_mlx *m, float ang)
{
int color ;
ang = normalize_ang(ang);
t_point h_hit = horizontalinter(m, ang);
t_point v_hit = verticalinter(m, ang);
t_point closest = v_hit.dist2pl > h_hit.dist2pl ? h_hit : v_hit;
if (closest.hit)
color = rgb_to_int(0,255,0);
else
color = rgb_to_int(0,0,255);
int lineheigth = ((TILES * 5) / closest.dist2pl) * 277;
int drawStart = -lineheigth / 2 + HEIGHT / 2;
if(drawStart < 0)drawStart = 0;
int drawEnd = lineheigth / 2 + HEIGHT / 2;
if(drawEnd >= HEIGHT)drawEnd = HEIGHT - 1;
mlx_line_to(m, closest.x,drawStart , closest.x, drawEnd, color);
printf("%f\n", closest.dist2pl);
}
void cast_rays(t_mlx *m)
{
float r_angle = m->p->ang - (FOV / 2);
for(int i = 0; i < RAY_NUM; i++)
{
calc_rays(m, r_angle);
r_angle += (FOV / RAY_NUM);
}
}
i've tried calculating line heights differently but with no sucess

How to make Bresenham algorithm working backward?

I got an exersise where I would like to draw a line with Bressenham algorithm.
The thing is that it's working perfectly for lines who goes down and on the right, but when the line goes up or backward, it doesn't work anymore ...
Does anybody can help me on that ?
void draw_line(t_data img, int xStart, int yStart, int xEnd, int yEnd)
{
int dx;
int dy;
int pk;
int x;
int y;
dx = xEnd - xStart;
dy = yEnd - yStart;
x = xStart;
y = yStart;
while(x <= xEnd)
{
if(pk >= 0)
{
printf("in if ");
my_mlx_pixel_put(&img, x, y, 0x00FF0000);
y = y + 1;
pk = pk + 2 * dy - 2 * dx;
}
else
{
my_mlx_pixel_put(&img, x, y, 0x00FF0000);
pk = pk + 2 * dy;
}
x = x + 1;
count ++;
}
}
Its working for this
draw_line(img, 300, 300, 400, 360);
But not for this
draw_line(img, 300, 300, 200, 260);
Thanks for your help !!
You are working in the first octant. If you want to draw lines in all direction you have to check the 8 octant.
here is my implentation of bresenham for the 8 octant:
void bresenham(int x1, int y1, int x2, int y2) {
int dx = x2 - x1;
int dy = y2 - y1;
int error;
/** first quarter */
if(dx >= 0 && dy >= 0) {
/** 1st octant */
if (dx >= dy) {
error = -dx;
int y = y1;
for(int x = x1; x < x2; x++) {
draw_pixel(x, y);
error = error + 2 * dy;
if (error >= 0) {
y++;
error = error - 2 * dx;
}
}
}
/** 2nd octant */
else {
error = -dy;
int x = x1;
for(int y = y1; y < y2; y++) {
draw_pixel(x, y);
error = error + 2 * dx;
if (error >= 0) {
x++;
error = error - 2 * dy ;
}
}
}
}
/** second quarter */
else if (dx <= 0 && dy >= 0) {
/** 4th octant */
if(dx < -dy) {
error = dx;
int y = y1;
for(int x = x1; x > x2; x--) {
draw_pixel(x, y);
error = error + 2 * dy;
if (error >= 0) {
y++;
error = error + 2 * dx;
}
}
}
/** 3rd octant */
else {
error = -dy;
int x = x1;
for(int y = y1; y < y2; y++) {
draw_pixel(x, y);
error = error - 2 * dx;
if (error >= 0) {
x--;
error = error - 2 * dy;
}
}
}
}
/** 3rd quarter */
else if (dx <= 0 && dy <= 0) {
/** 5th octant */
if(dx <= dy) {
error = 2 * dx;
int y = y1;
for(int x = x1; x > x2; x--) {
draw_pixel(x, y);
error = error - 2 * dy;
if (error >= 0) {
y--;
error = error + 2 * dx;
}
}
}
/** 6th octant */
else {
error = 2 * dy;
int x = x1;
for(int y = y1; y > y2; y--) {
draw_pixel(x, y);
error = error - 2 * dx;
if (error >= 0) {
x--;
error = error + 2 * dy ;
}
}
}
}
/* 4th quarter */
else if(dx >= 0 && dy <= 0) {
/** 7th octant */
if(dx < -dy) {
error = 2 * dy;
int x = x1;
for(int y = y1; y > y2; y--) {
draw_pixel(x, y);
error = error + 2 * dx;
if (error >= 0) {
x++;
error = error + 2 * dy ;
}
}
}
/** 8th octant */
else {
error = -dx;
int y = y1;
for(int x = x1; x < x2; x++) {
draw_pixel(x, y);
error = error - 2 * dy;
if (error >= 0) {
y--;
error = error - 2 * dx;
}
}
}
}
}

cell overlap removal in vlsi placement

Below code is to remove overlap among cells residing inside grids.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
//coordinate representation
struct Point
{
double x;
double y;
};
//block representation with 4 coordinates
struct Block
{
unsigned int id;
struct Point bottomLeft, topLeft, bottomRight, topRight;
double width, height;
double whitespace;
};
struct Overlap
{
double overlapLength;
struct Block *b1, *b2;
} OL[1000];
struct Block *b;
struct Block ROW1, ROW2, ROW3;
int comparator(const void *p, const void *q)
{
return (((struct Overlap *)p)->overlapLength -
(((struct Overlap *)q)->overlapLength));
}
//intialise Blocks using bottom left x,y coordinate
void intialiseBlock(struct Block *B)
{
B->topLeft.x = B->bottomLeft.x;
B->topLeft.y = B->height + B->bottomLeft.y;
B->bottomRight.x = B->width + B->bottomLeft.x;
B->bottomRight.y = B->bottomLeft.y;
B->topRight.x = B->width + B->bottomLeft.x;
B->topRight.y = B->height + B->bottomLeft.y;
}
//update coordinate
void move(double xDelta, double yDelta, struct Point *p)
{
// Parameter values are increments to the current coordinates
p->x += xDelta;
p->y += yDelta;
}
//calculate and return distance between 2 points
double distance(const struct Point aPoint, const struct Point bPoint)
{
return sqrt((aPoint.x - bPoint.x) * (aPoint.x - bPoint.x) +
(aPoint.y - bPoint.y) * (aPoint.y - bPoint.y));
}
//generate width of cell using number of cells
double computeCellWidth(int ncell)
{
double width = (0.8 * 400) / ncell;
return width;
}
//create a
unsigned int rand_interval(unsigned int min, unsigned int max)
{
int r;
const unsigned int range = 1 + max - min;
const unsigned int buckets = RAND_MAX / range;
const unsigned int limit = buckets * range;
/* Create equal size buckets all in a row, then fire randomly towards
* the buckets until you land in one of them. All buckets are equally
* likely. If you land off the end of the line of buckets, try again. */
do
{
r = rand();
} while (r >= limit);
return min + (r / buckets);
}
//place blocks in appropriate rows
void placeVertical(struct Block *b, int n, struct Block ROW1, struct Block ROW2,
struct Block ROW3)
{
for (int i = 0; i < n; i++)
{
double distanceFromBottom = 0.0;
double distanceFromTop = 0.0;
// check if Inside Row1 and Row2
if ((b[i].bottomLeft.y < ROW1.topLeft.y) && (b[i].topLeft.y > ROW1.topLeft.y))
{
//printf("ROW1 and ROW2 Executed\n");
distanceFromBottom = ROW1.topLeft.y - b[i].bottomLeft.y;
distanceFromTop = b[i].height - distanceFromBottom;
if (distanceFromBottom > distanceFromTop)
{
move(0, -distanceFromTop, &b[i].bottomLeft);
move(0, -distanceFromTop, &b[i].topLeft);
move(0, -distanceFromTop, &b[i].bottomRight);
move(0, -distanceFromTop, &b[i].topRight);
}
else
{
move(0, distanceFromBottom, &b[i].bottomLeft);
move(0, distanceFromBottom, &b[i].topLeft);
move(0, distanceFromBottom, &b[i].bottomRight);
move(0, distanceFromBottom, &b[i].topRight);
}
}
// check if Inside Row2 and Row3
else if ((b[i].bottomLeft.y < ROW2.topLeft.y) && (b[i].topLeft.y > ROW2.topLeft.y))
{
//System.out.println("ROW2 and ROW3 Executed");
distanceFromBottom = ROW2.topLeft.y - b[i].bottomLeft.y;
distanceFromTop = b[i].height - distanceFromBottom;
if (distanceFromBottom > distanceFromTop)
{
move(0, -distanceFromTop, &b[i].bottomLeft);
move(0, -distanceFromTop, &b[i].topLeft);
move(0, -distanceFromTop, &b[i].bottomRight);
move(0, -distanceFromTop, &b[i].topRight);
}
else
{
move(0, distanceFromBottom, &b[i].bottomLeft);
move(0, distanceFromBottom, &b[i].topLeft);
move(0, distanceFromBottom, &b[i].bottomRight);
move(0, distanceFromBottom, &b[i].topRight);
}
}
else if ((b[i].bottomLeft.y >= ROW1.bottomLeft.y) && (b[i].topLeft.y <= ROW1.topLeft.y))
{
// do nothing in ROW1
}
else if ((b[i].bottomLeft.y >= ROW2.bottomLeft.y) && (b[i].topLeft.y <= ROW2.topLeft.y))
{
// do nothing in ROW2
}
else // ((b[i].bottomLeft.y >=
// ROW2.bottomLeft.y)&&(b[i].topLeft.y <=
// ROW2.topLeft.y))
{
// do nothing in ROW3
}
}
}
//use when floating point operations create run time problems
void linkfloat()
{
float a = 0.0, *x;
x = &a;
a = *x;
}
int findOverlaps(struct Block *b, int n)
{
int k, j, p = 0;
//struct Overlap OL[200];
//short flag = FALSE;
double overlapLength = 0.0;
for (int i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (k == j)
continue;
overlapLength = 0.0;
//for ROW1
if (b[k].bottomLeft.y >= 0 && b[k].topLeft.y <= 100 && b[j].bottomLeft.y >= 0 && b[j].topLeft.y <= 100)
{
//if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
//For Row2
else if (b[k].bottomLeft.y >= 100 && b[k].topLeft.y <= 200 && b[j].bottomLeft.y >= 100 && b[j].topLeft.y <= 200)
{
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
//For Row3
else if (b[k].bottomLeft.y >= 200 && b[k].topLeft.y <= 300 && b[j].bottomLeft.y >= 200 && b[j].topLeft.y <= 300)
{
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
else
{
//do nothing
}
}
}
return p;
}
struct Block *
getBlock(struct Block *b, int n, int id)
{
int i;
for (i = 0; i < n; i++)
{
if (id == b[i].id)
return (b + i);
}
return NULL;
}
void placeHorizontalGreedy(struct Block *b, int n)
{
struct Block *t = NULL;
int p = 0, k = 0;
p = findOverlaps(b, n);
qsort(OL, p, sizeof(struct Overlap), comparator);
while (TRUE)
{
t = getBlock(b, 12, OL[k].b2->id);
if (t != NULL)
{
//t->bottomLeft.x = t->bottomLeft.x+OL[0].overlapLength;
if ((t->bottomLeft.x + OL[0].overlapLength + t->width) <= ROW1.bottomRight.x)
{
move(OL[0].overlapLength, 0, &t->bottomLeft);
intialiseBlock(t);
}
}
p = findOverlaps(b, n);
if (p == 0)
break;
else
qsort(OL, p, sizeof(struct Overlap), comparator);
}
}
void placeHorizontalNonGreedy(struct Block *b, int n, struct Block ROW1,
struct Block ROW2, struct Block ROW3)
{
int k, j, p = 0;
double overlapLength = 0.0;
for (int i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (k == j)
continue;
overlapLength = 0.0;
//check if in Row1
if (b[k].bottomLeft.y >= ROW1.bottomLeft.y && b[k].topLeft.y <= ROW1.topLeft.y && b[j].bottomLeft.y >= ROW1.bottomLeft.y && b[j].topLeft.y <= ROW1.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
ROW1.bottomRight.x)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
else
{
b[j].bottomLeft.x =
b[j].bottomLeft.x + (ROW1.bottomRight.x -
b[j].bottomRight.x);
}
}
}
}
//check if in Row2
else if (b[k].bottomLeft.y >= ROW2.bottomLeft.y && b[k].topLeft.y <= ROW2.topLeft.y && b[j].bottomLeft.y >= ROW2.bottomLeft.y && b[j].topLeft.y <= ROW2.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
400)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
}
}
}
//check if in Row3
else if (b[k].bottomLeft.y >= ROW3.bottomLeft.y && b[k].topLeft.y <= ROW3.topLeft.y && b[j].bottomLeft.y >= ROW3.bottomLeft.y && b[j].topLeft.y <= ROW3.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
400)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
}
}
}
else
{
//printf("Invalid input\n");
continue;
}
}
}
}
int main()
{
//struct Block b[16];
//struct Block b[4];
//struct Block *b;
//struct Block ROW1, ROW2, ROW3;
//FILE *fp = fopen("/home/jeetu/experimentprograms/recordcoord.txt", "w+");
//FILE *fp = fopen("/home/jeetu/experimentprograms/blockcoordinates.txt", "r");
int ncell = 0, width = 0, i = 0, totalncells = 0, id = 0;
double distanceFromBottom = 0.0;
double distanceFromTop = 0.0;
int x = 0, y = 0, temp = 0, d = 0;
printf("Enter number of cells: ");
scanf("%d", &ncell);
width = computeCellWidth(ncell);
//width = 40;
b = (struct Block *)malloc(3 * ncell * sizeof(struct Block));
//b = (struct Block *)malloc(12 * sizeof(struct Block));
srand(time(0));
ROW1.bottomLeft.x = 0;
ROW1.bottomLeft.y = 0;
ROW1.height = 100;
ROW1.width = 400;
ROW1.whitespace = 40000;
intialiseBlock(&ROW1);
ROW2.bottomLeft.x = 0;
ROW2.bottomLeft.y = 100;
ROW2.height = 100;
ROW2.width = 400;
ROW2.whitespace = 40000;
intialiseBlock(&ROW2);
ROW3.bottomLeft.x = 0;
ROW3.bottomLeft.y = 200;
ROW3.height = 100;
ROW3.width = 400;
ROW3.whitespace = 40000;
intialiseBlock(&ROW3);
for (i = 0; i < ncell; i++)
{
if (i == 0)
{
// x = rand_interval(0, width / 2);
x = rand() % (width / 2);
//y = rand_interval(0, 70);
y = rand() % 70;
temp = x;
}
//m = rand();
else
{
x = rand_interval((temp + (int)width / 2), temp + width);
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
//y = rand_interval(0, 70);
y = rand() % 70;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW1
if (b[totalncells].bottomLeft.y >= ROW1.bottomLeft.y && b[totalncells].topLeft.y <= ROW1.topLeft.y)
{
ROW1.whitespace =
ROW1.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
temp = 0;
//Generate random coordinates For Row2
for (i = 0; i < ncell; i++)
{
//int x = 0, y = 0, m = 0, d = 0;
if (i == 0)
{
/*x = rand_interval(0, width / 2);
y = rand_interval(100, 170); */
//x = rand() % (width / 2);
x = rand() % (width / 2);
y = (rand() % (170 - 100)) + 100;
temp = x;
}
//m = rand();
else
{
/*x = rand_interval((temp + (int)width / 2), 400 - (int)width);
y = rand_interval(100, 170); */
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
x = rand_interval((temp + (int)width / 2), temp + width);
y = (rand() % (170 - 100)) + 100;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW2
if (b[totalncells].bottomLeft.y >= ROW2.bottomLeft.y && b[totalncells].topLeft.y <= ROW2.topLeft.y)
{
ROW2.whitespace =
ROW2.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
temp = 0;
//Generate random coordinates For Row3
for (i = 0; i < ncell; i++)
{
//int x = rand_interval(0, 100 - (int)width);
//int y = rand_interval(20, 25); //cell height is 5 so max will reach 30
//int x = 0, y = 0, m = 0, d = 0;
if (i == 0)
{
/*x = rand_interval(0, width / 2);
y = rand_interval(200, 250); */
x = rand() % (width / 2);
y = (rand() % (250 - 200)) + 200;
temp = x;
}
//m = rand();
else
{
/*x = rand_interval((temp + (int)width / 2), 400 - (int)width);
y = rand_interval(200, 250); */
x = rand_interval((temp + (int)width / 2), temp + width);
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
y = (rand() % (250 - 200)) + 200;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW3
if (b[totalncells].bottomLeft.y >= ROW3.bottomLeft.y && b[totalncells].topLeft.y <= ROW3.topLeft.y)
{
ROW3.whitespace =
ROW3.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
for (i = 0; i < totalncells; i++)
{
//printf("%f %f %f %f\n", b[i].bottomLeft.x, b[i].bottomLeft.y, b[i].width, b[i].height);
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
placeVertical(b, totalncells, ROW1, ROW2, ROW3);
//placeVerticalWithDensityConstraints(b,totalncells,ROW1,ROW2,ROW3);
printf("\nAfter vertical Updation\n");
for (i = 0; i < totalncells; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
/*placeHorizontalNonGreedy(b, 12, ROW1, ROW2, ROW3);
printf("\nAfter Horizontal Updation(Non greedy)\n");
for (i = 0; i < 12; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x, (int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
} */
placeHorizontalGreedy(b, totalncells);
printf("\nAfter Horizontal Updation(Greedy)\n");
for (i = 0; i < totalncells; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
return 0;
}
Explanation about the code
in this program I have defined three structures
one to represent a Point,one to represent rectangular block with 4 coordinates,one to represent overlap between pair of cells.
There is function(computeCellWidth) to dynamically compute width of cells according to a formula.
There are three rows ROW1,ROW2,ROW3 in which cells will reside.
This program will first ask for number of cells and this is numbers of cells per row.At first x,y coordinates for each cell is randomly generated.Then placeVertical() function will move cells to different rows which are spanning across two rows.Then there is a placeHorizontalGreedy() function which will remove overlap among cells by first finding overlaplength and then sorting them and removing the overlap between cells which has least overlap and this process will continue till either there will be no overlaps or overlap removal is not possible anymore.Here I would like to bring to the notice of everybody that cells will be moved towards the right of the grid to remove overlaps.In placeHorizontalGreedy() function I have used a variable p which will indicate number of overlaps after each iteration.for small number of cells testing for p to be zero works fine but not as I increase the numbers.Plus how can I make sure that overlaps exists but overlap removal is not possible anymore,so that I can stop the loop. Please help me out.

function in queen's Attack II returns wrong answer

I'm solving Queen's Attack II problem in Hackerrank. My idea is traverse through every obstacles to find the closest obstacle in each directions (left, right, up down and 4 diagons. My function only passed half of testcases. Then I search on the Internet and I found a similar solution but different in code structure, obsiously it passed all testcases.
My function:
int queensAttack(int n, int k, int r_q, int c_q, int obstacles_rows, int obstacles_columns, int **obstacles) {
long a[8];
a[0]=c_q-1;
a[1]=n-c_q;
a[2]=r_q-1;
a[3]=n-r_q;
a[4]=min(a[3], a[1]);
a[5]=min(a[2], a[1]);
a[6]=min(a[2], a[0]);
a[7]=min(a[3], a[0]);
int x=obstacles[i][1], y=obstacles[i][0];
for (int i=0; i<obstacles_rows; i++) {
if(y==r_q && x<c_q) a[0]=min(a[0], c_q-x-1);
else if(y==r_q && x>c_q) a[1]=min(a[1], x-c_q-1);
else if(x==c_q && y<r_q) a[2]=min(a[2], r_q-y-1);
else if(x==c_q && y>r_q) a[3]=min(a[3], y-r_q-1);
else if(y-r_q==x-c_q) a[4]=min(a[4], y-r_q-1);
else if(r_q-y==x-c_q) a[5]=min(a[5], r_q-y-1);
else if(r_q-y==c_q-x) a[6]=min(a[6], r_q-y-1);
else if(y-r_q==c_q-x) a[7]=min(a[7], y-r_q-1);
}
int result=0;
for (int i=0; i<8; i++) {
result+=a[i];
}
return result;
}
Their fucntion:
int queensAttack(int n, int k, int r_q, int c_q, int obstacles_rows, int obstacles_columns, int **obstacles) {
a[0] = c_q -1 ;
a[1] = n -r_q;
a[2] = n -c_q;
a[3] = r_q -1;
a[4] = min(a[0],a[1]);
a[5] = min(a[1],a[2]);
a[6] = min(a[2],a[3]);
a[7] = min(a[3],a[0]);
int x,y;
while (--k >= 0)
{
y = obstacles[k][0] - r_q;
x = obstacles[k][1] - c_q;
if (x == 0)
{
if (y > 0)
{
a[1] = min(a[1], y - 1);
}
else
{
a[3] = min(a[3], -(y + 1));
}
}
else if (y == 0)
{
if (x > 0)
{
a[2] = min(a[2], x - 1);
}
else
{
a[0] = min(a[0], -(x + 1));
}
}
else
{
float m = (float)y / x;
if (m == 1.0)
{
if (x > 0)
{
a[5] = min(a[5], x - 1);
}
else
{
a[7] = min(a[7], -y - 1);
}
}
else if (m == -1.0)
{
if (x > 0)
{
a[6] = min(a[6], x - 1);
}
else
{
a[4] = min(a[4], y - 1);
}
}
}
}
int result=0;
for (int i=0; i<8; i++) {
result+=a[i];
}
return result;
}
Where am I wrong?
Any help would be appreciated.
Some issues:
1) This line should not occur before the loop, but as a first statement inside the loop body:
int x=obstacles[i][1], y=obstacles[i][0];
2) The second half of the loop has conditions which cause a problem. For instance when y-r_q==x-c_q is true, then also r_q-y==c_q-x is true, and vice versa. So this expression tells you whether an obstacle is on a queen's diagonal, but not on which side of the queen. As a consequence, the argument you pass to the min function could be negative, and this should never happen. You need an additional condition, much like you have in the first half of that if-chain. So change the second half to this:
else if(y-r_q==x-c_q && y>r_q) a[4]=min(a[4], y-r_q-1);
else if(r_q-y==x-c_q && y<r_q) a[5]=min(a[5], r_q-y-1);
else if(r_q-y==c_q-x && y<r_q) a[6]=min(a[6], r_q-y-1);
else if(y-r_q==c_q-x && y>r_q) a[7]=min(a[7], y-r_q-1);
It took me some time to figure out this one. My first code couldn't get through the time execution time limits. So, some math comes handy. First I calculate the total number of moves as there are no obstacles, just using math. If there are no obstacles that is the answer.
If there are obstacles, loop through them, using boolean to close each direction that is found and using math calculate the non moves. But I still had error, because the obstacles had to be sorted from the queen to the farthest obstacles position.
Here is my code in Java.
int vertHor = n - 1;
int d1 = Math.min(n - c_q, n - r_q) + Math.min(r_q - 1, c_q - 1);
int d2 = Math.min(c_q - 1, n - r_q) + Math.min(n - c_q, r_q - 1);
int total = vertHor * 2 + d1 + d2;
if (k == 0) {
return total;
}
boolean u = false;
boolean d = false;
boolean l = false;
boolean r = false;
boolean ul = false;
boolean ur = false;
boolean dl = false;
boolean dr = false;
Arrays.sort(obstacles, (int[] x, int[] y) -> Math.min(Math.abs(x[0] - r_q), Math.abs(x[1] - c_q))
- Math.min(Math.abs(y[0] - r_q), Math.abs(y[1] - c_q)));
for (int[] obs : obstacles) {
int oRow = obs[0];
int oCol = obs[1];
if (oRow == r_q) {
if (oCol < c_q && !l) {
total -= oCol;
l = true;
} else if (!r) {
total -= n - oCol + 1;
r = true;
}
} else if (oCol == c_q) {
if (oRow < r_q && !d) {
total -= oRow;
d = true;
} else if (!u) {
total -= n - oRow + 1;
u = true;
}
} else if (Math.abs(c_q - oCol) == Math.abs(r_q - oRow)) {//oCol != c_q && oRow != r_q) {
if (oCol < c_q && oRow > r_q && !ul) {
total -= Math.min(n - oRow + 1, oCol);
ul = true;
} else if (oCol < c_q && oRow < r_q && !dl) {
total -= Math.min(oRow, oCol);
dl = true;
} else if (oCol > c_q && oRow < r_q && !dr) {
total -= Math.min(oRow, n - oCol + 1);
dr = true;
} else if (oCol > c_q && oRow > r_q && !ur) {
total -= Math.min(n - oRow, n - oCol) + 1;
ur = true;
}
}
if (u && d && l && r && ul && ur && dl && dr) {
break;
}
}
return total;

function to draw a straight line in c

I'm trying to create a function to draw a straight line by reading two points from the user, (x1,y1) where the line begins and (x2,y2) where it ends.
here's my function:
void line(struct pixels* screen)
{
float X, Y;
int i, j, x1, y1, x2, y2, mX, mY;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if ((x1 >= 0 && x1 <= screen->width) && (y1 >= 0 && y1 <= screen->height) && (x2 >= 0 && x2 <= screen->width) && (y2 >= 0 && y2 <= screen->height))
{
X = (x2 - x1);
Y = (y2 - y1);
if (X < 0)
mX = X*(-1);
else
mX = X;
if (Y < 0)
mY = Y*(-1);
else
mY = Y;
if( mX>mY )
{
if (X > 0)
{
for (i = 0; i < X; i++)
{
j = (int)(((i*Y) / X) + 0.5);
screen->pixel[x1 + i][y1 + j] = '*';
}
}
else
{
for (i = 0; i > X; i--)
{
j = (int)(((i*Y) / X) + 0.5);
screen->pixel[x1 + i][y1 + j] = '*';
}
}
}
else
{
if (Y > 0)
{
for (j = 0; j < Y; j++)
{
i = (int)(((j*X) / Y) + 0.5);
screen->pixel[x1 + i][y1 + j] = '*';
}
}
else
{
for (j = 0; j > Y; j--)
{
i = (int)(((j*X) / Y) + 0.5);
screen->pixel[x1 + i][y1 + j] = '*';
}
}
}
}
else
printf("ERROR: coordinates exceed the screen limits\n");
}
the problem is : when the user enters for example line from (1,1) to (10,10) the code works perfectly, but when it's from (10,10) to (1,1) it doesn't work!
Google Bresenham’s Line Drawing Algorithm. There is a fantastic tutorial/explanation of how do to this kind of thing at How OpenGL works: software renderer in 500 lines of code. Your specific question is brought up in the article. Highly recommended.
Here is his C++ implementation:
void line(int x0, int y0, int x1, int y1, TGAImage &image, TGAColor color) {
bool steep = false;
if (std::abs(x0-x1)<std::abs(y0-y1)) {
std::swap(x0, y0);
std::swap(x1, y1);
steep = true;
}
if (x0>x1) {
std::swap(x0, x1);
std::swap(y0, y1);
}
int dx = x1-x0;
int dy = y1-y0;
float derror = std::abs(dy/float(dx));
float error = 0;
int y = y0;
for (int x=x0; x<=x1; x++) {
if (steep) {
image.set(y, x, color);
} else {
image.set(x, y, color);
}
error += derror;
if (error>.5) {
y += (y1>y0?1:-1);
error -= 1.;
}
}
}

Resources