Setting HatchPatternFillType not working for Gradient?

Hi,

I am trying to code some patterns and I am stuck at gradients. Somehow, I cannot set the FillType to “Gradient”, Solid and Lines work though (see https://developer.rhino3d.com/api/rhinocommon/rhino.docobjects.hatchpatternfilltype). Does anybody know why? :slight_smile:

Here is the code snippet:
import Rhino
grad_hatch = Rhino.DocObjects.HatchPattern()
grad_hatch.FillType = Rhino.DocObjects.HatchPatternFillType.Gradient
print(grad_hatch.FillType #->Solid (expected: Gradient)

Please run Rhino’s SystemInfo command and copy/paste the output text file here.

Rhino 8 SR8 2024-6-18 (Rhino 8, 8.8.24170.13001, Git hash:master @ c3cc7c123163b65d85b517aff795627d5b12166b)
License type: Educational, build 2024-06-18
License details: Cloud Zoo

Windows 11 (10.0.26100 SR0.0) or greater (Physical RAM: 64GB)
.NET 7.0.0

Computer platform: DESKTOP

Standard graphics configuration.
Primary display and OpenGL: NVIDIA GeForce RTX 4090 (NVidia) Memory: 24GB, Driver date: 8-14-2024 (M-D-Y). OpenGL Ver: 4.6.0 NVIDIA 560.94
> Accelerated graphics device with 4 adapter port(s)
- Windows Main Display attached to adapter port #0
- Secondary monitor attached to adapter port #1

Secondary graphics devices.
Intel(R) UHD Graphics 770 (Intel) Memory: 2GB, Driver date: 8-19-2024 (M-D-Y).
> Integrated graphics device with 4 adapter port(s)
- There are no monitors attached to this device!

OpenGL Settings
Safe mode: Off
Use accelerated hardware modes: On
Redraw scene when viewports are exposed: On
Graphics level being used: OpenGL 4.6 (primary GPU’s maximum)

Anti-alias mode: 4x
Mip Map Filtering: Linear
Anisotropic Filtering Mode: High

Vendor Name: NVIDIA Corporation
Render version: 4.6
Shading Language: 4.60 NVIDIA
Driver Date: 8-14-2024
Driver Version: 32.0.15.6094
Maximum Texture size: 32768 x 32768
Z-Buffer depth: 24 bits
Maximum Viewport size: 32768 x 32768
Total Video Memory: 24564 MB

Rhino plugins that do not ship with Rhino
C:\Users\Windows\AppData\Roaming\McNeel\Rhinoceros\8.0\Plug-ins\SpeckleRhino2 (8dd5f30b-a13d-4a24-abdc-3e05c8c87143)\SpeckleConnectorRhino.rhp “SpeckleConnectorRhino” 2.19.1.15397
C:\Users\Windows\AppData\Roaming\McNeel\Rhinoceros\packages\7.0\NVIDIADenoiser\0.4.3\NVIDIADenoiser.Windows.rhp “NVIDIADenoiser.Windows” 0.4.3.0

Rhino plugins that ship with Rhino
C:\Program Files\Rhino 8\Plug-ins\Commands.rhp “Commands” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\WebBrowser.rhp “WebBrowser”
C:\Program Files\Rhino 8\Plug-ins\rdk.rhp “Renderer Development Kit”
C:\Program Files\Rhino 8\Plug-ins\RhinoRenderCycles.rhp “Rhino Render” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\rdk_etoui.rhp “RDK_EtoUI” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\NamedSnapshots.rhp “Snapshots”
C:\Program Files\Rhino 8\Plug-ins\MeshCommands.rhp “MeshCommands” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\IronPython\RhinoDLR_Python.rhp “IronPython” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\RhinoCycles.rhp “RhinoCycles” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\Grasshopper\GrasshopperPlugin.rhp “Grasshopper” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\RhinoCode\RhinoCodePlugin.rhp “RhinoCodePlugin” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\Toolbars\Toolbars.rhp “Toolbars” 8.8.24170.13001
C:\Program Files\Rhino 8\Plug-ins\3dxrhino.rhp “3Dconnexion 3D Mouse”
C:\Program Files\Rhino 8\Plug-ins\Displacement.rhp “Displacement”
C:\Program Files\Rhino 8\Plug-ins\SectionTools.rhp “SectionTools”
C:\Program Files\Rhino 8\Plug-ins\export_PDF.rhp “PDF Export” 8.8.24170.13001

To enable a gradient hatch you’ll need to use the SetGradientFill method available on the HatchGeometry. There may be more that we need to expose for RhinoCommon to be able to successfully do this.

https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.hatch/setgradientfill

Thanks your your answer. I know about this function, and at least I was able to create the color gradient and assign it to the hatch. Yet, I did not find the function to set the “Fill Style” to “Linear Reflected” as done manaully in the Colors section of the hatch properties. I still have some unexpected behaviour, as the hatch does not follow the color stop definitions entirely and I don’t know how to contoll the positions of the color stops within the acual hatch by code.

If you have any leads on something, that would be super cool :slight_smile:

Everything is configured through the ColorGradient object not the hatch geometry.

https://developer.rhino3d.com/api/rhinocommon/rhino.display.colorgradient

ColorGradient has a GradientType enum. This is what you need to set the fill style.
https://developer.rhino3d.com/api/rhinocommon/rhino.display.gradienttype

To set colors and their location you’ll use an array of ColorStop Objects set on the ColorGradient where the t parameter value is a 0 - 1 location 0.5 being half way. Make sure you also define a Start and Stop

https://developer.rhino3d.com/api/rhinocommon/rhino.display.colorstop

You can get and set color stop collections using member functions of the ColorGradient. GetColorStops and SetColorStops

https://developer.rhino3d.com/api/rhinocommon/rhino.display.colorgradient/setcolorstops#(ienumerable<colorstop>)

1 Like

Hi @Trav, thanks for the support. I got it running. I will post my code here, just in case anybody wants to have some matplotlib-styles colorbars in his Rhino document.

Yet, it works only up to 8 colorstops (which is sufficient for me), than it behaves buggy.

import matplotlib.pyplot as plt
import numpy as np
import Rhino
import ghpythonlib.treehelpers as th
from System.Drawing import Color
from matplotlib.colors import LinearSegmentedColormap

"""
Create a colorbar in Rhino matching a definition in Matplotlib


Inputs of the Grasshopper-Node (all set to Item access and no TypeHint)
crv (Rhino.Geometry.Curve)
    A closed curve used as the outline for the colorbar
cmap_name (str)
    Name of the cmap in matplotlib
number_of_segments (int)
    How many points are sampled. Note: WORKS ONLY PROPERLY UP TO 8
trigger_and_bake (bool)
    Run and bake to Rhino
"""
ghenv.Component.Message = "ColorbarMatplotlibStyle"


def analyze_crv(crv):
    """
    Simplified analysis of the curve to determine start and endpoints for the gradient.
    Expand this function, if you need a gradient that is not on Rhino.Geometry.Plane.WorldXY
    or a direction that is not Rhino.Geometry.Vector3d(0,1,0)
    """
    if not crv.IsClosed:
        raise ValueError("Expected a closed curve ")
    bbox = crv.GetBoundingBox(True)
    sp = bbox.Min
    ep = Rhino.Geometry.Point3d(sp.X, bbox.Max.Y, bbox.Max.Z)
    print(type(crv))
    return crv, sp, ep



def sample_colors(cmap_name, number_of_segments):
    colors = []
    
    # Add custom colormap or get the one specified
    if cmap_name in ["Plaxis", "RedGreen", "GreeenRed"]:
        cmap = LinearSegmentedColormap.from_list("GreenToRed", [(0,1,0), (1,0,0)])
    else:
        cmap = plt.get_cmap(cmap_name)

    segments = np.arange(number_of_segments)
    segments = [float(i/(len(segments)-1)) for i in segments]

    for value in segments:
        rgb = cmap(value)
        rgb = [rgb[0], rgb[1], rgb[2]]
        rgb = [float(i*255) for i in rgb]
        color = Color.FromArgb(*rgb)
        colors.append(color)

    return colors, segments


def create_color_gradient(colors, segments, sp = Rhino.Geometry.Point3d(0,0,0), ep = Rhino.Geometry.Point3d(0,100,0)):
    color_gradient = Rhino.Display.ColorGradient()
    color_gradient.GradientType = Rhino.Display.GradientType.Linear
    color_gradient.StartPoint = sp
    color_gradient.EndPoint = ep
    cstops = []
    
    for ind, c in enumerate(colors):
        stop = segments[ind]
        cstop = Rhino.Display.ColorStop(c, stop)
        cstops.append(cstop)

    color_gradient.SetColorStops(cstops) 

    return color_gradient

def add_hatch(crv, gradient):
    if "Solid" in [i.Name for i in Rhino.RhinoDoc.ActiveDoc.HatchPatterns]:
        hatch_pattern_ind = [i.Name for i in Rhino.RhinoDoc.ActiveDoc.HatchPatterns].index("Solid")
    else:
        hatch_pattern_ind = Rhino.RhinoDoc.ActiveDoc.HatchPatterns.Add(Rhino.DocObjects.HatchPattern.Defaults.Solid)
    
    hatch = Rhino.Geometry.Hatch.Create([crv], hatch_pattern_ind, 0., 1)[0]
    
    # Create and set attributes 
    attr = Rhino.DocObjects.ObjectAttributes()
    attr.Name = "Hatch_with_gradient"

    if gradient:
        hatch.SetGradientFill(gradient)

    # Bake to document
    hatch_id = Rhino.RhinoDoc.ActiveDoc.Objects.AddHatch(hatch, attr)

    return hatch, hatch_id


if trigger_and_bake == True:
    crv, sp, ep = analyze_crv(crv)
    colors, segments = sample_colors(cmap_name, number_of_segments)
    color_gradient = create_color_gradient(colors, segments, sp, ep)
    hatch, hatch_id = add_hatch(crv, color_gradient)
    hatch.SetGradientFill(color_gradient)
    Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw()