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.

New Feature: Attractor Pattern

Evan_ReeseEvan_Reese Member Posts: 482 PRO
edited August 31 in General
I'm happy to release Attractor Pattern for use. There are more things I'd like to do with this sometime, but the core functionality is there. Since it's a kind of complex UI, I made a 6-minute video explaining what everything is. Here's an example of one of the many things you could use it for.


I want to thank @maximilian_schommer for his Surface Pattern feature, which I dissected and borrowed from heavily for this feature. Couldn't have done it without that great reference. Also, big thanks to @ilya_baran whose pseudo-random number generator I co-opted for the random pattern function.

If you run into unexpected behavior while using it, please let me know and share a document with an example so I can improve it.

If you check out my code and see any obvious ways to optimize the performance, I'm very open to ideas. Since it's such a heavy feature efficiency is extra important, and I don't know much about shaving milliseconds off of operations.
Evan Reese / Principal and Industrial Designer with Fractal
Website: fractalmade.com
Instagram: @evan.reese.designs

Comments

  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    @Evan_Reese

    Could you add a HSV input for the colour?

    It seems more intuitive than RGB for some colours (at least for me).

    I did do an algorithm a little while ago for converting HSV to a colour (based on a StackExchange answer):
    https://cad.onshape.com/documents/44a687b24ed2559c60798e23/w/376aa1c19dcc30a04d5ed003/e/7491f2707f2ef42a181f1a22

    export const HUE_BOUNDS = { (unitless) : [0, 0, 360] } as IntegerBoundSpec;
    export const SATURATION_VALUE_BOUNDS = { (unitless) : [0, 0.75, 1] } as RealBoundSpec;
    
    export function colorHsv(hue is number, saturation is number, value is number) returns Color
    precondition
    {
        isInteger(hue, HUE_BOUNDS);
        isReal(saturation, SATURATION_VALUE_BOUNDS);
        isReal(value, SATURATION_VALUE_BOUNDS);
    }
    {
        // Algorithm from https://cs.stackexchange.com/questions/64549/convert-hsv-to-rgb-colors
        var h is number = hue / 60;
        if (hue >= 300)
            h = (hue - 300) / 60;
    
        const max is number = value;
        const chroma is number = saturation * value;
        const min is number = max - chroma;
    
        var red;
        var green;
        var blue;
    
        if (h < 0)
        {
            red = max;
            green = min;
            blue = min - h * chroma;
        }
        else if (h < 1)
        {
            red = max;
            green = min + h * chroma;
            blue = min;
        }
        else if (h < 2)
        {
            red = min - (h - 2) * chroma;
            green = max;
            blue = min;
        }
        else if (h < 3)
        {
            red = min;
            green = max;
            blue = min + (h - 2) * chroma;
        }
        else if (h < 4)
        {
            red = min;
            green = min - (h - 4) * chroma;
            blue = max;
        }
        else if (h < 5)
        {
            red = min + (h - 4) * chroma;
            green = min;
            blue = max;
        }
    
        return color(red, green, blue);
    }
    MB - I make FeatureScripts: View FeatureScripts
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    @Evan_Reese

    Could you add a HSV input for the colour?
    Yup. I'll review your code and implement it sometime.
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    As a test, I just added HSL (this is what I'm used calling it) to my Part Color feature. I'll add it to Attractor Pattern soon too. Thanks for the suggestion and code @MBartlett21 !

    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • mark_leichlitermark_leichliter Member Posts: 12 ✭✭
    Great work, Evan! And thanks for including an example of multiple patterns - looking forward to messing around with this when I have a chance. Thanks again!
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    @Evan_Reese

    Could you add a HSV input for the colour?

    It seems more intuitive than RGB for some colours (at least for me).

    I did do an algorithm a little while ago for converting HSV to a colour (based on a StackExchange answer):
    https://cad.onshape.com/documents/44a687b24ed2559c60798e23/w/376aa1c19dcc30a04d5ed003/e/7491f2707f2ef42a181f1a22

    export const HUE_BOUNDS = { (unitless) : [0, 0, 360] } as IntegerBoundSpec;
    export const SATURATION_VALUE_BOUNDS = { (unitless) : [0, 0.75, 1] } as RealBoundSpec;
    
    export function colorHsv(hue is number, saturation is number, value is number) returns Color
    precondition
    {
        isInteger(hue, HUE_BOUNDS);
        isReal(saturation, SATURATION_VALUE_BOUNDS);
        isReal(value, SATURATION_VALUE_BOUNDS);
    }
    {
        // Algorithm from https://cs.stackexchange.com/questions/64549/convert-hsv-to-rgb-colors
        var h is number = hue / 60;
        if (hue >= 300)
            h = (hue - 300) / 60;
    
        const max is number = value;
        const chroma is number = saturation * value;
        const min is number = max - chroma;
    
        var red;
        var green;
        var blue;
    
        if (h < 0)
        {
            red = max;
            green = min;
            blue = min - h * chroma;
        }
        else if (h < 1)
        {
            red = max;
            green = min + h * chroma;
            blue = min;
        }
        else if (h < 2)
        {
            red = min - (h - 2) * chroma;
            green = max;
            blue = min;
        }
        else if (h < 3)
        {
            red = min;
            green = max;
            blue = min + (h - 2) * chroma;
        }
        else if (h < 4)
        {
            red = min;
            green = min - (h - 4) * chroma;
            blue = max;
        }
        else if (h < 5)
        {
            red = min + (h - 4) * chroma;
            green = min;
            blue = max;
        }
    
        return color(red, green, blue);
    }
    It's implemented 👍🏼
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • romeograhamromeograham Member Posts: 431 PRO
    My Goodness @Evan_Reese
    This is very, very nice.
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    My Goodness @Evan_Reese
    This is very, very nice.
    Thanks, Romeo.
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • romeograhamromeograham Member Posts: 431 PRO
    One initial thought - I think I'd like radial options (particularly for rotation). Think of a mandala / sunburst pattern - could be quite simple if the pattern was build radially, rather than on a grid. This becomes (maybe) useful for seed bodies that are not round / square. 

    Or - could we have all the instance's Y-axis (say) point toward your attractor...if the attractor was a point, it would be kind of a radial pattern.

    Anyway - super cool feature. Thanks for sharing it with us!
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    edited September 3
    @Evan_Reese
    I had a bit of a look at the speed of the feature, and found that the default transforms for scaling and rotation are taking up a fair proportion of the time. If they are instead done with identityTransform, the total time reduces somewhat.
    Edited Code:
                // part rotation
                var angleTransform = identityTransform();
                if (definition.rotationBool)
                {
                    var remapAngle = remap(distances[i], measuredMin, measuredMax, angleNear, angleFar);
                    angleTransform = rotationAround(angleAxis, remapAngle);
                }
    
                // scale
                var scaleTransform = identityTransform();
                if (definition.scaleBool)
                {
                    var remapX = remap(distances[i], measuredMin, measuredMax, scaleNear.x, scaleFar.x);
                    var remapY = remap(distances[i], measuredMin, measuredMax, scaleNear.y, scaleFar.y);
                    var remapZ = remap(distances[i], measuredMin, measuredMax, scaleNear.z, scaleFar.z);
                    scaleTransform = scaleNonuniformly(remapX, remapY, remapZ, bodyMate);
                }
    MB - I make FeatureScripts: View FeatureScripts
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    Also, would you be able to change the rotation inputs to allow full 360 bounds (including negative)

    If you use the ANGLE_360_BOUNDS and ANGLE_360_ZERO_DEFAULT_BOUNDS for the input, it will allow all available angles including negative ones.
    MB - I make FeatureScripts: View FeatureScripts
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    Thanks for looking at the performance! I'm sure I don't know enough about that. I'll look into your suggestion there, but it's new to me, so I'll have some reading to do.
    As for the angles, I'm using custom bounds so you can actually put in numbers much higher than 360, which can give some cool effects. I can update it so it can go just as far in the negative direction in case that's useful. I actually don't think I understand the request fully though since I can't imagine why I'd need to enter a negative value, when I can just tick the opposite direction boolean. What am I missing?



    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    One initial thought - I think I'd like radial options (particularly for rotation). Think of a mandala / sunburst pattern - could be quite simple if the pattern was build radially, rather than on a grid. This becomes (maybe) useful for seed bodies that are not round / square. 

    Or - could we have all the instance's Y-axis (say) point toward your attractor...if the attractor was a point, it would be kind of a radial pattern.

    Anyway - super cool feature. Thanks for sharing it with us!
    I like the idea of adding some more base grids, maybe similar to my Speaker Pattern feature. I could also do just a standard polar grid. Maybe someday. I've also considered making them all point toward the attractor, which could be done, but is definitely more complex. It's on my list, but not at the top. Next, I'd like to get some kind of falloff types other than linear so the pattern transitions more smoothly. I'm also interested in finding a way to pull/repell instances toward and away from the attractor (while keeping them on the surface).
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    @Evan_Reese
    The names of the Onshape bounds are misleading.
    If you look at the source[1], it allows from -100000 to 100000.

    [1]: https://cad.onshape.com/documents/12312312345abcabcabcdeff/v/812aa61a84190f49bc3c509d/e/87b09e244a234eb791b47826?jumpToIndex=7367&showReturnToWorkspaceLink=true

    The reason I would like it to be able to have negative numbers is to have it configurable more easily, rather than having to configure opposite direction. For instance, the move face feature does not allow a negative number, so I have to configure its opposite direction input as well.
    MB - I make FeatureScripts: View FeatureScripts
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    That makes sense, and thanks for pointing that out about the default bounds. I've added negative bounds but kept them custom so I can have different defaults for Near and Far values, so users see something cool happen as soon as they check the box.
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    I just updated the feature to now have one non-linear falloff type to get a wavy look. I also made it so that composite parts can be colored by coloring the faces of each object.
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    @Evan_Reese

    Could you make it use booleanBodies instead of opBoolean, please, so that it can work with sheet metal parts?
    MB - I make FeatureScripts: View FeatureScripts
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    @Evan_Reese

    Could you make it use booleanBodies instead of opBoolean, please, so that it can work with sheet metal parts?
    Yes at some point. It's been on my list to figure out sheet metal compatibility. Thanks for the nudge in the right direction. Is it as simple as just replacing that section of code with another equally short one or is there more to it?

    I still also need to implement your identity transform suggestion too
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • Evan_ReeseEvan_Reese Member Posts: 482 PRO
    Evan Reese / Principal and Industrial Designer with Fractal
    Website: fractalmade.com
    Instagram: @evan.reese.designs
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 1,881 PRO
    Yup
    MB - I make FeatureScripts: View FeatureScripts
Sign In or Register to comment.