Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth derivative directions, add function options #110

Merged
merged 5 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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