Source code for TXLWizard.Patterns.Structure

'''
Implements a class for `Structure` objects (`STRUCT`).\n
A `Structure` is a container for `Pattern` objects.
'''

import os.path
import sys
sys.path.append(os.path.abspath(os.path.dirname(__file__)+'/../'))

import AbstractPattern
from Helpers import Tuttifrutti
import copy
import importlib


[docs]class Structure(AbstractPattern.AbstractPattern): ''' Implements a class for `Structure` objects.\n Corresponds to the TXL command `STRUCT`.\n A `Structure` is a container for `Pattern` objects. Parameters --------- ID: str Unique identification of the structure. Also used when referencing to this structure. TXLOutput: bool, optional If set to False, the TXL Output is suppressed.\n Defaults to True **kwargs keyword arguments passed to the :class:`TXLWizard.Patterns.AbstractPattern.AbstractPattern` constructor. Can specify attributes of the current pattern. Examples -------- IGNORE: >>> import sys >>> import os.path >>> sys.path.append(os.path.abspath(os.path.dirname(__file__)+'/../../')) IGNORE Import required modules >>> import TXLWizard.TXLWriter Initialize TXLWriter >>> TXLWriter = TXLWizard.TXLWriter.TXLWriter() Create Content Structure >>> CircleStructure = TXLWriter.AddContentStructure('MyCircleID', ... TXLOutput = True ... ) >>> CircleStructure.AddPattern( ... 'Circle', ... Center=[0, 0], ... Radius=50, ... Layer=1 ... ) #doctest: +ELLIPSIS <TXLWizard.Patterns.Circle.Circle object at 0x...> Generate Files >>> TXLWriter.GenerateFiles('Tests/Results/Patterns/Structure') ''' def __init__(self, ID, **kwargs): super(Structure, self).__init__(**kwargs) #: str: specifies the type of the pattern. Set to 'Structure' self.Type = 'Structure' #: str: Unique identification of the structure. Also used when referencing to this structure. self.ID = ID #: list of :class:`TXLWizard.Patterns.AbstractPattern.AbstractPattern`: Patterns that are contained in this structure self.Patterns = [] #: bool: If set to False, the TXL Output is suppressed. self.TXLOutput = True #: dict: attribute values of the next pattern to be added. Default values are copied from `self.DefaultAttributes` self.CurrentAttributes = copy.copy(self.DefaultAttributes) for i in self.CurrentAttributes: if i in kwargs: self.CurrentAttributes[i] = kwargs[i] if 'TXLOutput' in kwargs: self.TXLOutput = kwargs['TXLOutput']
[docs] def AddPattern(self, PatternType, **kwargs): ''' Adds a `Pattern` of type `PatternType` to the structure. Creates an instance of `TXLWizard.Patterns.{PatternType}.{PatternType}`. The `kwargs` are passed to the corresponding constructor and allow specifying pattern parameters as defined in the constructor of the corresponding pattern class and attributes as defined in :class:`TXLWizard.Patterns.AbstractPattern.AbstractPattern`. Parameters ---------- PatternType: {'Array', 'Circle', 'Ellipse', 'Polygon', 'Polyline', 'Reference'} Type of the pattern to be added. **kwargs keyword arguments are passed to the corresponding constructor and allow specifying pattern parameters as defined in the constructor of the corresponding pattern class and attributes as defined in :class:`TXLWizard.Patterns.AbstractPattern.AbstractPattern`. Returns ------- :class:`TXLWizard.Patterns.{PatternType}.{PatternType}` returns the created pattern object ''' f = importlib.import_module('.' + PatternType, __package__) class_ = getattr(f, PatternType) kwargs['ParentStructure'] = self kwargs['TXLWriter'] = self._TXLWriter for i in self.CurrentAttributes: if i in kwargs: self.CurrentAttributes[i] = kwargs[i] elif self.CurrentAttributes[i] != None: kwargs[i] = self.CurrentAttributes[i] Pattern = class_(**kwargs) self.Patterns.append(Pattern) return Pattern
def GetTXLOutput(self): CurrentAttributes = copy.copy(self.DefaultAttributes) TXL = '' TXL += 'STRUCT ' + self.ID + '\n' # TXL += self._GetAttributesTXL(CurrentAttributes) for i in self.Patterns: NewCurrentAttributes = copy.copy(self.DefaultAttributes) AttributesChanged = False for j in i.Attributes: if i.Attributes[j] != None and CurrentAttributes[j] != i.Attributes[j]: NewCurrentAttributes[j] = i.Attributes[j] AttributesChanged = True elif CurrentAttributes[j] != None: NewCurrentAttributes[j] = CurrentAttributes[j] CurrentAttributes = NewCurrentAttributes if AttributesChanged: TXL += self._GetAttributesTXL(CurrentAttributes) TXL += i.GetTXLOutput() TXL += 'ENDSTRUCT' + '\n\n' return TXL def _GetAttributesTXL(self, Attributes): ''' Generates the TXL commands for the attributes given in `Attributes` Parameters ---------- Attributes: dict Dictionary with attributes and their values. Returns ------- str TXL commands for the attributes specified ''' AttributeMapping = { 'Layer': 'LAYER {:d}', 'DataType': 'DATATYPE {:d}', 'RotationAngle': 'ANGLE ' + self._GetFloatFormatString() + '', 'StrokeWidth': 'WIDTH ' + self._GetFloatFormatString() + '', 'ScaleFactor': 'MAG ' + self._GetFloatFormatString() + '' } TXL = '' for i in Attributes: if Attributes[i] != None: TXL += AttributeMapping[i].format(Attributes[i]) + '\n' return TXL def GetSVGOutput(self): CurrentAttributes = copy.copy(self.DefaultAttributes) SVG = '' SVG += '<g id="' + self.ID.replace('+', '') + '" ' + self._GetSVGAttributesString() + '>' + '\n' for i in self.Patterns: NewCurrentAttributes = copy.copy(self.DefaultAttributes) for j in i.Attributes: if i.Attributes[j] != None and CurrentAttributes[j] != i.Attributes[j]: NewCurrentAttributes[j] = i.Attributes[j] elif CurrentAttributes[j] != None: NewCurrentAttributes[j] = CurrentAttributes[j] CurrentAttributes = NewCurrentAttributes if abs(i._OriginPoint[0]) > 0 or abs(i._OriginPoint[1]) > 0: Transforms = [ ('translate(' + self._GetFloatFormatString() + ',' + self._GetFloatFormatString() + ')').format( i._OriginPoint[0], i._OriginPoint[1]) ] else: Transforms = [] SVGAttributes = self._GetPatternSVGAttributesString(i.Type, CurrentAttributes, { 'transform': Transforms }) SVG += ('' + '<g ' + SVGAttributes + '>' + '\n' + ' ' + i.GetSVGOutput() + '</g>' + '\n') SVG += '</g>' + '\n' return SVG def _GetPatternSVGAttributesString(self, PatternType, Attributes, OverrideSVGAttributes={}): ''' Generate SVG attributes according to the `PatternType` and `Attributes` specified. SVG attributes can also be overridden or added with `OverrideSVGAttributes` Parameters ---------- PatternType: str Type of the pattern Attributes: dict Attributes of the pattern OverrideSVGAttributes: dict Dictionary with SVG attributes that will be added or overridden. Returns ------- str SVG attributes ''' SVGAttributes = { 'style': [], 'class': [], 'transform': [] } Tuttifrutti.update(SVGAttributes, OverrideSVGAttributes, True) for i in Attributes: if Attributes[i] != None: if i == 'Layer': SVGAttributes['class'].append('Layer{:d}'.format(Attributes[i])) elif i == 'RotationAngle' and PatternType in ['Reference']: SVGAttributes['transform'].append( ('rotate(' + self._GetFloatFormatString() + ')').format(Attributes[i])) elif i == 'ScaleFactor' and PatternType in ['Reference']: SVGAttributes['transform'].append( ('scale(' + self._GetFloatFormatString() + ')').format(Attributes[i])) # if i == 'StrokeWidth' and False: # SVGAttributes['style'].append('stroke-width: {:1.4f}'.format(Attributes[i])) return super(Structure, self)._GetSVGAttributesString(SVGAttributes)