Import_3ds: Improved distance cue node setup
[blender-addons.git] / precision_drawing_tools / pdt_trig_waves.py
blob037cc6273b9487f19a2deaea8992a23e8464f346
1 # SPDX-FileCopyrightText: 2019-2022 Alan Odom (Clockmender)
2 # SPDX-FileCopyrightText: 2019-2022 Rune Morling (ermo)
4 # SPDX-License-Identifier: GPL-2.0-or-later
6 import bpy
7 import bmesh
8 from math import sin, cos, tan, pi
9 from mathutils import Vector
10 from .pdt_functions import (
11 set_mode,
12 view_coords,
15 class PDT_OT_WaveGenerator(bpy.types.Operator):
16 """Generate Trig Waves in Active Object"""
17 bl_idname = "pdt.wave_generator"
18 bl_label = "Generate Waves"
19 bl_options = {"REGISTER", "UNDO"}
21 @classmethod
22 def poll(cls, context):
23 pg = context.scene.pdt_pg
24 return pg.trig_obj is not None
26 def execute(self, context):
27 """Generate Trig Waves in Active Object.
29 Note:
30 Uses all the PDT trig_* variables.
32 This function will draw a trigonometrical wave based upon cycle length
33 One cycle is assumed to be 180 degrees, so half a revolution of an imaginary
34 rotating object. If a full cycle from 0 to 360 degrees is required, the cycles
35 number should be set to 2.
37 Args:
38 context: Blender bpy.context instance.
40 Returns:
41 Nothing.
42 """
44 pg = context.scene.pdt_pg
45 plane = pg.plane
46 # Find the horizontal, vertical and depth axes in the view from working plane.
47 # Order is: H, V, D.
49 a1, a2, a3 = set_mode(plane)
50 # Make sure object selected in the UI is the active object.
52 for obj in bpy.data.objects:
53 obj.select_set(state=False)
54 context.view_layer.objects.active = pg.trig_obj
55 # x_inc is the increase in X (Horiz axis) per unit of resolution of the wave, so if
56 # resolution is 9, nine points will be drawn in each cycle representing increases of
57 # 20 degrees and 1/9th of the cycle length.
59 x_inc = pg.trig_len / pg.trig_res
61 if pg.trig_del:
62 # Delete all existing vertices first.
64 bpy.ops.object.mode_set(mode='EDIT')
65 for v in pg.trig_obj.data.vertices:
66 v.select = True
67 bpy.ops.mesh.delete(type='VERT')
68 bpy.ops.object.mode_set(mode='OBJECT')
70 if pg.trig_obj.mode != "EDIT":
71 bpy.ops.object.mode_set(mode='EDIT')
72 bm = bmesh.from_edit_mesh(pg.trig_obj.data)
74 # Loop for each point in the number of cycles times the resolution value.
75 # Uses basic trigonomtry to calculate the wave locations.
76 # If Absolute has been set, all values are made positive.
77 # z_val is assumed to be the offset from the horizontal axis of the wave.
78 # These values will be offset by the Offset Vector given in the UI.
80 for i in range((pg.trig_res * pg.trig_cycles) + 1):
81 # Uses a calculation of trig function angle of imaginary object times maximum amplitude
82 # of wave. So with reolution at 9, angular increments are 20 degrees.
83 # Angles must be in Radians for this calcultion.
85 if pg.trig_type == "sin":
86 if pg.trig_abs:
87 z_val = abs(sin((i / pg.trig_res) * pi) * pg.trig_amp)
88 else:
89 z_val = sin((i / pg.trig_res) * pi) * pg.trig_amp
90 elif pg.trig_type == "cos":
91 if pg.trig_abs:
92 z_val = abs(cos((i / pg.trig_res) * pi) * pg.trig_amp)
93 else:
94 z_val = cos((i / pg.trig_res) * pi) * pg.trig_amp
95 else:
96 if pg.trig_abs:
97 z_val = abs(tan((i / pg.trig_res) * pi) * pg.trig_amp)
98 else:
99 z_val = tan((i / pg.trig_res) * pi) * pg.trig_amp
101 if abs(z_val) > pg.trig_tanmax:
102 if z_val >= 0:
103 z_val = pg.trig_tanmax
104 else:
105 if pg.trig_abs:
106 z_val = pg.trig_tanmax
107 else:
108 z_val = -pg.trig_tanmax
110 # Start with Offset Vector from UI and add wave offsets to it.
111 # Axis a3 (depth) is never changed from offset vector in UI.
113 vert_loc = Vector(pg.trig_off)
114 vert_loc[a1] = vert_loc[a1] + (i * x_inc)
115 vert_loc[a2] = vert_loc[a2] + z_val
116 if plane == "LO":
117 # Translate view local coordinates (horiz, vert, depth) into World XYZ
119 vert_loc = view_coords(vert_loc[a1], vert_loc[a2], vert_loc[a3])
120 vertex_new = bm.verts.new(vert_loc)
121 # Refresh Vertices list in object data.
123 bm.verts.ensure_lookup_table()
124 if i > 0:
125 # Make an edge from last two vertices in object data.
127 bm.edges.new([bm.verts[-2], vertex_new])
129 bmesh.update_edit_mesh(pg.trig_obj.data)
130 bpy.ops.object.mode_set(mode='OBJECT')
132 return {"FINISHED"}