How do I extrude along a curve, in a script?

Scripting
2010-02-12
2013-06-05
  • Jeff Silver

    Jeff Silver - 2010-02-12

    I want to make a threaded object (e.g. a nut/bolt). I thought a good way to make the thread would be to define its profile and extrude that along a spiral. I've done this manually, but want to do it in a script. Can anyone tell me how to do that? Or suggest an alternative way to make a thread?

     
  • Pete

    Pete - 2010-02-13

    As it happens here is something close to your question.

    All of the thread:
    http://www.friendlyskies.net/aoiforum/viewtopic.php?id=2160&p=1

    The post where it's explained.
    http://www.friendlyskies.net/aoiforum/viewtopic.php?pid=17464#p17464

    Basically making the spiral form out of a profile woud be relatively easy in a script, but joining the edges correctly might not. At least if you want it to be a single surface. If you can live with a thread, that has only been wrapped around an axis as a separate object, a script could produce the thread as a spline mesh - but it takes some basic trigonometry to do.

     
  • Pete

    Pete - 2010-02-13

    >> but it takes some basic trigonometry to do.

    Or maybe not - there also are ways just to rotate coordinate systems an move points… Hmm… Sorry, I can't go there now.

     
  • Jeff Silver

    Jeff Silver - 2010-02-13

    Thanks. There's some interesting stuff there. And I was impressed by your model. But I still don't know how to do an extrude from a script. I was hoping for a class/method that would take a profile and a curve, and extrude the one along the other, as the GUI extrude tool does. (I can do the trigonometry.)

    Is there perhaps some general way to invoke GUI tools from inside a script?

     
  • Pete

    Pete - 2010-02-13

    Sorry. Your point is to do it by a script… I missed that part.

    I don't think, that the tools can be invoked by a script. (Somebody correct me if I'm wrong.) I also checked the API and I did not find a way of  telling the direction of the curve at a point. To do that you'd probably have to subdivide the curve into small pieces enough to be able to tell the direction by two points. So, if it's essential to you to do it along another curve, then it gets a kind of tricky. - Maybe download the source code and find out how it was actually done in the tool?

    If you could use a spiral form, that has just been created along an axis without a guide curve, that should be easier: Basically so: Create a new coordinate system. Calculate how many vertices you'd need for your new object. Keep rotating (and propagating) the coordinate system step by step and copy positions to the vertices from the model curve as you go. And finally create a new n*m spline mesh and set the vertex positions to the ones you calculated.

    At least that would be the principle. I have played with coordinate systems and spline meshes in scritps before, but it has been a while now…. So I'd have to do some digging.

    My answer is probably not very satisfactory this time either. Apologies for that ;)

     
  • Pete

    Pete - 2010-02-14

    :banging head to keyboard: -Yes of course…

    Anyhow, I felt like refreshing my memory a bit and here's what I got. It only extrueds a helix form along the scene Y-axis, but consider it a prototype ;)

    // Extrude properties
    // 
    rounds = 3.0; // use a negative value to reverse
    pitch = 0.7; // use a negative value to reverse
    segmentsPerRound = 16;
    pitchPerStep = (double)pitch/segmentsPerRound;
    rotPerStep = 360.0/segmentsPerRound;
    // check if anything was selected
    selection = window.getScene().getSelection();
    if (selection.length < 1) 
        {new MessageDialog(window,"Select a curve");return;}
    // get a copy of the profile curve
    curveInfo =  window.getScene().getObject(selection[0]).duplicate();
    curve = curveInfo.getObject();
    // check if it's a curve
    if (!(curve instanceof artofillusion.object.Curve)) 
        {new MessageDialog(window,"Not a curve");return;}
    // new coordinate systems
    meshOrigin = new Vec3(0.0,0.0,0.0);
    meshAxis = new Vec3(0.0,1.0,0.0);
    meshZ = new Vec3(0.0,0.0,1.0);
    meshCoordinates = new CoordinateSystem(meshOrigin,meshZ,meshAxis);
    curveCoordinates = curveInfo.getCoords();
    //set some variables
    curveVertPos = curve.getVertexPositions();
    m = (int)rounds*segmentsPerRound+1;
    n = curveVertPos.length;
    yAdd = new Vec3(0.0,0.0,0.0);
    meshVertPos = new Vec3[m][n];
    vertexPos = new Vec3(0.0,0.0,0.0);
    vertexCoords = meshCoordinates.duplicate(); //This just a fast way to declare a coordinate system
    // create mesh properties
    mSmooth = new float[m];
    nSmooth = curve.getSmoothness();
    smoothingMethod = curve.getSmoothingMethod();
    //smoothingMethod = Mesh.INTERPOLATING;
    //smoothingMethod = Mesh.APPROXIMATING;
    //smoothingMethod = Mesh.NO_SMOOTHING;
    mClosed = false;
    nClosed = curve.isClosed();
    //Calculate the new coordinate points
    //The idea is to set a coordinate system to the vertex 
    //that is being copied and trace the origin of it back 
    //to the coordinate system of the mesh.
    for (i=0;i<m;i++)
    {
        mSmooth[i] = 1.0f;
        yAdd.set(0.0,(double)pitchPerStep*i,0.0);
        meshCoordinates.setOrientation(0.0,-rotPerStep*i,0.0);
        //meshCoordinates.setOrigin(yAdd);
        for (j=0;j<n;j++)
        {
            vertexCoords.setOrigin(curveVertPos[j]);
            vertexCoords.transformCoordinates(curveCoordinates.fromLocal());
            vertexCoords.transformCoordinates(meshCoordinates.fromLocal());
            vertexPos = vertexCoords.getOrigin().plus(yAdd);
            meshVertPos[i][j] = vertexPos;
        }
    }
    // "Make a mess"
    mesh = new SplineMesh(meshVertPos,mSmooth,nSmooth,smoothingMethod,mClosed,nClosed);
    meshInfo = new ObjectInfo(mesh,meshCoordinates,"HelixExtrude");
    // Add it to the scene
    window.addObject(meshInfo,null); 
    window.rebuildItemList();
    
     
  • Pete

    Pete - 2010-02-14

    And a minor fix yet….

    This line:
    m = (int)rounds*segmentsPerRound+1;
    should be:
    m = (int)(rounds*segmentsPerRound+1);

    and after the for-loops add:
    meshCoordinates.setOrientation(0.0,0.0,0.0);
    :)

     
  • Jeff Silver

    Jeff Silver - 2010-02-14

    Thanks guys! Especially peastman for the pointer to ExtrudeTool (well if you don't know about it, who would?) I did actually get something working by diving into the ExtrudeDialog class. In order to instantiate it successfully, I had to have an object selected. What I didn't know was that you can invoke a method at class level, as is done in ExtrudeTool. (I've done some Java, but I'm mainly a C/Python guy.) Personally, I'd have done the implementation the other way round; putting the functionality in a non-GUI class and treating the GUI class as a layer on top of that. But the class-level invocation makes the distinction somewhat academic.

     
  • Peter Eastman

    Peter Eastman - 2010-02-14

    > Personally, I'd have done the implementation the other way round; putting the functionality in a non-GUI class and treating the GUI class as a layer on top of that.

    So would I. :)  It's been a lot of years since I wrote that, and I think my programming style has improved since then.

    Peter

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks