Открыть боковую панель
nikitronn
sverchok
Коммиты
6b09bd34
Не подтверждена
Коммит
6b09bd34
создал
Апр 12, 2022
по автору
nikitron
Зафиксировано автором
GitHub
Апр 12, 2022
Просмотр файлов
Merge pull request #3674 from rastart/master
add FCStd read and write nodes
владельцы
6be04f3e
9cd424ad
Изменения
11
Скрыть пробелы
Построчно
Рядом
docs/nodes/exchange/FCStd_read.rst
0 → 100644
Просмотр файла @
6b09bd34
FCStd Read (Exchange)
===========
Functionality
-------------
Parameters
----------
Inputs
------
Outputs
-------
Examples
--------
docs/nodes/exchange/FCStd_sketch.rst
0 → 100644
Просмотр файла @
6b09bd34
FCStd Sketch (Exchange)
===========
Functionality
-------------
Parameters
----------
Inputs
------
Outputs
-------
Examples
--------
\ No newline at end of file
docs/nodes/exchange/FCStd_spreadsheet.rst
0 → 100644
Просмотр файла @
6b09bd34
FCStd Spreadsheet (Exchange)
===========
Functionality
-------------
Parameters
----------
Inputs
------
Outputs
-------
Examples
--------
\ No newline at end of file
docs/nodes/exchange/FCStd_write.rst
0 → 100644
Просмотр файла @
6b09bd34
FCStd Write (Exchange)
===========
Functionality
-------------
Parameters
----------
Inputs
------
Outputs
-------
Examples
--------
\ No newline at end of file
docs/nodes/exchange/exchange_index.rst
Просмотр файла @
6b09bd34
...
@@ -10,4 +10,8 @@ Exchange
...
@@ -10,4 +10,8 @@ Exchange
bezier_in
bezier_in
nurbs_in
nurbs_in
receive_from_sorcar
receive_from_sorcar
gcode_exporter
FCStd_sketch
\ No newline at end of file
FCStd_spreadsheet
FCStd_write
FCStd_read
gcode_exporter
index.md
Просмотр файла @
6b09bd34
...
@@ -675,7 +675,12 @@
...
@@ -675,7 +675,12 @@
SvExportSolidNode
SvExportSolidNode
SvReceiveFromSorcarNode
SvReceiveFromSorcarNode
SvExportGcodeNode
SvExportGcodeNode
SvReadFCStdNode
SvWriteFCStdNode
SvReadFCStdSketchNode
SvFCStdSpreadsheetNode
SvApproxSubdtoNurbsNode
## Script
## Script
SvFormulaNodeMk5
SvFormulaNodeMk5
SvFormulaInterpolateNode
SvFormulaInterpolateNode
...
...
nodes/exchange/FCStd_read.py
0 → 100644
Просмотр файла @
6b09bd34
from
sverchok.dependencies
import
FreeCAD
from
sverchok.utils.dummy_nodes
import
add_dummy
from
sverchok.utils.sv_operator_mixins
import
SvGenericNodeLocator
if
FreeCAD
is
None
:
add_dummy
(
'SvReadFCStdNode'
,
'SvReadFCStdNode'
,
'FreeCAD'
)
else
:
F
=
FreeCAD
import
bpy
from
bpy.props
import
StringProperty
,
BoolProperty
,
EnumProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
from
sverchok.utils.logging
import
info
class
SvReadFCStdOperator
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_read_fcstd_operator"
bl_label
=
"read freecad file"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
def
execute
(
self
,
context
):
node
=
self
.
get_node
(
context
)
if
not
node
:
return
{
'CANCELLED'
}
if
not
any
(
socket
.
is_linked
for
socket
in
node
.
outputs
):
return
{
'CANCELLED'
}
if
not
node
.
inputs
[
'File Path'
].
is_linked
:
return
{
'CANCELLED'
}
node
.
read_FCStd
(
node
)
updateNode
(
node
,
context
)
return
{
'FINISHED'
}
class
SvReadFCStdNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: Read FreeCAD file
Tooltip: import parts from a .FCStd file
"""
bl_idname
=
'SvReadFCStdNode'
bl_label
=
'Read FCStd'
bl_icon
=
'IMPORT'
solid_catergory
=
"Outputs"
read_update
:
BoolProperty
(
name
=
"read_update"
,
default
=
True
)
read_body
:
BoolProperty
(
name
=
"read_body"
,
default
=
True
,
update
=
updateNode
)
read_part
:
BoolProperty
(
name
=
"read_part"
,
default
=
True
,
update
=
updateNode
)
tool_parts
:
BoolProperty
(
name
=
"tool_parts"
,
default
=
False
,
update
=
updateNode
)
read_features
:
BoolProperty
(
name
=
"read_features"
,
default
=
False
,
update
=
updateNode
)
inv_filter
:
BoolProperty
(
name
=
"inv_filter"
,
default
=
False
,
update
=
updateNode
)
selected_label
:
StringProperty
(
default
=
'Select FC Part'
)
selected_part
:
StringProperty
(
default
=
''
,
update
=
updateNode
)
def
draw_buttons
(
self
,
context
,
layout
):
col
=
layout
.
column
(
align
=
True
)
if
self
.
inputs
[
'File Path'
].
is_linked
:
self
.
wrapper_tracked_ui_draw_op
(
col
,
SvShowFcstdNamesOp
.
bl_idname
,
icon
=
'TRIA_DOWN'
,
text
=
self
.
selected_label
)
col
.
prop
(
self
,
'read_update'
,
text
=
'global update'
)
col
.
prop
(
self
,
'read_body'
)
col
.
prop
(
self
,
'read_part'
)
col
.
prop
(
self
,
'tool_parts'
)
if
self
.
tool_parts
:
col
.
prop
(
self
,
'read_features'
)
col
.
prop
(
self
,
'inv_filter'
)
self
.
wrapper_tracked_ui_draw_op
(
layout
,
SvReadFCStdOperator
.
bl_idname
,
icon
=
'FILE_REFRESH'
,
text
=
"UPDATE"
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvFilePathSocket'
,
"File Path"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Part Filter"
)
self
.
outputs
.
new
(
'SvSolidSocket'
,
"Solid"
)
def
read_FCStd
(
self
,
node
):
files
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
part_filter
=
[]
if
node
.
inputs
[
'Part Filter'
].
is_linked
:
part_filter
=
node
.
inputs
[
'Part Filter'
].
sv_get
()[
0
]
if
node
.
selected_part
!=
''
and
not
node
.
selected_part
in
part_filter
:
part_filter
.
append
(
node
.
selected_part
)
solids
=
[]
obj_mask
=
[]
if
node
.
read_features
:
obj_mask
.
append
(
'PartDesign'
)
if
node
.
read_part
:
obj_mask
.
append
(
'Part'
)
if
node
.
read_body
:
obj_mask
.
append
(
'PartDesign::Body'
)
for
f
in
files
:
S
=
LoadSolid
(
f
,
part_filter
,
obj_mask
,
node
.
tool_parts
,
node
.
inv_filter
)
for
s
in
S
:
solids
.
append
(
s
)
node
.
outputs
[
'Solid'
].
sv_set
(
solids
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
return
if
not
self
.
inputs
[
'File Path'
].
is_linked
:
return
if
self
.
read_update
:
self
.
read_FCStd
(
self
)
else
:
return
class
SvShowFcstdNamesOp
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_show_fcstd_names"
bl_label
=
"Show parts list"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
bl_property
=
"option"
def
LabelReader
(
self
,
context
):
labels
=
[(
''
,
''
,
''
)]
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
fc_file_list
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
obj_mask
=
[]
if
node
.
read_features
:
obj_mask
.
append
(
'PartDesign'
)
if
node
.
read_part
:
obj_mask
.
append
(
'Part'
)
if
node
.
read_body
:
obj_mask
.
append
(
'PartDesign::Body'
)
for
f
in
fc_file_list
:
try
:
F
.
open
(
f
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
f
)
F
.
setActiveDocument
(
Fname
)
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Module
in
obj_mask
or
obj
.
TypeId
in
obj_mask
:
labels
.
append
(
(
obj
.
Label
,
obj
.
Label
,
obj
.
Label
)
)
except
:
info
(
'FCStd label read error'
)
finally
:
F
.
closeDocument
(
Fname
)
return
labels
option
:
EnumProperty
(
items
=
LabelReader
)
tree_name
:
StringProperty
()
node_name
:
StringProperty
()
def
execute
(
self
,
context
):
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
node
.
name_filter
=
self
.
option
node
.
selected_label
=
self
.
option
node
.
selected_part
=
self
.
option
bpy
.
context
.
area
.
tag_redraw
()
return
{
'FINISHED'
}
def
invoke
(
self
,
context
,
event
):
context
.
space_data
.
cursor_location_from_region
(
event
.
mouse_region_x
,
event
.
mouse_region_y
)
wm
=
context
.
window_manager
wm
.
invoke_search_popup
(
self
)
return
{
'FINISHED'
}
def
LoadSolid
(
fc_file
,
part_filter
,
obj_mask
,
tool_parts
,
inv_filter
):
objs
=
set
()
outList
=
set
()
solids
=
set
()
try
:
F
.
open
(
fc_file
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
fc_file
)
F
.
setActiveDocument
(
Fname
)
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Module
in
obj_mask
or
obj
.
TypeId
in
obj_mask
:
objs
.
add
(
obj
)
if
not
tool_parts
and
obj
.
TypeId
in
(
'Part::Cut'
,
'Part::Fuse'
,
'Part::MultiCommon'
,
'Part::Section'
,
'Part::FeaturePython'
):
if
len
(
obj
.
OutList
)
>
0
:
for
out_obj
in
obj
.
OutList
:
outList
.
add
(
out_obj
)
objs
=
objs
-
outList
for
obj
in
objs
:
if
not
inv_filter
:
if
obj
.
Label
in
part_filter
or
len
(
part_filter
)
==
0
:
solids
.
add
(
obj
.
Shape
)
else
:
if
not
obj
.
Label
in
part_filter
:
solids
.
add
(
obj
.
Shape
)
except
:
info
(
'FCStd read error'
)
finally
:
F
.
closeDocument
(
Fname
)
return
solids
def
open_fc_file
(
fc_file
):
F
.
open
(
fc_file
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
fc_file
)
F
.
setActiveDocument
(
Fname
)
def
register
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
register_class
(
SvReadFCStdNode
)
bpy
.
utils
.
register_class
(
SvShowFcstdNamesOp
)
bpy
.
utils
.
register_class
(
SvReadFCStdOperator
)
def
unregister
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvReadFCStdNode
)
bpy
.
utils
.
unregister_class
(
SvShowFcstdNamesOp
)
bpy
.
utils
.
register_class
(
SvReadFCStdOperator
)
\ No newline at end of file
nodes/exchange/FCStd_sketch.py
0 → 100644
Просмотр файла @
6b09bd34
from
sverchok.dependencies
import
FreeCAD
from
sverchok.utils.dummy_nodes
import
add_dummy
import
mathutils
from
sverchok.utils.sv_operator_mixins
import
SvGenericNodeLocator
if
FreeCAD
is
None
:
add_dummy
(
'SvReadFCStdSketchNode'
,
'SvReadFCStdSketchNode'
,
'FreeCAD'
)
else
:
F
=
FreeCAD
import
bpy
import
numpy
as
np
from
bpy.props
import
StringProperty
,
IntProperty
,
BoolProperty
,
EnumProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
from
sverchok.utils.logging
import
info
class
SvReadFCStdSketchOperator
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_read_fcstd_sketch_operator"
bl_label
=
"read freecad sketch"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
def
execute
(
self
,
context
):
node
=
self
.
get_node
(
context
)
if
not
node
:
return
{
'CANCELLED'
}
node
.
read_sketch
(
node
)
updateNode
(
node
,
context
)
return
{
'FINISHED'
}
class
SvReadFCStdSketchNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: Read FreeCAD file
Tooltip: import parts from a .FCStd file
"""
bl_idname
=
'SvReadFCStdSketchNode'
bl_label
=
'Read FCStd Sketches'
bl_icon
=
'IMPORT'
solid_catergory
=
"Outputs"
max_points
:
IntProperty
(
name
=
"max_points"
,
default
=
50
,
update
=
updateNode
)
read_update
:
BoolProperty
(
name
=
"read_update"
,
default
=
True
)
inv_filter
:
BoolProperty
(
name
=
"inv_filter"
,
default
=
False
,
update
=
updateNode
)
selected_label
:
StringProperty
(
default
=
'Select FC Part'
)
selected_part
:
StringProperty
(
default
=
''
,
update
=
updateNode
)
read_mode
:
EnumProperty
(
name
=
'mode'
,
description
=
'read geometry / construction'
,
items
=
[
(
'geometry'
,
'geometry'
,
'geometry'
),
(
'construction'
,
'construction'
,
'construction'
),
(
'BOTH'
,
'BOTH'
,
'BOTH'
)],
default
=
'geometry'
,
update
=
updateNode
)
def
draw_buttons
(
self
,
context
,
layout
):
col
=
layout
.
column
(
align
=
True
)
col
.
prop
(
self
,
'read_mode'
)
if
self
.
inputs
[
'File Path'
].
is_linked
:
self
.
wrapper_tracked_ui_draw_op
(
col
,
SvShowFcstdSketchNamesOp
.
bl_idname
,
icon
=
'TRIA_DOWN'
,
text
=
self
.
selected_label
)
col
.
prop
(
self
,
'max_points'
)
col
.
prop
(
self
,
'read_update'
)
col
.
prop
(
self
,
'inv_filter'
)
self
.
wrapper_tracked_ui_draw_op
(
layout
,
SvReadFCStdSketchOperator
.
bl_idname
,
icon
=
'FILE_REFRESH'
,
text
=
"UPDATE"
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvFilePathSocket'
,
"File Path"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Sketch Filter"
)
self
.
outputs
.
new
(
'SvVerticesSocket'
,
"Verts"
)
self
.
outputs
.
new
(
'SvStringsSocket'
,
"Edges"
)
self
.
outputs
.
new
(
'SvCurveSocket'
,
"Curve"
)
def
read_sketch
(
self
,
node
):
if
not
any
(
socket
.
is_linked
for
socket
in
node
.
outputs
):
return
if
not
node
.
inputs
[
'File Path'
].
is_linked
:
return
if
node
.
read_update
:
files
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
sketch_filter
=
[]
if
node
.
inputs
[
'Sketch Filter'
].
is_linked
:
sketch_filter
=
node
.
inputs
[
'Sketch Filter'
].
sv_get
()[
0
]
if
node
.
selected_part
!=
''
and
not
node
.
selected_part
in
sketch_filter
:
sketch_filter
.
append
(
node
.
selected_part
)
Verts
=
[]
Edges
=
[]
curves_out
=
[]
for
f
in
files
:
S
=
LoadSketch
(
f
,
sketch_filter
,
node
.
max_points
,
node
.
inv_filter
,
node
.
read_mode
)
for
i
in
S
[
0
]:
Verts
.
append
(
i
)
for
i
in
S
[
1
]:
Edges
.
append
(
i
)
for
i
in
S
[
2
]:
curves_out
.
append
(
i
)
node
.
outputs
[
'Verts'
].
sv_set
([
Verts
])
node
.
outputs
[
'Edges'
].
sv_set
([
Edges
])
node
.
outputs
[
'Curve'
].
sv_set
(
curves_out
)
else
:
return
def
process
(
self
):
self
.
read_sketch
(
self
)
class
SvShowFcstdSketchNamesOp
(
bpy
.
types
.
Operator
):
bl_idname
=
"node.sv_show_fcstd_sketch_names"
bl_label
=
"Show parts list"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
bl_property
=
"option"
def
LabelReader
(
self
,
context
):
labels
=
[(
''
,
''
,
''
)]
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
fc_file_list
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
try
:
for
f
in
fc_file_list
:
F
.
open
(
f
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
f
)
F
.
setActiveDocument
(
Fname
)
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Module
==
'Sketcher'
:
labels
.
append
(
(
obj
.
Label
,
obj
.
Label
,
obj
.
Label
)
)
F
.
closeDocument
(
Fname
)
except
:
info
(
'FCStd read error'
)
return
labels
option
:
EnumProperty
(
items
=
LabelReader
)
tree_name
:
StringProperty
()
node_name
:
StringProperty
()
def
execute
(
self
,
context
):
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
node
.
name_filter
=
self
.
option
node
.
selected_label
=
self
.
option
node
.
selected_part
=
self
.
option
bpy
.
context
.
area
.
tag_redraw
()
return
{
'FINISHED'
}
def
invoke
(
self
,
context
,
event
):
context
.
space_data
.
cursor_location_from_region
(
event
.
mouse_region_x
,
event
.
mouse_region_y
)
wm
=
context
.
window_manager
wm
.
invoke_search_popup
(
self
)
return
{
'FINISHED'
}
def
LoadSketch
(
fc_file
,
sketch_filter
,
max_points
,
inv_filter
,
read_mode
):
import
Part
sketches
=
[]
Verts
=
[]
Edges
=
[]
Curves
=
[]
#___________________GET FC FILE
try
:
F
.
open
(
fc_file
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
fc_file
)
F
.
setActiveDocument
(
Fname
)
except
:
info
(
'FCStd read error'
)
return
(
Verts
,
Edges
,
Curves
)
#___________________SEARCH FOR SKETCHES
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Module
==
'Sketcher'
:
if
not
inv_filter
:
if
obj
.
Label
in
sketch_filter
or
len
(
sketch_filter
)
==
0
:
sketches
.
append
(
obj
)
else
:
if
not
obj
.
Label
in
sketch_filter
:
sketches
.
append
(
obj
)
if
len
(
sketches
)
==
0
:
return
(
Verts
,
Edges
)
#__ search for max single perimeter in sketches geometry
#__ (to use as resampling reference)
max_len
=
set
()
for
s
in
sketches
:
for
g
in
s
.
Geometry
:
if
not
isinstance
(
g
,
Part
.
Point
)
:
max_len
.
add
(
g
.
length
()
)
max_len
=
max
(
max_len
)
#___________________CONVERT SKETCHES GEOMETRY
for
s
in
sketches
:
#get sketch plane placement to local - global conversion
s_placement
=
s
.
Placement
if
len
(
s
.
InList
)
>
0
:
s_placement
=
s
.
InList
[
0
].
Placement
.
multiply
(
s_placement
)
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> EVALUATE CURVE START
for
i
,
geo
in
enumerate
(
s
.
Geometry
):
if
read_mode
==
'geometry'
:
if
s
.
getConstruction
(
i
)
:
continue
#FREECAD 0.18 #if geo.Construction : continue
elif
read_mode
==
'construction'
:
if
not
s
.
getConstruction
(
i
)
:
continue
#FREECAD 0.18 #if not geo.Construction : continue
v_set
=
[]
e_set
=
[]
#LINE CASE
if
isinstance
(
geo
,
Part
.
LineSegment
):
geo_points
=
2
#POINT CASE
elif
isinstance
(
geo
,
Part
.
Point
):
geo_points
=
1
else
:
geo_points
=
int
(
max_points
*
geo
.
length
()
/
max_len
)
+
1
if
geo_points
<
2
:
geo_points
=
2
if
geo_points
!=
1
:
verts
=
geo
.
discretize
(
Number
=
geo_points
)
else
:
verts
=
[
(
geo
.
X
,
geo
.
Y
,
geo
.
Z
)
]
for
v
in
verts
:
v_co
=
F
.
Vector
(
(
v
[
0
],
v
[
1
],
v
[
2
]
)
)
abs_co
=
FreeCAD_abs_placement
(
s_placement
,
v_co
).
Base
v_set
.
append
(
(
abs_co
.
x
,
abs_co
.
y
,
abs_co
.
z
)
)
for
i
in
range
(
len
(
v_set
)
-
1
):
v_count
=
len
(
Verts
)
e_set
.
append
(
(
v_count
+
i
,
v_count
+
i
+
1
)
)
Verts
.
extend
(
v_set
)
Edges
.
extend
(
e_set
)
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< EVALUATE CURVE END
#-------------------------------------------------------------
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FC CURVE TO SV CURVE
#LINE
if
isinstance
(
geo
,
Part
.
LineSegment
):
from
sverchok.utils.curve
import
SvLine
point1
=
np
.
array
(
v_set
[
0
])
direction
=
np
.
array
(
v_set
[
1
])
-
point1
line
=
SvLine
(
point1
,
direction
)
line
.
u_bounds
=
(
0
,
1
)
Curves
.
append
(
line
)
#CIRCLE
elif
isinstance
(
geo
,
Part
.
Circle
)
or
isinstance
(
geo
,
Part
.
ArcOfCircle
):
from
sverchok.utils.curve
import
SvCircle
from
mathutils
import
Matrix
center
=
F
.
Vector
(
(
geo
.
Location
.
x
,
geo
.
Location
.
y
,
geo
.
Location
.
z
)
)
c_placement
=
FreeCAD_abs_placement
(
s_placement
,
center
)
placement_mat
=
c_placement
.
toMatrix
()
b_mat
=
Matrix
()
r
=
0
;
c
=
0
for
i
in
placement_mat
.
A
:
if
c
==
4
:
r
+=
1
;
c
=
0
b_mat
[
r
][
c
]
=
i
c
+=
1
curve
=
SvCircle
(
matrix
=
b_mat
,
radius
=
geo
.
Radius
)
if
isinstance
(
geo
,
Part
.
ArcOfCircle
):
curve
.
u_bounds
=
(
geo
.
FirstParameter
,
geo
.
LastParameter
)
Curves
.
append
(
curve
)
elif
geo_points
!=
1
:
geo
=
geo
.
toNurbs
()
from
sverchok.utils.nurbs_common
import
SvNurbsMaths
from
sverchok.utils.curve
import
SvNurbsCurve
abs_poles
=
[]
for
vec
in
geo
.
getPoles
():
abs_co
=
FreeCAD_abs_placement
(
s_placement
,
vec
).
Base
abs_poles
.
append
(
(
abs_co
.
x
,
abs_co
.
y
,
abs_co
.
z
)
)
new_curve
=
SvNurbsCurve
.
build
(
SvNurbsMaths
.
FREECAD
,
geo
.
Degree
,
geo
.
KnotSequence
,
abs_poles
,
geo
.
getWeights
()
)
Curves
.
append
(
new_curve
)
F
.
closeDocument
(
Fname
)
return
(
Verts
,
Edges
,
Curves
)
def
FC_matrix_to_mathutils_format
(
fc_matrix
):
row
=
0
col
=
0
b_matrix
=
mathutils
.
Matrix
()
for
i
in
fc_matrix
.
A
:
if
col
==
4
:
row
+=
1
;
col
=
0
b_matrix
[
row
][
col
]
=
i
col
+=
1
return
b_matrix
def
FreeCAD_abs_placement
(
sketch_placement
,
p_co
):
p_co
=
F
.
Vector
(
(
p_co
[
0
],
p_co
[
1
],
p_co
[
2
]
)
)
local_placement
=
F
.
Placement
()
local_placement
.
Base
=
p_co
return
sketch_placement
.
multiply
(
local_placement
)
def
register
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
register_class
(
SvReadFCStdSketchNode
)
bpy
.
utils
.
register_class
(
SvShowFcstdSketchNamesOp
)
bpy
.
utils
.
register_class
(
SvReadFCStdSketchOperator
)
def
unregister
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvReadFCStdSketchNode
)
bpy
.
utils
.
unregister_class
(
SvShowFcstdSketchNamesOp
)
bpy
.
utils
.
unregister_class
(
SvReadFCStdSketchOperator
)
nodes/exchange/FCStd_spreadsheet.py
0 → 100644
Просмотр файла @
6b09bd34
from
sverchok.dependencies
import
FreeCAD
from
sverchok.utils.dummy_nodes
import
add_dummy
from
sverchok.utils.sv_operator_mixins
import
SvGenericNodeLocator
if
FreeCAD
is
None
:
add_dummy
(
'SvFCStdSpreadsheetNode'
,
'SvFCStdSpreadsheetNode'
,
'FreeCAD'
)
else
:
F
=
FreeCAD
import
bpy
from
bpy.props
import
StringProperty
,
IntProperty
,
BoolProperty
,
EnumProperty
,
FloatProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
from
sverchok.utils.logging
import
info
class
SvFCStdSpreadsheetOperator
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_fcstd_spreadsheet_operator"
bl_label
=
"read/write freecad spreadsheet"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
def
execute
(
self
,
context
):
node
=
self
.
get_node
(
context
)
if
not
node
:
return
{
'CANCELLED'
}
node
.
edit_spreadsheet
(
node
)
updateNode
(
node
,
context
)
return
{
'FINISHED'
}
class
SvFCStdSpreadsheetNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: Read FreeCAD file
Tooltip: Read/write FCStd Spreadsheets from a .FCStd file
"""
bl_idname
=
'SvFCStdSpreadsheetNode'
bl_label
=
'Read/write Spreadsheets'
bl_icon
=
'IMPORT'
solid_catergory
=
"Outputs"
auto_update
:
BoolProperty
(
name
=
"auto_update"
,
default
=
True
)
write_update
:
BoolProperty
(
name
=
"read_update"
,
default
=
True
)
write_parameter
:
BoolProperty
(
name
=
"write_parameter"
,
default
=
False
)
selected_label
:
StringProperty
(
default
=
'Spreadsheet'
)
selected_sheet
:
StringProperty
(
default
=
''
,
update
=
updateNode
)
selected_par_label
:
StringProperty
(
default
=
'Parameter'
)
selected_par
:
StringProperty
(
default
=
''
,
update
=
updateNode
)
cell_in
:
FloatProperty
(
name
=
"cell_in"
,
description
=
'cell_in'
,
default
=
0.0
)
def
draw_buttons
(
self
,
context
,
layout
):
col
=
layout
.
column
(
align
=
True
)
if
self
.
inputs
[
'File Path'
].
is_linked
:
self
.
wrapper_tracked_ui_draw_op
(
col
,
SvShowFcstdSpreadsheetsOp
.
bl_idname
,
icon
=
'TRIA_DOWN'
,
text
=
self
.
selected_label
)
if
self
.
inputs
[
'File Path'
].
is_linked
:
self
.
wrapper_tracked_ui_draw_op
(
col
,
SvShowFcstdParNamesOp
.
bl_idname
,
icon
=
'TRIA_DOWN'
,
text
=
self
.
selected_par_label
)
col
.
prop
(
self
,
'auto_update'
)
col
.
prop
(
self
,
'write_parameter'
)
self
.
wrapper_tracked_ui_draw_op
(
layout
,
SvFCStdSpreadsheetOperator
.
bl_idname
,
icon
=
'FILE_REFRESH'
,
text
=
"UPDATE"
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvFilePathSocket'
,
"File Path"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"cell_in"
).
prop_name
=
'cell_in'
self
.
outputs
.
new
(
'SvStringsSocket'
,
"cell_out"
)
def
edit_spreadsheet
(
self
,
node
):
if
not
node
.
inputs
[
'File Path'
].
is_linked
:
return
if
node
.
selected_par
!=
''
:
files
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
cell_out
=
None
for
f
in
files
:
cell_out
=
WriteParameter
(
f
,
node
.
selected_sheet
,
node
.
selected_par
,
node
.
inputs
[
'cell_in'
].
sv_get
()[
0
][
0
],
node
.
write_parameter
)
if
cell_out
!=
None
:
node
.
outputs
[
'cell_out'
].
sv_set
(
[[
cell_out
]]
)
else
:
node
.
outputs
[
'cell_out'
].
sv_set
(
[
]
)
return
def
process
(
self
):
if
self
.
auto_update
:
self
.
edit_spreadsheet
(
self
)
class
SvShowFcstdSpreadsheetsOp
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_show_fcstd_spreadsheets"
bl_label
=
"Show spreadsheet list"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
bl_property
=
"option"
def
LabelReader
(
self
,
context
):
labels
=
[(
''
,
''
,
''
)]
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
fc_file_list
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
try
:
for
f
in
fc_file_list
:
F
.
open
(
f
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
f
)
F
.
setActiveDocument
(
Fname
)
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Module
==
'Spreadsheet'
:
labels
.
append
(
(
obj
.
Label
,
obj
.
Label
,
obj
.
Label
)
)
except
:
info
(
'LabelReader Spreadsheet error'
)
finally
:
F
.
closeDocument
(
Fname
)
return
labels
option
:
EnumProperty
(
items
=
LabelReader
)
tree_name
:
StringProperty
()
node_name
:
StringProperty
()
def
execute
(
self
,
context
):
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
node
.
name_filter
=
self
.
option
node
.
selected_label
=
self
.
option
node
.
selected_sheet
=
self
.
option
bpy
.
context
.
area
.
tag_redraw
()
return
{
'FINISHED'
}
def
invoke
(
self
,
context
,
event
):
context
.
space_data
.
cursor_location_from_region
(
event
.
mouse_region_x
,
event
.
mouse_region_y
)
wm
=
context
.
window_manager
wm
.
invoke_search_popup
(
self
)
return
{
'FINISHED'
}
class
SvShowFcstdParNamesOp
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_show_fcstd_par_names"
bl_label
=
"Show parameter list"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
bl_property
=
"option"
def
LabelReader
(
self
,
context
):
labels
=
[(
''
,
''
,
''
)]
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
fc_file_list
=
node
.
inputs
[
'File Path'
].
sv_get
()[
0
]
try
:
for
f
in
fc_file_list
:
F
.
open
(
f
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
f
)
F
.
setActiveDocument
(
Fname
)
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Label
==
node
.
selected_sheet
:
props
=
obj
.
PropertiesList
for
label
in
props
:
alias
=
obj
.
getCellFromAlias
(
label
)
if
alias
:
labels
.
append
(
(
label
,
label
,
label
)
)
except
:
info
(
'Label reader read cell error'
)
finally
:
F
.
closeDocument
(
Fname
)
return
labels
option
:
EnumProperty
(
items
=
LabelReader
)
tree_name
:
StringProperty
()
node_name
:
StringProperty
()
def
execute
(
self
,
context
):
tree
=
bpy
.
data
.
node_groups
[
self
.
tree_name
]
node
=
tree
.
nodes
[
self
.
node_name
]
node
.
name_filter
=
self
.
option
node
.
selected_par_label
=
self
.
option
node
.
selected_par
=
self
.
option
bpy
.
context
.
area
.
tag_redraw
()
return
{
'FINISHED'
}
def
invoke
(
self
,
context
,
event
):
context
.
space_data
.
cursor_location_from_region
(
event
.
mouse_region_x
,
event
.
mouse_region_y
)
wm
=
context
.
window_manager
wm
.
invoke_search_popup
(
self
)
return
{
'FINISHED'
}
def
WriteParameter
(
fc_file
,
spreadsheet
,
alias
,
par_write
,
write
):
#___________________GET FC FILE
try
:
F
.
open
(
fc_file
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
fc_file
)
F
.
setActiveDocument
(
Fname
)
#___________________SEARCH FOR SKETCHES
cell_out
=
None
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
obj
.
Label
==
spreadsheet
:
if
alias
in
obj
.
PropertiesList
:
cell
=
obj
.
getCellFromAlias
(
alias
)
if
write
:
obj
.
set
(
cell
,
str
(
par_write
))
F
.
ActiveDocument
.
recompute
()
F
.
getDocument
(
Fname
).
save
()
cell_out
=
obj
.
get
(
cell
)
break
except
:
info
(
'WriteParameter error'
)
finally
:
F
.
closeDocument
(
Fname
)
return
cell_out
def
register
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
register_class
(
SvFCStdSpreadsheetNode
)
bpy
.
utils
.
register_class
(
SvShowFcstdSpreadsheetsOp
)
bpy
.
utils
.
register_class
(
SvShowFcstdParNamesOp
)
bpy
.
utils
.
register_class
(
SvFCStdSpreadsheetOperator
)
def
unregister
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvFCStdSpreadsheetNode
)
bpy
.
utils
.
unregister_class
(
SvShowFcstdSpreadsheetsOp
)
bpy
.
utils
.
unregister_class
(
SvShowFcstdParNamesOp
)
bpy
.
utils
.
unregister_class
(
SvFCStdSpreadsheetOperator
)
nodes/exchange/FCStd_write.py
0 → 100644
Просмотр файла @
6b09bd34
from
sverchok.dependencies
import
FreeCAD
from
sverchok.utils.dummy_nodes
import
add_dummy
from
sverchok.utils.sv_operator_mixins
import
SvGenericNodeLocator
if
FreeCAD
is
None
:
add_dummy
(
'SvWriteFCStdNode'
,
'SvWriteFCStdNode'
,
'FreeCAD'
)
else
:
F
=
FreeCAD
import
bpy
from
bpy.props
import
StringProperty
,
BoolProperty
,
EnumProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
# OLD throttled
from
sverchok.data_structure
import
updateNode
,
match_long_repeat
# NEW throttle_and_update_node
from
sverchok.utils.logging
import
info
class
SvWriteFCStdOperator
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.sv_write_fcstd_operator"
bl_label
=
"write freecad file"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
def
execute
(
self
,
context
):
node
=
self
.
get_node
(
context
)
if
not
node
:
return
{
'CANCELLED'
}
node
.
write_FCStd
(
node
)
updateNode
(
node
,
context
)
return
{
'FINISHED'
}
class
SvWriteFCStdNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: write FreeCAD file
Tooltip: write parts in a .FCStd file
"""
bl_idname
=
'SvWriteFCStdNode'
bl_label
=
'Write FCStd'
bl_icon
=
'IMPORT'
solid_catergory
=
"Inputs"
write_update
:
BoolProperty
(
name
=
"write_update"
,
default
=
False
)
part_name
:
StringProperty
(
name
=
"part_name"
,
default
=
"part_name"
)
#@throttled
def
changeMode
(
self
,
context
):
if
self
.
obj_format
==
'mesh'
:
if
'Verts'
not
in
self
.
inputs
:
self
.
inputs
.
remove
(
self
.
inputs
[
'Solid'
])
self
.
inputs
.
new
(
'SvVerticesSocket'
,
'Verts'
)
self
.
inputs
.
new
(
'SvVerticesSocket'
,
'Faces'
)
return
else
:
if
'Solid'
not
in
self
.
inputs
:
self
.
inputs
.
remove
(
self
.
inputs
[
'Verts'
])
self
.
inputs
.
remove
(
self
.
inputs
[
'Faces'
])
self
.
inputs
.
new
(
'SvSolidSocket'
,
'Solid'
)
return
obj_format
:
EnumProperty
(
name
=
'format'
,
description
=
'choose format'
,
items
=
{
(
'solid'
,
'solid'
,
'solid'
),
(
'mesh'
,
'mesh'
,
'mesh'
)},
default
=
'solid'
,
update
=
changeMode
)
def
draw_buttons
(
self
,
context
,
layout
):
layout
.
label
(
text
=
"write name:"
)
col
=
layout
.
column
(
align
=
True
)
col
.
prop
(
self
,
'part_name'
,
text
=
""
)
col
.
prop
(
self
,
'obj_format'
,
text
=
""
)
col
.
prop
(
self
,
'write_update'
)
if
self
.
obj_format
==
'mesh'
:
col
.
label
(
text
=
"need triangle meshes"
)
self
.
wrapper_tracked_ui_draw_op
(
layout
,
SvWriteFCStdOperator
.
bl_idname
,
icon
=
'FILE_REFRESH'
,
text
=
"UPDATE"
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvFilePathSocket'
,
"File Path"
)
if
self
.
obj_format
==
'mesh'
:
self
.
inputs
.
new
(
'SvVerticesSocket'
,
"Verts"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Faces"
)
else
:
self
.
inputs
.
new
(
'SvSolidSocket'
,
'Solid'
)
def
write_FCStd
(
self
,
node
):
if
not
node
.
inputs
[
'File Path'
].
is_linked
:
return
files
=
node
.
inputs
[
'File Path'
].
sv_get
()
if
not
len
(
files
[
0
])
==
1
:
print
(
'FCStd write node support just 1 file at once'
)
return
fc_file
=
files
[
0
][
0
]
if
node
.
obj_format
==
'mesh'
:
if
any
((
node
.
inputs
[
'Verts'
].
is_linked
,
node
.
inputs
[
'Faces'
].
is_linked
)):
verts_in
=
node
.
inputs
[
'Verts'
].
sv_get
(
deepcopy
=
False
)
pols_in
=
node
.
inputs
[
'Faces'
].
sv_get
(
deepcopy
=
False
)
verts
,
pols
=
match_long_repeat
([
verts_in
,
pols_in
])
fc_write_parts
(
fc_file
,
verts
,
pols
,
node
.
part_name
,
None
,
node
.
obj_format
)
elif
node
.
obj_format
==
'solid'
:
if
node
.
inputs
[
'Solid'
].
is_linked
:
solid
=
node
.
inputs
[
'Solid'
].
sv_get
()
fc_write_parts
(
fc_file
,
None
,
None
,
node
.
part_name
,
solid
,
node
.
obj_format
)
else
:
return
def
process
(
self
):
if
self
.
write_update
:
self
.
write_FCStd
(
self
)
else
:
return
def
fc_write_parts
(
fc_file
,
verts
,
faces
,
part_name
,
solid
,
mod
):
try
:
F
.
open
(
fc_file
)
Fname
=
bpy
.
path
.
display_name_from_filepath
(
fc_file
)
except
:
info
(
'FCStd open error'
)
return
F
.
setActiveDocument
(
Fname
)
fc_root
=
F
.
getDocument
(
Fname
)
obj_names
=
set
(
[
i
.
Name
for
i
in
fc_root
.
Objects
]
)
part_name
+=
'_sv_'
#->suffix added to avoid deleting erroneusly freecad objects
# SEARCH the freecad project for previous writed parts from this node
if
part_name
in
obj_names
:
#if the part name is numberless is detected as single
fc_root
.
removeObject
(
part_name
)
else
:
for
name
in
obj_names
:
#if not, check the fc project if there are parts with same root name
if
part_name
in
name
:
fc_root
.
removeObject
(
name
)
############### if there, previous writed parts are removed ####################
############### so then write them again...
if
mod
==
'solid'
:
#EXPORT SOLID
for
i
,
s
in
enumerate
(
solid
):
new_part
=
F
.
ActiveDocument
.
addObject
(
"Part::Feature"
,
part_name
+
str
(
i
)
)
#multiple: give numbered name
new_part
.
Shape
=
s
else
:
#EXPORT MESH
import
Mesh
for
i
in
range
(
len
(
verts
)):
temp_faces
=
faces
[
i
]
temp_verts
=
verts
[
i
]
meshdata
=
[]
for
f
in
temp_faces
:
v1
,
v2
,
v3
=
f
[
0
],
f
[
1
],
f
[
2
]
meshdata
.
append
(
temp_verts
[
v1
]
)
meshdata
.
append
(
temp_verts
[
v2
]
)
meshdata
.
append
(
temp_verts
[
v3
]
)
mesh
=
Mesh
.
Mesh
(
meshdata
)
obj
=
F
.
ActiveDocument
.
addObject
(
"Mesh::Feature"
,
part_name
+
str
(
i
)
)
obj
.
Mesh
=
mesh
F
.
ActiveDocument
.
recompute
()
F
.
getDocument
(
Fname
).
save
()
F
.
closeDocument
(
Fname
)
def
register
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
register_class
(
SvWriteFCStdNode
)
bpy
.
utils
.
register_class
(
SvWriteFCStdOperator
)
def
unregister
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvWriteFCStdNode
)
bpy
.
utils
.
unregister_class
(
SvWriteFCStdOperator
)
nodes/exchange/approx_subd_to_nurbs.py
0 → 100644
Просмотр файла @
6b09bd34
import
bpy
,
bmesh
from
sverchok.dependencies
import
FreeCAD
from
sverchok.utils.dummy_nodes
import
add_dummy
from
sverchok.utils.sv_operator_mixins
import
SvGenericNodeLocator
if
FreeCAD
is
None
:
add_dummy
(
'SvReadFCStdNode'
,
'SvReadFCStdNode'
,
'FreeCAD'
)
else
:
F
=
FreeCAD
import
bpy
from
bpy.props
import
StringProperty
,
BoolProperty
,
EnumProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
from
sverchok.utils.logging
import
info
class
SvApproxSubdtoNurbsOperator
(
bpy
.
types
.
Operator
,
SvGenericNodeLocator
):
bl_idname
=
"node.approx_subd_nurbs_operator"
bl_label
=
"Approx Subd-Nurbs"
bl_options
=
{
'INTERNAL'
,
'REGISTER'
}
def
execute
(
self
,
context
):
node
=
self
.
get_node
(
context
)
if
not
node
:
return
{
'CANCELLED'
}
if
not
any
(
socket
.
is_linked
for
socket
in
node
.
outputs
):
return
{
'CANCELLED'
}
try
:
node
.
inputs
[
'Subd Obj'
].
sv_get
()[
0
]
except
:
return
{
'CANCELLED'
}
node
.
Approximate
(
node
)
updateNode
(
node
,
context
)
return
{
'FINISHED'
}
class
SvApproxSubdtoNurbsNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: Approximate Subd to Nurbs
Tooltip: Approximate Subd to Nurbs
"""
bl_idname
=
'SvApproxSubdtoNurbsNode'
bl_label
=
'Approximate Subd to Nurb'
bl_icon
=
'IMPORT'
solid_catergory
=
"Outputs"
auto_update
:
BoolProperty
(
name
=
"auto_update"
,
default
=
True
)
def
draw_buttons
(
self
,
context
,
layout
):
col
=
layout
.
column
(
align
=
True
)
col
.
prop
(
self
,
'auto_update'
,
text
=
'global update'
)
self
.
wrapper_tracked_ui_draw_op
(
layout
,
SvApproxSubdtoNurbsOperator
.
bl_idname
,
icon
=
'FILE_REFRESH'
,
text
=
"UPDATE"
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvObjectSocket'
,
"Subd Obj"
)
self
.
outputs
.
new
(
'SvSolidSocket'
,
"Solid"
)
def
Approximate
(
self
,
node
):
S
=
ApproxSubdToNurbs
(
node
.
inputs
[
'Subd Obj'
].
sv_get
()[
0
]
)
node
.
outputs
[
'Solid'
].
sv_set
(
S
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
return
try
:
self
.
inputs
[
'Subd Obj'
].
sv_get
()[
0
]
except
:
return
if
self
.
auto_update
:
self
.
Approximate
(
self
)
else
:
return
def
ApproxSubdToNurbs
(
Object
):
from
FreeCAD
import
Part
from
FreeCAD.Part
import
BSplineCurve
from
FreeCAD.Part
import
makeCompound
F
.
newDocument
(
"freecad_temp"
)
F
.
setActiveDocument
(
'freecad_temp'
)
patches
=
[]
obj
=
Object
if
obj
.
modifiers
[
0
].
levels
<=
1
:
return
[]
else
:
obj
.
modifiers
[
0
].
levels
-=
1
obj
.
modifiers
[
0
].
subdivision_type
=
"SIMPLE"
depsgraph
=
bpy
.
context
.
evaluated_depsgraph_get
()
obj
=
obj
.
evaluated_get
(
depsgraph
)
bm
=
bmesh
.
new
()
bm
.
from_mesh
(
obj
.
data
)
face_corners
=
set
()
for
f
in
bm
.
faces
:
corners
=
[]
for
l
in
f
.
loops
:
pos
=
(
l
.
vert
.
co
.
x
,
l
.
vert
.
co
.
y
,
l
.
vert
.
co
.
z
)
corners
.
append
(
pos
)
face_corners
.
add
(
tuple
(
corners
))
bm
.
free
()
obj
=
Object
obj
.
modifiers
[
0
].
levels
+=
1
depsgraph
=
bpy
.
context
.
evaluated_depsgraph_get
()
obj
=
obj
.
evaluated_get
(
depsgraph
)
bm
=
bmesh
.
new
()
bm
.
from_mesh
(
obj
.
data
)
borders
=
[]
centers
=
[]
bm
.
verts
.
ensure_lookup_table
()
bm
.
edges
.
ensure_lookup_table
()
for
quad_co
in
face_corners
:
quad
=
[]
for
co
in
quad_co
:
for
v
in
bm
.
verts
:
if
(
v
.
co
.
x
,
v
.
co
.
y
,
v
.
co
.
z
)
==
co
:
quad
.
append
(
v
.
index
)
edges
=
[]
for
i
in
range
(
4
):
j
=
0
if
i
==
3
else
i
+
1
for
vert
in
bm
.
verts
:
pool
=
set
()
for
e
in
vert
.
link_edges
:
for
v
in
e
.
verts
:
pool
.
add
(
v
.
index
)
edge
=
set
((
quad
[
i
],
quad
[
j
]))
if
edge
.
issubset
(
pool
):
edge
=
(
quad
[
i
],
vert
.
index
,
quad
[
j
]
)
edges
.
append
(
edge
)
set1
=
set
()
for
e
in
bm
.
verts
[
edges
[
0
][
1
]].
link_edges
:
for
v
in
e
.
verts
:
set1
.
add
(
v
.
index
)
set2
=
set
()
for
e
in
bm
.
verts
[
edges
[
1
][
1
]].
link_edges
:
for
v
in
e
.
verts
:
set2
.
add
(
v
.
index
)
borders
.
append
(
edges
)
centers
.
append
(
((
set1
&
set2
)
-
set
(
quad
)).
pop
()
)
obj
=
Object
obj
.
modifiers
[
0
].
subdivision_type
=
"CATMULL_CLARK"
depsgraph
=
bpy
.
context
.
evaluated_depsgraph_get
()
obj
=
obj
.
evaluated_get
(
depsgraph
)
bm
=
bmesh
.
new
()
bm
.
from_mesh
(
obj
.
data
)
bm
.
verts
.
ensure_lookup_table
()
bm
.
edges
.
ensure_lookup_table
()
v_borders
=
[]
v_centers
=
[]
for
p
in
centers
:
p
=
bm
.
verts
[
p
]
v_centers
.
append
(
(
p
.
co
.
x
,
p
.
co
.
y
,
p
.
co
.
z
)
)
for
b
in
borders
:
border
=
[]
for
e
in
b
:
edges
=
[]
for
p
in
e
:
p
=
bm
.
verts
[
p
]
edges
.
append
(
(
p
.
co
.
x
,
p
.
co
.
y
,
p
.
co
.
z
)
)
border
.
append
(
edges
)
v_borders
.
append
(
border
)
bm
.
free
()
for
i
in
range
(
len
(
centers
)):
p
=
v_borders
[
i
]
cen
=
v_centers
[
i
]
curves
=
[]
item
=
0
CEN
=
F
.
ActiveDocument
.
addObject
(
'Part::Feature'
,
'boundary_center%s'
%
item
)
CEN
.
Shape
=
Part
.
Point
(
F
.
Vector
(
cen
)
).
toShape
()
for
b
in
p
:
Points
=
[]
Points
.
append
(
F
.
Vector
(
b
[
0
])
)
Points
.
append
(
F
.
Vector
(
b
[
1
])
)
Points
.
append
(
F
.
Vector
(
b
[
2
])
)
curve
=
BSplineCurve
()
curve
.
increaseDegree
(
1
)
curve
.
interpolate
(
Points
)
curves
.
append
(
curve
)
com
=
makeCompound
([
x
.
toShape
()
for
x
in
curves
])
com_obj
=
F
.
ActiveDocument
.
addObject
(
'Part::Feature'
,
'boundary_edges%s'
%
item
)
com_obj
.
Shape
=
com
F
.
ActiveDocument
.
recompute
()
edge_names
=
[
"Edge%d"
%
(
n
+
1
)
for
n
in
range
(
len
(
com
.
Edges
))]
patch
=
F
.
ActiveDocument
.
addObject
(
"Surface::Filling"
,
"Surface%s"
%
item
)
patch
.
BoundaryEdges
=
(
com_obj
,
edge_names
)
patch
.
Points
=
(
CEN
,
"Vertex1"
)
F
.
ActiveDocument
.
recompute
()
item
+=
1
F
.
ActiveDocument
.
recompute
()
SURFS
=
[]
for
obj
in
F
.
ActiveDocument
.
Objects
:
if
'Surface'
in
obj
.
Name
:
SURFS
.
append
(
obj
)
F
.
activeDocument
().
addObject
(
"Part::Compound"
,
"Compound"
)
COMPOUND
=
F
.
ActiveDocument
.
getObject
(
"Compound"
)
COMPOUND
.
Links
=
SURFS
F
.
ActiveDocument
.
recompute
()
COMPOUND
.
recompute
()
SHELL
=
Part
.
Solid
(
Part
.
Shell
(
COMPOUND
.
Shape
.
Faces
)
)
F
.
closeDocument
(
"freecad_temp"
)
return
[
SHELL
]
def
register
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
register_class
(
SvApproxSubdtoNurbsOperator
)
bpy
.
utils
.
register_class
(
SvApproxSubdtoNurbsNode
)
def
unregister
():
if
FreeCAD
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvApproxSubdtoNurbsOperator
)
bpy
.
utils
.
unregister_class
(
SvApproxSubdtoNurbsNode
)
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать