Skip to content

Commit

Permalink
Merge pull request #110 from rchristie/smooth_direction
Browse files Browse the repository at this point in the history
Smooth derivative directions, add function options
  • Loading branch information
rchristie authored Dec 9, 2020
2 parents e5cdfb4 + 1e6404e commit a7310c9
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 85 deletions.
114 changes: 63 additions & 51 deletions src/scaffoldmaker/meshtypes/meshtype_1d_path1.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,56 +131,66 @@ def generateBaseMesh(cls, region, options):
return []

@classmethod
def smoothPath(cls, region, options, editGroupName, mode : DerivativeScalingMode):
x, d1 = extractPathParametersFromRegion(region, [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1])
d1 = smoothCubicHermiteDerivativesLine(x, d1, magnitudeScalingMode=mode)
setPathParameters(region, [ Node.VALUE_LABEL_D_DS1 ], [ d1 ], editGroupName)
return False, True # settings not changed, nodes changed

@classmethod
def makeD2Normal(cls, region, options, editGroupName):
if not options['D2 derivatives']:
return
d1, d2 = extractPathParametersFromRegion(region, [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2])
for c in range(len(d1)):
td2 = vector.vectorRejection(d2[c], d1[c])
d2[c] = vector.setMagnitude(td2, vector.magnitude(d2[c]))
setPathParameters(region, [Node.VALUE_LABEL_D_DS2], [d2], editGroupName)
return False, True # settings not changed, nodes changed

@classmethod
def makeD3Normal(cls, region, options, editGroupName):
if not options['D3 derivatives']:
return
def makeSideDerivativesNormal(cls, region, options, functionOptions, editGroupName):
makeD2Normal = options['D2 derivatives'] and functionOptions['Make D2 normal']
makeD3Normal = options['D3 derivatives'] and functionOptions['Make D3 normal']
if not (makeD2Normal or makeD3Normal):
return False, False
valueLabels = [ Node.VALUE_LABEL_D_DS1 ]
if options['D2 derivatives']:
d1, d2, d3 = extractPathParametersFromRegion(region, [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2,
Node.VALUE_LABEL_D_DS3])
for c in range(len(d1)):
d3[c] = vector.setMagnitude(vector.crossproduct3(d1[c], d2[c]), vector.magnitude(d3[c]))
else:
d1, d3 = extractPathParametersFromRegion(region, [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS3])
valueLabels.append(Node.VALUE_LABEL_D_DS2)
if options['D3 derivatives']:
valueLabels.append(Node.VALUE_LABEL_D_DS3)
parameters = extractPathParametersFromRegion(region, valueLabels)
d1 = parameters[0]
modifyParameters = []
modifyValueLabels = []
if makeD2Normal:
d2 = parameters[1]
for c in range(len(d1)):
td3 = vector.vectorRejection(d3[c], d1[c])
d3[c] = vector.setMagnitude(td3, vector.magnitude(d3[c]))
setPathParameters(region, [Node.VALUE_LABEL_D_DS3], [d3], editGroupName)
td2 = vector.vectorRejection(d2[c], d1[c])
d2[c] = vector.setMagnitude(td2, vector.magnitude(d2[c]))
modifyParameters.append(d2)
modifyValueLabels.append(Node.VALUE_LABEL_D_DS2)
if makeD3Normal:
d3 = parameters[-1]
if options['D2 derivatives']:
for c in range(len(d1)):
d3[c] = vector.setMagnitude(vector.crossproduct3(d1[c], d2[c]), vector.magnitude(d3[c]))
else:
for c in range(len(d1)):
td3 = vector.vectorRejection(d3[c], d1[c])
d3[c] = vector.setMagnitude(td3, vector.magnitude(d3[c]))
modifyParameters.append(d3)
modifyValueLabels.append(Node.VALUE_LABEL_D_DS3)
setPathParameters(region, modifyValueLabels, modifyParameters, editGroupName)
return False, True # settings not changed, nodes changed

@classmethod
def smoothCrossDX(cls, region, options, editGroupName, valueLabel):
if valueLabel == Node.VALUE_LABEL_D_DS2:
if not options['D2 derivatives']:
return
crossDerivativeLabel = Node.VALUE_LABEL_D2_DS1DS2
elif valueLabel == Node.VALUE_LABEL_D_DS3:
if not options['D3 derivatives']:
return
crossDerivativeLabel = Node.VALUE_LABEL_D2_DS1DS3
else:
assert False, 'Invalid value label'
valueLabels = [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, valueLabel, crossDerivativeLabel]
x, d1, d2, d12 = extractPathParametersFromRegion(region, valueLabels)
d12 = smoothCubicHermiteCrossDerivativesLine(x, d1, d2, d12)
setPathParameters(region, [ crossDerivativeLabel ], [ d12 ], editGroupName)
def smoothSideCrossDerivatives(cls, region, options, functionOptions, editGroupName):
smoothD12 = options['D2 derivatives'] and functionOptions['Smooth D12']
smoothD13 = options['D3 derivatives'] and functionOptions['Smooth D13']
if not (smoothD12 or smoothD13):
return False, False
valueLabels = [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1 ]
if smoothD12:
valueLabels += [ Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2 ]
if smoothD13:
valueLabels += [ Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ]
parameters = extractPathParametersFromRegion(region, valueLabels)
x = parameters[0]
d1 = parameters[1]
modifyParameters = []
modifyValueLabels = []
if smoothD12:
d12 = smoothCubicHermiteCrossDerivativesLine(x, d1, parameters[2], parameters[3])
modifyParameters.append(d12)
modifyValueLabels.append(Node.VALUE_LABEL_D2_DS1DS2)
if smoothD13:
d13 = smoothCubicHermiteCrossDerivativesLine(x, d1, parameters[-2], parameters[-1])
modifyParameters.append(d13)
modifyValueLabels.append(Node.VALUE_LABEL_D2_DS1DS3)
setPathParameters(region, modifyValueLabels, modifyParameters, editGroupName)
return False, True # settings not changed, nodes changed

