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

pdt_cad_module.py « precision_drawing_tools - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 21a5c6c700b99b63f153a675c14b6ecca446dfd9 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
#
# <pep8 compliant>
#
# ----------------------------------------------------------
# Author: Zeffii
# Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
# ----------------------------------------------------------
#
import bmesh
from mathutils import Vector
from mathutils.geometry import intersect_line_line, intersect_point_line
from .pdt_functions import debug

def point_on_edge(p, edge):
    """Find Point on Edge.

    Args:
        p:        vector
        edge:     tuple containing 2 vectors.

    Returns:
        True if point p happens to lie on the edge, False otherwise.
    """

    pt, _percent = intersect_point_line(p, *edge)
    on_line = (pt - p).length < 1.0e-5
    return on_line and (0.0 <= _percent <= 1.0)


def line_from_edge_intersect(edge1, edge2):
    """Get New Line from Intersections.

    Prepares input for sending to intersect_line_line

    Args:
        edge1, edge2: tuples containing 2 vectors.

    Returns:
        Output of intersect_line_line.
    """

    [p1, p2], [p3, p4] = edge1, edge2
    return intersect_line_line(p1, p2, p3, p4)


def get_intersection(edge1, edge2):
    """Get Intersections of 2 Edges.

    Args:
        edge1, edge2: tuples containing 2 vectors.

    Returns:
        The point halfway on line. See intersect_line_line.
    """

    line = line_from_edge_intersect(edge1, edge2)
    if line:
        return (line[0] + line[1]) / 2


def test_coplanar(edge1, edge2):
    """Test 2 Edges are Co-planar.

    The line that describes the shortest line between the two edges would be short if the
    lines intersect mathematically. If this line is longer than 1.0e-5 then they are either
    coplanar or parallel

    Args:
        edge1, edge2: tuples containing 2 vectors.

    Returns:
        True if edge1 and edge2 or coplanar, False otherwise.
    """

    line = line_from_edge_intersect(edge1, edge2)
    if line:
        return (line[0] - line[1]).length < 1.0e-5


def closest_idx(pt, e):
    """Get Closest Vertex to input point.

    If both points in e are equally far from pt, then v1 is returned.

    Args:
        pt:       vector
        e:        bmesh edge

    Returns:
        Index of vertex closest to pt.
    """

    if isinstance(e, bmesh.types.BMEdge):
        ev = e.verts
        v1 = ev[0].co
        v2 = ev[1].co
        distance_test = (v1 - pt).length <= (v2 - pt).length
        return ev[0].index if distance_test else ev[1].index

    debug(f"Received {e}, check expected input in docstring ")


def closest_vector(pt, e):
    """Return Closest Vector to input Point.

    If both points in e are equally far from pt, then v1 is returned.

    Args:
        pt:       vector
        e:        tuple containing 2 vectors

    Returns:
        Vector closest to pt.
    """

    if isinstance(e, tuple) and all([isinstance(co, Vector) for co in e]):
        v1, v2 = e
        distance_test = (v1 - pt).length <= (v2 - pt).length
        return v1 if distance_test else v2

    debug(f"Received {e}, check expected input in docstring ")


def coords_tuple_from_edge_idx(bm, idx):
    """Return Tuple from Vertex."""
    return tuple(v.co for v in bm.edges[idx].verts)


def vectors_from_indices(bm, raw_vert_indices):
    """Return List of vectors from input indices."""
    return [bm.verts[i].co for i in raw_vert_indices]


def vertex_indices_from_edges_tuple(bm, edge_tuple):
    """Return List of vertices.

    Args:
        bm:           is a bmesh representation
        edge_tuple:   contains 2 edge indices.

    Returns:
        The vertex indices of edge_tuple.
    """

    def k(v, w):
        return bm.edges[edge_tuple[v]].verts[w].index

    return [k(i >> 1, i % 2) for i in range(4)]


def get_vert_indices_from_bmedges(edges):
    """Return List of Edges for evaluation.

    Args:
        bmedges:      a list of 2 bm edges

    Returns:
        The vertex indices of edge_tuple as a flat list.
    """
    temp_edges = []
    debug(edges)
    for e in edges:
        for v in e.verts:
            temp_edges.append(v.index)
    return temp_edges


def num_edges_point_lies_on(pt, edges):
    """Returns the number of edges that a point lies on."""
    res = [point_on_edge(pt, edge) for edge in [edges[:2], edges[2:]]]
    return len([i for i in res if i])


def find_intersecting_edges(bm, pt, idx1, idx2):
    """Find Intercecting Edges.

    Args:
        pt:           Vector
        idx1, ix2:    edge indices

    Returns:
        The list of edge indices where pt is on those edges.
    """
    if not pt:
        return []
    idxs = [idx1, idx2]
    edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs]
    return [idx for edge, idx in zip(edges, idxs) if point_on_edge(pt, edge)]


def vert_idxs_from_edge_idx(bm, idx):
    edge = bm.edges[idx]
    return edge.verts[0].index, edge.verts[1].index