Ich weiß nicht, wie ich mein Problem gut umfassend erklären soll. Deshalb zeige ich Ihnen ein Beispiel...
Ich habe dieses Array, das die Vertices-Indizes für jedes Quad oder Dreieck angibt:
>>> faces
array([[0, 1, 2, 3],
[4, 7, 6, 5],
[0, 4, 1, 0],
[1, 5, 6, 2],
[2, 6, 7, 3],
[4, 0, 3, 7],
[1, 4, 5, 0]])
Dreiecke sind die Elemente, die mit enden0
Ich möchte eine Transformation wie folgt vornehmen:
>>> faces
array([[0, 1, 2, 3], #->[[0, 1, 2], [0, 2, 3],
[4, 7, 6, 5], #-> [4, 7, 6], [4, 6, 5],
[0, 4, 1, 0], #-> [0, 4, 1],
[1, 5, 6, 2], #-> [1, 5, 6], [1, 6, 2],
[2, 6, 7, 3], #-> [2, 6, 7], [2, 7, 3],
[4, 0, 3, 7], #-> [4, 0, 3], [4, 3, 7],
[1, 4, 5, 0]]) #-> [1, 4, 5]]
Wie kann ich diese Transformation also effizient gestalten?
Ich habe eine Funktion, die es anders löst. Platzieren Sie die von den Quads erhaltenen Dreiecke am Ende des Arrays.
def v_raw_to_tris(tessfaces):
len_tessfaces = len(tessfaces)
quad_indices = tessfaces[:, 3].nonzero()[0]
t3 = np.empty(((len_tessfaces + len(quad_indices)), 3), 'i4')
t3[:len_tessfaces] = tessfaces[:,:3]
t3[len_tessfaces:] = tessfaces[quad_indices][:, (0, 2, 3)]
return t3
Aber ich möchte nicht, dass die resultierenden Dreiecke am Ende des Arrays stehen. Und ja vor den originalen Quads
Lösung des Problems
Wir könnten jede Reihe mit dem einmaligen Verschieben für jede Reihe als zwei Reihen replizieren und die dreieckigen am Ende ausblenden. Die Implementierung würde in etwa so aussehen -
def transform1(a):
idx = np.flatnonzero(a[:,-1] == 0)
out0 = np.empty((a.shape[0],2,3),dtype=a.dtype)
out0[:,0,1:] = a[:,1:-1]
out0[:,1,1:] = a[:,2:]
out0[...,0] = a[:,0,None]
out0.shape = (-1,3)
mask = np.ones(out0.shape[0],dtype=bool)
mask[idx*2+1] = 0
return out0[mask]
Probelauf -
In [94]: a
Out[94]:
array([[0, 1, 2, 3],
[4, 7, 6, 5],
[0, 4, 1, 0],
[1, 5, 6, 2],
[2, 6, 7, 3],
[4, 0, 3, 7],
[1, 4, 5, 0]])
In [95]: transform1(a)
Out[95]:
array([[0, 1, 2],
[0, 2, 3],
[4, 7, 6],
[4, 6, 5],
[0, 4, 1],
[1, 5, 6],
[1, 6, 2],
[2, 6, 7],
[2, 7, 3],
[4, 0, 3],
[4, 3, 7],
[1, 4, 5]])
Mögliche Verbesserung
Wir können einführen np.lib.stride_tricks.as_strided
, um die zweistufigen Zuweisungen für zu ersetzenout0[:,0,1:]
und out0[:,1,1:]
als eine zu ersetzen, und das sollte es hoffentlich verbessern, so -
from numpy.lib.stride_tricks import as_strided
def strided_axis1(a, L):
s0,s1 = a.strides
m,n = a.shape
nL = n-L+1
return as_strided(a, (m,nL,L),(s0,s1,s1))
def transform2(a):
idx = np.flatnonzero(a[:,-1] == 0)
out0 = np.empty((a.shape[0],2,3),dtype=a.dtype)
out0[...,1:] = strided_axis1(a[:,1:], 2)
out0[...,0] = a[:,0,None]
out0.shape = (-1,3)
mask = np.ones(out0.shape[0],dtype=bool)
mask[idx*2+1] = 0
return out0[mask]
Keine Kommentare:
Kommentar veröffentlichen