Grasshopper Python 106

Loops (II)

In the previous lesson we introduced some loops. Working with conditional statements and loops together with numbers and strings will be more than enough most of the times, remember you still have all the power of out-of-the-box grasshopper, so Point3d is part of the RhinoCommon library. Being a Reference-Type class, we should declare it as we did with lists.

Point3d myPoint = new Point3d();

Let’s create a point from scratch with components:

private void RunScript(ref object A)
  {
    Point3d myPoint = new Point3d();
    myPoint.X = 1.0; //set the X property
    myPoint.Y = 3.0; //set the Y property
    myPoint.Z = 4.0; //set the Z property
    A = myPoint;
  }

We can do the whole thing if we pass the coordinates to the constructing sentence:

 private void RunScript(ref object A)
  {
    Point3d myPoint = new Point3d(1.0, 3.0, 4.0);

    A = myPoint;
  }

 A Spiral

Mixing point lists and loops we can start building familiar curves.

private void RunScript(ref object A)
  {
    //declare a point list
    List<Point3d> myPtList = new List<Point3d>();
    //declare variables for each coordiate
    double Xcoord, Ycoord, Zcoord;
    //set the radius, this could be an input variable
    double radius = 10.0;
    //build a buffer point
    Point3d myPt;
    //start the loop, the number of points could also be an input variable
    for (int i = 0; i < 100; i++){
      //calculate each coordinate
      Xcoord = radius * Math.Cos(Math.PI * 2 * i / 100);
      Ycoord = radius * Math.Sin(Math.PI * 2 * i / 100);
      Zcoord = i;
      //build a point with the coordinates
      myPt = new Point3d(Xcoord, Ycoord, Zcoord);
      //add the point to the list
      myPtList.Add(myPt);
    }
    //output the list
    A = myPtList;
  }

Distance Meter

The following code takes a point cloud and returns the distance between each of them and a sample point together with the furthest and closest one

  private void RunScript(List<Point3d> x, Point3d y, ref object A, ref object B, ref object C)
  {
    List<double> distList = new List<double>(); //declare the list for holding distances

    double dist = 0.0; //declare a distance buffer
    double minDist = y.DistanceTo(x[0]); //declare a variable for holding the minimum distance, initialize it with a posssible value
    double maxDist = 0.0; //declare a variable for holding the maximum distance, initialize it at 0.0

    B = x[0]; //set the B output to something
    C = x[0]; //set the C output to something

    foreach (Point3d samplePt in x){ //start the loop

      dist = y.DistanceTo(samplePt); //calculate the distance between y and the sample point
      distList.Add(dist); //add the distance to the list

      if (dist < minDist){ //if the distance is smaller than the current minimum, we have a new minimum

        B = samplePt; //output the corresponding point
        minDist = dist; //set the distance as the new minimum

      }

      if (dist > maxDist){ //if the distance is larger than the current maximun, we have a new maximum

        C = samplePt; //output the corresponing point
        maxDist = dist; //set the distance as the new maximum

      }
    }

    A = distList; //finally, output the list of distances
  }

A key aspect here is to initialize the minDist and maxDist variables with the right values. If you pick 0.0 as the initial value for minDist there is no lower value possible, and if you pick a random number, you might be assuming there will be a distance smaller than that number. That is why we pick a real value as the first state.

Nested Loops

Nested loops are loops happening inside other loops. This gives access to complex operations where we need to cross-evaluate certain variables or work with multiple dimensions. It is also worth nothing that nested loops are dangerous if used without care, a loop within a loop within a loop, each one having 100 steps will result in a million calls being processed by the computer, and depending on the case, this could hang your computer without mercy.

Let’s see an example of nested loops to create a grid of points. Keep in mind that each loop needs its iterator.

 private void RunScript(int x, int y, double s, ref object A)
  {
    List<Point3d> ptGrid = new List<Point3d>(); //create a list for the points
    Point3d samplePt; //create a placeholder point

    for (int i = 0; i < x; i++){ //start outer loop for first coordinate
      for(int j = 0; j < y; j++){ //start inner loop for second coordinate

        samplePt = new Point3d(i * s, j * s, 0); //create samplePt with x and y coordinates
        ptGrid.Add(samplePt); //add the point to the list

      }
    }

    A = ptGrid; //output the list
  }

