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.

featurescript: How to get a midpoint

alan_1alan_1 Member Posts: 14 EDU
I am trying to get a midpoint of a line

Here's the parameter:
        annotation { "Name" : "Lines", "Filter" : EntityType.EDGE && SketchObject.YES && GeometryType.LINE }
        definition.lines is Query;

And here's some code that I wrote.
        const lines = evaluateQuery(context, definition.lines);

        for (var line in lines) {
            var endpoints = qVertexAdjacent(line, EntityType.VERTEX);   
            for (var epoint in endpoints ) {
                var point is Vector = worldToPlane(topPlane, evVertexPoint(context, { "vertex" : epoint }));
                var pvec = vector(point[0], point[1]);
                // Will use the point for various operations.
            }
        }


I want to get the midpoint of each line and use it to do an extrude.  Any idea how I might do this?  The code above is just a starting point (no pun intended).  The line with worldToPlane() is failing for me.

Disclaimer: I am a featurescript noob.

Tagged:

Comments

  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    One easy way is with evEdgeTangentLine.

        for (var line in lines) { 
            var midpoint = evEdgeTangentLine(context, {
                    "edge" : line,
                    "parameter" : 0.5
            }).origin;
            debug(context, midpoint);
        }
  • alan_1alan_1 Member Posts: 14 EDU
    interesting and I might say weird.  But it works.
    Thanks!
    I also found that this works:
                var endpoints = evaluateQuery(context, qVertexAdjacent(line, EntityType.VERTEX));
                var A is Vector = evVertexPoint(context, { "vertex" : endpoints[0] });
                var B is Vector = evVertexPoint(context, { "vertex" : endpoints[1] });
                var midpoint = vector( (A[0] + B[0]) / 2, (A[1] + B[1]) / 2 );


  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,215
    edited June 2016
    @alan_1 in your method, your resulting midpoint vector is 2D (since you didn't add a third component).  An easier way of doing this that will give you a 3D vector is just:

    var midpoint = (A + B ) / 2;
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • alan_1alan_1 Member Posts: 14 EDU
    ok.  I also tried doing a vector difference, but that's giving me negative units.  The result is then treated as having a different type than other vectors and I can no longer do arithmetic on them.  Here's my example:
                var endpoints = evaluateQuery(context, qVertexAdjacent(line, EntityType.VERTEX));
                var A is Vector = evVertexPoint(context, { "vertex" : endpoints[0] });
                var B is Vector = evVertexPoint(context, { "vertex" : endpoints[1] });
                var normal = perpendicularVector(B - A) / norm(B - A);
                A += normal; // I get the error "Precondition of operator+ failed (lhs.unit == rhs.unit)"


    Here's the value of normal:
    Vector : [ ValueWithUnits : { "unit" : UnitSpec : { "meter" : -1 } , "value" : 6.273386374957768 } , ValueWithUnits : { "unit" : UnitSpec : { "meter" : -1 } , "value" : 8.171252121669061 } , ValueWithUnits : { "unit" : UnitSpec : { "meter" : -1 } , "value" : -0 } ]

    Note the '"meter" : -1'

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,215
    I am not entirely sure what you mean by "get the midpoint and use it to do an extrude" -- perhaps if you post a manually modeled picture of what you want to accomplish in FS we could be more helpful.

    In terms of the units mismatch, here's how to think about it to understand what's going on:

    A and B are vectors with length units.  B - A is therefore also a vector with length units.
    perpendicularVector(A - B ) is a vector with no units and of length 1.  (I'm clarifying the documentation to state that explicitly)
    norm(B - A) has length units (it is the distance between A and B )
    If you divide a unitless vector by a length, you get a vector with units 1/length, hence the meters^-1 in your output.

    Perhaps you wanted to multiply by norm(A - B ) instead?  Also, perhaps you want to do evOwnerSketchPlane(context, { entity : line }).normal
    to get the normal of the line's sketch plane (rather than an arbitrary perpendicularVector).
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • alan_1alan_1 Member Posts: 14 EDU
    That's very helpful Ilya.  Thanks!  I was misinterpreting the documentation of perpendicularVector() and the meaning of 'UnitSpec : { "meter" : -1 }'.  I had been hoping to get a vector in the line's sketch plane that is perpendicular to the vector A-B, but I still don't see an easy way to do that with the tools given.  I have been digging trying to find something appropriate.  Maybe using skConstraint() with "constraintType" : ConstraintType.PERPENDICULAR and with two lines: the original one discussed and one that goes through the midpoint.  The only problem is I don't know how to create a new point for the 2nd plane without specifying its location and thus defeating the skContstraint().  Maybe I'm just thinking about it wrong though.
    BTW, the documentation for skConstraint doesn't even mention "localFirst".  Doh!  I got lucky and found a reference to it in an example.  Who knows what other mystery parameters it might accept!?

    There's probably a way to project the perpendicular line onto the sketch plane I suppose.  skConstraint() seems to have something like this.

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,215
    Here's some example code that will hopefully help:

    annotation { "Feature Type Name" : "Perpendicular" }
    export const perpendicular = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "My Query", "Filter" : EntityType.EDGE && SketchObject.YES, "MaxNumberOfPicks" : 1 }
            definition.line is Query;
        }
        {
            var sketchPlane is Plane = evOwnerSketchPlane(context, { "entity" : definition.line });
            var selectedLine is Line = evEdgeTangentLine(context, { "edge" : definition.line, "parameter" : 0.5 });
            var midpoint is Vector = selectedLine.origin; // Length units
            var perpendicular is Vector = cross(sketchPlane.normal, selectedLine.direction); // Unitless, normalized
            debug(context, line(midpoint, perpendicular));
        });


    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • alan_1alan_1 Member Posts: 14 EDU
    Thanks again.  Problem solved!

Sign In or Register to comment.