Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Collaboration Time!!!

Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
Okay Ladies and Gents, 

I am wanting to create a dummy proof table, meaning that the user is only going to have certain options to choose from and BAM, they get a modeled table. I've got some of the code and some of the parts but really need the support of the community to finish this off. Yes, I admit, I am wanting to use this as a learning experience but I thought this would be a good idea to start using OnShape and FS to it's potential. 

I have the table top already made and I have a separate feature to bring in the legs... While this is fine, it's not %100 what I am after. 


Here is the link to the document
https://cad.onshape.com/documents/986d7839f605b08daf5b62c4/w/99657d4a66565336c6f8f2ed/e/37a9ad7c057bbfc7f7a76bb5

Here is the code to create the table top
FeatureScript 392;
import(path : "onshape/std/geometry.fs", version : "392.0");

export enum TableTopSize
{
    annotation {"Name" : "24 inch"}
    ONE,
    annotation {"Name" : "30 inch"}
    TWO,
    annotation {"Name" : "36 inch"}
    THREE,
    annotation {"Name" : "42 inch"}
    FOUR,
}
export function evTableTopSize(value is TableTopSize)
{
    return {
        "ONE" : 24*inch,
        "TWO" : 30*inch,
        "THREE" : 36*inch,
        "FOUR"  : 42*inch
    }[value as string];
}
annotation { "Feature Type Name" : "Table Creator" }
export const myTableCreator = defineFeature(function(context is Context, id is Id, definition is map)
    precondition
    {
        annotation { "Name" : "Table Top Size" }
        definition.tableTopSize is TableTopSize;
        
        
    }
    {
        
        var tableTop = evTableTopSize(definition.tableTopSize);
        var legLoc1 = 4*inch;
        var legLoc2 = tableTop - 4*inch;
        var tableVerticies = [vector(0*inch, 0*inch), vector(0*inch, tableTop), vector(tableTop, tableTop), vector(tableTop, 0*inch)];
        var legLocationVerticies = [vector(legLoc1, legLoc1), vector(legLoc1, legLoc2), vector(legLoc2, legLoc1), vector(legLoc2, legLoc2)];
        var tableSketch = newSketch(context, id + "TableSketch", {
                "sketchPlane" : qCreatedBy(makeId("Top"), EntityType.FACE)
        });
        skLineSegment(tableSketch, "line1", {
                "start" : tableVerticies[0],
                "end" : tableVerticies[1]
        });
        skLineSegment(tableSketch, "line2", {
                "start" : tableVerticies[1],
                "end" : tableVerticies[2]
        });
        skLineSegment(tableSketch, "line3", {
                "start" : tableVerticies[2],
                "end" : tableVerticies[3]
        });
        skLineSegment(tableSketch, "line4", {
                "start" : tableVerticies[3],
                "end" : tableVerticies[0]
        });
        skCircle(tableSketch, "Leg1", {
                "center" : legLocationVerticies[0],
                "radius" : 1 * inch
        });
        skCircle(tableSketch, "Leg2", {
                "center" : legLocationVerticies[1],
                "radius" : 1 * inch
        });
        skCircle(tableSketch, "Leg3", {
                "center" : legLocationVerticies[2],
                "radius" : 1 * inch
        });
        skCircle(tableSketch, "Leg4", {
                "center" : legLocationVerticies[3],
                "radius" : 1 * inch
        });
        skSolve(tableSketch);
        var tableRegion = qSketchRegion(id + "TableSketch");
        extrude(context, id + "extrude1", {
                "entities" : qSketchRegion(id + "TableSketch"),
                "endBound" : BoundingType.BLIND,
                "depth" : 1.5 * inch
        });
    });
And here is what I have to bring in the leg

FeatureScript 392;
import(path : "onshape/std/geometry.fs", version : "392.0");
PART::import(path : "b0ce9ce1e52b3c3c2503487d", version : "2e1edf42723d4d88750dd977");
// PART::import(path : "1c26e00fc778219a6a385f3a", version : "f71775f0a10f7cfd8dbea65b");
// PART::import(path : "c79f1a234a9f7dcf3cd1da1e", version : "60326f3c3ce5854d658b085b");