Challenge

1. Write a component that creates points arranged in the shape of a sphere with Radius R and centered at the origin.

2. Write a component that creates points arranged in the shape of a thorus with radius R1 and R2 and centered at the origin.

[EDIT] Challenge Solutions:

Challenge 1. Points Sphere:

  private void RunScript(double R, int u, int v, ref object A)
  {

    List<Point3d> ptList = new List<Point3d>(); //declare a list to hold the points

    for (int i = 0; i < u; i++){ //outer loop for u subdivisions of the alfa angle, between 0 and 2*PI
      double alfa = Math.PI * 2 * i / u;  //calculate alfa as a fraction of 2*PI

      for (int j = 0; j <= v; j++){ //inner loop for v subdivisions of the beta angle (0 to PI)

        double beta = Math.PI * j / v; //calculate beta as a fraction of PI

        double ptX = R * Math.Cos(alfa) * Math.Sin(beta); //parametric equation of the sphere
        double ptY = R * Math.Sin(alfa) * Math.Sin(beta);
        double ptZ = R * Math.Cos(beta);

        Point3d pt = new Point3d(ptX, ptY, ptZ); //create the point
        ptList.Add(pt); //add it to the list
      }
    }

    A = ptList; //output the list of points
  }

Challenge 2. Points Torus:

  private void RunScript(double R, double r, int u, int v, ref object A)
  {

    List<Point3d> ptList = new List<Point3d>(); //create a list to hold the points
    for (int i = 0; i < u; i++){ //outer loop
      double alpha = Math.PI * 2 * i / u; //calculate alpha as a fraction of 2*PI

      for (int j = 0; j < v; j++){ //inner loop

        double beta = Math.PI * 2 * j / v; //calculate beta as a fraction of PI

        double ptX = (R + r * Math.Cos(beta)) * Math.Cos(alpha); //torus equation
        double ptY = (R + r * Math.Cos(beta)) * Math.Sin(alpha);
        double ptZ = r * Math.Sin(beta);

        Point3d pt = new Point3d(ptX, ptY, ptZ); //create the point
        ptList.Add(pt); //add it to the list
      }
    }

    A = ptList; //output the list
  }

 A little note:

Please note that in this two examples, the inner and outer loops can be swapped together and that script would “build” the points then following Parallels > Meridians. See the example with the sphere:

private void RunScript(double R, int u, int v, ref object A)
  {

    List<Point3d> ptList = new List<Point3d>(); //declare a list to hold the points

    for (int i = 0; i <= u; i++){ //outer loop for u subdivisions of the alfa angle, between 0 and PI
      double alpha = Math.PI * i / u;  //calculate alpha as a fraction of PI

      for (int j = 0; j < v; j++){ //inner loop for v subdivisions of the beta angle (0 to 2*PI)

        double beta = Math.PI * 2 * j / v; //calculate beta as a fraction of 2*PI

        double ptX = R * Math.Cos(beta) * Math.Sin(alpha); //parametric equation of the sphere
        double ptY = R * Math.Sin(beta) * Math.Sin(alpha);
        double ptZ = R * Math.Cos(alpha);

        Point3d pt = new Point3d(ptX, ptY, ptZ); //create the point
        ptList.Add(pt); //add it to the list
      }
    }

    A = ptList; //output the list of points
  }

Download the solutions here (GH 0.9.0014)

Final Challenge

Write a component that calculates the first n prime numbers, with n being a reasonable number, not too big.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit exceeded. Please complete the captcha once again.

  • Before submitting your inquiry, take a look at the basic information on data protection here.

    Modelical.com informs you that the personal data you provide will be processed by MODELICAL CONSULTORIA S.L. as the party responsible for this website.

    Purpose of the collection and processing of personal data: To send the information that the user requires through the website. - Legitimation: Consent of the interested party. - Recipients: Hosting: Gigas, 100% Spanish and 100% secure hosting. - Rights: You may exercise your rights of access, rectification, limitation and deletion of unsubscribe@modelical.com data as well as the right to lodge a complaint with a supervisory authority.