Pick X points on a circle which are on screen in C#
I have a few sets of information available to me, currently:
- position on screen (Point)
- orientation of point (double, say 15 degrees)
- distance (length from point)
What I want to do is pick X (less than 6 I think) number of points in an angular spread facing the same orientation as the position with a distance of distance so that they are always on screen.
I can do this, but my implementation does not take into account the f开发者_高级运维act that some of the points end up off the screen, and all my attempts are quite poor and overly complex.
Does anyone have a good way of doing this?
EDIT: Added graphic to show what im after...
A simple way of "projecting" a point (X1, Y1) along a trajectory/orientation for a distance to X2, Y2 you can use the following;
X2 = X1 + (int)(Math.Sin(orientation) * distance);
Y2 = Y1 + (int)(Math.Cos(orientation) * distance);
Where orientation is a radian double value. You may want to round the result since (int) is a brutal way to convert to int.
If you want to pick a point X/Y that is atleast distance d from point pX, pY then you know that the hypotenuse ( SquareRoot ( (X-pX)^2 + (Y-pY)^2 ) is less than d^2.
Is X/Y less than d from pX/pY?
bool isTooClose = ( ((X - pY)*(X - pY)) + ((Y - pY)*(Y - pY)) < (d*d));
If you know the screen size, then just check the boundaries.
bool isOnScreen = ( (pY > 0) && (pX > 0) && (pX < Screen.Width) && (pY < Screen.Height));
If you want to know that a circle is completely on screen, use the above isOnScreen and subtract/add the radius of the circle to the boundary. For example
bool isCircleOnScreen = ( (pY > r) && (pX > r) && (pX < (Screen.Width - r)) && (pY < (Screen.Height - r)));
To pick a point (X2, Y2) on a circle you can use the formula at the top.
This ended up being my implementation:
private static int[] DetermineTagPointsRange(Point location, double orientation, float distance)
{
const int screenWidth = 1024;
const int screenHieght = 768;
const int sampleCount = 10;
const int totalAngleSpread = 360;
const int angleInc = totalAngleSpread / sampleCount;
var lowestAngle = -1;
var highestAngle = -1;
for (var i = 0; i < sampleCount; i++)
{
var thisAngle = angleInc*i;
var endPointX = location.X + (int)(Math.Sin(ToRad(thisAngle)) * distance);
var endPointY = location.Y - (int)(Math.Cos(ToRad(thisAngle)) * distance);
bool isOnScreen = ((endPointY > 0) && (endPointX > 0) && (endPointX < screenWidth) && (endPointY < screenHieght));
if (isOnScreen)
{
if (thisAngle <= lowestAngle || lowestAngle == -1)
lowestAngle = thisAngle;
if (thisAngle >= highestAngle || highestAngle == -1)
highestAngle = thisAngle;
}
}
return new int[] {lowestAngle, highestAngle};
}
Thanks for the help
精彩评论