// export enum LegOptions
// {
//     annotation {"Name": "Round Leg 1"}
//     FpDkrwSQ3HtgoSB_1,
//     annotation {"Name": "Round Leg 2"}
//     FTDZgmKUHISz1PO_0,
//     annotation {"Name": "Round Leg 3"}
//     FhcUhDPPvmJadnm_0
// }
annotation { "Feature Type Name" : "Import Leg" }
export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
    precondition
    {
        annotation { "Name" : "Point", "Filter" : EntityType.VERTEX, /*"MaxNumberOfPicks" : 1*/ }
        definition.point is Query;

        // annotation { "Name" : "Leg Choice" }
        // definition.legChoice is LegOptions;
        
    }
    {
        var transforms = [];
        var point = definition.point;
        opMergeContexts(context, id + "mergeContexts1", {
                    "contextFrom" : PART::build()
                });
        var importedPart = qCreatedBy(id + "mergeContexts1", EntityType.BODY);
        var location = evVertexPoint(context, { "vertex" : point });
        var origin = vector(0, 0, 0) * inch;
        opTransform(context, id + "transform1", { "bodies" : importedPart, "transform" : transform(location - origin) });
    });



The problem is that I want to eliminate all mouse clicks and be able to toggle between different legs.

Any and all help is appreciated. 

Thank you
Digital Engineering

