Открыть боковую панель
nikitronn
sverchok
Коммиты
16cb41f9
Коммит
16cb41f9
создал
Сен 17, 2022
по автору
satabol
Просмотр файлов
Merge branch 'master' into update_menu_nodes_comments_v14
владельцы
9f88c7b4
2a31dd17
Изменения
16
Скрыть пробелы
Построчно
Рядом
core/events.py
Просмотр файла @
16cb41f9
...
...
@@ -90,6 +90,10 @@ class FileEvent:
pass
class
UndoEvent
:
"""Undo handler was executed"""
class
TreesGraphEvent
:
"""It indicates that something was changed in trees relations defined via
group nodes"""
...
...
core/group_update_system.py
Просмотр файла @
16cb41f9
...
...
@@ -50,6 +50,14 @@ def control_center(event):
elif
type
(
event
)
is
ev
.
TreesGraphEvent
:
trees_graph
.
is_updated
=
False
# nodes will have another hash id and the comparison method will decide that
# all nodes are new, and won't be able to detect changes, and will update all
# Unlike main trees, groups can't do this via GroupTreeEvent because it
# should be called only when a group is edited by user
elif
type
(
event
)
is
ev
.
UndoEvent
:
for
gt
in
BlTrees
().
sv_group_trees
:
GroupUpdateTree
.
get
(
gt
).
is_updated
=
False
else
:
was_executed
=
False
...
...
core/handlers.py
Просмотр файла @
16cb41f9
...
...
@@ -65,6 +65,8 @@ def sv_handler_undo_post(scene):
undo_handler_node_count
[
'sv_groups'
]
=
0
handle_event
(
ev
.
UndoEvent
())
@
persistent
def
sv_update_handler
(
scene
):
...
...
@@ -162,9 +164,9 @@ def sv_post_load(scene):
with
catch_log_error
():
if
any
(
not
n
.
is_registered_node_type
()
for
ng
in
BlTrees
().
sv_trees
for
n
in
ng
.
nodes
):
old_nodes
.
register_all
()
old_nodes
.
mark_all
()
dummy_nodes
.
register_all
()
dummy_nodes
.
mark_all
()
old_nodes
.
mark_all
()
dummy_nodes
.
mark_all
()
with
catch_log_error
():
settings
.
apply_theme_if_necessary
()
...
...
core/update_system.py
Просмотр файла @
16cb41f9
...
...
@@ -476,6 +476,10 @@ class UpdateTree(SearchTree):
"""Remove tree data or data of all trees from the cache"""
if
tree
is
not
None
and
tree
.
tree_id
in
cls
.
_tree_catch
:
del
cls
.
_tree_catch
[
tree
.
tree_id
]
# reset nested trees too
for
group
in
(
n
for
n
in
tree
.
nodes
if
hasattr
(
n
,
'node_tree'
)):
UpdateTree
.
reset_tree
(
group
.
node_tree
)
else
:
cls
.
_tree_catch
.
clear
()
...
...
docs/nodes/surface/sphere.rst
Просмотр файла @
16cb41f9
...
...
@@ -10,6 +10,7 @@ This node generates a spherical Surface object. Several parametrizations are ava
* Equirectangular
* Lambert
* Gall Stereographic
* NURBS Sphere
For formulas, please refer to Wikipedia: https://en.wikipedia.org/wiki/List_of_map_projections
...
...
docs/nodes/viz/viewer_draw_surface.rst
Просмотр файла @
16cb41f9
...
...
@@ -82,6 +82,10 @@ The parameters of the node are (in this order):
* **Display Control Net**, **Control Net Color**, **Control Net Line Width**.
Control display of surface's control net (edges between control points), for
NURBS and NURBS-like surfaces. Control net is not displayed by default.
* **Display Node Lines**, **Node Lines Color**, **Node Lines Width**. Conrtol
display of node lines, i.e. isolines at U and V parameters according to node
values of knotvectors along U and V parameter directions. Node lines are not
displayed by default.
.. image:: https://user-images.githubusercontent.com/14288520/190234804-8789ca5c-d35a-46f3-9c6c-95cc440ce394.png
:target: https://user-images.githubusercontent.com/14288520/190234804-8789ca5c-d35a-46f3-9c6c-95cc440ce394.png
...
...
nodes/scene/3dview_props.py
Просмотр файла @
16cb41f9
...
...
@@ -81,6 +81,10 @@ class Sv3DviewPropsNode(bpy.types.Node, SverchCustomTreeNode):
row
=
layout
.
row
(
align
=
True
)
row
.
prop
(
prefs
.
inputs
,
'view_rotate_method'
,
text
=
'orbit'
,
expand
=
True
)
def
process
(
self
):
pass
return
def
register
():
bpy
.
utils
.
register_class
(
Sv3DviewPropsNode
)
...
...
nodes/surface/sphere.py
Просмотр файла @
16cb41f9
...
...
@@ -7,7 +7,8 @@ from bpy.props import FloatProperty, EnumProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
zip_long_repeat
,
ensure_nesting_level
from
sverchok.utils.surface
import
SvLambertSphere
,
SvEquirectSphere
,
SvGallSphere
,
SvDefaultSphere
from
sverchok.utils.surface.sphere
import
SvLambertSphere
,
SvEquirectSphere
,
SvGallSphere
,
SvDefaultSphere
from
sverchok.utils.surface.algorithms
import
build_nurbs_sphere
class
SvSphereNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
...
...
@@ -22,7 +23,8 @@ class SvSphereNode(bpy.types.Node, SverchCustomTreeNode):
(
'DEFAULT'
,
"Default"
,
"Based on spherical coordinates"
,
0
),
(
'EQUIRECT'
,
"Equirectangular"
,
"Equirectangular (geographic) projection"
,
1
),
(
'LAMBERT'
,
"Lambert"
,
"Lambert cylindrical equal-area projection"
,
2
),
(
'GALL'
,
"Gall Stereographic"
,
"Gall stereographic projection"
,
3
)
(
'GALL'
,
"Gall Stereographic"
,
"Gall stereographic projection"
,
3
),
(
'NURBS'
,
"NURBS Sphere"
,
"NURBS Sphere"
,
4
)
]
def
update_sockets
(
self
,
context
):
...
...
@@ -79,8 +81,12 @@ class SvSphereNode(bpy.types.Node, SverchCustomTreeNode):
surface
=
SvEquirectSphere
(
np
.
array
(
center
),
radius
,
theta1
)
elif
self
.
projection
==
'LAMBERT'
:
surface
=
SvLambertSphere
(
np
.
array
(
center
),
radius
)
el
se
:
el
if
self
.
projection
==
'GALL'
:
surface
=
SvGallSphere
(
np
.
array
(
center
),
radius
)
elif
self
.
projection
==
'NURBS'
:
surface
=
build_nurbs_sphere
(
np
.
array
(
center
),
radius
)
else
:
raise
Exception
(
"Unsupported projection type"
)
surfaces_out
.
append
(
surface
)
self
.
outputs
[
'Surface'
].
sv_set
(
surfaces_out
)
...
...
nodes/viz/viewer_draw_surface.py
Просмотр файла @
16cb41f9
...
...
@@ -56,6 +56,12 @@ def draw_surfaces(context, args):
if
node
.
draw_edges
:
draw_edges
(
e_shader
,
item
.
points_list
,
item
.
edges
,
node
.
edges_line_width
,
node
.
edges_color
)
if
node
.
draw_node_lines
and
item
.
node_u_isoline_data
is
not
None
:
for
line
in
item
.
node_u_isoline_data
:
draw_edges
(
e_shader
,
line
.
points
,
line
.
edges
,
node
.
node_lines_width
,
node
.
node_lines_color
)
for
line
in
item
.
node_v_isoline_data
:
draw_edges
(
e_shader
,
line
.
points
,
line
.
edges
,
node
.
node_lines_width
,
node
.
node_lines_color
)
if
node
.
draw_control_net
and
item
.
cpts_list
is
not
None
:
draw_edges
(
e_shader
,
item
.
cpts_list
,
item
.
control_net
,
node
.
control_net_line_width
,
node
.
control_net_color
)
...
...
@@ -182,6 +188,23 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
min
=
1
,
default
=
3
,
update
=
updateNode
)
draw_node_lines
:
BoolProperty
(
name
=
"Display node lines"
,
default
=
False
,
update
=
updateNode
)
node_lines_color
:
FloatVectorProperty
(
name
=
"Node Lines Color"
,
default
=
(
0.2
,
0.0
,
0.0
,
1.0
),
size
=
4
,
min
=
0.0
,
max
=
1.0
,
subtype
=
'COLOR'
,
update
=
updateNode
)
node_lines_width
:
IntProperty
(
name
=
"Node Lines Width"
,
min
=
1
,
default
=
2
,
update
=
updateNode
)
light_vector
:
FloatVectorProperty
(
name
=
'Light Direction'
,
subtype
=
'DIRECTION'
,
min
=
0
,
max
=
1
,
size
=
3
,
default
=
(
0.2
,
0.6
,
0.4
),
update
=
updateNode
)
...
...
@@ -220,6 +243,11 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
row
.
prop
(
self
,
'control_net_color'
,
text
=
""
)
row
.
prop
(
self
,
'control_net_line_width'
,
text
=
"px"
)
row
=
grid
.
row
(
align
=
True
)
row
.
prop
(
self
,
'draw_node_lines'
,
icon
=
'EVENT_N'
,
text
=
''
)
row
.
prop
(
self
,
'node_lines_color'
,
text
=
""
)
row
.
prop
(
self
,
'node_lines_width'
,
text
=
"px"
)
row
=
layout
.
row
(
align
=
True
)
row
.
scale_y
=
4.0
if
self
.
prefs_over_sized_buttons
else
1
self
.
wrapper_tracked_ui_draw_op
(
row
,
SvBakeSurfaceOp
.
bl_idname
,
icon
=
'OUTLINER_OB_MESH'
,
text
=
"B A K E"
)
...
...
old_nodes/__init__.py
Просмотр файла @
16cb41f9
...
...
@@ -46,16 +46,16 @@ def is_old(node_info: Union[str, bpy.types.Node]):
raise
TypeError
(
f
"String or Node is expected,
{
node_info
}
is given"
)
def
mark_old
(
node
):
def
mark_old
(
node
,
text
=
"Deprecated node!"
):
"""Create a frame node around given one with deprecated label"""
if
node
.
parent
and
node
.
parent
.
label
==
"Deprecated node!"
:
if
node
.
parent
and
node
.
parent
.
label
==
text
:
return
ng
=
node
.
id_data
frame
=
ng
.
nodes
.
new
(
"NodeFrame"
)
if
node
.
parent
:
frame
.
parent
=
node
.
parent
node
.
parent
=
frame
frame
.
label
=
"Deprecated node!"
frame
.
label
=
text
frame
.
use_custom_color
=
True
frame
.
color
=
(.
8
,
0
,
0
)
frame
.
shrink
=
True
...
...
@@ -67,6 +67,22 @@ def mark_all():
if
node
.
bl_idname
in
old_bl_idnames
:
mark_old
(
node
)
def
has_old_nodes
(
tree
)
->
bool
:
"""Recursive search of deprecated nodes"""
for
n
in
tree
.
nodes
:
if
n
.
bl_idname
in
old_bl_idnames
:
return
True
elif
hasattr
(
n
,
'node_tree'
)
and
has_old_nodes
(
n
.
node_tree
):
return
True
return
False
# mark group nodes if they have deprecated nodes inside
for
node
in
(
n
for
t
in
BlTrees
().
sv_main_trees
for
n
in
t
.
nodes
):
if
not
hasattr
(
node
,
'node_tree'
):
continue
if
has_old_nodes
(
node
.
node_tree
):
mark_old
(
node
,
text
=
"Has deprecated nodes!"
)
def
register_old
(
bl_id
):
"""Register old node class"""
...
...
utils/curve/knotvector.py
Просмотр файла @
16cb41f9
...
...
@@ -96,6 +96,12 @@ def average(knotvectors):
kvs
=
np
.
array
(
knotvectors
)
return
kvs
.
mean
(
axis
=
0
)
def
calc_nodes
(
degree
,
n_cpts
,
knotvector
):
nodes
=
np
.
zeros
((
n_cpts
,))
for
i
in
range
(
n_cpts
):
nodes
[
i
]
=
knotvector
[
i
+
1
:
i
+
degree
+
1
].
mean
()
return
nodes
def
to_multiplicity
(
knot_vector
,
tolerance
=
1e-6
):
count
=
0
prev_u
=
None
...
...
utils/curve/nurbs.py
Просмотр файла @
16cb41f9
...
...
@@ -332,14 +332,8 @@ class SvNurbsCurve(SvCurve):
raise
Exception
(
"Not implemented!"
)
def
calc_greville_ts
(
self
):
cpts
=
self
.
get_control_points
()
n
=
len
(
cpts
)
p
=
self
.
get_degree
()
gps
=
np
.
zeros
((
n
,))
kv
=
self
.
get_knotvector
()
for
i
in
range
(
n
):
gps
[
i
]
=
kv
[
i
+
1
:
i
+
p
+
1
].
mean
()
return
gps
n
=
len
(
self
.
get_control_points
())
return
sv_knotvector
.
calc_nodes
(
self
.
get_degree
(),
n
,
self
.
get_knotvector
())
def
calc_greville_points
(
self
):
return
self
.
evaluate_array
(
self
.
calc_greville_ts
())
...
...
@@ -973,7 +967,7 @@ class SvGeomdlCurve(SvNurbsCurve):
r
.
u_bounds
=
self
.
u_bounds
return
r
def
remove_knot
(
self
,
u
,
count
=
1
,
target
=
None
,
if_possible
=
False
):
def
remove_knot
(
self
,
u
,
count
=
1
,
target
=
None
,
if_possible
=
False
,
tolerance
=
None
):
if
(
count
is
None
)
==
(
target
is
None
):
raise
Exception
(
"Either count or target must be specified"
)
...
...
utils/nurbs_common.py
Просмотр файла @
16cb41f9
...
...
@@ -168,7 +168,7 @@ def from_homogenous(control_points):
elif
control_points
.
ndim
==
3
:
# surface
weights
=
control_points
[:,:,
3
]
weighted
=
control_points
[:,:,
0
:
3
]
points
=
weighted
/
weights
[
np
.
newaxis
]
.
T
points
=
weighted
/
np
.
transpose
(
weights
[
np
.
newaxis
]
,
axes
=
(
1
,
2
,
0
))
return
points
,
weights
else
:
raise
Exception
(
f
"control_points have ndim=
{
control_points
.
ndim
}
, supported are only 2 and 3"
)
...
...
utils/surface/algorithms.py
Просмотр файла @
16cb41f9
...
...
@@ -30,6 +30,7 @@ from sverchok.utils.curve.algorithms import (
from
sverchok.utils.surface.core
import
SvSurface
,
UnsupportedSurfaceTypeException
from
sverchok.utils.surface.nurbs
import
SvNurbsSurface
from
sverchok.utils.surface.data
import
*
from
sverchok.utils.nurbs_common
import
SvNurbsBasisFunctions
from
sverchok.utils.logging
import
info
,
debug
class
SvInterpolatingSurface
(
SvSurface
):
...
...
@@ -1376,3 +1377,91 @@ def remove_excessive_knots(surface, direction, tolerance=1e-6):
return
surface
def
build_nurbs_sphere
(
center
,
radius
):
"""
Generate NURBS Surface representing a sphere.
Sphere is defined here as a surface of revolution of
half a circle.
"""
vectorx
=
np
.
array
([
0.0
,
0.0
,
radius
])
axis
=
np
.
array
([
0.0
,
0.0
,
1.0
])
normal
=
np
.
array
([
1.0
,
0.0
,
0.0
])
matrix
=
SvCircle
.
calc_matrix
(
normal
,
vectorx
)
matrix
=
Matrix
.
Translation
(
center
)
@
Matrix
(
matrix
).
to_4x4
()
arc
=
SvCircle
(
matrix
=
matrix
,
radius
=
radius
,
normal
=
normal
,
vectorx
=
vectorx
)
arc
.
u_bounds
=
(
0.0
,
pi
)
return
nurbs_revolution_surface
(
arc
.
to_nurbs
(),
center
,
axis
,
0
,
2
*
pi
,
global_origin
=
True
)
def
deform_nurbs_surface
(
src_surface
,
uknots
,
vknots
,
points
):
"""
Move some control points of a NURBS surface so that at
given parameter values it passes through the given points.
NB: rational surfaces are not supported yet.
Parameters:
* src_surface - SvNurbsSurface instance
* uknots, vknots - np.array of shape (n,): U and V coordinates
of points to be moved
* points: np.array of shape (n,3): desired locations of surface points.
Output:
* SvNurbsSurface instance.
"""
n
=
len
(
points
)
if
len
(
uknots
)
!=
n
or
len
(
vknots
)
!=
n
:
raise
Exception
(
"Number of points, uknots and vknots must be equal"
)
if
src_surface
.
is_rational
():
raise
UnsupportedSurfaceTypeException
(
"Rational surfaces are not supported yet"
)
ndim
=
3
knotvector_u
=
src_surface
.
get_knotvector_u
()
knotvector_v
=
src_surface
.
get_knotvector_v
()
basis_u
=
SvNurbsBasisFunctions
(
knotvector_u
)
basis_v
=
SvNurbsBasisFunctions
(
knotvector_v
)
degree_u
=
src_surface
.
get_degree_u
()
degree_v
=
src_surface
.
get_degree_v
()
ncpts_u
,
ncpts_v
,
_
=
src_surface
.
get_control_points
().
shape
nsu
=
np
.
array
([
basis_u
.
derivative
(
i
,
degree_u
,
0
)(
uknots
)
for
i
in
range
(
ncpts_u
)])
nsv
=
np
.
array
([
basis_v
.
derivative
(
i
,
degree_v
,
0
)(
vknots
)
for
i
in
range
(
ncpts_v
)])
nsu_t
=
np
.
transpose
(
nsu
[
np
.
newaxis
],
axes
=
(
1
,
0
,
2
))
# (ncpts_u, 1, n)
nsv_t
=
nsv
[
np
.
newaxis
]
# (1, ncpts_v, n)
ns_t
=
nsu_t
*
nsv_t
# (ncpts_u, ncpts_v, n)
denominator
=
ns_t
.
sum
(
axis
=
0
).
sum
(
axis
=
0
)
n_equations
=
n
*
ndim
n_unknowns
=
ncpts_u
*
ncpts_v
*
ndim
#print(f"Eqs: {n_equations}, Unk: {n_unknowns}")
A
=
np
.
zeros
((
n_equations
,
n_unknowns
))
for
u_idx
in
range
(
ncpts_u
):
for
v_idx
in
range
(
ncpts_v
):
cpt_idx
=
ncpts_v
*
u_idx
+
v_idx
for
pt_idx
in
range
(
n
):
alpha
=
nsu
[
u_idx
][
pt_idx
]
*
nsv
[
v_idx
][
pt_idx
]
/
denominator
[
pt_idx
]
for
dim_idx
in
range
(
ndim
):
A
[
ndim
*
pt_idx
+
dim_idx
,
ndim
*
cpt_idx
+
dim_idx
]
=
alpha
src_points
=
src_surface
.
evaluate_array
(
uknots
,
vknots
)
B
=
np
.
zeros
((
n_equations
,
1
))
for
pt_idx
,
point
in
enumerate
(
points
):
B
[
pt_idx
*
3
:
pt_idx
*
3
+
3
,
0
]
=
point
[
np
.
newaxis
]
-
src_points
[
pt_idx
][
np
.
newaxis
]
if
n_equations
==
n_unknowns
:
print
(
"Well-determined"
,
n_equations
)
A1
=
np
.
linalg
.
inv
(
A
)
X
=
(
A1
@
B
).
T
elif
n_equations
<
n_unknowns
:
print
(
"Underdetermined"
,
n_equations
,
n_unknowns
)
A1
=
np
.
linalg
.
pinv
(
A
)
X
=
(
A1
@
B
).
T
else
:
# n_equations > n_unknowns
print
(
"Overdetermined"
,
n_equations
,
n_unknowns
)
X
,
residues
,
rank
,
singval
=
np
.
linalg
.
lstsq
(
A
,
B
)
d_cpts
=
X
.
reshape
((
ncpts_u
,
ncpts_v
,
ndim
))
cpts
=
src_surface
.
get_control_points
()
surface
=
SvNurbsSurface
.
build
(
src_surface
.
get_nurbs_implementation
(),
degree_u
,
degree_v
,
knotvector_u
,
knotvector_v
,
cpts
+
d_cpts
)
return
surface
utils/surface/bakery.py
Просмотр файла @
16cb41f9
...
...
@@ -12,6 +12,8 @@ import bpy
from
sverchok.utils.modules.polygon_utils
import
pols_normals
from
sverchok.utils.modules.vertex_utils
import
np_vertex_normals
from
sverchok.utils.math
import
np_dot
from
sverchok.utils.curve.algorithms
import
SvIsoUvCurve
from
sverchok.utils.curve.bakery
import
CurveData
def
make_quad_edges
(
n_u
,
n_v
):
edges
=
[]
...
...
@@ -87,6 +89,14 @@ def calc_surface_data(light_vector, surface_color, n_u, n_v, points):
return
tris
,
colors
class
SurfaceData
(
object
):
class
IsoCurveConfig
(
object
):
def
__init__
(
self
):
self
.
draw_line
=
True
self
.
draw_verts
=
False
self
.
draw_control_polygon
=
False
self
.
draw_control_points
=
False
self
.
draw_nodes
=
False
def
__init__
(
self
,
node
,
surface
,
resolution_u
,
resolution_v
):
self
.
node
=
node
self
.
surface
=
surface
...
...
@@ -111,6 +121,17 @@ class SurfaceData(object):
else
:
self
.
cpts_list
=
None
if
hasattr
(
surface
,
'calc_greville_us'
):
nodes_u
=
surface
.
calc_greville_us
()
nodes_v
=
surface
.
calc_greville_vs
()
node_u_isolines
=
[
SvIsoUvCurve
(
surface
,
'U'
,
u
)
for
u
in
nodes_u
]
node_v_isolines
=
[
SvIsoUvCurve
(
surface
,
'V'
,
v
)
for
v
in
nodes_v
]
cfg
=
SurfaceData
.
IsoCurveConfig
()
self
.
node_u_isoline_data
=
[
CurveData
(
cfg
,
isoline
,
resolution_v
)
for
isoline
in
node_u_isolines
]
self
.
node_v_isoline_data
=
[
CurveData
(
cfg
,
isoline
,
resolution_u
)
for
isoline
in
node_v_isolines
]
else
:
self
.
node_u_isoline_data
=
node_v_isoline_data
=
None
self
.
edges
=
make_quad_edges
(
resolution_u
,
resolution_v
)
self
.
tris
,
self
.
tri_colors
=
calc_surface_data
(
node
.
light_vector
,
node
.
surface_color
,
resolution_u
,
resolution_v
,
self
.
points
)
...
...
utils/surface/nurbs.py
Просмотр файла @
16cb41f9
...
...
@@ -119,6 +119,23 @@ class SvNurbsSurface(SvSurface):
def
iso_curve
(
self
,
fixed_direction
,
param
):
raise
Exception
(
"Not implemented"
)
def
is_rational
(
self
,
tolerance
=
1e-4
):
weights
=
self
.
get_weights
()
w
,
W
=
weights
.
min
(),
weights
.
max
()
return
(
W
-
w
)
>
tolerance
def
calc_greville_us
(
self
):
n
=
self
.
get_control_points
().
shape
[
0
]
p
=
self
.
get_degree_u
()
kv
=
self
.
get_knotvector_u
()
return
sv_knotvector
.
calc_nodes
(
p
,
n
,
kv
)
def
calc_greville_vs
(
self
):
n
=
self
.
get_control_points
().
shape
[
1
]
p
=
self
.
get_degree_v
()
kv
=
self
.
get_knotvector_v
()
return
sv_knotvector
.
calc_nodes
(
p
,
n
,
kv
)
def
get_homogenous_control_points
(
self
):
"""
...
...
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать