Checking if rectangle B is wholly contained in rectangle A - c#

Hi guys assist me with checking if rectangle B is wholly contained in rectangle A, here is a sample code to work with:
Class Rectangle
Public class Rectangle
{
Public int X1 { get; set; }
Public int X2 { get; set; }
Public int Y1 { get; set; }
Public int Y2 { get; set; }
public bool IsWhollyContained(Rectangle otherRectangle)
{
//Write your code here
}
}
Main Method
Public static void main(string[] args)
{
Rectangle A = new Rectangle { X1 = 2, Y1 = 1, X2 = 4, Y2 = 4}};
Rectangle B = new Rectangle { X1 = 1, Y1 = 6, X2 = 5, Y2 = 1}};
bool isContained = B.IsWhollyContained(A);
}
The task is to complete method IsWhollyContained. Please assist if you know the answer, the language used is C#. Thanks guys.

sort the rectangle's points to be sure that you're getting the right bound of rectangle than compare the points, try this:
public bool IsWhollyContained(Rectangle otherRectangle)
{
int rec1Xb = X1 > X2 ? X1 : X2;
int rec1Xs = X1 > X2 ? X2 : X1;
int rec1Yb = Y1 > Y2 ? Y1 : Y2;
int rec1Ys = Y1 > Y2 ? Y2 : Y1;
int rec2Xb = otherRectangle.X1 < otherRectangle.X2 ? otherRectangle.X1 : otherRectangle.X2;
int rec2Xs = otherRectangle.X1 < otherRectangle.X2 ? otherRectangle.X2 : otherRectangle.X1;
int rec2Yb = otherRectangle.Y1 < otherRectangle.Y2 ? otherRectangle.Y1 : otherRectangle.Y2;
int rec2Ys = otherRectangle.Y1 < otherRectangle.Y2 ? otherRectangle.Y2 : otherRectangle.Y1;
return rec1Xs >= rec2Xs &&
rec1Xb <= rec2Xb &&
rec1Ys >= rec2Ys &&
rec1Yb <= rec2Yb;
}

I am assuming that X1, X2, Y1 and Y2 are the coordinates for the lower left and upper right corners of your rectangle.
If another rectangle is supposed to be located inside the first one, the following conditions must be fulfilled:
rectangle1.X1 < rectangle2.X1
rectangle1.Y1 < rectangle2.Y1
rectangle1.X2 > rectangle2.X2
rectangle1.Y2 > rectangle2.Y2
But you don't need to store all those coordinates in your rectangle. System.Drawing has something called Point, you can assign an X- and a Y-Coordinate to that. But if you're already including System.Drawing you can just go with what Hazem Abdullah suggested.

You may use the following code if you are using the System.Drawing Rectangle
Rectangle rect1, rect2;
// initialize them
if(rect1.Contains(rect2))
{
// do...
}
Here is the link 1
If you are using your own rectangle you may check if all the corner points from the first rectangle belong to the second one.
bool PointInsideRectangle(Point pt, double y0, double x0, double y1, double x1)
{
if (x1 < x0)
{
return pt.X < x0 && pt.X > x1 && pt.Y < y0 && pt.Y > y1;
}
// it crosses the date line
return (pt.X < x0 || pt.X > x1) && pt.Y < y0 && pt.Y > y1;
}
Or you need to only check the x0,y0 from the first rectangle to compare with the x0,y0 from the second rectangle, and with, height from the first rectangle and compare it with the second one.

Related

Random Walker loop issue for C#

