Using an object as argument in RunScript


(Arne) #1

Hi,
I 'm using this function to find all controlpoints within a closed curve on a mesh surface.
It works ok, but the command asks the user to select the closing curve. I already have the curve as a RhinoObject “region”. Is there a way to pass this in the RunScript so that the user do not have to click it?

Thanks

    private ArrayList getMeshGripsWithinRegion(RhinoObject mesh, RhinoObject region)
    {
        RhinoApp.RunScript("_-CullControlPolygon Cull=Yes", false); 
        RhinoApp.RunScript("_-SelBoundary", false);

        var grips = mesh.GetGrips();
        var selectedGrips = new ArrayList();
        foreach (var g in grips)
        {
            if (g.IsSelected(true) > 0)
            {
                selectedGrips.Add(g);
            }
        }

        return selectedGrips;
    }

#2

Hi @arne1,

if region is a RhinoObject it has an Id. If you really want to script rhino commands, you could either run _SelId first, followed by the region.Id, then use _SelBoundary or alternatively you can nest _SelId and pass region.Id like this (if nothing is selected):

_SelBoundary _SelId c2796a3f-1a7f-4e1c-98c8-2e9bceabfc38

btw. best thing is try scripted rhino commands using the macro editor, or not script rhino commands at all :slight_smile:

_
c.


(Arne) #3

@clement!

Thank you for the answer, I will try this.
Actually I would prefer not to use script, but I thought some commands like SelBoundary were not available in RhinoCommon, is it? Or can it be done in another way?

/Arne


#4

@arne1, you could iterate over the mesh grips and check if their locations are inside your closed polyline on the mesh using:

Rhino.Geometry.Curve.Contains(region_curve, grip_point, view_plane)

Since _SelBoundary is view based, you’ll need to find out to which view you test against using above method. You need to provide a custom plane, which is based on the view. Alternatively, but also including a view, you could use:

Rhino.DocObjects.Tables.ObjectTable.FindByCrossingWindowRegion

however this only works if the mesh grips are enabled and selectable and if you’re in the correct view. Below is a quick python example, i’ve tested with a mesh sphere (grips enabled) and a closed polyline on the mesh:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def DoSomething():
    msg = "Select closed polyline to use as a selection boundary"
    id = rs.GetObject(msg, 4, True, False)
    if not id: return
    
    curve = rs.coercecurve(id, -1, True)
    rc, polyline = curve.TryGetPolyline()
    if not rc: return
    
    view = scriptcontext.doc.Views.ActiveView.ActiveViewport
    obj_filter = Rhino.DocObjects.ObjectType.Grip
    inside = True
    
    finder = scriptcontext.doc.Objects.FindByCrossingWindowRegion
    result = finder(view, polyline, inside, obj_filter)
    if result.Count != 0: 
        for grip in result: 
            grip.Select(True)
    
    scriptcontext.doc.Views.Redraw()
    
DoSomething()

_
c.


(Arne) #5

Thanks a lot @clement,

I have tried both to script _SelBoundary and to loop through the grips using the Contains method.
In my test the Script way took 2.5 seconds and the “Contains” method took 7.7 seconds.
My mesh has over 100 000 vertices.
What would be really great would be to be able to modify the vertices directly without first have to make a copy and then update the grips. Do you know if there is a way to change a vertex x, y, z values without the need of any copy? I would be happy to write such plugin in C++ if needed.

Thanks


#6

@arne1, i would like to get the big picture of what you’re trying to do and why. Are you selecting the mesh grips because you want to transform them ? Is this done using GripObject.Move followed by ObjectTable.GripUpdate() ? If yes, may be indeed slow.

You have full access to the Mesh.Vertices and can modify their locations instead without turning Grips on.

_
c.


(Arne) #7

@clement, Very sorry for my late response. For some reason my notification mail ended up in my spam folder.
Your answer makes me really hopeful of a faster solution.
You are correct, I am currently using GripObject.Move and then GripUpdate.

I’ll try to explain what I want to do. So I have this big mesh. I also have a closed polyline on the mesh surface. Created by using Curve->PolyLine->OnMesh.
I want to be able to move all mesh vertices that are located within the closed poly line.
I use SelBoundary to find grips and “CullControlPolygon Cull=Yes” to avoid selecting grips that is facing away.
The final goal is to find all vertices located within the boundary of my closed polyline and to be able to change the x, y and z values of these vertices. I need it to be fast, because i want to be able to change the x, y and z values using for example a slider and see the rendered mesh changing in real time. And it would be really great if I did not need to use the grips. They destroy the rendering of the mesh surface.
Hope I was able to explain what I meant.
/Arne


#8

Hi @arne1, see if below example helps. The speed is related to the amount of mesh vertices in the polyline (or curve) and you also have to do the culling to avoid that hidden vertices not facing the camera are included in your transform…

MeshRandomizeAreaInCrv.py (1.5 KB)

_
c.


(Arne) #9

Thanks @clement,
How would I do this with RhinoCommon and c#?

/Arne