2015-11-02 50 views
1

我有一個程序,我需要從父行遞歸生成新的行,以便它看起來像一棵樹。我遇到的問題是我不知道如何在角度A處製作子線,其中A在10到80或100到170度之間,相對於其父線。創建從另一條線上的一個點開始並以給定角度延伸給定長度的線的最佳方式是什麼?

我的當前算法步驟如下:

  1. 選擇從父的(X1,Y1)的隨機長度(稱之爲newBranchDist)點是小於總親本系的長度(使用距離式)
  2. 查找使用Math.Cos(A)次newBranchDist
  3. 使用Math.Sin(A)次newBranchDist發現新線的y軸座標的新生產線的x座標
  4. 現在我們有(X1,Y1 )爲該線的一個點進行座標。

在這一點上,我需要計算(x2,y2)在角度A相對於父行。有什麼建議麼?

編輯:此外,我的程序將隨機選擇父行的哪一側繪製新行。所以,有時它會成爲角度A,其他時間會成爲A + 90.

+0

我看不到有關隨機角度的任何事情。你需要計算它還是在給定的時間間隔內是「任何」角度?此外,你可能會發佈一個** short **樣本,你現在已經有了這個算法。有時候,它可以幫助你理解這個問題。第2行會在原始行的同一點開始嗎? –

+0

這似乎更像是一個幾何問題,而不是一個編程問題。這是不完全清楚你想要做什麼。 –

+0

@MattBurland - 這個問題似乎與確定子分支的算法有關,我認爲這種混淆正是因爲OP對如何生成這樣的算法感到困惑。他似乎在思考如何使用面向對象的思想來解決這個問題。但我認爲你是對的,這有一個沉重的幾何構件。可能是幾何組件將他從OO扔掉,並讓他只考慮程序。 – AgapwIesu

回答

2

您需要知道父行的角度以及子行的角度。你的條款令人困惑,所以我將使用一點點不同。需要注意的是,所有分支的角度應該存儲爲相對於水平的角度,儘管您需要計算它們相對於父分支來執行10-80,100-170的事情。但是,從橫向的角度計算是很容易的和如下:

1. figure out origin of the new branch<p> 
    a. BreakOffDistance = a random number less than the parent length (random distance from the start of the parent branch) 
    b. NewBranchOriginX = ParentBranchOriginX + BreakOffDistance * cos(ParentBranchAngle); 
    c. NewBranchOriginY = ParentBranchOriginY + BreakOffDistance * sin(ParentBranchAngle); 
2. figure out a random angle to the new, child line; 
    a. figure out random angle between 10 and 80 or 100 and 170. 
    b. NewBranchAngle = ParentBranchAngle - 90 + RandomAngle. 
     (all branch angles relative to horizontal, right?) 
3. figure out random length of new branch - less than parent? 
4. The previous steps determine the new branch - origin point, angle and length. But to figure out its endpoint so you can draw it: 
    a. NewBranchEndX = NewBranchOriginX + NewBranchLength * cos(NewBranchAngle); 
    b. NewBranchEndY = NewBranchOriginY + NewBranchLength * sin(NewBranchAngle); 

因爲屏幕座標是天翻地覆,你可能需要更換加號的步驟1B,1C,和4A和4B與減號。另外,如果你試圖模擬一棵樹,我認爲選擇10-80或100-170的新分支的角度是不對的。樹上的分支喜歡長出來,在爲每個新分支計算角度時不難做到這一點。最後,如果你在三維空間中想到它,你的樹會更加現實。有一棵樹可以向着和遠離你的方向以及兩側生長分支。這也相當簡單,但比你要求的要多。

+0

它的主旨對我來說似乎是正確的。但是,它確實比這更復雜。只實現這個算法仍然不適合我(見上面的評論) - 我從來沒有能夠得到一條線,其起始(x,y)座標在其父分支上。不過,我相信這更多是因爲我在處理三角學垃圾方面的能力不足,而不是這個算法中的缺陷。不過,我認爲這比這更復雜一點。 – reubonwry

3

對結果做一些假設,因爲我不清楚你的目標是什麼,我會說計算如下。

int x2 = x1 + newBranchDist * Math.Cos(a); 
int y2 = y1 + newBranchDist * Math.Sin(a); 

然後,你可以通過畢達哥拉斯定理來驗證長度。

double lengthSquared = Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2); 
double lengthRooted = Math.Pow(lengthSquared, 0.5); 
2

通過這樣的課程,您可以先進行計算並在第三步中繪製整個事物。

這段代碼完全沒有用處。會出現一些錯誤,但你可能會想到如何做到這一點...

public class MyLine { 
    private Random random; 
    public MyLine(int Level, PointF Start, PointF End, int Angle) { 
     this.random = new Random(); 
     this.Level = Level; 
     this.Start = Start; 
     this.End = End; 
     this.Angle = Angle; 
    } 

    public int Level{get;set;} 

    public PointF Start { get; set; } 
    public PointF End { get; set; } 

    public float MyLength { 
     get { 
      return (float)Math.Sqrt(Math.Pow(End.X - Start.X, 2) + Math.Pow(End.Y - Start.Y, 2)); 
     } 
    } 
    public int Angle { get; set; } 

    public MyLine MySideLine { get; set; } 

    public void CalculateSideLine() { 
     float middleX = Start.X + (End.X - Start.X)/2f; 

     float k = (End.Y - Start.Y)/(End.X - Start.X); 
     float d = (End.X * Start.Y - Start.X * End.Y)/(End.X - Start.X); 

     float middleY = k * middleX + d; 

     PointF newStart = new PointF(middleX, middleY); 
     int angle = random.Next(10, 80); 
     if (random.Next(0, 1) == 0) 
      angle = angle + 90; 

     float LengthPercentage = (float)random.NextDouble(); 
     if (LengthPercentage < 0.5) 
      LengthPercentage = 0.5f; 

     float newLength = MyLength * LengthPercentage; 

     //Now we know the starting point of the new line, its angle and the length 
     //I do not have enough time to write the complete calculation down but it's result would be a new endPoint 
     //You think of a circle with its middle on "newStart" and its radius = "newLength". 
     //This circle you'll have to intersect with the line through "newStart" with the given angle. 
     //There are two results, you have to choose the one in the right direction 
     PointF newEnd = new PointF(0, 0); //This you'll have to find yourself... 

     this.MySideLine = new MyLine(this.Level++, newStart, newEnd, angle); 

     //this will calculate a new nested side line and - kind of recursively - go deeper and deeper. 
     //you'll have to find a break condition on a certain level. 
     this.MySideLine.CalculateSideLine(); 

     //Be aware of randomly angle of 90 or 0. you might want to calculate two side lines on each twig (otherwise it will not look like a tree) 

    } 

    //This will draw the line to a Graphics (e.g. look at Form.CreateGraphics()) 
    //it will kind of recursively draw down the full tree. 
    public void DrawMeAndMySideLine(Graphics g){ 
     g.DrawLine(Pens.Black,this.Start,this.End); 
     this.MySideLine.DrawMeAndMySideLine(g); 
    } 
} 
相關問題