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.

Why does this mate connector flip 180° depending on the curve angle?

Evan_ReeseEvan_Reese Member Posts: 2,077 PRO
edited November 2021 in General
Why does a mate connector made on a curve flip depending on where the curve is relative to the front plane? I know I could set the secondary direction of the mate connector to the top plane to probably fix this, but it's I think it's really a demo of the curve's orientations changing which causes downstream issues for me that can't be easily fixed.

I made this simplified example document of the issue I'm having, but this is actually causing some pretty big headaches on a pretty big project for me right now. I've got a master sketch that is driving all kinds of things including some patterns and things like that. This issue seems to also mess up some of the replicate features in our assembly, since instances on the other side of the front plane are all flipped the wrong way and the mate features can't be manually flipped.

Anybody know why it's this way?


Evan Reese / Principal and Industrial Designer with Ovyl
Website: ovyl.io

Best Answer

Answers

  • konstantin_shiriazdanovkonstantin_shiriazdanov Member Posts: 1,221 ✭✭✭✭✭
    I believe since x axis of mate connector is not constrained here it tries to be aligned at sharp angle to global x direction in the first place, and because of this it flips direction when crosses global x axis
  • Evan_ReeseEvan_Reese Member Posts: 2,077 PRO
    Thanks, I guess I get that, but it does feel like it's pretty unpredictable. The main issue it's causing for me is when using replicate in an assembly. Instances on one side of the x axis work, but instances on the other side and upside down and can't be edited, so I'll have to forget about replicate for now and just copy/paste and mate each one individually, which I don't love.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • mahirmahir Member, Developers Posts: 1,301 ✭✭✭✭✭
    Thanks, I guess I get that, but it does feel like it's pretty unpredictable.
    It's predictable, but probably not intuitive. Hopefully, for your specific application it won't be too difficult to add secondary axis geometry that can move with your master sketch elements.
  • Evan_ReeseEvan_Reese Member Posts: 2,077 PRO
    haha, I appreciate the semantic pedantry. You're right, it's unintuitive.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,056 PRO
    edited November 2021
    I've had this unintuitive feature pop when creating a sketch. I think it's inherent in all 3D CAD systems. I've always wondered how OS & SW handled this basic issue. It's discontinuous and ubiquitous.
    .

    Let's say you have nothing to reference, a blank slate, and you want to create a plane normal to Z:

    So you cross Z & X to create Y, then Z & Y to create the real X. This is your algorithm, a simple triple product, a mate connector.




    Now you want a plane normal to X:


    Use your algorithm and X=0 and everything crashes. At some point you have to be discontinuous and change your reference to Y.



    In an empty world, you cannot have a continuous expression making a simple decision to create a plane. You have to decide whether  you're crossing with X or Y. So when do you decide?


    //create sketch
    var xDir;
    if (abs(evAxis(context, {"axis" : MCs[0]}).direction[1]) > .707) xDir=vector(1, 0, 0); else xDir=vector(0, 1, 0); //flip x along y


    When I wrote the cable featurescript, the cable rendering would crash every so often. Since I was creating the sketch relative to the world, I have to decide which to cross with X or Y. After I added this, it became more robust, at least for sketch orientation creation.


    I think what your seeing is this basic 3D artifact animated. In 3D cad you have to make this decision at some time. Aligning X is always a real pain.
      



  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,200
    Answer ✓
    It's not just 3D CAD, it's a mathematical issue -- there is just no way to assign a coordinate system continuously given one axis: https://en.wikipedia.org/wiki/Hairy_ball_theorem
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • Evan_ReeseEvan_Reese Member Posts: 2,077 PRO
    Thanks @billy2and @ilya_baran. I think that makes sense.

    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,056 PRO
    What's most interesting is it's always been there and we've been dealing with it since the concept of x, y, z.



    @ilya_baran "hairy_ball_theorem" where do you find this stuff?




  • George_AndersonGeorge_Anderson Member Posts: 71 ✭✭
    edited November 2021
    Hence the `perpendicularVector` function I guess!

    export function perpendicularVector(vec is Vector) returns Vector<br>precondition @size(vec) == 3;<br>{<br>    if (vec[0] is ValueWithUnits)<br>        vec = [vec[0].value, vec[1].value, vec[2].value] as Vector;<br>    if (squaredNorm(vec) < TOLERANCE.zeroLength * TOLERANCE.zeroLength)<br>        return vector(1, 0, 0);<br>    var different = vector(0, 0, 0);<br>    // The numbers are "random" and close to 1.  They're to avoid instability in cases likely to occur.<br>    if (abs(vec[0]) > 1.036663652861932668633 * abs(vec[1]))<br>    {<br>        if (abs(vec[0]) > .951702989392233451722 * abs(vec[2]))<br>            different[2] = 1;<br>        else<br>            different[1] = 1;<br>    }<br>    else<br>    {<br>        if (abs(vec[1]) > .920419947455385938102 * abs(vec[2]))<br>            different[0] = 1;<br>        else<br>            different[1] = 1;<br>    }<br>    return normalize(cross(different, vec));<br>}

    (^^ Not sure why this formats as one line....)

  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,056 PRO
    I'm wondering if your function is a cross product?  Looks like it.

    I think they're checking for 2 parallel vectors which will divide by zero can crash. Not a good thing.


Sign In or Register to comment.