Skip to content

Commit

Permalink
New nodes (sphere and torus) new fetures (UVW segmentation) and numer…
Browse files Browse the repository at this point in the history
…ous bug fixes
  • Loading branch information
wassimj committed May 29, 2022
1 parent dd01d17 commit a59f48a
Show file tree
Hide file tree
Showing 45 changed files with 492 additions and 2,449 deletions.
6 changes: 5 additions & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
bl_info = {
"name": "Topologic",
"author": "Wassim Jabi",
"version": (0, 8, 1, 5),
"version": (0, 8, 1, 6),
"blender": (3, 1, 0),
"location": "Node Editor",
"category": "Node",
Expand Down Expand Up @@ -138,8 +138,10 @@ def nodes_index():
("Topologic.CellPipe", "SvCellPipe"),
("Topologic.CellPrism", "SvCellPrism"),
("Topologic.CellSets", "SvCellSets"),
("Topologic.CellSphere", "SvCellSphere"),
("Topologic.CellSuperCells", "SvCellSuperCells"),
("Topologic.CellSurfaceArea", "SvCellSurfaceArea"),
("Topologic.CellTorus", "SvCellTorus"),
("Topologic.CellVolume", "SvCellVolume"),
("Topologic.CellComplexByFaces", "SvCellComplexByFaces"),
("Topologic.CellComplexByCells", "SvCellComplexByCells"),
Expand Down Expand Up @@ -606,8 +608,10 @@ def draw(self, context):
['SvCellPipe'],
['SvCellPrism'],
['SvCellSets'],
['SvCellSphere'],
['SvCellSuperCells'],
['SvCellSurfaceArea'],
['SvCellTorus'],
['SvCellVolume'],
])

Expand Down
48 changes: 32 additions & 16 deletions nodes/Topologic/CellByLoft.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import topologic
from topologic import Vertex, Edge, Wire, Face, Shell, Cell, CellComplex, Cluster, Topology

from . import CellByFaces
from . import Replication, CellByFaces

# From https://stackabuse.com/python-how-to-flatten-list-of-lists/
def flatten(element):
Expand All @@ -18,18 +18,19 @@ def flatten(element):
returnList = [element]
return returnList

def processItem(item, tol):
faces = [topologic.Face.ByExternalBoundary(item[0])]
faces.append(topologic.Face.ByExternalBoundary(item[-1]))
for i in range(len(item)-1):
wire1 = item[i]
wire2 = item[i+1]
def processItem(item):
wires, tolerance = item
faces = [topologic.Face.ByExternalBoundary(wires[0])]
faces.append(topologic.Face.ByExternalBoundary(wires[-1]))
for i in range(len(wires)-1):
wire1 = wires[i]
wire2 = wires[i+1]
w1_edges = []
_ = wire1.Edges(None, w1_edges)
w2_edges = []
_ = wire2.Edges(None, w2_edges)
if len(w1_edges) != len(w2_edges):
raise Exception("Shell.ByLoft - Error: The two wires do not have the same number of edges.")
raise Exception("Cell.ByLoft - Error: The two wires do not have the same number of edges.")
for j in range (len(w1_edges)):
e1 = w1_edges[j]
e2 = w2_edges[j]
Expand All @@ -50,10 +51,11 @@ def processItem(item, tol):
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e5, e4])))
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e2, e5, e3])))
try:
return CellByFaces.processItem(faces, tol)
return CellByFaces.processItem(faces, tolerance)
except:
return topologic.Cluster.ByTopologies(faces)

replication = [("Trim", "Trim", "", 1),("Iterate", "Iterate", "", 2),("Repeat", "Repeat", "", 3),("Interlace", "Interlace", "", 4)]

class SvCellByLoft(bpy.types.Node, SverchCustomTreeNode):
"""
Expand All @@ -62,23 +64,37 @@ class SvCellByLoft(bpy.types.Node, SverchCustomTreeNode):
"""
bl_idname = 'SvCellByLoft'
bl_label = 'Cell.ByLoft'
Tol: FloatProperty(name='Tol', default=0.0001, precision=4, update=updateNode)
Tolerance: FloatProperty(name="Tolerance", default=0.0001, precision=4, update=updateNode)
Replication: EnumProperty(name="Replication", description="Replication", default="Iterate", items=replication, update=updateNode)

