我正在嘗試在給定角度(Theta)處繪製一個矩形對象中的漸變,其中漸變的末端觸及矩形的周長。在給定角度的矩形上查找點
我想到用切線會的工作,但我遇到麻煩瑣碎的問題。有一個簡單的算法,我只是想念?
結束結果
所以,這將是一個函數(角度,RectX1,RectX2,RectY1,RectY2)。我希望它以[x1,x2,y1,y2]的形式返回,以便漸變將在廣場上繪製。 在我的問題中,如果原點爲0,那麼x2 = -x1和y2 = -y1。但它並不總是在原點上。
我正在嘗試在給定角度(Theta)處繪製一個矩形對象中的漸變,其中漸變的末端觸及矩形的周長。在給定角度的矩形上查找點
我想到用切線會的工作,但我遇到麻煩瑣碎的問題。有一個簡單的算法,我只是想念?
結束結果
所以,這將是一個函數(角度,RectX1,RectX2,RectY1,RectY2)。我希望它以[x1,x2,y1,y2]的形式返回,以便漸變將在廣場上繪製。 在我的問題中,如果原點爲0,那麼x2 = -x1和y2 = -y1。但它並不總是在原點上。
我們叫一個和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
一個小三角福,我們可以得到的座標爲每個區域所需交集。
所以Z0爲交點爲區域1和3
而Z1表達被用於交點爲區域2和所需的株中的表達4
根據區域從(X0,Y0)傳遞到Z0或Z1。所以記住譚(φ)= SIN(φ)/餘弦(φ)
Lines in regions Start End ====================================================================== 1 and 3 (X0,Y0) (X0 + a/2 , (a/2 * Tan(φ))+ Y0 2 and 4 (X0,Y0) (X0 + b/(2* Tan(φ)) , b/2 + Y0)
要知道的談的每個象限中的符號(φ),並且該角度總是從正x測量軸鎖定。
HTH!
幹得好!我會看看我能用這些信息做些什麼。 – bradlis7 2010-11-01 23:39:58
優秀的答案!謝謝! – BillyBBone 2012-02-26 08:06:43
我不明白你的答案或其他答案中的兩個角度φ和θ代表什麼 - 這個問題只是指定一個角度嗎?對於區域1中的相交/結束點,與3相比,不應該有不同的x座標(對於區域2中的相交點與4相比,不同的y座標)? – 2012-03-02 01:20:42
繼你的照片後,我會假定矩形的居中位置是(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。
有一個很好的(更方案的iOS /目標-C)的回答這個問題在Find the CGPoint on a UIView rectangle intersected by a straight line at a given angle from the center point涉及以下步驟:
好吧,哇!,我終於得到了這個。
注意:我基於belisarius的真棒答案。如果你喜歡這個,請也喜歡他。我所做的只是將他所說的話變成代碼。
下面是它在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;
}
此外,這裏有一個我創建的測試視圖來驗證它的工作原理。創建這個視圖並將它放在某個地方,它會讓另一個小視圖圍繞邊緣滑動。
@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
的JavaScript版本:
function edgeOfView(rect, deg) {
var twoPI = Math.PI*2;
var theta = deg * Math.PI/180;
while (theta < -Math.PI) {
theta += twoPI;
}
while (theta > Math.PI) {
theta -= twoPI;
}
var rectAtan = Math.atan2(rect.height, rect.width);
var tanTheta = Math.tan(theta);
var region;
if ((theta > -rectAtan) && (theta <= rectAtan)) {
region = 1;
} else if ((theta > rectAtan) && (theta <= (Math.PI - rectAtan))) {
region = 2;
} else if ((theta > (Math.PI - rectAtan)) || (theta <= -(Math.PI - rectAtan))) {
region = 3;
} else {
region = 4;
}
var edgePoint = {x: rect.width/2, y: rect.height/2};
var xFactor = 1;
var 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 * (rect.width/2.); // "Z0"
edgePoint.y += yFactor * (rect.width/2.) * tanTheta;
} else {
edgePoint.x += xFactor * (rect.height/(2. * tanTheta)); // "Z1"
edgePoint.y += yFactor * (rect.height/2.);
}
return edgePoint;
};
男人非常感謝你,我剛開始寫它,然後發現有人已經做到了:) – 2015-10-19 02:54:10
什麼照片有問題怎麼辦?只有線的一端(我假設線是這種情況下的斜邊)觸及邊界。該線會始終通過(或如圖所示,始於)起點? – aaronasterling 2010-10-31 02:42:01
@aaronasterling,這是我對我想達到的理解。我需要X和Y.三角形會根據角度改變。 – bradlis7 2010-10-31 03:04:42