My Mandelbrot Set displays wrong outlines when plotting with few iterations - c

I'm writing a program that plots the Mandelbrot set in C.
I've been able to display it and it looks fine however when I lower the number of iterations I get this effect that generates what I can only describe as "clouds":
And here's how it should look (I got it from a website) :
.
How can I make mine look like the above?
Here's the code that plots a single point:
double getFracPoint(double x,double y){
//scale x and y
x = x * ((plotEnd.x-plotStart.x) / SCREENWIDTH) + plotStart.x;
y = y * ((plotEnd.y-plotStart.y) / SCREENHEIGHT) + plotStart.y;
x/=zoom;
y/=zoom;
//instead of using the complex number library of the C standard
//I decided to use regular numbers as it turns out to be faster.
//The first number is the real part the second number is the imaginary
//part.
double z[2];
z[0] = z[1] = 0;
double c[2];
c[0] = x;
c[1] = y;
int n = 0;
for(int i = 0; i < ITERS; i++,n++){
//if it's out of boundaries we are sure it does not belong to the set.
if(z[0] > 4 || -4 > z[0] || -4 > z[1] || 4 < z[1])
break;
double t = z[1]; //store z[1]
//multiply z to itself
z[1] = (z[0] * z[1]) + (z[0] * z[1]);
z[0] = z[0] * z[0] + -(t*t);
//add C to Z
z[0] += c[0];
z[1] += c[1];
}
return (double)n/(double)ITERS;
}
What am I doing wrong here?

Your "out of bounds" test checks that z falls within a square of radius 4:
if(z[0] > 4 || -4 > z[0] || -4 > z[1] || 4 < z[1])
The typical test, however, is to check the Euclidean distance from origin (i.e. the complex number norm, i.e. check that it falls within a circle of radius 4):
if(z[0]*z[0] + z[1]*z[1] > 4*4)

Related

How to find out whether the largest rectangle contains other smaller rectangles