def sv_init(self, context):
self.inputs.new('SvStringsSocket', 'Wires')
self.inputs.new('SvStringsSocket', 'Tol').prop_name='Tol'
self.inputs.new('SvStringsSocket', 'Tolerance').prop_name = 'Tolerance'
self.outputs.new('SvStringsSocket', 'Cell')

def process(self):
if not any(socket.is_linked for socket in self.outputs):
return
wiresList = self.inputs['Wires'].sv_get(deepcopy=False)
tol = self.inputs['Tol'].sv_get(deepcopy=True, default=0.0001)[0][0]
if isinstance(wiresList[0], list) == False:
wiresList = self.inputs['Wires'].sv_get(deepcopy=True)
if not isinstance(wiresList[0], list):
wiresList = [wiresList]
toleranceList = self.inputs['Tolerance'].sv_get(deepcopy=True)
toleranceList = Replication.flatten(toleranceList)
inputs = [wiresList, toleranceList]
if ((self.Replication) == "Trim"):
inputs = Replication.trim(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Iterate"):
inputs = Replication.iterate(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Repeat"):
inputs = Replication.repeat(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Interlace"):
inputs = list(Replication.interlace(inputs))
outputs = []
for wireList in wiresList:
outputs.append(processItem(wireList, tol))
for anInput in inputs:
outputs.append(processItem(anInput))
self.outputs['Cell'].sv_set(outputs)

def register():
Expand Down
42 changes: 29 additions & 13 deletions nodes/Topologic/CellComplexByLoft.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import topologic
from topologic import Vertex, Edge, Wire, Face, Shell, Cell, CellComplex, Cluster, Topology
from . import CellComplexByFaces
from . import Replication, CellComplexByFaces

# From https://stackabuse.com/python-how-to-flatten-list-of-lists/
def flatten(element):
Expand All @@ -17,11 +17,12 @@ def flatten(element):
returnList = [element]
return returnList

def processItem(item, tol):
faces = [topologic.Face.ByExternalBoundary(item[0])]
for i in range(len(item)-1):
wire1 = item[i]
wire2 = item[i+1]
def processItem(item):
wires, tolerance = item
faces = [topologic.Face.ByExternalBoundary(wires[0])]
for i in range(len(wires)-1):
wire1 = wires[i]
wire2 = wires[i+1]
faces.append(topologic.Face.ByExternalBoundary(wire2))
w1_edges = []
_ = wire1.Edges(None, w1_edges)
Expand Down Expand Up @@ -54,7 +55,9 @@ def processItem(item, tol):
e5 = topologic.Edge.ByStartVertexEndVertex(e1.StartVertex(), e2.EndVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e5, e4])))
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e2, e5, e3])))
return CellComplexByFaces.processItem(faces, tol)
return CellComplexByFaces.processItem(faces, tolerance)

replication = [("Trim", "Trim", "", 1),("Iterate", "Iterate", "", 2),("Repeat", "Repeat", "", 3),("Interlace", "Interlace", "", 4)]

class SvCellComplexByLoft(bpy.types.Node, SverchCustomTreeNode):
"""
Expand All @@ -63,23 +66,36 @@ class SvCellComplexByLoft(bpy.types.Node, SverchCustomTreeNode):
"""
bl_idname = 'SvCellComplexByLoft'
bl_label = 'CellComplex.ByLoft'
Tol: FloatProperty(name='Tol', default=0.0001, precision=4, update=updateNode)
Tolerance: FloatProperty(name="Tolerance", default=0.0001, precision=4, update=updateNode)
Replication: EnumProperty(name="Replication", description="Replication", default="Iterate", items=replication, update=updateNode)

def sv_init(self, context):
self.inputs.new('SvStringsSocket', 'Wires')
self.inputs.new('SvStringsSocket', 'Tol').prop_name='Tol'
self.inputs.new('SvStringsSocket', 'Tolerance').prop_name = 'Tolerance'
self.outputs.new('SvStringsSocket', 'CellComplex')