Comments

  • 3dcad3dcad Member, OS Professional, Mentor Posts: 2,475 PRO
    What if you create parametric table with default tools and use FS to run parameters? I understand that you are using this as example but I would see a lot of potential if it is possible to create 'user interface' and limits for parameters using feature script.

    A while back, I was thinking chest of drawers created completely with FS but it needs some serious coding to create slides etc. so I came up with idea to combine FS with parametric model 
    //rami
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    So you're saying kind of like Inventor with forms? A 'pre-modeled template' so to say?  That would work and I would like to see an example of what you are talking about. 

    I admit, I need to brush up on my coding and maybe even take a few more classes so that I understand everything. 
    So I will have to apologize up front for the waves of questions I will have throughout this process.

    What I lack in knowledge I more than make up for in enthusiasm.  
    Digital Engineering
  • 3dcad3dcad Member, OS Professional, Mentor Posts: 2,475 PRO
    I have only two problems with FS. 1. I don't know how to code 2. At the moment I don't have enough time to learn.

    But I'm very interested in use cases, so I would also like to see an example of what I suggested (if it's possible).
    //rami
  • lougallolougallo Member, Moderator, Onshape Employees, Developers, csevp Posts: 2,004
    edited August 2016
    A good example is in the FS Example doc with the measure.  That uses the measure to add more rungs to a ladder (if you wanted to get fancy with the number of legs). It could be brought in like you have it setup in your second script, add that in the first but then insert it derived and then transform it into position
    Lou Gallo / PD/UX - Support - Community / Onshape, Inc.
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    So many thanks to everyone especially @lougallo to make this become a reality. 

    This is only the beginning and I am looking forward to elaborating and collaborating on this project. 

    Here is the code to generate a table with only 2 options.

    FeatureScript 392;
    import(path : "onshape/std/geometry.fs", version : "392.0");
    PART1::import(path : "392d6670a9ca658624f6f039", version : "4ea81d227ee95c6d48b0f081");
    PART2::import(path : "50535b0307a6601ab9087392", version : "454d11ae0c9aa25211855470");
    
    
    export enum TableTopSize
    {
        annotation { "Name" : "24 inch" }
        ONE,
        annotation { "Name" : "30 inch" }
        TWO,
        annotation { "Name" : "36 inch" }
        THREE,
        annotation { "Name" : "42 inch" }
        FOUR,
    }
    
    export function evTableTopSize(value is TableTopSize)
    {
        return {
                    "ONE" : 24 * inch,
                    "TWO" : 30 * inch,
                    "THREE" : 36 * inch,
                    "FOUR" : 42 * inch
                }[value as string];
    }
    
    export enum LegType
    {
        annotation { "Name" : "Leg 1" }
        LEG1,
        annotation { "Name" : "Leg 2" }
        LEG2,
    }
    annotation { "Feature Type Name" : "Table Creator" }
    export const myTableCreator = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "Table Top Size" }
            definition.tableTopSize is TableTopSize;
            annotation { "Name" : "Leg Choice" }
            definition.legChoice is LegType;
        }
        {
    
            var tableTop = evTableTopSize(definition.tableTopSize);
            var legLoc1 = 4 * inch;
            var legLoc2 = tableTop - 4 * inch;
            var tableVertices = [vector(0 * inch, 0 * inch), vector(0 * inch, tableTop), vector(tableTop, tableTop), vector(tableTop, 0 * inch)];
            var legLocationVertices = [vector(legLoc1, legLoc1), vector(legLoc1, legLoc2), vector(legLoc2, legLoc1), vector(legLoc2, legLoc2)];
            var tableSketch = newSketch(context, id + "TableSketch", {
                    "sketchPlane" : qCreatedBy(makeId("Top"), EntityType.FACE)
                });
            skLineSegment(tableSketch, "line1", {
                        "start" : tableVertices[0],
                        "end" : tableVertices[1]
                    });
            skLineSegment(tableSketch, "line2", {
                        "start" : tableVertices[1],
                        "end" : tableVertices[2]
                    });
            skLineSegment(tableSketch, "line3", {
                        "start" : tableVertices[2],
                        "end" : tableVertices[3]
                    });
            skLineSegment(tableSketch, "line4", {
                        "start" : tableVertices[3],
                        "end" : tableVertices[0]
                    });
            skCircle(tableSketch, "Leg1", {
                        "center" : legLocationVertices[0],
                        "radius" : 1 * inch
                    });
            skCircle(tableSketch, "Leg2", {
                        "center" : legLocationVertices[1],
                        "radius" : 1 * inch
                    });
            skCircle(tableSketch, "Leg3", {
                        "center" : legLocationVertices[2],
                        "radius" : 1 * inch
                    });
            skCircle(tableSketch, "Leg4", {
                        "center" : legLocationVertices[3],
                        "radius" : 1 * inch
                    });
            skSolve(tableSketch);
            var tableRegion = qSketchRegion(id + "TableSketch");
            extrude(context, id + "extrude1", {
                        "entities" : tableRegion,
                        "endBound" : BoundingType.BLIND,
                        "depth" : 1.5 * inch
                    });
    
            // Have to get the origin so I can covert your 2D points into 3D world points for the transform
            var origin = vector(0, 0, 0) * inch;
            var xaxis = vector(0, 0, 1) * inch;
            var zaxis = vector(1, 0, 0) * inch;
            var skplane = plane(origin, xaxis, zaxis);
            // Loop thru the points in legLocationVertices
            for (var i = 0; i <= size(legLocationVertices) - 1; i += 1)
            {
                {
                    // Convert to world 3D points
                    var point = planeToWorld(skplane, legLocationVertices[i]);
                    // Build the PS in a separate context
                    var legimport is Context = PART1::build();
                    // Determine the leg choice from default LEG1
                    if(definition.legChoice == LegType.LEG2){
                            legimport = PART2::build();
                        }
                
                    // Delete its construction planes and origin
                    opDeleteBodies(legimport, id + "deleteDefaultGeometry", {
                                "entities" : qUnion([
                                            qConstructionFilter(qBodyType(qEverything(EntityType.BODY), BodyType.SHEET), ConstructionObject.YES),
                                            qCreatedBy(makeId("Origin"))
                                        ])
                            });
                    opMergeContexts(context, id + '_' + i + "mergeContexts", {
                                "contextFrom" : legimport
                            });
    
                    var importedPart = qCreatedBy(id + '_' + i + "mergeContexts", EntityType.BODY);
    
                    opTransform(context, id + '_' + i + "transform", { "bodies" : importedPart, "transform" : transform(point) });
                }
            }
        });


    Please let me know what you all think!! 
    Digital Engineering
  • lougallolougallo Member, Moderator, Onshape Employees, Developers, csevp Posts: 2,004
    Lou Gallo / PD/UX - Support - Community / Onshape, Inc.
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    Amazing stuff @lougallo !!

    Digital Engineering
  • 3dcad3dcad Member, OS Professional, Mentor Posts: 2,475 PRO
    Link this into webshop and get orders with updated BOM into production - that would be pretty cool..

    @lougallo
    thanks for this example, I suppose you 'modeled' table top with FS code? Is it possible to do the same so that you have table top in one part studio and you use variables to control the size?
    //rami
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    I've inquired on this and I think FS is not capable of doing this (for now)

    I get the feeling that it is just around the corner.
    Digital Engineering
  • 3dcad3dcad Member, OS Professional, Mentor Posts: 2,475 PRO
    I suppose it could be possible but variables need to be on same part studio where you run 'table script'.. I really like the super clean feature list of that Lou's example though..
    //rami
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    @lougallo@ilya_baran @kevin_o_toole_1
    can you explain why this will not work if I change the sketchPlane?
    from:
    var tableSketch = newSketch(context, id + "TableSketch", {
                    "sketchPlane" : qCreatedBy(makeId("Top"), EntityType.FACE)
                });
    to:
    var tableSketch = newSketch(context, id + "TableSketch", {
                    "sketchPlane" : qCreatedBy(makeId("Front"), EntityType.FACE)
                });

    Digital Engineering
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    edited August 2016
    Okay, so further playing around with this it seems that this particular code is only good for a sketch that is created on the 'Top' plane.

    What if a user wanted to use the 'Front' plane? 

    Further more, if the user wanted to make a symmetric part and place legs on the bottom and plates on the top?  

    Edit: Also the orientation of the derived/imported part, for example I want the legs to come in rotated 45 degrees. 
    Digital Engineering
  • lougallolougallo Member, Moderator, Onshape Employees, Developers, csevp Posts: 2,004
    You have to remember that when you use a version (linked docs) it is not changable.  You can run FS on a model and change things but in the case I had, I had to have the data there... However you could do alterations to it after the fact but I would probably just build the components via FS to start.
    Lou Gallo / PD/UX - Support - Community / Onshape, Inc.
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    @lougallo

    I don't want to change the derived part, rather just place it on an exact point and plane (whether its on the top or bottom) and if the base sketch, in this case the table top, if it's on the top, front or right plane and then rotate the legs. 

    The reason I would like to import parts rather than writing in code is to be able to import complicated parts that would require too much code to write (if it's even possible)

    Forgive me if I am misunderstanding something. 


    Digital Engineering
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    I imagine it would rely heavily on the origin of the imported part studio? 
            var origin = vector(0, 0, 0) * inch;
            var xaxis = vector(0, 0, 1) * inch;
            var zaxis = vector(1, 0, 0) * inch;
            var skplane = plane(origin, xaxis, zaxis);
    This section is still a bit confusing to me... I assume that the understanding of this would point me in the right direction of what I want to accomplish.

    Digital Engineering
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 5,715
    Use newSketchOnPlane - you can pass your skplane into it and it's much easier to use.
    Senior Director, Technical Services, EMEAI
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    @NeilCooke I apologize, but I'm not %100 sure what you mean? 

    I have a FS that creates a rectangle on the 'Front' plane and has circle cut outs that can be either on the right or left.

    I have a PS that is not ambidextrous (there for would have to be rotated 180 degrees depending on the side.

    Also, my rectangle is extruded symmetrically. So I would like to be able to imported part follow the desired face. 

    Since we can not control variables from PS through FS, I figured this might be a sort of work around (if at all possible to do the above mentioned)
    Digital Engineering
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 5,715
    edited August 2016
    Sorry I didn't read the whole thread just your bit about not being able to create a sketch on the front plane - I will read and answer later.
    Senior Director, Technical Services, EMEAI
  • Dylan_StewartDylan_Stewart Member, Developers Posts: 107 PRO
    @NeilCooke Thank you. 

    I'm now wondering if the 'opTransform' can be simplified?

    opTransform(context, id + "transform1",{
               "bodies" : importedPart,
               "transform" : ??vector(1, 1)??

    Digital Engineering
Sign In or Register to comment.