Skip to content

Commit

Permalink
Merge pull request #5035 from nortikin/fix_5034_Apply_Vector_Field_No…
Browse files Browse the repository at this point in the history
…de_performance_proposal

fix #5034. Apply Vector Field Node performance proposal solution
  • Loading branch information
satabol authored Oct 29, 2023
2 parents d85084d + 1f247fd commit 8e19ef8
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 48 deletions.
3 changes: 1 addition & 2 deletions utils/field/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,8 +1044,7 @@ def _evaluate(self, vertices):
if self.only_2D:
return self.surface.evaluate_array(us, vs)

surf_vertices = self.surface.evaluate_array(us, vs)
spline_normals = self.surface.normal_array(us, vs)
spline_normals, surf_vertices = self.surface.normal_vertices_array(us, vs)
zs = vertices[:,self.orient_axis].flatten()
zs = zs[np.newaxis].T
v1 = zs * spline_normals
Expand Down
98 changes: 57 additions & 41 deletions utils/surface/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from mathutils import Matrix, Vector


from sverchok.utils.math import (
ZERO, FRENET, HOUSEHOLDER, TRACK, DIFF, TRACK_NORMAL,
np_dot
Expand Down Expand Up @@ -158,60 +159,75 @@ def normal(self, u, v):
# normals = [self._normal(u, v) for u,v in zip(us, vs)]
# return np.array(normals)

def normal_array(self, us, vs):
def normal_vertices_array(self, us, vs):
h = 0.001
result = np.empty((len(us), 3))
_points = np.empty( (0, 3), dtype=np.float64)
_points_u_h = np.empty( (0, 3), dtype=np.float64)
_points_v_h = np.empty( (0, 3), dtype=np.float64)
v_to_u = defaultdict(list)
v_to_i = defaultdict(list)
for i, (u, v) in enumerate(zip(us, vs)):
v_to_u[v].append(u)
v_to_i[v].append(i)
for v, us_by_v in v_to_u.items():
us_by_v = np.array(us_by_v)
is_by_v = v_to_i[v]
v_to_i_flatten = np.hstack(np.array( list(v_to_i.values())).flatten())

list_spline_v = []
list_spline_h = []
_v = np.array( list(v_to_u.keys()), dtype=np.float64 )
for i_spline, v_spline in enumerate(self.v_splines):
v_min, v_max = v_spline.get_u_bounds()
_vx = (v_max-v_min)*_v+v_min
_list_v_i = np.where( _vx+h<v_max, _vx , _vx-h)
_list_h_i = np.where( _vx+h<v_max, _vx+h, _vx )
list_spline_v.append( _list_v_i )
list_spline_h.append( _list_h_i )

r_v = []
r_h = []
for i, v_spline in enumerate(self.v_splines):
_r_v, _r_h = v_spline.evaluate_array( np.concatenate( (list_spline_v[i], list_spline_h[i]) )).reshape(2,-1,3) # to increase performance for one call
r_v.append( _r_v )
r_h.append( _r_h )

u_min, u_max = 0.0, 1.0

for i_on_spline, (v, _us_by_v) in enumerate(v_to_u.items()):
us_by_v = np.array(_us_by_v)
#i_by_v = v_to_i[v]
spline_vertices = []
spline_vertices_h = []
for v_spline in self.v_splines:
v_min, v_max = v_spline.get_u_bounds()
vx = (v_max - v_min) * v + v_min
if vx +h <= v_max:
point = v_spline.evaluate(vx)
point_h = v_spline.evaluate(vx + h)
else:
point = v_spline.evaluate(vx - h)
point_h = v_spline.evaluate(vx)
spline_vertices.append(point)

for i_spline, v_spline in enumerate(self.v_splines):
point_v = r_v[i_spline][i_on_spline]
point_h = r_h[i_spline][i_on_spline]
spline_vertices.append(point_v)
spline_vertices_h.append(point_h)

if v+h <= v_max:
u_spline = self.get_u_spline(v, spline_vertices)
u_spline = self.get_u_spline(v , spline_vertices )
u_spline_h = self.get_u_spline(v+h, spline_vertices_h)
else:
u_spline = self.get_u_spline(v-h, spline_vertices)
u_spline_h = self.get_u_spline(v, spline_vertices_h)
u_min, u_max = 0.0, 1.0
u_spline = self.get_u_spline(v-h, spline_vertices )
u_spline_h = self.get_u_spline(v , spline_vertices_h)

good_us = us_by_v + h < u_max
bad_us = np.logical_not(good_us)

good_points = np.broadcast_to(good_us[np.newaxis].T, (len(us_by_v), 3)).flatten()
bad_points = np.logical_not(good_points)
points = np.empty((len(us_by_v), 3))
points[good_us] = u_spline.evaluate_array(us_by_v[good_us])
points[bad_us] = u_spline.evaluate_array(us_by_v[bad_us] - h)
points_u_h = np.empty((len(us_by_v), 3))
points_u_h[good_us] = u_spline.evaluate_array(us_by_v[good_us] + h)
points_u_h[bad_us] = u_spline.evaluate_array(us_by_v[bad_us])
points_v_h = u_spline_h.evaluate_array(us_by_v)

dvs = (points_v_h - points) / h
dus = (points_u_h - points) / h
normals = np.cross(dus, dvs)
norms = np.linalg.norm(normals, axis=1, keepdims=True)
normals = normals / norms
us_v_gb = np.where( good_us, us_by_v , us_by_v-h )
us_h_gb = np.where( good_us, us_by_v+h, us_by_v )

idxs = np.array(is_by_v)[np.newaxis].T
np.put_along_axis(result, idxs, normals, axis=0)
return result
points, points_u_h = u_spline.evaluate_array( np.concatenate( (us_v_gb, us_h_gb) ) ).reshape(2,-1,3) # to increase performance for one call
points_v_h = u_spline_h.evaluate_array(us_by_v)
_points = np.concatenate( (_points, points) )
_points_u_h = np.concatenate( (_points_u_h, points_u_h) )
_points_v_h = np.concatenate( (_points_v_h, points_v_h) )

_dvs = (_points_v_h - _points)/h
_dus = (_points_u_h - _points)/h
_normals = np.cross(_dus, _dvs)
_norms = np.linalg.norm(_normals, axis=1, keepdims=True)
_normals = _normals / _norms
_result_normals = _normals[np.argsort(v_to_i_flatten)]
_result_point = _points[np.argsort(v_to_i_flatten)]
return _result_normals, _result_point

PROJECT = 'project'
COPROJECT = 'coproject'
Expand Down Expand Up @@ -296,7 +312,7 @@ def normal(self, u, v):
normal = normal / n
return normal

def normal_array(self, us, vs):
def normal_vertices_array(self, us, vs):
surf_vertices = self.evaluate_array(us, vs)
u_plus = self.evaluate_array(us + self.normal_delta, vs)
v_plus = self.evaluate_array(us, vs + self.normal_delta)
Expand All @@ -309,7 +325,7 @@ def normal_array(self, us, vs):
#if norm != 0:
normal = normal / norm
#self.info("Normals: %s", normal)
return normal
return normal, surf_vertices

class SvRevolutionSurface(SvSurface):
__description__ = "Revolution"
Expand Down
10 changes: 7 additions & 3 deletions utils/surface/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ def normal(self, u, v):
return normal

def normal_array(self, us, vs):
normal, *_ = self.normal_vertices_array(us, vs)
return normal

def normal_vertices_array(self, us, vs):
surf_vertices = self.evaluate_array(us, vs)
u_plus = self.evaluate_array(us + self.normal_delta, vs)
v_plus = self.evaluate_array(us, vs + self.normal_delta)
Expand All @@ -50,7 +54,7 @@ def normal_array(self, us, vs):
#if norm != 0:
normal = normal / norm
#self.info("Normals: %s", normal)
return normal
return normal, surf_vertices

def derivatives_data_array(self, us, vs):
if hasattr(self, 'normal_delta'):
Expand Down Expand Up @@ -403,7 +407,7 @@ def evaluate_array(self, us, vs):
def normal(self, u, v):
return self.normal_array(np.array([u]), np.array([v]))[0]

def normal_array(self, us, vs):
def normal_vertices_array(self, us, vs):
surf_vertices = self.evaluate_array(us, vs)
u_plus = self.evaluate_array(us + self.normal_delta, vs)
v_plus = self.evaluate_array(us, vs + self.normal_delta)
Expand All @@ -416,5 +420,5 @@ def normal_array(self, us, vs):
#if norm != 0:
normal = normal / norm
#self.info("Normals: %s", normal)
return normal
return normal, surf_vertices

4 changes: 2 additions & 2 deletions utils/surface/rbf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def evaluate_array(self, us, vs):
def normal(self, u, v):
return self.normal_array(np.array([u]), np.array([v]))[0]

def normal_array(self, us, vs):
def normal_vertices_array(self, us, vs):
surf_vertices = self.evaluate_array(us, vs)
u_plus = self.evaluate_array(us + self.normal_delta, vs)
v_plus = self.evaluate_array(us, vs + self.normal_delta)
Expand All @@ -82,5 +82,5 @@ def normal_array(self, us, vs):
#if norm != 0:
normal = normal / norm
#self.info("Normals: %s", normal)
return normal
return normal, surf_vertices

0 comments on commit 8e19ef8

Please sign in to comment.