Creating closed extrusion


#1

Hello
I am trying to create a closed extrusion object. I am using C# and rhino common for Rhino5. I do not have a lot of experience coding.
I have a set of planar 3D points and height which I would like to convert to a closed extrusion. Could someone please point me to an example or give some hints?


(Menno Deij - van Rijswijk) #2

You should convert the points to a curve, this could be a poly curve. Then use Extrusion.Create to make the extrusion. See also http://4.rhino3d.com/5/rhinocommon/html/M_Rhino_Geometry_Extrusion_Create.htm


#3

Hello
Thank you for your reply.
I finally managed to get an extrusion object but nothing shows in the rhino viewport. So my code looks like this:

This opens the form to give parameters:

 protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
           Application.Run(new Form1());       
            return Result.Success;
        }

Then this function is supposed to create the extrusion and is called from within the form:

public class DrawKN
    {
        public static PolyCurve DrawKN1()
        {
          [cut]
            PolyCurve Contour = new PolyCurve();
            Contour.Append(LineA);
            Contour.Append(LineB);
            Contour.Append(LineC);
            Contour.Append(LineD);
            Contour.MakeClosed(0);
            Extrusion KN1Bracket = Extrusion.Create(Contour,5,true);
            return null;
        }
    }

In debug extrusion variable seem fine. I tried AddExtrusion method but I cannot make it work. It tells me that System.Guid does not contain AddExtrusion.


(Menno Deij - van Rijswijk) #4

It seems that there is a problem with PolyCurve.MakeClosed. When I run the code below, the polycurve does not close, independent of the value used as tolerance.

{
    Point3d p00 = new Point3d(0, 0, 0);
    Point3d p10 = new Point3d(1, 0, 0);
    Point3d p01 = new Point3d(0, 1, 0);
    Point3d p11 = new Point3d(1, 1, 0);

    PolyCurve pc = new PolyCurve();
    pc.Append(new Line(p00, p10));
    pc.Append(new Line(p10, p11));
    pc.Append(new Line(p11, p01));
    pc.MakeClosed(0); // if I use a value of 2, 10 or 100 it never gets closed

    doc.Objects.AddCurve(pc);
    Extrusion e = Extrusion.Create(pc, 10, true);
    doc.Objects.AddExtrusion(e);

    return Result.Success;
}

The solution here is to close the contour by hand with a line from the end of LineD to the start of LineA:

PolyCurve Contour = new PolyCurve();
Contour.Append(LineA);
Contour.Append(LineB);
Contour.Append(LineC);
Contour.Append(LineD);
Contour.Append(new Line(LineD.To, LineA.From)); // close by adding a line
Extrusion KN1Bracket = Extrusion.Create(Contour,5,true);

I reported this as a bug http://mcneel.myjetbrains.com/youtrack/issue/RH-29951


#5

Thank you for your reply.
I think that the problem is hidden much deeper. It looks like I lack understanding of the use of this expression:

 doc.Objects.AddExtrusion(e);

What I need to do is to call it from the class that is outside a rhino command class:

public class BracketWizardCommand : Command
    {
        public BracketWizardCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static BracketWizardCommand Instance
        {
            get;
            private set;
        }

        ///<returns>The command name as it appears on the Rhino command line.</returns>
        public override string EnglishName
        {
            get { return "BracketWizardCommand"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
            Application.Run(new Form1());
            return Result.Success;
        }
    }
    public class BracketParameters
    public class DrawKN
        {
            public static PolyCurve DrawKN1() 
            {
              
             [cut]

                PolyCurve Contour = new PolyCurve();
                Contour.Append(LineA);
                Contour.Append(LineB);
                Contour.Append(LineC);
                Contour.Append(LineD);
                Contour.Append(LineE);
                Extrusion KN1Bracket = Extrusion.Create(Contour,5,true);
                doc.Objects.AddExtrusion(e);
                return null;
            }
        }
    }

Function DrawKN1() is called from within the form every time when any of the values are changed. From what I grasp I have already created an object which is in the memory but needs to be added to the document.


(Steve Baer) #6

Never show forms this way in Rhino. Create an instance of the form and call ShowDialog

var frm = new Form1();
frm.ShowDialog(RhinoApp.MainWindow());

If you have a function in your form which adds elements to the document; you’ll want to construct your form with a variable holding on to the RhinoDoc

var frm = new Form1(doc);

Hope this helps


#7

