6 from __future__ import absolute_import
7 #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
10 from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting
11 from fabmetheus_utilities.vector3 import Vector3
12 from fabmetheus_utilities import archive
13 from fabmetheus_utilities import euclidean
14 from fabmetheus_utilities import gcodec
15 from fabmetheus_utilities import settings
22 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
23 __credits__ = 'Art of Illusion <http://www.artofillusion.org/>'
24 __date__ = '$Date: 2008/02/05 $'
25 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
28 globalModuleFunctionsDictionary = {}
31 def addPrefixDictionary(dictionary, keys, value):
32 'Add prefixed key values to dictionary.'
34 dictionary[key.lstrip('_')] = value
36 def addQuoteWord(evaluatorWords, word):
37 'Add quote word and remainder if the word starts with a quote character or dollar sign, otherwise add the word.'
39 evaluatorWords.append(word)
41 firstCharacter = word[0]
42 if firstCharacter == '$':
43 dotIndex = word.find('.', 1)
45 evaluatorWords.append(word[: dotIndex])
46 evaluatorWords.append(word[dotIndex :])
48 if firstCharacter != '"' and firstCharacter != "'":
49 evaluatorWords.append(word)
51 nextQuoteIndex = word.find(firstCharacter, 1)
52 if nextQuoteIndex < 0 or nextQuoteIndex == len(word) - 1:
53 evaluatorWords.append(word)
56 evaluatorWords.append(word[: nextQuoteIndex])
57 evaluatorWords.append(word[nextQuoteIndex :])
59 def addToPathsRecursively(paths, vector3Lists):
60 'Add to vector3 paths recursively.'
61 if vector3Lists.__class__ == Vector3 or vector3Lists.__class__ .__name__ == 'Vector3Index':
62 paths.append([ vector3Lists ])
65 for vector3List in vector3Lists:
66 if vector3List.__class__ == list:
67 addToPathsRecursively(paths, vector3List)
68 elif vector3List.__class__ == Vector3:
69 path.append(vector3List)
73 def addValueToEvaluatedDictionary(elementNode, evaluatedDictionary, key):
74 'Get the evaluated dictionary.'
75 value = getEvaluatedValueObliviously(elementNode, key)
77 valueString = str(elementNode.attributes[key])
78 print('Warning, addValueToEvaluatedDictionary in evaluate can not get a value for:')
80 evaluatedDictionary[key + '__Warning__'] = 'Can not evaluate: ' + valueString.replace('"', ' ').replace( "'", ' ')
82 evaluatedDictionary[key] = value
84 def addVector3ToElementNode(elementNode, key, vector3):
85 'Add vector3 to xml element.'
86 elementNode.attributes[key] = '[%s,%s,%s]' % (vector3.x, vector3.y, vector3.z)
88 def compareExecutionOrderAscending(module, otherModule):
89 'Get comparison in order to sort modules in ascending execution order.'
90 if module.globalExecutionOrder < otherModule.globalExecutionOrder:
92 if module.globalExecutionOrder > otherModule.globalExecutionOrder:
94 if module.__name__ < otherModule.__name__:
96 return int(module.__name__ > otherModule.__name__)
98 def convertToPaths(dictionary):
99 'Recursively convert any ElementNodes to paths.'
100 if dictionary.__class__ == Vector3 or dictionary.__class__.__name__ == 'Vector3Index':
102 keys = getKeys(dictionary)
106 value = dictionary[key]
107 if value.__class__.__name__ == 'ElementNode':
108 if value.xmlObject != None:
109 dictionary[key] = getFloatListListsByPaths(value.xmlObject.getPaths())
111 convertToPaths(dictionary[key])
113 def convertToTransformedPaths(dictionary):
114 'Recursively convert any ElementNodes to paths.'
115 if dictionary.__class__ == Vector3 or dictionary.__class__.__name__ == 'Vector3Index':
117 keys = getKeys(dictionary)
121 value = dictionary[key]
122 if value.__class__.__name__ == 'ElementNode':
123 if value.xmlObject != None:
124 dictionary[key] = value.xmlObject.getTransformedPaths()
126 convertToTransformedPaths(dictionary[key])
128 def executeLeftOperations( evaluators, operationLevel ):
129 'Evaluate the expression value from the numeric and operation evaluators.'
130 for negativeIndex in xrange( - len(evaluators), - 1 ):
131 evaluatorIndex = negativeIndex + len(evaluators)
132 evaluators[evaluatorIndex].executeLeftOperation( evaluators, evaluatorIndex, operationLevel )
134 def executeNextEvaluatorArguments(evaluator, evaluators, evaluatorIndex, nextEvaluator):
135 'Execute the nextEvaluator arguments.'
136 if evaluator.value == None:
137 print('Warning, executeNextEvaluatorArguments in evaluate can not get a evaluator.value for:')
138 print(evaluatorIndex)
142 nextEvaluator.value = evaluator.value(*nextEvaluator.arguments)
143 del evaluators[evaluatorIndex]
145 def executePairOperations(evaluators, operationLevel):
146 'Evaluate the expression value from the numeric and operation evaluators.'
147 for negativeIndex in xrange(1 - len(evaluators), - 1):
148 evaluatorIndex = negativeIndex + len(evaluators)
149 evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, operationLevel)
151 def getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators):
152 'Get the bracket evaluators.'
153 return getEvaluatedExpressionValueEvaluators(evaluators[bracketBeginIndex + 1 : bracketEndIndex])
155 def getBracketsExist(evaluators):
156 'Evaluate the expression value.'
157 bracketBeginIndex = None
158 for negativeIndex in xrange( - len(evaluators), 0 ):
159 bracketEndIndex = negativeIndex + len(evaluators)
160 evaluatorEnd = evaluators[ bracketEndIndex ]
161 evaluatorWord = evaluatorEnd.word
162 if evaluatorWord in ['(', '[', '{']:
163 bracketBeginIndex = bracketEndIndex
164 elif evaluatorWord in [')', ']', '}']:
165 if bracketBeginIndex == None:
166 print('Warning, bracketBeginIndex in evaluateBrackets in evaluate is None.')
167 print('This may be because the brackets are not balanced.')
169 del evaluators[ bracketEndIndex ]
171 evaluators[ bracketBeginIndex ].executeBracket(bracketBeginIndex, bracketEndIndex, evaluators)
172 evaluators[ bracketBeginIndex ].word = None
176 def getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators):
177 'Get the bracket values and delete the evaluator.'
178 evaluatedExpressionValueEvaluators = getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators)
180 for evaluatedExpressionValueEvaluator in evaluatedExpressionValueEvaluators:
181 bracketValues.append( evaluatedExpressionValueEvaluator.value )
182 del evaluators[ bracketBeginIndex + 1: bracketEndIndex + 1 ]
185 def getCapitalizedSuffixKey(prefix, suffix):
186 'Get key with capitalized suffix.'
187 if prefix == '' or prefix.endswith('.'):
188 return prefix + suffix
189 return prefix + suffix[:1].upper()+suffix[1:]
191 def getDictionarySplitWords(dictionary, value):
192 'Get split line for evaluators.'
193 if getIsQuoted(value):
195 for dictionaryKey in dictionary.keys():
196 value = value.replace(dictionaryKey, ' ' + dictionaryKey + ' ')
197 dictionarySplitWords = []
198 for word in value.split():
199 dictionarySplitWords.append(word)
200 return dictionarySplitWords
202 def getElementNodeByKey(elementNode, key):
203 'Get the xml element by key.'
204 if key not in elementNode.attributes:
206 word = str(elementNode.attributes[key]).strip()
207 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
208 if evaluatedLinkValue.__class__.__name__ == 'ElementNode':
209 return evaluatedLinkValue
210 print('Warning, could not get ElementNode in getElementNodeByKey in evaluate for:')
212 print(evaluatedLinkValue)
216 def getElementNodeObject(evaluatedLinkValue):
217 'Get ElementNodeObject.'
218 if evaluatedLinkValue.__class__.__name__ != 'ElementNode':
219 print('Warning, could not get ElementNode in getElementNodeObject in evaluate for:')
220 print(evaluatedLinkValue.__class__.__name__)
221 print(evaluatedLinkValue)
223 if evaluatedLinkValue.xmlObject == None:
224 print('Warning, evaluatedLinkValue.xmlObject is None in getElementNodeObject in evaluate for:')
225 print(evaluatedLinkValue)
227 return evaluatedLinkValue.xmlObject
229 def getElementNodesByKey(elementNode, key):
230 'Get the xml elements by key.'
231 if key not in elementNode.attributes:
233 word = str(elementNode.attributes[key]).strip()
234 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
235 if evaluatedLinkValue.__class__.__name__ == 'ElementNode':
236 return [evaluatedLinkValue]
237 if evaluatedLinkValue.__class__ == list:
238 return evaluatedLinkValue
239 print('Warning, could not get ElementNodes in getElementNodesByKey in evaluate for:')
241 print(evaluatedLinkValue)
245 def getEndIndexConvertEquationValue( bracketEndIndex, evaluatorIndex, evaluators ):
246 'Get the bracket end index and convert the equation value evaluators into a string.'
247 evaluator = evaluators[evaluatorIndex]
248 if evaluator.__class__ != EvaluatorValue:
249 return bracketEndIndex
250 if not evaluator.word.startswith('equation.'):
251 return bracketEndIndex
252 if evaluators[ evaluatorIndex + 1 ].word != ':':
253 return bracketEndIndex
254 valueBeginIndex = evaluatorIndex + 2
255 equationValueString = ''
256 for valueEvaluatorIndex in xrange( valueBeginIndex, len(evaluators) ):
257 valueEvaluator = evaluators[ valueEvaluatorIndex ]
258 if valueEvaluator.word == ',' or valueEvaluator.word == '}':
259 if equationValueString == '':
260 return bracketEndIndex
262 evaluators[ valueBeginIndex ] = EvaluatorValue( equationValueString )
263 valueDeleteIndex = valueBeginIndex + 1
264 del evaluators[ valueDeleteIndex : valueEvaluatorIndex ]
265 return bracketEndIndex - valueEvaluatorIndex + valueDeleteIndex
266 equationValueString += valueEvaluator.word
267 return bracketEndIndex
269 def getEvaluatedBoolean(defaultValue, elementNode, key):
270 'Get the evaluated boolean.'
271 if elementNode == None:
273 if key in elementNode.attributes:
274 return euclidean.getBooleanFromValue(getEvaluatedValueObliviously(elementNode, key))
277 def getEvaluatedDictionaryByCopyKeys(copyKeys, elementNode):
278 'Get the evaluated dictionary by copyKeys.'
279 evaluatedDictionary = {}
280 for key in elementNode.attributes.keys():
282 evaluatedDictionary[key] = elementNode.attributes[key]
284 addValueToEvaluatedDictionary(elementNode, evaluatedDictionary, key)
285 return evaluatedDictionary
287 def getEvaluatedDictionaryByEvaluationKeys(elementNode, evaluationKeys):
288 'Get the evaluated dictionary.'
289 evaluatedDictionary = {}
290 for key in elementNode.attributes.keys():
291 if key in evaluationKeys:
292 addValueToEvaluatedDictionary(elementNode, evaluatedDictionary, key)
293 return evaluatedDictionary
295 def getEvaluatedExpressionValue(elementNode, value):
296 'Evaluate the expression value.'
298 return getEvaluatedExpressionValueBySplitLine(elementNode, getEvaluatorSplitWords(value))
300 print('Warning, in getEvaluatedExpressionValue in evaluate could not get a value for:')
302 traceback.print_exc(file=sys.stdout)
305 def getEvaluatedExpressionValueBySplitLine(elementNode, words):
306 'Evaluate the expression value.'
308 for wordIndex, word in enumerate(words):
310 nextWordIndex = wordIndex + 1
311 if nextWordIndex < len(words):
312 nextWord = words[nextWordIndex]
313 evaluator = getEvaluator(elementNode, evaluators, nextWord, word)
314 if evaluator != None:
315 evaluators.append(evaluator)
316 while getBracketsExist(evaluators):
318 evaluatedExpressionValueEvaluators = getEvaluatedExpressionValueEvaluators(evaluators)
319 if len( evaluatedExpressionValueEvaluators ) > 0:
320 return evaluatedExpressionValueEvaluators[0].value
323 def getEvaluatedExpressionValueEvaluators(evaluators):
324 'Evaluate the expression value from the numeric and operation evaluators.'
325 for evaluatorIndex, evaluator in enumerate(evaluators):
326 evaluator.executeCenterOperation(evaluators, evaluatorIndex)
327 for negativeIndex in xrange(1 - len(evaluators), 0):
328 evaluatorIndex = negativeIndex + len(evaluators)
329 evaluators[evaluatorIndex].executeRightOperation(evaluators, evaluatorIndex)
330 executeLeftOperations(evaluators, 200)
331 for operationLevel in [80, 60, 40, 20, 15]:
332 executePairOperations(evaluators, operationLevel)
333 executeLeftOperations(evaluators, 13)
334 executePairOperations(evaluators, 12)
335 for negativeIndex in xrange(-len(evaluators), 0):
336 evaluatorIndex = negativeIndex + len(evaluators)
337 evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, 10)
338 for evaluatorIndex in xrange(len(evaluators) - 1, -1, -1):
339 evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, 0)
342 def getEvaluatedFloat(defaultValue, elementNode, key):
343 'Get the evaluated float.'
344 if elementNode == None:
346 if key in elementNode.attributes:
347 return euclidean.getFloatFromValue(getEvaluatedValueObliviously(elementNode, key))
350 def getEvaluatedInt(defaultValue, elementNode, key):
351 'Get the evaluated int.'
352 if elementNode == None:
354 if key in elementNode.attributes:
356 return getIntFromFloatString(getEvaluatedValueObliviously(elementNode, key))
358 print('Warning, could not evaluate the int.')
360 print(elementNode.attributes[key])
363 def getEvaluatedIntByKeys(defaultValue, elementNode, keys):
364 'Get the evaluated int by keys.'
366 defaultValue = getEvaluatedInt(defaultValue, elementNode, key)
369 def getEvaluatedLinkValue(elementNode, word):
370 'Get the evaluated link value.'
373 if getStartsWithCurlyEqualRoundSquare(word):
374 return getEvaluatedExpressionValue(elementNode, word)
377 def getEvaluatedString(defaultValue, elementNode, key):
378 'Get the evaluated string.'
379 if elementNode == None:
381 if key in elementNode.attributes:
382 return str(getEvaluatedValueObliviously(elementNode, key))
385 def getEvaluatedValue(defaultValue, elementNode, key):
386 'Get the evaluated value.'
387 if elementNode == None:
389 if key in elementNode.attributes:
390 return getEvaluatedValueObliviously(elementNode, key)
393 def getEvaluatedValueObliviously(elementNode, key):
394 'Get the evaluated value.'
395 value = str(elementNode.attributes[key]).strip()
396 if key == 'id' or key == 'name' or key == 'tags':
398 return getEvaluatedLinkValue(elementNode, value)
400 def getEvaluator(elementNode, evaluators, nextWord, word):
402 if word in globalSplitDictionary:
403 return globalSplitDictionary[word](elementNode, word)
404 firstCharacter = word[: 1]
405 if firstCharacter == "'" or firstCharacter == '"':
407 if firstCharacter == word[-1]:
408 return EvaluatorValue(word[1 : -1])
409 if firstCharacter == '$':
410 return EvaluatorValue(word[1 :])
411 dotIndex = word.find('.')
412 functions = elementNode.getXMLProcessor().functions
413 if dotIndex > -1 and len(word) > 1:
414 if dotIndex == 0 and word[1].isalpha():
415 return EvaluatorAttribute(elementNode, word)
417 untilDot = word[: dotIndex]
418 if untilDot in globalModuleEvaluatorDictionary:
419 return globalModuleEvaluatorDictionary[untilDot](elementNode, word)
420 if len(functions) > 0:
421 if untilDot in functions[-1].localDictionary:
422 return EvaluatorLocal(elementNode, word)
423 if firstCharacter.isalpha() or firstCharacter == '_':
424 if len(functions) > 0:
425 if word in functions[-1].localDictionary:
426 return EvaluatorLocal(elementNode, word)
427 wordElement = elementNode.getElementNodeByID(word)
428 if wordElement != None:
429 if wordElement.getNodeName() == 'class':
430 return EvaluatorClass(wordElement, word)
431 if wordElement.getNodeName() == 'function':
432 return EvaluatorFunction(wordElement, word)
433 return EvaluatorValue(word)
434 return EvaluatorNumeric(elementNode, word)
436 def getEvaluatorSplitWords(value):
437 'Get split words for evaluators.'
438 if value.startswith('='):
439 value = value[len('=') :]
442 global globalDictionaryOperatorBegin
447 for characterIndex in xrange(len(value)):
448 character = value[characterIndex]
449 if character == '"' or character == "'":
450 if quoteString == None:
452 elif quoteString != None:
453 if character == quoteString[: 1]:
454 uniqueQuoteIndex = getUniqueQuoteIndex(uniqueQuoteIndex, value)
455 uniqueToken = getTokenByNumber(uniqueQuoteIndex)
456 quoteDictionary[uniqueToken] = quoteString + character
457 character = uniqueToken
459 if quoteString == None:
462 quoteString += character
463 beginSplitWords = getDictionarySplitWords(globalDictionaryOperatorBegin, word)
464 global globalSplitDictionaryOperator
465 evaluatorSplitWords = []
466 for beginSplitWord in beginSplitWords:
467 if beginSplitWord in globalDictionaryOperatorBegin:
468 evaluatorSplitWords.append(beginSplitWord)
470 evaluatorSplitWords += getDictionarySplitWords(globalSplitDictionaryOperator, beginSplitWord)
471 for evaluatorSplitWordIndex, evaluatorSplitWord in enumerate(evaluatorSplitWords):
472 for quoteDictionaryKey in quoteDictionary.keys():
473 if quoteDictionaryKey in evaluatorSplitWord:
474 evaluatorSplitWords[evaluatorSplitWordIndex] = evaluatorSplitWord.replace(quoteDictionaryKey, quoteDictionary[quoteDictionaryKey])
475 evaluatorTransitionWords = []
476 for evaluatorSplitWord in evaluatorSplitWords:
477 addQuoteWord(evaluatorTransitionWords, evaluatorSplitWord)
478 return evaluatorTransitionWords
480 def getFloatListFromBracketedString( bracketedString ):
481 'Get list from a bracketed string.'
482 if not getIsBracketed( bracketedString ):
484 bracketedString = bracketedString.strip().replace('[', '').replace(']', '').replace('(', '').replace(')', '')
485 if len( bracketedString ) < 1:
487 splitLine = bracketedString.split(',')
489 for word in splitLine:
490 evaluatedFloat = euclidean.getFloatFromValue(word)
491 if evaluatedFloat != None:
492 floatList.append( evaluatedFloat )
495 def getFloatListListsByPaths(paths):
496 'Get float lists by paths.'
501 floatListList.append( point.getFloatList() )
502 return floatListLists
504 def getIntFromFloatString(value):
505 'Get the int from the string.'
506 floatString = str(value).strip()
507 if floatString == '':
509 dotIndex = floatString.find('.')
512 return int( round( float(floatString) ) )
514 def getIsBracketed(word):
515 'Determine if the word is bracketed.'
518 firstCharacter = word[0]
519 lastCharacter = word[-1]
520 if firstCharacter == '(' and lastCharacter == ')':
522 return firstCharacter == '[' and lastCharacter == ']'
524 def getIsQuoted(word):
525 'Determine if the word is quoted.'
528 firstCharacter = word[0]
529 lastCharacter = word[-1]
530 if firstCharacter == '"' and lastCharacter == '"':
532 return firstCharacter == "'" and lastCharacter == "'"
534 def getKeys(repository):
535 'Get keys for repository.'
536 repositoryClass = repository.__class__
537 if repositoryClass == list or repositoryClass == tuple:
538 return range(len(repository))
539 if repositoryClass == dict:
540 return repository.keys()
543 def getLocalAttributeValueString(key, valueString):
544 'Get the local attribute value string with augmented assignment.'
545 augmentedStatements = '+= -= *= /= %= **='.split()
546 for augmentedStatement in augmentedStatements:
547 if valueString.startswith(augmentedStatement):
548 return key + augmentedStatement[: -1] + valueString[len(augmentedStatement) :]
551 def getMatchingPlugins(elementNode, namePathDictionary):
552 'Get the plugins whose names are in the attribute dictionary.'
554 namePathDictionaryCopy = namePathDictionary.copy()
555 for key in elementNode.attributes:
556 dotIndex = key.find('.')
558 keyUntilDot = key[: dotIndex]
559 if keyUntilDot in namePathDictionaryCopy:
560 pluginModule = archive.getModuleWithPath( namePathDictionaryCopy[ keyUntilDot ] )
561 del namePathDictionaryCopy[ keyUntilDot ]
562 if pluginModule != None:
563 matchingPlugins.append( pluginModule )
564 return matchingPlugins
566 def getNextChildIndex(elementNode):
567 'Get the next childNode index.'
568 for childNodeIndex, childNode in enumerate( elementNode.parentNode.childNodes ):
569 if childNode == elementNode:
570 return childNodeIndex + 1
571 return len( elementNode.parentNode.childNodes )
573 def getPathByKey(defaultPath, elementNode, key):
574 'Get path from prefix and xml element.'
575 if key not in elementNode.attributes:
577 word = str(elementNode.attributes[key]).strip()
578 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
579 if evaluatedLinkValue.__class__ == list:
580 return getPathByList(evaluatedLinkValue)
581 elementNodeObject = getElementNodeObject(evaluatedLinkValue)
582 if elementNodeObject == None:
584 return elementNodeObject.getPaths()[0]
586 def getPathByList(vertexList):
587 'Get the paths by list.'
588 if len(vertexList) < 1:
590 if vertexList[0].__class__ != list:
591 vertexList = [vertexList]
593 for floatList in vertexList:
594 vector3 = getVector3ByFloatList(floatList, Vector3())
598 def getPathByPrefix(elementNode, path, prefix):
599 'Get path from prefix and xml element.'
601 print('Warning, bug, path is too small in evaluate in setPathByPrefix.')
603 pathByKey = getPathByKey([], elementNode, getCapitalizedSuffixKey(prefix, 'path'))
604 if len( pathByKey ) < len(path):
605 for pointIndex in xrange( len( pathByKey ) ):
606 path[pointIndex] = pathByKey[pointIndex]
609 path[0] = getVector3ByPrefix(path[0], elementNode, getCapitalizedSuffixKey(prefix, 'pathStart'))
610 path[-1] = getVector3ByPrefix(path[-1], elementNode, getCapitalizedSuffixKey(prefix, 'pathEnd'))
613 def getPathsByKey(defaultPaths, elementNode, key):
615 if key not in elementNode.attributes:
617 word = str(elementNode.attributes[key]).strip()
618 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
619 if evaluatedLinkValue.__class__ == dict or evaluatedLinkValue.__class__ == list:
620 convertToPaths(evaluatedLinkValue)
621 return getPathsByLists(evaluatedLinkValue)
622 elementNodeObject = getElementNodeObject(evaluatedLinkValue)
623 if elementNodeObject == None:
625 return elementNodeObject.getPaths()
627 def getPathsByLists(vertexLists):
628 'Get paths by lists.'
629 vector3Lists = getVector3ListsRecursively(vertexLists)
631 addToPathsRecursively(paths, vector3Lists)
634 def getRadiusArealizedBasedOnAreaRadius(elementNode, radius, sides):
635 'Get the areal radius from the radius, number of sides and cascade radiusAreal.'
636 if elementNode.getCascadeBoolean(False, 'radiusAreal'):
638 return radius * euclidean.getRadiusArealizedMultiplier(sides)
640 def getSidesBasedOnPrecision(elementNode, radius):
641 'Get the number of polygon sides.'
642 return int(math.ceil(math.sqrt(0.5 * radius / setting.getPrecision(elementNode)) * math.pi))
644 def getSidesMinimumThreeBasedOnPrecision(elementNode, radius):
645 'Get the number of polygon sides, with a minimum of three.'
646 return max(getSidesBasedOnPrecision(elementNode, radius), 3)
648 def getSidesMinimumThreeBasedOnPrecisionSides(elementNode, radius):
649 'Get the number of polygon sides, with a minimum of three.'
650 sides = getSidesMinimumThreeBasedOnPrecision(elementNode, radius)
651 return getEvaluatedFloat(sides, elementNode, 'sides')
653 def getSplitDictionary():
654 'Get split dictionary.'
655 global globalSplitDictionaryOperator
656 splitDictionary = globalSplitDictionaryOperator.copy()
657 global globalDictionaryOperatorBegin
658 splitDictionary.update( globalDictionaryOperatorBegin )
659 splitDictionary['and'] = EvaluatorAnd
660 splitDictionary['false'] = EvaluatorFalse
661 splitDictionary['False'] = EvaluatorFalse
662 splitDictionary['or'] = EvaluatorOr
663 splitDictionary['not'] = EvaluatorNot
664 splitDictionary['true'] = EvaluatorTrue
665 splitDictionary['True'] = EvaluatorTrue
666 splitDictionary['none'] = EvaluatorNone
667 splitDictionary['None'] = EvaluatorNone
668 return splitDictionary
670 def getStartsWithCurlyEqualRoundSquare(word):
671 'Determine if the word starts with round or square brackets.'
672 return word.startswith('{') or word.startswith('=') or word.startswith('(') or word.startswith('[')
674 def getTokenByNumber(number):
675 'Get token by number.'
676 return '_%s_' % number
678 def getTransformedPathByKey(defaultTransformedPath, elementNode, key):
679 'Get transformed path from prefix and xml element.'
680 if key not in elementNode.attributes:
681 return defaultTransformedPath
682 value = elementNode.attributes[key]
683 if value.__class__ == list:
685 word = str(value).strip()
686 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
687 if evaluatedLinkValue.__class__ == list:
688 return getPathByList(evaluatedLinkValue)
689 elementNodeObject = getElementNodeObject(evaluatedLinkValueClass)
690 if elementNodeObject == None:
691 return defaultTransformedPath
692 return elementNodeObject.getTransformedPaths()[0]
694 def getTransformedPathByPrefix(elementNode, path, prefix):
695 'Get path from prefix and xml element.'
697 print('Warning, bug, path is too small in evaluate in setPathByPrefix.')
699 pathByKey = getTransformedPathByKey([], elementNode, getCapitalizedSuffixKey(prefix, 'path'))
700 if len( pathByKey ) < len(path):
701 for pointIndex in xrange( len( pathByKey ) ):
702 path[pointIndex] = pathByKey[pointIndex]
705 path[0] = getVector3ByPrefix(path[0], elementNode, getCapitalizedSuffixKey(prefix, 'pathStart'))
706 path[-1] = getVector3ByPrefix(path[-1], elementNode, getCapitalizedSuffixKey(prefix, 'pathEnd'))
709 def getTransformedPathsByKey(defaultTransformedPaths, elementNode, key):
710 'Get transformed paths by key.'
711 if key not in elementNode.attributes:
712 return defaultTransformedPaths
713 value = elementNode.attributes[key]
714 if value.__class__ == list:
715 return getPathsByLists(value)
716 word = str(value).strip()
717 evaluatedLinkValue = getEvaluatedLinkValue(elementNode, word)
718 if evaluatedLinkValue.__class__ == dict or evaluatedLinkValue.__class__ == list:
719 convertToTransformedPaths(evaluatedLinkValue)
720 return getPathsByLists(evaluatedLinkValue)
721 elementNodeObject = getElementNodeObject(evaluatedLinkValue)
722 if elementNodeObject == None:
723 return defaultTransformedPaths
724 return elementNodeObject.getTransformedPaths()
726 def getUniqueQuoteIndex( uniqueQuoteIndex, word ):
727 'Get uniqueQuoteIndex.'
728 uniqueQuoteIndex += 1
729 while getTokenByNumber(uniqueQuoteIndex) in word:
730 uniqueQuoteIndex += 1
731 return uniqueQuoteIndex
733 def getUniqueToken(word):
736 for character in uniqueString:
737 if character not in word:
741 for character in uniqueString:
742 uniqueToken = character + str(uniqueNumber)
743 if uniqueToken not in word:
747 def getVector3ByDictionary( dictionary, vector3 ):
748 'Get vector3 by dictionary.'
749 if 'x' in dictionary:
750 vector3 = getVector3IfNone(vector3)
751 vector3.x = euclidean.getFloatFromValue(dictionary['x'])
752 if 'y' in dictionary:
753 vector3 = getVector3IfNone(vector3)
754 vector3.y = euclidean.getFloatFromValue(dictionary['y'])
755 if 'z' in dictionary:
756 vector3 = getVector3IfNone(vector3)
757 vector3.z = euclidean.getFloatFromValue( dictionary['z'] )
760 def getVector3ByDictionaryListValue(value, vector3):
761 'Get vector3 by dictionary, list or value.'
762 if value.__class__ == Vector3 or value.__class__.__name__ == 'Vector3Index':
764 if value.__class__ == dict:
765 return getVector3ByDictionary(value, vector3)
766 if value.__class__ == list:
767 return getVector3ByFloatList(value, vector3)
768 floatFromValue = euclidean.getFloatFromValue(value)
769 if floatFromValue == None:
771 vector3.setToXYZ(floatFromValue, floatFromValue, floatFromValue)
774 def getVector3ByFloatList(floatList, vector3):
775 'Get vector3 by float list.'
776 if len(floatList) > 0:
777 vector3 = getVector3IfNone(vector3)
778 vector3.x = euclidean.getFloatFromValue(floatList[0])
779 if len(floatList) > 1:
780 vector3 = getVector3IfNone(vector3)
781 vector3.y = euclidean.getFloatFromValue(floatList[1])
782 if len(floatList) > 2:
783 vector3 = getVector3IfNone(vector3)
784 vector3.z = euclidean.getFloatFromValue(floatList[2])
787 def getVector3ByMultiplierPrefix( elementNode, multiplier, prefix, vector3 ):
788 'Get vector3 from multiplier, prefix and xml element.'
789 if multiplier == 0.0:
791 oldMultipliedValueVector3 = vector3 * multiplier
792 vector3ByPrefix = getVector3ByPrefix(oldMultipliedValueVector3.copy(), elementNode, prefix)
793 if vector3ByPrefix == oldMultipliedValueVector3:
795 return vector3ByPrefix / multiplier
797 def getVector3ByMultiplierPrefixes( elementNode, multiplier, prefixes, vector3 ):
798 'Get vector3 from multiplier, prefixes and xml element.'
799 for prefix in prefixes:
800 vector3 = getVector3ByMultiplierPrefix( elementNode, multiplier, prefix, vector3 )
803 def getVector3ByPrefix(defaultVector3, elementNode, prefix):
804 'Get vector3 from prefix and xml element.'
805 value = getEvaluatedValue(None, elementNode, prefix)
807 defaultVector3 = getVector3ByDictionaryListValue(value, defaultVector3)
808 prefix = archive.getUntilDot(prefix)
809 x = getEvaluatedFloat(None, elementNode, prefix + '.x')
811 defaultVector3 = getVector3IfNone(defaultVector3)
813 y = getEvaluatedFloat(None, elementNode, prefix + '.y')
815 defaultVector3 = getVector3IfNone(defaultVector3)
817 z = getEvaluatedFloat(None, elementNode, prefix + '.z')
819 defaultVector3 = getVector3IfNone(defaultVector3)
821 return defaultVector3
823 def getVector3ByPrefixes( elementNode, prefixes, vector3 ):
824 'Get vector3 from prefixes and xml element.'
825 for prefix in prefixes:
826 vector3 = getVector3ByPrefix(vector3, elementNode, prefix)
829 def getVector3FromElementNode(elementNode):
830 'Get vector3 from xml element.'
832 getEvaluatedFloat(0.0, elementNode, 'x'),
833 getEvaluatedFloat(0.0, elementNode, 'y'),
834 getEvaluatedFloat(0.0, elementNode, 'z'))
835 return getVector3ByPrefix(vector3, elementNode, 'cartesian')
837 def getVector3IfNone(vector3):
838 'Get new vector3 if the original vector3 is none.'
843 def getVector3ListsRecursively(floatLists):
844 'Get vector3 lists recursively.'
845 if len(floatLists) < 1:
847 firstElement = floatLists[0]
848 if firstElement.__class__ == Vector3:
850 if firstElement.__class__ != list:
851 return getVector3ByFloatList(floatLists, Vector3())
852 vector3ListsRecursively = []
853 for floatList in floatLists:
854 vector3ListsRecursively.append(getVector3ListsRecursively(floatList))
855 return vector3ListsRecursively
857 def getVisibleObjects(archivableObjects):
858 'Get the visible objects.'
860 for archivableObject in archivableObjects:
861 if archivableObject.getVisible():
862 visibleObjects.append(archivableObject)
863 return visibleObjects
865 def processArchivable(archivableClass, elementNode):
866 'Get any new elements and process the archivable.'
867 if elementNode == None:
869 elementNode.xmlObject = archivableClass()
870 elementNode.xmlObject.setToElementNode(elementNode)
871 elementNode.getXMLProcessor().processChildNodes(elementNode)
873 def processCondition(elementNode):
874 'Process the xml element condition.'
875 xmlProcessor = elementNode.getXMLProcessor()
876 if elementNode.xmlObject == None:
877 elementNode.xmlObject = ModuleElementNode(elementNode)
878 if elementNode.xmlObject.conditionSplitWords == None:
880 if len(xmlProcessor.functions ) < 1:
881 print('Warning, the (in) element is not in a function in processCondition in evaluate for:')
884 if int(getEvaluatedExpressionValueBySplitLine(elementNode, elementNode.xmlObject.conditionSplitWords)) > 0:
885 xmlProcessor.functions[-1].processChildNodes(elementNode)
887 elementNode.xmlObject.processElse(elementNode)
889 def removeIdentifiersFromDictionary(dictionary):
890 'Remove the identifier elements from a dictionary.'
891 euclidean.removeElementsFromDictionary(dictionary, ['id', 'name', 'tags'])
894 def setAttributesByArguments(argumentNames, arguments, elementNode):
895 'Set the attribute dictionary to the arguments.'
896 for argumentIndex, argument in enumerate(arguments):
897 elementNode.attributes[argumentNames[argumentIndex]] = argument
899 def setFunctionLocalDictionary(arguments, function):
900 'Evaluate the function statement and delete the evaluators.'
901 function.localDictionary = {'_arguments' : arguments}
902 if len(arguments) > 0:
903 firstArgument = arguments[0]
904 if firstArgument.__class__ == dict:
905 function.localDictionary = firstArgument
907 if 'parameters' not in function.elementNode.attributes:
909 parameters = function.elementNode.attributes['parameters'].strip()
912 parameterWords = parameters.split(',')
913 for parameterWordIndex, parameterWord in enumerate(parameterWords):
914 strippedWord = parameterWord.strip()
915 keyValue = KeyValue().getByEqual(strippedWord)
916 if parameterWordIndex < len(arguments):
917 function.localDictionary[keyValue.key] = arguments[parameterWordIndex]
919 strippedValue = keyValue.value
920 if strippedValue == None:
921 print('Warning there is no default parameter in getParameterValue for:')
923 print(parameterWords)
925 print(function.elementNode.attributes)
927 strippedValue = strippedValue.strip()
928 function.localDictionary[keyValue.key.strip()] = strippedValue
929 if len(arguments) > len(parameterWords):
930 print('Warning there are too many initializeFunction parameters for:')
931 print(function.elementNode.attributes)
932 print(parameterWords)
935 def setLocalAttribute(elementNode):
936 'Set the local attribute if any.'
937 if elementNode.xmlObject != None:
939 for key in elementNode.attributes:
940 if key[: 1].isalpha():
941 value = getEvaluatorSplitWords(getLocalAttributeValueString(key, elementNode.attributes[key].strip()))
942 elementNode.xmlObject = KeyValue(key, value)
944 elementNode.xmlObject = KeyValue()
948 'Class to get equation results.'
949 def __init__(self, elementNode):
951 self.elementNode = elementNode
952 self.localDictionary = {}
953 self.xmlProcessor = elementNode.getXMLProcessor()
956 'Get the string representation of this Class.'
957 return str(self.__dict__)
959 def getReturnValue(self):
961 self.getReturnValueWithoutDeletion()
962 del self.xmlProcessor.functions[-1]
963 return self.returnValue
965 def processChildNodes(self, elementNode):
966 'Process childNodes if shouldReturn is false.'
967 for childNode in elementNode.childNodes:
968 if self.shouldReturn:
970 self.xmlProcessor.processElementNode(childNode)
973 class ClassFunction(BaseFunction):
974 'Class to get class results.'
975 def getReturnValueByArguments(self, *arguments):
976 'Get return value by arguments.'
977 setFunctionLocalDictionary(arguments, self)
978 return self.getReturnValue()
980 def getReturnValueWithoutDeletion(self):
981 'Get return value without deleting last function.'
982 self.returnValue = None
983 self.shouldReturn = False
984 self.xmlProcessor.functions.append(self)
985 self.processChildNodes(self.elementNode)
986 return self.returnValue
990 'Class to hold class attributes and functions.'
991 def __init__(self, elementNode):
993 self.functionDictionary = elementNode.xmlObject.functionDictionary
994 self.selfDictionary = {}
995 for variable in elementNode.xmlObject.variables:
996 self.selfDictionary[variable] = None
999 'Get the string representation of this Class.'
1000 return str(self.__dict__)
1002 def _getAccessibleAttribute(self, attributeName):
1003 'Get the accessible attribute.'
1004 if attributeName in self.selfDictionary:
1005 return self.selfDictionary[attributeName]
1006 if attributeName in self.functionDictionary:
1007 function = self.functionDictionary[attributeName]
1008 function.classObject = self
1009 return function.getReturnValueByArguments
1012 def _setAccessibleAttribute(self, attributeName, value):
1013 'Set the accessible attribute.'
1014 if attributeName in self.selfDictionary:
1015 self.selfDictionary[attributeName] = value
1026 'Base evaluator class.'
1027 def __init__(self, elementNode, word):
1028 'Set value to none.'
1033 'Get the string representation of this Class.'
1034 return str(self.__dict__)
1036 def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ):
1037 'Execute the bracket.'
1040 def executeCenterOperation(self, evaluators, evaluatorIndex):
1041 'Execute operator which acts on the center.'
1044 def executeDictionary(self, dictionary, evaluators, keys, evaluatorIndex, nextEvaluator):
1045 'Execute the dictionary.'
1046 del evaluators[evaluatorIndex]
1047 enumeratorKeys = euclidean.getEnumeratorKeys(dictionary, keys)
1048 if enumeratorKeys.__class__ == list:
1049 nextEvaluator.value = []
1050 for enumeratorKey in enumeratorKeys:
1051 if enumeratorKey in dictionary:
1052 nextEvaluator.value.append(dictionary[enumeratorKey])
1054 print('Warning, key in executeKey in Evaluator in evaluate is not in for:')
1055 print(enumeratorKey)
1058 if enumeratorKeys in dictionary:
1059 nextEvaluator.value = dictionary[enumeratorKeys]
1061 print('Warning, key in executeKey in Evaluator in evaluate is not in for:')
1062 print(enumeratorKeys)
1065 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1066 'Execute the function.'
1069 def executeKey(self, evaluators, keys, evaluatorIndex, nextEvaluator):
1070 'Execute the key index.'
1071 if self.value.__class__ == str:
1072 self.executeString(evaluators, keys, evaluatorIndex, nextEvaluator)
1074 if self.value.__class__ == list:
1075 self.executeList(evaluators, keys, evaluatorIndex, nextEvaluator)
1077 if self.value.__class__ == dict:
1078 self.executeDictionary(self.value, evaluators, keys, evaluatorIndex, nextEvaluator)
1080 getAccessibleDictionaryFunction = getattr(self.value, '_getAccessibleDictionary', None)
1081 if getAccessibleDictionaryFunction != None:
1082 self.executeDictionary(getAccessibleDictionaryFunction(), evaluators, keys, evaluatorIndex, nextEvaluator)
1084 if self.value.__class__.__name__ != 'ElementNode':
1086 del evaluators[evaluatorIndex]
1087 enumeratorKeys = euclidean.getEnumeratorKeys(self.value.attributes, keys)
1088 if enumeratorKeys.__class__ == list:
1089 nextEvaluator.value = []
1090 for enumeratorKey in enumeratorKeys:
1091 if enumeratorKey in self.value.attributes:
1092 nextEvaluator.value.append(getEvaluatedExpressionValue(self.value, self.value.attributes[enumeratorKey]))
1094 print('Warning, key in executeKey in Evaluator in evaluate is not in for:')
1095 print(enumeratorKey)
1096 print(self.value.attributes)
1098 if enumeratorKeys in self.value.attributes:
1099 nextEvaluator.value = getEvaluatedExpressionValue(self.value, self.value.attributes[enumeratorKeys])
1101 print('Warning, key in executeKey in Evaluator in evaluate is not in for:')
1102 print(enumeratorKeys)
1103 print(self.value.attributes)
1105 def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel):
1106 'Execute operator which acts from the left.'
1109 def executeList(self, evaluators, keys, evaluatorIndex, nextEvaluator):
1110 'Execute the key index.'
1111 del evaluators[evaluatorIndex]
1112 enumeratorKeys = euclidean.getEnumeratorKeys(self.value, keys)
1113 if enumeratorKeys.__class__ == list:
1114 nextEvaluator.value = []
1115 for enumeratorKey in enumeratorKeys:
1116 intKey = euclidean.getIntFromValue(enumeratorKey)
1117 if self.getIsInRange(intKey):
1118 nextEvaluator.value.append(self.value[intKey])
1120 print('Warning, key in executeList in Evaluator in evaluate is not in for:')
1121 print(enumeratorKey)
1124 intKey = euclidean.getIntFromValue(enumeratorKeys)
1125 if self.getIsInRange(intKey):
1126 nextEvaluator.value = self.value[intKey]
1128 print('Warning, key in executeList in Evaluator in evaluate is not in for:')
1129 print(enumeratorKeys)
1132 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1133 'Operate on two evaluators.'
1136 def executeRightOperation( self, evaluators, evaluatorIndex ):
1137 'Execute operator which acts from the right.'
1140 def executeString(self, evaluators, keys, evaluatorIndex, nextEvaluator):
1141 'Execute the string.'
1142 del evaluators[evaluatorIndex]
1143 enumeratorKeys = euclidean.getEnumeratorKeys(self.value, keys)
1144 if enumeratorKeys.__class__ == list:
1145 nextEvaluator.value = ''
1146 for enumeratorKey in enumeratorKeys:
1147 intKey = euclidean.getIntFromValue(enumeratorKey)
1148 if self.getIsInRange(intKey):
1149 nextEvaluator.value += self.value[intKey]
1151 print('Warning, key in executeString in Evaluator in evaluate is not in for:')
1152 print(enumeratorKey)
1155 intKey = euclidean.getIntFromValue(enumeratorKeys)
1156 if self.getIsInRange(intKey):
1157 nextEvaluator.value = self.value[intKey]
1159 print('Warning, key in executeString in Evaluator in evaluate is not in for:')
1160 print(enumeratorKeys)
1163 def getIsInRange(self, keyIndex):
1164 'Determine if the keyIndex is in range.'
1165 if keyIndex == None:
1167 return keyIndex >= -len(self.value) and keyIndex < len(self.value)
1170 class EvaluatorAddition(Evaluator):
1171 'Class to add two evaluators.'
1172 def executePair( self, evaluators, evaluatorIndex ):
1173 'Add two evaluators.'
1174 leftIndex = evaluatorIndex - 1
1175 rightIndex = evaluatorIndex + 1
1177 print('Warning, no leftKey in executePair in EvaluatorAddition for:')
1179 print(evaluatorIndex)
1181 del evaluators[evaluatorIndex]
1183 if rightIndex >= len(evaluators):
1184 print('Warning, no rightKey in executePair in EvaluatorAddition for:')
1186 print(evaluatorIndex)
1188 del evaluators[evaluatorIndex]
1190 rightValue = evaluators[rightIndex].value
1191 evaluators[leftIndex].value = self.getOperationValue(evaluators[leftIndex].value, evaluators[rightIndex].value)
1192 del evaluators[ evaluatorIndex : evaluatorIndex + 2 ]
1194 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1195 'Operate on two evaluators.'
1196 if operationLevel == 20:
1197 self.executePair(evaluators, evaluatorIndex)
1199 def getEvaluatedValues(self, enumerable, keys, value):
1200 'Get evaluatedValues.'
1201 if enumerable.__class__ == dict:
1202 evaluatedValues = {}
1204 evaluatedValues[key] = self.getOperationValue(value, enumerable[key])
1205 return evaluatedValues
1206 evaluatedValues = []
1208 evaluatedValues.append(self.getOperationValue(value, enumerable[key]))
1209 return evaluatedValues
1211 def getOperationValue(self, leftValue, rightValue):
1212 'Get operation value.'
1213 leftKeys = getKeys(leftValue)
1214 rightKeys = getKeys(rightValue)
1215 if leftKeys == None and rightKeys == None:
1216 return self.getValueFromValuePair(leftValue, rightValue)
1217 if leftKeys == None:
1218 return self.getEvaluatedValues(rightValue, rightKeys, leftValue)
1219 if rightKeys == None:
1220 return self.getEvaluatedValues(leftValue, leftKeys, rightValue)
1221 leftKeys.sort(reverse=True)
1222 rightKeys.sort(reverse=True)
1223 if leftKeys != rightKeys:
1224 print('Warning, the leftKeys are different from the rightKeys in getOperationValue in EvaluatorAddition for:')
1233 if leftValue.__class__ == dict or rightValue.__class__ == dict:
1234 evaluatedValues = {}
1235 for leftKey in leftKeys:
1236 evaluatedValues[leftKey] = self.getOperationValue(leftValue[leftKey], rightValue[leftKey])
1237 return evaluatedValues
1238 evaluatedValues = []
1239 for leftKey in leftKeys:
1240 evaluatedValues.append(self.getOperationValue(leftValue[leftKey], rightValue[leftKey]))
1241 return evaluatedValues
1243 def getValueFromValuePair(self, leftValue, rightValue):
1245 return leftValue + rightValue
1248 class EvaluatorEqual(EvaluatorAddition):
1249 'Class to compare two evaluators.'
1250 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1251 'Operate on two evaluators.'
1252 if operationLevel == 15:
1253 self.executePair(evaluators, evaluatorIndex)
1255 def getBooleanFromValuePair(self, leftValue, rightValue):
1256 'Compare two values.'
1257 return leftValue == rightValue
1259 def getValueFromValuePair(self, leftValue, rightValue):
1260 'Get value from comparison.'
1261 return self.getBooleanFromValuePair(leftValue, rightValue)
1264 class EvaluatorSubtraction(EvaluatorAddition):
1265 'Class to subtract two evaluators.'
1266 def executeLeft( self, evaluators, evaluatorIndex ):
1267 'Minus the value to the right.'
1268 leftIndex = evaluatorIndex - 1
1269 rightIndex = evaluatorIndex + 1
1272 leftValue = evaluators[leftIndex].value
1273 if leftValue != None:
1275 rightValue = evaluators[rightIndex].value
1276 if rightValue == None:
1277 print('Warning, can not minus.')
1278 print(evaluators[rightIndex].word)
1280 evaluators[rightIndex].value = self.getNegativeValue(rightValue)
1281 del evaluators[evaluatorIndex]
1283 def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel):
1284 'Minus the value to the right.'
1285 if operationLevel == 200:
1286 self.executeLeft(evaluators, evaluatorIndex)
1288 def getNegativeValue( self, value ):
1289 'Get the negative value.'
1290 keys = getKeys(value)
1292 return self.getValueFromSingleValue(value)
1294 value[key] = self.getNegativeValue(value[key])
1297 def getValueFromSingleValue( self, value ):
1301 def getValueFromValuePair(self, leftValue, rightValue):
1302 'Subtract two values.'
1303 return leftValue - rightValue
1306 class EvaluatorAnd(EvaluatorAddition):
1307 'Class to compare two evaluators.'
1308 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1309 'Operate on two evaluators.'
1310 if operationLevel == 12:
1311 self.executePair(evaluators, evaluatorIndex)
1313 def getBooleanFromValuePair(self, leftValue, rightValue):
1315 return leftValue and rightValue
1317 def getValueFromValuePair(self, leftValue, rightValue):
1318 'Get value from comparison.'
1319 return self.getBooleanFromValuePair(leftValue, rightValue)
1322 class EvaluatorAttribute(Evaluator):
1323 'Class to handle an attribute.'
1324 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1325 'Execute the function.'
1326 executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator)
1328 def executeRightOperation( self, evaluators, evaluatorIndex ):
1329 'Execute operator which acts from the right.'
1330 attributeName = self.word[1 :]
1331 previousIndex = evaluatorIndex - 1
1332 previousEvaluator = evaluators[previousIndex]
1333 if previousEvaluator.value.__class__ == dict:
1334 from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import dictionary_attribute
1335 self.value = dictionary_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value)
1336 elif previousEvaluator.value.__class__ == list:
1337 from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import list_attribute
1338 self.value = list_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value)
1339 elif previousEvaluator.value.__class__ == str:
1340 from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import string_attribute
1341 self.value = string_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value)
1343 attributeKeywords = attributeName.split('.')
1344 self.value = previousEvaluator.value
1345 for attributeKeyword in attributeKeywords:
1346 self.value = getattr(self.value, '_getAccessibleAttribute', None)(attributeKeyword)
1347 if self.value == None:
1348 print('Warning, EvaluatorAttribute in evaluate can not get a getAccessibleAttributeFunction for:')
1349 print(attributeName)
1350 print(previousEvaluator.value)
1353 del evaluators[previousIndex]
1356 class EvaluatorBracketCurly(Evaluator):
1357 'Class to evaluate a string.'
1358 def executeBracket(self, bracketBeginIndex, bracketEndIndex, evaluators):
1359 'Execute the bracket.'
1360 for evaluatorIndex in xrange(bracketEndIndex - 3, bracketBeginIndex, - 1):
1361 bracketEndIndex = getEndIndexConvertEquationValue(bracketEndIndex, evaluatorIndex, evaluators)
1362 evaluatedExpressionValueEvaluators = getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators)
1364 for evaluatedExpressionValueEvaluator in evaluatedExpressionValueEvaluators:
1365 keyValue = evaluatedExpressionValueEvaluator.value
1366 self.value[keyValue.key] = keyValue.value
1367 del evaluators[bracketBeginIndex + 1: bracketEndIndex + 1]
1370 class EvaluatorBracketRound(Evaluator):
1371 'Class to evaluate a string.'
1372 def __init__(self, elementNode, word):
1373 'Set value to none.'
1378 def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ):
1379 'Execute the bracket.'
1380 self.arguments = getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators)
1381 if len( self.arguments ) < 1:
1383 if len( self.arguments ) > 1:
1384 self.value = self.arguments
1386 self.value = self.arguments[0]
1388 def executeRightOperation( self, evaluators, evaluatorIndex ):
1389 'Evaluate the statement and delete the evaluators.'
1390 previousIndex = evaluatorIndex - 1
1391 if previousIndex < 0:
1393 evaluators[ previousIndex ].executeFunction( evaluators, previousIndex, self )
1396 class EvaluatorBracketSquare(Evaluator):
1397 'Class to evaluate a string.'
1398 def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ):
1399 'Execute the bracket.'
1400 self.value = getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators)
1402 def executeRightOperation( self, evaluators, evaluatorIndex ):
1403 'Evaluate the statement and delete the evaluators.'
1404 previousIndex = evaluatorIndex - 1
1405 if previousIndex < 0:
1407 if self.value.__class__ != list:
1409 evaluators[ previousIndex ].executeKey( evaluators, self.value, previousIndex, self )
1412 class EvaluatorClass(Evaluator):
1413 'Class evaluator class.'
1414 def __init__(self, elementNode, word):
1415 'Set value to none.'
1416 self.elementNode = elementNode
1420 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1421 'Execute the function.'
1422 if self.elementNode.xmlObject == None:
1423 self.elementNode.xmlObject = FunctionVariable(self.elementNode)
1424 nextEvaluator.value = ClassObject(self.elementNode)
1425 initializeFunction = None
1426 if '_init' in self.elementNode.xmlObject.functionDictionary:
1427 function = self.elementNode.xmlObject.functionDictionary['_init']
1428 function.classObject = nextEvaluator.value
1429 setFunctionLocalDictionary(nextEvaluator.arguments, function)
1430 function.getReturnValue()
1431 del evaluators[evaluatorIndex]
1434 class EvaluatorComma(Evaluator):
1435 'Class to join two evaluators.'
1436 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1437 'Operate on two evaluators.'
1438 if operationLevel != 0:
1440 previousIndex = evaluatorIndex - 1
1441 if previousIndex < 0:
1442 evaluators[evaluatorIndex].value = None
1444 if evaluators[previousIndex].word == ',':
1445 evaluators[evaluatorIndex].value = None
1447 del evaluators[evaluatorIndex]
1450 class EvaluatorConcatenate(Evaluator):
1451 'Class to join two evaluators.'
1452 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1453 'Operate on two evaluators.'
1454 if operationLevel != 80:
1456 leftIndex = evaluatorIndex - 1
1458 del evaluators[evaluatorIndex]
1460 rightIndex = evaluatorIndex + 1
1461 if rightIndex >= len(evaluators):
1462 del evaluators[ leftIndex : rightIndex ]
1464 leftValue = evaluators[leftIndex].value
1465 rightValue = evaluators[rightIndex].value
1466 if leftValue.__class__ == rightValue.__class__ and (leftValue.__class__ == list or rightValue.__class__ == str):
1467 evaluators[leftIndex].value = leftValue + rightValue
1468 del evaluators[ evaluatorIndex : evaluatorIndex + 2 ]
1470 if leftValue.__class__ == list and rightValue.__class__ == int:
1472 originalList = leftValue[:]
1473 for copyIndex in xrange( rightValue - 1 ):
1474 leftValue += originalList
1475 evaluators[leftIndex].value = leftValue
1476 del evaluators[ evaluatorIndex : evaluatorIndex + 2 ]
1478 if leftValue.__class__ == dict and rightValue.__class__ == dict:
1479 leftValue.update(rightValue)
1480 evaluators[leftIndex].value = leftValue
1481 del evaluators[ evaluatorIndex : evaluatorIndex + 2 ]
1483 del evaluators[ leftIndex : evaluatorIndex + 2 ]
1486 class EvaluatorDictionary(Evaluator):
1487 'Class to join two evaluators.'
1488 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1489 'Operate on two evaluators.'
1490 if operationLevel != 10:
1492 leftEvaluatorIndex = evaluatorIndex - 1
1493 if leftEvaluatorIndex < 0:
1494 print('Warning, leftEvaluatorIndex is less than zero in EvaluatorDictionary for:')
1498 rightEvaluatorIndex = evaluatorIndex + 1
1499 if rightEvaluatorIndex >= len(evaluators):
1500 print('Warning, rightEvaluatorIndex too high in EvaluatorDictionary for:')
1501 print(rightEvaluatorIndex)
1505 evaluators[rightEvaluatorIndex].value = KeyValue(evaluators[leftEvaluatorIndex].value, evaluators[rightEvaluatorIndex].value)
1506 del evaluators[ leftEvaluatorIndex : rightEvaluatorIndex ]
1509 class EvaluatorDivision(EvaluatorAddition):
1510 'Class to divide two evaluators.'
1511 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1512 'Operate on two evaluators.'
1513 if operationLevel == 40:
1514 self.executePair(evaluators, evaluatorIndex)
1516 def getValueFromValuePair(self, leftValue, rightValue):
1517 'Divide two values.'
1518 return leftValue / rightValue
1521 class EvaluatorElement(Evaluator):
1522 'Element evaluator class.'
1523 def __init__(self, elementNode, word):
1524 'Set value to none.'
1525 self.elementNode = elementNode
1529 def executeCenterOperation(self, evaluators, evaluatorIndex):
1530 'Execute operator which acts on the center.'
1531 dotIndex = self.word.find('.')
1533 print('Warning, EvaluatorElement in evaluate can not find the dot for:')
1537 attributeName = self.word[dotIndex + 1 :]
1538 moduleName = self.word[: dotIndex]
1539 if moduleName in globalModuleFunctionsDictionary:
1540 self.value = globalModuleFunctionsDictionary[moduleName](attributeName, self.elementNode)
1543 if moduleName in globalElementNameSet:
1544 pluginModule = archive.getModuleWithPath(archive.getElementsPath(moduleName))
1545 if pluginModule == None:
1546 print('Warning, EvaluatorElement in evaluate can not get a pluginModule for:')
1550 getAccessibleAttributeFunction = pluginModule._getAccessibleAttribute
1551 globalModuleFunctionsDictionary[moduleName] = getAccessibleAttributeFunction
1552 self.value = getAccessibleAttributeFunction(attributeName, self.elementNode)
1554 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1555 'Execute the function.'
1556 executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator)
1559 class EvaluatorFalse(Evaluator):
1560 'Class to evaluate a string.'
1561 def __init__(self, elementNode, word):
1562 'Set value to zero.'
1567 class EvaluatorFunction(Evaluator):
1568 'Function evaluator class.'
1569 def __init__(self, elementNode, word):
1570 'Set value to none.'
1571 self.elementNode = elementNode
1575 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1576 'Execute the function.'
1577 if self.elementNode.xmlObject == None:
1578 if 'return' in self.elementNode.attributes:
1579 value = self.elementNode.attributes['return']
1580 self.elementNode.xmlObject = getEvaluatorSplitWords(value)
1582 self.elementNode.xmlObject = []
1583 self.function = Function(self.elementNode )
1584 setFunctionLocalDictionary(nextEvaluator.arguments, self.function)
1585 nextEvaluator.value = self.function.getReturnValue()
1586 del evaluators[evaluatorIndex]
1589 class EvaluatorFundamental(Evaluator):
1590 'Fundamental evaluator class.'
1591 def executeCenterOperation(self, evaluators, evaluatorIndex):
1592 'Execute operator which acts on the center.'
1593 dotIndex = self.word.find('.')
1595 print('Warning, EvaluatorFundamental in evaluate can not find the dot for:')
1599 attributeName = self.word[dotIndex + 1 :]
1600 moduleName = self.word[: dotIndex]
1601 if moduleName in globalModuleFunctionsDictionary:
1602 self.value = globalModuleFunctionsDictionary[moduleName](attributeName)
1605 if moduleName in globalFundamentalNameSet:
1606 pluginModule = archive.getModuleWithPath(archive.getFundamentalsPath(moduleName))
1608 underscoredName = '_' + moduleName
1609 if underscoredName in globalFundamentalNameSet:
1610 pluginModule = archive.getModuleWithPath(archive.getFundamentalsPath(underscoredName))
1611 if pluginModule == None:
1612 print('Warning, EvaluatorFundamental in evaluate can not get a pluginModule for:')
1616 getAccessibleAttributeFunction = pluginModule._getAccessibleAttribute
1617 globalModuleFunctionsDictionary[moduleName] = getAccessibleAttributeFunction
1618 self.value = getAccessibleAttributeFunction(attributeName)
1620 def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator):
1621 'Execute the function.'
1622 executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator)
1625 class EvaluatorGreaterEqual( EvaluatorEqual ):
1626 'Class to compare two evaluators.'
1627 def getBooleanFromValuePair(self, leftValue, rightValue):
1628 'Compare two values.'
1629 return leftValue >= rightValue
1632 class EvaluatorGreater( EvaluatorEqual ):
1633 'Class to compare two evaluators.'
1634 def getBooleanFromValuePair(self, leftValue, rightValue):
1635 'Compare two values.'
1636 return leftValue > rightValue
1639 class EvaluatorLessEqual( EvaluatorEqual ):
1640 'Class to compare two evaluators.'
1641 def getBooleanFromValuePair(self, leftValue, rightValue):
1642 'Compare two values.'
1643 return leftValue <= rightValue
1646 class EvaluatorLess( EvaluatorEqual ):
1647 'Class to compare two evaluators.'
1648 def getBooleanFromValuePair(self, leftValue, rightValue):
1649 'Compare two values.'
1650 return leftValue < rightValue
1653 class EvaluatorLocal(EvaluatorElement):
1654 'Class to get a local variable.'
1655 def executeCenterOperation(self, evaluators, evaluatorIndex):
1656 'Execute operator which acts on the center.'
1657 functions = self.elementNode.getXMLProcessor().functions
1658 if len(functions) < 1:
1659 print('Warning, there are no functions in EvaluatorLocal in evaluate for:')
1662 attributeKeywords = self.word.split('.')
1663 self.value = functions[-1].localDictionary[attributeKeywords[0]]
1664 for attributeKeyword in attributeKeywords[1 :]:
1665 self.value = self.value._getAccessibleAttribute(attributeKeyword)
1668 class EvaluatorModulo( EvaluatorDivision ):
1669 'Class to modulo two evaluators.'
1670 def getValueFromValuePair(self, leftValue, rightValue):
1671 'Modulo two values.'
1672 return leftValue % rightValue
1675 class EvaluatorMultiplication( EvaluatorDivision ):
1676 'Class to multiply two evaluators.'
1677 def getValueFromValuePair(self, leftValue, rightValue):
1678 'Multiply two values.'
1679 return leftValue * rightValue
1682 class EvaluatorNone(Evaluator):
1683 'Class to evaluate None.'
1684 def __init__(self, elementNode, word):
1685 'Set value to none.'
1687 self.word = str(word)
1690 class EvaluatorNot(EvaluatorSubtraction):
1691 'Class to compare two evaluators.'
1692 def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel):
1693 'Minus the value to the right.'
1694 if operationLevel == 13:
1695 self.executeLeft(evaluators, evaluatorIndex)
1697 def getValueFromSingleValue( self, value ):
1702 class EvaluatorNotEqual( EvaluatorEqual ):
1703 'Class to compare two evaluators.'
1704 def getBooleanFromValuePair(self, leftValue, rightValue):
1705 'Compare two values.'
1706 return leftValue != rightValue
1709 class EvaluatorNumeric(Evaluator):
1710 'Class to evaluate a string.'
1711 def __init__(self, elementNode, word):
1717 self.value = float(word)
1719 self.value = int(word)
1721 print('Warning, EvaluatorNumeric in evaluate could not get a numeric value for:')
1726 class EvaluatorOr( EvaluatorAnd ):
1727 'Class to compare two evaluators.'
1728 def getBooleanFromValuePair(self, leftValue, rightValue):
1730 return leftValue or rightValue
1733 class EvaluatorPower(EvaluatorAddition):
1734 'Class to power two evaluators.'
1735 def executePairOperation(self, evaluators, evaluatorIndex, operationLevel):
1736 'Operate on two evaluators.'
1737 if operationLevel == 60:
1738 self.executePair(evaluators, evaluatorIndex)
1740 def getValueFromValuePair(self, leftValue, rightValue):
1741 'Power of two values.'
1742 return leftValue ** rightValue
1745 class EvaluatorSelf(EvaluatorElement):
1746 'Class to handle self.'
1747 def executeCenterOperation(self, evaluators, evaluatorIndex):
1748 'Execute operator which acts on the center.'
1749 functions = self.elementNode.getXMLProcessor().functions
1750 if len(functions) < 1:
1751 print('Warning, there are no functions in executeCenterOperation in EvaluatorSelf in evaluate for:')
1752 print(self.elementNode)
1754 function = functions[-1]
1755 attributeKeywords = self.word.split('.')
1756 self.value = function.classObject
1757 for attributeKeyword in attributeKeywords[1 :]:
1758 self.value = self.value._getAccessibleAttribute(attributeKeyword)
1761 class EvaluatorTrue(Evaluator):
1762 'Class to evaluate a string.'
1763 def __init__(self, elementNode, word):
1764 'Set value to true.'
1769 class EvaluatorValue(Evaluator):
1770 'Class to evaluate a string.'
1771 def __init__(self, word):
1772 'Set value to none.'
1774 self.word = str(word)
1777 class Function(BaseFunction):
1778 'Class to get equation results.'
1779 def __init__(self, elementNode):
1781 self.elementNode = elementNode
1782 self.evaluatorSplitLine = elementNode.xmlObject
1783 self.localDictionary = {}
1784 self.xmlProcessor = elementNode.getXMLProcessor()
1786 def getReturnValueWithoutDeletion(self):
1787 'Get return value without deleting last function.'
1788 self.returnValue = None
1789 self.xmlProcessor.functions.append(self)
1790 if len(self.evaluatorSplitLine) < 1:
1791 self.shouldReturn = False
1792 self.processChildNodes(self.elementNode)
1794 self.returnValue = getEvaluatedExpressionValueBySplitLine(self.elementNode, self.evaluatorSplitLine)
1795 return self.returnValue
1798 class FunctionVariable:
1799 'Class to hold class functions and variable set.'
1800 def __init__(self, elementNode):
1802 self.functionDictionary = {}
1804 self.processClass(elementNode)
1806 def addToVariableSet(self, elementNode):
1808 setLocalAttribute(elementNode)
1809 keySplitLine = elementNode.xmlObject.key.split('.')
1810 if len(keySplitLine) == 2:
1811 if keySplitLine[0] == 'self':
1812 variable = keySplitLine[1]
1813 if variable not in self.variables:
1814 self.variables.append(variable)
1816 def processClass(self, elementNode):
1817 'Add class to FunctionVariable.'
1818 for childNode in elementNode.childNodes:
1819 self.processFunction(childNode)
1820 if 'parentNode' in elementNode.attributes:
1821 self.processClass(elementNode.getElementNodeByID(elementNode.attributes['parentNode']))
1823 def processFunction(self, elementNode):
1824 'Add function to function dictionary.'
1825 if elementNode.getNodeName() != 'function':
1827 idKey = elementNode.attributes['id']
1828 if idKey in self.functionDictionary:
1830 self.functionDictionary[idKey] = ClassFunction(elementNode)
1831 for childNode in elementNode.childNodes:
1832 self.processStatement(childNode)
1834 def processStatement(self, elementNode):
1835 'Add self statement to variables.'
1836 if elementNode.getNodeName() == 'statement':
1837 self.addToVariableSet(elementNode)
1838 for childNode in elementNode.childNodes:
1839 self.processStatement(childNode)
1843 'Class to hold a key value.'
1844 def __init__(self, key=None, value=None):
1850 'Get the string representation of this KeyValue.'
1851 return str(self.__dict__)
1853 def getByCharacter( self, character, line ):
1855 dotIndex = line.find( character )
1860 self.key = line[: dotIndex]
1861 self.value = line[dotIndex + 1 :]
1864 def getByDot(self, line):
1866 return self.getByCharacter('.', line )
1868 def getByEqual(self, line):
1870 return self.getByCharacter('=', line )
1873 class ModuleElementNode:
1874 'Class to get the in attribute, the index name and the value name.'
1875 def __init__( self, elementNode):
1877 self.conditionSplitWords = None
1878 self.elseElement = None
1879 if 'condition' in elementNode.attributes:
1880 self.conditionSplitWords = getEvaluatorSplitWords( elementNode.attributes['condition'] )
1882 print('Warning, could not find the condition attribute in ModuleElementNode in evaluate for:')
1885 if len( self.conditionSplitWords ) < 1:
1886 self.conditionSplitWords = None
1887 print('Warning, could not get split words for the condition attribute in ModuleElementNode in evaluate for:')
1889 nextIndex = getNextChildIndex(elementNode)
1890 if nextIndex >= len( elementNode.parentNode.childNodes ):
1892 nextElementNode = elementNode.parentNode.childNodes[ nextIndex ]
1893 lowerLocalName = nextElementNode.getNodeName().lower()
1894 if lowerLocalName != 'else' and lowerLocalName != 'elif':
1896 xmlProcessor = elementNode.getXMLProcessor()
1897 if lowerLocalName not in xmlProcessor.namePathDictionary:
1899 self.pluginModule = archive.getModuleWithPath( xmlProcessor.namePathDictionary[ lowerLocalName ] )
1900 if self.pluginModule == None:
1902 self.elseElement = nextElementNode
1904 def processElse(self, elementNode):
1905 'Process the else statement.'
1906 if self.elseElement != None:
1907 self.pluginModule.processElse( self.elseElement)
1910 globalCreationDictionary = archive.getGeometryDictionary('creation')
1911 globalDictionaryOperatorBegin = {
1912 '||' : EvaluatorConcatenate,
1913 '==' : EvaluatorEqual,
1914 '>=' : EvaluatorGreaterEqual,
1915 '<=' : EvaluatorLessEqual,
1916 '!=' : EvaluatorNotEqual,
1917 '**' : EvaluatorPower }
1918 globalModuleEvaluatorDictionary = {}
1919 globalFundamentalNameSet = set(archive.getPluginFileNamesFromDirectoryPath(archive.getFundamentalsPath()))
1920 addPrefixDictionary(globalModuleEvaluatorDictionary, globalFundamentalNameSet, EvaluatorFundamental)
1921 globalElementNameSet = set(archive.getPluginFileNamesFromDirectoryPath(archive.getElementsPath()))
1922 addPrefixDictionary(globalModuleEvaluatorDictionary, globalElementNameSet, EvaluatorElement)
1923 globalModuleEvaluatorDictionary['self'] = EvaluatorSelf
1924 globalSplitDictionaryOperator = {
1925 '+' : EvaluatorAddition,
1926 '{' : EvaluatorBracketCurly,
1928 '(' : EvaluatorBracketRound,
1930 '[' : EvaluatorBracketSquare,
1932 ',' : EvaluatorComma,
1933 ':' : EvaluatorDictionary,
1934 '/' : EvaluatorDivision,
1935 '>' : EvaluatorGreater,
1936 '<' : EvaluatorLess,
1937 '%' : EvaluatorModulo,
1938 '*' : EvaluatorMultiplication,
1939 '-' : EvaluatorSubtraction }
1940 globalSplitDictionary = getSplitDictionary() # must be after globalSplitDictionaryOperator