קובץ:Animation stirling engine.ogv
לקובץ המקורי (קובץ וידאו Theora של Ogg, באורך 40 שניות, 1,000 × 1,000 פיקסלים, 996 קילו־ביטים בשנייה, גודל הקובץ: 4.76 מ"ב)
זהו קובץ שמקורו במיזם ויקישיתוף. תיאורו בדף תיאור הקובץ המקורי (בעברית) מוצג למטה. |
תוכן עניינים
תקציר
תיאורAnimation stirling engine.ogv |
English: Animation of a stirling engine in alpha configuration running as a motor.A regenerator is included. |
תאריך יצירה | |
מקור | נוצר על־ידי מעלה היצירה |
יוצר | Menner |
רישיון
קובץ זה זמין לפי תנאי הקדשה עולמית לנחלת הכלל CC0 1.0 של Creative Commons. | |
האדם ששייך יצירה להיתר הזה הקדיש את היצירה לנחלת הכלל על־ידי ויתור על כל הזכויות שלו או שלה על היצירה בכל העולם לפי חוק זכויות יוצרים, לרבות כל הזכויות הקשורות או הסמוכות כקבוע בחוק. באפשרותך להעתיק, לשנות, להפיץ, או להציג את היצירה, אפילו למטרות מסחריות, וכל זה אפילו מבלי לבקש רשות.
http://creativecommons.org/publicdomain/zero/1.0/deed.enCC0Creative Commons Zero, Public Domain Dedicationfalsefalse |
Source code
Recommended tools:
- Java (Java 8 used)
- mjpeg tools (2.1 used)
- inkscape (0.48 used)
- ffmpeg2theora (0.29 used)
- Eclipse (4.4.1 used)
All tools are available for Linux and Windows.
Core tool is Java. Additional helper tools and scripts generate a encoded video from a sequence of svg files. See below
The file File:Stirling template.svg serves as template used by Java code.
Java
Create a Java project with Eclipse. It requires only one file with one class.
package wikipedia.stirling;
import java.io.File;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Locale;
import javax.swing.JFileChooser;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* The StirlingSvgManipulator takes a specially prepared template SVG file and from that it creates a
* sequence of animated SVG files explaining a stirling engine. The template SVG was created with the
* popular Inkscape illustration tool.
*
* StirlingSvgManipulator opens the SVG file a XML based format by using a DOM parser. With DOM specially
* tagged SVG graphic elements can be searched and manipulated. Mostly the "matrix" attribute from SVG
* is used to translate and rotate elements. Further corners of a rectangular path are edited to expand
* and shrink its volume.
*
*/
public class StirlingSvgManipulator {
static final String filename = "stirling";
static final String template = filename + "_template.svg";
static final int duration = 4*10; // duration in seconds
static final int framerate = 30; // frame rate per second
static final double angularSpeed = 1./10.; // rotations per second
static final double Length = 350.;
static final double LengthPiston = 150.;
static final double Excentricity = 100.;
static final int OffsetX = 250;
static final int OffsetY = 250;
/**
* @param args
*
* Opens a file chooser dialog which requires to select the directory where the template SVG is found
* and the resulting SVG files are placed.
*
* @throws Exception
*/
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
Path wspPath = null;
Path templatePath = null;
JFileChooser filechooser = new JFileChooser();
filechooser.setCurrentDirectory(new java.io.File("."));
filechooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
filechooser.setAcceptAllFileFilterUsed(false);
filechooser.setDialogTitle("Select working directory");
int approve = filechooser.showOpenDialog(null);
if(approve == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " +
filechooser.getSelectedFile().getAbsolutePath());
Path path = filechooser.getSelectedFile().toPath();
wspPath = Paths.get(path.toString(), "svg");
templatePath = Paths.get(path.toString(), template);
} else {
System.out.println("Execution canceled!");
return;
}
mkdirSvg(wspPath);
StirlingSvgManipulator template = new StirlingSvgManipulator(templatePath);
template.load();
for (int count = 0 ; count <= (duration * framerate); count++) { // time in seconds
System.out.println("===============================");
System.out.println("Iteration: " + String.valueOf(count));
System.out.println("===============================");
double time = (double) count / (double) framerate;
template.setAngle(2. * Math.PI * angularSpeed * time);
template.applySettings();
Path destination = Paths.get(wspPath.toString(), filename + "-" + String.format("%04d", count) + ".svg");
template.save(destination);
}
long endTime = System.currentTimeMillis();
System.out.println("Execution time: " + String.valueOf((endTime-startTime)/1000) + "s");
System.out.println("Finished");
}
public static void mkdirSvg(Path dir) throws IOException {
boolean success = false;
File directory = dir.toFile();
if (directory.exists()) {
System.out.println("Directory already exists!");
} else {
success = directory.mkdir();
if (success == true) {
System.out.println("Successful");
} else {
throw new IOException("can't make directory for " + dir.toString());
}
}
}
private Path templatePath = null;
private Document document = null;
private double angleRad = 0.;
private double x;
private double y;
private double xStroke;
private double yStroke;
private double alpha1; // Angle between conrod and y axis
private double alpha2; // Angle between conrod and x axis
/**
*
* Konstruktor
*
* @param templatePath
*/
public StirlingSvgManipulator(Path templatePath) {
// TODO Auto-generated constructor stub
this.templatePath = templatePath;
}
/**
*
* Load template with StaXParser
* @throws Exception
*
*/
public void load() throws Exception {
// TODO Auto-generated method stub
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
document = docBuilder.parse(templatePath.toFile());
} catch (IOException | ParserConfigurationException e) {
System.out.print("Error loading " + templatePath.toString() + "\n");
e.printStackTrace();
throw e;
}
}
/**
*
* Write XML file with StaXParser
*
* @param destination
* @throws TransformerException
*/
public void save(Path destination) throws TransformerException {
try {
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer trans = transFactory.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.METHOD, "xml");
trans.transform(new DOMSource(document), new StreamResult(destination.toFile()));
} catch (TransformerConfigurationException e) {
e.printStackTrace();
throw e;
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
}
/**
*
* @param rad Angular position for the engine
*/
public void setAngle(double rad) {
angleRad = rad;
}
public void applySettings() {
System.out.println( "calcParameters();");
calcParameters();
System.out.println( "applyKolben();");
applyPiston();
System.out.println( "applyHeatexchanger();");
applyHeatexchanger();
System.out.println( "applyVolumen();");
applyVolume();
}
private void calcParameters() {
x = Math.cos(angleRad);
y = Math.sin(angleRad);
alpha1 = Math.acos(x * Excentricity / Length);
alpha2 = Math.acos(y * Excentricity / Length);
xStroke = x * Excentricity + Math.sqrt(Length * Length - (y*Excentricity)*(y*Excentricity)) - Length;
yStroke = y * Excentricity + Math.sqrt(Length * Length - (x*Excentricity)*(x*Excentricity)) - Length; // Pythagoras
}
private void applyVolume() {
NodeList nodes = document.getElementsByTagName("g");
System.out.println( "Gefunden: " + Integer.toString(nodes.getLength()) + " groups");
nodes.item(0);
for (int i = 0; i < nodes.getLength(); ++i) {
Node node = nodes.item(i);
NamedNodeMap attributes = node.getAttributes();
Node id = attributes.getNamedItem("id");
if(id.getNodeValue().equals("gVolume1") == true) {
NodeList childNodes = node.getChildNodes();
Node volumen = childNodes.item(1);
NamedNodeMap childAttributes = volumen.getAttributes();
Node childId = childAttributes.getNamedItem("id");
if(childId.getNodeValue().equals("pVolume1") == true) {
Node d = childAttributes.getNamedItem("d");
System.out.print("Volume path d: " + d.getNodeValue() + "\n");
String[] parameters = d.getNodeValue().split(" ");
if(parameters.length != 6) {
throw new NullPointerException();
}
String[] links = parameters[3].split(",");
String[] rechts = parameters[4].split(",");
links[1] = String.format(Locale.US, "%.3f", yStroke);
rechts[1] = String.format( Locale.US, "%.3f", yStroke);
parameters[3] = links[0] + "," + links[1];
parameters[4] = rechts[0] + "," + rechts[1];
StringBuilder parametersBuild = new StringBuilder();
for(String parameter : parameters) {
parametersBuild.append(parameter + " ");
}
d.setNodeValue(parametersBuild.toString().trim());
}
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String offset = String.format(Locale.US, "%.3f", (double) OffsetY + Length + LengthPiston);
String matrix = "translate(" + String.valueOf(OffsetX) + "," + offset + ")";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
if(id.getNodeValue().equals("gVolume2") == true) {
NodeList childNodes = node.getChildNodes();
Node volumen = childNodes.item(1);
NamedNodeMap childAttributes = volumen.getAttributes();
Node childId = childAttributes.getNamedItem("id");
if(childId.getNodeValue().equals("pVolume2") == true) {
Node d = childAttributes.getNamedItem("d");
System.out.print("Volume path d: " + d.getNodeValue() + "\n");
String[] parameters = d.getNodeValue().split(" ");
if(parameters.length != 6) {
throw new NullPointerException();
}
String[] links = parameters[3].split(",");
String[] rechts = parameters[4].split(",");
links[0] = String.format(Locale.US, "%.3f", xStroke);
rechts[0] = String.format( Locale.US, "%.3f", xStroke);
parameters[3] = links[0] + "," + links[1];
parameters[4] = rechts[0] + "," + rechts[1];
StringBuilder parametersBuild = new StringBuilder();
for(String parameter : parameters) {
parametersBuild.append(parameter + " ");
}
d.setNodeValue(parametersBuild.toString().trim());
}
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String offset = String.format(Locale.US, "%.3f", (double) OffsetX + Length + LengthPiston);
String matrix = "translate(" + offset + "," + String.valueOf(OffsetY) + ")";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
}
}
/**
*
* applyHeatexchanter()
*
* This Drawing is not very precise and just for illustration to get an idea about the state of the heat exchanger.
*
*/
private void applyHeatexchanger() {
NodeList nodes = document.getElementsByTagName("linearGradient");
System.out.println( "Gefunden: " + Integer.toString(nodes.getLength()) + " linear Gradient(s)");
nodes.item(0);
double sum = ( x + -1. * y)/Math.sqrt(2.);
double pos = 0.5 + 0.4 * sum; // TODO magic numbers
double delta = 0.1;
System.out.println("");
//double sum =
// V_1 / V_2
// V_1 = x_hub
// V_2 = y_hub
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
NamedNodeMap attributes = node.getAttributes();
Node id = attributes.getNamedItem("id");
System.out.println("Gradient -ID: " + id.getNodeValue());
if(id.getNodeValue().equals("linearGradientHeat") == true) {
NodeList stopNodes = node.getChildNodes();
System.out.println( "Gefunden: " + Integer.toString(stopNodes.getLength()) + " stop(s)");
// stopNodes.item(0);
for (int j = 0; j < stopNodes.getLength(); j++) {
Node stopNode = stopNodes.item(j);
if(stopNode.getNodeName().equals("stop") == true) {
NamedNodeMap stopAttributes = stopNode.getAttributes();
System.out.println( "Gefunden: " + Integer.toString(stopAttributes.getLength()) + " stop attribut(e)");
Node stopId = stopAttributes.getNamedItem("id");
if(stopId.getNodeValue().equals("stopRed") == true) {
System.out.println("Stop ID: " + stopId.getNodeValue());
Node offset = stopAttributes.getNamedItem("offset");
offset.setNodeValue(String.valueOf(pos - delta));
}
if(stopId.getNodeValue().equals("stopBlue1") == true) {
System.out.println("Stop ID: " + stopId.getNodeValue());
Node offset = stopAttributes.getNamedItem("offset");
offset.setNodeValue(String.valueOf(pos + delta));
}
}
}
}
}
}
private void applyPiston() {
NodeList nodes = document.getElementsByTagName("g");
System.out.println( "Found: " + Integer.toString(nodes.getLength()) + " groups");
nodes.item(0);
double alpha_x1 = Math.cos(alpha1);
double alpha_y1 = Math.sin(alpha1);
double alpha_x2 = Math.cos(alpha2);
double alpha_y2 = Math.sin(alpha2);
System.out.println("alpha: " + String.format(Locale.US, "%.3f, alpha_x: ", alpha1) +
String.format(Locale.US, "%.3f, alpha_y: ", alpha_x1) + String.format( Locale.US, "%.3f, ", alpha_y1));
for (int i = 0; i < nodes.getLength(); ++i) {
Node node = nodes.item(i);
NamedNodeMap attributes = node.getAttributes();
Node id = attributes.getNamedItem("id");
System.out.println("Group-ID: " + id.getNodeValue());
if(id.getNodeValue().equals("gCrankShaft") == true) {
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String matrix = "matrix(" + String.valueOf(-1. * y) + "," + String.valueOf(x) +
"," + String.valueOf(-1. * x) + "," + String.valueOf(-1. * y) + ",0,0)";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
if(id.getNodeValue().equals("gConrod1") == true) { // Pleuel
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String matrix = "matrix(" + String.valueOf(alpha_y1) + "," + String.valueOf(alpha_x1) +
"," + String.valueOf(-1. * alpha_x1) + "," + String.valueOf(alpha_y1) + "," +
String.valueOf(Excentricity * x) + "," + String.valueOf(Excentricity * y) + ")";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
if(id.getNodeValue().equals("gPiston1") == true) {
Node transform = attributes.getNamedItem("transform");
String yMove = String.format(Locale.US, "%.3f", yStroke + Length);
String translate = "translate(0," + yMove + ")";
transform.setNodeValue(translate);
}
if(id.getNodeValue().equals("gConrod2") == true) { // Pleuel
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String matrix = "matrix("
+ String.valueOf(alpha_x2) + "," + String.valueOf(alpha_y2) +
"," + String.valueOf(alpha_y2) + "," + String.valueOf(-1. *alpha_x2) + "," +
String.valueOf(Excentricity * x) + "," + String.valueOf(Excentricity * y) + ")";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
if(id.getNodeValue().equals("gPiston2") == true) {
Node transform = attributes.getNamedItem("transform");
String xMove = String.format(Locale.US, "%.3f", xStroke + Length);
String translate = "translate(" + xMove + ",0)";
transform.setNodeValue(translate);
}
if(id.getNodeValue().equals("gCrankDrive") == true) {
Node transform = attributes.getNamedItem("transform");
System.out.print("transform: " + transform.getNodeValue() + "\n");
String matrix = "translate(" + String.valueOf(OffsetX) + "," + String.valueOf(OffsetY) + ")";
System.out.println(matrix);
transform.setNodeValue(matrix);
}
}
}
}
svg_to_png
@echo off
Echo Converting...
set start=%time%
echo %CD%
rmdir png /s /q
mkdir png
cd svg
for %%f in (*.svg) do (
call :convert %%f
)
echo Start time: %start%
echo End time: %time%
timeout /T -1
goto :EOF
:convert
echo %1
set ink="C:\Program Files (x86)\Inkscape\inkscape.exe"
set svg=%1
set png=%svg%
set png=%png:~0,-3%
set png=../png/%png%png
%ink% --file=%svg% --export-png=%png% --export-background=white --without-gui
rem convert %svg% -background white -flatten %png%
echo %png%
goto :EOF
cd ..
png_to_ogv
@echo off
echo Converting...
set start=%time%
echo %CD%
echo %temp%
call :convert
echo Start time: %start%
echo End time: %time%
timeout /T -1
goto :EOF
:convert
set png2yuv="%CD%\mjpeg_tools\bin\png2yuv.exe"
set framerate=30
set filename=stirling
%png2yuv% -j .\png\%filename%-%%04d.png -f %framerate% -I p -b 0 > %temp%\out.yuv
.\ffmpeg2theora-0.29.exe %temp%\out.yuv -F %framerate% -v 9 -o %filename%.ogv
del %temp%\out.yuv /q /s
goto :EOF
פריטים שמוצגים בקובץ הזה
מוצג
ערך כלשהו ללא פריט ויקינתונים
10 בדצמבר 2014
application/ogg
4,986,682 בית
40.03333333333333 שנייה
1,000 פיקסל
1,000 פיקסל
היסטוריית הקובץ
ניתן ללחוץ על תאריך/שעה כדי לראות את הקובץ כפי שנראה באותו זמן.
תאריך/שעה | תמונה ממוזערת | ממדים | משתמש | הערה | |
---|---|---|---|---|---|
נוכחית | 18:14, 10 בדצמבר 2014 | 40 שניות, 1,000 × 1,000 (4.76 מ"ב) | Menner | update | |
16:05, 10 בדצמבר 2014 | 25 שניות, 1,000 × 1,000 (3.49 מ"ב) | Menner | User created page with UploadWizard |
שימוש בקובץ
אין בוויקיפדיה דפים המשתמשים בקובץ זה.
שימוש גלובלי בקובץ
אתרי הוויקי השונים הבאים משתמשים בקובץ זה:
- שימוש באתר de.wikipedia.org
מטא־נתונים
קובץ זה מכיל מידע נוסף, שכנראה הגיע ממצלמה דיגיטלית או מסורק שבהם הקובץ נוצר או עבר דיגיטציה.
אם הקובץ שונה ממצבו הראשוני, כמה מהנתונים להלן עלולים שלא לשקף באופן מלא את הקובץ הנוכחי.
תוכנה בשימוש |
|
---|