This breaks the code. I can no longer interact with rhino like pick points etc. and ok and exit buttons no longer work. I tried to change focus settings for this form but this made no difference. Adding (doc) gives an error:
Error 1 ‘BracketWizard.Form1’ does not contain a constructor that takes 1 arguments

Do I need to change something in the form code?


(Dale Fugier) #8

Hi Mike,

I think you are running into some “learning pains”, as you’ve said that you don’t have a lot of coding experience.

Doing something like this:

Application.Run(new Form1());

is what you would do if you were writing a standalone application (.EXE) and wanted to show your “main” window. But you are not running as a standalone application. You are running inside of an assembly (.DLL). Thus, the way you display a form is different, as mentioned above.

Here are the two different ways a form can be displayed:

https://msdn.microsoft.com/en-us/library/aa984358(v=vs.71).aspx

Most Rhino commands display modal forms. That is, the form must be closed before you can continue working or run another command.

With this said, what are you trying to create? Is there a command in Rhino that somewhat behaves similar to what you want to do?


#9

This helped a lot. The form works as before now. Thank you both very much. I will investigate doc issue later this week.
I am trying to create a plugin that will create extrusions from data placed in the form by the user. It will have to show preview in the viewport as the values are changed and give some additional information to help with the design.
I have done some scripts in Python for Rhino but it was way easier. I think that the primer pdf helped a lot in the learning process.


#10

Unfortunately I couldn’t make any progress with this. I am using visual studio 2013 express and a template for rhino plugins. What I have now looks like this:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
 
            var frm = new Form1();
            frm.Show(RhinoApp.MainWindow());

            return Result.Success;
        }

Then I have a form created with a designer. Form shows up and I can enquire for points and everything I need. I can also update the form with the input values from Rhino. However I cannot add anything to the model space. When I make a change suggested by stevebaer:

 protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
 
            var frm = new Form1(doc);
            frm.Show(RhinoApp.MainWindow());

            return Result.Success;
        }

I get an error:
Error 1 ‘BracketWizard.Form1’ does not contain a constructor that takes 1 arguments

The idea is to add an extrusion from form event code every time value is changed.
Any guidance, help or even a link to a place where I can read about it would be mostly appreciated.


(Menno Deij - van Rijswijk) #11

The idea is that you let your form accept the document as a constructor parameter like so:

public class Form1
{
    private RhinoDoc m_doc; // m_doc is a field
    public Form1(RhinoDoc doc) // doc is a constructor parameter
    {
        m_doc = doc;
    }

    // all other methods of the Form1 class come here
}

Then, all the other methods of the Form1 class can use the m_doc field, for example to add stuff to the model space. Because it is a so-called “member field”, it is customary to put m_ in front of the name of the field.

Hang in there - like Dale said, these are “learning pains”.


#12

Hello
Thank you all very much for help. I added InitializeComponent(); after m_doc = doc; and everything seems to work fine now.


#13

Hello
Its me again. The functionality of the plugin file seems ok however I get a following problem. After loading the .rhp file in Rhino and calling a command with a button I can use it once. After it finishes calling it again does nothing. The same behaviour is occurring during the debug. Restarting Rhino allows me to use the plugin again but again only once.

I close the form with a button calling an event:

private void ExitButton_Click(object sender, EventArgs e)
        {
            PurgeObjects();
            m_doc.Views.Redraw();
            this.Close();
        }

Or with an OK button which is almost the same:

    private void OKButton_Click(object sender, EventArgs e)
    {
        m_doc.Views.Redraw();
        this.Close();
    }

I suspect that there is some particular way I should use to close the form within Rhino. Any ideas?


(Dale Fugier) #14

Its pretty hard to tell what is going on without seeing more source code. Feel free to email me (dale@mcneel.com) your project if you want further assistance.


#15

I have managed to find the troublemaker. The InitializeDict() method seems to trigger the problem.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
            BracketParameters.InitializeDict();

            var frm = new BracketCreatetForm(doc);
            frm.Show(RhinoApp.MainWindow());

            return Result.Success;
        }
    }
    public class BracketParameters
    {
        public static Dictionary<string, object> BrParam = new Dictionary<string, object>();
        public static void InitializeDict()
        {
            BrParam.Add("A", (double)50);
         }
    }

Moving the method to a position after the form code like this:

 var frm = new BracketCreatetForm(doc);
 frm.Show(RhinoApp.MainWindow());
 BracketParameters.InitializeDict();

Solves the problem. I do not know why but it seems to work. However all the variables and dictionaries stay in Rhino memory. Is there a convenient way to clean it?