GJK.processTetrehedron()   D
last analyzed

Complexity

Conditions 10

Size

Total Lines 58

Duplication

Lines 36
Ratio 62.07 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
dl 36
loc 58
rs 4.9315
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like GJK.processTetrehedron() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
from gem import vector
2
3
class SimplexVerts(object):
4
    def __init__(self):
5
        self.p1 = vector.Vector(2)
6
        self.p2 = vector.Vector(2)
7
        self.p = vector.Vector(2)
8
        self.u = 1
9
        self.index1 = 0
10
        self.index2 = 0
11
12
    def copy(self, v):
13
        self.p1 = v.p1
14
        self.p2 = v.p2
15
        self.p = v.p
16
        self.u = v.u
17
        self.index1 = v.index1
18
        self.index2 = v.index2
19
20
class Simplex(object):
21
    def __init__(self, vertices):
22
        self.vertices = []
23
        self.vertices.append(vertices)
24
25
    def __getitem__(self, key):
26
        return self.vertices[key]
27
28
    def getCount(self):
29
        return len(self.vertices)
30
31
    def add(self, vertex):
32
        self.vertices.append(vertex)
33
34
    def copy(self, s):
35
        self.vertices = s.vertices
36
37
    def remove(self, vertex):
38
        index = 0
39
        for i in range(len(self.vertices)):
40
            if vertex == self.vertices[i]:
41
                index = i
42
        #Trash the value
43
        del self.vertices[index]
44
45
def Support(regionOne, regionTwo, direction):
46
    '''Makes use of the primities. Each primitive has its own getFurthestPoint function. '''
47
    return regionOne.getFurthestPoint(direction) - regionTwo.getFurthestPoint(-direction)
48
49
class GJK(object):
50
    def __init__(self):
51
        self.direction = vector.Vector(3)
52
53
    def intersects(self, regionOne, regionTwo):
54
        # Get initial point on the Minkowski difference
55
        s = Support(regionOne, regionTwo, vector.Vector(3).one())
56
57
        # Create the inital simplex
58
        simplex = Simplex(s)
59
60
        # Choose an initial direction towards the origin
61
        self.direction = -s
62
63
        # Choose a maximum number of iterations to avoid
64
        # an infinite loop during non-convergent search.
65
        maxIterations = 50
66
67
        for i in range(maxIterations):
68
            # Get our next simplex point towards the origin
69
            a = Support(regionOne, regionTwo, self.direction)
70
71
            # If we move toward the origin and didn't pass it
72
            # then we never will and there is no intersection
73
            if (a.isInOppositeDirection(self.direction)):
74
                return False
75
76
            # Otherwise we add the new point to the simplex and process it.
77
            simplex.add(a)
78
79
            # Here we either find a collision or we find the closest feature of 
80
            # simplex to the origin, make the new simplex and update the direction
81
            # to move toward the origin from that feature.
82
            if self.processSimplex(simplex):
83
                return True
84
85
        # If we still couldn't find a simplex that contains the origin
86
        # then we probably have an intersection
87
        return True
88
89
    def processSimplex(self, simplex):
90
        '''Either finds a collision or the closest feature of the simplex to the origin, and updates the simplex and direction'''
91
        if (simplex.getCount() == 2):
92
            return self.processLine(simplex)
93
        elif (simplex.getCount() == 3):
94
            return self.processTriangle(simplex)
95
        else:
96
            return self.processTetrehedron(simplex)
97
98
    def processLine(self, simplex):
99
        '''Determines which Veronoi region of a tetrehedron the origin is in, utilizing the preserved winding of the simplex to eliminate certain regions'''
100
        a = simplex[1]
101
        b = simplex[0]
102
103
        ab = b - a
104
        aO = -a
105
106
        if(ab.isInSameDirection(aO)):
107
            #dot = ab.dot(aO)
108
            #angle = math.acos(dot / ab.magnitude() * aO.magnitude())
109
            self.direction = vector.cross(vector.cross(ab, aO), ab)
110
        else:
111
            simplex.remove(b)
112
            self.direction = aO
113
        return False
114
115
    def processTriangle(self, simplex):
