Python 以给定角度在矩形上查找点
我试着在一个矩形物体上画一个梯度,有一个给定的角度(θ),梯度的末端接触到矩形的周长 我原以为使用切线会管用,但我很难解决这些问题。是否有一个简单的算法,我只是错过了 最终结果 这是(角度,RectX1,RectX2,RectY1,RectY2)的函数。我希望它以[x1,x2,y1,y2]的形式返回,这样梯度就会画出正方形。Python 以给定角度在矩形上查找点,python,math,graphics,geometry,Python,Math,Graphics,Geometry,我试着在一个矩形物体上画一个梯度,有一个给定的角度(θ),梯度的末端接触到矩形的周长 我原以为使用切线会管用,但我很难解决这些问题。是否有一个简单的算法,我只是错过了 最终结果 这是(角度,RectX1,RectX2,RectY1,RectY2)的函数。我希望它以[x1,x2,y1,y2]的形式返回,这样梯度就会画出正方形。 在我的问题中,如果原点是0,那么x2=-x1和y2=-y1。但它并不总是在原点上。根据您的图片,我将假设矩形的中心是(0,0),右上角是(w,h)。然后连接(0,0)到(
在我的问题中,如果原点是0,那么x2=-x1和y2=-y1。但它并不总是在原点上。根据您的图片,我将假设矩形的中心是(0,0),右上角是(w,h)。然后连接(0,0)到(w,h)的线与X轴形成一个角φ,其中tan(φ)=h/w 假设θ>φ,我们正在寻找点(x,y),您绘制的线与矩形的上边缘相交。那么y/x=tan(θ)。我们知道y=h,所以,解x,我们得到x=h/tan(θ) 如果θ<φ,则直线在(x,y)处与矩形的右边缘相交。这一次,我们知道x=w,所以y=tan(θ)*w.我们把a和b称为矩形边,把(x0,y0)称为矩形中心的坐标 您需要考虑四个地区: Region from to Where ==================================================================== 1 -arctan(b/a) +arctan(b/a) Right green triangle 2 +arctan(b/a) π-arctan(b/a) Upper yellow triangle 3 π-arctan(b/a) π+arctan(b/a) Left green triangle 4 π+arctan(b/a) -arctan(b/a) Lower yellow triangle 地区从哪里到哪里 ==================================================================== 1-arctan(b/a)+arctan(b/a)直角绿色三角形 2+arctan(b/a)π-arctan(b/a)上黄色三角形 3π-arctan(b/a)π+arctan(b/a)左绿色三角形 4π+arctan(b/a)-arctan(b/a)下黄色三角形 使用一点三角函数fu,我们可以得到每个区域中所需交点的坐标 因此Z0是区域1和3交点的表达式
Z1是区域2和4交点的表达式 所需的线从(X0,Y0)传递到Z0或Z1,具体取决于区域。记住Tan(φ)=Sin(φ)/Cos(φ) 区域中的线从开始到结束 ====================================================================== 1和3(X0,Y0)(X0+a/2,(a/2*Tan(φ))+Y0 2和4(X0,Y0)(X0+b/(2*Tan(φ)),b/2+Y0) 只需注意每个象限中的Tan(φ)符号,并且始终从正x轴逆时针测量角度 HTH!这个问题有一个很好的答案(更具程序性的iOS/Objective-C),涉及以下步骤:
+ (CGPoint) edgeOfView: (UIView*) view atAngle: (float) theta
{
// Move theta to range -M_PI .. M_PI
const double twoPI = M_PI * 2.;
while (theta < -M_PI)
{
theta += twoPI;
}
while (theta > M_PI)
{
theta -= twoPI;
}
// find edge ofview
// Ref: http://stackoverflow.com/questions/4061576/finding-points-on-a-rectangle-at-a-given-angle
float aa = view.bounds.size.width; // "a" in the diagram
float bb = view.bounds.size.height; // "b"
// Find our region (diagram)
float rectAtan = atan2f(bb, aa);
float tanTheta = tan(theta);
int region;
if ((theta > -rectAtan)
&& (theta <= rectAtan) )
{
region = 1;
}
else if ((theta > rectAtan)
&& (theta <= (M_PI - rectAtan)) )
{
region = 2;
}
else if ((theta > (M_PI - rectAtan))
|| (theta <= -(M_PI - rectAtan)) )
{
region = 3;
}
else
{
region = 4;
}
CGPoint edgePoint = view.center;
float xFactor = 1;
float yFactor = 1;
switch (region)
{
case 1: yFactor = -1; break;
case 2: yFactor = -1; break;
case 3: xFactor = -1; break;
case 4: xFactor = -1; break;
}
if ((region == 1)
|| (region == 3) )
{
edgePoint.x += xFactor * (aa / 2.); // "Z0"
edgePoint.y += yFactor * (aa / 2.) * tanTheta;
}
else // region 2 or 4
{
edgePoint.x += xFactor * (bb / (2. * tanTheta)); // "Z1"
edgePoint.y += yFactor * (bb / 2.);
}
return edgePoint;
}
Javascript版本:
功能边视图(矩形、度){
var twoPI=Math.PI*2;
varθ=摄氏度*数学π/180;
while(θ<-Math.PI){
θ+=twoPI;
}
while(theta>Math.PI){
θ-=twoPI;
}
var rectAtan=Math.atan2(rect.height,rect.width);
var tanTheta=数学tan(θ);
var区域;
如果((θ>-rectAtan)&&(θrectAtan)&&&(θ(Math.PI-rectAtan))| |(θ对于Java,LibGDX。为了提高精度,我将角度设为两倍
public static Vector2 projectToRectEdge(double angle, float width, float height, Vector2 out)
{
return projectToRectEdgeRad(Math.toRadians(angle), width, height, out);
}
public static Vector2 projectToRectEdgeRad(double angle, float width, float height, Vector2 out)
{
float theta = negMod((float)angle + MathUtils.PI, MathUtils.PI2) - MathUtils.PI;
float diag = MathUtils.atan2(height, width);
float tangent = (float)Math.tan(angle);
if (theta > -diag && theta <= diag)
{
out.x = width / 2f;
out.y = width / 2f * tangent;
}
else if(theta > diag && theta <= MathUtils.PI - diag)
{
out.x = height / 2f / tangent;
out.y = height / 2f;
}
else if(theta > MathUtils.PI - diag && theta <= MathUtils.PI + diag)
{
out.x = -width / 2f;
out.y = -width / 2f * tangent;
}
else
{
out.x = -height / 2f / tangent;
out.y = -height / 2f;
}
return out;
}
public static Vector2 projectToRectEdge(双角度、浮动宽度、浮动高度、Vector2 out)
{
将投影仪返回到CTEREDGERAD(数学半径(角度)、宽度、高度、out);
}
公共静态矢量2 projectToRectEdgeRad(双角度、浮动宽度、浮动高度、矢量2输出)
{
浮点θ=negMod((浮点)角度+MathUtils.PI,MathUtils.PI2)-MathUtils.PI;
float diag=MathUtils.atan2(高度、宽度);
浮动切线=(浮动)数学tan(角度);
如果(θ> -diag & &θdiag & & theta MaTuffL.Pi-dia&&theta < P>虚幻引擎4(UE4)C++版本
注意:这是基于奥利的。基于贝里萨利斯的。如果这对你有帮助的话,给那些家伙投票
更改:使用UE4语法和函数,角度被否定
标题
UFUNCTION(BlueprintCallable,meta=(DisplayName=“投影到矩形边(弧度)”),Category=“数学|几何”)
静态空心投影到矩形边缘点(FVector2D范围、浮动角度、FVector2D和边缘位置);
代码
void UFunctionLibrary::ProjectToRectangleEdgeradans(FVector2D范围、浮动角度、FVector2D和EdgeLocation)
{
//将θ移到-M_π..M_π的范围内。同时也将角度取反,以便按预期工作。
浮点θ=FMath::展开半径(-角度);
//参考:http://s
@interface DebugEdgeView()
{
int degrees;
UIView *dotView;
NSTimer *timer;
}
@end
@implementation DebugEdgeView
- (void) dealloc
{
[timer invalidate];
}
- (id) initWithFrame: (CGRect) frame
{
self = [super initWithFrame: frame];
if (self)
{
self.backgroundColor = [[UIColor magentaColor] colorWithAlphaComponent: 0.25];
degrees = 0;
self.clipsToBounds = NO;
// create subview dot
CGRect dotRect = CGRectMake(frame.size.width / 2., frame.size.height / 2., 20, 20);
dotView = [[DotView alloc] initWithFrame: dotRect];
dotView.backgroundColor = [UIColor magentaColor];
[self addSubview: dotView];
// move it around our edges
timer = [NSTimer scheduledTimerWithTimeInterval: (5. / 360.)
target: self
selector: @selector(timerFired:)
userInfo: nil
repeats: YES];
}
return self;
}
- (void) timerFired: (NSTimer*) timer
{
float radians = ++degrees * M_PI / 180.;
if (degrees > 360)
{
degrees -= 360;
}
dispatch_async(dispatch_get_main_queue(), ^{
CGPoint edgePoint = [MFUtils edgeOfView: self atAngle: radians];
edgePoint.x += (self.bounds.size.width / 2.) - self.center.x;
edgePoint.y += (self.bounds.size.height / 2.) - self.center.y;
dotView.center = edgePoint;
});
}
@end
public static Vector2 projectToRectEdge(double angle, float width, float height, Vector2 out)
{
return projectToRectEdgeRad(Math.toRadians(angle), width, height, out);
}
public static Vector2 projectToRectEdgeRad(double angle, float width, float height, Vector2 out)
{
float theta = negMod((float)angle + MathUtils.PI, MathUtils.PI2) - MathUtils.PI;
float diag = MathUtils.atan2(height, width);
float tangent = (float)Math.tan(angle);
if (theta > -diag && theta <= diag)
{
out.x = width / 2f;
out.y = width / 2f * tangent;
}
else if(theta > diag && theta <= MathUtils.PI - diag)
{
out.x = height / 2f / tangent;
out.y = height / 2f;
}
else if(theta > MathUtils.PI - diag && theta <= MathUtils.PI + diag)
{
out.x = -width / 2f;
out.y = -width / 2f * tangent;
}
else
{
out.x = -height / 2f / tangent;
out.y = -height / 2f;
}
return out;
}
import math
import matplotlib.pyplot as plt
twoPI = math.pi * 2.0
PI = math.pi
def get_points(width, height, theta):
theta %= twoPI
aa = width
bb = height
rectAtan = math.atan2(bb,aa)
tanTheta = math.tan(theta)
xFactor = 1
yFactor = 1
# determine regions
if theta > twoPI-rectAtan or theta <= rectAtan:
region = 1
elif theta > rectAtan and theta <= PI-rectAtan:
region = 2
elif theta > PI - rectAtan and theta <= PI + rectAtan:
region = 3
xFactor = -1
yFactor = -1
elif theta > PI + rectAtan and theta < twoPI - rectAtan:
region = 4
xFactor = -1
yFactor = -1
else:
print(f"region assign failed : {theta}")
raise
# print(region, xFactor, yFactor)
edgePoint = [0,0]
## calculate points
if (region == 1) or (region == 3):
edgePoint[0] += xFactor * (aa / 2.)
edgePoint[1] += yFactor * (aa / 2.) * tanTheta
else:
edgePoint[0] += xFactor * (bb / (2. * tanTheta))
edgePoint[1] += yFactor * (bb / 2.)
return region, edgePoint
l_x = []
l_y = []
theta = 0
for _ in range(10000):
r, (x, y) = get_points(600,300, theta)
l_x.append(x)
l_y.append(y)
theta += (0.01 / PI)
if _ % 100 == 0:
print(r, x,y)
plt.plot(l_x, l_y)
plt.show()