Process SMIL directives in XML data: Difference between revisions
m (</smil> on its own line) |
(→Tcl: Added implementation) |
||
Line 60: | Line 60: | ||
</Scene> |
</Scene> |
||
</X3D></lang> |
</X3D></lang> |
||
=={{header|Tcl}}== |
|||
{{works with|Tcl|8.6}} |
|||
{{libheader|tDOM}} |
|||
<lang tcl>package require Tcl 8.6 |
|||
package require tdom |
|||
# Applies a time-based interpolation to generate a space-separated list |
|||
proc interpolate {time info} { |
|||
dict with info { |
|||
scan $begin "%fs" begin |
|||
scan $dur "%fs" dur |
|||
} |
|||
if {$time < $begin} { |
|||
return $from |
|||
} elseif {$time > $begin+$dur} { |
|||
return $to |
|||
} |
|||
set delta [expr {($time - $begin) / $dur}] |
|||
return [lmap f $from t $to {expr {$f + ($t-$f)*$delta}}] |
|||
} |
|||
# Applies SMIL <transform> elements to their container |
|||
proc applySMILtransform {sourceDocument time} { |
|||
set doc [dom parse [$sourceDocument asXML]] |
|||
foreach smil [$doc selectNodes //smil] { |
|||
foreach context [$smil selectNodes {//*[animate]}] { |
|||
set animator [$context selectNodes animate] |
|||
set animated [$context selectNodes @[$animator @attributeName]] |
|||
$context removeChild $animator |
|||
$context setAttribute [$animator @attributeName] \ |
|||
[interpolate $time [lindex [$animator asList] 1]] |
|||
} |
|||
if {[$smil parentNode] eq ""} { |
|||
set reparent 1 |
|||
} else { |
|||
[$smil parentNode] replaceChild $smil [$smil firstChild] |
|||
} |
|||
} |
|||
if {[info exist reparent]} { |
|||
set doc [dom parse [[$smil firstChild] asXML]] |
|||
} |
|||
return $doc |
|||
} |
|||
set t [expr {[lindex $argv 0] + 0.0}] |
|||
set result [applySMILtransform [dom parse [read stdin]] $t] |
|||
puts {<?xml version="1.0" ?>} |
|||
puts -nonewline [$result asXML -indent 2]</lang> |
|||
{{out|Demonstration}} |
|||
Note that <tt>input.smil</tt> contains the source document from the task description. |
|||
<pre> |
|||
$ tclsh8.6 applySmil.tcl 0 < input.smil |
|||
<?xml version="1.0" ?> |
|||
<X3D> |
|||
<Scene> |
|||
<Viewpoint position="0 0 8" orientation="0 0 1 0"/> |
|||
<PointLight color="1 1 1" location="0 2 0"/> |
|||
<Shape> |
|||
<Box size="2.0 1.0 2.0"/> |
|||
<Appearance> |
|||
<Material diffuseColor="0.0 0.6 1.0"/> |
|||
</Appearance> |
|||
</Shape> |
|||
</Scene> |
|||
</X3D> |
|||
$ tclsh8.6 applySmil.tcl 2 < input.smil |
|||
<?xml version="1.0" ?> |
|||
<X3D> |
|||
<Scene> |
|||
<Viewpoint position="0 0 8" orientation="0 0 1 0"/> |
|||
<PointLight color="1 1 1" location="0 2 0"/> |
|||
<Shape> |
|||
<Box size="1.8 1.2 1.8"/> |
|||
<Appearance> |
|||
<Material diffuseColor="0.2 0.5599999999999999 0.8"/> |
|||
</Appearance> |
|||
</Shape> |
|||
</Scene> |
|||
</X3D> |
|||
</pre> |
Revision as of 08:09, 27 May 2014
In order to represent evolutions of contents over time, the SMIL standard provides a solution to record the animation of data. Smil animations can be added to any kind of contents formated in XML.
The task is to create an utility that given the first Smiled XML file, would return the following ones:
<lang xml><?xml version="1.0" ?> <smil> <X3D>
<Scene> <Viewpoint position="0 0 8" orientation="0 0 1 0"/> <PointLight color='1 1 1' location='0 2 0'/> <Shape> <Box size='2 1 2'> <animate attributeName="size" from="2 1 2" to="1 2 1" begin="0s" dur="10s"/> </Box> <Appearance> <Material diffuseColor='0.0 0.6 1.0'> <animate attributeName="diffuseColor" from="0.0 0.6 1.0" to="1.0 0.4 0.0" begin="0s" dur="10s"/> </Material> </Appearance> </Shape> </Scene>
</X3D> </smil></lang>
At t = 0 second here is the expected output:
<lang xml><?xml version="1.0" ?> <X3D>
<Scene> <Viewpoint position="0 0 8" orientation="0 0 1 0"/> <PointLight color='1 1 1' location='0 2 0'/> <Shape> <Box size='2 1 2'/> <Appearance> <Material diffuseColor='0.0 0.6 1.0'/> </Appearance> </Shape> </Scene>
</X3D></lang>
At t = 2 second here is the expected output:
<lang xml><?xml version="1.0" ?> <X3D>
<Scene> <Viewpoint position="0 0 8" orientation="0 0 1 0"/> <PointLight color='1 1 1' location='0 2 0'/> <Shape> <Box size='1.8 1.2 1.8'/> <Appearance> <Material diffuseColor='0.2 0.56 0.8'/> </Appearance> </Shape> </Scene>
</X3D></lang>
Tcl
<lang tcl>package require Tcl 8.6 package require tdom
- Applies a time-based interpolation to generate a space-separated list
proc interpolate {time info} {
dict with info {
scan $begin "%fs" begin scan $dur "%fs" dur
} if {$time < $begin} {
return $from
} elseif {$time > $begin+$dur} {
return $to
} set delta [expr {($time - $begin) / $dur}] return [lmap f $from t $to {expr {$f + ($t-$f)*$delta}}]
}
- Applies SMIL <transform> elements to their container
proc applySMILtransform {sourceDocument time} {
set doc [dom parse [$sourceDocument asXML]] foreach smil [$doc selectNodes //smil] {
foreach context [$smil selectNodes {//*[animate]}] { set animator [$context selectNodes animate] set animated [$context selectNodes @[$animator @attributeName]] $context removeChild $animator $context setAttribute [$animator @attributeName] \ [interpolate $time [lindex [$animator asList] 1]] } if {[$smil parentNode] eq ""} { set reparent 1 } else { [$smil parentNode] replaceChild $smil [$smil firstChild] }
} if {[info exist reparent]} {
set doc [dom parse [[$smil firstChild] asXML]]
} return $doc
}
set t [expr {[lindex $argv 0] + 0.0}] set result [applySMILtransform [dom parse [read stdin]] $t] puts {<?xml version="1.0" ?>} puts -nonewline [$result asXML -indent 2]</lang>
- Demonstration:
Note that input.smil contains the source document from the task description.
$ tclsh8.6 applySmil.tcl 0 < input.smil <?xml version="1.0" ?> <X3D> <Scene> <Viewpoint position="0 0 8" orientation="0 0 1 0"/> <PointLight color="1 1 1" location="0 2 0"/> <Shape> <Box size="2.0 1.0 2.0"/> <Appearance> <Material diffuseColor="0.0 0.6 1.0"/> </Appearance> </Shape> </Scene> </X3D> $ tclsh8.6 applySmil.tcl 2 < input.smil <?xml version="1.0" ?> <X3D> <Scene> <Viewpoint position="0 0 8" orientation="0 0 1 0"/> <PointLight color="1 1 1" location="0 2 0"/> <Shape> <Box size="1.8 1.2 1.8"/> <Appearance> <Material diffuseColor="0.2 0.5599999999999999 0.8"/> </Appearance> </Shape> </Scene> </X3D>