From 66c410621848b805096d5e8ca282f5155fa1a4bb Mon Sep 17 00:00:00 2001 From: mutablehurdle Date: Thu, 27 Jan 2022 08:08:50 -0800 Subject: [PATCH 1/5] Extra SDF primitives for some minimal surfaces and MetaCORE surfaces --- __init__.py | 8 +- nodes/sdf_primitives/sdf_EB.py | 108 +++++++++++++++++++++++++ nodes/sdf_primitives/sdf_MO.py | 117 +++++++++++++++++++++++++++ nodes/sdf_primitives/sdf_gyroid.py | 117 +++++++++++++++++++++++++++ nodes/sdf_primitives/sdf_schwarzD.py | 108 +++++++++++++++++++++++++ nodes/sdf_primitives/sdf_schwarzP.py | 108 +++++++++++++++++++++++++ 6 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 nodes/sdf_primitives/sdf_EB.py create mode 100644 nodes/sdf_primitives/sdf_MO.py create mode 100644 nodes/sdf_primitives/sdf_gyroid.py create mode 100644 nodes/sdf_primitives/sdf_schwarzD.py create mode 100644 nodes/sdf_primitives/sdf_schwarzP.py diff --git a/__init__.py b/__init__.py index 1189e57..f52f9a3 100644 --- a/__init__.py +++ b/__init__.py @@ -47,8 +47,7 @@ def nodes_index(): ("curve.intersect_surface_plane", "SvExCrossSurfacePlaneNode"), ("curve.fourier_curve", "SvFourierCurveNode"), ("curve.approximate_fourier_curve", "SvApproxFourierCurveNode"), - ("curve.interpolate_fourier_curve", "SvInterpFourierCurveNode"), - ("curve.geodesic_curve", "SvExGeodesicCurveNode") + ("curve.interpolate_fourier_curve", "SvInterpFourierCurveNode") ]), ("Extra Fields", [ ("field.vfield_lines_on_surface", "SvExVFieldLinesOnSurfNode"), @@ -75,6 +74,11 @@ def nodes_index(): ("sdf_primitives.sdf_cylinder", "SvExSdfCylinderNode"), ("sdf_primitives.sdf_rounded_cylinder", "SvExSdfRoundedCylinderNode"), ("sdf_primitives.sdf_capsule", "SvExSdfCapsuleNode"), + ("sdf_primitives.sdf_gyroid", "SvExSdfGyroidNode"), + ("sdf_primitives.sdf_schwarzP", "SvExSdfSchwarzPNode"), + ("sdf_primitives.sdf_schwarzD", "SvExSdfSchwarzDNode"), + ("sdf_primitives.sdf_MO", "SvExSdfMONode"), + ("sdf_primitives.sdf_EB", "SvExSdfEBNode"), None, ("sdf_primitives.sdf2d_circle", "SvExSdf2dCircleNode"), ("sdf_primitives.sdf2d_hexagon", "SvExSdf2dHexagonNode"), diff --git a/nodes/sdf_primitives/sdf_EB.py b/nodes/sdf_primitives/sdf_EB.py new file mode 100644 index 0000000..5b6b48d --- /dev/null +++ b/nodes/sdf_primitives/sdf_EB.py @@ -0,0 +1,108 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfEBNode', "SDF EB", 'sdf') +else: + from sdf import * + +class SvExSdfEBNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF EB + Tooltip: SDF EB + """ + bl_idname = 'SvExSdfEBNode' + bl_label = 'SDF EB' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness : FloatProperty( + name = "Thickness", + default = 0.1, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness").prop_name = 'thickness' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, origin in zip_long_repeat(*params): + sdf = EB(thickness, size=(size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfEBNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfEBNode) diff --git a/nodes/sdf_primitives/sdf_MO.py b/nodes/sdf_primitives/sdf_MO.py new file mode 100644 index 0000000..2dddd00 --- /dev/null +++ b/nodes/sdf_primitives/sdf_MO.py @@ -0,0 +1,117 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfMONode', "SDF MO", 'sdf') +else: + from sdf import * + +class SvExSdfMONode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF MO + Tooltip: SDF MO + """ + bl_idname = 'SvExSdfMONode' + bl_label = 'SDF MO' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness : FloatProperty( + name = "Thickness", + default = 0.1, + min = 0.0, + update=updateNode) + + slant : FloatProperty( + name = "Slant", + default = 1.0, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness").prop_name = 'thickness' + self.inputs.new('SvStringsSocket', "Slant").prop_name = 'slant' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + slant_s = self.inputs['Slant'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2) + slant_s = ensure_nesting_level(slant_s, 2) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, slant_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, slant, origin in zip_long_repeat(*params): + sdf = MO(thickness, slant, size=(size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfMONode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfMONode) diff --git a/nodes/sdf_primitives/sdf_gyroid.py b/nodes/sdf_primitives/sdf_gyroid.py new file mode 100644 index 0000000..d6efe16 --- /dev/null +++ b/nodes/sdf_primitives/sdf_gyroid.py @@ -0,0 +1,117 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfGyroidNode', "SDF Gyroid", 'sdf') +else: + from sdf import * + +class SvExSdfGyroidNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF Gyroid + Tooltip: SDF Gyroid + """ + bl_idname = 'SvExSdfGyroidNode' + bl_label = 'SDF Gyroid' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness : FloatProperty( + name = "Thickness", + default = 0.1, + min = 0.0, + update=updateNode) + + value : FloatProperty( + name = "Value", + default = 0.0, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness").prop_name = 'thickness' + self.inputs.new('SvStringsSocket', "Value").prop_name = 'value' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + value_s = self.inputs['Value'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2) + value_s = ensure_nesting_level(value_s, 2) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, value_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, value, origin in zip_long_repeat(*params): + sdf = gyroid(thickness, value, size=(size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfGyroidNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfGyroidNode) diff --git a/nodes/sdf_primitives/sdf_schwarzD.py b/nodes/sdf_primitives/sdf_schwarzD.py new file mode 100644 index 0000000..46cf2c7 --- /dev/null +++ b/nodes/sdf_primitives/sdf_schwarzD.py @@ -0,0 +1,108 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfSchwarzDNode', "SDF Schwarz D", 'sdf') +else: + from sdf import * + +class SvExSdfSchwarzDNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF Schwarz D + Tooltip: SDF Schwarz D + """ + bl_idname = 'SvExSdfSchwarzDNode' + bl_label = 'SDF Schwarz D' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness : FloatProperty( + name = "Thickness", + default = 0.1, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness").prop_name = 'thickness' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, origin in zip_long_repeat(*params): + sdf = schwarzD(thickness, size=(size_x,size_y,size_z),center = origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfSchwarzDNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfSchwarzDNode) diff --git a/nodes/sdf_primitives/sdf_schwarzP.py b/nodes/sdf_primitives/sdf_schwarzP.py new file mode 100644 index 0000000..0496e8c --- /dev/null +++ b/nodes/sdf_primitives/sdf_schwarzP.py @@ -0,0 +1,108 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfSchwarzPNode', "SDF Schwarz P", 'sdf') +else: + from sdf import * + +class SvExSdfSchwarzPNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF Schwarz P + Tooltip: SDF Schwarz P + """ + bl_idname = 'SvExSdfSchwarzPNode' + bl_label = 'SDF Schwarz P' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness : FloatProperty( + name = "Thickness", + default = 0.1, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness").prop_name = 'thickness' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, origin in zip_long_repeat(*params): + sdf = schwarzP(thickness, size = (size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfSchwarzPNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfSchwarzPNode) From 900bc2da7908317f0c0f77e2288ef283922edfac Mon Sep 17 00:00:00 2001 From: mutablehurdle <80230725+mutablehurdle@users.noreply.github.com> Date: Sun, 6 Feb 2022 09:55:03 -0800 Subject: [PATCH 2/5] linear graded gyroid --- .DS_Store | Bin 0 -> 6148 bytes __init__.py | 1 + nodes/.DS_Store | Bin 0 -> 6148 bytes nodes/sdf_primitives/sdf_graded_gyroid.py | 139 ++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 .DS_Store create mode 100644 nodes/.DS_Store create mode 100644 nodes/sdf_primitives/sdf_graded_gyroid.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5d2fd34527e557a6ab9b9754a2a9061347b9245e GIT binary patch literal 6148 zcmeHK!Ab)$5S?hN>5ABcpvPRi_0U=oJqSzHgEwJC4=U|$x7dYsQ@UG=*2?~d{*hnc z?>Li0tyXU$QZg`klgUiB^B_qF09a!X)&R-?z)=Yc4i4W4t&>j4obeP9nc5=_hG{Q| zWiS&l^*`Pm?C z`2BO59s5}~F!qU*@w@E@r%`9vEU)g%B=e)B(^tt+*ujvCvnUDWuptLYn5um|y})^i zmzw4E(P+E2QxWz0?zkdGyPMUD*s5=j$0feDQQJFeUEkh~?#B<0npK8ZkdhUHZ}5c1 zM2TVAjsyIW6h7g;@%l+DlPmPniu1t<2xuceJ-D5?-DZlNZ;Smx2y$X&wiqx6hA+)l zS+*L>fMwtp7@+$>pc1+UbB*fiz(KVDhy`>jL7RFB$`J-#gSkdrL18)-QKvG~VlbVK zeqrKVgSkeX4$L$k%zT-d4uz?&|D0rJmI2Ga zOfkR;2i`#gOEPckRB`my3e*-V3B~0aRSFK~IaUTe#p|d_a7~bb=o-v5q6fwP5l}SP K!7}it47>uq@tuYM literal 0 HcmV?d00001 diff --git a/__init__.py b/__init__.py index f52f9a3..e200ce8 100644 --- a/__init__.py +++ b/__init__.py @@ -75,6 +75,7 @@ def nodes_index(): ("sdf_primitives.sdf_rounded_cylinder", "SvExSdfRoundedCylinderNode"), ("sdf_primitives.sdf_capsule", "SvExSdfCapsuleNode"), ("sdf_primitives.sdf_gyroid", "SvExSdfGyroidNode"), + ("sdf_primitives.sdf_graded_gyroid", "SvExSdfGradedGyroidNode"), ("sdf_primitives.sdf_schwarzP", "SvExSdfSchwarzPNode"), ("sdf_primitives.sdf_schwarzD", "SvExSdfSchwarzDNode"), ("sdf_primitives.sdf_MO", "SvExSdfMONode"), diff --git a/nodes/.DS_Store b/nodes/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5d7c352d38496e671c390d73dede8376205042ca GIT binary patch literal 6148 zcmeHK%}T>S5T317w-vPqL63X!) zGrL<+svfn-49tF$*_r+M5_U5HAez0P4p0FAiAq=~Ve^GhKk1khtY->Q=rKCbg%EB~ zv$1G)Odv@24Foa@jFqNX0_U@C`=WnXJ(}=%kq5r z%)L(fZsujZwCQzE=;^@Au6=7CCQ0;ed;U?_?zbvSJ4u{*VchQOIyK$7nR~R>%Y%~cYGr$Zm1Cz^uJ+b86wg`@4Ku(D{7(i% zao62#;@<4tI<`x?YZdA_Dhb8q2H#WA&{r|W(p9{Iss;Uu3`ECbZV){v{3D=g;D#Ca HRR-Pw-gjX7 literal 0 HcmV?d00001 diff --git a/nodes/sdf_primitives/sdf_graded_gyroid.py b/nodes/sdf_primitives/sdf_graded_gyroid.py new file mode 100644 index 0000000..398a44c --- /dev/null +++ b/nodes/sdf_primitives/sdf_graded_gyroid.py @@ -0,0 +1,139 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfGradedGyroidNode', "SDF GradedGyroid", 'sdf') +else: + from sdf import * + +class SvExSdfGradedGyroidNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF Graded Gyroid + Tooltip: SDF Graded Gyroid + """ + bl_idname = 'SvExSdfGradedGyroidNode' + bl_label = 'SDF Graded Gyroid' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + thickness_min : FloatProperty( + name = "Thickness minimum", + default = 0.1, + min = 0.0, + update=updateNode) + + thickness_max : FloatProperty( + name = "Thickness maximum", + default = 0.1, + min = 0.0, + update=updateNode) + + value_min : FloatProperty( + name = "Value minimum", + default = 0.0, + min = 0.0, + update=updateNode) + + value_max : FloatProperty( + name = "Value maximum", + default = 0.0, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvStringsSocket', "Thickness minimum").prop_name = 'thickness_min' + self.inputs.new('SvStringsSocket', "Thickness maximum").prop_name = 'thickness_max' + + self.inputs.new('SvStringsSocket', "Value minimum").prop_name = 'value_min' + self.inputs.new('SvStringsSocket', "Value maximum").prop_name = 'value_max' + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_min_s = self.inputs['Thickness minimum'].sv_get() + thickness_max_s = self.inputs['Thickness maximum'].sv_get() + + value_min_s = self.inputs['Value minimum'].sv_get() + value_max_s = self.inputs['Value maximum'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_min_s = ensure_nesting_level(thickness_min_s, 2) + thickness_max_s = ensure_nesting_level(thickness_max_s, 2) + + value_min_s = ensure_nesting_level(value_min_s, 2) + value_max_s = ensure_nesting_level(value_max_s, 2) + + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_min_s, thickness_max_s, value_min_s, value_max_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness_min,thickness_max, value_min, value_max origin in zip_long_repeat(*params): + sdf = graded_gyroid(thickness_min, thickness_max, value_min, value_max, size=(size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfGyroidNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfGyroidNode) From 898a8df9be4af9aeb371cd75116d70d94ac67a37 Mon Sep 17 00:00:00 2001 From: mutablehurdle Date: Thu, 3 Mar 2022 13:49:28 -0800 Subject: [PATCH 3/5] fixed typo in linear_graded_gyroid --- .DS_Store | Bin 6148 -> 6148 bytes nodes/sdf_primitives/sdf_graded_gyroid.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.DS_Store b/.DS_Store index 5d2fd34527e557a6ab9b9754a2a9061347b9245e..6a1c326784b5e077bb21a8a3c2016e7780dd3bf0 100644 GIT binary patch delta 94 zcmZoMXfc=|#>B)qu~2NHo+2aj#(>?7jLegHSbj<~00ApQ9z#Au3PUPGaanLtUQT{q sI#85xvml2U%fyC@o7p+|Ie@x>{O`<@`9&N#K$;jC7+5w(h^%1-05GH#P5=M^ delta 157 zcmZoMXfc=|#>B!ku~2NHo+2ab#(>?7iw&5W7+ELtF#R-UWME)mWyoX5XGmd4WhgES zF3QWv&r1i2f@HW5G7Jg~$v{;F43(3mm~JRyl|k0MS&{h~<7Rdaeh#4JK+bpO$^0UY R96(c Date: Thu, 3 Mar 2022 13:54:08 -0800 Subject: [PATCH 4/5] functionally graded gyroid --- __init__.py | 1 + nodes/sdf/sdf_transition_linear.py | 1 - .../sdf_functionally_graded_gyroid.py | 107 ++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 nodes/sdf_primitives/sdf_functionally_graded_gyroid.py diff --git a/__init__.py b/__init__.py index e200ce8..0cacd52 100644 --- a/__init__.py +++ b/__init__.py @@ -76,6 +76,7 @@ def nodes_index(): ("sdf_primitives.sdf_capsule", "SvExSdfCapsuleNode"), ("sdf_primitives.sdf_gyroid", "SvExSdfGyroidNode"), ("sdf_primitives.sdf_graded_gyroid", "SvExSdfGradedGyroidNode"), + ("sdf_primitives.sdf_functionally_graded_gyroid", "SvExSdfFunctionallyGradedGyroidNode"), ("sdf_primitives.sdf_schwarzP", "SvExSdfSchwarzPNode"), ("sdf_primitives.sdf_schwarzD", "SvExSdfSchwarzDNode"), ("sdf_primitives.sdf_MO", "SvExSdfMONode"), diff --git a/nodes/sdf/sdf_transition_linear.py b/nodes/sdf/sdf_transition_linear.py index 5a9ce31..f4de3b9 100644 --- a/nodes/sdf/sdf_transition_linear.py +++ b/nodes/sdf/sdf_transition_linear.py @@ -94,4 +94,3 @@ def register(): def unregister(): if sdf is not None: bpy.utils.unregister_class(SvExSdfLinearTransitionNode) - diff --git a/nodes/sdf_primitives/sdf_functionally_graded_gyroid.py b/nodes/sdf_primitives/sdf_functionally_graded_gyroid.py new file mode 100644 index 0000000..1ee5fd4 --- /dev/null +++ b/nodes/sdf_primitives/sdf_functionally_graded_gyroid.py @@ -0,0 +1,107 @@ +import numpy as np + +import bpy +from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty, FloatVectorProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level +from sverchok.utils.dummy_nodes import add_dummy +from sverchok_extra.dependencies import sdf +from sverchok_extra.utils.sdf import * + +if sdf is None: + add_dummy('SvExSdfFunctionallyGradedGyroidNode', "SDF Functionally Graded Gyroid", 'sdf') +else: + from sdf import * + +class SvExSdfFunctionallyGradedGyroidNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: SDF Functionally Graded Gyroid + Tooltip: SDF Functionally Graded Gyroid + """ + bl_idname = 'SvExSdfFunctionallyGradedGyroidNode' + bl_label = 'SDF Functionally Graded Gyroid' + bl_icon = 'MESH_CAPSULE' + + size_x : FloatProperty( + name = "X Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_y : FloatProperty( + name = "Y Size", + default = 1.0, + min = 0.0, + update=updateNode) + + size_z : FloatProperty( + name = "Z Size", + default = 1.0, + min = 0.0, + update=updateNode) + + origin: FloatVectorProperty( + name="Origin", + default=(0, 0, 0), + size=3, + update=updateNode) + + flat_output : BoolProperty( + name = "Flat output", + default = True, + update=updateNode) + + def draw_buttons(self, context, layout): + layout.prop(self, 'flat_output') + + def sv_init(self, context): + self.inputs.new('SvStringsSocket', "XSize").prop_name = 'size_x' + self.inputs.new('SvStringsSocket', "YSize").prop_name = 'size_y' + self.inputs.new('SvStringsSocket', "ZSize").prop_name = 'size_z' + self.inputs.new('SvScalarFieldSocket', "Thickness") + self.inputs.new('SvScalarFieldSocket', "Value") + self.inputs.new('SvVerticesSocket', "Origin").prop_name = 'origin' + self.outputs.new('SvScalarFieldSocket', "SDF") + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + size_x_s = self.inputs['XSize'].sv_get() + size_y_s = self.inputs['YSize'].sv_get() + size_z_s = self.inputs['ZSize'].sv_get() + thickness_s = self.inputs['Thickness'].sv_get() + value_s = self.inputs['Value'].sv_get() + origins_s = self.inputs['Origin'].sv_get() + + size_x_s = ensure_nesting_level(size_x_s, 2) + size_y_s = ensure_nesting_level(size_y_s, 2) + size_z_s = ensure_nesting_level(size_z_s, 2) + thickness_s = ensure_nesting_level(thickness_s, 2, data_types=(SvScalarField,)) + value_s = ensure_nesting_level(value_s, 2, data_types=(SvScalarField,)) + origins_s = ensure_nesting_level(origins_s, 3) + + fields_out = [] + for params in zip_long_repeat(size_x_s, size_y_s, size_z_s, thickness_s, value_s, origins_s): + new_fields = [] + for size_x, size_y, size_z, thickness, value, origin in zip_long_repeat(*params): + thickness = scalar_field_to_sdf(thickness, 0) + value = scalar_field_to_sdf(value, 0) + sdf = FG_gyroid(thickness, value, size=(size_x,size_y,size_z),center=origin).translate(origin) + field = SvExSdfScalarField(sdf) + new_fields.append(field) + if self.flat_output: + fields_out.extend(new_fields) + else: + fields_out.append(new_fields) + + self.outputs['SDF'].sv_set(fields_out) + +def register(): + if sdf is not None: + bpy.utils.register_class(SvExSdfFunctionallyGradedGyroidNode) + +def unregister(): + if sdf is not None: + bpy.utils.unregister_class(SvExSdfFunctionallyGradedGyroidNode) From cb19dc859c5a181b565583496b913c5de84491d0 Mon Sep 17 00:00:00 2001 From: mutablehurdle Date: Thu, 3 Mar 2022 13:54:56 -0800 Subject: [PATCH 5/5] Update sdf_graded_gyroid.py --- nodes/sdf_primitives/sdf_graded_gyroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodes/sdf_primitives/sdf_graded_gyroid.py b/nodes/sdf_primitives/sdf_graded_gyroid.py index 566cc90..9aa110c 100644 --- a/nodes/sdf_primitives/sdf_graded_gyroid.py +++ b/nodes/sdf_primitives/sdf_graded_gyroid.py @@ -56,13 +56,13 @@ class SvExSdfGradedGyroidNode(bpy.types.Node, SverchCustomTreeNode): value_min : FloatProperty( name = "Value minimum", default = 0.0, - min = 0.0, + min = -1.73, update=updateNode) value_max : FloatProperty( name = "Value maximum", default = 0.0, - min = 0.0, + min = -1.73, update=updateNode) origin: FloatVectorProperty(