顯示具有 <分享> 標籤的文章。 顯示所有文章
顯示具有 <分享> 標籤的文章。 顯示所有文章

2013年7月2日 星期二

<分享> 除去交集線(兩種版本) remove intersection line in grasshopper



檔案下載 :
https://dl.dropboxusercontent.com/u/29860061/remove%20intersection%20line-web.gh

因為目前有寫到需要處理交集線段的案子,所以使用grasshopper C#寫一個線段判斷與自身之外的所有線段做交集處理。

這邊提供兩個版本,RILn A 是線段頭尾交集就算交集並自動除去其中一條。RILn B 就算是線段頭尾交集程式也自動保留兩條曲線。

需要注意的是只能是線段data type - Line 不能是curve 否則內建的判斷程序會出錯。
因為我調用的功能是
Rhino.Geometry.Intersect.Intersection.LineLine(Line, Line, Double%, Double%, Double, Boolean);


操作前

操作後

其他線段測試

2013年6月16日 星期日

<分享> 如何除去圓外點 how to remove points of outside circle

檔案下載 :
https://dl.dropboxusercontent.com/u/29860061/inside%20outside%20web.gh

如何除去圓外點 how to remove points of outside circle

因為使用Grasshopper 中的containment component 所得到的輸出結果是 0 = outside, 1 =coincident, 2=inside, 但我們只需要輸出結果為2的狀態,所以我寫一個判斷式把輸出的結果如果為0 則為false 其他的都是 true,這樣表示我們只要把false (outside)的結果刪除就好,留下的即是在圓內的點。

圖1表示矩形佈點後還有圓型的範圍先確定。
圖1

 圖2經過判斷式後獲得園內的點。
圖2
圖3使用圓內的去連成最短路徑的曲線樣式。
圖3


圖4

2013年3月17日 星期日

<分享> circle packing 2D 在vb / c#的差別

目標 : 把circle packing vb component 轉譯成 c# component


描述:
想把之前沒搞懂packing 的邏輯在整理一下,並且翻出之前網路上david 寫好的vb legacy Circle packing component 來轉譯成 C#。起初想說只要把變數名稱還有方法宣告的部分改寫就好,沒想到果然在過程中還是遇到一些問題。像是再判斷創建點是否在現有的圓內時,需要跳出迴圈繼續計算下一個創建點直到創建點都在現有圓外時的部分。

vb 的寫法是
      For Each crc As OnCircle In circles
 If (point.DistanceTo(crc.Center) < crc.radius) Then Continue Do
      Next

C#的寫法如果只用continue 則程式的判斷將不會去除圓內點
  foreach(Circle crc in circles){
          if(point.DistanceTo(crc.Center) < crc.Radius){
            continue;
          }

圓內點沒被排除狀況


C#正確改寫方法應該使用關鍵字 goto; 離開判斷並且到最外層的do while迴圈
  foreach(Circle crc in circles){
          if(point.DistanceTo(crc.Center) < crc.Radius){
            goto label;
          }

正確結果



參考案例 :
http://www.grasshopper3d.com/forum/topics/circle-packing-constraints?commentId=2985220%3AComment%3A105142

http://www.grasshopper3d.com/forum/topics/circle-packing-1


檔案 :

流程步驟 :


Main Code:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
vb legacy parts ->
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    If (C Is Nothing) Then Return
    If (N <= 0) Then Return

    If (Not C.IsClosed) Then
      Print("Your input curve is not closed.")
      Return
    End If

    Dim bbox As OnBoundingBox = C.BoundingBox()
    Dim U As New OnInterval(bbox.Min().x, bbox.Max().x)
    Dim V As New OnInterval(bbox.Min().y, bbox.Max().y)

    Dim rnd As New Random(7)

    Dim circles As New List(Of OnCircle)
    Dim attempts As Int32 = 0

    Do While (attempts < 1000)
      attempts += 1

      Dim point As New On3dPoint(U.ParameterAt(rnd.NextDouble()), V.ParameterAt(rnd.NextDouble()), 0)

      If (Rhutil.RhinoPointInPlanarClosedCurve(point, C, OnPlane.World_xy) <> 1) Then Continue Do
      For Each crc As OnCircle In circles
        If (point.DistanceTo(crc.Center) < crc.radius) Then Continue Do
      Next

      Dim ct As Double : C.GetClosestPoint(point, ct)
      Dim cp As On3dPoint = C.PointAt(ct)
      Dim radius As Double = point.DistanceTo(cp)

      For Each crc As OnCircle In circles
        Dim dist As Double = point.DistanceTo(crc.Center) - crc.radius
        If (dist < radius) Then radius = dist
      Next

      Dim circle As New OnCircle(point, radius)
      circles.add(circle)
      If (circles.Count >= N) Then Exit Do
      attempts = 0
    Loop

    A = circles

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
C# parts ->
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BoundingBox bbox;
    bbox = xCrv.GetBoundingBox(true);

    Interval U = new Interval(bbox.Min.X, bbox.Max.X);
    Interval V = new Interval(bbox.Min.Y, bbox.Max.Y);
    Random rnd = new Random(7);
    List<Circle> circles = new List<Circle>();

    int attempts = 0;

    label: do{

        attempts += 1;

        Point3d point = new Point3d(U.ParameterAt(rnd.NextDouble()), V.ParameterAt(rnd.NextDouble()), 0);

        //point inside existing circle -> regenerate a new point//
        foreach(Circle crc in circles){
          if(point.DistanceTo(crc.Center) < crc.Radius){
            goto label;
          }
        }

        //using bounding points as base point to calculate closest point//
        Double ct;
        xCrv.ClosestPoint(point, out ct);
        Point3d cp = xCrv.PointAt(ct);
        Double radius = point.DistanceTo(cp);;

        //point outside existing circle -> find the closest distance//
        foreach(Circle crc in circles){
          Double dist = point.DistanceTo(crc.Center) - crc.Radius;
          if(dist < radius){
            radius = dist;
          }
        }


        Circle circle = new Circle(point, radius);
        circles.Add(circle);

        if(circles.Count >= Num){
          break;
        }

      }while(attempts < 1000);

    Acrv = circles;


結果圖片:


基本circle packing
顯示圓內點
把之前找尋最近點的function 導入,產生不同圖形
把之前找尋最近點的function 導入,並刪除交集線段,產生不同圖形

套用在不同曲線上



2013年3月15日 星期五

<分享>Group flatten List with different number

目標 : group flatten List with different number

檔案 : https://dl.dropbox.com/u/29860061/group%20flatten%20List%20with%20different%20number%28web%29.gh

比較 :


圖1 : 因為GH 內建所提供的data mapping 可以把flatten list 群組但是只限定每個branch中有固定的item,實在是不怎麼聰明。




圖2 : 所以我寫一個讓使用者可以依據想要的數量分別對使用者輸入flatten list,後進行不同數量的分組行為,大家可以看到處理後的數值在最右邊,分別依據使用者所輸入的5、4、5..等不同的群組內的數量作grouping

圖3 : 比較data mapping 與 C# grouping 的差別

注意 -----------> 
1.使用者輸入的數值請把它變成flatten list
2.輸入的分組數目總數請等於使用者所輸入flatten list的總數相等

example ->
分組數 3、3、6、2 -> 總數 3+3+6+2 = 14
flatten list的總數 -> 就是要數入14個數值






Main Code:


 DataTree<Point3d> myTree = new DataTree<Point3d>();

    //copy original objects
    List<Point3d> myLsPoints = new List<Point3d>();
    myLsPoints = xpoint;

    int tempInt;
    Print("count ={0}", yint.Count.ToString());
    int tempInt2;

    for(int i = 0;i < yint.Count;i++){

      tempInt = yint[i];

      GH_Path aa = new GH_Path(i);

      if(i == 0){

        tempIntA = 0;
      }else{
        tempInt2 = yint[i - 1];
        tempIntA += tempInt2;

      }
      Print("start index tempIntA ={0}", tempIntA);
      tempIntB = tempIntA + tempInt - 1;
      Print("end index tempIntB ={0}", tempIntB);

      List<Point3d> LsPoints = new List<Point3d>();
      for(int j = tempIntA;j <= tempIntB;j++){
        LsPoints.Add(myLsPoints[j]);
      }

      myTree.AddRange(LsPoints, aa);
    }

    A = myTree;



<分享>How to use timer component into C# script with multiply points

目標 : Using timer component into C# script.

檔案 : https://dl.dropbox.com/u/29860061/bouncing%20points%20with%20array.gh


流程步驟 :

1.在全域區塊(global variable)中設定需要被內部區塊改變的變數。

  List<Point3d> ListPts1 = new List<Point3d>();
  List<Point3d> ListPts2 = new List<Point3d>();
  List<Point3d> ListPts3 = new List<Point3d>();

  double[] xx = {0,1,2};
  double[] yy = {0,1,2};
  double[] speedx = {1,4,8};
  double[] speedy = {2,2,2};
注意: 在全域區塊中 GH C# component 不能使用迴圈去assign 陣列中的數值....很奇怪

2.創建初始點,我們即將改變點的x,y座標。

Point3d myPoint = new Point3d(xx[i], yy[i], 0);

3.隨著timer 的計數器增加,點座標的x,y值會依據使用者設定的speedx/speedy 增加。

xx[i] += speedx[i];
yy[i] += speedy[i];



4.設定彈跳範圍,如果彈跳超出範圍則程式需要改變speedx/speedy 的方向。
if(x[i]x > boundX )
if(xx[i] < 0 )
if(yy[i] > boundy )
if(yy[i] < 0 )



5.清除紀錄,如果使用者重新執行bounce point,請程式清除上一次的點座標,並使x,y座標返回預設值。

      ListPts1.Clear();
      ListPts2.Clear();
      ListPts3.Clear();
      for(int i = 0;i < 3;i++){
        xx[i] = yy[i] = 0;
      }


Main Code:


if(start){

      for(int i = 0;i < 3;i++){

        Point3d myPoint = new Point3d(xx[i], yy[i], 0);

        if(i == 0){
          ListPts1.Add(myPoint);
        }

        if(i == 1){
          ListPts2.Add(myPoint);
        }

        if(i == 2){
          ListPts3.Add(myPoint);
        }

        xx[i] += speedx[i];
        yy[i] += speedy[i];

        if(xx[i] > boundX ){
          xx[i] = boundX;
          speedx[i] *= -1;
        }

        if(xx[i] < 0 ){
          xx[i] = 0;
          speedx[i] *= -1;
        }

        if(yy[i] > boundy ){
          yy[i] = boundy;
          speedy[i] *= -1;
        }

        if(yy[i] < 0 ){
          yy[i] = 0;
          speedy[i] *= -1;
        }
      }

    }else{
      ListPts1.Clear();
      ListPts2.Clear();
      ListPts3.Clear();
      for(int i = 0;i < 3;i++){
        xx[i] = yy[i] = 0;
      }
    }

    A = ListPts1;
    B = ListPts2;
    C = ListPts3;


影片:



結果圖片:
GH C# Definition




timer count A

timer count B

timer count C


<分享>How to use timer component into C# script

目標 : Using timer component into C# script.

檔案 : https://dl.dropbox.com/u/29860061/bounce%20point.gh


流程步驟 :

1.在全域區塊(global variable)中設定需要被內部區塊改變的變數。

2.創建初始點,我們即將改變點的x,y座標。

Point3d myPoint = new Point3d(xx, yy, 0);

3.隨著timer 的計數器增加,點座標的x,y值會依據使用者設定的speedx/speedy 增加。

xx += speedx;
yy += speedy;



4.設定彈跳範圍,如果彈跳超出範圍則程式需要改變speedx/speedy 的方向。
if(xx > boundX )
if(xx < 0 )
if(yy > boundy )
if(yy < 0 )


5.清除紀錄,如果使用者重新執行bounce point,請程式清除上一次的點座標,並使x,y座標返回預設值。

   ListPts.Clear();
   xx = yy = 0;



Main Code:


if(start){

      Point3d myPoint = new Point3d(xx, yy, 0);
      ListPts.Add(myPoint);

      xx += speedx;
      yy += speedy;

      if(xx > boundX ){
        xx = boundX;
        speedx *= -1;
      }

      if(xx < 0 ){
        xx = 0;
        speedx *= -1;
      }

      if(yy > boundy ){
        yy = boundy;
        speedy *= -1;
      }

      if(yy < 0 ){
        yy = 0;
        speedy *= -1;
      }

    }else{
      ListPts.Clear();
      xx = yy = 0;
    }

    A = ListPts;

影片:


結果圖片:


GH C# Definition

timer count A

timer count B

timer count C