Skip to content

Commit

Permalink
Bug fixes and new nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
wassimj committed May 26, 2022
1 parent 4d73f51 commit 45ef653
Show file tree
Hide file tree
Showing 48 changed files with 2,409 additions and 374 deletions.
519 changes: 256 additions & 263 deletions __init__.py

Large diffs are not rendered by default.

Binary file modified examples/TopologicEnergy/TopologicBuildingWithDictionaries.blend
Binary file not shown.
Binary file modified examples/TopologicEnergy/TopologicBuildingWithDictionaries.blend1
Binary file not shown.
14 changes: 10 additions & 4 deletions nodes/Topologic/CellComplexByLoft.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ def processItem(item, tol):
try:
e3 = topologic.Edge.ByStartVertexEndVertex(e1.StartVertex(), e2.StartVertex())
except:
e4 = topologic.Edge.ByStartVertexEndVertex(e1.EndVertex(), e2.EndVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e2, e4])))
try:
e4 = topologic.Edge.ByStartVertexEndVertex(e1.EndVertex(), e2.EndVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e2, e4])))
except:
pass
try:
e4 = topologic.Edge.ByStartVertexEndVertex(e1.EndVertex(), e2.EndVertex())
except:
e3 = topologic.Edge.ByStartVertexEndVertex(e1.StartVertex(), e2.StartVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e2, e3])))
try:
e3 = topologic.Edge.ByStartVertexEndVertex(e1.StartVertex(), e2.StartVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e2, e3])))
except:
pass
if e3 and e4:
e5 = topologic.Edge.ByStartVertexEndVertex(e1.StartVertex(), e2.EndVertex())
faces.append(topologic.Face.ByExternalBoundary(topologic.Wire.ByEdges([e1, e5, e4])))
Expand Down
52 changes: 37 additions & 15 deletions nodes/Topologic/CellPipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,27 +123,33 @@ def processItem(item):
endcapA = item[5]
endcapB = item[6]

length = topologic.EdgeUtility.Length(edge)
origin = edge.StartVertex()
x1 = origin.X()
y1 = origin.Y()
z1 = origin.Z()
x2 = edge.EndVertex().X()
y2 = edge.EndVertex().Y()
z2 = edge.EndVertex().Z()
startU = startOffset / length
endU = 1.0 - (endOffset / length)
sv = topologic.EdgeUtility.PointAtParameter(edge, startU)
ev = topologic.EdgeUtility.PointAtParameter(edge, endU)
new_edge = topologic.Edge.ByStartVertexEndVertex(sv, ev)
x1 = sv.X()
y1 = sv.Y()
z1 = sv.Z()
x2 = ev.X()
y2 = ev.Y()
z2 = ev.Z()
dx = x2 - x1
dy = y2 - y1
dz = z2 - z1
dz = z2 - z1
dist = math.sqrt(dx**2 + dy**2 + dz**2)

baseV = []
topV = []

for i in range(sides):
angle = math.radians(360/sides)*i
x = math.sin(angle)*radius + origin.X()
y = math.cos(angle)*radius + origin.Y()
z = origin.Z()
baseV.append(topologic.Vertex.ByCoordinates(x,y,z+startOffset))
topV.append(topologic.Vertex.ByCoordinates(x,y,z+dist-endOffset))
x = math.sin(angle)*radius + sv.X()
y = math.cos(angle)*radius + sv.Y()
z = sv.Z()
baseV.append(topologic.Vertex.ByCoordinates(x,y,z))
topV.append(topologic.Vertex.ByCoordinates(x,y,z+dist))

baseWire = wireByVertices(baseV)
topWire = wireByVertices(topV)
Expand All @@ -154,11 +160,27 @@ def processItem(item):
theta = 0
else:
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)
cyl = topologic.TopologyUtility.Rotate(cyl, sv, 0, 1, 0, theta)
cyl = topologic.TopologyUtility.Rotate(cyl, sv, 0, 0, 1, phi)
zzz = topologic.Vertex.ByCoordinates(0,0,0)
returnList = [cyl]
if endcapA:
origin = edge.StartVertex()
x1 = origin.X()
y1 = origin.Y()
z1 = origin.Z()
x2 = edge.EndVertex().X()
y2 = edge.EndVertex().Y()
z2 = edge.EndVertex().Z()
dx = x2 - x1
dy = y2 - y1
dz = z2 - z1
dist = math.sqrt(dx**2 + dy**2 + dz**2)
phi = math.degrees(math.atan2(dy, dx)) # Rotation around Y-Axis
if dist < 0.0001:
theta = 0
else:
theta = math.degrees(math.acos(dz/dist)) # Rotation around Z-Axis
endcapA = topologic.Topology.DeepCopy(endcapA)
endcapA = topologic.TopologyUtility.Rotate(endcapA, zzz, 0, 1, 0, theta)
endcapA = topologic.TopologyUtility.Rotate(endcapA, zzz, 0, 0, 1, phi + 180)
Expand Down
140 changes: 140 additions & 0 deletions nodes/Topologic/DictionaryByCustomProperties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import bpy
from bpy.props import StringProperty, BoolProperty, FloatProperty, EnumProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
import idprop

import topologic
from topologic import Vertex, Edge, Wire, Face, Shell, Cell, CellComplex, Cluster, Topology, Dictionary
import time

# From https://stackabuse.com/python-how-to-flatten-list-of-lists/
def flatten(element):
returnList = []
if isinstance(element, list) == True:
for anItem in element:
returnList = returnList + flatten(anItem)
else:
returnList = [element]
return returnList

def listAttributeValues(listAttribute):
listAttributes = listAttribute.ListValue()
returnList = []
for attr in listAttributes:
if isinstance(attr, topologic.IntAttribute):
returnList.append(attr.IntValue())
elif isinstance(attr, topologic.DoubleAttribute):
returnList.append(attr.DoubleValue())
elif isinstance(attr, topologic.StringAttribute):
returnList.append(attr.StringValue())
return returnList

def valueAtKey(item, key):
try:
attr = item.ValueAtKey(key)
except:
raise Exception("Dictionary.ValueAtKey - Error: Could not retrieve a Value at the specified key ("+key+")")
if isinstance(attr, topologic.IntAttribute):
return (attr.IntValue())
elif isinstance(attr, topologic.DoubleAttribute):
return (attr.DoubleValue())
elif isinstance(attr, topologic.StringAttribute):
return (attr.StringValue())
elif isinstance(attr, topologic.ListAttribute):
return (listAttributeValues(attr))
else:
return None

def processKeysValues(keys, values):
if len(keys) != len(values):
raise Exception("DictionaryByKeysValues - Keys and Values do not have the same length")
stl_keys = []
stl_values = []
for i in range(len(keys)):
if keys[i] in '_RNA_UI':
continue
if isinstance(keys[i], str):
stl_keys.append(keys[i])
else:
stl_keys.append(str(keys[i]))
if isinstance(values[i], list) and len(values[i]) == 1:
value = values[i][0]
else:
value = values[i]
if isinstance(value, idprop.types.IDPropertyArray):
value = value.to_list()
if isinstance(value, bool):
if value == False:
stl_values.append(topologic.IntAttribute(0))
else:
stl_values.append(topologic.IntAttribute(1))
elif isinstance(value, int):
stl_values.append(topologic.IntAttribute(value))
elif isinstance(value, float):
stl_values.append(topologic.DoubleAttribute(value))
elif isinstance(value, str):
stl_values.append(topologic.StringAttribute(value))
elif isinstance(value, list):
l = []
for v in value:
if isinstance(v, bool):
l.append(topologic.IntAttribute(v))
elif isinstance(v, int):
l.append(topologic.IntAttribute(v))
elif isinstance(v, float):
l.append(topologic.DoubleAttribute(v))
elif isinstance(v, str):
l.append(topologic.StringAttribute(v))
stl_values.append(topologic.ListAttribute(l))
else:
stl_values.append(topologic.StringAttribute(str(value)))
myDict = topologic.Dictionary.ByKeysValues(stl_keys, stl_values)
return myDict

def processItem(source):
#keys = source.keys()
#print(keys)
print(source["name"])
#if len(keys) < 1:
#raise Exception("DictionaryByCustomProperties - Error: The source has no custom properties")
values = []
for aKey in keys:
value = source[aKey]
values.append(source[aKey])
return processKeysValues(keys, values)

class SvDictionaryByCustomProperties(bpy.types.Node, SverchCustomTreeNode):

"""
Triggers: Topologic
Tooltip: Creates a dictionary from the custom properties of the input Blender Object
"""
bl_idname = 'SvDictionaryByCustomProperties'
bl_label = 'Dictionary.ByCustomProperties'

def sv_init(self, context):
self.inputs.new('SvStringsSocket', 'Source')
self.outputs.new('SvStringsSocket', 'Dictionary')

def process(self):
start = time.time()
if not any(socket.is_linked for socket in self.outputs):
return
if not any(socket.is_linked for socket in self.inputs):
self.outputs['Dictionary'].sv_set([])
return
sourceList = self.inputs['Source'].sv_get(deepcopy=True)
sourceList = flatten(sourceList)
outputs = []
for anInput in sourceList:
outputs.append(processItem(anInput))
self.outputs['Dictionary'].sv_set(outputs)
end = time.time()
print("Dictionary.ByCustomProperties Operation consumed "+str(round(end - start,2))+" seconds")

def register():
bpy.utils.register_class(SvDictionaryByCustomProperties)

def unregister():
bpy.utils.unregister_class(SvDictionaryByCustomProperties)
151 changes: 151 additions & 0 deletions nodes/Topologic/EdgeVertexByParameter-orig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import bpy
from bpy.props import FloatProperty, StringProperty, EnumProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode

import topologic

# From https://stackabuse.com/python-how-to-flatten-list-of-lists/
def flatten(element):
returnList = []
if isinstance(element, list) == True:
for anItem in element:
returnList = returnList + flatten(anItem)
else:
returnList = [element]
return returnList

def repeat(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

# From https://stackoverflow.com/questions/34432056/repeat-elements-of-list-between-each-other-until-we-reach-a-certain-length
def onestep(cur,y,base):
# one step of the iteration
if cur is not None:
y.append(cur)
base.append(cur)
else:
y.append(base[0]) # append is simplest, for now
base = base[1:]+[base[0]] # rotate
return base

def iterate(list):
maxLength = len(list[0])
returnList = []
for aSubList in list:
newLength = len(aSubList)
if newLength > maxLength:
maxLength = newLength
for anItem in list:
for i in range(len(anItem), maxLength):
anItem.append(None)
y=[]
base=[]
for cur in anItem:
base = onestep(cur,y,base)
# print(base,y)
returnList.append(y)
return returnList

def trim(list):
minLength = len(list[0])
returnList = []
for aSubList in list:
newLength = len(aSubList)
if newLength < minLength:
minLength = newLength
for anItem in list:
anItem = anItem[:minLength]
returnList.append(anItem)
return returnList

# Adapted from https://stackoverflow.com/questions/533905/get-the-cartesian-product-of-a-series-of-lists
def interlace(ar_list):
if not ar_list:
yield []
else:
for a in ar_list[0]:
for prod in interlace(ar_list[1:]):
yield [a,]+prod

def transposeList(l):
length = len(l[0])
returnList = []
for i in range(length):
tempRow = []
for j in range(len(l)):
tempRow.append(l[j][i])
returnList.append(tempRow)
return returnList

def processItem(item):
edge = item[0]
parameter = item[1]
vertex = None
try:
vertex = topologic.EdgeUtility.PointAtParameter(edge, parameter)
except:
vertex = None
return vertex

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

class SvEdgeVertexByParameter(bpy.types.Node, SverchCustomTreeNode):
"""
Triggers: Topologic
Tooltip: Creates a Vertex at the parameter value of the input Edge
"""
bl_idname = 'SvEdgeVertexByParameter'
bl_label = 'Edge.VertexByParameter'
Parameter: FloatProperty(name="Parameter", default=0.5, precision=4, min=0, max=1, update=updateNode)
Replication: EnumProperty(name="Replication", description="Replication", default="Iterate", items=replication, update=updateNode)

def sv_init(self, context):
self.inputs.new('SvStringsSocket', 'Edge')
self.inputs.new('SvStringsSocket', 'Parameter').prop_name='Parameter'
self.outputs.new('SvStringsSocket', 'Vertex')

def draw_buttons(self, context, layout):
layout.prop(self, "Replication",text="")

def process(self):
if not any(socket.is_linked for socket in self.outputs):
return
edgeList = self.inputs['Edge'].sv_get(deepcopy=False)
parameterList = self.inputs['Parameter'].sv_get(deepcopy=False)
edgeList = flatten(edgeList)
parameterList = flatten(parameterList)
inputs = [edgeList, parameterList]
if ((self.Replication) == "Trim"):
inputs = trim(inputs)
inputs = transposeList(inputs)
elif ((self.Replication) == "Iterate"):
inputs = iterate(inputs)
inputs = transposeList(inputs)
elif ((self.Replication) == "Repeat"):
inputs = repeat(inputs)
inputs = transposeList(inputs)
elif ((self.Replication) == "Interlace"):
inputs = list(interlace(inputs))
outputs = []
for anInput in inputs:
outputs.append(processItem(anInput))
self.outputs['Vertex'].sv_set(outputs)

def register():
bpy.utils.register_class(SvEdgeVertexByParameter)

def unregister():
bpy.utils.unregister_class(SvEdgeVertexByParameter)
Loading

0 comments on commit 45ef653

Please sign in to comment.