Welcome to mirror list, hosted at ThFree Co, Russian Federation.

pdt_trig_waves.py « precision_drawing_tools - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 84bc4b6fbd73623d414675574b29497567871c97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# SPDX-License-Identifier: GPL-2.0-or-later

# -----------------------------------------------------------------------
# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
# -----------------------------------------------------------------------
#
import bpy
import bmesh
from math import sin, cos, tan, pi
from mathutils import Vector
from .pdt_functions import (
    set_mode,
    view_coords,
)

class PDT_OT_WaveGenerator(bpy.types.Operator):
    """Generate Trig Waves in Active Object"""
    bl_idname = "pdt.wave_generator"
    bl_label = "Generate Waves"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        pg = context.scene.pdt_pg
        return pg.trig_obj is not None

    def execute(self, context):
        """Generate Trig Waves in Active Object.

        Note:
            Uses all the PDT trig_* variables.

            This function will draw a trigonometrical wave based upon cycle length
            One cycle is assumed to be 180 degrees, so half a revolution of an imaginary
            rotating object. If a full cycle from 0 to 360 degrees is required, the cycles
            number should be set to 2.

        Args:
            context: Blender bpy.context instance.

        Returns:
            Nothing.
        """

        pg = context.scene.pdt_pg
        plane = pg.plane
        # Find the horizontal, vertical and depth axes in the view from working plane.
        # Order is: H, V, D.
        #
        a1, a2, a3 = set_mode(plane)
        # Make sure object selected in the UI is the active object.
        #
        for obj in bpy.data.objects:
            obj.select_set(state=False)
        context.view_layer.objects.active = pg.trig_obj
        # x_inc is the increase in X (Horiz axis) per unit of resolution of the wave, so if
        # resolution is 9, nine points will be drawn in each cycle representing increases of
        # 20 degrees and 1/9th of the cycle length.
        #
        x_inc = pg.trig_len / pg.trig_res

        if pg.trig_del:
            # Delete all existing vertices first.
            #
            bpy.ops.object.mode_set(mode='EDIT')
            for v in pg.trig_obj.data.vertices:
                v.select = True
            bpy.ops.mesh.delete(type='VERT')
            bpy.ops.object.mode_set(mode='OBJECT')

        if pg.trig_obj.mode != "EDIT":
            bpy.ops.object.mode_set(mode='EDIT')
        bm = bmesh.from_edit_mesh(pg.trig_obj.data)

        # Loop for each point in the number of cycles times the resolution value.
        # Uses basic trigonomtry to calculate the wave locations.
        # If Absolute has been set, all values are made positive.
        # z_val is assumed to be the offset from the horizontal axis of the wave.
        # These values will be offset by the Offset Vector given in the UI.
        #
        for i in range((pg.trig_res * pg.trig_cycles) + 1):
            # Uses a calculation of trig function angle of imaginary object times maximum amplitude
            # of wave. So with reolution at 9, angular increments are 20 degrees.
            # Angles must be in Radians for this calcultion.
            #
            if pg.trig_type == "sin":
                if pg.trig_abs:
                    z_val = abs(sin((i / pg.trig_res) * pi) * pg.trig_amp)
                else:
                    z_val = sin((i / pg.trig_res) * pi) * pg.trig_amp
            elif pg.trig_type == "cos":
                if pg.trig_abs:
                    z_val = abs(cos((i / pg.trig_res) * pi) * pg.trig_amp)
                else:
                    z_val = cos((i / pg.trig_res) * pi) * pg.trig_amp
            else:
                if pg.trig_abs:
                    z_val = abs(tan((i / pg.trig_res) * pi) * pg.trig_amp)
                else:
                    z_val = tan((i / pg.trig_res) * pi) * pg.trig_amp

                if abs(z_val) > pg.trig_tanmax:
                    if z_val >= 0:
                        z_val = pg.trig_tanmax
                    else:
                        if pg.trig_abs:
                            z_val = pg.trig_tanmax
                        else:
                            z_val = -pg.trig_tanmax

            # Start with Offset Vector from UI and add wave offsets to it.
            # Axis a3 (depth) is never changed from offset vector in UI.
            #
            vert_loc = Vector(pg.trig_off)
            vert_loc[a1] = vert_loc[a1] + (i * x_inc)
            vert_loc[a2] = vert_loc[a2] + z_val
            if plane == "LO":
                # Translate view local coordinates (horiz, vert, depth) into World XYZ
                #
                vert_loc = view_coords(vert_loc[a1], vert_loc[a2], vert_loc[a3])
            vertex_new = bm.verts.new(vert_loc)
            # Refresh Vertices list in object data.
            #
            bm.verts.ensure_lookup_table()
            if i > 0:
                # Make an edge from last two vertices in object data.
                #
                bm.edges.new([bm.verts[-2], vertex_new])

        bmesh.update_edit_mesh(pg.trig_obj.data)
        bpy.ops.object.mode_set(mode='OBJECT')

        return {"FINISHED"}