I am working on a simple Random Walker program that should draw a 10p long line, then choose a random cardinal direction to draw another line (also 10p long) until a certain number of lines have been reached.
I am using four coordinates to draw the line (two coordinates for X and two for Y). The Y coordinates are pushed into a Stack after every line is drawn and they are popped out as the X coordinates. This should ensure that the starting point of every second line is the end-point of the previous line.
The program draws on a Windows Form after pushing a Button controller. As of now, the output is something like this:
This here is my event handler code block for the button:
// Graphics and Pen classes instantiated
Graphics graphics;
graphics = this.CreateGraphics();
Pen pen = new Pen(Color.Black);
pen.Width = 1;
// lineLength is 10 pixels
// gridLength and gridWidth are needed to keep the Random Path inside a 600×600 field (this is not yet implemented in the code)
// lineCount is for maximizing the number of lines to be drawn and to control the loop
int lineLength = 10;
int gridWidth = 600;
int gridLength = 600;
int lineCount = 0;
// Starting line drawn with the following coordinates:
int x1 = 20;
int x2 = 20;
int y1 = 20;
int y2 = 30;
graphics.DrawLine(pen, x1, y1, x2, y2);
lineCount++;
// Stack initialized to store "y" coordinates
// "y" coordinates should be passed on as "x" coordinates for every consecutive lines
// so that the ending point's coordinate of a line
Stack<int> stackY = new Stack<int>();
stackY.Push(y2);
stackY.Push(y1);
for (lineCount = 1; lineCount <= 64; lineCount++)
{
// X pops current Y coordinates from stack
x1 = stackY.Pop();
x2 = stackY.Pop();
// Initializing the random number (between 1 and 4) generator to choose from the cardinal directions
Random rnd = new Random();
int dir = rnd.Next(1, 5);
switch (dir)
{
// up
case 1:
y1 = y1 + lineLength; // y1 plus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2); //drawing the line
stackY.Push(y2); // pushing the current y coordinates into the stack
stackY.Push(y1);
break;
// right
case 2:
y1 = y2 + lineLength; // y2 plus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
// down
case 3:
y1 = y1 - lineLength; // y1 minus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
// left
case 4:
y2 = y2 - lineLength; // y2 minus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
} //switch
} //for
} //event handler
I am not really sure what went wrong - I appreciate any heads-up and advices! Thank you!
You are making this far more complicated than you need to. Also you are mixing the x and y coordinates in a way that doesn't make sense.
You don't need a stack, just store the most recent points. Something like this.
int x = 20, y = 20;
int new_x = x, new_y = y;
Random rnd = new Random();
for (int i = 0; i < numLines; i++)
{
int dir = rnd.Next(1, 5);
if (dir == 1) new_x += lineLength;
if (dir == 2) new_x -= lineLength;
if (dir == 3) new_y += lineLength;
if (dir == 4) new_y -= lineLength;
graphics.DrawLine(pen, x, y, new_x, new_y);
x = new_x;
y = new_y;
}
Also you don't need to redeclare the Random object every time, just once before the loop.

Traverse Pixels in a circle from the center

