问题
This is an offshoot of another question and has to do with Keith Randall's answer to the problem. Please do have a quick look at the image there to see what the function below is trying to do.
In short, any two points on a 2D grid would have two diagonal intersections if x2 != x1 and y2 != y1. I implemented the following function but cannot figure out how to determine which cell to subtract delta from and which to add to. As a result, for some pair of coordinates, the results are accurate while for others they are reversed.
// This class is the same as [Point] except
// it uses BigInteger instead of Int32 types.
public class Cell
{
System.Numerics.BigInteger X = 0;
System.Numerics.BigInteger Y = 0;
}
public List<Cell> GetIntersections (Cell c1, Cell c2)
{
List<Cell> cells = new List<Cell>();
System.Numerics.BigInteger delta = 0;
System.Numerics.BigInteger deltaHalf = 0;
System.Numerics.BigInteger width = 0;
System.Numerics.BigInteger height = 0;
width = System.Numerics.BigInteger.Abs(c2.X - c1.X);
height = System.Numerics.BigInteger.Abs(c2.Y - c1.Y);
delta = System.Numerics.BigInteger.Abs(height - width);
deltaHalf = System.Numerics.BigInteger.Divide(delta, 2);
// INTRODUCE CONDITIONS HERE TO DETERMINE +/- COMBINATION.
cells.Add(new Cell(c1.X - deltaHalf, c1.Y + deltaHalf));
cells.Add(new Cell(c2.X + deltaHalf, c2.Y - deltaHalf));
return (cells);
}
At first I thought this was a simple gradient/slope issue but I cannot seem to find a consistent correlation between slope and +/- deltaHalf combinations.
IMPORTANT: Please note that acceptable answers should only do x1, y1, x2, y2 comparisons. Actually calculating the slope of the line is not an option due to performance penalties. We are already doing a division by 2 and cannot afford another.
回答1:
You can't simply use the hypoteneuse (delta). You must discover the triangle altitude. And, as you'll see, to get the altitude you must calculate the legs (using Pythagorean theorem).
However, to achieve this using BigInteger will need some extra help, because there will be a square root. I used the solution provided here (Newton Raphson method).
Let's get those values:
// leg = sqrt(hypoteneuse²)/2)
triangleLeg = SqRtN(System.Numerics.BigInteger.Divide(System.Numerics.BigInteger.Pow(delta, 2), 2));
// altitude = leg²/hypoteneuse
triangleAltitude = System.Numerics.BigInteger.Divide(System.Numerics.BigInteger.Pow(triangleLeg, 2), delta);
Now, to the points, we are going to use deltaHalf (for Y) and triangleAltitude (for
X).
I've done this way:
// INTRODUCE CONDITIONS HERE TO DETERMINE +/- COMBINATION.
cells.Add(
new Cell()
{
X = c1.X < c2.X? c1.X - triangleAltitude : c1.X + triangleAltitude,
Y = c1.Y < c2.Y ? c1.Y - deltaHalf : c1.Y + deltaHalf
}
);
cells.Add(
new Cell()
{
X = c2.X < c1.X ? c2.X - triangleAltitude : c2.X + triangleAltitude,
Y = c2.Y < c1.Y ? c2.Y - deltaHalf : c2.Y + deltaHalf
}
);
Any feedback will be appreciated.
回答2:
I knew the answer was somewhere in simple comparisons instead of having to calculate hypotenuse.
public List<Cell> GetCellIntersections (Cell cell1, Cell cell2)
{
Cell c1 = null;
Cell c2 = null;
List<Cell> cells = null;
System.Numerics.BigInteger delta = 0;
System.Numerics.BigInteger deltaHalf = 0;
System.Numerics.BigInteger width = 0;
System.Numerics.BigInteger height = 0;
cells = new List<Cell>();
// Sorting on y reduces conditions from 8 to 4.
if (cell1.Y < cell2.Y)
{
c1 = cell1;
c2 = cell2;
}
else
{
c1 = cell2;
c2 = cell1;
}
if ((c1.X != c2.X) && (c1.Y != c2.Y))
{
width = System.Numerics.BigInteger.Abs(c2.X - c1.X);
height = System.Numerics.BigInteger.Abs(c2.Y - c1.Y);
delta = System.Numerics.BigInteger.Abs(height - width);
deltaHalf = System.Numerics.BigInteger.Divide(delta, 2);
if ((c1.X < c2.X) && (c1.Y < c2.Y))
{
if (width < height)
{
cells.Add(new Cell(this, c1.X - deltaHalf, c1.Y + deltaHalf));
cells.Add(new Cell(this, c2.X + deltaHalf, c2.Y - deltaHalf));
}
else
{
cells.Add(new Cell(this, c1.X + deltaHalf, c1.Y - deltaHalf));
cells.Add(new Cell(this, c2.X - deltaHalf, c2.Y + deltaHalf));
}
}
else
{
if (width < height)
{
cells.Add(new Cell(this, c1.X + deltaHalf, c1.Y + deltaHalf));
cells.Add(new Cell(this, c2.X - deltaHalf, c2.Y - deltaHalf));
}
else
{
cells.Add(new Cell(this, c1.X - deltaHalf, c1.Y - deltaHalf));
cells.Add(new Cell(this, c2.X + deltaHalf, c2.Y + deltaHalf));
}
}
}
return (cells);
}
来源:https://stackoverflow.com/questions/11852284/how-to-determine-sign-when-calculating-diagonal-intersections-between-two-po