def RenderAnimatedPart(Data): """ Renders list of strings that will be injected to frame """ # ----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default # ----------------------------------------------------------------------------- # TODO: string concatenation is slow robot_sprite = "" path = "" sparks = "" side = 0.5 IT = tIndentTracker(' ') robot_sprite += SVGGroup( IT, { 'transform': 'rotate(%g %g %g)' % ((Data['ActualOrientation'] * 180 / pi) + 180.0, Data['ActualPosition'][0], Data['ActualPosition'][1]) }) # robot_sprite += SVGGroup(IT, {'transform': 'scale(2)'}) robot_sprite += IT( '<polygon points="%g,%g %g,%g %g,%g" style="fill:lime;' '' 'stroke:purple;stroke-width:0.06" />' % (Data['ActualPosition'][0] + side / 2.0, Data['ActualPosition'][1] - side / 2.0, Data['ActualPosition'][0] + side / 2.0, Data['ActualPosition'][1] + side / 2.0, Data['ActualPosition'][0] - side, Data['ActualPosition'][1])) robot_sprite += SVGGroupEnd(IT) # robot_sprite += SVGGroupEnd(IT) ActualPath = Field('ActualPath', None) if ActualPath is not None: path += IT('<!-- Actual path -->') path += SVGPath(IT, ShapeFromVertices(ActualPath, 1), { 'stroke': '#40f', 'stroke-width': '0.02' }) # ?? # Paths in rainbow colours Paths = Field('Paths', None) if Paths is not None and len(Paths) > 0: NumPaths = len(Paths) path += IT('<!-- Paths in rainbow colours -->') for PathIx, Path in enumerate(Paths): if NumPaths >= 2: Progress = float(PathIx) / float(NumPaths - 1) else: Progress = 1.0 Opacity = 1.0 if Progress in [0.0, 1.0] else 0.60 + 0.00 * Progress ColourStr = ProgressColourStr(Progress, Opacity) path += IT('<!-- Path %d, (%.1f%%) -->' % (PathIx, 100.0 * Progress)) path += SVGPath(IT, Path, {"stroke": ColourStr}) Sparks = Field('Sparks', None) if Sparks is not None and len(Sparks) > 0: B = (Pt_Break, None) sparks += IT('<!-- Points of interests (sparks) -->') for SparkPos in Sparks: SparkPos = (SparkPos[0], SparkPos[1]) S = (GreekCross(SparkPos, 0.4) + [B] + PiecewiseArc(SparkPos, 0.25, (0, 2.0 * pi), 8)) sparks += IT('<!-- Goal position -->') sparks += SVGPath(IT, S, { 'stroke': '#d00', 'stroke-width': '0.1', 'stroke-linecap': 'butt' }) # End of plot return [robot_sprite, path, sparks]
def RenderFrameTemplate(Data, draw_dynamic_elements=True): '''Return Data rendered to an SVG file in a string. Data is a dictionary with the keys: Title: This title is rendered and is embedded in the SVG header. Grid: See SVGGrid(). Map: The map is a 2D array of integers for hazards (1) and clear spaces (0). StartPos: The car starts here. The coordinates are units of map squares and the origin is in the centre of Map[0][0]. GoalPos: Hopefully the car ends within GoalThreshold of here. GoalThreshold: The radius of the goal zone is measured in grid units. Sparks: Each time a collision occurs, a coordinate pair is added to Sparks. Paths: For the puspose of visualising progressive path modifications, Paths is a list of Shapes to be rendered in red-to-indigo rainbow colours. ''' # ----------------------------------------------------------------------------- # Shorthand A = Pt_Anchor C = Pt_Control B = (Pt_Break, None) # ----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default # ----------------------------------------------------------------------------- IT = tIndentTracker(' ') Result = '' Title = Field('Title', '(Untitled)') Result += SVGStart(IT, Title, { 'width': '28cm', 'height': '19cm', 'viewBox': '0 0 28 19' }) Result += IT('<defs>') IT.StepIn() Result += IT('<marker id="ArrowHead"', ' viewBox="0 0 10 10" refX="0" refY="5"', ' markerUnits="strokeWidth"', ' markerWidth="8" markerHeight="6"', ' orient="auto">' ' <path d="M 0,0 L 10,5 L 0,10"/>', '</marker>') # Sparks are not used # Result += SparkSymbolDef(IT, 'spark') if Sparks is not None else '' # More marker, symbol and gradient definitions can go here. IT.StepOut() Result += IT('</defs>') # Background Result += IT( '<rect x="0" y="0" width="28" height="19" stroke="none" fill="white"/>' ) # Outer group Result += IT('<!-- Outer group -->') Result += SVGGroup(IT, {'stroke': 'black', 'stroke-width': '0.025'}) # Grid group # Substitute for the group created by SVGGrid that is now deleted Result += SVGGroup( IT, { 'stroke': 'black', 'stroke-width': 'butt', 'transform': 'matrix(1.5, 0, 0, 1.5, 5.5, 1.5)', 'fill': 'none' }) Result += IT('<!-- Background -->') # Extract part of SVG with board board_data = open(Data['Map']['vector_graphics_file']).read().splitlines() board_data = board_data[board_data.index("<!-- Board -->") + 1:] board_data = board_data[0:board_data.index("<!-- Board -->")] Result += IT("\n".join(board_data)) # Iniial position StartPos = Field('StartPos', None) if StartPos is not None: S = [(A, (-1.0, -1.0)), (A, (-1.0, +1.0)), (A, (+1.0, +1.0)), (A, (+1.0, -1.0)), (A, (-1.0, -1.0))] Result += IT('<!-- Initial position -->') Result += SVGPath(IT, TransformedShape(AffineMtxTS(StartPos, 0.3), S), { 'stroke': '#09f', 'stroke-width': '0.1', 'stroke-linecap': 'square' }) # Robot if draw_dynamic_elements: Result += IT('{0}') else: Result += '' # Goal position GoalPos = Field('GoalPos', None) if GoalPos is not None: GoalThreshold = Field('GoalThreshold', None) if GoalThreshold is not None: Result += IT('<!-- Goal threshold -->') Result += IT('<circle cx="%g" cy="%g" r="%g"' % (GoalPos[0], GoalPos[1], GoalThreshold)) IT.StepIn(2) Result += IT( 'fill="rgba(0, 255, 0, 0.1)" stroke="#0d0" stroke-width="0.02"/>' ) IT.StepOut(2) S = (GreekCross(GoalPos, 0.4) + [B] + PiecewiseArc(GoalPos, 0.25, (0, 2.0 * pi), 8)) Result += IT('<!-- Goal position -->') Result += SVGPath(IT, S, { 'stroke': '#0d0', 'stroke-width': '0.1', 'stroke-linecap': 'butt' }) # Sparks if draw_dynamic_elements: Result += IT("{2}") else: Result += '' # if Sparks is not None and len(Sparks) > 0: # Result += IT('<!-- Points of interests (sparks) -->') # Result += SVGGroup(IT, {'transform': 'translate(-0.5, -0.5)'}) # for SparkPos in Sparks: # Result += IT( # ('<use x="%g" y="%g"' % (SparkPos[0], SparkPos[1])) + # ' width="1" height="1" xlink:href="#spark"/>' # ) # Result += SVGGroupEnd(IT) # Actual path if draw_dynamic_elements: Result += IT("{1}") else: Result += '' # End board group # This ends the newly added group substituting the SVGGrid group. # Moved here the SVGGroupEnd which was for some reason previously appended # to the Actual path element making the code look convoluted Result += SVGGroupEnd(IT) # Title and legend Result += IT('<!-- Title background -->') Result += IT( '<rect x="0" y="0" width="28" height="1.1" stroke="none" fill="white"/>' ) Result += IT('<!-- Title group -->') Result += SVGGroup( IT, { 'font-family': 'sans-serif', 'font-size': '0.36', 'font-weight': 'normal', 'fill': 'black', 'stroke': 'none' }) Result += IT('<!-- Title -->') Result += SVGText(IT, (0.5, 0.82), Title, { 'font-size': '0.72', 'font-weight': 'bold' }) Result += IT('<!-- Legend line labels-->') Result += SVGText(IT, (19.5, 0.82), 'Actual path') Result += IT('<!-- Legend lines -->') Result += SVGGroup(IT, { 'fill': 'none', 'stroke-width': '0.12', 'stroke-linecap': 'round' }) Result += SVGPath(IT, [(Pt_Anchor, (18.5, 0.7)), (Pt_Anchor, (19.3, 0.7))], {'stroke': '#40f'}) Result += SVGGroupEnd(IT) # End of title group Result += SVGGroupEnd(IT) # End of outer group Result += SVGGroupEnd(IT) Result += SVGEnd(IT) return Result
def RenderFrameTemplate(Data, draw_dynamic_elements=True): '''Return Data rendered to an SVG file in a string. Data is a dictionary with the keys: Title: This title is rendered and is embedded in the SVG header. Grid: See SVGGrid(). Map: The map is a 2D array of integers for hazards (1) and clear spaces (0). StartPos: The car starts here. The coordinates are units of map squares and the origin is in the centre of Map[0][0]. GoalPos: Hopefully the car ends within GoalThreshold of here. GoalThreshold: The radius of the goal zone is measured in grid units. Sparks: Each time a collision occurs, a coordinate pair is added to Sparks. Paths: For the puspose of visualising progressive path modifications, Paths is a list of Shapes to be rendered in red-to-indigo rainbow colours. ''' # ----------------------------------------------------------------------------- # Shorthand A = Pt_Anchor C = Pt_Control B = (Pt_Break, None) # ----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default # ----------------------------------------------------------------------------- IT = tIndentTracker(' ') Result = '' Title = Field('Title', '(Untitled)') Result += SVGStart(IT, Title, { 'width': '28cm', 'height': '19cm', 'viewBox': '0 0 28 19' }) Result += IT('<defs>') IT.StepIn() Result += IT( '<marker id="ArrowHead"', ' viewBox="0 0 10 10" refX="0" refY="5"', ' markerUnits="strokeWidth"', ' markerWidth="8" markerHeight="6"', ' orient="auto">' ' <path d="M 0,0 L 10,5 L 0,10"/>', '</marker>' ) # Sparks are not used # Result += SparkSymbolDef(IT, 'spark') if Sparks is not None else '' # More marker, symbol and gradient definitions can go here. IT.StepOut() Result += IT('</defs>') # Background Result += IT( '<rect x="0" y="0" width="28" height="19" stroke="none" fill="white"/>' ) # Outer group Result += IT('<!-- Outer group -->') Result += SVGGroup(IT, {'stroke': 'black', 'stroke-width': '0.025'}) # Grid group # Substitute for the group created by SVGGrid that is now deleted Result += SVGGroup(IT, {'stroke': 'black', 'stroke-width':'butt', 'transform': 'matrix(1.5, 0, 0, 1.5, 5.5, 1.5)', 'fill': 'none'}) Result += IT('<!-- Background -->') # Extract part of SVG with board board_data = open(Data['Map']['vector_graphics_file']).read().splitlines() board_data = board_data[board_data.index("<!-- Board -->")+1:] board_data = board_data[0:board_data.index("<!-- Board -->")] Result += IT("\n".join(board_data)) # Iniial position StartPos = Field('StartPos', None) if StartPos is not None: S = [ (A, (-1.0, -1.0)), (A, (-1.0, +1.0)), (A, (+1.0, +1.0)), (A, (+1.0, -1.0)), (A, (-1.0, -1.0)) ] Result += IT('<!-- Initial position -->') Result += SVGPath(IT, TransformedShape(AffineMtxTS(StartPos, 0.3), S), {'stroke': '#09f', 'stroke-width': '0.1', 'stroke-linecap': 'square'} ) # Robot if draw_dynamic_elements: Result += IT('{0}') else: Result += '' # Goal position GoalPos = Field('GoalPos', None) if GoalPos is not None: GoalThreshold = Field('GoalThreshold', None) if GoalThreshold is not None: Result += IT('<!-- Goal threshold -->') Result += IT( '<circle cx="%g" cy="%g" r="%g"' % (GoalPos[0], GoalPos[1], GoalThreshold) ) IT.StepIn(2) Result += IT( 'fill="rgba(0, 255, 0, 0.1)" stroke="#0d0" stroke-width="0.02"/>' ) IT.StepOut(2) S = ( GreekCross(GoalPos, 0.4) + [B] + PiecewiseArc(GoalPos, 0.25, (0, 2.0 * pi), 8) ) Result += IT('<!-- Goal position -->') Result += SVGPath(IT, S, { 'stroke': '#0d0', 'stroke-width': '0.1', 'stroke-linecap': 'butt' }) # Sparks if draw_dynamic_elements: Result += IT("{2}") else: Result += '' # if Sparks is not None and len(Sparks) > 0: # Result += IT('<!-- Points of interests (sparks) -->') # Result += SVGGroup(IT, {'transform': 'translate(-0.5, -0.5)'}) # for SparkPos in Sparks: # Result += IT( # ('<use x="%g" y="%g"' % (SparkPos[0], SparkPos[1])) + # ' width="1" height="1" xlink:href="#spark"/>' # ) # Result += SVGGroupEnd(IT) # Actual path if draw_dynamic_elements: Result += IT("{1}") else: Result += '' # End board group # This ends the newly added group substituting the SVGGrid group. # Moved here the SVGGroupEnd which was for some reason previously appended # to the Actual path element making the code look convoluted Result += SVGGroupEnd(IT) # Title and legend Result += IT('<!-- Title background -->') Result += IT( '<rect x="0" y="0" width="28" height="1.1" stroke="none" fill="white"/>' ) Result += IT('<!-- Title group -->') Result += SVGGroup(IT, { 'font-family': 'sans-serif', 'font-size': '0.36', 'font-weight': 'normal', 'fill': 'black', 'stroke': 'none' }) Result += IT('<!-- Title -->') Result += SVGText(IT, (0.5, 0.82), Title, { 'font-size': '0.72', 'font-weight': 'bold' }) Result += IT('<!-- Legend line labels-->') Result += SVGText(IT, (19.5, 0.82), 'Actual path') Result += IT('<!-- Legend lines -->') Result += SVGGroup(IT, { 'fill': 'none', 'stroke-width': '0.12', 'stroke-linecap': 'round' }) Result += SVGPath(IT, [(Pt_Anchor, (18.5, 0.7)), (Pt_Anchor, (19.3, 0.7))], {'stroke': '#40f'} ) Result += SVGGroupEnd(IT) # End of title group Result += SVGGroupEnd(IT) # End of outer group Result += SVGGroupEnd(IT) Result += SVGEnd(IT) return Result
def RenderAnimatedPart(Data): """ Renders list of strings that will be injected to frame """ # ----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default # ----------------------------------------------------------------------------- # TODO: string concatenation is slow robot_sprite = "" path = "" sparks = "" side = 0.5 IT = tIndentTracker(' ') robot_sprite += SVGGroup(IT, {'transform': 'rotate(%g %g %g)' % ( (Data['ActualOrientation'] * 180 / pi) + 180.0, Data['ActualPosition'][0], Data['ActualPosition'][1]) }) # robot_sprite += SVGGroup(IT, {'transform': 'scale(2)'}) robot_sprite += IT('<polygon points="%g,%g %g,%g %g,%g" style="fill:lime;' '' 'stroke:purple;stroke-width:0.06" />' % (Data['ActualPosition'][0] + side / 2.0, Data['ActualPosition'][1] - side / 2.0, Data['ActualPosition'][0] + side / 2.0, Data['ActualPosition'][1] + side / 2.0, Data['ActualPosition'][0] - side, Data['ActualPosition'][1] )) robot_sprite += SVGGroupEnd(IT) # robot_sprite += SVGGroupEnd(IT) ActualPath = Field('ActualPath', None) if ActualPath is not None: path += IT('<!-- Actual path -->') path += SVGPath(IT, ShapeFromVertices(ActualPath, 1), {'stroke': '#40f', 'stroke-width': '0.02'} ) # ?? # Paths in rainbow colours Paths = Field('Paths', None) if Paths is not None and len(Paths) > 0: NumPaths = len(Paths) path += IT('<!-- Paths in rainbow colours -->') for PathIx, Path in enumerate(Paths): if NumPaths >= 2: Progress = float(PathIx) / float(NumPaths - 1) else: Progress = 1.0 Opacity = 1.0 if Progress in [0.0, 1.0] else 0.60 + 0.00 * Progress ColourStr = ProgressColourStr(Progress, Opacity) path += IT('<!-- Path %d, (%.1f%%) -->' % (PathIx, 100.0 * Progress)) path += SVGPath(IT, Path, {"stroke": ColourStr}) Sparks = Field('Sparks', None) if Sparks is not None and len(Sparks) > 0: B = (Pt_Break, None) sparks += IT('<!-- Points of interests (sparks) -->') for SparkPos in Sparks: SparkPos = (SparkPos[0], SparkPos[1]) S = ( GreekCross(SparkPos, 0.4) + [B] + PiecewiseArc(SparkPos, 0.25, (0, 2.0 * pi), 8) ) sparks += IT('<!-- Goal position -->') sparks += SVGPath(IT, S, { 'stroke': '#d00', 'stroke-width': '0.1', 'stroke-linecap': 'butt' }) # End of plot return [robot_sprite, path, sparks]
def RenderToSVG(Data): '''Return data rendered to an SVG file in a string. Grid is a dictionary with the keys: Title: This title is rendered and is embedded in the SVG header. Grid: See SVGGrid(). Paths: A list of Shapes to be rendered in red-to-indigo rainbow colours. BadPaths: A list of Shapes to be rendered in a faded colour. ''' #----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default #----------------------------------------------------------------------------- IT = tIndentTracker(' ') Result = '' Title = Field('Title', '(Untitled)') Result += SVGStart(IT, Title, { 'width': '28cm', 'height': '19cm', 'viewBox': '0 0 28 19', }) Result += IT('<defs>') IT.StepIn() Result += IT( '<marker id="ArrowHead"', ' viewBox="0 0 10 10" refX="0" refY="5"', ' markerUnits="strokeWidth"', ' markerWidth="16" markerHeight="12"', ' orient="auto">' ' <path d="M 0,0 L 10,5 L 0,10 z"/>', '</marker>' ) # More marker, symbol and gradient definitions can go here. IT.StepOut() Result += IT('</defs>') # Background Result += IT( '<!-- Background -->', '<rect x="0" y="0" width="28" height="19" stroke="none" fill="white"/>' ) # Outer group Result += IT('<!-- Outer group -->') Result += SVGGroup(IT, {'stroke': 'black', 'stroke-width': '0.025'}) # Plots of both rejected and tentatively accepted paths Result += IT('<!-- Grid -->') Result += SVGGrid(IT, Data['Grid']) # Rejected paths BadPaths = Field('BadPaths', None) if BadPaths is not None: Result += IT('<!-- Rejected paths -->') Result += SVGGroup(IT, { 'opacity': '0.10', 'stroke': '#ff0099' }) NumBadPaths = len(BadPaths) for PathIx, Path in enumerate(BadPaths): Result += SVGPath(IT, Path) Result += SVGGroupEnd(IT) # Axes Result += IT('<!-- Axes -->') RangeMin = Data['Grid']['RangeMinima'] RangeMax = Data['Grid']['RangeMaxima'] Result += SVGGroup(IT, { 'stroke': 'black', 'stroke-width': '0.05', 'stroke-linecap': 'square', 'marker-end': 'url(#ArrowHead)' }) Result += SVGPath(IT, [(Pt_Anchor, (RangeMin[0], 0.0)), (Pt_Anchor, (RangeMax[0] + 0.1, 0.0))] ) Result += SVGPath(IT, [(Pt_Anchor, (0.0, RangeMin[1])), (Pt_Anchor, (0.0, RangeMax[1] + 0.1))] ) Result += SVGGroupEnd(IT) # Paths in rainbow colours Paths = Field('Paths', None) if Paths is not None: NumPaths = len(Paths) Result += IT('<!-- Paths in rainbow colours -->') for PathIx, Path in enumerate(Paths): if NumPaths >= 2: Progress = float(PathIx) / float(NumPaths - 1) else: Progress = 1.0 Opacity = 1.0 if Progress in [0.0, 1.0] else 0.60 + 0.00 * Progress ColourStr = ProgressColourStr(Progress, Opacity) Result += IT('<!-- Path %d, (%.1f%%) -->' % (PathIx, 100.0 * Progress)) Result += SVGPath(IT, Path, {"stroke": ColourStr}) # End of plot Result += SVGGroupEnd(IT) # Title and legend Result += IT('<!-- Title background -->') Result += IT( '<rect x="0" y="0" width="28" height="1.1" stroke="none" fill="white"/>' ) Result += IT('<!-- Title group -->') Result += SVGGroup(IT, { 'font-family': 'sans-serif', 'font-size': '0.36', 'font-weight': 'normal', 'fill': 'black', 'stroke': 'none' }) Result += IT('<!-- Title -->') Result += SVGText(IT, (0.5, 0.82), Title, { 'font-size': '0.72', 'font-weight': 'bold' }) Result += IT('<!-- Legend line labels-->') Result += SVGText(IT, (23.5, 0.82), 'Initial') Result += SVGText(IT, (26.0, 0.82), 'Final') Result += IT('<!-- Legend lines -->') Result += SVGGroup(IT, { 'fill': 'none', 'stroke-width': '0.1', 'stroke-linecap': 'round' }) Result += SVGPath(IT, [(Pt_Anchor, (22.5, 0.7)), (Pt_Anchor, (23.3, 0.7))], {'stroke': ProgressColourStr(0.0)} ) Result += SVGPath(IT, [(Pt_Anchor, (25.0, 0.7)), (Pt_Anchor, (25.8, 0.7))], {'stroke': ProgressColourStr(1.0)} ) Result += SVGGroupEnd(IT) # End of title group Result += SVGGroupEnd(IT) # End of outer group Result += SVGGroupEnd(IT) Result += SVGEnd(IT) return Result
def RenderFrameTemplate(Data, draw_dynamic_elements=True): '''Return Data rendered to an SVG file in a string. Data is a dictionary with the keys: Title: This title is rendered and is embedded in the SVG header. Grid: See SVGGrid(). Map: The map is a 2D array of integers for hazards (1) and clear spaces (0). StartPos: The car starts here. The coordinates are units of map squares and the origin is in the centre of Map[0][0]. GoalPos: Hopefully the car ends within GoalThreshold of here. GoalThreshold: The radius of the goal zone is measured in grid units. Sparks: Each time a collision occurs, a coordinate pair is added to Sparks. Paths: For the puspose of visualising progressive path modifications, Paths is a list of Shapes to be rendered in red-to-indigo rainbow colours. ''' #----------------------------------------------------------------------------- # Shorthand A = Pt_Anchor C = Pt_Control B = (Pt_Break, None) #----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default #----------------------------------------------------------------------------- IT = tIndentTracker(' ') Result = '' SparkSymbol = '' Sparks = Field('Sparks', None) Title = Field('Title', '(Untitled)') Result += SVGStart(IT, Title, { 'width': '28cm', 'height': '19cm', 'viewBox': '0 0 28 19' }) Result += IT('<defs>') IT.StepIn() Result += IT( '<marker id="ArrowHead"', ' viewBox="0 0 10 10" refX="0" refY="5"', ' markerUnits="strokeWidth"', ' markerWidth="8" markerHeight="6"', ' orient="auto">' ' <path d="M 0,0 L 10,5 L 0,10 z"/>', '</marker>' ) Result += SparkSymbolDef(IT, 'spark') if Sparks is not None else '' # More marker, symbol and gradient definitions can go here. IT.StepOut() Result += IT('</defs>') # Background Result += IT( '<!-- Background -->', '<rect x="0" y="0" width="28" height="19" stroke="none" fill="white"/>' ) # Outer group Result += IT('<!-- Outer group -->') Result += SVGGroup(IT, {'stroke': 'black', 'stroke-width': '0.025'}) # Plot with grid Result += IT('<!-- Grid -->') Result += SVGGrid(IT, Data['Grid']) # Maze Map = Field('Map', None) if Map is not None: Result += IT('<!-- Hazards -->') Result += SVGGroup(IT, { 'fill': '#a40', 'stroke': 'black', 'stroke-width': '0.01', 'stroke-linecap': 'butt', }) scale_color = 255.0/len(Map) arrow_colors = {MAP_SPECIAL_DIRECTION: '00F5F1', MAP_SPECIAL_OPTIMAL: 'F58F00'} for i in range(len(Map)): for j in range(len(Map[0])): if Map[i][j] == 1: #Result += IT('<circle cx="%g" cy="%g" r="0.495"/>\n' % (i, j)) Result += IT('<rect x="%g" y="%g" width="1" height="1" stroke="none" fill="#B30000"/>\n' %(i - 0.5, j - 0.5)) elif type(Map[i][j]) is list: if Map[i][j][0] == MAP_SPECIAL_EUCLIDEAN_DISTANCE: Result += IT('<rect x="%g" y="%g" width="1" height="1" stroke="none" fill="rgb(%g,%g,%g)"/>\n' %(i - 0.5, j - 0.5, max(0, 255-int(scale_color*Map[i][j][1])), max(0, 255-int(scale_color*Map[i][j][1])), max(0, 255-int(scale_color*Map[i][j][1])) )) else: Result += SVGGroup(IT, {'transform': 'translate(%g, %g)' % (i, j)}) Result += SVGGroup(IT, {'transform': 'scale(0.0005)'}) Result += SVGGroup(IT, {'transform': 'rotate(%g, %g, %g)' % (45*Map[i][j][1] -270, i-0.5, i-0.5)}) Result += IT('<polygon style="stroke:none; ' 'fill:#%s;" points="100,600 100,-200 ' '500,200 500,-100 0,-600 -500,-100 -500,' '200 -100,-200 -100,600 "/>'%(arrow_colors[Map[i][j][0]],)) Result += SVGGroupEnd(IT) Result += SVGGroupEnd(IT) Result += SVGGroupEnd(IT) Result += SVGGroupEnd(IT) # Iniial position StartPos = Field('StartPos', None) if StartPos is not None: S = [ (A, (-1.0, -1.0)), (A, (-1.0, +1.0)), (A, (+1.0, +1.0)), (A, (+1.0, -1.0)), (A, (-1.0, -1.0)) ] Result += IT('<!-- Initial position -->') Result += SVGPath(IT, TransformedShape(AffineMtxTS(StartPos, 0.3), S), {'stroke': '#09f', 'stroke-width': '0.1', 'stroke-linecap': 'square'} ) # Robot if draw_dynamic_elements: Result += '{0}' else: Result += '' #side = 0.2 #Result += SVGGroup(IT, {'transform': 'rotate(%g %g %g)'%( # (Data['ActualOrientation'] * 180 / pi) + 180.0, # Data['ActualPosition'][0], Data['ActualPosition'][1]) #}) #Result += IT('<polygon points="%g,%g %g,%g %g,%g" style="fill:lime;stroke:purple;stroke-width:0.01" />' #%(Data['ActualPosition'][0] + side/2.0, Data['ActualPosition'][1] - side/2.0, #Data['ActualPosition'][0] + side/2.0, Data['ActualPosition'][1] + side/2.0, # Data['ActualPosition'][0] - side, Data['ActualPosition'][1] #)) #Result += SVGGroupEnd(IT) # Goal position GoalPos = Field('GoalPos', None) if GoalPos is not None: GoalThreshold = Field('GoalThreshold', None) if GoalThreshold is not None: Result += IT('<!-- Goal threshold -->') Result += IT( '<circle cx="%g" cy="%g" r="%g"' % (GoalPos[0], GoalPos[1], GoalThreshold) ) IT.StepIn(2) Result += IT( 'fill="rgba(0, 255, 0, 0.1)" stroke="#0d0" stroke-width="0.02"/>' ) IT.StepOut(2) S = ( GreekCross(GoalPos, 0.4) + [B] + PiecewiseArc(GoalPos, 0.25, (0, 2.0 * pi), 8) ) Result += IT('<!-- Goal position -->') Result += SVGPath(IT, S, { 'stroke': '#0d0', 'stroke-width': '0.1', 'stroke-linecap': 'butt' }) # Sparks if Sparks is not None and len(Sparks) > 0: Result += IT('<!-- Points of collision (sparks) -->') Result += SVGGroup(IT, {'transform': 'translate(-0.5, -0.5)'}) for SparkPos in Sparks: Result += IT( ('<use x="%g" y="%g"' % (SparkPos[0], SparkPos[1])) + ' width="1" height="1" xlink:href="#spark"/>' ) Result += SVGGroupEnd(IT) # Actual path if draw_dynamic_elements: Result += "{1}" else: Result += '' # #ActualPath = Field('ActualPath', None) #if ActualPath is not None: # Result += IT('<!-- Actual path -->') # Result += SVGPath(IT, # ShapeFromVertices(ActualPath, 1), # {'stroke': '#40f', 'stroke-width': '0.02'} # ) # # ## ?? ## Paths in rainbow colours #Paths = Field('Paths', None) #if Paths is not None and len(Paths) > 0: # # NumPaths = len(Paths) # # Result += IT('<!-- Paths in rainbow colours -->') # for PathIx, Path in enumerate(Paths): # if NumPaths >= 2: # Progress = float(PathIx) / float(NumPaths - 1) # else: # Progress = 1.0 # Opacity = 1.0 if Progress in [0.0, 1.0] else 0.60 + 0.00 * Progress # ColourStr = ProgressColourStr(Progress, Opacity) # Result += IT('<!-- Path %d, (%.1f%%) -->' % (PathIx, 100.0 * Progress)) # Result += SVGPath(IT, Path, {"stroke": ColourStr}) # ## End of plot # #Result += SVGGroupEnd(IT) # Title and legend Result += IT('<!-- Title background -->') Result += IT( '<rect x="0" y="0" width="28" height="1.1" stroke="none" fill="white"/>' ) Result += IT('<!-- Title group -->') Result += SVGGroup(IT, { 'font-family': 'sans-serif', 'font-size': '0.36', 'font-weight': 'normal', 'fill': 'black', 'stroke': 'none' }) Result += IT('<!-- Title -->') Result += SVGText(IT, (0.5, 0.82), Title, { 'font-size': '0.72', 'font-weight': 'bold' }) Result += IT('<!-- Legend line labels-->') Result += SVGText(IT, (19.5, 0.82), 'Actual path') #Result += SVGText(IT, (22.6, 0.82), 'Estimated') #Result += SVGText(IT, (26.0, 0.82), 'Actual') Result += IT('<!-- Legend lines -->') Result += SVGGroup(IT, { 'fill': 'none', 'stroke-width': '0.12', 'stroke-linecap': 'round' }) Result += SVGPath(IT, [(Pt_Anchor, (18.5, 0.7)), (Pt_Anchor, (19.3, 0.7))], {'stroke': '#40f'} ) #Result += SVGPath(IT, # [(Pt_Anchor, (21.6, 0.7)), (Pt_Anchor, (22.4, 0.7))], # {'stroke': '#f09', 'stroke-dasharray': '0.075 0.15'} #) # #Result += SVGPath(IT, # [(Pt_Anchor, (25.0, 0.7)), (Pt_Anchor, (25.8, 0.7))], # {'stroke': '#40f'} #) Result += SVGGroupEnd(IT) # End of title group Result += SVGGroupEnd(IT) # End of outer group Result += SVGGroupEnd(IT) Result += SVGEnd(IT) return Result
def RenderAnimatedPart(Data): """ Renders list of strings that will be injected to frame """ #----------------------------------------------------------------------------- def Field(Name, Default): return Data[Name] if Name in Data else Default #----------------------------------------------------------------------------- robot_sprite = "" side = 0.5 IT = tIndentTracker(' ') robot_sprite += SVGGroup(IT, {'transform': 'rotate(%g %g %g)'%( (Data['ActualOrientation'] * 180 / pi) + 180.0, Data['ActualPosition'][0], Data['ActualPosition'][1]) }) #robot_sprite += SVGGroup(IT, {'transform': 'scale(2)'}) robot_sprite += IT('<polygon points="%g,%g %g,%g %g,%g" style="fill:lime;' '' 'stroke:purple;stroke-width:0.06" />' %(Data['ActualPosition'][0] + side/2.0, Data['ActualPosition'][1] - side/2.0, Data['ActualPosition'][0] + side/2.0, Data['ActualPosition'][1] + side/2.0, Data['ActualPosition'][0] - side, Data['ActualPosition'][1] )) robot_sprite += SVGGroupEnd(IT) #robot_sprite += SVGGroupEnd(IT) path = "" ActualPath = Field('ActualPath', None) if ActualPath is not None: path += IT('<!-- Actual path -->') path += SVGPath(IT, ShapeFromVertices(ActualPath, 1), {'stroke': '#40f', 'stroke-width': '0.02'} ) # ?? # Paths in rainbow colours Paths = Field('Paths', None) if Paths is not None and len(Paths) > 0: NumPaths = len(Paths) path += IT('<!-- Paths in rainbow colours -->') for PathIx, Path in enumerate(Paths): if NumPaths >= 2: Progress = float(PathIx) / float(NumPaths - 1) else: Progress = 1.0 Opacity = 1.0 if Progress in [0.0, 1.0] else 0.60 + 0.00 * Progress ColourStr = ProgressColourStr(Progress, Opacity) path += IT('<!-- Path %d, (%.1f%%) -->' % (PathIx, 100.0 * Progress)) path += SVGPath(IT, Path, {"stroke": ColourStr}) # End of plot path += SVGGroupEnd(IT) return [robot_sprite, path]