001    /*
002     * Copyright 2011 Christian Kumpe http://kumpe.de/christian/java
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package de.kumpe.hadooptimizer.examples.painting;
017    
018    import static java.lang.String.*;
019    
020    import java.io.IOException;
021    import java.io.OutputStream;
022    import java.util.Locale;
023    
024    import javax.xml.parsers.DocumentBuilder;
025    import javax.xml.parsers.DocumentBuilderFactory;
026    import javax.xml.transform.Transformer;
027    import javax.xml.transform.TransformerException;
028    import javax.xml.transform.TransformerFactory;
029    import javax.xml.transform.dom.DOMSource;
030    import javax.xml.transform.stream.StreamResult;
031    import javax.xml.xpath.XPath;
032    import javax.xml.xpath.XPathConstants;
033    import javax.xml.xpath.XPathFactory;
034    
035    import org.apache.hadoop.conf.Configuration;
036    import org.apache.hadoop.fs.FileSystem;
037    import org.apache.hadoop.fs.Path;
038    import org.apache.hadoop.io.LongWritable;
039    import org.apache.hadoop.io.ObjectWritable;
040    import org.apache.hadoop.io.SequenceFile;
041    import org.w3c.dom.Document;
042    import org.w3c.dom.Element;
043    
044    /**
045     * TODO document!
046     * 
047     * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a>
048     */
049    public class AnimationSvgRenderer {
050            public static void main(final String[] args) throws Exception {
051                    new AnimationSvgRenderer().run();
052            }
053    
054            private Element[] triangles;
055            private DOMSource source;
056            private Transformer transformer;
057            private StreamResult result;
058            private String outputPath;
059    
060            protected void run() throws Exception {
061                    // parse the result-template
062                    final DocumentBuilder documentBuilder = DocumentBuilderFactory
063                                    .newInstance().newDocumentBuilder();
064                    final Document document = documentBuilder.parse(getClass()
065                                    .getResourceAsStream("/ResultTemplate (Animation).svg"));
066    
067                    // extract necessary elements
068                    final XPath xPath = XPathFactory.newInstance().newXPath();
069                    final Element triangle = (Element) xPath.evaluate(
070                                    "//path[@id='dreieck']", document, XPathConstants.NODE);
071                    triangle.removeAttribute("id");
072                    final Element parent = (Element) triangle.getParentNode();
073                    parent.removeChild(triangle);
074    
075                    // create 50 triangles
076                    triangles = new Element[50];
077                    for (int i = 0; i < triangles.length; i++) {
078                            triangles[i] = (Element) triangle.cloneNode(false);
079                            parent.appendChild(triangles[i]);
080                    }
081    
082                    final Element zyklus = (Element) xPath.evaluate(
083                                    "//tspan[@id='zyklus']", document, XPathConstants.NODE);
084                    final Element bewertung = (Element) xPath.evaluate(
085                                    "//tspan[@id='bewertung']", document, XPathConstants.NODE);
086                    final Element geschwindigkeit = (Element) xPath
087                                    .evaluate("//tspan[@id='geschwindigkeit']", document,
088                                                    XPathConstants.NODE);
089                    final Element punkt = (Element) xPath.evaluate("//path[@id='punkt']",
090                                    document, XPathConstants.NODE);
091    
092                    final String transform = punkt.getAttribute("transform");
093                    final String[] parts = transform.split(",|\\(|\\)");
094                    final double ox = Double.parseDouble(parts[1]);
095                    final double oy = Double.parseDouble(parts[2]);
096    
097                    // initialize the transformer for writing the SVG-output
098                    source = new DOMSource(document);
099                    result = new StreamResult();
100                    transformer = TransformerFactory.newInstance().newTransformer();
101    
102                    outputPath = "/home/baumbart/KIT/Animation/";
103    
104                    // open input
105                    final Configuration conf = new Configuration();
106                    final Path inputPath = new Path(
107                                    "file:///home/baumbart/KIT/de.kumpe.hadooptimizer.examples.painting.SvgRenderer-20110423-173603/output/part-r-00000");
108                    final FileSystem inputFileSystem = inputPath.getFileSystem(conf);
109                    final SequenceFile.Reader reader = new SequenceFile.Reader(
110                                    inputFileSystem, inputPath, conf);
111    
112                    final LongWritable key = new LongWritable();
113                    final ObjectWritable value = new ObjectWritable();
114                    while (reader.next(key, value)) {
115                            final double[] values = (double[]) value.get();
116                            final long cycle = (long) values[0];
117                            System.out.println(cycle);
118                            zyklus.setTextContent(String.format("Zyklus: %,d", cycle));
119                            bewertung.setTextContent(String
120                                            .format("Bewertung: %.2f", values[3]));
121                            geschwindigkeit.setTextContent("");
122    
123                            punkt.setAttribute(
124                                            "transform",
125                                            String.format(Locale.ENGLISH, "translate(%f,%f)", ox
126                                                            + cycle * 550.541 / 1500000, oy - values[3] / 140
127                                                            * 323.140));
128    
129                            configureTriangles(values);
130                            writeSvgResultDocument(cycle);
131                    }
132    
133            }
134    
135            private void configureTriangles(final double[] values) {
136                    for (int i = 0; i < triangles.length; i++) {
137                            // extract and clip the values
138                            final double opacity = clip(values[7 * i + 5 + 0] / 312, 0, 1);
139                            final double x1 = clip(values[7 * i + 5 + 1], 0, 312);
140                            final double y1 = clip(values[7 * i + 5 + 2], 0, 312);
141                            final double x2 = clip(values[7 * i + 5 + 3], 0, 312);
142                            final double y2 = clip(values[7 * i + 5 + 4], 0, 312);
143                            final double x3 = clip(values[7 * i + 5 + 5], 0, 312);
144                            final double y3 = clip(values[7 * i + 5 + 6], 0, 312);
145    
146                            // set the coordinates
147                            triangles[i].setAttribute(
148                                            "d",
149                                            format(Locale.US, "M %f,%f %f,%f %f,%f %1$f,%2$f z", x1,
150                                                            y1, x2, y2, x3, y3));
151    
152                            // set the opacity
153                            triangles[i]
154                                            .setAttribute(
155                                                            "style",
156                                                            format(Locale.US,
157                                                                            "fill:#000000;stroke:#00ffff;stroke-width:0.1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.75;fill-opacity:%f",
158                                                                            opacity));
159                    }
160            }
161    
162            private void writeSvgResultDocument(final long cycle) throws IOException {
163                    // create the SVG-file
164                    final Path outputPath = new Path(format("%s/result%06d.svg",
165                                    this.outputPath, cycle));
166                    final FileSystem fileSystem = outputPath
167                                    .getFileSystem(new Configuration());
168                    final OutputStream outputStream = fileSystem.create(outputPath);
169                    result.setOutputStream(outputStream);
170    
171                    try {
172                            // write the SVG-file
173                            transformer.transform(source, result);
174                    } catch (final TransformerException e) {
175                            throw new RuntimeException(e);
176                    }
177    
178                    outputStream.close();
179            }
180    
181            private double clip(final double value, final double min, final double max) {
182                    final double diff = max - min;
183                    return Math.abs(Math.abs(value % (diff * 2)) - diff) + min;
184            }
185    }