I need an algorithm like Bresenham's circle algorithm, but with some modifications.
The algorithm must visit all pixels in the radius (so essentially a fill).
The algorithm must start from the center of the circle
It must visit all points that would normally be visited (no holes)
It must visit each point in the circle exactly once
One technique I came up with would first determine all pixel coordinates inside the circle by just going through the rectangle of the circle and checking with Math.Sqrt if it is inside the circle.
Then it would order the pixels by distance and then visit each of them.
That would be exactly what I want, with the exception of being fast.
So my questions is:
Is there a fast way to do this without fetching,ordering and then visiting each pixel?
Just for clarification I do not actually want to draw onto the image, I only want to traverse them in the described order.
First, we can use fact, that circle can be divided in 8 octants. So we just need to fill single octant and use simple +- coordinate change to get full circle. So if we try to fill only one octant, we need to worry only about 2 directions from center : left and left top. Also, clever use of data structures like priority queue (.NET doesn't have it, so you need to find it somewhere else) and hash map can drastically improve performance.
/// <summary>
/// Make sure it is structure.
/// </summary>
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
public int DistanceSqrt()
{
return X * X + Y * Y;
}
}
/// <summary>
/// Points ordered by distance from center that are on "border" of the circle.
/// </summary>
public static PriorityQueue<Point> _pointsToAdd = new PriorityQueue<Point>();
/// <summary>
/// Set of pixels that were already added, so we don't visit single pixel twice. Could be replaced with 2D array of bools.
/// </summary>
public static HashSet<Point> _addedPoints = new HashSet<Point>();
public static List<Point> FillCircle(int radius)
{
List<Point> points = new List<Point>();
_pointsToAdd.Enqueue(new Point { X = 1, Y = 0 }, 1);
_pointsToAdd.Enqueue(new Point { X = 1, Y = 1 }, 2);
points.Add(new Point {X = 0, Y = 0});
while(true)
{
var point = _pointsToAdd.Dequeue();
_addedPoints.Remove(point);
if (point.X >= radius)
break;
points.Add(new Point() { X = -point.X, Y = point.Y });
points.Add(new Point() { X = point.Y, Y = point.X });
points.Add(new Point() { X = -point.Y, Y = -point.X });
points.Add(new Point() { X = point.X, Y = -point.Y });
// if the pixel is on border of octant, then add it only to even half of octants
bool isBorder = point.Y == 0 || point.X == point.Y;
if(!isBorder)
{
points.Add(new Point() {X = point.X, Y = point.Y});
points.Add(new Point() {X = -point.X, Y = -point.Y});
points.Add(new Point() {X = -point.Y, Y = point.X});
points.Add(new Point() {X = point.Y, Y = -point.X});
}
Point pointToLeft = new Point() {X = point.X + 1, Y = point.Y};
Point pointToLeftTop = new Point() {X = point.X + 1, Y = point.Y + 1};
if(_addedPoints.Add(pointToLeft))
{
// if it is first time adding this point
_pointsToAdd.Enqueue(pointToLeft, pointToLeft.DistanceSqrt());
}
if(_addedPoints.Add(pointToLeftTop))
{
// if it is first time adding this point
_pointsToAdd.Enqueue(pointToLeftTop, pointToLeftTop.DistanceSqrt());
}
}
return points;
}
I will leave the expansion to full list on you. Also make sure borders of the octants don't cause doubling of the points.
Ok, I couldn't handle it and did it myself. Also, to make sure it has properties you desire I did simple test :
var points = FillCircle(50);
bool hasDuplicates = points.Count != points.Distinct().Count();
bool isInOrder = points.Zip(points.Skip(1), (p1, p2) => p1.DistanceSqrt() <= p2.DistanceSqrt()).All(x => x);
I found a solution that satisfies my performance needs.
It's very simple, just a offset array.
static Point[] circleOffsets;
static int[] radiusToMaxIndex;
static void InitCircle(int radius)
{
List<Point> results = new List<Point>((radius * 2) * (radius * 2));
for (int y = -radius; y <= radius; y++)
for (int x = -radius; x <= radius; x++)
results.Add(new Point(x, y));
circleOffsets = results.OrderBy(p =>
{
int dx = p.X;
int dy = p.Y;
return dx * dx + dy * dy;
})
.TakeWhile(p =>
{
int dx = p.X;
int dy = p.Y;
var r = dx * dx + dy * dy;
return r < radius * radius;
})
.ToArray();
radiusToMaxIndex = new int[radius];
for (int r = 0; r < radius; r++)
radiusToMaxIndex[r] = FindLastIndexWithinDistance(circleOffsets, r);
}
static int FindLastIndexWithinDistance(Point[] offsets, int maxR)
{
int lastIndex = 0;
for (int i = 0; i < offsets.Length; i++)
{
var p = offsets[i];
int dx = p.X;
int dy = p.Y;
int r = dx * dx + dy * dy;
if (r > maxR * maxR)
{
return lastIndex + 1;
}
lastIndex = i;
}
return 0;
}
With this code you just get the index where to stop from radiusToMaxIndex, then loop through circleOffsets and visit those pixels.
It will cost lot of memory like this, but you can always change the datatype of the offsets from Point to a custom one with Bytes as members.
This solution is extremely fast, fast enough for my needs. It obviously has the drawback of using some memory, but lets be honest, instantiating a System.Windows.Form uses up more memory than this...
You have already mentioned Bresenhams's circle algorithm. That is a good starting point: You could start with the centre pixel and then draw Bresenham circles of increasing size.
The problem is that the Bresenham circle algorithm will miss pixels near the diagonals in a kind of Moiré effect. In another question, I have adopted the Bresenham algorithm for drawing between an inner and outer circle. With that algorithm as base, the strategy of drawing circles in a loop works.
Because the Bresenham algorithm can place pixels only at discrete integer coordinates, the order of visiting pixels will not be strictly in order of increasing distance. But the distance will always be within one pixel of the current circle you are drawing.
An implementation is below. That's in C, but it only uses scalars, so it shouldn't be hard to adapt to C#. The setPixel is what you do to each pixel when iterating.
void xLinePos(int x1, int x2, int y)
{
x1++;
while (x1 <= x2) setPixel(x1++, y);
}
void yLinePos(int x, int y1, int y2)
{
y1++;
while (y1 <= y2) setPixel(x, y1++);
}
void xLineNeg(int x1, int x2, int y)
{
x1--;
while (x1 >= x2) setPixel(x1--, y);
}
void yLineNeg(int x, int y1, int y2)
{
y1--;
while (y1 >= y2) setPixel(x, y1--);
}
void circle2(int xc, int yc, int inner, int outer)
{
int xo = outer;
int xi = inner;
int y = 0;
int erro = 1 - xo;
int erri = 1 - xi;
int patch = 0;
while (xo >= y) {
if (xi < y) {
xi = y;
patch = 1;
}
xLinePos(xc + xi, xc + xo, yc + y);
yLineNeg(xc + y, yc - xi, yc - xo);
xLineNeg(xc - xi, xc - xo, yc - y);
yLinePos(xc - y, yc + xi, yc + xo);
if (y) {
yLinePos(xc + y, yc + xi, yc + xo);
xLinePos(xc + xi, xc + xo, yc - y);
yLineNeg(xc - y, yc - xi, yc - xo);
xLineNeg(xc - xi, xc - xo, yc + y);
}
y++;
if (erro < 0) {
erro += 2 * y + 1;
} else {
xo--;
erro += 2 * (y - xo + 1);
}
if (y > inner) {
xi = y;
} else {
if (erri < 0) {
erri += 2 * y + 1;
} else {
xi--;
erri += 2 * (y - xi + 1);
}
}
}
if (patch) {
y--;
setPixel(xc + y, yc + y);
setPixel(xc + y, yc - y);
setPixel(xc - y, yc - y);
setPixel(xc - y, yc + y);
}
}
/*
* Scan pixels in circle in order of increasing distance
* from centre
*/
void scan(int xc, int yc, int r)
{
int i;
setPixel(xc, yc);
for (i = 0; i < r; i++) {
circle2(xc, yc, i, i + 1);
}
}
This code takes care of not visiting pixels that are in two octants by skipping coincident picels on alterante octants. (Edit: There was still abug in the original code, but it's fixed now by means of the ´patch` variable.)
There's also room for improvement: The inner circle is basically the outer circle of the previous iteration, so there's no point in calculating it twice; you could keep an array of the outer points of the previous circle.
The xLinePos functions are also a bit too complicated. There are never more than two pixels drawn in that function, usually only one.
If the roughness of the search order bothers you, you can run a more exact algorithm once at the beginning of the program, where you calculate a traversing order for all circles up to a reasonable maximum radius. You can then keep that data and use it for iterating all circles with smaller radii.

Iteration of an Unknown Number in C#

Let's say I have a formula which contains a variable that user has to guess. But at the end of formula, that variable is calculated again and if the first one and second one doesn't match, formulation has to be solved again with a new value. Shortly assume that I have a formula like this (mine is much more complex and longer than this);
double y1 = Convert.ToDouble(txtboxPredefinedY.Text);
double x, z, Ort;
double y2 = 0;
while (y1 != y2)
{
x = (Math.Pow(y1, 2)) + 10;
z = (y1 - 2) / 3;
y2 = (x / z);
Ort = (y2 + y1)/2;
y1 = Ort;
if (y1 == y2)
break;
}
txtboxResult.Text = r.ToString();
So the y1 variable I defined first has to match the last variable y2. To achieve this I calculate the whole formula and find a new y1, re-calculate formula.
I want to define a y1 value and let the application correct me. For example this code should return me a value of 3.3158. If first input is 3.3158 than y1 becomes equal to y2.
I couldn't use while iteration correctly. How can I fix this? Or maybe, how should I build my while block to give me exact equation?
When working with Double you should compare with tolerance:
double y1 = Convert.ToDouble(txtboxPredefinedY.Text);
double x, z, Ort;
double y2 = 0;
double tolerance = 0.001;
while (Math.Abs(y1 - y2) >= tolerance) {
x = (Math.Pow(y1, 2)) + 10;
z = (y1 - 2) / 3;
y2 = (x / z);
Ort = (y2 + y1)/2;
y1 = Ort;
}
Comparisons like y1 != y2 as well as y1 == y2 may fail because of round-up errors.

Drawing on a canvas a big pixels

I am writing an app which allow user to draw on a touch screen display. I am currently using the method below and it work very well. This method is producing a “high resolution image” since for almost every single pixel a line is drawn (e.g. 100, 100 -> 102, 103).
Here is my question. I’d like user to draw a “low resolution picture” (big pixels board) where you can intentionally see pixels of 50×50 (e.g. 100, 100 -> 150, 150). Does anybody have an idea on how to accomplish that? I am using Silverlight for Windows Phone. I was thinking about building a big grid of 50×50 pixels, but there might be too many controls.
void FingerMove(object sender, MouseEventArgs e)
{
if (this.IsDrawing)
{
this.DestinationPoint = e.GetPosition(paint);
Line line = new Line
{
Stroke = this.Color,
X1 = this.DestinationPoint.X,
Y1 = this.DestinationPoint.Y,
X2 = this.OriginPoint.X,
Y2 = this.OriginPoint.Y,
StrokeStartLineCap = PenLineCap.Round,
StrokeEndLineCap = PenLineCap.Round,
StrokeThickness = 15,
Opacity = 1,
};
Debug.WriteLine(string.Join(",", line.X1, line.Y1, line.X2, line.Y2));
paint.Children.Add(line);
}
this.OriginPoint = this.DestinationPoint;
}
#Amr has the right idea. I'll give you this code with the caveat that I haven't tested it at all. I took the line segment intersection algorithm from here.
First, you need to set up a list of Rectangles and add them to the canvas that are your "pixels":
private List<Rectangle> _rects = new List<Rectangle>();
private void GenerateRects()
{
int width = 300; // or whatever dimensions...
int height = 300;
int gridSize = 50;
for (int x = 0; x < width; x += gridSize)
{
for (int y = 0; y < height; y += gridSize)
{
var rect = new Rectangle
{
Opacity = 0,
Width = Math.Min(gridSize, width - x),
Height = Math.Min(gridSize, height - y),
};
Canvas.SetLeft(rect, x);
Canvas.SetTop(rect, y);
_rects.Add(rect);
this.paint.Children.Add(rect);
}
}
}
We'll need these helper methods:
class LineSegment
{
public double X1 { get; set; }
public double X2 { get; set; }
public double Y1 { get; set; }
public double Y2 { get; set; }
}
private static bool SegmentsIntersect(LineSegment A, LineSegment B)
{
double x1 = A.X1, x2 = A.X2, x3 = B.X1, x4 = B.X2;
double y1 = A.Y1, y2 = A.Y2, y3 = B.Y1, y4 = B.Y2;
double denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
if (denominator == 0)
return false;
double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
return (ua > 0 && ua < 1 && ub > 0 && ub < 1);
}
private static bool RectIntersectsLine(Rect A, LineSegment B)
{
return (SegmentsIntersect(B, new LineSegment { X1 = A.X, Y1 = A.Y, X2 = A.X, Y2 = A.Y + A.Height }) ||
SegmentsIntersect(B, new LineSegment { X1 = A.X, Y1 = A.Y + A.Height, X2 = A.X + A.Width, Y2 = A.Y + A.Height }) ||
SegmentsIntersect(B, new LineSegment { X1 = A.X + A.Width, Y1 = A.Y + A.Height, X2 = A.X + A.Width, Y2 = A.Y }) ||
SegmentsIntersect(B, new LineSegment { X1 = A.X + A.Width, Y1 = A.Y, X2 = A.X, Y2 = A.Y }) ||
RectContainsPoint(A, new Point(B.X1, B.Y1)) ||
RectContainsPoint(A, new Point(B.X2, B.Y2)));
}
private static bool RectContainsPoint(Rect A, Point B)
{
return (B.X > A.X && B.X < A.X + A.Width && B.Y > A.Y && B.Y < A.Y + A.Height);
}
Then, in the FingerMove function, we loop through each Rectangle to see if it intersects. If it does, we change its color:
void FingerMove(object sender, MouseEventArgs e)
{
if (this.IsDrawing)
{
this.DestinationPoint = e.GetPosition(paint);
LineSegment line = new LineSegment
{
X1 = this.DestinationPoint.X,
Y1 = this.DestinationPoint.Y,
X2 = this.OriginPoint.X,
Y2 = this.OriginPoint.Y
};
foreach (var rect in _rects)
{
var x = Canvas.GetLeft(rect);
var y = Canvas.GetTop(rect);
if (RectIntersectsLine(new Rect(x, y, rect.Width, rect.Height) , line))
{
rect.Opacity = 1;
rect.Fill = Color;
}
}
}
this.OriginPoint = this.DestinationPoint;
}
If you simply want to make the line thicker, just experiment with possible values of StrokeThickness untill you get the desired effect.
If you want to manually draw the line by filling up large areas of the screen say (50x50) rectangles, you could do the follwing:
divide the screen into 50x50 rectangles
check which rectangles are intersected by the line drawn by the user
only draw the rectangles from step 2
This would give you the 'snap to grid' line that you want.

Line rasterisation: Cover all pixels, regardless of line gradient?

Basically, I want to use a line algo to determine which cells to check for collisions for my raycaster.
Bresenham isn't great for this as it uses a unified-thickness approach, meaning that it ignores cells that aren't at least half-covering the line. Not great at all, because it means that some segments of my line aren't being checked for intersections with the cells, leading to errors.
I can't seem to find any "thick-line" algorithms, can anyone help me find one?
Green: What I would like.
Red: What I currently have and don't want.
I had exactly the same problem as you and found an very simple solution. Usually, Bresenham has two consecutive if's to determine whether it should increase the coordinate for the two dimensions:
public void drawLine(int x0, int y0, int x1, int y1, char ch) {
int dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2; // error value e_xy
for (;;) {
put(x0, y0, ch);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
// horizontal step?
if (e2 > dy) {
err += dy;
x0 += sx;
}
// vertical step?
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
Now all you have to do is to insert an else before the second if:
public void drawLineNoDiagonalSteps(int x0, int y0, int x1, int y1, char ch) {
int dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2;
for (;;) {
put(x0, y0, ch);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
// EITHER horizontal OR vertical step (but not both!)
if (e2 > dy) {
err += dy;
x0 += sx;
} else if (e2 < dx) { // <--- this "else" makes the difference
err += dx;
y0 += sy;
}
}
}
Now the algorithm doesn't change both coordinates at once anymore.
I haven't thoroughly tested this but it seems to work pretty well.
This thread old, but I thought it'd be worth putting this on the Internet:
// This prints the pixels from (x, y), increasing by dx and dy.
// Based on the DDA algorithm (uses floating point calculations).
void pixelsAfter(int x, int y, int dx, int dy)
{
// Do not count pixels |dx|==|dy| diagonals twice:
int steps = Math.abs(dx) == Math.abs(dy)
? Math.abs(dx) : Math.abs(dx) + Math.abs(dy);
double xPos = x;
double yPos = y;
double incX = (dx + 0.0d) / steps;
double incY = (dy + 0.0d) / steps;
System.out.println(String.format("The pixels after (%d,%d) are:", x, y));
for(int k = 0; k < steps; k++)
{
xPos += incX;
yPos += incY;
System.out.println(String.format("A pixel (%d) after is (%d, %d)",
k + 1, (int)Math.floor(xPos), (int)Math.floor(yPos)));
}
}
Without loss of generality, assume x2 >= x1, then
int x = floor(x1);
int y = floor(y1);
double slope = (x2 - x1) / (y2 - y1);
if (y2 >= y1) {
while (y < y2) {
int r = floor(slope * (y - y1) + x1);
do {
usepixel(x, y);
++x;
} while (x < r);
usepixel(x, y);
++y;
}
}
else {
while (y > y2) {
int r = floor(slope * (y - y1) + x1);
do {
usepixel(x, y);
++x;
} while (x < r);
usepixel(x, y);
--y;
}
}
The floor calls can probably be written just as a cast-to-integer.
There is an interesting article available in GPU Gems, maybe it can help you: Chapter 22. Fast Prefiltered Lines
What about Bresenham with an additional constraint that no diagonal moves are allowed: Generate the points with the traditional algorithm, then as a post-processing step insert extra steps needed to make only orthogonal movements.
You could find all the intersections your ray has with the horizontal grid lines, and then mark all the cells on a row that either have an intersection point on one side, or are between the two cells with the intersections on the row.
Finding the intersections can be done by starting from the origin, advancing the point to the first intersection (and marking the cells in the process), finding out the vector that takes you from an intersection to the next (both these operations are basic similar triangles (or trig)) and then advancing column by column until you've gone far enough. Advancing column by column involves one vector addition per column, and a small loop to fill in the cells between the ones with intersections. Replace "mark" with "process" if you're processing the cells on the fly - this algorithm is guaranteed to mark each cell only once.
The same could be done with the vertical lines, but grids are generally stored in horizontal slices so I chose that. If you're using trig, you'll need to handle straight horizontal lines with a special case.
By the way, as far as I know, this is how old grid-based raycaster "3D" games (like Wolfenstein 3D) were done. I first read about this algorithm from this book, eons ago.

Categories