I have to create a program that generates 3 random rectangles and finds the area of ​​each using the coordinates of the upper left point and the bottom right point (coordinates are random and between (-50;50).
The problem is that it must determine the largest rectangle and indicate whether the other two/one are/is located in it, if not - display the corresponding message.
It's not a overlap, other rectangles/rectangle must be fully in the biggest one.
Here is what I've already done:
#include <stdio.h>
#include <locale>
struct Point {
int x;
int y;
};
struct Rectangle {
struct Point topLeft;
struct Point botRight;
};
int Area(struct Rectangle r) {
int length, breadth;
length = r.botRight.x - r.topLeft.x;
breadth = r.topLeft.y - r.botRight.y;
return length * breadth;
}
int main() {
srand(time(NULL));
struct Rectangle r1, r2, r3;
r1.topLeft.x = -50 + rand() % 50;
r1.topLeft.y = -50 + rand() % 50;
r1.botRight.x = -50 + rand() % 50;
r1.botRight.y = -50 + rand() % 50;
while (r1.botRight.x <= r1.topLeft.x) {
r1.botRight.x = -50 + rand() % 50;
}
while (r1.topLeft.y <= r1.botRight.y) {
r1.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 1----------\n");
printf("\tTop left point is x = %d y = %d\n", r1.topLeft.x, r1.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r1.botRight.x, r1.botRight.y);
printf("\tArea is %d\n", Area(r1));
r2.topLeft.x = -50 + rand() % 50;
r2.topLeft.y = -50 + rand() % 50;
r2.botRight.x = -50 + rand() % 50;
r2.botRight.y = -50 + rand() % 50;
while (r2.botRight.x <= r2.topLeft.x) {
r2.botRight.x = -50 + rand() % 50;
}
while (r2.topLeft.y <= r2.botRight.y) {
r2.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 2----------\n");
printf("\tTop left point is x = %d y = %d\n", r2.topLeft.x, r2.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r2.botRight.x, r2.botRight.y);
printf("\tArea is %d\n", Area(r2));
r3.topLeft.x = -50 + rand() % 50;
r3.topLeft.y = -50 + rand() % 50;
r3.botRight.x = -50 + rand() % 50;
r3.botRight.y = -50 + rand() % 50;
while (r3.botRight.x <= r3.topLeft.x) {
r3.botRight.x = -50 + rand() % 50;
}
while (r3.topLeft.y <= r3.botRight.y) {
r3.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 3----------\n");
printf("\tTop left point is x = %d y = %d\n", r3.topLeft.x, r3.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r3.botRight.x, r3.botRight.y);
printf("\tArea is %d\n\n", Area(r3));
if (Area(r1) >= Area(r2) && Area(r1) >= Area(r3))
printf("\tRECTANGLE 1 HAS A BIGGEST AREA --> %d\n", Area(r1));
if (Area(r2) >= Area(r1) && Area(r2) >= Area(r3))
printf("\tRECTANGLE 2 HAS A BIGGEST AREA --> %d\n", Area(r2));
if (Area(r3) >= Area(r1) && Area(r3) >= Area(r2))
printf("\tRECTANGLE 3 HAS A BIGGEST AREA --> %d\n", Area(r3));
}
Item 1:
There really is no need to use a point struct. The problem is simple enough to merely keep track to 2 values for x and 2 values for y. While we're at it, the area of each rectangle could be stored, too.
typedef struct {
int x0, x1, y0, y1, area;
} Rect;
Notice that there is no bias in the names x0 and x1. Attempting to control which coordinate pair is "top left" and which is "bottom right" is difficult. A rectangle has two horizonal edges (importantly they are not equal). Merely store the lower and higher values of y. Similarly, store only the "left & right" values of the vertical edges x... This makes life simple.
Item 2:
It's worthwhile, if possible, to think and to code without immediate concern for negative numbers.
const int wid = 101; // for -50 to +50
const int hgt = 101; // for -50 to +50
Item 3:
Generating 3 sets of values by copy/paste of code indicates that this should be done in a function called 3 times. (Imagine the next assignment is "do the same for 20 rectangles.")
Below includes two bonus "branchless" functions that return the minimum or maximum of two integer values.
int min( int x, int y ) { return y ^ ((x^y) & -(x<y)); }
int max( int x, int y ) { return y ^ ((x^y) & -(x>y)); }
void genRect( Rect *r ) {
int v0 = rand() % wid; // A random horizontal value (a vertical line)
int v1 = ( v0 + 1 + rand()%(wid-3) ) % wid; // A different horizontal value
r->x0 = min( v0, v1 ); // the lower of the two values
r->x1 = max( v0, v1 ); // and the higher
// do the same for horizontal edges (vertical boundaries)
v0 = rand() % hgt;
v1 = ( r->y0 + 1 + rand()%(hgt-3) ) % hgt;
r->y0 = min( v0, v1 );
r->y1 = max( v0, v1 );
// calc and store the area, too
r->area = (r->x1 - r->x0) * (r->y1 - r->y0);
}
Important to note is that the calculation of the second value for x and for y will never be the same as the first value. The OP code had the potential to generate a "left edge" at the right boundary, then enter an endless loop trying to generate a value that was always rejected.
As suggested in the other answer, it is now easy to qsort() the small array (big rectangles may contain smaller ones).
The search for one inside another is much simpler with comparing x0 against x0 and x1 against x1... (Likewise for the y dimension).
Because the code has been dealing with (0,0) to (100,100) inclusive, the output is where to tailor to suit the assignment.
void print( int n, Rect *r ) {
printf( "Rect %d: BotLft(%d,%d) TopRgt(%d, %d) Area %d\n",
n, r->x0 - 50, r->y0 - 50, r->x1 - 50, r->y1 - 50, r->area );
}
I leave it as an exercise for the reader to eliminate the arbitrary constants above.
Finally, it is a trivial exercise to determine if the xy boundaries of one smaller rectangle fall completely within the xy boundaries of a larger one. A single if() statement with 4 conditions would suffice.
PS: I completed the code and ran it a few times. It was only by increasing the number of candidate rectangles that luck would have it that a larger did contain a smaller. The sample size of only 3 rectangles will take a lot of iterations to, by chance, define one inside another...
First, you need an array of Rectangles and sort them by their area:
struct Rectangle rects[N];
//return:
//- negative value, if a < b
//- zero, if a == b
//- positive value, if a > b
int rect_cmp(const void *a, const void *b)
{
return Area(*((struct Rectangle*)a)) - Area(*((struct Rectangle*)b));
}
//use qsort: https://en.cppreference.com/w/c/algorithm/qsort
qsort(rects, N, sizeof(struct Rectangle), rect_cmp);
The array rects will now contain all the rectangles, sorted in ascending order, from lowest to highest area.
From now on, all you have to do is to iterate over the array and test if the largest rectangle encloses the following, subsequent rectangles.
The following code picks the largest rectangle and iterates over all subsequent rectangles to test if they are inside. Then pick the second largest and do the testing again, and so on, e.g.
for (int i=N-1; i >= 0; --i) { //current largest rectangle
for (int j=i-1; j >= 0; --j) { //test if the next rectangles in sequence are inside
if (contains(rects[i], rects[j])) {
//rect[j] inside rect[i]
} else {
//rect[j] not inside rect[i]
}
}
}
A possible outcome could be that the first rect neither contains the second and third rect but the second rect could contain the third one.

Ray Tracing calculation in C

I'm new to ray tracing and trying to program one in C. But My program keep on showing a dot (around 1-3 pixel) of the sphere in the wrong places and now I'm confused. This feels like a very stupid question, but I'm confused about exactly how big is 1 radius of a sphere? What I mean by that is if the radius is 1, the circle is 2 pixels?
I know all the calculations and I triple checked if I had any errors in my codes. but just incase, here is part of my codes:
Directions:
//size: 1024x768, view point (512 384 1), screen (0 0 0) to (1024 768 0)
ray[0] = x - start_x;
ray[1] = y - start_y;
ray[2] = 0 - start_z;
//normalize
double length;
length = (sqrt((ray[0]*ray[0]) + (ray[1]*ray[1]) + (ray[2]*ray[2])));
ray[0] = ray[0]/length;
ray[1] = ray[1]/length;
ray[2] = ray[2]/length;
Intersection:
temp = top; //my struct with sphere data, _x, _y, _z, _r, _red, _green, _blue
//x and y is the current pixel value
while (temp != NULL) {
x_diff = start_x - temp->_x + 0.0;
y_diff = start_y - temp->_y + 0.0;
z_diff = start_z - temp->_z + 0.0;
//a = 1 because my direction is a normalized
b = 2.0 * ((rayVector[0] * x_diff) + (rayVector[1] * y_diff) + (rayVector[2] * z_diff));
c = (x_diff * x_diff * 1.0) + (y_diff * y_diff) + (z_diff * z_diff) - (temp->_r * temp->_r);
check = (b * b) - (4.0 * c);
if (check < 0) { //0
pixels[width][height][0] = 0.0;
pixels[width][height][1] = 0.0;
pixels[width][height][2] = 0.0;
}
else if (check == 0) { //1
r1 = (b * -1.0) /2.0;
if (r1 < nearest_z) {
nearest_z = r1;
pixels[width][height][0] = temp->_red;
pixels[width][height][1] = temp->_green;
pixels[width][height][2] = temp->_blue;
}
}
else { //2
r1 = ((b * -1.0) + sqrt(check))/2.0;
r2 = ((b * -1.0) - sqrt(check))/2.0;
if ((r1 < r2) && (r1 < nearest_z)) {
nearest_z = r1;
pixels[width][height][0] = 255.0;
pixels[width][height][1] = 0;
pixels[width][height][2] = 0;
}
else if ((r2 < r1) && (r2 < nearest_z)) {
nearest_z = r2;
pixels[width][height][0] = temp->_red;
pixels[width][height][1] = temp->_green;
pixels[width][height][2] = temp->_blue;
}
}
temp = temp->next;
}
I haven't done any lightings yet since the flat colouring it doesn't work. I'm new to openGL so expect me to miss some common functions in the codes. Thanks in advance.
Edit:
I only have one sphere currently, but my output looks like: img1
I was expecting a bigger circle? Also, I had a printf for each intersection (if there is) and when I manually plot in a paper, it is a 4x5 pixel square. But there are 4 dots in the output.
Edit 2: I change the size of the sphere to: x = 512 y = 384 z = -21 r = 30, it gave me this:
img2
Again, I only have one sphere and there are 4 in the image. Also, there are holds between the lines?
If I change the z value to -20, now my output is all white (colour of sphere).
I use glDrawPixels(1024,768,GL_RGB,GL_FLOAT,pixels); to draw
I had a RBG output file, everything seems to be in the right place. but when I draw on the program, it is off.

Issues trying to scale up sine wave in c

Hopefully somebody can point out why this isnt working or where i may be going wrong. Im producing a sine wave by way of for loops in c. The ultimate aim is to produce a .ppm file displaying this. Im working on a 1 to 1 pixel ratio. My box is 128H*256W. The sine wave is displaying but due to the answer being produced in rads the result is a very small two pixel high "wave". I assume this is due to the rad values being between 1 and -1. This is my code. I tried just simply timesing by a greater number to increase the size of the y values in the hopes it would plot correctly but this does little or worse causes the applicattion to stop running. Any ideas very welcome.
for (x = 0; x < H; x++)
{
y =(int) H/2+ sin(x*(2*PI));
y = y * 50;
image[y][x][1] = 0;
image[y][x][2] = 255;
image[y][x][3] = 0;
}
EDIT: This is what is being produced in the .ppm file when opened via infraview. Also im #defining PI 3.141592653589793. Again is this possibly an area of issue.
first sine wave .ppm
I conject that y is an int.
Your sin value will be truncated to an integer; 0 for most cases, but very occasionally -1 or +1.
The fix is simple: use a floating point for y, and cast once you want to use it as an array index.
As y is commented to be an int and H appears to be an int constant, perform calculations as double first, then convert to int.
Use round to avoid truncations effect of simply casting a double to int.
y = (int) round(50*(sin(x*(2*PI)) + H/2.0));
Original code also scaled H/2 by 50. I think code may only want to scale the sin() and not the offset.
#define XOffset 0
#define YOffset (H/2.0)
#define XScale (2*PI)
#define YScale 50
y = (int) round(YScale*sin(x*XScale + XOffset) + YOffset);
Defensive programming tip: since y is calculated, insure it is in the valid index range before using it as an index.
// Assuming image` is a fixed sized array
#define Y_MAX (sizeof image/sizeof image[0] - 1)
if (y >= 0 && y <= Y_MAX) {
image[y][x][1] = 0;
image[y][x][2] = 255;
image[y][x][3] = 0;
}
y = y * 50, where y = H/2 (+ or - 1) gives you y around 25*H, which is out of bounds.
A closer approximation is this:
y = (int) ( H/2 + H/2 * sin(x*2*PI) )
which gives the extremes H/2 - H/2 = 0 and H/2 + H/2 = H, which is one too high. So, we scale not by H/2 but by (H-1)/2:
y = (int) ( H/2 + (H-1)/2 * sin(x*2*PI) )
which gives us an y-range 0 to H-1.
To have a bit more control over the period of the sine wave, let's write it like this:
sin( x/W * 2*PI )
Here, we divide x by W so that x/W itself will range from 0 to 1.
It is then scaled by 2*PI to produce a range from 0 to 2π. This will plot one period of the sine wave across the entire width. If we introduce a frequency factor f:
sin( f * x/W * 2*PI )
we can now say how many periods to draw, even fractions. For f=1 it will draw one period, f=2 two periods, and f=1 half a period.
Here's a small JS demo showing three values for f: 0.5 is red, 1 is green and 2 is white:
var c = document.getElementById('c'),
W = c.width,
H = c.height,
ctx = c.getContext('2d'),
image = ctx.getImageData(0,0,W,H);
for ( var i = 0; i < image.data.length; i +=4) {
image.data[i+0]=0;
image.data[i+1]=0;
image.data[i+2]=0;
image.data[i+3]=255;
}
function render(image,colidx,f) {
for ( var x = 0; x < W; x++ )
{
var y = H/2 - Math.round( H/2 * Math.sin(f*x/W*Math.PI*2) );
if ( y >=0 && y < H ) {
if ( colidx & 1 ) image.data[ 4*( W*y + x ) + 0] = 255;
if ( colidx & 2 ) image.data[ 4*( W*y + x ) + 1] = 255;
if ( colidx & 4 ) image.data[ 4*( W*y + x ) + 2] = 255;
}
}
}
render(image,1,0.5);
render(image,2,1);
render(image,7,2);
ctx.putImageData(image, 0,0);
canvas{ border: 1px solid red;}
<canvas id='c' width='256' height='128'></canvas>
The code then becomes:
float f = 1;
for (x = 0; x < W; x++)
{
y = (int) ( (H-1)/2 + (H-1)/2 * sin(f * x/W * 2*PI) );
image[y][x][0] = 0;
image[y][x][1] = 255;
image[y][x][2] = 0;
}

Smallest solution to system of linear equations

I need to find the smallest number of steps it takes to get between two points in a grid. If you are positioned at the center, and you can only move in 8 directions to the integer points surrounding you, then what's the least number of steps to take to get to a destination point?
I have a solution for this, but it is massively ugly and I'm honestly a bit ashamed of it:
/**
* #details Each point in the graph is a linear combination of these vectors:
*
* [x] = a[0] + b[1] + c[1] + d[ 1]
* [y] [1] [1] [0] [-1]
*
* EQ1: c + b + d == x
* EQ2: a + b - d == y
*
* Any path can be simplified to involve at most two of these variables, so we
* can solve the linear equations above with the knowledge that at least two of
* a, b, c, and d are 0. The sum of the absolute value of the coefficients is
* the number of steps taken in the grid.
*/
unsigned min_distance(point_t start, point_t goal)
{
int a, b, c, d;
int swap, steps;
int x, y;
x = goal.x - start.x;
y = goal.y - start.y;
/* Possible simple shortcuts */
if (x == 0 || y == 0) {
steps = abs(x) + abs(y);
} else if (abs(x) == abs(y)) {
steps = abs(y);
} else {
b = x, a = y - b;
steps = abs(a) + abs(b);
c = x, a = y;
swap = abs(a) + abs(c);
if (steps > swap)
steps = swap;
d = x, a = y + d;
swap = abs(a) + abs(d);
if (steps > swap)
steps = swap;
b = y, c = x - b;
swap = abs(b) + abs(c);
if (steps > swap)
steps = swap;
b = (x + y) / 2, d = b - y;
swap = abs(b) + abs(d);
if ((x + y) % 2 == 0 && steps > swap)
steps = swap;
d = -y, c = x - d;
swap = abs(c) + abs(d);
if (steps > swap)
steps = swap;
}
return steps;
}
The comment at the top explains the actual algorithm: represent each valid step as a column vector in a matrix, then find the smallest solution to the resulting system of linear equations.
In this case I saw the best answer would use at most two variables, and solved the equation six times by setting different combinations of the variables to 0. That's too specific! I want to be able to change the rules about which steps are valid and still be able to find the min distance.
EDIT: I realize this is a very poor simple example of what I'm trying to do, because of how easy it is to simplify the problem in this case. The goal is to calculate the number of steps given arbitrary stepping rules. If it the allowed steps instead looked like this then I'd start with a different matrix ([0 2 3 4 x; 1 2 0 -4 y]) and find the least solution to a different system of equations (2b + 3c + 4d = x, a + 2b - 4d = y). I'm actually trying to write a procedure that can work with any set of vectors to find the minimum number of steps.
...Any advice or criticism?

Intersection points of line bisector with rectangle

I've been trying to wrap my head around this the whole day...
Basically, I have the coordinates of two points that will always be inside a rectangle.
I also know the position of the corners of the rectangle. Those two entry points are given at runtime.
I need an algorithm to find the 2 points where the bisector line made by the line segment between the given points intersects that rectangle.
Some details:
In the above image, A and B are given by their coordinates: A(x1, y1) and B(x2, y2). Basically, I'll need to find position of C and D.
Red X is the center of the AB segment. This point (let's call it center) will have to be on the CD line.
What I've did:
found the center:
center.x = (A.x+B.x)/2;
center.y = (A.y+B.y)/2;
found CD slope:
AB_slope = A.y - B.y / A.x - B.x;
CD_slope = -1/AB_slope;
Knowing the center and CD slope gave me the equation of CD and such, I've attempted to find a solution by trying the position of the points on all the 4 borders of the rectangle.
However, for some reason it doesn't work: every time I have a solution let's say for C, D is plotted outside or vice-versa.
Here are the equations I'm using:
knowing x:
y = (CD_slope * (x - center.x)) + center.y;
if y > 0 && y < 512: #=> solution found!
knowing y:
x = (y - center.y + CD_slope*center.x)/CD_slope;
if x > 0 && x < 512: #=> solution found!
From this, I could also end up with another segment (let's say I've found C and I know the center), but geometry failed on me to find the extension of this segment till it intersects the other side of the rectangle.
Updated to include coding snippet
(see comments in main function)
typedef struct { double x; double y; } Point;
Point calculate_center(Point p1, Point p2) {
Point point;
point.x = (p1.x+p2.x)/2;
point.y = (p1.y+p2.y)/2;
return point;
}
double calculate_pslope(Point p1, Point p2) {
double dy = p1.y - p2.y;
double dx = p1.x - p2.x;
double slope = dy/dx; // this is p1 <-> p2 slope
return -1/slope;
}
int calculate_y_knowing_x(double pslope, Point center, double x, Point *point) {
double min= 0.00;
double max= 512.00;
double y = (pslope * (x - center.x)) + center.y;
if(y >= min && y <= max) {
point->x = corner;
point->y = y;
printf("++> found Y for X, point is P(%f, %f)\n", point->x, point->y);
return 1;
}
return 0;
}
int calculate_x_knowing_y(double pslope, Point center, double y, Point *point) {
double min= 0.00;
double max= 512.00;
double x = (y - center.y + pslope*center.x)/pslope;
if(x >= min && x <= max) {
point->x = x;
point->y = y;
printf("++> found X for Y, point is: P(%f, %f)\n", point->x, point->y);
return 1;
}
return 0;
}
int main(int argc, char **argv) {
Point A, B;
// parse argv and define A and B
// this code is omitted here, let's assume:
// A.x = 175.00;
// A.y = 420.00;
// B.x = 316.00;
// B.y = 62.00;
Point C;
Point D;
Point center;
double pslope;
center = calculate_center(A, B);
pslope = calculate_pslope(A, B);
// Here's where the fun happens:
// I'll need to find the right succession of calls to calculate_*_knowing_*
// for 4 cases: x=0, X=512 #=> call calculate_y_knowing_x
// y=0, y=512 #=> call calculate_x_knowing_y
// and do this 2 times for both C and D points.
// Also, if point C is found, point D should not be on the same side (thus C != D)
// for the given A and B points the succession is:
calculate_y_knowing_x(pslope, center, 0.00, C);
calculate_y_knowing_x(pslope, center, 512.00, D);
// will yield: C(0.00, 144.308659), D(512.00, 345.962291)
// But if A(350.00, 314.00) and B(106.00, 109.00)
// the succesion should be:
// calculate_y_knowing_x(pslope, center, 0.00, C);
// calculate_x_knowing_y(pslope, center, 512.00, D);
// to yield C(0.00, 482.875610) and D(405.694672, 0.00)
return 0;
}
This is C code.
Notes:
The image was drawn by hand.
The coordinate system is rotated 90° CCW but should not have an impact on the solution
I'm looking for an algorithm in C, but I can read other programming languages
This is a 2D problem
You have the equation for CD (in the form (y - y0) = m(x - x0)) which you can transform into the form y = mx + c. You can also transform it into the form x = (1/m)y - (c/m).
You then simply need to find solutions for when x=0, x=512, y=0, y=512.
The following code should do the trick:
typedef struct { float x; float y; } Point;
typedef struct { Point point[2]; } Line;
typedef struct { Point origin; float width; float height; } Rect;
typedef struct { Point origin; Point direction; } Vector;
Point SolveVectorForX(Vector vector, float x)
{
Point solution;
solution.x = x;
solution.y = vector.origin.y +
(x - vector.origin.x)*vector.direction.y/vector.direction.x;
return solution;
}
Point SolveVectorForY(Vector vector, float y)
{
Point solution;
solution.x = vector.origin.x +
(y - vector.origin.y)*vector.direction.x/vector.direction.y;
solution.y = y;
return solution;
}
Line FindLineBisectorIntersectionWithRect(Rect rect, Line AB)
{
Point A = AB.point[0];
Point B = AB.point[1];
int pointCount = 0;
int testEdge = 0;
Line result;
Vector CD;
// CD.origin = midpoint of line AB
CD.origin.x = (A.x + B.x)/2.0;
CD.origin.y = (A.y + B.y)/2.0;
// CD.direction = negative inverse of AB.direction (perpendicular to AB)
CD.direction.x = (B.y - A.y);
CD.direction.y = (A.x - B.x);
// for each edge of the rectangle, check:
// 1. that an intersection with CD is possible (avoid division by zero)
// 2. that the intersection point falls within the endpoints of the edge
// 3. if both check out, use that point as one of the solution points
while ((++testEdge <= 4) && (pointCount < 2))
{
Point point;
switch (testEdge)
{
case 1: // check minimum x edge of rect
if (CD.direction.x == 0) { continue; }
point = SolveVectorForX(CD, rect.origin.x);
if (point.y < rect.origin.y) { continue; }
if (point.y > (rect.origin.y + rect.height)) { continue; }
break;
case 2: // check maximum x edge of rect
if (CD.direction.x == 0) { continue; }
point = SolveVectorForX(CD, rect.origin.x + rect.width);
if (point.y < rect.origin.y) { continue; }
if (point.y > (rect.origin.y + rect.height)) { continue; }
break;
case 3: // check minimum y edge of rect
if (CD.direction.y == 0) { continue; }
point = SolveVectorForY(CD, rect.origin.y);
if (point.x < rect.origin.x) { continue; }
if (point.x > (rect.origin.x + rect.width)) { continue; }
break;
case 4: // check maximum y edge of rect
if (CD.direction.y == 0) { continue; }
point = SolveVectorForY(CD, rect.origin.y + rect.height);
if (point.x < rect.origin.x) { continue; }
if (point.x > (rect.origin.x + rect.width)) { continue; }
break;
};
// if we made it here, this point is one of the solution points
result.point[pointCount++] = point;
}
// pointCount should always be 2
assert(pointCount == 2);
return result;
}
We start from the center point C and the direction of AB, D:
C.x = (A.x+B.x) / 2
C.y = (A.y+B.y) / 2
D.x = (A.x-B.x) / 2
D.y = (A.y-B.y) / 2
then if P is a point on the line, CP must be perpendicular to D. The equation of the line is:
DotProduct(P-C, D) = 0
or
CD = C.x*D.x + C.y*D.y
P.x * D.x + P.y * D.y - CD = 0
for each of the four edges of the square, we have an equation:
P.x=0 -> P.y = CD / D.y
P.y=0 -> P.x = CD / D.x
P.x=512 -> P.y = (CD - 512*D.x) / D.y
P.y=512 -> P.x = (CD - 512*D.y) / D.x
Except for degenerate cases where 2 points coincide, only 2 of these 4 points will have both P.x and P.y between 0 and 512. You'll also have to check for the special cases D.x = 0 or D.y = 0.

Resources