@classmethod
Expand All @@ -189,12 +199,14 @@ def getInteractiveFunctions(cls):
Supply client with functions for smoothing path parameters.
"""
return Scaffold_base.getInteractiveFunctions() + [
("Smooth D1 arithmetic", lambda region, options, editGroupName: cls.smoothPath(region, options, editGroupName, DerivativeScalingMode.ARITHMETIC_MEAN)),
("Smooth D1 harmonic", lambda region, options, editGroupName: cls.smoothPath(region, options, editGroupName, DerivativeScalingMode.HARMONIC_MEAN)),
("Make D2 normal", lambda region, options, editGroupName: cls.makeD2Normal(region, options, editGroupName)),
("Make D3 normal", lambda region, options, editGroupName: cls.makeD3Normal(region, options, editGroupName)),
("Smooth D2", lambda region, options, editGroupName: cls.smoothCrossDX(region, options, editGroupName, Node.VALUE_LABEL_D_DS2)),
("Smooth D3", lambda region, options, editGroupName: cls.smoothCrossDX(region, options, editGroupName, Node.VALUE_LABEL_D_DS3))
("Make side derivatives normal...",
{ 'Make D2 normal': True,
'Make D3 normal': True },
lambda region, options, functionOptions, editGroupName: cls.makeSideDerivativesNormal(region, options, functionOptions, editGroupName)),
("Smooth side cross derivatives...",
{ 'Smooth D12' : True,
'Smooth D13' : True },
lambda region, options, functionOptions, editGroupName: cls.smoothSideCrossDerivatives(region, options, functionOptions, editGroupName))
]


Expand Down
43 changes: 25 additions & 18 deletions src/scaffoldmaker/meshtypes/scaffold_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,7 @@ def generateMesh(cls, region, options):
return annotationGroups

@classmethod
def smoothDerivativeMagnitudes(cls, region, options, editGroupName, scalingMode : DerivativeScalingMode):
fieldmodule = region.getFieldmodule()
coordinatesField = fieldmodule.findFieldByName('coordinates').castFiniteElement()
groupName = 'cmiss_selection'
selectionGroup = fieldmodule.findFieldByName(groupName).castGroup()
if not selectionGroup.isValid():
groupName = False # smooth whole model
smoothing = DerivativeSmoothing(region, coordinatesField, groupName, scalingMode, editGroupName)
smoothing.smooth()
del smoothing
return False, True # settings not changed, nodes changed

@classmethod
def printNodeFieldParameters(cls, region, options, editGroupName):
def printNodeFieldParameters(cls, region, options, functionOptions, editGroupName):
'''
Interactive function for printing node field parameters for pasting into code.
'''
Expand All @@ -182,9 +169,25 @@ def printNodeFieldParameters(cls, region, options, editGroupName):
return False, False
coordinates = fieldmodule.findFieldByName('coordinates').castFiniteElement()
valueLabels, fieldParameters = extract_node_field_parameters(nodeset, coordinates)
print_node_field_parameters(valueLabels, fieldParameters) #, format_string='{:8.3f}')
numberFormat = '{:' + functionOptions['Number format (e.g. 8.3f)'] + '}'
print_node_field_parameters(valueLabels, fieldParameters, numberFormat)
return False, False # no change to settings, nor node parameters

@classmethod
def smoothDerivatives(cls, region, options, functionOptions, editGroupName):
fieldmodule = region.getFieldmodule()
coordinatesField = fieldmodule.findFieldByName('coordinates').castFiniteElement()
groupName = 'cmiss_selection'
selectionGroup = fieldmodule.findFieldByName(groupName).castGroup()
if not selectionGroup.isValid():
groupName = False # smooth whole model
updateDirections = functionOptions['Update directions']
scalingMode = DerivativeScalingMode.ARITHMETIC_MEAN if functionOptions['Scaling mode']['Arithmetic mean'] else DerivativeScalingMode.HARMONIC_MEAN
smoothing = DerivativeSmoothing(region, coordinatesField, groupName, scalingMode, editGroupName)
smoothing.smooth(updateDirections)
del smoothing
return False, True # settings not changed, nodes changed

@classmethod
def getInteractiveFunctions(cls):
"""
Expand All @@ -200,7 +203,11 @@ def getInteractiveFunctions(cls):
:return: list(tuples), (name : str, callable(region, options, editGroupName)).
"""
return [
("Smooth derivative magnitudes arithmetic", lambda region, options, editGroupName: cls.smoothDerivativeMagnitudes(region, options, editGroupName, DerivativeScalingMode.ARITHMETIC_MEAN)),
("Smooth derivative magnitudes harmonic", lambda region, options, editGroupName: cls.smoothDerivativeMagnitudes(region, options, editGroupName, DerivativeScalingMode.HARMONIC_MEAN)),
("Print node parameters", lambda region, options, editGroupName: cls.printNodeFieldParameters(region, options, editGroupName))
("Print node parameters...",
{ 'Number format (e.g. 8.3f)': ' 11e' },
lambda region, options, functionOptions, editGroupName: cls.printNodeFieldParameters(region, options, functionOptions, editGroupName)),
("Smooth derivatives...",
{ 'Update directions': False,
'Scaling mode': { 'Arithmetic mean': True, 'Harmonic mean': False } },
lambda region, options, functionOptions, editGroupName: cls.smoothDerivatives(region, options, functionOptions, editGroupName))
]
Loading

0 comments on commit a7310c9

Please sign in to comment.