Skip to content
Snippets Groups Projects
add_curve_simple.py 46.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
            # general options
            col = layout.column()
    
            col.prop(self, "Simple_Type")
    
    
            l = 0
            s = 0
    
            if self.Simple_Type == 'Line':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_endlocation")
    
                v = Vector(self.Simple_endlocation) - Vector(self.Simple_startlocation)
                l = v.length
    
            if self.Simple_Type == 'Distance':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_length")
                col.prop(self, "Simple_center")
    
                l = self.Simple_length
    
            if self.Simple_Type == 'Angle':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_length")
                col.prop(self, "Simple_angle")
    
    
                row = layout.row()
    
                row.prop(self, "Simple_degrees_or_radians", expand=True)
    
    
            if self.Simple_Type == 'Circle':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_radius")
    
    
                l = 2 * pi * abs(self.Simple_radius)
                s = pi * self.Simple_radius * self.Simple_radius
    
            if self.Simple_Type == 'Ellipse':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_a", text="Radius a")
                col.prop(self, "Simple_b", text="Radius b")
    
                l = pi * (3 * (self.Simple_a + self.Simple_b) -
                              sqrt((3 * self.Simple_a + self.Simple_b) *
                              (self.Simple_a + 3 * self.Simple_b)))
    
    
                s = pi * abs(self.Simple_b) * abs(self.Simple_a)
    
            if self.Simple_Type == 'Arc':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_radius")
    
                col = box.column(align=True)
                col.prop(self, "Simple_startangle")
                col.prop(self, "Simple_endangle")
    
                row = layout.row()
    
                row.prop(self, "Simple_degrees_or_radians", expand=True)
    
    
                l = abs(pi * self.Simple_radius * (self.Simple_endangle - self.Simple_startangle) / 180)
    
            if self.Simple_Type == 'Sector':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_radius")
    
                col = box.column(align=True)
                col.prop(self, "Simple_startangle")
                col.prop(self, "Simple_endangle")
    
                row = layout.row()
    
                row.prop(self, "Simple_degrees_or_radians", expand=True)
    
                l = abs(pi * self.Simple_radius *
                       (self.Simple_endangle - self.Simple_startangle) / 180) + self.Simple_radius * 2
    
                s = pi * self.Simple_radius * self.Simple_radius * \
                    abs(self.Simple_endangle - self.Simple_startangle) / 360
    
    
            if self.Simple_Type == 'Segment':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_a", text="Radius a")
                col.prop(self, "Simple_b", text="Radius b")
    
                col = box.column(align=True)
                col.prop(self, "Simple_startangle")
                col.prop(self, "Simple_endangle")
    
    
                row = layout.row()
    
                row.prop(self, "Simple_degrees_or_radians", expand=True)
    
    
                la = abs(pi * self.Simple_a * (self.Simple_endangle - self.Simple_startangle) / 180)
                lb = abs(pi * self.Simple_b * (self.Simple_endangle - self.Simple_startangle) / 180)
                l = abs(self.Simple_a - self.Simple_b) * 2 + la + lb
    
    
                sa = pi * self.Simple_a * self.Simple_a * \
                    abs(self.Simple_endangle - self.Simple_startangle) / 360
    
                sb = pi * self.Simple_b * self.Simple_b * \
                    abs(self.Simple_endangle - self.Simple_startangle) / 360
    
    
                s = abs(sa - sb)
    
            if self.Simple_Type == 'Rectangle':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_width")
                col.prop(self, "Simple_length")
                col.prop(self, "Simple_rounded")
    
                box.prop(self, "Simple_center")
    
                l = 2 * abs(self.Simple_width) + 2 * abs(self.Simple_length)
                s = abs(self.Simple_width) * abs(self.Simple_length)
    
            if self.Simple_Type == 'Rhomb':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_width")
                col.prop(self, "Simple_length")
                col.prop(self, "Simple_center")
    
    
                g = hypot(self.Simple_width / 2, self.Simple_length / 2)
                l = 4 * g
                s = self.Simple_width * self.Simple_length / 2
    
            if self.Simple_Type == 'Polygon':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_radius")
    
    
            if self.Simple_Type == 'Polygon_ab':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text="Polygon ab Options:")
                col.prop(self, "Simple_sides")
                col.prop(self, "Simple_a")
                col.prop(self, "Simple_b")
    
    
            if self.Simple_Type == 'Trapezoid':
                box = layout.box()
    
                col = box.column(align=True)
                col.label(text=self.Simple_Type + " Options:")
                col.prop(self, "Simple_a")
                col.prop(self, "Simple_b")
                col.prop(self, "Simple_h")
    
                box.prop(self, "Simple_center")
    
                g = hypot(self.Simple_h, (self.Simple_a - self.Simple_b) / 2)
                l = self.Simple_a + self.Simple_b + g * 2
                s = (abs(self.Simple_a) + abs(self.Simple_b)) / 2 * self.Simple_h
    
            row = layout.row()
    
            row.prop(self, "shape", expand=True)
    
            box = layout.box()
    
            box.label(text="Location:")
    
            box.prop(self, "Simple_startlocation")
    
            box = layout.box()
    
            box.label(text="Rotation:")
    
            box.prop(self, "Simple_rotation_euler")
    
            if l != 0 or s != 0:
                box = layout.box()
                box.label(text="Statistics:", icon="INFO")
    
            if l != 0:
                l_str = str(round(l, 4))
    
                box.label(text="Length: " + l_str)
    
            if s != 0:
                s_str = str(round(s, 4))
    
                box.label(text="Area: " + s_str)
    
    
        @classmethod
        def poll(cls, context):
    
            return context.scene is not None
    
    
        def execute(self, context):
            # main function
            self.align_matrix = align_matrix(context, self.Simple_startlocation)
            main(context, self, self.align_matrix)
    
            return {'FINISHED'}
    
    # ------------------------------------------------------------
    # Fillet
    
    
    class BezierPointsFillet(Operator):
    
        bl_idname = "curve.bezier_points_fillet"
    
        bl_label = "Bezier points Fillet"
        bl_description = "Bezier points Fillet"
    
        bl_options = {'REGISTER', 'UNDO', 'PRESET'}
    
        Fillet_radius : FloatProperty(
    
                name="Radius",
                default=0.25,
                unit='LENGTH',
                description="Radius"
                )
        Types = [('Round', "Round", "Round"),
                 ('Chamfer', "Chamfer", "Chamfer")]
    
        Fillet_Type : EnumProperty(
    
                name="Type",
                description="Fillet type",
                items=Types
                )
    
    
        def draw(self, context):
            layout = self.layout
    
            # general options
            col = layout.column()
    
            col.prop(self, "Fillet_radius")
            col.prop(self, "Fillet_Type", expand=True)
    
    
        @classmethod
        def poll(cls, context):
    
            return context.scene is not None
    
    
        def execute(self, context):
            # main function
            spline = bpy.context.object.data.splines.active
            selected = [p for p in spline.bezier_points if p.select_control_point]
    
            bpy.ops.curve.handle_type_set(type='VECTOR')
            n = 0
            ii = []
            for p in spline.bezier_points:
                if p.select_control_point:
                    ii.append(n)
                    n += 1
                else:
                    n += 1
    
            if n > 2:
                jn = 0
                for j in ii:
    
                    j += jn
    
                    selected_all = [p for p in spline.bezier_points]
    
                    bpy.ops.curve.select_all(action='DESELECT')
    
                    if j != 0 and j != n - 1:
                        selected_all[j].select_control_point = True
                        selected_all[j + 1].select_control_point = True
                        bpy.ops.curve.subdivide()
                        selected_all = [p for p in spline.bezier_points]
    
                        selected4 = [selected_all[j - 1], selected_all[j],
                                     selected_all[j + 1], selected_all[j + 2]]
    
                        jn += 1
                        n += 1
    
                    elif j == 0:
                        selected_all[j].select_control_point = True
                        selected_all[j + 1].select_control_point = True
                        bpy.ops.curve.subdivide()
                        selected_all = [p for p in spline.bezier_points]
    
                        selected4 = [selected_all[n], selected_all[0],
                                     selected_all[1], selected_all[2]]
    
                        jn += 1
                        n += 1
    
                    elif j == n - 1:
                        selected_all[j].select_control_point = True
                        selected_all[j - 1].select_control_point = True
                        bpy.ops.curve.subdivide()
                        selected_all = [p for p in spline.bezier_points]
    
                        selected4 = [selected_all[0], selected_all[n],
                                     selected_all[n - 1], selected_all[n - 2]]
    
    
                    selected4[2].co = selected4[1].co
                    s1 = Vector(selected4[0].co) - Vector(selected4[1].co)
                    s2 = Vector(selected4[3].co) - Vector(selected4[2].co)
                    s1.normalize()
                    s11 = Vector(selected4[1].co) + s1 * self.Fillet_radius
                    selected4[1].co = s11
                    s2.normalize()
                    s22 = Vector(selected4[2].co) + s2 * self.Fillet_radius
                    selected4[2].co = s22
    
                    if self.Fillet_Type == 'Round':
                        if j != n - 1:
                            selected4[2].handle_right_type = 'VECTOR'
                            selected4[1].handle_left_type = 'VECTOR'
                            selected4[1].handle_right_type = 'ALIGNED'
                            selected4[2].handle_left_type = 'ALIGNED'
                        else:
                            selected4[1].handle_right_type = 'VECTOR'
                            selected4[2].handle_left_type = 'VECTOR'
                            selected4[2].handle_right_type = 'ALIGNED'
                            selected4[1].handle_left_type = 'ALIGNED'
                    if self.Fillet_Type == 'Chamfer':
                        selected4[2].handle_right_type = 'VECTOR'
                        selected4[1].handle_left_type = 'VECTOR'
                        selected4[1].handle_right_type = 'VECTOR'
                        selected4[2].handle_left_type = 'VECTOR'
    
            bpy.ops.curve.select_all(action='SELECT')
            bpy.ops.curve.spline_type_set(type='BEZIER')
    
            return {'FINISHED'}
    
    def subdivide_cubic_bezier(p1, p2, p3, p4, t):
        p12 = (p2 - p1) * t + p1
        p23 = (p3 - p2) * t + p2
        p34 = (p4 - p3) * t + p3
        p123 = (p23 - p12) * t + p12
        p234 = (p34 - p23) * t + p23
        p1234 = (p234 - p123) * t + p123
        return [p12, p123, p1234, p234, p34]
    
    
    # ------------------------------------------------------------
    # BezierDivide Operator
    
    
    class BezierDivide(Operator):
    
        bl_idname = "curve.bezier_spline_divide"
    
        bl_label = "Bezier Spline Divide"
        bl_description = "Bezier Divide (enters edit mode) for Fillet Curves"
    
        bl_options = {'REGISTER', 'UNDO'}
    
        # align_matrix for the invoke
    
        align_matrix : Matrix()
    
        Bezier_t : FloatProperty(
    
                name="t (0% - 100%)",
                default=50.0,
                min=0.0, soft_min=0.0,
                max=100.0, soft_max=100.0,
                description="t (0% - 100%)"
                )
    
    
        @classmethod
        def poll(cls, context):
    
            return context.scene is not None
    
    
        def execute(self, context):
            # main function
            spline = bpy.context.object.data.splines.active
            selected_all = [p for p in spline.bezier_points if p.select_control_point]
    
            selected = []
            n = 0
            for j in spline.bezier_points:
                n += 1
                if j.select_control_point:
                    selected.append(n)
    
            selected_all[0].handle_right_type = 'FREE'
            selected_all[0].handle_left_type = 'FREE'
            selected_all[1].handle_right_type = 'FREE'
            selected_all[1].handle_left_type = 'FREE'
    
            if abs(selected[0] - selected[1]) == 1:
                h = subdivide_cubic_bezier(
                        selected_all[0].co, selected_all[0].handle_right,
                        selected_all[1].handle_left, selected_all[1].co, self.Bezier_t / 100
                        )
                bpy.ops.curve.subdivide(1)
                selected_all = [p for p in spline.bezier_points if p.select_control_point]
                selected_all[0].handle_right = h[0]
                selected_all[1].co = h[2]
                selected_all[1].handle_left = h[1]
                selected_all[1].handle_right = h[3]
                selected_all[2].handle_left = h[4]
            else:
                h = subdivide_cubic_bezier(
                        selected_all[1].co, selected_all[1].handle_right,
                        selected_all[0].handle_left, selected_all[0].co, self.Bezier_t / 100
                        )
                bpy.ops.curve.subdivide(1)
                selected_all = [p for p in spline.bezier_points if p.select_control_point]
                selected_all[1].handle_right = h[0]
                selected_all[2].co = h[2]
                selected_all[2].handle_left = h[1]
                selected_all[2].handle_right = h[3]
                selected_all[0].handle_left = h[4]
    
    classes = [
        Simple,
        BezierDivide,
        BezierPointsFillet
    ]
    
        from bpy.utils import register_class
        for cls in classes:
            register_class(cls)
    
        bpy.types.VIEW3D_MT_curve_add.append(menu)
        bpy.types.VIEW3D_MT_edit_curve_specials.prepend(Simple_curve_edit_menu)
    
        from bpy.utils import unregister_class
        for cls in reversed(classes):
            unregister_class(cls)
    
        bpy.types.VIEW3D_MT_curve_add.remove(menu)
        bpy.types.VIEW3D_MT_edit_curve_specials.remove(Simple_curve_edit_menu)
    
    
    if __name__ == "__main__":
        register()