116
        '''Determines which Veronoi region of a tetrehedron the origin is in, utilizing the preserved winding of the simplex to eliminate certain regions'''
117
        a = simplex[2]
118
        b = simplex[1]
119
        c = simplex[0]
120
121
        ab = b - a
122
        ac = c - a
123
        abc = vector.cross(ab, ac)
124
        aO = -a
125
126
        acNormal = vector.cross(abc, ac)
127
        abNormal = vector.cross(ab, abc)
128
129
        if(acNormal.isInSameDirection(aO)):
130
            if(ac.isInSameDirection(aO)):
131
                simplex.remove(b)
132
                self.direction = vector.cross(vector.cross(ac, aO), ac)
133
            else:
134
                if(ab.isInSameDirection(aO)):
135
                    simplex.remove(c)
136
                    self.direction = vector.cross(vector.cross(ab, aO), ab)
137
                else:
138
                    simplex.remove(b)
139
                    simplex.remove(c)
140
                    self.direction = aO
141
        else:
142 View Code Duplication
            if (abNormal.isInSameDirection(aO)):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
143
                if(ab.isInSameDirection(aO)):
144
                    simplex.remove(c)
145
                    self.direction = vector.cross(vector.cross(ab, aO), ab)
146
                else:
147
                    simplex.remove(b)
148
                    simplex.remove(c)
149
                    self.direction = aO
150
            else:
151
                if(abc.isInSameDirection(aO)):
152
                    self.direction = vector.cross(vector.cross(abc, aO), abc)
153
                else:
154
                    self.direction = vector.cross(vector.cross(-abc, aO), -abc)
155
        return False
156
157
    def processTetrehedron(self, simplex):
158
        '''Determines which Veronoi region of a tetrehedron the origin is in, utilizing the preserved winding of the simplex to eliminate certain regions'''
159
        a = simplex[3]
160
        b = simplex[2]
161
        c = simplex[1]
162
        d = simplex[0]
163
164
        ac = c - a
165
        ad = d - a
166
        ab = b - a
167
        #bc = c - b
168
        #bd = d - b
169
170
        acd = vector.cross(ad, ac)
171
        abd = vector.cross(ab, ad)
172
        abc = vector.cross(ac, ab)
173
174
        aO = -a
175
176
        if (abc.isInSameDirection(aO)):
177 View Code Duplication
            if (vector.cross(abc, ac).isInSameDirection(aO)):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
178
                simplex.remove(b)
179
                simplex.remove(d)
180
                self.direction = vector.cross(vector.cross(ac, aO), ac)
181
            elif(vector.cross(ab, abc).isInSameDirection(aO)):
182
                simplex.remove(c)
183
                simplex.remove(d)
184
                self.direction = vector.cross(vector.cross(ab, aO), ab)
185
            else:
186
                simplex.remove(d)
187
                self.direction = abc
188
        elif (acd.isInSameDirection(aO)):
189 View Code Duplication
            if (vector.cross(acd, ad).isInSameDirection(aO)):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
190
                simplex.remove(b)
191
                simplex.remove(c)
192
                self.direction = vector.cross(vector.cross(ad, aO), ad)
193
            elif(vector.cross(ac, acd).isInSameDirection(aO)):
194
                simplex.remove(b)
195
                simplex.remove(d)
196
                self.direction = vector.cross(vector.cross(ac, aO), ac)
197
            else:
198
                simplex.remove(b)
199
                self.direction = acd
200 View Code Duplication
        elif(abd.isInSameDirection(aO)):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
201
            if(vector.cross(abd, ab).isInSameDirection(aO)):
202
                simplex.remove(b)
203
                simplex.remove(d)
204
                self.direction = vector.cross(vector.cross(ab, aO), ab)
205
            elif(vector.cross(ab, abd).isInSameDirection(aO)):
206
                simplex.remove(b)
207
                simplex.remove(c)
208
                self.direction = vector.cross(vector.cross(ad, aO), ad)
209
            else:
210
                simplex.remove(c)
211
                self.direction = abd
212
        else:
213
            return True
214
        return False
215
216
217
218
219
220
221