Flow syntax in Python

Hello,

Is there any way to use the Flow commands within a python script?

Thanks!

Hi Michael - you can use it more or less directly with the correct input to say

rs.Command("_Flow " etc etc)

Is that what you mean?

-Pascal

I’d like to flow an object just like if I was trying to scale it. I couldn’t find anything in the RhinoScript API for it. Rhino - RhinoScriptSyntax (rhino3d.com)

if switch:
    origin = rs.AddPoint( (0,0,0) )
    a = rs.ScaleObject(x, origin, (scaleX, scaleY, scaleZ), y );

Hi Michael - In this case you will need to use rs.Command() or dig into RhinoCommon and use the flow space morph
https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.morphs.flowspacemorph

I’ll poke around some more but I don’t think it is in rhinoscriptsyntax

btw, you can specify the origin directly in scaling without adding a point object to the document…

rs.ScaleObject(ID,(0,0,0), (2,3,4))

-Pascal

Yea I’ve done it in a C# script but wasn’t sure if there was a way in Python. Thanks for the tip!

    Rhino.Geometry.Morphs.FlowSpaceMorph myFlow = new Rhino.Geometry.Morphs.FlowSpaceMorph(b, t, false, false, true);
    for(int i = 0; i < x.Count; i++) x[i] = myFlow.MorphPoint(x[i]);
    A = x;

You can use RhinoCommon directly from Python, in case you’re wondering.

Ok great, thanks!

getting an error for this line trying to implement the R8 Rhino Common. It worked fine for Rhino 7. (Specifically C#)

for(int i = 0; i < x.Count; i++) x[i] = myFlow.MorphPoint(x[i]);

NullReferenceException: Object reference not set to an instance of an object.
at Script_Instance.RunScript(List`1 x, Curve b, Curve t, Object& A) in rhinocode:///grasshopper/1/d475bc8a-4cb5-41c1-9b1c-4f98dbf156a5/5afef0e3-f50f-46fc-baec-f111398b7eb0:line 39

That error is more the department of @eirannejad . But either way probably more useful if you also posted the script code.

Anyway, here a quick snippet in just simple ScriptEditor with a document that has two curves and ten points:

The script

#! python3

import scriptcontext as sc

import Rhino

b, t = (c.Geometry for c in sc.doc.Objects if isinstance(c, Rhino.DocObjects.CurveObject))
x = [p.Geometry.Location for p in sc.doc.Objects if isinstance(p, Rhino.DocObjects.PointObject)]

myFlow = Rhino.Geometry.Morphs.FlowSpaceMorph(b, t, False, False, True)

y = [myFlow.MorphPoint(e) for e in x]

for e in x: print(f"x element: {e}")
for e in y: print(f"y element: {e}")

@double.m.designed Sharing (even a portion) of the faulty script would be very helpful

C# Script

Here is the two scripts side by side, the left one is from Rhino 7 and the right one is from Rhino 8.

Rhino 7

using System;
using System.Collections;
using System.Collections.Generic;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

/// <summary>
/// This class will be instantiated on demand by the Script component.
/// </summary>
public class Script_Instance : GH_ScriptInstance
{
  /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
  /// <param name="text">String to print.</param>
  private void Print(string text) { /* Implementation hidden. */ }
  /// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
  /// <param name="format">String format.</param>
  /// <param name="args">Formatting parameters.</param>
  private void Print(string format, params object[] args) { /* Implementation hidden. */ }
  /// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj) { /* Implementation hidden. */ }
  /// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj, string method_name) { /* Implementation hidden. */ }

  /// <summary>Gets the current Rhino document.</summary>
  private readonly RhinoDoc RhinoDocument;
  /// <summary>Gets the Grasshopper document that owns this script.</summary>
  private readonly GH_Document GrasshopperDocument;
  /// <summary>Gets the Grasshopper script component that owns this script.</summary>
  private readonly IGH_Component Component;
  /// <summary>
  /// Gets the current iteration count. The first call to RunScript() is associated with Iteration==0.
  /// Any subsequent call within the same solution will increment the Iteration count.
  /// </summary>
  private readonly int Iteration;

  /// <summary>
  /// This procedure contains the user code. Input parameters are provided as regular arguments,
  /// Output parameters as ref arguments. You don't have to assign output parameters,
  /// they will have a default value.
  /// </summary>
  private void RunScript(List<Point3d> x, Curve b, Curve t, out object A)
  {

    Rhino.Geometry.Morphs.FlowSpaceMorph myFlow = new Rhino.Geometry.Morphs.FlowSpaceMorph(b, t, false, false, false);
    for(int i = 0; i < x.Count; i++) x[i] = myFlow.MorphPoint(x[i]);
    A = x;

  }

  // <Custom additional code> 

  // </Custom additional code> 
}

and Rhino 8

// Grasshopper Script Instance
#region Usings
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
#endregion

public class Script_Instance : GH_ScriptInstance
{
    #region Notes
    /* 
      Members:
        RhinoDoc RhinoDocument
        GH_Document GrasshopperDocument
        IGH_Component Component
        int Iteration

      Methods (Virtual & overridable):
        Print(string text)
        Print(string format, params object[] args)
        Reflect(object obj)
        Reflect(object obj, string method_name)
    */
    #endregion

    private void RunScript(List<Point3d> x, Curve b, Curve t, ref object A)
    {
        Rhino.Geometry.Morphs.FlowSpaceMorph myFlow = new Rhino.Geometry.Morphs.FlowSpaceMorph(b, t, false, false, false);
        for(int i = 0; i < x.Count; i++) x[i] = myFlow.MorphPoint(x[i]);
        A = x; 
    }
}

@double.m.designed

Does this work on your Rhino?

test_rhinocommon_flowSpaceMorph.ghx (83.7 KB)

Yes all 3 work, I’ll review the files and see where my syntax may be incorrect.

Thanks!

1 Like

Anytime. I am glad it is working