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

cad_module.py « mesh_tiny_cad - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 01e86f5734b05f23b7ae0b2b9df84fe67a248960 (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
# SPDX-License-Identifier: GPL-2.0-or-later


import bmesh

from mathutils import Vector, geometry
from mathutils.geometry import intersect_line_line as LineIntersect
from mathutils.geometry import intersect_point_line as PtLineIntersect


class CAD_prefs:
    VTX_PRECISION = 1.0e-5
    VTX_DOUBLES_THRSHLD = 0.0001


def point_on_edge(p, edge):
    '''
    > p:        vector
    > edge:     tuple of 2 vectors
    < returns:  True / False if a point happens to lie on an edge
    '''
    pt, _percent = PtLineIntersect(p, *edge)
    on_line = (pt - p).length < CAD_prefs.VTX_PRECISION
    return on_line and (0.0 <= _percent <= 1.0)


def line_from_edge_intersect(edge1, edge2):
    '''
    > takes 2 tuples, each tuple contains 2 vectors
    - prepares input for sending to intersect_line_line
    < returns output of intersect_line_line
    '''
    [p1, p2], [p3, p4] = edge1, edge2
    return LineIntersect(p1, p2, p3, p4)


def get_intersection(edge1, edge2):
    '''
    > takes 2 tuples, each tuple contains 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):
    '''
    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 the VTX_PRECISION then they are either
    coplanar or parallel.
    '''
    line = line_from_edge_intersect(edge1, edge2)
    if line:
        return (line[0] - line[1]).length < CAD_prefs.VTX_PRECISION


def closest_idx(pt, e):
    '''
    > pt:       vector
    > e:        bmesh edge
    < returns:  returns index of vertex closest to pt.

    if both points in e are equally far from pt, then v1 is returned.
    '''
    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

    print("received {0}, check expected input in docstring ".format(e))


def closest_vector(pt, e):
    '''
    > pt:       vector
    > e:        2 vector tuple
    < returns:
    pt, 2 vector tuple: returns closest vector to pt

    if both points in e are equally far from pt, then v1 is returned.
    '''
    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

    print("received {0}, check expected input in docstring ".format(e))


def coords_tuple_from_edge_idx(bm, idx):
    ''' bm is a bmesh representation '''
    return tuple(v.co for v in bm.edges[idx].verts)


def vectors_from_indices(bm, raw_vert_indices):
    ''' bm is a bmesh representation '''
    return [bm.verts[i].co for i in raw_vert_indices]


def vertex_indices_from_edges_tuple(bm, edge_tuple):
    '''
    > bm:           is a bmesh representation
    > edge_tuple:   contains two 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):
    '''
    > bmedges:      a list of two bm edges
    < returns the vertex indices of edge_tuple as a flat list.
    '''
    temp_edges = []
    print(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):
    '''
    > 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 duplicates(indices):
    return len(set(indices)) < 4


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