From 2aa955ccff1d0974964962d53396782606137ecb Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Mon, 21 Sep 2020 02:04:42 +0500 Subject: [PATCH 1/2] Move "Solid from two Faces" back to Solids. --- index.md | 2 +- nodes/solid/ruled_solid.py | 24 +++++------------------- utils/curve/bezier.py | 12 ++++++++++++ utils/curve/splines.py | 6 ++++++ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/index.md b/index.md index 8632dfccb..df38719b9 100644 --- a/index.md +++ b/index.md @@ -230,6 +230,7 @@ SvMirrorSolidNode SvOffsetSolidNode SvSolidFromFacesNode + SvRuledSolidNode SvSolidFaceExtrudeNode SvSolidFaceSolidifyNode SvSolidFaceRevolveNode @@ -674,7 +675,6 @@ SvPulgaPhysicsNode SvTopologySimple SvSweepModulator - SvRuledSolidNode --- SvGetPropNodeMK2 SvSetPropNodeMK2 diff --git a/nodes/solid/ruled_solid.py b/nodes/solid/ruled_solid.py index 11443a8a3..083eefc91 100644 --- a/nodes/solid/ruled_solid.py +++ b/nodes/solid/ruled_solid.py @@ -101,21 +101,9 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): default = False, update = updateNode) - precision_min: FloatProperty( - name = "Min Precision", - default = 0.01, - precision=6, - update = updateNode) - - precision_max: FloatProperty( - name = "Max Precision", - default = 0.01, - precision=6, - update = updateNode) - - precision_work: FloatProperty( - name = "Working Precision", - default = 0.01, + precision: FloatProperty( + name = "Precision", + default = 0.001, precision=6, update = updateNode) @@ -139,9 +127,7 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): def draw_buttons_ext(self, context, layout): self.draw_buttons(context, layout) - layout.prop(self, 'precision_work') - layout.prop(self, 'precision_min') - layout.prop(self, 'precision_max') + layout.prop(self, 'precision') def make_solid(self, face1, face2): if self.flip_face1: @@ -174,7 +160,7 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): solid = Part.makeSolid(sh) if not solid.isValid(): self.debug("Resulting solid is not valid!") - if not solid.fix(self.precision_work, self.precision_min, self.precision_max): + if not solid.fix(self.precision, self.precision, self.precision): self.error("Solid is not valid, and is not possible to fix") return solid diff --git a/utils/curve/bezier.py b/utils/curve/bezier.py index aaa861c3d..7ce26cb3b 100644 --- a/utils/curve/bezier.py +++ b/utils/curve/bezier.py @@ -312,6 +312,12 @@ class SvBezierCurve(SvCurve): return SvBezierCurve(points) return self.to_nurbs().lerp_to(curve2, coefficient) + def split_at(self, t): + return self.to_nurbs().split_at(t) + + def cut_segment(self, new_t_min, new_t_max, rescale=False): + return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale) + def to_bezier(self): return self @@ -447,6 +453,12 @@ class SvCubicBezierCurve(SvCurve): return SvCubicBezierCurve(p1, p2, p3, p4) return self.to_nurbs().lerp_to(curve2, coefficient) + def split_at(self, t): + return self.to_nurbs().split_at(t) + + def cut_segment(self, new_t_min, new_t_max, rescale=False): + return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale) + def to_bezier(self): return self diff --git a/utils/curve/splines.py b/utils/curve/splines.py index 699e73d79..39364c67a 100644 --- a/utils/curve/splines.py +++ b/utils/curve/splines.py @@ -85,3 +85,9 @@ class SvSplineCurve(SvCurve): def lerp_to(self, curve2, coefficient): return self.to_nurbs().lerp_to(curve2, coefficient) + def split_at(self, t): + return self.to_nurbs().split_at(t) + + def cut_segment(self, new_t_min, new_t_max, rescale=False): + return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale) + -- GitLab From 17f10fae091654610ac09e094c6799e0ad291112 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Mon, 21 Sep 2020 19:54:07 +0500 Subject: [PATCH 2/2] Docuemntation for "Solid from two Faces" --- docs/nodes/solid/ruled_solid.rst | 94 +++++++++++++++++++++++++++ docs/nodes/solid/solid_from_faces.rst | 12 +++- docs/nodes/solid/solid_index.rst | 1 + nodes/solid/ruled_solid.py | 19 +++++- tests/docs_tests.py | 1 - 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 docs/nodes/solid/ruled_solid.rst diff --git a/docs/nodes/solid/ruled_solid.rst b/docs/nodes/solid/ruled_solid.rst new file mode 100644 index 000000000..b699110a3 --- /dev/null +++ b/docs/nodes/solid/ruled_solid.rst @@ -0,0 +1,94 @@ +Solid from two Faces +================ + +Dependencies +------------ + +This node requires FreeCAD_ library to work. + +.. _FreeCAD: ../../solids.rst + +Functionality +------------- + +This node generates a Solid object from two Faces ("floor" and "ceiling") by +adding linear surfaces to connect their edges ("walls"). + +**NOTE**: the node requires that two Face objects provided have exactly the +same number of edges. Hint: if you are generating Faces from Curves, you can +use "Split Curve" node to increase the number of edges. + +Depending on the way how you generate "floor" and "ceiling" surfaces, it can +appear that the order or the direction of their edges will be incorrect; in +such cases weird invalid bodies would be generated. To deal with such cases, +the node suggest options to reverse the order of edges, or direction of edges. + +By default, the node will check that the Solid object it constructed is "valid" +in terms of FreeCAD's OCCT kernel: all faces have coinciding edges, all normals +are pointing outside, and so on. If the node will find that the solid is not +valid, it will try to automatically fix it. If this automatic fix process +fails, the node will raise an exception (become red) and processing will stop. + +**NOTE**: some operations with Solid objects which are not "valid" are known to +cause crashes. So it is strongly recomended to have "Validate" parameter turned +on. + +Solid Face object can be created with nodes from "Make Face" submenu (such as +"Face from Curve"); also any NURBS or NURBS-like surface can be used as a Solid +Face. + +Inputs +------ + +This node has the following inputs: + +* **SolidFace1**. The first Solid Face object (to be used as "floor", for + example). This input is mandatory. +* **SolidFace2**. The second Solid Face object (to be used as "ceiling", for + example). This input is mandatory. + +Parameters +---------- + +This node has the following parameters: + +* **Flip Face 1**, **Flip Face 2**. If checked, the node will flip first or + second Face, correspondingly (invert it's normal direction). It can be + required to build a proper Solid object. Unchecked by default. +* **Rev. Edges 1**, **Rev. Edges 2**. If checked, the node will reverse the + order of edges of first or second Face, correspondingly. It can be requierd + to build a proper Solid object. Unchecked by default. +* **Flip Edges 1**, **Flip Edges 2**. If checked, the node will reverse the + direction of each edge of first or second Face, correspondingly. It can be + required to build a proper Solid object. Unchecked by default. +* **Validate**. This parameter is available in the N panel only. If checked, + the node will check that the Solid object it constructed is "valid" in terms + of FreeCAD's OCCT kernel: all faces have coinciding edges, all normals are + pointing outside, and so on. If the node will find that the solid is not + valid, it will try to automatically fix it. If this automatic fix process + fails, the node will raise an exception (become red) and processing will + stop. So if this parameter is checked, you can be sure that the generated + Solid object is "valid". If not checked, the node will not validate the + created object. In most cases, you have to check this parameter; it is + checked by default. **NOTE**: some operations with Solid objects which are + not "valid" are known to cause crashes. +* **Tolerance**. This parameter is available in the N panel, only if + **Validate** parameter is checked. Tolerance for automatic "fix" process. The + default value is 0.001. + +Outputs +------- + +This node has the following output: + +* **Solid**. The generated Solid object. + +Example of usage +---------------- + +Generate two cubic splines from randomized polygons; subdivide each spline into +four parts, to build a Coons surface from each of them; then connect these two +surfaces into one Solid: + +.. image:: https://user-images.githubusercontent.com/284644/93722058-7ccdd680-fbad-11ea-8319-d7f3e8cf04ac.png + diff --git a/docs/nodes/solid/solid_from_faces.rst b/docs/nodes/solid/solid_from_faces.rst index 75fdab467..7e9c651e0 100644 --- a/docs/nodes/solid/solid_from_faces.rst +++ b/docs/nodes/solid/solid_from_faces.rst @@ -17,6 +17,16 @@ Solid object, the faces must already have their edges and vertices exactly coinciding. Usually the only way to guarantee that is to construct all these Faces from the same set of Edges. +By default, the node will check that the Solid object it constructed is "valid" +in terms of FreeCAD's OCCT kernel: all faces have coinciding edges, all normals +are pointing outside, and so on. If the node will find that the solid is not +valid, it will try to automatically fix it. If this automatic fix process +fails, the node will raise an exception (become red) and processing will stop. + +**NOTE**: some operations with Solid objects which are not "valid" are known to +cause crashes. So it is strongly recomended to have "Validate" parameter turned +on. + Solid Face object can be created with nodes from "Make Face" submenu (such as "Face from Curve"); also any NURBS or NURBS-like surface can be used as a Solid Face. @@ -65,7 +75,7 @@ This node has the following output: * **Solid**. The generated Solid object. Example of usage -================ +---------------- Make a side surface by lofting between three cubic splines; make top and bottom faces with "Frame from Curve" node from the first and the last spline; then diff --git a/docs/nodes/solid/solid_index.rst b/docs/nodes/solid/solid_index.rst index 9a910675c..c6697f720 100644 --- a/docs/nodes/solid/solid_index.rst +++ b/docs/nodes/solid/solid_index.rst @@ -20,6 +20,7 @@ Solid mirror_solid offset_solid solid_from_faces + ruled_solid extrude_face solidify_face revolve_face diff --git a/nodes/solid/ruled_solid.py b/nodes/solid/ruled_solid.py index 083eefc91..a3568cb0c 100644 --- a/nodes/solid/ruled_solid.py +++ b/nodes/solid/ruled_solid.py @@ -101,8 +101,15 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): default = False, update = updateNode) + validate : BoolProperty( + name = "Validate", + description = "Make sure that the constructed body is valid in terms of OCC core", + default = True, + update = updateNode) + + precision: FloatProperty( - name = "Precision", + name = "Tolerance", default = 0.001, precision=6, update = updateNode) @@ -127,7 +134,9 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): def draw_buttons_ext(self, context, layout): self.draw_buttons(context, layout) - layout.prop(self, 'precision') + layout.prop(self, 'validate') + if self.validate: + layout.prop(self, 'precision') def make_solid(self, face1, face2): if self.flip_face1: @@ -161,7 +170,11 @@ class SvRuledSolidNode(bpy.types.Node, SverchCustomTreeNode): if not solid.isValid(): self.debug("Resulting solid is not valid!") if not solid.fix(self.precision, self.precision, self.precision): - self.error("Solid is not valid, and is not possible to fix") + message = "Solid is not valid, and is not possible to fix" + if self.validate: + raise Exception(message) + else: + self.error(message) return solid def process(self): diff --git a/tests/docs_tests.py b/tests/docs_tests.py index 6c2489c20..b9a903810 100644 --- a/tests/docs_tests.py +++ b/tests/docs_tests.py @@ -155,7 +155,6 @@ vd_attr_node.py scalar_field_point.py bvh_nearest_new.py quads_to_nurbs.py -ruled_solid.py location.py sun_position.py""".split("\n") -- GitLab