def process(self):
if not any(socket.is_linked for socket in self.outputs):
return
wiresList = self.inputs['Wires'].sv_get(deepcopy=False)
if isinstance(wiresList[0], list) == False:
if not isinstance(wiresList[0], list):
wiresList = [wiresList]
tol = self.inputs['Tol'].sv_get(deepcopy=True, default=0.0001)[0][0]
toleranceList = Replication.flatten(toleranceList)
inputs = [wiresList, toleranceList]
if ((self.Replication) == "Trim"):
inputs = Replication.trim(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Iterate"):
inputs = Replication.iterate(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Repeat"):
inputs = Replication.repeat(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Interlace"):
inputs = list(Replication.interlace(inputs))
outputs = []
for wireList in wiresList:
outputs.append(processItem(wireList, tol))
for anInput in inputs:
outputs.append(processItem(anInput))
self.outputs['CellComplex'].sv_set(outputs)

def register():
Expand Down
94 changes: 56 additions & 38 deletions nodes/Topologic/CellCylinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import topologic
from topologic import Vertex, Edge, Wire, Face, Shell, Cell, CellComplex, Cluster, Topology
import math
from . import Replication, CellByLoft

def wireByVertices(vList):
edges = []
Expand All @@ -31,13 +32,15 @@ def wireByVertices(vList):
return topologic.Wire.ByEdges(edges)

def processItem(item, originLocation):
origin = item[0]
radius = item[1]
height = item[2]
sides = item[3]
dirX = item[4]
dirY = item[5]
dirZ = item[6]
origin, \
radius, \
height, \
uSides, \
vSides, \
dirX, \
dirY, \
dirZ, \
tolerance = item
baseV = []
topV = []
xOffset = 0
Expand All @@ -49,18 +52,20 @@ def processItem(item, originLocation):
xOffset = radius
yOffset = radius

for i in range(sides):
angle = math.radians(360/sides)*i
for i in range(uSides):
angle = math.radians(360/uSides)*i
x = math.sin(angle)*radius + origin.X() + xOffset
y = math.cos(angle)*radius + origin.Y() + yOffset
z = origin.Z() + zOffset
baseV.append(topologic.Vertex.ByCoordinates(x,y,z))
topV.append(topologic.Vertex.ByCoordinates(x,y,z+height))

baseWire = wireByVertices(baseV)
topWire = wireByVertices(topV)
wires = [baseWire, topWire]
cyl = topologic.CellUtility.ByLoft(wires)
topologies = []
for i in range(vSides+1):
topologies.append(topologic.TopologyUtility.Translate(baseWire, 0, 0, height/float(vSides)*i))
cyl = CellByLoft.processItem([topologies, tolerance])

x1 = origin.X()
y1 = origin.Y()
z1 = origin.Z()
Expand All @@ -78,24 +83,11 @@ def processItem(item, originLocation):
theta = math.degrees(math.acos(dz/dist)) # Rotation around Z-Axis
cyl = topologic.TopologyUtility.Rotate(cyl, origin, 0, 1, 0, theta)
cyl = topologic.TopologyUtility.Rotate(cyl, origin, 0, 0, 1, phi)
return topologic.CellUtility.ByLoft(wires)
return cyl

def matchLengths(list):
maxLength = len(list[0])
for aSubList in list:
newLength = len(aSubList)
if newLength > maxLength:
maxLength = newLength
for anItem in list:
if (len(anItem) > 0):
itemToAppend = anItem[-1]
else:
itemToAppend = None
for i in range(len(anItem), maxLength):
anItem.append(itemToAppend)
return list

originLocations = [("Bottom", "Bottom", "", 1),("Center", "Center", "", 2),("LowerLeft", "LowerLeft", "", 3)]
replication = [("Trim", "Trim", "", 1),("Iterate", "Iterate", "", 2),("Repeat", "Repeat", "", 3),("Interlace", "Interlace", "", 4)]

class SvCellCylinder(bpy.types.Node, SverchCustomTreeNode):
"""
Expand All @@ -106,20 +98,25 @@ class SvCellCylinder(bpy.types.Node, SverchCustomTreeNode):
bl_label = 'Cell.Cylinder'
Radius: FloatProperty(name="Radius", default=1, min=0.0001, precision=4, update=updateNode)
Height: FloatProperty(name="Height", default=1, min=0.0001, precision=4, update=updateNode)
Sides: IntProperty(name="Sides", default=16, min=3, max=360, update=updateNode)
USides: IntProperty(name="U Sides", default=16, min=3, update=updateNode)
VSides: IntProperty(name="V Sides", default=1, min=1, update=updateNode)
DirX: FloatProperty(name="Dir X", default=0, precision=4, update=updateNode)
DirY: FloatProperty(name="Dir Y", default=0, precision=4, update=updateNode)
DirZ: FloatProperty(name="Dir Z", default=1, precision=4, update=updateNode)
originLocation: EnumProperty(name="originLocation", description="Specify origin location", default="Bottom", items=originLocations, update=updateNode)
Tolerance: FloatProperty(name="Tolerance", default=0.0001, precision=4, update=updateNode)
Replication: EnumProperty(name="Replication", description="Replication", default="Iterate", items=replication, update=updateNode)

def sv_init(self, context):
self.inputs.new('SvStringsSocket', 'Origin')
self.inputs.new('SvStringsSocket', 'Radius').prop_name = 'Radius'
self.inputs.new('SvStringsSocket', 'Height').prop_name = 'Height'
self.inputs.new('SvStringsSocket', 'Sides').prop_name = 'Sides'
self.inputs.new('SvStringsSocket', 'U Sides').prop_name = 'USides'
self.inputs.new('SvStringsSocket', 'V Sides').prop_name = 'VSides'
self.inputs.new('SvStringsSocket', 'Dir X').prop_name = 'DirX'
self.inputs.new('SvStringsSocket', 'Dir Y').prop_name = 'DirY'
self.inputs.new('SvStringsSocket', 'Dir Z').prop_name = 'DirZ'
self.inputs.new('SvStringsSocket', 'Tolerance').prop_name='Tolerance'
self.outputs.new('SvStringsSocket', 'Cell')

def draw_buttons(self, context, layout):
Expand All @@ -132,16 +129,37 @@ def process(self):
originList = [topologic.Vertex.ByCoordinates(0,0,0)]
else:
originList = self.inputs['Origin'].sv_get(deepcopy=True)
radiusList = self.inputs['Radius'].sv_get(deepcopy=True)[0]
heightList = self.inputs['Height'].sv_get(deepcopy=True)[0]
sidesList = self.inputs['Sides'].sv_get(deepcopy=True)[0]
dirXList = self.inputs['Dir X'].sv_get(deepcopy=True)[0]
dirYList = self.inputs['Dir Y'].sv_get(deepcopy=True)[0]
dirZList = self.inputs['Dir Z'].sv_get(deepcopy=True)[0]
matchLengths([originList, radiusList, heightList, sidesList, dirXList, dirYList, dirZList])
newInputs = zip(originList, radiusList, heightList, sidesList, dirXList, dirYList, dirZList)
originList = Replication.flatten(originList)
radiusList = self.inputs['Radius'].sv_get(deepcopy=True)
heightList = self.inputs['Height'].sv_get(deepcopy=True)
uSidesList = self.inputs['U Sides'].sv_get(deepcopy=True)
vSidesList = self.inputs['V Sides'].sv_get(deepcopy=True)
dirXList = self.inputs['Dir X'].sv_get(deepcopy=True)
dirYList = self.inputs['Dir Y'].sv_get(deepcopy=True)
dirZList = self.inputs['Dir Z'].sv_get(deepcopy=True)
toleranceList = self.inputs['Tolerance'].sv_get(deepcopy=True)
radiusList = Replication.flatten(radiusList)
heightList = Replication.flatten(heightList)
uSidesList = Replication.flatten(uSidesList)
vSidesList = Replication.flatten(vSidesList)
dirXList = Replication.flatten(dirXList)
dirYList = Replication.flatten(dirYList)
dirZList = Replication.flatten(dirZList)
toleranceList = Replication.flatten(toleranceList)
inputs = [originList, radiusList, heightList, uSidesList, vSidesList, dirXList, dirYList, dirZList, toleranceList]
if ((self.Replication) == "Trim"):
inputs = Replication.trim(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Iterate"):
inputs = Replication.iterate(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Repeat"):
inputs = Replication.repeat(inputs)
inputs = Replication.transposeList(inputs)
elif ((self.Replication) == "Interlace"):
inputs = list(Replication.interlace(inputs))
outputs = []
for anInput in newInputs:
for anInput in inputs:
outputs.append(processItem(anInput, self.originLocation))
self.outputs['Cell'].sv_set(outputs)

Expand Down
Loading

0 comments on commit a59f48a

Please sign in to comment.